I'm trying to impliment CSS animation transitions for items displayed in a Nivo Lightbox. I've got the new function inserted and running, but the 2 following functions run before it is complete.
$('.nivo-lightbox-prev').off('click').on('click', function(e){
e.preventDefault();
var index = galleryItems.index(currentLink);
currentLink = galleryItems.eq(index - 1);
if(!$(currentLink).length) currentLink = galleryItems.last();
$this.options.beforePrev.call(this, [ currentLink ]); # <---- new function I added
$this.processContent(content, currentLink); # <---- existing function 1
$this.options.onPrev.call(this, [ currentLink ]); # <---- existing function 2
});
The only way I know would be to put them in a callback, but .call() doesn't accept a callback.
I tried this:
function beforePrev(callback){
$this.options.beforePrev.call(this, [ currentLink ]);
callback();
}
function onPrev(){
$this.processContent(content, currentLink);
$this.options.onPrev.call(this, [ currentLink ]);
}
beforePrev(onPrev);
but it behaved the same.
In case it's relevant the code for beforePrev is:
beforePrev: function() {
el = $('.nivo-lightbox-content');
el.addClass('animated fadeOutLeft');
el.one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function (e) {
el.removeClass('fadeOutLeft');
});
},
Can anyone point me in the right direction?
Update / edit for extra clarity: This is the full original Nivo code: link
From my reading of it, $this
is just a standard variable referring to the init function, not a DOM object. I think this is one of the reasons this seems hard to do.
Turns out deferind / promise is the key here, using jQuery's .when(): http://api.jquery.com/jquery.when/
This answer: How to use "queue" or "deferred" in what condition? What are their designing purpose? helped - .queue() is primarily for animations and acts on a DOM object, whereas .deferred() is for async operations.
So in this example:
$('.nivo-lightbox-prev').off('click').on('click', function(e){
e.preventDefault();
var index = galleryItems.index(currentLink);
currentLink = galleryItems.eq(index - 1);
if(!$(currentLink).length) currentLink = galleryItems.last();
$.when($this.options.beforePrev.call(this, [ currentLink ])).done(function(){
$this.processContent(content, currentLink);
$this.options.onPrev.call(this, [ currentLink ]);
});
});
Then in the beforePrev function, start by setting up a .deferred() object, then .resolve() when it is complete, and finally pass the .promise() back:
beforePrev: function() {
var deferred = $.Deferred();
el = $('.nivo-lightbox-content');
el.addClass('fastAnimated fadeOutRight');
el.one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function (e) {
el.removeClass('fadeOutRight');
deferred.resolve();
});
return deferred.promise();
},