diff options
author | Petr Vobornik <pvoborni@redhat.com> | 2012-05-07 18:27:29 +0200 |
---|---|---|
committer | Petr Vobornik <pvoborni@redhat.com> | 2012-05-11 17:16:53 +0200 |
commit | 1db7e1d193734bd30dc1a491622d15bc48658dc5 (patch) | |
tree | 405b95a591826d59b3907bac27649b638886c90b | |
parent | 84ffd3306bc7d3d3f6ead12d757c31fd183239d6 (diff) | |
download | freeipa-framework.tar.gz freeipa-framework.tar.xz freeipa-framework.zip |
Eventsframework
-rw-r--r-- | install/ui/framework.js | 128 | ||||
-rw-r--r-- | install/ui/test/framework_tests.js | 40 |
2 files changed, 152 insertions, 16 deletions
diff --git a/install/ui/framework.js b/install/ui/framework.js index ebd8df9bf..6fa51daf8 100644 --- a/install/ui/framework.js +++ b/install/ui/framework.js @@ -43,7 +43,47 @@ IFW.unregister = function(class_name) { }; IFW.event = function() { - return {}; + var that = {}; + + that.listeners = []; + + //adds callback to listeners. If context is specified it binds callback + //to context so 'this' property will be evaluated as context. + that.on = function(callback, context) { + + var _callback = callback; + + if (context) { + _callback = function() { + var args = Array.prototype.slice.call(arguments); + callback.apply(context, args); + }; + } + + this.listeners.push(_callback); + }; + + //removes listener + that.off = function(callback) { + for (var i=0; i < this.listeners.length; i++) { + if(callback === this.listeners[i]) { + this.listeners.splice(i,1); + break; + } + } + }; + + //triggers this event + that.trigger = function(args, context) { + args = args || []; + context = context || this; + + for (var i=0; i < this.listeners.length; i++) { + this.listeners[i].apply(context, args); + } + }; + + return that; }; //creates base object - Framework's root class @@ -69,25 +109,48 @@ IFW.object = function() { //event catalogue events: $.ordered_map(), - //raises existing event - raise: function(event_name, args) { + //trigger existing event + trigger: function(event_name, args) { - var event = this.events[event_name]; + var event = this.events.get(event_name); - if (event) event.notify(args); + if (event) event.trigger(args, this.obj); }, - //registers event + //registers event - creates new event, no listeners + //If event exists, it doesn't create a new one. event: function(name) { - var event = IFW.event(); + var event = this.events.get(name); - this.obj[name] = event; - this.events.put(name, event); + if (!event) { + event = IFW.event(); + this.obj[name] = event; + this.events.put(name, event); + } + return event; + }, + + //adds listener to event + //proxy for events[name].on. Creates new one if it doesn't exists. + on: function(name, handler, context) { + + var event = this.event(name); + event.on(handler, context); + }, + + //removes listeners from event + off: function(name, handler) { + var event = this.events.get(name); + if (event) { + event.off(handler); + } }, //registers new method for current class. A way of overriding methods. - method: function(name, func, pre_event, post_event) { + method: function(name, func, options) { + + options = options || {}; //to 'that' objects sets functions which raises preevent then executes //function in 'that' object context and finishes with raising post event @@ -97,16 +160,48 @@ IFW.object = function() { //method. And the nice part is that events are raised in proper way //regardless whether ancestor method is called. var _ = this; - this.obj[name] = function(args) { + var pre_handler, post_handler, pre_e_name, post_e_name; + + if (options.pre_event) { + + pre_e_name = typeof options.pre_event === 'string' ? + options.pre_event : 'pre_'+name; + + pre_handler = function(args) { + _.trigger(pre_e_name, args); + }; + } - if (pre_event) { - _.raise('pre'+name, args); + if (options.post_event) { + + post_e_name = typeof options.post_event === 'string' ? + options.post_event : 'post_'+name; + + post_handler = function(args) { + _.trigger(post_e_name, args); + }; + } + + if (options.pre_handler) { + pre_handler = options.pre_handler; + } + + if (options.post_handler) { + post_handler = options.post_handler; + } + + this.obj[name] = function() { + + var args = Array.prototype.slice.call(arguments); + + if (pre_handler) { + pre_handler.call(_.obj, args); } - func.call(_.obj, args); + func.apply(_.obj, args); - if (post_event) { - _.raise('post'+name, args); + if (post_handler) { + post_handler.call(_.obj, args); } }; @@ -161,6 +256,7 @@ IFW.object = function() { return that; }; + //main function for creating new classes IFW.type = function(class_name, ancestor) { diff --git a/install/ui/test/framework_tests.js b/install/ui/test/framework_tests.js index e82a54a5f..296e74ebe 100644 --- a/install/ui/test/framework_tests.js +++ b/install/ui/test/framework_tests.js @@ -33,6 +33,28 @@ module('framework',{ that.foo = spec.foo || 'facet_foo'; that.baz = spec.baz || 'facet_baz'; that.bar = spec.bar || 'facet_bar'; + this._.on('pre_with_events', this.preevent_handler, this); + this._.on('post_with_events', this.postevent_handler, this); + }); + + that._.method('with_events', function(first, second) { + this.with_events_called = true; + this.with_events_attrs = [first, second]; + }, { + pre_event: true, + post_event: true + }); + + that._.method('preevent_handler', function(first, second) { + that.preevent_handler_called = true; + this.preevent_handler_bound = true; + this.preevent_handler_attrs = [first, second]; + }); + + that._.method('postevent_handler', function(first, second) { + that.postevent_handler_called = true; + this.postevent_handler_bound = true; + this.postevent_handler_attrs = [first, second]; }); return that; @@ -79,4 +101,22 @@ test("Build and inheritence" ,function() { same(details_facet.foo, 'facet_foo', "Property - ancestor's default"); same(details_facet.baz, 'details_baz', "Property - child's default"); same(details_facet.bar, 'custom_bar', "Property - custom"); + + //test method calls and pre/post events + + var attrs = ["first", "second"]; + details_facet.with_events(attrs[0], attrs[1]); + + ok(details_facet.with_events_called, "With events called."); + same(details_facet.with_events_attrs, attrs, "With event called with good attrs"); + + ok(details_facet.preevent_handler_called, "Pre event called."); + ok(details_facet.preevent_handler_bound, "Pre event correctly bounded."); + same(details_facet.preevent_handler_attrs, attrs, "Pre event called with good attrs"); + + ok(details_facet.postevent_handler_called, "Post event called."); + ok(details_facet.postevent_handler_bound, "Post event correctly bounded."); + same(details_facet.postevent_handler_attrs, attrs, "Post event called with good attrs"); + + //calls }); |