I'm writing a js script that people will add to their web site by adding a single line of code to the header or end of the body part of their HTML.
My question is how to do the onload right on the external js file. Will the code below work? Can't it possibly run after the onload of the document and miss the onload event?
function c_onload () { alert ('onload'); }
if (window.attachEvent) {window.attachEvent('onload', c_onload);}
else if (window.addEventListener) {window.addEventListener('load', c_onload, false);}
else {document.addEventListener('load', c_onload, false);}
(I can't use Jquery or any other library)
What is your last else-clause
else {document.addEventListener('load', c_onload, false);
for? It's rather useless, imho.
The following should be a cross-browser solution: It first checks for addEventListener(), then attachEvent() and falls back to onload = ...
function chain(f1, f2) {
return typeof f1 !== 'function' ? f2 : function() {
var r1 = f1.apply(this, arguments),
r2 = f2.apply(this, arguments);
return typeof r1 === 'undefined' ? r2 : (r1 && r2);
};
}
function addOnloadListener(func) {
if(window.addEventListener)
window.addEventListener('load', func, false);
else if(window.attachEvent)
window.attachEvent('onload', func);
else window.onload = chain(window.onload, func);
}
Also, what kgiannakakis stated
The reason is that browsers handle the onLoad event differently.
is not true: all major browsers handle window.onload the same way, ie the listener function gets executed after the external resources - including your external script - have been loaded. The problem lies with DOMContentLoaded - that's where the hacks with doScroll(), defer, onreadystatechange and whatever else someone has cooked up come to play.
Depending on your target audience, you may either want to drop the fallback code or even use it exclusively. My vote would go for dropping it.
I am afraid that if you can't use jQuery or some other library you need to reproduce a way good deal of their functionality. The reason is that browsers handle the onLoad event differently.
I recommend that you download jQuery's code and see how the documentready function is implemented.
The onLoad event is supposed to be run when the element it is attached to is loaded. But some browsers* misinpret this as "beforeload" or "sometime during load" so the safest option to be sure something is run after all html is loaded, is to add a call to the function on the bottom of the HTML source, like this:
...
<script type="text/javascript">
c_onload();
</script>
</body>
</html>
(* at least some versions of Safari for Windows I do beleave have this issue)
Related
Today I am Playing with DOM readyState,And I find something strange in JQuery.ready(),
JQuery.ready() event occurs before DOMContentload event then i put interactive in my code
like : document.readyState === "interactive"
Then this code is load before Jquery.ready() So, I have a question , is
JQuery.ready() is equal or similar to document.readyState === "interactive?
and What Technique JQuery Applies in there .ready() Event ?
How I apply this .ready() in my pure Javascript ?
I read lots of similar post of that type but no one gives the exact solution to implement JQuery.ready() on JavaScript they all load after DOMContentload not when .ready().
Here MY Jsfiddle
when we browse something the document.readyState can be one of the following:
loading
The document is still loading.
interactive
The document has finished loading and the document has been parsed but sub-resources such as images, stylesheets, and frames are still loading.
complete
The document and all sub-resources have finished loading. The state indicates that the load event is about to fire.
JQuery.ready() is not equal or similar to document.readyState === "interactive because .redyState return a string interactive or loading browser is syncing data from server, when it done it return complete string and create a load event.
The jQuery uses the above functionality to create the doc.ready() for their library.
if you wish to run your function after loading the document, there are many ways... but one of these
function myFun(){
// All your JS code which will use in your document
console.log("Hey now I am ready to run");
}
// just call the myFun() in a eventListene function as callback function
//the myFun will run after the
document.addEventListener('DOMContentLoaded', myFun, false);
A little idea what jQuery does (which will work wherever the script tag is placed).
const ready =(fun) => {
if(document.ready == 'interactive' || document.readyState =="complete"){
// calling function
setTimeout(fun, 1);
}
// we can also implement by event listner
else {
document.addEventListener("DOMContentLoaded", fun);
}
}
ready(() => {
// This is the functin whitch pass to the ready function
console.log("I am ready.")
});
hey I know that is not good but the idea behind it is that.
A little idea what jQuery does (which will work wherever the script tag is placed).
The alternative ways are
if supported, it tries the standard:
window.addEventListener('load', fn, false )
with a fallback to:
document.addEventListener('DOMContentLoaded', fn, false);
with a fallback to:
window.addEventListener('load', fn, false )
or for older versions of IE, it uses:
document.attachEvent("onreadystatechange", fn);
window.attachEvent("onload", fn);
the information taken from :document.ready on MDN
I'm wondering how to add another method call to the window.onload event once it has already
been assigned a method call.
Suppose somewhere in the script I have this assignment...
window.onload = function(){ some_methods_1() };
and then later on in the script I have this assignment
window.onload = function(){ some_methods_2() };
As it stands, only some_methods_2 will be called. Is there any way to add to the previous window.onload callback without cancelling some_methods_1 ? (and also without including both some_methods_1() and some_methods_2() in the same function block).
I guess this question is not really about window.onload but a question about javascript in general. I DON'T want to assign something to window.onload in such a way that that if another developer were to work on the script and add a piece of code that also uses window.onload (without looking at my previous code), he would disable my onload event.
I'm also wondering the same thing about
$(document).ready()
in jquery.
How can I add to it without destroying what came before, or what might come after?
If you are using jQuery, you don't have to do anything special. Handlers added via $(document).ready() don't overwrite each other, but rather execute in turn:
$(document).ready(func1)
...
$(document).ready(func2)
If you are not using jQuery, you could use addEventListener, as demonstrated by Karaxuna, plus attachEvent for IE<9.
Note that onload is not equivalent to $(document).ready() - the former waits for CSS, images... as well, while the latter waits for the DOM tree only. Modern browsers (and IE since IE9) support the DOMContentLoaded event on the document, which corresponds to the jQuery ready event, but IE<9 does not.
if(window.addEventListener){
window.addEventListener('load', func1)
}else{
window.attachEvent('onload', func1)
}
...
if(window.addEventListener){
window.addEventListener('load', func2)
}else{
window.attachEvent('onload', func2)
}
If neither option is available (for example, you are not dealing with DOM nodes), you can still do this (I am using onload as an example, but other options are available for onload):
var oldOnload1=window.onload;
window.onload=function(){
oldOnload1 && oldOnload1();
func1();
}
...
var oldOnload2=window.onload;
window.onload=function(){
oldOnload2 && oldOnload2();
func2();
}
or, to avoid polluting the global namespace (and likely encountering namespace collisions), using the import/export IIFE pattern:
window.onload=(function(oldLoad){
return function(){
oldLoad && oldLoad();
func1();
}
})(window.onload)
...
window.onload=(function(oldLoad){
return function(){
oldLoad && oldLoad();
func2();
}
})(window.onload)
You can use attachEvent(ie8) and addEventListener instead
addEvent(window, 'load', function(){ some_methods_1() });
addEvent(window, 'load', function(){ some_methods_2() });
function addEvent(element, eventName, fn) {
if (element.addEventListener)
element.addEventListener(eventName, fn, false);
else if (element.attachEvent)
element.attachEvent('on' + eventName, fn);
}
There are basically two ways
store the previous value of window.onload so your code can call a previous handler if present before or after your code executes
using the addEventListener approach (that of course Microsoft doesn't like and requires you to use another different name).
The second method will give you a bit more safety if another script wants to use window.onload and does it without thinking to cooperation but the main assumption for Javascript is that all the scripts will cooperate like you are trying to do.
Note that a bad script that is not designed to work with other unknown scripts will be always able to break a page for example by messing with prototypes, by contaminating the global namespace or by damaging the dom.
This might not be a popular option, but sometimes the scripts end up being distributed in various chunks, in that case I've found this to be a quick fix
if(window.onload != null){var f1 = window.onload;}
window.onload=function(){
//do something
if(f1!=null){f1();}
}
then somewhere else...
if(window.onload != null){var f2 = window.onload;}
window.onload=function(){
//do something else
if(f2!=null){f2();}
}
this will update the onload function and chain as needed
A pure JavaScript (no jQuery) method that would not override existing onload events but instead add to it, would be:
window.addEventListener('load', function() {
// do your things here
}
Using jQuery, I can use the following function to execute code as soon as the DOM has loaded:
$(function() {
// do stuff here
});
Or equivalently:
$(document).ready(function() {
// do stuff here
});
In trying to get a better understanding of raw javascript, I'm using this code to achieve a similar effect:
window.onload = function() {
// do stuff here
}
Is this method cross-browser compatible? Are there any better ways to achieve this functionality?
Yes it is cross-browser compatible, but onLoad waits for everything on the page to load before it fires. Internally jQuery.ready uses the DOMContentLoaded event and a few hacks to support older browsers that don't support DOMContentLoaded. Most modern browsers support DOMContentLoaded including IE starting with version 9. You can test whether a browser supports DOMContentLoaded using this page.
If you are not using a DOM library such as jQuery which has built in support for DOMContentLoaded, you could use DOMContentLoaded and then fallback to onLoad if the browser doesn't support it.
(function () { // Encapsulating our variables with a IIFE
var hasRun = false; // a flag to make sure we only fire the event once
// in browsers that support both events
var loadHandler = function (evt) {
if (!hasRun) {
hasRun = true;
console.log('loaded via ' + evt.type);
}
};
document.addEventListener('DOMContentLoaded', loadHandler, false);
window.addEventListener('load', loadHandler, false);
}());
Unless you are expecting visitors with very old browsers like IE8, you are totally safe to just use DOMContentLoaded without a backup.
document.addEventListener('DOMContentLoaded', function (evt) {
console.log('loaded via ' + evt.type);
}, false);
This is similar to what JQuery does:
window.$ = {};
$.ready = function(fn) {
if (document.readyState == "complete")
return fn();
if (window.addEventListener)
window.addEventListener("load", fn, false);
else if (window.attachEvent)
window.attachEvent("onload", fn);
else
window.onload = fn;
}
And to use it:
$.ready(function() {
// code here...
});
The window onload method is cross-browser compatible, but there is a better alternative.
The jQuery ready event fires when the DOM is ready.
The window onload event fires when all data is downloaded.
So, let's say you have lots of images (or one BIG one) on your page. The html file will finish downloading and be ready for manipulation long before the images are done downloading. So jQuery's ready event shoots and you can start doing great JavaScript stuff while all those pretty pics download.
That's one of the reasons it's a good idea to use a js library.
When there aren't that many images then the difference is negligible. Though, you can only set ONE method at a time on the onload event. You can, however, set jQuery's ready event multiple times and each method will get called sequentially.
Cross-browser compatibility would have to depend on how you define the term "browser". Like for instance if it's a text based browser, then it might not be what you're looking for.
To answer your question, it will be cross-browser compatible if that particular browser warrants window.onload feature.
As a general guide, we usually use libraries that are tested so that we allow the libraries to take care of such "cross-browser" compatibility and we deal with the actual application logic.
Hope it helps!
I am having trouble with some JavaScript running before the page is completely rendered in IE 6 (maybe other versions too but just testing IE6 for now. Firefox seems to be OK). I can get around this by calling the js on window.onload like this:
window.onload = function(){doIt();}
However, my concern is the fact that I will overwrite anything else that may already be in window.onload. The code will be used as part of a library so I can not guarantee that window.onload will not be set somewhere else by someone else. I would rather append my function to the onload event like this:
window.onload += function(){doIt1();}
window.onload += function(){doIt2();}
But when I do so, only doit2() is called. Is there a way to register an event handler for when the page is fully rendered? My second thought would be to just put my code in a loop checking to make sure all my objects exist before running. But I am scared that this could potentially lockup the browser.
Just for some background info, my code is hiding/showing iFrames. I know that I can use the iFrame's onload attribute but I need all of the iFrames to be fully loaded before calling the code.
Any thoughts from the community? Thanks in advance for you input.
Use this generic addLoadEvent function...
function addLoadEvent(func) {
if(typeof window.onload != 'function')
window.onload = func;
else {
var oldLoad = window.onload;
window.onload = function() {
if(oldLoad) oldLoad();
func();
}
}
}
This essentially queues up functions to be executed. It never overwrites a previously assigned handler. Sample usage below...
addLoadEvent(function() { alert("One!"); });
addLoadEvent(two);
function two() {
alert("Two!");
}
I want to mention that libraries like jQuery take care of known issues like this for you.
In my ASP.NET User Control I'm adding some JavaScript to the window.onload event:
if (!Page.ClientScript.IsStartupScriptRegistered(this.GetType(), onloadScriptName))
Page.ClientScript.RegisterStartupScript(this.GetType(), onloadScriptName,
"window.onload = function() {myFunction();};", true);
My problem is, if there is already something in the onload event, than this overwrites it. How would I go about allowing two user controls to each execute JavaScript in the onload event?
Edit: Thanks for the info on third party libraries. I'll keep them in mind.
Most of the "solutions" suggested are Microsoft-specific, or require bloated libraries. Here's one good way. This works with W3C-compliant browsers and with Microsoft IE.
if (window.addEventListener) // W3C standard
{
window.addEventListener('load', myFunction, false); // NB **not** 'onload'
}
else if (window.attachEvent) // Microsoft
{
window.attachEvent('onload', myFunction);
}
There still is an ugly solution (which is far inferior to using a framework or addEventListener/attachEvent) that is to save the current onload event:
function addOnLoad(fn)
{
var old = window.onload;
window.onload = function()
{
old();
fn();
};
}
addOnLoad(function()
{
// your code here
});
addOnLoad(function()
{
// your code here
});
addOnLoad(function()
{
// your code here
});
Note that frameworks like jQuery will provide a way to execute code when the DOM is ready and not when the page loads.
DOM being ready means that your HTML has loaded but not external components like images or stylesheets, allowing you to be called long before the load event fires.
I had a similar problem today so I solved it having an index.js with the following:
window.onloadFuncs = [];
window.onload = function()
{
for(var i in this.onloadFuncs)
{
this.onloadFuncs[i]();
}
}
and in additional js files that i want to attach the onload event I just have to do this:
window.onloadFuncs.push(function(){
// code here
});
I normally use jQuery though, but this time I was restricted to pure js wich forced to use my mind for a while!
Mootools is another great JavaScript framework which is fairly easy to use, and like RedWolves said with jQuery you can can just keep chucking as many handlers as you want.
For every *.js file I include I just wrap the code in a function.
window.addEvent('domready', function(){
alert('Just put all your code here');
});
And there are also advantages of using domready instead of onload
Try this:
window.attachEvent("onload", myOtherFunctionToCall);
function myOtherFunctionToCall() {
// do something
}
edit: hey, I was just getting ready to log in with Firefox and reformat this myself! Still doesn't seem to format code for me with IE7.
I don't know a lot about ASP.NET, but why not write a custom function for the onload event that in turn calls both functions for you? If you've got two functions, call them both from a third script which you register for the event.
Actually, according to this MSDN page, it looks like you can call this function multiple times to register multiple scripts. You just need to use different keys (the second argument).
Page.ClientScript.RegisterStartupScript(
this.GetType(), key1, function1, true);
Page.ClientScript.RegisterStartupScript(
this.GetType(), key2, function2, true);
I believe that should work.
You can do this with jquery
$(window).load(function () {
// jQuery functions to initialize after the page has loaded.
});