0

I am writing a little plugin like this:

(function($){
  $.fn.extend({
    myplugin: function (callback) {
      return this.each(function(){
        $(this).one('load',function(){
          // Manipulate Images
        }) ;
      }) ;
    }
  }) ;
})(jQuery);

I want to fire a callback after plugin finishes its job:

jQuery('img').myplugin({function(){
  // Do something
}) ;

How can I do this?

Edit: It is still not solved, even I got a minus point because of my question found not clearly specified. But it must be obviously a little bit tricky solution. Are there any js ninja who can solve this?

Thank you!

Munawir
  • 3,346
  • 9
  • 33
  • 51
Digerkam
  • 1,826
  • 4
  • 24
  • 39

4 Answers4

2

I would use deferred objects:

(function($) {

    $.fn.extend({
        myplugin: function (callback) {

            // create array of deferred objects to track loading
            var dfds = this.map(function(ix, el) {
                return $.Deferred(function(def) {
                    $(el).one('load', def.resolve)
                         .one('error', def.resolve);
                }).promise();
            }).get();

            // register the final callback
            $.when.apply($, dfds).done(callback);

            // and chain
            return this;
        }
    }) ;
})(jQuery) ;

See http://jsfiddle.net/Yq4Mf/1/ (thanks @salexch for the initial fiddle which I've then forked with my answer)

Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • @salexch the problem with that version is that it'll fire the alert as soon as _any_ image fails, rather than waiting for every image to do its thing. That's why my version above uses `.resolve` both for success and failure. – Alnitak Jan 19 '13 at 08:57
  • @salexch and that's why it's wrong - `$.when()` will fire immediately there's any `.reject` in its list, and not wait for any other outstanding deferred items to be resolved. p.s. there's no need to wrap `task.resolve` in a closure, you can pass it directly as a callback. – Alnitak Jan 19 '13 at 09:00
  • Wow Thank you!! Thats script has many features that I dont know! What does "this.resolve" mean? Can I replace my image manipulation function with it? – Digerkam Jan 19 '13 at 10:11
  • 1
    @Digerkam `.resolve` is used to "complete" the promise that a deferred object returns. (A deferred object returns a "promise" to return something later, instead of returning a value now). You can put a different function there, but make sure you call `def.resolve()` at the end of that function. NB: I've added the `def` parameter to `$.Deferred()` and changed `this` to `def` so you can do that. – Alnitak Jan 19 '13 at 10:56
  • Could you share an example for custom function? Sorry I didnt get where I should put my function that handle each image.. – Digerkam Jan 19 '13 at 11:31
  • I never used deffered helpers before, but I prepared this: http://jsfiddle.net/akkara/wZCJY/2/ looks work fine, what is your opinion about it? does "when" work with job array also? Thank you! – Digerkam Jan 19 '13 at 11:41
  • @Digerkam see http://jsfiddle.net/Yq4Mf/2/ for example including image handling. What do you mean by "job" array? – Alnitak Jan 19 '13 at 11:44
1

Easiest solution would be

 var cnt = 0;    
 (function($){
    $.fn.extend({
        myplugin: function (callback) {
            cnt = this.length;
            return this.each(function(){
                $(this).one('load',function(){
                    // Manipulate Images

                    // Fire callback
                    if (--cnt==0) callback();
                }).error(function(){
                   if (--cnt==0) callback();
                }) ;
            }) ;
        }
    }) ;
})(jQuery) ;
Wolf
  • 2,150
  • 1
  • 15
  • 11
0

Try this:

(function($){
    $.fn.extend({
        myplugin: function (callback) {
            this.each(function(){
                $(this).one('load', function() {
                    // Manipulate Images
                }) ;
            });
            callback();
            return this;
        }
    }) ;
})(jQuery);

Edit: Reverted. Your question is not very clearly specified...

Cecchi
  • 1,525
  • 9
  • 9
0

A solution :

(function($){
    $.fn.extend({
        myplugin: function (callback) {
            var nb = this.length;
            return this.each(function(){
                $(this).one('load',function(){
                    // Manipulate Images
                    if (--nb==0) callback();
                }) ;
            }) ;
        }
    }) ;
})(jQuery) ;
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758