jQuery - run multiple methods sequentially - javascript

if i do:
method();
method();
both calls will run in parallel (at same time)
i just would like to make the second method(); wait until the first method(); is finished before to start, and do it dynamically cause i can't know how many times i will launch method(); at same time .
Is it possible?
just for example, those runs at same time as i can see... http://jsfiddle.net/Lcgb8/

You could use then if you return a Deferred.
E.g.
function method() {
var d = $.Deferred();
//do something async
setTimeout(function () {
d.resolve('some data'); //inform listeners that the process is completed
}, 2000);
return d; //return the deferred object
}
Then you could do:
method().then(method).then(method).then(method);
Note that the return value of each call will be passed as first argument to the next call, respectively.
EDIT: Here's an example on how you could queue the async operations dynamically.
FIDDLE
function changeColorAsync(color) {
var d = $.Deferred();
setTimeout(function () {
$('body').css('background', color);
d.resolve();
}, 4000);
return d;
}
$(function () {
$('#color-form').on('submit', function (e) {
var color = $(this).find(':checked').val(), d;
d = d?
d.then(changeColorAsync.bind(this, color)) :
changeColorAsync(color);
return false;
});
});

Here is a sequentially animation using transitionend
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>animation</title>
<style>
div{
width:50px;height:50px;background-color:#093;
-webkit-transition:all 300ms ease;
}
div.move{-webkit-transform:translate3d(200px,0,0);}/*GPU HW acceleration*/
</style>
<script>
(function(W){
var D,d,L,c=0;
function init(){
D=W.document;d=D.getElementsByTagName('div');L=d.length;var l=d.length;
while(l--){d[l].addEventListener('transitionend',next,false)}
next();
}
function next(){
d[c].classList[(d[c].className=='move'?'remove':'add')]('move');
c++;c=(c==L?0:c);
}
W.addEventListener('load',init,false);
})(window)
</script>
</head>
<body><div></div><div></div><div></div><div></div></body>
</html>
it had little error fixed now..
supports infinite div's and it's infinite loop using low resources. =)
your method() would be my next()
if someone want's to jsfiddle it... i don't use that.
ps.: pure javascript (no jquery) + css3 (with -webkit prefix);
example
http://jsfiddle.net/4eujG/

Have a look at jQuery.queue().

Using callback:
var test = function (letter, callback) {
console.log(letter);
if (typeof callback !== 'undefined') {
callback();
}
};
Now you can run it:
test('a', function () {
test('b', function () {
test('c')
});
});
The result in console is:
a
b
c
Is it helpful to you?

$( "div" ).promise().done(function() {
$( "p" ).append( " Finished! " );
});
Hope this example must have cleared your query
LIVE DEMO
Javascript, and most other languages, run code sequentially.
Therefore, they will not both run at the same time.
In fact, it is not possible to run two different pieces of Javascript code at the same time. However, in many other languages, it is possible using threads.
However, if they make AJAX calls, the corresponding server-side code called by both functions will run simultaneously.
To prevent that, you'll need to make the first function accept a callback parameter and pass it the second function.

Related

How do I trigger a javascript function if body is clicked after certain seconds?

I need to trigger a window.open function on the click of body, but only if the click is after few seconds.
EXAMPLE:- if the second click is done immediately, it shouldn't open the window. but after 5 seconds, if the click is made, the window should open.
My code isn't working.
<script>
setInterval(myadFunction,5000);
function myadFunction()
{
$("body").click(function () {
window.open("https://www.google.com");
});
}
</script>
This is a wordpress website., and I entered this code before <body> tag.
Why isn't it working?
You can use a flag to simulate what you want. In this case "canClick" flag will do the job for you.Reset it back to true after your desired timeout.
var canClick = true;
$("body").click(function () {
if (canClick) {
window.open("https://www.google.com");
canClick = false;
setTimeout(() => {
canClick = true
}, 5000);
}
});
Let me know if you face any issue with this snippet.
You could try something like:
<button onclick="timeFunction()">Submit</button>
<script>
function timeFunction() {
setTimeout(function(){ window.open("https://www.google.com"); }, 5000);
}
</script>
It consists of this:
setTimeout(functionname, milliseconds, arg1, arg2, arg3...)
The following are the parameters −
functionname − The function name for the function to be executed.
milliseconds − The number of milliseconds.
arg1, arg2, arg3: These are the arguments passed to the function.
First of all. You should make sure that you are placing the code in the right place. Since it's Wordpress. That bugger really get on my nerves. Try putting it in the active theme.
var click_allowed = 0; //global var (you use const if supported)
setTimeout(function(){ click_allowed = 1; },5000);
jQuery('body').click(function(){
if(click_allowed) window.open("https://www.google.com");
});
jQuery has been used instead of $ for the selectors due to wordpress native jquery limitation.
you can use settimeout(function, millisecond)

Make a Testimonial Scroller Stay on the Screen Before Fading Out

I have a testimonial scroller that shows one testimonial, fades out, shows the next, fades out, and returns to the first.
My issue is that after the fade in animation, the fade out animation begins immediately. It doesn't give enough time for someone to read it.
$(document).ready(function() {
function doFade() {
$("#one").fadeIn(6000,function() {
$("#one").fadeOut(6000).delay(3000);
setTimeout(fadeTwo,6000);
});
}
function fadeTwo() {
$("#two").fadeIn(6000,function() {
$("#two").fadeOut(6000).delay(3000);
setTimeout(fadeThree,6000);
});
}
function fadeThree() {
$("#three").fadeIn(4000,function() {
$("#three").fadeOut(6000).delay(3000);
setTimeout(doFade,6000);
});
}
doFade();
});
jQuery's delay function will only delay functions that are called after it in the chain, so it is having no effect on your code. Delay docs
You need to use it before the call to fadeOut, e.g.
$(document).ready(function() {
function doFade() {
$("#one").fadeIn(6000,function() {
setTimeout(fadeTwo,6000);
})
.delay(3000)
.fadeOut(6000);
}
function fadeTwo() {
$("#two").fadeIn(6000,function() {
setTimeout(fadeThree,6000);
})
.delay(3000)
.fadeOut(6000);
}
function fadeThree() {
$("#three").fadeIn(6000,function() {
setTimeout(doFade,6000);
})
.delay(3000)
.fadeOut(6000);
}
doFade();
});
Edit:
You are currently setting a timeout to execute the next function, within the complete callback of fadeIn. This is a bit confusing to my mind, and I think it is simpler and clearer to do something like the following. In addition, there is no reason to define the three functions within the ready function - it is personal preference but I like to keep the amount of code within a callback to a minimum, such as...
$(document).ready(function() {
doFade();
});
function doFade() {
setTimeout(fadeTwo,12000);
$("#one").fadeIn(6000).delay(3000).fadeOut(6000);
}
function fadeTwo() {
setTimeout(fadeThree,12000);
$("#two").fadeIn(6000).delay(3000).fadeOut(6000);
}
function fadeThree() {
setTimeout(doFade,12000);
$("#three").fadeIn(6000).delay(3000).fadeOut(6000);
}
Edit 2:
In further effort to reduce the amount we repeat ourselves, we can extract the whole animation sequence into a function:
$(document).ready(function() {
doFade();
});
function fadeInThenOut(element) {
element.fadeIn(6000).delay(3000).fadeOut(6000);
}
function doFade() {
setTimeout(fadeTwo,12000);
fadeInThenOut($("#one"));
}
function fadeTwo() {
setTimeout(fadeThree,12000);
fadeInThenOut($("#two"));
}
function fadeThree() {
setTimeout(doFade,12000);
fadeInThenOut($("#three"));
}
Edit 3:
At this point we probably notice how similar our three functions are, and want some way to reduce that repetitiveness. So we could use recursion, and just change which element we pass in each time.
$(document).ready(function() {
doFade();
});
function doFade(elementNumber) {
const elementNumber = elementNumber < testimonialElements.length ? elementNumber : 0;
setTimeout(doFade(elementNumber + 1),12000);
$('#' + testimonialElements[elementNumber]).fadeIn(6000).delay(3000).fadeOut(6000);
}
var testimonialElements = ["one","two","three"];
While this solution may lose something in readability and simplicity, the great advantage is that when you add a fourth testimonial, you don't need to write a function to handle it. All you would do is change the testimonialElements array to include the new element id.

how to pass parameter in jquery using .on?

Good Day, this maybe a silly question :) how can I pass a parameter to an external javascript function using .on ?
view:
<script>
var attachedPo = 0;
$this.ready(function(){
$('.chckboxPo').on('ifChecked', addPoToBill(attachedPo));
$('.chckboxPo').on('ifUnchecked', removePoToBill(attachedPo ));
});
</script>
external script:
function addPoToBill(attachedPo){
attachedPo++;
}
function removePoToBill(attachedPo){
attachedPo--;
}
but Im getting an error! thanks for guiding :)
You need to wrap your handlers in anonymous functions:
$('.chckboxPo')
.on('ifChecked', function() {
addPoToBill(attachedPo);
})
.on('ifUnchecked', function() {
removePoToBill(attachedPo);
});
You can also chain the calls to on as they are being attached to the same element.
If your intention is to count how many boxes are checked, via passing variable indirectly to functions try using an object instead like this:
JSFiddle: http://jsfiddle.net/TrueBlueAussie/pBkhX/
var attachedPo = {
count: 0
};
$(function () {
$('.chckboxPo')
.on('change', function () {
if ($(this).is(':checked')) {
addPoToBill(attachedPo);
} else {
removePoToBill(attachedPo);
}
$("#output").prepend("" + attachedPo.count + "<br/>");
});
});
function addPoToBill(attachedPo) {
attachedPo.count++;
}
function removePoToBill(attachedPo) {
attachedPo.count--;
}
If it is not doing anything else you can simplify the whole thing to count checked checkboxes:
$(function () {
var attachedPo = 0;
$('.chckboxPo')
.on('change', function () {
attachedPo = $(".chckboxPo:checked").length;
});
});
"DOM Ready" events:
you also needed to wrap it in a ready handler like this instead of what you have now:
$(function(){
...
});
*Note: $(function(){YOUR CODE HERE}); is just a shortcut for $(document).ready(function(){YOUR CODE HERE});
You can also do the "safer version" (that ensures a locally scoped $) like this:
jQuery(function($){
...
});
This works because jQuery passes a reference to itself through as the first parameter when your "on load" anonymous function is called.
There are other variations to avoid conflicts with other libraries (not very common as most modern libs know to leave $ to jQuery nowadays). Just look up jQuery.noConflict to find out more.

Defer a Function Until Several Animations Complete

I've found a lot of questions about deferring, promises, running javascript synchronously, etc. and I've tried numerous things already but still can't get this to work.
Edit Here's a little more explanation on the problem. fetchData has a routine that depends on all the code inside showStuff being complete. In particular, there's divs that get created using percentage of screen size, and we need to get the height of those divs so we can draw gauges inside them. fetchData is running before slideDown() is complete. Please see the additional console.log code I've added directly below.
My button onClick() calls showOverlay().
function showOverlay() {
showStuff().promise().done( function() {
console.log($("#gauge1").height()); //returns -0.5625 or something close
fetchData(); //ajax call
});
}
function showStuff() {
$("#overlay").fadeIn(200);
$("#gauges").slideDown(800);
$(".gauge").each(function() {
$( this ).show(); //unhides #gauge1 div
});
}
The error I'm getting says: cannot call method 'promise' of undefined.
I'm not showing my fetchData() function but it basically uses ajax to call a web service and then creates gauges on the screen using Raphael. If fetchData runs before the animations are complete the gauges are not displayed correctly because their size is relative to the .gauge div's.
Edit1
Neither of the examples below work. They both run without errors but return too quickly.
function showOverlay() {
showStuff().promise().done(function() {
fetchData();
});
}
function showStuff() {
var def = $.Deferred();
$("#overlay").fadeIn(200);
$("#gauges").slideDown(800);
$(".gauge").each(function() {
$( this ).show();
});
def.resolve();
return def;
}
Doesn't work either:
function showOverlay() {
$.when(showStuff()).done(function() {
fetchData();
});
}
function showStuff() {
$("#overlay").fadeIn(200);
$("#gauges").slideDown(800);
$(".gauge").each(function() {
$( this ).show();
});
}
You've 2 issues, the deferred and thats not how you run animations one after the other.
This will get you part of the way:
function showStuff() {
var deferred = $.Deferred();
$("#overlay").fadeIn(300,function(){
$("#gauges").slideDown(800,function(){
$(".gauge").show(); //doing this one after another takes more code.
deferred.resolve();
});
});
return deferred;
}
Heres the codepen: http://codepen.io/krismeister/pen/pvgKj
If you need to do sophisticated animations like this. You might find better results with GSAP.
Heres how to stagger:
http://www.greensock.com/jump-start-js/#stagger
Try to use $.when() instead:
$.when(showStuff()).done(function() {
fetchData();
});
You a) need to return something from showStuff b) should return a promise directly, so that the .promise() method is unnecessary:
function showOverlay() {
showStuff().done(function() {
fetchData();
});
}
function showStuff() {
return $("#overlay").fadeIn(200).promise().then(function() {
return $("#gauges").slideDown(800).promise();
}).then(function() {
return $(".gauge").show().promise();
});
}

Detecting when jasmine tests complete

I am running jasmine tests like this;
jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
jasmine.getEnv().execute();
I would like to detect, using JavaScript, when the tests complete. How can I?
As #Xv. suggests, adding a reporter will work. You can do something as simple as:
jasmine.getEnv().addReporter({
jasmineDone: function () {
// the specs have finished!
}
});
See http://jasmine.github.io/2.2/custom_reporter.html.
Some alternative ways:
A) Use the ConsoleRunner, that accepts an onComplete option. Older versions (1.2rc1) receive the complete callback as a standalone parameter.
Since you also supply the function that writes (options.print) you keep control about having the test reports written to the console.
You can have several reporters active at the same time jasmineEnv.addReporter().
B) Haven't tried, but you could create your own reporter, with empty implementations of every public method but jasmineDone()
C) Check an old post in the Jasmine google group, where the author saves and overrides jasmine.getEnv().currentRunner().finishCallback:
var oldCallback = jasmineEnv.currentRunner().finishCallback;
jasmineEnv.currentRunner().finishCallback = function () {
oldCallback.apply(this, arguments);
$("body").append( "<div id='_test_complete_signal_'></div" );
};
jasmineEnv.execute();
I found two different ways to solve this issue. One is to hack jasmine to throw a custom event when it completes. Because I wanted to screen scrape after the test loaded, I inserted the event trigger into jasmine-html.js at the end of "reportRunnerResults"
$( 'body' ).trigger( "jasmine:complete" );
Then it's a matter of listening for the event:
$( 'body' ).bind("jasmine:complete", function(e) { ... }
In my case, I was running jasmine in an iFrame and wanted to pass the results to a parent window, so I trigger an event in the parent from my first bind:
$(window.parent).find('body').trigger("jasmine:complete");
It is also possible to do this without jquery. My strategy was to poll for text to be added to the "finished-at" span. In this example I poll every .5 seconds for 8 seconds.
var counter = 0;
function checkdone() {
if ( $('#test-frame' ).contents().find('span.finished-at').text().length > 0) {
...
clearInterval(timer);
} else {
counter += 500;
if (counter > 8000) {
...
clearInterval(timer);
}
}
}
var timer = setInterval( "checkdone()", 500 );
I'm running Jasmine 1.3.1 with the HtmlReporter. I ended up hooking in like this:
var orig_done = jasmineEnv.currentRunner_.finishCallback;
jasmineEnv.currentRunner_.finishCallback = function() {
orig_done.call(this);
// custom code here
};

Categories

Resources