[KSS-checkins] r41970 - kukit/kukit.js/branch/ree-load-event-cleanup/kukit

reebalazs at codespeak.net reebalazs at codespeak.net
Sun Apr 8 21:16:00 CEST 2007


Author: reebalazs
Date: Sun Apr  8 21:16:00 2007
New Revision: 41970

Modified:
   kukit/kukit.js/branch/ree-load-event-cleanup/kukit/eventreg.js
Log:
First a little refactoring for event binding reg, to introduce some iterators that we will use

Modified: kukit/kukit.js/branch/ree-load-event-cleanup/kukit/eventreg.js
==============================================================================
--- kukit/kukit.js/branch/ree-load-event-cleanup/kukit/eventreg.js	(original)
+++ kukit/kukit.js/branch/ree-load-event-cleanup/kukit/eventreg.js	Sun Apr  8 21:16:00 2007
@@ -1,9 +1,6 @@
 /*
-* 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>
+* Copyright (c) 2005-2007
+* Authors: KSS Project Contributors (see docs/CREDITS.txt)
 *
 * 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
@@ -81,7 +78,7 @@
 /* events (methods) registration  helpers (not to be called directly) */
 
 kukit.er.EventRegistry.prototype._register = function(namespace, eventname, klass,
-        bindmethodname, defaultactionmethodname, bindmethodapi) {
+        bindmethodname, defaultactionmethodname, itername) {
     if (typeof(defaultactionmethodname) == 'undefined') {
         throw 'some arguments are not passed when calling EventRegistry.register';
     }
@@ -105,42 +102,50 @@
         }
         throw 'In EventRegistry.register double registration of key "' + key + '"';
     }
+    // check the iterator.
+    if  (! kukit.er.getBindIterator(itername)) {
+        throw 'In EventRegistry.register unknown bind iterator "' + itername + '"';
+    }
     // register it
     this.content[key] = {
         'classname': classname,
         'bindmethodname': bindmethodname,
         'defaultactionmethodname': defaultactionmethodname,
-        'bindmethodapi': bindmethodapi
+        'itername': itername
         };
 };
 
 /* 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
+kukit.er.EventRegistry.prototype._registerEventSet = function(namespace, names, itername, bindmethodname) {
+    // At this name the values 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,
+        'itername': itername,
+        'bindmethodname': bindmethodname
+        });
 };
 
-
 /* 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]);
+    this._register(namespace, eventname, klass, bindmethodname, defaultactionmethodname, 'each');
+    this._registerEventSet(namespace, [eventname], 'each', bindmethodname);
 };
 
 kukit.er.EventRegistry.prototype.registerForAllEvents = function(namespace, eventnames, klass,
-        bindmethodname, defaultactionmethodname) {
+        bindmethodname, defaultactionmethodname, itername) {
     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._register(namespace, eventname, klass, bindmethodname, defaultactionmethodname, itername);
     }
-    this._registerEventSet(namespace, eventnames);
+    this._registerEventSet(namespace, eventnames, itername, bindmethodname);
 };
 
 kukit.er.EventRegistry.prototype._getKey = function(namespace, eventname) {
@@ -502,7 +507,7 @@
     // 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
@@ -512,70 +517,13 @@
 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);
-        }
-    }
+    this.binding.processBindingEvents(this.binderinstance)
     // 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
@@ -588,12 +536,14 @@
 */
 
 kukit.er.OperRegistry = function () {
-    this.info = {};
+    this.infopername = {};
+    this.infopernode = {};
 };
 
+// XXX XXX XXX we can do this without full cloning, more efficiently.
 kukit.er.OperRegistry.prototype.propagateTo = function (newreg) {
-    for (var key in this.info) {
-        var rules_per_name = this.info[key];
+    for (var key in this.infopername) {
+        var rules_per_name = this.infopername[key];
         for (var name in rules_per_name) {
             var oper = rules_per_name[name];
             newreg.bindOper(oper);
@@ -601,12 +551,18 @@
     }
 };
 
-kukit.er.OperRegistry.prototype.checkOperBindable = function (oper) {
+kukit.er.OperRegistry.prototype.checkOperBindable = function (oper, name, nodehash) {
     // 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);
+    //
+    // Remark. We need  different check and bind method, because we need to bind to the currently
+    // processed nodes, but we need to check duplication in all the previously bound nodes.
+    var info = this.infopername;
+    // name and nodehash are for speedup.
+    if (typeof(nodehash) == 'undefined') {
+        name = oper.eventrule.kss_selector.name;
+        nodehash = kukit.rd.hashnode(oper.node);
+    }
     var rules_per_name = info[name];
     if (typeof(rules_per_name) == 'undefined') {
         // Create an empty list.
@@ -619,15 +575,40 @@
     
 kukit.er.OperRegistry.prototype.bindOper = function (oper) {
     // Marks binding between binderinstance, eventname, node.
+    var name = oper.eventrule.kss_selector.name;
     var nodehash = kukit.rd.hashnode(oper.node);
-    var rules_per_name = this.checkOperBindable(oper);
+    var rules_per_name = this.checkOperBindable(oper, name, nodehash);
     rules_per_name[nodehash] = oper;
+    // also store per node info
+    var rules_per_node = this.infopernode[nodehash];
+    if (typeof(rules_per_node) == 'undefined') {
+        // Create an empty list.
+        rules_per_node = this.infopernode[nodehash] = {};
+    }
+    rules_per_node[name] = oper;
+};
+
+// XXX This will need refactoring.
+/// We would only want to lookup from our registry and not the other way around.
+kukit.er.OperRegistry.prototype.processBindingEvents = function (binderinstance) {
+    var eventRegistry = kukit.eventsGlobalRegistry;
+    for (var i=0; i < eventRegistry.eventsets.length; i++) {
+        var eventset = eventRegistry.eventsets[i];
+        if (binderinstance.__event_namespace__ == eventset.namespace) {
+            // Process the binding event set. This will call the actual bindmethods
+            // according to the specified iterator.
+            var iterator = kukit.er.getBindIterator(eventset.itername);
+            iterator.call(this, eventset, binderinstance);
+        }
+    }
 };
 
+// XXX The following methods will probably disappear as iterators replace their functionality.
+
 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];
+    var rules_per_name = this.infopername[name];
     if (typeof(rules_per_name) == 'undefined') {
         return null;
     }
@@ -643,7 +624,7 @@
 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];
+    var rules_per_name = this.infopername[name];
     if (typeof(rules_per_name) != 'undefined') {
         // take the values as a list
         for (var nodehash in rules_per_name) {
@@ -654,12 +635,78 @@
     return opers;
 };
 
-kukit.er.OperRegistry.prototype.getBoundOpersForEventSet = function (names) {
-    // Returns all opers for a given eventset.
+// Iterators
+// The getBindIterator returns a function that gets executed on
+// the oper registry.
+//
+// Iterators receive the eventset as a parameter
+// plus a binderinstance and a method. They need to iterate by calling this
+// as method.call(binderinstance, ...); where ... can be any parameters this
+// given iteration specifies.
+//
+
+kukit.er.getBindIterator = function(itername) {
+    return kukit.er.OperRegistry.prototype['iter_' + itername];
+};
+
+kukit.er.OperRegistry.prototype.call_bind_method = function (eventset, binderinstance, p1, p2, p3, p4, p5, p6) {
+    var method = binderinstance[eventset.bindmethodname];
+    // Protect the binding for better logging
+    try {
+        method.call(binderinstance, p1, p2, p3, p4, p5, p6);
+    } catch(e) {
+        throw new kukit.err.rd.EventBindError('Error during binding, reason: [' + e + ']',  oper.getEventName(), oper.getEventNamespace());
+    }
+};
+
+// This calls the bind method by each bound oper one by one. Eventname and func_to_bind are passed too.
+// this is the legacy ("each") way
+kukit.er.OperRegistry.prototype.iter_each = function (eventset, binderinstance) {
+    for (var i=0; i<eventset.names.length; i++) {
+        var rules_per_name = this.infopername[eventset.names[i]];
+        if (typeof(rules_per_name) != 'undefined') {
+            for (var nodehash in rules_per_name) {
+                var oper = rules_per_name[nodehash];
+                var eventname = oper.getEventName();
+                var func_to_bind = oper.makeExecuteActionsHook();
+                this.call_bind_method(eventset, binderinstance, eventname, func_to_bind, oper);
+            }
+        }
+    }
+};
+
+// This calls the bind method by the list of bound opers
+kukit.er.OperRegistry.prototype.iter_opers = function (eventset, binderinstance) {
     var opers = [];
-    for (var i=0; i<names.length; i++) {
-        var name = names[i];
-        opers = opers.concat(this.getBoundOpers(name));
+    for (var i=0; i<eventset.names.length; i++) {
+        var rules_per_name = this.infopername[eventset.names[i]];
+        if (typeof(rules_per_name) != 'undefined') {
+            for (var nodehash in rules_per_name) {
+                opers.push(rules_per_name[nodehash]);
+            }
+        }
     }
-    return opers;
+    this.call_bind_method(eventset, binderinstance, opers);
 };
+
+// This calls the bind method by a mapping eventname:oper per each bound node individually
+kukit.er.OperRegistry.prototype.iter_node = function (eventset, binderinstance) {
+    for (var nodehash in this.infopernode) {
+        var rules_per_node = this.infopernode[nodehash];
+        // filter only the nodes we are interested in
+        var filtered_rules = {};
+        var found = false;
+        for (var name in eventset.names) {
+            var oper = rules_per_node[name];
+            if (typeof(oper) != 'undefined') {
+                filtered_rules[name] = oper;
+                found = true;
+            }
+        }
+        // call it
+        if (found) {
+            this.call_bind_method(eventset, binderinstance, filtered_rules);
+        }
+    }
+};
+


More information about the Kukit-checkins mailing list