javascript callback context issue - javascript

Trying to make a simple widget.
Steps:
1) Load jQuery if not already there
2) Callback a function
<html>
<head>
<script type="text/javascript">
function load(callback){
console.log('load');
if (typeof jQuery !== "function") {
var js = document.createElement("script");
var he = document.getElementsByTagName('head')[0];
js.type = "text/javascript";
js.src = "http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js";
he.appendChild(js);
js.addEventListener("load", function () {
callback();
});
}
else
{
callback();
}
}
load(function(){
chart();
})
function chart(){
$('#chart').html("id : "+Math.random());
}
// alert('This alert breaks!');
</script>
</head>
<body>
<div id="chart"></div>
</body>
</html>
Code works without alert. Cant understand the context issue
Thanks

Alright, figured out the problem.
Your code is not inside a DOM ready handler.
It will work if the alert isnt there since the function call is asynchronous and the DOM is ready before the AJAX is complete.
but when the alert is there, it create a breakpoint in your code and the DOM will not complete until you click ok. The probleme is that the AJAX request isnt stopped. When you click ok, the AJAX will be finish and run the callback before the DOM is ready.

Move your script block out of the head tag and place it at the end of the body right before </body>.

Related

How can I insert a delay before executing next line in FrontEnd JS script? [duplicate]

Is there an easy hook for detecting that a window opened by a script has finished loading? Basically, I want the equivalent of the onLoad() hook, but I can't set it directly -- assume that the child document is a given and I can't actually put any code of my own in it.
For instance, say I have the following two files:
parent.html:
<html>
<head>
<title>Parent</title>
</head>
<script type="text/javascript">
var w;
function loadChild() {
w = window.open();
w.location.href="child.html";
// block until child has finished loading... how?
w.doSomething();
}
</script>
</html>
<body>
I am a parent window. Click me.
</body>
child.html:
<html>
<head>
<title>Child</title>
</head>
<script type="text/javascript">
function doSomething() {
alert("Hi there");
}
</script>
</html>
<body>
I am a child window
</body>
Since setting location.href is non-blocking, w.doSomething() isn't defined yet and the doSomething() call blows up. How can I detect that the child has finished loading?
This works if the location of the newly opened window is same-origin:
var w = window.open('child.html')
w.addEventListener('load', w.doSomething, true);
The accepted answer does not solve the original problem:
w = window.open();
w.location.href="child.html";
// block until child has finished loading... how?
w.doSomething();
In order to solve this we need to know a little bit more about how page loading goes in the background. Actually it is something asynchronous, so when you write w.location.href="child.html"; and call the w.doSomething(); immediately after that, it won't wait until the new page is loaded. While browser developers solved the loading of the iframes pretty well, the same is not true for child windows. There is no API for that, so all you can do is writing some kind of workaround. What you can do is using the proper defer function from the unload event listener of the child window:
w.addEventListener("unload", function (){
defer(function (){
w.doSomething();
});
});
As usual by client side js development, each of the browsers work completely differently.
The best solution is using a defer function, which calls the callback when the document of the child window is in a loading readyState, where you can add a load handler. If it calls the callback before that, then in the current browsers, the new document is not yet created, so the load handler will be added to the old document, which will be later replaced by the new document, and hence the load handler will be lost. The only exception is Firefox, because that browser keeps the load handlers added to the window. If the browser calls the defer callback after the loading readyState, then in some of the current browsers there can be even more than 2500 msec delay after the page is actually loaded. I have no clue why some of the browsers have such huge delays by some of the defers by child window document loading. I searched for a while, but did not find any answer. Some of the browsers don't have any "loading" defer, so by those all you can do is using a "delayed" defer, and hope for the best. According to my test results a MessageChannel based solution is the best multi-browser "loading" defer:
function defer (callback) {
var channel = new MessageChannel();
channel.port1.onmessage = function (e) {
callback();
};
channel.port2.postMessage(null);
}
So you can do something like:
w.addEventListener("unload", function (){
// note: Safari supports pagehide only
defer(function (){
if (w.document.readyState === "loading")
w.addEventListener("load", function (){
w.doSomething();
});
else
w.doSomething();
});
});
If you want to support Safari, then you should use pagehide instead of unload. The pagehide event is supported from IE 11, so if you want to support even older browsers, then you must use both unload and pagehide and start the defer only with one of them if both are available.
var awaitLoad = function (win, cb){
var wasCalled = false;
function unloadListener(){
if (wasCalled)
return;
wasCalled = true;
win.removeEventListener("unload", unloadListener);
win.removeEventListener("pagehide", unloadListener);
// Firefox keeps window event listeners for multiple page loads
defer(function (){
win.document.readyState;
// IE sometimes throws security error if not accessed 2 times
if (win.document.readyState === "loading")
win.addEventListener("load", function loadListener(){
win.removeEventListener("load", loadListener);
cb();
});
else
cb();
});
};
win.addEventListener("unload", unloadListener);
win.addEventListener("pagehide", unloadListener);
// Safari does not support unload
});
w = window.open();
w.location.href="child.html";
awaitLoad(w, function (){
w.doSomething();
});
If Promises and async functions are supported, then you can use something like the following:
w = window.open();
await load(w, "child.html");
w.doSomething();
but that is a different story...
how about
parent.html:
<html>
<head>
<title>Parent</title>
</head>
<script type="text/javascript">
var w;
function loadChild() {
w = window.open();
w.location.href="child.html";
// like this (with jquery)
$(w).ready(function()
{
w.doSomething();
});
}
</script>
</html>
<body>
I am a parent window. Click me.
</body>

How can I perform a JavaScript function defined into a .js file included in my page from the page?

I am pretty new in JavaScript and I have the following doubt.
Into a JSP page I include a .js file that contains a function definition, in this way:
<script src="<c:url value="resources/js/userAgentInfo.js" />"></script>
Into this userAgentInfo.js file I have define a function, something like this:
function exludeUserAgent() {
...............................................
...............................................
...............................................
if (browserName === "Microsoft Internet Explorer" && majorVersion <= 10) {
alert("EXCLUDE");
return true;
}
return false;
}
Ok, now my problem is: how can I call and perform this exludeUserAgent() function into my page? I have included the file that contain its definition but now I want to perform it when the page is loaded.
Tnx
Write the below code in your JSP page:
<script type="text/javascript">
$(document).ready(function(){
exludeUserAgent()
});
</script>
Just use this single block in your webpage:
<script type="text/javascript"> exludeUserAgent();</script>
if you have jQuery in your page try:
<script type="text/javascript">
$(document).ready(function(){
exludeUserAgent()
});
</script>
if no jQuery is available you can try:
<script type="text/javascript">
window.onload = function(){
exludeUserAgent();
};
</script>
both script blocks just need to be part of your jsp
Typically, I attach an event to the onload event of the window. This will be fired whenever all the resources initially present on the page have loaded (css/html/images/sounds/videos).
To do this, you simply need do the following:
window.addEventListener('load', onDocLoaded, false);
Next, you need a function that will actually handle this event:
function onDocLoaded(evt)
{
/* initialization code goes here */
}
In your case, you'd just need to add a call to the exludeUserAgent function to the body of onDocLoaded.
Wy to wait until the page load?
I think you want to do that immediately when your script file loads.
Just add call to the function on the script file:
exludeUserAgent()
function exludeUserAgent() {
...............................................
...............................................
...............................................
if (browserName === "Microsoft Internet Explorer" && majorVersion <= 10) {
alert("EXCLUDE");
return true;
}
return false;
}
One more note: As you can see you can call the function before you defined it. This is how JavaScript works...

How can I make this function execute automatically / on load [duplicate]

Traditionally, to call a JavaScript function once the page has loaded, you'd add an onload attribute to the body containing a bit of JavaScript (usually only calling a function)
<body onload="foo()">
When the page has loaded, I want to run some JavaScript code to dynamically populate portions of the page with data from the server. I can't use the onload attribute since I'm using JSP fragments, which have no body element I can add an attribute to.
Is there any other way to call a JavaScript function on load? I'd rather not use jQuery as I'm not very familiar with it.
If you want the onload method to take parameters, you can do something similar to this:
window.onload = function() {
yourFunction(param1, param2);
};
This binds onload to an anonymous function, that when invoked, will run your desired function, with whatever parameters you give it. And, of course, you can run more than one function from inside the anonymous function.
Another way to do this is by using event listeners, here's how you use them:
document.addEventListener("DOMContentLoaded", function() {
your_function(...);
});
Explanation:
DOMContentLoaded It means when the DOM objects of the document are fully loaded and seen by JavaScript. Also this could have been "click", "focus"...
function() Anonymous function, will be invoked when the event occurs.
Your original question was unclear, assuming Kevin's edit/interpretation is correct, then this first option doesn't apply
The typical options is using the onload event:
<body onload="javascript:SomeFunction()">
....
You can also place your JavaScript at the very end of the body; it won't start executing until the doc is complete.
<body>
...
<script type="text/javascript">
SomeFunction();
</script>
</body>
Another option is to use a JS framework which intrinsically does this:
// jQuery
$(document).ready( function () {
SomeFunction();
});
function yourfunction() { /* do stuff on page load */ }
window.onload = yourfunction;
Or with jQuery if you want:
$(function(){
yourfunction();
});
If you want to call more than one function on page load, take a look at this article for more information:
Using Multiple JavaScript Onload Functions
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
function codeAddress() {
alert('ok');
}
window.onload = codeAddress;
</script>
</head>
<body>
</body>
</html>
You have to call the function you want to be called on load (i.e., load of the document/page).
For example, the function you want to load when document or page load is called "yourFunction". This can be done by calling the function on load event of the document. Please see the code below for more detail.
Try the code below:
<script src="js/jquery-1.11.0.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
yourFunction();
});
function yourFunction(){
//some code
}
</script>
here's the trick (works everywhere):
r(function(){
alert('DOM Ready!');
});
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}
For detect loaded html (from server) inserted into DOM use MutationObserver or detect moment in your loadContent function when data are ready to use
let ignoreFirstChange = 0;
let observer = (new MutationObserver((m, ob)=>
{
if(ignoreFirstChange++ > 0) console.log('Element added on', new Date());
}
)).observe(content, {childList: true, subtree:true });
// TEST: simulate element loading
let tmp=1;
function loadContent(name) {
setTimeout(()=>{
console.log(`Element ${name} loaded`)
content.innerHTML += `<div>My name is ${name}</div>`;
},1500*tmp++)
};
loadContent('Senna');
loadContent('Anna');
loadContent('John');
<div id="content"><div>

How do I call a JavaScript function on page load?

Traditionally, to call a JavaScript function once the page has loaded, you'd add an onload attribute to the body containing a bit of JavaScript (usually only calling a function)
<body onload="foo()">
When the page has loaded, I want to run some JavaScript code to dynamically populate portions of the page with data from the server. I can't use the onload attribute since I'm using JSP fragments, which have no body element I can add an attribute to.
Is there any other way to call a JavaScript function on load? I'd rather not use jQuery as I'm not very familiar with it.
If you want the onload method to take parameters, you can do something similar to this:
window.onload = function() {
yourFunction(param1, param2);
};
This binds onload to an anonymous function, that when invoked, will run your desired function, with whatever parameters you give it. And, of course, you can run more than one function from inside the anonymous function.
Another way to do this is by using event listeners, here's how you use them:
document.addEventListener("DOMContentLoaded", function() {
your_function(...);
});
Explanation:
DOMContentLoaded It means when the DOM objects of the document are fully loaded and seen by JavaScript. Also this could have been "click", "focus"...
function() Anonymous function, will be invoked when the event occurs.
Your original question was unclear, assuming Kevin's edit/interpretation is correct, then this first option doesn't apply
The typical options is using the onload event:
<body onload="javascript:SomeFunction()">
....
You can also place your JavaScript at the very end of the body; it won't start executing until the doc is complete.
<body>
...
<script type="text/javascript">
SomeFunction();
</script>
</body>
Another option is to use a JS framework which intrinsically does this:
// jQuery
$(document).ready( function () {
SomeFunction();
});
function yourfunction() { /* do stuff on page load */ }
window.onload = yourfunction;
Or with jQuery if you want:
$(function(){
yourfunction();
});
If you want to call more than one function on page load, take a look at this article for more information:
Using Multiple JavaScript Onload Functions
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
function codeAddress() {
alert('ok');
}
window.onload = codeAddress;
</script>
</head>
<body>
</body>
</html>
You have to call the function you want to be called on load (i.e., load of the document/page).
For example, the function you want to load when document or page load is called "yourFunction". This can be done by calling the function on load event of the document. Please see the code below for more detail.
Try the code below:
<script src="js/jquery-1.11.0.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
yourFunction();
});
function yourFunction(){
//some code
}
</script>
here's the trick (works everywhere):
r(function(){
alert('DOM Ready!');
});
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}
For detect loaded html (from server) inserted into DOM use MutationObserver or detect moment in your loadContent function when data are ready to use
let ignoreFirstChange = 0;
let observer = (new MutationObserver((m, ob)=>
{
if(ignoreFirstChange++ > 0) console.log('Element added on', new Date());
}
)).observe(content, {childList: true, subtree:true });
// TEST: simulate element loading
let tmp=1;
function loadContent(name) {
setTimeout(()=>{
console.log(`Element ${name} loaded`)
content.innerHTML += `<div>My name is ${name}</div>`;
},1500*tmp++)
};
loadContent('Senna');
loadContent('Anna');
loadContent('John');
<div id="content"><div>

Delaying a jquery script until everything else has loaded

I have a jquery script which I need to run only once everything else on the page, including some other javascripts (over which I have no control) have finished doing their thing.
I though perhaps there was an alternative to $(document).ready but I haven't been able to find it.
You can have $(document).ready() multiple times in a page. The code gets run in the sequence in which it appears.
You can use the $(window).load() event for your code since this happens after the page is fully loaded and all the code in the various $(document).ready() handlers have finished running.
$(window).load(function(){
//your code here
});
This code block solve my problem,
<script type="text/javascript">
$(window).bind("load", function () {
// Code here
});
</script>
Multiple $(document).ready() will fire in order top down on the page. The last $(document).ready() will fire last on the page. Inside the last $(document).ready(), you can trigger a new custom event to fire after all the others..
Wrap your code in an event handler for the new custom event.
<html>
<head>
<script>
$(document).on("my-event-afterLastDocumentReady", function () {
// Fires LAST
});
$(document).ready(function() {
// Fires FIRST
});
$(document).ready(function() {
// Fires SECOND
});
$(document).ready(function() {
// Fires THIRD
});
</script>
<body>
... other code, scripts, etc....
</body>
</html>
<script>
$(document).ready(function() {
// Fires FOURTH
// This event will fire after all the other $(document).ready() functions have completed.
// Usefull when your script is at the top of the page, but you need it run last
$(document).trigger("my-event-afterLastDocumentReady");
});
</script>
From here:
// Add jQuery
var GM_JQ = document.createElement('script');
GM_JQ.src = 'http://jquery.com/src/jquery-latest.js';
GM_JQ.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(GM_JQ);
// Check if jQuery's loaded
function GM_wait()
{
if(typeof unsafeWindow.jQuery == 'undefined')
{
window.setTimeout(GM_wait,100);
}
else
{
$ = unsafeWindow.jQuery;
letsJQuery();
}
}
GM_wait();
// All your GM code must be inside this function
function letsJQuery()
{
// Do your jQuery stuff in here
}
This will wait until jQuery is loaded to use it, but you can use the same concept, setting variables in your other scripts (or checking them if they're not your script) to wait until they're loaded to use them.
For example, on my site, I use this for asynchronous JS loading and waiting until they're finished before doing anything with them using jQuery:
<script type="text/javascript" language="JavaScript">
function js(url){
s = document.createElement("script");
s.type = "text/javascript";
s.src = url;
document.getElementsByTagName("head")[0].appendChild(s);
}
js("/js/jquery-ui.js");
js("/js/jrails.js");
js("/js/jquery.jgrowl-min.js");
js("/js/jquery.scrollTo-min.js");
js("/js/jquery.corner-min.js");
js("/js/jquery.cookie-min.js");
js("/js/application-min.js");
function JS_wait() {
if (typeof $.cookie == 'undefined' || // set in jquery.cookie-min.js
typeof getLastViewedAnchor == 'undefined' || // set in application-min.js
typeof getLastViewedArchive == 'undefined' || // set in application-min.js
typeof getAntiSpamValue == 'undefined') // set in application-min.js
{
window.setTimeout(JS_wait, 100);
}
else
{
JS_ready();
}
}
function JS_ready() {
// snipped
};
$(document).ready(JS_wait);
</script>
Have you tried loading all the initialization functions using the $().ready, running the jQuery function you wanted last?
Perhaps you can use setTimeout() on the $().ready function you wanted to run, calling the functionality you wanted to load.
Or, use setInterval() and have the interval check to see if all the other load functions have completed (store the status in a boolean variable). When conditions are met, you could cancel the interval and run the load function.
It turns out that because of a peculiar mixture of javascript frameworks that I needed to initiate the script using an event listener provide by one of the other frameworks.
The following script ensures that my_finalFunction runs after your page has been fully loaded with images, stylesheets and external content:
<script>
document.addEventListener("load", my_finalFunction, false);
function my_finalFunction(e) {
/* things to do after all has been loaded */
}
</script>
A good explanation is provided by kirupa on running your code at the right time, see https://www.kirupa.com/html5/running_your_code_at_the_right_time.htm.

Categories