I've had this happen in Chrome and IE...
If I click a link to navigate away from a page while requirejs is still loading or getting scripts, I get random errors. Sorry if this is vague...
For example, in require.js itself, I received an error today:
Unable to get value of the property 'normalize': object is null or undefined
In the following block:
//If current map is not normalized, wait for that
//normalized name to load instead of continuing.
if (this.map.unnormalized) {
//Normalize the ID if the plugin allows it.
if (plugin.normalize) {
name = plugin.normalize(name, function (name) {
return normalize(name, parentName, true);
}) || '';
}
//prefix and name should already be normalized, no need
//for applying map config again either.
normalizedMap = makeModuleMap(map.prefix + '!' + name,
I've received other errors in my own defined js files where they start executing the code before the dependencies are fully loaded. I get the feeling that when the browser is asked to navigate away from the current page, it stops all ajax calls and thus truncating some of the js.
Is there a way to prevent these sort of errors?
Avoid running code in the define function's scope. Start your app's logic once everything has loaded by writing your code in functions that get executed when your page is ready.
Also what do you mean by navigate? If you navigate away the page goes away, as well as its errors. Is this pushAPI style navigation with the app staying loaded, or a complete and full browser navigation?
Related
I am using the WebBrowser Component in System.Windows.Forms. The code loads content from a website and returns it properly. There is a JavaScript which is executed and loading some of the DOMs after the page has loaded completely.
The JavaScript is not finished loading by the time the .Navigate method finished execution. If I set a Breakpoint on the .Navigate in Debug mode, It will, clearly because .Navigate is asynchronous, run through the process of loading the page including the scripts.
void LoadPageWithScripts() {
Browser.Navigate("mypagewithscriptsurl");
// whatever comes next prevents the DOM generated by the script from beeing loaded
// ... e.g.:
Console.WriteLine("whatever");
// use Browser.Document later
}
I know, this question is similar to the one provided here: JavaScript only works...
Unfortunately, I have no Influence on the page which is loaded, so the approaches I have seen there, are not suitable for my needs.
I have tried to simply work with Thread.Sleep, as suggested by many forums. But even this won't work. As soon as the code continues to run past the .Navigate method, the JavaScript is lost. Only setting a break point on it will work currently.
Browser.Navigate("pageUrl");
Browser.Navigate("pageurl");
// Very bad solution
Thread.Sleep(2000);
while (true)
{
if (Browser.ReadyState == WebBrowserReadyState.Complete)
{
// do something
break;
}
else
{
Application.DoEvents();
}
}
Using the DocumentCompleted Event will not work, since the Script is not loaded before the document is in completed state.
Browser.Navigate("pageUrl");
Browser.DocumentCompleted += (o, e) =>
{
var text = Browser.DocumentText;
Console.WriteLine(text);
};
Hope to find some help.
I am trying to implement the displaying of a web page in Qt. I chose to use the Qt WebEngine to achieve my task. Here's what I did :
Wrote a sample web page consisting of a empty form.
Wrote a JS file with just an API to create a radio button inside the form.
In my code, it looks like this :
View = new QWebEngineView(this);
// read the js file using qfile
file.open("path to jsFile");
myJsApi = file.Readall();
View->page()->runjavascript (myjsapi);
View->page()->runjavascript ("createRadioButton(\"button1\");");
I find that the runJavaScript() function has no effect on the web page. I can see the web page in the output window, but the radio button I expected is not present. What am I doing wrong?
I think you will have to connect the signal loadFinished(bool) of your page() to a slot, then execute runJavaScript() in this slot.
void yourClass::mainFunction()
{
View = new QWebEngineView(this);
connect( View->page(), SIGNAL(loadFinished(bool)), this, SLOT(slotForRunJS(bool)));
}
void yourClass::slotForRunJS(bool ok)
{
// read the js file using qfile
file.open("path to jsFile");
myJsApi = file.Readall();
View->page()->runJavaScript(myjsapi);
View->page()->runJavaScript("createRadioButton(\"button1\");");
}
I had this problem, runJavascript didn't have any effect. I had to put some html content into the view (with page().setHtml("") before running it.
Check the application output, it might contain JavaScript errors. Even if your JS code is valid, you might encounter the situation where the script is run before DOMContentLoaded event, that is document.readyState == 'loading'. Therefore, the DOM might not be available yet, as well as variables or functions provided by other scripts. If you depend on them for your code to run, when you detect this readyState, either wait for the event or try calling the function later, after a timeout. The second approach with timeout might be needed if you need to get the result of the code execution, as this can be done only synchronously.
Using the below code, when the page loads and there is no cookie, the condition is met and
Walkthrough.runWalkthrough();
is executed. The intro.js walkthrough starts but it skips steps, it will go from step 1,3,6. When I refresh the cookie is still stored and running Walkthrough.runWalkthrough(); launches the walkthrough with all functionality in tact. Wondering how to get around this issue?
getData: function(setting) {
Walkthrough.setting = setting;
$.getJSON("/account/walkthrough", function(data) {
Walkthrough['info'] = data['steps'][setting];
}).done(function(data) {
if (!Walkthrough.getCookie(Walkthrough['lookup'][setting])) {
Walkthrough.runWalkthrough();
}
});
My theory is the IF statement is the cause of the issue because when the IF statement is removed the walkthrough starts with no issues, only when its wrapped inside the IF are steps being skipped. Wondering why?
The problem was the if statement was conflicting with an if statement in another part of the code that was executing the same function. By removing the other function that sets the cookie and adding a step for cookie setting inside the conditional shown above, the problem was eliminated and the code became more cohesive as well.
I need to know if this is correct. I'm just beginning in app development using WinJS. I've identified the source of the problem and got rid of it but I don't know if that's the correct method.Please help!
// Optimize the load of the application and while the splash screen is
// shown, execute high priority scheduled work.
ui.disableAnimations();
var p = ui.processAll().then(function () {
//return nav.navigate(nav.location || Application.navigator.home, nav.state);
return nav.navigate(nav.location || app.local, nav.state)
}).then(function () {
return sched.requestDrain(sched.Priority.aboveNormal + 1);
}).then(function () {
ui.enableAnimations();
});
The problem is in the first .then(). The commented line was the default line, I've changed it for the app to work.I've absolutely no idea what it is.Please tell me what it means and what is changed. By the way, 'app' is WinJS.Application and Application is a WinJS namespace in navigator.js where the home property is located.
This error would suggest that navigator.js isn't being loaded by the time this code is executed. The Application namespace, which is entirely arbitrary and unrelated to WinJS.Application, is defined only in navigator.js, so if that file isn't loaded that namespace won't exist.
A WinJS namespace, by the way, is just a formalization of a module pattern in JavaScript that helps you keep the global namespace from getting cluttered. Declaring a namespace like navigator.js does it:
WinJS.Namespace.define("Application", {
PageControlNavigator: WinJS.Class.define(
just creates a single object in the global namespace called "Application" and then defines members for it. (You can change "Application" to anything you want, by the way. Nothing else in navigator.js relies on it, and navigator.js is something that comes from the app templates in Visual Studio and isn't part of WinJS itself.)
So again, my suspicion is that you don't have (or whatever the proper path is) in your default.html, the path to it isn't correct, or that perhaps it's being loaded after the other code is trying to execute. Try setting breakpoints on WinJS.Namespace.define and see if that file is loaded and the breakpoint gets hit.
I am making a feed reader in Visual Studio using JavaScript, and when I run it, I get an error:
0x800a138f - JavaScript runtime error: Unable to get property 'addEventListener' of undefined or null reference
and the code that is affected is:
articlelistElement.addEventListener("iteminvoked", itemInvoked);
articleListElement refers to a variable that references a WinJS.UI.Listview.
Thanks for your help!
If your document.getElementById("articlelist") is returning null, then you must be attempting to add the listener before the DOM is actually loaded.
If you started with the Blank project template, then in default.js you'll see this code:
app.onactivated = function (args) {
if (args.detail.kind === activation.ActivationKind.launch) {
if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
// TODO: This application has been newly launched. Initialize
// your application here.
} else {
// TODO: This application has been reactivated from suspension.
// Restore application state here.
}
args.setPromise(WinJS.UI.processAll());
}
};
Until this activated event is called, the DOM won't be ready and getElementById can return null. (For a full run-down of the activation sequence, see Chapter 3 of my free ebook, Programming Windows Store Apps with HTML, CSS, and JavaScript).
If you're using the Navigation or Grid app templates, then you need to place that initialization code inside the page control's ready method (or the processed method). With the Navigation template, you'll see that code in pages/home/home.js. (The same chapter of my free ebook talks about page controls.)
That's the first step--if you're calling getElementById at the right time, then it should give you back the div where you declare the ListView.
There's more to the story, however, because to attach an event handler properly to a WinJS control, you have to make sure that control has been instantiated. This is the purpose of WinJS.UI.processAll in the Blank template code above (the same call is also made automatically as part of loading a page control).
WinJS.UI.processAll (or WinJS.UI.process, which works in an individual element and its children rather than the whole document), goes through the DOM looking for data-win-control attributes. When it finds one, it parses the data-win-options attribute (if you provide one), and then calls the constructor identified in data-win-control with that parsed options object.
Until that happens, the where you declare the control will just be a div and not contain any other control structure.
With page controls, again, within the processed or ready methods the controls should be instantiated. In the Blank template, you need to attach a completed handler to WinJS.UI.processAll:
args.setPromise(WinJS.UI.processAll().then(function () {
//Controls have been instantiated, do initialization here
//Note that calling .then and not .done is necessary because we need to return a promise
//to args.setPromise.
});
At that point, then, document.getElementById("articlelist") should get you to the ListView's host div.
The last step is that to attach a handler to a WinJS control event, you have to add the listener to the control object not the host div, which you get through the .winControl property of that host element. So your code needs to look like this:
articlelistElement.winControl.addEventListener("iteminvoked", itemInvoked);