Now for whatever reason the original author does something on initialization I can't quite make sense of. There is this code which seems to me to be redundant:
if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', init, false);
}
(function() {
/*#cc_on
try {
document.body.doScroll('up');
return init();
} catch(e) {}
/*#if (false) #*/
if (/loaded|complete/.test(document.readyState)) return init();
/*#end #*/
if (!init.done) setTimeout(arguments.callee, 30);
})();
if (window.addEventListener) {
window.addEventListener('load', init, false);
} else if (window.attachEvent) {
window.attachEvent('onload', init);
}
function init()
{
if (arguments.callee.done) return;
arguments.callee.done = true;
// do your thing
//[...]
}
What might the purpose of this be? Or is it nonsense?
The code is making sure that init() function gets called.
It's binding the init function to event listeners that fire when the DOM or page have been loaded.
If those events have already been fired determined by the readyState then it's calling init directly, otherwise it keeps checking every 30 milliseconds for the readyState.
// Call init function when DOM is loaded
if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', init, false);
}
// Immediately invoked function expression that calls init
// function if doScroll method does not throw error.
(function() {
try {
document.body.doScroll('up');
return init();
} catch(e) {}
// Call init function if DOMContentLoaded event has already been
// fired or if page is already loaded.
if (/loaded|complete/.test(document.readyState)) return init();
// arguments.callee is a reference to it's executing function
// which is this immediately invoked function expression.
// It will keep calling it every 30 milliseconds while init
// has not been called yet.
if (!init.done) setTimeout(arguments.callee, 30);
})();
// Call init function when window is loaded.
// `load` event is fired after DOMContentReady, when
// everything has loaded in the page.
if (window.addEventListener) {
window.addEventListener('load', init, false);
// Same as above but for IE versions 8 or less
} else if (window.attachEvent) {
window.attachEvent('onload', init);
}
function init() {
// If init has been called then immediately return.
if (arguments.callee.done) return;
// Set flag on itself to indicate that it init been called.
arguments.callee.done = true;
// do your thing
//[...]
}
Related
I want to execute some part of my addon code on page load, so I'm looking for page load event in browsers.
if (window.addEventListener)
window.addEventListener("load", func, false);
else if (window.attachEvent)
window.attachEvent("onload", func);
function func() {
alert("page loaded");
//my code here
}
In Firefox I'm able to catch load event, but in IE9 I'm unable to get this. Alternately, using jQuery call:
$(document).ready(function(){
//my code here
});
we can get this, but I need this functionality without using jQuery.
This will execute in IE9:
window.onload = func;
To modify your code:
if (window.addEventListener) {
window.addEventListener("load", func, false);
} else if (window.attachEvent) {
window.attachEvent("onload", func);
} else {
window['onload'] = func;
}
The more general event handler attachment would be:
function Subscribe(event, element, func) {
if (element.addEventListener) {
element.addEventListener(event, func, false);
} else if (element.attachEvent) {
element.attachEvent("on" + event, func);
} else {
element['on' + event] = func;
}
}
Subscribe('load', window, func);
maybe you can try this
window.onload = function () {
// do something here
};
I have the following code and the second onload event is not firing:
<script type="text/javascript">
var startime = (new Date()).getTime();
window.onload = function(){ record_visit('ol'); } //ol - onload
window.onload = function(){ setInterval("upState()", 30000); }
window.onbeforeunload = function(){ record_visit('obul'); } //obul = onbeforeunload
function record_visit(value) {
var x = (window.ActiveXObject) ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest();
x.open("GET", "count_visit.php?t=" + (((new Date()).getTime() - startime) / 1000)+"&type="+value+"&url="+escape(window.location.href), false);
x.send(null);
}
function upState()
{
// create the AJAX variable
var xmlhttp;
if (window.XMLHttpRequest)
xmlhttp = new XMLHttpRequest();
else
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
// make the AJAX call
xmlhttp.open("GET", "count_visit.php?t=" + (((new Date()).getTime() - startime) / 1000)+"&type=update&url="+escape(window.location.href), false);
x.send(null);
}
</script>
All I need here is to send request using count_visit.php and update the table that the visitor is still online.
I tried some code I found in some site but still it's not firing. here's the code:
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {
oldonload();
}
func();
}
}
}
addLoadEvent(record_visit('ol'));
addLoadEvent(setInterval("upState()", 30000));
Any help please.
With the second window.onload you are overwriting the one that was defined before. As you are not using jQuery (which makes these things easier) use the following function
function myEvent(where,evt,func,op)
{
if (op)
{
if (where.attachEvent) where.attachEvent("on"+evt,func);
else if (where.addEventListener) where.addEventListener(evt,func,false)
}
else
{
if (where.detachEvent) where.detachEvent("on"+evt,func);
else if (where.removeEventListener) where.removeEventListener(evt,func,false);
}
}
where - object where you are adding your event listener to
evt - the name of the event (without 'on' part)
func - function to be called on event
op - if it is set to true the function will add listener and if it is set to false the function will remove listener.
Call it as myEvent(window, 'load', func, true); And does not matter how many functions you add - all of them will be called at the given event.
ps: or you can just combine the content of both functions manually :))
window.onload = function(){
record_visit('ol');
setInterval(upState, 30000);
}
using this method you have to check the existence of the previous event handler, save it in some global variable and call it later when you will be dealing with execution of the final and the only one window.onload function. You were trying to do it in the last portion of the code.
if you want two functions to fire on window.onload, you could do it like this:
function onload1 (){
alert("onload1");
}
function onload2 (){
alert("onload2");
}
window.onload = function() {
onload1();
onload2();
}
How much I dig into JavaScript, I find myself asking that much. For example we have window.onresize event handler and if I say:
window.onresize = resize;
function resize()
{
console.log("resize event detected!");
}
Wouldn't that kill all other functions which is connected to the same event and just log my message in console?
If so I think there should be another notifier which tells me about window resize event - or a workaround maybe - without overriding other functions which are bound to same event.
Or am I totally confused by its usage?
Instead of replacing such a catch-all handler, you should just add a DOM 2 listener like this:
window.addEventListener("resize", myResizeFunction);
or in more details:
if (window.addEventListener) { // most non-IE browsers and IE9
window.addEventListener("resize", myResizeFunction, false);
} else if (window.attachEvent) { // Internet Explorer 5 or above
window.attachEvent("onresize", myResizeFunction);
}
You can save the old onresize function and call that either before or after your custom resize function. An example that should work would be something like this:
var oldResize = window.onresize;
function resize() {
console.log("resize event detected!");
if (typeof oldResize === 'function') {
oldResize();
}
}
window.onresize = resize;
This method can have issues if there are several onresize functions. You could save the old onresize function as part of a closure and call the old one after your function.
function addResizeEvent(func) {
var oldResize = window.onresize;
window.onresize = function () {
func();
if (typeof oldResize === 'function') {
oldResize();
}
};
}
function foo() {
console.log("resize foo event detected!");
}
function bar() {
console.log("resize bar event detected!");
}
addResizeEvent(foo);
addResizeEvent(bar);
When you call addResizeEvent, you pass it a function that you want to register. It takes the old resize function and stores it as oldResize. When the resize happens, it will call your function and then call the old resize function. You should be able to add as many calls as you would like.
In this example, when a window resizes, it will call bar, then foo, then whatever was stored in window.resize (if there was anything).
One way of doing it is like this:
function resize() { /* ... */ }
var existing = window.onresize;
window.onresize = function() {
if (existing) {
existing();
}
resize();
}
Or you can use something like jQuery which wraps all that stuff in a much simpler construct:
$(window).resize(function() { /* ... */ });
That automatically handles multiple handlers and stuff for you.
I'm using the popular addLoadEvent as follows for all my JS loading:
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {
oldonload();
}
func();
}
}
}
addLoadEvent( locationToggle );
addLoadEvent( step1 );
addLoadEvent( step2 );
addLoadEvent( step3 );
addLoadEvent( getCounties );
addLoadEvent( mapSelection);
Everything I've read suggests this is a fairly bullet proof way of avoiding onload conflicts. And yet this method doesn't appear to working any better than wrapping the functions in an anonymous window.onload function. Both methods are causing identical onload conflicts with this set of functions.
I am loading these functions from within the same file as the addLoadEvent function itself. I'm also using calender.js which is a third party file which uses mootools 1.2.4 in an additional file. My files are otherwise free of Javascript.
First, could someone verify I've not damaged the code and I'm using it right. Second could someone suggest why the above is not resolving the conflicts?
edit
The problem persists with all other Javascript files disabled.
Your code is fine. The problem is that setting event handlers in the DOM 0 way doesn't ensure that they won't replaced by other code.
You may try the new W3C standard addEventListener and the IE version attachEvent, because the handlers you attach by them cannot be replaced by 3rd party code.
// window.onload W3C cross-browser with a fallback
function addLoadEvent(func) {
if (window.addEventListener)
window.addEventListener("load", func, false);
else if (window.attachEvent)
window.attachEvent("onload", func);
else { // fallback
var old = window.onload;
window.onload = function() {
if (old) old();
func();
};
}
}
Note, that IE will execute the function in reversed order not in the order you added them (if this is a concern).
Finally, I don't know when you want to run your code, but if you don't want to wait for images to load you can execute your functions earlier then window.onload.
Dean Edwards has a nice script which will let you to do that.
With this you can attach your functions for an earlier event: document.ready (DOMContentLoaded)
// document.ready
function addLoadEvent(func) {
if (typeof func == "function") {
addLoadEvent.queue.push(func);
}
}
addLoadEvent.queue = [];
//////////////////////////////////////////////////////////////////////////////
// Dean Edwards/Matthias Miller/John Resig
function init() {
// quit if this function has already been called
if (arguments.callee.done) return;
// flag this function so we don't do the same thing twice
arguments.callee.done = true;
// kill the timer
if (_timer) clearInterval(_timer);
// do stuff: execute the queue
var que = addLoadEvent.queue;
var len = que.length;
for(var i = 0; i < len; i++) {
if (typeof que[i] == "function") {
que[i]();
}
}
};
/* for Mozilla/Opera9 */
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", init, false);
}
/* for Internet Explorer */
/*#cc_on #*/
/*#if (#_win32)
document.write("<script id=__ie_onload defer src=javascript:void(0)>"
+"<\/script>");
var script = document.getElementById("__ie_onload");
script.onreadystatechange = function() {
if (this.readyState == "complete") {
init(); // call the onload handler
}
};
/*#end #*/
/* for Safari */
if (/WebKit/i.test(navigator.userAgent)) { // sniff
var _timer = setInterval(function() {
if (/loaded|complete/.test(document.readyState)) {
init(); // call the onload handler
}
}, 10);
}
/* for other browsers */
window.onload = init;
Note: the usage is the same for both methods as it was for your version.
I want to call a function after a document loads, but the document may or may not have finished loading yet. If it did load, then I can just call the function. If it did NOT load, then I can attach an event listener. I can't add an eventlistener after onload has already fired since it won't get called. So how can I check if the document has loaded? I tried the code below but it doesn't entirely work. Any ideas?
var body = document.getElementsByTagName('BODY')[0];
// CONDITION DOES NOT WORK
if (body && body.readyState == 'loaded') {
DoStuffFunction();
} else {
// CODE BELOW WORKS
if (window.addEventListener) {
window.addEventListener('load', DoStuffFunction, false);
} else {
window.attachEvent('onload', DoStuffFunction);
}
}
There's no need for all the code mentioned by galambalazs. The cross-browser way to do it in pure JavaScript is simply to test document.readyState:
if (document.readyState === "complete") { init(); }
This is also how jQuery does it.
Depending on where the JavaScript is loaded, this can be done inside an interval:
var readyStateCheckInterval = setInterval(function() {
if (document.readyState === "complete") {
clearInterval(readyStateCheckInterval);
init();
}
}, 10);
In fact, document.readyState can have three states:
Returns "loading" while the document is loading, "interactive" once it is finished parsing but still loading sub-resources, and "complete" once it has loaded.
-- document.readyState at Mozilla Developer Network
So if you only need the DOM to be ready, check for document.readyState === "interactive". If you need the whole page to be ready, including images, check for document.readyState === "complete".
No need for a library. jQuery used this script for a while, btw.
http://dean.edwards.name/weblog/2006/06/again/
// Dean Edwards/Matthias Miller/John Resig
function init() {
// quit if this function has already been called
if (arguments.callee.done) return;
// flag this function so we don't do the same thing twice
arguments.callee.done = true;
// kill the timer
if (_timer) clearInterval(_timer);
// do stuff
};
/* for Mozilla/Opera9 */
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", init, false);
}
/* for Internet Explorer */
/*#cc_on #*/
/*#if (#_win32)
document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
var script = document.getElementById("__ie_onload");
script.onreadystatechange = function() {
if (this.readyState == "complete") {
init(); // call the onload handler
}
};
/*#end #*/
/* for Safari */
if (/WebKit/i.test(navigator.userAgent)) { // sniff
var _timer = setInterval(function() {
if (/loaded|complete/.test(document.readyState)) {
init(); // call the onload handler
}
}, 10);
}
/* for other browsers */
window.onload = init;
You probably want to use something like jQuery, which makes JS programming easier.
Something like:
$(document).ready(function(){
// Your code here
});
Would seem to do what you are after.
if(document.readyState === 'complete') {
DoStuffFunction();
} else {
if (window.addEventListener) {
window.addEventListener('load', DoStuffFunction, false);
} else {
window.attachEvent('onload', DoStuffFunction);
}
}
If you actually want this code to run at load, not at domready (ie you need the images to be loaded as well), then unfortunately the ready function doesn't do it for you. I generally just do something like this:
Include in document javascript (ie always called before onload fired):
var pageisloaded=0;
window.addEvent('load',function(){
pageisloaded=1;
});
Then your code:
if (pageisloaded) {
DoStuffFunction();
} else {
window.addEvent('load',DoStuffFunction);
}
(Or the equivalent in your framework of preference.) I use this code to do precaching of javascript and images for future pages. Since the stuff I'm getting isn't used for this page at all, I don't want it to take precedence over the speedy download of images.
There may be a better way, but I've yet to find it.
Mozila Firefox says that onreadystatechange is an alternative to DOMContentLoaded.
// alternative to DOMContentLoaded
document.onreadystatechange = function () {
if (document.readyState == "complete") {
initApplication();
}
}
In DOMContentLoaded the Mozila's doc says:
The DOMContentLoaded event is fired when the document has been
completely loaded and parsed, without waiting for stylesheets, images,
and subframes to finish loading (the load event can be used to detect
a fully-loaded page).
I think load event should be used for a full document+resources loading.
The above one with JQuery is the easiest and mostly used way. However you can use pure javascript but try to define this script in the head so that it is read at the beginning. What you are looking for is window.onload event.
Below is a simple script that I created to run a counter. The counter then stops after 10 iterations
window.onload=function()
{
var counter = 0;
var interval1 = setInterval(function()
{
document.getElementById("div1").textContent=counter;
counter++;
if(counter==10)
{
clearInterval(interval1);
}
},1000);
}
Try this:
var body = document.getElementsByTagName('BODY')[0];
// CONDITION DOES NOT WORK
if ((body && body.readyState == 'loaded') || (body && body.readyState == 'complete') ) {
DoStuffFunction();
} else {
// CODE BELOW WORKS
if (window.addEventListener) {
window.addEventListener('load', DoStuffFunction, false);
} else {
window.attachEvent('onload',DoStuffFunction);
}
}
I have other solution, my application need to be started when new object of MyApp is created, so it looks like:
function MyApp(objId){
this.init=function(){
//.........
}
this.run=function(){
if(!document || !document.body || !window[objId]){
window.setTimeout(objId+".run();",100);
return;
}
this.init();
};
this.run();
}
//and i am starting it
var app=new MyApp('app');
it is working on all browsers, that i know.