[KSS-checkins] r41903 - in kukit/kukit.js/branch/fschulze-js-compression/kukit: . progress
fschulze at codespeak.net
fschulze at codespeak.net
Thu Apr 5 12:48:46 CEST 2007
Author: fschulze
Date: Thu Apr 5 12:48:44 2007
New Revision: 41903
Added:
kukit/kukit.js/branch/fschulze-js-compression/kukit/progress/
kukit/kukit.js/branch/fschulze-js-compression/kukit/progress/eventreg-1.js
kukit/kukit.js/branch/fschulze-js-compression/kukit/progress/eventreg-2.js
kukit/kukit.js/branch/fschulze-js-compression/kukit/progress/eventreg-3.js
kukit/kukit.js/branch/fschulze-js-compression/kukit/progress/eventreg-4.js
kukit/kukit.js/branch/fschulze-js-compression/kukit/progress/eventreg-5.js
kukit/kukit.js/branch/fschulze-js-compression/kukit/progress/eventreg-6.js
kukit/kukit.js/branch/fschulze-js-compression/kukit/progress/eventreg-org.js
kukit/kukit.js/branch/fschulze-js-compression/kukit/sizes.sh (contents, props changed)
Modified:
kukit/kukit.js/branch/fschulze-js-compression/kukit/eventreg.js
Log:
Example on how to make the code compression friendlier.
Modified: kukit/kukit.js/branch/fschulze-js-compression/kukit/eventreg.js
==============================================================================
--- kukit/kukit.js/branch/fschulze-js-compression/kukit/eventreg.js (original)
+++ kukit/kukit.js/branch/fschulze-js-compression/kukit/eventreg.js Thu Apr 5 12:48:44 2007
@@ -22,8 +22,14 @@
kukit.er = {};
+// start local scope
+var _er = function() {
-kukit.er.eventClassCounter = 0;
+var _kukit = kukit;
+var _kukit_er = _kukit.er;
+_kukit_er._eventClassCounter = 0;
+
+var _undefined = 'undefined';
/*
*
@@ -41,148 +47,148 @@
* func must be a class (constructor) function, this is the class that
* implements the binder.
*/
-kukit.er.EventRegistry = function () {
+_kukit_er.EventRegistry = function () {
this.content = {};
this.classes = {};
this.eventsets = [];
};
/* binder registration */
+var _kukit_er_EventRegistry_prototype = _kukit_er.EventRegistry.prototype;
-kukit.er.EventRegistry.prototype.registerBinder = function(classname, func) {
- if (typeof(func) == 'undefined') {
+_kukit_er_EventRegistry_prototype.registerBinder = function($classname, $func) {
+ if (typeof($func) == _undefined) {
throw 'func argument is mandatory when registering an event binder (EventRegistry.registerBinder).';
}
- if (this.classes[classname]) {
+ if (this.classes[$classname]) {
// Do not allow redefinition
- kukit.logError('Error : event class "' + classname + '" already registered.');
+ _kukit.logError('Error : event class "' + $classname + '" already registered.');
return;
}
// Decorate and store the class
- kukit.er.decorateEventBinderClass(func);
- this.classes[classname] = func;
+ _kukit_er.decorateEventBinderClass($func);
+ this.classes[$classname] = $func;
};
-kukit.er.EventRegistry.prototype.existsBinder = function(classname) {
- var func = this.classes[classname];
- return (typeof(func) != 'undefined');
+_kukit_er_EventRegistry_prototype.existsBinder = function($classname) {
+ var $func = this.classes[$classname];
+ return (typeof($func) != _undefined);
};
-kukit.er.EventRegistry.prototype.getBinder = function(classname) {
- var func = this.classes[classname];
- if (! func) {
+_kukit_er_EventRegistry_prototype.getBinder = function($classname) {
+ var $func = this.classes[$classname];
+ if (! $func) {
// not found
- throw 'Error : undefined event setup type ' + classname;
+ throw 'Error : undefined event setup type ' + $classname;
}
- return func;
+ return $func;
};
/* events (methods) registration helpers (not to be called directly) */
-kukit.er.EventRegistry.prototype._register = function(namespace, eventname, klass,
- bindmethodname, defaultactionmethodname, bindmethodapi) {
- if (typeof(defaultactionmethodname) == 'undefined') {
+_kukit_er_EventRegistry_prototype._register = function($$namespace, $eventname, $klass,
+ $bindmethodname, $defaultactionmethodname, $$bindmethodapi) {
+ if (typeof($defaultactionmethodname) == _undefined) {
throw 'some arguments are not passed when calling EventRegistry.register';
}
// Find out the class name. (Not specified now.)
- var classname = klass.prototype.__classname__;
- if (typeof(classname) == 'undefined') {
+ var $classname = $klass.prototype.__classname__;
+ if (typeof($classname) == _undefined) {
// Create a classname, and register it too.
- classname = '' + kukit.er.eventClassCounter;
- kukit.er.eventClassCounter += 1;
- this.registerBinder(classname, klass);
- klass.prototype.__classname__ = classname;
+ $classname = '' + _kukit_er._eventClassCounter;
+ _kukit_er._eventClassCounter += 1;
+ this.registerBinder($classname, $klass);
+ $klass.prototype.__classname__ = $classname;
}
- if (!eventname) {
+ if (!$eventname) {
throw 'eventname argument cannot be empty when registering an event (EventRegistry.register)';
}
- var key = this._getKey(namespace, eventname);
- var entry = this.content[key];
- if (typeof(entry) != 'undefined') {
- if (key[0] == '-') {
- key = key.substring(1);
+ var $key = this._getKey($$namespace, $eventname);
+ var $$value = this.content[$key];
+ if (typeof($$value) != _undefined) {
+ if ($key[0] == '-') {
+ $key = $key.substring(1);
}
- throw 'In EventRegistry.register double registration of key "' + key + '"';
+ throw 'In EventRegistry.register double registration of key "' + $key + '"';
}
// register it
- this.content[key] = {
- 'classname': classname,
- 'bindmethodname': bindmethodname,
- 'defaultactionmethodname': defaultactionmethodname,
- 'bindmethodapi': bindmethodapi
+ this.content[$key] = {
+ 'classname': $classname,
+ 'bindmethodname': $bindmethodname,
+ 'defaultactionmethodname': $defaultactionmethodname,
+ 'bindmethodapi': $$bindmethodapi
};
};
/* events (methods) binding "ForAll" registration */
-kukit.er.EventRegistry.prototype._registerEventSet = function(namespace, names) {
+_kukit_er_EventRegistry_prototype._registerEventSet = function($$namespace, $names) {
// At this name the class and event should be checked already. so this should
// be called _after_ _register.
- this.eventsets.push({'namespace': namespace, 'names': names});
+ this.eventsets.push({'namespace': $$namespace, 'names': $names});
};
/* there are the actual registration methods, to be called from plugins */
-kukit.er.EventRegistry.prototype.register = function(namespace, eventname, klass,
- bindmethodname, defaultactionmethodname) {
- this._register(namespace, eventname, klass, bindmethodname, defaultactionmethodname, 'old');
- this._registerEventSet(namespace, [eventname]);
+_kukit_er_EventRegistry_prototype.register = function($$namespace, $eventname, $klass,
+ $bindmethodname, $defaultactionmethodname) {
+ this._register($$namespace, $eventname, $klass, $bindmethodname, $defaultactionmethodname, 'old');
+ this._registerEventSet($$namespace, [$eventname]);
};
-kukit.er.EventRegistry.prototype.registerForAllEvents = function(namespace, eventnames, klass,
- bindmethodname, defaultactionmethodname) {
- if (typeof(eventnames) == 'string') {
- eventnames = [eventnames];
+_kukit_er_EventRegistry_prototype.registerForAllEvents = function($$namespace, $eventnames, $klass,
+ $bindmethodname, $defaultactionmethodname) {
+ if (typeof($eventnames) == 'string') {
+ $eventnames = [$eventnames];
}
- for (var i=0; i<eventnames.length; i++) {
- var eventname = eventnames[i];
- this._register(namespace, eventname, klass, bindmethodname, defaultactionmethodname, 'new');
+ for (var i=0; i<$eventnames.length; i++) {
+ var $$eventname = $eventnames[i];
+ this._register($$namespace, $$eventname, $klass, $bindmethodname, $defaultactionmethodname, 'new');
}
- this._registerEventSet(namespace, eventnames);
+ this._registerEventSet($$namespace, $eventnames);
};
-kukit.er.EventRegistry.prototype._getKey = function(namespace, eventname) {
- if (namespace == null) {
- namespace = '';
- } else if (namespace.split('-') > 1) {
+_kukit_er_EventRegistry_prototype._getKey = function($$namespace, $eventname) {
+ if ($$namespace == null) {
+ $$namespace = '';
+ } else if ($$namespace.split('-') > 1) {
throw 'In EventRegistry.register namespace cannot contain -';
}
- return namespace + '-' + eventname;
+ return $$namespace + '-' + $eventname;
+};
+
+_kukit_er_EventRegistry_prototype.exists = function($$namespace, $eventname) {
+ var $key = this._getKey($$namespace, $eventname);
+ return (typeof(this.content[$key]) != _undefined);
};
-kukit.er.EventRegistry.prototype.exists = function(namespace, eventname) {
- var key = this._getKey(namespace, eventname);
- var entry = this.content[key];
- return (typeof(entry) != 'undefined');
-};
-
-kukit.er.EventRegistry.prototype.get = function(namespace, eventname) {
- var key = this._getKey(namespace, eventname);
- var entry = this.content[key];
- if (typeof(entry) == 'undefined') {
- if (key[0] == '-') {
- key = key.substring(1);
- throw 'Error : undefined global event key ' + key + ' (or maybe namespace is missing?)';
+_kukit_er_EventRegistry_prototype.get = function($$namespace, $eventname) {
+ var $key = this._getKey($$namespace, $eventname);
+ var $$value = this.content[$key];
+ if (typeof($$value) == _undefined) {
+ if ($key[0] == '-') {
+ $key = $key.substring(1);
+ throw 'Error : undefined global event key ' + $key + ' (or maybe namespace is missing?)';
} else {
- throw 'Error : undefined event key ' + key;
+ throw 'Error : undefined event key ' + $key;
}
}
- return entry;
+ return $$value;
};
-kukit.eventsGlobalRegistry = new kukit.er.EventRegistry();
-
+_kukit.eventsGlobalRegistry = new _kukit_er.EventRegistry();
+_kukit_eventsGlobalRegistry = _kukit.eventsGlobalRegistry;
/* XXX deprecated methods, to be removed asap */
-kukit.er.eventRegistry = {};
-kukit.er.eventRegistry.register = function(namespace, eventname, klass,
- bindmethodname, defaultactionmethodname) {
- kukit.logWarning('Deprecated kukit.er.eventRegistry.register, use kukit.eventsGlobalRegistry.register instead! (' + namespace + '-' + eventname + ')');
- kukit.eventsGlobalRegistry.register(namespace, eventname, klass,
- bindmethodname, defaultactionmethodname);
+_kukit_er.eventRegistry = {};
+_kukit_er.eventRegistry.register = function($$namespace, $eventname, $klass,
+ $bindmethodname, $defaultactionmethodname) {
+ _kukit.logWarning('Deprecated _kukit_er.eventRegistry.register, use kukit.eventsGlobalRegistry.register instead! (' + $$namespace + '-' + $eventname + ')');
+ _kukit_eventsGlobalRegistry.register($$namespace, $eventname, $klass,
+ $bindmethodname, $defaultactionmethodname);
};
/* Event class decoration
@@ -253,148 +259,149 @@
* so we create a new oper below
*/
-kukit.er.EventBinder__continue_event__ = function(name, node, parms) {
+_kukit_er.EventBinder__continue_event__ = function($name, $$node, $parms) {
// Trigger a continuation event bound to a given state instance, given node
// (or on document, if node = null)
//
- var oper = new kukit.op.Oper();
- oper.node = node;
- if (node) {
+ var $oper = new _kukit.op.Oper();
+ $oper.node = $$node;
+ if ($$node) {
// if we found the binding, just use that
- var info = kukit.engine.binderInfoRegistry.getBinderInfoById(this.__binder_id__);
- var newoper = info.bound.getBoundOperForNode(name, node);
- if (newoper) {
- oper = newoper;
+ var info = _kukit.engine.binderInfoRegistry.getBinderInfoById(this.__binder_id__);
+ var $$newoper = info.bound.getBoundOperForNode($name, $$node);
+ if ($$newoper) {
+ $oper = $$newoper;
}
} else {
- oper.eventrule = kukit.engine.documentRules.getMergedRule('document', name, this);
+ $oper.eventrule = _kukit.engine.documentRules.getMergedRule('document', $name, this);
}
// Look up the behaviour rule, if any.
- var behav_eventrule = kukit.engine.documentRules.getMergedRule('behaviour', name, this);
- if (behav_eventrule) {
- if (! oper.eventrule) {
+ var $$behav_eventrule = _kukit.engine.documentRules.getMergedRule('behaviour', $name, this);
+ if ($$behav_eventrule) {
+ if (! $oper.eventrule) {
// There was no node matching for the rule, use behaviour rule
// this allows to set up parametrized actions in general.
- oper.eventrule = behav_eventrule;
+ $oper.eventrule = $$behav_eventrule;
} else {
// XXX this case should go away, as we should check this already from binding time
// and signal the appropriate error.
// Also note that behaviour roles will only be allowed for "non-binding" events.
- kukit.logError('Behaviour rule for continuation event "' + name + '" will be ignored, because we found an explicit rule.');
+ _kukit.logError('Behaviour rule for continuation event "' + $name + '" will be ignored, because we found an explicit rule.');
}
}
// If parameters are specified in the call, use them.
- if (typeof(parms) != 'undefined') {
- oper.parms = parms;
+ if (typeof($parms) != _undefined) {
+ $oper.parms = $parms;
} else {
- oper.parms = {};
+ $oper.parms = {};
}
// (if eventrule is null here, we can yet have the default method, so go on.)
- this._EventBinder_triggerevent(name, oper);
- kukit.logDebug('Continuation event "' + name + '" executed on same node.');
+ this._EventBinder_triggerevent($name, $oper);
+ _kukit.logDebug('Continuation event "' + $name + '" executed on same node.');
};
-kukit.er.EventBinder__continue_event_allnodes__ = function(name, parms) {
+_kukit_er.EventBinder__continue_event_allnodes__ = function($name, $parms) {
// Trigger an event bound to a given state instance, on all nodes.
// (or on document, if node = null)
// if no other nodes execute.
- var executed = 0;
+ var $$executed = 0;
// Normal rules. If any of those match, execute them too
// each on the node that it selects - not on the original node.
- var oper = new kukit.op.Oper();
- var info = kukit.engine.binderInfoRegistry.getBinderInfoById(this.__binder_id__);
- var opers = info.getBoundOpers(name);
- for (var i=0; i<opers.length; i++) {
- var oper = opers[i];
- var newoper = oper.clone();
- if (typeof(parms) != 'undefined') {
- newoper.parms = parms;
+ // XXX - fschulze - not used it seems:
+ // var oper = new _kukit.op.Oper();
+ var info = _kukit.engine.binderInfoRegistry.getBinderInfoById(this.__binder_id__);
+ var $opers = info.getBoundOpers($name);
+ for (var i=0; i<$opers.length; i++) {
+ var $$newoper = $opers[i].clone();
+ if (typeof($parms) != _undefined) {
+ $$newoper.parms = $parms;
} else {
- newoper.parms = {};
+ $$newoper.parms = {};
}
- this._EventBinder_triggerevent(name, newoper);
- executed += 1;
+ this._EventBinder_triggerevent($name, $$newoper);
+ $$executed += 1;
}
- kukit.logDebug('Event "' + name + '" executed on ' + executed + ' nodes.');
+ _kukit.logDebug('Event "' + $name + '" executed on ' + $$executed + ' nodes.');
};
-kukit.er.EventBinder_makeFuncToBind = function(name, node) {
- var executor = new kukit.er.LateBinder(this, name, node);
+_kukit_er.EventBinder_makeFuncToBind = function($name, $$node) {
+ var executor = new _kukit_er.LateBinder(this, $name, $$node);
return function() {
executor.executeActions();
};
};
-kukit.er.LateBinder = function(binderinstance, name, node) {
- this.binderinstance = binderinstance;
- this.name = name;
- this.node = node;
+_kukit_er.LateBinder = function($$binderinstance, $name, $$node) {
+ this.binderinstance = $$binderinstance;
+ this.name = $name;
+ this.node = $$node;
this.bound = null;
};
-kukit.er.LateBinder.prototype.executeActions = function() {
+_kukit_er.LateBinder.prototype.executeActions = function() {
if (! this.bound) {
- kukit.log('Attempt of late binding for event ' + this.name + ', node ' + this.node.nodeName);
- if (kukit.hasFirebug) {
- kukit.log(this.node);
- }
- var info = kukit.engine.binderInfoRegistry.getBinderInfoById(this.binderinstance.__binder_id__);
- var oper = info.bound.getBoundOperForNode(this.name, this.node);
- if (oper) {
+ _kukit.log('Attempt of late binding for event ' + this.name + ', node ' + this.node.nodeName);
+ if (_kukit.hasFirebug) {
+ _kukit.log(this.node);
+ }
+ var info = _kukit.engine.binderInfoRegistry.getBinderInfoById(this.binderinstance.__binder_id__);
+ var $oper = info.bound.getBoundOperForNode(this.name, this.node);
+ if ($oper) {
// (if eventrule is null here, we can yet have the default method, so go on.)
- oper.parms = {};
+ $oper.parms = {};
this.bound = function() {
- this.binderinstance._EventBinder_triggerevent(this.name, oper);
+ this.binderinstance._EventBinder_triggerevent(this.name, $oper);
};
- kukit.log('node bound');
+ _kukit.log('node bound');
} else {
- kukit.logWarning('no node bound');
+ _kukit.logWarning('no node bound');
this.bound = function() {};
}
}
this.bound();
};
-kukit.er.EventBinder_triggerevent = function(name, oper) {
+_kukit_er.EventBinder_triggerevent = function($name, $oper) {
// Private. Called from __continue_event__ or from main event execution.
- oper.binderinstance = this;
- if (oper.eventrule) {
+ $oper.binderinstance = this;
+ if ($oper.eventrule) {
// Call the actions, if we had an event rule.
// This includes calling the default action.
- oper.eventrule.actions.execute(oper);
+ $oper.eventrule.actions.execute($oper);
} else {
// In case there is no event rule, just call the default event action.
- var namespace = this.__event_namespace__;
- kukit.logDebug('Calling implicit event "' + name + '" on namespace "' + namespace + '"');
- var success = oper.executeDefaultAction(name, true);
+ var $$namespace = this.__event_namespace__;
+ _kukit.logDebug('Calling implicit event "' + $name + '" on namespace "' + $$namespace + '"');
+ var success = $oper.executeDefaultAction($name, true);
if (! success) {
// instead of the standard message give more specific reason:
// either way we should have executed something...
- throw 'Could not trigger event name "' + name + '" on namespace "' + namespace + '", because there is neither an explicit kss rule, nor a default method';
+ throw 'Could not trigger event name "' + $name + '" on namespace "' + $$namespace + '", because there is neither an explicit kss rule, nor a default method';
}
}
};
/* (default) method call handling */
-kukit.er.EventBinder_callmethod = function(namespace, name, oper, methodname) {
+_kukit_er.EventBinder_callmethod = function($$namespace, $name, $oper, $methodname) {
// hidden method for calling just a method and checking that is exists.
// (called from oper)
- var method = this[methodname];
+ var method = this[$methodname];
if (! method) {
- throw 'Could not trigger event name "' + name + '" on namespace "' + namespace + '", because the method "' + methodname + '" does not exist.';
+ throw 'Could not trigger event name "' + $name + '" on namespace "' + $$namespace + '", because the method "' + $methodname + '" does not exist.';
}
// call it
- oper.binderinstance = this;
- method.call(this, name, oper);
+ $oper.binderinstance = this;
+ method.call(this, $name, $oper);
};
-kukit.er.decorateEventBinderClass = function(cls) {
- cls.prototype.__continue_event__ = kukit.er.EventBinder__continue_event__;
- cls.prototype.__continue_event_allnodes__ = kukit.er.EventBinder__continue_event_allnodes__;
- cls.prototype._EventBinder_triggerevent = kukit.er.EventBinder_triggerevent;
- cls.prototype._EventBinder_callmethod = kukit.er.EventBinder_callmethod;
- cls.prototype.__make_func_to_bind__ = kukit.er.EventBinder_makeFuncToBind;
+_kukit_er.decorateEventBinderClass = function(cls) {
+ var $prototype = cls.prototype;
+ $prototype.__continue_event__ = _kukit_er.EventBinder__continue_event__;
+ $prototype.__continue_event_allnodes__ = _kukit_er.EventBinder__continue_event_allnodes__;
+ $prototype._EventBinder_triggerevent = _kukit_er.EventBinder_triggerevent;
+ $prototype._EventBinder_callmethod = _kukit_er.EventBinder_callmethod;
+ $prototype.__make_func_to_bind__ = _kukit_er.EventBinder_makeFuncToBind;
};
/* Event instance registry
@@ -405,72 +412,74 @@
*
*/
-kukit.er.BinderInfoRegistry = function () {
+_kukit_er.BinderInfoRegistry = function () {
this.info = {};
};
-kukit.er.BinderInfoRegistry.prototype.getOrCreateBinderInfo = function (id, classname, namespace) {
+var _kukit_er_BinderInfoRegistry_prototype = _kukit_er.BinderInfoRegistry.prototype;
+
+_kukit_er_BinderInfoRegistry_prototype.getOrCreateBinderInfo = function (id, $classname, $$namespace) {
// Get or create the event.
- var binderinfo = this.info[id];
- if (typeof(binderinfo) == 'undefined') {
+ var $binderinfo = this.info[id];
+ if (typeof($binderinfo) == _undefined) {
// Create a new event.
- kukit.logDebug('instantiating event id=' + id + ', classname=' + classname + ', namespace=' + namespace);
- binderinstance = new (kukit.eventsGlobalRegistry.getBinder(classname))();
+ _kukit.logDebug('instantiating event id=' + id + ', classname=' + $classname + ', namespace=' + $$namespace);
+ $$binderinstance = new (_kukit_eventsGlobalRegistry.getBinder($classname))();
- binderinfo = this.info[id] = new kukit.er.BinderInfo(binderinstance);
+ $binderinfo = this.info[id] = new _kukit_er.BinderInfo($$binderinstance);
// decorate it with id and class
- binderinstance.__binder_id__ = id;
- binderinstance.__binder_classname__ = classname;
- binderinstance.__event_namespace__ = namespace;
+ $$binderinstance.__binder_id__ = id;
+ $$binderinstance.__binder_classname__ = $classname;
+ $$binderinstance.__event_namespace__ = $$namespace;
// store the bound rules
- //binderinstance.__bound_rules__ = [];
- } else if (binderinfo.getBinderInstance().__binder_classname__ != classname) {
+ //$$binderinstance.__bound_rules__ = [];
+ } else if ($binderinfo.getBinderInstance().__binder_classname__ != $classname) {
// just paranoia
- throw 'Conflicting class for event id "' + id + '", "' + binderinfo.getBinderInstance().__binder_classname__
- + '" != "' + classname + '"';
+ throw 'Conflicting class for event id "' + id + '", "' + $binderinfo.getBinderInstance().__binder_classname__
+ + '" != "' + $classname + '"';
}
- return binderinfo;
+ return $binderinfo;
};
-kukit.er.BinderInfoRegistry.prototype.getBinderInfoById = function (id) {
+_kukit_er_BinderInfoRegistry_prototype.getBinderInfoById = function (id) {
// Get an event.
- var binderinfo = this.info[id];
- if (typeof(binderinfo) == 'undefined') {
+ var $binderinfo = this.info[id];
+ if (typeof($binderinfo) == _undefined) {
throw 'Event with id "' + id + '" not found.';
}
- return binderinfo;
+ return $binderinfo;
};
-kukit.er.BinderInfoRegistry.prototype.getSingletonBinderInfoByName = function (namespace, name) {
+_kukit_er_BinderInfoRegistry_prototype.getSingletonBinderInfoByName = function ($$namespace, $name) {
//Get classname
- var classname = kukit.eventsGlobalRegistry.get(namespace, name).classname;
+ var $classname = _kukit_eventsGlobalRegistry.get($$namespace, $name).classname;
// Get an event.
- var id = kukit.rd.makeId(namespace, classname);
- var binderinfo = this.info[id];
- if (typeof(binderinfo) == 'undefined') {
- throw 'Singleton event with namespace "' + namespace + '" and (event) name "' + name + '" not found.';
+ var id = _kukit.rd.makeId($$namespace, $classname);
+ var $binderinfo = this.info[id];
+ if (typeof($binderinfo) == _undefined) {
+ throw 'Singleton event with namespace "' + $$namespace + '" and (event) name "' + $name + '" not found.';
}
- return binderinfo;
+ return $binderinfo;
};
-kukit.er.BinderInfoRegistry.prototype.startBindingPhase = function () {
+_kukit_er_BinderInfoRegistry_prototype.startBindingPhase = function () {
// At the end of the binding phase, we want to process our events. This
// must include all the binder instances we bound in this phase.
for (var id in this.info) {
- var binderinfo = this.info[id];
+ var $binderinfo = this.info[id];
// process binding on this instance.
- binderinfo.startBindingPhase();
+ $binderinfo.startBindingPhase();
}
};
-kukit.er.BinderInfoRegistry.prototype.processBindingEvents = function () {
+_kukit_er_BinderInfoRegistry_prototype.processBindingEvents = function () {
// At the end of the binding phase, we want to process our events. This
// must include all the binder instances we bound in this phase.
for (var id in this.info) {
- var binderinfo = this.info[id];
+ var $binderinfo = this.info[id];
// process binding on this instance.
- binderinfo.processBindingEvents();
+ $binderinfo.processBindingEvents();
}
};
@@ -482,39 +491,40 @@
*
*/
-kukit.er.BinderInfo = function (binderinstance) {
- this.binderinstance = binderinstance;
- this.bound = new kukit.er.OperRegistry();
+_kukit_er.BinderInfo = function ($$binderinstance) {
+ this.binderinstance = $$binderinstance;
+ this.bound = new _kukit_er.OperRegistry();
this.startBindingPhase();
};
-kukit.er.BinderInfo.prototype.getBinderInstance = function () {
+var _kukit_er_BinderInfo_prototype = _kukit_er.BinderInfo.prototype;
+
+_kukit_er_BinderInfo_prototype.getBinderInstance = function () {
return this.binderinstance;
};
-kukit.er.BinderInfo.prototype.startBindingPhase = function () {
+_kukit_er_BinderInfo_prototype.startBindingPhase = function () {
// The bindind phase starts and it has the information for
// the currently on-bound events.
- this.binding = new kukit.er.OperRegistry();
+ this.binding = new _kukit_er.OperRegistry();
};
-kukit.er.BinderInfo.prototype.bindOper = function (oper) {
+_kukit_er_BinderInfo_prototype.bindOper = function ($oper) {
// We mark a given oper. This means a binding on the binderinstance
// for given event, node and eventrule (containing event namespace,
// name, and evt- parms.)
// first see if it can go to already bound ones
- this.bound.checkOperBindable(oper);
+ this.bound.checkOperBindable($oper);
// then register it properly to the binding events
- this.binding.bindOper(oper);
+ this.binding.bindOper($oper);
};
-kukit.er.BinderInfo.prototype.processBindingEvents = function () {
+_kukit_er_BinderInfo_prototype.processBindingEvents = function () {
// We came to the end of the binding phase. Now we process all our binding
// events, This will do the actual binding on the browser side.
- var eventRegistry = kukit.eventsGlobalRegistry;
- for (var i=0; i < eventRegistry.eventsets.length; i++) {
- var eventset = eventRegistry.eventsets[i];
+ for (var i=0; i < _kukit_eventsGlobalRegistry.eventsets.length; i++) {
+ var eventset = _kukit_eventsGlobalRegistry.eventsets[i];
if (this.binderinstance.__event_namespace__ == eventset.namespace) {
this._processBindingEventSet(eventset.names);
}
@@ -525,52 +535,53 @@
this.binding = null;
};
-kukit.er.BinderInfo.prototype._processBindingEventSet = function (names) {
+_kukit_er_BinderInfo_prototype._processBindingEventSet = function (names) {
// Bind finally for all the opers collected
- var opers = this.binding.getBoundOpersForEventSet(names);
- if (opers.length == 0) {
+ var $opers = this.binding.getBoundOpersForEventSet(names);
+ if ($opers.length == 0) {
return;
}
// find the bind method
// (We use the name and namespace from the first oper, as the bindmethod
// should be identical anyway.
- var kss_selector = opers[0].eventrule.kss_selector;
- var namespace = kss_selector.namespace;
- var name = kss_selector.name;
- var reg = kukit.eventsGlobalRegistry.get(namespace, name);
- var methodname = reg.bindmethodname;
+ var kss_selector = $opers[0].eventrule.kss_selector;
+ var $$namespace = kss_selector.namespace;
+ var $name = kss_selector.name;
+ var reg = _kukit_eventsGlobalRegistry.get($$namespace, $name);
+ var $methodname = reg.bindmethodname;
// XXX this is now disabled. We want to allow these events to "bind" on different nodes,
// however there is no actual event bound.
- if (! methodname) {
+ if (! $methodname) {
return;
- //throw new kukit.err.rd.EventBindError('Method is not defined as bindable', name, namespace);
+ //throw new kukit.err.rd.EventBindError('Method is not defined as bindable', $name, $$namespace);
}
- var method = this.binderinstance[methodname];
- if (typeof(method) == 'undefined' ) {
- throw new kukit.err.rd.EventBindError('Method "' + methodname + '" does not exist', name, namespace);
+ var method = this.binderinstance[$methodname];
+ if (typeof(method) == _undefined ) {
+ throw new _kukit.err.rd.EventBindError('Method "' + $methodname + '" does not exist', $name, $$namespace);
}
// Ok. Now decide if we go with the new or the old api.
if (reg.bindmethodapi == 'new') {
// Protect the binding for better logging
try {
- method.call(binderinstance, opers);
+ // XXX - fschulze - this was "binderinstance" which seemed wrong
+ method.call(this.binderinstance, $opers);
} catch(e) {
- throw new kukit.err.rd.EventBindError('Error during binding, reason: [' + e + ']', name, namespace);
+ throw new _kukit.err.rd.EventBindError('Error during binding, reason: [' + e + ']', $name, $$namespace);
}
} else { // old
- for (var i=0; i<opers.length; i++) {
- var oper = opers[i];
+ for (var i=0; i<$opers.length; i++) {
+ var oper = $opers[i];
var func_to_bind = oper.makeExecuteActionsHook();
if (this.binderinstance != oper.binderinstance) {
- throw new kukit.err.rd.EventBindError('fatal: wrong binder instance');
+ throw new _kukit.err.rd.EventBindError('fatal: wrong binder instance');
}
- var binderinstance = oper.binderinstance;
- var eventname = oper.getEventName();
+ var $$binderinstance = oper.binderinstance;
+ var $eventname = oper.getEventName();
// Protect the binding for better logging
try {
- method.call(binderinstance, eventname, func_to_bind, oper);
+ method.call($$binderinstance, $eventname, func_to_bind, oper);
} catch(e) {
- throw new kukit.err.rd.EventBindError('Error during binding, reason: [' + e + ']', eventname, oper.getEventNamespace());
+ throw new _kukit.err.rd.EventBindError('Error during binding, reason: [' + e + ']', $eventname, oper.getEventNamespace());
}
}
}
@@ -587,79 +598,81 @@
* a given event setup phase.
*/
-kukit.er.OperRegistry = function () {
+_kukit_er.OperRegistry = function () {
this.info = {};
};
-kukit.er.OperRegistry.prototype.propagateTo = function (newreg) {
- for (var key in this.info) {
- var rules_per_name = this.info[key];
- for (var name in rules_per_name) {
- var oper = rules_per_name[name];
- newreg.bindOper(oper);
+var _kukit_er_OperRegistry_prototype = _kukit_er.OperRegistry.prototype;
+
+_kukit_er_OperRegistry_prototype.propagateTo = function ($$newreg) {
+ for (var $key in this.info) {
+ var $rules_per_name = this.info[$key];
+ for (var $name in $rules_per_name) {
+ $$newreg.bindOper($rules_per_name[$name]);
}
}
};
-kukit.er.OperRegistry.prototype.checkOperBindable = function (oper) {
+_kukit_er_OperRegistry_prototype.checkOperBindable = function ($oper) {
// Check if the binding with this oper could be done.
// Throw exception otherwise.
- var info = this.info;
- var name = oper.eventrule.kss_selector.name;
- var nodehash = kukit.rd.hashnode(oper.node);
- var rules_per_name = info[name];
- if (typeof(rules_per_name) == 'undefined') {
+ var $name = $oper.eventrule.kss_selector.name;
+ var $$nodehash = _kukit.rd.hashnode($oper.node);
+ var $rules_per_name = this.info[$name];
+ if (typeof($rules_per_name) == _undefined) {
// Create an empty list.
- rules_per_name = info[name] = {};
- } else if (typeof(rules_per_name[nodehash]) != 'undefined') {
- throw 'Mismatch in bind registry, ' + name + ' already bound to node in this instance.';
+ $rules_per_name = this.info[$name] = {};
+ } else if (typeof($rules_per_name[$$nodehash]) != _undefined) {
+ throw 'Mismatch in bind registry, ' + $name + ' already bound to node in this instance.';
}
- return rules_per_name;
+ return $rules_per_name;
};
-kukit.er.OperRegistry.prototype.bindOper = function (oper) {
+_kukit_er_OperRegistry_prototype.bindOper = function ($oper) {
// Marks binding between binderinstance, eventname, node.
- var nodehash = kukit.rd.hashnode(oper.node);
- var rules_per_name = this.checkOperBindable(oper);
- rules_per_name[nodehash] = oper;
+ var $$nodehash = _kukit.rd.hashnode($oper.node);
+ var $rules_per_name = this.checkOperBindable($oper);
+ $rules_per_name[$$nodehash] = $oper;
};
-kukit.er.OperRegistry.prototype.getBoundOperForNode = function (name, node) {
+_kukit_er_OperRegistry_prototype.getBoundOperForNode = function ($name, $$node) {
// Get the oper that is bound to a given eventname to a node in this binderinstance
// returns null, if there is no such oper.
- var rules_per_name = this.info[name];
- if (typeof(rules_per_name) == 'undefined') {
+ var $rules_per_name = this.info[$name];
+ if (typeof($rules_per_name) == _undefined) {
return null;
}
- var nodehash = kukit.rd.hashnode(node);
- var oper = rules_per_name[nodehash];
- if (typeof(oper) == 'undefined') {
+ var $$nodehash = _kukit.rd.hashnode($$node);
+ var $oper = $rules_per_name[$$nodehash];
+ if (typeof($oper) == _undefined) {
return null;
}
// Return it
- return oper;
+ return $oper;
};
-kukit.er.OperRegistry.prototype.getBoundOpers = function (name) {
+_kukit_er_OperRegistry_prototype.getBoundOpers = function ($name) {
// Get the opers bound to a given eventname (to any node) in this binderinstance
- var opers = [];
- var rules_per_name = this.info[name];
- if (typeof(rules_per_name) != 'undefined') {
+ var $opers = [];
+ var $rules_per_name = this.info[$name];
+ if (typeof($rules_per_name) != _undefined) {
// take the values as a list
- for (var nodehash in rules_per_name) {
- opers.push(rules_per_name[nodehash]);
+ for (var $$nodehash in $rules_per_name) {
+ $opers.push($rules_per_name[$$nodehash]);
}
}
// Return it
- return opers;
+ return $opers;
};
-kukit.er.OperRegistry.prototype.getBoundOpersForEventSet = function (names) {
+_kukit_er_OperRegistry_prototype.getBoundOpersForEventSet = function ($names) {
// Returns all opers for a given eventset.
- var opers = [];
- for (var i=0; i<names.length; i++) {
- var name = names[i];
- opers = opers.concat(this.getBoundOpers(name));
+ var $opers = [];
+ for (var i=0; i<$names.length; i++) {
+ $opers = $opers.concat(this.getBoundOpers($names[i]));
}
- return opers;
+ return $opers;
};
+
+// end local scope
+}();
Added: kukit/kukit.js/branch/fschulze-js-compression/kukit/progress/eventreg-1.js
==============================================================================
--- (empty file)
+++ kukit/kukit.js/branch/fschulze-js-compression/kukit/progress/eventreg-1.js Thu Apr 5 12:48:44 2007
@@ -0,0 +1,670 @@
+/*
+* Copyright (c) 2005-2006
+* Authors:
+* Godefroid Chapelle <gotcha at bubblenet.be>
+* Florian Schulze <florian.schulze at gmx.net>
+* Balázs Reé <ree at greenfinity.hu>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as published
+* by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+* 02111-1307, USA.
+*/
+
+kukit.er = {};
+
+// start local scope
+var _er = function() {
+
+kukit.er.eventClassCounter = 0;
+
+/*
+*
+* class CommandRegistry
+*
+* available for plugin registration
+*
+* usage:
+*
+* kukit.eventsGlobalRegistry.register(namespace, eventname, func,
+* bindmethodname, defaultactionmethodname);
+*
+* namespace = null: means global namespace
+* defaultactionmethodname = null: if there is no default action implemented
+* func must be a class (constructor) function, this is the class that
+* implements the binder.
+*/
+kukit.er.EventRegistry = function () {
+ this.content = {};
+ this.classes = {};
+ this.eventsets = [];
+};
+
+/* binder registration */
+
+kukit.er.EventRegistry.prototype.registerBinder = function(classname, func) {
+ if (typeof(func) == 'undefined') {
+ throw 'func argument is mandatory when registering an event binder (EventRegistry.registerBinder).';
+ }
+ if (this.classes[classname]) {
+ // Do not allow redefinition
+ kukit.logError('Error : event class "' + classname + '" already registered.');
+ return;
+
+ }
+ // Decorate and store the class
+ kukit.er.decorateEventBinderClass(func);
+ this.classes[classname] = func;
+};
+
+kukit.er.EventRegistry.prototype.existsBinder = function(classname) {
+ var func = this.classes[classname];
+ return (typeof(func) != 'undefined');
+};
+
+kukit.er.EventRegistry.prototype.getBinder = function(classname) {
+ var func = this.classes[classname];
+ if (! func) {
+ // not found
+ throw 'Error : undefined event setup type ' + classname;
+ }
+ return func;
+};
+
+/* events (methods) registration helpers (not to be called directly) */
+
+kukit.er.EventRegistry.prototype._register = function(namespace, eventname, klass,
+ bindmethodname, defaultactionmethodname, bindmethodapi) {
+ if (typeof(defaultactionmethodname) == 'undefined') {
+ throw 'some arguments are not passed when calling EventRegistry.register';
+ }
+ // Find out the class name. (Not specified now.)
+ var classname = klass.prototype.__classname__;
+ if (typeof(classname) == 'undefined') {
+ // Create a classname, and register it too.
+ classname = '' + kukit.er.eventClassCounter;
+ kukit.er.eventClassCounter += 1;
+ this.registerBinder(classname, klass);
+ klass.prototype.__classname__ = classname;
+ }
+ if (!eventname) {
+ throw 'eventname argument cannot be empty when registering an event (EventRegistry.register)';
+ }
+ var key = this._getKey(namespace, eventname);
+ var entry = this.content[key];
+ if (typeof(entry) != 'undefined') {
+ if (key[0] == '-') {
+ key = key.substring(1);
+ }
+ throw 'In EventRegistry.register double registration of key "' + key + '"';
+ }
+ // register it
+ this.content[key] = {
+ 'classname': classname,
+ 'bindmethodname': bindmethodname,
+ 'defaultactionmethodname': defaultactionmethodname,
+ 'bindmethodapi': bindmethodapi
+ };
+};
+
+/* events (methods) binding "ForAll" registration */
+
+kukit.er.EventRegistry.prototype._registerEventSet = function(namespace, names) {
+ // At this name the class and event should be checked already. so this should
+ // be called _after_ _register.
+ this.eventsets.push({'namespace': namespace, 'names': names});
+};
+
+
+/* there are the actual registration methods, to be called from plugins */
+
+kukit.er.EventRegistry.prototype.register = function(namespace, eventname, klass,
+ bindmethodname, defaultactionmethodname) {
+ this._register(namespace, eventname, klass, bindmethodname, defaultactionmethodname, 'old');
+ this._registerEventSet(namespace, [eventname]);
+};
+
+kukit.er.EventRegistry.prototype.registerForAllEvents = function(namespace, eventnames, klass,
+ bindmethodname, defaultactionmethodname) {
+ if (typeof(eventnames) == 'string') {
+ eventnames = [eventnames];
+ }
+ for (var i=0; i<eventnames.length; i++) {
+ var eventname = eventnames[i];
+ this._register(namespace, eventname, klass, bindmethodname, defaultactionmethodname, 'new');
+ }
+ this._registerEventSet(namespace, eventnames);
+};
+
+kukit.er.EventRegistry.prototype._getKey = function(namespace, eventname) {
+ if (namespace == null) {
+ namespace = '';
+ } else if (namespace.split('-') > 1) {
+ throw 'In EventRegistry.register namespace cannot contain -';
+ }
+ return namespace + '-' + eventname;
+};
+
+kukit.er.EventRegistry.prototype.exists = function(namespace, eventname) {
+ var key = this._getKey(namespace, eventname);
+ var entry = this.content[key];
+ return (typeof(entry) != 'undefined');
+};
+
+kukit.er.EventRegistry.prototype.get = function(namespace, eventname) {
+ var key = this._getKey(namespace, eventname);
+ var entry = this.content[key];
+ if (typeof(entry) == 'undefined') {
+ if (key[0] == '-') {
+ key = key.substring(1);
+ throw 'Error : undefined global event key ' + key + ' (or maybe namespace is missing?)';
+ } else {
+ throw 'Error : undefined event key ' + key;
+ }
+ }
+ return entry;
+};
+
+kukit.eventsGlobalRegistry = new kukit.er.EventRegistry();
+
+
+/* XXX deprecated methods, to be removed asap */
+
+kukit.er.eventRegistry = {};
+kukit.er.eventRegistry.register = function(namespace, eventname, klass,
+ bindmethodname, defaultactionmethodname) {
+ kukit.logWarning('Deprecated kukit.er.eventRegistry.register, use kukit.eventsGlobalRegistry.register instead! (' + namespace + '-' + eventname + ')');
+ kukit.eventsGlobalRegistry.register(namespace, eventname, klass,
+ bindmethodname, defaultactionmethodname);
+};
+
+/* Event class decoration
+*
+* poor man's subclassing
+* This is called automatically on registration, to dress
+* up the event class with the necessary methods
+*
+*/
+
+/* Provide callins on the state instance that execute a given
+* continuation event.
+* Parameters will be the ones specified in the call +
+* those defined in the rule will be added too. (Parameters can
+* be accessed with the "pass" kss parameter provider.)
+*
+* Call examples:
+*
+* trigger an event bound to a given state instance, same node
+*
+* binderinstance.__continue_event__('doit', oper.node, {'extravalue': '5'});
+*
+* with kss rule:
+*
+* node.selector:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* or
+*
+* behaviour.selector:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* trigger an event bound to a given state instance, and the document
+* (different from current scope)
+*
+* binderinstance.__continue_event__('doit', null, {'extravalue': '5'});
+*
+* with kss rule:
+*
+* document:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* or
+*
+* behaviour.selector:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* trigger an event on all the nodes + document bound to a given state instance
+*
+* binderinstance.__continue_event_allnodes__('doit', {'extravalue': '5'});
+*
+* with kss rule:
+*
+* node.selector:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* p.s. oper is not required to make it easy to adapt existing code
+* so we create a new oper below
+*/
+
+kukit.er.EventBinder__continue_event__ = function(name, node, parms) {
+ // Trigger a continuation event bound to a given state instance, given node
+ // (or on document, if node = null)
+ //
+ var oper = new kukit.op.Oper();
+ oper.node = node;
+ if (node) {
+ // if we found the binding, just use that
+ var info = kukit.engine.binderInfoRegistry.getBinderInfoById(this.__binder_id__);
+ var newoper = info.bound.getBoundOperForNode(name, node);
+ if (newoper) {
+ oper = newoper;
+ }
+ } else {
+ oper.eventrule = kukit.engine.documentRules.getMergedRule('document', name, this);
+ }
+ // Look up the behaviour rule, if any.
+ var behav_eventrule = kukit.engine.documentRules.getMergedRule('behaviour', name, this);
+ if (behav_eventrule) {
+ if (! oper.eventrule) {
+ // There was no node matching for the rule, use behaviour rule
+ // this allows to set up parametrized actions in general.
+ oper.eventrule = behav_eventrule;
+ } else {
+ // XXX this case should go away, as we should check this already from binding time
+ // and signal the appropriate error.
+ // Also note that behaviour roles will only be allowed for "non-binding" events.
+ kukit.logError('Behaviour rule for continuation event "' + name + '" will be ignored, because we found an explicit rule.');
+ }
+ }
+ // If parameters are specified in the call, use them.
+ if (typeof(parms) != 'undefined') {
+ oper.parms = parms;
+ } else {
+ oper.parms = {};
+ }
+ // (if eventrule is null here, we can yet have the default method, so go on.)
+ this._EventBinder_triggerevent(name, oper);
+ kukit.logDebug('Continuation event "' + name + '" executed on same node.');
+};
+
+kukit.er.EventBinder__continue_event_allnodes__ = function(name, parms) {
+ // Trigger an event bound to a given state instance, on all nodes.
+ // (or on document, if node = null)
+ // if no other nodes execute.
+ var executed = 0;
+ // Normal rules. If any of those match, execute them too
+ // each on the node that it selects - not on the original node.
+ var oper = new kukit.op.Oper();
+ var info = kukit.engine.binderInfoRegistry.getBinderInfoById(this.__binder_id__);
+ var opers = info.getBoundOpers(name);
+ for (var i=0; i<opers.length; i++) {
+ var oper = opers[i];
+ var newoper = oper.clone();
+ if (typeof(parms) != 'undefined') {
+ newoper.parms = parms;
+ } else {
+ newoper.parms = {};
+ }
+ this._EventBinder_triggerevent(name, newoper);
+ executed += 1;
+ }
+ kukit.logDebug('Event "' + name + '" executed on ' + executed + ' nodes.');
+};
+
+kukit.er.EventBinder_makeFuncToBind = function(name, node) {
+ var executor = new kukit.er.LateBinder(this, name, node);
+ return function() {
+ executor.executeActions();
+ };
+};
+
+kukit.er.LateBinder = function(binderinstance, name, node) {
+ this.binderinstance = binderinstance;
+ this.name = name;
+ this.node = node;
+ this.bound = null;
+};
+
+kukit.er.LateBinder.prototype.executeActions = function() {
+ if (! this.bound) {
+ kukit.log('Attempt of late binding for event ' + this.name + ', node ' + this.node.nodeName);
+ if (kukit.hasFirebug) {
+ kukit.log(this.node);
+ }
+ var info = kukit.engine.binderInfoRegistry.getBinderInfoById(this.binderinstance.__binder_id__);
+ var oper = info.bound.getBoundOperForNode(this.name, this.node);
+ if (oper) {
+ // (if eventrule is null here, we can yet have the default method, so go on.)
+ oper.parms = {};
+ this.bound = function() {
+ this.binderinstance._EventBinder_triggerevent(this.name, oper);
+ };
+ kukit.log('node bound');
+ } else {
+ kukit.logWarning('no node bound');
+ this.bound = function() {};
+ }
+ }
+ this.bound();
+};
+
+kukit.er.EventBinder_triggerevent = function(name, oper) {
+ // Private. Called from __continue_event__ or from main event execution.
+ oper.binderinstance = this;
+ if (oper.eventrule) {
+ // Call the actions, if we had an event rule.
+ // This includes calling the default action.
+ oper.eventrule.actions.execute(oper);
+ } else {
+ // In case there is no event rule, just call the default event action.
+ var namespace = this.__event_namespace__;
+ kukit.logDebug('Calling implicit event "' + name + '" on namespace "' + namespace + '"');
+ var success = oper.executeDefaultAction(name, true);
+ if (! success) {
+ // instead of the standard message give more specific reason:
+ // either way we should have executed something...
+ throw 'Could not trigger event name "' + name + '" on namespace "' + namespace + '", because there is neither an explicit kss rule, nor a default method';
+ }
+ }
+};
+
+/* (default) method call handling */
+
+kukit.er.EventBinder_callmethod = function(namespace, name, oper, methodname) {
+ // hidden method for calling just a method and checking that is exists.
+ // (called from oper)
+ var method = this[methodname];
+ if (! method) {
+ throw 'Could not trigger event name "' + name + '" on namespace "' + namespace + '", because the method "' + methodname + '" does not exist.';
+ }
+ // call it
+ oper.binderinstance = this;
+ method.call(this, name, oper);
+};
+
+kukit.er.decorateEventBinderClass = function(cls) {
+ cls.prototype.__continue_event__ = kukit.er.EventBinder__continue_event__;
+ cls.prototype.__continue_event_allnodes__ = kukit.er.EventBinder__continue_event_allnodes__;
+ cls.prototype._EventBinder_triggerevent = kukit.er.EventBinder_triggerevent;
+ cls.prototype._EventBinder_callmethod = kukit.er.EventBinder_callmethod;
+ cls.prototype.__make_func_to_bind__ = kukit.er.EventBinder_makeFuncToBind;
+};
+
+/* Event instance registry
+*
+* class BinderInfoRegistry
+*
+* used in run-time to keep track of the event instances
+*
+*/
+
+kukit.er.BinderInfoRegistry = function () {
+ this.info = {};
+};
+
+kukit.er.BinderInfoRegistry.prototype.getOrCreateBinderInfo = function (id, classname, namespace) {
+ // Get or create the event.
+ var binderinfo = this.info[id];
+ if (typeof(binderinfo) == 'undefined') {
+ // Create a new event.
+ kukit.logDebug('instantiating event id=' + id + ', classname=' + classname + ', namespace=' + namespace);
+ binderinstance = new (kukit.eventsGlobalRegistry.getBinder(classname))();
+
+ binderinfo = this.info[id] = new kukit.er.BinderInfo(binderinstance);
+
+ // decorate it with id and class
+ binderinstance.__binder_id__ = id;
+ binderinstance.__binder_classname__ = classname;
+ binderinstance.__event_namespace__ = namespace;
+ // store the bound rules
+ //binderinstance.__bound_rules__ = [];
+ } else if (binderinfo.getBinderInstance().__binder_classname__ != classname) {
+ // just paranoia
+ throw 'Conflicting class for event id "' + id + '", "' + binderinfo.getBinderInstance().__binder_classname__
+ + '" != "' + classname + '"';
+ }
+ return binderinfo;
+};
+
+kukit.er.BinderInfoRegistry.prototype.getBinderInfoById = function (id) {
+ // Get an event.
+ var binderinfo = this.info[id];
+ if (typeof(binderinfo) == 'undefined') {
+ throw 'Event with id "' + id + '" not found.';
+ }
+ return binderinfo;
+};
+
+kukit.er.BinderInfoRegistry.prototype.getSingletonBinderInfoByName = function (namespace, name) {
+ //Get classname
+ var classname = kukit.eventsGlobalRegistry.get(namespace, name).classname;
+ // Get an event.
+ var id = kukit.rd.makeId(namespace, classname);
+ var binderinfo = this.info[id];
+ if (typeof(binderinfo) == 'undefined') {
+ throw 'Singleton event with namespace "' + namespace + '" and (event) name "' + name + '" not found.';
+ }
+ return binderinfo;
+};
+
+kukit.er.BinderInfoRegistry.prototype.startBindingPhase = function () {
+ // At the end of the binding phase, we want to process our events. This
+ // must include all the binder instances we bound in this phase.
+ for (var id in this.info) {
+ var binderinfo = this.info[id];
+ // process binding on this instance.
+ binderinfo.startBindingPhase();
+ }
+};
+
+kukit.er.BinderInfoRegistry.prototype.processBindingEvents = function () {
+ // At the end of the binding phase, we want to process our events. This
+ // must include all the binder instances we bound in this phase.
+ for (var id in this.info) {
+ var binderinfo = this.info[id];
+ // process binding on this instance.
+ binderinfo.processBindingEvents();
+ }
+};
+
+/*
+* class BinderInfo
+*
+* Information about the given binder instance. This contains the instance and
+* various binding info. Follows the workflow of the binding in different stages.
+*
+*/
+
+kukit.er.BinderInfo = function (binderinstance) {
+ this.binderinstance = binderinstance;
+ this.bound = new kukit.er.OperRegistry();
+ this.startBindingPhase();
+};
+
+kukit.er.BinderInfo.prototype.getBinderInstance = function () {
+ return this.binderinstance;
+};
+
+kukit.er.BinderInfo.prototype.startBindingPhase = function () {
+ // The bindind phase starts and it has the information for
+ // the currently on-bound events.
+ this.binding = new kukit.er.OperRegistry();
+};
+
+kukit.er.BinderInfo.prototype.bindOper = function (oper) {
+ // We mark a given oper. This means a binding on the binderinstance
+ // for given event, node and eventrule (containing event namespace,
+ // name, and evt- parms.)
+
+ // first see if it can go to already bound ones
+ this.bound.checkOperBindable(oper);
+ // then register it properly to the binding events
+ this.binding.bindOper(oper);
+};
+
+kukit.er.BinderInfo.prototype.processBindingEvents = function () {
+ // We came to the end of the binding phase. Now we process all our binding
+ // events, This will do the actual binding on the browser side.
+ var eventRegistry = kukit.eventsGlobalRegistry;
+ for (var i=0; i < eventRegistry.eventsets.length; i++) {
+ var eventset = eventRegistry.eventsets[i];
+ if (this.binderinstance.__event_namespace__ == eventset.namespace) {
+ this._processBindingEventSet(eventset.names);
+ }
+ }
+ // Now we to add these to the new ones.
+ this.binding.propagateTo(this.bound);
+ // Delete them from the registry, to protect against accidents.
+ this.binding = null;
+};
+
+kukit.er.BinderInfo.prototype._processBindingEventSet = function (names) {
+ // Bind finally for all the opers collected
+ var opers = this.binding.getBoundOpersForEventSet(names);
+ if (opers.length == 0) {
+ return;
+ }
+ // find the bind method
+ // (We use the name and namespace from the first oper, as the bindmethod
+ // should be identical anyway.
+ var kss_selector = opers[0].eventrule.kss_selector;
+ var namespace = kss_selector.namespace;
+ var name = kss_selector.name;
+ var reg = kukit.eventsGlobalRegistry.get(namespace, name);
+ var methodname = reg.bindmethodname;
+ // XXX this is now disabled. We want to allow these events to "bind" on different nodes,
+ // however there is no actual event bound.
+ if (! methodname) {
+ return;
+ //throw new kukit.err.rd.EventBindError('Method is not defined as bindable', name, namespace);
+ }
+ var method = this.binderinstance[methodname];
+ if (typeof(method) == 'undefined' ) {
+ throw new kukit.err.rd.EventBindError('Method "' + methodname + '" does not exist', name, namespace);
+ }
+ // Ok. Now decide if we go with the new or the old api.
+ if (reg.bindmethodapi == 'new') {
+ // Protect the binding for better logging
+ try {
+ method.call(binderinstance, opers);
+ } catch(e) {
+ throw new kukit.err.rd.EventBindError('Error during binding, reason: [' + e + ']', name, namespace);
+ }
+ } else { // old
+ for (var i=0; i<opers.length; i++) {
+ var oper = opers[i];
+ var func_to_bind = oper.makeExecuteActionsHook();
+ if (this.binderinstance != oper.binderinstance) {
+ throw new kukit.err.rd.EventBindError('fatal: wrong binder instance');
+ }
+ var binderinstance = oper.binderinstance;
+ var eventname = oper.getEventName();
+ // Protect the binding for better logging
+ try {
+ method.call(binderinstance, eventname, func_to_bind, oper);
+ } catch(e) {
+ throw new kukit.err.rd.EventBindError('Error during binding, reason: [' + e + ']', eventname, oper.getEventNamespace());
+ }
+ }
+ }
+};
+
+
+/*
+* class OperRegistry
+*
+* OperRegistry is associated with a binder instance in the
+* BinderInfoRegistry, and remembers bounding information.
+* This is used both to remember all the bindings for a given
+* instance, but also just to remember the bindings done during
+* a given event setup phase.
+*/
+
+kukit.er.OperRegistry = function () {
+ this.info = {};
+};
+
+kukit.er.OperRegistry.prototype.propagateTo = function (newreg) {
+ for (var key in this.info) {
+ var rules_per_name = this.info[key];
+ for (var name in rules_per_name) {
+ var oper = rules_per_name[name];
+ newreg.bindOper(oper);
+ }
+ }
+};
+
+kukit.er.OperRegistry.prototype.checkOperBindable = function (oper) {
+ // Check if the binding with this oper could be done.
+ // Throw exception otherwise.
+ var info = this.info;
+ var name = oper.eventrule.kss_selector.name;
+ var nodehash = kukit.rd.hashnode(oper.node);
+ var rules_per_name = info[name];
+ if (typeof(rules_per_name) == 'undefined') {
+ // Create an empty list.
+ rules_per_name = info[name] = {};
+ } else if (typeof(rules_per_name[nodehash]) != 'undefined') {
+ throw 'Mismatch in bind registry, ' + name + ' already bound to node in this instance.';
+ }
+ return rules_per_name;
+};
+
+kukit.er.OperRegistry.prototype.bindOper = function (oper) {
+ // Marks binding between binderinstance, eventname, node.
+ var nodehash = kukit.rd.hashnode(oper.node);
+ var rules_per_name = this.checkOperBindable(oper);
+ rules_per_name[nodehash] = oper;
+};
+
+kukit.er.OperRegistry.prototype.getBoundOperForNode = function (name, node) {
+ // Get the oper that is bound to a given eventname to a node in this binderinstance
+ // returns null, if there is no such oper.
+ var rules_per_name = this.info[name];
+ if (typeof(rules_per_name) == 'undefined') {
+ return null;
+ }
+ var nodehash = kukit.rd.hashnode(node);
+ var oper = rules_per_name[nodehash];
+ if (typeof(oper) == 'undefined') {
+ return null;
+ }
+ // Return it
+ return oper;
+};
+
+kukit.er.OperRegistry.prototype.getBoundOpers = function (name) {
+ // Get the opers bound to a given eventname (to any node) in this binderinstance
+ var opers = [];
+ var rules_per_name = this.info[name];
+ if (typeof(rules_per_name) != 'undefined') {
+ // take the values as a list
+ for (var nodehash in rules_per_name) {
+ opers.push(rules_per_name[nodehash]);
+ }
+ }
+ // Return it
+ return opers;
+};
+
+kukit.er.OperRegistry.prototype.getBoundOpersForEventSet = function (names) {
+ // Returns all opers for a given eventset.
+ var opers = [];
+ for (var i=0; i<names.length; i++) {
+ var name = names[i];
+ opers = opers.concat(this.getBoundOpers(name));
+ }
+ return opers;
+};
+
+// end local scope
+}();
Added: kukit/kukit.js/branch/fschulze-js-compression/kukit/progress/eventreg-2.js
==============================================================================
--- (empty file)
+++ kukit/kukit.js/branch/fschulze-js-compression/kukit/progress/eventreg-2.js Thu Apr 5 12:48:44 2007
@@ -0,0 +1,670 @@
+/*
+* Copyright (c) 2005-2006
+* Authors:
+* Godefroid Chapelle <gotcha at bubblenet.be>
+* Florian Schulze <florian.schulze at gmx.net>
+* Balázs Reé <ree at greenfinity.hu>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as published
+* by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+* 02111-1307, USA.
+*/
+
+kukit.er = {};
+
+// start local scope
+var _er = function() {
+
+kukit.er.eventClassCounter = 0;
+
+/*
+*
+* class CommandRegistry
+*
+* available for plugin registration
+*
+* usage:
+*
+* kukit.eventsGlobalRegistry.register(namespace, eventname, func,
+* bindmethodname, defaultactionmethodname);
+*
+* namespace = null: means global namespace
+* defaultactionmethodname = null: if there is no default action implemented
+* func must be a class (constructor) function, this is the class that
+* implements the binder.
+*/
+kukit.er.EventRegistry = function () {
+ this.content = {};
+ this.classes = {};
+ this.eventsets = [];
+};
+
+/* binder registration */
+
+kukit.er.EventRegistry.prototype.registerBinder = function($classname, $func) {
+ if (typeof($func) == 'undefined') {
+ throw 'func argument is mandatory when registering an event binder (EventRegistry.registerBinder).';
+ }
+ if (this.classes[$classname]) {
+ // Do not allow redefinition
+ kukit.logError('Error : event class "' + $classname + '" already registered.');
+ return;
+
+ }
+ // Decorate and store the class
+ kukit.er.decorateEventBinderClass($func);
+ this.classes[$classname] = $func;
+};
+
+kukit.er.EventRegistry.prototype.existsBinder = function($classname) {
+ var $func = this.classes[$classname];
+ return (typeof($func) != 'undefined');
+};
+
+kukit.er.EventRegistry.prototype.getBinder = function($classname) {
+ var $func = this.classes[$classname];
+ if (! $func) {
+ // not found
+ throw 'Error : undefined event setup type ' + $classname;
+ }
+ return $func;
+};
+
+/* events (methods) registration helpers (not to be called directly) */
+
+kukit.er.EventRegistry.prototype._register = function($namespace, $eventname, $klass,
+ $bindmethodname, $defaultactionmethodname, $$bindmethodapi) {
+ if (typeof($defaultactionmethodname) == 'undefined') {
+ throw 'some arguments are not passed when calling EventRegistry.register';
+ }
+ // Find out the class name. (Not specified now.)
+ var $classname = $klass.prototype.__classname__;
+ if (typeof($classname) == 'undefined') {
+ // Create a classname, and register it too.
+ $classname = '' + kukit.er.eventClassCounter;
+ kukit.er.eventClassCounter += 1;
+ this.registerBinder($classname, $klass);
+ $klass.prototype.__classname__ = $classname;
+ }
+ if (!$eventname) {
+ throw 'eventname argument cannot be empty when registering an event (EventRegistry.register)';
+ }
+ var key = this._getKey($namespace, $eventname);
+ var entry = this.content[key];
+ if (typeof(entry) != 'undefined') {
+ if (key[0] == '-') {
+ key = key.substring(1);
+ }
+ throw 'In EventRegistry.register double registration of key "' + key + '"';
+ }
+ // register it
+ this.content[key] = {
+ 'classname': $classname,
+ 'bindmethodname': $bindmethodname,
+ 'defaultactionmethodname': $defaultactionmethodname,
+ 'bindmethodapi': $$bindmethodapi
+ };
+};
+
+/* events (methods) binding "ForAll" registration */
+
+kukit.er.EventRegistry.prototype._registerEventSet = function($namespace, names) {
+ // At this name the class and event should be checked already. so this should
+ // be called _after_ _register.
+ this.eventsets.push({'namespace': $namespace, 'names': names});
+};
+
+
+/* there are the actual registration methods, to be called from plugins */
+
+kukit.er.EventRegistry.prototype.register = function($namespace, $eventname, $klass,
+ $bindmethodname, $defaultactionmethodname) {
+ this._register($namespace, $eventname, $klass, $bindmethodname, $defaultactionmethodname, 'old');
+ this._registerEventSet($namespace, [$eventname]);
+};
+
+kukit.er.EventRegistry.prototype.registerForAllEvents = function($namespace, $eventnames, $klass,
+ $bindmethodname, $defaultactionmethodname) {
+ if (typeof($eventnames) == 'string') {
+ $eventnames = [$eventnames];
+ }
+ for (var i=0; i<$eventnames.length; i++) {
+ var $$eventname = $eventnames[i];
+ this._register($namespace, $$eventname, $klass, $bindmethodname, $defaultactionmethodname, 'new');
+ }
+ this._registerEventSet($namespace, $eventnames);
+};
+
+kukit.er.EventRegistry.prototype._getKey = function($namespace, $eventname) {
+ if ($namespace == null) {
+ $namespace = '';
+ } else if ($namespace.split('-') > 1) {
+ throw 'In EventRegistry.register namespace cannot contain -';
+ }
+ return $namespace + '-' + $eventname;
+};
+
+kukit.er.EventRegistry.prototype.exists = function($namespace, $eventname) {
+ var key = this._getKey($namespace, $eventname);
+ var entry = this.content[key];
+ return (typeof(entry) != 'undefined');
+};
+
+kukit.er.EventRegistry.prototype.get = function($namespace, $eventname) {
+ var key = this._getKey($namespace, $eventname);
+ var entry = this.content[key];
+ if (typeof(entry) == 'undefined') {
+ if (key[0] == '-') {
+ key = key.substring(1);
+ throw 'Error : undefined global event key ' + key + ' (or maybe namespace is missing?)';
+ } else {
+ throw 'Error : undefined event key ' + key;
+ }
+ }
+ return entry;
+};
+
+kukit.eventsGlobalRegistry = new kukit.er.EventRegistry();
+
+
+/* XXX deprecated methods, to be removed asap */
+
+kukit.er.eventRegistry = {};
+kukit.er.eventRegistry.register = function($namespace, $eventname, $klass,
+ $bindmethodname, $defaultactionmethodname) {
+ kukit.logWarning('Deprecated kukit.er.eventRegistry.register, use kukit.eventsGlobalRegistry.register instead! (' + $namespace + '-' + $eventname + ')');
+ kukit.eventsGlobalRegistry.register($namespace, $eventname, $klass,
+ $bindmethodname, $defaultactionmethodname);
+};
+
+/* Event class decoration
+*
+* poor man's subclassing
+* This is called automatically on registration, to dress
+* up the event class with the necessary methods
+*
+*/
+
+/* Provide callins on the state instance that execute a given
+* continuation event.
+* Parameters will be the ones specified in the call +
+* those defined in the rule will be added too. (Parameters can
+* be accessed with the "pass" kss parameter provider.)
+*
+* Call examples:
+*
+* trigger an event bound to a given state instance, same node
+*
+* binderinstance.__continue_event__('doit', oper.node, {'extravalue': '5'});
+*
+* with kss rule:
+*
+* node.selector:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* or
+*
+* behaviour.selector:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* trigger an event bound to a given state instance, and the document
+* (different from current scope)
+*
+* binderinstance.__continue_event__('doit', null, {'extravalue': '5'});
+*
+* with kss rule:
+*
+* document:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* or
+*
+* behaviour.selector:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* trigger an event on all the nodes + document bound to a given state instance
+*
+* binderinstance.__continue_event_allnodes__('doit', {'extravalue': '5'});
+*
+* with kss rule:
+*
+* node.selector:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* p.s. oper is not required to make it easy to adapt existing code
+* so we create a new oper below
+*/
+
+kukit.er.EventBinder__continue_event__ = function(name, node, parms) {
+ // Trigger a continuation event bound to a given state instance, given node
+ // (or on document, if node = null)
+ //
+ var oper = new kukit.op.Oper();
+ oper.node = node;
+ if (node) {
+ // if we found the binding, just use that
+ var info = kukit.engine.binderInfoRegistry.getBinderInfoById(this.__binder_id__);
+ var newoper = info.bound.getBoundOperForNode(name, node);
+ if (newoper) {
+ oper = newoper;
+ }
+ } else {
+ oper.eventrule = kukit.engine.documentRules.getMergedRule('document', name, this);
+ }
+ // Look up the behaviour rule, if any.
+ var behav_eventrule = kukit.engine.documentRules.getMergedRule('behaviour', name, this);
+ if (behav_eventrule) {
+ if (! oper.eventrule) {
+ // There was no node matching for the rule, use behaviour rule
+ // this allows to set up parametrized actions in general.
+ oper.eventrule = behav_eventrule;
+ } else {
+ // XXX this case should go away, as we should check this already from binding time
+ // and signal the appropriate error.
+ // Also note that behaviour roles will only be allowed for "non-binding" events.
+ kukit.logError('Behaviour rule for continuation event "' + name + '" will be ignored, because we found an explicit rule.');
+ }
+ }
+ // If parameters are specified in the call, use them.
+ if (typeof(parms) != 'undefined') {
+ oper.parms = parms;
+ } else {
+ oper.parms = {};
+ }
+ // (if eventrule is null here, we can yet have the default method, so go on.)
+ this._EventBinder_triggerevent(name, oper);
+ kukit.logDebug('Continuation event "' + name + '" executed on same node.');
+};
+
+kukit.er.EventBinder__continue_event_allnodes__ = function(name, parms) {
+ // Trigger an event bound to a given state instance, on all nodes.
+ // (or on document, if node = null)
+ // if no other nodes execute.
+ var executed = 0;
+ // Normal rules. If any of those match, execute them too
+ // each on the node that it selects - not on the original node.
+ var oper = new kukit.op.Oper();
+ var info = kukit.engine.binderInfoRegistry.getBinderInfoById(this.__binder_id__);
+ var opers = info.getBoundOpers(name);
+ for (var i=0; i<opers.length; i++) {
+ var oper = opers[i];
+ var newoper = oper.clone();
+ if (typeof(parms) != 'undefined') {
+ newoper.parms = parms;
+ } else {
+ newoper.parms = {};
+ }
+ this._EventBinder_triggerevent(name, newoper);
+ executed += 1;
+ }
+ kukit.logDebug('Event "' + name + '" executed on ' + executed + ' nodes.');
+};
+
+kukit.er.EventBinder_makeFuncToBind = function(name, node) {
+ var executor = new kukit.er.LateBinder(this, name, node);
+ return function() {
+ executor.executeActions();
+ };
+};
+
+kukit.er.LateBinder = function(binderinstance, name, node) {
+ this.binderinstance = binderinstance;
+ this.name = name;
+ this.node = node;
+ this.bound = null;
+};
+
+kukit.er.LateBinder.prototype.executeActions = function() {
+ if (! this.bound) {
+ kukit.log('Attempt of late binding for event ' + this.name + ', node ' + this.node.nodeName);
+ if (kukit.hasFirebug) {
+ kukit.log(this.node);
+ }
+ var info = kukit.engine.binderInfoRegistry.getBinderInfoById(this.binderinstance.__binder_id__);
+ var oper = info.bound.getBoundOperForNode(this.name, this.node);
+ if (oper) {
+ // (if eventrule is null here, we can yet have the default method, so go on.)
+ oper.parms = {};
+ this.bound = function() {
+ this.binderinstance._EventBinder_triggerevent(this.name, oper);
+ };
+ kukit.log('node bound');
+ } else {
+ kukit.logWarning('no node bound');
+ this.bound = function() {};
+ }
+ }
+ this.bound();
+};
+
+kukit.er.EventBinder_triggerevent = function(name, oper) {
+ // Private. Called from __continue_event__ or from main event execution.
+ oper.binderinstance = this;
+ if (oper.eventrule) {
+ // Call the actions, if we had an event rule.
+ // This includes calling the default action.
+ oper.eventrule.actions.execute(oper);
+ } else {
+ // In case there is no event rule, just call the default event action.
+ var $namespace = this.__event_namespace__;
+ kukit.logDebug('Calling implicit event "' + name + '" on namespace "' + $namespace + '"');
+ var success = oper.executeDefaultAction(name, true);
+ if (! success) {
+ // instead of the standard message give more specific reason:
+ // either way we should have executed something...
+ throw 'Could not trigger event name "' + name + '" on namespace "' + $namespace + '", because there is neither an explicit kss rule, nor a default method';
+ }
+ }
+};
+
+/* (default) method call handling */
+
+kukit.er.EventBinder_callmethod = function($namespace, name, oper, methodname) {
+ // hidden method for calling just a method and checking that is exists.
+ // (called from oper)
+ var method = this[methodname];
+ if (! method) {
+ throw 'Could not trigger event name "' + name + '" on namespace "' + $namespace + '", because the method "' + methodname + '" does not exist.';
+ }
+ // call it
+ oper.binderinstance = this;
+ method.call(this, name, oper);
+};
+
+kukit.er.decorateEventBinderClass = function(cls) {
+ cls.prototype.__continue_event__ = kukit.er.EventBinder__continue_event__;
+ cls.prototype.__continue_event_allnodes__ = kukit.er.EventBinder__continue_event_allnodes__;
+ cls.prototype._EventBinder_triggerevent = kukit.er.EventBinder_triggerevent;
+ cls.prototype._EventBinder_callmethod = kukit.er.EventBinder_callmethod;
+ cls.prototype.__make_func_to_bind__ = kukit.er.EventBinder_makeFuncToBind;
+};
+
+/* Event instance registry
+*
+* class BinderInfoRegistry
+*
+* used in run-time to keep track of the event instances
+*
+*/
+
+kukit.er.BinderInfoRegistry = function () {
+ this.info = {};
+};
+
+kukit.er.BinderInfoRegistry.prototype.getOrCreateBinderInfo = function (id, $classname, $namespace) {
+ // Get or create the event.
+ var binderinfo = this.info[id];
+ if (typeof(binderinfo) == 'undefined') {
+ // Create a new event.
+ kukit.logDebug('instantiating event id=' + id + ', classname=' + $classname + ', namespace=' + $namespace);
+ binderinstance = new (kukit.eventsGlobalRegistry.getBinder($classname))();
+
+ binderinfo = this.info[id] = new kukit.er.BinderInfo(binderinstance);
+
+ // decorate it with id and class
+ binderinstance.__binder_id__ = id;
+ binderinstance.__binder_classname__ = $classname;
+ binderinstance.__event_namespace__ = $namespace;
+ // store the bound rules
+ //binderinstance.__bound_rules__ = [];
+ } else if (binderinfo.getBinderInstance().__binder_classname__ != $classname) {
+ // just paranoia
+ throw 'Conflicting class for event id "' + id + '", "' + binderinfo.getBinderInstance().__binder_classname__
+ + '" != "' + $classname + '"';
+ }
+ return binderinfo;
+};
+
+kukit.er.BinderInfoRegistry.prototype.getBinderInfoById = function (id) {
+ // Get an event.
+ var binderinfo = this.info[id];
+ if (typeof(binderinfo) == 'undefined') {
+ throw 'Event with id "' + id + '" not found.';
+ }
+ return binderinfo;
+};
+
+kukit.er.BinderInfoRegistry.prototype.getSingletonBinderInfoByName = function ($namespace, name) {
+ //Get classname
+ var $classname = kukit.eventsGlobalRegistry.get($namespace, name).classname;
+ // Get an event.
+ var id = kukit.rd.makeId($namespace, $classname);
+ var binderinfo = this.info[id];
+ if (typeof(binderinfo) == 'undefined') {
+ throw 'Singleton event with namespace "' + $namespace + '" and (event) name "' + name + '" not found.';
+ }
+ return binderinfo;
+};
+
+kukit.er.BinderInfoRegistry.prototype.startBindingPhase = function () {
+ // At the end of the binding phase, we want to process our events. This
+ // must include all the binder instances we bound in this phase.
+ for (var id in this.info) {
+ var binderinfo = this.info[id];
+ // process binding on this instance.
+ binderinfo.startBindingPhase();
+ }
+};
+
+kukit.er.BinderInfoRegistry.prototype.processBindingEvents = function () {
+ // At the end of the binding phase, we want to process our events. This
+ // must include all the binder instances we bound in this phase.
+ for (var id in this.info) {
+ var binderinfo = this.info[id];
+ // process binding on this instance.
+ binderinfo.processBindingEvents();
+ }
+};
+
+/*
+* class BinderInfo
+*
+* Information about the given binder instance. This contains the instance and
+* various binding info. Follows the workflow of the binding in different stages.
+*
+*/
+
+kukit.er.BinderInfo = function (binderinstance) {
+ this.binderinstance = binderinstance;
+ this.bound = new kukit.er.OperRegistry();
+ this.startBindingPhase();
+};
+
+kukit.er.BinderInfo.prototype.getBinderInstance = function () {
+ return this.binderinstance;
+};
+
+kukit.er.BinderInfo.prototype.startBindingPhase = function () {
+ // The bindind phase starts and it has the information for
+ // the currently on-bound events.
+ this.binding = new kukit.er.OperRegistry();
+};
+
+kukit.er.BinderInfo.prototype.bindOper = function (oper) {
+ // We mark a given oper. This means a binding on the binderinstance
+ // for given event, node and eventrule (containing event namespace,
+ // name, and evt- parms.)
+
+ // first see if it can go to already bound ones
+ this.bound.checkOperBindable(oper);
+ // then register it properly to the binding events
+ this.binding.bindOper(oper);
+};
+
+kukit.er.BinderInfo.prototype.processBindingEvents = function () {
+ // We came to the end of the binding phase. Now we process all our binding
+ // events, This will do the actual binding on the browser side.
+ var eventRegistry = kukit.eventsGlobalRegistry;
+ for (var i=0; i < eventRegistry.eventsets.length; i++) {
+ var eventset = eventRegistry.eventsets[i];
+ if (this.binderinstance.__event_namespace__ == eventset.namespace) {
+ this._processBindingEventSet(eventset.names);
+ }
+ }
+ // Now we to add these to the new ones.
+ this.binding.propagateTo(this.bound);
+ // Delete them from the registry, to protect against accidents.
+ this.binding = null;
+};
+
+kukit.er.BinderInfo.prototype._processBindingEventSet = function (names) {
+ // Bind finally for all the opers collected
+ var opers = this.binding.getBoundOpersForEventSet(names);
+ if (opers.length == 0) {
+ return;
+ }
+ // find the bind method
+ // (We use the name and namespace from the first oper, as the bindmethod
+ // should be identical anyway.
+ var kss_selector = opers[0].eventrule.kss_selector;
+ var $namespace = kss_selector.namespace;
+ var name = kss_selector.name;
+ var reg = kukit.eventsGlobalRegistry.get($namespace, name);
+ var methodname = reg.bindmethodname;
+ // XXX this is now disabled. We want to allow these events to "bind" on different nodes,
+ // however there is no actual event bound.
+ if (! methodname) {
+ return;
+ //throw new kukit.err.rd.EventBindError('Method is not defined as bindable', name, $namespace);
+ }
+ var method = this.binderinstance[methodname];
+ if (typeof(method) == 'undefined' ) {
+ throw new kukit.err.rd.EventBindError('Method "' + methodname + '" does not exist', name, $namespace);
+ }
+ // Ok. Now decide if we go with the new or the old api.
+ if (reg.bindmethodapi == 'new') {
+ // Protect the binding for better logging
+ try {
+ method.call(binderinstance, opers);
+ } catch(e) {
+ throw new kukit.err.rd.EventBindError('Error during binding, reason: [' + e + ']', name, $namespace);
+ }
+ } else { // old
+ for (var i=0; i<opers.length; i++) {
+ var oper = opers[i];
+ var func_to_bind = oper.makeExecuteActionsHook();
+ if (this.binderinstance != oper.binderinstance) {
+ throw new kukit.err.rd.EventBindError('fatal: wrong binder instance');
+ }
+ var binderinstance = oper.binderinstance;
+ var $eventname = oper.getEventName();
+ // Protect the binding for better logging
+ try {
+ method.call(binderinstance, $eventname, func_to_bind, oper);
+ } catch(e) {
+ throw new kukit.err.rd.EventBindError('Error during binding, reason: [' + e + ']', $eventname, oper.getEventNamespace());
+ }
+ }
+ }
+};
+
+
+/*
+* class OperRegistry
+*
+* OperRegistry is associated with a binder instance in the
+* BinderInfoRegistry, and remembers bounding information.
+* This is used both to remember all the bindings for a given
+* instance, but also just to remember the bindings done during
+* a given event setup phase.
+*/
+
+kukit.er.OperRegistry = function () {
+ this.info = {};
+};
+
+kukit.er.OperRegistry.prototype.propagateTo = function (newreg) {
+ for (var key in this.info) {
+ var rules_per_name = this.info[key];
+ for (var name in rules_per_name) {
+ var oper = rules_per_name[name];
+ newreg.bindOper(oper);
+ }
+ }
+};
+
+kukit.er.OperRegistry.prototype.checkOperBindable = function (oper) {
+ // Check if the binding with this oper could be done.
+ // Throw exception otherwise.
+ var info = this.info;
+ var name = oper.eventrule.kss_selector.name;
+ var nodehash = kukit.rd.hashnode(oper.node);
+ var rules_per_name = info[name];
+ if (typeof(rules_per_name) == 'undefined') {
+ // Create an empty list.
+ rules_per_name = info[name] = {};
+ } else if (typeof(rules_per_name[nodehash]) != 'undefined') {
+ throw 'Mismatch in bind registry, ' + name + ' already bound to node in this instance.';
+ }
+ return rules_per_name;
+};
+
+kukit.er.OperRegistry.prototype.bindOper = function (oper) {
+ // Marks binding between binderinstance, eventname, node.
+ var nodehash = kukit.rd.hashnode(oper.node);
+ var rules_per_name = this.checkOperBindable(oper);
+ rules_per_name[nodehash] = oper;
+};
+
+kukit.er.OperRegistry.prototype.getBoundOperForNode = function (name, node) {
+ // Get the oper that is bound to a given eventname to a node in this binderinstance
+ // returns null, if there is no such oper.
+ var rules_per_name = this.info[name];
+ if (typeof(rules_per_name) == 'undefined') {
+ return null;
+ }
+ var nodehash = kukit.rd.hashnode(node);
+ var oper = rules_per_name[nodehash];
+ if (typeof(oper) == 'undefined') {
+ return null;
+ }
+ // Return it
+ return oper;
+};
+
+kukit.er.OperRegistry.prototype.getBoundOpers = function (name) {
+ // Get the opers bound to a given eventname (to any node) in this binderinstance
+ var opers = [];
+ var rules_per_name = this.info[name];
+ if (typeof(rules_per_name) != 'undefined') {
+ // take the values as a list
+ for (var nodehash in rules_per_name) {
+ opers.push(rules_per_name[nodehash]);
+ }
+ }
+ // Return it
+ return opers;
+};
+
+kukit.er.OperRegistry.prototype.getBoundOpersForEventSet = function (names) {
+ // Returns all opers for a given eventset.
+ var opers = [];
+ for (var i=0; i<names.length; i++) {
+ var name = names[i];
+ opers = opers.concat(this.getBoundOpers(name));
+ }
+ return opers;
+};
+
+// end local scope
+}();
Added: kukit/kukit.js/branch/fschulze-js-compression/kukit/progress/eventreg-3.js
==============================================================================
--- (empty file)
+++ kukit/kukit.js/branch/fschulze-js-compression/kukit/progress/eventreg-3.js Thu Apr 5 12:48:44 2007
@@ -0,0 +1,671 @@
+/*
+* Copyright (c) 2005-2006
+* Authors:
+* Godefroid Chapelle <gotcha at bubblenet.be>
+* Florian Schulze <florian.schulze at gmx.net>
+* Balázs Reé <ree at greenfinity.hu>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as published
+* by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+* 02111-1307, USA.
+*/
+
+kukit.er = {};
+
+// start local scope
+var _er = function() {
+
+_kukit_er = kukit.er;
+_kukit_er.eventClassCounter = 0;
+
+/*
+*
+* class CommandRegistry
+*
+* available for plugin registration
+*
+* usage:
+*
+* kukit.eventsGlobalRegistry.register(namespace, eventname, func,
+* bindmethodname, defaultactionmethodname);
+*
+* namespace = null: means global namespace
+* defaultactionmethodname = null: if there is no default action implemented
+* func must be a class (constructor) function, this is the class that
+* implements the binder.
+*/
+_kukit_er.EventRegistry = function () {
+ this.content = {};
+ this.classes = {};
+ this.eventsets = [];
+};
+
+/* binder registration */
+
+_kukit_er.EventRegistry.prototype.registerBinder = function($classname, $func) {
+ if (typeof($func) == 'undefined') {
+ throw 'func argument is mandatory when registering an event binder (EventRegistry.registerBinder).';
+ }
+ if (this.classes[$classname]) {
+ // Do not allow redefinition
+ kukit.logError('Error : event class "' + $classname + '" already registered.');
+ return;
+
+ }
+ // Decorate and store the class
+ _kukit_er.decorateEventBinderClass($func);
+ this.classes[$classname] = $func;
+};
+
+_kukit_er.EventRegistry.prototype.existsBinder = function($classname) {
+ var $func = this.classes[$classname];
+ return (typeof($func) != 'undefined');
+};
+
+_kukit_er.EventRegistry.prototype.getBinder = function($classname) {
+ var $func = this.classes[$classname];
+ if (! $func) {
+ // not found
+ throw 'Error : undefined event setup type ' + $classname;
+ }
+ return $func;
+};
+
+/* events (methods) registration helpers (not to be called directly) */
+
+_kukit_er.EventRegistry.prototype._register = function($namespace, $eventname, $klass,
+ $bindmethodname, $defaultactionmethodname, $$bindmethodapi) {
+ if (typeof($defaultactionmethodname) == 'undefined') {
+ throw 'some arguments are not passed when calling EventRegistry.register';
+ }
+ // Find out the class name. (Not specified now.)
+ var $classname = $klass.prototype.__classname__;
+ if (typeof($classname) == 'undefined') {
+ // Create a classname, and register it too.
+ $classname = '' + _kukit_er.eventClassCounter;
+ _kukit_er.eventClassCounter += 1;
+ this.registerBinder($classname, $klass);
+ $klass.prototype.__classname__ = $classname;
+ }
+ if (!$eventname) {
+ throw 'eventname argument cannot be empty when registering an event (EventRegistry.register)';
+ }
+ var key = this._getKey($namespace, $eventname);
+ var entry = this.content[key];
+ if (typeof(entry) != 'undefined') {
+ if (key[0] == '-') {
+ key = key.substring(1);
+ }
+ throw 'In EventRegistry.register double registration of key "' + key + '"';
+ }
+ // register it
+ this.content[key] = {
+ 'classname': $classname,
+ 'bindmethodname': $bindmethodname,
+ 'defaultactionmethodname': $defaultactionmethodname,
+ 'bindmethodapi': $$bindmethodapi
+ };
+};
+
+/* events (methods) binding "ForAll" registration */
+
+_kukit_er.EventRegistry.prototype._registerEventSet = function($namespace, names) {
+ // At this name the class and event should be checked already. so this should
+ // be called _after_ _register.
+ this.eventsets.push({'namespace': $namespace, 'names': names});
+};
+
+
+/* there are the actual registration methods, to be called from plugins */
+
+_kukit_er.EventRegistry.prototype.register = function($namespace, $eventname, $klass,
+ $bindmethodname, $defaultactionmethodname) {
+ this._register($namespace, $eventname, $klass, $bindmethodname, $defaultactionmethodname, 'old');
+ this._registerEventSet($namespace, [$eventname]);
+};
+
+_kukit_er.EventRegistry.prototype.registerForAllEvents = function($namespace, $eventnames, $klass,
+ $bindmethodname, $defaultactionmethodname) {
+ if (typeof($eventnames) == 'string') {
+ $eventnames = [$eventnames];
+ }
+ for (var i=0; i<$eventnames.length; i++) {
+ var $$eventname = $eventnames[i];
+ this._register($namespace, $$eventname, $klass, $bindmethodname, $defaultactionmethodname, 'new');
+ }
+ this._registerEventSet($namespace, $eventnames);
+};
+
+_kukit_er.EventRegistry.prototype._getKey = function($namespace, $eventname) {
+ if ($namespace == null) {
+ $namespace = '';
+ } else if ($namespace.split('-') > 1) {
+ throw 'In EventRegistry.register namespace cannot contain -';
+ }
+ return $namespace + '-' + $eventname;
+};
+
+_kukit_er.EventRegistry.prototype.exists = function($namespace, $eventname) {
+ var key = this._getKey($namespace, $eventname);
+ var entry = this.content[key];
+ return (typeof(entry) != 'undefined');
+};
+
+_kukit_er.EventRegistry.prototype.get = function($namespace, $eventname) {
+ var key = this._getKey($namespace, $eventname);
+ var entry = this.content[key];
+ if (typeof(entry) == 'undefined') {
+ if (key[0] == '-') {
+ key = key.substring(1);
+ throw 'Error : undefined global event key ' + key + ' (or maybe namespace is missing?)';
+ } else {
+ throw 'Error : undefined event key ' + key;
+ }
+ }
+ return entry;
+};
+
+kukit.eventsGlobalRegistry = new _kukit_er.EventRegistry();
+
+
+/* XXX deprecated methods, to be removed asap */
+
+_kukit_er.eventRegistry = {};
+_kukit_er.eventRegistry.register = function($namespace, $eventname, $klass,
+ $bindmethodname, $defaultactionmethodname) {
+ kukit.logWarning('Deprecated _kukit_er.eventRegistry.register, use kukit.eventsGlobalRegistry.register instead! (' + $namespace + '-' + $eventname + ')');
+ kukit.eventsGlobalRegistry.register($namespace, $eventname, $klass,
+ $bindmethodname, $defaultactionmethodname);
+};
+
+/* Event class decoration
+*
+* poor man's subclassing
+* This is called automatically on registration, to dress
+* up the event class with the necessary methods
+*
+*/
+
+/* Provide callins on the state instance that execute a given
+* continuation event.
+* Parameters will be the ones specified in the call +
+* those defined in the rule will be added too. (Parameters can
+* be accessed with the "pass" kss parameter provider.)
+*
+* Call examples:
+*
+* trigger an event bound to a given state instance, same node
+*
+* binderinstance.__continue_event__('doit', oper.node, {'extravalue': '5'});
+*
+* with kss rule:
+*
+* node.selector:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* or
+*
+* behaviour.selector:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* trigger an event bound to a given state instance, and the document
+* (different from current scope)
+*
+* binderinstance.__continue_event__('doit', null, {'extravalue': '5'});
+*
+* with kss rule:
+*
+* document:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* or
+*
+* behaviour.selector:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* trigger an event on all the nodes + document bound to a given state instance
+*
+* binderinstance.__continue_event_allnodes__('doit', {'extravalue': '5'});
+*
+* with kss rule:
+*
+* node.selector:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* p.s. oper is not required to make it easy to adapt existing code
+* so we create a new oper below
+*/
+
+_kukit_er.EventBinder__continue_event__ = function(name, node, parms) {
+ // Trigger a continuation event bound to a given state instance, given node
+ // (or on document, if node = null)
+ //
+ var oper = new kukit.op.Oper();
+ oper.node = node;
+ if (node) {
+ // if we found the binding, just use that
+ var info = kukit.engine.binderInfoRegistry.getBinderInfoById(this.__binder_id__);
+ var newoper = info.bound.getBoundOperForNode(name, node);
+ if (newoper) {
+ oper = newoper;
+ }
+ } else {
+ oper.eventrule = kukit.engine.documentRules.getMergedRule('document', name, this);
+ }
+ // Look up the behaviour rule, if any.
+ var behav_eventrule = kukit.engine.documentRules.getMergedRule('behaviour', name, this);
+ if (behav_eventrule) {
+ if (! oper.eventrule) {
+ // There was no node matching for the rule, use behaviour rule
+ // this allows to set up parametrized actions in general.
+ oper.eventrule = behav_eventrule;
+ } else {
+ // XXX this case should go away, as we should check this already from binding time
+ // and signal the appropriate error.
+ // Also note that behaviour roles will only be allowed for "non-binding" events.
+ kukit.logError('Behaviour rule for continuation event "' + name + '" will be ignored, because we found an explicit rule.');
+ }
+ }
+ // If parameters are specified in the call, use them.
+ if (typeof(parms) != 'undefined') {
+ oper.parms = parms;
+ } else {
+ oper.parms = {};
+ }
+ // (if eventrule is null here, we can yet have the default method, so go on.)
+ this._EventBinder_triggerevent(name, oper);
+ kukit.logDebug('Continuation event "' + name + '" executed on same node.');
+};
+
+_kukit_er.EventBinder__continue_event_allnodes__ = function(name, parms) {
+ // Trigger an event bound to a given state instance, on all nodes.
+ // (or on document, if node = null)
+ // if no other nodes execute.
+ var executed = 0;
+ // Normal rules. If any of those match, execute them too
+ // each on the node that it selects - not on the original node.
+ var oper = new kukit.op.Oper();
+ var info = kukit.engine.binderInfoRegistry.getBinderInfoById(this.__binder_id__);
+ var opers = info.getBoundOpers(name);
+ for (var i=0; i<opers.length; i++) {
+ var oper = opers[i];
+ var newoper = oper.clone();
+ if (typeof(parms) != 'undefined') {
+ newoper.parms = parms;
+ } else {
+ newoper.parms = {};
+ }
+ this._EventBinder_triggerevent(name, newoper);
+ executed += 1;
+ }
+ kukit.logDebug('Event "' + name + '" executed on ' + executed + ' nodes.');
+};
+
+_kukit_er.EventBinder_makeFuncToBind = function(name, node) {
+ var executor = new _kukit_er.LateBinder(this, name, node);
+ return function() {
+ executor.executeActions();
+ };
+};
+
+_kukit_er.LateBinder = function(binderinstance, name, node) {
+ this.binderinstance = binderinstance;
+ this.name = name;
+ this.node = node;
+ this.bound = null;
+};
+
+_kukit_er.LateBinder.prototype.executeActions = function() {
+ if (! this.bound) {
+ kukit.log('Attempt of late binding for event ' + this.name + ', node ' + this.node.nodeName);
+ if (kukit.hasFirebug) {
+ kukit.log(this.node);
+ }
+ var info = kukit.engine.binderInfoRegistry.getBinderInfoById(this.binderinstance.__binder_id__);
+ var oper = info.bound.getBoundOperForNode(this.name, this.node);
+ if (oper) {
+ // (if eventrule is null here, we can yet have the default method, so go on.)
+ oper.parms = {};
+ this.bound = function() {
+ this.binderinstance._EventBinder_triggerevent(this.name, oper);
+ };
+ kukit.log('node bound');
+ } else {
+ kukit.logWarning('no node bound');
+ this.bound = function() {};
+ }
+ }
+ this.bound();
+};
+
+_kukit_er.EventBinder_triggerevent = function(name, oper) {
+ // Private. Called from __continue_event__ or from main event execution.
+ oper.binderinstance = this;
+ if (oper.eventrule) {
+ // Call the actions, if we had an event rule.
+ // This includes calling the default action.
+ oper.eventrule.actions.execute(oper);
+ } else {
+ // In case there is no event rule, just call the default event action.
+ var $namespace = this.__event_namespace__;
+ kukit.logDebug('Calling implicit event "' + name + '" on namespace "' + $namespace + '"');
+ var success = oper.executeDefaultAction(name, true);
+ if (! success) {
+ // instead of the standard message give more specific reason:
+ // either way we should have executed something...
+ throw 'Could not trigger event name "' + name + '" on namespace "' + $namespace + '", because there is neither an explicit kss rule, nor a default method';
+ }
+ }
+};
+
+/* (default) method call handling */
+
+_kukit_er.EventBinder_callmethod = function($namespace, name, oper, methodname) {
+ // hidden method for calling just a method and checking that is exists.
+ // (called from oper)
+ var method = this[methodname];
+ if (! method) {
+ throw 'Could not trigger event name "' + name + '" on namespace "' + $namespace + '", because the method "' + methodname + '" does not exist.';
+ }
+ // call it
+ oper.binderinstance = this;
+ method.call(this, name, oper);
+};
+
+_kukit_er.decorateEventBinderClass = function(cls) {
+ cls.prototype.__continue_event__ = _kukit_er.EventBinder__continue_event__;
+ cls.prototype.__continue_event_allnodes__ = _kukit_er.EventBinder__continue_event_allnodes__;
+ cls.prototype._EventBinder_triggerevent = _kukit_er.EventBinder_triggerevent;
+ cls.prototype._EventBinder_callmethod = _kukit_er.EventBinder_callmethod;
+ cls.prototype.__make_func_to_bind__ = _kukit_er.EventBinder_makeFuncToBind;
+};
+
+/* Event instance registry
+*
+* class BinderInfoRegistry
+*
+* used in run-time to keep track of the event instances
+*
+*/
+
+_kukit_er.BinderInfoRegistry = function () {
+ this.info = {};
+};
+
+_kukit_er.BinderInfoRegistry.prototype.getOrCreateBinderInfo = function (id, $classname, $namespace) {
+ // Get or create the event.
+ var binderinfo = this.info[id];
+ if (typeof(binderinfo) == 'undefined') {
+ // Create a new event.
+ kukit.logDebug('instantiating event id=' + id + ', classname=' + $classname + ', namespace=' + $namespace);
+ binderinstance = new (kukit.eventsGlobalRegistry.getBinder($classname))();
+
+ binderinfo = this.info[id] = new _kukit_er.BinderInfo(binderinstance);
+
+ // decorate it with id and class
+ binderinstance.__binder_id__ = id;
+ binderinstance.__binder_classname__ = $classname;
+ binderinstance.__event_namespace__ = $namespace;
+ // store the bound rules
+ //binderinstance.__bound_rules__ = [];
+ } else if (binderinfo.getBinderInstance().__binder_classname__ != $classname) {
+ // just paranoia
+ throw 'Conflicting class for event id "' + id + '", "' + binderinfo.getBinderInstance().__binder_classname__
+ + '" != "' + $classname + '"';
+ }
+ return binderinfo;
+};
+
+_kukit_er.BinderInfoRegistry.prototype.getBinderInfoById = function (id) {
+ // Get an event.
+ var binderinfo = this.info[id];
+ if (typeof(binderinfo) == 'undefined') {
+ throw 'Event with id "' + id + '" not found.';
+ }
+ return binderinfo;
+};
+
+_kukit_er.BinderInfoRegistry.prototype.getSingletonBinderInfoByName = function ($namespace, name) {
+ //Get classname
+ var $classname = kukit.eventsGlobalRegistry.get($namespace, name).classname;
+ // Get an event.
+ var id = kukit.rd.makeId($namespace, $classname);
+ var binderinfo = this.info[id];
+ if (typeof(binderinfo) == 'undefined') {
+ throw 'Singleton event with namespace "' + $namespace + '" and (event) name "' + name + '" not found.';
+ }
+ return binderinfo;
+};
+
+_kukit_er.BinderInfoRegistry.prototype.startBindingPhase = function () {
+ // At the end of the binding phase, we want to process our events. This
+ // must include all the binder instances we bound in this phase.
+ for (var id in this.info) {
+ var binderinfo = this.info[id];
+ // process binding on this instance.
+ binderinfo.startBindingPhase();
+ }
+};
+
+_kukit_er.BinderInfoRegistry.prototype.processBindingEvents = function () {
+ // At the end of the binding phase, we want to process our events. This
+ // must include all the binder instances we bound in this phase.
+ for (var id in this.info) {
+ var binderinfo = this.info[id];
+ // process binding on this instance.
+ binderinfo.processBindingEvents();
+ }
+};
+
+/*
+* class BinderInfo
+*
+* Information about the given binder instance. This contains the instance and
+* various binding info. Follows the workflow of the binding in different stages.
+*
+*/
+
+_kukit_er.BinderInfo = function (binderinstance) {
+ this.binderinstance = binderinstance;
+ this.bound = new _kukit_er.OperRegistry();
+ this.startBindingPhase();
+};
+
+_kukit_er.BinderInfo.prototype.getBinderInstance = function () {
+ return this.binderinstance;
+};
+
+_kukit_er.BinderInfo.prototype.startBindingPhase = function () {
+ // The bindind phase starts and it has the information for
+ // the currently on-bound events.
+ this.binding = new _kukit_er.OperRegistry();
+};
+
+_kukit_er.BinderInfo.prototype.bindOper = function (oper) {
+ // We mark a given oper. This means a binding on the binderinstance
+ // for given event, node and eventrule (containing event namespace,
+ // name, and evt- parms.)
+
+ // first see if it can go to already bound ones
+ this.bound.checkOperBindable(oper);
+ // then register it properly to the binding events
+ this.binding.bindOper(oper);
+};
+
+_kukit_er.BinderInfo.prototype.processBindingEvents = function () {
+ // We came to the end of the binding phase. Now we process all our binding
+ // events, This will do the actual binding on the browser side.
+ var eventRegistry = kukit.eventsGlobalRegistry;
+ for (var i=0; i < eventRegistry.eventsets.length; i++) {
+ var eventset = eventRegistry.eventsets[i];
+ if (this.binderinstance.__event_namespace__ == eventset.namespace) {
+ this._processBindingEventSet(eventset.names);
+ }
+ }
+ // Now we to add these to the new ones.
+ this.binding.propagateTo(this.bound);
+ // Delete them from the registry, to protect against accidents.
+ this.binding = null;
+};
+
+_kukit_er.BinderInfo.prototype._processBindingEventSet = function (names) {
+ // Bind finally for all the opers collected
+ var opers = this.binding.getBoundOpersForEventSet(names);
+ if (opers.length == 0) {
+ return;
+ }
+ // find the bind method
+ // (We use the name and namespace from the first oper, as the bindmethod
+ // should be identical anyway.
+ var kss_selector = opers[0].eventrule.kss_selector;
+ var $namespace = kss_selector.namespace;
+ var name = kss_selector.name;
+ var reg = kukit.eventsGlobalRegistry.get($namespace, name);
+ var methodname = reg.bindmethodname;
+ // XXX this is now disabled. We want to allow these events to "bind" on different nodes,
+ // however there is no actual event bound.
+ if (! methodname) {
+ return;
+ //throw new kukit.err.rd.EventBindError('Method is not defined as bindable', name, $namespace);
+ }
+ var method = this.binderinstance[methodname];
+ if (typeof(method) == 'undefined' ) {
+ throw new kukit.err.rd.EventBindError('Method "' + methodname + '" does not exist', name, $namespace);
+ }
+ // Ok. Now decide if we go with the new or the old api.
+ if (reg.bindmethodapi == 'new') {
+ // Protect the binding for better logging
+ try {
+ method.call(binderinstance, opers);
+ } catch(e) {
+ throw new kukit.err.rd.EventBindError('Error during binding, reason: [' + e + ']', name, $namespace);
+ }
+ } else { // old
+ for (var i=0; i<opers.length; i++) {
+ var oper = opers[i];
+ var func_to_bind = oper.makeExecuteActionsHook();
+ if (this.binderinstance != oper.binderinstance) {
+ throw new kukit.err.rd.EventBindError('fatal: wrong binder instance');
+ }
+ var binderinstance = oper.binderinstance;
+ var $eventname = oper.getEventName();
+ // Protect the binding for better logging
+ try {
+ method.call(binderinstance, $eventname, func_to_bind, oper);
+ } catch(e) {
+ throw new kukit.err.rd.EventBindError('Error during binding, reason: [' + e + ']', $eventname, oper.getEventNamespace());
+ }
+ }
+ }
+};
+
+
+/*
+* class OperRegistry
+*
+* OperRegistry is associated with a binder instance in the
+* BinderInfoRegistry, and remembers bounding information.
+* This is used both to remember all the bindings for a given
+* instance, but also just to remember the bindings done during
+* a given event setup phase.
+*/
+
+_kukit_er.OperRegistry = function () {
+ this.info = {};
+};
+
+_kukit_er.OperRegistry.prototype.propagateTo = function (newreg) {
+ for (var key in this.info) {
+ var rules_per_name = this.info[key];
+ for (var name in rules_per_name) {
+ var oper = rules_per_name[name];
+ newreg.bindOper(oper);
+ }
+ }
+};
+
+_kukit_er.OperRegistry.prototype.checkOperBindable = function (oper) {
+ // Check if the binding with this oper could be done.
+ // Throw exception otherwise.
+ var info = this.info;
+ var name = oper.eventrule.kss_selector.name;
+ var nodehash = kukit.rd.hashnode(oper.node);
+ var rules_per_name = info[name];
+ if (typeof(rules_per_name) == 'undefined') {
+ // Create an empty list.
+ rules_per_name = info[name] = {};
+ } else if (typeof(rules_per_name[nodehash]) != 'undefined') {
+ throw 'Mismatch in bind registry, ' + name + ' already bound to node in this instance.';
+ }
+ return rules_per_name;
+};
+
+_kukit_er.OperRegistry.prototype.bindOper = function (oper) {
+ // Marks binding between binderinstance, eventname, node.
+ var nodehash = kukit.rd.hashnode(oper.node);
+ var rules_per_name = this.checkOperBindable(oper);
+ rules_per_name[nodehash] = oper;
+};
+
+_kukit_er.OperRegistry.prototype.getBoundOperForNode = function (name, node) {
+ // Get the oper that is bound to a given eventname to a node in this binderinstance
+ // returns null, if there is no such oper.
+ var rules_per_name = this.info[name];
+ if (typeof(rules_per_name) == 'undefined') {
+ return null;
+ }
+ var nodehash = kukit.rd.hashnode(node);
+ var oper = rules_per_name[nodehash];
+ if (typeof(oper) == 'undefined') {
+ return null;
+ }
+ // Return it
+ return oper;
+};
+
+_kukit_er.OperRegistry.prototype.getBoundOpers = function (name) {
+ // Get the opers bound to a given eventname (to any node) in this binderinstance
+ var opers = [];
+ var rules_per_name = this.info[name];
+ if (typeof(rules_per_name) != 'undefined') {
+ // take the values as a list
+ for (var nodehash in rules_per_name) {
+ opers.push(rules_per_name[nodehash]);
+ }
+ }
+ // Return it
+ return opers;
+};
+
+_kukit_er.OperRegistry.prototype.getBoundOpersForEventSet = function (names) {
+ // Returns all opers for a given eventset.
+ var opers = [];
+ for (var i=0; i<names.length; i++) {
+ var name = names[i];
+ opers = opers.concat(this.getBoundOpers(name));
+ }
+ return opers;
+};
+
+// end local scope
+}();
Added: kukit/kukit.js/branch/fschulze-js-compression/kukit/progress/eventreg-4.js
==============================================================================
--- (empty file)
+++ kukit/kukit.js/branch/fschulze-js-compression/kukit/progress/eventreg-4.js Thu Apr 5 12:48:44 2007
@@ -0,0 +1,678 @@
+/*
+* Copyright (c) 2005-2006
+* Authors:
+* Godefroid Chapelle <gotcha at bubblenet.be>
+* Florian Schulze <florian.schulze at gmx.net>
+* Balázs Reé <ree at greenfinity.hu>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as published
+* by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+* 02111-1307, USA.
+*/
+
+kukit.er = {};
+
+// start local scope
+var _er = function() {
+
+var _kukit_er = kukit.er;
+_kukit_er.eventClassCounter = 0;
+
+/*
+*
+* class CommandRegistry
+*
+* available for plugin registration
+*
+* usage:
+*
+* kukit.eventsGlobalRegistry.register(namespace, eventname, func,
+* bindmethodname, defaultactionmethodname);
+*
+* namespace = null: means global namespace
+* defaultactionmethodname = null: if there is no default action implemented
+* func must be a class (constructor) function, this is the class that
+* implements the binder.
+*/
+_kukit_er.EventRegistry = function () {
+ this.content = {};
+ this.classes = {};
+ this.eventsets = [];
+};
+
+/* binder registration */
+var _kukit_er_EventRegistry_prototype = _kukit_er.EventRegistry.prototype;
+
+_kukit_er_EventRegistry_prototype.registerBinder = function($classname, $func) {
+ if (typeof($func) == 'undefined') {
+ throw 'func argument is mandatory when registering an event binder (EventRegistry.registerBinder).';
+ }
+ if (this.classes[$classname]) {
+ // Do not allow redefinition
+ kukit.logError('Error : event class "' + $classname + '" already registered.');
+ return;
+
+ }
+ // Decorate and store the class
+ _kukit_er.decorateEventBinderClass($func);
+ this.classes[$classname] = $func;
+};
+
+_kukit_er_EventRegistry_prototype.existsBinder = function($classname) {
+ var $func = this.classes[$classname];
+ return (typeof($func) != 'undefined');
+};
+
+_kukit_er_EventRegistry_prototype.getBinder = function($classname) {
+ var $func = this.classes[$classname];
+ if (! $func) {
+ // not found
+ throw 'Error : undefined event setup type ' + $classname;
+ }
+ return $func;
+};
+
+/* events (methods) registration helpers (not to be called directly) */
+
+_kukit_er_EventRegistry_prototype._register = function($namespace, $eventname, $klass,
+ $bindmethodname, $defaultactionmethodname, $$bindmethodapi) {
+ if (typeof($defaultactionmethodname) == 'undefined') {
+ throw 'some arguments are not passed when calling EventRegistry.register';
+ }
+ // Find out the class name. (Not specified now.)
+ var $classname = $klass.prototype.__classname__;
+ if (typeof($classname) == 'undefined') {
+ // Create a classname, and register it too.
+ $classname = '' + _kukit_er.eventClassCounter;
+ _kukit_er.eventClassCounter += 1;
+ this.registerBinder($classname, $klass);
+ $klass.prototype.__classname__ = $classname;
+ }
+ if (!$eventname) {
+ throw 'eventname argument cannot be empty when registering an event (EventRegistry.register)';
+ }
+ var key = this._getKey($namespace, $eventname);
+ var entry = this.content[key];
+ if (typeof(entry) != 'undefined') {
+ if (key[0] == '-') {
+ key = key.substring(1);
+ }
+ throw 'In EventRegistry.register double registration of key "' + key + '"';
+ }
+ // register it
+ this.content[key] = {
+ 'classname': $classname,
+ 'bindmethodname': $bindmethodname,
+ 'defaultactionmethodname': $defaultactionmethodname,
+ 'bindmethodapi': $$bindmethodapi
+ };
+};
+
+/* events (methods) binding "ForAll" registration */
+
+_kukit_er_EventRegistry_prototype._registerEventSet = function($namespace, names) {
+ // At this name the class and event should be checked already. so this should
+ // be called _after_ _register.
+ this.eventsets.push({'namespace': $namespace, 'names': names});
+};
+
+
+/* there are the actual registration methods, to be called from plugins */
+
+_kukit_er_EventRegistry_prototype.register = function($namespace, $eventname, $klass,
+ $bindmethodname, $defaultactionmethodname) {
+ this._register($namespace, $eventname, $klass, $bindmethodname, $defaultactionmethodname, 'old');
+ this._registerEventSet($namespace, [$eventname]);
+};
+
+_kukit_er_EventRegistry_prototype.registerForAllEvents = function($namespace, $eventnames, $klass,
+ $bindmethodname, $defaultactionmethodname) {
+ if (typeof($eventnames) == 'string') {
+ $eventnames = [$eventnames];
+ }
+ for (var i=0; i<$eventnames.length; i++) {
+ var $$eventname = $eventnames[i];
+ this._register($namespace, $$eventname, $klass, $bindmethodname, $defaultactionmethodname, 'new');
+ }
+ this._registerEventSet($namespace, $eventnames);
+};
+
+_kukit_er_EventRegistry_prototype._getKey = function($namespace, $eventname) {
+ if ($namespace == null) {
+ $namespace = '';
+ } else if ($namespace.split('-') > 1) {
+ throw 'In EventRegistry.register namespace cannot contain -';
+ }
+ return $namespace + '-' + $eventname;
+};
+
+_kukit_er_EventRegistry_prototype.exists = function($namespace, $eventname) {
+ var key = this._getKey($namespace, $eventname);
+ var entry = this.content[key];
+ return (typeof(entry) != 'undefined');
+};
+
+_kukit_er_EventRegistry_prototype.get = function($namespace, $eventname) {
+ var key = this._getKey($namespace, $eventname);
+ var entry = this.content[key];
+ if (typeof(entry) == 'undefined') {
+ if (key[0] == '-') {
+ key = key.substring(1);
+ throw 'Error : undefined global event key ' + key + ' (or maybe namespace is missing?)';
+ } else {
+ throw 'Error : undefined event key ' + key;
+ }
+ }
+ return entry;
+};
+
+kukit.eventsGlobalRegistry = new _kukit_er.EventRegistry();
+
+
+/* XXX deprecated methods, to be removed asap */
+
+_kukit_er.eventRegistry = {};
+_kukit_er.eventRegistry.register = function($namespace, $eventname, $klass,
+ $bindmethodname, $defaultactionmethodname) {
+ kukit.logWarning('Deprecated _kukit_er.eventRegistry.register, use kukit.eventsGlobalRegistry.register instead! (' + $namespace + '-' + $eventname + ')');
+ kukit.eventsGlobalRegistry.register($namespace, $eventname, $klass,
+ $bindmethodname, $defaultactionmethodname);
+};
+
+/* Event class decoration
+*
+* poor man's subclassing
+* This is called automatically on registration, to dress
+* up the event class with the necessary methods
+*
+*/
+
+/* Provide callins on the state instance that execute a given
+* continuation event.
+* Parameters will be the ones specified in the call +
+* those defined in the rule will be added too. (Parameters can
+* be accessed with the "pass" kss parameter provider.)
+*
+* Call examples:
+*
+* trigger an event bound to a given state instance, same node
+*
+* binderinstance.__continue_event__('doit', oper.node, {'extravalue': '5'});
+*
+* with kss rule:
+*
+* node.selector:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* or
+*
+* behaviour.selector:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* trigger an event bound to a given state instance, and the document
+* (different from current scope)
+*
+* binderinstance.__continue_event__('doit', null, {'extravalue': '5'});
+*
+* with kss rule:
+*
+* document:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* or
+*
+* behaviour.selector:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* trigger an event on all the nodes + document bound to a given state instance
+*
+* binderinstance.__continue_event_allnodes__('doit', {'extravalue': '5'});
+*
+* with kss rule:
+*
+* node.selector:doit {
+* action-client: log;
+* log-message: pass(extravalue);
+* }
+*
+* p.s. oper is not required to make it easy to adapt existing code
+* so we create a new oper below
+*/
+
+_kukit_er.EventBinder__continue_event__ = function(name, node, parms) {
+ // Trigger a continuation event bound to a given state instance, given node
+ // (or on document, if node = null)
+ //
+ var oper = new kukit.op.Oper();
+ oper.node = node;
+ if (node) {
+ // if we found the binding, just use that
+ var info = kukit.engine.binderInfoRegistry.getBinderInfoById(this.__binder_id__);
+ var newoper = info.bound.getBoundOperForNode(name, node);
+ if (newoper) {
+ oper = newoper;
+ }
+ } else {
+ oper.eventrule = kukit.engine.documentRules.getMergedRule('document', name, this);
+ }
+ // Look up the behaviour rule, if any.
+ var behav_eventrule = kukit.engine.documentRules.getMergedRule('behaviour', name, this);
+ if (behav_eventrule) {
+ if (! oper.eventrule) {
+ // There was no node matching for the rule, use behaviour rule
+ // this allows to set up parametrized actions in general.
+ oper.eventrule = behav_eventrule;
+ } else {
+ // XXX this case should go away, as we should check this already from binding time
+ // and signal the appropriate error.
+ // Also note that behaviour roles will only be allowed for "non-binding" events.
+ kukit.logError('Behaviour rule for continuation event "' + name + '" will be ignored, because we found an explicit rule.');
+ }
+ }
+ // If parameters are specified in the call, use them.
+ if (typeof(parms) != 'undefined') {
+ oper.parms = parms;
+ } else {
+ oper.parms = {};
+ }
+ // (if eventrule is null here, we can yet have the default method, so go on.)
+ this._EventBinder_triggerevent(name, oper);
+ kukit.logDebug('Continuation event "' + name + '" executed on same node.');
+};
+
+_kukit_er.EventBinder__continue_event_allnodes__ = function(name, parms) {
+ // Trigger an event bound to a given state instance, on all nodes.
+ // (or on document, if node = null)
+ // if no other nodes execute.
+ var executed = 0;
+ // Normal rules. If any of those match, execute them too
+ // each on the node that it selects - not on the original node.
+ var oper = new kukit.op.Oper();
+ var info = kukit.engine.binderInfoRegistry.getBinderInfoById(this.__binder_id__);
+ var opers = info.getBoundOpers(name);
+ for (var i=0; i<opers.length; i++) {
+ var oper = opers[i];
+ var newoper = oper.clone();
+ if (typeof(parms) != 'undefined') {
+ newoper.parms = parms;
+ } else {
+ newoper.parms = {};
+ }
+ this._EventBinder_triggerevent(name, newoper);
+ executed += 1;
+ }
+ kukit.logDebug('Event "' + name + '" executed on ' + executed + ' nodes.');
+};
+
+_kukit_er.EventBinder_makeFuncToBind = function(name, node) {
+ var executor = new _kukit_er.LateBinder(this, name, node);
+ return function() {
+ executor.executeActions();
+ };
+};
+
+_kukit_er.LateBinder = function(binderinstance, name, node) {
+ this.binderinstance = binderinstance;
+ this.name = name;
+ this.node = node;
+ this.bound = null;
+};
+
+_kukit_er.LateBinder.prototype.executeActions = function() {
+ if (! this.bound) {
+ kukit.log('Attempt of late binding for event ' + this.name + ', node ' + this.node.nodeName);
+ if (kukit.hasFirebug) {
+ kukit.log(this.node);
+ }
+ var info = kukit.engine.binderInfoRegistry.getBinderInfoById(this.binderinstance.__binder_id__);
+ var oper = info.bound.getBoundOperForNode(this.name, this.node);
+ if (oper) {
+ // (if eventrule is null here, we can yet have the default method, so go on.)
+ oper.parms = {};
+ this.bound = function() {
+ this.binderinstance._EventBinder_triggerevent(this.name, oper);
+ };
+ kukit.log('node bound');
+ } else {
+ kukit.logWarning('no node bound');
+ this.bound = function() {};
+ }
+ }
+ this.bound();
+};
+
+_kukit_er.EventBinder_triggerevent = function(name, oper) {
+ // Private. Called from __continue_event__ or from main event execution.
+ oper.binderinstance = this;
+ if (oper.eventrule) {
+ // Call the actions, if we had an event rule.
+ // This includes calling the default action.
+ oper.eventrule.actions.execute(oper);
+ } else {
+ // In case there is no event rule, just call the default event action.
+ var $namespace = this.__event_namespace__;
+ kukit.logDebug('Calling implicit event "' + name + '" on namespace "' + $namespace + '"');
+ var success = oper.executeDefaultAction(name, true);
+ if (! success) {
+ // instead of the standard message give more specific reason:
+ // either way we should have executed something...
+ throw 'Could not trigger event name "' + name + '" on namespace "' + $namespace + '", because there is neither an explicit kss rule, nor a default method';
+ }
+ }
+};
+
+/* (default) method call handling */
+
+_kukit_er.EventBinder_callmethod = function($namespace, name, oper, methodname) {
+ // hidden method for calli