JxBrowser onStartLoadingFrame Data Passing Issue - jxbrowser

I am currently using JxBrowser 6.19.1 and I would like to ask if it is possible to set a variable value when I first start loading a page, by using onStartLoadingFrame. Then I am going to use that data in the page.
For example:
final JFrame frame = new JFrame("Hello World!");
final Browser browser = new Browser();
BrowserView view = new BrowserView(browser);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(view, BorderLayout.CENTER);
frame.setSize(400, 300);
frame.setVisible(true);
browser.addLoadListener(new LoadAdapter() {
#Override
public void onStartLoadingFrame(StartLoadingEvent event) {
browser.executeJavaScriptAndReturnValue("var data = 1"); // does not work every single time, real question
}
});
browser.loadURL("echo.html");
where my echo.html will be something like this:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<h1>Echo Page</h1>
<script>
alert(data);
</script>
</body>
The question comes, sometimes it prompt the alert, sometimes doesn't. Does anyone know why? (Due to Multitheading?) Is that any work around for this?
Hope someone can help me with that. Thanks.

If you need to execute some JavaScript code before any other JavaScript on the loaded web page is executed, then you should use the onScriptContextCreated JavaScript context event as shown below:
browser.addScriptContextListener(new ScriptContextAdapter() {
#Override
public void onScriptContextCreated(ScriptContextEvent event) {
event.getBrowser().executeJavaScript("var data = 1");
}
});
In this case, the data JavaScript variable will be set properly, and the script on the web page will always work as expected.

Related

Blazor's OnInitializedAsync event fires before DOM is finished

I'm currently working on a hosted/client Blazor WebAssembly app, which when initially run works fine.
In the 'OnInitializedAsync' method of the page being rendered is a javascript call to retrieve the width of an html element on the page. If I set a breakpoint in the javascript function, on initial app run the browser is displaying the rendered page and the element properties are correctly retrieved. However, when I refresh the browser page, when the breakpoint is hit the browser hasn't finished rendering the page and so the element's width is zero.
Can anyone tell me why this is and how I can fix the problem?
<div #ref="_carPanelWidth">
....
</div>
#code {
private ElementReference _carPanelWidth;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
var carPanelWidth = await JsRuntime.InvokeAsync<int>("utilityFunctions.getElementWidth", new object[] { _carPanelWidth });
StateHasChanged();
}
}
window.utilityFunctions = {
getElementWidth: function (element) {
return element.offsetWidth;
}
};
I deal with a similar situation when rendering grids. It causes a flashiness which looks unprofessional.
What I do is mark the html elements as hidden and later show them, when I know everything is loaded. This completely eliminates flash, if that is the problem you are having.
<div id="table_id_div" style="visibility:hidden">
I use interopt to apply the DataTable.com stuff to the table and when that is complete the javascript runs...
$("#" + tableName + "_div").attr('style', 'visibility : visible');
This seems to do the trick.

Creating a "toast"

I have been trying to get similar functionality to an Android "toast" using Xamarin forms. After looking around, I found what I think is a good solution. The general approach appears to be to make a new Absolute layout, and make it appear for a set time, then disappear. While I think I generally understand what is being done, I can't seem to get it to work. Can anyone suggest how I would use this class if I want to make a toast appear in my MainPage? Should I be adding an AbsoluteLayout in the XAML file? Sorry, I'm sure this is a simple question, but I can't really figure out what to do...
Any help would be greatly appreciated!
public static class Popper
{
public async static Task Pop (string message, AbsoluteLayout attachLayout, int showforMilliseconds = 1500)
{
var container = new StackLayout
{
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
BackgroundColor = Color.FromHex ("#DDEFEFEF"),
Padding = 10
};
var label = new Label
{
Text = message,
FontAttributes = FontAttributes.Bold,
Style = (Style)Application.Current.Resources["PopupText"]
};
container.Children.Add (label);
container.Scale = 0;
container.Opacity = 0;
attachLayout.Children.Add (container, attachLayout.Bounds, AbsoluteLayoutFlags.PositionProportional);
container.ScaleTo (1.0f, 100);
container.FadeTo (1.0f, 100);
await Task.Delay (showforMilliseconds);
container.ScaleTo (0.0f, 250);
await container.FadeTo (0.0f, 250);
attachLayout.Children.Remove (container);
}
}
On Android you don't have to reinvent the wheel since Toast exists natively. On other platforms there is no such thing like Toast, therefor there is no silver-bullet solution here. This problem have been solved by multiple people in multiple ways, thats why I left a comment that your question might be a duplicate of existing thread with multiple examples.
Now about your idea. Your implementation is working, however it will show Toast only on an AbsoluteLayout. Why to set such a restriction? If you will recheck the link I shared in comments you will find a more appropriate and elegant solutions.
I can't seem to get it to work.
All you need is a an AbsoluteLayout on your page so you could call your method:
await Popper.Pop("Hello world", referenceToYourAbsoluteLayout, 5000);
If you still for some reason want to stick to this exact solution, maybe it will make sense to have an extension method instead. However this solution just does not make sense for the average user.
P.S: Once again, please check the existing thread for more information and details.
P.S.S: Usage example of your code snippet
<!-- XXXPage.xaml -->
<?xml version="1.0" encoding="utf-8"?>
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XXX"
x:Class="XXX.XXXPage">
<AbstractLayout x:name="myLayout />
</ContentPage>
// XXXPage.xaml.cs
public partial class XXXPage : ContentPage
{
public Test999Page()
{
InitializeComponent();
}
async protected override void OnAppearing()
{
base.OnAppearing();
await Popper.Pop("Hello world", myLayout, 5000);
}
}

How to reload data in Simile Timeline

I created a SIMILE Timeline that uses an XML file as data source which is created by a method when an aspx command is invoked.
The problem is that when the XML file is updated the Timeline isn't updated and shows the data of the first load. The data is only refreshed when I close the browser and open again the Web Application with the Timeline. Even if I go to another page of my Web Application and then come back to the page with the Timeline the data showed stills the same.
I already confirmed that the XML file is created/updated before the script that creates the Timeline be invoked and I also tried some tricks like force the PageLoad(), do a Response.Redirect() and don't use cache.
My function onLoad() is similiar to the original provided by simile-widget. Code:
<head>
...
<meta http-equiv="pragma" content="no-cache" />
<META HTTP-EQUIV="Expires" CONTENT="-1">
...
var tl;
function onLoad() {
$(document).ready(function() {
var eventSource1 = new Timeline.DefaultEventSource(0);
var theme1 = Timeline.ClassicTheme.create();
theme1.timeline_start = new Date(Date.UTC(2010, 0, 1));
theme1.timeline_stop = new Date(Date.UTC(2014, 0, 1));
var d = theme1.timeline_start;
var bandInfos = [
Timeline.createBandInfo({ ... }),
Timeline.createBandInfo({ ... })
];
bandInfos[1].syncWith = 0;
bandInfos[1].highlight = true;
// create the Timeline
tl = Timeline.create(document.getElementById("tl"), bandInfos);
var url = '.';
// references in the data
tl.loadXML("batch_data.xml", function(xml, url)
{eventSource1.loadXML(xml, url); });
tl.finishedEventLoading();
});
}
...
</head>
<body onload="onLoad();" onresize="onResize();">
<form id="form1" runat="server">
<div id="tl" runat="server">
...
</div>
</form>
</body>
Thanks!
The first clue you wrap your javascript code onLoad function. Try to create a button to update the page using the function onClick event. If you like to upgrade to a period of time you can use the JavaScript timing event.
Here is a link to a documentation of a timing event examples
I put the example this simple as posible:
setInterval(function(){alert("Hello")},3000);
and this is the sintax
window.setInterval("javascript function",milliseconds);

Unable to get unique id for element error with GUI extension popup

I'm building a GUI extension that includes a popup that is opened on the click of a new button in the ribbon bar. The popup includes a dropdown that is dynamically populated with some information gathered from the system using the Core Service. At least that's the idea. I am able to get the button to appear, and it opens the popup, but as soon as I start with the javascript for the popup I get an error Unable to get unique id for element and the CME doesn't finish loading. Here's what I have so far:
Popup ASPX
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="SwitchUserPopup.aspx.cs" Inherits="SwitchUser.Popups.SwitchUserPopup" %>
<%# Import Namespace="Tridion.Web.UI.Core" %>
<%# Import Namespace="Tridion.Web.UI" %>
<%# Import Namespace="System.Web" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:c="http://www.sdltridion.com/web/ui/controls">
<head runat="server">
<title>Select User</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>Select User</h1>
<c:dropdown id="SwitchUserDropdown" runat="server" nullable="false"/>
</div>
</form>
</body>
</html>
Popup ASPX Code
namespace SwitchUser.Popups
{
[ControlResourcesDependency(new [] { typeof(Popup),
typeof(Tridion.Web.UI.Controls.Button),
typeof(Stack),
typeof(Dropdown),
typeof(List) })]
[ControlResources("SwitchUser.Resources")]
public partial class SwitchUserPopup : TridionPage
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
TridionManager tm = new TridionManager();
tm.Editor = "SwitchUser";
System.Web.UI.HtmlControls.HtmlGenericControl dep =
new System.Web.UI.HtmlControls.HtmlGenericControl("dependency");
dep.InnerText = "Tridion.Web.UI.Editors.CME";
tm.dependencies.Add(dep);
System.Web.UI.HtmlControls.HtmlGenericControl dep2 =
new System.Web.UI.HtmlControls.HtmlGenericControl("dependency");
dep2.InnerText = "Tridion.Web.UI.Editors.CME.commands";
tm.dependencies.Add(dep2);
//Add them to the Head section
this.Header.Controls.Add(tm); //At(0, tm);
}
}
}
Popup JS
Type.registerNamespace("SwitchUser.Popups");
SwitchUser.Popups.SwitchUser = function (element) {
Type.enableInterface(this, "SwitchUser.Popups.SwitchUser");
this.addInterface("Tridion.Cme.View");
};
SwitchUser.Popups.SwitchUser.prototype.initialize = function () {
$log.message("Initializing Switch User popup...");
this.callBase("Tridion.Cme.View", "initialize");
var p = this.properties;
var c = p.controls;
c.UserDropdown = $controls.getControl($("#SwitchUserDropdown"), "Tridion.Controls.Dropdown");
};
$display.registerView(SwitchUser.Popups.SwitchUser);
The extension is configured correctly in System.config - I can see the log message in the javascript console. However, I also see this Unable to get unique id for element error with the following additional information:
anonymous(object{..})
WebRequest.completed(object{..})
Net.loadFile$onComplete(object{..})
Net.loadFile$onOperationCompleted()
Xml.loadXmlDocuments$onSuccess(array1)
Xml.loadXmlDocument$onSuccess(array1)
Dropdown.setup$filesLoaded(object{..})
setupDone()
anonymous(function: DisplayController$start())
DisplayController.start()
anonymous()
anonymous(undefined, "Tridion.Controls.Dropdown")
Tridion.Assert$raiseError("Unable to get unique id for element.")
From that logged info it seems that the problem is the dropdown. If I comment out the line in my JS that registers the view then I don't get the error, but I also don't get the log message so I suspect that this is a mandatory call. Can anyone shed any light on why this might be happening? I've been using the Example PowerTool code as a reference, and I believe I've replicated what is there...
Update
I tried to step through the code - I found a suitable line and placed a breakpoint there. Then I reloaded the CME and suddenly my breakpoint was on a line that had no relevance to my code, and I couldn't find anything related to my code. However, according to the console it is still being executed.
So, instead I put log messages in my initialize method as follows:
SwitchUser.Popups.SwitchUser.prototype.initialize = function () {
$log.message("Initializing Switch User popup...");
this.callBase("Tridion.Cme.View", "initialize");
$log.message("Tridion.Cme.View callBase done");
var p = this.properties;
var c = p.controls;
$log.message("Set properties and controls");
c.UserDropdown = $controls.getControl($("#SwitchUserDropdown"), "Tridion.Controls.Dropdown");
$log.message("Got UserDropdown control");
};
I can see in the console that it logs as far as Set properties and controls and then I get the error.
I put a breakpoint in the getControl method and was able to determine why I was getting the error. $("#SwitchUserDropdown") was not finding anything so when the code below was running it threw the error:
var id = Tridion.Utils.Dom.getUniqueID(element);
if (id)
{
var control = instances[id];
if (!control)
{
control = instances[id] = new ctor(element, settings);
if (Tridion.Type.isFunction(control.initialize))
{
control.initialize();
}
}
}
else
{
Tridion.Utils.Assert.raiseError("Unable to get unique id for element.");
}
return control;
It seems obvious now that I know why it was happening that the code was running at the wrong time. I believe it shouldn't run when the CME loads, but only when the popup is opened. This leads me to look at the configuration of the resources in my Editor config file. I had previously grouped my popup's JS with other resources associated with the ribbon toolbar button. By placing the popup specific resources in their own resource group I was able to stop the error and successfully get the control.

Virtual Listview for ASP.net?

Is there a virtual listview for ASP.net?
Most tables (and grids, listview, data tables, data grids, grid views, list grids) i find for asp.net expect the user to page through data.
i want a listview that contains, for example, 10,000 items; and i don't want 10 pages.
The problem of a long list was solved in 1994 using a listview in "virtual" mode. The control need only be given the number of items to show. The control information about those items as required (i.e. as the user scrolls them into view, or tries to sort on a column).
Has anyone created a virtual listview (presumably using Asynchronous Javascript and XML, or Synchronous Javascript and XML)?
If the answer's "no": don't be afraid to answer the question. There's nothing wrong with an answer of:
No.
I just make one virtual ListView sample.
I start with a repeater that I render divs, with an attribute that contain the Data Base id that need to be loaded.
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<div data-id="<%# GetID(Container.DataItem) %>" class="DataLine">
loading...
</div>
</ItemTemplate>
</asp:Repeater>
Next the javascript that check if this div is visible, and get the data using ajax.
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>
<script>
function isScrolledIntoView(elem)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = elem.offset().top;
var elemBottom = elemTop + elem.height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
var cTimerID = null;
function RunWithSomeDelay()
{
if(cTimerID)
clearTimeout(cTimerID);
cTimerID = setTimeout(CheckWhatToShow, 1000);
}
function CheckWhatToShow()
{
$(".DataLine").each(function(i, selected) {
var ThisOne = $(selected);
if(ThisOne.attr("Done") != "1")
{
if(isScrolledIntoView(ThisOne))
{
ThisOne.attr("Done", "1");
// here you can use a simple ajax load, to load your data.
ThisOne.text(ThisOne.attr("data-id"));
}
}
});
}
$(document).ready(function() {
// first time run
CheckWhatToShow();
// run on scrool
$(window).scroll(RunWithSomeDelay);
});
</script>
and here is my code behind as test that one
public partial class Dokimes_StackOverFlow_VirtualList : System.Web.UI.Page
{
List<int> oMainIds = new List<int>();
protected void Page_Load(object sender, EventArgs e)
{
for (int i = 0; i < 3000; i++)
oMainIds.Add(i);
Repeater1.DataSource = oMainIds;
Repeater1.DataBind();
}
public int GetID(object oItem){
return (int)oItem;
}
}
I tested and its working just find.
and here is the source code: http://www.planethost.gr/VirtualList.rar
Improvements that can be done:
To optimize what div to search for visibility base on the scroll point.
To load a group of data and place them on divs
Update
I make some speed optimizing, and add ajax call test. For this optimizations work correct the height of the div that contains the data must be the same across the page. Left to load a group of data, get them as json and place them on the correct place.
http://www.planethost.gr/VirtualList2.rar
Try to look at infinite scroll jQuery plugin. I think that is it like what are you looking for.

Resources