Custom Events are Pretty Cool

Chris Coyier //

Let's say you are working on a web application in jQuery and you are tasked with writing an accordion suited to the needs of your web app. You decide to make it into a plugin. That way anywhere in this app that needs an accordion, they can load this plugin and call it upon semantic markup that is ready to become an accordion. Then ta-da, they have a lovely working accordion.

Now another developer is using your accordion and they want to be able to Ajax load some content into one of the sections of the accordion, but only when that section is opened. Together you decide that you should keep your code separate. The generic functionality of how an accordion works should be separate from code specific to one accordion on one page of an app.

Callbacks, the traditional way

One way to approach that would be to write "callbacks" into your plugin. The other developer would specify the name of a function that she wants run when certain actions happen on that accordion. So the calling of it might be like:

$(".accordion").accordion({
  panelOpen: myPanelOpenCallback,
  panelClose: myPanelCloseCallback;
});

And they would have created those callback functions themselves:

function myPanelOpenCallback() {
  // Do Ajax stuff 
}

Then the plugin itself would honor those callbacks in its related internal functions:

$.fn.accordion = function(options) {
    
	return this.each(function(i, el) {

	  var base = el;
	  
	  base.init = function() {
	  	// Do initialization stuff
	  };
	  
	  base.openPanel = function(panel) {
	  	// Open panel
		
		// Do callback
		options.panelOpen.call();
	  };
	  
	  base.closePanel = function(panel) {
	  	// Open panel
		
		// Do callback
		options.panelClose.call();
	  };
	  
	  base.init();
	       
	});
  
};

View Demo of Callback Model

Custom Events, a better way

Now let's say a third developer gets involved, and they also want to write a bit of JavaScript that reacts to a panel opening as well. For the sake of a use case, say what's inside the accordion panels are settings, and this developer wants to save those settings whenever keys are opened or closed automatically.

Now we're in an interesting position. We've already defined our callback for accordion panels opening and closing. So in the callback model, these developers are going to have to get together on that callback and run both of their code in that one callback. Not that big of a deal, but now we're forced to mix code when that might not be ideal. Remember we started this whole thing off by separating specific functionalities.

Here's where custom events are super rad. Instead of firing off a specified callback, the accordion functionality plugin fires off a custom event. Custom events are just like any other event (e.g. click) only they are only declared and called programmatically.

First, callbacks are gone, we just call the accordion plugin without them:

$(".accordion").accordion();

Now in place of where we called the callbacks, we'll trigger our Custom Event. Basically, just make up a name that makes sense (like you are naming a function).

// OUT
// options.panelOpen.call();

// IN
panel.trigger("panelOpen");

Now our other developers can bind their stuff to this custom event and do their own thing.

$(".panel").on("panelOpen", function() {
   // Developer 1: do Ajax stuff
});

// Meanwhile, in another part of town...
$(".panel").on("panelOpen", function() {
   // Developer 2: do saving stuff
});

Yay for freedom! Yay for separation of functionality!

In my opinion custom events are just better all around. I do think they require a bit more communication though. You'll probably have to write up some comments somewhere that explain what custom events are fired and when and make that easy to discover.

View Demo of Custom Events model

More Information

The scenario outlined above is very simple. The following two articles go way more into depth about Custom Events including more complex examples and more information on how they work.