Eventify

Не давали мне покоя рассуждения начатые в заметке Продвинутая теория создания плагинов и решил я написать плагин, который бы переводил все методы переданного объекта в события. Конечно же сам объект не должен быть нарушен, то есть должен иметь возможность вызывать свои методы напрямую, более того при любом вызове любого метода должны отрабатывать еще два события onBeforeMethod и onAfterMethod.

Скорее всего сейчас вас мучает вопрос на кой хер это вообще надо. Это глубоко эзотерические размышления над архитектурой, которые простым людям нах не нужны. Но я надеюсь что в конце концов они приведут к какой-то универсальной форме создания плагинов не нарушая идеологию jQuery но позволяя передавать данные и получать результаты в плагин простым и красивым способом.

Итак что же вышло?


(function($) {

    var Plugin = function (elt, obj) {
        var element = $(elt);
        for (var prop in obj){
            (function(self,obj,prop){
                if ($.isFunction(obj[prop])){
                    self[prop] = function(){
                        var result, eventName = prop.charAt(0).toUpperCase() + prop.substr(1);
                        element.trigger("onBefore" + eventName, [self, arguments]);
                        result = obj[prop].apply(self, arguments);
                        element.trigger("onAfter" + eventName, [self, arguments, result]);
                    };
                    element.bind(prop, $.proxy(function(){
                        self[prop].apply(self, Array.prototype.slice.call(arguments, 1));
                    }, self));
                }else{
                    self[prop] = obj[prop];
                }
            })(this,obj,prop);
        }
    };

    $.fn.plugin = function(obj) {
        this.each(function() {
            new Plugin(this, obj);
        });
        return this;
    };

})(jQuery);

Использовать можно примерно так


$(document).ready(function(){
    $("#qwerty").bind("onBeforeMethod1 onAfterMethod1 onBeforeMethod2 onAfterMethod2", function(e){
        console.log(e.type, arguments);
    }).plugin({
        method1 : function (){
            console.log("method1",this);
            this.method2(1,2,3);
        },
        method2 : function (){
            console.log("method2",this);
            console.log("method2",arguments);
            return arguments;
        }
    }).trigger("method1").trigger("method2",[1,2,3])
});

2 Комментарии “Eventify

  1. Ой как все это похоже на AOP — аспектно ориентированное программирование…
    пример на прототипе:

    
    var AOPUtils = {
        addBefore: function(object, methodName, invokedObject, invokedMethodName) {
            var oldMethod = object[methodName];
            object[methodName] = function() {
              var args = $A(arguments);
              try {
                if (Object.isFunction(invokedObject)) {
                  invokedObject.call(invokedObject, args);
                } else {
                  invokedObject[invokedMethodName].call(invokedObject, args);
                }
              } catch (e) {
                alert("An exception occurred in method '" + methodName + "' Error: " + e.message);
              }
              try {
                var result = oldMethod.apply(object, args);
              } catch (e) {
                alert("An exception occurred in method '" + methodName + "' Error: " + e.message);
              }
              return result;
            };
        }
    };
    

    Как использовать:

    
    var SomeClass = Class.create({
        simplemethod: function(url) {
            alert(url);
        }
    });
    
    var sobject = new SomeClass();
    AOPUtils.addBefore(sobject, "simplemethod", function(args) {
        var url = args[0];
        url += "?param=test";
        args[0] = url;
    });
    
    sobject.simplemethod("http://test.com");
    

Комментарии закрыты