I still don't have tight grip on promises. Say I have a code:
selected.eq(i) // blink
.fadeOut( 200 ).delay( 50 ).fadeIn( 400 )
.delay( 100 )
.fadeOut( 200 ).delay( 50 ).fadeIn( 400 );
and later I call:
selected.unbind('click')
.promise().done(function ()
{
selected.fadeOut(500);
});
It works as excepted -- once the blinking is done, the last fadeOut
kicks in. But when I do the blinking via plugin (with setup to use jQuery animation) so my entire first part is just one call:
selected.eq(i).modernBlink({
duration: 750,
iterationCount: 3,
auto: true}
);
the body of blink is:
ModernBlink.prototype._fallbackAnimation = function _fallbackAnimation( iterationCount ) {
var self = this,
duration = this.options.duration / 2;
if ( iterationCount > 0 || iterationCount === 'infinite' ) {
iterationCount = iterationCount === "infinite" ? "infinite" : iterationCount - 1;
this.el.animate( { 'opacity': 0 }, duration ).promise().done( function() {
self.el.animate( { 'opacity': 1 }, duration );
self._fallbackAnimation( iterationCount );
});
}
};
so it is recursive call based on promise
as well. The outcome is different -- after first iteration from blink
my code kicks in, because my promise
won.
The visual effect is -- blink, fade out (mine part), keep blinking.
My question is -- how to tell jQuery the blink
promises are more important than mine?
NOTE: I cannot attach directly the second part to the first part, because they are scattered in code, and sometimes the first part is not executed.
The code of blink comes from Modern Blink by leonderijke. MB was used here as example!
UPDATE: Big picture, I don't know if this helpful or not, but anyway:
if (Environment.Mode=='blink') // my private settings variable
call_blink(); // part 1, presented above
call_fade_out(); // part 2, presented above
This is why, I cannot chain them. I have similar "configuration" of code used some more, so I would like to understand it, and use it here and in other places.
Try utilizing the animationend
event
$.each(["webkit", "moz", "MS", "o", ""], function (k, v) {
selected[0].addEventListener(v !== "" ? v + "AnimationEnd" : "animationend"
, function (e) {
$(this).unbind('click')
.promise().done(function (el) {
el.fadeOut(500);
console.log("done")
});
})
})
jsfiddle http://jsfiddle.net/guest271314/x7gqb1g4/
An alternative approach ; "infinite" loop by maintaining count !== 0
, "stop" by calling .stop()
, clearQueue()
setting .data()
flag
// v2
// `d` : duration , `count` : iteration
(function ($) {
$.fn.blink = blink;
function blink(d, count) {
var el = $(this);
$.fx.interval = 0;
return el.each(function (i, elem) {
var elem = $(elem);
elem.data("count", count);
return elem.fadeTo(d, "0", "linear", function () {
elem.fadeTo(d, "1", "linear", function () {
elem.data("count", --count);
return (elem.data("count") !== 0 && !elem.data("stop")
? elem.blink(d, elem.data("count"))
: elem.stop(true, true).data("stop", false))
})
})
}).promise("fx")
};
}(jQuery));
// e.g.,
var selected = $("div")
, button = $("button:first")
, stop = $("button:last");
selected.on("click", function (e) {
// start `$.fn.blink` , log returned `promise` on stop
$(this).blink(750, 10).then(function (el) {
console.log(el, el.queue(), el.data());
})
});
button.on("click", function () {
// unbind `click` event
selected.unbind('click')
.promise().then(function (el) {
el.fadeOut(500);
});
});
stop.on("click", function () {
// stop animation
selected.data("count", null).data("stop", true).clearQueue()
})
jsfiddle http://jsfiddle.net/guest271314/33ptL9do/
You will need to make modernBlink
return a promise that represents the result you are after - the end of the blinking. It simply is impossible to intercept animations that will only be chained in the future. The plugin you're using should return a promise, or at least provide a callback; if it doesn't to that you'll need to use a different one or fork it.
In your case, the blink method will need to repeatedly chain itself to the promise by using then
:
ModernBlink.prototype._fallbackAnimation = function(iterationCount) {
var self = this,
duration = this.options.duration / 2;
if (iterationCount === 'infinite' || iterationCount-- > 0) {
return this.el.animate({'opacity': 0}, duration).promise()
.then(function() {
return self.el.animate({'opacity': 1}, duration).promise();
})
.then(function() {
return self._fallbackAnimation(iterationCount);
});
} else {
return this;
}
};
Now, your big picture might look like this:
if (Environment.Mode=='blink')
var step1 = new ModernBlink()._fallbackAnimation(5);
else
var step1 = jQuery.when(undefined);
var step2 = step1.then(call_fade_out);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With