Simplest way to add callbacks to a jQuery plugin

I’ve looked at adding callbacks to a jQuery plugin and they all seem quite convoluted and use .call(this). E.g.

http://stackoverflow.com/questions/2534436/jquery-plugin-adding-callback-functionality/2534466#2534466

I’ve got it to work like this:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title></title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script>
    
        ;(function($){
        
            $.fn.pluginName = function(options) {  
            
                /**
                 * Defaults
                 */
                var defaults = {  
                
                    foo: 'bar',
                    init: function () {},
                    complete: function () {}
                
                };
                
                
                /**
                 * Options
                 */
                var options = $.extend(defaults, options);
                var objArray = this;
        
        
                /**
                 * Return each object
                 */
                return this.each(function() {
                
                    options.init($(this).attr('id'));
                
                 });        
            
            };
        
        })(jQuery);
    
        $(function() {
        
            $('div').pluginName({
            
                init: function(id) { alert(id); },
                complete: function() { }
            
            });
        
        });
    
    </script>
</head>
<body>
    <div id="1"></div>
    <div id="2"></div>
</body>
</html>

It seems simpler to just pass the functions as regular options/parameters. Am I missing something? Is there something mine doesn’t do that the example does?

I’ve looked at adding callbacks to a jQuery plugin and they all seem quite convoluted and use .call(this).

that is done to retain the execution context since the execution context in the jQuery method (when called) may differ (e.g. any event listeners are executed on the DOM elements itself, not on their jQuery pendents).

It seems simpler to just pass the functions as regular options/parameters.

sometimes (e.g. when a callback is something like a required parameter) it makes more sense to pass in a callback directly (think of $.post()) than an optional (!) option.

Thanks. Would you mind giving an example? Sorry, I’m not quite sure what you mean.

example of what?

Sorry, I wasn’t clear. I’ve looked into this a bit more. Are you saying that when you call the callback using call(this, …) the “this” in the DOM element in its current state rather than a cached jQuery object?

No.

consider this example:

$('div').on('click', function (evt) {
    console.log(this.toString());
});

Perhaps an example will help. As Dormilich says, it’s all about execution context:

<div id="myDiv">hi</div>

$.fn.myPlugin = function(opts) {
  if (typeof opts.callback == 'function') { 
    opts.callback.call(this);
  }
};

$('div').myPlugin({
  callback: function() {
    console.log(this);
  }
});

outputs:

[div#myDiv, prevObject: m.fn.init[1], context: document, selector: "div", jquery: "1.11.1", constructor: function&#8230;] 

Whereas calling the callback without setting the execution context:

<div id="myDiv">hi</div>

$.fn.myPlugin = function(opts) {
  if (typeof opts.callback == 'function') { 
    opts.[B]callback()[/B];
  }
};

$('div').myPlugin({
  callback: function() {
    console.log(this);
  }
});

outputs:

Object {callback: function}

Thanks for the example, I understand it a bit better now!

I’ve tested this:

opts.callback(this);

And then:

$('div').myPlugin({
  callback: function(currentObj) {
    console.log(currentObj);
  }
});

Is there any functional difference between this and your first example?

You’re passing the execution context as a parameter to your callback function.
That would get confusing quite quickly.

E.g.

$('div').myPlugin({
  callback: function(currentObj) {
    console.log(currentObj);
    console.log(this);
  }
});

Outputs:

[div#myDiv, prevObject: m.fn.init[1], context: document, selector: "div", jquery: "1.11.1", constructor: function&#8230;] 
Object {callback: function}

Thanks. Yes, your way is cleaner.

Thanks both for your help.