Subversion Repositories Applications.papyrus

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2150 mathias 1
/*
2
	Copyright (c) 2004-2007, The Dojo Foundation
3
	All Rights Reserved.
4
 
5
	Licensed under the Academic Free License version 2.1 or above OR the
6
	modified BSD license. For more information on Dojo licensing, see:
7
 
8
		http://dojotoolkit.org/book/dojo-book-0-9/introduction/licensing
9
*/
10
 
11
/*
12
	This is a compiled version of Dojo, built for deployment and not for
13
	development. To get an editable version, please visit:
14
 
15
		http://dojotoolkit.org
16
 
17
	for documentation and information on getting the source.
18
*/
19
 
20
if(typeof dojo == "undefined"){
21
 
22
// TODOC: HOW TO DOC THE BELOW?
23
// @global: djConfig
24
// summary:
25
//		Application code can set the global 'djConfig' prior to loading
26
//		the library to override certain global settings for how dojo works.
27
// description:  The variables that can be set are as follows:
28
//			- isDebug: false
29
//			- libraryScriptUri: ""
30
//			- locale: undefined
31
//			- extraLocale: undefined
32
//			- preventBackButtonFix: true
33
// note:
34
//		'djConfig' does not exist under 'dojo.*' so that it can be set before the
35
//		'dojo' variable exists.
36
// note:
37
//		Setting any of these variables *after* the library has loaded does
38
//		nothing at all.
39
 
40
(function(){
41
	// make sure djConfig is defined
42
	if(typeof this["djConfig"] == "undefined"){
43
		this.djConfig = {};
44
	}
45
 
46
	// firebug stubs
47
	if((!this["console"])||(!console["firebug"])){
48
		this.console = {};
49
	}
50
 
51
	var cn = [
52
		"assert", "count", "debug", "dir", "dirxml", "error", "group",
53
		"groupEnd", "info", "log", "profile", "profileEnd", "time",
54
		"timeEnd", "trace", "warn"
55
	];
56
	var i=0, tn;
57
	while((tn=cn[i++])){
58
		if(!console[tn]){
59
			console[tn] = function(){};
60
		}
61
	}
62
 
63
	//TODOC:  HOW TO DOC THIS?
64
	// dojo is the root variable of (almost all) our public symbols -- make sure it is defined.
65
	if(typeof this["dojo"] == "undefined"){
66
		this.dojo = {};
67
	}
68
 
69
	var d = dojo;
70
 
71
	// summary:
72
	//		return the current global context object
73
	//		(e.g., the window object in a browser).
74
	// description:
75
	//		Refer to 'dojo.global' rather than referring to window to ensure your
76
	//		code runs correctly in contexts other than web browsers (eg: Rhino on a server).
77
	dojo.global = this;
78
 
79
	var _config =/*===== djConfig = =====*/{
80
		isDebug: false,
81
		libraryScriptUri: "",
82
		preventBackButtonFix: true,
83
		delayMozLoadingFix: false
84
	};
85
 
86
	for(var option in _config){
87
		if(typeof djConfig[option] == "undefined"){
88
			djConfig[option] = _config[option];
89
		}
90
	}
91
 
92
	var _platforms = ["Browser", "Rhino", "Spidermonkey", "Mobile"];
93
	var t;
94
	while(t=_platforms.shift()){
95
		d["is"+t] = false;
96
	}
97
 
98
	// Override locale setting, if specified
99
	dojo.locale = djConfig.locale;
100
 
101
	//TODOC:  HOW TO DOC THIS?
102
	dojo.version = {
103
		// summary: version number of this instance of dojo.
104
		major: 1, minor: 0, patch: 2, flag: "",
105
		revision: Number("$Rev: 11832 $".match(/[0-9]+/)[0]),
106
		toString: function(){
107
			with(d.version){
108
				return major + "." + minor + "." + patch + flag + " (" + revision + ")";	// String
109
			}
110
		}
111
	}
112
 
113
	// Register with the OpenAjax hub
114
	if(typeof OpenAjax != "undefined"){
115
		OpenAjax.hub.registerLibrary("dojo", "http://dojotoolkit.org", d.version.toString());
116
	}
117
 
118
	dojo._mixin = function(/*Object*/ obj, /*Object*/ props){
119
		// summary:
120
		//		Adds all properties and methods of props to obj. This addition is
121
		//		"prototype extension safe", so that instances of objects will not
122
		//		pass along prototype defaults.
123
		var tobj = {};
124
		for(var x in props){
125
			// the "tobj" condition avoid copying properties in "props"
126
			// inherited from Object.prototype.  For example, if obj has a custom
127
			// toString() method, don't overwrite it with the toString() method
128
			// that props inherited from Object.prototype
129
			if(tobj[x] === undefined || tobj[x] != props[x]){
130
				obj[x] = props[x];
131
			}
132
		}
133
		// IE doesn't recognize custom toStrings in for..in
134
		if(d["isIE"] && props){
135
			var p = props.toString;
136
			if(typeof p == "function" && p != obj.toString && p != tobj.toString &&
137
				p != "\nfunction toString() {\n    [native code]\n}\n"){
138
					obj.toString = props.toString;
139
			}
140
		}
141
		return obj; // Object
142
	}
143
 
144
	dojo.mixin = function(/*Object*/obj, /*Object...*/props){
145
		// summary:	Adds all properties and methods of props to obj.
146
		for(var i=1, l=arguments.length; i<l; i++){
147
			d._mixin(obj, arguments[i]);
148
		}
149
		return obj; // Object
150
	}
151
 
152
	dojo._getProp = function(/*Array*/parts, /*Boolean*/create, /*Object*/context){
153
		var obj=context||d.global;
154
		for(var i=0, p; obj&&(p=parts[i]); i++){
155
			obj = (p in obj ? obj[p] : (create ? obj[p]={} : undefined));
156
		}
157
		return obj; // mixed
158
	}
159
 
160
	dojo.setObject = function(/*String*/name, /*mixed*/value, /*Object*/context){
161
		// summary:
162
		//		Set a property from a dot-separated string, such as "A.B.C"
163
		//	description:
164
		//		Useful for longer api chains where you have to test each object in
165
		//		the chain, or when you have an object reference in string format.
166
		//		Objects are created as needed along 'path'.
167
		//	name:
168
		//		Path to a property, in the form "A.B.C".
169
		//	context:
170
		//		Optional. Object to use as root of path. Defaults to
171
		//		'dojo.global'. Null may be passed.
172
		var parts=name.split("."), p=parts.pop(), obj=d._getProp(parts, true, context);
173
		return (obj && p ? (obj[p]=value) : undefined); // mixed
174
	}
175
 
176
	dojo.getObject = function(/*String*/name, /*Boolean*/create, /*Object*/context){
177
		// summary:
178
		//		Get a property from a dot-separated string, such as "A.B.C"
179
		//	description:
180
		//		Useful for longer api chains where you have to test each object in
181
		//		the chain, or when you have an object reference in string format.
182
		//	name:
183
		//		Path to an property, in the form "A.B.C".
184
		//	context:
185
		//		Optional. Object to use as root of path. Defaults to
186
		//		'dojo.global'. Null may be passed.
187
		//	create:
188
		//		Optional. If true, Objects will be created at any point along the
189
		//		'path' that is undefined.
190
		return d._getProp(name.split("."), create, context); // mixed
191
	}
192
 
193
	dojo.exists = function(/*String*/name, /*Object?*/obj){
194
		// summary:
195
		//		determine if an object supports a given method
196
		// description:
197
		//		useful for longer api chains where you have to test each object in
198
		//		the chain
199
		// name:
200
		//		Path to an object, in the form "A.B.C".
201
		// obj:
202
		//		Object to use as root of path. Defaults to
203
		//		'dojo.global'. Null may be passed.
204
		return !!d.getObject(name, false, obj); // Boolean
205
	}
206
 
207
 
208
	dojo["eval"] = function(/*String*/ scriptFragment){
209
		// summary:
210
		//		Perform an evaluation in the global scope.  Use this rather than
211
		//		calling 'eval()' directly.
212
		// description:
213
		//		Placed in a separate function to minimize size of trapped
214
		//		evaluation context.
215
		// note:
216
		//	 - JSC eval() takes an optional second argument which can be 'unsafe'.
217
		//	 - Mozilla/SpiderMonkey eval() takes an optional second argument which is the
218
		//  	 scope object for new symbols.
219
 
220
		// FIXME: investigate Joseph Smarr's technique for IE:
221
		//		http://josephsmarr.com/2007/01/31/fixing-eval-to-use-global-scope-in-ie/
222
		//	see also:
223
		// 		http://trac.dojotoolkit.org/ticket/744
224
		return d.global.eval ? d.global.eval(scriptFragment) : eval(scriptFragment); 	// mixed
225
	}
226
 
227
	/*=====
228
		dojo.deprecated = function(behaviour, extra, removal){
229
			//	summary:
230
			//		Log a debug message to indicate that a behavior has been
231
			//		deprecated.
232
			//	behaviour: String
233
			//		The API or behavior being deprecated. Usually in the form
234
			//		of "myApp.someFunction()".
235
			//	extra: String?
236
			//		Text to append to the message. Often provides advice on a
237
			//		new function or facility to achieve the same goal during
238
			//		the deprecation period.
239
			//	removal: String?
240
			//		Text to indicate when in the future the behavior will be
241
			//		removed. Usually a version number.
242
			//	example:
243
			//	|	dojo.deprecated("myApp.getTemp()", "use myApp.getLocaleTemp() instead", "1.0");
244
		}
245
 
246
		dojo.experimental = function(moduleName, extra){
247
			//	summary: Marks code as experimental.
248
			//	description:
249
			//	 	This can be used to mark a function, file, or module as
250
			//	 	experimental.  Experimental code is not ready to be used, and the
251
			//	 	APIs are subject to change without notice.  Experimental code may be
252
			//	 	completed deleted without going through the normal deprecation
253
			//	 	process.
254
			//	moduleName: String
255
			//	 	The name of a module, or the name of a module file or a specific
256
			//	 	function
257
			//	extra: String?
258
			//	 	some additional message for the user
259
			//	example:
260
			//	|	dojo.experimental("dojo.data.Result");
261
			//	example:
262
			//	|	dojo.experimental("dojo.weather.toKelvin()", "PENDING approval from NOAA");
263
		}
264
	=====*/
265
 
266
	//Real functions declared in dojo._firebug.firebug.
267
	d.deprecated = d.experimental = function(){};
268
 
269
})();
270
// vim:ai:ts=4:noet
271
 
272
/*
273
 * loader.js - A bootstrap module.  Runs before the hostenv_*.js file. Contains
274
 * all of the package loading methods.
275
 */
276
 
277
(function(){
278
	var d = dojo;
279
 
280
	dojo.mixin(dojo, {
281
		_loadedModules: {},
282
		_inFlightCount: 0,
283
		_hasResource: {},
284
 
285
		// FIXME: it should be possible to pull module prefixes in from djConfig
286
		_modulePrefixes: {
287
			dojo: {name: "dojo", value: "."},
288
			doh: {name: "doh", value: "../util/doh"},
289
			tests: {name: "tests", value: "tests"}
290
		},
291
 
292
		_moduleHasPrefix: function(/*String*/module){
293
			// summary: checks to see if module has been established
294
			var mp = this._modulePrefixes;
295
			return !!(mp[module] && mp[module].value); // Boolean
296
		},
297
 
298
		_getModulePrefix: function(/*String*/module){
299
			// summary: gets the prefix associated with module
300
			var mp = this._modulePrefixes;
301
			if(this._moduleHasPrefix(module)){
302
				return mp[module].value; // String
303
			}
304
			return module; // String
305
		},
306
 
307
		_loadedUrls: [],
308
 
309
		//WARNING:
310
		//		This variable is referenced by packages outside of bootstrap:
311
		//		FloatingPane.js and undo/browser.js
312
		_postLoad: false,
313
 
314
		//Egad! Lots of test files push on this directly instead of using dojo.addOnLoad.
315
		_loaders: [],
316
		_unloaders: [],
317
		_loadNotifying: false
318
	});
319
 
320
 
321
		dojo._loadPath = function(/*String*/relpath, /*String?*/module, /*Function?*/cb){
322
		// 	summary:
323
		//		Load a Javascript module given a relative path
324
		//
325
		//	description:
326
		//		Loads and interprets the script located at relpath, which is
327
		//		relative to the script root directory.  If the script is found but
328
		//		its interpretation causes a runtime exception, that exception is
329
		//		not caught by us, so the caller will see it.  We return a true
330
		//		value if and only if the script is found.
331
		//
332
		// relpath:
333
		//		A relative path to a script (no leading '/', and typically ending
334
		//		in '.js').
335
		// module:
336
		//		A module whose existance to check for after loading a path.  Can be
337
		//		used to determine success or failure of the load.
338
		// cb:
339
		//		a callback function to pass the result of evaluating the script
340
 
341
		var uri = (((relpath.charAt(0) == '/' || relpath.match(/^\w+:/))) ? "" : this.baseUrl) + relpath;
342
		if(djConfig.cacheBust && d.isBrowser){
343
			uri += "?" + String(djConfig.cacheBust).replace(/\W+/g,"");
344
		}
345
		try{
346
			return !module ? this._loadUri(uri, cb) : this._loadUriAndCheck(uri, module, cb); // Boolean
347
		}catch(e){
348
			console.debug(e);
349
			return false; // Boolean
350
		}
351
	}
352
 
353
	dojo._loadUri = function(/*String (URL)*/uri, /*Function?*/cb){
354
		//	summary:
355
		//		Loads JavaScript from a URI
356
		//	description:
357
		//		Reads the contents of the URI, and evaluates the contents.  This is
358
		//		used to load modules as well as resource bundles. Returns true if
359
		//		it succeeded. Returns false if the URI reading failed.  Throws if
360
		//		the evaluation throws.
361
		//	uri: a uri which points at the script to be loaded
362
		//	cb:
363
		//		a callback function to process the result of evaluating the script
364
		//		as an expression, typically used by the resource bundle loader to
365
		//		load JSON-style resources
366
 
367
		if(this._loadedUrls[uri]){
368
			return true; // Boolean
369
		}
370
		var contents = this._getText(uri, true);
371
		if(!contents){ return false; } // Boolean
372
		this._loadedUrls[uri] = true;
373
		this._loadedUrls.push(uri);
374
		if(cb){ contents = '('+contents+')'; }
375
		var value = d["eval"](contents+"\r\n//@ sourceURL="+uri);
376
		if(cb){ cb(value); }
377
		return true; // Boolean
378
	}
379
 
380
	// FIXME: probably need to add logging to this method
381
	dojo._loadUriAndCheck = function(/*String (URL)*/uri, /*String*/moduleName, /*Function?*/cb){
382
		// summary: calls loadUri then findModule and returns true if both succeed
383
		var ok = false;
384
		try{
385
			ok = this._loadUri(uri, cb);
386
		}catch(e){
387
			console.debug("failed loading " + uri + " with error: " + e);
388
		}
389
		return Boolean(ok && this._loadedModules[moduleName]); // Boolean
390
	}
391
 
392
	dojo.loaded = function(){
393
		// summary:
394
		//		signal fired when initial environment and package loading is
395
		//		complete. You may use dojo.addOnLoad() or dojo.connect() to
396
		//		this method in order to handle initialization tasks that
397
		//		require the environment to be initialized. In a browser host,
398
		//		declarative widgets will be constructed when this function
399
		//		finishes runing.
400
		this._loadNotifying = true;
401
		this._postLoad = true;
402
		var mll = this._loaders;
403
 
404
		//Clear listeners so new ones can be added
405
		//For other xdomain package loads after the initial load.
406
		this._loaders = [];
407
 
408
		for(var x=0; x<mll.length; x++){
409
			mll[x]();
410
		}
411
 
412
		this._loadNotifying = false;
413
 
414
		//Make sure nothing else got added to the onload queue
415
		//after this first run. If something did, and we are not waiting for any
416
		//more inflight resources, run again.
417
		if(d._postLoad && d._inFlightCount == 0 && this._loaders.length > 0){
418
			d._callLoaded();
419
		}
420
	}
421
 
422
	dojo.unloaded = function(){
423
		// summary:
424
		//		signal fired by impending environment destruction. You may use
425
		//		dojo.addOnUnload() or dojo.connect() to this method to perform
426
		//		page/application cleanup methods.
427
		var mll = this._unloaders;
428
		while(mll.length){
429
			(mll.pop())();
430
		}
431
	}
432
 
433
	dojo.addOnLoad = function(/*Object?*/obj, /*String|Function*/functionName){
434
		// summary:
435
		//		Registers a function to be triggered after the DOM has finished
436
		//		loading and widgets declared in markup have been instantiated.
437
		//		Images and CSS files may or may not have finished downloading when
438
		//		the specified function is called.  (Note that widgets' CSS and HTML
439
		//		code is guaranteed to be downloaded before said widgets are
440
		//		instantiated.)
441
		// example:
442
		//	|	dojo.addOnLoad(functionPointer);
443
		//	|	dojo.addOnLoad(object, "functionName");
444
		if(arguments.length == 1){
445
			d._loaders.push(obj);
446
		}else if(arguments.length > 1){
447
			d._loaders.push(function(){
448
				obj[functionName]();
449
			});
450
		}
451
 
452
		//Added for xdomain loading. dojo.addOnLoad is used to
453
		//indicate callbacks after doing some dojo.require() statements.
454
		//In the xdomain case, if all the requires are loaded (after initial
455
		//page load), then immediately call any listeners.
456
		if(d._postLoad && d._inFlightCount == 0 && !d._loadNotifying){
457
			d._callLoaded();
458
		}
459
	}
460
 
461
	dojo.addOnUnload = function(/*Object?*/obj, /*String|Function?*/functionName){
462
		// summary: registers a function to be triggered when the page unloads
463
		// example:
464
		//	|	dojo.addOnUnload(functionPointer)
465
		//	|	dojo.addOnUnload(object, "functionName")
466
		if(arguments.length == 1){
467
			d._unloaders.push(obj);
468
		}else if(arguments.length > 1){
469
			d._unloaders.push(function(){
470
				obj[functionName]();
471
			});
472
		}
473
	}
474
 
475
	dojo._modulesLoaded = function(){
476
		if(d._postLoad){ return; }
477
		if(d._inFlightCount > 0){
478
			console.debug("files still in flight!");
479
			return;
480
		}
481
		d._callLoaded();
482
	}
483
 
484
	dojo._callLoaded = function(){
485
		//The "object" check is for IE, and the other opera check fixes an issue
486
		//in Opera where it could not find the body element in some widget test cases.
487
		//For 0.9, maybe route all browsers through the setTimeout (need protection
488
		//still for non-browser environments though). This might also help the issue with
489
		//FF 2.0 and freezing issues where we try to do sync xhr while background css images
490
		//are being loaded (trac #2572)? Consider for 0.9.
491
		if(typeof setTimeout == "object" || (djConfig["useXDomain"] && d.isOpera)){
492
			setTimeout("dojo.loaded();", 0);
493
		}else{
494
			d.loaded();
495
		}
496
	}
497
 
498
	dojo._getModuleSymbols = function(/*String*/modulename){
499
		// summary:
500
		//		Converts a module name in dotted JS notation to an array
501
		//		representing the path in the source tree
502
		var syms = modulename.split(".");
503
		for(var i = syms.length; i>0; i--){
504
			var parentModule = syms.slice(0, i).join(".");
505
			if((i==1) && !this._moduleHasPrefix(parentModule)){
506
				// Support default module directory (sibling of dojo) for top-level modules
507
				syms[0] = "../" + syms[0];
508
			}else{
509
				var parentModulePath = this._getModulePrefix(parentModule);
510
				if(parentModulePath != parentModule){
511
					syms.splice(0, i, parentModulePath);
512
					break;
513
				}
514
			}
515
		}
516
		// console.debug(syms);
517
		return syms; // Array
518
	}
519
 
520
	dojo._global_omit_module_check = false;
521
 
522
	dojo._loadModule = dojo.require = function(/*String*/moduleName, /*Boolean?*/omitModuleCheck){
523
		//	summary:
524
		//		loads a Javascript module from the appropriate URI
525
		//	moduleName: String
526
		//	omitModuleCheck: Boolean?
527
		//	description:
528
		//		_loadModule("A.B") first checks to see if symbol A.B is defined. If
529
		//		it is, it is simply returned (nothing to do).
530
		//
531
		//		If it is not defined, it will look for "A/B.js" in the script root
532
		//		directory.
533
		//
534
		//		It throws if it cannot find a file to load, or if the symbol A.B is
535
		//		not defined after loading.
536
		//
537
		//		It returns the object A.B.
538
		//
539
		//		This does nothing about importing symbols into the current package.
540
		//		It is presumed that the caller will take care of that. For example,
541
		//		to import all symbols:
542
		//
543
		//		|	with (dojo._loadModule("A.B")) {
544
		//		|		...
545
		//		|	}
546
		//
547
		//		And to import just the leaf symbol:
548
		//
549
		//		|	var B = dojo._loadModule("A.B");
550
		//	   	|	...
551
		//	returns: the required namespace object
552
		omitModuleCheck = this._global_omit_module_check || omitModuleCheck;
553
		var module = this._loadedModules[moduleName];
554
		if(module){
555
			return module;
556
		}
557
 
558
		// convert periods to slashes
559
		var relpath = this._getModuleSymbols(moduleName).join("/") + '.js';
560
 
561
		var modArg = (!omitModuleCheck) ? moduleName : null;
562
		var ok = this._loadPath(relpath, modArg);
563
 
564
		if((!ok)&&(!omitModuleCheck)){
565
			throw new Error("Could not load '" + moduleName + "'; last tried '" + relpath + "'");
566
		}
567
 
568
		// check that the symbol was defined
569
		// Don't bother if we're doing xdomain (asynchronous) loading.
570
		if((!omitModuleCheck)&&(!this["_isXDomain"])){
571
			// pass in false so we can give better error
572
			module = this._loadedModules[moduleName];
573
			if(!module){
574
				throw new Error("symbol '" + moduleName + "' is not defined after loading '" + relpath + "'");
575
			}
576
		}
577
 
578
		return module;
579
	}
580
 
581
	dojo.provide = function(/*String*/ resourceName){
582
		//	summary:
583
		//		Each javascript source file must have (exactly) one dojo.provide()
584
		//		call at the top of the file, corresponding to the file name.
585
		//		For example, js/dojo/foo.js must have dojo.provide("dojo.foo"); at the
586
		//		top of the file.
587
		//	description:
588
		//		Each javascript source file is called a resource.  When a resource
589
		//		is loaded by the browser, dojo.provide() registers that it has been
590
		//		loaded.
591
		//
592
		//		For backwards compatibility reasons, in addition to registering the
593
		//		resource, dojo.provide() also ensures that the javascript object
594
		//		for the module exists.  For example,
595
		//		dojo.provide("dojo.io.cometd"), in addition to registering that
596
		//		cometd.js is a resource for the dojo.iomodule, will ensure that
597
		//		the dojo.io javascript object exists, so that calls like
598
		//		dojo.io.foo = function(){ ... } don't fail.
599
		//
600
		//		In the case of a build (or in the future, a rollup), where multiple
601
		//		javascript source files are combined into one bigger file (similar
602
		//		to a .lib or .jar file), that file will contain multiple
603
		//		dojo.provide() calls, to note that it includes multiple resources.
604
 
605
		//Make sure we have a string.
606
		resourceName = resourceName + "";
607
		return (d._loadedModules[resourceName] = d.getObject(resourceName, true)); // Object
608
	}
609
 
610
	//Start of old bootstrap2:
611
 
612
	dojo.platformRequire = function(/*Object containing Arrays*/modMap){
613
		//	description:
614
		//		This method taks a "map" of arrays which one can use to optionally
615
		//		load dojo modules. The map is indexed by the possible
616
		//		dojo.name_ values, with two additional values: "default"
617
		//		and "common". The items in the "default" array will be loaded if
618
		//		none of the other items have been choosen based on the
619
		//		hostenv.name_ item. The items in the "common" array will _always_
620
		//		be loaded, regardless of which list is chosen.  Here's how it's
621
		//		normally called:
622
		//
623
		//		|	dojo.platformRequire({
624
		//		|		// an example that passes multiple args to _loadModule()
625
		//		|		browser: [
626
		//		|			["foo.bar.baz", true, true],
627
		//		|			"foo.sample",
628
		//		|			"foo.test,
629
		//		|		],
630
		//		|		default: [ "foo.sample.*" ],
631
		//		|		common: [ "really.important.module.*" ]
632
		//		|	});
633
 
634
		// FIXME: dojo.name_ no longer works!!
635
 
636
		var common = modMap["common"]||[];
637
		var result = common.concat(modMap[d._name]||modMap["default"]||[]);
638
 
639
		for(var x=0; x<result.length; x++){
640
			var curr = result[x];
641
			if(curr.constructor == Array){
642
				d._loadModule.apply(d, curr);
643
			}else{
644
				d._loadModule(curr);
645
			}
646
		}
647
	}
648
 
649
 
650
	dojo.requireIf = function(/*Boolean*/ condition, /*String*/ resourceName){
651
		// summary:
652
		//		If the condition is true then call dojo.require() for the specified
653
		//		resource
654
		if(condition === true){
655
			// FIXME: why do we support chained require()'s here? does the build system?
656
			var args = [];
657
			for(var i = 1; i < arguments.length; i++){
658
				args.push(arguments[i]);
659
			}
660
			d.require.apply(d, args);
661
		}
662
	}
663
 
664
	dojo.requireAfterIf = d.requireIf;
665
 
666
	dojo.registerModulePath = function(/*String*/module, /*String*/prefix){
667
		//	summary:
668
		//		maps a module name to a path
669
		//	description:
670
		//		An unregistered module is given the default path of ../<module>,
671
		//		relative to Dojo root. For example, module acme is mapped to
672
		//		../acme.  If you want to use a different module name, use
673
		//		dojo.registerModulePath.
674
		d._modulePrefixes[module] = { name: module, value: prefix };
675
	}
676
 
677
	dojo.requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String?*/availableFlatLocales){
678
		// summary:
679
		//		Declares translated resources and loads them if necessary, in the
680
		//		same style as dojo.require.  Contents of the resource bundle are
681
		//		typically strings, but may be any name/value pair, represented in
682
		//		JSON format.  See also dojo.i18n.getLocalization.
683
		// moduleName:
684
		//		name of the package containing the "nls" directory in which the
685
		//		bundle is found
686
		// bundleName:
687
		//		bundle name, i.e. the filename without the '.js' suffix
688
		// locale:
689
		//		the locale to load (optional)  By default, the browser's user
690
		//		locale as defined by dojo.locale
691
		// availableFlatLocales:
692
		//		A comma-separated list of the available, flattened locales for this
693
		//		bundle. This argument should only be set by the build process.
694
		// description:
695
		//		Load translated resource bundles provided underneath the "nls"
696
		//		directory within a package.  Translated resources may be located in
697
		//		different packages throughout the source tree.  For example, a
698
		//		particular widget may define one or more resource bundles,
699
		//		structured in a program as follows, where moduleName is
700
		//		mycode.mywidget and bundleNames available include bundleone and
701
		//		bundletwo:
702
		//
703
		//			...
704
		//			mycode/
705
		//			 mywidget/
706
		//			  nls/
707
		//			   bundleone.js (the fallback translation, English in this example)
708
		//			   bundletwo.js (also a fallback translation)
709
		//			   de/
710
		//			    bundleone.js
711
		//			    bundletwo.js
712
		//			   de-at/
713
		//			    bundleone.js
714
		//			   en/
715
		//			    (empty; use the fallback translation)
716
		//			   en-us/
717
		//			    bundleone.js
718
		//			   en-gb/
719
		//			    bundleone.js
720
		//			   es/
721
		//			    bundleone.js
722
		//			    bundletwo.js
723
		//			  ...etc
724
		//			...
725
		//
726
		//		Each directory is named for a locale as specified by RFC 3066,
727
		//		(http://www.ietf.org/rfc/rfc3066.txt), normalized in lowercase.
728
		//		Note that the two bundles in the example do not define all the same
729
		//		variants.  For a given locale, bundles will be loaded for that
730
		//		locale and all more general locales above it, including a fallback
731
		//		at the root directory.  For example, a declaration for the "de-at"
732
		//		locale will first load nls/de-at/bundleone.js, then
733
		//		nls/de/bundleone.js and finally nls/bundleone.js.  The data will be
734
		//		flattened into a single Object so that lookups will follow this
735
		//		cascading pattern.  An optional build step can preload the bundles
736
		//		to avoid data redundancy and the multiple network hits normally
737
		//		required to load these resources.
738
 
739
		d.require("dojo.i18n");
740
		d.i18n._requireLocalization.apply(d.hostenv, arguments);
741
	};
742
 
743
 
744
	var ore = new RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$");
745
	var ire = new RegExp("^((([^:]+:)?([^@]+))@)?([^:]*)(:([0-9]+))?$");
746
 
747
	dojo._Url = function(/*dojo._Url||String...*/){
748
		// summary:
749
		//		Constructor to create an object representing a URL.
750
		//		It is marked as private, since we might consider removing
751
		//		or simplifying it.
752
		// description:
753
		//		Each argument is evaluated in order relative to the next until
754
		//		a canonical uri is produced. To get an absolute Uri relative to
755
		//		the current document use:
756
		//      	new dojo._Url(document.baseURI, url)
757
 
758
		var n = null;
759
 
760
		// TODO: support for IPv6, see RFC 2732
761
		var _a = arguments;
762
		var uri = _a[0];
763
		// resolve uri components relative to each other
764
		for(var i = 1; i<_a.length; i++){
765
			if(!_a[i]){ continue; }
766
 
767
			// Safari doesn't support this.constructor so we have to be explicit
768
			// FIXME: Tracked (and fixed) in Webkit bug 3537.
769
			//		http://bugs.webkit.org/show_bug.cgi?id=3537
770
			var relobj = new d._Url(_a[i]+"");
771
			var uriobj = new d._Url(uri+"");
772
 
773
			if(
774
				(relobj.path=="")	&&
775
				(!relobj.scheme)	&&
776
				(!relobj.authority)	&&
777
				(!relobj.query)
778
			){
779
				if(relobj.fragment != n){
780
					uriobj.fragment = relobj.fragment;
781
				}
782
				relobj = uriobj;
783
			}else if(!relobj.scheme){
784
				relobj.scheme = uriobj.scheme;
785
 
786
				if(!relobj.authority){
787
					relobj.authority = uriobj.authority;
788
 
789
					if(relobj.path.charAt(0) != "/"){
790
						var path = uriobj.path.substring(0,
791
							uriobj.path.lastIndexOf("/") + 1) + relobj.path;
792
 
793
						var segs = path.split("/");
794
						for(var j = 0; j < segs.length; j++){
795
							if(segs[j] == "."){
796
								if(j == segs.length - 1){
797
									segs[j] = "";
798
								}else{
799
									segs.splice(j, 1);
800
									j--;
801
								}
802
							}else if(j > 0 && !(j == 1 && segs[0] == "") &&
803
								segs[j] == ".." && segs[j-1] != ".."){
804
 
805
								if(j == (segs.length - 1)){
806
									segs.splice(j, 1);
807
									segs[j - 1] = "";
808
								}else{
809
									segs.splice(j - 1, 2);
810
									j -= 2;
811
								}
812
							}
813
						}
814
						relobj.path = segs.join("/");
815
					}
816
				}
817
			}
818
 
819
			uri = "";
820
			if(relobj.scheme){
821
				uri += relobj.scheme + ":";
822
			}
823
			if(relobj.authority){
824
				uri += "//" + relobj.authority;
825
			}
826
			uri += relobj.path;
827
			if(relobj.query){
828
				uri += "?" + relobj.query;
829
			}
830
			if(relobj.fragment){
831
				uri += "#" + relobj.fragment;
832
			}
833
		}
834
 
835
		this.uri = uri.toString();
836
 
837
		// break the uri into its main components
838
		var r = this.uri.match(ore);
839
 
840
		this.scheme = r[2] || (r[1] ? "" : n);
841
		this.authority = r[4] || (r[3] ? "" : n);
842
		this.path = r[5]; // can never be undefined
843
		this.query = r[7] || (r[6] ? "" : n);
844
		this.fragment  = r[9] || (r[8] ? "" : n);
845
 
846
		if(this.authority != n){
847
			// server based naming authority
848
			r = this.authority.match(ire);
849
 
850
			this.user = r[3] || n;
851
			this.password = r[4] || n;
852
			this.host = r[5];
853
			this.port = r[7] || n;
854
		}
855
	}
856
 
857
	dojo._Url.prototype.toString = function(){ return this.uri; };
858
 
859
	dojo.moduleUrl = function(/*String*/module, /*dojo._Url||String*/url){
860
		// summary:
861
		//		Returns a Url object relative to a module
862
		//
863
		// example:
864
		//	|	dojo.moduleUrl("dojo.widget","templates/template.html");
865
		// example:
866
		//	|	dojo.moduleUrl("acme","images/small.png")
867
 
868
		var loc = dojo._getModuleSymbols(module).join('/');
869
		if(!loc){ return null; }
870
		if(loc.lastIndexOf("/") != loc.length-1){
871
			loc += "/";
872
		}
873
 
874
		//If the path is an absolute path (starts with a / or is on another
875
		//domain/xdomain) then don't add the baseUrl.
876
		var colonIndex = loc.indexOf(":");
877
		if(loc.charAt(0) != "/" && (colonIndex == -1 || colonIndex > loc.indexOf("/"))){
878
			loc = d.baseUrl + loc;
879
		}
880
 
881
		return new d._Url(loc, url); // String
882
	}
883
})();
884
 
885
if(typeof window != 'undefined'){
886
	dojo.isBrowser = true;
887
	dojo._name = "browser";
888
 
889
 
890
	// attempt to figure out the path to dojo if it isn't set in the config
891
	(function(){
892
		var d = dojo;
893
		// this is a scope protection closure. We set browser versions and grab
894
		// the URL we were loaded from here.
895
 
896
		// grab the node we were loaded from
897
		if(document && document.getElementsByTagName){
898
			var scripts = document.getElementsByTagName("script");
899
			var rePkg = /dojo(\.xd)?\.js([\?\.]|$)/i;
900
			for(var i = 0; i < scripts.length; i++){
901
				var src = scripts[i].getAttribute("src");
902
				if(!src){ continue; }
903
				var m = src.match(rePkg);
904
				if(m){
905
					// find out where we came from
906
					if(!djConfig["baseUrl"]){
907
						djConfig["baseUrl"] = src.substring(0, m.index);
908
					}
909
					// and find out if we need to modify our behavior
910
					var cfg = scripts[i].getAttribute("djConfig");
911
					if(cfg){
912
						var cfgo = eval("({ "+cfg+" })");
913
						for(var x in cfgo){
914
							djConfig[x] = cfgo[x];
915
						}
916
					}
917
					break; // "first Dojo wins"
918
				}
919
			}
920
		}
921
		d.baseUrl = djConfig["baseUrl"];
922
 
923
		// fill in the rendering support information in dojo.render.*
924
		var n = navigator;
925
		var dua = n.userAgent;
926
		var dav = n.appVersion;
927
		var tv = parseFloat(dav);
928
 
929
		d.isOpera = (dua.indexOf("Opera") >= 0) ? tv : 0;
930
		d.isKhtml = (dav.indexOf("Konqueror") >= 0)||(dav.indexOf("Safari") >= 0) ? tv : 0;
931
		if(dav.indexOf("Safari") >= 0){
932
			d.isSafari = parseFloat(dav.split("Version/")[1]) || 2;
933
		}
934
		var geckoPos = dua.indexOf("Gecko");
935
		d.isMozilla = d.isMoz = ((geckoPos >= 0)&&(!d.isKhtml)) ? tv : 0;
936
		d.isFF = 0;
937
		d.isIE = 0;
938
		try{
939
			if(d.isMoz){
940
				d.isFF = parseFloat(dua.split("Firefox/")[1].split(" ")[0]);
941
			}
942
			if((document.all)&&(!d.isOpera)){
943
				d.isIE = parseFloat(dav.split("MSIE ")[1].split(";")[0]);
944
			}
945
		}catch(e){}
946
 
947
		//Workaround to get local file loads of dojo to work on IE 7
948
		//by forcing to not use native xhr.
949
		if(dojo.isIE && (window.location.protocol === "file:")){
950
			djConfig.ieForceActiveXXhr=true;
951
		}
952
 
953
		var cm = document["compatMode"];
954
		d.isQuirks = (cm == "BackCompat")||(cm == "QuirksMode")||(d.isIE < 6);
955
 
956
		// TODO: is the HTML LANG attribute relevant?
957
		d.locale = djConfig.locale || (d.isIE ? n.userLanguage : n.language).toLowerCase();
958
 
959
		d._println = console.debug;
960
 
961
		// These are in order of decreasing likelihood; this will change in time.
962
		d._XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
963
 
964
		d._xhrObj= function(){
965
			// summary:
966
			//		does the work of portably generating a new XMLHTTPRequest
967
			//		object.
968
			var http = null;
969
			var last_e = null;
970
			if(!dojo.isIE || !djConfig.ieForceActiveXXhr){
971
				try{ http = new XMLHttpRequest(); }catch(e){}
972
			}
973
			if(!http){
974
				for(var i=0; i<3; ++i){
975
					var progid = dojo._XMLHTTP_PROGIDS[i];
976
					try{
977
						http = new ActiveXObject(progid);
978
					}catch(e){
979
						last_e = e;
980
					}
981
 
982
					if(http){
983
						dojo._XMLHTTP_PROGIDS = [progid];  // so faster next time
984
						break;
985
					}
986
				}
987
			}
988
 
989
			if(!http){
990
				throw new Error("XMLHTTP not available: "+last_e);
991
			}
992
 
993
			return http; // XMLHTTPRequest instance
994
		}
995
 
996
		d._isDocumentOk = function(http){
997
			var stat = http.status || 0;
998
			return ( (stat>=200)&&(stat<300))|| 	// Boolean
999
				(stat==304)|| 						// allow any 2XX response code
1000
				(stat==1223)|| 						// get it out of the cache
1001
				(!stat && (location.protocol=="file:" || location.protocol=="chrome:") ); // Internet Explorer mangled the status code
1002
		}
1003
 
1004
		//See if base tag is in use.
1005
		//This is to fix http://trac.dojotoolkit.org/ticket/3973,
1006
		//but really, we need to find out how to get rid of the dojo._Url reference
1007
		//below and still have DOH work with the dojo.i18n test following some other
1008
		//test that uses the test frame to load a document (trac #2757).
1009
		//Opera still has problems, but perhaps a larger issue of base tag support
1010
		//with XHR requests (hasBase is true, but the request is still made to document
1011
		//path, not base path).
1012
		var owloc = window.location+"";
1013
		var base = document.getElementsByTagName("base");
1014
		var hasBase = (base && base.length > 0);
1015
 
1016
		d._getText = function(/*URI*/ uri, /*Boolean*/ fail_ok){
1017
			// summary: Read the contents of the specified uri and return those contents.
1018
			// uri:
1019
			//		A relative or absolute uri. If absolute, it still must be in
1020
			//		the same "domain" as we are.
1021
			// fail_ok:
1022
			//		Default false. If fail_ok and loading fails, return null
1023
			//		instead of throwing.
1024
			// returns: The response text. null is returned when there is a
1025
			//		failure and failure is okay (an exception otherwise)
1026
 
1027
			// alert("_getText: " + uri);
1028
 
1029
			// NOTE: must be declared before scope switches ie. this._xhrObj()
1030
			var http = this._xhrObj();
1031
 
1032
			if(!hasBase && dojo._Url){
1033
				uri = (new dojo._Url(owloc, uri)).toString();
1034
			}
1035
			/*
1036
			console.debug("_getText:", uri);
1037
			console.debug(window.location+"");
1038
			alert(uri);
1039
			*/
1040
 
1041
			http.open('GET', uri, false);
1042
			try{
1043
				http.send(null);
1044
				// alert(http);
1045
				if(!d._isDocumentOk(http)){
1046
					var err = Error("Unable to load "+uri+" status:"+ http.status);
1047
					err.status = http.status;
1048
					err.responseText = http.responseText;
1049
					throw err;
1050
				}
1051
			}catch(e){
1052
				if(fail_ok){ return null; } // null
1053
				// rethrow the exception
1054
				throw e;
1055
			}
1056
			return http.responseText; // String
1057
		}
1058
	})();
1059
 
1060
	dojo._initFired = false;
1061
	//	BEGIN DOMContentLoaded, from Dean Edwards (http://dean.edwards.name/weblog/2006/06/again/)
1062
	dojo._loadInit = function(e){
1063
		dojo._initFired = true;
1064
		// allow multiple calls, only first one will take effect
1065
		// A bug in khtml calls events callbacks for document for event which isnt supported
1066
		// for example a created contextmenu event calls DOMContentLoaded, workaround
1067
		var type = (e && e.type) ? e.type.toLowerCase() : "load";
1068
		if(arguments.callee.initialized || (type!="domcontentloaded" && type!="load")){ return; }
1069
		arguments.callee.initialized = true;
1070
		if(typeof dojo["_khtmlTimer"] != 'undefined'){
1071
			clearInterval(dojo._khtmlTimer);
1072
			delete dojo._khtmlTimer;
1073
		}
1074
 
1075
		if(dojo._inFlightCount == 0){
1076
			dojo._modulesLoaded();
1077
		}
1078
	}
1079
 
1080
	//	START DOMContentLoaded
1081
	// Mozilla and Opera 9 expose the event we could use
1082
	if(document.addEventListener){
1083
		// NOTE:
1084
		//		due to a threading issue in Firefox 2.0, we can't enable
1085
		//		DOMContentLoaded on that platform. For more information, see:
1086
		//		http://trac.dojotoolkit.org/ticket/1704
1087
		if(dojo.isOpera|| (dojo.isMoz && (djConfig["enableMozDomContentLoaded"] === true))){
1088
			document.addEventListener("DOMContentLoaded", dojo._loadInit, null);
1089
		}
1090
 
1091
		//	mainly for Opera 8.5, won't be fired if DOMContentLoaded fired already.
1092
		//  also used for Mozilla because of trac #1640
1093
		window.addEventListener("load", dojo._loadInit, null);
1094
	}
1095
 
1096
	if(/(WebKit|khtml)/i.test(navigator.userAgent)){ // sniff
1097
		dojo._khtmlTimer = setInterval(function(){
1098
			if(/loaded|complete/.test(document.readyState)){
1099
				dojo._loadInit(); // call the onload handler
1100
			}
1101
		}, 10);
1102
	}
1103
	//	END DOMContentLoaded
1104
 
1105
	(function(){
1106
 
1107
		var _w = window;
1108
		var _handleNodeEvent = function(/*String*/evtName, /*Function*/fp){
1109
			// summary:
1110
			//		non-destructively adds the specified function to the node's
1111
			//		evtName handler.
1112
			// evtName: should be in the form "onclick" for "onclick" handlers.
1113
			// Make sure you pass in the "on" part.
1114
			var oldHandler = _w[evtName] || function(){};
1115
			_w[evtName] = function(){
1116
				fp.apply(_w, arguments);
1117
				oldHandler.apply(_w, arguments);
1118
			}
1119
		}
1120
 
1121
		if(dojo.isIE){
1122
			// 	for Internet Explorer. readyState will not be achieved on init
1123
			// 	call, but dojo doesn't need it however, we'll include it
1124
			// 	because we don't know if there are other functions added that
1125
			// 	might.  Note that this has changed because the build process
1126
			// 	strips all comments -- including conditional ones.
1127
 
1128
			document.write('<scr'+'ipt defer src="//:" '
1129
				+ 'onreadystatechange="if(this.readyState==\'complete\'){dojo._loadInit();}">'
1130
				+ '</scr'+'ipt>'
1131
			);
1132
 
1133
			// IE WebControl hosted in an application can fire "beforeunload" and "unload"
1134
			// events when control visibility changes, causing Dojo to unload too soon. The
1135
			// following code fixes the problem
1136
			// Reference: http://support.microsoft.com/default.aspx?scid=kb;en-us;199155
1137
			var _unloading = true;
1138
			_handleNodeEvent("onbeforeunload", function(){
1139
				_w.setTimeout(function(){ _unloading = false; }, 0);
1140
			});
1141
			_handleNodeEvent("onunload", function(){
1142
				if(_unloading){ dojo.unloaded(); }
1143
			});
1144
 
1145
			try{
1146
				document.namespaces.add("v","urn:schemas-microsoft-com:vml");
1147
				document.createStyleSheet().addRule("v\\:*", "behavior:url(#default#VML)");
1148
			}catch(e){}
1149
		}else{
1150
			// FIXME: dojo.unloaded requires dojo scope, so using anon function wrapper.
1151
			_handleNodeEvent("onbeforeunload", function() { dojo.unloaded(); });
1152
		}
1153
 
1154
	})();
1155
 
1156
	/*
1157
	OpenAjax.subscribe("OpenAjax", "onload", function(){
1158
		if(dojo._inFlightCount == 0){
1159
			dojo._modulesLoaded();
1160
		}
1161
	});
1162
 
1163
	OpenAjax.subscribe("OpenAjax", "onunload", function(){
1164
		dojo.unloaded();
1165
	});
1166
	*/
1167
} //if (typeof window != 'undefined')
1168
 
1169
//Load debug code if necessary.
1170
// dojo.requireIf((djConfig["isDebug"] || djConfig["debugAtAllCosts"]), "dojo.debug");
1171
 
1172
//window.widget is for Dashboard detection
1173
//The full conditionals are spelled out to avoid issues during builds.
1174
//Builds may be looking for require/requireIf statements and processing them.
1175
// dojo.requireIf(djConfig["debugAtAllCosts"] && !window.widget && !djConfig["useXDomain"], "dojo.browser_debug");
1176
// dojo.requireIf(djConfig["debugAtAllCosts"] && !window.widget && djConfig["useXDomain"], "dojo.browser_debug_xd");
1177
 
1178
if(djConfig.isDebug){
1179
		dojo.require("dojo._firebug.firebug");
1180
}
1181
 
1182
if(djConfig.debugAtAllCosts){
1183
	djConfig.useXDomain = true;
1184
	dojo.require("dojo._base._loader.loader_xd");
1185
	dojo.require("dojo._base._loader.loader_debug");
1186
	dojo.require("dojo.i18n");
1187
}
1188
 
1189
};
1190
 
1191
if(!dojo._hasResource["dojo._base.lang"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
1192
dojo._hasResource["dojo._base.lang"] = true;
1193
dojo.provide("dojo._base.lang");
1194
 
1195
// Crockford (ish) functions
1196
 
1197
dojo.isString = function(/*anything*/ it){
1198
	// summary:	Return true if it is a String
1199
	return typeof it == "string" || it instanceof String; // Boolean
1200
}
1201
 
1202
dojo.isArray = function(/*anything*/ it){
1203
	// summary: Return true if it is an Array
1204
	return it && it instanceof Array || typeof it == "array"; // Boolean
1205
}
1206
 
1207
/*=====
1208
dojo.isFunction = function(it){
1209
	// summary: Return true if it is a Function
1210
	// it: anything
1211
}
1212
=====*/
1213
 
1214
dojo.isFunction = (function(){
1215
	var _isFunction = function(/*anything*/ it){
1216
		return typeof it == "function" || it instanceof Function; // Boolean
1217
	};
1218
 
1219
	return dojo.isSafari ?
1220
		// only slow this down w/ gratuitious casting in Safari since it's what's b0rken
1221
		function(/*anything*/ it){
1222
			if(typeof it == "function" && it == "[object NodeList]"){ return false; }
1223
			return _isFunction(it); // Boolean
1224
		} : _isFunction;
1225
})();
1226
 
1227
dojo.isObject = function(/*anything*/ it){
1228
	// summary:
1229
	//		Returns true if it is a JavaScript object (or an Array, a Function or null)
1230
	return it !== undefined &&
1231
		(it === null || typeof it == "object" || dojo.isArray(it) || dojo.isFunction(it)); // Boolean
1232
}
1233
 
1234
dojo.isArrayLike = function(/*anything*/ it){
1235
	//	summary:
1236
	//		similar to dojo.isArray() but more permissive
1237
	//	description:
1238
	//		Doesn't strongly test for "arrayness".  Instead, settles for "isn't
1239
	//		a string or number and has a length property". Arguments objects
1240
	//		and DOM collections will return true when passed to
1241
	//		dojo.isArrayLike(), but will return false when passed to
1242
	//		dojo.isArray().
1243
	//	return:
1244
	//		If it walks like a duck and quicks like a duck, return true
1245
	var d = dojo;
1246
	return it && it !== undefined &&
1247
		// keep out built-in constructors (Number, String, ...) which have length
1248
		// properties
1249
		!d.isString(it) && !d.isFunction(it) &&
1250
		!(it.tagName && it.tagName.toLowerCase() == 'form') &&
1251
		(d.isArray(it) || isFinite(it.length)); // Boolean
1252
}
1253
 
1254
dojo.isAlien = function(/*anything*/ it){
1255
	// summary:
1256
	//		Returns true if it is a built-in function or some other kind of
1257
	//		oddball that *should* report as a function but doesn't
1258
	return it && !dojo.isFunction(it) && /\{\s*\[native code\]\s*\}/.test(String(it)); // Boolean
1259
}
1260
 
1261
dojo.extend = function(/*Object*/ constructor, /*Object...*/ props){
1262
	// summary:
1263
	//		Adds all properties and methods of props to constructor's
1264
	//		prototype, making them available to all instances created with
1265
	//		constructor.
1266
	for(var i=1, l=arguments.length; i<l; i++){
1267
		dojo._mixin(constructor.prototype, arguments[i]);
1268
	}
1269
	return constructor; // Object
1270
}
1271
 
1272
dojo._hitchArgs = function(scope, method /*,...*/){
1273
	var pre = dojo._toArray(arguments, 2);
1274
	var named = dojo.isString(method);
1275
	return function(){
1276
		// arrayify arguments
1277
		var args = dojo._toArray(arguments);
1278
		// locate our method
1279
		var f = named ? (scope||dojo.global)[method] : method;
1280
		// invoke with collected args
1281
		return f && f.apply(scope || this, pre.concat(args)); // mixed
1282
 	} // Function
1283
}
1284
 
1285
dojo.hitch = function(/*Object*/scope, /*Function|String*/method /*,...*/){
1286
	// summary:
1287
	//		Returns a function that will only ever execute in the a given scope.
1288
	//		This allows for easy use of object member functions
1289
	//		in callbacks and other places in which the "this" keyword may
1290
	//		otherwise not reference the expected scope.
1291
	//		Any number of default positional arguments may be passed as parameters
1292
	//		beyond "method".
1293
	//		Each of these values will be used to "placehold" (similar to curry)
1294
	//		for the hitched function.
1295
	// scope:
1296
	//		The scope to use when method executes. If method is a string,
1297
	//		scope is also the object containing method.
1298
	// method:
1299
	//		A function to be hitched to scope, or the name of the method in
1300
	//		scope to be hitched.
1301
	// example:
1302
	//	|	dojo.hitch(foo, "bar")();
1303
	//		runs foo.bar() in the scope of foo
1304
	// example:
1305
	//	|	dojo.hitch(foo, myFunction);
1306
	//		returns a function that runs myFunction in the scope of foo
1307
	if(arguments.length > 2){
1308
		return dojo._hitchArgs.apply(dojo, arguments); // Function
1309
	}
1310
	if(!method){
1311
		method = scope;
1312
		scope = null;
1313
	}
1314
	if(dojo.isString(method)){
1315
		scope = scope || dojo.global;
1316
		if(!scope[method]){ throw(['dojo.hitch: scope["', method, '"] is null (scope="', scope, '")'].join('')); }
1317
		return function(){ return scope[method].apply(scope, arguments || []); }; // Function
1318
	}
1319
	return !scope ? method : function(){ return method.apply(scope, arguments || []); }; // Function
1320
}
1321
 
1322
/*=====
1323
dojo.delegate = function(obj, props){
1324
	//	summary:
1325
	//		returns a new object which "looks" to obj for properties which it
1326
	//		does not have a value for. Optionally takes a bag of properties to
1327
	//		seed the returned object with initially.
1328
	//	description:
1329
	//		This is a small implementaton of the Boodman/Crockford delegation
1330
	//		pattern in JavaScript. An intermediate object constructor mediates
1331
	//		the prototype chain for the returned object, using it to delegate
1332
	//		down to obj for property lookup when object-local lookup fails.
1333
	//		This can be thought of similarly to ES4's "wrap", save that it does
1334
	//		not act on types but rather on pure objects.
1335
	//	obj:
1336
	//		The object to delegate to for properties not found directly on the
1337
	//		return object or in props.
1338
	//	props:
1339
	//		an object containing properties to assign to the returned object
1340
	//	returns:
1341
	//		an Object of anonymous type
1342
	//	example:
1343
	//	|	var foo = { bar: "baz" };
1344
	//	|	var thinger = dojo.delegate(foo, { thud: "xyzzy"});
1345
	//	|	thinger.bar == "baz"; // delegated to foo
1346
	//	|	foo.xyzzy == undefined; // by definition
1347
	//	|	thinger.xyzzy == "xyzzy"; // mixed in from props
1348
	//	|	foo.bar = "thonk";
1349
	//	|	thinger.bar == "thonk"; // still delegated to foo's bar
1350
}
1351
=====*/
1352
 
1353
 
1354
dojo.delegate = dojo._delegate = function(obj, props){
1355
 
1356
	// boodman/crockford delegation
1357
	function TMP(){};
1358
	TMP.prototype = obj;
1359
	var tmp = new TMP();
1360
	if(props){
1361
		dojo.mixin(tmp, props);
1362
	}
1363
	return tmp; // Object
1364
}
1365
 
1366
dojo.partial = function(/*Function|String*/method /*, ...*/){
1367
	// summary:
1368
	//		similar to hitch() except that the scope object is left to be
1369
	//		whatever the execution context eventually becomes.
1370
	//	description:
1371
	//		Calling dojo.partial is the functional equivalent of calling:
1372
	//		|	dojo.hitch(null, funcName, ...);
1373
	var arr = [ null ];
1374
	return dojo.hitch.apply(dojo, arr.concat(dojo._toArray(arguments))); // Function
1375
}
1376
 
1377
dojo._toArray = function(/*Object*/obj, /*Number?*/offset, /*Array?*/ startWith){
1378
	// summary:
1379
	//		Converts an array-like object (i.e. arguments, DOMCollection)
1380
	//		to an array. Returns a new Array object.
1381
	// obj:
1382
	//		the object to "arrayify". We expect the object to have, at a
1383
	//		minimum, a length property which corresponds to integer-indexed
1384
	//		properties.
1385
	// offset:
1386
	//		the location in obj to start iterating from. Defaults to 0. Optional.
1387
	// startWith:
1388
	//		An array to pack with the properties of obj. If provided,
1389
	//		properties in obj are appended at the end of startWith and
1390
	//		startWith is the returned array.
1391
	var arr = startWith||[];
1392
	for(var x = offset || 0; x < obj.length; x++){
1393
		arr.push(obj[x]);
1394
	}
1395
	return arr; // Array
1396
}
1397
 
1398
dojo.clone = function(/*anything*/ o){
1399
	// summary:
1400
	//		Clones objects (including DOM nodes) and all children.
1401
	//		Warning: do not clone cyclic structures.
1402
	if(!o){ return o; }
1403
	if(dojo.isArray(o)){
1404
		var r = [];
1405
		for(var i = 0; i < o.length; ++i){
1406
			r.push(dojo.clone(o[i]));
1407
		}
1408
		return r; // Array
1409
	}
1410
	if(!dojo.isObject(o)){
1411
		return o;	/*anything*/
1412
	}
1413
	if(o.nodeType && o.cloneNode){ // isNode
1414
		return o.cloneNode(true); // Node
1415
	}
1416
	if(o instanceof Date){
1417
		return new Date(o.getTime());	// Date
1418
	}
1419
	// Generic objects
1420
	var r = new o.constructor(); // specific to dojo.declare()'d classes!
1421
	for(var i in o){
1422
		if(!(i in r) || r[i] != o[i]){
1423
			r[i] = dojo.clone(o[i]);
1424
		}
1425
	}
1426
	return r; // Object
1427
}
1428
 
1429
dojo.trim = function(/*String*/ str){
1430
	// summary:
1431
	//		trims whitespaces from both sides of the string
1432
	// description:
1433
	//		This version of trim() was selected for inclusion into the base due
1434
	//		to its compact size and relatively good performance (see Steven
1435
	//		Levithan's blog:
1436
	//		http://blog.stevenlevithan.com/archives/faster-trim-javascript).
1437
	//		The fastest but longest version of this function is located at
1438
	//		dojo.string.trim()
1439
	return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');	// String
1440
}
1441
 
1442
}
1443
 
1444
if(!dojo._hasResource["dojo._base.declare"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
1445
dojo._hasResource["dojo._base.declare"] = true;
1446
dojo.provide("dojo._base.declare");
1447
 
1448
 
1449
// this file courtesy of the TurboAjax group, licensed under a Dojo CLA
1450
 
1451
dojo.declare = function(/*String*/ className, /*Function|Function[]*/ superclass, /*Object*/ props){
1452
	//	summary:
1453
	//		Create a feature-rich constructor from compact notation
1454
	//	className:
1455
	//		The name of the constructor (loosely, a "class")
1456
	//		stored in the "declaredClass" property in the created prototype
1457
	//	superclass:
1458
	//		May be null, a Function, or an Array of Functions. If an array,
1459
	//		the first element is used as the prototypical ancestor and
1460
	//		any following Functions become mixin ancestors.
1461
	//	props:
1462
	//		An object whose properties are copied to the
1463
	//		created prototype.
1464
	//		Add an instance-initialization function by making it a property
1465
	//		named "constructor".
1466
	//	description:
1467
	//		Create a constructor using a compact notation for inheritance and
1468
	//		prototype extension.
1469
	//
1470
	//		All superclasses (including mixins) must be Functions (not simple Objects).
1471
	//
1472
	//		Mixin ancestors provide a type of multiple inheritance. Prototypes of mixin
1473
	//		ancestors are copied to the new class: changes to mixin prototypes will
1474
	//		not affect classes to which they have been mixed in.
1475
	//
1476
	//		"className" is cached in "declaredClass" property of the new class.
1477
	//
1478
	//	example:
1479
	//	|	dojo.declare("my.classes.bar", my.classes.foo, {
1480
	//	|		// properties to be added to the class prototype
1481
	//	|		someValue: 2,
1482
	//	|		// initialization function
1483
	//	|		constructor: function(){
1484
	//	|			this.myComplicatedObject = new ReallyComplicatedObject();
1485
	//	|		},
1486
	//	|		// other functions
1487
	//	|		someMethod: function(){
1488
	//	|			doStuff();
1489
	//	|		}
1490
	//	|	);
1491
 
1492
	// argument juggling (deprecated)
1493
	if(dojo.isFunction(props)||(arguments.length>3)){
1494
		dojo.deprecated("dojo.declare: for class '" + className + "' pass initializer function as 'constructor' property instead of as a separate argument.", "", "1.0");
1495
		var c = props;
1496
		props = arguments[3] || {};
1497
		props.constructor = c;
1498
	}
1499
	// process superclass argument
1500
	// var dd=dojo.declare, mixins=null;
1501
	var dd=arguments.callee, mixins=null;
1502
	if(dojo.isArray(superclass)){
1503
		mixins = superclass;
1504
		superclass = mixins.shift();
1505
	}
1506
	// construct intermediate classes for mixins
1507
	if(mixins){
1508
		for(var i=0, m; i<mixins.length; i++){
1509
			m = mixins[i];
1510
			if(!m){throw("Mixin #" + i + " to declaration of " + className + " is null. It's likely a required module is not loaded.")};
1511
			superclass = dd._delegate(superclass, m);
1512
		}
1513
	}
1514
	// prepare values
1515
	var init=(props||0).constructor, ctor=dd._delegate(superclass), fn;
1516
	// name methods (experimental)
1517
	for(var i in props){if(dojo.isFunction(fn=props[i])&&(!0[i])){fn.nom=i;}}
1518
	// decorate prototype
1519
	dojo.extend(ctor, {declaredClass: className, _constructor: init, preamble: null}, props||0);
1520
	// special help for IE
1521
	ctor.prototype.constructor = ctor;
1522
	// create named reference
1523
	return dojo.setObject(className, ctor); // Function
1524
}
1525
 
1526
dojo.mixin(dojo.declare, {
1527
	_delegate: function(base, mixin){
1528
		var bp = (base||0).prototype, mp = (mixin||0).prototype;
1529
		// fresh constructor, fresh prototype
1530
		var ctor = dojo.declare._makeCtor();
1531
		// cache ancestry
1532
		dojo.mixin(ctor, {superclass: bp, mixin: mp, extend: dojo.declare._extend});
1533
		// chain prototypes
1534
		if(base){ctor.prototype = dojo._delegate(bp);}
1535
		// add mixin and core
1536
		dojo.extend(ctor, dojo.declare._core, mp||0, {_constructor: null, preamble: null});
1537
		// special help for IE
1538
		ctor.prototype.constructor = ctor;
1539
		// name this class for debugging
1540
		ctor.prototype.declaredClass = (bp||0).declaredClass + '_' + (mp||0).declaredClass;
1541
		return ctor;
1542
	},
1543
	_extend: function(props){
1544
		for(var i in props){if(dojo.isFunction(fn=props[i])&&(!0[i])){fn.nom=i;}}
1545
		dojo.extend(this, props);
1546
	},
1547
	_makeCtor: function(){
1548
		// we have to make a function, but don't want to close over anything
1549
		return function(){ this._construct(arguments); }
1550
	},
1551
	_core: {
1552
		_construct: function(args){
1553
			var c=args.callee, s=c.superclass, ct=s&&s.constructor, m=c.mixin, mct=m&&m.constructor, a=args, ii, fn;
1554
			// side-effect of = used on purpose here, lint may complain, don't try this at home
1555
			if(a[0]){
1556
				// FIXME: preambles for each mixin should be allowed
1557
				// FIXME:
1558
				//		should we allow the preamble here NOT to modify the
1559
				//		default args, but instead to act on each mixin
1560
				//		independently of the class instance being constructed
1561
				//		(for impdedence matching)?
1562
 
1563
				// allow any first argument w/ a "preamble" property to act as a
1564
				// class preamble (not exclusive of the prototype preamble)
1565
				if(/*dojo.isFunction*/(fn = a[0]["preamble"])){
1566
					a = fn.apply(this, a) || a;
1567
				}
1568
			}
1569
			// prototype preamble
1570
			if(fn=c.prototype.preamble){a = fn.apply(this, a) || a;}
1571
			// FIXME:
1572
			//		need to provide an optional prototype-settable
1573
			//		"_explicitSuper" property which disables this
1574
			// initialize superclass
1575
			if(ct&&ct.apply){ct.apply(this, a);}
1576
			// initialize mixin
1577
			if(mct&&mct.apply){mct.apply(this, a);}
1578
			// initialize self
1579
			if(ii=c.prototype._constructor){ii.apply(this, args);}
1580
			// post construction
1581
			if(this.constructor.prototype==c.prototype && (ct=this.postscript)){ct.apply(this, args)};
1582
		},
1583
		_findMixin: function(mixin){
1584
			var c = this.constructor, p, m;
1585
			while(c){
1586
				p = c.superclass;
1587
				m = c.mixin;
1588
				if(m==mixin || (m instanceof mixin.constructor)){return p;}
1589
				if(m && (m=m._findMixin(mixin))){return m;}
1590
				c = p && p.constructor;
1591
			}
1592
		},
1593
		_findMethod: function(name, method, ptype, has){
1594
			// consciously trading readability for bytes and speed in this low-level method
1595
			var p=ptype, c, m, f;
1596
			do{
1597
				c = p.constructor;
1598
				m = c.mixin;
1599
				// find method by name in our mixin ancestor
1600
				if(m && (m=this._findMethod(name, method, m, has))){return m};
1601
				// if we found a named method that either exactly-is or exactly-is-not 'method'
1602
				if((f=p[name])&&(has==(f==method))){return p};
1603
				// ascend chain
1604
				p = c.superclass;
1605
			}while(p);
1606
			// if we couldn't find an ancestor in our primary chain, try a mixin chain
1607
			return !has && (p=this._findMixin(ptype)) && this._findMethod(name, method, p, has);
1608
		},
1609
		inherited: function(name, args, newArgs){
1610
			// optionalize name argument (experimental)
1611
			var a = arguments;
1612
			if(!dojo.isString(a[0])){newArgs=args; args=name; name=args.callee.nom;}
1613
			var c=args.callee, p=this.constructor.prototype, a=newArgs||args, fn, mp;
1614
			// if not an instance override
1615
			if(this[name]!=c || p[name]==c){
1616
				mp = this._findMethod(name, c, p, true);
1617
				if(!mp){throw(this.declaredClass + ': name argument ("' + name + '") to inherited must match callee (declare.js)');}
1618
				p = this._findMethod(name, c, mp, false);
1619
			}
1620
			fn = p && p[name];
1621
			// FIXME: perhaps we should throw here?
1622
			if(!fn){console.debug(mp.declaredClass + ': no inherited "' + name + '" was found (declare.js)'); return;}
1623
			// if the function exists, invoke it in our scope
1624
			return fn.apply(this, a);
1625
		}
1626
	}
1627
});
1628
 
1629
}
1630
 
1631
if(!dojo._hasResource["dojo._base.connect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
1632
dojo._hasResource["dojo._base.connect"] = true;
1633
dojo.provide("dojo._base.connect");
1634
 
1635
 
1636
// this file courtesy of the TurboAjax Group, licensed under a Dojo CLA
1637
 
1638
// low-level delegation machinery
1639
dojo._listener = {
1640
	// create a dispatcher function
1641
	getDispatcher: function(){
1642
		// following comments pulled out-of-line to prevent cloning them
1643
		// in the returned function.
1644
		// - indices (i) that are really in the array of listeners (ls) will
1645
		//   not be in Array.prototype. This is the 'sparse array' trick
1646
		//   that keeps us safe from libs that take liberties with built-in
1647
		//   objects
1648
		// - listener is invoked with current scope (this)
1649
		return function(){
1650
			var ap=Array.prototype, c=arguments.callee, ls=c._listeners, t=c.target;
1651
			// return value comes from original target function
1652
			var r=t && t.apply(this, arguments);
1653
			// invoke listeners after target function
1654
			for(var i in ls){
1655
				if(!(i in ap)){
1656
					ls[i].apply(this, arguments);
1657
				}
1658
			}
1659
			// return value comes from original target function
1660
			return r;
1661
		}
1662
	},
1663
	// add a listener to an object
1664
	add: function(/*Object*/ source, /*String*/ method, /*Function*/ listener){
1665
		// Whenever 'method' is invoked, 'listener' will have the same scope.
1666
		// Trying to supporting a context object for the listener led to
1667
		// complexity.
1668
		// Non trivial to provide 'once' functionality here
1669
		// because listener could be the result of a dojo.hitch call,
1670
		// in which case two references to the same hitch target would not
1671
		// be equivalent.
1672
		source = source || dojo.global;
1673
		// The source method is either null, a dispatcher, or some other function
1674
		var f = source[method];
1675
		// Ensure a dispatcher
1676
		if(!f||!f._listeners){
1677
			var d = dojo._listener.getDispatcher();
1678
			// original target function is special
1679
			d.target = f;
1680
			// dispatcher holds a list of listeners
1681
			d._listeners = [];
1682
			// redirect source to dispatcher
1683
			f = source[method] = d;
1684
		}
1685
		// The contract is that a handle is returned that can
1686
		// identify this listener for disconnect.
1687
		//
1688
		// The type of the handle is private. Here is it implemented as Integer.
1689
		// DOM event code has this same contract but handle is Function
1690
		// in non-IE browsers.
1691
		//
1692
		// We could have separate lists of before and after listeners.
1693
		return f._listeners.push(listener) ; /*Handle*/
1694
	},
1695
	// remove a listener from an object
1696
	remove: function(/*Object*/ source, /*String*/ method, /*Handle*/ handle){
1697
		var f = (source||dojo.global)[method];
1698
		// remember that handle is the index+1 (0 is not a valid handle)
1699
		if(f && f._listeners && handle--){
1700
			delete f._listeners[handle];
1701
		}
1702
	}
1703
};
1704
 
1705
// Multiple delegation for arbitrary methods.
1706
 
1707
// This unit knows nothing about DOM,
1708
// but we include DOM aware
1709
// documentation and dontFix
1710
// argument here to help the autodocs.
1711
// Actual DOM aware code is in event.js.
1712
 
1713
dojo.connect = function(/*Object|null*/ obj,
1714
						/*String*/ event,
1715
						/*Object|null*/ context,
1716
						/*String|Function*/ method,
1717
						/*Boolean*/ dontFix){
1718
	// summary:
1719
	//		Create a link that calls one function when another executes.
1720
	//
1721
	// description:
1722
	//		Connects method to event, so that after event fires, method
1723
	//		does too. All connected functions are passed the same arguments as
1724
	//		the event function was initially called with. You may connect as
1725
	//		many methods to event as needed.
1726
	//
1727
	//		event must be a string. If obj is null, dojo.global is used.
1728
	//
1729
	//		null arguments may simply be omitted.
1730
	//
1731
	//		obj[event] can resolve to a function or undefined (null).
1732
	//		If obj[event] is null, it is assigned a function.
1733
	//
1734
	//		The return value is a handle that is needed to
1735
	//		remove this connection with dojo.disconnect.
1736
	//
1737
	// obj:
1738
	//		The source object for the event function.
1739
	//		Defaults to dojo.global if null.
1740
	//		If obj is a DOM node, the connection is delegated
1741
	//		to the DOM event manager (unless dontFix is true).
1742
	//
1743
	// event:
1744
	//		String name of the event function in obj.
1745
	//		I.e. identifies a property obj[event].
1746
	//
1747
	// context:
1748
	//		The object that method will receive as "this".
1749
	//
1750
	//		If context is null and method is a function, then method
1751
	//		inherits the context of event.
1752
	//
1753
	//		If method is a string then context must be the source
1754
	//		object object for method (context[method]). If context is null,
1755
	//		dojo.global is used.
1756
	//
1757
	// method:
1758
	//		A function reference, or name of a function in context.
1759
	//		The function identified by method fires after event does.
1760
	//		method receives the same arguments as the event.
1761
	//		See context argument comments for information on method's scope.
1762
	//
1763
	// dontFix:
1764
	//		If obj is a DOM node, set dontFix to true to prevent delegation
1765
	//		of this connection to the DOM event manager.
1766
	//
1767
	// example:
1768
	//		When obj.onchange(), do ui.update():
1769
	//	|	dojo.connect(obj, "onchange", ui, "update");
1770
	//	|	dojo.connect(obj, "onchange", ui, ui.update); // same
1771
	//
1772
	// example:
1773
	//		Using return value for disconnect:
1774
	//	|	var link = dojo.connect(obj, "onchange", ui, "update");
1775
	//	|	...
1776
	//	|	dojo.disconnect(link);
1777
	//
1778
	// example:
1779
	//		When onglobalevent executes, watcher.handler is invoked:
1780
	//	|	dojo.connect(null, "onglobalevent", watcher, "handler");
1781
	//
1782
	// example:
1783
	//		When ob.onCustomEvent executes, customEventHandler is invoked:
1784
	//	|	dojo.connect(ob, "onCustomEvent", null, "customEventHandler");
1785
	//	|	dojo.connect(ob, "onCustomEvent", "customEventHandler"); // same
1786
	//
1787
	// example:
1788
	//		When ob.onCustomEvent executes, customEventHandler is invoked
1789
	//		with the same scope (this):
1790
	//	|	dojo.connect(ob, "onCustomEvent", null, customEventHandler);
1791
	//	|	dojo.connect(ob, "onCustomEvent", customEventHandler); // same
1792
	//
1793
	// example:
1794
	//		When globalEvent executes, globalHandler is invoked
1795
	//		with the same scope (this):
1796
	//	|	dojo.connect(null, "globalEvent", null, globalHandler);
1797
	//	|	dojo.connect("globalEvent", globalHandler); // same
1798
 
1799
	// normalize arguments
1800
	var a=arguments, args=[], i=0;
1801
	// if a[0] is a String, obj was ommited
1802
	args.push(dojo.isString(a[0]) ? null : a[i++], a[i++]);
1803
	// if the arg-after-next is a String or Function, context was NOT omitted
1804
	var a1 = a[i+1];
1805
	args.push(dojo.isString(a1)||dojo.isFunction(a1) ? a[i++] : null, a[i++]);
1806
	// absorb any additional arguments
1807
	for(var l=a.length; i<l; i++){	args.push(a[i]); }
1808
	// do the actual work
1809
	return dojo._connect.apply(this, args); /*Handle*/
1810
}
1811
 
1812
// used by non-browser hostenvs. always overriden by event.js
1813
dojo._connect = function(obj, event, context, method){
1814
	var l=dojo._listener, h=l.add(obj, event, dojo.hitch(context, method));
1815
	return [obj, event, h, l]; // Handle
1816
}
1817
 
1818
dojo.disconnect = function(/*Handle*/ handle){
1819
	// summary:
1820
	//		Remove a link created by dojo.connect.
1821
	// description:
1822
	//		Removes the connection between event and the method referenced by handle.
1823
	// handle:
1824
	//		the return value of the dojo.connect call that created the connection.
1825
	if(handle && handle[0] !== undefined){
1826
		dojo._disconnect.apply(this, handle);
1827
		// let's not keep this reference
1828
		delete handle[0];
1829
	}
1830
}
1831
 
1832
dojo._disconnect = function(obj, event, handle, listener){
1833
	listener.remove(obj, event, handle);
1834
}
1835
 
1836
// topic publish/subscribe
1837
 
1838
dojo._topics = {};
1839
 
1840
dojo.subscribe = function(/*String*/ topic, /*Object|null*/ context, /*String|Function*/ method){
1841
	//	summary:
1842
	//		Attach a listener to a named topic. The listener function is invoked whenever the
1843
	//		named topic is published (see: dojo.publish).
1844
	//		Returns a handle which is needed to unsubscribe this listener.
1845
	//	context:
1846
	//		Scope in which method will be invoked, or null for default scope.
1847
	//	method:
1848
	//		The name of a function in context, or a function reference. This is the function that
1849
	//		is invoked when topic is published.
1850
	//	example:
1851
	//	|	dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); };
1852
	//	|	dojo.publish("alerts", [ "read this", "hello world" ]);
1853
 
1854
	// support for 2 argument invocation (omitting context) depends on hitch
1855
	return [topic, dojo._listener.add(dojo._topics, topic, dojo.hitch(context, method))]; /*Handle*/
1856
}
1857
 
1858
dojo.unsubscribe = function(/*Handle*/ handle){
1859
	//	summary:
1860
	//	 	Remove a topic listener.
1861
	//	handle:
1862
	//	 	The handle returned from a call to subscribe.
1863
	//	example:
1864
	//	|	var alerter = dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); };
1865
	//	|	...
1866
	//	|	dojo.unsubscribe(alerter);
1867
	if(handle){
1868
		dojo._listener.remove(dojo._topics, handle[0], handle[1]);
1869
	}
1870
}
1871
 
1872
dojo.publish = function(/*String*/ topic, /*Array*/ args){
1873
	//	summary:
1874
	//	 	Invoke all listener method subscribed to topic.
1875
	//	topic:
1876
	//	 	The name of the topic to publish.
1877
	//	args:
1878
	//	 	An array of arguments. The arguments will be applied
1879
	//	 	to each topic subscriber (as first class parameters, via apply).
1880
	//	example:
1881
	//	|	dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); };
1882
	//	|	dojo.publish("alerts", [ "read this", "hello world" ]);
1883
 
1884
	// Note that args is an array, which is more efficient vs variable length
1885
	// argument list.  Ideally, var args would be implemented via Array
1886
	// throughout the APIs.
1887
	var f = dojo._topics[topic];
1888
	if(f){
1889
		f.apply(this, args||[]);
1890
	}
1891
}
1892
 
1893
dojo.connectPublisher = function(	/*String*/ topic,
1894
									/*Object|null*/ obj,
1895
									/*String*/ event){
1896
	//	summary:
1897
	//	 	Ensure that everytime obj.event() is called, a message is published
1898
	//	 	on the topic. Returns a handle which can be passed to
1899
	//	 	dojo.disconnect() to disable subsequent automatic publication on
1900
	//	 	the topic.
1901
	//	topic:
1902
	//	 	The name of the topic to publish.
1903
	//	obj:
1904
	//	 	The source object for the event function. Defaults to dojo.global
1905
	//	 	if null.
1906
	//	event:
1907
	//	 	The name of the event function in obj.
1908
	//	 	I.e. identifies a property obj[event].
1909
	//	example:
1910
	//	|	dojo.connectPublisher("/ajax/start", dojo, "xhrGet"};
1911
	var pf = function(){ dojo.publish(topic, arguments); }
1912
	return (event) ? dojo.connect(obj, event, pf) : dojo.connect(obj, pf); //Handle
1913
};
1914
 
1915
}
1916
 
1917
if(!dojo._hasResource["dojo._base.Deferred"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
1918
dojo._hasResource["dojo._base.Deferred"] = true;
1919
dojo.provide("dojo._base.Deferred");
1920
 
1921
 
1922
dojo.Deferred = function(/*Function?*/ canceller){
1923
	// summary:
1924
	//		Encapsulates a sequence of callbacks in response to a value that
1925
	//		may not yet be available.  This is modeled after the Deferred class
1926
	//		from Twisted <http://twistedmatrix.com>.
1927
	// description:
1928
	//		JavaScript has no threads, and even if it did, threads are hard.
1929
	//		Deferreds are a way of abstracting non-blocking events, such as the
1930
	//		final response to an XMLHttpRequest. Deferreds create a promise to
1931
	//		return a response a some point in the future and an easy way to
1932
	//		register your interest in receiving that response.
1933
	//
1934
	//		The most important methods for Deffered users are:
1935
	//
1936
	//			* addCallback(handler)
1937
	//			* addErrback(handler)
1938
	//			* callback(result)
1939
	//			* errback(result)
1940
	//
1941
	//		In general, when a function returns a Deferred, users then "fill
1942
	//		in" the second half of the contract by registering callbacks and
1943
	//		error handlers. You may register as many callback and errback
1944
	//		handlers as you like and they will be executed in the order
1945
	//		registered when a result is provided. Usually this result is
1946
	//		provided as the result of an asynchronous operation. The code
1947
	//		"managing" the Deferred (the code that made the promise to provide
1948
	//		an answer later) will use the callback() and errback() methods to
1949
	//		communicate with registered listeners about the result of the
1950
	//		operation. At this time, all registered result handlers are called
1951
	//		*with the most recent result value*.
1952
	//
1953
	//		Deferred callback handlers are treated as a chain, and each item in
1954
	//		the chain is required to return a value that will be fed into
1955
	//		successive handlers. The most minimal callback may be registered
1956
	//		like this:
1957
	//
1958
	//		|	var d = new dojo.Deferred();
1959
	//		|	d.addCallback(function(result){ return result; });
1960
	//
1961
	//		Perhaps the most common mistake when first using Deferreds is to
1962
	//		forget to return a value (in most cases, the value you were
1963
	//		passed).
1964
	//
1965
	//		The sequence of callbacks is internally represented as a list of
1966
	//		2-tuples containing the callback/errback pair.  For example, the
1967
	//		following call sequence:
1968
	//
1969
	//		|	var d = new dojo.Deferred();
1970
	//		|	d.addCallback(myCallback);
1971
	//		|	d.addErrback(myErrback);
1972
	//		|	d.addBoth(myBoth);
1973
	//		|	d.addCallbacks(myCallback, myErrback);
1974
	//
1975
	//		is translated into a Deferred with the following internal
1976
	//		representation:
1977
	//
1978
	//		|	[
1979
	//		|		[myCallback, null],
1980
	//		|		[null, myErrback],
1981
	//		|		[myBoth, myBoth],
1982
	//		|		[myCallback, myErrback]
1983
	//		|	]
1984
	//
1985
	//		The Deferred also keeps track of its current status (fired).  Its
1986
	//		status may be one of three things:
1987
	//
1988
	//			* -1: no value yet (initial condition)
1989
	//			* 0: success
1990
	//			* 1: error
1991
	//
1992
	//		A Deferred will be in the error state if one of the following three
1993
	//		conditions are met:
1994
	//
1995
	//			1. The result given to callback or errback is "instanceof" Error
1996
	//			2. The previous callback or errback raised an exception while
1997
	//			   executing
1998
	//			3. The previous callback or errback returned a value
1999
	//			   "instanceof" Error
2000
	//
2001
	//		Otherwise, the Deferred will be in the success state. The state of
2002
	//		the Deferred determines the next element in the callback sequence
2003
	//		to run.
2004
	//
2005
	//		When a callback or errback occurs with the example deferred chain,
2006
	//		something equivalent to the following will happen (imagine
2007
	//		that exceptions are caught and returned):
2008
	//
2009
	//		|	// d.callback(result) or d.errback(result)
2010
	//		|	if(!(result instanceof Error)){
2011
	//		|		result = myCallback(result);
2012
	//		|	}
2013
	//		|	if(result instanceof Error){
2014
	//		|		result = myErrback(result);
2015
	//		|	}
2016
	//		|	result = myBoth(result);
2017
	//		|	if(result instanceof Error){
2018
	//		|		result = myErrback(result);
2019
	//		|	}else{
2020
	//		|		result = myCallback(result);
2021
	//		|	}
2022
	//
2023
	//		The result is then stored away in case another step is added to the
2024
	//		callback sequence.	Since the Deferred already has a value
2025
	//		available, any new callbacks added will be called immediately.
2026
	//
2027
	//		There are two other "advanced" details about this implementation
2028
	//		that are useful:
2029
	//
2030
	//		Callbacks are allowed to return Deferred instances themselves, so
2031
	//		you can build complicated sequences of events with ease.
2032
	//
2033
	//		The creator of the Deferred may specify a canceller.  The canceller
2034
	//		is a function that will be called if Deferred.cancel is called
2035
	//		before the Deferred fires. You can use this to implement clean
2036
	//		aborting of an XMLHttpRequest, etc. Note that cancel will fire the
2037
	//		deferred with a CancelledError (unless your canceller returns
2038
	//		another kind of error), so the errbacks should be prepared to
2039
	//		handle that error for cancellable Deferreds.
2040
	// example:
2041
	//	|	var deferred = new dojo.Deferred();
2042
	//	|	setTimeout(function(){ deferred.callback({success: true}); }, 1000);
2043
	//	|	return deferred;
2044
	// example:
2045
	//		Deferred objects are often used when making code asynchronous. It
2046
	//		may be easiest to write functions in a synchronous manner and then
2047
	//		split code using a deferred to trigger a response to a long-lived
2048
	//		operation. For example, instead of register a callback function to
2049
	//		denote when a rendering operation completes, the function can
2050
	//		simply return a deferred:
2051
	//
2052
	//		|	// callback style:
2053
	//		|	function renderLotsOfData(data, callback){
2054
	//		|		var success = false
2055
	//		|		try{
2056
	//		|			for(var x in data){
2057
	//		|				renderDataitem(data[x]);
2058
	//		|			}
2059
	//		|			success = true;
2060
	//		|		}catch(e){ }
2061
	//		|		if(callback){
2062
	//		|			callback(success);
2063
	//		|		}
2064
	//		|	}
2065
	//
2066
	//		|	// using callback style
2067
	//		|	renderLotsOfData(someDataObj, function(success){
2068
	//		|		// handles success or failure
2069
	//		|		if(!success){
2070
	//		|			promptUserToRecover();
2071
	//		|		}
2072
	//		|	});
2073
	//		|	// NOTE: no way to add another callback here!!
2074
	// example:
2075
	//		Using a Deferred doesn't simplify the sending code any, but it
2076
	//		provides a standard interface for callers and senders alike,
2077
	//		providing both with a simple way to service multiple callbacks for
2078
	//		an operation and freeing both sides from worrying about details
2079
	//		such as "did this get called already?". With Deferreds, new
2080
	//		callbacks can be added at any time.
2081
	//
2082
	//		|	// Deferred style:
2083
	//		|	function renderLotsOfData(data){
2084
	//		|		var d = new dojo.Deferred();
2085
	//		|		try{
2086
	//		|			for(var x in data){
2087
	//		|				renderDataitem(data[x]);
2088
	//		|			}
2089
	//		|			d.callback(true);
2090
	//		|		}catch(e){
2091
	//		|			d.errback(new Error("rendering failed"));
2092
	//		|		}
2093
	//		|		return d;
2094
	//		|	}
2095
	//
2096
	//		|	// using Deferred style
2097
	//		|	renderLotsOfData(someDataObj).addErrback(function(){
2098
	//		|		promptUserToRecover();
2099
	//		|	});
2100
	//		|	// NOTE: addErrback and addCallback both return the Deferred
2101
	//		|	// again, so we could chain adding callbacks or save the
2102
	//		|	// deferred for later should we need to be notified again.
2103
	// example:
2104
	//		In this example, renderLotsOfData is syncrhonous and so both
2105
	//		versions are pretty artificial. Putting the data display on a
2106
	//		timeout helps show why Deferreds rock:
2107
	//
2108
	//		|	// Deferred style and async func
2109
	//		|	function renderLotsOfData(data){
2110
	//		|		var d = new dojo.Deferred();
2111
	//		|		setTimeout(function(){
2112
	//		|			try{
2113
	//		|				for(var x in data){
2114
	//		|					renderDataitem(data[x]);
2115
	//		|				}
2116
	//		|				d.callback(true);
2117
	//		|			}catch(e){
2118
	//		|				d.errback(new Error("rendering failed"));
2119
	//		|			}
2120
	//		|		}, 100);
2121
	//		|		return d;
2122
	//		|	}
2123
	//
2124
	//		|	// using Deferred style
2125
	//		|	renderLotsOfData(someDataObj).addErrback(function(){
2126
	//		|		promptUserToRecover();
2127
	//		|	});
2128
	//
2129
	//		Note that the caller doesn't have to change his code at all to
2130
	//		handle the asynchronous case.
2131
 
2132
	this.chain = [];
2133
	this.id = this._nextId();
2134
	this.fired = -1;
2135
	this.paused = 0;
2136
	this.results = [null, null];
2137
	this.canceller = canceller;
2138
	this.silentlyCancelled = false;
2139
};
2140
 
2141
dojo.extend(dojo.Deferred, {
2142
	/*
2143
	makeCalled: function(){
2144
		// summary:
2145
		//		returns a new, empty deferred, which is already in the called
2146
		//		state. Calling callback() or errback() on this deferred will
2147
		//		yeild an error and adding new handlers to it will result in
2148
		//		them being called immediately.
2149
		var deferred = new dojo.Deferred();
2150
		deferred.callback();
2151
		return deferred;
2152
	},
2153
 
2154
	toString: function(){
2155
		var state;
2156
		if(this.fired == -1){
2157
			state = 'unfired';
2158
		}else{
2159
			state = this.fired ? 'success' : 'error';
2160
		}
2161
		return 'Deferred(' + this.id + ', ' + state + ')';
2162
	},
2163
	*/
2164
 
2165
	_nextId: (function(){
2166
		var n = 1;
2167
		return function(){ return n++; };
2168
	})(),
2169
 
2170
	cancel: function(){
2171
		// summary:
2172
		//		Cancels a Deferred that has not yet received a value, or is
2173
		//		waiting on another Deferred as its value.
2174
		// description:
2175
		//		If a canceller is defined, the canceller is called. If the
2176
		//		canceller did not return an error, or there was no canceller,
2177
		//		then the errback chain is started.
2178
		var err;
2179
		if(this.fired == -1){
2180
			if(this.canceller){
2181
				err = this.canceller(this);
2182
			}else{
2183
				this.silentlyCancelled = true;
2184
			}
2185
			if(this.fired == -1){
2186
				if(!(err instanceof Error)){
2187
					var res = err;
2188
					err = new Error("Deferred Cancelled");
2189
					err.dojoType = "cancel";
2190
					err.cancelResult = res;
2191
				}
2192
				this.errback(err);
2193
			}
2194
		}else if(	(this.fired == 0) &&
2195
					(this.results[0] instanceof dojo.Deferred)
2196
		){
2197
			this.results[0].cancel();
2198
		}
2199
	},
2200
 
2201
 
2202
	_resback: function(res){
2203
		// summary:
2204
		//		The private primitive that means either callback or errback
2205
		this.fired = ((res instanceof Error) ? 1 : 0);
2206
		this.results[this.fired] = res;
2207
		this._fire();
2208
	},
2209
 
2210
	_check: function(){
2211
		if(this.fired != -1){
2212
			if(!this.silentlyCancelled){
2213
				throw new Error("already called!");
2214
			}
2215
			this.silentlyCancelled = false;
2216
			return;
2217
		}
2218
	},
2219
 
2220
	callback: function(res){
2221
		// summary:	Begin the callback sequence with a non-error value.
2222
 
2223
		/*
2224
		callback or errback should only be called once on a given
2225
		Deferred.
2226
		*/
2227
		this._check();
2228
		this._resback(res);
2229
	},
2230
 
2231
	errback: function(/*Error*/res){
2232
		// summary:
2233
		//		Begin the callback sequence with an error result.
2234
		this._check();
2235
		if(!(res instanceof Error)){
2236
			res = new Error(res);
2237
		}
2238
		this._resback(res);
2239
	},
2240
 
2241
	addBoth: function(/*Function||Object*/cb, /*Optional, String*/cbfn){
2242
		// summary:
2243
		//		Add the same function as both a callback and an errback as the
2244
		//		next element on the callback sequence.	This is useful for code
2245
		//		that you want to guarantee to run, e.g. a finalizer.
2246
		var enclosed = dojo.hitch(cb, cbfn);
2247
		if(arguments.length > 2){
2248
			enclosed = dojo.partial(enclosed, arguments, 2);
2249
		}
2250
		return this.addCallbacks(enclosed, enclosed);
2251
	},
2252
 
2253
	addCallback: function(cb, cbfn){
2254
		// summary:
2255
		//		Add a single callback to the end of the callback sequence.
2256
		var enclosed = dojo.hitch(cb, cbfn);
2257
		if(arguments.length > 2){
2258
			enclosed = dojo.partial(enclosed, arguments, 2);
2259
		}
2260
		return this.addCallbacks(enclosed, null);
2261
	},
2262
 
2263
	addErrback: function(cb, cbfn){
2264
		// summary:
2265
		//		Add a single callback to the end of the callback sequence.
2266
		var enclosed = dojo.hitch(cb, cbfn);
2267
		if(arguments.length > 2){
2268
			enclosed = dojo.partial(enclosed, arguments, 2);
2269
		}
2270
		return this.addCallbacks(null, enclosed);
2271
	},
2272
 
2273
	addCallbacks: function(cb, eb){
2274
		// summary:
2275
		//		Add separate callback and errback to the end of the callback
2276
		//		sequence.
2277
		this.chain.push([cb, eb])
2278
		if(this.fired >= 0){
2279
			this._fire();
2280
		}
2281
		return this;
2282
	},
2283
 
2284
	_fire: function(){
2285
		// summary:
2286
		//		Used internally to exhaust the callback sequence when a result
2287
		//		is available.
2288
		var chain = this.chain;
2289
		var fired = this.fired;
2290
		var res = this.results[fired];
2291
		var self = this;
2292
		var cb = null;
2293
		while(
2294
			(chain.length > 0) &&
2295
			(this.paused == 0)
2296
		){
2297
			// Array
2298
			var f = chain.shift()[fired];
2299
			if(!f){ continue; }
2300
			try{
2301
				res = f(res);
2302
				fired = ((res instanceof Error) ? 1 : 0);
2303
				if(res instanceof dojo.Deferred){
2304
					cb = function(res){
2305
						self._resback(res);
2306
						// inlined from _pause()
2307
						self.paused--;
2308
						if(
2309
							(self.paused == 0) &&
2310
							(self.fired >= 0)
2311
						){
2312
							self._fire();
2313
						}
2314
					}
2315
					// inlined from _unpause
2316
					this.paused++;
2317
				}
2318
			}catch(err){
2319
				console.debug(err);
2320
				fired = 1;
2321
				res = err;
2322
			}
2323
		}
2324
		this.fired = fired;
2325
		this.results[fired] = res;
2326
		if((cb)&&(this.paused)){
2327
			// this is for "tail recursion" in case the dependent
2328
			// deferred is already fired
2329
			res.addBoth(cb);
2330
		}
2331
	}
2332
});
2333
 
2334
}
2335
 
2336
if(!dojo._hasResource["dojo._base.json"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2337
dojo._hasResource["dojo._base.json"] = true;
2338
dojo.provide("dojo._base.json");
2339
 
2340
dojo.fromJson = function(/*String*/ json){
2341
	// summary:
2342
	// 		evaluates the passed string-form of a JSON object
2343
	// json:
2344
	//		a string literal of a JSON item, for instance:
2345
	//			'{ "foo": [ "bar", 1, { "baz": "thud" } ] }'
2346
	// return:
2347
	//		An object, the result of the evaluation
2348
 
2349
	// FIXME: should this accept mozilla's optional second arg?
2350
	try {
2351
		return eval("(" + json + ")");
2352
	}catch(e){
2353
		console.debug(e);
2354
		return json;
2355
	}
2356
}
2357
 
2358
dojo._escapeString = function(/*String*/str){
2359
	//summary:
2360
	//		Adds escape sequences for non-visual characters, double quote and
2361
	//		backslash and surrounds with double quotes to form a valid string
2362
	//		literal.
2363
	return ('"' + str.replace(/(["\\])/g, '\\$1') + '"'
2364
		).replace(/[\f]/g, "\\f"
2365
		).replace(/[\b]/g, "\\b"
2366
		).replace(/[\n]/g, "\\n"
2367
		).replace(/[\t]/g, "\\t"
2368
		).replace(/[\r]/g, "\\r"); // string
2369
}
2370
 
2371
dojo.toJsonIndentStr = "\t";
2372
dojo.toJson = function(/*Object*/ it, /*Boolean?*/ prettyPrint, /*String?*/ _indentStr){
2373
	// summary:
2374
	//		Create a JSON serialization of an object.
2375
	//		Note that this doesn't check for infinite recursion, so don't do that!
2376
	//
2377
	// it:
2378
	//		an object to be serialized. Objects may define their own
2379
	//		serialization via a special "__json__" or "json" function
2380
	//		property. If a specialized serializer has been defined, it will
2381
	//		be used as a fallback.
2382
	//
2383
	// prettyPrint:
2384
	//		if true, we indent objects and arrays to make the output prettier.
2385
	//		The variable dojo.toJsonIndentStr is used as the indent string
2386
	//		-- to use something other than the default (tab),
2387
	//		change that variable before calling dojo.toJson().
2388
	//
2389
	// _indentStr:
2390
	//		private variable for recursive calls when pretty printing, do not use.
2391
	//
2392
	// return:
2393
	//		a String representing the serialized version of the passed object.
2394
 
2395
	_indentStr = _indentStr || "";
2396
	var nextIndent = (prettyPrint ? _indentStr + dojo.toJsonIndentStr : "");
2397
	var newLine = (prettyPrint ? "\n" : "");
2398
	var objtype = typeof(it);
2399
	if(objtype == "undefined"){
2400
		return "undefined";
2401
	}else if((objtype == "number")||(objtype == "boolean")){
2402
		return it + "";
2403
	}else if(it === null){
2404
		return "null";
2405
	}
2406
	if(dojo.isString(it)){
2407
		return dojo._escapeString(it);
2408
	}
2409
	if(it.nodeType && it.cloneNode){ // isNode
2410
		return ""; // FIXME: would something like outerHTML be better here?
2411
	}
2412
	// recurse
2413
	var recurse = arguments.callee;
2414
	// short-circuit for objects that support "json" serialization
2415
	// if they return "self" then just pass-through...
2416
	var newObj;
2417
	if(typeof it.__json__ == "function"){
2418
		newObj = it.__json__();
2419
		if(it !== newObj){
2420
			return recurse(newObj, prettyPrint, nextIndent);
2421
		}
2422
	}
2423
	if(typeof it.json == "function"){
2424
		newObj = it.json();
2425
		if(it !== newObj){
2426
			return recurse(newObj, prettyPrint, nextIndent);
2427
		}
2428
	}
2429
	// array
2430
	if(dojo.isArray(it)){
2431
		var res = [];
2432
		for(var i = 0; i < it.length; i++){
2433
			var val = recurse(it[i], prettyPrint, nextIndent);
2434
			if(typeof(val) != "string"){
2435
				val = "undefined";
2436
			}
2437
			res.push(newLine + nextIndent + val);
2438
		}
2439
		return "[" + res.join(", ") + newLine + _indentStr + "]";
2440
	}
2441
	/*
2442
	// look in the registry
2443
	try {
2444
		window.o = it;
2445
		newObj = dojo.json.jsonRegistry.match(it);
2446
		return recurse(newObj, prettyPrint, nextIndent);
2447
	}catch(e){
2448
		// console.debug(e);
2449
	}
2450
	// it's a function with no adapter, skip it
2451
	*/
2452
	if(objtype == "function"){
2453
		return null;
2454
	}
2455
	// generic object code path
2456
	var output = [];
2457
	for(var key in it){
2458
		var keyStr;
2459
		if(typeof(key) == "number"){
2460
			keyStr = '"' + key + '"';
2461
		}else if(typeof(key) == "string"){
2462
			keyStr = dojo._escapeString(key);
2463
		}else{
2464
			// skip non-string or number keys
2465
			continue;
2466
		}
2467
		val = recurse(it[key], prettyPrint, nextIndent);
2468
		if(typeof(val) != "string"){
2469
			// skip non-serializable values
2470
			continue;
2471
		}
2472
		// FIXME: use += on Moz!!
2473
		//	 MOW NOTE: using += is a pain because you have to account for the dangling comma...
2474
		output.push(newLine + nextIndent + keyStr + ": " + val);
2475
	}
2476
	return "{" + output.join(", ") + newLine + _indentStr + "}";
2477
}
2478
 
2479
}
2480
 
2481
if(!dojo._hasResource["dojo._base.array"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2482
dojo._hasResource["dojo._base.array"] = true;
2483
 
2484
dojo.provide("dojo._base.array");
2485
 
2486
(function(){
2487
	var _getParts = function(arr, obj, cb){
2488
		return [
2489
			(dojo.isString(arr) ? arr.split("") : arr),
2490
			(obj||dojo.global),
2491
			// FIXME: cache the anonymous functions we create here?
2492
			(dojo.isString(cb) ? (new Function("item", "index", "array", cb)) : cb)
2493
		];
2494
	}
2495
 
2496
	dojo.mixin(dojo, {
2497
		indexOf: function(	/*Array*/		array,
2498
							/*Object*/		value,
2499
							/*Integer?*/	fromIndex,
2500
							/*Boolean?*/	findLast){
2501
			// summary:
2502
			//		locates the first index of the provided value in the
2503
			//		passed array. If the value is not found, -1 is returned.
2504
			// description:
2505
			//		For details on this method, see:
2506
			// 			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf
2507
 
2508
			var i = 0, step = 1, end = array.length;
2509
			if(findLast){
2510
				i = end - 1;
2511
				step = end = -1;
2512
			}
2513
			for(i = fromIndex || i; i != end; i += step){
2514
				if(array[i] == value){ return i; }
2515
			}
2516
			return -1;	// Number
2517
		},
2518
 
2519
		lastIndexOf: function(/*Array*/array, /*Object*/value, /*Integer?*/fromIndex){
2520
			// summary:
2521
			//		locates the last index of the provided value in the passed array.
2522
			//		If the value is not found, -1 is returned.
2523
			// description:
2524
			//		For details on this method, see:
2525
			// 			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf
2526
			return dojo.indexOf(array, value, fromIndex, true); // Number
2527
		},
2528
 
2529
		forEach: function(/*Array*/arr, /*Function*/callback, /*Object?*/obj){
2530
			// summary:
2531
			//		for every item in arr, call callback with that item as its
2532
			//		only parameter.
2533
			// description:
2534
			//		Return values are ignored. This function
2535
			//		corresponds (and wraps) the JavaScript 1.6 forEach method. For
2536
			//		more details, see:
2537
			//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:forEach
2538
 
2539
			// match the behavior of the built-in forEach WRT empty arrs
2540
			if(!arr || !arr.length){ return; }
2541
 
2542
			// FIXME: there are several ways of handilng thisObject. Is
2543
			// dojo.global always the default context?
2544
			var _p = _getParts(arr, obj, callback); arr = _p[0];
2545
			for(var i=0,l=_p[0].length; i<l; i++){
2546
				_p[2].call(_p[1], arr[i], i, arr);
2547
			}
2548
		},
2549
 
2550
		_everyOrSome: function(/*Boolean*/every, /*Array*/arr, /*Function*/callback, /*Object?*/obj){
2551
			var _p = _getParts(arr, obj, callback); arr = _p[0];
2552
			for(var i = 0, l = arr.length; i < l; i++){
2553
				var result = !!_p[2].call(_p[1], arr[i], i, arr);
2554
				if(every ^ result){
2555
					return result; // Boolean
2556
				}
2557
			}
2558
			return every; // Boolean
2559
		},
2560
 
2561
		every: function(/*Array*/arr, /*Function*/callback, /*Object?*/thisObject){
2562
			// summary:
2563
			//		Determines whether or not every item in the array satisfies the
2564
			//		condition implemented by callback.
2565
			// description:
2566
			//		The parameter thisObject may be used to
2567
			//		scope the call to callback. The function signature is derived
2568
			//		from the JavaScript 1.6 Array.every() function. More
2569
			//		information on this can be found here:
2570
			//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:every
2571
			// example:
2572
			//	|	dojo.every([1, 2, 3, 4], function(item){ return item>1; });
2573
			//		returns false
2574
			// example:
2575
			//	|	dojo.every([1, 2, 3, 4], function(item){ return item>0; });
2576
			//		returns true
2577
			return this._everyOrSome(true, arr, callback, thisObject); // Boolean
2578
		},
2579
 
2580
		some: function(/*Array*/arr, /*Function*/callback, /*Object?*/thisObject){
2581
			// summary:
2582
			//		Determines whether or not any item in the array satisfies the
2583
			//		condition implemented by callback.
2584
			// description:
2585
			//		The parameter thisObject may be used to
2586
			//		scope the call to callback. The function signature is derived
2587
			//		from the JavaScript 1.6 Array.some() function. More
2588
			//		information on this can be found here:
2589
			//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:some
2590
			// example:
2591
			//	|	dojo.some([1, 2, 3, 4], function(item){ return item>1; });
2592
			//		returns true
2593
			// example:
2594
			//	|	dojo.some([1, 2, 3, 4], function(item){ return item<1; });
2595
			//		returns false
2596
			return this._everyOrSome(false, arr, callback, thisObject); // Boolean
2597
		},
2598
 
2599
		map: function(/*Array*/arr, /*Function*/func, /*Function?*/obj){
2600
			// summary:
2601
			//		applies a function to each element of an Array and creates
2602
			//		an Array with the results
2603
			// description:
2604
			//		Returns a new array constituted from the return values of
2605
			//		passing each element of arr into unary_func. The obj parameter
2606
			//		may be passed to enable the passed function to be called in
2607
			//		that scope.  In environments that support JavaScript 1.6, this
2608
			//		function is a passthrough to the built-in map() function
2609
			//		provided by Array instances. For details on this, see:
2610
			// 			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:map
2611
			// example:
2612
			//	|	dojo.map([1, 2, 3, 4], function(item){ return item+1 });
2613
			//		returns [2, 3, 4, 5]
2614
			var _p = _getParts(arr, obj, func); arr = _p[0];
2615
			var outArr = ((arguments[3]) ? (new arguments[3]()) : []);
2616
			for(var i=0;i<arr.length;++i){
2617
				outArr.push(_p[2].call(_p[1], arr[i], i, arr));
2618
			}
2619
			return outArr; // Array
2620
		},
2621
 
2622
		filter: function(/*Array*/arr, /*Function*/callback, /*Object?*/obj){
2623
			// summary:
2624
			//		Returns a new Array with those items from arr that match the
2625
			//		condition implemented by callback. ob may be used to
2626
			//		scope the call to callback. The function signature is derived
2627
			//		from the JavaScript 1.6 Array.filter() function.
2628
			//
2629
			//		More information on the JS 1.6 API can be found here:
2630
			//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:filter
2631
			// example:
2632
			//	|	dojo.filter([1, 2, 3, 4], function(item){ return item>1; });
2633
			//		returns [2, 3, 4]
2634
 
2635
			var _p = _getParts(arr, obj, callback); arr = _p[0];
2636
			var outArr = [];
2637
			for(var i = 0; i < arr.length; i++){
2638
				if(_p[2].call(_p[1], arr[i], i, arr)){
2639
					outArr.push(arr[i]);
2640
				}
2641
			}
2642
			return outArr; // Array
2643
		}
2644
	});
2645
})();
2646
 
2647
}
2648
 
2649
if(!dojo._hasResource["dojo._base.Color"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2650
dojo._hasResource["dojo._base.Color"] = true;
2651
dojo.provide("dojo._base.Color");
2652
 
2653
 
2654
 
2655
dojo.Color = function(/*Array|String|Object*/ color){
2656
	// summary:
2657
	//		takes a named string, hex string, array of rgb or rgba values,
2658
	//		an object with r, g, b, and a properties, or another dojo.Color object
2659
	if(color){ this.setColor(color); }
2660
};
2661
 
2662
// FIXME: there's got to be a more space-efficient way to encode or discover these!!  Use hex?
2663
dojo.Color.named = {
2664
	black:      [0,0,0],
2665
	silver:     [192,192,192],
2666
	gray:       [128,128,128],
2667
	white:      [255,255,255],
2668
	maroon:		[128,0,0],
2669
	red:        [255,0,0],
2670
	purple:		[128,0,128],
2671
	fuchsia:	[255,0,255],
2672
	green:	    [0,128,0],
2673
	lime:	    [0,255,0],
2674
	olive:		[128,128,0],
2675
	yellow:		[255,255,0],
2676
	navy:       [0,0,128],
2677
	blue:       [0,0,255],
2678
	teal:		[0,128,128],
2679
	aqua:		[0,255,255]
2680
};
2681
 
2682
 
2683
dojo.extend(dojo.Color, {
2684
	r: 255, g: 255, b: 255, a: 1,
2685
	_set: function(r, g, b, a){
2686
		var t = this; t.r = r; t.g = g; t.b = b; t.a = a;
2687
	},
2688
	setColor: function(/*Array|String|Object*/ color){
2689
		// summary:
2690
		//		takes a named string, hex string, array of rgb or rgba values,
2691
		//		an object with r, g, b, and a properties, or another dojo.Color object
2692
		var d = dojo;
2693
		if(d.isString(color)){
2694
			d.colorFromString(color, this);
2695
		}else if(d.isArray(color)){
2696
			d.colorFromArray(color, this);
2697
		}else{
2698
			this._set(color.r, color.g, color.b, color.a);
2699
			if(!(color instanceof d.Color)){ this.sanitize(); }
2700
		}
2701
		return this;	// dojo.Color
2702
	},
2703
	sanitize: function(){
2704
		// summary:
2705
		//		makes sure that the object has correct attributes
2706
		// description:
2707
		//		the default implementation does nothing, include dojo.colors to
2708
		//		augment it to real checks
2709
		return this;	// dojo.Color
2710
	},
2711
	toRgb: function(){
2712
		// summary: returns 3 component array of rgb values
2713
		var t = this;
2714
		return [t.r, t.g, t.b];	// Array
2715
	},
2716
	toRgba: function(){
2717
		// summary: returns a 4 component array of rgba values
2718
		var t = this;
2719
		return [t.r, t.g, t.b, t.a];	// Array
2720
	},
2721
	toHex: function(){
2722
		// summary: returns a css color string in hexadecimal representation
2723
		var arr = dojo.map(["r", "g", "b"], function(x){
2724
			var s = this[x].toString(16);
2725
			return s.length < 2 ? "0" + s : s;
2726
		}, this);
2727
		return "#" + arr.join("");	// String
2728
	},
2729
	toCss: function(/*Boolean?*/ includeAlpha){
2730
		// summary: returns a css color string in rgb(a) representation
2731
		var t = this, rgb = t.r + ", " + t.g + ", " + t.b;
2732
		return (includeAlpha ? "rgba(" + rgb + ", " + t.a : "rgb(" + rgb) + ")";	// String
2733
	},
2734
	toString: function(){
2735
		// summary: returns a visual representation of the color
2736
		return this.toCss(true); // String
2737
	}
2738
});
2739
 
2740
dojo.blendColors = function(
2741
	/*dojo.Color*/ start,
2742
	/*dojo.Color*/ end,
2743
	/*Number*/ weight,
2744
	/*dojo.Color?*/ obj
2745
){
2746
	// summary:
2747
	//		blend colors end and start with weight from 0 to 1, 0.5 being a 50/50 blend,
2748
	//		can reuse a previously allocated dojo.Color object for the result
2749
	var d = dojo, t = obj || new dojo.Color();
2750
	d.forEach(["r", "g", "b", "a"], function(x){
2751
		t[x] = start[x] + (end[x] - start[x]) * weight;
2752
		if(x != "a"){ t[x] = Math.round(t[x]); }
2753
	});
2754
	return t.sanitize();	// dojo.Color
2755
};
2756
 
2757
dojo.colorFromRgb = function(/*String*/ color, /*dojo.Color?*/ obj){
2758
	// summary: get rgb(a) array from css-style color declarations
2759
	var m = color.toLowerCase().match(/^rgba?\(([\s\.,0-9]+)\)/);
2760
	return m && dojo.colorFromArray(m[1].split(/\s*,\s*/), obj);	// dojo.Color
2761
};
2762
 
2763
dojo.colorFromHex = function(/*String*/ color, /*dojo.Color?*/ obj){
2764
	// summary: converts a hex string with a '#' prefix to a color object.
2765
	//	Supports 12-bit #rgb shorthand.
2766
	var d = dojo, t = obj || new d.Color(),
2767
		bits = (color.length == 4) ? 4 : 8,
2768
		mask = (1 << bits) - 1;
2769
	color = Number("0x" + color.substr(1));
2770
	if(isNaN(color)){
2771
		return null; // dojo.Color
2772
	}
2773
	d.forEach(["b", "g", "r"], function(x){
2774
		var c = color & mask;
2775
		color >>= bits;
2776
		t[x] = bits == 4 ? 17 * c : c;
2777
	});
2778
	t.a = 1;
2779
	return t;	// dojo.Color
2780
};
2781
 
2782
dojo.colorFromArray = function(/*Array*/ a, /*dojo.Color?*/ obj){
2783
	// summary: builds a color from 1, 2, 3, or 4 element array
2784
	var t = obj || new dojo.Color();
2785
	t._set(Number(a[0]), Number(a[1]), Number(a[2]), Number(a[3]));
2786
	if(isNaN(t.a)){ t.a = 1; }
2787
	return t.sanitize();	// dojo.Color
2788
};
2789
 
2790
dojo.colorFromString = function(/*String*/ str, /*dojo.Color?*/ obj){
2791
	//	summary:
2792
	//		parses str for a color value.
2793
	//	description:
2794
	//		Acceptable input values for str may include arrays of any form
2795
	//		accepted by dojo.colorFromArray, hex strings such as "#aaaaaa", or
2796
	//		rgb or rgba strings such as "rgb(133, 200, 16)" or "rgba(10, 10,
2797
	//		10, 50)"
2798
	//	returns:
2799
	//		a dojo.Color object. If obj is passed, it will be the return value.
2800
	var a = dojo.Color.named[str];
2801
	return a && dojo.colorFromArray(a, obj) || dojo.colorFromRgb(str, obj) || dojo.colorFromHex(str, obj);
2802
};
2803
 
2804
}
2805
 
2806
if(!dojo._hasResource["dojo._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2807
dojo._hasResource["dojo._base"] = true;
2808
dojo.provide("dojo._base");
2809
 
2810
 
2811
 
2812
 
2813
 
2814
 
2815
 
2816
 
2817
 
2818
 
2819
 
2820
 
2821
 
2822
 
2823
 
2824
(function(){
2825
	if(djConfig.require){
2826
		for(var x=0; x<djConfig.require.length; x++){
2827
			dojo["require"](djConfig.require[x]);
2828
		}
2829
	}
2830
})();
2831
 
2832
}
2833
 
2834
if(!dojo._hasResource["dojo._base.window"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2835
dojo._hasResource["dojo._base.window"] = true;
2836
dojo.provide("dojo._base.window");
2837
 
2838
dojo._gearsObject = function(){
2839
	// summary:
2840
	//		factory method to get a Google Gears plugin instance to
2841
	//		expose in the browser runtime environment, if present
2842
	var factory;
2843
	var results;
2844
 
2845
	var gearsObj = dojo.getObject("google.gears");
2846
	if(gearsObj){ return gearsObj; } // already defined elsewhere
2847
 
2848
	if(typeof GearsFactory != "undefined"){ // Firefox
2849
		factory = new GearsFactory();
2850
	}else{
2851
		if(dojo.isIE){
2852
			// IE
2853
			try{
2854
				factory = new ActiveXObject("Gears.Factory");
2855
			}catch(e){
2856
				// ok to squelch; there's no gears factory.  move on.
2857
			}
2858
		}else if(navigator.mimeTypes["application/x-googlegears"]){
2859
			// Safari?
2860
			factory = document.createElement("object");
2861
			factory.setAttribute("type", "application/x-googlegears");
2862
			factory.setAttribute("width", 0);
2863
			factory.setAttribute("height", 0);
2864
			factory.style.display = "none";
2865
			document.documentElement.appendChild(factory);
2866
		}
2867
	}
2868
 
2869
	// still nothing?
2870
	if(!factory){ return null; }
2871
 
2872
	// define the global objects now; don't overwrite them though if they
2873
	// were somehow set internally by the Gears plugin, which is on their
2874
	// dev roadmap for the future
2875
	dojo.setObject("google.gears.factory", factory);
2876
	return dojo.getObject("google.gears");
2877
};
2878
 
2879
// see if we have Google Gears installed, and if
2880
// so, make it available in the runtime environment
2881
// and in the Google standard 'google.gears' global object
2882
dojo.isGears = (!!dojo._gearsObject())||0;
2883
 
2884
// @global: dojo.doc
2885
 
2886
// summary:
2887
//		Current document object. 'dojo.doc' can be modified
2888
//		for temporary context shifting. Also see dojo.withDoc().
2889
// description:
2890
//    Refer to dojo.doc rather
2891
//    than referring to 'window.document' to ensure your code runs
2892
//    correctly in managed contexts.
2893
dojo.doc = window["document"] || null;
2894
 
2895
dojo.body = function(){
2896
	// summary:
2897
	//		return the body object associated with dojo.doc
2898
 
2899
	// Note: document.body is not defined for a strict xhtml document
2900
	// Would like to memoize this, but dojo.doc can change vi dojo.withDoc().
2901
	return dojo.doc.body || dojo.doc.getElementsByTagName("body")[0];
2902
}
2903
 
2904
dojo.setContext = function(/*Object*/globalObject, /*DocumentElement*/globalDocument){
2905
	// summary:
2906
	//		changes the behavior of many core Dojo functions that deal with
2907
	//		namespace and DOM lookup, changing them to work in a new global
2908
	//		context. The varibles dojo.global and dojo.doc
2909
	//		are modified as a result of calling this function.
2910
	dojo.global = globalObject;
2911
	dojo.doc = globalDocument;
2912
};
2913
 
2914
dojo._fireCallback = function(callback, context, cbArguments){
2915
	// FIXME: should migrate to using "dojo.isString"!
2916
	if(context && dojo.isString(callback)){
2917
		callback = context[callback];
2918
	}
2919
	return (context ? callback.apply(context, cbArguments || [ ]) : callback());
2920
}
2921
 
2922
dojo.withGlobal = function(	/*Object*/globalObject,
2923
							/*Function*/callback,
2924
							/*Object?*/thisObject,
2925
							/*Array?*/cbArguments){
2926
	// summary:
2927
	//		Call callback with globalObject as dojo.global and
2928
	//		globalObject.document as dojo.doc. If provided, globalObject
2929
	//		will be executed in the context of object thisObject
2930
	// description:
2931
	//		When callback() returns or throws an error, the dojo.global
2932
	//		and dojo.doc will be restored to its previous state.
2933
	var rval;
2934
	var oldGlob = dojo.global;
2935
	var oldDoc = dojo.doc;
2936
	try{
2937
		dojo.setContext(globalObject, globalObject.document);
2938
		rval = dojo._fireCallback(callback, thisObject, cbArguments);
2939
	}finally{
2940
		dojo.setContext(oldGlob, oldDoc);
2941
	}
2942
	return rval;
2943
}
2944
 
2945
dojo.withDoc = function(	/*Object*/documentObject,
2946
							/*Function*/callback,
2947
							/*Object?*/thisObject,
2948
							/*Array?*/cbArguments){
2949
	// summary:
2950
	//		Call callback with documentObject as dojo.doc. If provided,
2951
	//		callback will be executed in the context of object thisObject
2952
	// description:
2953
	//		When callback() returns or throws an error, the dojo.doc will
2954
	//		be restored to its previous state.
2955
	var rval;
2956
	var oldDoc = dojo.doc;
2957
	try{
2958
		dojo.doc = documentObject;
2959
		rval = dojo._fireCallback(callback, thisObject, cbArguments);
2960
	}finally{
2961
		dojo.doc = oldDoc;
2962
	}
2963
	return rval;
2964
};
2965
 
2966
//Register any module paths set up in djConfig. Need to do this
2967
//in the hostenvs since hostenv_browser can read djConfig from a
2968
//script tag's attribute.
2969
(function(){
2970
	var mp = djConfig["modulePaths"];
2971
	if(mp){
2972
		for(var param in mp){
2973
			dojo.registerModulePath(param, mp[param]);
2974
		}
2975
	}
2976
})();
2977
 
2978
}
2979
 
2980
if(!dojo._hasResource["dojo._base.event"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2981
dojo._hasResource["dojo._base.event"] = true;
2982
dojo.provide("dojo._base.event");
2983
 
2984
 
2985
// this file courtesy of the TurboAjax Group, licensed under a Dojo CLA
2986
 
2987
(function(){
2988
	// DOM event listener machinery
2989
	var del = dojo._event_listener = {
2990
		add: function(/*DOMNode*/node, /*String*/name, /*Function*/fp){
2991
			if(!node){return;}
2992
			name = del._normalizeEventName(name);
2993
 
2994
			fp = del._fixCallback(name, fp);
2995
 
2996
			var oname = name;
2997
			if((!dojo.isIE)&&((name == "mouseenter")||(name == "mouseleave"))){
2998
				var oname = name;
2999
				var ofp = fp;
3000
				name = (name == "mouseenter") ? "mouseover" : "mouseout";
3001
				fp = function(e){
3002
					// thanks ben!
3003
					var id = dojo.isDescendant(e.relatedTarget, node);
3004
					if(id == false){
3005
						// e.type = oname; // FIXME: doesn't take?
3006
						return ofp.call(this, e);
3007
					}
3008
				}
3009
			}
3010
 
3011
			node.addEventListener(name, fp, false);
3012
			return fp; /*Handle*/
3013
		},
3014
		remove: function(/*DOMNode*/node, /*String*/event, /*Handle*/handle){
3015
			// summary:
3016
			//		clobbers the listener from the node
3017
			// node:
3018
			//		DOM node to attach the event to
3019
			// event:
3020
			//		the name of the handler to remove the function from
3021
			// handle:
3022
			//		the handle returned from add
3023
			(node)&&(node.removeEventListener(del._normalizeEventName(event), handle, false));
3024
		},
3025
		_normalizeEventName: function(/*String*/name){
3026
			// Generally, name should be lower case, unless it is special
3027
			// somehow (e.g. a Mozilla DOM event).
3028
			// Remove 'on'.
3029
			return (name.slice(0,2)=="on" ? name.slice(2) : name);
3030
		},
3031
		_fixCallback: function(/*String*/name, fp){
3032
			// By default, we only invoke _fixEvent for 'keypress'
3033
			// If code is added to _fixEvent for other events, we have
3034
			// to revisit this optimization.
3035
			// This also applies to _fixEvent overrides for Safari and Opera
3036
			// below.
3037
			return (name!="keypress" ? fp : function(e){ return fp.call(this, del._fixEvent(e, this)); });
3038
		},
3039
		_fixEvent: function(evt, sender){
3040
			// _fixCallback only attaches us to keypress.
3041
			// Switch on evt.type anyway because we might
3042
			// be called directly from dojo.fixEvent.
3043
			switch(evt.type){
3044
				case "keypress":
3045
					del._setKeyChar(evt);
3046
					break;
3047
			}
3048
			return evt;
3049
		},
3050
		_setKeyChar: function(evt){
3051
			evt.keyChar = (evt.charCode ? String.fromCharCode(evt.charCode) : '');
3052
		}
3053
	};
3054
 
3055
	// DOM events
3056
 
3057
	dojo.fixEvent = function(/*Event*/evt, /*DOMNode*/sender){
3058
		// summary:
3059
		//		normalizes properties on the event object including event
3060
		//		bubbling methods, keystroke normalization, and x/y positions
3061
		// evt: Event
3062
		//		native event object
3063
		// sender: DOMNode
3064
		//		node to treat as "currentTarget"
3065
		return del._fixEvent(evt, sender);
3066
	}
3067
 
3068
	dojo.stopEvent = function(/*Event*/evt){
3069
		// summary:
3070
		//		prevents propagation and clobbers the default action of the
3071
		//		passed event
3072
		// evt: Event
3073
		//		The event object. If omitted, window.event is used on IE.
3074
		evt.preventDefault();
3075
		evt.stopPropagation();
3076
		// NOTE: below, this method is overridden for IE
3077
	}
3078
 
3079
	// the default listener to use on dontFix nodes, overriden for IE
3080
	var node_listener = dojo._listener;
3081
 
3082
	// Unify connect and event listeners
3083
	dojo._connect = function(obj, event, context, method, dontFix){
3084
		// FIXME: need a more strict test
3085
		var isNode = obj && (obj.nodeType||obj.attachEvent||obj.addEventListener);
3086
		// choose one of three listener options: raw (connect.js), DOM event on a Node, custom event on a Node
3087
		// we need the third option to provide leak prevention on broken browsers (IE)
3088
		var lid = !isNode ? 0 : (!dontFix ? 1 : 2), l = [dojo._listener, del, node_listener][lid];
3089
		// create a listener
3090
		var h = l.add(obj, event, dojo.hitch(context, method));
3091
		// formerly, the disconnect package contained "l" directly, but if client code
3092
		// leaks the disconnect package (by connecting it to a node), referencing "l"
3093
		// compounds the problem.
3094
		// instead we return a listener id, which requires custom _disconnect below.
3095
		// return disconnect package
3096
		return [ obj, event, h, lid ];
3097
	}
3098
 
3099
	dojo._disconnect = function(obj, event, handle, listener){
3100
		([dojo._listener, del, node_listener][listener]).remove(obj, event, handle);
3101
	}
3102
 
3103
	// Constants
3104
 
3105
	// Public: client code should test
3106
	// keyCode against these named constants, as the
3107
	// actual codes can vary by browser.
3108
	dojo.keys = {
3109
		BACKSPACE: 8,
3110
		TAB: 9,
3111
		CLEAR: 12,
3112
		ENTER: 13,
3113
		SHIFT: 16,
3114
		CTRL: 17,
3115
		ALT: 18,
3116
		PAUSE: 19,
3117
		CAPS_LOCK: 20,
3118
		ESCAPE: 27,
3119
		SPACE: 32,
3120
		PAGE_UP: 33,
3121
		PAGE_DOWN: 34,
3122
		END: 35,
3123
		HOME: 36,
3124
		LEFT_ARROW: 37,
3125
		UP_ARROW: 38,
3126
		RIGHT_ARROW: 39,
3127
		DOWN_ARROW: 40,
3128
		INSERT: 45,
3129
		DELETE: 46,
3130
		HELP: 47,
3131
		LEFT_WINDOW: 91,
3132
		RIGHT_WINDOW: 92,
3133
		SELECT: 93,
3134
		NUMPAD_0: 96,
3135
		NUMPAD_1: 97,
3136
		NUMPAD_2: 98,
3137
		NUMPAD_3: 99,
3138
		NUMPAD_4: 100,
3139
		NUMPAD_5: 101,
3140
		NUMPAD_6: 102,
3141
		NUMPAD_7: 103,
3142
		NUMPAD_8: 104,
3143
		NUMPAD_9: 105,
3144
		NUMPAD_MULTIPLY: 106,
3145
		NUMPAD_PLUS: 107,
3146
		NUMPAD_ENTER: 108,
3147
		NUMPAD_MINUS: 109,
3148
		NUMPAD_PERIOD: 110,
3149
		NUMPAD_DIVIDE: 111,
3150
		F1: 112,
3151
		F2: 113,
3152
		F3: 114,
3153
		F4: 115,
3154
		F5: 116,
3155
		F6: 117,
3156
		F7: 118,
3157
		F8: 119,
3158
		F9: 120,
3159
		F10: 121,
3160
		F11: 122,
3161
		F12: 123,
3162
		F13: 124,
3163
		F14: 125,
3164
		F15: 126,
3165
		NUM_LOCK: 144,
3166
		SCROLL_LOCK: 145
3167
	};
3168
 
3169
	// IE event normalization
3170
	if(dojo.isIE){
3171
		var _trySetKeyCode = function(e, code){
3172
			try{
3173
				// squelch errors when keyCode is read-only
3174
				// (e.g. if keyCode is ctrl or shift)
3175
				return (e.keyCode = code);
3176
			}catch(e){
3177
				return 0;
3178
			}
3179
		}
3180
 
3181
		// by default, use the standard listener
3182
		var iel = dojo._listener;
3183
		// dispatcher tracking property
3184
		if(!djConfig._allow_leaks){
3185
			// custom listener that handles leak protection for DOM events
3186
			node_listener = iel = dojo._ie_listener = {
3187
				// support handler indirection: event handler functions are
3188
				// referenced here. Event dispatchers hold only indices.
3189
				handlers: [],
3190
				// add a listener to an object
3191
				add: function(/*Object*/ source, /*String*/ method, /*Function*/ listener){
3192
					source = source || dojo.global;
3193
					var f = source[method];
3194
					if(!f||!f._listeners){
3195
						var d = dojo._getIeDispatcher();
3196
						// original target function is special
3197
						d.target = f && (ieh.push(f) - 1);
3198
						// dispatcher holds a list of indices into handlers table
3199
						d._listeners = [];
3200
						// redirect source to dispatcher
3201
						f = source[method] = d;
3202
					}
3203
					return f._listeners.push(ieh.push(listener) - 1) ; /*Handle*/
3204
				},
3205
				// remove a listener from an object
3206
				remove: function(/*Object*/ source, /*String*/ method, /*Handle*/ handle){
3207
					var f = (source||dojo.global)[method], l = f&&f._listeners;
3208
					if(f && l && handle--){
3209
						delete ieh[l[handle]];
3210
						delete l[handle];
3211
					}
3212
				}
3213
			};
3214
			// alias used above
3215
			var ieh = iel.handlers;
3216
		}
3217
 
3218
		dojo.mixin(del, {
3219
			add: function(/*DOMNode*/node, /*String*/event, /*Function*/fp){
3220
				if(!node){return;} // undefined
3221
				event = del._normalizeEventName(event);
3222
				if(event=="onkeypress"){
3223
					// we need to listen to onkeydown to synthesize
3224
					// keypress events that otherwise won't fire
3225
					// on IE
3226
					var kd = node.onkeydown;
3227
					if(!kd||!kd._listeners||!kd._stealthKeydown){
3228
						// we simply ignore this connection when disconnecting
3229
						// because it's side-effects are harmless
3230
						del.add(node, "onkeydown", del._stealthKeyDown);
3231
						// we only want one stealth listener per node
3232
						node.onkeydown._stealthKeydown = true;
3233
					}
3234
				}
3235
				return iel.add(node, event, del._fixCallback(fp));
3236
			},
3237
			remove: function(/*DOMNode*/node, /*String*/event, /*Handle*/handle){
3238
				iel.remove(node, del._normalizeEventName(event), handle);
3239
			},
3240
			_normalizeEventName: function(/*String*/eventName){
3241
				// Generally, eventName should be lower case, unless it is
3242
				// special somehow (e.g. a Mozilla event)
3243
				// ensure 'on'
3244
				return (eventName.slice(0,2)!="on" ? "on"+eventName : eventName);
3245
			},
3246
			_nop: function(){},
3247
			_fixEvent: function(/*Event*/evt, /*DOMNode*/sender){
3248
				// summary:
3249
				//		normalizes properties on the event object including event
3250
				//		bubbling methods, keystroke normalization, and x/y positions
3251
				// evt: native event object
3252
				// sender: node to treat as "currentTarget"
3253
				if(!evt){
3254
					var w = (sender)&&((sender.ownerDocument || sender.document || sender).parentWindow)||window;
3255
					evt = w.event;
3256
				}
3257
				if(!evt){return(evt);}
3258
				evt.target = evt.srcElement;
3259
				evt.currentTarget = (sender || evt.srcElement);
3260
				evt.layerX = evt.offsetX;
3261
				evt.layerY = evt.offsetY;
3262
				// FIXME: scroll position query is duped from dojo.html to
3263
				// avoid dependency on that entire module. Now that HTML is in
3264
				// Base, we should convert back to something similar there.
3265
				var se = evt.srcElement, doc = (se && se.ownerDocument) || document;
3266
				// DO NOT replace the following to use dojo.body(), in IE, document.documentElement should be used
3267
				// here rather than document.body
3268
				var docBody = ((dojo.isIE<6)||(doc["compatMode"]=="BackCompat")) ? doc.body : doc.documentElement;
3269
				var offset = dojo._getIeDocumentElementOffset();
3270
				evt.pageX = evt.clientX + dojo._fixIeBiDiScrollLeft(docBody.scrollLeft || 0) - offset.x;
3271
				evt.pageY = evt.clientY + (docBody.scrollTop || 0) - offset.y;
3272
				if(evt.type == "mouseover"){
3273
					evt.relatedTarget = evt.fromElement;
3274
				}
3275
				if(evt.type == "mouseout"){
3276
					evt.relatedTarget = evt.toElement;
3277
				}
3278
				evt.stopPropagation = del._stopPropagation;
3279
				evt.preventDefault = del._preventDefault;
3280
				return del._fixKeys(evt);
3281
			},
3282
			_fixKeys: function(evt){
3283
				switch(evt.type){
3284
					case "keypress":
3285
						var c = ("charCode" in evt ? evt.charCode : evt.keyCode);
3286
						if (c==10){
3287
							// CTRL-ENTER is CTRL-ASCII(10) on IE, but CTRL-ENTER on Mozilla
3288
							c=0;
3289
							evt.keyCode = 13;
3290
						}else if(c==13||c==27){
3291
							c=0; // Mozilla considers ENTER and ESC non-printable
3292
						}else if(c==3){
3293
							c=99; // Mozilla maps CTRL-BREAK to CTRL-c
3294
						}
3295
						// Mozilla sets keyCode to 0 when there is a charCode
3296
						// but that stops the event on IE.
3297
						evt.charCode = c;
3298
						del._setKeyChar(evt);
3299
						break;
3300
				}
3301
				return evt;
3302
			},
3303
			// some ctrl-key combinations (mostly w/punctuation) do not emit a char code in IE
3304
			// we map those virtual key codes to ascii here
3305
			// not valid for all (non-US) keyboards, so maybe we shouldn't bother
3306
			_punctMap: {
3307
				106:42,
3308
				111:47,
3309
				186:59,
3310
				187:43,
3311
				188:44,
3312
				189:45,
3313
				190:46,
3314
				191:47,
3315
				192:96,
3316
				219:91,
3317
				220:92,
3318
				221:93,
3319
				222:39
3320
			},
3321
			_stealthKeyDown: function(evt){
3322
				// IE doesn't fire keypress for most non-printable characters.
3323
				// other browsers do, we simulate it here.
3324
				var kp=evt.currentTarget.onkeypress;
3325
				// only works if kp exists and is a dispatcher
3326
				if(!kp||!kp._listeners)return;
3327
				// munge key/charCode
3328
				var k=evt.keyCode;
3329
				// These are Windows Virtual Key Codes
3330
				// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp
3331
				var unprintable = (k!=13)&&(k!=32)&&(k!=27)&&(k<48||k>90)&&(k<96||k>111)&&(k<186||k>192)&&(k<219||k>222);
3332
				// synthesize keypress for most unprintables and CTRL-keys
3333
				if(unprintable||evt.ctrlKey){
3334
					var c = (unprintable ? 0 : k);
3335
					if(evt.ctrlKey){
3336
						if(k==3 || k==13){
3337
							return; // IE will post CTRL-BREAK, CTRL-ENTER as keypress natively
3338
						}else if(c>95 && c<106){
3339
							c -= 48; // map CTRL-[numpad 0-9] to ASCII
3340
						}else if((!evt.shiftKey)&&(c>=65&&c<=90)){
3341
							c += 32; // map CTRL-[A-Z] to lowercase
3342
						}else{
3343
							c = del._punctMap[c] || c; // map other problematic CTRL combinations to ASCII
3344
						}
3345
					}
3346
					// simulate a keypress event
3347
					var faux = del._synthesizeEvent(evt, {type: 'keypress', faux: true, charCode: c});
3348
					kp.call(evt.currentTarget, faux);
3349
					evt.cancelBubble = faux.cancelBubble;
3350
					evt.returnValue = faux.returnValue;
3351
					_trySetKeyCode(evt, faux.keyCode);
3352
				}
3353
			},
3354
			// Called in Event scope
3355
			_stopPropagation: function(){
3356
				this.cancelBubble = true;
3357
			},
3358
			_preventDefault: function(){
3359
				// Setting keyCode to 0 is the only way to prevent certain keypresses (namely
3360
				// ctrl-combinations that correspond to menu accelerator keys).
3361
				// Otoh, it prevents upstream listeners from getting this information
3362
				// Try to split the difference here by clobbering keyCode only for ctrl
3363
				// combinations. If you still need to access the key upstream, bubbledKeyCode is
3364
				// provided as a workaround.
3365
				this.bubbledKeyCode = this.keyCode;
3366
				if(this.ctrlKey){_trySetKeyCode(this, 0);}
3367
				this.returnValue = false;
3368
			}
3369
		});
3370
 
3371
		// override stopEvent for IE
3372
		dojo.stopEvent = function(evt){
3373
			evt = evt || window.event;
3374
			del._stopPropagation.call(evt);
3375
			del._preventDefault.call(evt);
3376
		}
3377
	}
3378
 
3379
	del._synthesizeEvent = function(evt, props){
3380
			var faux = dojo.mixin({}, evt, props);
3381
			del._setKeyChar(faux);
3382
			// FIXME: would prefer to use dojo.hitch: dojo.hitch(evt, evt.preventDefault);
3383
			// but it throws an error when preventDefault is invoked on Safari
3384
			// does Event.preventDefault not support "apply" on Safari?
3385
			faux.preventDefault = function(){ evt.preventDefault(); };
3386
			faux.stopPropagation = function(){ evt.stopPropagation(); };
3387
			return faux;
3388
	}
3389
 
3390
	// Opera event normalization
3391
	if(dojo.isOpera){
3392
		dojo.mixin(del, {
3393
			_fixEvent: function(evt, sender){
3394
				switch(evt.type){
3395
					case "keypress":
3396
						var c = evt.which;
3397
						if(c==3){
3398
							c=99; // Mozilla maps CTRL-BREAK to CTRL-c
3399
						}
3400
						// can't trap some keys at all, like INSERT and DELETE
3401
						// there is no differentiating info between DELETE and ".", or INSERT and "-"
3402
						c = ((c<41)&&(!evt.shiftKey) ? 0 : c);
3403
						if((evt.ctrlKey)&&(!evt.shiftKey)&&(c>=65)&&(c<=90)){
3404
							// lowercase CTRL-[A-Z] keys
3405
							c += 32;
3406
						}
3407
						return del._synthesizeEvent(evt, { charCode: c });
3408
				}
3409
				return evt;
3410
			}
3411
		});
3412
	}
3413
 
3414
	// Safari event normalization
3415
	if(dojo.isSafari){
3416
		dojo.mixin(del, {
3417
			_fixEvent: function(evt, sender){
3418
				switch(evt.type){
3419
					case "keypress":
3420
						var c = evt.charCode, s = evt.shiftKey, k = evt.keyCode;
3421
						// FIXME: This is a hack, suggest we rethink keyboard strategy.
3422
						// Arrow and page keys have 0 "keyCode" in keypress events.on Safari for Windows
3423
						k = k || identifierMap[evt.keyIdentifier] || 0;
3424
						if(evt.keyIdentifier=="Enter"){
3425
							c = 0; // differentiate Enter from CTRL-m (both code 13)
3426
						}else if((evt.ctrlKey)&&(c>0)&&(c<27)){
3427
							c += 96; // map CTRL-[A-Z] codes to ASCII
3428
						} else if (c==dojo.keys.SHIFT_TAB) {
3429
							c = dojo.keys.TAB; // morph SHIFT_TAB into TAB + shiftKey: true
3430
							s = true;
3431
						} else {
3432
							c = (c>=32 && c<63232 ? c : 0); // avoid generating keyChar for non-printables
3433
						}
3434
						return del._synthesizeEvent(evt, {charCode: c, shiftKey: s, keyCode: k});
3435
				}
3436
				return evt;
3437
			}
3438
		});
3439
 
3440
		dojo.mixin(dojo.keys, {
3441
			SHIFT_TAB: 25,
3442
			UP_ARROW: 63232,
3443
			DOWN_ARROW: 63233,
3444
			LEFT_ARROW: 63234,
3445
			RIGHT_ARROW: 63235,
3446
			F1: 63236,
3447
			F2: 63237,
3448
			F3: 63238,
3449
			F4: 63239,
3450
			F5: 63240,
3451
			F6: 63241,
3452
			F7: 63242,
3453
			F8: 63243,
3454
			F9: 63244,
3455
			F10: 63245,
3456
			F11: 63246,
3457
			F12: 63247,
3458
			PAUSE: 63250,
3459
			DELETE: 63272,
3460
			HOME: 63273,
3461
			END: 63275,
3462
			PAGE_UP: 63276,
3463
			PAGE_DOWN: 63277,
3464
			INSERT: 63302,
3465
			PRINT_SCREEN: 63248,
3466
			SCROLL_LOCK: 63249,
3467
			NUM_LOCK: 63289
3468
		});
3469
		var dk = dojo.keys, identifierMap = { "Up": dk.UP_ARROW, "Down": dk.DOWN_ARROW, "Left": dk.LEFT_ARROW, "Right": dk.RIGHT_ARROW, "PageUp": dk.PAGE_UP, "PageDown": dk.PAGE_DOWN };
3470
	}
3471
})();
3472
 
3473
if(dojo.isIE){
3474
	// keep this out of the closure
3475
	// closing over 'iel' or 'ieh' b0rks leak prevention
3476
	// ls[i] is an index into the master handler array
3477
	dojo._getIeDispatcher = function(){
3478
		return function(){
3479
			var ap=Array.prototype, h=dojo._ie_listener.handlers, c=arguments.callee, ls=c._listeners, t=h[c.target];
3480
			// return value comes from original target function
3481
			var r = t && t.apply(this, arguments);
3482
			// invoke listeners after target function
3483
			for(var i in ls){
3484
				if(!(i in ap)){
3485
					h[ls[i]].apply(this, arguments);
3486
				}
3487
			}
3488
			return r;
3489
		}
3490
	}
3491
	// keep this out of the closure to reduce RAM allocation
3492
	dojo._event_listener._fixCallback = function(fp){
3493
		var f = dojo._event_listener._fixEvent;
3494
		return function(e){ return fp.call(this, f(e, this)); };
3495
	}
3496
}
3497
 
3498
}
3499
 
3500
if(!dojo._hasResource["dojo._base.html"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
3501
dojo._hasResource["dojo._base.html"] = true;
3502
 
3503
dojo.provide("dojo._base.html");
3504
 
3505
// FIXME: need to add unit tests for all the semi-public methods
3506
 
3507
try{
3508
	document.execCommand("BackgroundImageCache", false, true);
3509
}catch(e){
3510
	// sane browsers don't have cache "issues"
3511
}
3512
 
3513
// =============================
3514
// DOM Functions
3515
// =============================
3516
 
3517
/*=====
3518
dojo.byId = function(id, doc){
3519
	//	summary:
3520
	//		similar to other library's "$" function, takes a
3521
	//		string representing a DOM id or a DomNode
3522
	//		and returns the corresponding DomNode. If a Node is
3523
	//		passed, this function is a no-op. Returns a
3524
	//		single DOM node or null, working around several
3525
	//		browser-specific bugs to do so.
3526
	//	id: String|DOMNode
3527
	//	 	DOM id or DOM Node
3528
	//	doc: DocumentElement
3529
	//		Document to work in. Defaults to the current value of
3530
	//		dojo.doc.  Can be used to retreive
3531
	//		node references from other documents.
3532
=====*/
3533
if(dojo.isIE || dojo.isOpera){
3534
	dojo.byId = function(id, doc){
3535
		if(dojo.isString(id)){
3536
			var _d = doc || dojo.doc;
3537
			var te = _d.getElementById(id);
3538
			// attributes.id.value is better than just id in case the
3539
			// user has a name=id inside a form
3540
			if(te && te.attributes.id.value == id){
3541
				return te;
3542
			}else{
3543
				var eles = _d.all[id];
3544
				if(!eles){ return; }
3545
				if(!eles.length){ return eles; }
3546
				// if more than 1, choose first with the correct id
3547
				var i=0;
3548
				while((te=eles[i++])){
3549
					if(te.attributes.id.value == id){ return te; }
3550
				}
3551
			}
3552
		}else{
3553
			return id; // DomNode
3554
		}
3555
	}
3556
}else{
3557
	dojo.byId = function(id, doc){
3558
		if(dojo.isString(id)){
3559
			return (doc || dojo.doc).getElementById(id);
3560
		}else{
3561
			return id; // DomNode
3562
		}
3563
	}
3564
}
3565
/*=====
3566
}
3567
=====*/
3568
 
3569
(function(){
3570
	/*
3571
	dojo.createElement = function(obj, parent, position){
3572
		// TODO: need to finish this!
3573
	}
3574
	*/
3575
 
3576
	var _destroyContainer = null;
3577
	dojo._destroyElement = function(/*String||DomNode*/node){
3578
		// summary:
3579
		//		removes node from its parent, clobbers it and all of its
3580
		//		children.
3581
		//	node:
3582
		//		the element to be destroyed, either as an ID or a reference
3583
 
3584
		node = dojo.byId(node);
3585
		try{
3586
			if(!_destroyContainer){
3587
				_destroyContainer = document.createElement("div");
3588
			}
3589
			_destroyContainer.appendChild(node.parentNode ? node.parentNode.removeChild(node) : node);
3590
			// NOTE: see http://trac.dojotoolkit.org/ticket/2931. This may be a bug and not a feature
3591
			_destroyContainer.innerHTML = "";
3592
		}catch(e){
3593
			/* squelch */
3594
		}
3595
	};
3596
 
3597
	dojo.isDescendant = function(/*DomNode|String*/node, /*DomNode|String*/ancestor){
3598
		//	summary:
3599
		//		Returns true if node is a descendant of ancestor
3600
		//	node: id or node reference to test
3601
		//	ancestor: id or node reference of potential parent to test against
3602
		try{
3603
			node = dojo.byId(node);
3604
			ancestor = dojo.byId(ancestor);
3605
			while(node){
3606
				if(node === ancestor){
3607
					return true; // Boolean
3608
				}
3609
				node = node.parentNode;
3610
			}
3611
		}catch(e){ return -1; /* squelch */ }
3612
		return false; // Boolean
3613
	};
3614
 
3615
	dojo.setSelectable = function(/*DomNode|String*/node, /*Boolean*/selectable){
3616
		//	summary: enable or disable selection on a node
3617
		//	node:
3618
		//		id or reference to node
3619
		//	selectable:
3620
		node = dojo.byId(node);
3621
		if(dojo.isMozilla){
3622
			node.style.MozUserSelect = selectable ? "" : "none";
3623
		}else if(dojo.isKhtml){
3624
			node.style.KhtmlUserSelect = selectable ? "auto" : "none";
3625
		}else if(dojo.isIE){
3626
			node.unselectable = selectable ? "" : "on";
3627
			dojo.query("*", node).forEach(function(descendant){
3628
				descendant.unselectable = selectable ? "" : "on";
3629
			});
3630
		}
3631
		//FIXME: else?  Opera?
3632
	};
3633
 
3634
	var _insertBefore = function(/*Node*/node, /*Node*/ref){
3635
		ref.parentNode.insertBefore(node, ref);
3636
		return true;	//	boolean
3637
	}
3638
 
3639
	var _insertAfter = function(/*Node*/node, /*Node*/ref){
3640
		//	summary:
3641
		//		Try to insert node after ref
3642
		var pn = ref.parentNode;
3643
		if(ref == pn.lastChild){
3644
			pn.appendChild(node);
3645
		}else{
3646
			return _insertBefore(node, ref.nextSibling);	//	boolean
3647
		}
3648
		return true;	//	boolean
3649
	}
3650
 
3651
	dojo.place = function(/*String|DomNode*/node, /*String|DomNode*/refNode, /*String|Number*/position){
3652
		//	summary:
3653
		//		attempt to insert node in relation to ref based on position
3654
		//	node:
3655
		//		id or reference to node to place relative to refNode
3656
		//	refNode:
3657
		//		id or reference of node to use as basis for placement
3658
		//	position:
3659
		//		string noting the position of node relative to refNode or a
3660
		//		number indicating the location in the childNodes collection of
3661
		//		refNode. Accepted string values are:
3662
		//			* before
3663
		//			* after
3664
		//			* first
3665
		//			* last
3666
		//		"first" and "last" indicate positions as children of refNode.
3667
 
3668
		// FIXME: need to write tests for this!!!!
3669
		if(!node || !refNode || position === undefined){
3670
			return false;	//	boolean
3671
		}
3672
		node = dojo.byId(node);
3673
		refNode = dojo.byId(refNode);
3674
		if(typeof position == "number"){
3675
			var cn = refNode.childNodes;
3676
			if((position == 0 && cn.length == 0) ||
3677
				cn.length == position){
3678
				refNode.appendChild(node); return true;
3679
			}
3680
			if(position == 0){
3681
				return _insertBefore(node, refNode.firstChild);
3682
			}
3683
			return _insertAfter(node, cn[position-1]);
3684
		}
3685
		switch(position.toLowerCase()){
3686
			case "before":
3687
				return _insertBefore(node, refNode);	//	boolean
3688
			case "after":
3689
				return _insertAfter(node, refNode);		//	boolean
3690
			case "first":
3691
				if(refNode.firstChild){
3692
					return _insertBefore(node, refNode.firstChild);	//	boolean
3693
				}else{
3694
					refNode.appendChild(node);
3695
					return true;	//	boolean
3696
				}
3697
				break;
3698
			default: // aka: last
3699
				refNode.appendChild(node);
3700
				return true;	//	boolean
3701
		}
3702
	}
3703
 
3704
	// Box functions will assume this model.
3705
	// On IE/Opera, BORDER_BOX will be set if the primary document is in quirks mode.
3706
	// Can be set to change behavior of box setters.
3707
 
3708
	// can be either:
3709
	//	"border-box"
3710
	//	"content-box" (default)
3711
	dojo.boxModel = "content-box";
3712
 
3713
	// We punt per-node box mode testing completely.
3714
	// If anybody cares, we can provide an additional (optional) unit
3715
	// that overrides existing code to include per-node box sensitivity.
3716
 
3717
	// Opera documentation claims that Opera 9 uses border-box in BackCompat mode.
3718
	// but experiments (Opera 9.10.8679 on Windows Vista) indicate that it actually continues to use content-box.
3719
	// IIRC, earlier versions of Opera did in fact use border-box.
3720
	// Opera guys, this is really confusing. Opera being broken in quirks mode is not our fault.
3721
 
3722
	if(dojo.isIE /*|| dojo.isOpera*/){
3723
		var _dcm = document.compatMode;
3724
		// client code may have to adjust if compatMode varies across iframes
3725
		dojo.boxModel = (_dcm=="BackCompat")||(_dcm=="QuirksMode")||(dojo.isIE<6) ? "border-box" : "content-box";
3726
	}
3727
 
3728
	// =============================
3729
	// Style Functions
3730
	// =============================
3731
 
3732
	// getComputedStyle drives most of the style code.
3733
	// Wherever possible, reuse the returned object.
3734
	//
3735
	// API functions below that need to access computed styles accept an
3736
	// optional computedStyle parameter.
3737
	//
3738
	// If this parameter is omitted, the functions will call getComputedStyle themselves.
3739
	//
3740
	// This way, calling code can access computedStyle once, and then pass the reference to
3741
	// multiple API functions.
3742
	//
3743
	// This is a faux declaration to take pity on the doc tool
3744
 
3745
/*=====
3746
	dojo.getComputedStyle = function(node){
3747
		//	summary:
3748
		//		Returns a "computed style" object.
3749
		//	description:
3750
		//		get "computed style" object which can be used to gather
3751
		//		information about the current state of the rendered node.
3752
		//
3753
		//		Note that this may behave differently on different browsers.
3754
		//		Values may have different formats and value encodings across
3755
		//		browsers.
3756
		//
3757
		//		Use the dojo.style() method for more consistent (pixelized)
3758
		//		return values.
3759
		//	node: DOMNode
3760
		//		a reference to a DOM node. Does NOT support taking an
3761
		//		ID string for speed reasons.
3762
		//	example:
3763
		//	|	dojo.getComputedStyle(dojo.byId('foo')).borderWidth;
3764
		return; // CSS2Properties
3765
	}
3766
=====*/
3767
 
3768
	var gcs, dv = document.defaultView;
3769
	if(dojo.isSafari){
3770
		gcs = function(/*DomNode*/node){
3771
			var s = dv.getComputedStyle(node, null);
3772
			if(!s && node.style){
3773
				node.style.display = "";
3774
				s = dv.getComputedStyle(node, null);
3775
			}
3776
			return s || {};
3777
		};
3778
	}else if(dojo.isIE){
3779
		gcs = function(node){
3780
			return node.currentStyle;
3781
		};
3782
	}else{
3783
		gcs = function(node){
3784
			return dv.getComputedStyle(node, null);
3785
		};
3786
	}
3787
	dojo.getComputedStyle = gcs;
3788
 
3789
	if(!dojo.isIE){
3790
		dojo._toPixelValue = function(element, value){
3791
			// style values can be floats, client code may want
3792
			// to round for integer pixels.
3793
			return parseFloat(value) || 0;
3794
		}
3795
	}else{
3796
		dojo._toPixelValue = function(element, avalue){
3797
			if(!avalue){ return 0; }
3798
			// on IE7, medium is usually 4 pixels
3799
			if(avalue=="medium"){ return 4; }
3800
			// style values can be floats, client code may
3801
			// want to round this value for integer pixels.
3802
			if(avalue.slice && (avalue.slice(-2)=='px')){ return parseFloat(avalue); }
3803
			with(element){
3804
				var sLeft = style.left;
3805
				var rsLeft = runtimeStyle.left;
3806
				runtimeStyle.left = currentStyle.left;
3807
				try{
3808
					// 'avalue' may be incompatible with style.left, which can cause IE to throw
3809
					// this has been observed for border widths using "thin", "medium", "thick" constants
3810
					// those particular constants could be trapped by a lookup
3811
					// but perhaps there are more
3812
					style.left = avalue;
3813
					avalue = style.pixelLeft;
3814
				}catch(e){
3815
					avalue = 0;
3816
				}
3817
				style.left = sLeft;
3818
				runtimeStyle.left = rsLeft;
3819
			}
3820
			return avalue;
3821
		}
3822
	}
3823
 
3824
	// FIXME: there opacity quirks on FF that we haven't ported over. Hrm.
3825
	/*=====
3826
	dojo._getOpacity = function(node){
3827
			//	summary:
3828
			//		Returns the current opacity of the passed node as a
3829
			//		floating-point value between 0 and 1.
3830
			//	node: DomNode
3831
			//		a reference to a DOM node. Does NOT support taking an
3832
			//		ID string for speed reasons.
3833
			//	return: Number between 0 and 1
3834
	}
3835
	=====*/
3836
 
3837
	dojo._getOpacity = (dojo.isIE ? function(node){
3838
			try{
3839
				return (node.filters.alpha.opacity / 100); // Number
3840
			}catch(e){
3841
				return 1; // Number
3842
			}
3843
		} : function(node){
3844
			return dojo.getComputedStyle(node).opacity;
3845
		}
3846
	);
3847
 
3848
	/*=====
3849
	dojo._setOpacity = function(node, opacity){
3850
			//	summary:
3851
			//		set the opacity of the passed node portably. Returns the
3852
			//		new opacity of the node.
3853
			//	node: DOMNode
3854
			//		a reference to a DOM node. Does NOT support taking an
3855
			//		ID string for performance reasons.
3856
			//	opacity: Number
3857
			//		A Number between 0 and 1. 0 specifies transparent.
3858
			//	return: Number between 0 and 1
3859
	}
3860
	=====*/
3861
 
3862
	dojo._setOpacity = (dojo.isIE ? function(/*DomNode*/node, /*Number*/opacity){
3863
			if(opacity == 1){
3864
				// on IE7 Alpha(Filter opacity=100) makes text look fuzzy so remove it altogether (bug #2661)
3865
				node.style.cssText = node.style.cssText.replace(/FILTER:[^;]*;/i, "");
3866
				if(node.nodeName.toLowerCase() == "tr"){
3867
					dojo.query("> td", node).forEach(function(i){
3868
						i.style.cssText = i.style.cssText.replace(/FILTER:[^;]*;/i, "");
3869
					});
3870
				}
3871
			}else{
3872
				var o = "Alpha(Opacity="+(opacity*100)+")";
3873
				node.style.filter = o;
3874
			}
3875
			if(node.nodeName.toLowerCase() == "tr"){
3876
				dojo.query("> td", node).forEach(function(i){
3877
					i.style.filter = o;
3878
				});
3879
			}
3880
			return opacity;
3881
		} : function(node, opacity){
3882
			return node.style.opacity = opacity;
3883
		}
3884
	);
3885
 
3886
	var _pixelNamesCache = {
3887
		width: true, height: true, left: true, top: true
3888
	};
3889
	var _toStyleValue = function(node, type, value){
3890
		type = type.toLowerCase();
3891
		if(_pixelNamesCache[type] === true){
3892
			return dojo._toPixelValue(node, value)
3893
		}else if(_pixelNamesCache[type] === false){
3894
			return value;
3895
		}else{
3896
			if(dojo.isOpera && type == "cssText"){
3897
				// FIXME: add workaround for #2855 here
3898
			}
3899
			if(
3900
				(type.indexOf("margin") >= 0) ||
3901
				// (type.indexOf("border") >= 0) ||
3902
				(type.indexOf("padding") >= 0) ||
3903
				(type.indexOf("width") >= 0) ||
3904
				(type.indexOf("height") >= 0) ||
3905
				(type.indexOf("max") >= 0) ||
3906
				(type.indexOf("min") >= 0) ||
3907
				(type.indexOf("offset") >= 0)
3908
			){
3909
				_pixelNamesCache[type] = true;
3910
				return dojo._toPixelValue(node, value)
3911
			}else{
3912
				_pixelNamesCache[type] = false;
3913
				return value;
3914
			}
3915
		}
3916
	}
3917
 
3918
	// public API
3919
 
3920
	dojo.style = function(/*DomNode|String*/ node, /*String*/style, /*String?*/value){
3921
		//	summary:
3922
		//		gets or sets a style property on node. If 2 arguments are
3923
		//		passed, acts as a getter. If value is passed, acts as a setter
3924
		//		for the property.
3925
		//	node:
3926
		//		id or reference to node to get/set style for
3927
		//	style:
3928
		//		the style property to set in DOM-accessor format
3929
		//		("borderWidth", not "border-width").
3930
		//	value:
3931
		//		optional. If passed, sets value on the node for style, handling
3932
		//		cross-browser concerns.
3933
		var n=dojo.byId(node), args=arguments.length, op=(style=="opacity");
3934
		if(args==3){
3935
			return op ? dojo._setOpacity(n, value) : n.style[style] = value; /*Number*/
3936
		}
3937
		if(args==2 && op){
3938
			return dojo._getOpacity(n);
3939
		}
3940
		var s = dojo.getComputedStyle(n);
3941
		return (args == 1) ? s : _toStyleValue(n, style, s[style]); /* CSS2Properties||String||Number */
3942
	}
3943
 
3944
	// =============================
3945
	// Box Functions
3946
	// =============================
3947
 
3948
	dojo._getPadExtents = function(/*DomNode*/n, /*Object*/computedStyle){
3949
		//	summary:
3950
		// 		Returns object with special values specifically useful for node
3951
		// 		fitting.
3952
		// 			l/t = left/top padding (respectively)
3953
		// 			w = the total of the left and right padding
3954
		// 			h = the total of the top and bottom padding
3955
		//		If 'node' has position, l/t forms the origin for child nodes.
3956
		//		The w/h are used for calculating boxes.
3957
		//		Normally application code will not need to invoke this
3958
		//		directly, and will use the ...box... functions instead.
3959
		var
3960
			s=computedStyle||gcs(n),
3961
			px=dojo._toPixelValue,
3962
			l=px(n, s.paddingLeft),
3963
			t=px(n, s.paddingTop);
3964
		return {
3965
			l: l,
3966
			t: t,
3967
			w: l+px(n, s.paddingRight),
3968
			h: t+px(n, s.paddingBottom)
3969
		};
3970
	}
3971
 
3972
	dojo._getBorderExtents = function(/*DomNode*/n, /*Object*/computedStyle){
3973
		//	summary:
3974
		//		returns an object with properties useful for noting the border
3975
		//		dimensions.
3976
		// 			l/t = the sum of left/top border (respectively)
3977
		//			w = the sum of the left and right border
3978
		//			h = the sum of the top and bottom border
3979
		//		The w/h are used for calculating boxes.
3980
		//		Normally application code will not need to invoke this
3981
		//		directly, and will use the ...box... functions instead.
3982
		var
3983
			ne='none',
3984
			px=dojo._toPixelValue,
3985
			s=computedStyle||gcs(n),
3986
			bl=(s.borderLeftStyle!=ne ? px(n, s.borderLeftWidth) : 0),
3987
			bt=(s.borderTopStyle!=ne ? px(n, s.borderTopWidth) : 0);
3988
		return {
3989
			l: bl,
3990
			t: bt,
3991
			w: bl + (s.borderRightStyle!=ne ? px(n, s.borderRightWidth) : 0),
3992
			h: bt + (s.borderBottomStyle!=ne ? px(n, s.borderBottomWidth) : 0)
3993
		};
3994
	}
3995
 
3996
	dojo._getPadBorderExtents = function(/*DomNode*/n, /*Object*/computedStyle){
3997
		//	summary:
3998
		//		returns object with properties useful for box fitting with
3999
		//		regards to padding.
4000
		//			l/t = the sum of left/top padding and left/top border (respectively)
4001
		//			w = the sum of the left and right padding and border
4002
		//			h = the sum of the top and bottom padding and border
4003
		//		The w/h are used for calculating boxes.
4004
		//		Normally application code will not need to invoke this
4005
		//		directly, and will use the ...box... functions instead.
4006
		var
4007
			s=computedStyle||gcs(n),
4008
			p=dojo._getPadExtents(n, s),
4009
			b=dojo._getBorderExtents(n, s);
4010
		return {
4011
			l: p.l + b.l,
4012
			t: p.t + b.t,
4013
			w: p.w + b.w,
4014
			h: p.h + b.h
4015
		};
4016
	}
4017
 
4018
	dojo._getMarginExtents = function(n, computedStyle){
4019
		//	summary:
4020
		//		returns object with properties useful for box fitting with
4021
		//		regards to box margins (i.e., the outer-box).
4022
		//			l/t = marginLeft, marginTop, respectively
4023
		//			w = total width, margin inclusive
4024
		//			h = total height, margin inclusive
4025
		//		The w/h are used for calculating boxes.
4026
		//		Normally application code will not need to invoke this
4027
		//		directly, and will use the ...box... functions instead.
4028
		var
4029
			s=computedStyle||gcs(n),
4030
			px=dojo._toPixelValue,
4031
			l=px(n, s.marginLeft),
4032
			t=px(n, s.marginTop),
4033
			r=px(n, s.marginRight),
4034
			b=px(n, s.marginBottom);
4035
		if (dojo.isSafari && (s.position != "absolute")){
4036
			// FIXME: Safari's version of the computed right margin
4037
			// is the space between our right edge and the right edge
4038
			// of our offsetParent.
4039
			// What we are looking for is the actual margin value as
4040
			// determined by CSS.
4041
			// Hack solution is to assume left/right margins are the same.
4042
			r = l;
4043
		}
4044
		return {
4045
			l: l,
4046
			t: t,
4047
			w: l+r,
4048
			h: t+b
4049
		};
4050
	}
4051
 
4052
	// Box getters work in any box context because offsetWidth/clientWidth
4053
	// are invariant wrt box context
4054
	//
4055
	// They do *not* work for display: inline objects that have padding styles
4056
	// because the user agent ignores padding (it's bogus styling in any case)
4057
	//
4058
	// Be careful with IMGs because they are inline or block depending on
4059
	// browser and browser mode.
4060
 
4061
	// Although it would be easier to read, there are not separate versions of
4062
	// _getMarginBox for each browser because:
4063
	// 1. the branching is not expensive
4064
	// 2. factoring the shared code wastes cycles (function call overhead)
4065
	// 3. duplicating the shared code wastes bytes
4066
 
4067
	dojo._getMarginBox = function(/*DomNode*/node, /*Object*/computedStyle){
4068
		// summary:
4069
		//		returns an object that encodes the width, height, left and top
4070
		//		positions of the node's margin box.
4071
		var s = computedStyle||gcs(node), me = dojo._getMarginExtents(node, s);
4072
		var	l = node.offsetLeft - me.l,	t = node.offsetTop - me.t;
4073
		if(dojo.isMoz){
4074
			// Mozilla:
4075
			// If offsetParent has a computed overflow != visible, the offsetLeft is decreased
4076
			// by the parent's border.
4077
			// We don't want to compute the parent's style, so instead we examine node's
4078
			// computed left/top which is more stable.
4079
			var sl = parseFloat(s.left), st = parseFloat(s.top);
4080
			if(!isNaN(sl) && !isNaN(st)){
4081
				l = sl, t = st;
4082
			}else{
4083
				// If child's computed left/top are not parseable as a number (e.g. "auto"), we
4084
				// have no choice but to examine the parent's computed style.
4085
				var p = node.parentNode;
4086
				if(p && p.style){
4087
					var pcs = gcs(p);
4088
					if(pcs.overflow != "visible"){
4089
						var be = dojo._getBorderExtents(p, pcs);
4090
						l += be.l, t += be.t;
4091
					}
4092
				}
4093
			}
4094
		}else if(dojo.isOpera){
4095
			// On Opera, offsetLeft includes the parent's border
4096
			var p = node.parentNode;
4097
			if(p){
4098
				var be = dojo._getBorderExtents(p);
4099
				l -= be.l, t -= be.t;
4100
			}
4101
		}
4102
		return {
4103
			l: l,
4104
			t: t,
4105
			w: node.offsetWidth + me.w,
4106
			h: node.offsetHeight + me.h
4107
		};
4108
	}
4109
 
4110
	dojo._getContentBox = function(node, computedStyle){
4111
		// summary:
4112
		//		Returns an object that encodes the width, height, left and top
4113
		//		positions of the node's content box, irrespective of the
4114
		//		current box model.
4115
 
4116
		// clientWidth/Height are important since the automatically account for scrollbars
4117
		// fallback to offsetWidth/Height for special cases (see #3378)
4118
		var s=computedStyle||gcs(node), pe=dojo._getPadExtents(node, s), be=dojo._getBorderExtents(node, s), w=node.clientWidth, h;
4119
		if(!w){
4120
			w=node.offsetWidth, h=node.offsetHeight;
4121
		}else{
4122
			h=node.clientHeight, be.w = be.h = 0;
4123
		}
4124
		// On Opera, offsetLeft includes the parent's border
4125
		if(dojo.isOpera){ pe.l += be.l; pe.t += be.t; };
4126
		return {
4127
			l: pe.l,
4128
			t: pe.t,
4129
			w: w - pe.w - be.w,
4130
			h: h - pe.h - be.h
4131
		};
4132
	}
4133
 
4134
	dojo._getBorderBox = function(node, computedStyle){
4135
		var s=computedStyle||gcs(node), pe=dojo._getPadExtents(node, s), cb=dojo._getContentBox(node, s);
4136
		return {
4137
			l: cb.l - pe.l,
4138
			t: cb.t - pe.t,
4139
			w: cb.w + pe.w,
4140
			h: cb.h + pe.h
4141
		};
4142
	}
4143
 
4144
	// Box setters depend on box context because interpretation of width/height styles
4145
	// vary wrt box context.
4146
	//
4147
	// The value of dojo.boxModel is used to determine box context.
4148
	// dojo.boxModel can be set directly to change behavior.
4149
	//
4150
	// Beware of display: inline objects that have padding styles
4151
	// because the user agent ignores padding (it's a bogus setup anyway)
4152
	//
4153
	// Be careful with IMGs because they are inline or block depending on
4154
	// browser and browser mode.
4155
	//
4156
	// Elements other than DIV may have special quirks, like built-in
4157
	// margins or padding, or values not detectable via computedStyle.
4158
	// In particular, margins on TABLE do not seems to appear
4159
	// at all in computedStyle on Mozilla.
4160
 
4161
	dojo._setBox = function(/*DomNode*/node, /*Number?*/l, /*Number?*/t, /*Number?*/w, /*Number?*/h, /*String?*/u){
4162
		//	summary:
4163
		//		sets width/height/left/top in the current (native) box-model
4164
		//		dimentions. Uses the unit passed in u.
4165
		//	node: DOM Node reference. Id string not supported for performance reasons.
4166
		//	l: optional. left offset from parent.
4167
		//	t: optional. top offset from parent.
4168
		//	w: optional. width in current box model.
4169
		//	h: optional. width in current box model.
4170
		//	u: optional. unit measure to use for other measures. Defaults to "px".
4171
		u = u || "px";
4172
		with(node.style){
4173
			if(!isNaN(l)){ left = l+u; }
4174
			if(!isNaN(t)){ top = t+u; }
4175
			if(w>=0){ width = w+u; }
4176
			if(h>=0){ height = h+u; }
4177
		}
4178
	}
4179
 
4180
	dojo._usesBorderBox = function(/*DomNode*/node){
4181
		//	summary:
4182
		//		True if the node uses border-box layout.
4183
 
4184
		// We could test the computed style of node to see if a particular box
4185
		// has been specified, but there are details and we choose not to bother.
4186
		var n = node.tagName;
4187
		// For whatever reason, TABLE and BUTTON are always border-box by default.
4188
		// If you have assigned a different box to either one via CSS then
4189
		// box functions will break.
4190
		return dojo.boxModel=="border-box" || n=="TABLE" || n=="BUTTON"; // boolean
4191
	}
4192
 
4193
	dojo._setContentSize = function(/*DomNode*/node, /*Number*/widthPx, /*Number*/heightPx, /*Object*/computedStyle){
4194
		//	summary:
4195
		//		Sets the size of the node's contents, irrespective of margins,
4196
		//		padding, or borders.
4197
		var bb = dojo._usesBorderBox(node);
4198
		if(bb){
4199
			var pb = dojo._getPadBorderExtents(node, computedStyle);
4200
			if(widthPx>=0){ widthPx += pb.w; }
4201
			if(heightPx>=0){ heightPx += pb.h; }
4202
		}
4203
		dojo._setBox(node, NaN, NaN, widthPx, heightPx);
4204
	}
4205
 
4206
	dojo._setMarginBox = function(/*DomNode*/node, 	/*Number?*/leftPx, /*Number?*/topPx,
4207
													/*Number?*/widthPx, /*Number?*/heightPx,
4208
													/*Object*/computedStyle){
4209
		//	summary:
4210
		//		sets the size of the node's margin box and palcement
4211
		//		(left/top), irrespective of box model. Think of it as a
4212
		//		passthrough to dojo._setBox that handles box-model vagaries for
4213
		//		you.
4214
 
4215
		var s = computedStyle || dojo.getComputedStyle(node);
4216
		// Some elements have special padding, margin, and box-model settings.
4217
		// To use box functions you may need to set padding, margin explicitly.
4218
		// Controlling box-model is harder, in a pinch you might set dojo.boxModel.
4219
		var bb=dojo._usesBorderBox(node),
4220
				pb=bb ? _nilExtents : dojo._getPadBorderExtents(node, s),
4221
				mb=dojo._getMarginExtents(node, s);
4222
		if(widthPx>=0){	widthPx = Math.max(widthPx - pb.w - mb.w, 0); }
4223
		if(heightPx>=0){ heightPx = Math.max(heightPx - pb.h - mb.h, 0); }
4224
		dojo._setBox(node, leftPx, topPx, widthPx, heightPx);
4225
	}
4226
 
4227
	var _nilExtents = { l:0, t:0, w:0, h:0 };
4228
 
4229
	// public API
4230
 
4231
	dojo.marginBox = function(/*DomNode|String*/node, /*Object?*/box){
4232
		//	summary:
4233
		//		getter/setter for the margin-box of node.
4234
		//	description:
4235
		//		Returns an object in the expected format of box (regardless
4236
		//		if box is passed). The object might look like:
4237
		//			{ l: 50, t: 200, w: 300: h: 150 }
4238
		//		for a node offset from its parent 50px to the left, 200px from
4239
		//		the top with a margin width of 300px and a margin-height of
4240
		//		150px.
4241
		//	node:
4242
		//		id or reference to DOM Node to get/set box for
4243
		//	box:
4244
		//		optional. If passed, denotes that dojo.marginBox() should
4245
		//		update/set the margin box for node. Box is an object in the
4246
		//		above format. All properties are optional if passed.
4247
		var n=dojo.byId(node), s=gcs(n), b=box;
4248
		return !b ? dojo._getMarginBox(n, s) : dojo._setMarginBox(n, b.l, b.t, b.w, b.h, s); // Object
4249
	}
4250
 
4251
	dojo.contentBox = function(/*DomNode|String*/node, /*Object?*/box){
4252
		//	summary:
4253
		//		getter/setter for the content-box of node.
4254
		//	description:
4255
		//		Returns an object in the expected format of box (regardless if box is passed).
4256
		//		The object might look like:
4257
		//			{ l: 50, t: 200, w: 300: h: 150 }
4258
		//		for a node offset from its parent 50px to the left, 200px from
4259
		//		the top with a content width of 300px and a content-height of
4260
		//		150px. Note that the content box may have a much larger border
4261
		//		or margin box, depending on the box model currently in use and
4262
		//		CSS values set/inherited for node.
4263
		//	node:
4264
		//		id or reference to DOM Node to get/set box for
4265
		//	box:
4266
		//		optional. If passed, denotes that dojo.contentBox() should
4267
		//		update/set the content box for node. Box is an object in the
4268
		//		above format. All properties are optional if passed.
4269
		var n=dojo.byId(node), s=gcs(n), b=box;
4270
		return !b ? dojo._getContentBox(n, s) : dojo._setContentSize(n, b.w, b.h, s); // Object
4271
	}
4272
 
4273
	// =============================
4274
	// Positioning
4275
	// =============================
4276
 
4277
	var _sumAncestorProperties = function(node, prop){
4278
		if(!(node = (node||0).parentNode)){return 0};
4279
		var val, retVal = 0, _b = dojo.body();
4280
		while(node && node.style){
4281
			if(gcs(node).position == "fixed"){
4282
				return 0;
4283
			}
4284
			val = node[prop];
4285
			if(val){
4286
				retVal += val - 0;
4287
				// opera and khtml #body & #html has the same values, we only
4288
				// need one value
4289
				if(node == _b){ break; }
4290
			}
4291
			node = node.parentNode;
4292
		}
4293
		return retVal;	//	integer
4294
	}
4295
 
4296
	dojo._docScroll = function(){
4297
		var _b = dojo.body();
4298
		var _w = dojo.global;
4299
		var de = dojo.doc.documentElement;
4300
		return {
4301
			y: (_w.pageYOffset || de.scrollTop || _b.scrollTop || 0),
4302
			x: (_w.pageXOffset || dojo._fixIeBiDiScrollLeft(de.scrollLeft) || _b.scrollLeft || 0)
4303
		};
4304
	};
4305
 
4306
	dojo._isBodyLtr = function(){
4307
		//FIXME: could check html and body tags directly instead of computed style?  need to ignore case, accept empty values
4308
		return !("_bodyLtr" in dojo) ?
4309
			dojo._bodyLtr = dojo.getComputedStyle(dojo.body()).direction == "ltr" :
4310
			dojo._bodyLtr; // Boolean
4311
	}
4312
 
4313
	dojo._getIeDocumentElementOffset = function(){
4314
		// summary
4315
		// The following values in IE contain an offset:
4316
		//     event.clientX
4317
		//     event.clientY
4318
		//     node.getBoundingClientRect().left
4319
		//     node.getBoundingClientRect().top
4320
		// But other position related values do not contain this offset, such as
4321
		// node.offsetLeft, node.offsetTop, node.style.left and node.style.top.
4322
		// The offset is always (2, 2) in LTR direction. When the body is in RTL
4323
		// direction, the offset counts the width of left scroll bar's width.
4324
		// This function computes the actual offset.
4325
 
4326
		//NOTE: assumes we're being called in an IE browser
4327
 
4328
		var de = dojo.doc.documentElement;
4329
		if(dojo.isIE >= 7){
4330
			return {x: de.getBoundingClientRect().left, y: de.getBoundingClientRect().top}; // Object
4331
		}else{
4332
			// IE 6.0
4333
			return {x: dojo._isBodyLtr() || window.parent == window ?
4334
				de.clientLeft : de.offsetWidth - de.clientWidth - de.clientLeft,
4335
				y: de.clientTop}; // Object
4336
		}
4337
	};
4338
 
4339
	dojo._fixIeBiDiScrollLeft = function(/*Integer*/ scrollLeft){
4340
		// In RTL direction, scrollLeft should be a negative value, but IE
4341
		// returns a positive one. All codes using documentElement.scrollLeft
4342
		// must call this function to fix this error, otherwise the position
4343
		// will offset to right when there is a horizonal scrollbar.
4344
		if(dojo.isIE && !dojo._isBodyLtr()){
4345
			var de = dojo.doc.documentElement;
4346
			return scrollLeft + de.clientWidth - de.scrollWidth; // Integer
4347
		}
4348
		return scrollLeft; // Integer
4349
	}
4350
 
4351
	dojo._abs = function(/*DomNode*/node, /*Boolean?*/includeScroll){
4352
		//	summary:
4353
		//		Gets the absolute position of the passed element based on the
4354
		//		document itself. Returns an object of the form:
4355
		//			{ x: 100, y: 300 }
4356
		//		if includeScroll is passed, the x and y values will include any
4357
		//		document offsets that may affect the position relative to the
4358
		//		viewport.
4359
 
4360
		// FIXME: need to decide in the brave-new-world if we're going to be
4361
		// margin-box or border-box.
4362
		var ownerDocument = node.ownerDocument;
4363
		var ret = {
4364
			x: 0,
4365
			y: 0
4366
		};
4367
		var hasScroll = false;
4368
 
4369
		// targetBoxType == "border-box"
4370
		var db = dojo.body();
4371
		if(dojo.isIE){
4372
			var client = node.getBoundingClientRect();
4373
			var offset = dojo._getIeDocumentElementOffset();
4374
			ret.x = client.left - offset.x;
4375
			ret.y = client.top - offset.y;
4376
		}else if(ownerDocument["getBoxObjectFor"]){
4377
			// mozilla
4378
			var bo = ownerDocument.getBoxObjectFor(node);
4379
			ret.x = bo.x - _sumAncestorProperties(node, "scrollLeft");
4380
			ret.y = bo.y - _sumAncestorProperties(node, "scrollTop");
4381
		}else{
4382
			if(node["offsetParent"]){
4383
				hasScroll = true;
4384
				var endNode;
4385
				// in Safari, if the node is an absolutely positioned child of
4386
				// the body and the body has a margin the offset of the child
4387
				// and the body contain the body's margins, so we need to end
4388
				// at the body
4389
				// FIXME: getting contrary results to the above in latest WebKit.
4390
				if(dojo.isSafari &&
4391
					//(node.style.getPropertyValue("position") == "absolute") &&
4392
					(gcs(node).position == "absolute") &&
4393
					(node.parentNode == db)){
4394
					endNode = db;
4395
				}else{
4396
					endNode = db.parentNode;
4397
				}
4398
				if(node.parentNode != db){
4399
					var nd = node;
4400
					if(dojo.isOpera || (dojo.isSafari >= 3)){ nd = db; }
4401
					ret.x -= _sumAncestorProperties(nd, "scrollLeft");
4402
					ret.y -= _sumAncestorProperties(nd, "scrollTop");
4403
				}
4404
				var curnode = node;
4405
				do{
4406
					var n = curnode["offsetLeft"];
4407
					//FIXME: ugly hack to workaround the submenu in
4408
					//popupmenu2 does not shown up correctly in opera.
4409
					//Someone have a better workaround?
4410
					if(!dojo.isOpera || n>0){
4411
						ret.x += isNaN(n) ? 0 : n;
4412
					}
4413
					var m = curnode["offsetTop"];
4414
					ret.y += isNaN(m) ? 0 : m;
4415
					curnode = curnode.offsetParent;
4416
				}while((curnode != endNode)&&curnode);
4417
			}else if(node["x"]&&node["y"]){
4418
				ret.x += isNaN(node.x) ? 0 : node.x;
4419
				ret.y += isNaN(node.y) ? 0 : node.y;
4420
			}
4421
		}
4422
		// account for document scrolling
4423
		// if offsetParent is used, ret value already includes scroll position
4424
		// so we may have to actually remove that value if !includeScroll
4425
		if(hasScroll || includeScroll){
4426
			var scroll = dojo._docScroll();
4427
			var m = hasScroll ? (!includeScroll ? -1 : 0) : 1;
4428
			ret.y += m*scroll.y;
4429
			ret.x += m*scroll.x;
4430
		}
4431
 
4432
		return ret; // object
4433
	}
4434
 
4435
	// FIXME: need a setter for coords or a moveTo!!
4436
	dojo.coords = function(/*DomNode|String*/node, /*Boolean?*/includeScroll){
4437
		//	summary:
4438
		//		Returns an object that measures margin box width/height and
4439
		//		absolute positioning data from dojo._abs(). Return value will
4440
		//		be in the form:
4441
		//			{ l: 50, t: 200, w: 300: h: 150, x: 100, y: 300 }
4442
		//		does not act as a setter. If includeScroll is passed, the x and
4443
		//		y params are affected as one would expect in dojo._abs().
4444
		var n=dojo.byId(node), s=gcs(n), mb=dojo._getMarginBox(n, s);
4445
		var abs = dojo._abs(n, includeScroll);
4446
		mb.x = abs.x;
4447
		mb.y = abs.y;
4448
		return mb;
4449
	}
4450
})();
4451
 
4452
// =============================
4453
// (CSS) Class Functions
4454
// =============================
4455
 
4456
dojo.hasClass = function(/*DomNode|String*/node, /*String*/classStr){
4457
	//	summary:
4458
	//		Returns whether or not the specified classes are a portion of the
4459
	//		class list currently applied to the node.
4460
	return ((" "+dojo.byId(node).className+" ").indexOf(" "+classStr+" ") >= 0);  // Boolean
4461
};
4462
 
4463
dojo.addClass = function(/*DomNode|String*/node, /*String*/classStr){
4464
	//	summary:
4465
	//		Adds the specified classes to the end of the class list on the
4466
	//		passed node.
4467
	node = dojo.byId(node);
4468
	var cls = node.className;
4469
	if((" "+cls+" ").indexOf(" "+classStr+" ") < 0){
4470
		node.className = cls + (cls ? ' ' : '') + classStr;
4471
	}
4472
};
4473
 
4474
dojo.removeClass = function(/*DomNode|String*/node, /*String*/classStr){
4475
	// summary: Removes the specified classes from node.
4476
	node = dojo.byId(node);
4477
	var t = dojo.trim((" " + node.className + " ").replace(" " + classStr + " ", " "));
4478
	if(node.className != t){ node.className = t; }
4479
};
4480
 
4481
dojo.toggleClass = function(/*DomNode|String*/node, /*String*/classStr, /*Boolean?*/condition){
4482
	//	summary:
4483
	//		Adds a class to node if not present, or removes if present.
4484
	//		Pass a boolean condition if you want to explicitly add or remove.
4485
	//	condition:
4486
	//		If passed, true means to add the class, false means to remove.
4487
	if(condition === undefined){
4488
		condition = !dojo.hasClass(node, classStr);
4489
	}
4490
	dojo[condition ? "addClass" : "removeClass"](node, classStr);
4491
};
4492
 
4493
}
4494
 
4495
if(!dojo._hasResource["dojo._base.NodeList"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
4496
dojo._hasResource["dojo._base.NodeList"] = true;
4497
dojo.provide("dojo._base.NodeList");
4498
 
4499
 
4500
 
4501
(function(){
4502
 
4503
	var d = dojo;
4504
 
4505
	var tnl = function(arr){
4506
		arr.constructor = dojo.NodeList;
4507
		dojo._mixin(arr, dojo.NodeList.prototype);
4508
		return arr;
4509
	}
4510
 
4511
	dojo.NodeList = function(){
4512
		//	summary:
4513
		//		dojo.NodeList is as subclass of Array which adds syntactic
4514
		//		sugar for chaining, common iteration operations, animation,
4515
		//		and node manipulation. NodeLists are most often returned as
4516
		//		the result of dojo.query() calls.
4517
		//	example:
4518
		//		create a node list from a node
4519
		//		|	new dojo.NodeList(dojo.byId("foo"));
4520
 
4521
		return tnl(Array.apply(null, arguments));
4522
	}
4523
 
4524
	dojo.NodeList._wrap = tnl;
4525
 
4526
	dojo.extend(dojo.NodeList, {
4527
		// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array#Methods
4528
 
4529
		// FIXME: handle return values for #3244
4530
		//		http://trac.dojotoolkit.org/ticket/3244
4531
 
4532
		// FIXME:
4533
		//		need to wrap or implement:
4534
		//			join (perhaps w/ innerHTML/outerHTML overload for toString() of items?)
4535
		//			reduce
4536
		//			reduceRight
4537
 
4538
		slice: function(/*===== begin, end =====*/){
4539
			// summary:
4540
			//		Returns a new NodeList, maintaining this one in place
4541
			// description:
4542
			//		This method behaves exactly like the Array.slice method
4543
			//		with the caveat that it returns a dojo.NodeList and not a
4544
			//		raw Array. For more details, see:
4545
			//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:slice
4546
			// begin: Integer
4547
			//		Can be a positive or negative integer, with positive
4548
			//		integers noting the offset to begin at, and negative
4549
			//		integers denoting an offset from the end (i.e., to the left
4550
			//		of the end)
4551
			// end: Integer?
4552
			//		Optional parameter to describe what position relative to
4553
			//		the NodeList's zero index to end the slice at. Like begin,
4554
			//		can be positive or negative.
4555
			var a = dojo._toArray(arguments);
4556
			return tnl(a.slice.apply(this, a));
4557
		},
4558
 
4559
		splice: function(/*===== index, howmany, item =====*/){
4560
			// summary:
4561
			//		Returns a new NodeList, manipulating this NodeList based on
4562
			//		the arguments passed, potentially splicing in new elements
4563
			//		at an offset, optionally deleting elements
4564
			// description:
4565
			//		This method behaves exactly like the Array.splice method
4566
			//		with the caveat that it returns a dojo.NodeList and not a
4567
			//		raw Array. For more details, see:
4568
			//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:splice
4569
			// index: Integer
4570
			//		begin can be a positive or negative integer, with positive
4571
			//		integers noting the offset to begin at, and negative
4572
			//		integers denoting an offset from the end (i.e., to the left
4573
			//		of the end)
4574
			// howmany: Integer?
4575
			//		Optional parameter to describe what position relative to
4576
			//		the NodeList's zero index to end the slice at. Like begin,
4577
			//		can be positive or negative.
4578
			// item: Object...?
4579
			//		Any number of optional parameters may be passed in to be
4580
			//		spliced into the NodeList
4581
			// returns:
4582
			//		dojo.NodeList
4583
			var a = dojo._toArray(arguments);
4584
			return tnl(a.splice.apply(this, a));
4585
		},
4586
 
4587
		concat: function(/*===== item =====*/){
4588
			// summary:
4589
			//		Returns a new NodeList comprised of items in this NodeList
4590
			//		as well as items passed in as parameters
4591
			// description:
4592
			//		This method behaves exactly like the Array.concat method
4593
			//		with the caveat that it returns a dojo.NodeList and not a
4594
			//		raw Array. For more details, see:
4595
			//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:concat
4596
			// item: Object...?
4597
			//		Any number of optional parameters may be passed in to be
4598
			//		spliced into the NodeList
4599
			// returns:
4600
			//		dojo.NodeList
4601
			var a = dojo._toArray(arguments, 0, [this]);
4602
			return tnl(a.concat.apply([], a));
4603
		},
4604
 
4605
		indexOf: function(/*Object*/ value, /*Integer?*/ fromIndex){
4606
			//	summary:
4607
			//		see dojo.indexOf(). The primary difference is that the acted-on
4608
			//		array is implicitly this NodeList
4609
			// value:
4610
			//		The value to search for.
4611
			// fromIndex:
4612
			//		The loction to start searching from. Optional. Defaults to 0.
4613
			//	description:
4614
			//		For more details on the behavior of indexOf, see:
4615
			//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf
4616
			//	returns:
4617
			//		Positive Integer or 0 for a match, -1 of not found.
4618
			return d.indexOf(this, value, fromIndex); // Integer
4619
		},
4620
 
4621
		lastIndexOf: function(/*===== value, fromIndex =====*/){
4622
			// summary:
4623
			//		see dojo.lastIndexOf(). The primary difference is that the
4624
			//		acted-on array is implicitly this NodeList
4625
			//	description:
4626
			//		For more details on the behavior of lastIndexOf, see:
4627
			//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf
4628
			// value: Object
4629
			//		The value to search for.
4630
			// fromIndex: Integer?
4631
			//		The loction to start searching from. Optional. Defaults to 0.
4632
			// returns:
4633
			//		Positive Integer or 0 for a match, -1 of not found.
4634
			return d.lastIndexOf.apply(d, d._toArray(arguments, 0, [this])); // Integer
4635
		},
4636
 
4637
		every: function(/*Function*/callback, /*Object?*/thisObject){
4638
			//	summary:
4639
			//		see dojo.every() and:
4640
			//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:every
4641
			//		Takes the same structure of arguments and returns as
4642
			//		dojo.every() with the caveat that the passed array is
4643
			//		implicitly this NodeList
4644
			return d.every(this, callback, thisObject); // Boolean
4645
		},
4646
 
4647
		some: function(/*Function*/callback, /*Object?*/thisObject){
4648
			//	summary:
4649
			//		see dojo.some() and:
4650
			//			http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:some
4651
			//		Takes the same structure of arguments and returns as
4652
			//		dojo.some() with the caveat that the passed array is
4653
			//		implicitly this NodeList
4654
			return d.some(this, callback, thisObject); // Boolean
4655
		},
4656
 
4657
		map: function(/*Function*/ func, /*Function?*/ obj){
4658
			//	summary:
4659
			//		see dojo.map(). The primary difference is that the acted-on
4660
			//		array is implicitly this NodeList and the return is a
4661
			//		dojo.NodeList (a subclass of Array)
4662
 
4663
			return d.map(this, func, obj, d.NodeList); // dojo.NodeList
4664
		},
4665
 
4666
		forEach: function(callback, thisObj){
4667
			//	summary:
4668
			//		see dojo.forEach(). The primary difference is that the acted-on
4669
			//		array is implicitly this NodeList
4670
 
4671
			d.forEach(this, callback, thisObj);
4672
			return this; // dojo.NodeList non-standard return to allow easier chaining
4673
		},
4674
 
4675
		// custom methods
4676
 
4677
		coords: function(){
4678
			//	summary:
4679
			// 		Returns the box objects all elements in a node list as
4680
			// 		an Array (*not* a NodeList)
4681
 
4682
			return d.map(this, d.coords);
4683
		},
4684
 
4685
		style: function(/*===== property, value =====*/){
4686
			//	summary:
4687
			//		gets or sets the CSS property for every element in the NodeList
4688
			//	property: String
4689
			//		the CSS property to get/set, in JavaScript notation
4690
			//		("lineHieght" instead of "line-height")
4691
			//	value: String?
4692
			//		optional. The value to set the property to
4693
			//	return:
4694
			//		if no value is passed, the result is an array of strings.
4695
			//		If a value is passed, the return is this NodeList
4696
			var aa = d._toArray(arguments, 0, [null]);
4697
			var s = this.map(function(i){
4698
				aa[0] = i;
4699
				return d.style.apply(d, aa);
4700
			});
4701
			return (arguments.length > 1) ? this : s; // String||dojo.NodeList
4702
		},
4703
 
4704
		styles: function(/*===== property, value =====*/){
4705
			//	summary:
4706
			//		Deprecated. Use NodeList.style instead. Will be removed in
4707
			//		Dojo 1.1. Gets or sets the CSS property for every element
4708
			//		in the NodeList
4709
			//	property: String
4710
			//		the CSS property to get/set, in JavaScript notation
4711
			//		("lineHieght" instead of "line-height")
4712
			//	value: String?
4713
			//		optional. The value to set the property to
4714
			//	return:
4715
			//		if no value is passed, the result is an array of strings.
4716
			//		If a value is passed, the return is this NodeList
4717
			d.deprecated("NodeList.styles", "use NodeList.style instead", "1.1");
4718
			return this.style.apply(this, arguments);
4719
		},
4720
 
4721
		addClass: function(/*String*/ className){
4722
			// summary:
4723
			//		adds the specified class to every node in the list
4724
			//
4725
			this.forEach(function(i){ d.addClass(i, className); });
4726
			return this;
4727
		},
4728
 
4729
		removeClass: function(/*String*/ className){
4730
			this.forEach(function(i){ d.removeClass(i, className); });
4731
			return this;
4732
		},
4733
 
4734
		// FIXME: toggleClass()? connectPublisher()? connectRunOnce()?
4735
 
4736
		place: function(/*String||Node*/ queryOrNode, /*String*/ position){
4737
			//	summary:
4738
			//		places elements of this node list relative to the first element matched
4739
			//		by queryOrNode. Returns the original NodeList.
4740
			//	queryOrNode:
4741
			//		may be a string representing any valid CSS3 selector or a DOM node.
4742
			//		In the selector case, only the first matching element will be used
4743
			//		for relative positioning.
4744
			//	position:
4745
			//		can be one of:
4746
			//			"last"||"end" (default)
4747
			//			"first||"start"
4748
			//			"before"
4749
			//			"after"
4750
			// 		or an offset in the childNodes property
4751
			var item = d.query(queryOrNode)[0];
4752
			position = position||"last";
4753
 
4754
			for(var x=0; x<this.length; x++){
4755
				d.place(this[x], item, position);
4756
			}
4757
			return this; // dojo.NodeList
4758
		},
4759
 
4760
		connect: function(/*String*/ methodName, /*Object||Function||String*/ objOrFunc, /*String?*/ funcName){
4761
			//	summary:
4762
			//		attach event handlers to every item of the NodeList. Uses dojo.connect()
4763
			//		so event properties are normalized
4764
			//	methodName:
4765
			//		the name of the method to attach to. For DOM events, this should be
4766
			//		the lower-case name of the event
4767
			//	objOrFunc:
4768
			//		if 2 arguments are passed (methodName, objOrFunc), objOrFunc should
4769
			//		reference a function or be the name of the function in the global
4770
			//		namespace to attach. If 3 arguments are provided
4771
			//		(methodName, objOrFunc, funcName), objOrFunc must be the scope to
4772
			//		locate the bound function in
4773
			//	funcName:
4774
			//		optional. A string naming the function in objOrFunc to bind to the
4775
			//		event. May also be a function reference.
4776
			//	example:
4777
			//		add an onclick handler to every button on the page
4778
			//		|	dojo.query("onclick", function(e){
4779
			//		|		console.debug("clicked!");
4780
			//		|	});
4781
			// example:
4782
			//		attach foo.bar() to every odd div's onmouseover
4783
			//		|	dojo.query("div:nth-child(odd)").onclick("onmouseover", foo, "bar");
4784
			this.forEach(function(item){
4785
				d.connect(item, methodName, objOrFunc, funcName);
4786
			});
4787
			return this; // dojo.NodeList
4788
		},
4789
 
4790
		orphan: function(/*String?*/ simpleFilter){
4791
			//	summary:
4792
			//		removes elements in this list that match the simple
4793
			//		filter from their parents and returns them as a new
4794
			//		NodeList.
4795
			//	simpleFilter: single-expression CSS filter
4796
			//	return: a dojo.NodeList of all of the elements orpahned
4797
			var orphans = (simpleFilter) ? d._filterQueryResult(this, simpleFilter) : this;
4798
			orphans.forEach(function(item){
4799
				if(item["parentNode"]){
4800
					item.parentNode.removeChild(item);
4801
				}
4802
			});
4803
			return orphans; // dojo.NodeList
4804
		},
4805
 
4806
		adopt: function(/*String||Array||DomNode*/ queryOrListOrNode, /*String?*/ position){
4807
			//	summary:
4808
			//		places any/all elements in queryOrListOrNode at a
4809
			//		position relative to the first element in this list.
4810
			//		Returns a dojo.NodeList of the adopted elements.
4811
			//	queryOrListOrNode:
4812
			//		a DOM node or a query string or a query result.
4813
			//		Represents the nodes to be adopted relative to the
4814
			//		first element of this NodeList.
4815
			//	position:
4816
			//		optional. One of:
4817
			//			"last"||"end" (default)
4818
			//			"first||"start"
4819
			//			"before"
4820
			//			"after"
4821
			// 		or an offset in the childNodes property
4822
			var item = this[0];
4823
			return d.query(queryOrListOrNode).forEach(function(ai){ d.place(ai, item, (position||"last")); }); // dojo.NodeList
4824
		},
4825
 
4826
		// FIXME: do we need this?
4827
		query: function(/*String*/ queryStr){
4828
			//	summary:
4829
			//		Returns a new, flattened NodeList. Elements of the new list
4830
			//		satisfy the passed query but use elements of the
4831
			//		current NodeList as query roots.
4832
 
4833
			queryStr = queryStr||"";
4834
 
4835
			// FIXME: probably slow
4836
			var ret = d.NodeList();
4837
			this.forEach(function(item){
4838
				d.query(queryStr, item).forEach(function(subItem){
4839
					if(typeof subItem != "undefined"){
4840
						ret.push(subItem);
4841
					}
4842
				});
4843
			});
4844
			return ret; // dojo.NodeList
4845
		},
4846
 
4847
		filter: function(/*String*/ simpleQuery){
4848
			//	summary:
4849
			// 		"masks" the built-in javascript filter() method to support
4850
			//		passing a simple string filter in addition to supporting
4851
			//		filtering function objects.
4852
			//	example:
4853
			//		"regular" JS filter syntax as exposed in dojo.filter:
4854
			//		|	dojo.query("*").filter(function(item){
4855
			//		|		// highlight every paragraph
4856
			//		|		return (item.nodeName == "p");
4857
			//		|	}).styles("backgroundColor", "yellow");
4858
			// example:
4859
			//		the same filtering using a CSS selector
4860
			//		|	dojo.query("*").filter("p").styles("backgroundColor", "yellow");
4861
 
4862
			var items = this;
4863
			var _a = arguments;
4864
			var r = d.NodeList();
4865
			var rp = function(t){
4866
				if(typeof t != "undefined"){
4867
					r.push(t);
4868
				}
4869
			}
4870
			if(d.isString(simpleQuery)){
4871
				items = d._filterQueryResult(this, _a[0]);
4872
				if(_a.length == 1){
4873
					// if we only got a string query, pass back the filtered results
4874
					return items; // dojo.NodeList
4875
				}
4876
				// if we got a callback, run it over the filtered items
4877
				d.forEach(d.filter(items, _a[1], _a[2]), rp);
4878
				return r; // dojo.NodeList
4879
			}
4880
			// handle the (callback, [thisObject]) case
4881
			d.forEach(d.filter(items, _a[0], _a[1]), rp);
4882
			return r; // dojo.NodeList
4883
 
4884
		},
4885
 
4886
		/*
4887
		// FIXME: should this be "copyTo" and include parenting info?
4888
		clone: function(){
4889
			// summary:
4890
			//		creates node clones of each element of this list
4891
			//		and returns a new list containing the clones
4892
		},
4893
		*/
4894
 
4895
		addContent: function(/*String*/ content, /*String||Integer?*/ position){
4896
			//	summary:
4897
			//		add a node or some HTML as a string to every item in the list.
4898
			//		Returns the original list.
4899
			//	content:
4900
			//		the HTML in string format to add at position to every item
4901
			//	position:
4902
			//		One of:
4903
			//			"last"||"end" (default)
4904
			//			"first||"start"
4905
			//			"before"
4906
			//			"after"
4907
			//		or an integer offset in the childNodes property
4908
			var ta = d.doc.createElement("span");
4909
			if(d.isString(content)){
4910
				ta.innerHTML = content;
4911
			}else{
4912
				ta.appendChild(content);
4913
			}
4914
			var ct = ((position == "first")||(position == "after")) ? "lastChild" : "firstChild";
4915
			this.forEach(function(item){
4916
				var tn = ta.cloneNode(true);
4917
				while(tn[ct]){
4918
					d.place(tn[ct], item, position);
4919
				}
4920
			});
4921
			return this; // dojo.NodeList
4922
		}
4923
	});
4924
 
4925
	// syntactic sugar for DOM events
4926
	d.forEach([
4927
		"blur", "click", "keydown", "keypress", "keyup", "mousedown", "mouseenter",
4928
		"mouseleave", "mousemove", "mouseout", "mouseover", "mouseup"
4929
		], function(evt){
4930
			var _oe = "on"+evt;
4931
			dojo.NodeList.prototype[_oe] = function(a, b){
4932
				return this.connect(_oe, a, b);
4933
			}
4934
				// FIXME: should these events trigger publishes?
4935
				/*
4936
				return (a ? this.connect(_oe, a, b) :
4937
							this.forEach(function(n){
4938
								// FIXME:
4939
								//		listeners get buried by
4940
								//		addEventListener and can't be dug back
4941
								//		out to be triggered externally.
4942
								// see:
4943
								//		http://developer.mozilla.org/en/docs/DOM:element
4944
 
4945
								console.debug(n, evt, _oe);
4946
 
4947
								// FIXME: need synthetic event support!
4948
								var _e = { target: n, faux: true, type: evt };
4949
								// dojo._event_listener._synthesizeEvent({}, { target: n, faux: true, type: evt });
4950
								try{ n[evt](_e); }catch(e){ console.debug(e); }
4951
								try{ n[_oe](_e); }catch(e){ console.debug(e); }
4952
							})
4953
				);
4954
			}
4955
			*/
4956
		}
4957
	);
4958
 
4959
})();
4960
 
4961
}
4962
 
4963
if(!dojo._hasResource["dojo._base.query"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
4964
dojo._hasResource["dojo._base.query"] = true;
4965
dojo.provide("dojo._base.query");
4966
 
4967
 
4968
/*
4969
	dojo.query() architectural overview:
4970
 
4971
		dojo.query is a relatively full-featured CSS3 query library. It is
4972
		designed to take any valid CSS3 selector and return the nodes matching
4973
		the selector. To do this quickly, it processes queries in several
4974
		steps, applying caching where profitable.
4975
 
4976
		The steps (roughly in reverse order of the way they appear in the code):
4977
			1.) check to see if we already have a "query dispatcher"
4978
				- if so, use that with the given parameterization. Skip to step 4.
4979
			2.) attempt to determine which branch to dispatch the query to:
4980
				- JS (optimized DOM iteration)
4981
				- xpath (for browsers that support it and where it's fast)
4982
				- native (not available in any browser yet)
4983
			3.) tokenize and convert to executable "query dispatcher"
4984
				- this is where the lion's share of the complexity in the
4985
				  system lies. In the DOM version, the query dispatcher is
4986
				  assembled as a chain of "yes/no" test functions pertaining to
4987
				  a section of a simple query statement (".blah:nth-child(odd)"
4988
				  but not "div div", which is 2 simple statements). Individual
4989
				  statement dispatchers are cached (to prevent re-definition)
4990
				  as are entire dispatch chains (to make re-execution of the
4991
				  same query fast)
4992
				- in the xpath path, tokenization yeilds a concatenation of
4993
				  parameterized xpath selectors. As with the DOM version, both
4994
				  simple selector blocks and overall evaluators are cached to
4995
				  prevent re-defintion
4996
			4.) the resulting query dispatcher is called in the passed scope (by default the top-level document)
4997
				- for DOM queries, this results in a recursive, top-down
4998
				  evaluation of nodes based on each simple query section
4999
				- xpath queries can, thankfully, be executed in one shot
5000
			5.) matched nodes are pruned to ensure they are unique
5001
*/
5002
 
5003
;(function(){
5004
	// define everything in a closure for compressability reasons. "d" is an
5005
	// alias to "dojo" since it's so frequently used. This seems a
5006
	// transformation that the build system could perform on a per-file basis.
5007
 
5008
	////////////////////////////////////////////////////////////////////////
5009
	// Utility code
5010
	////////////////////////////////////////////////////////////////////////
5011
 
5012
	var d = dojo;
5013
	var childNodesName = dojo.isIE ? "children" : "childNodes";
5014
 
5015
	var getQueryParts = function(query){
5016
		// summary: state machine for query tokenization
5017
		if(query.charAt(query.length-1) == ">"){
5018
			query += " *"
5019
		}
5020
		query += " "; // ensure that we terminate the state machine
5021
 
5022
		var ts = function(s, e){
5023
			return d.trim(query.slice(s, e));
5024
		}
5025
 
5026
		// the overall data graph of the full query, as represented by queryPart objects
5027
		var qparts = [];
5028
		// state keeping vars
5029
		var inBrackets = -1;
5030
		var inParens = -1;
5031
		var inMatchFor = -1;
5032
		var inPseudo = -1;
5033
		var inClass = -1;
5034
		var inId = -1;
5035
		var inTag = -1;
5036
		var lc = ""; // the last character
5037
		var cc = ""; // the current character
5038
		var pStart;
5039
		// iteration vars
5040
		var x = 0; // index in the query
5041
		var ql = query.length;
5042
		var currentPart = null; // data structure representing the entire clause
5043
		var _cp = null; // the current pseudo or attr matcher
5044
 
5045
		var endTag = function(){
5046
			if(inTag >= 0){
5047
				var tv = (inTag == x) ? null : ts(inTag, x).toLowerCase();
5048
				currentPart[ (">~+".indexOf(tv) < 0)? "tag" : "oper" ] = tv;
5049
				inTag = -1;
5050
			}
5051
		}
5052
 
5053
		var endId = function(){
5054
			if(inId >= 0){
5055
				currentPart.id = ts(inId, x).replace(/\\/g, "");
5056
				inId = -1;
5057
			}
5058
		}
5059
 
5060
		var endClass = function(){
5061
			if(inClass >= 0){
5062
				currentPart.classes.push(ts(inClass+1, x).replace(/\\/g, ""));
5063
				inClass = -1;
5064
			}
5065
		}
5066
 
5067
		var endAll = function(){
5068
			endId(); endTag(); endClass();
5069
		}
5070
 
5071
		for(; x<ql, lc=cc, cc=query.charAt(x); x++){
5072
			if(lc == "\\"){ continue; }
5073
			if(!currentPart){
5074
				// NOTE: I hate all this alloc, but it's shorter than writing tons of if's
5075
				pStart = x;
5076
				currentPart = {
5077
					query: null,
5078
					pseudos: [],
5079
					attrs: [],
5080
					classes: [],
5081
					tag: null,
5082
					oper: null,
5083
					id: null
5084
				};
5085
				inTag = x;
5086
			}
5087
 
5088
			if(inBrackets >= 0){
5089
				// look for a the close first
5090
				if(cc == "]"){
5091
					if(!_cp.attr){
5092
						_cp.attr = ts(inBrackets+1, x);
5093
					}else{
5094
						_cp.matchFor = ts((inMatchFor||inBrackets+1), x);
5095
					}
5096
					var cmf = _cp.matchFor;
5097
					if(cmf){
5098
						if(	(cmf.charAt(0) == '"') || (cmf.charAt(0)  == "'") ){
5099
							_cp.matchFor = cmf.substring(1, cmf.length-1);
5100
						}
5101
					}
5102
					currentPart.attrs.push(_cp);
5103
					_cp = null; // necessaray?
5104
					inBrackets = inMatchFor = -1;
5105
				}else if(cc == "="){
5106
					var addToCc = ("|~^$*".indexOf(lc) >=0 ) ? lc : "";
5107
					_cp.type = addToCc+cc;
5108
					_cp.attr = ts(inBrackets+1, x-addToCc.length);
5109
					inMatchFor = x+1;
5110
				}
5111
				// now look for other clause parts
5112
			}else if(inParens >= 0){
5113
				if(cc == ")"){
5114
					if(inPseudo >= 0){
5115
						_cp.value = ts(inParens+1, x);
5116
					}
5117
					inPseudo = inParens = -1;
5118
				}
5119
			}else if(cc == "#"){
5120
				endAll();
5121
				inId = x+1;
5122
			}else if(cc == "."){
5123
				endAll();
5124
				inClass = x;
5125
			}else if(cc == ":"){
5126
				endAll();
5127
				inPseudo = x;
5128
			}else if(cc == "["){
5129
				endAll();
5130
				inBrackets = x;
5131
				_cp = {
5132
					/*=====
5133
					attr: null, type: null, matchFor: null
5134
					=====*/
5135
				};
5136
			}else if(cc == "("){
5137
				if(inPseudo >= 0){
5138
					_cp = {
5139
						name: ts(inPseudo+1, x),
5140
						value: null
5141
					}
5142
					currentPart.pseudos.push(_cp);
5143
				}
5144
				inParens = x;
5145
			}else if(cc == " " && lc != cc){
5146
				// note that we expect the string to be " " terminated
5147
				endAll();
5148
				if(inPseudo >= 0){
5149
					currentPart.pseudos.push({ name: ts(inPseudo+1, x) });
5150
				}
5151
				currentPart.hasLoops = (
5152
						currentPart.pseudos.length ||
5153
						currentPart.attrs.length ||
5154
						currentPart.classes.length	);
5155
				currentPart.query = ts(pStart, x);
5156
				currentPart.tag = (currentPart["oper"]) ? null : (currentPart.tag || "*");
5157
				qparts.push(currentPart);
5158
				currentPart = null;
5159
			}
5160
		}
5161
		return qparts;
5162
	};
5163
 
5164
 
5165
	////////////////////////////////////////////////////////////////////////
5166
	// XPath query code
5167
	////////////////////////////////////////////////////////////////////////
5168
 
5169
	// this array is a lookup used to generate an attribute matching function.
5170
	// There is a similar lookup/generator list for the DOM branch with similar
5171
	// calling semantics.
5172
	var xPathAttrs = {
5173
		"*=": function(attr, value){
5174
			return "[contains(@"+attr+", '"+ value +"')]";
5175
		},
5176
		"^=": function(attr, value){
5177
			return "[starts-with(@"+attr+", '"+ value +"')]";
5178
		},
5179
		"$=": function(attr, value){
5180
			return "[substring(@"+attr+", string-length(@"+attr+")-"+(value.length-1)+")='"+value+"']";
5181
		},
5182
		"~=": function(attr, value){
5183
			return "[contains(concat(' ',@"+attr+",' '), ' "+ value +" ')]";
5184
		},
5185
		"|=": function(attr, value){
5186
			return "[contains(concat(' ',@"+attr+",' '), ' "+ value +"-')]";
5187
		},
5188
		"=": function(attr, value){
5189
			return "[@"+attr+"='"+ value +"']";
5190
		}
5191
	};
5192
 
5193
	// takes a list of attribute searches, the overall query, a function to
5194
	// generate a default matcher, and a closure-bound method for providing a
5195
	// matching function that generates whatever type of yes/no distinguisher
5196
	// the query method needs. The method is a bit tortured and hard to read
5197
	// because it needs to be used in both the XPath and DOM branches.
5198
	var handleAttrs = function(	attrList,
5199
								query,
5200
								getDefault,
5201
								handleMatch){
5202
		d.forEach(query.attrs, function(attr){
5203
			var matcher;
5204
			// type, attr, matchFor
5205
			if(attr.type && attrList[attr.type]){
5206
				matcher = attrList[attr.type](attr.attr, attr.matchFor);
5207
			}else if(attr.attr.length){
5208
				matcher = getDefault(attr.attr);
5209
			}
5210
			if(matcher){ handleMatch(matcher); }
5211
		});
5212
	}
5213
 
5214
	var buildPath = function(query){
5215
		var xpath = ".";
5216
		var qparts = getQueryParts(d.trim(query));
5217
		while(qparts.length){
5218
			var tqp = qparts.shift();
5219
			var prefix;
5220
			// FIXME: need to add support for ~ and +
5221
			if(tqp.oper == ">"){
5222
				prefix = "/";
5223
				// prefix = "/child::node()";
5224
				tqp = qparts.shift();
5225
			}else{
5226
				prefix = "//";
5227
				// prefix = "/descendant::node()"
5228
			}
5229
 
5230
			// get the tag name (if any)
5231
 
5232
			xpath += prefix + tqp.tag;
5233
 
5234
			// check to see if it's got an id. Needs to come first in xpath.
5235
			if(tqp.id){
5236
				xpath += "[@id='"+tqp.id+"'][1]";
5237
			}
5238
 
5239
			d.forEach(tqp.classes, function(cn){
5240
				var cnl = cn.length;
5241
				var padding = " ";
5242
				if(cn.charAt(cnl-1) == "*"){
5243
					padding = ""; cn = cn.substr(0, cnl-1);
5244
				}
5245
				xpath +=
5246
					"[contains(concat(' ',@class,' '), ' "+
5247
					cn + padding + "')]";
5248
			});
5249
 
5250
			handleAttrs(xPathAttrs, tqp,
5251
				function(condition){
5252
						return "[@"+condition+"]";
5253
				},
5254
				function(matcher){
5255
					xpath += matcher;
5256
				}
5257
			);
5258
 
5259
			// FIXME: need to implement pseudo-class checks!!
5260
		};
5261
		return xpath;
5262
	};
5263
 
5264
	var _xpathFuncCache = {};
5265
	var getXPathFunc = function(path){
5266
		if(_xpathFuncCache[path]){
5267
			return _xpathFuncCache[path];
5268
		}
5269
 
5270
		var doc = d.doc;
5271
		// var parent = d.body(); // FIXME
5272
		// FIXME: don't need to memoize. The closure scope handles it for us.
5273
		var xpath = buildPath(path);
5274
 
5275
		var tf = function(parent){
5276
			// XPath query strings are memoized.
5277
			var ret = [];
5278
			var xpathResult;
5279
			try{
5280
				xpathResult = doc.evaluate(xpath, parent, null,
5281
												// XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null);
5282
												XPathResult.ANY_TYPE, null);
5283
			}catch(e){
5284
				console.debug("failure in exprssion:", xpath, "under:", parent);
5285
				console.debug(e);
5286
			}
5287
			var result = xpathResult.iterateNext();
5288
			while(result){
5289
				ret.push(result);
5290
				result = xpathResult.iterateNext();
5291
			}
5292
			return ret;
5293
		}
5294
		return _xpathFuncCache[path] = tf;
5295
	};
5296
 
5297
	/*
5298
	d.xPathMatch = function(query){
5299
		// XPath based DOM query system. Handles a small subset of CSS
5300
		// selectors, subset is identical to the non-XPath version of this
5301
		// function.
5302
 
5303
		// FIXME: need to add support for alternate roots
5304
		return getXPathFunc(query)();
5305
	}
5306
	*/
5307
 
5308
	////////////////////////////////////////////////////////////////////////
5309
	// DOM query code
5310
	////////////////////////////////////////////////////////////////////////
5311
 
5312
	var _filtersCache = {};
5313
	var _simpleFiltersCache = {};
5314
 
5315
	// the basic building block of the yes/no chaining system. agree(f1, f2)
5316
	// generates a new function which returns the boolean results of both of
5317
	// the passed functions to a single logical-anded result.
5318
	var agree = function(first, second){
5319
		if(!first){ return second; }
5320
		if(!second){ return first; }
5321
 
5322
		return function(){
5323
			return first.apply(window, arguments) && second.apply(window, arguments);
5324
		}
5325
	}
5326
 
5327
	var _filterDown = function(element, queryParts, matchArr, idx){
5328
		var nidx = idx+1;
5329
		var isFinal = (queryParts.length == nidx);
5330
		var tqp = queryParts[idx];
5331
 
5332
		// see if we can constrain our next level to direct children
5333
		if(tqp.oper == ">"){
5334
			var ecn = element[childNodesName];
5335
			if(!ecn || !ecn.length){
5336
				return;
5337
			}
5338
			nidx++;
5339
			isFinal = (queryParts.length == nidx);
5340
			// kinda janky, too much array alloc
5341
			var tf = getFilterFunc(queryParts[idx+1]);
5342
			// for(var x=ecn.length-1, te; x>=0, te=ecn[x]; x--){
5343
			for(var x=0, ecnl=ecn.length, te; x<ecnl, te=ecn[x]; x++){
5344
				if(tf(te)){
5345
					if(isFinal){
5346
						matchArr.push(te);
5347
					}else{
5348
						_filterDown(te, queryParts, matchArr, nidx);
5349
					}
5350
				}
5351
				/*
5352
				if(x==0){
5353
					break;
5354
				}
5355
				*/
5356
			}
5357
		}
5358
 
5359
		// otherwise, keep going down, unless we'er at the end
5360
		var candidates = getElementsFunc(tqp)(element);
5361
		if(isFinal){
5362
			while(candidates.length){
5363
				matchArr.push(candidates.shift());
5364
			}
5365
			/*
5366
			candidates.unshift(0, matchArr.length-1);
5367
			matchArr.splice.apply(matchArr, candidates);
5368
			*/
5369
		}else{
5370
			// if we're not yet at the bottom, keep going!
5371
			while(candidates.length){
5372
				_filterDown(candidates.shift(), queryParts, matchArr, nidx);
5373
			}
5374
		}
5375
	}
5376
 
5377
	var filterDown = function(elements, queryParts){
5378
		var ret = [];
5379
 
5380
		// for every root, get the elements that match the descendant selector
5381
		// for(var x=elements.length-1, te; x>=0, te=elements[x]; x--){
5382
		var x = elements.length - 1, te;
5383
		while(te = elements[x--]){
5384
			_filterDown(te, queryParts, ret, 0);
5385
		}
5386
		return ret;
5387
	}
5388
 
5389
	var getFilterFunc = function(q){
5390
		// note: query can't have spaces!
5391
		if(_filtersCache[q.query]){
5392
			return _filtersCache[q.query];
5393
		}
5394
		var ff = null;
5395
 
5396
		// does it have a tagName component?
5397
		if(q.tag){
5398
			if(q.tag == "*"){
5399
				ff = agree(ff,
5400
					function(elem){
5401
						return (elem.nodeType == 1);
5402
					}
5403
				);
5404
			}else{
5405
				// tag name match
5406
				ff = agree(ff,
5407
					function(elem){
5408
						return (
5409
							(elem.nodeType == 1) &&
5410
							(q.tag == elem.tagName.toLowerCase())
5411
						);
5412
						// return isTn;
5413
					}
5414
				);
5415
			}
5416
		}
5417
 
5418
		// does the node have an ID?
5419
		if(q.id){
5420
			ff = agree(ff,
5421
				function(elem){
5422
					return (
5423
						(elem.nodeType == 1) &&
5424
						(elem.id == q.id)
5425
					);
5426
				}
5427
			);
5428
		}
5429
 
5430
		if(q.hasLoops){
5431
			// if we have other query param parts, make sure we add them to the
5432
			// filter chain
5433
			ff = agree(ff, getSimpleFilterFunc(q));
5434
		}
5435
 
5436
		return _filtersCache[q.query] = ff;
5437
	}
5438
 
5439
	var getNodeIndex = function(node){
5440
		// NOTE:
5441
		//		we could have a more accurate caching mechanism by invalidating
5442
		//		caches after the query has finished, but I think that'd lead to
5443
		//		significantly more cache churn than the cache would provide
5444
		//		value for in the common case. Generally, we're more
5445
		//		conservative (and therefore, more accurate) than jQuery and
5446
		//		DomQuery WRT node node indexes, but there may be corner cases
5447
		//		in which we fall down.  How much we care about them is TBD.
5448
 
5449
		var pn = node.parentNode;
5450
		var pnc = pn.childNodes;
5451
 
5452
		// check to see if we can trust the cache. If not, re-key the whole
5453
		// thing and return our node match from that.
5454
 
5455
		var nidx = -1;
5456
		var child = pn.firstChild;
5457
		if(!child){
5458
			return nidx;
5459
		}
5460
 
5461
		var ci = node["__cachedIndex"];
5462
		var cl = pn["__cachedLength"];
5463
 
5464
		// only handle cache building if we've gone out of sync
5465
		if(((typeof cl == "number")&&(cl != pnc.length))||(typeof ci != "number")){
5466
			// rip though the whole set, building cache indexes as we go
5467
			pn["__cachedLength"] = pnc.length;
5468
			var idx = 1;
5469
			do{
5470
				// we only assign indexes for nodes with nodeType == 1, as per:
5471
				//		http://www.w3.org/TR/css3-selectors/#nth-child-pseudo
5472
				// only elements are counted in the search order, and they
5473
				// begin at 1 for the first child's index
5474
 
5475
				if(child === node){
5476
					nidx = idx;
5477
				}
5478
				if(child.nodeType == 1){
5479
					child["__cachedIndex"] = idx;
5480
					idx++;
5481
				}
5482
				child = child.nextSibling;
5483
			}while(child);
5484
		}else{
5485
			// NOTE:
5486
			//		could be incorrect in some cases (node swaps involving the
5487
			//		passed node, etc.), but we ignore those due to the relative
5488
			//		unlikelihood of that occuring
5489
			nidx = ci;
5490
		}
5491
		return nidx;
5492
	}
5493
 
5494
	var firedCount = 0;
5495
 
5496
	var blank = "";
5497
	var _getAttr = function(elem, attr){
5498
		if(attr == "class"){
5499
			return elem.className || blank;
5500
		}
5501
		if(attr == "for"){
5502
			return elem.htmlFor || blank;
5503
		}
5504
		return elem.getAttribute(attr, 2) || blank;
5505
	}
5506
 
5507
	var attrs = {
5508
		"*=": function(attr, value){
5509
			return function(elem){
5510
				// E[foo*="bar"]
5511
				//		an E element whose "foo" attribute value contains
5512
				//		the substring "bar"
5513
				return (_getAttr(elem, attr).indexOf(value)>=0);
5514
			}
5515
		},
5516
		"^=": function(attr, value){
5517
			// E[foo^="bar"]
5518
			//		an E element whose "foo" attribute value begins exactly
5519
			//		with the string "bar"
5520
			return function(elem){
5521
				return (_getAttr(elem, attr).indexOf(value)==0);
5522
			}
5523
		},
5524
		"$=": function(attr, value){
5525
			// E[foo$="bar"]
5526
			//		an E element whose "foo" attribute value ends exactly
5527
			//		with the string "bar"
5528
			var tval = " "+value;
5529
			return function(elem){
5530
				var ea = " "+_getAttr(elem, attr);
5531
				return (ea.lastIndexOf(value)==(ea.length-value.length));
5532
			}
5533
		},
5534
		"~=": function(attr, value){
5535
			// E[foo~="bar"]
5536
			//		an E element whose "foo" attribute value is a list of
5537
			//		space-separated values, one of which is exactly equal
5538
			//		to "bar"
5539
 
5540
			// return "[contains(concat(' ',@"+attr+",' '), ' "+ value +" ')]";
5541
			var tval = " "+value+" ";
5542
			return function(elem){
5543
				var ea = " "+_getAttr(elem, attr)+" ";
5544
				return (ea.indexOf(tval)>=0);
5545
			}
5546
		},
5547
		"|=": function(attr, value){
5548
			// E[hreflang|="en"]
5549
			//		an E element whose "hreflang" attribute has a
5550
			//		hyphen-separated list of values beginning (from the
5551
			//		left) with "en"
5552
			var valueDash = " "+value+"-";
5553
			return function(elem){
5554
				var ea = " "+(elem.getAttribute(attr, 2) || "");
5555
				return (
5556
					(ea == value) ||
5557
					(ea.indexOf(valueDash)==0)
5558
				);
5559
			}
5560
		},
5561
		"=": function(attr, value){
5562
			return function(elem){
5563
				return (_getAttr(elem, attr) == value);
5564
			}
5565
		}
5566
	};
5567
 
5568
	var pseudos = {
5569
		"first-child": function(name, condition){
5570
			return function(elem){
5571
				if(elem.nodeType != 1){ return false; }
5572
				// check to see if any of the previous siblings are elements
5573
				var fc = elem.previousSibling;
5574
				while(fc && (fc.nodeType != 1)){
5575
					fc = fc.previousSibling;
5576
				}
5577
				return (!fc);
5578
			}
5579
		},
5580
		"last-child": function(name, condition){
5581
			return function(elem){
5582
				if(elem.nodeType != 1){ return false; }
5583
				// check to see if any of the next siblings are elements
5584
				var nc = elem.nextSibling;
5585
				while(nc && (nc.nodeType != 1)){
5586
					nc = nc.nextSibling;
5587
				}
5588
				return (!nc);
5589
			}
5590
		},
5591
		"empty": function(name, condition){
5592
			return function(elem){
5593
				// DomQuery and jQuery get this wrong, oddly enough.
5594
				// The CSS 3 selectors spec is pretty explicit about
5595
				// it, too.
5596
				var cn = elem.childNodes;
5597
				var cnl = elem.childNodes.length;
5598
				// if(!cnl){ return true; }
5599
				for(var x=cnl-1; x >= 0; x--){
5600
					var nt = cn[x].nodeType;
5601
					if((nt == 1)||(nt == 3)){ return false; }
5602
				}
5603
				return true;
5604
			}
5605
		},
5606
		/* non standard!
5607
		"contains": function(name, condition){
5608
			return function(elem){
5609
				// FIXME: I dislike this version of "contains", as
5610
				// whimsical attribute could set it off. An inner-text
5611
				// based version might be more accurate, but since
5612
				// jQuery and DomQuery also potentially get this wrong,
5613
				// I'm leaving it for now.
5614
				return (elem.innerHTML.indexOf(condition) >= 0);
5615
			}
5616
		},
5617
		*/
5618
		"not": function(name, condition){
5619
			var ntf = getFilterFunc(getQueryParts(condition)[0]);
5620
			return function(elem){
5621
				return (!ntf(elem));
5622
			}
5623
		},
5624
		"nth-child": function(name, condition){
5625
			var pi = parseInt;
5626
			if(condition == "odd"){
5627
				return function(elem){
5628
					return (
5629
						((getNodeIndex(elem)) % 2) == 1
5630
					);
5631
				}
5632
			}else if((condition == "2n")||
5633
				(condition == "even")){
5634
				return function(elem){
5635
					return ((getNodeIndex(elem) % 2) == 0);
5636
				}
5637
			}else if(condition.indexOf("0n+") == 0){
5638
				var ncount = pi(condition.substr(3));
5639
				return function(elem){
5640
					return (elem.parentNode[childNodesName][ncount-1] === elem);
5641
				}
5642
			}else if(	(condition.indexOf("n+") > 0) &&
5643
						(condition.length > 3) ){
5644
				var tparts = condition.split("n+", 2);
5645
				var pred = pi(tparts[0]);
5646
				var idx = pi(tparts[1]);
5647
				return function(elem){
5648
					return ((getNodeIndex(elem) % pred) == idx);
5649
				}
5650
			}else if(condition.indexOf("n") == -1){
5651
				var ncount = pi(condition);
5652
				return function(elem){
5653
					return (getNodeIndex(elem) == ncount);
5654
				}
5655
			}
5656
		}
5657
	};
5658
 
5659
	var defaultGetter = (d.isIE) ? function(cond){
5660
		var clc = cond.toLowerCase();
5661
		return function(elem){
5662
			return elem[cond]||elem[clc];
5663
		}
5664
	} : function(cond){
5665
		return function(elem){
5666
			return (elem && elem.getAttribute && elem.hasAttribute(cond));
5667
		}
5668
	};
5669
 
5670
	var getSimpleFilterFunc = function(query){
5671
 
5672
		var fcHit = (_simpleFiltersCache[query.query]||_filtersCache[query.query]);
5673
		if(fcHit){ return fcHit; }
5674
 
5675
		var ff = null;
5676
 
5677
		// the only case where we'll need the tag name is if we came from an ID query
5678
		if(query.id){ // do we have an ID component?
5679
			if(query.tag != "*"){
5680
				ff = agree(ff, function(elem){
5681
					return (elem.tagName.toLowerCase() == query.tag);
5682
				});
5683
			}
5684
		}
5685
 
5686
		// if there's a class in our query, generate a match function for it
5687
		d.forEach(query.classes, function(cname, idx, arr){
5688
			// get the class name
5689
			var isWildcard = cname.charAt(cname.length-1) == "*";
5690
			if(isWildcard){
5691
				cname = cname.substr(0, cname.length-1);
5692
			}
5693
			// I dislike the regex thing, even if memozied in a cache, but it's VERY short
5694
			var re = new RegExp("(?:^|\\s)" + cname + (isWildcard ? ".*" : "") + "(?:\\s|$)");
5695
			ff = agree(ff, function(elem){
5696
				return re.test(elem.className);
5697
			});
5698
			ff.count = idx;
5699
		});
5700
 
5701
		d.forEach(query.pseudos, function(pseudo){
5702
			if(pseudos[pseudo.name]){
5703
				ff = agree(ff, pseudos[pseudo.name](pseudo.name, pseudo.value));
5704
			}
5705
		});
5706
 
5707
		handleAttrs(attrs, query, defaultGetter,
5708
			function(tmatcher){ ff = agree(ff, tmatcher); }
5709
		);
5710
		if(!ff){
5711
			ff = function(){ return true; };
5712
		}
5713
		return _simpleFiltersCache[query.query] = ff;
5714
	}
5715
 
5716
	var _getElementsFuncCache = { };
5717
 
5718
	var getElementsFunc = function(query, root){
5719
		var fHit = _getElementsFuncCache[query.query];
5720
		if(fHit){ return fHit; }
5721
 
5722
		// NOTE: this function is in the fast path! not memoized!!!
5723
 
5724
		// the query doesn't contain any spaces, so there's only so many
5725
		// things it could be
5726
 
5727
		if(query.id && !query.hasLoops && !query.tag){
5728
			// ID-only query. Easy.
5729
			return _getElementsFuncCache[query.query] = function(root){
5730
				// FIXME: if root != document, check for parenting!
5731
				return [ d.byId(query.id) ];
5732
			}
5733
		}
5734
 
5735
		var filterFunc = getSimpleFilterFunc(query);
5736
 
5737
		var retFunc;
5738
		if(query.tag && query.id && !query.hasLoops){
5739
			// we got a filtered ID search (e.g., "h4#thinger")
5740
			retFunc = function(root){
5741
				var te = d.byId(query.id);
5742
				if(filterFunc(te)){
5743
					return [ te ];
5744
				}
5745
			}
5746
		}else{
5747
			var tret;
5748
 
5749
			if(!query.hasLoops){
5750
				// it's just a plain-ol elements-by-tag-name query from the root
5751
				retFunc = function(root){
5752
					var ret = [];
5753
					var te, x=0, tret = root.getElementsByTagName(query.tag);
5754
					while(te=tret[x++]){
5755
						ret.push(te);
5756
					}
5757
					return ret;
5758
				}
5759
			}else{
5760
				retFunc = function(root){
5761
					var ret = [];
5762
					var te, x=0, tret = root.getElementsByTagName(query.tag);
5763
					while(te=tret[x++]){
5764
						if(filterFunc(te)){
5765
							ret.push(te);
5766
						}
5767
					}
5768
					return ret;
5769
				}
5770
			}
5771
		}
5772
		return _getElementsFuncCache[query.query] = retFunc;
5773
	}
5774
 
5775
	var _partsCache = {};
5776
 
5777
	////////////////////////////////////////////////////////////////////////
5778
	// the query runner
5779
	////////////////////////////////////////////////////////////////////////
5780
 
5781
	// this is the second level of spliting, from full-length queries (e.g.,
5782
	// "div.foo .bar") into simple query expressions (e.g., ["div.foo",
5783
	// ".bar"])
5784
	var _queryFuncCache = {
5785
		"*": d.isIE ?
5786
			function(root){
5787
					return root.all;
5788
			} :
5789
			function(root){
5790
				 return root.getElementsByTagName("*");
5791
			},
5792
		">": function(root){
5793
			var ret = [];
5794
			var te, x=0, tret = root[childNodesName];
5795
			while(te=tret[x++]){
5796
				if(te.nodeType == 1){ ret.push(te); }
5797
			}
5798
			return ret;
5799
		}
5800
	};
5801
 
5802
	var getStepQueryFunc = function(query){
5803
		// if it's trivial, get a fast-path dispatcher
5804
		var qparts = getQueryParts(d.trim(query));
5805
		// if(query[query.length-1] == ">"){ query += " *"; }
5806
		if(qparts.length == 1){
5807
			var tt = getElementsFunc(qparts[0]);
5808
			tt.nozip = true;
5809
			return tt;
5810
		}
5811
 
5812
		// otherwise, break it up and return a runner that iterates over the parts recursively
5813
		var sqf = function(root){
5814
			var localQueryParts = qparts.slice(0); // clone the src arr
5815
			var candidates;
5816
			if(localQueryParts[0].oper == ">"){
5817
				candidates = [ root ];
5818
				// root = document;
5819
			}else{
5820
				candidates = getElementsFunc(localQueryParts.shift())(root);
5821
			}
5822
			return filterDown(candidates, localQueryParts);
5823
		}
5824
		return sqf;
5825
	}
5826
 
5827
	// a specialized method that implements our primoridal "query optimizer".
5828
	// This allows us to dispatch queries to the fastest subsystem we can get.
5829
	var _getQueryFunc = (
5830
		// NOTE:
5831
		//		XPath on the Webkit nighlies is slower than it's DOM iteration
5832
		//		for most test cases
5833
		// FIXME:
5834
		//		we should try to capture some runtime speed data for each query
5835
		//		function to determine on the fly if we should stick w/ the
5836
		//		potentially optimized variant or if we should try something
5837
		//		new.
5838
		(document["evaluate"] && !d.isSafari) ?
5839
		function(query){
5840
			// has xpath support that's faster than DOM
5841
			var qparts = query.split(" ");
5842
			// can we handle it?
5843
			if(	(document["evaluate"])&&
5844
				(query.indexOf(":") == -1)&&
5845
				(
5846
					(true) // ||
5847
					// (query.indexOf("[") == -1) ||
5848
					// (query.indexOf("=") == -1)
5849
				)
5850
			){
5851
				// dojo.debug(query);
5852
				// should we handle it?
5853
 
5854
				// kind of a lame heuristic, but it works
5855
				if(
5856
					// a "div div div" style query
5857
					((qparts.length > 2)&&(query.indexOf(">") == -1))||
5858
					// or something else with moderate complexity. kinda janky
5859
					(qparts.length > 3)||
5860
					(query.indexOf("[")>=0)||
5861
					// or if it's a ".thinger" query
5862
					((1 == qparts.length)&&(0 <= query.indexOf(".")))
5863
 
5864
				){
5865
					// use get and cache a xpath runner for this selector
5866
					return getXPathFunc(query);
5867
				}
5868
			}
5869
 
5870
			// fallthrough
5871
			return getStepQueryFunc(query);
5872
		} : getStepQueryFunc
5873
	);
5874
	// uncomment to disable XPath for testing and tuning the DOM path
5875
	// _getQueryFunc = getStepQueryFunc;
5876
 
5877
	// FIXME: we've got problems w/ the NodeList query()/filter() functions if we go XPath for everything
5878
 
5879
	// uncomment to disable DOM queries for testing and tuning XPath
5880
	// _getQueryFunc = getXPathFunc;
5881
 
5882
	// this is the primary caching for full-query results. The query dispatcher
5883
	// functions are generated here and then pickled for hash lookup in the
5884
	// future
5885
	var getQueryFunc = function(query){
5886
		// return a cached version if one is available
5887
		if(_queryFuncCache[query]){ return _queryFuncCache[query]; }
5888
		if(0 > query.indexOf(",")){
5889
			// if it's not a compound query (e.g., ".foo, .bar"), cache and return a dispatcher
5890
			return _queryFuncCache[query] = _getQueryFunc(query);
5891
		}else{
5892
			// if it's a complex query, break it up into it's constituent parts
5893
			// and return a dispatcher that will merge the parts when run
5894
 
5895
			// var parts = query.split(", ");
5896
			var parts = query.split(/\s*,\s*/);
5897
			var tf = function(root){
5898
				var pindex = 0; // avoid array alloc for every invocation
5899
				var ret = [];
5900
				var tp;
5901
				while(tp = parts[pindex++]){
5902
					ret = ret.concat(_getQueryFunc(tp, tp.indexOf(" "))(root));
5903
				}
5904
				return ret;
5905
			}
5906
			// ...cache and return
5907
			return _queryFuncCache[query] = tf;
5908
		}
5909
	}
5910
 
5911
	// FIXME:
5912
	//		Dean's new Base2 uses a system whereby queries themselves note if
5913
	//		they'll need duplicate filtering. We need to get on that plan!!
5914
 
5915
	// attempt to efficiently determine if an item in a list is a dupe,
5916
	// returning a list of "uniques", hopefully in doucment order
5917
	var _zipIdx = 0;
5918
	var _zip = function(arr){
5919
		if(arr && arr.nozip){ return d.NodeList._wrap(arr); }
5920
		var ret = new d.NodeList();
5921
		if(!arr){ return ret; }
5922
		if(arr[0]){
5923
			ret.push(arr[0]);
5924
		}
5925
		if(arr.length < 2){ return ret; }
5926
		_zipIdx++;
5927
		arr[0]["_zipIdx"] = _zipIdx;
5928
		for(var x=1, te; te = arr[x]; x++){
5929
			if(arr[x]["_zipIdx"] != _zipIdx){
5930
				ret.push(te);
5931
			}
5932
			te["_zipIdx"] = _zipIdx;
5933
		}
5934
		// FIXME: should we consider stripping these properties?
5935
		return ret;
5936
	}
5937
 
5938
	// the main exectuor
5939
	d.query = function(query, root){
5940
		//	summary:
5941
		//		returns nodes which match the given CSS3 selector, searching the
5942
		//		entire document by default but optionally taking a node to scope
5943
		//		the search by. Returns an instance of dojo.NodeList.
5944
		//	description:
5945
		//		dojo.query() is the swiss army knife of DOM node manipulation in
5946
		//		Dojo. Much like Prototype's "$$" (bling-bling) function or JQuery's
5947
		//		"$" function, dojo.query provides robust, high-performance
5948
		//		CSS-based node selector support with the option of scoping searches
5949
		//		to a particular sub-tree of a document.
5950
		//
5951
		//		Supported Selectors:
5952
		//		--------------------
5953
		//
5954
		//		dojo.query() supports a rich set of CSS3 selectors, including:
5955
		//
5956
		//			* class selectors (e.g., ".foo")
5957
		//			* node type selectors like "span"
5958
		//			* " " descendant selectors
5959
		//			* ">" child element selectors
5960
		//			* "#foo" style ID selectors
5961
		//			* "*" universal selector
5962
		//			* attribute queries:
5963
		//				* "[foo]" attribute presence selector
5964
		//				* "[foo='bar']" attribute value exact match
5965
		//				* "[foo~='bar']" attribute value list item match
5966
		//				* "[foo^='bar']" attribute start match
5967
		//				* "[foo$='bar']" attribute end match
5968
		//				* "[foo*='bar']" attribute substring match
5969
		//			* ":first-child", ":last-child" positional selectors
5970
		//			* ":nth-child(n)", ":nth-child(2n+1)" style positional calculations
5971
		//			* ":nth-child(even)", ":nth-child(odd)" positional selectors
5972
		//			* ":not(...)" negation pseudo selectors
5973
		//
5974
		//		Any legal combination of those selector types as per the CSS 3 sepc
5975
		//		will work with dojo.query(), including compound selectors (","
5976
		//		delimited). Very complex and useful searches can be constructed
5977
		//		with this palette of selectors and when combined with functions for
5978
		//		maniplation presented by dojo.NodeList, many types of DOM
5979
		//		manipulation operations become very straightforward.
5980
		//
5981
		//		Unsupported Selectors:
5982
		//		--------------------
5983
		//
5984
		//		While dojo.query handles many CSS3 selectors, some fall outside of
5985
		//		what's resaonable for a programmatic node querying engine to
5986
		//		handle. Currently unsupported selectors include:
5987
		//
5988
		//			* namespace-differentiated selectors of any form
5989
		//			* "~", the immediately preceeded-by sibling selector
5990
		//			* "+", the preceeded-by sibling selector
5991
		//			* all "::" pseduo-element selectors
5992
		//			* certain pseduo-selectors which don't get a lot of day-to-day use:
5993
		//				* :root, :lang(), :target, :focus
5994
		//			* all visual and state selectors:
5995
		//				* :root, :active, :hover, :visisted, :link, :enabled, :disabled, :checked
5996
		//			* :*-of-type pseudo selectors
5997
		//
5998
		//		dojo.query and XML Documents:
5999
		//		-----------------------------
6000
		//		FIXME
6001
		//
6002
		//	query: String
6003
		//		The CSS3 expression to match against. For details on the syntax of
6004
		//		CSS3 selectors, see:
6005
		//			http://www.w3.org/TR/css3-selectors/#selectors
6006
		//	root: String|DOMNode?
6007
		//		A node (or string ID of a node) to scope the search from. Optional.
6008
		//	returns:
6009
		//		An instance of dojo.NodeList. Many methods are available on
6010
		//		NodeLists for searching, iterating, manipulating, and handling
6011
		//		events on the matched nodes in the returned list.
6012
 
6013
		// return is always an array
6014
		// NOTE: elementsById is not currently supported
6015
		// NOTE: ignores xpath-ish queries for now
6016
		if(query.constructor == d.NodeList){
6017
			return query;
6018
		}
6019
		if(!d.isString(query)){
6020
			return new d.NodeList(query); // dojo.NodeList
6021
		}
6022
		if(d.isString(root)){
6023
			root = d.byId(root);
6024
		}
6025
 
6026
		// FIXME: should support more methods on the return than the stock array.
6027
		return _zip(getQueryFunc(query)(root||d.doc));
6028
	}
6029
 
6030
	/*
6031
	// exposing these was a mistake
6032
	d.query.attrs = attrs;
6033
	d.query.pseudos = pseudos;
6034
	*/
6035
 
6036
	// one-off function for filtering a NodeList based on a simple selector
6037
	d._filterQueryResult = function(nodeList, simpleFilter){
6038
		var tnl = new d.NodeList();
6039
		var ff = (simpleFilter) ? getFilterFunc(getQueryParts(simpleFilter)[0]) : function(){ return true; };
6040
		for(var x=0, te; te = nodeList[x]; x++){
6041
			if(ff(te)){ tnl.push(te); }
6042
		}
6043
		return tnl;
6044
	}
6045
})();
6046
 
6047
}
6048
 
6049
if(!dojo._hasResource["dojo._base.xhr"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
6050
dojo._hasResource["dojo._base.xhr"] = true;
6051
dojo.provide("dojo._base.xhr");
6052
 
6053
 
6054
 
6055
 
6056
 
6057
(function(){
6058
	var _d = dojo;
6059
	function setValue(/*Object*/obj, /*String*/name, /*String*/value){
6060
		//summary:
6061
		//		For the nameed property in object, set the value. If a value
6062
		//		already exists and it is a string, convert the value to be an
6063
		//		array of values.
6064
		var val = obj[name];
6065
		if(_d.isString(val)){
6066
			obj[name] = [val, value];
6067
		}else if(_d.isArray(val)){
6068
			val.push(value);
6069
		}else{
6070
			obj[name] = value;
6071
		}
6072
	}
6073
 
6074
	dojo.formToObject = function(/*DOMNode||String*/ formNode){
6075
		// summary:
6076
		//		dojo.formToObject returns the values encoded in an HTML form as
6077
		//		string properties in an object which it then returns. Disabled form
6078
		//		elements, buttons, and other non-value form elements are skipped.
6079
		//		Multi-select elements are returned as an array of string values.
6080
		// description:
6081
		//		This form:
6082
		//
6083
		//			<form id="test_form">
6084
		//				<input type="text" name="blah" value="blah">
6085
		//				<input type="text" name="no_value" value="blah" disabled>
6086
		//				<input type="button" name="no_value2" value="blah">
6087
		//				<select type="select" multiple name="multi" size="5">
6088
		//					<option value="blah">blah</option>
6089
		//					<option value="thud" selected>thud</option>
6090
		//					<option value="thonk" selected>thonk</option>
6091
		//				</select>
6092
		//			</form>
6093
		//
6094
		//		yields this object structure as the result of a call to
6095
		//		formToObject():
6096
		//
6097
		//			{
6098
		//				blah: "blah",
6099
		//				multi: [
6100
		//					"thud",
6101
		//					"thonk"
6102
		//				]
6103
		//			};
6104
 
6105
		var ret = {};
6106
		var iq = "input:not([type=file]):not([type=submit]):not([type=image]):not([type=reset]):not([type=button]), select, textarea";
6107
		_d.query(iq, formNode).filter(function(node){
6108
			return (!node.disabled);
6109
		}).forEach(function(item){
6110
			var _in = item.name;
6111
			var type = (item.type||"").toLowerCase();
6112
			if(type == "radio" || type == "checkbox"){
6113
				if(item.checked){ setValue(ret, _in, item.value); }
6114
			}else if(item.multiple){
6115
				ret[_in] = [];
6116
				_d.query("option", item).forEach(function(opt){
6117
					if(opt.selected){
6118
						setValue(ret, _in, opt.value);
6119
					}
6120
				});
6121
			}else{
6122
				setValue(ret, _in, item.value);
6123
				if(type == "image"){
6124
					ret[_in+".x"] = ret[_in+".y"] = ret[_in].x = ret[_in].y = 0;
6125
				}
6126
			}
6127
		});
6128
		return ret; // Object
6129
	}
6130
 
6131
	dojo.objectToQuery = function(/*Object*/ map){
6132
		//	summary:
6133
		//		takes a key/value mapping object and returns a string representing
6134
		//		a URL-encoded version of that object.
6135
		//	example:
6136
		//		this object:
6137
		//
6138
		//		|	{
6139
		//		|		blah: "blah",
6140
		//		|		multi: [
6141
		//		|			"thud",
6142
		//		|			"thonk"
6143
		//		|		]
6144
		//		|	};
6145
		//
6146
		//	yeilds the following query string:
6147
		//
6148
		//	|	"blah=blah&multi=thud&multi=thonk"
6149
 
6150
 
6151
		// FIXME: need to implement encodeAscii!!
6152
		var ec = encodeURIComponent;
6153
		var ret = "";
6154
		var backstop = {};
6155
		for(var x in map){
6156
			if(map[x] != backstop[x]){
6157
				if(_d.isArray(map[x])){
6158
					for(var y=0; y<map[x].length; y++){
6159
						ret += ec(x) + "=" + ec(map[x][y]) + "&";
6160
					}
6161
				}else{
6162
					ret += ec(x) + "=" + ec(map[x]) + "&";
6163
				}
6164
			}
6165
		}
6166
		if(ret.length && ret.charAt(ret.length-1) == "&"){
6167
			ret = ret.substr(0, ret.length-1);
6168
		}
6169
		return ret; // String
6170
	}
6171
 
6172
	dojo.formToQuery = function(/*DOMNode||String*/ formNode){
6173
		// summary:
6174
		//		return URL-encoded string representing the form passed as either a
6175
		//		node or string ID identifying the form to serialize
6176
		return _d.objectToQuery(_d.formToObject(formNode)); // String
6177
	}
6178
 
6179
	dojo.formToJson = function(/*DOMNode||String*/ formNode, /*Boolean?*/prettyPrint){
6180
		// summary:
6181
		//		return a serialized JSON string from a form node or string
6182
		//		ID identifying the form to serialize
6183
		return _d.toJson(_d.formToObject(formNode), prettyPrint); // String
6184
	}
6185
 
6186
	dojo.queryToObject = function(/*String*/ str){
6187
		// summary:
6188
		//		returns an object representing a de-serialized query section of a
6189
		//		URL. Query keys with multiple values are returned in an array.
6190
		// description:
6191
		//		This string:
6192
		//
6193
		//			"foo=bar&foo=baz&thinger=%20spaces%20=blah&zonk=blarg&"
6194
		//
6195
		//		returns this object structure:
6196
		//
6197
		//			{
6198
		//				foo: [ "bar", "baz" ],
6199
		//				thinger: " spaces =blah",
6200
		//				zonk: "blarg"
6201
		//			}
6202
		//
6203
		//		Note that spaces and other urlencoded entities are correctly
6204
		//		handled.
6205
 
6206
		// FIXME: should we grab the URL string if we're not passed one?
6207
		var ret = {};
6208
		var qp = str.split("&");
6209
		var dc = decodeURIComponent;
6210
		_d.forEach(qp, function(item){
6211
			if(item.length){
6212
				var parts = item.split("=");
6213
				var name = dc(parts.shift());
6214
				var val = dc(parts.join("="));
6215
				if(_d.isString(ret[name])){
6216
					ret[name] = [ret[name]];
6217
				}
6218
				if(_d.isArray(ret[name])){
6219
					ret[name].push(val);
6220
				}else{
6221
					ret[name] = val;
6222
				}
6223
			}
6224
		});
6225
		return ret; // Object
6226
	}
6227
 
6228
	/*
6229
		from refactor.txt:
6230
 
6231
		all bind() replacement APIs take the following argument structure:
6232
 
6233
			{
6234
				url: "blah.html",
6235
 
6236
				// all below are optional, but must be supported in some form by
6237
				// every IO API
6238
				timeout: 1000, // milliseconds
6239
				handleAs: "text", // replaces the always-wrong "mimetype"
6240
				content: {
6241
					key: "value"
6242
				},
6243
 
6244
				// browser-specific, MAY be unsupported
6245
				sync: true, // defaults to false
6246
				form: dojo.byId("someForm")
6247
			}
6248
	*/
6249
 
6250
	// need to block async callbacks from snatching this thread as the result
6251
	// of an async callback might call another sync XHR, this hangs khtml forever
6252
	// must checked by watchInFlight()
6253
 
6254
	dojo._blockAsync = false;
6255
 
6256
	dojo._contentHandlers = {
6257
		"text": function(xhr){ return xhr.responseText; },
6258
		"json": function(xhr){
6259
			if(!djConfig.usePlainJson){
6260
				console.debug("Consider using mimetype:text/json-comment-filtered"
6261
					+ " to avoid potential security issues with JSON endpoints"
6262
					+ " (use djConfig.usePlainJson=true to turn off this message)");
6263
			}
6264
			return _d.fromJson(xhr.responseText);
6265
		},
6266
		"json-comment-filtered": function(xhr){
6267
			// NOTE: we provide the json-comment-filtered option as one solution to
6268
			// the "JavaScript Hijacking" issue noted by Fortify and others. It is
6269
			// not appropriate for all circumstances.
6270
 
6271
			var value = xhr.responseText;
6272
			var cStartIdx = value.indexOf("\/*");
6273
			var cEndIdx = value.lastIndexOf("*\/");
6274
			if(cStartIdx == -1 || cEndIdx == -1){
6275
				throw new Error("JSON was not comment filtered");
6276
			}
6277
			return _d.fromJson(value.substring(cStartIdx+2, cEndIdx));
6278
		},
6279
		"javascript": function(xhr){
6280
			// FIXME: try Moz and IE specific eval variants?
6281
			return _d.eval(xhr.responseText);
6282
		},
6283
		"xml": function(xhr){
6284
			if(_d.isIE && !xhr.responseXML){
6285
				_d.forEach(["MSXML2", "Microsoft", "MSXML", "MSXML3"], function(i){
6286
					try{
6287
						var doc = new ActiveXObject(prefixes[i]+".XMLDOM");
6288
						doc.async = false;
6289
						doc.loadXML(xhr.responseText);
6290
						return doc;	//	DOMDocument
6291
					}catch(e){ /* squelch */ };
6292
				});
6293
			}else{
6294
				return xhr.responseXML;
6295
			}
6296
		}
6297
	};
6298
 
6299
	dojo._contentHandlers["json-comment-optional"] = function(xhr){
6300
		var handlers = _d._contentHandlers;
6301
		try{
6302
			return handlers["json-comment-filtered"](xhr);
6303
		}catch(e){
6304
			return handlers["json"](xhr);
6305
		}
6306
	};
6307
 
6308
	/*=====
6309
	dojo.__ioArgs = function(kwArgs){
6310
		//	url: String
6311
		//		URL to server endpoint.
6312
		//	content: Object?
6313
		//		Contains properties with string values. These
6314
		//		properties will be serialized as name1=value2 and
6315
		//		passed in the request.
6316
		//	timeout: Integer?
6317
		//		Milliseconds to wait for the response. If this time
6318
		//		passes, the then error callbacks are called.
6319
		//	form: DOMNode?
6320
		//		DOM node for a form. Used to extract the form values
6321
		//		and send to the server.
6322
		//	preventCache: Boolean?
6323
		//		Default is false. If true, then a
6324
		//		"dojo.preventCache" parameter is sent in the request
6325
		//		with a value that changes with each request
6326
		//		(timestamp). Useful only with GET-type requests.
6327
		//	handleAs: String?
6328
		//		Acceptable values depend on the type of IO
6329
		//		transport (see specific IO calls for more information).
6330
		//	load: Function?
6331
		//		function(response, ioArgs){}. response is an Object, ioArgs
6332
		//		is of type dojo.__ioCallbackArgs. The load function will be
6333
		//		called on a successful response.
6334
		//	error: Function?
6335
		//		function(response, ioArgs){}. response is an Object, ioArgs
6336
		//		is of type dojo.__ioCallbackArgs. The error function will
6337
		//		be called in an error case.
6338
		//	handle: Function
6339
		//		function(response, ioArgs){}. response is an Object, ioArgs
6340
		//		is of type dojo.__ioCallbackArgs. The handle function will
6341
		//		be called in either the successful or error case.  For
6342
		//		the load, error and handle functions, the ioArgs object
6343
		//		will contain the following properties:
6344
	}
6345
	=====*/
6346
 
6347
	/*=====
6348
	dojo.__ioCallbackArgs = function(kwArgs){
6349
		//	args: Object
6350
		//		the original object argument to the IO call.
6351
		//	xhr: XMLHttpRequest
6352
		//		For XMLHttpRequest calls only, the
6353
		//		XMLHttpRequest object that was used for the
6354
		//		request.
6355
		//	url: String
6356
		//		The final URL used for the call. Many times it
6357
		//		will be different than the original args.url
6358
		//		value.
6359
		//	query: String
6360
		//		For non-GET requests, the
6361
		//		name1=value1&name2=value2 parameters sent up in
6362
		//		the request.
6363
		//	handleAs: String
6364
		//		The final indicator on how the response will be
6365
		//		handled.
6366
		//	id: String
6367
		//		For dojo.io.script calls only, the internal
6368
		//		script ID used for the request.
6369
		//	canDelete: Boolean
6370
		//		For dojo.io.script calls only, indicates
6371
		//		whether the script tag that represents the
6372
		//		request can be deleted after callbacks have
6373
		//		been called. Used internally to know when
6374
		//		cleanup can happen on JSONP-type requests.
6375
		//	json: Object
6376
		//		For dojo.io.script calls only: holds the JSON
6377
		//		response for JSONP-type requests. Used
6378
		//		internally to hold on to the JSON responses.
6379
		//		You should not need to access it directly --
6380
		//		the same object should be passed to the success
6381
		//		callbacks directly.
6382
	}
6383
	=====*/
6384
 
6385
 
6386
 
6387
	dojo._ioSetArgs = function(/*dojo.__ioArgs*/args,
6388
			/*Function*/canceller,
6389
			/*Function*/okHandler,
6390
			/*Function*/errHandler){
6391
		//	summary:
6392
		//		sets up the Deferred and ioArgs property on the Deferred so it
6393
		//		can be used in an io call.
6394
		//	args:
6395
		//		The args object passed into the public io call. Recognized properties on
6396
		//		the args object are:
6397
		//	canceller:
6398
		//		The canceller function used for the Deferred object. The function
6399
		//		will receive one argument, the Deferred object that is related to the
6400
		//		canceller.
6401
		//	okHandler:
6402
		//		The first OK callback to be registered with Deferred. It has the opportunity
6403
		//		to transform the OK response. It will receive one argument -- the Deferred
6404
		//		object returned from this function.
6405
		//	errHandler:
6406
		//		The first error callback to be registered with Deferred. It has the opportunity
6407
		//		to do cleanup on an error. It will receive two arguments: error (the
6408
		//		Error object) and dfd, the Deferred object returned from this function.
6409
 
6410
		var ioArgs = {args: args, url: args.url};
6411
 
6412
		//Get values from form if requestd.
6413
		var formObject = null;
6414
		if(args.form){
6415
			var form = _d.byId(args.form);
6416
			//IE requires going through getAttributeNode instead of just getAttribute in some form cases,
6417
			//so use it for all.  See #2844
6418
			var actnNode = form.getAttributeNode("action");
6419
			ioArgs.url = ioArgs.url || (actnNode ? actnNode.value : null);
6420
			formObject = _d.formToObject(form);
6421
		}
6422
 
6423
		// set up the query params
6424
		var miArgs = [{}];
6425
 
6426
		if(formObject){
6427
			// potentially over-ride url-provided params w/ form values
6428
			miArgs.push(formObject);
6429
		}
6430
		if(args.content){
6431
			// stuff in content over-rides what's set by form
6432
			miArgs.push(args.content);
6433
		}
6434
		if(args.preventCache){
6435
			miArgs.push({"dojo.preventCache": new Date().valueOf()});
6436
		}
6437
		ioArgs.query = _d.objectToQuery(_d.mixin.apply(null, miArgs));
6438
 
6439
		// .. and the real work of getting the deferred in order, etc.
6440
		ioArgs.handleAs = args.handleAs || "text";
6441
		var d = new _d.Deferred(canceller);
6442
		d.addCallbacks(okHandler, function(error){
6443
			return errHandler(error, d);
6444
		});
6445
 
6446
		//Support specifying load, error and handle callback functions from the args.
6447
		//For those callbacks, the "this" object will be the args object.
6448
		//The callbacks will get the deferred result value as the
6449
		//first argument and the ioArgs object as the second argument.
6450
		var ld = args.load;
6451
		if(ld && _d.isFunction(ld)){
6452
			d.addCallback(function(value){
6453
				return ld.call(args, value, ioArgs);
6454
			});
6455
		}
6456
		var err = args.error;
6457
		if(err && _d.isFunction(err)){
6458
			d.addErrback(function(value){
6459
				return err.call(args, value, ioArgs);
6460
			});
6461
		}
6462
		var handle = args.handle;
6463
		if(handle && _d.isFunction(handle)){
6464
			d.addBoth(function(value){
6465
				return handle.call(args, value, ioArgs);
6466
			});
6467
		}
6468
 
6469
		d.ioArgs = ioArgs;
6470
 
6471
		// FIXME: need to wire up the xhr object's abort method to something
6472
		// analagous in the Deferred
6473
		return d;
6474
	}
6475
 
6476
	var _deferredCancel = function(/*Deferred*/dfd){
6477
		//summary: canceller function for dojo._ioSetArgs call.
6478
 
6479
		dfd.canceled = true;
6480
		var xhr = dfd.ioArgs.xhr;
6481
		var _at = (typeof xhr.abort);
6482
		if((_at == "function")||(_at == "unknown")){
6483
			xhr.abort();
6484
		}
6485
		var err = new Error("xhr cancelled");
6486
		err.dojoType = "cancel";
6487
		return err;
6488
	}
6489
	var _deferredOk = function(/*Deferred*/dfd){
6490
		//summary: okHandler function for dojo._ioSetArgs call.
6491
 
6492
		return _d._contentHandlers[dfd.ioArgs.handleAs](dfd.ioArgs.xhr);
6493
	}
6494
	var _deferError = function(/*Error*/error, /*Deferred*/dfd){
6495
		//summary: errHandler function for dojo._ioSetArgs call.
6496
 
6497
		// console.debug("xhr error in:", dfd.ioArgs.xhr);
6498
		console.debug(error);
6499
		return error;
6500
	}
6501
 
6502
	var _makeXhrDeferred = function(/*dojo.__xhrArgs*/args){
6503
		//summary: makes the Deferred object for this xhr request.
6504
		var dfd = _d._ioSetArgs(args, _deferredCancel, _deferredOk, _deferError);
6505
		//Pass the args to _xhrObj, to allow xhr iframe proxy interceptions.
6506
		dfd.ioArgs.xhr = _d._xhrObj(dfd.ioArgs.args);
6507
		return dfd;
6508
	}
6509
 
6510
	// avoid setting a timer per request. It degrades performance on IE
6511
	// something fierece if we don't use unified loops.
6512
	var _inFlightIntvl = null;
6513
	var _inFlight = [];
6514
	var _watchInFlight = function(){
6515
		//summary:
6516
		//		internal method that checks each inflight XMLHttpRequest to see
6517
		//		if it has completed or if the timeout situation applies.
6518
 
6519
		var now = (new Date()).getTime();
6520
		// make sure sync calls stay thread safe, if this callback is called
6521
		// during a sync call and this results in another sync call before the
6522
		// first sync call ends the browser hangs
6523
		if(!_d._blockAsync){
6524
			// we need manual loop because we often modify _inFlight (and therefore 'i') while iterating
6525
			// note: the second clause is an assigment on purpose, lint may complain
6526
			for(var i=0, tif; (i<_inFlight.length)&&(tif=_inFlight[i]); i++){
6527
				var dfd = tif.dfd;
6528
				try{
6529
					if(!dfd || dfd.canceled || !tif.validCheck(dfd)){
6530
						_inFlight.splice(i--, 1);
6531
					}else if(tif.ioCheck(dfd)){
6532
						_inFlight.splice(i--, 1);
6533
						tif.resHandle(dfd);
6534
					}else if(dfd.startTime){
6535
						//did we timeout?
6536
						if(dfd.startTime + (dfd.ioArgs.args.timeout||0) < now){
6537
							_inFlight.splice(i--, 1);
6538
							var err = new Error("timeout exceeded");
6539
							err.dojoType = "timeout";
6540
							dfd.errback(err);
6541
							//Cancel the request so the io module can do appropriate cleanup.
6542
							dfd.cancel();
6543
						}
6544
					}
6545
				}catch(e){
6546
					// FIXME: make sure we errback!
6547
					console.debug(e);
6548
					dfd.errback(new Error("_watchInFlightError!"));
6549
				}
6550
			}
6551
		}
6552
 
6553
		if(!_inFlight.length){
6554
			clearInterval(_inFlightIntvl);
6555
			_inFlightIntvl = null;
6556
			return;
6557
		}
6558
 
6559
	}
6560
 
6561
	dojo._ioCancelAll = function(){
6562
		//summary: Cancels all pending IO requests, regardless of IO type
6563
		//(xhr, script, iframe).
6564
		try{
6565
			_d.forEach(_inFlight, function(i){
6566
				i.dfd.cancel();
6567
			});
6568
		}catch(e){/*squelch*/}
6569
	}
6570
 
6571
	//Automatically call cancel all io calls on unload
6572
	//in IE for trac issue #2357.
6573
	if(_d.isIE){
6574
		_d.addOnUnload(_d._ioCancelAll);
6575
	}
6576
 
6577
	_d._ioWatch = function(/*Deferred*/dfd,
6578
		/*Function*/validCheck,
6579
		/*Function*/ioCheck,
6580
		/*Function*/resHandle){
6581
		//summary: watches the io request represented by dfd to see if it completes.
6582
		//dfd:
6583
		//		The Deferred object to watch.
6584
		//validCheck:
6585
		//		Function used to check if the IO request is still valid. Gets the dfd
6586
		//		object as its only argument.
6587
		//ioCheck:
6588
		//		Function used to check if basic IO call worked. Gets the dfd
6589
		//		object as its only argument.
6590
		//resHandle:
6591
		//		Function used to process response. Gets the dfd
6592
		//		object as its only argument.
6593
		if(dfd.ioArgs.args.timeout){
6594
			dfd.startTime = (new Date()).getTime();
6595
		}
6596
		_inFlight.push({dfd: dfd, validCheck: validCheck, ioCheck: ioCheck, resHandle: resHandle});
6597
		if(!_inFlightIntvl){
6598
			_inFlightIntvl = setInterval(_watchInFlight, 50);
6599
		}
6600
		_watchInFlight(); // handle sync requests
6601
	}
6602
 
6603
	var _defaultContentType = "application/x-www-form-urlencoded";
6604
 
6605
	var _validCheck = function(/*Deferred*/dfd){
6606
		return dfd.ioArgs.xhr.readyState; //boolean
6607
	}
6608
	var _ioCheck = function(/*Deferred*/dfd){
6609
		return 4 == dfd.ioArgs.xhr.readyState; //boolean
6610
	}
6611
	var _resHandle = function(/*Deferred*/dfd){
6612
		if(_d._isDocumentOk(dfd.ioArgs.xhr)){
6613
			dfd.callback(dfd);
6614
		}else{
6615
			dfd.errback(new Error("bad http response code:" + dfd.ioArgs.xhr.status));
6616
		}
6617
	}
6618
 
6619
	var _doIt = function(/*String*/type, /*Deferred*/dfd){
6620
		// IE 6 is a steaming pile. It won't let you call apply() on the native function (xhr.open).
6621
		// workaround for IE6's apply() "issues"
6622
		var ioArgs = dfd.ioArgs;
6623
		var args = ioArgs.args;
6624
		ioArgs.xhr.open(type, ioArgs.url, args.sync !== true, args.user || undefined, args.password || undefined);
6625
		if(args.headers){
6626
			for(var hdr in args.headers){
6627
				if(hdr.toLowerCase() === "content-type" && !args.contentType){
6628
					args.contentType = args.headers[hdr];
6629
				}else{
6630
					ioArgs.xhr.setRequestHeader(hdr, args.headers[hdr]);
6631
				}
6632
			}
6633
		}
6634
		// FIXME: is this appropriate for all content types?
6635
		ioArgs.xhr.setRequestHeader("Content-Type", (args.contentType||_defaultContentType));
6636
		// FIXME: set other headers here!
6637
		try{
6638
			ioArgs.xhr.send(ioArgs.query);
6639
		}catch(e){
6640
			dfd.cancel();
6641
		}
6642
		_d._ioWatch(dfd, _validCheck, _ioCheck, _resHandle);
6643
		return dfd; //Deferred
6644
	}
6645
 
6646
	dojo._ioAddQueryToUrl = function(/*dojo.__ioCallbackArgs*/ioArgs){
6647
		//summary: Adds query params discovered by the io deferred construction to the URL.
6648
		//Only use this for operations which are fundamentally GET-type operations.
6649
		if(ioArgs.query.length){
6650
			ioArgs.url += (ioArgs.url.indexOf("?") == -1 ? "?" : "&") + ioArgs.query;
6651
			ioArgs.query = null;
6652
		}
6653
	}
6654
 
6655
	/*=====
6656
	dojo.__xhrArgs = function(kwArgs){
6657
		//	summary:
6658
		//		In addition to the properties listed for the dojo.__ioArgs type,
6659
		//		the following properties are allowed for dojo.xhr* methods.
6660
		//	handleAs:
6661
		//		String. Acceptable values are:
6662
		//			"text" (default)
6663
		//			"json"
6664
		//			"json-comment-optional"
6665
		//			"json-comment-filtered"
6666
		//			"javascript"
6667
		//			"xml"
6668
		//	sync:
6669
		//		Boolean. false is default. Indicates whether the request should
6670
		//		be a synchronous (blocking) request.
6671
		//	headers:
6672
		//		Object. Additional HTTP headers to send in the request.
6673
	}
6674
	=====*/
6675
 
6676
	dojo.xhrGet = function(/*dojo.__xhrArgs*/ args){
6677
		//	summary:
6678
		//		Sends an HTTP GET request to the server.
6679
		var dfd = _makeXhrDeferred(args);
6680
		_d._ioAddQueryToUrl(dfd.ioArgs);
6681
		return _doIt("GET", dfd); // dojo.Deferred
6682
	}
6683
 
6684
	dojo.xhrPost = function(/*dojo.__xhrArgs*/ args){
6685
		//summary:
6686
		//		Sends an HTTP POST request to the server.
6687
		return _doIt("POST", _makeXhrDeferred(args)); // dojo.Deferred
6688
	}
6689
 
6690
	dojo.rawXhrPost = function(/*dojo.__xhrArgs*/ args){
6691
		//	summary:
6692
		//		Sends an HTTP POST request to the server. In addtion to the properties
6693
		//		listed for the dojo.__xhrArgs type, the following property is allowed:
6694
		//	postData:
6695
		//		String. The raw data to send in the body of the POST request.
6696
		var dfd = _makeXhrDeferred(args);
6697
		dfd.ioArgs.query = args.postData;
6698
		return _doIt("POST", dfd); // dojo.Deferred
6699
	}
6700
 
6701
	dojo.xhrPut = function(/*dojo.__xhrArgs*/ args){
6702
		//	summary:
6703
		//		Sends an HTTP PUT request to the server.
6704
		return _doIt("PUT", _makeXhrDeferred(args)); // dojo.Deferred
6705
	}
6706
 
6707
	dojo.rawXhrPut = function(/*dojo.__xhrArgs*/ args){
6708
		//	summary:
6709
		//		Sends an HTTP PUT request to the server. In addtion to the properties
6710
		//		listed for the dojo.__xhrArgs type, the following property is allowed:
6711
		//	putData:
6712
		//		String. The raw data to send in the body of the PUT request.
6713
		var dfd = _makeXhrDeferred(args);
6714
		var ioArgs = dfd.ioArgs;
6715
		if(args["putData"]){
6716
			ioArgs.query = args.putData;
6717
			args.putData = null;
6718
		}
6719
		return _doIt("PUT", dfd); // dojo.Deferred
6720
	}
6721
 
6722
	dojo.xhrDelete = function(/*dojo.__xhrArgs*/ args){
6723
		//	summary:
6724
		//		Sends an HTTP DELETE request to the server.
6725
		var dfd = _makeXhrDeferred(args);
6726
		_d._ioAddQueryToUrl(dfd.ioArgs);
6727
		return _doIt("DELETE", dfd); // dojo.Deferred
6728
	}
6729
 
6730
	/*
6731
	dojo.wrapForm = function(formNode){
6732
		//summary:
6733
		//		A replacement for FormBind, but not implemented yet.
6734
 
6735
		// FIXME: need to think harder about what extensions to this we might
6736
		// want. What should we allow folks to do w/ this? What events to
6737
		// set/send?
6738
		throw new Error("dojo.wrapForm not yet implemented");
6739
	}
6740
	*/
6741
})();
6742
 
6743
}
6744
 
6745
if(!dojo._hasResource["dojo._base.fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
6746
dojo._hasResource["dojo._base.fx"] = true;
6747
dojo.provide("dojo._base.fx");
6748
 
6749
 
6750
 
6751
 
6752
 
6753
 
6754
/*
6755
	Animation losely package based on Dan Pupius' work, contributed under CLA:
6756
		http://pupius.co.uk/js/Toolkit.Drawing.js
6757
*/
6758
 
6759
dojo._Line = function(/*int*/ start, /*int*/ end){
6760
	//	summary:
6761
	//		dojo._Line is the object used to generate values from a start value
6762
	//		to an end value
6763
	//	start: int
6764
	//		Beginning value for range
6765
	//	end: int
6766
	//		Ending value for range
6767
	this.start = start;
6768
	this.end = end;
6769
	this.getValue = function(/*float*/ n){
6770
		//	summary: returns the point on the line
6771
		//	n: a floating point number greater than 0 and less than 1
6772
		return ((this.end - this.start) * n) + this.start; // Decimal
6773
	}
6774
}
6775
 
6776
dojo.declare("dojo._Animation", null, {
6777
	//	summary
6778
	//		A generic animation object that fires callbacks into it's handlers
6779
	//		object at various states
6780
	//
6781
	constructor: function(/*Object*/ args){
6782
		dojo.mixin(this, args);
6783
		if(dojo.isArray(this.curve)){
6784
			/* curve: Array
6785
				pId: a */
6786
			this.curve = new dojo._Line(this.curve[0], this.curve[1]);
6787
		}
6788
	},
6789
 
6790
	// duration: Integer
6791
	//	The time in milliseonds the animation will take to run
6792
	duration: 1000,
6793
 
6794
/*=====
6795
	// curve: dojo._Line||Array
6796
	//	A two element array of start and end values, or a dojo._Line instance to be
6797
	//	used in the Animation.
6798
	curve: null,
6799
 
6800
	// easing: Function
6801
	//	A Function to adjust the acceleration (or deceleration) of the progress
6802
	//	across a dojo._Line
6803
	easing: null,
6804
=====*/
6805
 
6806
	// repeat: Integer
6807
	//	The number of times to loop the animation
6808
	repeat: 0,
6809
 
6810
	// rate: Integer
6811
	//	the time in milliseconds to wait before advancing to next frame
6812
	//	(used as a fps timer: rate/1000 = fps)
6813
	rate: 10 /* 100 fps */,
6814
 
6815
/*=====
6816
	// delay: Integer
6817
	// 	The time in milliseconds to wait before starting animation after it has been .play()'ed
6818
	delay: null,
6819
 
6820
	// events
6821
	//
6822
	// beforeBegin: Event
6823
	//	Synthetic event fired before a dojo._Animation begins playing (synhcronous)
6824
	beforeBegin: null,
6825
 
6826
	// onBegin: Event
6827
	//	Synthetic event fired as a dojo._Animation begins playing (useful?)
6828
	onBegin: null,
6829
 
6830
	// onAnimate: Event
6831
	//	Synthetic event fired at each interval of a dojo._Animation
6832
	onAnimate: null,
6833
 
6834
	// onEnd: Event
6835
	//	Synthetic event fired after the final frame of a dojo._Animation
6836
	onEnd: null,
6837
 
6838
	// ???
6839
	onPlay: null,
6840
 
6841
	// onPause: Event
6842
	//	Synthetic event fired when a dojo._Animation is paused
6843
	onPause: null,
6844
 
6845
	// onStop: Event
6846
	//	Synthetic event fires when a dojo._Animation is stopped
6847
	onStop: null,
6848
 
6849
=====*/
6850
 
6851
	_percent: 0,
6852
	_startRepeatCount: 0,
6853
 
6854
	fire: function(/*Event*/ evt, /*Array?*/ args){
6855
		//	summary:
6856
		//		Convenience function.  Fire event "evt" and pass it the
6857
		//		arguments specified in "args".
6858
		//	evt:
6859
		//		The event to fire.
6860
		//	args:
6861
		//		The arguments to pass to the event.
6862
		if(this[evt]){
6863
			this[evt].apply(this, args||[]);
6864
		}
6865
		return this; // dojo._Animation
6866
	},
6867
 
6868
	play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
6869
		// summary:
6870
		//		Start the animation.
6871
		// delay:
6872
		//		How many milliseconds to delay before starting.
6873
		// gotoStart:
6874
		//		If true, starts the animation from the beginning; otherwise,
6875
		//		starts it from its current position.
6876
		var _t = this;
6877
		if(gotoStart){
6878
			_t._stopTimer();
6879
			_t._active = _t._paused = false;
6880
			_t._percent = 0;
6881
		}else if(_t._active && !_t._paused){
6882
			return _t; // dojo._Animation
6883
		}
6884
 
6885
		_t.fire("beforeBegin");
6886
 
6887
		var d = delay||_t.delay;
6888
		var _p = dojo.hitch(_t, "_play", gotoStart);
6889
		if(d > 0){
6890
			setTimeout(_p, d);
6891
			return _t; // dojo._Animation
6892
		}
6893
		_p();
6894
		return _t;
6895
	},
6896
 
6897
	_play: function(gotoStart){
6898
		var _t = this;
6899
		_t._startTime = new Date().valueOf();
6900
		if(_t._paused){
6901
			_t._startTime -= _t.duration * _t._percent;
6902
		}
6903
		_t._endTime = _t._startTime + _t.duration;
6904
 
6905
		_t._active = true;
6906
		_t._paused = false;
6907
 
6908
		var value = _t.curve.getValue(_t._percent);
6909
		if(!_t._percent){
6910
			if(!_t._startRepeatCount){
6911
				_t._startRepeatCount = _t.repeat;
6912
			}
6913
			_t.fire("onBegin", [value]);
6914
		}
6915
 
6916
		_t.fire("onPlay", [value]);
6917
 
6918
		_t._cycle();
6919
		return _t; // dojo._Animation
6920
	},
6921
 
6922
	pause: function(){
6923
		// summary: Pauses a running animation.
6924
		this._stopTimer();
6925
		if(!this._active){ return this; /*dojo._Animation*/}
6926
		this._paused = true;
6927
		this.fire("onPause", [this.curve.getValue(this._percent)]);
6928
		return this; // dojo._Animation
6929
	},
6930
 
6931
	gotoPercent: function(/*Decimal*/ percent, /*Boolean?*/ andPlay){
6932
		//	summary:
6933
		//		Sets the progress of the animation.
6934
		//	percent:
6935
		//		A percentage in decimal notation (between and including 0.0 and 1.0).
6936
		//	andPlay:
6937
		//		If true, play the animation after setting the progress.
6938
		this._stopTimer();
6939
		this._active = this._paused = true;
6940
		this._percent = percent;
6941
		if(andPlay){ this.play(); }
6942
		return this; // dojo._Animation
6943
	},
6944
 
6945
	stop: function(/*boolean?*/ gotoEnd){
6946
		// summary: Stops a running animation.
6947
		// gotoEnd: If true, the animation will end.
6948
		if(!this._timer){ return; }
6949
		this._stopTimer();
6950
		if(gotoEnd){
6951
			this._percent = 1;
6952
		}
6953
		this.fire("onStop", [this.curve.getValue(this._percent)]);
6954
		this._active = this._paused = false;
6955
		return this; // dojo._Animation
6956
	},
6957
 
6958
	status: function(){
6959
		// summary: Returns a string token representation of the status of
6960
		//			the animation, one of: "paused", "playing", "stopped"
6961
		if(this._active){
6962
			return this._paused ? "paused" : "playing"; // String
6963
		}
6964
		return "stopped"; // String
6965
	},
6966
 
6967
	_cycle: function(){
6968
		var _t = this;
6969
		if(_t._active){
6970
			var curr = new Date().valueOf();
6971
			var step = (curr - _t._startTime) / (_t._endTime - _t._startTime);
6972
 
6973
			if(step >= 1){
6974
				step = 1;
6975
			}
6976
			_t._percent = step;
6977
 
6978
			// Perform easing
6979
			if(_t.easing){
6980
				step = _t.easing(step);
6981
			}
6982
 
6983
			_t.fire("onAnimate", [_t.curve.getValue(step)]);
6984
 
6985
			if(step < 1){
6986
				_t._startTimer();
6987
			}else{
6988
				_t._active = false;
6989
 
6990
				if(_t.repeat > 0){
6991
					_t.repeat--;
6992
					_t.play(null, true);
6993
				}else if(_t.repeat == -1){
6994
					_t.play(null, true);
6995
				}else{
6996
					if(_t._startRepeatCount){
6997
						_t.repeat = _t._startRepeatCount;
6998
						_t._startRepeatCount = 0;
6999
					}
7000
				}
7001
				_t._percent = 0;
7002
				_t.fire("onEnd");
7003
			}
7004
		}
7005
		return _t; // dojo._Animation
7006
	}
7007
});
7008
 
7009
(function(){
7010
	var d = dojo;
7011
	var ctr = 0;
7012
	var _globalTimerList = [];
7013
	var runner = {
7014
		run: function(){}
7015
	};
7016
	var timer = null;
7017
	dojo._Animation.prototype._startTimer = function(){
7018
		// this._timer = setTimeout(dojo.hitch(this, "_cycle"), this.rate);
7019
		if(!this._timer){
7020
			this._timer = dojo.connect(runner, "run", this, "_cycle");
7021
			ctr++;
7022
		}
7023
		if(!timer){
7024
			timer = setInterval(dojo.hitch(runner, "run"), this.rate);
7025
		}
7026
	};
7027
 
7028
	dojo._Animation.prototype._stopTimer = function(){
7029
		dojo.disconnect(this._timer);
7030
		this._timer = null;
7031
		ctr--;
7032
		if(!ctr){
7033
			clearInterval(timer);
7034
			timer = null;
7035
		}
7036
	};
7037
 
7038
	var _makeFadeable = (d.isIE) ? function(node){
7039
		// only set the zoom if the "tickle" value would be the same as the
7040
		// default
7041
		var ns = node.style;
7042
		if(!ns.zoom.length && d.style(node, "zoom") == "normal"){
7043
			// make sure the node "hasLayout"
7044
			// NOTE: this has been tested with larger and smaller user-set text
7045
			// sizes and works fine
7046
			ns.zoom = "1";
7047
			// node.style.zoom = "normal";
7048
		}
7049
		// don't set the width to auto if it didn't already cascade that way.
7050
		// We don't want to f anyones designs
7051
		if(!ns.width.length && d.style(node, "width") == "auto"){
7052
			ns.width = "auto";
7053
		}
7054
	} : function(){};
7055
 
7056
	dojo._fade = function(/*Object*/ args){
7057
		//	summary:
7058
		//		Returns an animation that will fade the node defined by
7059
		//		args.node from the start to end values passed (args.start
7060
		//		args.end) (end is mandatory, start is optional)
7061
 
7062
		args.node = d.byId(args.node);
7063
		var fArgs = d.mixin({ properties: {} }, args);
7064
		var props = (fArgs.properties.opacity = {});
7065
		props.start = !("start" in fArgs) ?
7066
			function(){ return Number(d.style(fArgs.node, "opacity")); } : fArgs.start;
7067
		props.end = fArgs.end;
7068
 
7069
		var anim = d.animateProperty(fArgs);
7070
		d.connect(anim, "beforeBegin", d.partial(_makeFadeable, fArgs.node));
7071
 
7072
		return anim; // dojo._Animation
7073
	}
7074
 
7075
	/*=====
7076
	dojo.__fadeArgs = function(kwArgs){
7077
		//	duration: Integer?
7078
		//		Duration of the animation in milliseconds.
7079
		// easing: Function?
7080
		//		An easing function.
7081
	}
7082
	=====*/
7083
 
7084
	dojo.fadeIn = function(/*dojo.__fadeArgs*/ args){
7085
		// summary:
7086
		//		Returns an animation that will fade node defined in 'args' from
7087
		//		its current opacity to fully opaque.
7088
		return d._fade(d.mixin({ end: 1 }, args)); // dojo._Animation
7089
	}
7090
 
7091
	dojo.fadeOut = function(/*dojo.__fadeArgs*/  args){
7092
		// summary:
7093
		//		Returns an animation that will fade node defined in 'args'
7094
		//		from its current opacity to fully transparent.
7095
		return d._fade(d.mixin({ end: 0 }, args)); // dojo._Animation
7096
	}
7097
 
7098
	dojo._defaultEasing = function(/*Decimal?*/ n){
7099
		// summary: The default easing function for dojo._Animation(s)
7100
		return 0.5 + ((Math.sin((n + 1.5) * Math.PI))/2);
7101
	}
7102
 
7103
	var PropLine = function(properties){
7104
		this._properties = properties;
7105
		for(var p in properties){
7106
			var prop = properties[p];
7107
			if(prop.start instanceof d.Color){
7108
				// create a reusable temp color object to keep intermediate results
7109
				prop.tempColor = new d.Color();
7110
			}
7111
		}
7112
		this.getValue = function(r){
7113
			var ret = {};
7114
			for(var p in this._properties){
7115
				var prop = this._properties[p];
7116
				var start = prop.start;
7117
				if(start instanceof d.Color){
7118
					ret[p] = d.blendColors(start, prop.end, r, prop.tempColor).toCss();
7119
				}else if(!d.isArray(start)){
7120
					ret[p] = ((prop.end - start) * r) + start + (p != "opacity" ? prop.units||"px" : "");
7121
				}
7122
			}
7123
			return ret;
7124
		}
7125
	}
7126
 
7127
	dojo.animateProperty = function(/*Object*/ args){
7128
		//	summary:
7129
		//		Returns an animation that will transition the properties of
7130
		//		node defined in 'args' depending how they are defined in
7131
		//		'args.properties'
7132
		//
7133
		// description:
7134
		//		The foundation of most dojo.fx animations, dojo.AnimateProperty
7135
		//		will take an object of "properties" corresponding to style
7136
		//		properties, and animate them in parallel over a set duration.
7137
		//
7138
		//		args.node can be a String or a DomNode reference
7139
		//
7140
		// 	example:
7141
		//	|	dojo.animateProperty({ node: node, duration:2000,
7142
		//	|		properties: {
7143
		//	|			width: { start: '200', end: '400', unit:"px" },
7144
		//	|			height: { start:'200', end: '400', unit:"px" },
7145
		//	|			paddingTop: { start:'5', end:'50', unit:"px" }
7146
		//	|		}
7147
		//	|	}).play();
7148
		//
7149
 
7150
		args.node = d.byId(args.node);
7151
		if(!args.easing){ args.easing = d._defaultEasing; }
7152
 
7153
		var anim = new d._Animation(args);
7154
		d.connect(anim, "beforeBegin", anim, function(){
7155
			var pm = {};
7156
			for(var p in this.properties){
7157
				// Make shallow copy of properties into pm because we overwrite some values below.
7158
				// In particular if start/end are functions we don't want to overwrite them or
7159
				// the functions won't be called if the animation is reused.
7160
				var prop = (pm[p] = d.mixin({}, this.properties[p]));
7161
 
7162
				if(d.isFunction(prop.start)){
7163
					prop.start = prop.start();
7164
				}
7165
				if(d.isFunction(prop.end)){
7166
					prop.end = prop.end();
7167
				}
7168
 
7169
				var isColor = (p.toLowerCase().indexOf("color") >= 0);
7170
				function getStyle(node, p){
7171
					// dojo.style(node, "height") can return "auto" or "" on IE; this is more reliable:
7172
					var v = ({height: node.offsetHeight, width: node.offsetWidth})[p];
7173
					if(v !== undefined){ return v; }
7174
					v = d.style(node, p);
7175
					return (p=="opacity") ? Number(v) : parseFloat(v);
7176
				}
7177
				if(!("end" in prop)){
7178
					prop.end = getStyle(this.node, p);
7179
				}else if(!("start" in prop)){
7180
					prop.start = getStyle(this.node, p);
7181
				}
7182
 
7183
				if(isColor){
7184
					// console.debug("it's a color!");
7185
					prop.start = new d.Color(prop.start);
7186
					prop.end = new d.Color(prop.end);
7187
				}else{
7188
					prop.start = (p == "opacity") ? Number(prop.start) : parseFloat(prop.start);
7189
				}
7190
				// console.debug("start:", prop.start);
7191
				// console.debug("end:", prop.end);
7192
			}
7193
			this.curve = new PropLine(pm);
7194
		});
7195
		d.connect(anim, "onAnimate", anim, function(propValues){
7196
			// try{
7197
			for(var s in propValues){
7198
				// console.debug(s, propValues[s], this.node.style[s]);
7199
				d.style(this.node, s, propValues[s]);
7200
				// this.node.style[s] = propValues[s];
7201
			}
7202
			// }catch(e){ console.debug(dojo.toJson(e)); }
7203
		});
7204
		return anim; // dojo._Animation
7205
	}
7206
})();
7207
 
7208
}
7209