Reliably waiting for page to load or reflow in Awesomium.NET 1.7+ - awesomium

Which is the recommended way of waiting for a page to load/reflow in Awesomium.NET 1.7+ when running in a non-UI environment? I've tried this approach:
using (var view = WebCore.CreateWebView(...))
{
// Load page, resize view etc.
// ...
do
{
System.Threading.Thread.Sleep(50);
WebCore.Update();
} while (view.IsLoading);
// Do something with the page
// ...
}
However, this doesn't seem to work reliably - if I render the page to a bitmap after the loop it pretty often comes out blank (but not always). Is there a better way of waiting for page load/reflow?

Try subscribing to the WebView.DocumentReady event.

How you do it depends on what you are waiting for. The code in the question should work when waiting for a page to load, but resizing the view is different - check out the BitmapSurface.Resized event, it fires when the BitmapSurface has been resized and updated its buffer.

Related

How to display busy status in Kentico custom module

I have a custom module that contains a button. The button click performs a process that sometimes takes 5-10 seconds to complete. Is there a way in Kentico to display a custom busy message like the "Loading" message that Kentico displays during lengthy processes? I would like to show the same "Loading" msg that Kentico shows with my own custom message.
If your module is built using the out of the box page templates and webparts, this is included by default. If it is not and you're using custom aspx template pages, you'll need to ensure that the page in inherited properly and add that in. You might want to reference another out of the box module which is using code already like the Users in the Membership module.
Yes, but it depends on how things are set up.
If the button executes an Ajax Panel (it does a postback through an ajax call), then you can capture the ajax call and put your loading message there.
<script type="text/javascript>
var AjaxHandler = Sys.WebForms.PageRequestManager.getInstance();
AjaxHandler.add_beginRequest(beginRequestHandler);
AjaxHandler.add_endRequest(endRequestHandler);
function beginRequestHandler(sender, args) {
// Waiting
}
function endRequestHandler(sender, args) {
// close waiting
}
</script>
If you have it postbacking on the page, you can try to put a hook when the button is clicked to show the waiting, when the page refreshes then the waiting will of course be gone.
$("#mybutton").click(function() {
// Waiting
});

Liferay IPC listener runs multiple times

First of all sorry if this question has been already asked somewhere, but after a few hours on google I still can't find an answer.
I am pretty new in portlet development, (but we have a shortage of developers and I have to work with it time to time), so the solution might be something trivial, but I really don't have enough experience with it.
The problem is I have two portlets on a page and I try to let one of them know about changes in the other. For this I use IPC. In the first one I have a Liferay.fire function:
function fire(key,value){
Liferay.fire(
'category',{
id: key,
name: value
}
);
}
In the other I have a Liferay.on('category',function(category){...}) function with an ajax call inside and some rendering methods.
Now if I visit the mentioned page and click on the corresponding buttons, at first everything works just fine. However, if I navigate from this page and come back, the listener will run two times. Navigating again -> three times. And so on... But if I reload the page (with F5 or CTRL+F5), it starts over, so until further navigation the listener runs only once.
The other strange thing is no matter how many times the function runs, the input parameters are all the same for each.
For example, if I have left the page and went back to it 3 times and last time I chose the category with 'id=1', then the function will run 3 times with 'id=1'. Now if I choose 'id=2' it will run 3 times with 'id=2'.
If anyone has any idea I would be really grateful as I am stuck for almost a day now.
Thank you very much in advance and please let me know if you need any further info.
the problem you're having is caused by the global Liferay.on listeners that are being created but never removed.
In Liferay Portal 7.x, SPA navigation is enabled by default. This means that when you are navigating, the page isn't being completely refreshed, but simply updated with new data coming from the server.
In a traditional navigation scenario, every page refresh resets everything, so you don't have to be so careful about everything that's left behind. In an SPA scenario, however, global listeners such as Liferay.on or Liferay.after or body delegates can become problematic. Every time you're executing that code, you're adding yet another listener to the globally persisted Liferay object. The result is the observed multiple invocations of those listeners.
To fix it, you simply need to listen to the navigation event in order to detach your listeners like this:
var onCategory = function(event) {...};
var clearPortletHandlers = function(event) {
if (event.portletId === '<%= portletDisplay.getRootPortletId() %>') {
Liferay.detach('onCategoryHandler', onCategory);
Liferay.detach('destroyPortlet', clearPortletHandlers);
}
};
Liferay.on('category', onCategory);
Liferay.on('destroyPortlet', clearPortletHandlers);

Wait for chrome.tabs.update tab to finish loading

I'm trying to work on a chrome extension and am trying to clean up some of my code by relying on the sendMessage. However the callback function activates before the page has finished loading so in the case of a new tab, nobody receives and in the case of an existing tab the page that is being moved from is getting the message (but that isn't what I want). I've looked for other people asking about that problem with new tabs and there wasn't a clear answer, the best suggestion I've seen is to create a global variable and create a listener for tab loads and compare it against this global variable.
So the question is, is there a way to wait in the callback function until the page has loaded, or do I create an array of JS objects that contain the tab I'm waiting on and the information I want to send to that tab.
For reference here is the relevant code in the background javascript file.
chrome.tabs.sendMessage(tab.id, {info: "info"}, function(response)
{
//This line isn't used when I am navigating without changing tabs
chrome.tabs.create({url: response.info.linkUrl}, function(tab1)
{
chrome.tabs.update(tab1.id, {url: response.info.linkUrl}, function(tab2)
{
chrome.tabs.sendMessage(tab2.id, {info: "More Info"});
});
});
});
Otherwise I am able to confirm that all of my tab side code works, once my sendMessage was delayed enough for me to see that with my own eyes. My code is able to consistently make it past validation on the page being navigated away from, confirmed by checking document.url.
You can try injecting a second content script instead of a message.
It will execute in the same context as your other script.
Something along the lines of
chrome.tabs.executeScript(tab2.id,
{code: 'showInfo("More Info);', runAt: 'document_idle'}
);
where showInfo does the same as your message handler.
It's a bit of a hack and I'm not 100% sure the load order will be correct.
Other possible solutions are more complex.
For example, you can make the content script report back that it is ready and have a handler for that, for instance you can register a listener for onMessage in the background that waits for a message from that specific tab.id, sends "More Info" and then deregisters or disables itself.
Or, you could potentially switch to programmatic injection of your content script, which would let you control load order.

Creating UIElements outside Ui thread, Silverlight

In my silverlight 4.0 application, at one point, after user pushes a button, I have to create few UI objects that take some time (5-10seconds). During this time UI freezes of course. I decided to put creation of those objects in a background worker so UI could at least show progress bar.
But this solution does not work. To create UI object you have to be in UI thread.
If I put creation of those object inside Dispatcher.BeginInvoke() than again my UI freezes. In most cases without even showing progress bar. Is there a way around this?
Can I show progress bar while silverlight creates UI objects in the background?
Have a look at this forum post. It may help.
Instead of using:
System.Windows.Threading.Dispatcher.BeginInvoke(() => {});
They use:
System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() => {});
You can try displaying a custom message before creating UI objects inside BeginInvoke().
Example:
private void CreateObjects()
{
myMsg.Text = "Loading...";
Dispatcher.BeginInvoke(() => { AddObjects() });
}
Once all objects are created, disable the message.
You can try the similar thing with Progress Bar also.

QWebView setContent in a separate thread

I have an application that requires to use QWebView::setContent() to load some HTML content to a QWebView. All of this happens on an embedded device with ARMv5 processor (think 400 MHz). Most of the time, I can load the page in reasonable time (up to 5 seconds), however sometimes I have content that takes long time to load (~30 seconds for 300KB of content).
The problem is that the setContent call blocks the main thread. I need to be able to process events during the loading, and maybe even cancel the load if the user decides not to wait any longer.
I was thinking about running the setContent call in other thread, so that it does not block the event processing and I can cancel it if necessary. However, I get the dreaded "widgets must be created in the GUI thread", and I see no way of solving this easily.
Is it possible to run QWebView::setContent in a separate thread? If so, how? If not, is it possible to handle GUI events while setContent is running? Is it possible to "cancel" the setContent call?
EDIT
To clarify a bit more, what really interests me is how to be able to stop the setContent call and/or handle GUI messages, so that the interface remains responsive, with large amounts of data passed using setContent.
EDIT 2
To clarify even further, I am dealing with long, static content, i.e. no JavaScript, just a lot of static HTML, through which the user wants to scroll even while it is loading more content. The main idea is to allow her/him to go down a page even when the page is not fully loaded.
Some time ago I faced a similar problem. As far as I know, only the main contents of the page is acting synchronously.
The fact is that the GUI core "paints" the page and this is time consuming. So, the main thread gets freezed until the main contents is loaded completely.
In my case, the solution was simple: make the main contents a secondary one and work with local files!!!
So, what is my proposal:
1) Prepare a local file (/tmp/loader.html) that contains something like this:
<html>
<body onload='setTimeout(function() { window.location="contents.html"; }, 1000);'>
Loading...
</body>
</html>
2) Each time you need to load a new content, save it to the secondary file (/tmp/contents.html) and force the update of the loader (maybe also a refresh). Easy:
QFile f("/tmp/contents.html");
if (f.open(QFile::WriteOnly)) {
qint64 pos = 0;
while (pos < contents.length()) {
pos += f.write(contents.mid(pos, 1024)); // chunk of 1024
qApp->processEvents();
}
f.close();
webview->setUrl(QUrl::fromLocalFile("/tmp/loader.html"));
}
Observe that I permit the event loop to process pending events if the file saving is also slow...
3) Anytime you need to cancel the loading, you can load another contents, remove the contents file, or other possible approaches.
Note that, as far as I know, you would never make asynchronous the painting of the contents. And that is the real issue in embedded systems.
Since QWebView::setContent() is a blocking call, I ended up using a work-around. The main idea is that XML processing is much faster than rendering the page. Therefore I do the following:
Parse the document as XML DOM document (a reasonable assumption in my case), and find the body element.
Keep only a pre-defined number of child elements of body (something like 20 elements). Store the remaining elements in another XML DOM document.
Show the initial document (serialized XML) using QWebView::setContent(), which is relatively fast. Start a timer with timeout 0 on SLOT(loadNextChunk()).
loadNextChunk() moves another 20 or so elements from the backup document at the end of the body using body->appendInside(html), where body is a QWebElement.
Stop when no more elements are available.
This works because in between the calls to loadNextChunk(), the GUI has a chance to react to events.
QWebView, as its name suggests, is a widget. QWebPage, on the other hand, is a plain old QObject, with all the threading goodness you could possibly want.
Now tie it together:
void QWebView::setPage ( QWebPage * page )

Resources