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();
}
Related
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
//[...]
}
I am facing very strange thing with AJAX and Unobtrusive JavaScript that I have two pages
ajaxcontent.php
index.php
index.php has
<div id="cont"></div>
<input type="button" id="a" value="load plz.">
<script type="text/javascript">
document.getElementById('a').onclick = function () {
if (window.XMLHttpRequest) {
ari = new XMLHttpRequest();
} else {
ari = new ActiveXObject("Microsoft.XMLHTTP")
}
ari.onreadystatechange = function () {
if (ari.readyState == 4 && ari.status == 200) {
document.getElementById('cont').innerHTML = ari.responseText;
}
}
ari.open("GET","button.php",true);
ari.send();
}
document.getElementById('b').onclick = function () {
alert('a');
}
</script>
And ajaxcontent.php has only
<input type="button" id="b"/>
and the problem is unobtrusive Javascript is not working.
After laoding of ajaxcontent when i click on button it doesn't show alert pop up.
i have tried that i added
document.getElementById('b').onclick = function () {
alert('a');
}
this code on ajaxcontent.php but it still not working.
THe only way to make it work that i have to add inline javascript as
<input type="button" id="b" onclick="hi();"/>
and replace this function with
document.getElementById('b').onclick = function () {
alert('a');
}
with
function hi() {
alert('a');
}
so please help me that how to use unobtrusive js here and please don't give jQuery based answer thanks
First of all document.getElementById('b') can only find an element that is in the DOM at the time you call this function.
Because the element with the id b is in the data you request in the click event, the function will not find any element. You most likely should have seen an error in the console like cannot set property onclick of undefined.
AJAX requests are async by default (and you should not make them sync because this will block the window of the browser).
So you need to place the document.getElementById('b').onclick = ... in the onreadystatechange check right after the document.getElementById('cont').innerHTML = ari.responseText;
Here a simple example how to generalize your request:
function doAjaxRequest(url, complete, error) {
var ari; //<<<< you should define your variables using var otherwise it is set in the global scope
if (window.XMLHttpRequest) {
ari = new XMLHttpRequest();
} else {
ari = new ActiveXObject('Microsoft.XMLHTTP');
}
ari.onreadystatechange = function() {
if (ari.readyState === 4) {
if (ari.status === 200) {
// if complete callback is passed, then call it if request was successful
if (typeof complete === 'function') {
complete(ari.responseText);
}
} else {
// if error callback is passed then call it if request was not successful
if (typeof error === 'function') {
error(ari.status, ari.statusText);
}
}
}
}
ari.open('GET', url, true);
ari.send(null);
}
document.getElementById('a').onclick = function() {
doAjaxRequest('button.php', function( data ) {
document.getElementById('cont').innerHTML = data;
document.getElementById('b').onclick = function() {
alert('a');
}
}, function(errorCode, errorMessage) {
//do something on error
});
}
The onclick event attaches to elements currently in the DOM when the function is triggered. Because the button in ajaxcontent.php is added to the DOM after the function was called, no event is attached.
To rectify this, you can add a snippet inside ari.onreadystatechange to detatch events then attach the event again.
ari.onreadystatechange = function () {
if (ari.readyState == 4 && ari.status == 200) {
document.getElementById('cont').innerHTML = ari.responseText;
// remove events
document.getElementById('b').onclick = null;
// attach events
document.getElementById('b').onclick = function() {
alert('a');
}
}
}
It's important to remove events because it may (although i was using jQuery when i learnt by mistake) cause double execution.
If you add javascript code inside ajaxcontent.php, that code will not be executed unless you extend your ari.onreadystatechange function to scan for javascript and execute it. The way I do this, is I put my javascript in AJAX requested pages in a input with class 'ajax-js' and scan for those input boxes and execute the code one by one, removing the class as I go.
I'm using this code, which has stemmed from here and here.
$('#my_button').on('click', function (e) {
var iframe = document.createElement('iframe');
iframe.id = "my_iframe";
iframe.onload = function() {
var doc = iframe.contentDocument || iframe.contentWindow.document;
doc.getElementsByTagName('body')[0].innerHTML = "<p>test123</p>";
iframe.contentWindow.focus();
iframe.contentWindow.print();
$("#my_iframe", top.document).remove();
};
document.getElementsByTagName('body')[0].appendChild(iframe);
});
Without the remove line, it prints fine. However, the remove line removes the iframe before it has a chance to execute the print(). How can I set up some kind of callback so that it prints and only then removes the iframe?
Thanks.
I found this solution when I was searching for print event detection:
http://tjvantoll.com/2012/06/15/detecting-print-requests-with-javascript/
Here I add the JS code as requested by Stano, but it is important to also read the whole linked post as there are limitations to this approach. In general the post is about the onafterprint event that only works in IE and a solution to make that event work in other browsers.
(function() {
var beforePrint = function() {
console.log('Functionality to run before printing.');
};
var afterPrint = function() {
console.log('Functionality to run after printing');
};
if (window.matchMedia) {
var mediaQueryList = window.matchMedia('print');
mediaQueryList.addListener(function(mql) {
if (mql.matches) {
beforePrint();
} else {
afterPrint();
}
});
}
window.onbeforeprint = beforePrint;
window.onafterprint = afterPrint;
}());
create a function like this:
function printIframe(iframe,callback) {
iframe.contentWindow.print();
if (callback && typeof(callback) === "function") {
// execute the callback, passing parameters as necessary
callback();
}
}
and call it instead of the other two functions like this.
printIframe(iframe,function(){ $("#my_iframe", top.document).remove();})
if you like you can also put in a delay using the setTimeout.
setTimeout(function() {alert('hello');},1250);
Now, I have a problem with the ajax call which is when the web page is loaded, in the onload event of body, I assign it to call the functions which are startCount() and updateTable() this two functions contain the code that use ajax call to get the data from DB on the server side. The problem is when the ajax return it will return only one call and another call does not response. Please help me what happen and how I can slove it.
This is the onload in the body
<body onLoad="setAjaxConnection();startCount();updateTable()">
I use the XMLHttpRequest with the normal javascript, I do not use jQuery....
Use javascript closures. This link may help
http://dev.fyicenter.com/Interview-Questions/AJAX/How_do_I_handle_concurrent_AJAX_requests_.html
function AJAXInteraction(url, callback) {
var req = init();
req.onreadystatechange = processRequest;
function init() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
function processRequest () {
if (req.readyState == 4) {
if (req.status == 200) {
if (callback) callback(req.responseXML);
}
}
}
this.doGet = function() {
req.open("GET", url, true);
req.send(null);
}
this.doPost = function(body) {
req.open("POST", url, true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.send(body);
}
}
function startCount() {
var ai = new AJAXInteraction("/path/to/count.php", function(){alert("After startCount");});
ai.doGet();
}
function updateTable() {
var ai = new AJAXInteraction("/path/to/update.php", function(){alert("After updateTable");});
ai.doGet();
}
Have the 'onSuccess' of one call initiate the next ajax call. So you would call startCount() and when that returns you fire off updateTable().
function setAjaxConnection(){
//call Ajax here
setAjaxConnectionResponce;
}
function setAjaxConnectionResponce(){
//on readystate==4
startCount();
}
function startCount(){
// code for count
updateTable();
}
function updateTable(){
// code for update
}
<body onLoad="setAjaxConnection();">
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.