Subversion Repositories Applications.papyrus

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2150 mathias 1
if(!dojo._hasResource["dojo.parser"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2
dojo._hasResource["dojo.parser"] = true;
3
dojo.provide("dojo.parser");
4
dojo.require("dojo.date.stamp");
5
 
6
dojo.parser = new function(){
7
 
8
	var d = dojo;
9
 
10
	function val2type(/*Object*/ value){
11
		// summary:
12
		//		Returns name of type of given value.
13
 
14
		if(d.isString(value)){ return "string"; }
15
		if(typeof value == "number"){ return "number"; }
16
		if(typeof value == "boolean"){ return "boolean"; }
17
		if(d.isFunction(value)){ return "function"; }
18
		if(d.isArray(value)){ return "array"; } // typeof [] == "object"
19
		if(value instanceof Date) { return "date"; } // assume timestamp
20
		if(value instanceof d._Url){ return "url"; }
21
		return "object";
22
	}
23
 
24
	function str2obj(/*String*/ value, /*String*/ type){
25
		// summary:
26
		//		Convert given string value to given type
27
		switch(type){
28
			case "string":
29
				return value;
30
			case "number":
31
				return value.length ? Number(value) : NaN;
32
			case "boolean":
33
				// for checked/disabled value might be "" or "checked".  interpret as true.
34
				return typeof value == "boolean" ? value : !(value.toLowerCase()=="false");
35
			case "function":
36
				if(d.isFunction(value)){
37
					// IE gives us a function, even when we say something like onClick="foo"
38
					// (in which case it gives us an invalid function "function(){ foo }").
39
					//  Therefore, convert to string
40
					value=value.toString();
41
					value=d.trim(value.substring(value.indexOf('{')+1, value.length-1));
42
				}
43
				try{
44
					if(value.search(/[^\w\.]+/i) != -1){
45
						// TODO: "this" here won't work
46
						value = d.parser._nameAnonFunc(new Function(value), this);
47
					}
48
					return d.getObject(value, false);
49
				}catch(e){ return new Function(); }
50
			case "array":
51
				return value.split(/\s*,\s*/);
52
			case "date":
53
				switch(value){
54
					case "": return new Date("");	// the NaN of dates
55
					case "now": return new Date();	// current date
56
					default: return d.date.stamp.fromISOString(value);
57
				}
58
			case "url":
59
				return d.baseUrl + value;
60
			default:
61
				return d.fromJson(value);
62
		}
63
	}
64
 
65
	var instanceClasses = {
66
		// map from fully qualified name (like "dijit.Button") to structure like
67
		// { cls: dijit.Button, params: {label: "string", disabled: "boolean"} }
68
	};
69
 
70
	function getClassInfo(/*String*/ className){
71
		// className:
72
		//		fully qualified name (like "dijit.Button")
73
		// returns:
74
		//		structure like
75
		//			{
76
		//				cls: dijit.Button,
77
		//				params: { label: "string", disabled: "boolean"}
78
		//			}
79
 
80
		if(!instanceClasses[className]){
81
			// get pointer to widget class
82
			var cls = d.getObject(className);
83
			if(!d.isFunction(cls)){
84
				throw new Error("Could not load class '" + className +
85
					"'. Did you spell the name correctly and use a full path, like 'dijit.form.Button'?");
86
			}
87
			var proto = cls.prototype;
88
 
89
			// get table of parameter names & types
90
			var params={};
91
			for(var name in proto){
92
				if(name.charAt(0)=="_"){ continue; } 	// skip internal properties
93
				var defVal = proto[name];
94
				params[name]=val2type(defVal);
95
			}
96
 
97
			instanceClasses[className] = { cls: cls, params: params };
98
		}
99
		return instanceClasses[className];
100
	}
101
 
102
	this._functionFromScript = function(script){
103
		var preamble = "";
104
		var suffix = "";
105
		var argsStr = script.getAttribute("args");
106
		if(argsStr){
107
			d.forEach(argsStr.split(/\s*,\s*/), function(part, idx){
108
				preamble += "var "+part+" = arguments["+idx+"]; ";
109
			});
110
		}
111
		var withStr = script.getAttribute("with");
112
		if(withStr && withStr.length){
113
			d.forEach(withStr.split(/\s*,\s*/), function(part){
114
				preamble += "with("+part+"){";
115
				suffix += "}";
116
			});
117
		}
118
		return new Function(preamble+script.innerHTML+suffix);
119
	}
120
 
121
	this.instantiate = function(/* Array */nodes){
122
		// summary:
123
		//		Takes array of nodes, and turns them into class instances and
124
		//		potentially calls a layout method to allow them to connect with
125
		//		any children
126
		var thelist = [];
127
		d.forEach(nodes, function(node){
128
			if(!node){ return; }
129
			var type = node.getAttribute("dojoType");
130
			if((!type)||(!type.length)){ return; }
131
			var clsInfo = getClassInfo(type);
132
			var clazz = clsInfo.cls;
133
			var ps = clazz._noScript||clazz.prototype._noScript;
134
 
135
			// read parameters (ie, attributes).
136
			// clsInfo.params lists expected params like {"checked": "boolean", "n": "number"}
137
			var params = {};
138
			var attributes = node.attributes;
139
			for(var name in clsInfo.params){
140
				var item = attributes.getNamedItem(name);
141
				if(!item || (!item.specified && (!dojo.isIE || name.toLowerCase()!="value"))){ continue; }
142
				var value = item.value;
143
				// Deal with IE quirks for 'class' and 'style'
144
				switch(name){
145
				case "class":
146
					value = node.className;
147
					break;
148
				case "style":
149
					value = node.style && node.style.cssText; // FIXME: Opera?
150
				}
151
				var _type = clsInfo.params[name];
152
				params[name] = str2obj(value, _type);
153
			}
154
 
155
			// Process <script type="dojo/*"> script tags
156
			// <script type="dojo/method" event="foo"> tags are added to params, and passed to
157
			// the widget on instantiation.
158
			// <script type="dojo/method"> tags (with no event) are executed after instantiation
159
			// <script type="dojo/connect" event="foo"> tags are dojo.connected after instantiation
160
			if(!ps){
161
				var connects = [],	// functions to connect after instantiation
162
					calls = [];		// functions to call after instantiation
163
 
164
				d.query("> script[type^='dojo/']", node).orphan().forEach(function(script){
165
					var event = script.getAttribute("event"),
166
						type = script.getAttribute("type"),
167
						nf = d.parser._functionFromScript(script);
168
					if(event){
169
						if(type == "dojo/connect"){
170
							connects.push({event: event, func: nf});
171
						}else{
172
							params[event] = nf;
173
						}
174
					}else{
175
						calls.push(nf);
176
					}
177
				});
178
			}
179
 
180
			var markupFactory = clazz["markupFactory"];
181
			if(!markupFactory && clazz["prototype"]){
182
				markupFactory = clazz.prototype["markupFactory"];
183
			}
184
			// create the instance
185
			var instance = markupFactory ? markupFactory(params, node, clazz) : new clazz(params, node);
186
			thelist.push(instance);
187
 
188
			// map it to the JS namespace if that makes sense
189
			var jsname = node.getAttribute("jsId");
190
			if(jsname){
191
				d.setObject(jsname, instance);
192
			}
193
 
194
			// process connections and startup functions
195
			if(!ps){
196
				dojo.forEach(connects, function(connect){
197
					dojo.connect(instance, connect.event, null, connect.func);
198
				});
199
				dojo.forEach(calls, function(func){
200
					func.call(instance);
201
				});
202
			}
203
		});
204
 
205
		// Call startup on each top level instance if it makes sense (as for
206
		// widgets).  Parent widgets will recursively call startup on their
207
		// (non-top level) children
208
		d.forEach(thelist, function(instance){
209
			if(	instance  &&
210
				(instance.startup) &&
211
				((!instance.getParent) || (!instance.getParent()))
212
			){
213
				instance.startup();
214
			}
215
		});
216
		return thelist;
217
	};
218
 
219
	this.parse = function(/*DomNode?*/ rootNode){
220
		// summary:
221
		//		Search specified node (or root node) recursively for class instances,
222
		//		and instantiate them Searches for
223
		//		dojoType="qualified.class.name"
224
		var list = d.query('[dojoType]', rootNode);
225
		// go build the object instances
226
		var instances = this.instantiate(list);
227
		return instances;
228
	};
229
}();
230
 
231
//Register the parser callback. It should be the first callback
232
//after the a11y test.
233
 
234
(function(){
235
	var parseRunner = function(){
236
		if(djConfig["parseOnLoad"] == true){
237
			dojo.parser.parse();
238
		}
239
	};
240
 
241
	// FIXME: need to clobber cross-dependency!!
242
	if(dojo.exists("dijit.wai.onload") && (dijit.wai.onload === dojo._loaders[0])){
243
		dojo._loaders.splice(1, 0, parseRunner);
244
	}else{
245
		dojo._loaders.unshift(parseRunner);
246
	}
247
})();
248
 
249
//TODO: ported from 0.4.x Dojo.  Can we reduce this?
250
dojo.parser._anonCtr = 0;
251
dojo.parser._anon = {}; // why is this property required?
252
dojo.parser._nameAnonFunc = function(/*Function*/anonFuncPtr, /*Object*/thisObj){
253
	// summary:
254
	//		Creates a reference to anonFuncPtr in thisObj with a completely
255
	//		unique name. The new name is returned as a String.
256
	var jpn = "$joinpoint";
257
	var nso = (thisObj|| dojo.parser._anon);
258
	if(dojo.isIE){
259
		var cn = anonFuncPtr["__dojoNameCache"];
260
		if(cn && nso[cn] === anonFuncPtr){
261
			return anonFuncPtr["__dojoNameCache"];
262
		}
263
	}
264
	var ret = "__"+dojo.parser._anonCtr++;
265
	while(typeof nso[ret] != "undefined"){
266
		ret = "__"+dojo.parser._anonCtr++;
267
	}
268
	nso[ret] = anonFuncPtr;
269
	return ret; // String
270
}
271
 
272
}