summaryrefslogtreecommitdiff
path: root/lib/dojo/behavior.js.uncompressed.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dojo/behavior.js.uncompressed.js')
-rw-r--r--lib/dojo/behavior.js.uncompressed.js248
1 files changed, 248 insertions, 0 deletions
diff --git a/lib/dojo/behavior.js.uncompressed.js b/lib/dojo/behavior.js.uncompressed.js
new file mode 100644
index 000000000..4270501d1
--- /dev/null
+++ b/lib/dojo/behavior.js.uncompressed.js
@@ -0,0 +1,248 @@
+define("dojo/behavior", ["./_base/kernel", "./_base/lang", "./_base/array", "./_base/connect", "./query", "./ready"], function(dojo, lang, darray, connect, query, ready) {
+ // module:
+ // dojo/behavior
+ // summary:
+ // TODOC
+
+
+dojo.behavior = new function(){
+ // summary:
+ // Utility for unobtrusive/progressive event binding, DOM traversal,
+ // and manipulation.
+ //
+ // description:
+ //
+ // A very simple, lightweight mechanism for applying code to
+ // existing documents, based around `dojo.query` (CSS3 selectors) for node selection,
+ // and a simple two-command API: `dojo.behavior.add()` and `dojo.behavior.apply()`;
+ //
+ // Behaviors apply to a given page, and are registered following the syntax
+ // options described by `dojo.behavior.add` to match nodes to actions, or "behaviors".
+ //
+ // Added behaviors are applied to the current DOM when .apply() is called,
+ // matching only new nodes found since .apply() was last called.
+ //
+ 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(/* Object */behaviorObj){
+ // summary:
+ // Add the specified behavior to the list of behaviors, ignoring existing
+ // matches.
+ // behaviorObj: Object
+ // The behavior object that will be added to behaviors list. The behaviors
+ // in the list will be applied the next time apply() is called.
+ // description:
+ // 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.
+ //
+ // 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()`, using the
+ // matching node
+ //
+ // 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".
+ //
+ // dojo.behavior.add() can be called any number of times before
+ // the DOM is ready. `dojo.behavior.apply()` is called automatically
+ // by `dojo.addOnLoad`, though can be called to re-apply previously added
+ // behaviors anytime the DOM changes.
+ //
+ // There are a variety of formats permitted in the behaviorObject
+ //
+ // example:
+ // Simple list of properties. "found" is special. "Found" is assumed if
+ // no property object for a given selector, and property is a function.
+ //
+ // | dojo.behavior.add({
+ // | "#id": {
+ // | "found": function(element){
+ // | // node match found
+ // | },
+ // | "onclick": function(evt){
+ // | // register onclick handler for found node
+ // | }
+ // | },
+ // | "#otherid": function(element){
+ // | // assumes "found" with this syntax
+ // | }
+ // | });
+ //
+ // example:
+ // If property is a string, a dojo.publish will be issued on the channel:
+ //
+ // | dojo.behavior.add({
+ // | // dojo.publish() whenever class="noclick" found on anchors
+ // | "a.noclick": "/got/newAnchor",
+ // | "div.wrapper": {
+ // | "onclick": "/node/wasClicked"
+ // | }
+ // | });
+ // | dojo.subscribe("/got/newAnchor", function(node){
+ // | // handle node finding when dojo.behavior.apply() is called,
+ // | // provided a newly matched node is found.
+ // | });
+ //
+ // example:
+ // Scoping can be accomplished by passing an object as a property to
+ // a connection handle (on*):
+ //
+ // | dojo.behavior.add({
+ // | "#id": {
+ // | // like calling dojo.hitch(foo,"bar"). execute foo.bar() in scope of foo
+ // | "onmouseenter": { targetObj: foo, targetFunc: "bar" },
+ // | "onmouseleave": { targetObj: foo, targetFunc: "baz" }
+ // | }
+ // | });
+ //
+ // example:
+ // Bahaviors match on CSS3 Selectors, powered by dojo.query. Example selectors:
+ //
+ // | dojo.behavior.add({
+ // | // 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": {
+ // | // ...
+ // | }
+ // | });
+ //
+
+ 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((lang.isString(behavior))||(lang.isFunction(behavior))){
+ behavior = { found: behavior };
+ }
+ forIn(behavior, function(rule, ruleName){
+ arrIn(cversion, ruleName).push(rule);
+ });
+ });
+ };
+
+ var _applyToNode = function(node, action, ruleSetName){
+ if(lang.isString(action)){
+ if(ruleSetName == "found"){
+ connect.publish(action, [ node ]);
+ }else{
+ connect.connect(node, ruleSetName, function(){
+ connect.publish(action, arguments);
+ });
+ }
+ }else if(lang.isFunction(action)){
+ if(ruleSetName == "found"){
+ action(node);
+ }else{
+ connect.connect(node, ruleSetName, action);
+ }
+ }
+ };
+
+ this.apply = function(){
+ // summary:
+ // Applies all currently registered behaviors to the document.
+ //
+ // description:
+ // 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.
+ //
+ // apply() is called once automatically by `dojo.addOnLoad`, so
+ // registering behaviors with `dojo.behavior.add` before the DOM is
+ // ready is acceptable, provided the dojo.behavior module is ready.
+ //
+ // Calling appy() manually after manipulating the DOM is required
+ // to rescan the DOM and apply newly .add()ed behaviors, or to match
+ // nodes that match existing behaviors when those nodes are added to
+ // the DOM.
+ //
+ forIn(this._behaviors, function(tBehavior, id){
+ query(id).forEach(
+ function(elem){
+ var runFrom = 0;
+ var bid = "_dj_behavior_"+tBehavior.id;
+ if(typeof elem[bid] == "number"){
+ runFrom = elem[bid];
+ if(runFrom == (tBehavior.length)){
+ return;
+ }
+ }
+ // run through the versions, applying newer rules at each step
+
+ for(var x=runFrom, tver; tver = tBehavior[x]; x++){
+ forIn(tver, function(ruleSet, ruleSetName){
+ if(lang.isArray(ruleSet)){
+ darray.forEach(ruleSet, function(action){
+ _applyToNode(elem, action, ruleSetName);
+ });
+ }
+ });
+ }
+
+ // ensure that re-application only adds new rules to the node
+ elem[bid] = tBehavior.length;
+ }
+ );
+ });
+ };
+};
+
+ready(dojo.behavior, "apply"); // FIXME: should this use a priority? before/after parser priority?
+
+return dojo.behavior;
+});