summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Vobornik <pvoborni@redhat.com>2012-05-07 18:27:29 +0200
committerPetr Vobornik <pvoborni@redhat.com>2012-05-11 17:16:53 +0200
commit1db7e1d193734bd30dc1a491622d15bc48658dc5 (patch)
tree405b95a591826d59b3907bac27649b638886c90b
parent84ffd3306bc7d3d3f6ead12d757c31fd183239d6 (diff)
downloadfreeipa-framework.tar.gz
freeipa-framework.tar.xz
freeipa-framework.zip
Eventsframework
-rw-r--r--install/ui/framework.js128
-rw-r--r--install/ui/test/framework_tests.js40
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
});