Global JavaScript Events with jQuery

When building web applications with sophisticated client-side behavior (i.e., you have a lot of JavaScript) I work hard to define loosely-coupled JavaScript modules. Intentional developers strive for structured and modular server-side code, but because of JavaScript’s history we tend not to take the same care with it. We then repeat the sins of the past when we find ourselves with hundreds or thousands of lines of JavaScript that aren’t encapsulated and decoupled.

Key Point: Write loosely-coupled JavaScript modules within your application.

Of course, you do need some coupling between modules. To realize the interactions that must occur between JavaScript modules, consider using a global event technique. Modules publish information to the world when something interesting happens; other modules subscribe to information they need to react to.

Key Point: Publishers shouldn’t need to know anything about their subscribers.

Here are a few ways to set up a global publish/subscribe mechanism your JavaScript modules to use:

Roll Your Own

We don’t want to succumb to the “Not Invented Here” problem, but these few lines create a simple but useful window.Bus object that supports global events.

(<span class="kwrd">function</span>() {

    var subscriptions = null;

    window.Bus = {

        reset: <span class="kwrd">function</span>() {
             subscriptions = {};

        subscribe: <span class="kwrd">function</span>(messageType, callback) {
            <span class="kwrd">if</span> (<span class="kwrd">typeof</span> subscriptions[messageType] === <span class="rem">'undefined') {</span>
                subscriptions[messageType] = [];

        publish: <span class="kwrd">function</span>(messageType, args) {
            <span class="kwrd">if</span> (<span class="kwrd">typeof</span> subscriptions[messageType] === <span class="rem">'undefined') return;</span>
            var subscribers = subscriptions[messageType];
            <span class="kwrd">for</span> (var i=0; i&lt;subscribers.length; i++) {




// Subscriber usage:
window.Bus.subscribe(<span class="rem">'UserCreated', function(user) {</span>
    alert(<span class="rem">'User ' + user.Name + ' created!');</span>

// Publisher usage:
var newUser = { Name: <span class="str">"The Hulk"</span> };
window.Bus.publish(<span class="rem">'UserCreated', newUser);</span>


One quick way to get there without adding any more dependencies than you probably already have is it just use features jQuery’s eventing system. Here’s code that demonstrates how to use jQuery as a global pub/sub framework. In this example, there are two modules, a publisher and a subscriber, each with a bit of HTML and a bit of JavaScript. The JavaScript comments explain the main points.

<span class="kwrd">&lt;</span><span class="html">html</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">head</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">title</span><span class="kwrd">&gt;</span>Client-side Pub/Sub with jQuery<span class="kwrd">&lt;/</span><span class="html">title</span><span class="kwrd">&gt;</span>
    <span class="rem">&lt;!-- add reference to jQuery --&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">head</span><span class="kwrd">&gt;</span>

<span class="kwrd">&lt;</span><span class="html">body</span><span class="kwrd">&gt;</span>

    <span class="kwrd">&lt;</span><span class="html">div</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">input</span> <span class="attr">id</span><span class="kwrd">='PublishButton'</span> <span class="attr">type</span><span class="kwrd">='button'</span> <span class="attr">value</span><span class="kwrd">='Publish'</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">div</span><span class="kwrd">&gt;</span>

    <span class="kwrd">&lt;</span><span class="html">b</span><span class="kwrd">&gt;</span>Events:<span class="kwrd">&lt;/</span><span class="html">b</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">div</span> <span class="attr">id</span><span class="kwrd">='Subscriber1'</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">div</span><span class="kwrd">&gt;</span>

<span class="kwrd">&lt;/</span><span class="html">body</span><span class="kwrd">&gt;</span>

<span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">='text/javascript'</span><span class="kwrd">&gt;</span>
<span class="rem">// This function block correlates with the publisher's scope.</span>
$(<span class="kwrd">function</span>() {

    <span class="rem">// Represents a secret value only the publisher knows about directly,</span>
    <span class="rem">// but will include in its event args.</span>
    <span class="kwrd">var</span> someNumber = 7;

    <span class="rem">// When the button is clicked we publish an event.</span>
    $(<span class="str">"#PublishButton"</span>).click(<span class="kwrd">function</span>() {
        <span class="kwrd">var</span> dt = <span class="kwrd">new</span> Date();
        <span class="rem">//</span>
        <span class="rem">// The next line is the important one; notice how the event args</span>
        <span class="rem">// are passed as an array.</span>
        <span class="rem">//</span>
        $.<span class="kwrd">event</span>.trigger(<span class="str">'CustomEventName'</span>, [someNumber, dt]);


<span class="rem">// This function block correlates with the subscriber's scope.</span>
$(<span class="kwrd">function</span>() {
    <span class="rem">//</span>
    <span class="rem">// Notice how we're not calling bind() on the subscriber like a typical</span>
    <span class="rem">// jQuery event, but calling it on our own UI component.</span>
    <span class="rem">// Also notice how the event args, which were published as an array,</span>
    <span class="rem">// are flattened into individual parameters.</span>
    <span class="rem">//</span>
    $(<span class="str">"#Subscriber1"</span>).bind(<span class="str">'CustomEventName'</span>, <span class="kwrd">function</span>(<span class="kwrd">event</span>, number, date) {
        $(<span class="str">"&lt;div&gt;"</span>).text(<span class="str">"Event published: "</span> + number + <span class="str">" @ "</span> + date).appendTo($(<span class="kwrd">this</span>));
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>

<span class="kwrd">&lt;/</span><span class="html">html</span><span class="kwrd">&gt;</span>
.csharpcode, .csharpcode pre
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
.csharpcode .lnum { color: #606060; }

Use a Global Event Library

The following JavaScript libraries are a few that provide a global pub/sub infrastructure:

This entry was posted in JavaScript. Bookmark the permalink.