Another Note: Previous versions (v0.4+) were written in an attempt to remove the first argument and create a more future-proof API, but unfortunately this resulted in much less elegant, larger and slower code. The point of this plugin is to be TINY, to be used in situations where only size (not performance or usability) is the primary concern (tweets, code golf, etc).**

I frequently see comments about how jQuery's events system has unnecessary overhead that precludes it from being used as the core of a Pub/Sub implementation. The jQuery events system is tried-and-true, having been architected to be both fast and robust, and the vast majority of users of this plugin should never encounter any kind of performance issues.

Because this plugin's $.subscribe, $.unsubscribe and $.publish methods all use the jQuery .on(), .off() and .trigger() methods internally, those methods' complete signatures are available to you.

You can use namespaces for more control over unsubscribing and publishing.

Just use this handy terminology guide (jQuery events term → Pub/Sub term), and everything should make sense:

on → subscribe

off → unsubscribe

trigger → publish

type → topic

In addition, should you need it, these methods are fully compatible with the jQuery.proxy() method, in case you not only want more control over to which context the subscribed callback is bound, but want to be able to very easily unsubscribe via callback reference.

Regarding performance: If at some point, your application starts processing so many messages that performance issues start to develop, you could always write a replacement "jQuery Not-So-Tiny Pub/Sub" plugin with the same API and just drop it in as a replacement to this plugin. But keep in mind that you'll also need to add in the aforementioned features, too.

Cool, Ben. Thanks. I'm going to substitute this for my homebrew "signals", as mine doesn't have an "unsubscribe" yet. Come on over to github.com/timeglider some time and have a look around. I'll probably implement that table parser you whipped up next week.

ionutzp, I'd recommend checking out the MDC apply documentation, which explains in detail how .apply works.

In general, .apply gives you the ability to invoke a function, specifying the context in which it will execute (this inside the function) as well as specifying the arguments to be passed, but as an array. To make a long story short, I'm using .apply here to execute one object's method as if it were called as a method of a different object.

I thought this was very slow too, since it is DOM based. Here's jsperf comparing to higgins, with latest update to the final gist I could find for jQuery 1.6 which had the following optimization $({}) instead of $('<b/>'). This increases performance 100%. The original test /1 already had this optimization, and now I know why! http://jsperf.com/pub-sub-implementations/2

Drew, in making this into a "plugin" version that can be used with any version of jQuery, $({}) actually causes errors in some versions of jQuery, so I changed it to $('<b/>') (see the comments). Frankly, what was once very small and elegant has turned into a big, sloppy mess.

If you want "small and elegant" go for version 0.3 and just note that the event object is being passed as the first argument to the event handler!

This was linked as inclusion to the core, so I didn't give much attention to support in older versions of jQuery. The wrapper code should go away as well, or implemented differently to meld better with the core code, right?

It would be nice to have something that works today and will work this time next year (when our product ships). We're using $().bind currently, I thought it would be too slow and still have that concern. Using $({}) and $({<b/>}) provided better performance than Higgins, $({}) provided much better performance though.

Update: If you want the original TINY pub/sub plugin, use jQuery Tiny Pub/Sub v0.3 and just ignore the first argument passed to your callbacks (which is an event object). Versions v0.4+ were written in an attempt to remove that first argument and create a more future-proof API, but unfortunately this resulted in much less elegant, larger and slower code. The point of this plugin is to be TINY, to be used in situations where only size (not performance or usability) is the primary concern (tweets, code golf, etc).

The pub/sub pattern consists of two things: topics and messages. Topics are subscribed to by arbitrary listeners, and messages are received when that topic publishes a message. With event systems, events are bound to and fired from contexts (such as HTML elements), like the Bindable example you linked to.

The whole point of pub/sub is that it doesn't assume a context for it's topics/messages. Think of it like an application-wide notification system.

@bentruyman understood. i was just posting as a comparison. personally i use bindable not only on classes for custom events, but also the application level for handling app-wide pub/sub. i prefer it because i often have multiple apps on the same page and i can scope the pub/sub to an individual app instead of the global (which this basic pub/sub does) without need for unnecessarily deep namespacing. think of it as a var for pub/sub.

Does anyone have any thoughts on using this pattern with Zepto? I've found that Zepto doesn't like $({}), though it's fine with $('<b/>'). Is this a significant performance hit to use $('<b/>'), or is there a better way to port this plugin to Zepto?

@rwldrn Thanks, but my issue is that I haven't been able to figure out how to create an empty element in Zepto. I suppose I should pose that issue on a Zepto forum, but I thought someone might have a workaround here.

I have only one concern/suggestion to this relatively simple PubSub - it doesn't take into account published events that have already happened (in the past). Why is this important? Assume for a second that I want to subscribe to an event that had already happened, or I dont know that it happened, but still want my new subscriber to be triggered with the last-published values? My suggestion is to add something like this:

@gmanishvar o = $({}) simply creates a jQuery collection with an empty object {} that becomes the recipient of all the event triggers. As other comments show, the recipient could be anything like $('<b />').