JavaScript synchronous or not? - javascript

I am using Javascript with the window.onload and window.onbeforeunload functions.
In the onbeforeunload I want to run a code that removes an element from an existing list by iterating through the list via a method, but the method doesn't get executed.
When I use the same method in onload, everything works fine.
I think the code doesn't get executed in the onbeforeunload because the browser is already closed by then and that causes that the method doesn't get executed.
I think I need to do something Sychronous, do you guys have tips on how I can solve this?
// working
window.onload = function()
{
MethodA();
};
// not working
window.onbeforeunload = function()
{
MethodA();
};

Related

jscript onopen event failing to call function

I want to call a function when the browser opens (or reloads)
If I use:
window.onopen = window.alert("opened");
That works fine however:
window.onopen = winopen;
window.onresize = winopen;
function winopen()
{
alert("opened");
}
Does not. The window.onresize call does work, I'm also using the resize event to call a different function but put it in here just to test whether the function call worked at all as I have the resize event function call working elsewhere.
That's because you're misunderstanding a fundamental thing:
window.onopen = window.alert("opened");
Is assigning window.onopen the result of calling window.alert("opened"), which will call the function regardless.
The second way is the correct way of assigning functions, but there is no such event as onopen.
If you want to call a function on each page load, just call it in your .js file without anything else. The file will be parsed and executed every time the page loads.
So basically, you want:
window.onresize = winopen;
function winopen()
{
alert("opened");
}
winopen(); //Call it now.
In some cases, you may want for the DOM to finish loading (all HTML was parsed, browser is ready for DOM manipulation), in that case, you can use window.onload instead of window.onopen in your example.

Ajax .load() won't work when triggered initially

So I have a simple tab system which I handle with the .load function to load the desired content. The problem is that the page itself which contains this tab system is a ajax loaded content. And for some reason the initial call of the tab function to display the initial tab content won't work. But after manually choosing a tab, the load function loads the content properly.
her some code to look at:
The tab handler:
function loadTab(tab) {
$(".tab_a:eq("+otab+")").removeClass("tab_slc");
$('#tab_content').hide();
$('#tab_content').load("include/tab_downloadVersions.html .tab:eq("+tab+")");
$(".tab_a:eq("+tab+")").addClass("tab_slc");
$('#tab_content').fadeIn(function() {});
otab = tab;
}
at the end I call loadTab(tab); and the thing should be initialized. but for some reason the content remains empty. As soon as you manually click on a tab (I have an on click function which calls loadTab(tab) everything starts working)
Because the code by itself works, I think the problem is caused by the other script which handles the page itself. It is also a .load function which loads the page, which loads this tab system.
So do multiple .loads don't like each other? and if so, what can I change?
Thanks in advance ;)
EDIT: I could't post the entire code for some reason, but if you go here you can see the site in action with all the scripts:
n.ethz.ch/student/lukal/paint.net
The tab system is on the download page.
EDIT:-----------------------------------------------------------------------------------------------------------------------------
Big Update
So this is still the same issue but with a slight twist: I did what was recommended in the comments and put my secondary .load() call inside the success call of the first one.
$("#content").load("pages/contact #contentInside", function() {
$("#OtherContent").load("include/info #OtherContentInside");
});
So this works.
But now I had the great idea to make a giant load function. It is a slightly better function than just the plain load, cause it does some fading and stuff. But now I have the same problem, but even more complicated. I created the load function as a "plugin" so the function itself is in a different script file and therefore I can't access the inside of the success function. I solved this problem with a return $.ajax(); and a .done() call. The problem here is that there is some rare case where it just skips the secondary load function. So I am searching for a guaranteed way of controlling the order of the .load calls. Any idea?
The mock-up website is up to date with the new scripts if you wish to take a look. And people were complaining about potential virus spread from my link. For some reason I can't post long code snippets so the site is the best source I got to show everything. If you know a more trustworthy way to share my code please let me know.
We cannot see the rest of your code to tell where the initial call is being invoked from. A set up like the following should work:
$(function() {
var tab = 0;
loadTab( tab );
});
function loadTab(tab) {
//WHAT IS otab???
$(".tab_a:eq("+otab+")").removeClass("tab_slc"); //<<<==== otab
$('#tab_content').hide();
$('#tab_content').load("include/tab_downloadVersions.html .tab:eq("+tab+")");
$(".tab_a:eq("+tab+")").addClass("tab_slc");
$('#tab_content').fadeIn(function() {});
otab = tab;
}
Update
The reason it does not work initial is because otab is not defined the first time the function is called. You have initialized otab at the end of the function but you are using it at the beginning of the function.
UPDATE 2
I have had a chance to look at your code and I just found out what the issues are:
You do not have DOM ready
You are not calling the function on page load.
The following version of your code should work -- try not to use global variable as you're doing with otab. Since you're loading this script at the end of the page (an you are using event delegation) you may get away with DOM ready. Adding .trigger('click') or click() as indicated below should resolve the issue.
//Tab-loader
//Haeri Studios
var tab = 0;
var otab = tab;
var counter = 0;
//click detect
$(document).on('click', '.tab_a', function() {
tab = counter == 0 ? tab : ($(this).attr('id'));
loadTab(tab);
counter++;
return false;
})
.trigger('click'); //<<<<<===== This will call the function when the page loads
//Tab setup
function loadTab(tab) {
//Content Setup
$(".tab_a:eq("+otab+")").removeClass("tab_slc");
$('#tab_content').hide();
$('#tab_content').load("include/tab_downloadVersions.html .tab:eq("+tab+")");
$(".tab_a:eq("+tab+")").addClass("tab_slc");
$('#tab_content').fadeIn(function() {});
otab = tab;
}
//Initialize << WHAT ARE YOUR INTENTIONS HERE .. DO YOU REALLY NEED THIS PIECE?
$.ajax({success: function() {
loadTab(tab);
}});
A partial answer to this problem was to call the loadTab function inside the success call of the page load function, like charlietfl pointed out. But the problem is that there is no need to call the tabloader every time a new page gets called. So I would rather not have a rare call in every page setup function.
I am a bit disappointed by the system on stackoverflow. It seems like if you have not a high reputation level, no one gives a "S" about your questions. Well but at least some input was give, for which I am very thankful.
So by digging deeper into google I found out that the callback can be manually placed in the function where ever you like.
so if we have a function:
foo(lol, function() {
//This after
});
this does stuff after foo() is done. But what if we have another function inside foo() which we also need to wait for:
function foo(lol) {
bar(troll, function() {
//This first
});
}
The bar function is not relevant to the success call of foo. This causes the unpredictable outcome of calls.
The trick is to control when the success function of foo gets called.
If we add a parameter(callback) inside foo and call this "parameter" (callback();) inside the success call of bar, we can make sure the order is guaranteed.
And that's it:
function foo(lol, callback) {
bar(troll, function() {
//This first
callback(); //<-This callback placement defines when it should be triggered
});
}
foo(lol, function() {
//This after
});
We get:
//this first
//this after

Why windows.onload is executed several times?

I'm binding the window.onload event like this
// It's a little more complex than this, I analyze if there is any other function
// attached but for the sake of the question it's ok, this behaves the same.
window.onload = myfunction;
Onload is triggered twice on my local machine a several times on the production server
If I change it by the jQuery equivalent
$jQuery(window).load(myfunction);
It behaves as expected (executed only once).
Could you help me to understand possible reasons why the first option it's not working as supposed?
Thanks!
The parentheses on your assignment — myfunction() — executes your function. You haven't shown what myfunction does, but this means that the return value from that function is being assigned to window.onload, not the function itself. So, I don't know how that is getting executed, unless you have somehow got that to work, like ending the function with return this;
You want
window.onload = myfunction;
Given the nature of window.onload, it seems unlikely that pure browser events alone are making both calls to myfunction. Therefore, a breakpoint inside your function will help you see the call stack. I've included screenshots for Chrome.
Sample code:
var alertme = function() {
alert("Hello");
}
window.onload = alertme;
function testsecondcall() {
alertme();
}
testsecondcall();
Open your page in Chrome.
After the page has loaded once, open the Developer Tools panel and put a breakpoint on the line inside your function, then refresh the page.
Check the call stack of both times that it breaks. One will be empty (the actual window.onload). The other should give you some information like the following:
On the right, under "Call Stack", you see alertme is called by testsecondcall

Javascript Execute After Page Render IE6

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.

Add multiple window.onload events

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.
});

Categories

Resources