Subversion Repositories Applications.papyrus

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2150 mathias 1
if(!dojo._hasResource["dojo.behavior"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2
dojo._hasResource["dojo.behavior"] = true;
3
dojo.provide("dojo.behavior");
4
 
5
dojo.behavior = new function(){
6
	function arrIn(obj, name){
7
		if(!obj[name]){ obj[name] = []; }
8
		return obj[name];
9
	}
10
 
11
	var _inc = 0;
12
 
13
	function forIn(obj, scope, func){
14
		var tmpObj = {};
15
		for(var x in obj){
16
			if(typeof tmpObj[x] == "undefined"){
17
				if(!func){
18
					scope(obj[x], x);
19
				}else{
20
					func.call(scope, obj[x], x);
21
				}
22
			}
23
		}
24
	}
25
 
26
	// FIXME: need a better test so we don't exclude nightly Safari's!
27
	this._behaviors = {};
28
	this.add = function(behaviorObj){
29
		//	summary:
30
		//		add the specified behavior to the list of behaviors which will
31
		//		be applied the next time apply() is called. Calls to add() for
32
		//		an already existing behavior do not replace the previous rules,
33
		//		but are instead additive. New nodes which match the rule will
34
		//		have all add()-ed behaviors applied to them when matched.
35
		//
36
		//	description:
37
		//		behavior objects are specified in the following format(s):
38
		//
39
		//			{
40
		//			 	"#id": {
41
		//					"found": function(element){
42
		//						// ...
43
		//					},
44
		//
45
		//					"onblah": {targetObj: foo, targetFunc: "bar"},
46
		//
47
		//					"onblarg": "/foo/bar/baz/blarg",
48
		//
49
		//					"onevent": function(evt){
50
		//					},
51
		//
52
		//					"onotherevent: function(evt){
53
		//						// ...
54
		//					}
55
		//				},
56
		//
57
		//				"#id2": {
58
		//					// ...
59
		//				},
60
		//
61
		//				"#id3": function(element){
62
		//					// ...
63
		//				},
64
		//
65
		//				// publish the match on a topic
66
		//				"#id4": "/found/topic/name",
67
		//
68
		//				// match all direct descendants
69
		//				"#id4 > *": function(element){
70
		//					// ...
71
		//				},
72
		//
73
		//				// match the first child node that's an element
74
		//				"#id4 > :first-child": { ... },
75
		//
76
		//				// match the last child node that's an element
77
		//				"#id4 > :last-child":  { ... },
78
		//
79
		//				// all elements of type tagname
80
		//				"tagname": {
81
		//					// ...
82
		//				},
83
		//
84
		//				"tagname1 tagname2 tagname3": {
85
		//					// ...
86
		//				},
87
		//
88
		//				".classname": {
89
		//					// ...
90
		//				},
91
		//
92
		//				"tagname.classname": {
93
		//					// ...
94
		//				},
95
		//			}
96
		//
97
		//		The "found" method is a generalized handler that's called as soon
98
		//		as the node matches the selector. Rules for values that follow also
99
		//		apply to the "found" key.
100
		//
101
		//		The "on*" handlers are attached with dojo.connect().
102
		//
103
		//		If the value corresponding to the ID key is a function and not a
104
		//		list, it's treated as though it was the value of "found".
105
 
106
		var tmpObj = {};
107
		forIn(behaviorObj, this, function(behavior, name){
108
			var tBehavior = arrIn(this._behaviors, name);
109
			if(typeof tBehavior["id"] != "number"){
110
				tBehavior.id = _inc++;
111
			}
112
			var cversion = [];
113
			tBehavior.push(cversion);
114
			if((dojo.isString(behavior))||(dojo.isFunction(behavior))){
115
				behavior = { found: behavior };
116
			}
117
			forIn(behavior, function(rule, ruleName){
118
				arrIn(cversion, ruleName).push(rule);
119
			});
120
		});
121
	}
122
 
123
	var _applyToNode = function(node, action, ruleSetName){
124
		if(dojo.isString(action)){
125
			if(ruleSetName == "found"){
126
				dojo.publish(action, [ node ]);
127
			}else{
128
				dojo.connect(node, ruleSetName, function(){
129
					dojo.publish(action, arguments);
130
				});
131
			}
132
		}else if(dojo.isFunction(action)){
133
			if(ruleSetName == "found"){
134
				action(node);
135
			}else{
136
				dojo.connect(node, ruleSetName, action);
137
			}
138
		}
139
	}
140
 
141
	this.apply = function(){
142
		// summary:
143
		//		applies all currently registered behaviors to the document,
144
		//		taking care to ensure that only incremental updates are made
145
		//		since the last time add() or apply() were called. If new
146
		//		matching nodes have been added, all rules in a behavior will be
147
		//		applied to that node. For previously matched nodes, only
148
		//		behaviors which have been added since the last call to apply()
149
		//		will be added to the nodes.
150
		forIn(this._behaviors, function(tBehavior, id){
151
			dojo.query(id).forEach(
152
				function(elem){
153
					var runFrom = 0;
154
					var bid = "_dj_behavior_"+tBehavior.id;
155
					if(typeof elem[bid] == "number"){
156
						runFrom = elem[bid];
157
						// console.debug(bid, runFrom);
158
						if(runFrom == (tBehavior.length)){
159
							return;
160
						}
161
					}
162
					// run through the versions, applying newer rules at each step
163
 
164
					for(var x=runFrom, tver; tver = tBehavior[x]; x++){
165
						// console.debug(tver);
166
						forIn(tver, function(ruleSet, ruleSetName){
167
							if(dojo.isArray(ruleSet)){
168
								dojo.forEach(ruleSet, function(action){
169
									_applyToNode(elem, action, ruleSetName);
170
								});
171
							}
172
						});
173
					}
174
 
175
					// ensure that re-application only adds new rules to the node
176
					elem[bid] = tBehavior.length;
177
				}
178
			);
179
		});
180
	}
181
}
182
 
183
dojo.addOnLoad(dojo.behavior, "apply");
184
 
185
}