jarodtaylor
jarodtaylor

Reputation: 571

In JavaScript is it possible to add to a callback function instead of overwriting it?

I don't know if I'm saying this right, so I'll just ask by explaining with an example.

Let's say I've written a jQuery plugin with an onShowEdit callback.

I later use my plugin and add a bunch of other default functions/methods to the event:

$('.editable_module:not(.custom)').editable({
   onShowEdit: function(el){
      initRequired();
      $(':radio, :checkbox', el).prettyCheckboxes();
      initDatePickers();
      initChosen();
      initMaskedInputs();
      $('.dynamic_box.tabs').dynamicBoxTabs();
      $('.trigger_dynamic_box').triggerDynamicBox('true');
   }
});

So now I have a basic/default element (.editable_module) that calls the plugin and has some methods/functions that are going to be used in all instances.

My question comes when I have a need to add something to this for a 'one time' kind of deal (I need to add some behavior to this callback/event but not something that is used normally). Is it possible to extend or add to this callback/event without overwriting it? I mean, I know I can go in and do this:

$('#new_selector').editable({
   onShowEdit: function(el){
      initRequired();
      $(':radio, :checkbox', el).prettyCheckboxes();
      initDatePickers();
      initChosen();
      initMaskedInputs();
      $('.dynamic_box.tabs').dynamicBoxTabs();
      $('.trigger_dynamic_box').triggerDynamicBox('true');

      //ADD SOME NEW STUFF HERE
   }
});

But is that really my only option?

Thanks in advance for any input/suggestions.

Upvotes: 4

Views: 298

Answers (4)

S.Walker
S.Walker

Reputation: 166

Defining a separate function for onShowEdit should work.

var myOnShowEdit = function(el, extra_fn) {
    //standard functionality goes here
    if (typeof extra_fn==='function') extra_fn(); //support for extra stuff
}
$('.editable_module:not(.custom)').editable({
    onShowEdit: function(el) {
        myOnShowEdit(el);
    }
});
$('#new_selector').editable({
    onShowEdit: function(el) {
        myOnShowEdit(el, function(){console.log('hi');});
    }
});

This will give you fair flexibility to add whatever functionality you need in addition to the standard stuff. Just be aware of how this may shift contexts.

Upvotes: 0

Kevin B
Kevin B

Reputation: 95017

You could use the new $.Callbacks() method

var $onShowEditCBObj = $.Callbacks();
function onShowEditHandler() {
  $onShowEditCBObj.fire();
}
$('#new_selector').editable({
   onShowEdit: onShowEditHandler
});
// add default event to callbacks obj
$onShowEditCBObj.add(function(){
  initRequired();
  $(':radio, :checkbox', el).prettyCheckboxes();
  initDatePickers();
  initChosen();
  initMaskedInputs();
  $('.dynamic_box.tabs').dynamicBoxTabs();
  $('.trigger_dynamic_box').triggerDynamicBox('true');
});
// add a one time method to the callbacks obj
function oneTimeEvent () {
  alert("worky");
  $onShowEditCBObj.remove(oneTimeEvent);
}
$onShowEditCBObj.add(oneTimeEvent)

With this setup, you can change what callbacks will be fired without having to do anything extra to the editable plugin.

Edit: I didn't realize that you wrote the plugin. With that in mind, pimvdb's answer is more robust than requiring the developer to code a certain way.

Upvotes: 3

Beetroot-Beetroot
Beetroot-Beetroot

Reputation: 18078

If I understand the question correctly, the key word here is "factory".

jQuery is itself a factory but to get what you describe, you need your plugin also to be a factory within the factory. That requires the plugin to be written in a certain way.

Probably the easiest approach is to use jQuery's UI widget factory. Read about it here.

Upvotes: 0

pimvdb
pimvdb

Reputation: 154848

You could consider jQuery's own event system as follows: http://jsfiddle.net/VQqXM/1/. You can integrate this in your $.fn function pretty easily - just pass the appropriate function as property of the object instead of a function literal.

$("input").on("foo", function() {
    alert(1);
});

// later

$("input").on("foo", function() {
    alert(2);
});

// later

$("input").trigger("foo"); // alerts 1 and 2

You can simply use .on/.off to bind and unbind events, and trigger them all with .trigger. jQuery also supports namespacing of the event names to make sure you're not using an already used event.

Upvotes: 3

Related Questions