123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- 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");
- }
|