diff options
Diffstat (limited to 'includes/js/dojo/behavior.js')
-rw-r--r-- | includes/js/dojo/behavior.js | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/includes/js/dojo/behavior.js b/includes/js/dojo/behavior.js new file mode 100644 index 0000000..012f940 --- /dev/null +++ b/includes/js/dojo/behavior.js @@ -0,0 +1,185 @@ +if(!dojo._hasResource["dojo.behavior"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dojo.behavior"] = true; +dojo.provide("dojo.behavior"); + +dojo.behavior = new function(){ + function arrIn(obj, name){ + if(!obj[name]){ obj[name] = []; } + return obj[name]; + } + + var _inc = 0; + + function forIn(obj, scope, func){ + var tmpObj = {}; + for(var x in obj){ + if(typeof tmpObj[x] == "undefined"){ + if(!func){ + scope(obj[x], x); + }else{ + func.call(scope, obj[x], x); + } + } + } + } + + // FIXME: need a better test so we don't exclude nightly Safari's! + this._behaviors = {}; + this.add = function(behaviorObj){ + // summary: + // add the specified behavior to the list of behaviors which will + // be applied the next time apply() is called. Calls to add() for + // an already existing behavior do not replace the previous rules, + // but are instead additive. New nodes which match the rule will + // have all add()-ed behaviors applied to them when matched. + // + // description: + // behavior objects are specified in the following format(s): + // + // { + // "#id": { + // "found": function(element){ + // // ... + // }, + // + // "onblah": {targetObj: foo, targetFunc: "bar"}, + // + // "onblarg": "/foo/bar/baz/blarg", + // + // "onevent": function(evt){ + // }, + // + // "onotherevent: function(evt){ + // // ... + // } + // }, + // + // "#id2": { + // // ... + // }, + // + // "#id3": function(element){ + // // ... + // }, + // + // // publish the match on a topic + // "#id4": "/found/topic/name", + // + // // match all direct descendants + // "#id4 > *": function(element){ + // // ... + // }, + // + // // match the first child node that's an element + // "#id4 > :first-child": { ... }, + // + // // match the last child node that's an element + // "#id4 > :last-child": { ... }, + // + // // all elements of type tagname + // "tagname": { + // // ... + // }, + // + // "tagname1 tagname2 tagname3": { + // // ... + // }, + // + // ".classname": { + // // ... + // }, + // + // "tagname.classname": { + // // ... + // }, + // } + // + // The "found" method is a generalized handler that's called as soon + // as the node matches the selector. Rules for values that follow also + // apply to the "found" key. + // + // The "on*" handlers are attached with dojo.connect(). + // + // If the value corresponding to the ID key is a function and not a + // list, it's treated as though it was the value of "found". + + var tmpObj = {}; + forIn(behaviorObj, this, function(behavior, name){ + var tBehavior = arrIn(this._behaviors, name); + if(typeof tBehavior["id"] != "number"){ + tBehavior.id = _inc++; + } + var cversion = []; + tBehavior.push(cversion); + if((dojo.isString(behavior))||(dojo.isFunction(behavior))){ + behavior = { found: behavior }; + } + forIn(behavior, function(rule, ruleName){ + arrIn(cversion, ruleName).push(rule); + }); + }); + } + + var _applyToNode = function(node, action, ruleSetName){ + if(dojo.isString(action)){ + if(ruleSetName == "found"){ + dojo.publish(action, [ node ]); + }else{ + dojo.connect(node, ruleSetName, function(){ + dojo.publish(action, arguments); + }); + } + }else if(dojo.isFunction(action)){ + if(ruleSetName == "found"){ + action(node); + }else{ + dojo.connect(node, ruleSetName, action); + } + } + } + + this.apply = function(){ + // summary: + // applies all currently registered behaviors to the document, + // taking care to ensure that only incremental updates are made + // since the last time add() or apply() were called. If new + // matching nodes have been added, all rules in a behavior will be + // applied to that node. For previously matched nodes, only + // behaviors which have been added since the last call to apply() + // will be added to the nodes. + forIn(this._behaviors, function(tBehavior, id){ + dojo.query(id).forEach( + function(elem){ + var runFrom = 0; + var bid = "_dj_behavior_"+tBehavior.id; + if(typeof elem[bid] == "number"){ + runFrom = elem[bid]; + // console.debug(bid, runFrom); + if(runFrom == (tBehavior.length)){ + return; + } + } + // run through the versions, applying newer rules at each step + + for(var x=runFrom, tver; tver = tBehavior[x]; x++){ + // console.debug(tver); + forIn(tver, function(ruleSet, ruleSetName){ + if(dojo.isArray(ruleSet)){ + dojo.forEach(ruleSet, function(action){ + _applyToNode(elem, action, ruleSetName); + }); + } + }); + } + + // ensure that re-application only adds new rules to the node + elem[bid] = tBehavior.length; + } + ); + }); + } +} + +dojo.addOnLoad(dojo.behavior, "apply"); + +} |