--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/toolkit/javascript/nco/relations.js Thu Apr 10 14:20:23 2014 +0200
@@ -0,0 +1,213 @@
+function Relations() {
+ this.items = {};
+}
+
+Relations.prototype = {
+ constructor: Relations,
+
+ /**
+ * Add an element to the dictionnary under the given name.
+ *
+ * @param {String} id: identifier for the item
+ * @param {Object} element: item to register
+ *
+ * @returns {Connector}: inserted element wrapped with a Connector
+ */
+ add: function(id, element) {
+ return this.items[id] = new Connector(element, id, this);
+ },
+
+ remove: function(id) {
+
+ },
+
+ /**
+ * Gets the wanted item
+ *
+ * @param {String} id: item name
+ *
+ * @returns {Connector}: the wanted item, wrapped in a selector
+ */
+ get: function(id) {
+ return this.items[id];
+ },
+
+ /**
+ * Executes all the registered actions for a given element and a given event.
+ *
+ * First, if the required item is frozen, nothing is executed.
+ * Then, it checks every observer to see if they are locked, otherwise, their
+ * action is performed.
+ *
+ * @param {String} id: id of the element activated
+ * @param {String} event: name of the event activated
+ * @param eventParameters: parameters passed by the event raised
+ *
+ * @returns: null
+ */
+ execute: function(id, event, eventParameters) {
+ var item = this.get(id);
+ if (!item.isFrozen()) {
+ var functions = item.listenedEvents[event];
+ for(var i =0; i<functions.length; ++i) {
+ var observer = this.get(functions[i][0]);
+ if (!observer.isLocked()) {
+ functions[i][1](observer.element, eventParameters);
+ }
+ }
+ }
+ },
+
+ /**
+ * Executes an action on each selected item
+ *
+ * The selection is made through an selector string or directly a regular
+ * expression. Then, on each selected item, the given action is performed
+ * passed the item as this in the action.
+ *
+ * @param {String/RegExp} selector: selection test to get items
+ * @param {Function} action: action to perform
+ * @param {Boolean} getDetails: retrieve all information captured
+ * by special expressions
+ *
+ * @returns: {Integer} nombre d'éléments trouvés par la recherche
+ */
+ each: function(selector, action, getDetails) {
+ if (undefined==getDetails) {
+ getDetails = false;
+ }
+
+ var expr = this.buildExpression(selector, getDetails);
+ var compteur = 0;
+ if (false==getDetails) {
+ for (var itemName in this.items) {
+ if (expr.test(itemName)) {
+ action.call(this.items[itemName], this.items[itemName].element);
+ ++compteur;
+ }
+ }
+ }
+ else {
+ var details = null;
+ for (var itemName in this.items) {
+ details = itemName.match(expr);
+ if (null!=details) {
+ action.call(this.items[itemName], this.items[itemName].element, details);
+ ++compteur;
+ }
+ }
+ }
+
+ return compteur;
+ },
+
+ /**
+ * Build a selector from a string
+ *
+ * If a string is passed, it is turned as a RegExp.
+ * If an RegExp instance is passed, it is returned directly.
+ *
+ * @param string selector: string to turn as selector
+ * @param RegExp selector: regular expression to use
+ *
+ * @returns {RegExp}: selector
+ */
+ buildExpression: function(selector, getDetails) {
+ if (RegExp==selector) {
+ return selector;
+ }
+
+ var expression = selector;
+ expression = expression.replace(/(\(|\))/g, "\\$1");
+
+ if (false==getDetails) {
+ expression = expression.replace(/\[\[digit\]\]/g, "[0-9]+");
+ expression = expression.replace(/\[\[letter\]\]/g, "[a-zA-Z]+");
+ expression = expression.replace(/\./g, "\\.");
+ expression = expression.replace(/\?/g, ".");
+ expression = expression.replace(/\*/g, ".+");
+ }
+ else {
+ expression = expression.replace(/\[\[digit\]\]/g, "([0-9]+)");
+ expression = expression.replace(/\[\[letter\]\]/g, "([a-zA-Z]+)");
+ expression = expression.replace(/\./g, "\\.");
+ expression = expression.replace(/\?/g, "(.)");
+ expression = expression.replace(/\*/g, "(.+)");
+ }
+
+ return RegExp("^" + expression + "$");
+ }
+};
+
+function Connector(object, id, manager) {
+ this.manager = manager;
+ this.element = object;
+ this.id = id;
+ this.listenedEvents = {};
+ this.locked = false;
+ this.frozen = false;
+}
+
+Connector.prototype = {
+ constructor: Connector,
+
+ object: function() { return this.element; },
+
+ bind: function(event, id, action) {
+ if (undefined==action) {
+ this.bind(event, this.id, id);
+ }
+ else {
+ if (undefined!=this.listenedEvents[event]) {
+ this.listenedEvents[event].push([id, action]);
+ }
+ else {
+ var object = this;
+ this.listenedEvents[event] = [[id, action]];
+ this.element.on(event, function() {
+ object.manager.execute(object.id, event, arguments);
+ }) ;
+ }
+ }
+
+ return this;
+ },
+
+ bindTo: function(event, id, action) {
+ this.manager.get(id).bind(event, this.id, action);
+
+ return this;
+ },
+
+ unbind: function(id, event) {
+ return this;
+ },
+
+ click: function(id, action) {
+ return this.bind("click", id, action);
+ },
+
+ dblclick: function(id, action) {
+ return this.bind("dblclick", id, action);
+ },
+
+ mouseover: function(id, action) {
+ return this.bind("mouseover", id, action);
+ },
+
+ mouseout: function(id, action) {
+ return this.bind("mouseout", id, action);
+ },
+
+ lock: function() { this.locked = true; },
+
+ unlock: function() { this.locked = false; },
+
+ isLocked: function() { return true==this.locked; },
+
+ freeze: function() { this.frozen = true; },
+
+ unfreeze: function() { this.frozen = false; },
+
+ isFrozen: function() { return true==this.frozen; }
+};