I have a web element that only appears while the page (or a part of the page) is still loading and disappears when the page has been completely loaded. I would like to see precisely when this element disappears and I can do that by repeatedly running something like that in the browser console:
$("div.v-app-loading")
or alternatively:
document.getElementsByClassName('v-app-loading')
But in most cases everything happens too fast and I am unable to catch the exact moment. There must be a way to create a loop that will just run in the console and execute one of the commands I mentioned say every 0.5sec or even more frequently.
Could anyone point me to the right direction?
You can use Javascript's setInterval() as following:
function yourFunction(){
//do something here...
}
setInterval(yourFunction, 500); //Will run the function every half a second(500ms = 0.5s)
Maybe it's easier to use jQuery to detect when the page is loaded:
HTML
<body class="loading">
JS
// do something initially here
$(window).load(function () {
// do something when finished loading
$('body').removeClass('loading');
});
Edit: If you rather wanted to check for existence of an elemtent, do it in a recursive function call. You can throttle it with setTimeout, but you don't need to:
function checkElement() {
if ($('.v-app-loading').length) {
checkElement();
// or: setTimeout(checkElement, 100);
} else {
// Element disappeared
}
}
checkElement();
Related
Alright, right now I'm writing a little JavaScript code that I can just simply copy paste into the Firefox Console and run. (I'm sorry, I'm still a massive noob, and I want to write a little script that basically, opens a certain web page and collects information form certain divs in it.)
However, I'm struggling at the moment. I would like to open a certain webpage, and then, after it is entirely loaded, execute a certain function. (for simplyfying reasons, this function just counts from 0 to 99.)
function openGroupsPage() {
window.location.replace(groupURL);
setTimeout(function() {
for (i = 0; i < 100; i++) {
console.log(i)
}
} , 10000)
}
openGroupsPage()
My problem is : The incrementing function never gets called (or atleast it seems like it because i can never see any kind of output in the console.) Why is my setTimeout not working or what is another option to accomplish what I would like to do? I would just really like to run a specific function when the newly accessed website is finished loading entirely.
When you change the location, the window object and all of its associated things (including timers) are discarded and a new one created. You can't schedule code to run in the new document from within the old document (not even from the browser console). You'll have to paste and execute your code after navigating to the new page, not before, which means you can't navigate to it from within your code.
You might look at tools like TamperMonkey or GreaseMonkey and such that let you run code in response to pages loading that match certain URLs.
window.location.replace() exits the current page and loads a new one. So any remaining JavaScript of the current page isn't executed anymore
Your function is working fine the only problem is window.localtion line reload the website with the url you provided so the entire page is getting reload from start and your page lost your function.
try the below to understand
function openGroupsPage() {
//window.location.replace('http://www.google.com');
setTimeout(function() {
for (i = 0; i < 100; i++) {
console.log(i)
}
} , 1000)
}
openGroupsPage()
You could add an eventListener do the document of the page which fires when the page is loaded.
document.addEventListener('DOMContentLoaded' function(e) {
// page is loaded do you fancy stuff in here
// no timeout needed
});
EDIT: Overlooked that he want to do it over the console on a random page. This won't work because on locationchange all current scripts are stopped and global objects are destroyed.
Use something like Greasemonkey for that.
How to call a function after "Complete page load" and "after all external script execution" ?
I tried all 4 below option, but no luck!!!
$(document).ready..
$(window).load...
window.onload = ...
$(document).ready(function()...
Doing setTimeout works for me, But not sure if this 100% efficient!!!!
setTimeout(function(){
//your code here
}, 3000);
Please advice and help!!!
I have been terribly interested with your question and going deep to the jQuery source I came up with a mad hack :)
But the key point is that you should put this piece of code at the very beginning, right after you plug jQuery:
$.statesNum = 0;
$.fn.ready = function ( fn ) {
$.statesNum++;
jQuery.ready.promise().done( fn ).then(function () {
$.statesNum--;
if ($.statesNum == 0) {
$(document).trigger("afterReady");
}
});
return this;
};
Now whenever you want to execute something after all .ready functions are done you can do like this:
$(document).on("afterReady", function () {
alert("Hey, the ready functions are executed");
});
Scripts are loaded and executed in the order they appear in your HTML. If you have simple scripts, just put things you want to run later at the bottom.
However if you have complex scripts that run asynchronously (meaning they run in parallel), then it is impossible to know if they have finished executing without actually looking at what they do. E.g. do they (or can they) trigger an event that you can listen to? Or maybe you can use "promise" patterns.
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
I want to display a spinner before some complicated function, i.e. dummyCounter(). The code looks like:
function add1() {
msg.html('start counting~<br \>');
document.body.appendChild(div);
spinner.spin(div);
// display spinner before doing stuff
dummyCounter();
}
jsfiddle: http://jsfiddle.net/eGB5t/
However the spinner shows after the dummyCounter() function is finished.
I try to use callback to force spinner display earlier but still no good. Can anybody help? Thanks.
jsfiddle: http://jsfiddle.net/eGB5t/2/
You have a thinking failure. Spinners are usually used for asynchronous tasks, so you can see that there is something in progress. A callback is then used to remove the spin when the async action has finished, since you cannot tell before it starts when it will finish.
I made up a quick example to show you, how such an async function would work in this case, and you can clearly see how the spinner appears slightly before "google finished" appears.
http://jsfiddle.net/eGB5t/4/
I added the following instead of your counting method:
$.ajax("http://google.de").always(function() {
msg.append("google finished");
});
You add the spin before you count, then it counts, then you could remove the spinner. This is perfecty fine. Thing is, if you would count to let's say 9999999999999 (so it would take some seconds), a normal for loop like you're doing is completely blocking the browser, so you won't have any repaints (and therefore no spinner) at all, while the loop is running.
What you would have to do (in this case) is to introduce a worker to have multithreading functionality in javascript.
var x;
function add1() {
msg.html('start counting~<br \>');
spinner.spin(div);
x= setTimeout(document.body.appendChild(div),500);
}
I have several page elements I want to fade out. I then change the css class of them (while they are not visible) then fade them back in.
I thought I had ordered the execution flow properly but sure enough the css class transition is occurring before the fadeOut is complete. Visually what happens is that a person sees the css change and then fadeout occurs.
You can see it at the link below. Between slide 1 & 2 it happens but is not as noticeable as the css change is from class a to class a. Between slide 2 & 3 you can see it as that is from class a to class b.
http://staging.alexandredairy.com
jquery transition code onReady kicks it off:
var txtread =
{
onReady: function(_imgname)
{
txtread.fadeoutText(_imgname);
txtread.fadeinText();
},
fadeoutText: function(_imgname)
{
$("#pagetitle").fadeOut(1250);
$("#pagemenu").fadeOut(1250);
$("#pageslogan").fadeOut(1250);
$("#sitecopy").fadeOut(1550, txtread.TextReadabilityHandler(_imgname));
},
fadeinText: function()
{
$("#pagetitle").fadeIn(1250);
$("#pagemenu").fadeIn(1250);
$("#pageslogan").fadeIn(1250);
$("#sitecopy").fadeIn(1250);
},
TextReadabilityHandler: function(_imgNameSwitch)
{
if(_imgNameSwitch == 'Light')
{
$("#pagetitle").attr('class', 'sitetitle lighttextbackground');
$("#pagemenu").attr('class', 'sf-menu lighttextbackground');
$("#pageslogan").attr('class', 'slogan lighttextbackground');
}
else if (_imgNameSwitch == 'Dark_')
{
$("#pagetitle").attr('class', 'sitetitle darktextbackground');
$("#pagemenu").attr('class', 'sf-menu darktextbackground');
$("#pageslogan").attr('class', 'slogan darktextbackground');
}
else
{ alert(_imgNameSwitch); }
}
}
so I thought order of execution, longer fadeOut, and setting the fadeOut completed function last would keep things in order but alas. I was wrong.
Thank You
Edit
So now I have tried window.setTimeout and it behaves exactly the same as if the timeout doesn't even run???
OK my bad. I originally tried:
window.setTimeout(txtread.TextReadabilityHandler(_imgname), 3000);
and that didn't error or work. I then went back and reread a bit better and saw to use a callback so I rewrote this way:
window.setTimeout(function(){ txtread.TextReadabilityHandler(_imgname); }, 3000);
and now it is working.
My original question still applies though. I understand javascript is an asynchronous programming language but it is imperative no?? Perhaps I am getting terms jumbled in my head.
Does the following execute one after the other:
alert('1');
alert('2');
alert('3');
or do they all execute at once?
Your code includes the following.
onReady: function(_imgname)
{
txtread.fadeoutText(_imgname);
txtread.fadeinText();
}
You are correct in thinking that txtread.fadeinText() will not run until txtread.fadeoutText(_imgname) is complete. However, fadetextOut is completing before you are expecting it to.
fadeoutText: function(_imgname)
{
$("#pagetitle").fadeOut(1250);
$("#pagemenu").fadeOut(1250);
$("#pageslogan").fadeOut(1250);
$("#sitecopy").fadeOut(1550, txtread.TextReadabilityHandler(_imgname));
}
will return almost immediately, having told the various elements to fade out over a period of time. So calling txtread.fadeinText() will not wait for those elements to fade out.
You will need to add some form of callback to fadeinText and fadeoutText, which you can use to let other code know they have finished, like so.
onReady: function(_imgname)
{
txtread.fadeoutText(_imgname, function () {
txtread.fadeinText();
});
}
fadeoutText: function(_imgname, cb)
{
$("#pagetitle").fadeOut(1250);
$("#pagemenu").fadeOut(1250);
$("#pageslogan").fadeOut(1250);
$("#sitecopy").fadeOut(1550, function() {
txtread.TextReadabilityHandler(_imgname);
cb();
});
}
fadeinText: function(cb)
{
$("#pagetitle").fadeIn(1250);
$("#pagemenu").fadeIn(1250);
$("#pageslogan").fadeIn(1250);
$("#sitecopy").fadeIn(1250, cb);
}
The alerts would execute in order. Javascript is single threaded.
Edit: Er, I guess that is true for the most part
Check out this link for a good explination, especially regarding fades, etc.
Is JavaScript guaranteed to be single-threaded?
As Michael said, the javascript will all run at the same time. So, run your fadeout functions, then, once they're finished, call the csschange functions and, once that's complete, run the fade in functions.
I'd be able to write this in jQuery (as it's easy to add a function to run after another is complete). It should be straighforward in plain js, I just don't know the syntax so well . . .
in javascript commands are excuted in order , the thing is if you have error within just one command , it could stop the whole script from excution .
http://www.w3schools.com/js/js_statements.asp
Each statement is executed by the browser in the sequence they are
written.