Javascript Simple Observer.

Published on July 30, 2008

Javascript Simple Observer.

    The task is to link 2 absolutely any objects. You cannot change the source code of objects.

    Described below is designed for reader independence and a desire to understand the implementation.



    Example (exaggerated).

    There are 2 objects in the house:
    <div id = "a1" onclick = "alert (123)"> </div>
    <div id = "a2"> </div>
    



    And 1 javascript:
    Core = function () {
    	this.some = function (a, b, c, d, e, f, g) {
    		var a1 = $ ('a1'). innerHTML
    		var a2 = a + '' + b + '' + c + '' + d + '' + e + '' + f + '' + g
    		$ ('a1'). innerHTML = a1 + a2
    	}
    	this.another = function () {
    		var a = $ ('a1'). innerHTML
    		var a2 = 'some_text_more'
    		$ ('a1'). innerHTML = a + a2
    	}
    	this.another2 = function () {
    		var a = $ ('a2'). innerHTML
    		var a2 = 'yahoo'
    		$ ('a2'). innerHTML = a + a2
    	}
    }
    var Core = new Core ()
    



    Requires: respond to a1.onclick by calling Core.another2

    Implementation:
    var n = Observer.Attach ($ ('a1'), 'onclick', Core, 'another')
    



    Remove Observer:
    Observer.Dettach ($ ('a1'), n)
    



    Observer.
    The implementation is based on the cloning of the monitored object method.
    Observer.Attach clones the method, creating a new one with a unique name.
    The monitored method is assigned a new action containing a clone call and a call to the required function (obj2.call_back) The
    call sequence is controlled by the before parameter of the Observer.Attach method.
    Observer = function () {}
    Observer.prototype = {
    	List: {},
    	Attach: function (obj, method, obj2, call_back, before) {
    		var new_method = this.CloneOldMethod (obj, method)	
    		eval ('obj.' + method + '=' + this.NewDefaultMethod ('obj2', call_back, new_method, before))
    		return new_method 
    	},
    	Dettach: function (obj, observed_method) {
    		eval ('var m = this.List.' + observed_method)
    		eval ('obj.' + m.method + '= m.realization')
    		eval ('delete (obj.' + observed_method + ')')
    		eval ('delete (this.List.' + observed_method + ')')
    	},
    	NewDefaultMethod: function (obj_name, call_back, new_method, before) {
    		var m_old = 'this.' + new_method + '(arguments [0], arguments [1], arguments [2], arguments [3], arguments [4], arguments [5], arguments [6])'
    		var m_new = obj_name + '.' + call_back + '()'
    		var cmd = ''
    		cmd + = 'function () {'
    		before === true? cmd + = m_new + ';' + m_old: cmd + = m_old + ';' + m_new
    		cmd + = '}'
    		return cmd
    	},
    	CloneOldMethod: function (obj, method) {
    		var new_method = 'a' + this.giveUnique ()
    		eval ('obj.' + new_method + '= obj.' + method)
    		eval ('this.List.' + new_method + '= {object: obj, \' method \ ': method, implementation: obj.' + method + '}')
    		return new_method
    	},
    	giveUnique: function () {
    		return (new Date ()). getTime ()
    	}
    }
    Observer = new Observer ()