Related
I have some web pages which rely on body.onload (or, equivalently, window.onload) to set them up properly. Sometimes onload is not being called.
Is there a trick with some web browser (ideally Chrome, where this apparently happens most often) which will tell me what exactly is preventing the page from loading successfully?
Clue: this rarely (maybe even never) happens when I hit F5 to reload the whole page, but more generally it happens if a page has been arrived-at by clicking a link or pasting the url into the address bar. Is there a quirk of onload semantics that might be tripping me up?
N.B. The scripts themselves are not producing any errors in the console.
I think you want window.onload
I have tested such cases, and none of the following will work:
var callback = function() { alert("Body loaded"); };
$("body").load(callback);
document.body.addEventListener("load",callback,false);
However, document.body.onload seems to work fine. Make sure that body is correctly namespaced:
document.body //<body>
body //Reference error
If you're talking about:
<body onload="callback();"></body>
Then go back and review your code, because it should work.
Personally, I suggest using the load event of the window object or a framework's ready event.
//Execute when the window is loaded
var callback = function() {
//Your code goes here...
};
if (window.addEventListener) window.addEventListener("load",callback,false);
else window.attachEvent("load",callback);
With jQuery, you only need the following:
$(window).load(callback);
jQuery's ready event is as follows:
$(document).ready(callback);
//Or just:
$(callback);
MooTools use this:
window.addEvent("domready",callback);
And different libraries all have their own way.
window.popup = window.open($(this).attr('href'), 'Ad', 'left=20,top=20,width=500,height=500,toolbar=1,resizable=0');
$(window.popup).onload = function()
{
alert("Popup has loaded a page");
};
This doesn't work in any browser I've tried it with (IE, Firefox, Chrome). How can I detect when a page is loaded in the window (like an iframe onload)?
var myPopup = window.open(...);
myPopup.addEventListener('load', myFunction, false);
If you care about IE, use the following as the second line instead:
myPopup[myPopup.addEventListener ? 'addEventListener' : 'attachEvent'](
(myPopup.attachEvent ? 'on' : '') + 'load', myFunction, false
);
As you can see, supporting IE is quite cumbersome and should be avoided if possible. I mean, if you need to support IE because of your audience, by all means, do so.
If the pop-up's document is from a different domain, this is simply not possible.
Update April 2015: I was wrong about this: if you own both domains, you can use window.postMessage and the message event in pretty much all browsers that are relevant today.
If not, there's still no way you'll be able to make this work cross-browser without some help from the document being loaded into the pop-up. You need to be able to detect a change in the pop-up that occurs once it has loaded, which could be a variable that JavaScript in the pop-up page sets when it handles its own load event, or if you have some control of it you could add a call to a function in the opener.
As noted at Detecting the onload event of a window opened with window.open, the following solution is ideal:
/* Internet Explorer will throw an error on one of the two statements, Firefox on the other one of the two. */
(function(ow) {
ow.addEventListener("load", function() { alert("loaded"); }, false);
ow.attachEvent("onload", function() { alert("loaded"); }, false);
})(window.open(prompt("Where are you going today?", location.href), "snapDown"));
Other comments and answers perpetrate several erroneous misconceptions as explained below.
The following script demonstrates the fickleness of defining onload. Apply the script to a "fast loading" location for the window being opened, such as one with the file: scheme and compare this to a "slow" location to see the problem: it is possible to see either onload message or none at all (by reloading a loaded page all 3 variations can be seen). It is also assumed that the page being loaded itself does not define an onload event which would compound the problem.
The onload definitions are evidently not "inside pop-up document markup":
var popup = window.open(location.href, "snapDown");
popup.onload = function() { alert("message one"); };
alert("message 1 maybe too soon\n" + popup.onload);
popup.onload = function() { alert("message two"); };
alert("message 2 maybe too late\n" + popup.onload);
What you can do:
open a window with a "foreign" URL
on that window's address bar enter a javascript: URI -- the code will run with the same privileges as the domain of the "foreign" URL
The javascript: URI may need to be bookmarked if typing it in the address bar has no effect (may be the case with some browsers released around 2012)
Thus any page, well almost, irregardless of origin, can be modified like:
if(confirm("wipe out links & anchors?\n" + document.body.innerHTML))
void(document.body.innerHTML=document.body.innerHTML.replace(/<a /g,"< a "))
Well, almost:
jar:file:///usr/lib/firefox/omni.ja!/chrome/toolkit/content/global/aboutSupport.xhtml, Mozilla Firefox's troubleshooting page and other Jar archives are exceptions.
As another example, to routinely disable Google's usurping of target hits, change its rwt function with the following URI:
javascript: void(rwt = function(unusurpURL) { return unusurpURL; })
(Optionally Bookmark the above as e.g. "Spay Google" ("neutralize Google"?)
This bookmark is then clicked before any Google hits are clicked, so bookmarks of any of those hits are clean and not the mongrelized perverted aberrations that Google made of them.
Tests done with Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:11.0) Gecko/20100101 Firefox/11.0 UA string.
It should be noted that addEventListener in Firefox only has a non-standard fourth, boolean parameter, which if true allows untrusted content triggers to be instantiated for foreign pages.
Reference:
element.addEventListener | Document Object Model (DOM) | MDN:
Interaction between privileged and non-privileged pages | Code snippets | MDN:
This did the trick for me; full example:
HTML:
Click for my popup on same domain
Javascript:
(function(){
var doc = document;
jQuery('.import').click(function(e){
e.preventDefault();
window.popup = window.open(jQuery(this).attr('href'), 'importwindow', 'width=500, height=200, top=100, left=200, toolbar=1');
window.popup.onload = function() {
window.popup.onbeforeunload = function(){
doc.location.reload(true); //will refresh page after popup close
}
}
});
})();
onload event handler must be inside popup's HTML <body> markup.
First of all, when your first initial window is loaded, it is cached. Therefore, when creating a new window from the first window, the contents of the new window are not loaded from the server, but are loaded from the cache. Consequently, no onload event occurs when you create the new window.
However, in this case, an onpageshow event occurs. It always occurs after the onload event and even when the page is loaded from cache. Plus, it now supported by all major browsers.
window.popup = window.open($(this).attr('href'), 'Ad', 'left=20,top=20,width=500,height=500,toolbar=1,resizable=0');
$(window.popup).onpageshow = function() {
alert("Popup has loaded a page");
};
The w3school website elaborates more on this:
The onpageshow event is similar to the onload event, except that it occurs after the onload event when the page first loads. Also, the onpageshow event occurs every time the page is loaded, whereas the onload event does not occur when the page is loaded from the cache.
The core problem seems to be you are opening a window to show a page whose content is already cached in the browser. Therefore no loading happens and therefore no load-event happens.
One possibility could be to use the 'pageshow' -event instead, as described in:
https://support.microsoft.com/en-us/help/3011939/onload-event-does-not-occur-when-clicking-the-back-button-to-a-previou
Simple solution:
new_window = window.open(...);
new_window.document.write('<body onload="console.log(1);console.log(2);></body>');
When I use the back button on Firefox to reach a previously visited page, scripts on that page won't run again.
Is there any fix/workaround to have the scripts execute again when viewing the page the second time?
Please note that I have tested the same pages on Google Chrome and Internet Explorer and they work as intended.
Here are the files and the steps I used to test the problem:
(navigate to 0.html, click to get to 1.html, back button)
0.html
<html><body>
<script>
window.onload = function() { alert('window.onload alert'); };
alert('inline alert');
</script>
Click Me!
</body></html>
1.html
<html><body>
<p>Go BACK!</p>
</body></html>
Set an empty function to be called on window.onunload:
window.onunload = function(){};
e.g.
<html><body>
<script type="text/javascript">
window.onload = function() { alert('window.onload alert'); };
window.onunload = function(){};
alert('inline alert');
</script>
Click Me!
</body></html>
Source:
http://www.firefoxanswer.com/firefox/672-firefoxanswer.html (Archived Version)
When I use the back button on Firefox to reach a previously visited page, scripts on that page won't run again.
That's correct and that's a good thing.
When you hit a link in Firefox (and Safari, and Opera), it does not immediately destroy your page to go onto the next one. It keeps the page intact, merely hiding it from view. Should you hit the back button, it will then bring the old page back into view, without having to load the document again; this is much faster, resulting in smoother back/forward page transitions for the user.
This feature is called the bfcache.
Any content you added to the page during the user's previous load and use of it will still be there. Any event handlers you attached to page elements will still be attached. Any timeouts/intervals you set will still be active. So there's rarely any reason you need to know that you have been hidden and re-shown. It would be wrong to call onload or inline script code again, because any binding and content generation you did in that function would be executing a second time over the same content, with potentially disastrous results. (eg. document.write in inline script would totally destroy the page.)
The reason writing to window.onunload has an effect is that the browsers that implement bfcache have decided that — for compatibility with pages that really do need to know when they're being discarded — any page that declares an interest in knowing when onunload occurs will cause the bfcache to be disabled. That page will be loaded fresh when you go back to it, instead of fetched from the bfcache.
So if you set window.onunload= function() {};, what you're actually doing is deliberately breaking the bfcache. This will result in your pages being slow to navigate, and should not be used except as a last resort.
If you do need to know when the user leaves or comes back to your page, without messing up the bfcache, you can trap the onpageshow and onpagehide events instead:
window.onload=window.onpageshow= function() {
alert('Hello!');
};
You can check the persisted property of the pageshow event. It is set to false on initial page load. When page is loaded from cache it is set to true.
window.onpageshow = function(event) {
if (event.persisted) {
alert("From bfcache");
}
};
For some reason jQuery does not have this property in the event. You can find it from original event though.
$(window).bind("pageshow", function(event) {
if (event.originalEvent.persisted) {
alert("From bfcache");
}
});
In my case window.onunload with an empty function didn't help (I tried to set a value for dropdown when user uses backwards button). And window.onload didn't work for other reason - it was overridden by <body onload="...">.
So I tried this using jQuery and it worked like a charm:
$(window).on('pageshow', function() { alert("I'm happy"); });
Wire in an "onunload" event that does nothing:
<html><body>
<script type="text/javascript">
window.onload = function() { alert('window.onload alert'); };
window.onunload = function(){};
alert('inline alert');
</script>
Click Me!
</body></html>
As far as i know Firefox does not fire onLoad event on back.
It should trigger onFocus instead based from this link here.
A simple way to cause a page to execute JavaScript when the user navigates back to it using browser history is the OnPopState event. We use this to pause and replay the video on our home page (https://fynydd.com).
window.onpopstate = function() {
// Do stuff here...
};
for some cases like ajax operations url change listener can be used
$(window).on('hashchange', function() {
....
});
I am developing a web-based javascript/html application with a sister firefox-extension.
The application's page-javascript performs a few XHR calls immediately after page-load, in order to bring in and display all the content that the page requires.
Is there a way, without polling the DOM, that my extension can know that the page's initialisation procedures are complete?
Interesting question indeed..
I've just found out through this post on MozillaZine's forum an easy way to accomplish this. The technique basically consists in defining a custom DOM element within the web page, filling it with some arbitrary attributes, and then using it as the target of a custom event. The event can than be captured and used to pass values from the webpage to the extension.
Web page (assumes jquery is available)
<script type="text/javascript">
$(document).ready(function(){
$.get("http://mywebsite.net/ajax.php",function(data){
//[...]process data
//define a custom element and append it to the document
var element = document.createElement("MyExtensionDataElement");
element.setAttribute("application_state", "ready");
document.documentElement.appendChild(element);
//create a custom event and dispatch it
// using the custom element as its target
var ev = document.createEvent("Events");
ev.initEvent("MyExtensionEvent", true, false);
element.dispatchEvent(ev);
});
});
</script>
Chrome code:
function myListener(e) {
alert("data:" + e.target.getAttribute("application_state"));
}
function on_specialpage_load(event) {
if (event.originalTarget instanceof HTMLDocument &&
event.originalTarget.location.href == "http://mywebsite.net/myspecialpage.html") {
var doc=event.originalTarget;
doc.addEventListener("MyExtensionEvent", myListener, false, true);
}
}
gBrowser.addEventListener("DOMContentLoaded",on_specialpage_load,false);
Notice that doc.addEventListener has a fourth parameter, indicating that it will accept events coming from untrusted code. However you can add this event listener selectively, so that only trusted pages from your site will be able to pass values to the extension.
You could hook into the XMLHttpRequest object from your extension and monitor the requests, similar to what this GreaseMonkey script does (description). Add a wrapper to onreadystatechange in the same way he's added a wrapper to open which notifies the extension when complete. Probably also want some code which makes sure you're only doing this when visiting your own page.
Firebug does similar stuff for its Net panel, the codebase for that is a bit more intimidating though :) I also had a look at the Firebug Lite watchXHR function, but that code is a bit too cunning for me, if you can work it out let me know.
I'm having some issues with a jQuery AJAX call. My code works fine when I request a page with no javascript in it, but when I have script tags in my code, things start to get weird.
It seems that any script tags referencing external URLs cause the browser to redirect. In firefox, the page goes blank. In safari, the page clears and loads with the content of the AJAX response. In both browsers, the URL doesn't change.
To be specific about my problem; I have a tab control in which I'm trying to embed the walkscore widget. Since it's pretty heavy on the client side, I only want to actually load it once the user clicks the tab it's in. The walkscore AJAX page looks like this:
<script type="text/javascript">
var ws_address = "1 Market St, San Francisco";
var ws_width = "500";
</script>
<script type="text/javascript" src="http://www.walkscore.com/tile/show-tile.php?wsid=MY_WSID">
</script>
Is there some restriction on script tags referencing external sites on AJAX calls? Is there any nice way around this?
-- Edit --
OK I've been playing with it for a bit and have narrowed down the problem a little. Let me try give a better explanation at the same time:
I have two files, index.html and walkscore.html
index.html
function widget() {
var widget = $('#walkscore');
$.get('/walkscore.html', function(data) {
$('#loading').slideUp(function() {
widget.html(data);
loaded[name] = true;
widget.slideDown();
});
});
}
walkscore.html - as shown in the top code block
In index.html, I have a link that calls the widget function. Whenever I click this link, the whole page is replaced by the output of the js file. It happens regardless of the domain the js file is from. It only seems to happen with js files that have document.write in them. It behaves in exactly the same way when I use the $.getScript function, even when it's in index.html
-- Edit --
It seems it has everything to do with the document.write. I made a copy of the walkscore javascript and replaced all occurrences of document.write with jquery.html, and it seems to work properly. I'm (obviously) a js noob. Is this the expected behavior of document.write? How come it doesn't do it when I include the script on a page load?
Load script separately from html content, you can use $.getScript( ).
It has to do with the document.write in the response.. I was able to fix this in Firefox by doing this:
<script type="text/javascript">
// save default document.write function so we can set it back
var write_func_holder = document.write;
// redefine document.write to output text target div
document.write = function(text) {
$('#ad_container').html($('#ad_container').html() + text);
}
</script>
<script language="JavaScript" type="text/javascript" src="javascriptfile">
</script>
<script type="text/javascript">
// reset document.write function
document.write = write_func_holder;
</script>
I'm still getting an issue in Safari where the browser refreshes to a blank page with just the content of the document.write and IE6, IE7 doesn't do anything at all. Firefox works though.
I hope this helps someone figure out what wrong and they in turn can fix the IE6/7 and Safari issues
It happens because of the document.write call. Here's some info on what's going on:
Writing After A Page Has Been Loaded
If document.write() is invoked after a page has finished loading, the entire static (non-script generated) content of a page will be replaced with the write method's parameter. This scenario is most often played out when the write method is invoked from an event handler - whether the method is in a function called by the event handler or alone inside the handler - because event handlers are triggered after a page has finished loading. This is important to know because static content replacement is not always the desired result. Another common scenario for content overwite has to do with writing content to a new window. In this case, the overwrite of blank page is the goal.
(source)
The solution I went with was to eliminate the document.write commands, and replace the content of a div instead. If you're loading an external script, and have no control over it, you can replace the document.write function with your own. It's discussed here:
http://www.webxpertz.net/forums/showthread.php?threadid=11658
Hope that helps someone out there!
Replacing document.write is the way to go. This is shameless self promotion, but if you have a non-trivial case, writeCapture.js handles all the edge cases.
I would first check the response of that script source, maybe something in that causes the unwanted behavior.
I am experiencing the EXACT same behaviour and spent some frustrating hours last night trying to figure out what the problem was and searching for answers to no avail. I'm surprised this is mentioned anywhere in the jquery docs as it seems like a plausible problem not some crazy never-to-be-encountered bug.
Anyway, here's my story in case anyone searches for something related.
I have a jquery enabled page that loads some content into a div using $.ajax(), it all works perfectly. What I needed to do was include one of those twitter retweet buttons that shows a count and enables you to tweet about the content on the page. To do this a simple piece of javascript from them should be included on the page.
<script type="text/javascript" src="http://www.retweet.com/static/retweets.js"></script>
So in theory, that script tag should be returned in the ajax call and jquery should execute it and include the result of it, as I specified the data type as html in the $.ajax() call.
The external script on closer inspection does:
if(!url)
{
var url=window.location.href;
}
if(!size)
var size="big";
var height="75";
var width="54"
if(size=="small")
{
height="22";
width="120";
}
if(!username)
var username="none";
url=url.replace("?", "*");
var src="http://www.retweet.com/widget/button/"+size+"/"+username+"/"+url;
document.write('<iframe src="'+src+'" height="'+height+'" width="'+width+'" frameborder="0" scrolling="no"></iframe>');
Which obviously bombs out on the document.write.
Tonight i'll try the methods in this post and see if they work, thanks for the info.