1
\$\begingroup\$

I've tried out a hybrid type of event management model, combining elements of the addEventListener-type and the onEvent-type. What I don't like about the addEventListener model is that you have to consult the documentation to choose the right event type, example: addEventListener("click", callback). What I don't like about the onEvent model is that you can only have one listener. Below is what I came up with.

Functions for registering listeners:

function onClick(callback, callbackToReplace) {
    _registerEventHandler(_clickCallbackList, callback, callbackToReplace);
}
function onChange(callback, callbackToReplace) {
    _registerEventHandler(_changeCallbackList, callback, callbackToReplace);
}

The implementation of the function that does the actual registering and removal of listeners:

function _registerEventHandler(callbackList, callback, callbackToReplace) {
    if(callbackToReplace && callbackList.length > 0 && Object.prototype.toString.call(callbackToReplace) === "[object Function]") {
        for(var i=0, l=callbackList.length; i<l; i++) {
            if(callbackToReplace === callbackList[i]) {
                if(callback && Object.prototype.toString.call(callback) === "[object Function]")  {
                    callbackList.splice(i, 1, callback);
                }
                else {
                    callbackList.splice(i, 1);
                }
            }
        }
    }
    else if(callback && Object.prototype.toString.call(callback) === "[object Function]")  {
        callbackList.push(callback);
    }
}

The function used to trigger an event:

function _triggerCallbacks(callbackList, message) {
    for(var i = 0, l = callbackList.length; i<l; i++) {
        callbackList[i].call(null, message);    
    }
}

Examples of registering listeners:

function func1(message) {
    // Insert code here
}
function func2(message) {
    // Insert code here
}
function func3(message) {
    // Insert code here
}

onClick(func1); // Add first function
onClick(func2); // Add second function
onClick(func3, func2); // Replace second function with third function
onClick(null, func3); // Remove third function

If you're just adding listeners you simply skip the second argument, making it simple to use when simple is sufficient, but you can also replace and remove with a the same single method making use of the second argument. The model does require a separate method for each event type. This is a serious drawback since it makes changes to the interface of the module (compared to the extensible addEventListener model). On the other hand, adding support for new events in the addEventListener model requires publicizing this in some way, for example by adding a constant describing the event type. So, adding support for a new Event-type could be said to be functionally equivalent between the models (you still have to change the code, but you do it in different places).

I'm looking for some feedback on this hybrid model - positive and negative. I've used it in a couple of modules and it works fine, but I am concerned with size of the interface (requires more public functions) and the non-standard nature of the event handling model - will it be difficult for programmers to use the module just because it's non-standard and similar.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.