Possibly this has been discussed a zillion times and I'm over thinking this, but...
How does one create a 'blocking' jQuery animation?
I have a page which has a 'special' slider animation that executes the first time a user visits the site. But there is a 'normal' slider animation that fires every time the user visits the same page. Since both animations fire with document.ready() they both occur at the same time. What I -want- is for the first animation to fire and then when the user clicks a button to close the window -then- the second animation fires.
//pseudocode
jQuery( init );
function init() {
if(firstVisit) {
Animation1(); //Special. Only shows 1st visit to site
Animation2();
} else {
Animation2();
}
}
}();
Here's the site: http://jchmusic.com
I guess I can re-write the code for -both- so that the second one explicitly starts only when the user clicks the 'close' button on the first animation, but to -me- it would look much cleaner if I could just make the code on the first animation 'blocking'... ie. the second animation doesn't start until the first animation returns. I messed about with SetTimeOut and various 'loops' and all it does is hang the browser... I'm sure this has been mulled over many times.
Any ideas?
Related
I'm new to JavaScript.
I'm writing a simple code to add it in a chrome extension call it Shortkeys.
I just want the code to make a simple action:
Wait for a click of the mouse and then click a button in certain positions of the screen after 500 ms...
This is what I have written until this moment but is not working:
document.addEventListener('click', TimerThenPlay);
function TimerThenPlay(e) {
setTimeout(500)
document.elementFromPoint(1175, 85).click();
stop(TimerThenPlay);
clearTimeout(TimerThenPlay);
return;
};
What I'm doing wrong?
EDIT:
I have an APP running on Chrome...
I need to Click a Link and wait 500 ms to click a button... i can do that manually but sometimes dsnt work and i have to try again..
I realize that chrome has an extension that you can inject to the page a javascript code when u press a key in your keyboard. Thats why im using Shorkeys (if u know a better extension for this, just tell me).
Well... i have assign the < key to run the code...
What i need, is that everytime that i hit the < key... Chrome waits for a click (so i have time to look for the link that i want to open with de button)...
And when i click the link, it waits 500 ms and then click the button in the position that i select ( i cant use the Button ID cause it changes every minute).
I have tried the codes above and it works for the first time.. then, i dnt know why is keeping clicking 500 ms after a make a mouse click in the next pages... How can i stop that loop in the next page?
function TimerThenPlay(e) {
setTimeout(function(){
document.elementFromPoint(1175, 85).click();
stop(TimerThenPlay);
clearTimeout(TimerThenPlay);
},500)
}
SetTimeout method takes two arguments. First is function to execute after second argument time passes.
Hope this helps
Your setTimeout syntax is wrong.
Syntax of setTimeout:
setTimeout(function(){}, time)
you need to update your setTimeout function
function TimerThenPlay(e) {
setTimeout(function(){
document.elementFromPoint(1175, 85).click();
stop(TimerThenPlay);
clearTimeout(TimerThenPlay);
return;
},500)
};
I have an animation that triggers when a link is clicked. It is a jQuery animation that enlarges a div then fades out. To ensure speed, at the exact same time that the link is clicked, the redirect is fired off. This has to happen and I cannot put the redirect in the success function of jQuery's animate(). This redirect is done via a form submission. On Chrome, Firefox, and IE it works as expected, the animation plays and if the page loads entirely before the finish of the animation, it redirects but the animation does play.
On Safari (primarily testing on iPad), as soon as the link is clicked, the page seemingly 'freezes' and the animation fails to execute. There are also GIF's that are on the screen at page load, and if I click a link while those GIF's are on screen and animating, they pause as well. I have seen a post that says to set a timeout, apply styling, then submit, but the problem is that although the HTML will apply that CSS style, it still freezes the screen, and they are not dealing with animation, just static CSS styling.
Here is some example code to show the method of how I am accomplishing this (it is not tested just trying to illustrate my point, so there may be missing parts or syntax errors):
var someData = 'foo'; //This value is irrelevant, just there for syntactical consistency.
$("#link").on("click", function() {
var form = $("<form method='POST'></form>");
form.attr("action", "http://someurl.com");
var input = $("<input type='hidden'/>");
input.val(someData);
form.append(input);
$(document.body).append(form);
form.submit();
//Form has been submitted, now run a short animation for the remaining life of the current page
$(this).animate({width: "100px", height: "100px", opacity: "0"}, 150);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div id="link" style="width: 100px; height: 100px; background-color: #FFF">Click Me</div>
Essentially, I need to make sure that once the Safari browser begins to load a new page / link, it does not stop updating the current page. This sounds like a problem in Safari from what I have seen, but this issue has also not been run into very commonly across the web as I have seen. There are posts dealing with GIF animations, but this is a CSS style animation.
Thanks for any help!
What I have found is that Safari actually pauses all animations as soon as the pagehide event is fired, whenever the browser begins loading a new page.
After pagehide, it won't even allow CSS changes such as showing a spinner that was previously hidden.
In order to show the spinner before the pagehide event fires, I needed to add listeners for a[href] clicks and ajaxComplete events.
My guess is that Safari does this to enhance performamce by focusing all available CPU and GPU power to the rendering of the next page.
I think this is a bit extreme, and unfortunate for UX where in many mobile web applications we use spinner animations at page unload to show the user something is happening during the few seconds while a new page is being fetched.
I have so far not found a way to preserve motion animation during page unload; at best the spinner appears frozen but still shows up... a possible workaround is to use a static message to indicate it's "Loading..."
You could use a setTimeout to go to the link after the animation.
var someData = 'foo'; //This value is irrelevant, just there for syntactical consistency.
$("#link").on("click", function() {
setTimeout(doThisAfterTimeExpires,2000);
$(this).animate({width: "100px", height: "100px", opacity: "0"}, 150);
});
function doThisAfterTimeExpires(){
var form = $("<form method='POST'></form>");
form.attr("action", "http://someurl.com");
var input = $("<input type='hidden'/>");
input.val(someData);
form.append(input);
$(document.body).append(form);
form.submit();
}
Safari complains that it can't find the variable someData, it is trying to set the value of the input to the value of a variable that does not exist and stops executing that portion of the page's JavaScript.
[Error] ReferenceError: Can't find variable: someData
Just create the variable like this:
// [snip]
var input = $("<input type='hidden'/>");
var someData;
input.val(someData);
// [snip]
and it will work in Safari.
Write the code for animation before form submission. Perform form submission after some time. That is:
var someData = 'foo'; //This value is irrelevant, just there for syntactical consistency.
$("#link").on("click", function(e) {
//Write your code for animation at first.
$(this).animate({width: "100px", height: "100px", opacity: "0"}, 150);
//write the code for form submission
setTimeout(function() {
var form = $("<form method='POST'></form>");
form.attr("action", "http://someurl.com");
var input = $("<input type='hidden'/>");
input.val(someData);
form.append(input);
$(document.body).append(form);
form.submit();
}, 1000);
});
Possibly use some Ajax to load the new page in a hidden frame while the animation is still going. When it finishes loading, do a normal redirect to the same URL. Then hopefully it would be an instant redirect since the new page may then be cached and its underlying query already processed.
I had this issue for a long time and tested many differents ways.
I noticed that you still can use css animations, this mean you can still have an nice effect while safari is loading.
But, this require that your animations is not using any delays, Animation have to start as soon as the form is submitted.
For example, I wanted to have 3 car, appearing one after the other, while the page is loading.
As I was using a delay for each car before animation start, only the first one was appearing, then the animations stop, and car2, car3 never appeared.
But, when I removed the delay of the second and third car, this work fine, even if the animation is long.
This mean :
Animation delayed for 1s : Fail, don't even appear
Animation starting at 0s : Works, even if animations duration is above 5s.
So, I assume Safari is stopping all animations, except those already launched
This worked for me.
I had the same issue. Unfortunately, the solution using setTimeout() didn't work for me. With a submit delay the CSS animation starts, but freezes immediately when the page start loading.
So what I finally did, was a special animation, less dynamic, especially for safari browser:
var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
if(isSafari){ // If Safari browser
$("span#loading_without_spinner").css("display", "block"); // This span contains the text "Loading..."
}else{ // Other browsers
$j("span.spinner").css("display", "block"); // This span contains my css svg animation
}
I'm still interested if someone manages to force a CSS animation during a page load.
I have a page where I show a throbber when I navigate away from the page. Like <a onclick="throbber.show()"> on every link. When I now navigate back in Firefox, the throbber is still shown.
Is there any javascript event that is fired to the arriving webpage when I click back? Or one that is fired just when the webpage is changed to the new one? Or can I make my throbber more intelligent?
Thanks for any input!
put this in your html:
<form name="_browser"><input id="checker" value="1" type="hidden"></form>
and also this javascript:
function cacheCheck()
{
var checker = document.getElementById("checker");
if (checker.value == 2) return true;
checker.value = 2;
checker.defaultValue = 2;
return false;
}
function cacheReload()
{
if (cacheCheck()) location.reload(true);
}
and then call cacheReload when your page loads:
<body onload="cacheReload()">
Dldnh's answer inpired me to do some tests. I suspected that the body.onload() event would be called when going back and forth. So I created a simple testpage and found out that this is true in Firefox 10, IE7, IE 8, IE 9 and Chrome 17. Also jQuery(document).ready() will be called.
The very simple solution for hidind the throbber would therefore be either using
<body onload="hideThrobber()">
or using jQuery ready
jQuery(document).ready(function () {
hideThrobber();
};
to hide the throbber then. I implemented this and it seems to work fine on my page. Would be great if somebody with a similar problem could confirm this.
I also found this interesting Stackoverflow question. While it is a little outdated, the point that calling javascript on navigation back and forth slowing down the page is still true. But I would guess that todays JS-Engines are fast enough so this is not a real issue anymore.
If you can't turn off the throbber from the page you navigate to, there are a few things you can do. The trick is that the page will be left active, so you can start up some things before you leave, in the onclick. They aren't perfect though.
Start a timer. The timer will be running when you return to the page, so the timeout routine will be called, and you can switch the throbber off there.
Problem: if you set the timer interval too small, the timeout routine will be called before the user has actually left the page, and the throbber will stop. Or if you set the interval too large, it will take a while before the timeout routine kicks in after they have returned.
Add an event listener to the body that responds to the mousemove event, so that as soon as the user moves the mouse, the routine that turnes off the throbber will be called.
Problem: if the user clicks the browser's Back button, the mouse will be outside the window when the page is redisplayed, so the throbber will remain visible until the user moves the mouse into the window.
So, take your pick. Or do both. Just remember to clean up afterwards - stop the timer, remove the event listener.
I am having a Javascript function which displays timer.
Now,when timer reaches 2 minutes, I want to display a alert and continue my timer function.
But,my timer function stops till user clicks 'Ok' and then resumes from 1:59 secs.
Can anyone tell me how to keep the timer function running while popup box is displayed?
Here's my function to display timer.
var minutes=5;
var seconds=59;
function time_display(){
if(minutes==2 && seconds==0){
setTimeout('display_time_alert_two_minutes_left()',100);
}
if (seconds<=0){
seconds=59;
if(minutes>0)
minutes-=1;
}
else
seconds-=1;
$('time_left_in_minutes').innerHTML = minutes+"."+ ljust_zero(seconds);
setTimeout("time_display()",1000);
}
time_display();
and this is my alert function.
function display_time_alert_two_minutes_left(){
alert('Two minutes left');
}
Alert is a blocker, use custom javascript popups like lightbox,lytebox,jquery dialog,fancybox etc.
Or you can simply show/hide a floating div. This will solve the problem of your timer
getting stuck, and also enhance your user experience.
How about you use something thats no so intrusive, something like this
As alert() stops the rest of the javascript code executing, it would be better to use something that doesn't require an imperitive style of incrementing time.
How about you actually use the time/date functionality, which will 'keep counting'?
Edit : This will stop the web page updating when you call alert() but it will keep counting fine whilst an alert is open.
I have a page that on a certain action makes an iframe visible and fills the iframe with some HTML (say for example a multi-select box and an ok button).
The OK button on the iframe has the onClick method defined kinda like this:
onClick="parent.hideIFrame();parent.processMultiSelectBox();"
When User clicks OK on the iframe (presumably after playing with the multi-select box), I'd like the iFrame to disappear immediately and then the selected values in the multi-select box can be processed. But this is not what's happening. The iFrame remains visible during the time the other function runs and disappears only after the second function finishes.
The hideIFrame function is pretty straightforward:
function hideIFrame() {
frmObj = document.all.iFrameID;
if(frmObj) {
frmObj.style.visibility = "hidden";
}
}
I've paraphrased the above function for clarity (removed some indicator variable assignments etc.)
The second function actually loops on all the options in the multi-select object and does stuff with it. This takes about a half a second and only after that is done, does my iFrame disappear. It is a little bothersome to see it linger for half a second when I click ok.
My question is whether there is some way I can make the darn thing disappear faster. Speaking in "classical C" lingo, is there a "flush" for the change in visibility to happen immediately?
I did notice that if I put an "alert" as the first line in my second function, the iframe disappears immediately but now it is the OK on the alert box that lingers for the time it takes the second function to finish.
Thanks.
EDIT: Based on DDaviesBrackett's answer, this is what I ended up doing:
The onclick in the iframe changed to:
onClick="parent.hideAndProcessMultiSelectBox(parm1, parm2);"
The hideAndProcessMultiSelectBox function was defined as:
function hideAndProcessMultiSelectBox( parm1, parm2 ) {
hideIFrame();
setTimeout( function() { processMultiSelectBox( parm1, parm2 ); }, 0 );
}
Voila.. no delay..
You've gotten to the root of your problem already; document reflow doesn't happen until the current JS thread is done (so as not to repaint lots of times during JS execution). You need to return control to the browser before doing your expensive processing.
The simplest way to achieve that, though it doesn't make for obvious code in the slightest, is to call processMultiSelectBox in a setTimeout with a delay of 0:
onClick="parent.hideIFrame();parent.setTimeout(parent.processMultiSelectBox,0);"
If you need to pass parameters to the thing you're setting a timeout on, you have two options: set a timeout on a string that evals to Javascript (bad, bad, very bad, horrible) or define an anonymous function that calls the one you're interested in:
onClick="parent.hideIFrame();parent.setTimeout(function(){parent.processMultiSelectBox(foo, bar, 'baz');},0);"
RSolberg's response may also help, though there's a difference between visibility:hidden and display:none.