Object Subscript Pattern

I have said this before and will probably say it again, "I love CustomEvent". This was one of the major reasons why I chose YUI as my preferred JavaScript framework. Using CustomEvent you are able to create a subscribable event for anything you might want an event for, and fire that event programmatically.

I find this most useful when leveraging the Module Pattern, as I can keep the event management and all important methods private, while allowing users to define actions at key times during the execution of the code. You can also use this process to pass private data from inside the current Module Pattern to external Object with some degree of control (if absolutely necessary). However, for this pattern to work you need a way to expose the events to the other objects, without attaching every event to this. For this purpose I use the "Object Subscription Pattern", which uses one public method and coding conventions for subscribing to events. Here is an example of an Object, Dialog, using both the Module and "Object Subscription Pattern".

Example 1: Subscript Pattern, Dialog Object

var Dialog = function() {

    var CE = YAHOO.util.CustomEvent,
        F = function() {},
        that = null;

    var evt = {
        beforeCloseEvent: new CE(DialogBeforeCloseEvent, that, CE.FLAT),
        beforeOpenEvent: new CE(DialogBeforeOpenEvent, that, CE.FLAT),
        closeEvent: new CE(DialogCloseEvent, that, CE.FLAT),
        openEvent: new CE(DialogOpenEvent, that, CE.FLAT)

    /** private methods here */

    F.prototype = {
        EVENT_BEFORE_CLOSE: beforeClose,
        EVENT_BEFORE_OPEN: beforeOpen,
        EVENT_CLOSE: close,
        EVENT_OPEN: open,

        subscribe: function(type, func, obj) {
            var eventName = type + Event;
            if (evt[eventName]) {evt[eventName].subscribe(func, obj);}
            else {throw(Invalid event type ( + type + ) inside of Dialog.);}

    that = new F();
    return that;

Lets assume that Dialog is used to manage a div-based popup system, similar to YUI Dialog. In Example 1 we assume you might care about 4 events: after the dialog opens or closes, and before those same events. For this purpose we have created 4 custom events and attached them to the internal namespace evt. I always use the FLAT CustomEvent type, because I find the default annoying; the difference is well explained in the YUI documentation. The first parameter of CustomEvent is the name of your events and is very important, because the CustomEvent manager maintains a global list of all names to know what to subscribe to and fire. For this reason, make sure you use a unique name. I prefer the convention of the String NameOfObject + NameOfEvent + Event. The second parameter will be the execution scope of the callback Functions and I generally pass in a reference to the parent Module Pattern Object. The localized event name, attached to evt, should follow a convention as well; I prefer to use the String NameOfEvent + Event (this will be important in the public subscribe method).

Now, moving on the the public part of the Module Pattern. I have first exposed some constants that are the event names (NameOfEvent) that I used above. These constants make your public interface easier to read and use by others (and even yourself, when returning to an object you wrote some time ago), since there is no need to search the internal namespace for the available event names. The subscribe method is just a wrapper for calling the subscribe method of the internal CustomEvents with the proper parameters. We first test to make sure that the internal event exists, and throw an informative exception otherwise. The second parameter will be your callback function and the third is an optional, additional Object that will also be passed through to the callback method, when your CustomEvent is fired.

That is the gist of the pattern. You have exposed private module events through a public subscribe method. It is relatively simple to use and setup, just requiring that you use some conventions (mine or your own), with which you can apply the Subscription Pattern to any Module Pattern Object. Lastly, lets go over the actual firing of events. When a point in your code is reach and you want to fire an event, use the following syntax:

Example 2: Firing a CustomEvent

var open = function() {
    /** logic to show the dialog */
    evt.openEvent.fire([1, 2, 3]);

Example 2 could be an internal method of our Dialog object that actually shows the Dialog. Notice, we first first the beforeOpen event, followed by the opening logic, then we fire the open event. I have also illustrated with the open how to pass values through to the callback function. With FLAT CustomEvent types, this should always be an Array and will be the second parameter of your callback function.