PageSourceSearch

https://svc.mt.gov/itsd/dpage/Scripts/1.0/dpage/dpage.js.uncompressed.js

js mt.gov collected 2026-09-24 07:17:14 UTC 1,717,980 bytes, 50,197 lines download raw bytes

1(function(){
2    if(window.dojoConfig == null)
3        window.dojoConfig = {};
4    if(window.dojoConfig.packages == null)
5        window.dojoConfig.packages = [];
6
7    var packages = {
8        "dojo" : {location: "https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo"},
9        "dijit":{location: "https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dijit"},
10        "dojox":{location: "https://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojox"},
11        "dpage":{location: "https://svc.mt.gov/itsd/dpage/Scripts/1.0/dpage"},
12        "footable":{location: "https://svc.mt.gov/itsd/dpage/Scripts/1.0/footable"},
13        "jquery":{location: "https://svc.mt.gov/itsd/dpage/Scripts/1.0/jquery",main : "jquery"},
14        "jquery-ui":{location: "https://svc.mt.gov/itsd/dpage/Scripts/1.0/jquery-ui"},
15        "jQueryPrivate":{location: "https://svc.mt.gov/itsd/dpage/Scripts/1.0/jQueryPrivate",main: "jQueryPrivate"},
16        "xstyle":{location: "https://svc.mt.gov/itsd/dpage/Scripts/1.0/xstyle"},
17        "dpageRoot":{location: "https://svc.mt.gov/itsd/dpage"},
18        "put-selector":{location: "https://svc.mt.gov/itsd/dpage/Scripts/1.0/put-selector"}
19    };
20
21    //allow these to be overridden.
22    for(var i=0; i<window.dojoConfig.packages.length;i++){
23        if(packages[window.dojoConfig.packages[i]] != null){
24            delete packages[window.dojoConfig.packages[i]];
25        }
26    }
27
28    //add in required package configs.
29    for(var p in packages){
30        if(packages.hasOwnProperty(p)){
31            packages[p].name = p;
32            window.dojoConfig.packages.push(packages[p]);
33        }
34    }
35})();
36
37/*
38	Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
39	Available via Academic Free License >= 2.1 OR the modified BSD license.
40	see: http://dojotoolkit.org/license for details
41*/
42
43/*
44	This is an optimized version of Dojo, built for deployment and not for
45	development. To get sources and documentation, please visit:
46
47		http://dojotoolkit.org
48*/
49
50(function(
51	userConfig,
52	defaultConfig
53){
54	// summary:
55	//		This is the "source loader" and is the entry point for Dojo during development. You may also load Dojo with
56	//		any AMD-compliant loader via the package main module dojo/main.
57	// description:
58	//		This is the "source loader" for Dojo. It provides an AMD-compliant loader that can be configured
59	//		to operate in either synchronous or asynchronous modes. After the loader is defined, dojo is loaded
60	//		IAW the package main module dojo/main. In the event you wish to use a foreign loader, you may load dojo as a package
61	//		via the package main module dojo/main and this loader is not required; see dojo/package.json for details.
62	//
63	//		In order to keep compatibility with the v1.x line, this loader includes additional machinery that enables
64	//		the dojo.provide, dojo.require et al API. This machinery is loaded by default, but may be dynamically removed
65	//		via the has.js API and statically removed via the build system.
66	//
67	//		This loader includes sniffing machinery to determine the environment; the following environments are supported:
68	//
69	//		- browser
70	//		- node.js
71	//		- rhino
72	//
73	//		This is the so-called "source loader". As such, it includes many optional features that may be discarded by
74	//		building a customized version with the build system.
75
76	// Design and Implementation Notes
77	//
78	// This is a dojo-specific adaption of bdLoad, donated to the dojo foundation by Altoviso LLC.
79	//
80	// This function defines an AMD-compliant (http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition)
81	// loader that can be configured to operate in either synchronous or asynchronous modes.
82	//
83	// Since this machinery implements a loader, it does not have the luxury of using a load system and/or
84	// leveraging a utility library. This results in an unpleasantly long file; here is a road map of the contents:
85	//
86	//	 1. Small library for use implementing the loader.
87	//	 2. Define the has.js API; this is used throughout the loader to bracket features.
88	//	 3. Define the node.js and rhino sniffs and sniff.
89	//	 4. Define the loader's data.
90	//	 5. Define the configuration machinery.
91	//	 6. Define the script element sniffing machinery and sniff for configuration data.
92	//	 7. Configure the loader IAW the provided user, default, and sniffing data.
93	//	 8. Define the global require function.
94	//	 9. Define the module resolution machinery.
95	//	10. Define the module and plugin module definition machinery
96	//	11. Define the script injection machinery.
97	//	12. Define the window load detection.
98	//	13. Define the logging API.
99	//	14. Define the tracing API.
100	//	16. Define the AMD define function.
101	//	17. Define the dojo v1.x provide/require machinery--so called "legacy" modes.
102	//	18. Publish global variables.
103	//
104	// Language and Acronyms and Idioms
105	//
106	// moduleId: a CJS module identifier, (used for public APIs)
107	// mid: moduleId (used internally)
108	// packageId: a package identifier (used for public APIs)
109	// pid: packageId (used internally); the implied system or default package has pid===""
110	// pack: package is used internally to reference a package object (since javascript has reserved words including "package")
111	// prid: plugin resource identifier
112	// The integer constant 1 is used in place of true and 0 in place of false.
113
114	// define a minimal library to help build the loader
115	var	noop = function(){
116		},
117
118		isEmpty = function(it){
119			for(var p in it){
120				return 0;
121			}
122			return 1;
123		},
124
125		toString = {}.toString,
126
127		isFunction = function(it){
128			return toString.call(it) == "[object Function]";
129		},
130
131		isString = function(it){
132			return toString.call(it) == "[object String]";
133		},
134
135		isArray = function(it){
136			return toString.call(it) == "[object Array]";
137		},
138
139		forEach = function(vector, callback){
140			if(vector){
141				for(var i = 0; i < vector.length;){
142					callback(vector[i++]);
143				}
144			}
145		},
146
147		mix = function(dest, src){
148			for(var p in src){
149				dest[p] = src[p];
150			}
151			return dest;
152		},
153
154		makeError = function(error, info){
155			return mix(new Error(error), {src:"dojoLoader", info:info});
156		},
157
158		uidSeed = 1,
159
160		uid = function(){
161			// Returns a unique identifier (within the lifetime of the document) of the form /_d+/.
162			return "_" + uidSeed++;
163		},
164
165		// FIXME: how to doc window.require() api
166
167		// this will be the global require function; define it immediately so we can start hanging things off of it
168		req = function(
169			config,		  //(object, optional) hash of configuration properties
170			dependencies, //(array of commonjs.moduleId, optional) list of modules to be loaded before applying c
vendor: 61,510 bytes, lines 170-1904
170allback
171			callback	  //(function, optional) lambda expression to apply to module values implied by dependencies
172		){
173			return contextRequire(config, dependencies, callback, 0, req);
174		},
175
176		// the loader uses the has.js API to control feature inclusion/exclusion; define then use throughout
177		global = this,
178
179		doc = global.document,
180
181		element = doc && doc.createElement("DiV"),
182
183		has = req.has = function(name){
184			return isFunction(hasCache[name]) ? (hasCache[name] = hasCache[name](global, doc, element)) : hasCache[name];
185		},
186
187		hasCache = has.cache = defaultConfig.hasCache;
188
189	has.add = function(name, test, now, force){
190		(hasCache[name]===undefined || force) && (hasCache[name] = test);
191		return now && has(name);
192	};
193
194	 0 && has.add("host-node", userConfig.has && "host-node" in userConfig.has ?
195		userConfig.has["host-node"] :
196		(typeof process == "object" && process.versions && process.versions.node && process.versions.v8));
197	if( 0 ){
198		// fixup the default config for node.js environment
199		require("./_base/configNode.js").config(defaultConfig);
200		// remember node's require (with respect to baseUrl==dojo's root)
201		defaultConfig.loaderPatch.nodeRequire = require;
202	}
203
204	 0 && has.add("host-rhino", userConfig.has && "host-rhino" in userConfig.has ?
205		userConfig.has["host-rhino"] :
206		(typeof load == "function" && (typeof Packages == "function" || typeof Packages == "object")));
207	if( 0 ){
208		// owing to rhino's lame feature that hides the source of the script, give the user a way to specify the baseUrl...
209		for(var baseUrl = userConfig.baseUrl || ".", arg, rhinoArgs = this.arguments, i = 0; i < rhinoArgs.length;){
210			arg = (rhinoArgs[i++] + "").split("=");
211			if(arg[0] == "baseUrl"){
212				baseUrl = arg[1];
213				break;
214			}
215		}
216		load(baseUrl + "/_base/configRhino.js");
217		rhinoDojoConfig(defaultConfig, baseUrl, rhinoArgs);
218	}
219
220	has.add("host-webworker", ((typeof WorkerGlobalScope !== 'undefined') && (self instanceof WorkerGlobalScope)));
221	if(has("host-webworker")){
222		mix(defaultConfig.hasCache, {
223			"host-browser": 0,
224			"dom": 0,
225			"dojo-dom-ready-api": 0,
226			"dojo-sniff": 0,
227			"dojo-inject-api": 1,
228			"host-webworker": 1
229		});
230
231		defaultConfig.loaderPatch = {
232			injectUrl: function(url, callback){
233				// TODO:
234				//		This is not async, nor can it be in Webworkers.  It could be made better by passing
235				//		the entire require array into importScripts at.  This way the scripts are loaded in
236				//		async mode; even if the callbacks are ran in sync.  It is not a major issue as webworkers
237				//		tend to be long running where initial startup is not a major factor.
238
239				try{
240					importScripts(url);
241					callback();
242				}catch(e){
243					console.info("failed to load resource (" + url + ")");
244					console.error(e);
245				}
246			}
247		};
248	}
249
250	// userConfig has tests override defaultConfig has tests; do this after the environment detection because
251	// the environment detection usually sets some has feature values in the hasCache.
252	for(var p in userConfig.has){
253		has.add(p, userConfig.has[p], 0, 1);
254	}
255
256	//
257	// define the loader data
258	//
259
260	// the loader will use these like symbols if the loader has the traceApi; otherwise
261	// define magic numbers so that modules can be provided as part of defaultConfig
262	var	requested = 1,
263		arrived = 2,
264		nonmodule = 3,
265		executing = 4,
266		executed = 5;
267
268	if( 0 ){
269		// these make debugging nice; but using strings for symbols is a gross rookie error; don't do it for production code
270		requested = "requested";
271		arrived = "arrived";
272		nonmodule = "not-a-module";
273		executing = "executing";
274		executed = "executed";
275	}
276
277	var legacyMode = 0,
278		sync = "sync",
279		xd = "xd",
280		syncExecStack = [],
281		dojoRequirePlugin = 0,
282		checkDojoRequirePlugin = noop,
283		transformToAmd = noop,
284		getXhr;
285	if( 0 ){
286		req.isXdUrl = noop;
287
288		req.initSyncLoader = function(dojoRequirePlugin_, checkDojoRequirePlugin_, transformToAmd_){
289			// the first dojo/_base/loader loaded gets to define these variables; they are designed to work
290			// in the presence of zero to many mapped dojo/_base/loaders
291			if(!dojoRequirePlugin){
292				dojoRequirePlugin = dojoRequirePlugin_;
293				checkDojoRequirePlugin = checkDojoRequirePlugin_;
294				transformToAmd = transformToAmd_;
295			}
296
297			return {
298				sync:sync,
299				requested:requested,
300				arrived:arrived,
301				nonmodule:nonmodule,
302				executing:executing,
303				executed:executed,
304				syncExecStack:syncExecStack,
305				modules:modules,
306				execQ:execQ,
307				getModule:getModule,
308				injectModule:injectModule,
309				setArrived:setArrived,
310				signal:signal,
311				finishExec:finishExec,
312				execModule:execModule,
313				dojoRequirePlugin:dojoRequirePlugin,
314				getLegacyMode:function(){return legacyMode;},
315				guardCheckComplete:guardCheckComplete
316			};
317		};
318
319		if( 1  || has("host-webworker")){
320			// in legacy sync mode, the loader needs a minimal XHR library
321
322			var locationProtocol = location.protocol,
323				locationHost = location.host;
324			req.isXdUrl = function(url){
325				if(/^\./.test(url)){
326					// begins with a dot is always relative to page URL; therefore not xdomain
327					return false;
328				}
329				if(/^\/\//.test(url)){
330					// for v1.6- backcompat, url starting with // indicates xdomain
331					return true;
332				}
333				// get protocol and host
334				// \/+ takes care of the typical file protocol that looks like file:///drive/path/to/file
335				// locationHost is falsy if file protocol => if locationProtocol matches and is "file:", || will return false
336				var match = url.match(/^([^\/\:]+\:)\/+([^\/]+)/);
337				return match && (match[1] != locationProtocol || (locationHost && match[2] != locationHost));
338			};
339
340
341			// note: to get the file:// protocol to work in FF, you must set security.fileuri.strict_origin_policy to false in about:config
342			 1 || has.add("dojo-xhr-factory", 1);
343			has.add("dojo-force-activex-xhr",  1  && !doc.addEventListener && window.location.protocol == "file:");
344			has.add("native-xhr", typeof XMLHttpRequest != "undefined");
345			if(has("native-xhr") && !has("dojo-force-activex-xhr")){
346				getXhr = function(){
347					return new XMLHttpRequest();
348				};
349			}else{
350				// if in the browser an old IE; find an xhr
351				for(var XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'], progid, i = 0; i < 3;){
352					try{
353						progid = XMLHTTP_PROGIDS[i++];
354						if(new ActiveXObject(progid)){
355							// this progid works; therefore, use it from now on
356							break;
357						}
358					}catch(e){
359						// squelch; we're just trying to find a good ActiveX progid
360						// if they all fail, then progid ends up as the last attempt and that will signal the error
361						// the first time the client actually tries to exec an xhr
362					}
363				}
364				getXhr = function(){
365					return new ActiveXObject(progid);
366				};
367			}
368			req.getXhr = getXhr;
369
370			has.add("dojo-gettext-api", 1);
371			req.getText = function(url, async, onLoad){
372				var xhr = getXhr();
373				xhr.open('GET', fixupUrl(url), false);
374				xhr.send(null);
375				if(xhr.status == 200 || (!location.host && !xhr.status)){
376					if(onLoad){
377						onLoad(xhr.responseText, async);
378					}
379				}else{
380					throw makeError("xhrFailed", xhr.status);
381				}
382				return xhr.responseText;
383			};
384		}
385	}else{
386		req.async = 1;
387	}
388
389	//
390	// loader eval
391	//
392	var eval_ =
393		// use the function constructor so our eval is scoped close to (but not in) in the global space with minimal pollution
394		new Function('return eval(arguments[0]);');
395
396	req.eval =
397		function(text, hint){
398			return eval_(text + "\r\n//# sourceURL=" + hint);
399		};
400
401	//
402	// loader micro events API
403	//
404	var listenerQueues = {},
405		error = "error",
406		signal = req.signal = function(type, args){
407			var queue = listenerQueues[type];
408			// notice we run a copy of the queue; this allows listeners to add/remove
409			// other listeners without affecting this particular signal
410			forEach(queue && queue.slice(0), function(listener){
411				listener.apply(null, isArray(args) ? args : [args]);
412			});
413		},
414		on = req.on = function(type, listener){
415			// notice a queue is not created until a client actually connects
416			var queue = listenerQueues[type] || (listenerQueues[type] = []);
417			queue.push(listener);
418			return {
419				remove:function(){
420					for(var i = 0; i<queue.length; i++){
421						if(queue[i]===listener){
422							queue.splice(i, 1);
423							return;
424						}
425					}
426				}
427			};
428		};
429
430	// configuration machinery; with an optimized/built defaultConfig, all configuration machinery can be discarded
431	// lexical variables hold key loader data structures to help with minification; these may be completely,
432	// one-time initialized by defaultConfig for optimized/built versions
433	var
434		aliases
435			// a vector of pairs of [regexs or string, replacement] => (alias, actual)
436			= [],
437
438		paths
439			// CommonJS paths
440			= {},
441
442		pathsMapProg
443			// list of (from-path, to-path, regex, length) derived from paths;
444			// a "program" to apply paths; see computeMapProg
445			= [],
446
447		packs
448			// a map from packageId to package configuration object; see fixupPackageInfo
449			= {},
450
451		map = req.map
452			// AMD map config variable; dojo/_base/kernel needs req.map to figure out the scope map
453			= {},
454
455		mapProgs
456			// vector of quads as described by computeMapProg; map-key is AMD map key, map-value is AMD map value
457			= [],
458
459		modules
460			// A hash:(mid) --> (module-object) the module namespace
461			//
462			// pid: the package identifier to which the module belongs (e.g., "dojo"); "" indicates the system or default package
463			// mid: the fully-resolved (i.e., mappings have been applied) module identifier without the package identifier (e.g., "dojo/io/script")
464			// url: the URL from which the module was retrieved
465			// pack: the package object of the package to which the module belongs
466			// executed: 0 => not executed; executing => in the process of traversing deps and running factory; executed => factory has been executed
467			// deps: the dependency vector for this module (vector of modules objects)
468			// def: the factory for this module
469			// result: the result of the running the factory for this module
470			// injected: (0 | requested | arrived) the status of the module; nonmodule means the resource did not call define
471			// load: plugin load function; applicable only for plugins
472			//
473			// Modules go through several phases in creation:
474			//
475			// 1. Requested: some other module's definition or a require application contained the requested module in
476			//	  its dependency vector or executing code explicitly demands a module via req.require.
477			//
478			// 2. Injected: a script element has been appended to the insert-point element demanding the resource implied by the URL
479			//
480			// 3. Loaded: the resource injected in [2] has been evaluated.
481			//
482			// 4. Defined: the resource contained a define statement that advised the loader about the module. Notice that some
483			//	  resources may just contain a bundle of code and never formally define a module via define
484			//
485			// 5. Evaluated: the module was defined via define and the loader has evaluated the factory and computed a result.
486			= {},
487
488		cacheBust
489			// query string to append to module URLs to bust browser cache
490			= "",
491
492		cache
493			// hash:(mid | url)-->(function | string)
494			//
495			// A cache of resources. The resources arrive via a config.cache object, which is a hash from either mid --> function or
496			// url --> string. The url key is distinguished from the mid key by always containing the prefix "url:". url keys as provided
497			// by config.cache always have a string value that represents the contents of the resource at the given url. mid keys as provided
498			// by configl.cache always have a function value that causes the same code to execute as if the module was script injected.
499			//
500			// Both kinds of key-value pairs are entered into cache via the function consumePendingCache, which may relocate keys as given
501			// by any mappings *iff* the config.cache was received as part of a module resource request.
502			//
503			// Further, for mid keys, the implied url is computed and the value is entered into that key as well. This allows mapped modules
504			// to retrieve cached items that may have arrived consequent to another namespace.
505			//
506			 = {},
507
508		urlKeyPrefix
509			// the prefix to prepend to a URL key in the cache.
510			= "url:",
511
512		pendingCacheInsert
513			// hash:(mid)-->(function)
514			//
515			// Gives a set of cache modules pending entry into cache. When cached modules are published to the loader, they are
516			// entered into pendingCacheInsert; modules are then pressed into cache upon (1) AMD define or (2) upon receiving another
517			// independent set of cached modules. (1) is the usual case, and this case allows normalizing mids given in the pending
518			// cache for the local configuration, possibly relocating modules.
519			 = {},
520
521		dojoSniffConfig
522			// map of configuration variables
523			// give the data-dojo-config as sniffed from the document (if any)
524			= {},
525
526		insertPointSibling
527			// the nodes used to locate where scripts are injected into the document
528			= 0;
529
530	if( 1 ){
531		var consumePendingCacheInsert = function(referenceModule){
532				var p, item, match, now, m;
533				for(p in pendingCacheInsert){
534					item = pendingCacheInsert[p];
535					match = p.match(/^url\:(.+)/);
536					if(match){
537						cache[urlKeyPrefix + toUrl(match[1], referenceModule)] =  item;
538					}else if(p=="*now"){
539						now = item;
540					}else if(p!="*noref"){
541						m = getModuleInfo(p, referenceModule, true);
542						cache[m.mid] = cache[urlKeyPrefix + m.url] = item;
543					}
544				}
545				if(now){
546					now(createRequire(referenceModule));
547				}
548				pendingCacheInsert = {};
549			},
550
551			escapeString = function(s){
552				return s.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, function(c){ return "\\" + c; });
553			},
554
555			computeMapProg = function(map, dest){
556				// This routine takes a map as represented by a JavaScript object and initializes dest, a vector of
557				// quads of (map-key, map-value, refex-for-map-key, length-of-map-key), sorted decreasing by length-
558				// of-map-key. The regex looks for the map-key followed by either "/" or end-of-string at the beginning
559				// of a the search source. Notice the map-value is irrelevant to the algorithm
560				dest.splice(0, dest.length);
561				for(var p in map){
562					dest.push([
563						p,
564						map[p],
565						new RegExp("^" + escapeString(p) + "(\/|$)"),
566						p.length]);
567				}
568				dest.sort(function(lhs, rhs){ return rhs[3] - lhs[3]; });
569				return dest;
570			},
571
572			computeAliases = function(config, dest){
573				forEach(config, function(pair){
574					// take a fixed-up copy...
575					dest.push([isString(pair[0]) ? new RegExp("^" + escapeString(pair[0]) + "$") : pair[0], pair[1]]);
576				});
577			},
578
579
580			fixupPackageInfo = function(packageInfo){
581				// calculate the precise (name, location, main, mappings) for a package
582				var name = packageInfo.name;
583				if(!name){
584					// packageInfo must be a string that gives the name
585					name = packageInfo;
586					packageInfo = {name:name};
587				}
588				packageInfo = mix({main:"main"}, packageInfo);
589				packageInfo.location = packageInfo.location ? packageInfo.location : name;
590
591				// packageMap is deprecated in favor of AMD map
592				if(packageInfo.packageMap){
593					map[name] = packageInfo.packageMap;
594				}
595
596				if(!packageInfo.main.indexOf("./")){
597					packageInfo.main = packageInfo.main.substring(2);
598				}
599
600				// now that we've got a fully-resolved package object, push it into the configuration
601				packs[name] = packageInfo;
602			},
603
604			delayedModuleConfig
605				// module config cannot be consumed until the loader is completely initialized; therefore, all
606				// module config detected during booting is memorized and applied at the end of loader initialization
607				// TODO: this is a bit of a kludge; all config should be moved to end of loader initialization, but
608				// we'll delay this chore and do it with a final loader 1.x cleanup after the 2.x loader prototyping is complete
609				= [],
610
611
612			config = function(config, booting, referenceModule){
613				for(var p in config){
614					if(p=="waitSeconds"){
615						req.waitms = (config[p] || 0) * 1000;
616					}
617					if(p=="cacheBust"){
618						cacheBust = config[p] ? (isString(config[p]) ? config[p] : (new Date()).getTime() + "") : "";
619					}
620					if(p=="baseUrl" || p=="combo"){
621						req[p] = config[p];
622					}
623					if( 0  && p=="async"){
624						// falsy or "sync" => legacy sync loader
625						// "xd" => sync but loading xdomain tree and therefore loading asynchronously (not configurable, set automatically by the loader)
626						// "legacyAsync" => permanently in "xd" by choice
627						// "debugAtAllCosts" => trying to load everything via script injection (not implemented)
628						// otherwise, must be truthy => AMD
629						// legacyMode: sync | legacyAsync | xd | false
630						var mode = config[p];
631						req.legacyMode = legacyMode = (isString(mode) && /sync|legacyAsync/.test(mode) ? mode : (!mode ? sync : false));
632						req.async = !legacyMode;
633					}
634					if(config[p]!==hasCache){
635						// accumulate raw config info for client apps which can use this to pass their own config
636						req.rawConfig[p] = config[p];
637						p!="has" && has.add("config-"+p, config[p], 0, booting);
638					}
639				}
640
641				// make sure baseUrl exists
642				if(!req.baseUrl){
643					req.baseUrl = "./";
644				}
645				// make sure baseUrl ends with a slash
646				if(!/\/$/.test(req.baseUrl)){
647					req.baseUrl += "/";
648				}
649
650				// now do the special work for has, packages, packagePaths, paths, aliases, and cache
651
652				for(p in config.has){
653					has.add(p, config.has[p], 0, booting);
654				}
655
656				// for each package found in any packages config item, augment the packs map owned by the loader
657				forEach(config.packages, fixupPackageInfo);
658
659				// for each packagePath found in any packagePaths config item, augment the packageConfig
660				// packagePaths is deprecated; remove in 2.0
661				for(var baseUrl in config.packagePaths){
662					forEach(config.packagePaths[baseUrl], function(packageInfo){
663						var location = baseUrl + "/" + packageInfo;
664						if(isString(packageInfo)){
665							packageInfo = {name:packageInfo};
666						}
667						packageInfo.location = location;
668						fixupPackageInfo(packageInfo);
669					});
670				}
671
672				// notice that computeMapProg treats the dest as a reference; therefore, if/when that variable
673				// is published (see dojo-publish-privates), the published variable will always hold a valid value.
674
675				// this must come after all package processing since package processing may mutate map
676				computeMapProg(mix(map, config.map), mapProgs);
677				forEach(mapProgs, function(item){
678					item[1] = computeMapProg(item[1], []);
679					if(item[0]=="*"){
680						mapProgs.star = item;
681					}
682				});
683
684				// push in any paths and recompute the internal pathmap
685				computeMapProg(mix(paths, config.paths), pathsMapProg);
686
687				// aliases
688				computeAliases(config.aliases, aliases);
689
690				if(booting){
691					delayedModuleConfig.push({config:config.config});
692				}else{
693					for(p in config.config){
694						var module = getModule(p, referenceModule);
695						module.config = mix(module.config || {}, config.config[p]);
696					}
697				}
698
699				// push in any new cache values
700				if(config.cache){
701					consumePendingCacheInsert();
702					pendingCacheInsert = config.cache;
703					if(config.cache["*noref"]){
704						consumePendingCacheInsert();
705					}
706				}
707
708				signal("config", [config, req.rawConfig]);
709			};
710
711		//
712		// execute the various sniffs; userConfig can override and value
713		//
714
715		if(has("dojo-cdn") ||  1 ){
716			// the sniff regex looks for a src attribute ending in dojo.js, optionally preceded with a path.
717			// match[3] returns the path to dojo.js (if any) without the trailing slash. This is used for the
718			// dojo location on CDN deployments and baseUrl when either/both of these are not provided
719			// explicitly in the config data; this is the 1.6- behavior.
720
721			var scripts = doc.getElementsByTagName("script"),
722				i = 0,
723				script, dojoDir, src, match;
724			while(i < scripts.length){
725				script = scripts[i++];
726				if((src = script.getAttribute("src")) && (match = src.match(/(((.*)\/)|^)dojo\.js(\W|$)/i))){
727					// sniff dojoDir and baseUrl
728					dojoDir = match[3] || "";
729					defaultConfig.baseUrl = defaultConfig.baseUrl || dojoDir;
730
731					// remember an insertPointSibling
732					insertPointSibling = script;
733				}
734
735				// sniff configuration on attribute in script element
736				if((src = (script.getAttribute("data-dojo-config") || script.getAttribute("djConfig")))){
737					dojoSniffConfig = req.eval("({ " + src + " })", "data-dojo-config");
738
739					// remember an insertPointSibling
740					insertPointSibling = script;
741				}
742
743				// sniff requirejs attribute
744				if( 0 ){
745					if((src = script.getAttribute("data-main"))){
746						dojoSniffConfig.deps = dojoSniffConfig.deps || [src];
747					}
748				}
749			}
750		}
751
752		if( 0 ){
753			// pass down doh.testConfig from parent as if it were a data-dojo-config
754			try{
755				if(window.parent != window && window.parent.require){
756					var doh = window.parent.require("doh");
757					doh && mix(dojoSniffConfig, doh.testConfig);
758				}
759			}catch(e){}
760		}
761
762		// configure the loader; let the user override defaults
763		req.rawConfig = {};
764		config(defaultConfig, 1);
765
766		// do this before setting userConfig/sniffConfig to allow userConfig/sniff overrides
767		if(has("dojo-cdn")){
768			packs.dojo.location = dojoDir;
769			if(dojoDir){
770				dojoDir += "/";
771			}
772			packs.dijit.location = dojoDir + "../dijit/";
773			packs.dojox.location = dojoDir + "../dojox/";
774		}
775
776		config(userConfig, 1);
777		config(dojoSniffConfig, 1);
778
779	}else{
780		// no config API, assume defaultConfig has everything the loader needs...for the entire lifetime of the application
781		paths = defaultConfig.paths;
782		pathsMapProg = defaultConfig.pathsMapProg;
783		packs = defaultConfig.packs;
784		aliases = defaultConfig.aliases;
785		mapProgs = defaultConfig.mapProgs;
786		modules = defaultConfig.modules;
787		cache = defaultConfig.cache;
788		cacheBust = defaultConfig.cacheBust;
789
790		// remember the default config for other processes (e.g., dojo/config)
791		req.rawConfig = defaultConfig;
792	}
793
794
795	if( 0 ){
796		req.combo = req.combo || {add:noop};
797		var	comboPending = 0,
798			combosPending = [],
799			comboPendingTimer = null;
800	}
801
802
803	// build the loader machinery iaw configuration, including has feature tests
804	var	injectDependencies = function(module){
805			// checkComplete!=0 holds the idle signal; we're not idle if we're injecting dependencies
806			guardCheckComplete(function(){
807				forEach(module.deps, injectModule);
808				if( 0  && comboPending && !comboPendingTimer){
809					comboPendingTimer = setTimeout(function() {
810						comboPending = 0;
811						comboPendingTimer = null;
812						req.combo.done(function(mids, url) {
813							var onLoadCallback= function(){
814								// defQ is a vector of module definitions 1-to-1, onto mids
815								runDefQ(0, mids);
816								checkComplete();
817							};
818							combosPending.push(mids);
819							injectingModule = mids;
820							req.injectUrl(url, onLoadCallback, mids);
821							injectingModule = 0;
822						}, req);
823					}, 0);
824				}
825			});
826		},
827
828		contextRequire = function(a1, a2, a3, referenceModule, contextRequire){
829			var module, syntheticMid;
830			if(isString(a1)){
831				// signature is (moduleId)
832				module = getModule(a1, referenceModule, true);
833				if(module && module.executed){
834					return module.result;
835				}
836				throw makeError("undefinedModule", a1);
837			}
838			if(!isArray(a1)){
839				// a1 is a configuration
840				config(a1, 0, referenceModule);
841
842				// juggle args; (a2, a3) may be (dependencies, callback)
843				a1 = a2;
844				a2 = a3;
845			}
846			if(isArray(a1)){
847				// signature is (requestList [,callback])
848				if(!a1.length){
849					a2 && a2();
850				}else{
851					syntheticMid = "require*" + uid();
852
853					// resolve the request list with respect to the reference module
854					for(var mid, deps = [], i = 0; i < a1.length;){
855						mid = a1[i++];
856						deps.push(getModule(mid, referenceModule));
857					}
858
859					// construct a synthetic module to control execution of the requestList, and, optionally, callback
860					module = mix(makeModuleInfo("", syntheticMid, 0, ""), {
861						injected: arrived,
862						deps: deps,
863						def: a2 || noop,
864						require: referenceModule ? referenceModule.require : req,
865						gc: 1 //garbage collect
866					});
867					modules[module.mid] = module;
868
869					// checkComplete!=0 holds the idle signal; we're not idle if we're injecting dependencies
870					injectDependencies(module);
871
872					// try to immediately execute
873					// if already traversing a factory tree, then strict causes circular dependency to abort the execution; maybe
874					// it's possible to execute this require later after the current traversal completes and avoid the circular dependency.
875					// ...but *always* insist on immediate in synch mode
876					var strict = checkCompleteGuard && legacyMode!=sync;
877					guardCheckComplete(function(){
878						execModule(module, strict);
879					});
880					if(!module.executed){
881						// some deps weren't on board or circular dependency detected and strict; therefore, push into the execQ
882						execQ.push(module);
883					}
884					checkComplete();
885				}
886			}
887			return contextRequire;
888		},
889
890		createRequire = function(module){
891			if(!module){
892				return req;
893			}
894			var result = module.require;
895			if(!result){
896				result = function(a1, a2, a3){
897					return contextRequire(a1, a2, a3, module, result);
898				};
899				module.require = mix(result, req);
900				result.module = module;
901				result.toUrl = function(name){
902					return toUrl(name, module);
903				};
904				result.toAbsMid = function(mid){
905					return toAbsMid(mid, module);
906				};
907				if( 0 ){
908					result.undef = function(mid){
909						req.undef(mid, module);
910					};
911				}
912				if( 0 ){
913					result.syncLoadNls = function(mid){
914						var nlsModuleInfo = getModuleInfo(mid, module),
915							nlsModule = modules[nlsModuleInfo.mid];
916						if(!nlsModule || !nlsModule.executed){
917							cached = cache[nlsModuleInfo.mid] || cache[urlKeyPrefix + nlsModuleInfo.url];
918							if(cached){
919								evalModuleText(cached);
920								nlsModule = modules[nlsModuleInfo.mid];
921							}
922						}
923						return nlsModule && nlsModule.executed && nlsModule.result;
924					};
925				}
926
927			}
928			return result;
929		},
930
931		execQ =
932			// The list of modules that need to be evaluated.
933			[],
934
935		defQ =
936			// The queue of define arguments sent to loader.
937			[],
938
939		waiting =
940			// The set of modules upon which the loader is waiting for definition to arrive
941			{},
942
943		setRequested = function(module){
944			module.injected = requested;
945			waiting[module.mid] = 1;
946			if(module.url){
947				waiting[module.url] = module.pack || 1;
948			}
949			startTimer();
950		},
951
952		setArrived = function(module){
953			module.injected = arrived;
954			delete waiting[module.mid];
955			if(module.url){
956				delete waiting[module.url];
957			}
958			if(isEmpty(waiting)){
959				clearTimer();
960				 0  && legacyMode==xd && (legacyMode = sync);
961			}
962		},
963
964		execComplete = req.idle =
965			// says the loader has completed (or not) its work
966			function(){
967				return !defQ.length && isEmpty(waiting) && !execQ.length && !checkCompleteGuard;
968			},
969
970		runMapProg = function(targetMid, map){
971			// search for targetMid in map; return the map item if found; falsy otherwise
972			if(map){
973			for(var i = 0; i < map.length; i++){
974				if(map[i][2].test(targetMid)){
975					return map[i];
976				}
977			}
978			}
979			return 0;
980		},
981
982		compactPath = function(path){
983			var result = [],
984				segment, lastSegment;
985			path = path.replace(/\\/g, '/').split('/');
986			while(path.length){
987				segment = path.shift();
988				if(segment==".." && result.length && lastSegment!=".."){
989					result.pop();
990					lastSegment = result[result.length - 1];
991				}else if(segment!="."){
992					result.push(lastSegment= segment);
993				} // else ignore "."
994			}
995			return result.join("/");
996		},
997
998		makeModuleInfo = function(pid, mid, pack, url){
999			if( 0 ){
1000				var xd= req.isXdUrl(url);
1001				return {pid:pid, mid:mid, pack:pack, url:url, executed:0, def:0, isXd:xd, isAmd:!!(xd || (packs[pid] && packs[pid].isAmd))};
1002			}else{
1003				return {pid:pid, mid:mid, pack:pack, url:url, executed:0, def:0};
1004			}
1005		},
1006
1007		getModuleInfo_ = function(mid, referenceModule, packs, modules, baseUrl, mapProgs, pathsMapProg, aliases, alwaysCreate){
1008			// arguments are passed instead of using lexical variables so that this function my be used independent of the loader (e.g., the builder)
1009			// alwaysCreate is useful in this case so that getModuleInfo never returns references to real modules owned by the loader
1010			var pid, pack, midInPackage, mapItem, url, result, isRelative, requestedMid;
1011			requestedMid = mid;
1012			isRelative = /^\./.test(mid);
1013			if(/(^\/)|(\:)|(\.js$)/.test(mid) || (isRelative && !referenceModule)){
1014				// absolute path or protocol of .js filetype, or relative path but no reference module and therefore relative to page
1015				// whatever it is, it's not a module but just a URL of some sort
1016				// note: pid===0 indicates the routine is returning an unmodified mid
1017
1018				return makeModuleInfo(0, mid, 0, mid);
1019			}else{
1020				// relative module ids are relative to the referenceModule; get rid of any dots
1021				mid = compactPath(isRelative ? (referenceModule.mid + "/../" + mid) : mid);
1022				if(/^\./.test(mid)){
1023					throw makeError("irrationalPath", mid);
1024				}
1025				// at this point, mid is an absolute mid
1026
1027				// map the mid
1028				if(referenceModule){
1029					mapItem = runMapProg(referenceModule.mid, mapProgs);
1030				}
1031				mapItem = mapItem || mapProgs.star;
1032				mapItem = mapItem && runMapProg(mid, mapItem[1]);
1033
1034				if(mapItem){
1035					mid = mapItem[1] + mid.substring(mapItem[3]);
1036					}
1037
1038				match = mid.match(/^([^\/]+)(\/(.+))?$/);
1039				pid = match ? match[1] : "";
1040				if((pack = packs[pid])){
1041					mid = pid + "/" + (midInPackage = (match[3] || pack.main));
1042				}else{
1043					pid = "";
1044				}
1045
1046				// search aliases
1047				var candidateLength = 0,
1048					candidate = 0;
1049				forEach(aliases, function(pair){
1050					var match = mid.match(pair[0]);
1051					if(match && match.length>candidateLength){
1052						candidate = isFunction(pair[1]) ? mid.replace(pair[0], pair[1]) : pair[1];
1053					}
1054				});
1055				if(candidate){
1056					return getModuleInfo_(candidate, 0, packs, modules, baseUrl, mapProgs, pathsMapProg, aliases, alwaysCreate);
1057				}
1058
1059				result = modules[mid];
1060				if(result){
1061					return alwaysCreate ? makeModuleInfo(result.pid, result.mid, result.pack, result.url) : modules[mid];
1062				}
1063			}
1064			// get here iff the sought-after module does not yet exist; therefore, we need to compute the URL given the
1065			// fully resolved (i.e., all relative indicators and package mapping resolved) module id
1066
1067			// note: pid!==0 indicates the routine is returning a url that has .js appended unmodified mid
1068			mapItem = runMapProg(mid, pathsMapProg);
1069			if(mapItem){
1070				url = mapItem[1] + mid.substring(mapItem[3]);
1071			}else if(pid){
1072				url = pack.location + "/" + midInPackage;
1073			}else if( 0 ){
1074				url = "../" + mid;
1075			}else{
1076				url = mid;
1077			}
1078			// if result is not absolute, add baseUrl
1079			if(!(/(^\/)|(\:)/.test(url))){
1080				url = baseUrl + url;
1081			}
1082			url += ".js";
1083			return makeModuleInfo(pid, mid, pack, compactPath(url));
1084		},
1085
1086		getModuleInfo = function(mid, referenceModule, fromPendingCache){
1087			return getModuleInfo_(mid, referenceModule, packs, modules, req.baseUrl, fromPendingCache ? [] : mapProgs, fromPendingCache ? [] : pathsMapProg, fromPendingCache ? [] : aliases);
1088		},
1089
1090		resolvePluginResourceId = function(plugin, prid, referenceModule){
1091			return plugin.normalize ? plugin.normalize(prid, function(mid){return toAbsMid(mid, referenceModule);}) : toAbsMid(prid, referenceModule);
1092		},
1093
1094		dynamicPluginUidGenerator = 0,
1095
1096		getModule = function(mid, referenceModule, immediate){
1097			// compute and optionally construct (if necessary) the module implied by the mid with respect to referenceModule
1098			var match, plugin, prid, result;
1099			match = mid.match(/^(.+?)\!(.*)$/);
1100			if(match){
1101				// name was <plugin-module>!<plugin-resource-id>
1102				plugin = getModule(match[1], referenceModule, immediate);
1103
1104				if( 0  && legacyMode == sync && !plugin.executed){
1105					injectModule(plugin);
1106					if(plugin.injected===arrived && !plugin.executed){
1107						guardCheckComplete(function(){
1108							execModule(plugin);
1109						});
1110					}
1111					if(plugin.executed){
1112						promoteModuleToPlugin(plugin);
1113					}else{
1114						// we are in xdomain mode for some reason
1115						execQ.unshift(plugin);
1116					}
1117				}
1118
1119
1120
1121				if(plugin.executed === executed && !plugin.load){
1122					// executed the module not knowing it was a plugin
1123					promoteModuleToPlugin(plugin);
1124				}
1125
1126				// if the plugin has not been loaded, then can't resolve the prid and  must assume this plugin is dynamic until we find out otherwise
1127				if(plugin.load){
1128					prid = resolvePluginResourceId(plugin, match[2], referenceModule);
1129					mid = (plugin.mid + "!" + (plugin.dynamic ? ++dynamicPluginUidGenerator + "!" : "") + prid);
1130				}else{
1131					prid = match[2];
1132					mid = plugin.mid + "!" + (++dynamicPluginUidGenerator) + "!waitingForPlugin";
1133				}
1134				result = {plugin:plugin, mid:mid, req:createRequire(referenceModule), prid:prid};
1135			}else{
1136				result = getModuleInfo(mid, referenceModule);
1137			}
1138			return modules[result.mid] || (!immediate && (modules[result.mid] = result));
1139		},
1140
1141		toAbsMid = req.toAbsMid = function(mid, referenceModule){
1142			return getModuleInfo(mid, referenceModule).mid;
1143		},
1144
1145		toUrl = req.toUrl = function(name, referenceModule){
1146			var moduleInfo = getModuleInfo(name+"/x", referenceModule),
1147				url= moduleInfo.url;
1148			return fixupUrl(moduleInfo.pid===0 ?
1149				// if pid===0, then name had a protocol or absolute path; either way, toUrl is the identify function in such cases
1150				name :
1151				// "/x.js" since getModuleInfo automatically appends ".js" and we appended "/x" to make name look like a module id
1152				url.substring(0, url.length-5)
1153			);
1154		},
1155
1156		nonModuleProps = {
1157			injected: arrived,
1158			executed: executed,
1159			def: nonmodule,
1160			result: nonmodule
1161		},
1162
1163		makeCjs = function(mid){
1164			return modules[mid] = mix({mid:mid}, nonModuleProps);
1165		},
1166
1167		cjsRequireModule = makeCjs("require"),
1168		cjsExportsModule = makeCjs("exports"),
1169		cjsModuleModule = makeCjs("module"),
1170
1171		runFactory = function(module, args){
1172			req.trace("loader-run-factory", [module.mid]);
1173			var factory = module.def,
1174				result;
1175			 0  && syncExecStack.unshift(module);
1176			if( 0 ){
1177				try{
1178					result= isFunction(factory) ? factory.apply(null, args) : factory;
1179				}catch(e){
1180					signal(error, module.result = makeError("factoryThrew", [module, e]));
1181				}
1182			}else{
1183				result= isFunction(factory) ? factory.apply(null, args) : factory;
1184			}
1185			module.result = result===undefined && module.cjs ? module.cjs.exports : result;
1186			 0  && syncExecStack.shift(module);
1187		},
1188
1189		abortExec = {},
1190
1191		defOrder = 0,
1192
1193		promoteModuleToPlugin = function(pluginModule){
1194			var plugin = pluginModule.result;
1195			pluginModule.dynamic = plugin.dynamic;
1196			pluginModule.normalize = plugin.normalize;
1197			pluginModule.load = plugin.load;
1198			return pluginModule;
1199		},
1200
1201		resolvePluginLoadQ = function(plugin){
1202			// plugins is a newly executed module that has a loadQ waiting to run
1203
1204			// step 1: traverse the loadQ and fixup the mid and prid; remember the map from original mid to new mid
1205			// recall the original mid was created before the plugin was on board and therefore it was impossible to
1206			// compute the final mid; accordingly, prid may or may not change, but the mid will definitely change
1207			var map = {};
1208			forEach(plugin.loadQ, function(pseudoPluginResource){
1209				// manufacture and insert the real module in modules
1210				var prid = resolvePluginResourceId(plugin, pseudoPluginResource.prid, pseudoPluginResource.req.module),
1211					mid = plugin.dynamic ? pseudoPluginResource.mid.replace(/waitingForPlugin$/, prid) : (plugin.mid + "!" + prid),
1212					pluginResource = mix(mix({}, pseudoPluginResource), {mid:mid, prid:prid, injected:0});
1213				if(!modules[mid]){
1214					// create a new (the real) plugin resource and inject it normally now that the plugin is on board
1215					injectPlugin(modules[mid] = pluginResource);
1216				} // else this was a duplicate request for the same (plugin, rid) for a nondynamic plugin
1217
1218				// pluginResource is really just a placeholder with the wrong mid (because we couldn't calculate it until the plugin was on board)
1219				// mark is as arrived and delete it from modules; the real module was requested above
1220				map[pseudoPluginResource.mid] = modules[mid];
1221				setArrived(pseudoPluginResource);
1222				delete modules[pseudoPluginResource.mid];
1223			});
1224			plugin.loadQ = 0;
1225
1226			// step2: replace all references to any placeholder modules with real modules
1227			var substituteModules = function(module){
1228				for(var replacement, deps = module.deps || [], i = 0; i<deps.length; i++){
1229					replacement = map[deps[i].mid];
1230					if(replacement){
1231						deps[i] = replacement;
1232					}
1233				}
1234			};
1235			for(var p in modules){
1236				substituteModules(modules[p]);
1237			}
1238			forEach(execQ, substituteModules);
1239		},
1240
1241		finishExec = function(module){
1242			req.trace("loader-finish-exec", [module.mid]);
1243			module.executed = executed;
1244			module.defOrder = defOrder++;
1245			 0  && forEach(module.provides, function(cb){ cb(); });
1246			if(module.loadQ){
1247				// the module was a plugin
1248				promoteModuleToPlugin(module);
1249				resolvePluginLoadQ(module);
1250			}
1251			// remove all occurrences of this module from the execQ
1252			for(i = 0; i < execQ.length;){
1253				if(execQ[i] === module){
1254					execQ.splice(i, 1);
1255				}else{
1256					i++;
1257				}
1258			}
1259			// delete references to synthetic modules
1260			if (/^require\*/.test(module.mid)) {
1261				delete modules[module.mid];
1262			}
1263		},
1264
1265		circleTrace = [],
1266
1267		execModule = function(module, strict){
1268			// run the dependency vector, then run the factory for module
1269			if(module.executed === executing){
1270				req.trace("loader-circular-dependency", [circleTrace.concat(module.mid).join("->")]);
1271				return (!module.def || strict) ? abortExec :  (module.cjs && module.cjs.exports);
1272			}
1273			// at this point the module is either not executed or fully executed
1274
1275
1276			if(!module.executed){
1277				if(!module.def){
1278					return abortExec;
1279				}
1280				var mid = module.mid,
1281					deps = module.deps || [],
1282					arg, argResult,
1283					args = [],
1284					i = 0;
1285
1286				if( 0 ){
1287					circleTrace.push(mid);
1288					req.trace("loader-exec-module", ["exec", circleTrace.length, mid]);
1289				}
1290
1291				// for circular dependencies, assume the first module encountered was executed OK
1292				// modules that circularly depend on a module that has not run its factory will get
1293				// the pre-made cjs.exports===module.result. They can take a reference to this object and/or
1294				// add properties to it. When the module finally runs its factory, the factory can
1295				// read/write/replace this object. Notice that so long as the object isn't replaced, any
1296				// reference taken earlier while walking the deps list is still valid.
1297				module.executed = executing;
1298				while((arg = deps[i++])){
1299					argResult = ((arg === cjsRequireModule) ? createRequire(module) :
1300									((arg === cjsExportsModule) ? module.cjs.exports :
1301										((arg === cjsModuleModule) ? module.cjs :
1302											execModule(arg, strict))));
1303					if(argResult === abortExec){
1304						module.executed = 0;
1305						req.trace("loader-exec-module", ["abort", mid]);
1306						 0  && circleTrace.pop();
1307						return abortExec;
1308					}
1309					args.push(argResult);
1310				}
1311				runFactory(module, args);
1312				finishExec(module);
1313				 0  && circleTrace.pop();
1314			}
1315			// at this point the module is guaranteed fully executed
1316
1317			return module.result;
1318		},
1319
1320
1321		checkCompleteGuard = 0,
1322
1323		guardCheckComplete = function(proc){
1324			try{
1325				checkCompleteGuard++;
1326				proc();
1327			}finally{
1328				checkCompleteGuard--;
1329			}
1330			if(execComplete()){
1331				signal("idle", []);
1332			}
1333		},
1334
1335		checkComplete = function(){
1336			// keep going through the execQ as long as at least one factory is executed
1337			// plugins, recursion, cached modules all make for many execution path possibilities
1338			if(checkCompleteGuard){
1339				return;
1340			}
1341			guardCheckComplete(function(){
1342				checkDojoRequirePlugin();
1343				for(var currentDefOrder, module, i = 0; i < execQ.length;){
1344					currentDefOrder = defOrder;
1345					module = execQ[i];
1346					execModule(module);
1347					if(currentDefOrder!=defOrder){
1348						// defOrder was bumped one or more times indicating something was executed (note, this indicates
1349						// the execQ was modified, maybe a lot (for example a later module causes an earlier module to execute)
1350						checkDojoRequirePlugin();
1351						i = 0;
1352					}else{
1353						// nothing happened; check the next module in the exec queue
1354						i++;
1355					}
1356				}
1357			});
1358		};
1359
1360
1361	if( 0 ){
1362		req.undef = function(moduleId, referenceModule){
1363			// In order to reload a module, it must be undefined (this routine) and then re-requested.
1364			// This is useful for testing frameworks (at least).
1365			var module = getModule(moduleId, referenceModule);
1366			setArrived(module);
1367			mix(module, {def:0, executed:0, injected:0, node:0});
1368		};
1369	}
1370
1371	if( 1 ){
1372		if(has("dojo-loader-eval-hint-url")===undefined){
1373			has.add("dojo-loader-eval-hint-url", 1);
1374		}
1375
1376		var fixupUrl= typeof userConfig.fixupUrl == "function" ? userConfig.fixupUrl : function(url){
1377				url += ""; // make sure url is a Javascript string (some paths may be a Java string)
1378				return url + (cacheBust ? ((/\?/.test(url) ? "&" : "?") + cacheBust) : "");
1379			},
1380
1381			injectPlugin = function(
1382				module
1383			){
1384				// injects the plugin module given by module; may have to inject the plugin itself
1385				var plugin = module.plugin;
1386
1387				if(plugin.executed === executed && !plugin.load){
1388					// executed the module not knowing it was a plugin
1389					promoteModuleToPlugin(plugin);
1390				}
1391
1392				var onLoad = function(def){
1393						module.result = def;
1394						setArrived(module);
1395						finishExec(module);
1396						checkComplete();
1397					};
1398
1399				if(plugin.load){
1400					plugin.load(module.prid, module.req, onLoad);
1401				}else if(plugin.loadQ){
1402					plugin.loadQ.push(module);
1403				}else{
1404					// the unshift instead of push is important: we don't want plugins to execute as
1405					// dependencies of some other module because this may cause circles when the plugin
1406					// loadQ is run; also, generally, we want plugins to run early since they may load
1407					// several other modules and therefore can potentially unblock many modules
1408					plugin.loadQ = [module];
1409					execQ.unshift(plugin);
1410					injectModule(plugin);
1411				}
1412			},
1413
1414			// for IE, injecting a module may result in a recursive execution if the module is in the cache
1415
1416			cached = 0,
1417
1418			injectingModule = 0,
1419
1420			injectingCachedModule = 0,
1421
1422			evalModuleText = function(text, module){
1423				// see def() for the injectingCachedModule bracket; it simply causes a short, safe circuit
1424				if(has("config-stripStrict")){
1425					text = text.replace(/"use strict"/g, '');
1426				}
1427				injectingCachedModule = 1;
1428				if( 0 ){
1429					try{
1430						if(text===cached){
1431							cached.call(null);
1432						}else{
1433							req.eval(text, has("dojo-loader-eval-hint-url") ? module.url : module.mid);
1434						}
1435					}catch(e){
1436						signal(error, makeError("evalModuleThrew", module));
1437					}
1438				}else{
1439					if(text===cached){
1440						cached.call(null);
1441					}else{
1442						req.eval(text, has("dojo-loader-eval-hint-url") ? module.url : module.mid);
1443					}
1444				}
1445				injectingCachedModule = 0;
1446			},
1447
1448			injectModule = function(module){
1449				// Inject the module. In the browser environment, this means appending a script element into
1450				// the document; in other environments, it means loading a file.
1451				//
1452				// If in synchronous mode, then get the module synchronously if it's not xdomainLoading.
1453
1454				var mid = module.mid,
1455					url = module.url;
1456				if(module.executed || module.injected || waiting[mid] || (module.url && ((module.pack && waiting[module.url]===module.pack) || waiting[module.url]==1))){
1457					return;
1458				}
1459				setRequested(module);
1460
1461				if( 0 ){
1462					var viaCombo = 0;
1463					if(module.plugin && module.plugin.isCombo){
1464						// a combo plugin; therefore, must be handled by combo service
1465						// the prid should have already been converted to a URL (if required by the plugin) during
1466						// the normalize process; in any event, there is no way for the loader to know how to
1467						// to the conversion; therefore the third argument is zero
1468						req.combo.add(module.plugin.mid, module.prid, 0, req);
1469						viaCombo = 1;
1470					}else if(!module.plugin){
1471						viaCombo = req.combo.add(0, module.mid, module.url, req);
1472					}
1473					if(viaCombo){
1474						comboPending= 1;
1475						return;
1476					}
1477				}
1478
1479				if(module.plugin){
1480					injectPlugin(module);
1481					return;
1482				} // else a normal module (not a plugin)
1483
1484
1485				var onLoadCallback = function(){
1486					runDefQ(module);
1487					if(module.injected !== arrived){
1488						// the script that contained the module arrived and has been executed yet
1489						// nothing was added to the defQ (so it wasn't an AMD module) and the module
1490						// wasn't marked as arrived by dojo.provide (so it wasn't a v1.6- module);
1491						// therefore, it must not have been a module; adjust state accordingly
1492						if(has("dojo-enforceDefine")){
1493							signal(error, makeError("noDefine", module));
1494							return;
1495						}
1496						setArrived(module);
1497						mix(module, nonModuleProps);
1498						req.trace("loader-define-nonmodule", [module.url]);
1499					}
1500
1501					if( 0  && legacyMode){
1502						// must call checkComplete even in for sync loader because we may be in xdomainLoading mode;
1503						// but, if xd loading, then don't call checkComplete until out of the current sync traversal
1504						// in order to preserve order of execution of the dojo.required modules
1505						!syncExecStack.length && checkComplete();
1506					}else{
1507						checkComplete();
1508					}
1509				};
1510				cached = cache[mid] || cache[urlKeyPrefix + module.url];
1511				if(cached){
1512					req.trace("loader-inject", ["cache", module.mid, url]);
1513					evalModuleText(cached, module);
1514					onLoadCallback();
1515					return;
1516				}
1517				if( 0  && legacyMode){
1518					if(module.isXd){
1519						// switch to async mode temporarily; if current legacyMode!=sync, then is must be one of {legacyAsync, xd, false}
1520						legacyMode==sync && (legacyMode = xd);
1521						// fall through and load via script injection
1522					}else if(module.isAmd && legacyMode!=sync){
1523						// fall through and load via script injection
1524					}else{
1525						// mode may be sync, xd/legacyAsync, or async; module may be AMD or legacy; but module is always located on the same domain
1526						var xhrCallback = function(text){
1527							if(legacyMode==sync){
1528								// the top of syncExecStack gives the current synchronously executing module; the loader needs
1529								// to know this if it has to switch to async loading in the middle of evaluating a legacy module
1530								// this happens when a modules dojo.require's a module that must be loaded async because it's xdomain
1531								// (using unshift/shift because there is no back() methods for Javascript arrays)
1532								syncExecStack.unshift(module);
1533								evalModuleText(text, module);
1534								syncExecStack.shift();
1535
1536								// maybe the module was an AMD module
1537								runDefQ(module);
1538
1539								// legacy modules never get to defineModule() => cjs and injected never set; also evaluation implies executing
1540								if(!module.cjs){
1541									setArrived(module);
1542									finishExec(module);
1543								}
1544
1545								if(module.finish){
1546									// while synchronously evaluating this module, dojo.require was applied referencing a module
1547									// that had to be loaded async; therefore, the loader stopped answering all dojo.require
1548									// requests so they could be answered completely in the correct sequence; module.finish gives
1549									// the list of dojo.requires that must be re-applied once all target modules are available;
1550									// make a synthetic module to execute the dojo.require's in the correct order
1551
1552									// compute a guaranteed-unique mid for the synthetic finish module; remember the finish vector; remove it from the reference module
1553									// TODO: can we just leave the module.finish...what's it hurting?
1554									var finishMid = mid + "*finish",
1555										finish = module.finish;
1556									delete module.finish;
1557
1558									def(finishMid, ["dojo", ("dojo/require!" + finish.join(",")).replace(/\./g, "/")], function(dojo){
1559										forEach(finish, function(mid){ dojo.require(mid); });
1560									});
1561									// unshift, not push, which causes the current traversal to be reattempted from the top
1562									execQ.unshift(getModule(finishMid));
1563								}
1564								onLoadCallback();
1565							}else{
1566								text = transformToAmd(module, text);
1567								if(text){
1568									evalModuleText(text, module);
1569									onLoadCallback();
1570								}else{
1571									// if transformToAmd returned falsy, then the module was already AMD and it can be script-injected
1572									// do so to improve debugability(even though it means another download...which probably won't happen with a good browser cache)
1573									injectingModule = module;
1574									req.injectUrl(fixupUrl(url), onLoadCallback, module);
1575									injectingModule = 0;
1576								}
1577							}
1578						};
1579
1580						req.trace("loader-inject", ["xhr", module.mid, url, legacyMode!=sync]);
1581						if( 0 ){
1582							try{
1583								req.getText(url, legacyMode!=sync, xhrCallback);
1584							}catch(e){
1585								signal(error, makeError("xhrInjectFailed", [module, e]));
1586							}
1587						}else{
1588							req.getText(url, legacyMode!=sync, xhrCallback);
1589						}
1590						return;
1591					}
1592				} // else async mode or fell through in xdomain loading mode; either way, load by script injection
1593				req.trace("loader-inject", ["script", module.mid, url]);
1594				injectingModule = module;
1595				req.injectUrl(fixupUrl(url), onLoadCallback, module);
1596				injectingModule = 0;
1597			},
1598
1599			defineModule = function(module, deps, def){
1600				req.trace("loader-define-module", [module.mid, deps]);
1601
1602				if( 0  && module.plugin && module.plugin.isCombo){
1603					// the module is a plugin resource loaded by the combo service
1604					// note: check for module.plugin should be enough since normal plugin resources should
1605					// not follow this path; module.plugin.isCombo is future-proofing belt and suspenders
1606					module.result = isFunction(def) ? def() : def;
1607					setArrived(module);
1608					finishExec(module);
1609					return module;
1610				}
1611
1612				var mid = module.mid;
1613				if(module.injected === arrived){
1614					signal(error, makeError("multipleDefine", module));
1615					return module;
1616				}
1617				mix(module, {
1618					deps: deps,
1619					def: def,
1620					cjs: {
1621						id: module.mid,
1622						uri: module.url,
1623						exports: (module.result = {}),
1624						setExports: function(exports){
1625							module.cjs.exports = exports;
1626						},
1627						config:function(){
1628							return module.config;
1629						}
1630					}
1631				});
1632
1633				// resolve deps with respect to this module
1634				for(var i = 0; deps[i]; i++){
1635					deps[i] = getModule(deps[i], module);
1636				}
1637
1638				if( 0  && legacyMode && !waiting[mid]){
1639					// the module showed up without being asked for; it was probably in a <script> element
1640					injectDependencies(module);
1641					execQ.push(module);
1642					checkComplete();
1643				}
1644				setArrived(module);
1645
1646				if(!isFunction(def) && !deps.length){
1647					module.result = def;
1648					finishExec(module);
1649				}
1650
1651				return module;
1652			},
1653
1654			runDefQ = function(referenceModule, mids){
1655				// defQ is an array of [id, dependencies, factory]
1656				// mids (if any) is a vector of mids given by a combo service
1657				var definedModules = [],
1658					module, args;
1659				while(defQ.length){
1660					args = defQ.shift();
1661					mids && (args[0]= mids.shift());
1662					// explicit define indicates possible multiple modules in a single file; delay injecting dependencies until defQ fully
1663					// processed since modules earlier in the queue depend on already-arrived modules that are later in the queue
1664					// TODO: what if no args[0] and no referenceModule
1665					module = (args[0] && getModule(args[0])) || referenceModule;
1666					definedModules.push([module, args[1], args[2]]);
1667				}
1668				consumePendingCacheInsert(referenceModule);
1669				forEach(definedModules, function(args){
1670					injectDependencies(defineModule.apply(null, args));
1671				});
1672			};
1673	}
1674
1675	var timerId = 0,
1676		clearTimer = noop,
1677		startTimer = noop;
1678	if( 0 ){
1679		// Timer machinery that monitors how long the loader is waiting and signals an error when the timer runs out.
1680		clearTimer = function(){
1681			timerId && clearTimeout(timerId);
1682			timerId = 0;
1683		};
1684
1685		startTimer = function(){
1686			clearTimer();
1687			if(req.waitms){
1688				timerId = global.setTimeout(function(){
1689					clearTimer();
1690					signal(error, makeError("timeout", waiting));
1691				}, req.waitms);
1692			}
1693		};
1694	}
1695
1696	if ( 1 ) {
1697		// Test for IE's different way of signaling when scripts finish loading.  Note that according to
1698		// http://bugs.dojotoolkit.org/ticket/15096#comment:14, IE9 also needs to follow the
1699		// IE specific code path even though it has an addEventListener() method.
1700		// Unknown if special path needed on IE10+, which also has a document.attachEvent() method.
1701		// Should evaluate to false for Opera and Windows 8 apps, even though they document.attachEvent()
1702		//  is defined in both those environments.
1703		has.add("ie-event-behavior", doc.attachEvent && typeof Windows === "undefined" &&
1704			(typeof opera === "undefined" || opera.toString() != "[object Opera]"));
1705	}
1706
1707	if( 1  && ( 1  ||  1 )){
1708		var domOn = function(node, eventName, ieEventName, handler){
1709				// Add an event listener to a DOM node using the API appropriate for the current browser;
1710				// return a function that will disconnect the listener.
1711				if(!has("ie-event-behavior")){
1712					node.addEventListener(eventName, handler, false);
1713					return function(){
1714						node.removeEventListener(eventName, handler, false);
1715					};
1716				}else{
1717					node.attachEvent(ieEventName, handler);
1718					return function(){
1719						node.detachEvent(ieEventName, handler);
1720					};
1721				}
1722			},
1723			windowOnLoadListener = domOn(window, "load", "onload", function(){
1724				req.pageLoaded = 1;
1725				doc.readyState!="complete" && (doc.readyState = "complete");
1726				windowOnLoadListener();
1727			});
1728
1729		if( 1 ){
1730			// if the loader is on the page, there must be at least one script element
1731			// getting its parent and then doing insertBefore solves the "Operation Aborted"
1732			// error in IE from appending to a node that isn't properly closed; see
1733			// dojo/tests/_base/loader/requirejs/simple-badbase.html for an example
1734			// don't use scripts with type dojo/... since these may be removed; see #15809
1735			// prefer to use the insertPoint computed during the config sniff in case a script is removed; see #16958
1736			var scripts = doc.getElementsByTagName("script"),
1737				i = 0,
1738				script;
1739			while(!insertPointSibling){
1740				if(!/^dojo/.test((script = scripts[i++]) && script.type)){
1741					insertPointSibling= script;
1742				}
1743			}
1744
1745			req.injectUrl = function(url, callback, owner){
1746				// insert a script element to the insert-point element with src=url;
1747				// apply callback upon detecting the script has loaded.
1748
1749				var node = owner.node = doc.createElement("script"),
1750					onLoad = function(e){
1751						e = e || window.event;
1752						var node = e.target || e.srcElement;
1753						if(e.type === "load" || /complete|loaded/.test(node.readyState)){
1754							loadDisconnector();
1755							errorDisconnector();
1756							callback && callback();
1757						}
1758					},
1759					loadDisconnector = domOn(node, "load", "onreadystatechange", onLoad),
1760					errorDisconnector = domOn(node, "error", "onerror", function(e){
1761						loadDisconnector();
1762						errorDisconnector();
1763						signal(error, makeError("scriptError", [url, e]));
1764					});
1765
1766				node.type = "text/javascript";
1767				node.charset = "utf-8";
1768				node.src = url;
1769				insertPointSibling.parentNode.insertBefore(node, insertPointSibling);
1770				return node;
1771			};
1772		}
1773	}
1774
1775	if( 0 ){
1776		req.log = function(){
1777			try{
1778				for(var i = 0; i < arguments.length; i++){
1779					console.log(arguments[i]);
1780				}
1781			}catch(e){}
1782		};
1783	}else{
1784		req.log = noop;
1785	}
1786
1787	if( 0 ){
1788		var trace = req.trace = function(
1789			group,	// the trace group to which this application belongs
1790			args	// the contents of the trace
1791		){
1792			///
1793			// Tracing interface by group.
1794			//
1795			// Sends the contents of args to the console iff (req.trace.on && req.trace[group])
1796
1797			if(trace.on && trace.group[group]){
1798				signal("trace", [group, args]);
1799				for(var arg, dump = [], text= "trace:" + group + (args.length ? (":" + args[0]) : ""), i= 1; i<args.length;){
1800					arg = args[i++];
1801					if(isString(arg)){
1802						text += ", " + arg;
1803					}else{
1804						dump.push(arg);
1805					}
1806				}
1807				req.log(text);
1808				dump.length && dump.push(".");
1809				req.log.apply(req, dump);
1810			}
1811		};
1812		mix(trace, {
1813			on:1,
1814			group:{},
1815			set:function(group, value){
1816				if(isString(group)){
1817					trace.group[group]= value;
1818				}else{
1819					mix(trace.group, group);
1820				}
1821			}
1822		});
1823		trace.set(mix(mix(mix({}, defaultConfig.trace), userConfig.trace), dojoSniffConfig.trace));
1824		on("config", function(config){
1825			config.trace && trace.set(config.trace);
1826		});
1827	}else{
1828		req.trace = noop;
1829	}
1830
1831	var def = function(
1832		mid,		  //(commonjs.moduleId, optional)
1833		dependencies, //(array of commonjs.moduleId, optional) list of modules to be loaded before running factory
1834		factory		  //(any)
1835	){
1836		///
1837		// Advises the loader of a module factory. //Implements http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition.
1838		///
1839		//note
1840		// CommonJS factory scan courtesy of http://requirejs.org
1841
1842		var arity = arguments.length,
1843			defaultDeps = ["require", "exports", "module"],
1844			// the predominate signature...
1845			args = [0, mid, dependencies];
1846		if(arity==1){
1847			args = [0, (isFunction(mid) ? defaultDeps : []), mid];
1848		}else if(arity==2 && isString(mid)){
1849			args = [mid, (isFunction(dependencies) ? defaultDeps : []), dependencies];
1850		}else if(arity==3){
1851			args = [mid, dependencies, factory];
1852		}
1853
1854		if( 0  && args[1]===defaultDeps){
1855			args[2].toString()
1856				.replace(/(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg, "")
1857				.replace(/require\(["']([\w\!\-_\.\/]+)["']\)/g, function(match, dep){
1858				args[1].push(dep);
1859			});
1860		}
1861
1862		req.trace("loader-define", args.slice(0, 2));
1863		var targetModule = args[0] && getModule(args[0]),
1864			module;
1865		if(targetModule && !waiting[targetModule.mid]){
1866			// given a mid that hasn't been requested; therefore, defined through means other than injecting
1867			// consequent to a require() or define() application; examples include defining modules on-the-fly
1868			// due to some code path or including a module in a script element. In any case,
1869			// there is no callback waiting to finish processing and nothing to trigger the defQ and the
1870			// dependencies are never requested; therefore, do it here.
1871			injectDependencies(defineModule(targetModule, args[1], args[2]));
1872		}else if(!has("ie-event-behavior") || ! 1  || injectingCachedModule){
1873			// not IE path: anonymous module and therefore must have been injected; therefore, onLoad will fire immediately
1874			// after script finishes being evaluated and the defQ can be run from that callback to detect the module id
1875			defQ.push(args);
1876		}else{
1877			// IE path: possibly anonymous module and therefore injected; therefore, cannot depend on 1-to-1,
1878			// in-order exec of onLoad with script eval (since it's IE) and must manually detect here
1879			targetModule = targetModule || injectingModule;
1880			if(!targetModule){
1881				for(mid in waiting){
1882					module = modules[mid];
1883					if(module && module.node && module.node.readyState === 'interactive'){
1884						targetModule = module;
1885						break;
1886					}
1887				}
1888				if( 0  && !targetModule){
1889					for(var i = 0; i<combosPending.length; i++){
1890						targetModule = combosPending[i];
1891						if(targetModule.node && targetModule.node.readyState === 'interactive'){
1892							break;
1893						}
1894						targetModule= 0;
1895					}
1896				}
1897			}
1898			if( 0  && isArray(targetModule)){
1899				injectDependencies(defineModule(getModule(targetModule.shift()), args[1], args[2]));
1900				if(!targetModule.length){
1901					combosPending.splice(i, 1);
1902				}
1903			}else if(targetModule){
1904				consumePendingCacheInsert(targetModule);
1905				injectDependencies(defineModule(targetModule, args[1], args[2]));
1906			}else{
1907				signal(error, makeError("ieDefineFailed", args[0]));
1908			}
1909			checkComplete();
1910		}
1911	};
1912	def.amd = {
1913		vendor:"dojotoolkit.org"
1914	};
1915
1916	if( 0 ){
1917		req.def = def;
1918	}
1919
1920	// allow config to override default implementation of named functions; this is useful for
1921	// non-browser environments, e.g., overriding injectUrl, getText, log, etc. in node.js, Rhino, etc.
1922	// also useful for testing and monkey patching loader
1923	mix(mix(req, defaultConfig.loaderPatch), userConfig.loaderPatch);
1924
1925	// now that req is fully initialized and won't change, we can hook it up to the error signal
1926	on(error, function(arg){
1927		try{
1928			console.error(arg);
1929			if(arg instanceof Error){
1930				for(var p in arg){
1931					console.log(p + ":", arg[p]);
1932				}
1933				console.log(".");
1934			}
1935		}catch(e){}
1936	});
1937
1938	// always publish these
1939	mix(req, {
1940		uid:uid,
1941		cache:cache,
1942		packs:packs
1943	});
1944
1945
1946	if( 0 ){
1947		mix(req, {
1948			// these may be interesting to look at when debugging
1949			paths:paths,
1950			aliases:aliases,
1951			modules:modules,
1952			legacyMode:legacyMode,
1953			execQ:execQ,
1954			defQ:defQ,
1955			waiting:waiting,
1956
1957			// these are used for testing
1958			// TODO: move testing infrastructure to a different has feature
1959			packs:packs,
1960			mapProgs:mapProgs,
1961			pathsMapProg:pathsMapProg,
1962			listenerQueues:listenerQueues,
1963
1964			// these are used by the builder (at least)
1965			computeMapProg:computeMapProg,
1966			computeAliases:computeAliases,
1967			runMapProg:runMapProg,
1968			compactPath:compactPath,
1969			getModuleInfo:getModuleInfo_
1970		});
1971	}
1972
1973	// the loader can be defined exactly once; look for global define which is the symbol AMD loaders are
1974	// *required* to define (as opposed to require, which is optional)
1975	if(global.define){
1976		if( 0 ){
1977			signal(error, makeError("defineAlreadyDefined", 0));
1978		}
1979		return;
1980	}else{
1981		global.define = def;
1982		global.require = req;
1983		if( 0 ){
1984			require = req;
1985		}
1986	}
1987
1988	if( 0  && req.combo && req.combo.plugins){
1989		var plugins = req.combo.plugins,
1990			pluginName;
1991		for(pluginName in plugins){
1992			mix(mix(getModule(pluginName), plugins[pluginName]), {isCombo:1, executed:"executed", load:1});
1993		}
1994	}
1995
1996	if( 1 ){
1997		forEach(delayedModuleConfig, function(c){ config(c); });
1998		var bootDeps = dojoSniffConfig.deps ||	userConfig.deps || defaultConfig.deps,
1999			bootCallback = dojoSniffConfig.callback || userConfig.callback || defaultConfig.callback;
2000		req.boot = (bootDeps || bootCallback) ? [bootDeps || [], bootCallback] : 0;
2001	}
2002	if(! 1 ){
2003		!req.async && req(["dojo"]);
2004		req.boot && req.apply(null, req.boot);
2005	}
2006})
2007(this.dojoConfig || this.djConfig || this.require || {}, {
2008		async:1,
2009		hasCache:{
2010				'config-selectorEngine':"lite",
2011				'config-tlmSiblingOfDojo':1,
2012				'dojo-built':1,
2013				'dojo-loader':1,
2014				dom:1,
2015				'host-browser':1
2016		},
2017		packages:[
2018				{
2019					 location:".",
2020					 name:"dojo"
2021				},
2022				{
2023					 location:"../dijit",
2024					 name:"dijit"
2025				},
2026				{
2027					 location:"../dojox",
2028					 name:"dojox"
2029				},
2030				{
2031					 location:"../dpage",
2032					 name:"dpage"
2033				},
2034				{
2035					 location:"../footable",
2036					 name:"footable"
2037				},
2038				{
2039					 location:"../jquery",
2040					 main:"jquery",
2041					 name:"jquery"
2042				},
2043				{
2044					 location:"../jquery-ui",
2045					 name:"jquery-ui"
2046				},
2047				{
2048					 location:"../jQueryPrivate",
2049					 main:"jQueryPrivate",
2050					 name:"jQueryPrivate"
2051				},
2052				{
2053					 location:"../xstyle",
2054					 name:"xstyle"
2055				},
2056				{
2057					 location:"../put-selector",
2058					 main:"put",
2059					 name:"put-selector"
2060				}
2061		]
2062});require({cache:{
2063'dojo/main':function(){
2064define([
2065	"./_base/kernel",	// kernel.isAsync
2066	"./has",
2067	"require",
2068	"./sniff",
2069	"./_base/lang",
2070	"./_base/array",
2071	"./_base/config",
2072	"./ready",
2073	"./_base/declare",
2074	"./_base/connect",
2075	"./_base/Deferred",
2076	"./_base/json",
2077	"./_base/Color",
2078	"require",
2079	"./_base/browser",
2080	"require"
2081], function(kernel, has, require, sniff, lang, array, config, ready){
2082	// module:
2083	//		dojo/main
2084	// summary:
2085	//		This is the package main module for the dojo package; it loads dojo base appropriate for the execution environment.
2086
2087	// the preferred way to load the dojo firebug console is by setting  0  true in dojoConfig
2088	// the isDebug config switch is for backcompat and will work fine in sync loading mode; it works in
2089	// async mode too, but there's no guarantee when the module is loaded; therefore, if you need a firebug
2090	// console guaranteed at a particular spot in an app, either set config.has["dojo-firebug"] true before
2091	// loading dojo.js or explicitly include dojo/_firebug/firebug in a dependency list.
2092	if(config.isDebug){
2093		require(["./_firebug/firebug"]);
2094	}
2095
2096	// dojoConfig.require is deprecated; use the loader configuration property deps
2097	 0 && has.add("dojo-config-require", 1);
2098	if( 0 ){
2099		var deps= config.require;
2100		if(deps){
2101			// config.require may be dot notation
2102			deps= array.map(lang.isArray(deps) ? deps : [deps], function(item){ return item.replace(/\./g, "/"); });
2103			if(kernel.isAsync){
2104				require(deps);
2105			}else{
2106				// this is a bit janky; in 1.6- dojo is defined before these requires are applied; but in 1.7+
2107				// dojo isn't defined until returning from this module; this is only a problem in sync mode
2108				// since we're in sync mode, we know we've got our loader with its priority ready queue
2109				ready(1, function(){require(deps);});
2110			}
2111		}
2112	}
2113
2114	return kernel;
2115});
2116
2117},
2118'dojo/_base/kernel':function(){
2119define(["../has", "./config", "require", "module"], function(has, config, require, module){
2120	// module:
2121	//		dojo/_base/kernel
2122
2123	// This module is the foundational module of the dojo boot sequence; it defines the dojo object.
2124
2125	var
2126		// loop variables for this module
2127		i, p,
2128
2129		// create dojo, dijit, and dojox
2130		// FIXME: in 2.0 remove dijit, dojox being created by dojo
2131		global = (function () { return this; })(),
2132		dijit = {},
2133		dojox = {},
2134		dojo = {
2135			// summary:
2136			//		This module is the foundational module of the dojo boot sequence; it defines the dojo object.
2137
2138			// notice dojo takes ownership of the value of the config module
2139			config:config,
2140			global:global,
2141			dijit:dijit,
2142			dojox:dojox
2143		};
2144
2145
2146	// Configure the scope map. For a 100% AMD application, the scope map is not needed other than to provide
2147	// a _scopeName property for the dojo, dijit, and dojox root object so those packages can create
2148	// unique names in the global space.
2149	//
2150	// Built, legacy modules use the scope map to allow those modules to be expressed as if dojo, dijit, and dojox,
2151	// where global when in fact they are either global under different names or not global at all. In v1.6-, the
2152	// config variable "scopeMap" was used to map names as used within a module to global names. This has been
2153	// subsumed by the AMD map configuration variable which can relocate packages to different names. For backcompat,
2154	// only the "*" mapping is supported. See http://livedocs.dojotoolkit.org/developer/design/loader#legacy-cross-domain-mode for details.
2155	//
2156	// The following computations contort the packageMap for this dojo instance into a scopeMap.
2157	var scopeMap =
2158			// a map from a name used in a legacy module to the (global variable name, object addressed by that name)
2159			// always map dojo, dijit, and dojox
2160			{
2161				dojo:["dojo", dojo],
2162				dijit:["dijit", dijit],
2163				dojox:["dojox", dojox]
2164			},
2165
2166		packageMap =
2167			// the package map for this dojo instance; note, a foreign loader or no pacakgeMap results in the above default config
2168			(require.map && require.map[module.id.match(/[^\/]+/)[0]]),
2169
2170		item;
2171
2172
2173	// process all mapped top-level names for this instance of dojo
2174	for(p in packageMap){
2175		if(scopeMap[p]){
2176			// mapped dojo, dijit, or dojox
2177			scopeMap[p][0] = packageMap[p];
2178		}else{
2179			// some other top-level name
2180			scopeMap[p] = [packageMap[p], {}];
2181		}
2182	}
2183
2184	// publish those names to _scopeName and, optionally, the global namespace
2185	for(p in scopeMap){
2186		item = scopeMap[p];
2187		item[1]._scopeName = item[0];
2188		if(!config.noGlobals){
2189			global[item[0]] = item[1];
2190		}
2191	}
2192	dojo.scopeMap = scopeMap;
2193
2194	/*===== dojo.__docParserConfigureScopeMap(scopeMap); =====*/
2195
2196	// FIXME: dojo.baseUrl and dojo.config.baseUrl should be deprecated
2197	dojo.baseUrl = dojo.config.baseUrl = require.baseUrl;
2198	dojo.isAsync = ! 1  || require.async;
2199	dojo.locale = config.locale;
2200
2201	var rev = "$Rev: f4fef70 $".match(/[0-9a-f]{7,}/);
2202	dojo.version = {
2203		// summary:
2204		//		Version number of the Dojo Toolkit
2205		// description:
2206		//		Hash about the version, including
2207		//
2208		//		- major: Integer: Major version. If total version is "1.2.0beta1", will be 1
2209		//		- minor: Integer: Minor version. If total version is "1.2.0beta1", will be 2
2210		//		- patch: Integer: Patch version. If total version is "1.2.0beta1", will be 0
2211		//		- flag: String: Descriptor flag. If total version is "1.2.0beta1", will be "beta1"
2212		//		- revision: Number: The Git rev from which dojo was pulled
2213
2214		major: 1, minor: 10, patch: 4, flag: "",
2215		revision: rev ? rev[0] : NaN,
2216		toString: function(){
2217			var v = dojo.version;
2218			return v.major + "." + v.minor + "." + v.patch + v.flag + " (" + v.revision + ")";	// String
2219		}
2220	};
2221
2222	// If  1  is truthy, then as a dojo module is defined it should push it's definitions
2223	// into the dojo object, and conversely. In 2.0, it will likely be unusual to augment another object
2224	// as a result of defining a module. This has feature gives a way to force 2.0 behavior as the code
2225	// is migrated. Absent specific advice otherwise, set extend-dojo to truthy.
2226	 1 || has.add("extend-dojo", 1);
2227
2228
2229	(Function("d", "d.eval = function(){return d.global.eval ? d.global.eval(arguments[0]) : eval(arguments[0]);}"))(dojo);
2230	/*=====
2231	dojo.eval = function(scriptText){
2232		// summary:
2233		//		A legacy method created for use exclusively by internal Dojo methods. Do not use this method
2234		//		directly unless you understand its possibly-different implications on the platforms your are targeting.
2235		// description:
2236		//		Makes an attempt to evaluate scriptText in the global scope. The function works correctly for browsers
2237		//		that support indirect eval.
2238		//
2239		//		As usual, IE does not. On IE, the only way to implement global eval is to
2240		//		use execScript. Unfortunately, execScript does not return a value and breaks some current usages of dojo.eval.
2241		//		This implementation uses the technique of executing eval in the scope of a function that is a single scope
2242		//		frame below the global scope; thereby coming close to the global scope. Note carefully that
2243		//
2244		//		dojo.eval("var pi = 3.14;");
2245		//
2246		//		will define global pi in non-IE environments, but define pi only in a temporary local scope for IE. If you want
2247		//		to define a global variable using dojo.eval, write something like
2248		//
2249		//		dojo.eval("window.pi = 3.14;")
2250		// scriptText:
2251		//		The text to evaluation.
2252		// returns:
2253		//		The result of the evaluation. Often `undefined`
2254	};
2255	=====*/
2256
2257
2258	if( 0 ){
2259		dojo.exit = function(exitcode){
2260			quit(exitcode);
2261		};
2262	}else{
2263		dojo.exit = function(){
2264		};
2265	}
2266
2267	 1 || has.add("dojo-guarantee-console",
2268		// ensure that console.log, console.warn, etc. are defined
2269		1
2270	);
2271	if( 1 ){
2272		typeof console != "undefined" || (console = {});
2273		//	Be careful to leave 'log' always at the end
2274		var cn = [
2275			"assert", "count", "debug", "dir", "dirxml", "error", "group",
2276			"groupEnd", "info", "profile", "profileEnd", "time", "timeEnd",
2277			"trace", "warn", "log"
2278		];
2279		var tn;
2280		i = 0;
2281		while((tn = cn[i++])){
2282			if(!console[tn]){
2283				(function(){
2284					var tcn = tn + "";
2285					console[tcn] = ('log' in console) ? function(){
2286						var a = Array.prototype.slice.call(arguments);
2287						a.unshift(tcn + ":");
2288						console["log"](a.join(" "));
2289					} : function(){};
2290					console[tcn]._fake = true;
2291				})();
2292			}
2293		}
2294	}
2295
2296	 0 && has.add("dojo-debug-messages",
2297		// include dojo.deprecated/dojo.experimental implementations
2298		!!config.isDebug
2299	);
2300	dojo.deprecated = dojo.experimental =  function(){};
2301	if( 0 ){
2302		dojo.deprecated = function(/*String*/ behaviour, /*String?*/ extra, /*String?*/ removal){
2303			// summary:
2304			//		Log a debug message to indicate that a behavior has been
2305			//		deprecated.
2306			// behaviour: String
2307			//		The API or behavior being deprecated. Usually in the form
2308			//		of "myApp.someFunction()".
2309			// extra: String?
2310			//		Text to append to the message. Often provides advice on a
2311			//		new function or facility to achieve the same goal during
2312			//		the deprecation period.
2313			// removal: String?
2314			//		Text to indicate when in the future the behavior will be
2315			//		removed. Usually a version number.
2316			// example:
2317			//	| dojo.deprecated("myApp.getTemp()", "use myApp.getLocaleTemp() instead", "1.0");
2318
2319			var message = "DEPRECATED: " + behaviour;
2320			if(extra){ message += " " + extra; }
2321			if(removal){ message += " -- will be removed in version: " + removal; }
2322			console.warn(message);
2323		};
2324
2325		dojo.experimental = function(/* String */ moduleName, /* String? */ extra){
2326			// summary:
2327			//		Marks code as experimental.
2328			// description:
2329			//		This can be used to mark a function, file, or module as
2330			//		experimental.	 Experimental code is not ready to be used, and the
2331			//		APIs are subject to change without notice.	Experimental code may be
2332			//		completed deleted without going through the normal deprecation
2333			//		process.
2334			// moduleName: String
2335			//		The name of a module, or the name of a module file or a specific
2336			//		function
2337			// extra: String?
2338			//		some additional message for the user
2339			// example:
2340			//	| dojo.experimental("dojo.data.Result");
2341			// example:
2342			//	| dojo.experimental("dojo.weather.toKelvin()", "PENDING approval from NOAA");
2343
2344			var message = "EXPERIMENTAL: " + moduleName + " -- APIs subject to change without notice.";
2345			if(extra){ message += " " + extra; }
2346			console.warn(message);
2347		};
2348	}
2349
2350	 0 && has.add("dojo-modulePaths",
2351		// consume dojo.modulePaths processing
2352		1
2353	);
2354	if( 0 ){
2355		// notice that modulePaths won't be applied to any require's before the dojo/_base/kernel factory is run;
2356		// this is the v1.6- behavior.
2357		if(config.modulePaths){
2358			dojo.deprecated("dojo.modulePaths", "use paths configuration");
2359			var paths = {};
2360			for(p in config.modulePaths){
2361				paths[p.replace(/\./g, "/")] = config.modulePaths[p];
2362			}
2363			require({paths:paths});
2364		}
2365	}
2366
2367	 0 && has.add("dojo-moduleUrl",
2368		// include dojo.moduleUrl
2369		1
2370	);
2371	if( 0 ){
2372		dojo.moduleUrl = function(/*String*/module, /*String?*/url){
2373			// summary:
2374			//		Returns a URL relative to a module.
2375			// example:
2376			//	|	var pngPath = dojo.moduleUrl("acme","images/small.png");
2377			//	|	console.dir(pngPath); // list the object properties
2378			//	|	// create an image and set it's source to pngPath's value:
2379			//	|	var img = document.createElement("img");
2380			//	|	img.src = pngPath;
2381			//	|	// add our image to the document
2382			//	|	dojo.body().appendChild(img);
2383			// example:
2384			//		you may de-reference as far as you like down the package
2385			//		hierarchy.  This is sometimes handy to avoid lengthy relative
2386			//		urls or for building portable sub-packages. In this example,
2387			//		the `acme.widget` and `acme.util` directories may be located
2388			//		under different roots (see `dojo.registerModulePath`) but the
2389			//		the modules which reference them can be unaware of their
2390			//		relative locations on the filesystem:
2391			//	|	// somewhere in a configuration block
2392			//	|	dojo.registerModulePath("acme.widget", "../../acme/widget");
2393			//	|	dojo.registerModulePath("acme.util", "../../util");
2394			//	|
2395			//	|	// ...
2396			//	|
2397			//	|	// code in a module using acme resources
2398			//	|	var tmpltPath = dojo.moduleUrl("acme.widget","templates/template.html");
2399			//	|	var dataPath = dojo.moduleUrl("acme.util","resources/data.json");
2400
2401			dojo.deprecated("dojo.moduleUrl()", "use require.toUrl", "2.0");
2402
2403			// require.toUrl requires a filetype; therefore, just append the suffix "/*.*" to guarantee a filetype, then
2404			// remove the suffix from the result. This way clients can request a url w/out a filetype. This should be
2405			// rare, but it maintains backcompat for the v1.x line (note: dojo.moduleUrl will be removed in v2.0).
2406			// Notice * is an illegal filename so it won't conflict with any real path map that may exist the paths config.
2407			var result = null;
2408			if(module){
2409				result = require.toUrl(module.replace(/\./g, "/") + (url ? ("/" + url) : "") + "/*.*").replace(/\/\*\.\*/, "") + (url ? "" : "/");
2410			}
2411			return result;
2412		};
2413	}
2414
2415	dojo._hasResource = {}; // for backward compatibility with layers built with 1.6 tooling
2416
2417	return dojo;
2418});
2419
2420},
2421'dojo/has':function(){
2422define(["require", "module"], function(require, module){
2423	// module:
2424	//		dojo/has
2425	// summary:
2426	//		Defines the has.js API and several feature tests used by dojo.
2427	// description:
2428	//		This module defines the has API as described by the project has.js with the following additional features:
2429	//
2430	//		- the has test cache is exposed at has.cache.
2431	//		- the method has.add includes a forth parameter that controls whether or not existing tests are replaced
2432	//		- the loader's has cache may be optionally copied into this module's has cahce.
2433	//
2434	//		This module adopted from https://github.com/phiggins42/has.js; thanks has.js team!
2435
2436	// try to pull the has implementation from the loader; both the dojo loader and bdLoad provide one
2437	// if using a foreign loader, then the has cache may be initialized via the config object for this module
2438	// WARNING: if a foreign loader defines require.has to be something other than the has.js API, then this implementation fail
2439	var has = require.has || function(){};
2440	if(! 1 ){
2441		var
2442			isBrowser =
2443				// the most fundamental decision: are we in the browser?
2444				typeof window != "undefined" &&
2445				typeof location != "undefined" &&
2446				typeof document != "undefined" &&
2447				window.location == location && window.document == document,
2448
2449			// has API variables
2450			global = (function () { return this; })(),
2451			doc = isBrowser && document,
2452			element = doc && doc.createElement("DiV"),
2453			cache = (module.config && module.config()) || {};
2454
2455		has = function(name){
2456			// summary:
2457			//		Return the current value of the named feature.
2458			//
2459			// name: String|Integer
2460			//		The name (if a string) or identifier (if an integer) of the feature to test.
2461			//
2462			// description:
2463			//		Returns the value of the feature named by name. The feature must have been
2464			//		previously added to the cache by has.add.
2465
2466			return typeof cache[name] == "function" ? (cache[name] = cache[name](global, doc, element)) : cache[name]; // Boolean
2467		};
2468
2469		has.cache = cache;
2470
2471		has.add = function(name, test, now, force){
2472			// summary:
2473			//	 	Register a new feature test for some named feature.
2474			// name: String|Integer
2475			//	 	The name (if a string) or identifier (if an integer) of the feature to test.
2476			// test: Function
2477			//		 A test function to register. If a function, queued for testing until actually
2478			//		 needed. The test function should return a boolean indicating
2479			//	 	the presence of a feature or bug.
2480			// now: Boolean?
2481			//		 Optional. Omit if `test` is not a function. Provides a way to immediately
2482			//		 run the test and cache the result.
2483			// force: Boolean?
2484			//	 	Optional. If the test already exists and force is truthy, then the existing
2485			//	 	test will be replaced; otherwise, add does not replace an existing test (that
2486			//	 	is, by default, the first test advice wins).
2487			// example:
2488			//		A redundant test, testFn with immediate execution:
2489			//	|	has.add("javascript", function(){ return true; }, true);
2490			//
2491			// example:
2492			//		Again with the redundantness. You can do this in your tests, but we should
2493			//		not be doing this in any internal has.js tests
2494			//	|	has.add("javascript", true);
2495			//
2496			// example:
2497			//		Three things are passed to the testFunction. `global`, `document`, and a generic element
2498			//		from which to work your test should the need arise.
2499			//	|	has.add("bug-byid", function(g, d, el){
2500			//	|		// g	== global, typically window, yadda yadda
2501			//	|		// d	== document object
2502			//	|		// el == the generic element. a `has` element.
2503			//	|		return false; // fake test, byid-when-form-has-name-matching-an-id is slightly longer
2504			//	|	});
2505
2506			(typeof cache[name]=="undefined" || force) && (cache[name]= test);
2507			return now && has(name);
2508		};
2509
2510		// since we're operating under a loader that doesn't provide a has API, we must explicitly initialize
2511		// has as it would have otherwise been initialized by the dojo loader; use has.add to the builder
2512		// can optimize these away iff desired
2513		 1 || has.add("host-browser", isBrowser);
2514		 0 && has.add("host-node", (typeof process == "object" && process.versions && process.versions.node && process.versions.v8));
2515		 0 && has.add("host-rhino", (typeof load == "function" && (typeof Packages == "function" || typeof Packages == "object")));
2516		 1 || has.add("dom", isBrowser);
2517		 1 || has.add("dojo-dom-ready-api", 1);
2518		 1 || has.add("dojo-sniff", 1);
2519	}
2520
2521	if( 1 ){
2522		// Common application level tests
2523		has.add("dom-addeventlistener", !!document.addEventListener);
2524
2525		// Do the device and browser have touch capability?
2526		has.add("touch", "ontouchstart" in document
2527			|| ("onpointerdown" in document && navigator.maxTouchPoints > 0)
2528			|| window.navigator.msMaxTouchPoints);
2529
2530		// Touch events support
2531		has.add("touch-events", "ontouchstart" in document);
2532
2533		// Pointer Events support
2534		has.add("pointer-events", "onpointerdown" in document);
2535		has.add("MSPointer", "msMaxTouchPoints" in navigator); //IE10 (+IE11 preview)
2536
2537		// I don't know if any of these tests are really correct, just a rough guess
vendor: 4,863 bytes, lines 2538-2664
2538		has.add("device-width", screen.availWidth || innerWidth);
2539
2540		// Tests for DOMNode.attributes[] behavior:
2541		//	 - dom-attributes-explicit - attributes[] only lists explicitly user specified attributes
2542		//	 - dom-attributes-specified-flag (IE8) - need to check attr.specified flag to skip attributes user didn't specify
2543		//	 - Otherwise, in IE6-7. attributes[] will list hundreds of values, so need to do outerHTML to get attrs instead.
2544		var form = document.createElement("form");
2545		has.add("dom-attributes-explicit", form.attributes.length == 0); // W3C
2546		has.add("dom-attributes-specified-flag", form.attributes.length > 0 && form.attributes.length < 40);	// IE8
2547	}
2548
2549	has.clearElement = function(element){
2550		// summary:
2551		//	 Deletes the contents of the element passed to test functions.
2552		element.innerHTML= "";
2553		return element;
2554	};
2555
2556	has.normalize = function(id, toAbsMid){
2557		// summary:
2558		//	 Resolves id into a module id based on possibly-nested tenary expression that branches on has feature test value(s).
2559		//
2560		// toAbsMid: Function
2561		//	 Resolves a relative module id into an absolute module id
2562		var
2563			tokens = id.match(/[\?:]|[^:\?]*/g), i = 0,
2564			get = function(skip){
2565				var term = tokens[i++];
2566				if(term == ":"){
2567					// empty string module name, resolves to 0
2568					return 0;
2569				}else{
2570					// postfixed with a ? means it is a feature to branch on, the term is the name of the feature
2571					if(tokens[i++] == "?"){
2572						if(!skip && has(term)){
2573							// matched the feature, get the first value from the options
2574							return get();
2575						}else{
2576							// did not match, get the second value, passing over the first
2577							get(true);
2578							return get(skip);
2579						}
2580					}
2581					// a module
2582					return term || 0;
2583				}
2584			};
2585		id = get();
2586		return id && toAbsMid(id);
2587	};
2588
2589	has.load = function(id, parentRequire, loaded){
2590		// summary:
2591		//		Conditional loading of AMD modules based on a has feature test value.
2592		// id: String
2593		//		Gives the resolved module id to load.
2594		// parentRequire: Function
2595		//		The loader require function with respect to the module that contained the plugin resource in it's
2596		//		dependency list.
2597		// loaded: Function
2598		//	 Callback to loader that consumes result of plugin demand.
2599
2600		if(id){
2601			parentRequire([id], loaded);
2602		}else{
2603			loaded();
2604		}
2605	};
2606
2607	return has;
2608});
2609
2610},
2611'dojo/_base/config':function(){
2612define(["../has", "require"], function(has, require){
2613	// module:
2614	//		dojo/_base/config
2615
2616/*=====
2617return {
2618	// summary:
2619	//		This module defines the user configuration during bootstrap.
2620	// description:
2621	//		By defining user configuration as a module value, an entire configuration can be specified in a build,
2622	//		thereby eliminating the need for sniffing and or explicitly setting in the global variable dojoConfig.
2623	//		Also, when multiple instances of dojo exist in a single application, each will necessarily be located
2624	//		at an unique absolute module identifier as given by the package configuration. Implementing configuration
2625	//		as a module allows for specifying unique, per-instance configurations.
2626	// example:
2627	//		Create a second instance of dojo with a different, instance-unique configuration (assume the loader and
2628	//		dojo.js are already loaded).
2629	//		|	// specify a configuration that creates a new instance of dojo at the absolute module identifier "myDojo"
2630	//		|	require({
2631	//		|		packages:[{
2632	//		|			name:"myDojo",
2633	//		|			location:".", //assume baseUrl points to dojo.js
2634	//		|		}]
2635	//		|	});
2636	//		|
2637	//		|	// specify a configuration for the myDojo instance
2638	//		|	define("myDojo/config", {
2639	//		|		// normal configuration variables go here, e.g.,
2640	//		|		locale:"fr-ca"
2641	//		|	});
2642	//		|
2643	//		|	// load and use the new instance of dojo
2644	//		|	require(["myDojo"], function(dojo){
2645	//		|		// dojo is the new instance of dojo
2646	//		|		// use as required
2647	//		|	});
2648
2649	// isDebug: Boolean
2650	//		Defaults to `false`. If set to `true`, ensures that Dojo provides
2651	//		extended debugging feedback via Firebug. If Firebug is not available
2652	//		on your platform, setting `isDebug` to `true` will force Dojo to
2653	//		pull in (and display) the version of Firebug Lite which is
2654	//		integrated into the Dojo distribution, thereby always providing a
2655	//		debugging/logging console when `isDebug` is enabled. Note that
2656	//		Firebug's `console.*` methods are ALWAYS defined by Dojo. If
2657	//		`isDebug` is false and you are on a platform without Firebug, these
2658	//		methods will be defined as no-ops.
2659	isDebug: false,
2660
2661	// locale: String
2662	//		The locale to assume for loading localized resources in this page,
2663	//		specified according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt).
2664	//		Must be specified entirely in lowercase, e.g. `en-us` and `zh-cn`.
2665	//		See the documentation for `dojo.i18n` and `dojo.requireLocalization`
2666	//		for details on loading localized resources. If no locale is specified,
2667	//		Dojo assumes the locale of the user agent, according to `navigator.userLanguage`
2668	//		or `navigator.language` properties.
2669	locale: undefined,
2670
2671	// extraLocale: Array
2672	//		No default value. Specifies additional locales whose
2673	//		resources should also be loaded alongside the default locale when
2674	//		calls to `dojo.requireLocalization()` are processed.
2675	extraLocale: undefined,
2676
2677	// baseUrl: String
2678	//		The directory in which `dojo.js` is located. Under normal
2679	//		conditions, Dojo auto-detects the correct location from which it
2680	//		was loaded. You may need to manually configure `baseUrl` in cases
2681	//		where you have renamed `dojo.js` or in which `<base>` tags confuse
2682	//		some browsers (e.g. IE 6). The variable `dojo.baseUrl` is assigned
2683	//		either the value of `djConfig.baseUrl` if one is provided or the
2684	//		auto-detected root if not. Other modules are located relative to
2685	//		this path. The path should end in a slash.
2686	baseUrl: undefined,
2687
2688	// modulePaths: [deprecated] Object
2689	//		A map of module names to paths relative to `dojo.baseUrl`. The
2690	//		key/value pairs correspond directly to the arguments which
2691	//		`dojo.registerModulePath` accepts. Specifying
2692	//		`djConfig.modulePaths = { "foo": "../../bar" }` is the equivalent
2693	//		of calling `dojo.registerModulePath("foo", "../../bar");`. Multiple
2694	//		modules may be configured via `djConfig.modulePaths`.
2695	modulePaths: {},
2696
2697	// addOnLoad: Function|Array
2698	//		Adds a callback via dojo/ready. Useful when Dojo is added after
2699	//		the page loads and djConfig.afterOnLoad is true. Supports the same
2700	//		arguments as dojo/ready. When using a function reference, use
2701	//		`djConfig.addOnLoad = function(){};`. For object with function name use
2702	//		`djConfig.addOnLoad = [myObject, "functionName"];` and for object with
2703	//		function reference use
2704	//		`djConfig.addOnLoad = [myObject, function(){}];`
2705	addOnLoad: null,
2706
2707	// parseOnLoad: Boolean
2708	//		Run the parser after the page is loaded
2709	parseOnLoad: false,
2710
2711	// require: String[]
2712	//		An array of module names to be loaded immediately after dojo.js has been included
2713	//		in a page.
2714	require: [],
2715
2716	// defaultDuration: Number
2717	//		Default duration, in milliseconds, for wipe and fade animations within dijits.
2718	//		Assigned to dijit.defaultDuration.
2719	defaultDuration: 200,
2720
2721	// dojoBlankHtmlUrl: String
2722	//		Used by some modules to configure an empty iframe. Used by dojo/io/iframe and
2723	//		dojo/back, and dijit/popup support in IE where an iframe is needed to make sure native
2724	//		controls do not bleed through the popups. Normally this configuration variable
2725	//		does not need to be set, except when using cross-domain/CDN Dojo builds.
2726	//		Save dojo/resources/blank.html to your domain and set `djConfig.dojoBlankHtmlUrl`
2727	//		to the path on your domain your copy of blank.html.
2728	dojoBlankHtmlUrl: undefined,
2729
2730	// ioPublish: Boolean?
2731	//		Set this to true to enable publishing of topics for the different phases of
2732	//		IO operations. Publishing is done via dojo/topic.publish(). See dojo/main.__IoPublish for a list
2733	//		of topics that are published.
2734	ioPublish: false,
2735
2736	// useCustomLogger: Anything?
2737	//		If set to a value that evaluates to true such as a string or array and
2738	//		isDebug is true and Firebug is not available or running, then it bypasses
2739	//		the creation of Firebug Lite allowing you to define your own console object.
2740	useCustomLogger: undefined,
2741
2742	// transparentColor: Array
2743	//		Array containing the r, g, b components used as transparent color in dojo.Color;
2744	//		if undefined, [255,255,255] (white) will be used.
2745	transparentColor: undefined,
2746	
2747	// deps: Function|Array
2748	//		Defines dependencies to be used before the loader has been loaded.
2749	//		When provided, they cause the loader to execute require(deps, callback) 
2750	//		once it has finished loading. Should be used with callback.
2751	deps: undefined,
2752	
2753	// callback: Function|Array
2754	//		Defines a callback to be used when dependencies are defined before 
2755	//		the loader has been loaded. When provided, they cause the loader to 
2756	//		execute require(deps, callback) once it has finished loading. 
2757	//		Should be used with deps.
2758	callback: undefined,
2759	
2760	// deferredInstrumentation: Boolean
2761	//		Whether deferred instrumentation should be loaded or included
2762	//		in builds.
2763	deferredInstrumentation: true,
2764
2765	// useDeferredInstrumentation: Boolean|String
2766	//		Whether the deferred instrumentation should be used.
2767	//
2768	//		* `"report-rejections"`: report each rejection as it occurs.
2769	//		* `true` or `1` or `"report-unhandled-rejections"`: wait 1 second
2770	//			in an attempt to detect unhandled rejections.
2771	useDeferredInstrumentation: "report-unhandled-rejections"
2772};
2773=====*/
2774
2775	var result = {};
2776	if( 1 ){
2777		// must be the dojo loader; take a shallow copy of require.rawConfig
2778		var src = require.rawConfig, p;
2779		for(p in src){
2780			result[p] = src[p];
2781		}
2782	}else{
2783		var adviseHas = function(featureSet, prefix, booting){
2784			for(p in featureSet){
2785				p!="has" && has.add(prefix + p, featureSet[p], 0, booting);
2786			}
2787		};
2788		var global = (function () { return this; })();
2789		result =  1  ?
2790			// must be a built version of the dojo loader; all config stuffed in require.rawConfig
2791			require.rawConfig :
2792			// a foreign loader
2793			global.dojoConfig || global.djConfig || {};
2794		adviseHas(result, "config", 1);
2795		adviseHas(result.has, "", 1);
2796	}
2797
2798	if(!result.locale && typeof navigator != "undefined"){
2799		// Default locale for browsers.
2800		var language = (navigator.language || navigator.userLanguage);
2801		if(language){
2802			result.locale = language.toLowerCase();
2803		}
2804	}
2805
2806	return result;
2807});
2808
2809
2810},
2811'dojo/sniff':function(){
2812define(["./has"], function(has){
2813	// module:
2814	//		dojo/sniff
2815
2816	/*=====
2817	return function(){
2818		// summary:
2819		//		This module sets has() flags based on the current browser.
2820		//		It returns the has() function.
2821	};
2822	=====*/
2823
2824	if( 1 ){
2825		var n = navigator,
2826			dua = n.userAgent,
2827			dav = n.appVersion,
2828			tv = parseFloat(dav);
2829
2830		has.add("air", dua.indexOf("AdobeAIR") >= 0);
2831		has.add("msapp", parseFloat(dua.split("MSAppHost/")[1]) || undefined);
2832		has.add("khtml", dav.indexOf("Konqueror") >= 0 ? tv : undefined);
2833		has.add("webkit", parseFloat(dua.split("WebKit/")[1]) || undefined);
2834		has.add("chrome", parseFloat(dua.split("Chrome/")[1]) || undefined);
2835		has.add("safari", dav.indexOf("Safari")>=0 && !has("chrome") ? parseFloat(dav.split("Version/")[1]) : undefined);
2836		has.add("mac", dav.indexOf("Macintosh") >= 0);
2837		has.add("quirks", document.compatMode == "BackCompat");
2838		if(dua.match(/(iPhone|iPod|iPad)/)){
2839			var p = RegExp.$1.replace(/P/, "p");
2840			var v = dua.match(/OS ([\d_]+)/) ? RegExp.$1 : "1";
2841			var os = parseFloat(v.replace(/_/, ".").replace(/_/g, ""));
2842			has.add(p, os);		// "iphone", "ipad" or "ipod"
2843			has.add("ios", os);
2844		}
2845		has.add("android", parseFloat(dua.split("Android ")[1]) || undefined);
2846		has.add("bb", (dua.indexOf("BlackBerry") >= 0 || dua.indexOf("BB10") >= 0) && parseFloat(dua.split("Version/")[1]) || undefined);
2847		has.add("trident", parseFloat(dav.split("Trident/")[1]) || undefined);
2848
2849		has.add("svg", typeof SVGAngle !== "undefined");
2850
2851		if(!has("webkit")){
2852			// Opera
2853			if(dua.indexOf("Opera") >= 0){
2854				// see http://dev.opera.com/articles/view/opera-ua-string-changes and http://www.useragentstring.com/pages/Opera/
2855				// 9.8 has both styles; <9.8, 9.9 only old style
2856				has.add("opera", tv >= 9.8 ? parseFloat(dua.split("Version/")[1]) || tv : tv);
2857			}
2858
2859			// Mozilla and firefox
2860			if(dua.indexOf("Gecko") >= 0 && !has("khtml") && !has("webkit") && !has("trident")){
2861				has.add("mozilla", tv);
2862			}
2863			if(has("mozilla")){
2864				//We really need to get away from this. Consider a sane isGecko approach for the future.
2865				has.add("ff", parseFloat(dua.split("Firefox/")[1] || dua.split("Minefield/")[1]) || undefined);
2866			}
2867
2868			// IE
2869			if(document.all && !has("opera")){
2870				var isIE = parseFloat(dav.split("MSIE ")[1]) || undefined;
2871
2872				//In cases where the page has an HTTP header or META tag with
2873				//X-UA-Compatible, then it is in emulation mode.
2874				//Make sure isIE reflects the desired version.
2875				//document.documentMode of 5 means quirks mode.
2876				//Only switch the value if documentMode's major version
2877				//is different from isIE's major version.
2878				var mode = document.documentMode;
2879				if(mode && mode != 5 && Math.floor(isIE) != mode){
2880					isIE = mode;
2881				}
2882
2883				has.add("ie", isIE);
2884			}
2885
2886			// Wii
2887			has.add("wii", typeof opera != "undefined" && opera.wiiremote);
2888		}
2889	}
2890
2891	return has;
2892});
2893
2894},
2895'dojo/_base/lang':function(){
2896define(["./kernel", "../has", "../sniff"], function(dojo, has){
2897	// module:
2898	//		dojo/_base/lang
2899
2900	has.add("bug-for-in-skips-shadowed", function(){
2901		// if true, the for-in iterator skips object properties that exist in Object's prototype (IE 6 - ?)
2902		for(var i in {toString: 1}){
2903			return 0;
2904		}
2905		return 1;
2906	});
2907
2908	// Helper methods
2909	var _extraNames =
2910			has("bug-for-in-skips-shadowed") ?
2911				"hasOwnProperty.valueOf.isPrototypeOf.propertyIsEnumerable.toLocaleString.toString.constructor".split(".") : [],
2912
2913		_extraLen = _extraNames.length,
2914
2915		getProp = function(/*Array*/parts, /*Boolean*/create, /*Object*/context){
2916			if(!context){
2917				if(parts[0] && dojo.scopeMap[parts[0]]) {
2918					// Voodoo code from the old days where "dojo" or "dijit" maps to some special object
2919					// rather than just window.dojo
2920					context = dojo.scopeMap[parts.shift()][1];
2921				}else{
2922					context = dojo.global;
2923				}
2924			}
2925
2926			try{
2927				for(var i = 0; i < parts.length; i++){
2928					var p = parts[i];
2929					if(!(p in context)){
2930						if(create){
2931							context[p] = {};
2932						}else{
2933							return;		// return undefined
2934						}
2935					}
2936					context = context[p];
2937				}
2938				return context; // mixed
2939			}catch(e){
2940				// "p in context" throws an exception when context is a number, boolean, etc. rather than an object,
2941				// so in that corner case just return undefined (by having no return statement)
2942			}
2943		},
2944
2945		opts = Object.prototype.toString,
2946
2947		efficient = function(obj, offset, startWith){
2948			return (startWith||[]).concat(Array.prototype.slice.call(obj, offset||0));
2949		},
2950
2951		_pattern = /\{([^\}]+)\}/g;
2952
2953	// Module export
2954	var lang = {
2955		// summary:
2956		//		This module defines Javascript language extensions.
2957
2958		// _extraNames: String[]
2959		//		Lists property names that must be explicitly processed during for-in iteration
2960		//		in environments that have has("bug-for-in-skips-shadowed") true.
2961		_extraNames:_extraNames,
2962
2963		_mixin: function(dest, source, copyFunc){
2964			// summary:
2965			//		Copies/adds all properties of source to dest; returns dest.
2966			// dest: Object
2967			//		The object to which to copy/add all properties contained in source.
2968			// source: Object
2969			//		The object from which to draw all properties to copy into dest.
2970			// copyFunc: Function?
2971			//		The process used to copy/add a property in source; defaults to the Javascript assignment operator.
2972			// returns:
2973			//		dest, as modified
2974			// description:
2975			//		All properties, including functions (sometimes termed "methods"), excluding any non-standard extensions
2976			//		found in Object.prototype, are copied/added to dest. Copying/adding each particular property is
2977			//		delegated to copyFunc (if any); copyFunc defaults to the Javascript assignment operator if not provided.
2978			//		Notice that by default, _mixin executes a so-called "shallow copy" and aggregate types are copied/added by reference.
2979			var name, s, i, empty = {};
2980			for(name in source){
2981				// the (!(name in empty) || empty[name] !== s) condition avoids copying properties in "source"
2982				// inherited from Object.prototype.	 For example, if dest has a custom toString() method,
2983				// don't overwrite it with the toString() method that source inherited from Object.prototype
2984				s = source[name];
2985				if(!(name in dest) || (dest[name] !== s && (!(name in empty) || empty[name] !== s))){
2986					dest[name] = copyFunc ? copyFunc(s) : s;
2987				}
2988			}
2989
2990			if(has("bug-for-in-skips-shadowed")){
2991				if(source){
2992					for(i = 0; i < _extraLen; ++i){
2993						name = _extraNames[i];
2994						s = source[name];
2995						if(!(name in dest) || (dest[name] !== s && (!(name in empty) || empty[name] !== s))){
2996							dest[name] = copyFunc ? copyFunc(s) : s;
2997						}
2998					}
2999				}
3000			}
3001
3002			return dest; // Object
3003		},
3004
3005		mixin: function(dest, sources){
3006			// summary:
3007			//		Copies/adds all properties of one or more sources to dest; returns dest.
3008			// dest: Object
3009			//		The object to which to copy/add all properties contained in source. If dest is falsy, then
3010			//		a new object is manufactured before copying/adding properties begins.
3011			// sources: Object...
3012			//		One of more objects from which to draw all properties to copy into dest. sources are processed
3013			//		left-to-right and if more than one of these objects contain the same property name, the right-most
3014			//		value "wins".
3015			// returns: Object
3016			//		dest, as modified
3017			// description:
3018			//		All properties, including functions (sometimes termed "methods"), excluding any non-standard extensions
3019			//		found in Object.prototype, are copied/added from sources to dest. sources are processed left to right.
3020			//		The Javascript assignment operator is used to copy/add each property; therefore, by default, mixin
3021			//		executes a so-called "shallow copy" and aggregate types are copied/added by reference.
3022			// example:
3023			//		make a shallow copy of an object
3024			//	|	var copy = lang.mixin({}, source);
3025			// example:
3026			//		many class constructors often take an object which specifies
3027			//		values to be configured on the object. In this case, it is
3028			//		often simplest to call `lang.mixin` on the `this` object:
3029			//	|	declare("acme.Base", null, {
3030			//	|		constructor: function(properties){
3031			//	|			// property configuration:
3032			//	|			lang.mixin(this, properties);
3033			//	|
3034			//	|			console.log(this.quip);
3035			//	|			//	...
3036			//	|		},
3037			//	|		quip: "I wasn't born yesterday, you know - I've seen movies.",
3038			//	|		// ...
3039			//	|	});
3040			//	|
3041			//	|	// create an instance of the class and configure it
3042			//	|	var b = new acme.Base({quip: "That's what it does!" });
3043			// example:
3044			//		copy in properties from multiple objects
3045			//	|	var flattened = lang.mixin(
3046			//	|		{
3047			//	|			name: "Frylock",
3048			//	|			braces: true
3049			//	|		},
3050			//	|		{
3051			//	|			name: "Carl Brutanananadilewski"
3052			//	|		}
3053			//	|	);
3054			//	|
3055			//	|	// will print "Carl Brutanananadilewski"
3056			//	|	console.log(flattened.name);
3057			//	|	// will print "true"
3058			//	|	console.log(flattened.braces);
3059
3060			if(!dest){ dest = {}; }
3061			for(var i = 1, l = arguments.length; i < l; i++){
3062				lang._mixin(dest, arguments[i]);
3063			}
3064			return dest; // Object
3065		},
3066
3067		setObject: function(name, value, context){
3068			// summary:
3069			//		Set a property from a dot-separated string, such as "A.B.C"
3070			// description:
3071			//		Useful for longer api chains where you have to test each object in
3072			//		the chain, or when you have an object reference in string format.
3073			//		Objects are created as needed along `path`. Returns the passed
3074			//		value if setting is successful or `undefined` if not.
3075			// name: String
3076			//		Path to a property, in the form "A.B.C".
3077			// value: anything
3078			//		value or object to place at location given by name
3079			// context: Object?
3080			//		Optional. Object to use as root of path. Defaults to
3081			//		`dojo.global`.
3082			// example:
3083			//		set the value of `foo.bar.baz`, regardless of whether
3084			//		intermediate objects already exist:
3085			//	| lang.setObject("foo.bar.baz", value);
3086			// example:
3087			//		without `lang.setObject`, we often see code like this:
3088			//	| // ensure that intermediate objects are available
3089			//	| if(!obj["parent"]){ obj.parent = {}; }
3090			//	| if(!obj.parent["child"]){ obj.parent.child = {}; }
3091			//	| // now we can safely set the property
3092			//	| obj.parent.child.prop = "some value";
3093			//		whereas with `lang.setObject`, we can shorten that to:
3094			//	| lang.setObject("parent.child.prop", "some value", obj);
3095
3096			var parts = name.split("."), p = parts.pop(), obj = getProp(parts, true, context);
3097			return obj && p ? (obj[p] = value) : undefined; // Object
3098		},
3099
3100		getObject: function(name, create, context){
3101			// summary:
3102			//		Get a property from a dot-separated string, such as "A.B.C"
3103			// description:
3104			//		Useful for longer api chains where you have to test each object in
3105			//		the chain, or when you have an object reference in string format.
3106			// name: String
3107			//		Path to an property, in the form "A.B.C".
3108			// create: Boolean?
3109			//		Optional. Defaults to `false`. If `true`, Objects will be
3110			//		created at any point along the 'path' that is undefined.
3111			// context: Object?
3112			//		Optional. Object to use as root of path. Defaults to
3113			//		'dojo.global'. Null may be passed.
3114			return getProp(name ? name.split(".") : [], create, context); // Object
3115		},
3116
3117		exists: function(name, obj){
3118			// summary:
3119			//		determine if an object supports a given method
3120			// description:
3121			//		useful for longer api chains where you have to test each object in
3122			//		the chain. Useful for object and method detection.
3123			// name: String
3124			//		Path to an object, in the form "A.B.C".
3125			// obj: Object?
3126			//		Object to use as root of path. Defaults to
3127			//		'dojo.global'. Null may be passed.
3128			// example:
3129			//	| // define an object
3130			//	| var foo = {
3131			//	|		bar: { }
3132			//	| };
3133			//	|
3134			//	| // search the global scope
3135			//	| lang.exists("foo.bar"); // true
3136			//	| lang.exists("foo.bar.baz"); // false
3137			//	|
3138			//	| // search from a particular scope
3139			//	| lang.exists("bar", foo); // true
3140			//	| lang.exists("bar.baz", foo); // false
3141			return lang.getObject(name, false, obj) !== undefined; // Boolean
3142		},
3143
3144		// Crockford (ish) functions
3145
3146		isString: function(it){
3147			// summary:
3148			//		Return true if it is a String
3149			// it: anything
3150			//		Item to test.
3151			return (typeof it == "string" || it instanceof String); // Boolean
3152		},
3153
3154		isArray: function(it){
3155			// summary:
3156			//		Return true if it is an Array.
3157			//		Does not work on Arrays created in other windows.
3158			// it: anything
3159			//		Item to test.
3160			return it && (it instanceof Array || typeof it == "array"); // Boolean
3161		},
3162
3163		isFunction: function(it){
3164			// summary:
3165			//		Return true if it is a Function
3166			// it: anything
3167			//		Item to test.
3168			return opts.call(it) === "[object Function]";
3169		},
3170
3171		isObject: function(it){
3172			// summary:
3173			//		Returns true if it is a JavaScript object (or an Array, a Function
3174			//		or null)
3175			// it: anything
3176			//		Item to test.
3177			return it !== undefined &&
3178				(it === null || typeof it == "object" || lang.isArray(it) || lang.isFunction(it)); // Boolean
3179		},
3180
3181		isArrayLike: function(it){
3182			// summary:
3183			//		similar to isArray() but more permissive
3184			// it: anything
3185			//		Item to test.
3186			// returns:
3187			//		If it walks like a duck and quacks like a duck, return `true`
3188			// description:
3189			//		Doesn't strongly test for "arrayness".  Instead, settles for "isn't
3190			//		a string or number and has a length property". Arguments objects
3191			//		and DOM collections will return true when passed to
3192			//		isArrayLike(), but will return false when passed to
3193			//		isArray().
3194			return it && it !== undefined && // Boolean
3195				// keep out built-in constructors (Number, String, ...) which have length
3196				// properties
3197				!lang.isString(it) && !lang.isFunction(it) &&
3198				!(it.tagName && it.tagName.toLowerCase() == 'form') &&
3199				(lang.isArray(it) || isFinite(it.length));
3200		},
3201
3202		isAlien: function(it){
3203			// summary:
3204			//		Returns true if it is a built-in function or some other kind of
3205			//		oddball that *should* report as a function but doesn't
3206			return it && !lang.isFunction(it) && /\{\s*\[native code\]\s*\}/.test(String(it)); // Boolean
3207		},
3208
3209		extend: function(ctor, props){
3210			// summary:
3211			//		Adds all properties and methods of props to constructor's
3212			//		prototype, making them available to all instances created with
3213			//		constructor.
3214			// ctor: Object
3215			//		Target constructor to extend.
3216			// props: Object
3217			//		One or more objects to mix into ctor.prototype
3218			for(var i=1, l=arguments.length; i<l; i++){
3219				lang._mixin(ctor.prototype, arguments[i]);
3220			}
3221			return ctor; // Object
3222		},
3223
3224		_hitchArgs: function(scope, method){
3225			var pre = lang._toArray(arguments, 2);
3226			var named = lang.isString(method);
3227			return function(){
3228				// arrayify arguments
3229				var args = lang._toArray(arguments);
3230				// locate our method
3231				var f = named ? (scope||dojo.global)[method] : method;
3232				// invoke with collected args
3233				return f && f.apply(scope || this, pre.concat(args)); // mixed
3234			}; // Function
3235		},
3236
3237		hitch: function(scope, method){
3238			// summary:
3239			//		Returns a function that will only ever execute in the given scope.
3240			//		This allows for easy use of object member functions
3241			//		in callbacks and other places in which the "this" keyword may
3242			//		otherwise not reference the expected scope.
3243			//		Any number of default positional arguments may be passed as parameters
3244			//		beyond "method".
3245			//		Each of these values will be used to "placehold" (similar to curry)
3246			//		for the hitched function.
3247			// scope: Object
3248			//		The scope to use when method executes. If method is a string,
3249			//		scope is also the object containing method.
3250			// method: Function|String...
3251			//		A function to be hitched to scope, or the name of the method in
3252			//		scope to be hitched.
3253			// example:
3254			//	|	lang.hitch(foo, "bar")();
3255			//		runs foo.bar() in the scope of foo
3256			// example:
3257			//	|	lang.hitch(foo, myFunction);
3258			//		returns a function that runs myFunction in the scope of foo
3259			// example:
3260			//		Expansion on the default positional arguments passed along from
3261			//		hitch. Passed args are mixed first, additional args after.
3262			//	|	var foo = { bar: function(a, b, c){ console.log(a, b, c); } };
3263			//	|	var fn = lang.hitch(foo, "bar", 1, 2);
3264			//	|	fn(3); // logs "1, 2, 3"
3265			// example:
3266			//	|	var foo = { bar: 2 };
3267			//	|	lang.hitch(foo, function(){ this.bar = 10; })();
3268			//		execute an anonymous function in scope of foo
3269			if(arguments.length > 2){
3270				return lang._hitchArgs.apply(dojo, arguments); // Function
3271			}
3272			if(!method){
3273				method = scope;
3274				scope = null;
3275			}
3276			if(lang.isString(method)){
3277				scope = scope || dojo.global;
3278				if(!scope[method]){ throw(['lang.hitch: scope["', method, '"] is null (scope="', scope, '")'].join('')); }
3279				return function(){ return scope[method].apply(scope, arguments || []); }; // Function
3280			}
3281			return !scope ? method : function(){ return method.apply(scope, arguments || []); }; // Function
3282		},
3283
3284		delegate: (function(){
3285			// boodman/crockford delegation w/ cornford optimization
3286			function TMP(){}
3287			return function(obj, props){
3288				TMP.prototype = obj;
3289				var tmp = new TMP();
3290				TMP.prototype = null;
3291				if(props){
3292					lang._mixin(tmp, props);
3293				}
3294				return tmp; // Object
3295			};
3296		})(),
3297		/*=====
3298		delegate: function(obj, props){
3299			// summary:
3300			//		Returns a new object which "looks" to obj for properties which it
3301			//		does not have a value for. Optionally takes a bag of properties to
3302			//		seed the returned object with initially.
3303			// description:
3304			//		This is a small implementation of the Boodman/Crockford delegation
3305			//		pattern in JavaScript. An intermediate object constructor mediates
3306			//		the prototype chain for the returned object, using it to delegate
3307			//		down to obj for property lookup when object-local lookup fails.
3308			//		This can be thought of similarly to ES4's "wrap", save that it does
3309			//		not act on types but rather on pure objects.
3310			// obj: Object
3311			//		The object to delegate to for properties not found directly on the
3312			//		return object or in props.
3313			// props: Object...
3314			//		an object containing properties to assign to the returned object
3315			// returns:
3316			//		an Object of anonymous type
3317			// example:
3318			//	|	var foo = { bar: "baz" };
3319			//	|	var thinger = lang.delegate(foo, { thud: "xyzzy"});
3320			//	|	thinger.bar == "baz"; // delegated to foo
3321			//	|	foo.thud == undefined; // by definition
3322			//	|	thinger.thud == "xyzzy"; // mixed in from props
3323			//	|	foo.bar = "thonk";
3324			//	|	thinger.bar == "thonk"; // still delegated to foo's bar
3325		},
3326		=====*/
3327
3328		_toArray: has("ie") ?
3329			(function(){
3330				function slow(obj, offset, startWith){
3331					var arr = startWith||[];
3332					for(var x = offset || 0; x < obj.length; x++){
3333						arr.push(obj[x]);
3334					}
3335					return arr;
3336				}
3337				return function(obj){
3338					return ((obj.item) ? slow : efficient).apply(this, arguments);
3339				};
3340			})() : efficient,
3341		/*=====
3342		 _toArray: function(obj, offset, startWith){
3343			 // summary:
3344			 //		Converts an array-like object (i.e. arguments, DOMCollection) to an
3345			 //		array. Returns a new Array with the elements of obj.
3346			 // obj: Object
3347			 //		the object to "arrayify". We expect the object to have, at a
3348			 //		minimum, a length property which corresponds to integer-indexed
3349			 //		properties.
3350			 // offset: Number?
3351			 //		the location in obj to start iterating from. Defaults to 0.
3352			 //		Optional.
3353			 // startWith: Array?
3354			 //		An array to pack with the properties of obj. If provided,
3355			 //		properties in obj are appended at the end of startWith and
3356			 //		startWith is the returned array.
3357		 },
3358		 =====*/
3359
3360		partial: function(/*Function|String*/ method /*, ...*/){
3361			// summary:
3362			//		similar to hitch() except that the scope object is left to be
3363			//		whatever the execution context eventually becomes.
3364			// description:
3365			//		Calling lang.partial is the functional equivalent of calling:
3366			//		|	lang.hitch(null, funcName, ...);
3367			// method:
3368			//		The function to "wrap"
3369			var arr = [ null ];
3370			return lang.hitch.apply(dojo, arr.concat(lang._toArray(arguments))); // Function
3371		},
3372
3373		clone: function(/*anything*/ src){
3374			// summary:
3375			//		Clones objects (including DOM nodes) and all children.
3376			//		Warning: do not clone cyclic structures.
3377			// src:
3378			//		The object to clone
3379			if(!src || typeof src != "object" || lang.isFunction(src)){
3380				// null, undefined, any non-object, or function
3381				return src;	// anything
3382			}
3383			if(src.nodeType && "cloneNode" in src){
3384				// DOM Node
3385				return src.cloneNode(true); // Node
3386			}
3387			if(src instanceof Date){
3388				// Date
3389				return new Date(src.getTime());	// Date
3390			}
3391			if(src instanceof RegExp){
3392				// RegExp
3393				return new RegExp(src);   // RegExp
3394			}
3395			var r, i, l;
3396			if(lang.isArray(src)){
3397				// array
3398				r = [];
3399				for(i = 0, l = src.length; i < l; ++i){
3400					if(i in src){
3401						r.push(lang.clone(src[i]));
3402					}
3403				}
3404				// we don't clone functions for performance reasons
3405				//		}else if(d.isFunction(src)){
3406				//			// function
3407				//			r = function(){ return src.apply(this, arguments); };
3408			}else{
3409				// generic objects
3410				r = src.constructor ? new src.constructor() : {};
3411			}
3412			return lang._mixin(r, src, lang.clone);
3413		},
3414
3415
3416		trim: String.prototype.trim ?
3417			function(str){ return str.trim(); } :
3418			function(str){ return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); },
3419		/*=====
3420		 trim: function(str){
3421			 // summary:
3422			 //		Trims whitespace from both sides of the string
3423			 // str: String
3424			 //		String to be trimmed
3425			 // returns: String
3426			 //		Returns the trimmed string
3427			 // description:
3428			 //		This version of trim() was selected for inclusion into the base due
3429			 //		to its compact size and relatively good performance
3430			 //		(see [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript)
3431			 //		Uses String.prototype.trim instead, if available.
3432			 //		The fastest but longest version of this function is located at
3433			 //		lang.string.trim()
3434		 },
3435		 =====*/
3436
3437		replace: function(tmpl, map, pattern){
3438			// summary:
3439			//		Performs parameterized substitutions on a string. Throws an
3440			//		exception if any parameter is unmatched.
3441			// tmpl: String
3442			//		String to be used as a template.
3443			// map: Object|Function
3444			//		If an object, it is used as a dictionary to look up substitutions.
3445			//		If a function, it is called for every substitution with following parameters:
3446			//		a whole match, a name, an offset, and the whole template
3447			//		string (see https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/replace
3448			//		for more details).
3449			// pattern: RegEx?
3450			//		Optional regular expression objects that overrides the default pattern.
3451			//		Must be global and match one item. The default is: /\{([^\}]+)\}/g,
3452			//		which matches patterns like that: "{xxx}", where "xxx" is any sequence
3453			//		of characters, which doesn't include "}".
3454			// returns: String
3455			//		Returns the substituted string.
3456			// example:
3457			//	|	// uses a dictionary for substitutions:
3458			//	|	lang.replace("Hello, {name.first} {name.last} AKA {nick}!",
3459			//	|		{
3460			//	|			nick: "Bob",
3461			//	|			name: {
3462			//	|				first:	"Robert",
3463			//	|				middle: "X",
3464			//	|				last:		"Cringely"
3465			//	|			}
3466			//	|		});
3467			//	|	// returns: Hello, Robert Cringely AKA Bob!
3468			// example:
3469			//	|	// uses an array for substitutions:
3470			//	|	lang.replace("Hello, {0} {2}!",
3471			//	|		["Robert", "X", "Cringely"]);
3472			//	|	// returns: Hello, Robert Cringely!
3473			// example:
3474			//	|	// uses a function for substitutions:
3475			//	|	function sum(a){
3476			//	|		var t = 0;
3477			//	|		arrayforEach(a, function(x){ t += x; });
3478			//	|		return t;
3479			//	|	}
3480			//	|	lang.replace(
3481			//	|		"{count} payments averaging {avg} USD per payment.",
3482			//	|		lang.hitch(
3483			//	|			{ payments: [11, 16, 12] },
3484			//	|			function(_, key){
3485			//	|				switch(key){
3486			//	|					case "count": return this.payments.length;
3487			//	|					case "min":		return Math.min.apply(Math, this.payments);
3488			//	|					case "max":		return Math.max.apply(Math, this.payments);
3489			//	|					case "sum":		return sum(this.payments);
3490			//	|					case "avg":		return sum(this.payments) / this.payments.length;
3491			//	|				}
3492			//	|			}
3493			//	|		)
3494			//	|	);
3495			//	|	// prints: 3 payments averaging 13 USD per payment.
3496			// example:
3497			//	|	// uses an alternative PHP-like pattern for substitutions:
3498			//	|	lang.replace("Hello, ${0} ${2}!",
3499			//	|		["Robert", "X", "Cringely"], /\$\{([^\}]+)\}/g);
3500			//	|	// returns: Hello, Robert Cringely!
3501
3502			return tmpl.replace(pattern || _pattern, lang.isFunction(map) ?
3503				map : function(_, k){ return lang.getObject(k, false, map); });
3504		}
3505	};
3506
3507	 1  && lang.mixin(dojo, lang);
3508
3509	return lang;
3510});
3511
3512
3513},
3514'dojo/_base/array':function(){
3515define(["./kernel", "../has", "./lang"], function(dojo, has, lang){
3516	// module:
3517	//		dojo/_base/array
3518
3519	// our old simple function builder stuff
3520	var cache = {}, u;
3521
3522	function buildFn(fn){
3523		return cache[fn] = new Function("item", "index", "array", fn); // Function
3524	}
3525	// magic snippet: if(typeof fn == "string") fn = cache[fn] || buildFn(fn);
3526
3527	// every & some
3528
3529	function everyOrSome(some){
3530		var every = !some;
3531		return function(a, fn, o){
3532			var i = 0, l = a && a.length || 0, result;
3533			if(l && typeof a == "string") a = a.split("");
3534			if(typeof fn == "string") fn = cache[fn] || buildFn(fn);
3535			if(o){
3536				for(; i < l; ++i){
3537					result = !fn.call(o, a[i], i, a);
3538					if(some ^ result){
3539						return !result;
3540					}
3541				}
3542			}else{
3543				for(; i < l; ++i){
3544					result = !fn(a[i], i, a);
3545					if(some ^ result){
3546						return !result;
3547					}
3548				}
3549			}
3550			return every; // Boolean
3551		};
3552	}
3553
3554	// indexOf, lastIndexOf
3555
3556	function index(up){
3557		var delta = 1, lOver = 0, uOver = 0;
3558		if(!up){
3559			delta = lOver = uOver = -1;
3560		}
3561		return function(a, x, from, last){
3562			if(last && delta > 0){
3563				// TODO: why do we use a non-standard signature? why do we need "last"?
3564				return array.lastIndexOf(a, x, from);
3565			}
3566			var l = a && a.length || 0, end = up ? l + uOver : lOver, i;
3567			if(from === u){
3568				i = up ? lOver : l + uOver;
3569			}else{
3570				if(from < 0){
3571					i = l + from;
3572					if(i < 0){
3573						i = lOver;
3574					}
3575				}else{
3576					i = from >
3576= l ? l + uOver : from;
3577				}
3578			}
3579			if(l && typeof a == "string") a = a.split("");
3580			for(; i != end; i += delta){
3581				if(a[i] == x){
3582					return i; // Number
3583				}
3584			}
3585			return -1; // Number
3586		};
3587	}
3588
3589	var array = {
3590		// summary:
3591		//		The Javascript v1.6 array extensions.
3592
3593		every: everyOrSome(false),
3594		/*=====
3595		 every: function(arr, callback, thisObject){
3596			 // summary:
3597			 //		Determines whether or not every item in arr satisfies the
3598			 //		condition implemented by callback.
3599			 // arr: Array|String
3600			 //		the array to iterate on. If a string, operates on individual characters.
3601			 // callback: Function|String
3602			 //		a function is invoked with three arguments: item, index,
3603			 //		and array and returns true if the condition is met.
3604			 // thisObject: Object?
3605			 //		may be used to scope the call to callback
3606			 // returns: Boolean
3607			 // description:
3608			 //		This function corresponds to the JavaScript 1.6 Array.every() method, with one difference: when
3609			 //		run over sparse arrays, this implementation passes the "holes" in the sparse array to
3610			 //		the callback function with a value of undefined. JavaScript 1.6's every skips the holes in the sparse array.
3611			 //		For more details, see:
3612			 //		https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/every
3613			 // example:
3614			 //	|	// returns false
3615			 //	|	array.every([1, 2, 3, 4], function(item){ return item>1; });
3616			 // example:
3617			 //	|	// returns true
3618			 //	|	array.every([1, 2, 3, 4], function(item){ return item>0; });
3619		 },
3620		 =====*/
3621
3622		some: everyOrSome(true),
3623		/*=====
3624		some: function(arr, callback, thisObject){
3625			// summary:
3626			//		Determines whether or not any item in arr satisfies the
3627			//		condition implemented by callback.
3628			// arr: Array|String
3629			//		the array to iterate over. If a string, operates on individual characters.
3630			// callback: Function|String
3631			//		a function is invoked with three arguments: item, index,
3632			//		and array and returns true if the condition is met.
3633			// thisObject: Object?
3634			//		may be used to scope the call to callback
3635			// returns: Boolean
3636			// description:
3637			//		This function corresponds to the JavaScript 1.6 Array.some() method, with one difference: when
3638			//		run over sparse arrays, this implementation passes the "holes" in the sparse array to
3639			//		the callback function with a value of undefined. JavaScript 1.6's some skips the holes in the sparse array.
3640			//		For more details, see:
3641			//		https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/some
3642			// example:
3643			//	| // is true
3644			//	| array.some([1, 2, 3, 4], function(item){ return item>1; });
3645			// example:
3646			//	| // is false
3647			//	| array.some([1, 2, 3, 4], function(item){ return item<1; });
3648		},
3649		=====*/
3650
3651		indexOf: index(true),
3652		/*=====
3653		indexOf: function(arr, value, fromIndex, findLast){
3654			// summary:
3655			//		locates the first index of the provided value in the
3656			//		passed array. If the value is not found, -1 is returned.
3657			// description:
3658			//		This method corresponds to the JavaScript 1.6 Array.indexOf method, with two differences:
3659			//
3660			//		1. when run over sparse arrays, the Dojo function invokes the callback for every index
3661			//		   whereas JavaScript 1.6's indexOf skips the holes in the sparse array.
3662			//		2. uses equality (==) rather than strict equality (===)
3663			//
3664			//		For details on this method, see:
3665			//		https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/indexOf
3666			// arr: Array
3667			// value: Object
3668			// fromIndex: Integer?
3669			// findLast: Boolean?
3670			//		Makes indexOf() work like lastIndexOf().  Used internally; not meant for external usage.
3671			// returns: Number
3672		},
3673		=====*/
3674
3675		lastIndexOf: index(false),
3676		/*=====
3677		lastIndexOf: function(arr, value, fromIndex){
3678			// summary:
3679			//		locates the last index of the provided value in the passed
3680			//		array. If the value is not found, -1 is returned.
3681			// description:
3682		 	//		This method corresponds to the JavaScript 1.6 Array.lastIndexOf method, with two differences:
3683		 	//
3684		 	//		1. when run over sparse arrays, the Dojo function invokes the callback for every index
3685		 	//		   whereas JavaScript 1.6's lasIndexOf skips the holes in the sparse array.
3686		 	//		2. uses equality (==) rather than strict equality (===)
3687		 	//
3688		 	//		For details on this method, see:
3689		 	//		https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/lastIndexOf
3690			// arr: Array,
3691			// value: Object,
3692			// fromIndex: Integer?
3693			// returns: Number
3694		},
3695		=====*/
3696
3697		forEach: function(arr, callback, thisObject){
3698			// summary:
3699			//		for every item in arr, callback is invoked. Return values are ignored.
3700			//		If you want to break out of the loop, consider using array.every() or array.some().
3701			//		forEach does not allow breaking out of the loop over the items in arr.
3702			// arr:
3703			//		the array to iterate over. If a string, operates on individual characters.
3704			// callback:
3705			//		a function is invoked with three arguments: item, index, and array
3706			// thisObject:
3707			//		may be used to scope the call to callback
3708			// description:
3709			//		This function corresponds to the JavaScript 1.6 Array.forEach() method, with one difference: when
3710			//		run over sparse arrays, this implementation passes the "holes" in the sparse array to
3711			//		the callback function with a value of undefined. JavaScript 1.6's forEach skips the holes in the sparse array.
3712			//		For more details, see:
3713			//		https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/forEach
3714			// example:
3715			//	| // log out all members of the array:
3716			//	| array.forEach(
3717			//	|		[ "thinger", "blah", "howdy", 10 ],
3718			//	|		function(item){
3719			//	|			console.log(item);
3720			//	|		}
3721			//	| );
3722			// example:
3723			//	| // log out the members and their indexes
3724			//	| array.forEach(
3725			//	|		[ "thinger", "blah", "howdy", 10 ],
3726			//	|		function(item, idx, arr){
3727			//	|			console.log(item, "at index:", idx);
3728			//	|		}
3729			//	| );
3730			// example:
3731			//	| // use a scoped object member as the callback
3732			//	|
3733			//	| var obj = {
3734			//	|		prefix: "logged via obj.callback:",
3735			//	|		callback: function(item){
3736			//	|			console.log(this.prefix, item);
3737			//	|		}
3738			//	| };
3739			//	|
3740			//	| // specifying the scope function executes the callback in that scope
3741			//	| array.forEach(
3742			//	|		[ "thinger", "blah", "howdy", 10 ],
3743			//	|		obj.callback,
3744			//	|		obj
3745			//	| );
3746			//	|
3747			//	| // alternately, we can accomplish the same thing with lang.hitch()
3748			//	| array.forEach(
3749			//	|		[ "thinger", "blah", "howdy", 10 ],
3750			//	|		lang.hitch(obj, "callback")
3751			//	| );
3752			// arr: Array|String
3753			// callback: Function|String
3754			// thisObject: Object?
3755
3756			var i = 0, l = arr && arr.length || 0;
3757			if(l && typeof arr == "string") arr = arr.split("");
3758			if(typeof callback == "string") callback = cache[callback] || buildFn(callback);
3759			if(thisObject){
3760				for(; i < l; ++i){
3761					callback.call(thisObject, arr[i], i, arr);
3762				}
3763			}else{
3764				for(; i < l; ++i){
3765					callback(arr[i], i, arr);
3766				}
3767			}
3768		},
3769
3770		map: function(arr, callback, thisObject, Ctr){
3771			// summary:
3772			//		applies callback to each element of arr and returns
3773			//		an Array with the results
3774			// arr: Array|String
3775			//		the array to iterate on. If a string, operates on
3776			//		individual characters.
3777			// callback: Function|String
3778			//		a function is invoked with three arguments, (item, index,
3779			//		array),	 and returns a value
3780			// thisObject: Object?
3781			//		may be used to scope the call to callback
3782			// returns: Array
3783			// description:
3784			//		This function corresponds to the JavaScript 1.6 Array.map() method, with one difference: when
3785			//		run over sparse arrays, this implementation passes the "holes" in the sparse array to
3786			//		the callback function with a value of undefined. JavaScript 1.6's map skips the holes in the sparse array.
3787			//		For more details, see:
3788			//		https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
3789			// example:
3790			//	| // returns [2, 3, 4, 5]
3791			//	| array.map([1, 2, 3, 4], function(item){ return item+1 });
3792
3793			// TODO: why do we have a non-standard signature here? do we need "Ctr"?
3794			var i = 0, l = arr && arr.length || 0, out = new (Ctr || Array)(l);
3795			if(l && typeof arr == "string") arr = arr.split("");
3796			if(typeof callback == "string") callback = cache[callback] || buildFn(callback);
3797			if(thisObject){
3798				for(; i < l; ++i){
3799					out[i] = callback.call(thisObject, arr[i], i, arr);
3800				}
3801			}else{
3802				for(; i < l; ++i){
3803					out[i] = callback(arr[i], i, arr);
3804				}
3805			}
3806			return out; // Array
3807		},
3808
3809		filter: function(arr, callback, thisObject){
3810			// summary:
3811			//		Returns a new Array with those items from arr that match the
3812			//		condition implemented by callback.
3813			// arr: Array
3814			//		the array to iterate over.
3815			// callback: Function|String
3816			//		a function that is invoked with three arguments (item,
3817			//		index, array). The return of this function is expected to
3818			//		be a boolean which determines whether the passed-in item
3819			//		will be included in the returned array.
3820			// thisObject: Object?
3821			//		may be used to scope the call to callback
3822			// returns: Array
3823			// description:
3824			//		This function corresponds to the JavaScript 1.6 Array.filter() method, with one difference: when
3825			//		run over sparse arrays, this implementation passes the "holes" in the sparse array to
3826			//		the callback function with a value of undefined. JavaScript 1.6's filter skips the holes in the sparse array.
3827			//		For more details, see:
3828			//		https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
3829			// example:
3830			//	| // returns [2, 3, 4]
3831			//	| array.filter([1, 2, 3, 4], function(item){ return item>1; });
3832
3833			// TODO: do we need "Ctr" here like in map()?
3834			var i = 0, l = arr && arr.length || 0, out = [], value;
3835			if(l && typeof arr == "string") arr = arr.split("");
3836			if(typeof callback == "string") callback = cache[callback] || buildFn(callback);
3837			if(thisObject){
3838				for(; i < l; ++i){
3839					value = arr[i];
3840					if(callback.call(thisObject, value, i, arr)){
3841						out.push(value);
3842					}
3843				}
3844			}else{
3845				for(; i < l; ++i){
3846					value = arr[i];
3847					if(callback(value, i, arr)){
3848						out.push(value);
3849					}
3850				}
3851			}
3852			return out; // Array
3853		},
3854
3855		clearCache: function(){
3856			cache = {};
3857		}
3858	};
3859
3860
3861	 1  && lang.mixin(dojo, array);
3862
3863	return array;
3864});
3865
3866},
3867'dojo/ready':function(){
3868define(["./_base/kernel", "./has", "require", "./domReady", "./_base/lang"], function(dojo, has, require, domReady, lang){
3869	// module:
3870	//		dojo/ready
3871	// note:
3872	//		This module should be unnecessary in dojo 2.0
3873
3874	var
3875		// truthy if DOMContentLoaded or better (e.g., window.onload fired) has been achieved
3876		isDomReady = 0,
3877
3878		// The queue of functions waiting to execute as soon as dojo.ready conditions satisfied
3879		loadQ = [],
3880
3881		// prevent recursion in onLoad
3882		onLoadRecursiveGuard = 0,
3883
3884		handleDomReady = function(){
3885			isDomReady = 1;
3886			dojo._postLoad = dojo.config.afterOnLoad = true;
3887			onEvent();
3888		},
3889
3890		onEvent = function(){
3891			// Called when some state changes:
3892			//		- dom ready
3893			//		- dojo/domReady has finished processing everything in its queue
3894			//		- task added to loadQ
3895			//		- require() has finished loading all currently requested modules
3896			//
3897			// Run the functions queued with dojo.ready if appropriate.
3898
3899
3900			//guard against recursions into this function
3901			if(onLoadRecursiveGuard){
3902				return;
3903			}
3904			onLoadRecursiveGuard = 1;
3905
3906			// Run tasks in queue if require() is finished loading modules, the dom is ready, and there are no
3907			// pending tasks registered via domReady().
3908			// The last step is necessary so that a user defined dojo.ready() callback is delayed until after the
3909			// domReady() calls inside of dojo.	  Failure can be seen on dijit/tests/robot/Dialog_ally.html on IE8
3910			// because the dijit/focus.js domReady() callback doesn't execute until after the test starts running.
3911			while(isDomReady && (!domReady || domReady._Q.length == 0) && (require.idle ? require.idle() : true) && loadQ.length){
3912				var f = loadQ.shift();
3913				try{
3914					f();
3915				}catch(e){
3916					// force the dojo.js on("error") handler do display the message
3917					e.info = e.message;
3918					if(require.signal){
3919						require.signal("error", e);
3920					}else{
3921						throw e;
3922					}
3923				}
3924			}
3925
3926			onLoadRecursiveGuard = 0;
3927		};
3928
3929	// Check if we should run the next queue operation whenever require() finishes loading modules or domReady
3930	// finishes processing it's queue.
3931	require.on && require.on("idle", onEvent);
3932	if(domReady){
3933		domReady._onQEmpty = onEvent;
3934	}
3935
3936	var ready = dojo.ready = dojo.addOnLoad = function(priority, context, callback){
3937		// summary:
3938		//		Add a function to execute on DOM content loaded and all requested modules have arrived and been evaluated.
3939		//		In most cases, the `domReady` plug-in should suffice and this method should not be needed.
3940		//
3941		//		When called in a non-browser environment, just checks that all requested modules have arrived and been
3942		//		evaluated.
3943		// priority: Integer?
3944		//		The order in which to exec this callback relative to other callbacks, defaults to 1000
3945		// context: Object?|Function
3946		//		The context in which to run execute callback, or a callback if not using context
3947		// callback: Function?
3948		//		The function to execute.
3949		//
3950		// example:
3951		//	Simple DOM and Modules ready syntax
3952		//	|	require(["dojo/ready"], function(ready){
3953		//	|		ready(function(){ alert("Dom ready!"); });
3954		//	|	});
3955		//
3956		// example:
3957		//	Using a priority
3958		//	|	require(["dojo/ready"], function(ready){
3959		//	|		ready(2, function(){ alert("low priority ready!"); })
3960		//	|	});
3961		//
3962		// example:
3963		//	Using context
3964		//	|	require(["dojo/ready"], function(ready){
3965		//	|		ready(foo, function(){
3966		//	|			// in here, this == foo
3967		//	|		});
3968		//	|	});
3969		//
3970		// example:
3971		//	Using dojo/hitch style args:
3972		//	|	require(["dojo/ready"], function(ready){
3973		//	|		var foo = { dojoReady: function(){ console.warn(this, "dojo dom and modules ready."); } };
3974		//	|		ready(foo, "dojoReady");
3975		//	|	});
3976
3977		var hitchArgs = lang._toArray(arguments);
3978		if(typeof priority != "number"){
3979			callback = context;
3980			context = priority;
3981			priority = 1000;
3982		}else{
3983			hitchArgs.shift();
3984		}
3985		callback = callback ?
3986			lang.hitch.apply(dojo, hitchArgs) :
3987			function(){
3988				context();
3989			};
3990		callback.priority = priority;
3991		for(var i = 0; i < loadQ.length && priority >= loadQ[i].priority; i++){}
3992		loadQ.splice(i, 0, callback);
3993		onEvent();
3994	};
3995
3996	 1 || has.add("dojo-config-addOnLoad", 1);
3997	if( 1 ){
3998		var dca = dojo.config.addOnLoad;
3999		if(dca){
4000			ready[(lang.isArray(dca) ? "apply" : "call")](dojo, dca);
4001		}
4002	}
4003
4004	if( 0  && dojo.config.parseOnLoad && !dojo.isAsync){
4005		ready(99, function(){
4006			if(!dojo.parser){
4007				dojo.deprecated("Add explicit require(['dojo/parser']);", "", "2.0");
4008				require(["dojo/parser"]);
4009			}
4010		});
4011	}
4012
4013	if(domReady){
4014		domReady(handleDomReady);
4015	}else{
4016		handleDomReady();
4017	}
4018
4019	return ready;
4020});
4021
4022},
4023'dojo/domReady':function(){
4024define(['./has'], function(has){
4025	var global = (function () { return this; })(),
4026		doc = document,
4027		readyStates = { 'loaded': 1, 'complete': 1 },
4028		fixReadyState = typeof doc.readyState != "string",
4029		ready = !!readyStates[doc.readyState],
4030		readyQ = [],
4031		recursiveGuard;
4032
4033	function domReady(callback){
4034		// summary:
4035		//		Plugin to delay require()/define() callback from firing until the DOM has finished loading.
4036		readyQ.push(callback);
4037		if(ready){ processQ(); }
4038	}
4039	domReady.load = function(id, req, load){
4040		domReady(load);
4041	};
4042
4043	// Export queue so that ready() can check if it's empty or not.
4044	domReady._Q = readyQ;
4045	domReady._onQEmpty = function(){
4046		// summary:
4047		//		Private method overridden by dojo/ready, to notify when everything in the
4048		//		domReady queue has been processed.  Do not use directly.
4049		//		Will be removed in 2.0, along with domReady._Q.
4050	};
4051
4052	// For FF <= 3.5
4053	if(fixReadyState){ doc.readyState = "loading"; }
4054
4055	function processQ(){
4056		// Calls all functions in the queue in order, unless processQ() is already running, in which case just return
4057
4058		if(recursiveGuard){ return; }
4059		recursiveGuard = true;
4060
4061		while(readyQ.length){
4062			try{
4063				(readyQ.shift())(doc);
4064			}catch(err){
4065				console.error(err, "in domReady callback", err.stack);
4066			}
4067		}
4068
4069		recursiveGuard = false;
4070
4071		// Notification for dojo/ready.  Remove for 2.0.
4072		// Note that this could add more tasks to the ready queue.
4073		domReady._onQEmpty();
4074	}
4075
4076	if(!ready){
4077		var tests = [],
4078			detectReady = function(evt){
4079				evt = evt || global.event;
4080				if(ready || (evt.type == "readystatechange" && !readyStates[doc.readyState])){ return; }
4081
4082				// For FF <= 3.5
4083				if(fixReadyState){ doc.readyState = "complete"; }
4084
4085				ready = 1;
4086				processQ();
4087			},
4088			on = function(node, event){
4089				node.addEventListener(event, detectReady, false);
4090				readyQ.push(function(){ node.removeEventListener(event, detectReady, false); });
4091			};
4092
4093		if(!has("dom-addeventlistener")){
4094			on = function(node, event){
4095				event = "on" + event;
4096				node.attachEvent(event, detectReady);
4097				readyQ.push(function(){ node.detachEvent(event, detectReady); });
4098			};
4099
4100			var div = doc.createElement("div");
4101			try{
4102				if(div.doScroll && global.frameElement === null){
4103					// the doScroll test is only useful if we're in the top-most frame
4104					tests.push(function(){
4105						// Derived with permission from Diego Perini's IEContentLoaded
4106						// http://javascript.nwbox.com/IEContentLoaded/
4107						try{
4108							div.doScroll("left");
4109							return 1;
4110						}catch(e){}
4111					});
4112				}
4113			}catch(e){}
4114		}
4115
4116		on(doc, "DOMContentLoaded");
4117		on(global, "load");
4118
4119		if("onreadystatechange" in doc){
4120			on(doc, "readystatechange");
4121		}else if(!fixReadyState){
4122			// if the ready state property exists and there's
4123			// no readystatechange event, poll for the state
4124			// to change
4125			tests.push(function(){
4126				return readyStates[doc.readyState];
4127			});
4128		}
4129
4130		if(tests.length){
4131			var poller = function(){
4132				if(ready){ return; }
4133				var i = tests.length;
4134				while(i--){
4135					if(tests[i]()){
4136						detectReady("poller");
4137						return;
4138					}
4139				}
4140				setTimeout(poller, 30);
4141			};
4142			poller();
4143		}
4144	}
4145
4146	return domReady;
4147});
4148
4149},
4150'dojo/_base/declare':function(){
4151define(["./kernel", "../has", "./lang"], function(dojo, has, lang){
4152	// module:
4153	//		dojo/_base/declare
4154
4155	var mix = lang.mixin, op = Object.prototype, opts = op.toString,
4156		xtor = new Function, counter = 0, cname = "constructor";
4157
4158	function err(msg, cls){ throw new Error("declare" + (cls ? " " + cls : "") + ": " + msg); }
4159
4160	// C3 Method Resolution Order (see http://www.python.org/download/releases/2.3/mro/)
4161	function c3mro(bases, className){
4162		var result = [], roots = [{cls: 0, refs: []}], nameMap = {}, clsCount = 1,
4163			l = bases.length, i = 0, j, lin, base, top, proto, rec, name, refs;
4164
4165		// build a list of bases naming them if needed
4166		for(; i < l; ++i){
4167			base = bases[i];
4168			if(!base){
4169				err("mixin #" + i + " is unknown. Did you use dojo.require to pull it in?", className);
4170			}else if(opts.call(base) != "[object Function]"){
4171				err("mixin #" + i + " is not a callable constructor.", className);
4172			}
4173			lin = base._meta ? base._meta.bases : [base];
4174			top = 0;
4175			// add bases to the name map
4176			for(j = lin.length - 1; j >= 0; --j){
4177				proto = lin[j].prototype;
4178				if(!proto.hasOwnProperty("declaredClass")){
4179					proto.declaredClass = "uniqName_" + (counter++);
4180				}
4181				name = proto.declaredClass;
4182				if(!nameMap.hasOwnProperty(name)){
4183					nameMap[name] = {count: 0, refs: [], cls: lin[j]};
4184					++clsCount;
4185				}
4186				rec = nameMap[name];
4187				if(top && top !== rec){
4188					rec.refs.push(top);
4189					++top.count;
4190				}
4191				top = rec;
4192			}
4193			++top.count;
4194			roots[0].refs.push(top);
4195		}
4196
4197		// remove classes without external references recursively
4198		while(roots.length){
4199			top = roots.pop();
4200			result.push(top.cls);
4201			--clsCount;
4202			// optimization: follow a single-linked chain
4203			while(refs = top.refs, refs.length == 1){
4204				top = refs[0];
4205				if(!top || --top.count){
4206					// branch or end of chain => do not end to roots
4207					top = 0;
4208					break;
4209				}
4210				result.push(top.cls);
4211				--clsCount;
4212			}
4213			if(top){
4214				// branch
4215				for(i = 0, l = refs.length; i < l; ++i){
4216					top = refs[i];
4217					if(!--top.count){
4218						roots.push(top);
4219					}
4220				}
4221			}
4222		}
4223		if(clsCount){
4224			err("can't build consistent linearization", className);
4225		}
4226
4227		// calculate the superclass offset
4228		base = bases[0];
4229		result[0] = base ?
4230			base._meta && base === result[result.length - base._meta.bases.length] ?
4231				base._meta.bases.length : 1 : 0;
4232
4233		return result;
4234	}
4235
4236	function inherited(args, a, f){
4237		var name, chains, bases, caller, meta, base, proto, opf, pos,
4238			cache = this._inherited = this._inherited || {};
4239
4240		// crack arguments
4241		if(typeof args == "string"){
4242			name = args;
4243			args = a;
4244			a = f;
4245		}
4246		f = 0;
4247
4248		caller = args.callee;
4249		name = name || caller.nom;
4250		if(!name){
4251			err("can't deduce a name to call inherited()", this.declaredClass);
4252		}
4253
4254		meta = this.constructor._meta;
4255		bases = meta.bases;
4256
4257		pos = cache.p;
4258		if(name != cname){
4259			// method
4260			if(cache.c !== caller){
4261				// cache bust
4262				pos = 0;
4263				base = bases[0];
4264				meta = base._meta;
4265				if(meta.hidden[name] !== caller){
4266					// error detection
4267					chains = meta.chains;
4268					if(chains && typeof chains[name] == "string"){
4269						err("calling chained method with inherited: " + name, this.declaredClass);
4270					}
4271					// find caller
4272					do{
4273						meta = base._meta;
4274						proto = base.prototype;
4275						if(meta && (proto[name] === caller && proto.hasOwnProperty(name) || meta.hidden[name] === caller)){
4276							break;
4277						}
4278					}while(base = bases[++pos]); // intentional assignment
4279					pos = base ? pos : -1;
4280				}
4281			}
4282			// find next
4283			base = bases[++pos];
4284			if(base){
4285				proto = base.prototype;
4286				if(base._meta && proto.hasOwnProperty(name)){
4287					f = proto[name];
4288				}else{
4289					opf = op[name];
4290					do{
4291						proto = base.prototype;
4292						f = proto[name];
4293						if(f && (base._meta ? proto.hasOwnProperty(name) : f !== opf)){
4294							break;
4295						}
4296					}while(base = bases[++pos]); // intentional assignment
4297				}
4298			}
4299			f = base && f || op[name];
4300		}else{
4301			// constructor
4302			if(cache.c !== caller){
4303				// cache bust
4304				pos = 0;
4305				meta = bases[0]._meta;
4306				if(meta && meta.ctor !== caller){
4307					// error detection
4308					chains = meta.chains;
4309					if(!chains || chains.constructor !== "manual"){
4310						err("calling chained constructor with inherited", this.declaredClass);
4311					}
4312					// find caller
4313					while(base = bases[++pos]){ // intentional assignment
4314						meta = base._meta;
4315						if(meta && meta.ctor === caller){
4316							break;
4317						}
4318					}
4319					pos = base ? pos : -1;
4320				}
4321			}
4322			// find next
4323			while(base = bases[++pos]){	// intentional assignment
4324				meta = base._meta;
4325				f = meta ? meta.ctor : base;
4326				if(f){
4327					break;
4328				}
4329			}
4330			f = base && f;
4331		}
4332
4333		// cache the found super method
4334		cache.c = f;
4335		cache.p = pos;
4336
4337		// now we have the result
4338		if(f){
4339			return a === true ? f : f.apply(this, a || args);
4340		}
4341		// intentionally no return if a super method was not found
4342	}
4343
4344	function getInherited(name, args){
4345		if(typeof name == "string"){
4346			return this.__inherited(name, args, true);
4347		}
4348		return this.__inherited(name, true);
4349	}
4350
4351	function inherited__debug(args, a1, a2){
4352		var f = this.getInherited(args, a1);
4353		if(f){ return f.apply(this, a2 || a1 || args); }
4354		// intentionally no return if a super method was not found
4355	}
4356
4357	var inheritedImpl = dojo.config.isDebug ? inherited__debug : inherited;
4358
4359	// emulation of "instanceof"
4360	function isInstanceOf(cls){
4361		var bases = this.constructor._meta.bases;
4362		for(var i = 0, l = bases.length; i < l; ++i){
4363			if(bases[i] === cls){
4364				return true;
4365			}
4366		}
4367		return this instanceof cls;
4368	}
4369
4370	function mixOwn(target, source){
4371		// add props adding metadata for incoming functions skipping a constructor
4372		for(var name in source){
4373			if(name != cname && source.hasOwnProperty(name)){
4374				target[name] = source[name];
4375			}
4376		}
4377		if(has("bug-for-in-skips-shadowed")){
4378			for(var extraNames= lang._extraNames, i= extraNames.length; i;){
4379				name = extraNames[--i];
4380				if(name != cname && source.hasOwnProperty(name)){
4381					  target[name] = source[name];
4382				}
4383			}
4384		}
4385	}
4386
4387	// implementation of safe mixin function
4388	function safeMixin(target, source){
4389		// summary:
4390		//		Mix in properties skipping a constructor and decorating functions
4391		//		like it is done by declare().
4392		// target: Object
4393		//		Target object to accept new properties.
4394		// source: Object
4395		//		Source object for new properties.
4396		// description:
4397		//		This function is used to mix in properties like lang.mixin does,
4398		//		but it skips a constructor property and decorates functions like
4399		//		declare() does.
4400		//
4401		//		It is meant to be used with classes and objects produced with
4402		//		declare. Functions mixed in with dojo.safeMixin can use
4403		//		this.inherited() like normal methods.
4404		//
4405		//		This function is used to implement extend() method of a constructor
4406		//		produced with declare().
4407		//
4408		// example:
4409		//	|	var A = declare(null, {
4410		//	|		m1: function(){
4411		//	|			console.log("A.m1");
4412		//	|		},
4413		//	|		m2: function(){
4414		//	|			console.log("A.m2");
4415		//	|		}
4416		//	|	});
4417		//	|	var B = declare(A, {
4418		//	|		m1: function(){
4419		//	|			this.inherited(arguments);
4420		//	|			console.log("B.m1");
4421		//	|		}
4422		//	|	});
4423		//	|	B.extend({
4424		//	|		m2: function(){
4425		//	|			this.inherited(arguments);
4426		//	|			console.log("B.m2");
4427		//	|		}
4428		//	|	});
4429		//	|	var x = new B();
4430		//	|	dojo.safeMixin(x, {
4431		//	|		m1: function(){
4432		//	|			this.inherited(arguments);
4433		//	|			console.log("X.m1");
4434		//	|		},
4435		//	|		m2: function(){
4436		//	|			this.inherited(arguments);
4437		//	|			console.log("X.m2");
4438		//	|		}
4439		//	|	});
4440		//	|	x.m2();
4441		//	|	// prints:
4442		//	|	// A.m1
4443		//	|	// B.m1
4444		//	|	// X.m1
4445
4446		var name, t;
4447		// add props adding metadata for incoming functions skipping a constructor
4448		for(name in source){
4449			t = source[name];
4450			if((t !== op[name] || !(name in op)) && name != cname){
4451				if(opts.call(t) == "[object Function]"){
4452					// non-trivial function method => attach its name
4453					t.nom = name;
4454				}
4455				target[name] = t;
4456			}
4457		}
4458		if(has("bug-for-in-skips-shadowed")){
4459			for(var extraNames= lang._extraNames, i= extraNames.length; i;){
4460				name = extraNames[--i];
4461				t = source[name];
4462				if((t !== op[name] || !(name in op)) && name != cname){
4463					if(opts.call(t) == "[object Function]"){
4464						// non-trivial function method => attach its name
4465						  t.nom = name;
4466					}
4467					target[name] = t;
4468				}
4469			}
4470		}
4471		return target;
4472	}
4473
4474	function extend(source){
4475		declare.safeMixin(this.prototype, source);
4476		return this;
4477	}
4478
4479    function createSubclass(mixins, props){
4480        // crack parameters
4481        if(!(mixins instanceof Array || typeof mixins == 'function')){
4482            props = mixins;
4483            mixins = undefined;
4484        }
4485
4486        props = props || {};
4487        mixins = mixins || [];
4488
4489        return declare([this].concat(mixins), props);
4490    }
4491
4492	// chained constructor compatible with the legacy declare()
4493	function chainedConstructor(bases, ctorSpecial){
4494		return function(){
4495			var a = arguments, args = a, a0 = a[0], f, i, m,
4496				l = bases.length, preArgs;
4497
4498			if(!(this instanceof a.callee)){
4499				// not called via new, so force it
4500				return applyNew(a);
4501			}
4502
4503			//this._inherited = {};
4504			// perform the shaman's rituals of the original declare()
4505			// 1) call two types of the preamble
4506			if(ctorSpecial && (a0 && a0.preamble || this.preamble)){
4507				// full blown ritual
4508				preArgs = new Array(bases.length);
4509				// prepare parameters
4510				preArgs[0] = a;
4511				for(i = 0;;){
4512					// process the preamble of the 1st argument
4513					a0 = a[0];
4514					if(a0){
4515						f = a0.preamble;
4516						if(f){
4517							a = f.apply(this, a) || a;
4518						}
4519					}
4520					// process the preamble of this class
4521					f = bases[i].prototype;
4522					f = f.hasOwnProperty("preamble") && f.preamble;
4523					if(f){
4524						a = f.apply(this, a) || a;
4525					}
4526					// one peculiarity of the preamble:
4527					// it is called if it is not needed,
4528					// e.g., there is no constructor to call
4529					// let's watch for the last constructor
4530					// (see ticket #9795)
4531					if(++i == l){
4532						break;
4533					}
4534					preArgs[i] = a;
4535				}
4536			}
4537			// 2) call all non-trivial constructors using prepared arguments
4538			for(i = l - 1; i >= 0; --i){
4539				f = bases[i];
4540				m = f._meta;
4541				f = m ? m.ctor : f;
4542				if(f){
4543					f.apply(this, preArgs ? preArgs[i] : a);
4544				}
4545			}
4546			// 3) continue the original ritual: call the postscript
4547			f = this.postscript;
4548			if(f){
4549				f.apply(this, args);
4550			}
4551		};
4552	}
4553
4554
4555	// chained constructor compatible with the legacy declare()
4556	function singleConstructor(ctor, ctorSpecial){
4557		return function(){
4558			var a = arguments, t = a, a0 = a[0], f;
4559
4560			if(!(this instanceof a.callee)){
4561				// not called via new, so force it
4562				return applyNew(a);
4563			}
4564
4565			//this._inherited = {};
4566			// perform the shaman's rituals of the original declare()
4567			// 1) call two types of the preamble
4568			if(ctorSpecial){
4569				// full blown ritual
4570				if(a0){
4571					// process the preamble of the 1st argument
4572					f = a0.preamble;
4573					if(f){
4574						t = f.apply(this, t) || t;
4575					}
4576				}
4577				f = this.preamble;
4578				if(f){
4579					// process the preamble of this class
4580					f.apply(this, t);
4581					// one peculiarity of the preamble:
4582					// it is called even if it is not needed,
4583					// e.g., there is no constructor to call
4584					// let's watch for the last constructor
4585					// (see ticket #9795)
4586				}
4587			}
4588			// 2) call a constructor
4589			if(ctor){
4590				ctor.apply(this, a);
4591			}
4592			// 3) continue the original ritual: call the postscript
4593			f = this.postscript;
4594			if(f){
4595				f.apply(this, a);
4596			}
4597		};
4598	}
4599
4600	// plain vanilla constructor (can use inherited() to call its base constructor)
4601	function simpleConstructor(bases){
4602		return function(){
4603			var a = arguments, i = 0, f, m;
4604
4605			if(!(this instanceof a.callee)){
4606				// not called via new, so force it
4607				return applyNew(a);
4608			}
4609
4610			//this._inherited = {};
4611			// perform the shaman's rituals of the original declare()
4612			// 1) do not call the preamble
4613			// 2) call the top constructor (it can use this.inherited())
4614			for(; f = bases[i]; ++i){ // intentional assignment
4615				m = f._meta;
4616				f = m ? m.ctor : f;
4617				if(f){
4618					f.apply(this, a);
4619					break;
4620				}
4621			}
4622			// 3) call the postscript
4623			f = this.postscript;
4624			if(f){
4625				f.apply(this, a);
4626			}
4627		};
4628	}
4629
4630	function chain(name, bases, reversed){
4631		return function(){
4632			var b, m, f, i = 0, step = 1;
4633			if(reversed){
4634				i = bases.length - 1;
4635				step = -1;
4636			}
4637			for(; b = bases[i]; i += step){ // intentional assignment
4638				m = b._meta;
4639				f = (m ? m.hidden : b.prototype)[name];
4640				if(f){
4641					f.apply(this, arguments);
4642				}
4643			}
4644		};
4645	}
4646
4647	// forceNew(ctor)
4648	// return a new object that inherits from ctor.prototype but
4649	// without actually running ctor on the object.
4650	function forceNew(ctor){
4651		// create object with correct prototype using a do-nothing
4652		// constructor
4653		xtor.prototype = ctor.prototype;
4654		var t = new xtor;
4655		xtor.prototype = null;	// clean up
4656		return t;
4657	}
4658
4659	// applyNew(args)
4660	// just like 'new ctor()' except that the constructor and its arguments come
4661	// from args, which must be an array or an arguments object
4662	function applyNew(args){
4663		// create an object with ctor's prototype but without
4664		// calling ctor on it.
4665		var ctor = args.callee, t = forceNew(ctor);
4666		// execute the real constructor on the new object
4667		ctor.apply(t, args);
4668		return t;
4669	}
4670
4671	function declare(className, superclass, props){
4672		// summary:
4673		//		Create a feature-rich constructor from compact notation.
4674		// className: String?
4675		//		The optional name of the constructor (loosely, a "class")
4676		//		stored in the "declaredClass" property in the created prototype.
4677		//		It will be used as a global name for a created constructor.
4678		// superclass: Function|Function[]
4679		//		May be null, a Function, or an Array of Functions. This argument
4680		//		specifies a list of bases (the left-most one is the most deepest
4681		//		base).
4682		// props: Object
4683		//		An object whose properties are copied to the created prototype.
4684		//		Add an instance-initialization function by making it a property
4685		//		named "constructor".
4686		// returns: dojo/_base/declare.__DeclareCreatedObject
4687		//		New constructor function.
4688		// description:
4689		//		Create a constructor using a compact notation for inheritance and
4690		//		prototype extension.
4691		//
4692		//		Mixin ancestors provide a type of multiple inheritance.
4693		//		Prototypes of mixin ancestors are copied to the new class:
4694		//		changes to mixin prototypes will not affect classes to which
4695		//		they have been mixed in.
4696		//
4697		//		Ancestors can be compound classes created by this version of
4698		//		declare(). In complex cases all base classes are going to be
4699		//		linearized according to C3 MRO algorithm
4700		//		(see http://www.python.org/download/releases/2.3/mro/ for more
4701		//		details).
4702		//
4703		//		"className" is cached in "declaredClass" property of the new class,
4704		//		if it was supplied. The immediate super class will be cached in
4705		//		"superclass" property of the new class.
4706		//
4707		//		Methods in "props" will be copied and modified: "nom" property
4708		//		(the declared name of the method) will be added to all copied
4709		//		functions to help identify them for the internal machinery. Be
4710		//		very careful, while reusing methods: if you use the same
4711		//		function under different names, it can produce errors in some
4712		//		cases.
4713		//
4714		//		It is possible to use constructors created "manually" (without
4715		//		declare()) as bases. They will be called as usual during the
4716		//		creation of an instance, their methods will be chained, and even
4717		//		called by "this.inherited()".
4718		//
4719		//		Special property "-chains-" governs how to chain methods. It is
4720		//		a dictionary, which uses method names as keys, and hint strings
4721		//		as values. If a hint string is "after", this method will be
4722		//		called after methods of its base classes. If a hint string is
4723		//		"before", this method will be called before methods of its base
4724		//		classes.
4725		//
4726		//		If "constructor" is not mentioned in "-chains-" property, it will
4727		//		be chained using the legacy mode: using "after" chaining,
4728		//		calling preamble() method before each constructor, if available,
4729		//		and calling postscript() after all constructors were executed.
4730		//		If the hint is "after", it is chained as a regular method, but
4731		//		postscript() will be called after the chain of constructors.
4732		//		"constructor" cannot be chained "before", but it allows
4733		//		a special hint string: "manual", which means that constructors
4734		//		are not going to be chained in any way, and programmer will call
4735		//		them manually using this.inherited(). In the latter case
4736		//		postscript() will be called after the construction.
4737		//
4738		//		All chaining hints are "inherited" from base classes and
4739		//		potentially can be overridden. Be very careful when overriding
4740		//		hints! Make sure that all chained methods can work in a proposed
4741		//		manner of chaining.
4742		//
4743		//		Once a method was chained, it is impossible to unchain it. The
4744		//		only exception is "constructor". You don't need to define a
4745		//		method in order to supply a chaining hint.
4746		//
4747		//		If a method is chained, it cannot use this.inherited() because
4748		//		all other methods in the hierarchy will be called automatically.
4749		//
4750		//		Usually constructors and initializers of any kind are chained
4751		//		using "after" and destructors of any kind are chained as
4752		//		"before". Note that chaining assumes that chained methods do not
4753		//		return any value: any returned value will be discarded.
4754		//
4755		// example:
4756		//	|	declare("my.classes.bar", my.classes.foo, {
4757		//	|		// properties to be added to the class prototype
4758		//	|		someValue: 2,
4759		//	|		// initialization function
4760		//	|		constructor: function(){
4761		//	|			this.myComplicatedObject = new ReallyComplicatedObject();
4762		//	|		},
4763		//	|		// other functions
4764		//	|		someMethod: function(){
4765		//	|			doStuff();
4766		//	|		}
4767		//	|	});
4768		//
4769		// example:
4770		//	|	var MyBase = declare(null, {
4771		//	|		// constructor, properties, and methods go here
4772		//	|		// ...
4773		//	|	});
4774		//	|	var MyClass1 = declare(MyBase, {
4775		//	|		// constructor, properties, and methods go here
4776		//	|		// ...
4777		//	|	});
4778		//	|	var MyClass2 = declare(MyBase, {
4779		//	|		// constructor, properties, and methods go here
4780		//	|		// ...
4781		//	|	});
4782		//	|	var MyDiamond = declare([MyClass1, MyClass2], {
4783		//	|		// constructor, properties, and methods go here
4784		//	|		// ...
4785		//	|	});
4786		//
4787		// example:
4788		//	|	var F = function(){ console.log("raw constructor"); };
4789		//	|	F.prototype.method = function(){
4790		//	|		console.log("raw method");
4791		//	|	};
4792		//	|	var A = declare(F, {
4793		//	|		constructor: function(){
4794		//	|			console.log("A.constructor");
4795		//	|		},
4796		//	|		method: function(){
4797		//	|			console.log("before calling F.method...");
4798		//	|			this.inherited(arguments);
4799		//	|			console.log("...back in A");
4800		//	|		}
4801		//	|	});
4802		//	|	new A().method();
4803		//	|	// will print:
4804		//	|	// raw constructor
4805		//	|	// A.constructor
4806		//	|	// before calling F.method...
4807		//	|	// raw method
4808		//	|	// ...back in A
4809		//
4810		// example:
4811		//	|	var A = declare(null, {
4812		//	|		"-chains-": {
4813		//	|			destroy: "before"
4814		//	|		}
4815		//	|	});
4816		//	|	var B = declare(A, {
4817		//	|		constructor: function(){
4818		//	|			console.log("B.constructor");
4819		//	|		},
4820		//	|		destroy: function(){
4821		//	|			console.log("B.destroy");
4822		//	|		}
4823		//	|	});
4824		//	|	var C = declare(B, {
4825		//	|		constructor: function(){
4826		//	|			console.log("C.constructor");
4827		//	|		},
4828		//	|		destroy: function(){
4829		//	|			console.log("C.destroy");
4830		//	|		}
4831		//	|	});
4832		//	|	new C().destroy();
4833		//	|	// prints:
4834		//	|	// B.constructor
4835		//	|	// C.constructor
4836		//	|	// C.destroy
4837		//	|	// B.destroy
4838		//
4839		// example:
4840		//	|	var A = declare(null, {
4841		//	|		"-chains-": {
4842		//	|			constructor: "manual"
4843		//	|		}
4844		//	|	});
4845		//	|	var B = declare(A, {
4846		//	|		constructor: function(){
4847		//	|			// ...
4848		//	|			// call the base constructor with new parameters
4849		//	|			this.inherited(arguments, [1, 2, 3]);
4850		//	|			// ...
4851		//	|		}
4852		//	|	});
4853		//
4854		// example:
4855		//	|	var A = declare(null, {
4856		//	|		"-chains-": {
4857		//	|			m1: "before"
4858		//	|		},
4859		//	|		m1: function(){
4860		//	|			console.log("A.m1");
4861		//	|		},
4862		//	|		m2: function(){
4863		//	|			console.log("A.m2");
4864		//	|		}
4865		//	|	});
4866		//	|	var B = declare(A, {
4867		//	|		"-chains-": {
4868		//	|			m2: "after"
4869		//	|		},
4870		//	|		m1: function(){
4871		//	|			console.log("B.m1");
4872		//	|		},
4873		//	|		m2: function(){
4874		//	|			console.log("B.m2");
4875		//	|		}
4876		//	|	});
4877		//	|	var x = new B();
4878		//	|	x.m1();
4879		//	|	// prints:
4880		//	|	// B.m1
4881		//	|	// A.m1
4882		//	|	x.m2();
4883		//	|	// prints:
4884		//	|	// A.m2
4885		//	|	// B.m2
4886
4887		// crack parameters
4888		if(typeof className != "string"){
4889			props = superclass;
4890			superclass = className;
4891			className = "";
4892		}
4893		props = props || {};
4894
4895		var proto, i, t, ctor, name, bases, chains, mixins = 1, parents = superclass;
4896
4897		// build a prototype
4898		if(opts.call(superclass) == "[object Array]"){
4899			// C3 MRO
4900			bases = c3mro(superclass, className);
4901			t = bases[0];
4902			mixins = bases.length - t;
4903			superclass = bases[mixins];
4904		}else{
4905			bases = [0];
4906			if(superclass){
4907				if(opts.call(superclass) == "[object Function]"){
4908					t = superclass._meta;
4909					bases = bases.concat(t ? t.bases : superclass);
4910				}else{
4911					err("base class is not a callable constructor.", className);
4912				}
4913			}else if(superclass !== null){
4914				err("unknown base class. Did you use dojo.require to pull it in?", className);
4915			}
4916		}
4917		if(superclass){
4918			for(i = mixins - 1;; --i){
4919				proto = forceNew(superclass);
4920				if(!i){
4921					// stop if nothing to add (the last base)
4922					break;
4923				}
4924				// mix in properties
4925				t = bases[i];
4926				(t._meta ? mixOwn : mix)(proto, t.prototype);
4927				// chain in new constructor
4928				ctor = new Function;
4929				ctor.superclass = superclass;
4930				ctor.prototype = proto;
4931				superclass = proto.constructor = ctor;
4932			}
4933		}else{
4934			proto = {};
4935		}
4936		// add all properties
4937		declare.safeMixin(proto, props);
4938		// add constructor
4939		t = props.constructor;
4940		if(t !== op.constructor){
4941			t.nom = cname;
4942			proto.constructor = t;
4943		}
4944
4945		// collect chains and flags
4946		for(i = mixins - 1; i; --i){ // intentional assignment
4947			t = bases[i]._meta;
4948			if(t && t.chains){
4949				chains = mix(chains || {}, t.chains);
4950			}
4951		}
4952		if(proto["-chains-"]){
4953			chains = mix(chains || {}, proto["-chains-"]);
4954		}
4955
4956		// build ctor
4957		t = !chains || !chains.hasOwnProperty(cname);
4958		bases[0] = ctor = (chains && chains.constructor === "manual") ? simpleConstructor(bases) :
4959			(bases.length == 1 ? singleConstructor(props.constructor, t) : chainedConstructor(bases, t));
4960
4961		// add meta information to the constructor
4962		ctor._meta  = {bases: bases, hidden: props, chains: chains,
4963			parents: parents, ctor: props.constructor};
4964		ctor.superclass = superclass && superclass.prototype;
4965		ctor.extend = extend;
4966		ctor.createSubclass = createSubclass;
4967		ctor.prototype = proto;
4968		proto.constructor = ctor;
4969
4970		// add "standard" methods to the prototype
4971		proto.getInherited = getInherited;
4972		proto.isInstanceOf = isInstanceOf;
4973		proto.inherited    = inheritedImpl;
4974		proto.__inherited  = inherited;
4975
4976		// add name if specified
4977		if(className){
4978			proto.declaredClass = className;
4979			lang.setObject(className, ctor);
4980		}
4981
4982		// build chains and add them to the prototype
4983		if(chains){
4984			for(name in chains){
4985				if(proto[name] && typeof chains[name] == "string" && name != cname){
4986					t = proto[name] = chain(name, bases, chains[name] === "after");
4987					t.nom = name;
4988				}
4989			}
4990		}
4991		// chained methods do not return values
4992		// no need to chain "invisible" functions
4993
4994		return ctor;	// Function
4995	}
4996
4997	/*=====
4998	declare.__DeclareCreatedObject = {
4999		// summary:
5000		//		dojo/_base/declare() returns a constructor `C`.   `new C()` returns an Object with the following
5001		//		methods, in addition to the methods and properties specified via the arguments passed to declare().
5002
5003		inherited: function(name, args, newArgs){
5004			// summary:
5005			//		Calls a super method.
5006			// name: String?
5007			//		The optional method name. Should be the same as the caller's
5008			//		name. Usually "name" is specified in complex dynamic cases, when
5009			//		the calling method was dynamically added, undecorated by
5010			//		declare(), and it cannot be determined.
5011			// args: Arguments
5012			//		The caller supply this argument, which should be the original
5013			//		"arguments".
5014			// newArgs: Object?
5015			//		If "true", the found function will be returned without
5016			//		executing it.
5017			//		If Array, it will be used to call a super method. Otherwise
5018			//		"args" will be used.
5019			// returns:
5020			//		Whatever is returned by a super method, or a super method itself,
5021			//		if "true" was specified as newArgs.
5022			// description:
5023			//		This method is used inside method of classes produced with
5024			//		declare() to call a super method (next in the chain). It is
5025			//		used for manually controlled chaining. Consider using the regular
5026			//		chaining, because it is faster. Use "this.inherited()" only in
5027			//		complex cases.
5028			//
5029			//		This method cannot me called from automatically chained
5030			//		constructors including the case of a special (legacy)
5031			//		constructor chaining. It cannot be called from chained methods.
5032			//
5033			//		If "this.inherited()" cannot find the next-in-chain method, it
5034			//		does nothing and returns "undefined". The last method in chain
5035			//		can be a default method implemented in Object, which will be
5036			//		called last.
5037			//
5038			//		If "name" is specified, it is assumed that the method that
5039			//		received "args" is the parent method for this call. It is looked
5040			//		up in the chain list and if it is found the next-in-chain method
5041			//		is called. If it is not found, the first-in-chain method is
5042			//		called.
5043			//
5044			//		If "name" is not specified, it will be derived from the calling
5045			//		method (using a methoid property "nom").
5046			//
5047			// example:
5048			//	|	var B = declare(A, {
5049			//	|		method1: function(a, b, c){
5050			//	|			this.inherited(arguments);
5051			//	|		},
5052			//	|		method2: function(a, b){
5053			//	|			return this.inherited(arguments, [a + b]);
5054			//	|		}
5055			//	|	});
5056			//	|	// next method is not in the chain list because it is added
5057			//	|	// manually after the class was created.
5058			//	|	B.prototype.method3 = function(){
5059			//	|		console.log("This is a dynamically-added method.");
5060			//	|		this.inherited("method3", arguments);
5061			//	|	};
5062			// example:
5063			//	|	var B = declare(A, {
5064			//	|		method: function(a, b){
5065			//	|			var super = this.inherited(arguments, true);
5066			//	|			// ...
5067			//	|			if(!super){
5068			//	|				console.log("there is no super method");
5069			//	|				return 0;
5070			//	|			}
5071			//	|			return super.apply(this, arguments);
5072			//	|		}
5073			//	|	});
5074			return	{};	// Object
5075		},
5076
5077		getInherited: function(name, args){
5078			// summary:
5079			//		Returns a super method.
5080			// name: String?
5081			//		The optional method name. Should be the same as the caller's
5082			//		name. Usually "name" is specified in complex dynamic cases, when
5083			//		the calling method was dynamically added, undecorated by
5084			//		declare(), and it cannot be determined.
5085			// args: Arguments
5086			//		The caller supply this argument, which should be the original
5087			//		"arguments".
5088			// returns:
5089			//		Returns a super method (Function) or "undefined".
5090			// description:
5091			//		This method is a convenience method for "this.inherited()".
5092			//		It uses the same algorithm but instead of executing a super
5093			//		method, it returns it, or "undefined" if not found.
5094			//
5095			// example:
5096			//	|	var B = declare(A, {
5097			//	|		method: function(a, b){
5098			//	|			var super = this.getInherited(arguments);
5099			//	|			// ...
5100			//	|			if(!super){
5101			//	|				console.log("there is no super method");
5102			//	|				return 0;
5103			//	|			}
5104			//	|			return super.apply(this, arguments);
5105			//	|		}
5106			//	|	});
5107			return	{};	// Object
5108		},
5109
5110		isInstanceOf: function(cls){
5111			// summary:
5112			//		Checks the inheritance chain to see if it is inherited from this
5113			//		class.
5114			// cls: Function
5115			//		Class constructor.
5116			// returns:
5117			//		"true", if this object is inherited from this class, "false"
5118			//		otherwise.
5119			// description:
5120			//		This method is used with instances of classes produced with
5121			//		declare() to determine of they support a certain interface or
5122			//		not. It models "instanceof" operator.
5123			//
5124			// example:
5125			//	|	var A = declare(null, {
5126			//	|		// constructor, properties, and methods go here
5127			//	|		// ...
5128			//	|	});
5129			//	|	var B = declare(null, {
5130			//	|		// constructor, properties, and methods go here
5131			//	|		// ...
5132			//	|	});
5133			//	|	var C = declare([A, B], {
5134			//	|		// constructor, properties, and methods go here
5135			//	|		// ...
5136			//	|	});
5137			//	|	var D = declare(A, {
5138			//	|		// constructor, properties, and methods go here
5139			//	|		// ...
5140			//	|	});
5141			//	|
5142			//	|	var a = new A(), b = new B(), c = new C(), d = new D();
5143			//	|
5144			//	|	console.log(a.isInstanceOf(A)); // true
5145			//	|	console.log(b.isInstanceOf(A)); // false
5146			//	|	console.log(c.isInstanceOf(A)); // true
5147			//	|	console.log(d.isInstanceOf(A)); // true
5148			//	|
5149			//	|	console.log(a.isInstanceOf(B)); // false
5150			//	|	console.log(b.isInstanceOf(B)); // true
5151			//	|	console.log(c.isInstanceOf(B)); // true
5152			//	|	console.log(d.isInstanceOf(B)); // false
5153			//	|
5154			//	|	console.log(a.isInstanceOf(C)); // false
5155			//	|	console.log(b.isInstanceOf(C)); // false
5156			//	|	console.log(c.isInstanceOf(C)); // true
5157			//	|	console.log(d.isInstanceOf(C)); // false
5158			//	|
5159			//	|	console.log(a.isInstanceOf(D)); // false
5160			//	|	console.log(b.isInstanceOf(D)); // false
5161			//	|	console.log(c.isInstanceOf(D)); // false
5162			//	|	console.log(d.isInstanceOf(D)); // true
5163			return	{};	// Object
5164		},
5165
5166		extend: function(source){
5167			// summary:
5168			//		Adds all properties and methods of source to constructor's
5169			//		prototype, making them available to all instances created with
5170			//		constructor. This method is specific to constructors created with
5171			//		declare().
5172			// source: Object
5173			//		Source object which properties are going to be copied to the
5174			//		constructor's prototype.
5175			// description:
5176			//		Adds source properties to the constructor's prototype. It can
5177			//		override existing properties.
5178			//
5179			//		This method is similar to dojo.extend function, but it is specific
5180			//		to constructors produced by declare(). It is implemented
5181			//		using dojo.safeMixin, and it skips a constructor property,
5182			//		and properly decorates copied functions.
5183			//
5184			// example:
5185			//	|	var A = declare(null, {
5186			//	|		m1: function(){},
5187			//	|		s1: "Popokatepetl"
5188			//	|	});
5189			//	|	A.extend({
5190			//	|		m1: function(){},
5191			//	|		m2: function(){},
5192			//	|		f1: true,
5193			//	|		d1: 42
5194			//	|	});
5195		},
5196
5197		createSubclass: function(mixins, props){
5198			// summary:
5199			//		Create a subclass of the declared class from a list of base classes.
5200			// mixins: Function[]
5201			//		Specifies a list of bases (the left-most one is the most deepest
5202			//		base).
5203			// props: Object?
5204			//		An optional object whose properties are copied to the created prototype.
5205			// returns: dojo/_base/declare.__DeclareCreatedObject
5206			//		New constructor function.
5207			// description:
5208			//		Create a constructor using a compact notation for inheritance and
5209			//		prototype extension.
5210			//
5211			//		Mixin ancestors provide a type of multiple inheritance.
5212			//		Prototypes of mixin ancestors are copied to the new class:
5213			//		changes to mixin prototypes will not affect classes to which
5214			//		they have been mixed in.
5215			//
5216			// example:
5217			//	|	var A = declare(null, {
5218			//	|		m1: function(){},
5219			//	|		s1: "bar"
5220			//	|	});
5221			//	|	var B = declare(null, {
5222			//	|		m2: function(){},
5223			//	|		s2: "foo"
5224			//	|	});
5225			//	|	var C = declare(null, {
5226			//	|	});
5227			//	|	var D1 = A.createSubclass([B, C], {
5228			//	|		m1: function(){},
5229			//	|		d1: 42
5230			//	|	});
5231			//	|	var d1 = new D1();
5232			//	|
5233			//	|	// this is equivalent to:
5234			//	|	var D2 = declare([A, B, C], {
5235			//	|		m1: function(){},
5236			//	|		d1: 42
5237			//	|	});
5238			//	|	var d2 = new D2();
5239		}
5240	};
5241	=====*/
5242
5243	// For back-compat, remove for 2.0
5244	dojo.safeMixin = declare.safeMixin = safeMixin;
5245	dojo.declare = declare;
5246
5247	return declare;
5248});
5249
5250},
5251'dojo/_base/connect':function(){
5252define(["./kernel", "../on", "../topic", "../aspect", "./event", "../mouse", "./sniff", "./lang", "../keys"], function(dojo, on, hub, aspect, eventModule, mouse, has, lang){
5253// module:
5254//		dojo/_base/connect
5255
5256has.add("events-keypress-typed", function(){ // keypresses should only occur a printable character is hit
5257	var testKeyEvent = {charCode: 0};
5258	try{
5259		testKeyEvent = document.createEvent("KeyboardEvent");
5260		(testKeyEvent.initKeyboardEvent || testKeyEvent.initKeyEvent).call(testKeyEvent, "keypress", true, true, null, false, false, false, false, 9, 3);
5261	}catch(e){}
5262	return testKeyEvent.charCode == 0 && !has("opera");
5263});
5264
5265function connect_(obj, event, context, method, dontFix){
5266	method = lang.hitch(context, method);
5267	if(!obj || !(obj.addEventListener || obj.attachEvent)){
5268		// it is a not a DOM node and we are using the dojo.connect style of treating a
5269		// method like an event, must go right to aspect
5270		return aspect.after(obj || dojo.global, event, method, true);
5271	}
5272	if(typeof event == "string" && event.substring(0, 2) == "on"){
5273		event = event.substring(2);
5274	}
5275	if(!obj){
5276		obj = dojo.global;
5277	}
5278	if(!dontFix){
5279		switch(event){
5280			// dojo.connect has special handling for these event types
5281			case "keypress":
5282				event = keypress;
5283				break;
5284			case "mouseenter":
5285				event = mouse.enter;
5286				break;
5287			case "mouseleave":
5288				event = mouse.leave;
5289				break;
5290		}
5291	}
5292	return on(obj, event, method, dontFix);
5293}
5294
5295var _punctMap = {
5296	106:42,
5297	111:47,
5298	186:59,
5299	187:43,
5300	188:44,
5301	189:45,
5302	190:46,
5303	191:47,
5304	192:96,
5305	219:91,
5306	220:92,
5307	221:93,
5308	222:39,
5309	229:113
5310};
5311var evtCopyKey = has("mac") ? "metaKey" : "ctrlKey";
5312
5313
5314var _synthesizeEvent = function(evt, props){
5315	var faux = lang.mixin({}, evt, props);
5316	setKeyChar(faux);
5317	// FIXME: would prefer to use lang.hitch: lang.hitch(evt, evt.preventDefault);
5318	// but it throws an error when preventDefault is invoked on Safari
5319	// does Event.preventDefault not support "apply" on Safari?
5320	faux.preventDefault = function(){ evt.preventDefault(); };
5321	faux.stopPropagation = function(){ evt.stopPropagation(); };
5322	return faux;
5323};
5324function setKeyChar(evt){
5325	evt.keyChar = evt.charCode ? String.fromCharCode(evt.charCode) : '';
5326	evt.charOrCode = evt.keyChar || evt.keyCode;
5327}
5328var keypress;
5329if(has("events-keypress-typed")){
5330	// this emulates Firefox's keypress behavior where every keydown can correspond to a keypress
5331	var _trySetKeyCode = function(e, code){
5332		try{
5333			// squelch errors when keyCode is read-only
5334			// (e.g. if keyCode is ctrl or shift)
5335			return (e.keyCode = code);
5336		}catch(e){
5337			return 0;
5338		}
5339	};
5340	keypress = function(object, listener){
5341		var keydownSignal = on(object, "keydown", function(evt){
5342			// munge key/charCode
5343			var k=evt.keyCode;
5344			// These are Windows Virtual Key Codes
5345			// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp
5346			var unprintable = (k!=13) && k!=32 && (k!=27||!has("ie")) && (k<48||k>90) && (k<96||k>111) && (k<186||k>192) && (k<219||k>222) && k!=229;
5347			// synthesize keypress for most unprintables and CTRL-keys
5348			if(unprintable||evt.ctrlKey){
5349				var c = unprintable ? 0 : k;
5350				if(evt.ctrlKey){
5351					if(k==3 || k==13){
5352						return listener.call(evt.currentTarget, evt); // IE will post CTRL-BREAK, CTRL-ENTER as keypress natively
5353					}else if(c>95 && c<106){
5354						c -= 48; // map CTRL-[numpad 0-9] to ASCII
5355					}else if((!evt.shiftKey)&&(c>=65&&c<=90)){
5356						c += 32; // map CTRL-[A-Z] to lowercase
5357					}else{
5358						c = _punctMap[c] || c; // map other problematic CTRL combinations to ASCII
5359					}
5360				}
5361				// simulate a keypress event
5362				var faux = _synthesizeEvent(evt, {type: 'keypress', faux: true, charCode: c});
5363				listener.call(evt.currentTarget, faux);
5364				if(has("ie")){
5365					_trySetKeyCode(evt, faux.keyCode);
5366				}
5367			}
5368		});
5369		var keypressSignal = on(object, "keypress", function(evt){
5370			var c = evt.charCode;
5371			c = c>=32 ? c : 0;
5372			evt = _synthesizeEvent(evt, {charCode: c, faux: true});
5373			return listener.call(this, evt);
5374		});
5375		return {
5376			remove: function(){
5377				keydownSignal.remove();
5378				keypressSignal.remove();
5379			}
5380		};
5381	};
5382}else{
5383	if(has("opera")){
5384		keypress = function(object, listener){
5385			return on(object, "keypress", function(evt){
5386				var c = evt.which;
5387				if(c==3){
5388					c=99; // Mozilla maps CTRL-BREAK to CTRL-c
5389				}
5390				// can't trap some keys at all, like INSERT and DELETE
5391				// there is no differentiating info between DELETE and ".", or INSERT and "-"
5392				c = c<32 && !evt.shiftKey ? 0 : c;
5393				if(evt.ctrlKey && !evt.shiftKey && c>=65 && c<=90){
5394					// lowercase CTRL-[A-Z] keys
5395					c += 32;
5396				}
5397				return listener.call(this, _synthesizeEvent(evt, { charCode: c }));
5398			});
5399		};
5400	}else{
5401		keypress = function(object, listener){
5402			return on(object, "keypress", function(evt){
5403				setKeyChar(evt);
5404				return listener.call(this, evt);
5405			});
5406		};
5407	}
5408}
5409
5410var connect = {
5411	// summary:
5412	//		This module defines the dojo.connect API.
5413	//		This modules also provides keyboard event handling helpers.
5414	//		This module exports an extension event for emulating Firefox's keypress handling.
5415	//		However, this extension event exists primarily for backwards compatibility and
5416	//		is not recommended. WebKit and IE uses an alternate keypress handling (only
5417	//		firing for printable characters, to distinguish from keydown events), and most
5418	//		consider the WebKit/IE behavior more desirable.
5419
5420	_keypress:keypress,
5421
5422	connect:function(obj, event, context, method, dontFix){
5423		// summary:
5424		//		`dojo.connect` is a deprecated event handling and delegation method in
5425		//		Dojo. It allows one function to "listen in" on the execution of
5426		//		any other, triggering the second whenever the first is called. Many
5427		//		listeners may be attached to a function, and source functions may
5428		//		be either regular function calls or DOM events.
5429		//
5430		// description:
5431		//		Connects listeners to actions, so that after event fires, a
5432		//		listener is called with the same arguments passed to the original
5433		//		function.
5434		//
5435		//		Since `dojo.connect` allows the source of events to be either a
5436		//		"regular" JavaScript function or a DOM event, it provides a uniform
5437		//		interface for listening to all the types of events that an
5438		//		application is likely to deal with though a single, unified
5439		//		interface. DOM programmers may want to think of it as
5440		//		"addEventListener for everything and anything".
5441		//
5442		//		When setting up a connection, the `event` parameter must be a
5443		//		string that is the name of the method/event to be listened for. If
5444		//		`obj` is null, `kernel.global` is assumed, meaning that connections
5445		//		to global methods are supported but also that you may inadvertently
5446		//		connect to a global by passing an incorrect object name or invalid
5447		//		reference.
5448		//
5449		//		`dojo.connect` generally is forgiving. If you pass the name of a
5450		//		function or method that does not yet exist on `obj`, connect will
5451		//		not fail, but will instead set up a stub method. Similarly, null
5452		//		arguments may simply be omitted such that fewer than 4 arguments
5453		//		may be required to set up a connection See the examples for details.
5454		//
5455		//		The return value is a handle that is needed to
5456		//		remove this connection with `dojo.disconnect`.
5457		//
5458		// obj: Object?
5459		//		The source object for the event function.
5460		//		Defaults to `kernel.global` if null.
5461		//		If obj is a DOM node, the connection is delegated
5462		//		to the DOM event manager (unless dontFix is true).
5463		//
5464		// event: String
5465		//		String name of the event function in obj.
5466		//		I.e. identifies a property `obj[event]`.
5467		//
5468		// context: Object|null
5469		//		The object that method will receive as "this".
5470		//
5471		//		If context is null and method is a function, then method
5472		//		inherits the context of event.
5473		//
5474		//		If method is a string then context must be the source
5475		//		object object for method (context[method]). If context is null,
5476		//		kernel.global is used.
5477		//
5478		// method: String|Function
5479		//		A function reference, or name of a function in context.
5480		//		The function identified by method fires after event does.
5481		//		method receives the same arguments as the event.
5482		//		See context argument comments for information on method's scope.
5483		//
5484		// dontFix: Boolean?
5485		//		If obj is a DOM node, set dontFix to true to prevent delegation
5486		//		of this connection to the DOM event manager.
5487		//
5488		// example:
5489		//		When obj.onchange(), do ui.update():
5490		//	|	dojo.connect(obj, "onchange", ui, "update");
5491		//	|	dojo.connect(obj, "onchange", ui, ui.update); // same
5492		//
5493		// example:
5494		//		Using return value for disconnect:
5495		//	|	var link = dojo.connect(obj, "onchange", ui, "update");
5496		//	|	...
5497		//	|	dojo.disconnect(link);
5498		//
5499		// example:
5500		//		When onglobalevent executes, watcher.handler is invoked:
5501		//	|	dojo.connect(null, "onglobalevent", watcher, "handler");
5502		//
5503		// example:
5504		//		When ob.onCustomEvent executes, customEventHandler is invoked:
5505		//	|	dojo.connect(ob, "onCustomEvent", null, "customEventHandler");
5506		//	|	dojo.connect(ob, "onCustomEvent", "customEventHandler"); // same
5507		//
5508		// example:
5509		//		When ob.onCustomEvent executes, customEventHandler is invoked
5510		//		with the same scope (this):
5511		//	|	dojo.connect(ob, "onCustomEvent", null, customEventHandler);
5512		//	|	dojo.connect(ob, "onCustomEvent", customEventHandler); // same
5513		//
5514		// example:
5515		//		When globalEvent executes, globalHandler is invoked
5516		//		with the same scope (this):
5517		//	|	dojo.connect(null, "globalEvent", null, globalHandler);
5518		//	|	dojo.connect("globalEvent", globalHandler); // same
5519
5520		// normalize arguments
5521		var a=arguments, args=[], i=0;
5522		// if a[0] is a String, obj was omitted
5523		args.push(typeof a[0] == "string" ? null : a[i++], a[i++]);
5524		// if the arg-after-next is a String or Function, context was NOT omitted
5525		var a1 = a[i+1];
5526		args.push(typeof a1 == "string" || typeof a1 == "function" ? a[i++] : null, a[i++]);
5527		// absorb any additional arguments
5528		for(var l=a.length; i<l; i++){	args.push(a[i]); }
5529		return connect_.apply(this, args);
5530	},
5531
5532	disconnect:function(handle){
5533		// summary:
5534		//		Remove a link created by dojo.connect.
5535		// description:
5536		//		Removes the connection between event and the method referenced by handle.
5537		// handle: Handle
5538		//		the return value of the dojo.connect call that created the connection.
5539
5540		if(handle){
5541			handle.remove();
5542		}
5543	},
5544
5545	subscribe:function(topic, context, method){
5546		// summary:
5547		//		Attach a listener to a named topic. The listener function is invoked whenever the
5548		//		named topic is published (see: dojo.publish).
5549		//		Returns a handle which is needed to unsubscribe this listener.
5550		// topic: String
5551		//		The topic to which to subscribe.
5552		// context: Object?
5553		//		Scope in which method will be invoked, or null for default scope.
5554		// method: String|Function
5555		//		The name of a function in context, or a function reference. This is the function that
5556		//		is invoked when topic is published.
5557		// example:
5558		//	|	dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); });
5559		//	|	dojo.publish("alerts", [ "read this", "hello world" ]);
5560		return hub.subscribe(topic, lang.hitch(context, method));
5561	},
5562
5563	publish:function(topic, args){
5564		// summary:
5565		//		Invoke all listener method subscribed to topic.
5566		// topic: String
5567		//		The name of the topic to publish.
5568		// args: Array?
5569		//		An array of arguments. The arguments will be applied
5570		//		to each topic subscriber (as first class parameters, via apply).
5571		// example:
5572		//	|	dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); };
5573		//	|	dojo.publish("alerts", [ "read this", "hello world" ]);
5574		return hub.publish.apply(hub, [topic].concat(args));
5575	},
5576
5577	connectPublisher:function(topic, obj, event){
5578		// summary:
5579		//		Ensure that every time obj.event() is called, a message is published
5580		//		on the topic. Returns a handle which can be passed to
5581		//		dojo.disconnect() to disable subsequent automatic publication on
5582		//		the topic.
5583		// topic: String
5584		//		The name of the topic to publish.
5585		// obj: Object?
5586		//		The source object for the event function. Defaults to kernel.global
5587		//		if null.
5588		// event: String
5589		//		The name of the event function in obj.
5590		//		I.e. identifies a property obj[event].
5591		// example:
5592		//	|	dojo.connectPublisher("/ajax/start", dojo, "xhrGet");
5593		var pf = function(){ connect.publish(topic, arguments); };
5594		return event ? connect.connect(obj, event, pf) : connect.connect(obj, pf); //Handle
5595	},
5596
5597	isCopyKey: function(e){
5598		// summary:
5599		//		Checks an event for the copy key (meta on Mac, and ctrl anywhere else)
5600		// e: Event
5601		//		Event object to examine
5602		return e[evtCopyKey];	// Boolean
5603	}
5604};
5605
5606connect.unsubscribe = connect.disconnect;
5607/*=====
5608 connect.unsubscribe = function(handle){
5609	 // summary:
5610	 //		Remove a topic listener.
5611	 // handle: Handle
5612	 //		The handle returned from a call to subscribe.
5613	 // example:
5614	 //	|	var alerter = dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); };
5615	 //	|	...
5616	 //	|	dojo.unsubscribe(alerter);
5617 };
5618 =====*/
5619
5620 1  && lang.mixin(dojo, connect);
5621return connect;
5622
5623});
5624
5625
5626
5627},
5628'dojo/on':function(){
5629define(["./has!dom-addeventlistener?:./aspect", "./_base/kernel", "./sniff"], function(aspect, dojo, has){
5630
5631	"use strict";
5632	if( 1 ){ // check to make sure we are in a browser, this module should work anywhere
5633		var major = window.ScriptEngineMajorVersion;
5634		has.add("jscript", major && (major() + ScriptEngineMinorVersion() / 10));
5635		has.add("event-orientationchange", has("touch") && !has("android")); // TODO: how do we detect this?
5636		has.add("event-stopimmediatepropagation", window.Event && !!window.Event.prototype && !!window.Event.prototype.stopImmediatePropagation);
5637		has.add("event-focusin", function(global, doc, element){
5638			return 'onfocusin' in element;
5639		});
5640		
5641		if(has("touch")){
5642			has.add("touch-can-modify-event-delegate", function(){
5643				// This feature test checks whether deleting a property of an event delegate works
5644				// for a touch-enabled device. If it works, event delegation can be used as fallback
5645				// for browsers such as Safari in older iOS where deleting properties of the original
5646				// event does not work.
5647				var EventDelegate = function(){};
5648				EventDelegate.prototype =
5649					document.createEvent("MouseEvents"); // original event
5650				// Attempt to modify a property of an event delegate and check if
5651				// it succeeds. Depending on browsers and on whether dojo/on's
5652				// strict mode is stripped in a Dojo build, there are 3 known behaviors:
5653				// it may either succeed, or raise an error, or fail to set the property
5654				// without raising an error.
5655				try{
5656					var eventDelegate = new EventDelegate;
5657					eventDelegate.target = null;
5658					return eventDelegate.target === null;
5659				}catch(e){
5660					return false; // cannot use event delegation
5661				}
5662			});
5663		}
5664	}
5665	var on = function(target, type, listener, dontFix){
5666		// summary:
5667		//		A function that provides core event listening functionality. With this function
5668		//		you can provide a target, event type, and listener to be notified of
5669		//		future matching events that are fired.
5670		// target: Element|Object
5671		//		This is the target object or DOM element that to receive events from
5672		// type: String|Function
5673		//		This is the name of the event to listen for or an extension event type.
5674		// listener: Function
5675		//		This is the function that should be called when the event fires.
5676		// returns: Object
5677		//		An object with a remove() method that can be used to stop listening for this
5678		//		event.
5679		// description:
5680		//		To listen for "click" events on a button node, we can do:
5681		//		|	define(["dojo/on"], function(on){
5682		//		|		on(button, "click", clickHandler);
5683		//		|		...
5684		//		Evented JavaScript objects can also have their own events.
5685		//		|	var obj = new Evented;
5686		//		|	on(obj, "foo", fooHandler);
5687		//		And then we could publish a "foo" event:
5688		//		|	on.emit(obj, "foo", {key: "value"});
5689		//		We can use extension events as well. For example, you could listen for a tap gesture:
5690		//		|	define(["dojo/on", "dojo/gesture/tap", function(on, tap){
5691		//		|		on(button, tap, tapHandler);
5692		//		|		...
5693		//		which would trigger fooHandler. Note that for a simple object this is equivalent to calling:
5694		//		|	obj.onfoo({key:"value"});
5695		//		If you use on.emit on a DOM node, it will use native event dispatching when possible.
5696
5697		if(typeof target.on == "function" && typeof type != "function" && !target.nodeType){
5698			// delegate to the target's on() method, so it can handle it's own listening if it wants (unless it 
5699			// is DOM node and we may be dealing with jQuery or Prototype's incompatible addition to the
5700			// Element prototype 
5701			return target.on(type, listener);
5702		}
vendor: 17,232 bytes, lines 5703-6125
5703		// delegate to main listener code
5704		return on.parse(target, type, listener, addListener, dontFix, this);
5705	};
5706	on.pausable =  function(target, type, listener, dontFix){
5707		// summary:
5708		//		This function acts the same as on(), but with pausable functionality. The
5709		//		returned signal object has pause() and resume() functions. Calling the
5710		//		pause() method will cause the listener to not be called for future events. Calling the
5711		//		resume() method will cause the listener to again be called for future events.
5712		var paused;
5713		var signal = on(target, type, function(){
5714			if(!paused){
5715				return listener.apply(this, arguments);
5716			}
5717		}, dontFix);
5718		signal.pause = function(){
5719			paused = true;
5720		};
5721		signal.resume = function(){
5722			paused = false;
5723		};
5724		return signal;
5725	};
5726	on.once = function(target, type, listener, dontFix){
5727		// summary:
5728		//		This function acts the same as on(), but will only call the listener once. The 
5729		//		listener will be called for the first
5730		//		event that takes place and then listener will automatically be removed.
5731		var signal = on(target, type, function(){
5732			// remove this listener
5733			signal.remove();
5734			// proceed to call the listener
5735			return listener.apply(this, arguments);
5736		});
5737		return signal;
5738	};
5739	on.parse = function(target, type, listener, addListener, dontFix, matchesTarget){
5740		if(type.call){
5741			// event handler function
5742			// on(node, touch.press, touchListener);
5743			return type.call(matchesTarget, target, listener);
5744		}
5745
5746		if(type instanceof Array){
5747			// allow an array of event names (or event handler functions)
5748			events = type;
5749		}else if(type.indexOf(",") > -1){
5750			// we allow comma delimited event names, so you can register for multiple events at once
5751			var events = type.split(/\s*,\s*/);
5752		} 
5753		if(events){
5754			var handles = [];
5755			var i = 0;
5756			var eventName;
5757			while(eventName = events[i++]){
5758				handles.push(on.parse(target, eventName, listener, addListener, dontFix, matchesTarget));
5759			}
5760			handles.remove = function(){
5761				for(var i = 0; i < handles.length; i++){
5762					handles[i].remove();
5763				}
5764			};
5765			return handles;
5766		}
5767		return addListener(target, type, listener, dontFix, matchesTarget);
5768	};
5769	var touchEvents = /^touch/;
5770	function addListener(target, type, listener, dontFix, matchesTarget){
5771		// event delegation:
5772		var selector = type.match(/(.*):(.*)/);
5773		// if we have a selector:event, the last one is interpreted as an event, and we use event delegation
5774		if(selector){
5775			type = selector[2];
5776			selector = selector[1];
5777			// create the extension event for selectors and directly call it
5778			return on.selector(selector, type).call(matchesTarget, target, listener);
5779		}
5780		// test to see if it a touch event right now, so we don't have to do it every time it fires
5781		if(has("touch")){
5782			if(touchEvents.test(type)){
5783				// touch event, fix it
5784				listener = fixTouchListener(listener);
5785			}
5786			if(!has("event-orientationchange") && (type == "orientationchange")){
5787				//"orientationchange" not supported <= Android 2.1, 
5788				//but works through "resize" on window
5789				type = "resize"; 
5790				target = window;
5791				listener = fixTouchListener(listener);
5792			} 
5793		}
5794		if(addStopImmediate){
5795			// add stopImmediatePropagation if it doesn't exist
5796			listener = addStopImmediate(listener);
5797		}
5798		// normal path, the target is |this|
5799		if(target.addEventListener){
5800			// the target has addEventListener, which should be used if available (might or might not be a node, non-nodes can implement this method as well)
5801			// check for capture conversions
5802			var capture = type in captures,
5803				adjustedType = capture ? captures[type] : type;
5804			target.addEventListener(adjustedType, listener, capture);
5805			// create and return the signal
5806			return {
5807				remove: function(){
5808					target.removeEventListener(adjustedType, listener, capture);
5809				}
5810			};
5811		}
5812		type = "on" + type;
5813		if(fixAttach && target.attachEvent){
5814			return fixAttach(target, type, listener);
5815		}
5816		throw new Error("Target must be an event emitter");
5817	}
5818	on.matches = function(node, selector, context, children, matchesTarget) {
5819		// summary:
5820		//		Check if a node match the current selector within the constraint of a context
5821		// node: DOMNode
5822		//		The node that originate the event
5823		// selector: String
5824		//		The selector to check against
5825		// context: DOMNode
5826		//		The context to search in.
5827		// children: Boolean
5828		//		Indicates if children elements of the selector should be allowed. This defaults to
5829		//		true
5830		// matchesTarget: Object|dojo/query?
5831		//		An object with a property "matches" as a function. Default is dojo/query.
5832		//		Matching DOMNodes will be done against this function
5833		//		The function must return a Boolean.
5834		//		It will have 3 arguments: "node", "selector" and "context"
5835		//		True is expected if "node" is matching the current "selector" in the passed "context"
5836		// returns: DOMNode?
5837		//		The matching node, if any. Else you get false
5838
5839		// see if we have a valid matchesTarget or default to dojo/query
5840		matchesTarget = matchesTarget && matchesTarget.matches ? matchesTarget : dojo.query;
5841		children = children !== false;
5842		// there is a selector, so make sure it matches
5843		if(node.nodeType != 1){
5844			// text node will fail in native match selector
5845			node = node.parentNode;
5846		}
5847		while(!matchesTarget.matches(node, selector, context)){
5848			if(node == context || children === false || !(node = node.parentNode) || node.nodeType != 1){ // intentional assignment
5849				return false;
5850			}
5851		}
5852		return node;
5853	}
5854	on.selector = function(selector, eventType, children){
5855		// summary:
5856		//		Creates a new extension event with event delegation. This is based on
5857		//		the provided event type (can be extension event) that
5858		//		only calls the listener when the CSS selector matches the target of the event.
5859		//
5860		//		The application must require() an appropriate level of dojo/query to handle the selector.
5861		// selector:
5862		//		The CSS selector to use for filter events and determine the |this| of the event listener.
5863		// eventType:
5864		//		The event to listen for
5865		// children:
5866		//		Indicates if children elements of the selector should be allowed. This defaults to 
5867		//		true
5868		// example:
5869		// |	require(["dojo/on", "dojo/mouse", "dojo/query!css2"], function(on, mouse){
5870		// |		on(node, on.selector(".my-class", mouse.enter), handlerForMyHover);
5871		return function(target, listener){
5872			// if the selector is function, use it to select the node, otherwise use the matches method
5873			var matchesTarget = typeof selector == "function" ? {matches: selector} : this,
5874				bubble = eventType.bubble;
5875			function select(eventTarget){
5876				return on.matches(eventTarget, selector, target, children, matchesTarget);
5877			}
5878			if(bubble){
5879				// the event type doesn't naturally bubble, but has a bubbling form, use that, and give it the selector so it can perform the select itself
5880				return on(target, bubble(select), listener);
5881			}
5882			// standard event delegation
5883			return on(target, eventType, function(event){
5884				// call select to see if we match
5885				var eventTarget = select(event.target);
5886				// if it matches we call the listener
5887				if (eventTarget) {
5888					return listener.call(eventTarget, event);
5889				}
5890			});
5891		};
5892	};
5893
5894	function syntheticPreventDefault(){
5895		this.cancelable = false;
5896		this.defaultPrevented = true;
5897	}
5898	function syntheticStopPropagation(){
5899		this.bubbles = false;
5900	}
5901	var slice = [].slice,
5902		syntheticDispatch = on.emit = function(target, type, event){
5903		// summary:
5904		//		Fires an event on the target object.
5905		// target:
5906		//		The target object to fire the event on. This can be a DOM element or a plain 
5907		//		JS object. If the target is a DOM element, native event emitting mechanisms
5908		//		are used when possible.
5909		// type:
5910		//		The event type name. You can emulate standard native events like "click" and 
5911		//		"mouseover" or create custom events like "open" or "finish".
5912		// event:
5913		//		An object that provides the properties for the event. See https://developer.mozilla.org/en/DOM/event.initEvent 
5914		//		for some of the properties. These properties are copied to the event object.
5915		//		Of particular importance are the cancelable and bubbles properties. The
5916		//		cancelable property indicates whether or not the event has a default action
5917		//		that can be cancelled. The event is cancelled by calling preventDefault() on
5918		//		the event object. The bubbles property indicates whether or not the
5919		//		event will bubble up the DOM tree. If bubbles is true, the event will be called
5920		//		on the target and then each parent successively until the top of the tree
5921		//		is reached or stopPropagation() is called. Both bubbles and cancelable 
5922		//		default to false.
5923		// returns:
5924		//		If the event is cancelable and the event is not cancelled,
5925		//		emit will return true. If the event is cancelable and the event is cancelled,
5926		//		emit will return false.
5927		// details:
5928		//		Note that this is designed to emit events for listeners registered through
5929		//		dojo/on. It should actually work with any event listener except those
5930		//		added through IE's attachEvent (IE8 and below's non-W3C event emitting
5931		//		doesn't support custom event types). It should work with all events registered
5932		//		through dojo/on. Also note that the emit method does do any default
5933		//		action, it only returns a value to indicate if the default action should take
5934		//		place. For example, emitting a keypress event would not cause a character
5935		//		to appear in a textbox.
5936		// example:
5937		//		To fire our own click event
5938		//	|	require(["dojo/on", "dojo/dom"
5939		//	|	], function(on, dom){
5940		//	|		on.emit(dom.byId("button"), "click", {
5941		//	|			cancelable: true,
5942		//	|			bubbles: true,
5943		//	|			screenX: 33,
5944		//	|			screenY: 44
5945		//	|		});
5946		//		We can also fire our own custom events:
5947		//	|		on.emit(dom.byId("slider"), "slide", {
5948		//	|			cancelable: true,
5949		//	|			bubbles: true,
5950		//	|			direction: "left-to-right"
5951		//	|		});
5952		//	|	});
5953		var args = slice.call(arguments, 2);
5954		var method = "on" + type;
5955		if("parentNode" in target){
5956			// node (or node-like), create event controller methods
5957			var newEvent = args[0] = {};
5958			for(var i in event){
5959				newEvent[i] = event[i];
5960			}
5961			newEvent.preventDefault = syntheticPreventDefault;
5962			newEvent.stopPropagation = syntheticStopPropagation;
5963			newEvent.target = target;
5964			newEvent.type = type;
5965			event = newEvent;
5966		}
5967		do{
5968			// call any node which has a handler (note that ideally we would try/catch to simulate normal event propagation but that causes too much pain for debugging)
5969			target[method] && target[method].apply(target, args);
5970			// and then continue up the parent node chain if it is still bubbling (if started as bubbles and stopPropagation hasn't been called)
5971		}while(event && event.bubbles && (target = target.parentNode));
5972		return event && event.cancelable && event; // if it is still true (was cancelable and was cancelled), return the event to indicate default action should happen
5973	};
5974	var captures = has("event-focusin") ? {} : {focusin: "focus", focusout: "blur"};
5975	if(!has("event-stopimmediatepropagation")){
5976		var stopImmediatePropagation =function(){
5977			this.immediatelyStopped = true;
5978			this.modified = true; // mark it as modified so the event will be cached in IE
5979		};
5980		var addStopImmediate = function(listener){
5981			return function(event){
5982				if(!event.immediatelyStopped){// check to make sure it hasn't been stopped immediately
5983					event.stopImmediatePropagation = stopImmediatePropagation;
5984					return listener.apply(this, arguments);
5985				}
5986			};
5987		}
5988	} 
5989	if(has("dom-addeventlistener")){
5990		// emitter that works with native event handling
5991		on.emit = function(target, type, event){
5992			if(target.dispatchEvent && document.createEvent){
5993				// use the native event emitting mechanism if it is available on the target object
5994				// create a generic event				
5995				// we could create branch into the different types of event constructors, but 
5996				// that would be a lot of extra code, with little benefit that I can see, seems 
5997				// best to use the generic constructor and copy properties over, making it 
5998				// easy to have events look like the ones created with specific initializers
5999				var ownerDocument = target.ownerDocument || document;
6000				var nativeEvent = ownerDocument.createEvent("HTMLEvents");
6001				nativeEvent.initEvent(type, !!event.bubbles, !!event.cancelable);
6002				// and copy all our properties over
6003				for(var i in event){
6004					if(!(i in nativeEvent)){
6005						nativeEvent[i] = event[i];
6006					}
6007				}
6008				return target.dispatchEvent(nativeEvent) && nativeEvent;
6009			}
6010			return syntheticDispatch.apply(on, arguments); // emit for a non-node
6011		};
6012	}else{
6013		// no addEventListener, basically old IE event normalization
6014		on._fixEvent = function(evt, sender){
6015			// summary:
6016			//		normalizes properties on the event object including event
6017			//		bubbling methods, keystroke normalization, and x/y positions
6018			// evt:
6019			//		native event object
6020			// sender:
6021			//		node to treat as "currentTarget"
6022			if(!evt){
6023				var w = sender && (sender.ownerDocument || sender.document || sender).parentWindow || window;
6024				evt = w.event;
6025			}
6026			if(!evt){return evt;}
6027			try{
6028				if(lastEvent && evt.type == lastEvent.type  && evt.srcElement == lastEvent.target){
6029					// should be same event, reuse event object (so it can be augmented);
6030					// accessing evt.srcElement rather than evt.target since evt.target not set on IE until fixup below
6031					evt = lastEvent;
6032				}
6033			}catch(e){
6034				// will occur on IE on lastEvent.type reference if lastEvent points to a previous event that already
6035				// finished bubbling, but the setTimeout() to clear lastEvent hasn't fired yet
6036			}
6037			if(!evt.target){ // check to see if it has been fixed yet
6038				evt.target = evt.srcElement;
6039				evt.currentTarget = (sender || evt.srcElement);
6040				if(evt.type == "mouseover"){
6041					evt.relatedTarget = evt.fromElement;
6042				}
6043				if(evt.type == "mouseout"){
6044					evt.relatedTarget = evt.toElement;
6045				}
6046				if(!evt.stopPropagation){
6047					evt.stopPropagation = stopPropagation;
6048					evt.preventDefault = preventDefault;
6049				}
6050				switch(evt.type){
6051					case "keypress":
6052						var c = ("charCode" in evt ? evt.charCode : evt.keyCode);
6053						if (c==10){
6054							// CTRL-ENTER is CTRL-ASCII(10) on IE, but CTRL-ENTER on Mozilla
6055							c=0;
6056							evt.keyCode = 13;
6057						}else if(c==13||c==27){
6058							c=0; // Mozilla considers ENTER and ESC non-printable
6059						}else if(c==3){
6060							c=99; // Mozilla maps CTRL-BREAK to CTRL-c
6061						}
6062						// Mozilla sets keyCode to 0 when there is a charCode
6063						// but that stops the event on IE.
6064						evt.charCode = c;
6065						_setKeyChar(evt);
6066						break;
6067				}
6068			}
6069			return evt;
6070		};
6071		var lastEvent, IESignal = function(handle){
6072			this.handle = handle;
6073		};
6074		IESignal.prototype.remove = function(){
6075			delete _dojoIEListeners_[this.handle];
6076		};
6077		var fixListener = function(listener){
6078			// this is a minimal function for closing on the previous listener with as few as variables as possible
6079			return function(evt){
6080				evt = on._fixEvent(evt, this);
6081				var result = listener.call(this, evt);
6082				if(evt.modified){
6083					// cache the last event and reuse it if we can
6084					if(!lastEvent){
6085						setTimeout(function(){
6086							lastEvent = null;
6087						});
6088					}
6089					lastEvent = evt;
6090				}
6091				return result;
6092			};
6093		};
6094		var fixAttach = function(target, type, listener){
6095			listener = fixListener(listener);
6096			if(((target.ownerDocument ? target.ownerDocument.parentWindow : target.parentWindow || target.window || window) != top || 
6097						has("jscript") < 5.8) && 
6098					!has("config-_allow_leaks")){
6099				// IE will leak memory on certain handlers in frames (IE8 and earlier) and in unattached DOM nodes for JScript 5.7 and below.
6100				// Here we use global redirection to solve the memory leaks
6101				if(typeof _dojoIEListeners_ == "undefined"){
6102					_dojoIEListeners_ = [];
6103				}
6104				var emitter = target[type];
6105				if(!emitter || !emitter.listeners){
6106					var oldListener = emitter;
6107					emitter = Function('event', 'var callee = arguments.callee; for(var i = 0; i<callee.listeners.length; i++){var listener = _dojoIEListeners_[callee.listeners[i]]; if(listener){listener.call(this,event);}}');
6108					emitter.listeners = [];
6109					target[type] = emitter;
6110					emitter.global = this;
6111					if(oldListener){
6112						emitter.listeners.push(_dojoIEListeners_.push(oldListener) - 1);
6113					}
6114				}
6115				var handle;
6116				emitter.listeners.push(handle = (emitter.global._dojoIEListeners_.push(listener) - 1));
6117				return new IESignal(handle);
6118			}
6119			return aspect.after(target, type, listener, true);
6120		};
6121
6122		var _setKeyChar = function(evt){
6123			evt.keyChar = evt.charCode ? String.fromCharCode(evt.charCode) : '';
6124			evt.charOrCode = evt.keyChar || evt.keyCode;	// TODO: remove for 2.0
6125		};
6126		// Called in Event scope
6127		var stopPropagation = function(){
6128			this.cancelBubble = true;
6129		};
6130		var preventDefault = on._preventDefault = function(){
6131			// Setting keyCode to 0 is the only way to prevent certain keypresses (namely
6132			// ctrl-combinations that correspond to menu accelerator keys).
6133			// Otoh, it prevents upstream listeners from getting this information
6134			// Try to split the difference here by clobbering keyCode only for ctrl
6135			// combinations. If you still need to access the key upstream, bubbledKeyCode is
6136			// provided as a workaround.
6137			this.bubbledKeyCode = this.keyCode;
6138			if(this.ctrlKey){
6139				try{
6140					// squelch errors when keyCode is read-only
6141					// (e.g. if keyCode is ctrl or shift)
6142					this.keyCode = 0;
6143				}catch(e){
6144				}
6145			}
6146			this.defaultPrevented = true;
6147			this.returnValue = false;
6148			this.modified = true; // mark it as modified  (for defaultPrevented flag) so the event will be cached in IE
6149		};
6150	}
6151	if(has("touch")){ 
6152		var EventDelegate = function(){};
6153		var windowOrientation = window.orientation; 
6154		var fixTouchListener = function(listener){ 
6155			return function(originalEvent){ 
6156				//Event normalization(for ontouchxxx and resize): 
6157				//1.incorrect e.pageX|pageY in iOS 
6158				//2.there are no "e.rotation", "e.scale" and "onorientationchange" in Android
6159				//3.More TBD e.g. force | screenX | screenX | clientX | clientY | radiusX | radiusY
6160
6161				// see if it has already been corrected
6162				var event = originalEvent.corrected;
6163				if(!event){
6164					var type = originalEvent.type;
6165					try{
6166						delete originalEvent.type; // on some JS engines (android), deleting properties makes them mutable
6167					}catch(e){} 
6168					if(originalEvent.type){
6169						// Deleting the property of the original event did not work (this is the case of
6170						// browsers such as older Safari iOS), hence fallback:
6171						if(has("touch-can-modify-event-delegate")){
6172							// If deleting properties of delegated event works, use event delegation:
6173							EventDelegate.prototype = originalEvent;
6174							event = new EventDelegate;
6175						}else{
6176							// Otherwise last fallback: other browsers, such as mobile Firefox, do not like
6177							// delegated properties, so we have to copy
6178							event = {};
6179							for(var name in originalEvent){
6180								event[name] = originalEvent[name];
6181							}
6182						}
6183						// have to delegate methods to make them work
6184						event.preventDefault = function(){
6185							originalEvent.preventDefault();
6186						};
6187						event.stopPropagation = function(){
6188							originalEvent.stopPropagation();
6189						};
6190					}else{
6191						// deletion worked, use property as is
6192						event = originalEvent;
6193						event.type = type;
6194					}
6195					originalEvent.corrected = event;
6196					if(type == 'resize'){
6197						if(windowOrientation == window.orientation){ 
6198							return null;//double tap causes an unexpected 'resize' in Android
6199						} 
6200						windowOrientation = window.orientation;
6201						event.type = "orientationchange"; 
6202						return listener.call(this, event);
6203					}
6204					// We use the original event and augment, rather than doing an expensive mixin operation
6205					if(!("rotation" in event)){ // test to see if it has rotation
6206						event.rotation = 0; 
6207						event.scale = 1;
6208					}
6209					//use event.changedTouches[0].pageX|pageY|screenX|screenY|clientX|clientY|target
6210					var firstChangeTouch = event.changedTouches[0];
6211					for(var i in firstChangeTouch){ // use for-in, we don't need to have dependency on dojo/_base/lang here
6212						delete event[i]; // delete it first to make it mutable
6213						event[i] = firstChangeTouch[i];
6214					}
6215				}
6216				return listener.call(this, event); 
6217			}; 
6218		}; 
6219	}
6220	return on;
6221});
6222
6223},
6224'dojo/topic':function(){
6225define(["./Evented"], function(Evented){
6226
6227	// module:
6228	//		dojo/topic
6229
6230	var hub = new Evented;
6231	return {
6232		// summary:
6233		//		Pubsub hub.
6234		// example:
6235		//		| 	topic.subscribe("some/topic", function(event){
6236		//		|	... do something with event
6237		//		|	});
6238		//		|	topic.publish("some/topic", {name:"some event", ...});
6239
6240		publish: function(topic, event){
6241			// summary:
6242			//		Publishes a message to a topic on the pub/sub hub. All arguments after
6243			//		the first will be passed to the subscribers, so any number of arguments
6244			//		can be provided (not just event).
6245			// topic: String
6246			//		The name of the topic to publish to
6247			// event: Object
6248			//		An event to distribute to the topic listeners
6249			return hub.emit.apply(hub, arguments);
6250		},
6251
6252		subscribe: function(topic, listener){
6253			// summary:
6254			//		Subscribes to a topic on the pub/sub hub
6255			// topic: String
6256			//		The topic to subscribe to
6257			// listener: Function
6258			//		A function to call when a message is published to the given topic
6259			return hub.on.apply(hub, arguments);
6260		}
6261	};
6262});
6263
6264},
6265'dojo/Evented':function(){
6266define(["./aspect", "./on"], function(aspect, on){
6267	// module:
6268	//		dojo/Evented
6269
6270 	"use strict";
6271 	var after = aspect.after;
6272	function Evented(){
6273		// summary:
6274		//		A class that can be used as a mixin or base class,
6275		//		to add on() and emit() methods to a class
6276		//		for listening for events and emitting events:
6277		// example:
6278		//		|	define(["dojo/Evented", "dojo/_base/declare", "dojo/Stateful"
6279		//		|	], function(Evented, declare, Stateful){
6280		//		|		var EventedStateful = declare([Evented, Stateful], {...});
6281		//		|		var instance = new EventedStateful();
6282		//		|		instance.on("open", function(event){
6283		//		|		... do something with event
6284		//		|	 });
6285		//		|
6286		//		|	instance.emit("open", {name:"some event", ...});
6287	}
6288	Evented.prototype = {
6289		on: function(type, listener){
6290			return on.parse(this, type, listener, function(target, type){
6291				return after(target, 'on' + type, listener, true);
6292			});
6293		},
6294		emit: function(type, event){
6295			var args = [this];
6296			args.push.apply(args, arguments);
6297			return on.emit.apply(on, args);
6298		}
6299	};
6300	return Evented;
6301});
6302
6303},
6304'dojo/aspect':function(){
6305define([], function(){
6306
6307	// module:
6308	//		dojo/aspect
6309
6310	"use strict";
6311	var undefined, nextId = 0;
6312	function advise(dispatcher, type, advice, receiveArguments){
6313		var previous = dispatcher[type];
6314		var around = type == "around";
6315		var signal;
6316		if(around){
6317			var advised = advice(function(){
6318				return previous.advice(this, arguments);
6319			});
6320			signal = {
6321				remove: function(){
6322					if(advised){
6323						advised = dispatcher = advice = null;
6324					}
6325				},
6326				advice: function(target, args){
6327					return advised ?
6328						advised.apply(target, args) :  // called the advised function
6329						previous.advice(target, args); // cancelled, skip to next one
6330				}
6331			};
6332		}else{
6333			// create the remove handler
6334			signal = {
6335				remove: function(){
6336					if(signal.advice){
6337						var previous = signal.previous;
6338						var next = signal.next;
6339						if(!next && !previous){
6340							delete dispatcher[type];
6341						}else{
6342							if(previous){
6343								previous.next = next;
6344							}else{
6345								dispatcher[type] = next;
6346							}
6347							if(next){
6348								next.previous = previous;
6349							}
6350						}
6351
6352						// remove the advice to signal that this signal has been removed
6353						dispatcher = advice = signal.advice = null;
6354					}
6355				},
6356				id: nextId++,
6357				advice: advice,
6358				receiveArguments: receiveArguments
6359			};
6360		}
6361		if(previous && !around){
6362			if(type == "after"){
6363				// add the listener to the end of the list
6364				// note that we had to change this loop a little bit to workaround a bizarre IE10 JIT bug
6365				while(previous.next && (previous = previous.next)){}
6366				previous.next = signal;
6367				signal.previous = previous;
6368			}else if(type == "before"){
6369				// add to beginning
6370				dispatcher[type] = signal;
6371				signal.next = previous;
6372				previous.previous = signal;
6373			}
6374		}else{
6375			// around or first one just replaces
6376			dispatcher[type] = signal;
6377		}
6378		return signal;
6379	}
6380	function aspect(type){
6381		return function(target, methodName, advice, receiveArguments){
6382			var existing = target[methodName], dispatcher;
6383			if(!existing || existing.target != target){
6384				// no dispatcher in place
6385				target[methodName] = dispatcher = function(){
6386					var executionId = nextId;
6387					// before advice
6388					var args = arguments;
6389					var before = dispatcher.before;
6390					while(before){
6391						args = before.advice.apply(this, args) || args;
6392						before = before.next;
6393					}
6394					// around advice
vendor: 4,726 bytes, lines 6395-6496
6395					if(dispatcher.around){
6396						var results = dispatcher.around.advice(this, args);
6397					}
6398					// after advice
6399					var after = dispatcher.after;
6400					while(after && after.id < executionId){
6401						if(after.receiveArguments){
6402							var newResults = after.advice.apply(this, args);
6403							// change the return value only if a new value was returned
6404							results = newResults === undefined ? results : newResults;
6405						}else{
6406							results = after.advice.call(this, results, args);
6407						}
6408						after = after.next;
6409					}
6410					return results;
6411				};
6412				if(existing){
6413					dispatcher.around = {advice: function(target, args){
6414						return existing.apply(target, args);
6415					}};
6416				}
6417				dispatcher.target = target;
6418			}
6419			var results = advise((dispatcher || existing), type, advice, receiveArguments);
6420			advice = null;
6421			return results;
6422		};
6423	}
6424
6425	// TODOC: after/before/around return object
6426
6427	var after = aspect("after");
6428	/*=====
6429	after = function(target, methodName, advice, receiveArguments){
6430		// summary:
6431		//		The "after" export of the aspect module is a function that can be used to attach
6432		//		"after" advice to a method. This function will be executed after the original method
6433		//		is executed. By default the function will be called with a single argument, the return
6434		//		value of the original method, or the the return value of the last executed advice (if a previous one exists).
6435		//		The fourth (optional) argument can be set to true to so the function receives the original
6436		//		arguments (from when the original method was called) rather than the return value.
6437		//		If there are multiple "after" advisors, they are executed in the order they were registered.
6438		// target: Object
6439		//		This is the target object
6440		// methodName: String
6441		//		This is the name of the method to attach to.
6442		// advice: Function
6443		//		This is function to be called after the original method
6444		// receiveArguments: Boolean?
6445		//		If this is set to true, the advice function receives the original arguments (from when the original mehtod
6446		//		was called) rather than the return value of the original/previous method.
6447		// returns:
6448		//		A signal object that can be used to cancel the advice. If remove() is called on this signal object, it will
6449		//		stop the advice function from being executed.
6450	};
6451	=====*/
6452
6453	var before = aspect("before");
6454	/*=====
6455	before = function(target, methodName, advice){
6456		// summary:
6457		//		The "before" export of the aspect module is a function that can be used to attach
6458		//		"before" advice to a method. This function will be executed before the original method
6459		//		is executed. This function will be called with the arguments used to call the method.
6460		//		This function may optionally return an array as the new arguments to use to call
6461		//		the original method (or the previous, next-to-execute before advice, if one exists).
6462		//		If the before method doesn't return anything (returns undefined) the original arguments
6463		//		will be preserved.
6464		//		If there are multiple "before" advisors, they are executed in the reverse order they were registered.
6465		// target: Object
6466		//		This is the target object
6467		// methodName: String
6468		//		This is the name of the method to attach to.
6469		// advice: Function
6470		//		This is function to be called before the original method
6471	};
6472	=====*/
6473
6474	var around = aspect("around");
6475	/*=====
6476	 around = function(target, methodName, advice){
6477		// summary:
6478		//		The "around" export of the aspect module is a function that can be used to attach
6479		//		"around" advice to a method. The advisor function is immediately executed when
6480		//		the around() is called, is passed a single argument that is a function that can be
6481		//		called to continue execution of the original method (or the next around advisor).
6482		//		The advisor function should return a function, and this function will be called whenever
6483		//		the method is called. It will be called with the arguments used to call the method.
6484		//		Whatever this function returns will be returned as the result of the method call (unless after advise changes it).
6485		// example:
6486		//		If there are multiple "around" advisors, the most recent one is executed first,
6487		//		which can then delegate to the next one and so on. For example:
6488		//		|	around(obj, "foo", function(originalFoo){
6489		//		|		return function(){
6490		//		|			var start = new Date().getTime();
6491		//		|			var results = originalFoo.apply(this, arguments); // call the original
6492		//		|			var end = new Date().getTime();
6493		//		|			console.log("foo execution took " + (end - start) + " ms");
6494		//		|			return results;
6495		//		|		};
6496		//		|	});
6497		// target: Object
6498		//		This is the target object
6499		// methodName: String
6500		//		This is the name of the method to attach to.
6501		// advice: Function
6502		//		This is function to be called around the original method
6503	};
6504	=====*/
6505
6506	return {
6507		// summary:
6508		//		provides aspect oriented programming functionality, allowing for
6509		//		one to add before, around, or after advice on existing methods.
6510		// example:
6511		//	|	define(["dojo/aspect"], function(aspect){
6512		//	|		var signal = aspect.after(targetObject, "methodName", function(someArgument){
6513		//	|			this will be called when targetObject.methodName() is called, after the original function is called
6514		//	|		});
6515		//
6516		// example:
6517		//	The returned signal object can be used to cancel the advice.
6518		//	|	signal.remove(); // this will stop the advice from being executed anymore
6519		//	|	aspect.before(targetObject, "methodName", function(someArgument){
6520		//	|		// this will be called when targetObject.methodName() is called, before the original function is called
6521		//	|	 });
6522
6523		before: before,
6524		around: around,
6525		after: after
6526	};
6527});
6528
6529},
6530'dojo/_base/event':function(){
6531define(["./kernel", "../on", "../has", "../dom-geometry"], function(dojo, on, has, dom){
6532	// module:
6533	//		dojo/_base/event
6534
6535	if(on._fixEvent){
6536		var fixEvent = on._fixEvent;
6537		on._fixEvent = function(evt, se){
6538			// add some additional normalization for back-compat, this isn't in on.js because it is somewhat more expensive
6539			evt = fixEvent(evt, se);
6540			if(evt){
6541				dom.normalizeEvent(evt);
6542			}
6543			return evt;
6544		};		
6545	}
6546	
6547	var ret = {
6548		// summary:
6549		//		This module defines dojo DOM event API.   Usually you should use dojo/on, and evt.stopPropagation() +
6550		//		evt.preventDefault(), rather than this module.
6551
6552		fix: function(/*Event*/ evt, /*DOMNode*/ sender){
6553			// summary:
6554			//		normalizes properties on the event object including event
6555			//		bubbling methods, keystroke normalization, and x/y positions
6556			// evt: Event
6557			//		native event object
6558			// sender: DOMNode
6559			//		node to treat as "currentTarget"
6560			if(on._fixEvent){
6561				return on._fixEvent(evt, sender);
6562			}
6563			return evt;	// Event
6564		},
6565	
6566		stop: function(/*Event*/ evt){
6567			// summary:
6568			//		prevents propagation and clobbers the default action of the
6569			//		passed event
6570			// evt: Event
6571			//		The event object. If omitted, window.event is used on IE.
6572			if(has("dom-addeventlistener") || (evt && evt.preventDefault)){
6573				evt.preventDefault();
6574				evt.stopPropagation();
6575			}else{
6576				evt = evt || window.event;
6577				evt.cancelBubble = true;
6578				on._preventDefault.call(evt);
6579			}
6580		}
6581	};
6582
6583	if( 1 ){
6584		dojo.fixEvent = ret.fix;
6585		dojo.stopEvent = ret.stop;
6586	}
6587
6588	return ret;
6589});
6590
6591},
6592'dojo/dom-geometry':function(){
6593define(["./sniff", "./_base/window","./dom", "./dom-style"],
6594		function(has, win, dom, style){
6595	// module:
6596	//		dojo/dom-geometry
6597
6598	// the result object
6599	var geom = {
6600		// summary:
6601		//		This module defines the core dojo DOM geometry API.
6602	};
6603
6604	// Box functions will assume this model.
6605	// On IE/Opera, BORDER_BOX will be set if the primary document is in quirks mode.
6606	// Can be set to change behavior of box setters.
6607
6608	// can be either:
6609	//	"border-box"
6610	//	"content-box" (default)
6611	geom.boxModel = "content-box";
6612
6613	// We punt per-node box mode testing completely.
6614	// If anybody cares, we can provide an additional (optional) unit
6615	// that overrides existing code to include per-node box sensitivity.
6616
6617	// Opera documentation claims that Opera 9 uses border-box in BackCompat mode.
6618	// but experiments (Opera 9.10.8679 on Windows Vista) indicate that it actually continues to use content-box.
6619	// IIRC, earlier versions of Opera did in fact use border-box.
6620	// Opera guys, this is really confusing. Opera being broken in quirks mode is not our fault.
6621
6622	if(has("ie") /*|| has("opera")*/){
6623		// client code may have to adjust if compatMode varies across iframes
6624		geom.boxModel = document.compatMode == "BackCompat" ? "border-box" : "content-box";
6625	}
6626
6627	geom.getPadExtents = function getPadExtents(/*DomNode*/ node, /*Object*/ computedStyle){
6628		// summary:
6629		//		Returns object with special values specifically useful for node
6630		//		fitting.
6631		// description:
6632		//		Returns an object with `w`, `h`, `l`, `t` properties:
6633		//	|		l/t/r/b = left/top/right/bottom padding (respectively)
6634		//	|		w = the total of the left and right padding
6635		//	|		h = the total of the top and bottom padding
6636		//		If 'node' has position, l/t forms the origin for child nodes.
6637		//		The w/h are used for calculating boxes.
6638		//		Normally application code will not need to invoke this
6639		//		directly, and will use the ...box... functions instead.
6640		// node: DOMNode
6641		// computedStyle: Object?
6642		//		This parameter accepts computed styles object.
6643		//		If this parameter is omitted, the functions will call
6644		//		dojo/dom-style.getComputedStyle to get one. It is a better way, calling
6645		//		dojo/dom-style.getComputedStyle once, and then pass the reference to this
6646		//		computedStyle parameter. Wherever possible, reuse the returned
6647		//		object of dojo/dom-style.getComputedStyle().
6648
6649		node = dom.byId(node);
6650		var s = computedStyle || style.getComputedStyle(node), px = style.toPixelValue,
6651			l = px(node, s.paddingLeft), t = px(node, s.paddingTop), r = px(node, s.paddingRight), b = px(node, s.paddingBottom);
6652		return {l: l, t: t, r: r, b: b, w: l + r, h: t + b};
6653	};
6654
6655	var none = "none";
6656
6657	geom.getBorderExtents = function getBorderExtents(/*DomNode*/ node, /*Object*/ computedStyle){
6658		// summary:
6659		//		returns an object with properties useful for noting the border
6660		//		dimensions.
6661		// description:
6662		//		- l/t/r/b = the sum of left/top/right/bottom border (respectively)
6663		//		- w = the sum of the left and right border
6664		//		- h = the sum of the top and bottom border
6665		//
6666		//		The w/h are used for calculating boxes.
6667		//		Normally application code will not need to invoke this
6668		//		directly, and will use the ...box... functions instead.
6669		// node: DOMNode
6670		// computedStyle: Object?
6671		//		This parameter accepts computed styles object.
6672		//		If this parameter is omitted, the functions will call
6673		//		dojo/dom-style.getComputedStyle to get one. It is a better way, calling
6674		//		dojo/dom-style.getComputedStyle once, and then pass the reference to this
6675		//		computedStyle parameter. Wherever possible, reuse the returned
6676		//		object of dojo/dom-style.getComputedStyle().
6677
6678		node = dom.byId(node);
6679		var px = style.toPixelValue, s = computedStyle || style.getComputedStyle(node),
6680			l = s.borderLeftStyle != none ? px(node, s.borderLeftWidth) : 0,
6681			t = s.borderTopStyle != none ? px(node, s.borderTopWidth) : 0,
6682			r = s.borderRightStyle != none ? px(node, s.borderRightWidth) : 0,
6683			b = s.borderBottomStyle != none ? px(node, s.borderBottomWidth) : 0;
6684		return {l: l, t: t, r: r, b: b, w: l + r, h: t + b};
6685	};
6686
6687	geom.getPadBorderExtents = function getPadBorderExtents(/*DomNode*/ node, /*Object*/ computedStyle){
6688		// summary:
6689		//		Returns object with properties useful for box fitting with
6690		//		regards to padding.
6691		// description:
6692		//		- l/t/r/b = the sum of left/top/right/bottom padding and left/top/right/bottom border (respectively)
6693		//		- w = the sum of the left and right padding and border
6694		//		- h = the sum of the top and bottom padding and border
6695		//
6696		//		The w/h are used for calculating boxes.
6697		//		Normally application code will not need to invoke this
6698		//		directly, and will use the ...box... functions instead.
6699		// node: DOMNode
6700		// computedStyle: Object?
6701		//		This parameter accepts computed styles object.
6702		//		If this parameter is omitted, the functions will call
6703		//		dojo/dom-style.getComputedStyle to get one. It is a better way, calling
6704		//		dojo/dom-style.getComputedStyle once, and then pass the reference to this
6705		//		computedStyle parameter. Wherever possible, reuse the returned
6706		//		object of dojo/dom-style.getComputedStyle().
6707
6708		node = dom.byId(node);
6709		var s = computedStyle || style.getComputedStyle(node),
6710			p = geom.getPadExtents(node, s),
6711			b = geom.getBorderExtents(node, s);
6712		return {
6713			l: p.l + b.l,
6714			t: p.t + b.t,
6715			r: p.r + b.r,
6716			b: p.b + b.b,
6717			w: p.w + b.w,
6718			h: p.h + b.h
6719		};
6720	};
6721
6722	geom.getMarginExtents = function getMarginExtents(node, computedStyle){
6723		// summary:
6724		//		returns object with properties useful for box fitting with
6725		//		regards to box margins (i.e., the outer-box).
6726		//
6727		//		- l/t = marginLeft, marginTop, respectively
6728		//		- w = total width, margin inclusive
6729		//		- h = total height, margin inclusive
6730		//
6731		//		The w/h are used for calculating boxes.
6732		//		Normally application code will not need to invoke this
6733		//		directly, and will use the ...box... functions instead.
6734		// node: DOMNode
6735		// computedStyle: Object?
6736		//		This parameter accepts computed styles object.
6737		//		If this parameter is omitted, the functions will call
6738		//		dojo/dom-style.getComputedStyle to get one. It is a better way, calling
6739		//		dojo/dom-style.getComputedStyle once, and then pass the reference to this
6740		//		computedStyle parameter. Wherever possible, reuse the returned
6741		//		object of dojo/dom-style.getComputedStyle().
6742
6743		node = dom.byId(node);
6744		var s = computedStyle || style.getComputedStyle(node), px = style.toPixelValue,
6745			l = px(node, s.marginLeft), t = px(node, s.marginTop), r = px(node, s.marginRight), b = px(node, s.marginBottom);
6746		return {l: l, t: t, r: r, b: b, w: l + r, h: t + b};
6747	};
6748
6749	// Box getters work in any box context because offsetWidth/clientWidth
6750	// are invariant wrt box context
6751	//
6752	// They do *not* work for display: inline objects that have padding styles
6753	// because the user agent ignores padding (it's bogus styling in any case)
6754	//
6755	// Be careful with IMGs because they are inline or block depending on
6756	// browser and browser mode.
6757
6758	// Although it would be easier to read, there are not separate versions of
6759	// _getMarginBox for each browser because:
6760	// 1. the branching is not expensive
6761	// 2. factoring the shared code wastes cycles (function call overhead)
6762	// 3. duplicating the shared code wastes bytes
6763
6764	geom.getMarginBox = function getMarginBox(/*DomNode*/ node, /*Object*/ computedStyle){
6765		// summary:
6766		//		returns an object that encodes the width, height, left and top
6767		//		positions of the node's margin box.
6768		// node: DOMNode
6769		// computedStyle: Object?
6770		//		This parameter accepts computed styles object.
6771		//		If this parameter is omitted, the functions will call
6772		//		dojo/dom-style.getComputedStyle to get one. It is a better way, calling
6773		//		dojo/dom-style.getComputedStyle once, and then pass the reference to this
6774		//		computedStyle parameter. Wherever possible, reuse the returned
6775		//		object of dojo/dom-style.getComputedStyle().
6776
6777		node = dom.byId(node);
6778		var s = computedStyle || style.getComputedStyle(node), me = geom.getMarginExtents(node, s),
6779			l = node.offsetLeft - me.l, t = node.offsetTop - me.t, p = node.parentNode, px = style.toPixelValue, pcs;
6780		if(has("mozilla")){
6781			// Mozilla:
6782			// If offsetParent has a computed overflow != visible, the offsetLeft is decreased
6783			// by the parent's border.
6784			// We don't want to compute the parent's style, so instead we examine node's
6785			// computed left/top which is more stable.
6786			var sl = parseFloat(s.left), st = parseFloat(s.top);
6787			if(!isNaN(sl) && !isNaN(st)){
6788				l = sl;
6789				t = st;
6790			}else{
6791				// If child's computed left/top are not parseable as a number (e.g. "auto"), we
6792				// have no choice but to examine the parent's computed style.
6793				if(p && p.style){
6794					pcs = style.getComputedStyle(p);
6795					if(pcs.overflow != "visible"){
6796						l += pcs.borderLeftStyle != none ? px(node, pcs.borderLeftWidth) : 0;
6797						t += pcs.borderTopStyle != none ? px(node, pcs.borderTopWidth) : 0;
6798					}
6799				}
6800			}
6801		}else if(has("opera") || (has("ie") == 8 && !has("quirks"))){
6802			// On Opera and IE 8, offsetLeft/Top includes the parent's border
6803			if(p){
6804				pcs = style.getComputedStyle(p);
6805				l -= pcs.borderLeftStyle != none ? px(node, pcs.borderLeftWidth) : 0;
6806				t -= pcs.borderTopStyle != none ? px(node, pcs.borderTopWidth) : 0;
6807			}
6808		}
6809		return {l: l, t: t, w: node.offsetWidth + me.w, h: node.offsetHeight + me.h};
6810	};
6811
6812	geom.getContentBox = function getContentBox(node, computedStyle){
6813		// summary:
6814		//		Returns an object that encodes the width, height, left and top
6815		//		positions of the node's content box, irrespective of the
6816		//		current box model.
6817		// node: DOMNode
6818		// computedStyle: Object?
6819		//		This parameter accepts computed styles object.
6820		//		If this parameter is omitted, the functions will call
6821		//		dojo/dom-style.getComputedStyle to get one. It is a better way, calling
6822		//		dojo/dom-style.getComputedStyle once, and then pass the reference to this
6823		//		computedStyle parameter. Wherever possible, reuse the returned
6824		//		object of dojo/dom-style.getComputedStyle().
6825
6826		// clientWidth/Height are important since the automatically account for scrollbars
6827		// fallback to offsetWidth/Height for special cases (see #3378)
6828		node = dom.byId(node);
6829		var s = computedStyle || style.getComputedStyle(node), w = node.clientWidth, h,
6830			pe = geom.getPadExtents(node, s), be = geom.getBorderExtents(node, s);
6831		if(!w){
6832			w = node.offsetWidth;
6833			h = node.offsetHeight;
6834		}else{
6835			h = node.clientHeight;
6836			be.w = be.h = 0;
6837		}
6838		// On Opera, offsetLeft includes the parent's border
6839		if(has("opera")){
6840			pe.l += be.l;
6841			pe.t += be.t;
6842		}
6843		return {l: pe.l, t: pe.t, w: w - pe.w - be.w, h: h - pe.h - be.h};
6844	};
6845
vendor: 4,701 bytes, lines 6846-6969
6846	// Box setters depend on box context because interpretation of width/height styles
6847	// vary wrt box context.
6848	//
6849	// The value of boxModel is used to determine box context.
6850	// boxModel can be set directly to change behavior.
6851	//
6852	// Beware of display: inline objects that have padding styles
6853	// because the user agent ignores padding (it's a bogus setup anyway)
6854	//
6855	// Be careful with IMGs because they are inline or block depending on
6856	// browser and browser mode.
6857	//
6858	// Elements other than DIV may have special quirks, like built-in
6859	// margins or padding, or values not detectable via computedStyle.
6860	// In particular, margins on TABLE do not seems to appear
6861	// at all in computedStyle on Mozilla.
6862
6863	function setBox(/*DomNode*/ node, /*Number?*/ l, /*Number?*/ t, /*Number?*/ w, /*Number?*/ h, /*String?*/ u){
6864		// summary:
6865		//		sets width/height/left/top in the current (native) box-model
6866		//		dimensions. Uses the unit passed in u.
6867		// node:
6868		//		DOM Node reference. Id string not supported for performance
6869		//		reasons.
6870		// l:
6871		//		left offset from parent.
6872		// t:
6873		//		top offset from parent.
6874		// w:
6875		//		width in current box model.
6876		// h:
6877		//		width in current box model.
6878		// u:
6879		//		unit measure to use for other measures. Defaults to "px".
6880		u = u || "px";
6881		var s = node.style;
6882		if(!isNaN(l)){
6883			s.left = l + u;
6884		}
6885		if(!isNaN(t)){
6886			s.top = t + u;
6887		}
6888		if(w >= 0){
6889			s.width = w + u;
6890		}
6891		if(h >= 0){
6892			s.height = h + u;
6893		}
6894	}
6895
6896	function isButtonTag(/*DomNode*/ node){
6897		// summary:
6898		//		True if the node is BUTTON or INPUT.type="button".
6899		return node.tagName.toLowerCase() == "button" ||
6900			node.tagName.toLowerCase() == "input" && (node.getAttribute("type") || "").toLowerCase() == "button"; // boolean
6901	}
6902
6903	function usesBorderBox(/*DomNode*/ node){
6904		// summary:
6905		//		True if the node uses border-box layout.
6906
6907		// We could test the computed style of node to see if a particular box
6908		// has been specified, but there are details and we choose not to bother.
6909
6910		// TABLE and BUTTON (and INPUT type=button) are always border-box by default.
6911		// If you have assigned a different box to either one via CSS then
6912		// box functions will break.
6913
6914		return geom.boxModel == "border-box" || node.tagName.toLowerCase() == "table" || isButtonTag(node); // boolean
6915	}
6916
6917	geom.setContentSize = function setContentSize(/*DomNode*/ node, /*Object*/ box, /*Object*/ computedStyle){
6918		// summary:
6919		//		Sets the size of the node's contents, irrespective of margins,
6920		//		padding, or borders.
6921		// node: DOMNode
6922		// box: Object
6923		//		hash with optional "w", and "h" properties for "width", and "height"
6924		//		respectively. All specified properties should have numeric values in whole pixels.
6925		// computedStyle: Object?
6926		//		This parameter accepts computed styles object.
6927		//		If this parameter is omitted, the functions will call
6928		//		dojo/dom-style.getComputedStyle to get one. It is a better way, calling
6929		//		dojo/dom-style.getComputedStyle once, and then pass the reference to this
6930		//		computedStyle parameter. Wherever possible, reuse the returned
6931		//		object of dojo/dom-style.getComputedStyle().
6932
6933		node = dom.byId(node);
6934		var w = box.w, h = box.h;
6935		if(usesBorderBox(node)){
6936			var pb = geom.getPadBorderExtents(node, computedStyle);
6937			if(w >= 0){
6938				w += pb.w;
6939			}
6940			if(h >= 0){
6941				h += pb.h;
6942			}
6943		}
6944		setBox(node, NaN, NaN, w, h);
6945	};
6946
6947	var nilExtents = {l: 0, t: 0, w: 0, h: 0};
6948
6949	geom.setMarginBox = function setMarginBox(/*DomNode*/ node, /*Object*/ box, /*Object*/ computedStyle){
6950		// summary:
6951		//		sets the size of the node's margin box and placement
6952		//		(left/top), irrespective of box model. Think of it as a
6953		//		passthrough to setBox that handles box-model vagaries for
6954		//		you.
6955		// node: DOMNode
6956		// box: Object
6957		//		hash with optional "l", "t", "w", and "h" properties for "left", "right", "width", and "height"
6958		//		respectively. All specified properties should have numeric values in whole pixels.
6959		// computedStyle: Object?
6960		//		This parameter accepts computed styles object.
6961		//		If this parameter is omitted, the functions will call
6962		//		dojo/dom-style.getComputedStyle to get one. It is a better way, calling
6963		//		dojo/dom-style.getComputedStyle once, and then pass the reference to this
6964		//		computedStyle parameter. Wherever possible, reuse the returned
6965		//		object of dojo/dom-style.getComputedStyle().
6966
6967		node = dom.byId(node);
6968		var s = computedStyle || style.getComputedStyle(node), w = box.w, h = box.h,
6969		// Some elements have special padding, margin, and box-model settings.
6970		// To use box functions you may need to set padding, margin explicitly.
6971		// Controlling box-model is harder, in a pinch you might set dojo/dom-geometry.boxModel.
6972			pb = usesBorderBox(node) ? nilExtents : geom.getPadBorderExtents(node, s),
6973			mb = geom.getMarginExtents(node, s);
6974		if(has("webkit")){
6975			// on Safari (3.1.2), button nodes with no explicit size have a default margin
6976			// setting an explicit size eliminates the margin.
6977			// We have to swizzle the width to get correct margin reading.
6978			if(isButtonTag(node)){
6979				var ns = node.style;
6980				if(w >= 0 && !ns.width){
6981					ns.width = "4px";
6982				}
6983				if(h >= 0 && !ns.height){
6984					ns.height = "4px";
6985				}
6986			}
6987		}
6988		if(w >= 0){
6989			w = Math.max(w - pb.w - mb.w, 0);
6990		}
6991		if(h >= 0){
6992			h = Math.max(h - pb.h - mb.h, 0);
6993		}
6994		setBox(node, box.l, box.t, w, h);
6995	};
6996
6997	// =============================
6998	// Positioning
6999	// =============================
7000
7001	geom.isBodyLtr = function isBodyLtr(/*Document?*/ doc){
7002		// summary:
7003		//		Returns true if the current language is left-to-right, and false otherwise.
7004		// doc: Document?
7005		//		Optional document to query.   If unspecified, use win.doc.
7006		// returns: Boolean
7007
7008		doc = doc || win.doc;
7009		return (win.body(doc).dir || doc.documentElement.dir || "ltr").toLowerCase() == "ltr"; // Boolean
7010	};
7011
7012	geom.docScroll = function docScroll(/*Document?*/ doc){
7013		// summary:
7014		//		Returns an object with {node, x, y} with corresponding offsets.
7015		// doc: Document?
7016		//		Optional document to query.   If unspecified, use win.doc.
7017		// returns: Object
7018
7019		doc = doc || win.doc;
7020		var node = win.doc.parentWindow || win.doc.defaultView;   // use UI window, not dojo.global window.   TODO: use dojo/window::get() except for circular dependency problem
7021		return "pageXOffset" in node ? {x: node.pageXOffset, y: node.pageYOffset } :
7022			(node = has("quirks") ? win.body(doc) : doc.documentElement) &&
7023				{x: geom.fixIeBiDiScrollLeft(node.scrollLeft || 0, doc), y: node.scrollTop || 0 };
7024	};
7025
7026	if(has("ie")){
7027		geom.getIeDocumentElementOffset = function getIeDocumentElementOffset(/*Document?*/ doc){
7028			// summary:
7029			//		returns the offset in x and y from the document body to the
7030			//		visual edge of the page for IE
7031			// doc: Document?
7032			//		Optional document to query.   If unspecified, use win.doc.
7033			// description:
7034			//		The following values in IE contain an offset:
7035			//	|		event.clientX
7036			//	|		event.clientY
7037			//	|		node.getBoundingClientRect().left
7038			//	|		node.getBoundingClientRect().top
7039			//		But other position related values do not contain this offset,
7040			//		such as node.offsetLeft, node.offsetTop, node.style.left and
7041			//		node.style.top. The offset is always (2, 2) in LTR direction.
7042			//		When the body is in RTL direction, the offset counts the width
7043			//		of left scroll bar's width.  This function computes the actual
7044			//		offset.
7045
7046			//NOTE: assumes we're being called in an IE browser
7047
7048			doc = doc || win.doc;
7049			var de = doc.documentElement; // only deal with HTML element here, position() handles body/quirks
7050
7051			if(has("ie") < 8){
7052				var r = de.getBoundingClientRect(), // works well for IE6+
7053					l = r.left, t = r.top;
7054				if(has("ie") < 7){
7055					l += de.clientLeft;	// scrollbar size in strict/RTL, or,
7056					t += de.clientTop;	// HTML border size in strict
7057				}
7058				return {
7059					x: l < 0 ? 0 : l, // FRAME element border size can lead to inaccurate negative values
7060					y: t < 0 ? 0 : t
7061				};
7062			}else{
7063				return {
7064					x: 0,
7065					y: 0
7066				};
7067			}
7068		};
7069	}
7070
7071	geom.fixIeBiDiScrollLeft = function fixIeBiDiScrollLeft(/*Integer*/ scrollLeft, /*Document?*/ doc){
7072		// summary:
7073		//		In RTL direction, scrollLeft should be a negative value, but IE
7074		//		returns a positive one. All codes using documentElement.scrollLeft
7075		//		must call this function to fix this error, otherwise the position
7076		//		will offset to right when there is a horizontal scrollbar.
7077		// scrollLeft: Number
7078		// doc: Document?
7079		//		Optional document to query.   If unspecified, use win.doc.
7080		// returns: Number
7081
7082		// In RTL direction, scrollLeft should be a negative value, but IE
7083		// returns a positive one. All codes using documentElement.scrollLeft
7084		// must call this function to fix this error, otherwise the position
7085		// will offset to right when there is a horizontal scrollbar.
7086
7087		doc = doc || win.doc;
7088		var ie = has("ie");
7089		if(ie && !geom.isBodyLtr(doc)){
7090			var qk = has("quirks"),
7091				de = qk ? win.body(doc) : doc.documentElement,
7092				pwin = win.global;	// TODO: use winUtils.get(doc) after resolving circular dependency b/w dom-geometry.js and dojo/window.js
7093			if(ie == 6 && !qk && pwin.frameElement && de.scrollHeight > de.clientHeight){
7094				scrollLeft += de.clientLeft; // workaround ie6+strict+rtl+iframe+vertical-scrollbar bug where clientWidth is too small by clientLeft pixels
7095			}
7096			return (ie < 8 || qk) ? (scrollLeft + de.clientWidth - de.scrollWidth) : -scrollLeft; // Integer
7097		}
7098		return scrollLeft; // Integer
7099	};
7100
7101	geom.position = function(/*DomNode*/ node, /*Boolean?*/ includeScroll){
7102		// summary:
7103		//		Gets the position and size of the passed element relative to
7104		//		the viewport (if includeScroll==false), or relative to the
7105		//		document root (if includeScroll==true).
7106		//
7107		// description:
7108		//		Returns an object of the form:
7109		//		`{ x: 100, y: 300, w: 20, h: 15 }`.
7110		//		If includeScroll==true, the x and y values will include any
7111		//		document offsets that may affect the position relative to the
7112		//		viewport.
7113		//		Uses the border-box model (inclusive of border and padding but
7114		//		not margin).  Does not act as a setter.
7115		// node: DOMNode|String
7116		// includeScroll: Boolean?
7117		// returns: Object
7118
7119		node = dom.byId(node);
7120		var	db = win.body(node.ownerDocument),
7121			ret = node.getBoundingClientRect();
7122		ret = {x: ret.left, y: ret.top, w: ret.right - ret.left, h: ret.bottom - ret.top};
7123
7124		if(has("ie") < 9){
7125			// On IE<9 there's a 2px offset that we need to adjust for, see dojo.getIeDocumentElementOffset()
7126			var offset = geom.getIeDocumentElementOffset(node.ownerDocument);
7127
7128			// fixes the position in IE, quirks mode
7129			ret.x -= offset.x + (has("quirks") ? db.clientLeft + db.offsetLeft : 0);
7130			ret.y -= offset.y + (has("quirks") ? db.clientTop + db.offsetTop : 0);
7131		}
7132
7133		// account for document scrolling
7134		// if offsetParent is used, ret value already includes scroll position
7135		// so we may have to actually remove that value if !includeScroll
7136		if(includeScroll){
7137			var scroll = geom.docScroll(node.ownerDocument);
7138			ret.x += scroll.x;
7139			ret.y += scroll.y;
7140		}
7141
7142		return ret; // Object
7143	};
7144
7145	// random "private" functions wildly used throughout the toolkit
7146
7147	geom.getMarginSize = function getMarginSize(/*DomNode*/ node, /*Object*/ computedStyle){
7148		// summary:
7149		//		returns an object that encodes the width and height of
7150		//		the node's margin box
7151		// node: DOMNode|String
7152		// computedStyle: Object?
7153		//		This parameter accepts computed styles object.
7154		//		If this parameter is omitted, the functions will call
7155		//		dojo/dom-style.getComputedStyle to get one. It is a better way, calling
7156		//		dojo/dom-style.getComputedStyle once, and then pass the reference to this
7157		//		computedStyle parameter. Wherever possible, reuse the returned
7158		//		object of dojo/dom-style.getComputedStyle().
7159
7160		node = dom.byId(node);
7161		var me = geom.getMarginExtents(node, computedStyle || style.getComputedStyle(node));
7162		var size = node.getBoundingClientRect();
7163		return {
7164			w: (size.right - size.left) + me.w,
7165			h: (size.bottom - size.top) + me.h
7166		};
7167	};
7168
7169	geom.normalizeEvent = function(event){
7170		// summary:
7171		//		Normalizes the geometry of a DOM event, normalizing the pageX, pageY,
7172		//		offsetX, offsetY, layerX, and layerX properties
7173		// event: Object
7174		if(!("layerX" in event)){
7175			event.layerX = event.offsetX;
7176			event.layerY = event.offsetY;
7177		}
7178		if(!has("dom-addeventlistener")){
7179			// old IE version
7180			// FIXME: scroll position query is duped from dojo/_base/html to
7181			// avoid dependency on that entire module. Now that HTML is in
7182			// Base, we should convert back to something similar there.
7183			var se = event.target;
7184			var doc = (se && se.ownerDocument) || document;
7185			// DO NOT replace the following to use dojo/_base/window.body(), in IE, document.documentElement should be used
7186			// here rather than document.body
7187			var docBody = has("quirks") ? doc.body : doc.documentElement;
7188			var offset = geom.getIeDocumentElementOffset(doc);
7189			event.pageX = event.clientX + geom.fixIeBiDiScrollLeft(docBody.scrollLeft || 0, doc) - offset.x;
7190			event.pageY = event.clientY + (docBody.scrollTop || 0) - offset.y;
7191		}
7192	};
7193
7194	// TODO: evaluate separate getters/setters for position and sizes?
7195
7196	return geom;
7197});
7198
7199},
7200'dojo/_base/window':function(){
7201define(["./kernel", "./lang", "../sniff"], function(dojo, lang, has){
7202// module:
7203//		dojo/_base/window
7204
7205var ret = {
7206	// summary:
7207	//		API to save/set/restore the global/document scope.
7208
7209	global: dojo.global,
7210	/*=====
7211	 global: {
7212		 // summary:
7213		 //		Alias for the current window. 'global' can be modified
7214		 //		for temporary context shifting. See also withGlobal().
7215		 // description:
7216		 //		Use this rather than referring to 'window' to ensure your code runs
7217		 //		correctly in managed contexts.
7218	 },
7219	 =====*/
7220
7221	doc: dojo.global["document"] || null,
7222	/*=====
7223	doc: {
7224		// summary:
7225		//		Alias for the current document. 'doc' can be modified
7226		//		for temporary context shifting. See also withDoc().
7227		// description:
7228		//		Use this rather than referring to 'window.document' to ensure your code runs
7229		//		correctly in managed contexts.
7230		// example:
7231		//	|	n.appendChild(dojo.doc.createElement('div'));
7232	},
7233	=====*/
7234
7235	body: function(/*Document?*/ doc){
7236		// summary:
7237		//		Return the body element of the specified document or of dojo/_base/window::doc.
7238		// example:
7239		//	|	win.body().appendChild(dojo.doc.createElement('div'));
7240
7241		// Note: document.body is not defined for a strict xhtml document
7242		// Would like to memoize this, but dojo.doc can change vi dojo.withDoc().
7243		doc = doc || dojo.doc;
7244		return doc.body || doc.getElementsByTagName("body")[0]; // Node
7245	},
7246
7247	setContext: function(/*Object*/ globalObject, /*DocumentElement*/ globalDocument){
7248		// summary:
7249		//		changes the behavior of many core Dojo functions that deal with
7250		//		namespace and DOM lookup, changing them to work in a new global
7251		//		context (e.g., an iframe). The varibles dojo.global and dojo.doc
7252		//		are modified as a result of calling this function and the result of
7253		//		`dojo.body()` likewise differs.
7254		dojo.global = ret.global = globalObject;
7255		dojo.doc = ret.doc = globalDocument;
7256	},
7257
7258	withGlobal: function(	/*Object*/ globalObject,
7259							/*Function*/ callback,
7260							/*Object?*/ thisObject,
7261							/*Array?*/ cbArguments){
7262		// summary:
7263		//		Invoke callback with globalObject as dojo.global and
7264		//		globalObject.document as dojo.doc.
7265		// description:
7266		//		Invoke callback with globalObject as dojo.global and
7267		//		globalObject.document as dojo.doc. If provided, globalObject
7268		//		will be executed in the context of object thisObject
7269		//		When callback() returns or throws an error, the dojo.global
7270		//		and dojo.doc will be restored to its previous state.
7271
7272		var oldGlob = dojo.global;
7273		try{
7274			dojo.global = ret.global = globalObject;
7275			return ret.withDoc.call(null, globalObject.document, callback, thisObject, cbArguments);
7276		}finally{
7277			dojo.global = ret.global = oldGlob;
7278		}
7279	},
7280
7281	withDoc: function(	/*DocumentElement*/ documentObject,
7282						/*Function*/ callback,
7283						/*Object?*/ thisObject,
7284						/*Array?*/ cbArguments){
7285		// summary:
7286		//		Invoke callback with documentObject as dojo/_base/window::doc.
7287		// description:
7288		//		Invoke callback with documentObject as dojo/_base/window::doc. If provided,
7289		//		callback will be executed in the context of object thisObject
7290		//		When callback() returns or throws an error, the dojo/_base/window::doc will
7291		//		be restored to its previous state.
7292
7293		var oldDoc = ret.doc,
7294			oldQ = has("quirks"),
7295			oldIE = has("ie"), isIE, mode, pwin;
7296
7297		try{
7298			dojo.doc = ret.doc = documentObject;
7299			// update dojo.isQuirks and the value of the has feature "quirks".
7300			// remove setting dojo.isQuirks and dojo.isIE for 2.0
7301			dojo.isQuirks = has.add("quirks", dojo.doc.compatMode == "BackCompat", true, true); // no need to check for QuirksMode which was Opera 7 only
7302
7303			if(has("ie")){
7304				if((pwin = documentObject.parentWindow) && pwin.navigator){
7305					// re-run IE detection logic and update dojo.isIE / has("ie")
7306					// (the only time parentWindow/navigator wouldn't exist is if we were not
7307					// passed an actual legitimate document object)
7308					isIE = parseFloat(pwin.navigator.appVersion.split("MSIE ")[1]) || undefined;
7309					mode = documentObject.documentMode;
7310					if(mode && mode != 5 && Math.floor(isIE) != mode){
7311						isIE = mode;
7312					}
7313					dojo.isIE = has.add("ie", isIE, true, true);
7314				}
7315			}
7316
7317			if(thisObject && typeof callback == "string"){
7318				callback = thisObject[callback];
7319			}
7320
7321			return callback.apply(thisObject, cbArguments || []);
7322		}finally{
7323			dojo.doc = ret.doc = oldDoc;
7324			dojo.isQuirks = has.add("quirks", oldQ, true, true);
7325			dojo.isIE = has.add("ie", oldIE, true, true);
7326		}
7327	}
7328};
7329
7330 1  && lang.mixin(dojo, ret);
7331
7332return ret;
7333
7334});
7335
7336},
7337'dojo/dom':function(){
7338define(["./sniff", "./_base/window"],
7339		function(has, win){
7340	// module:
7341	//		dojo/dom
7342
7343	// FIXME: need to add unit tests for all the semi-public methods
7344
7345	if(has("ie") <= 7){
7346		try{
vendor: 4,151 bytes, lines 7347-7481
7347			document.execCommand("BackgroundImageCache", false, true);
7348		}catch(e){
7349			// sane browsers don't have cache "issues"
7350		}
7351	}
7352
7353	// =============================
7354	// DOM Functions
7355	// =============================
7356
7357	// the result object
7358	var dom = {
7359		// summary:
7360		//		This module defines the core dojo DOM API.
7361	};
7362
7363	if(has("ie")){
7364		dom.byId = function(id, doc){
7365			if(typeof id != "string"){
7366				return id;
7367			}
7368			var _d = doc || win.doc, te = id && _d.getElementById(id);
7369			// attributes.id.value is better than just id in case the
7370			// user has a name=id inside a form
7371			if(te && (te.attributes.id.value == id || te.id == id)){
7372				return te;
7373			}else{
7374				var eles = _d.all[id];
7375				if(!eles || eles.nodeName){
7376					eles = [eles];
7377				}
7378				// if more than 1, choose first with the correct id
7379				var i = 0;
7380				while((te = eles[i++])){
7381					if((te.attributes && te.attributes.id && te.attributes.id.value == id) || te.id == id){
7382						return te;
7383					}
7384				}
7385			}
7386		};
7387	}else{
7388		dom.byId = function(id, doc){
7389			// inline'd type check.
7390			// be sure to return null per documentation, to match IE branch.
7391			return ((typeof id == "string") ? (doc || win.doc).getElementById(id) : id) || null; // DOMNode
7392		};
7393	}
7394	/*=====
7395	 dom.byId = function(id, doc){
7396		// summary:
7397		//		Returns DOM node with matching `id` attribute or falsy value (ex: null or undefined)
7398		//		if not found.  If `id` is a DomNode, this function is a no-op.
7399		//
7400		// id: String|DOMNode
7401		//		A string to match an HTML id attribute or a reference to a DOM Node
7402		//
7403		// doc: Document?
7404		//		Document to work in. Defaults to the current value of
7405		//		dojo/_base/window.doc.  Can be used to retrieve
7406		//		node references from other documents.
7407		//
7408		// example:
7409		//		Look up a node by ID:
7410		//	|	require(["dojo/dom"], function(dom){
7411		//	|		var n = dom.byId("foo");
7412		//	|	});
7413		//
7414		// example:
7415		//		Check if a node exists, and use it.
7416		//	|	require(["dojo/dom"], function(dom){
7417		//	|		var n = dom.byId("bar");
7418		//	|		if(n){ doStuff() ... }
7419		//	|	});
7420		//
7421		// example:
7422		//		Allow string or DomNode references to be passed to a custom function:
7423		//	|	require(["dojo/dom"], function(dom){
7424		//	|		var foo = function(nodeOrId){
7425		//	|			nodeOrId = dom.byId(nodeOrId);
7426		//	|			// ... more stuff
7427		//	|		}
7428		//	|	});
7429	 };
7430	 =====*/
7431
7432	dom.isDescendant = function(/*DOMNode|String*/ node, /*DOMNode|String*/ ancestor){
7433		// summary:
7434		//		Returns true if node is a descendant of ancestor
7435		// node: DOMNode|String
7436		//		string id or node reference to test
7437		// ancestor: DOMNode|String
7438		//		string id or node reference of potential parent to test against
7439		//
7440		// example:
7441		//		Test is node id="bar" is a descendant of node id="foo"
7442		//	|	require(["dojo/dom"], function(dom){
7443		//	|		if(dom.isDescendant("bar", "foo")){ ... }
7444		//	|	});
7445
7446		try{
7447			node = dom.byId(node);
7448			ancestor = dom.byId(ancestor);
7449			while(node){
7450				if(node == ancestor){
7451					return true; // Boolean
7452				}
7453				node = node.parentNode;
7454			}
7455		}catch(e){ /* squelch, return false */ }
7456		return false; // Boolean
7457	};
7458
7459
7460	// TODO: do we need setSelectable in the base?
7461
7462	// Add feature test for user-select CSS property
7463	// (currently known to work in all but IE < 10 and Opera)
7464	// TODO: The user-select CSS property as of May 2014 is no longer part of
7465	// any CSS specification. In IE, -ms-user-select does not do the same thing
7466	// as the unselectable attribute on elements; namely, dijit Editor buttons
7467	// do not properly prevent the content of the editable content frame from
7468	// unblurring. As a result, the -ms- prefixed version is omitted here.
7469	has.add("css-user-select", function(global, doc, element){
7470		// Avoid exception when dom.js is loaded in non-browser environments
7471		if(!element){ return false; }
7472		
7473		var style = element.style;
7474		var prefixes = ["Khtml", "O", "Moz", "Webkit"],
7475			i = prefixes.length,
7476			name = "userSelect",
7477			prefix;
7478
7479		// Iterate prefixes from most to least likely
7480		do{
7481			if(typeof style[name] !== "undefined"){
7482				// Supported; return property name
7483				return name;
7484			}
7485		}while(i-- && (name = prefixes[i] + "UserSelect"));
7486
7487		// Not supported if we didn't return before now
7488		return false;
7489	});
7490
7491	/*=====
7492	dom.setSelectable = function(node, selectable){
7493		// summary:
7494		//		Enable or disable selection on a node
7495		// node: DOMNode|String
7496		//		id or reference to node
7497		// selectable: Boolean
7498		//		state to put the node in. false indicates unselectable, true
7499		//		allows selection.
7500		// example:
7501		//		Make the node id="bar" unselectable
7502		//	|	require(["dojo/dom"], function(dom){
7503		//	|		dom.setSelectable("bar");
7504		//	|	});
7505		// example:
7506		//		Make the node id="bar" selectable
7507		//	|	require(["dojo/dom"], function(dom){
7508		//	|		dom.setSelectable("bar", true);
7509		//	|	});
7510	};
7511	=====*/
7512
7513	var cssUserSelect = has("css-user-select");
7514	dom.setSelectable = cssUserSelect ? function(node, selectable){
7515		// css-user-select returns a (possibly vendor-prefixed) CSS property name
7516		dom.byId(node).style[cssUserSelect] = selectable ? "" : "none";
7517	} : function(node, selectable){
7518		node = dom.byId(node);
7519
7520		// (IE < 10 / Opera) Fall back to setting/removing the
7521		// unselectable attribute on the element and all its children
7522		var nodes = node.getElementsByTagName("*"),
7523			i = nodes.length;
7524
7525		if(selectable){
7526			node.removeAttribute("unselectable");
7527			while(i--){
7528				nodes[i].removeAttribute("unselectable");
7529			}
7530		}else{
7531			node.setAttribute("unselectable", "on");
7532			while(i--){
7533				nodes[i].setAttribute("unselectable", "on");
7534			}
7535		}
7536	};
7537
7538	return dom;
7539});
7540
7541},
7542'dojo/dom-style':function(){
7543define(["./sniff", "./dom"], function(has, dom){
7544	// module:
7545	//		dojo/dom-style
7546
7547	// =============================
7548	// Style Functions
7549	// =============================
7550
7551	// getComputedStyle drives most of the style code.
7552	// Wherever possible, reuse the returned object.
7553	//
7554	// API functions below that need to access computed styles accept an
7555	// optional computedStyle parameter.
7556	// If this parameter is omitted, the functions will call getComputedStyle themselves.
7557	// This way, calling code can access computedStyle once, and then pass the reference to
7558	// multiple API functions.
7559
7560	// Although we normally eschew argument validation at this
7561	// level, here we test argument 'node' for (duck)type,
7562	// by testing nodeType, ecause 'document' is the 'parentNode' of 'body'
7563	// it is frequently sent to this function even
7564	// though it is not Element.
7565	var getComputedStyle, style = {
7566		// summary:
7567		//		This module defines the core dojo DOM style API.
7568	};
7569	if(has("webkit")){
7570		getComputedStyle = function(/*DomNode*/ node){
7571			var s;
7572			if(node.nodeType == 1){
7573				var dv = node.ownerDocument.defaultView;
7574				s = dv.getComputedStyle(node, null);
7575				if(!s && node.style){
7576					node.style.display = "";
7577					s = dv.getComputedStyle(node, null);
7578				}
7579			}
7580			return s || {};
7581		};
7582	}
vendor: 9,086 bytes, lines 7582-7842
7582else if(has("ie") && (has("ie") < 9 || has("quirks"))){
7583		getComputedStyle = function(node){
7584			// IE (as of 7) doesn't expose Element like sane browsers
7585			// currentStyle can be null on IE8!
7586			return node.nodeType == 1 /* ELEMENT_NODE*/ && node.currentStyle ? node.currentStyle : {};
7587		};
7588	}else{
7589		getComputedStyle = function(node){
7590			return node.nodeType == 1 /* ELEMENT_NODE*/ ?
7591				node.ownerDocument.defaultView.getComputedStyle(node, null) : {};
7592		};
7593	}
7594	style.getComputedStyle = getComputedStyle;
7595	/*=====
7596	style.getComputedStyle = function(node){
7597		// summary:
7598		//		Returns a "computed style" object.
7599		//
7600		// description:
7601		//		Gets a "computed style" object which can be used to gather
7602		//		information about the current state of the rendered node.
7603		//
7604		//		Note that this may behave differently on different browsers.
7605		//		Values may have different formats and value encodings across
7606		//		browsers.
7607		//
7608		//		Note also that this method is expensive.  Wherever possible,
7609		//		reuse the returned object.
7610		//
7611		//		Use the dojo/dom-style.get() method for more consistent (pixelized)
7612		//		return values.
7613		//
7614		// node: DOMNode
7615		//		A reference to a DOM node. Does NOT support taking an
7616		//		ID string for speed reasons.
7617		// example:
7618		//	|	require(["dojo/dom-style", "dojo/dom"], function(domStyle, dom){
7619		//	|		domStyle.getComputedStyle(dom.byId('foo')).borderWidth;
7620		//	|	});
7621		//
7622		// example:
7623		//		Reusing the returned object, avoiding multiple lookups:
7624		//	|	require(["dojo/dom-style", "dojo/dom"], function(domStyle, dom){
7625		//	|		var cs = domStyle.getComputedStyle(dom.byId("someNode"));
7626		//	|		var w = cs.width, h = cs.height;
7627		//	|	});
7628		return; // CSS2Properties
7629	};
7630	=====*/
7631
7632	var toPixel;
7633	if(!has("ie")){
7634		toPixel = function(element, value){
7635			// style values can be floats, client code may want
7636			// to round for integer pixels.
7637			return parseFloat(value) || 0;
7638		};
7639	}else{
7640		toPixel = function(element, avalue){
7641			if(!avalue){ return 0; }
7642			// on IE7, medium is usually 4 pixels
7643			if(avalue == "medium"){ return 4; }
7644			// style values can be floats, client code may
7645			// want to round this value for integer pixels.
7646			if(avalue.slice && avalue.slice(-2) == 'px'){ return parseFloat(avalue); }
7647			var s = element.style, rs = element.runtimeStyle, cs = element.currentStyle,
7648				sLeft = s.left, rsLeft = rs.left;
7649			rs.left = cs.left;
7650			try{
7651				// 'avalue' may be incompatible with style.left, which can cause IE to throw
7652				// this has been observed for border widths using "thin", "medium", "thick" constants
7653				// those particular constants could be trapped by a lookup
7654				// but perhaps there are more
7655				s.left = avalue;
7656				avalue = s.pixelLeft;
7657			}catch(e){
7658				avalue = 0;
7659			}
7660			s.left = sLeft;
7661			rs.left = rsLeft;
7662			return avalue;
7663		};
7664	}
7665	style.toPixelValue = toPixel;
7666	/*=====
7667	style.toPixelValue = function(node, value){
7668		// summary:
7669		//		converts style value to pixels on IE or return a numeric value.
7670		// node: DOMNode
7671		// value: String
7672		// returns: Number
7673	};
7674	=====*/
7675
7676	// FIXME: there opacity quirks on FF that we haven't ported over. Hrm.
7677
7678	var astr = "DXImageTransform.Microsoft.Alpha";
7679	var af = function(n, f){
7680		try{
7681			return n.filters.item(astr);
7682		}catch(e){
7683			return f ? {} : null;
7684		}
7685	};
7686
7687	var _getOpacity =
7688		has("ie") < 9 || (has("ie") < 10 && has("quirks")) ? function(node){
7689			try{
7690				return af(node).Opacity / 100; // Number
7691			}catch(e){
7692				return 1; // Number
7693			}
7694		} :
7695		function(node){
7696			return getComputedStyle(node).opacity;
7697		};
7698
7699	var _setOpacity =
7700		has("ie") < 9 || (has("ie") < 10 && has("quirks")) ? function(/*DomNode*/ node, /*Number*/ opacity){
7701			if(opacity === ""){ opacity = 1; }
7702			var ov = opacity * 100, fullyOpaque = opacity === 1;
7703
7704			// on IE7 Alpha(Filter opacity=100) makes text look fuzzy so disable it altogether (bug #2661),
7705			// but still update the opacity value so we can get a correct reading if it is read later:
7706			// af(node, 1).Enabled = !fullyOpaque;
7707
7708			if(fullyOpaque){
7709				node.style.zoom = "";
7710				if(af(node)){
7711					node.style.filter = node.style.filter.replace(
7712						new RegExp("\\s*progid:" + astr + "\\([^\\)]+?\\)", "i"), "");
7713				}
7714			}else{
7715				node.style.zoom = 1;
7716				if(af(node)){
7717					af(node, 1).Opacity = ov;
7718				}else{
7719					node.style.filter += " progid:" + astr + "(Opacity=" + ov + ")";
7720				}
7721				af(node, 1).Enabled = true;
7722			}
7723
7724			if(node.tagName.toLowerCase() == "tr"){
7725				for(var td = node.firstChild; td; td = td.nextSibling){
7726					if(td.tagName.toLowerCase() == "td"){
7727						_setOpacity(td, opacity);
7728					}
7729				}
7730			}
7731			return opacity;
7732		} :
7733		function(node, opacity){
7734			return node.style.opacity = opacity;
7735		};
7736
7737	var _pixelNamesCache = {
7738		left: true, top: true
7739	};
7740	var _pixelRegExp = /margin|padding|width|height|max|min|offset/; // |border
7741	function _toStyleValue(node, type, value){
7742		//TODO: should we really be doing string case conversion here? Should we cache it? Need to profile!
7743		type = type.toLowerCase();
7744		if(has("ie") || has("trident")){
7745			if(value == "auto"){
7746				if(type == "height"){ return node.offsetHeight; }
7747				if(type == "width"){ return node.offsetWidth; }
7748			}
7749			if(type == "fontweight"){
7750				switch(value){
7751					case 700: return "bold";
7752					case 400:
7753					default: return "normal";
7754				}
7755			}
7756		}
7757		if(!(type in _pixelNamesCache)){
7758			_pixelNamesCache[type] = _pixelRegExp.test(type);
7759		}
7760		return _pixelNamesCache[type] ? toPixel(node, value) : value;
7761	}
7762
7763	var _floatAliases = {cssFloat: 1, styleFloat: 1, "float": 1};
7764
7765	// public API
7766
7767	style.get = function getStyle(/*DOMNode|String*/ node, /*String?*/ name){
7768		// summary:
7769		//		Accesses styles on a node.
7770		// description:
7771		//		Getting the style value uses the computed style for the node, so the value
7772		//		will be a calculated value, not just the immediate node.style value.
7773		//		Also when getting values, use specific style names,
7774		//		like "borderBottomWidth" instead of "border" since compound values like
7775		//		"border" are not necessarily reflected as expected.
7776		//		If you want to get node dimensions, use `dojo/dom-geometry.getMarginBox()`,
7777		//		`dojo/dom-geometry.getContentBox()` or `dojo/dom-geometry.getPosition()`.
7778		// node: DOMNode|String
7779		//		id or reference to node to get style for
7780		// name: String?
7781		//		the style property to get
7782		// example:
7783		//		Passing only an ID or node returns the computed style object of
7784		//		the node:
7785		//	|	require(["dojo/dom-style", "dojo/dom"], function(domStyle, dom){
7786		//	|		domStyle.get("thinger");
7787		//	|	});
7788		// example:
7789		//		Passing a node and a style property returns the current
7790		//		normalized, computed value for that property:
7791		//	|	require(["dojo/dom-style", "dojo/dom"], function(domStyle, dom){
7792		//	|		domStyle.get("thinger", "opacity"); // 1 by default
7793		//	|	});
7794
7795		var n = dom.byId(node), l = arguments.length, op = (name == "opacity");
7796		if(l == 2 && op){
7797			return _getOpacity(n);
7798		}
7799		name = _floatAliases[name] ? "cssFloat" in n.style ? "cssFloat" : "styleFloat" : name;
7800		var s = style.getComputedStyle(n);
7801		return (l == 1) ? s : _toStyleValue(n, name, s[name] || n.style[name]); /* CSS2Properties||String||Number */
7802	};
7803
7804	style.set = function setStyle(/*DOMNode|String*/ node, /*String|Object*/ name, /*String?*/ value){
7805		// summary:
7806		//		Sets styles on a node.
7807		// node: DOMNode|String
7808		//		id or reference to node to set style for
7809		// name: String|Object
7810		//		the style property to set in DOM-accessor format
7811		//		("borderWidth", not "border-width") or an object with key/value
7812		//		pairs suitable for setting each property.
7813		// value: String?
7814		//		If passed, sets value on the node for style, handling
7815		//		cross-browser concerns.  When setting a pixel value,
7816		//		be sure to include "px" in the value. For instance, top: "200px".
7817		//		Otherwise, in some cases, some browsers will not apply the style.
7818		//
7819		// example:
7820		//		Passing a node, a style property, and a value changes the
7821		//		current display of the node and returns the new computed value
7822		//	|	require(["dojo/dom-style"], function(domStyle){
7823		//	|		domStyle.set("thinger", "opacity", 0.5); // == 0.5
7824		//	|	});
7825		//
7826		// example:
7827		//		Passing a node, an object-style style property sets each of the values in turn and returns the computed style object of the node:
7828		//	|	require(["dojo/dom-style"], function(domStyle){
7829		//	|		domStyle.set("thinger", {
7830		//	|			"opacity": 0.5,
7831		//	|			"border": "3px solid black",
7832		//	|			"height": "300px"
7833		//	|		});
7834		//	|	});
7835		//
7836		// example:
7837		//		When the CSS style property is hyphenated, the JavaScript property is camelCased.
7838		//		font-size becomes fontSize, and so on.
7839		//	|	require(["dojo/dom-style", "dojo/dom"], function(domStyle, dom){
7840		//	|		domStyle.set("thinger",{
7841		//	|			fontSize:"14pt",
7842		//	|			letterSpacing:"1.2em"
7843		//	|		});
7844		//	|	});
7845		//
7846		// example:
7847		//		dojo/NodeList implements .style() using the same syntax, omitting the "node" parameter, calling
7848		//		dojo/dom-style.get() on every element of the list. See: `dojo/query` and `dojo/NodeList`
7849		//	|	require(["dojo/dom-style", "dojo/query", "dojo/NodeList-dom"],
7850		//	|	function(domStyle, query){
7851		//	|		query(".someClassName").style("visibility","hidden");
7852		//	|		// or
7853		//	|		query("#baz > div").style({
7854		//	|			opacity:0.75,
7855		//	|			fontSize:"13pt"
7856		//	|		});
7857		//	|	});
7858
7859		var n = dom.byId(node), l = arguments.length, op = (name == "opacity");
7860		name = _floatAliases[name] ? "cssFloat" in n.style ? "cssFloat" : "styleFloat" : name;
7861		if(l == 3){
7862			return op ? _setOpacity(n, value) : n.style[name] = value; // Number
7863		}
7864		for(var x in name){
7865			style.set(node, x, name[x]);
7866		}
7867		return style.getComputedStyle(n);
7868	};
7869
7870	return style;
7871});
7872
7873},
7874'dojo/mouse':function(){
7875define(["./_base/kernel", "./on", "./has", "./dom", "./_base/window"], function(dojo, on, has, dom, win){
7876
7877	// module:
7878	//		dojo/mouse
7879
7880    has.add("dom-quirks", win.doc && win.doc.compatMode == "BackCompat");
7881	has.add("events-mouseenter", win.doc && "onmouseenter" in win.doc.createElement("div"));
7882	has.add("events-mousewheel", win.doc && 'onmousewheel' in win.doc);
7883
7884	var mouseButtons;
7885	if((has("dom-quirks") && has("ie")) || !has("dom-addeventlistener")){
7886		mouseButtons = {
7887			LEFT:   1,
7888			MIDDLE: 4,
7889			RIGHT:  2,
7890			// helper functions
7891			isButton: function(e, button){ return e.button & button; },
7892			isLeft:   function(e){ return e.button & 1; },
7893			isMiddle: function(e){ return e.button & 4; },
7894			isRight:  function(e){ return e.button & 2; }
7895		};
7896	}else{
7897		mouseButtons = {
7898			LEFT:   0,
7899			MIDDLE: 1,
7900			RIGHT:  2,
7901			// helper functions
7902			isButton: function(e, button){ return e.button == button; },
7903			isLeft:   function(e){ return e.button == 0; },
7904			isMiddle: function(e){ return e.button == 1; },
7905			isRight:  function(e){ return e.button == 2; }
7906		};
7907	}
7908	dojo.mouseButtons = mouseButtons;
7909
7910/*=====
7911	dojo.mouseButtons = {
7912		// LEFT: Number
7913		//		Numeric value of the left mouse button for the platform.
7914		LEFT:   0,
7915		// MIDDLE: Number
7916		//		Numeric value of the middle mouse button for the platform.
7917		MIDDLE: 1,
7918		// RIGHT: Number
7919		//		Numeric value of the right mouse button for the platform.
7920		RIGHT:  2,
7921
7922		isButton: function(e, button){
7923			// summary:
7924			//		Checks an event object for a pressed button
7925			// e: Event
7926			//		Event object to examine
7927			// button: Number
7928			//		The button value (example: dojo.mouseButton.LEFT)
7929			return e.button == button; // Boolean
7930		},
7931		isLeft: function(e){
7932			// summary:
7933			//		Checks an event object for the pressed left button
7934			// e: Event
7935			//		Event object to examine
7936			return e.button == 0; // Boolean
7937		},
7938		isMiddle: function(e){
7939			// summary:
7940			//		Checks an event object for the pressed middle button
7941			// e: Event
7942			//		Event object to examine
7943			return e.button == 1; // Boolean
7944		},
7945		isRight: function(e){
7946			// summary:
7947			//		Checks an event object for the pressed right button
7948			// e: Event
7949			//		Event object to examine
7950			return e.button == 2; // Boolean
7951		}
7952	};
7953=====*/
7954
7955	function eventHandler(type, selectHandler){
7956		// emulation of mouseenter/leave with mouseover/out using descendant checking
7957		var handler = function(node, listener){
7958			return on(node, type, function(evt){
7959				if(selectHandler){
7960					return selectHandler(evt, listener);
7961				}
7962				if(!dom.isDescendant(evt.relatedTarget, node)){
7963					return listener.call(this, evt);
7964				}
7965			});
7966		};
7967		handler.bubble = function(select){
7968			return eventHandler(type, function(evt, listener){
7969				// using a selector, use the select function to determine if the mouse moved inside the selector and was previously outside the selector
7970				var target = select(evt.target);
7971				var relatedTarget = evt.relatedTarget;
7972				if(target && (target != (relatedTarget && relatedTarget.nodeType == 1 && select(relatedTarget)))){
7973					return listener.call(target, evt);
7974				} 
7975			});
7976		};
7977		return handler;
7978	}
7979	var wheel;
7980	if(has("events-mousewheel")){
7981		wheel = 'mousewheel';
7982	}else{ //firefox
7983		wheel = function(node, listener){
7984			return on(node, 'DOMMouseScroll', function(evt){
7985				evt.wheelDelta = -evt.detail;
7986				listener.call(this, evt);
7987			});
7988		};
7989	}
7990	return {
7991		// summary:
7992		//		This module provide mouse event handling utility functions and exports
7993		//		mouseenter and mouseleave event emulation.
7994		// example:
7995		//		To use these events, you register a mouseenter like this:
7996		//		|	define(["dojo/on", "dojo/mouse"], function(on, mouse){
7997		//		|		on(targetNode, mouse.enter, function(event){
7998		//		|			dojo.addClass(targetNode, "highlighted");
7999		//		|		});
8000		//		|		on(targetNode, mouse.leave, function(event){
8001		//		|			dojo.removeClass(targetNode, "highlighted");
8002		//		|		});
8003
8004		_eventHandler: eventHandler,		// for dojo/touch
8005
8006		// enter: Synthetic Event
8007		//		This is an extension event for the mouseenter that IE provides, emulating the
8008		//		behavior on other browsers.
8009		enter: eventHandler("mouseover"),
8010
8011		// leave: Synthetic Event
8012		//		This is an extension event for the mouseleave that IE provides, emulating the
8013		//		behavior on other browsers.
8014		leave: eventHandler("mouseout"),
8015
8016		// wheel: Normalized Mouse Wheel Event
8017		//		This is an extension event for the mousewheel that non-Mozilla browsers provide,
8018		//		emulating the behavior on Mozilla based browsers.
8019		wheel: wheel,
8020
8021		isLeft: mouseButtons.isLeft,
8022		/*=====
8023		isLeft: function(){
8024			// summary:
8025			//		Test an event object (from a mousedown event) to see if the left button was pressed.
8026		},
8027		=====*/
8028
8029		isMiddle: mouseButtons.isMiddle,
8030		/*=====
8031		 isMiddle: function(){
8032			 // summary:
8033			 //		Test an event object (from a mousedown event) to see if the middle button was pressed.
8034		 },
8035		 =====*/
8036
8037		isRight: mouseButtons.isRight
8038		/*=====
8039		 , isRight: function(){
8040			 // summary:
8041			 //		Test an event object (from a mousedown event) to see if the right button was pressed.
8042		 }
8043		 =====*/
8044	};
8045});
8046
8047},
8048'dojo/_base/sniff':function(){
8049define(["./kernel", "./lang", "../sniff"], function(dojo, lang, has){
8050	// module:
8051	//		dojo/_base/sniff
8052
8053	/*=====
8054	return {
8055		// summary:
8056		//		Deprecated.   New code should use dojo/sniff.
8057		//		This module populates the dojo browser version sniffing properties like dojo.isIE.
8058	};
8059	=====*/
8060
8061	if(! 1 ){
8062		return has;
8063	}
8064
8065	// no idea what this is for, or if it's used
8066	dojo._name = "browser";
8067
8068	lang.mixin(dojo, {
8069		// isBrowser: Boolean
8070		//		True if the client is a web-browser
8071		isBrowser: true,
8072
8073		// isFF: Number|undefined
8074		//		Version as a Number if client is FireFox. undefined otherwise. Corresponds to
8075		//		major detected FireFox version (1.5, 2, 3, etc.)
8076		isFF: has("ff"),
8077
8078		// isIE: Number|undefined
8079		//		Version as a Number if client is MSIE(PC). undefined otherwise. Corresponds to
8080		//		major detected IE version (6, 7, 8, etc.)
8081		isIE: has("ie"),
8082
8083		// isKhtml: Number|undefined
8084		//		Version as a Number if client is a KHTML browser. undefined otherwise. Corresponds to major
8085		//		detected version.
8086		isKhtml: has("khtml"),
8087
8088		// isWebKit: Number|undefined
8089		//		Version as a Number if client is a WebKit-derived browser (Konqueror,
8090		//		Safari, Chrome, etc.). undefined otherwise.
8091		isWebKit: has("webkit"),
8092
8093		// isMozilla: Number|undefined
8094		//		Version as a Number if client is a Mozilla-based browser (Firefox,
8095		//		SeaMonkey). undefined otherwise. Corresponds to major detected version.
8096		isMozilla: has("mozilla"),
8097		// isMoz: Number|undefined
8098		//		Version as a Number if client is a Mozilla-based browser (Firefox,
8099		//		SeaMonkey). undefined otherwise. Corresponds to major detected version.
8100		isMoz: has("mozilla"),
8101
8102		// isOpera: Number|undefined
8103		//		Version as a Number if client is Opera. undefined otherwise. Corresponds to
8104		//		major detected version.
8105		isOpera: has("opera"),
8106
8107		// isSafari: Number|undefined
8108		//		Version as a Number if client is Safari or iPhone. undefined otherwise.
8109		isSafari: has("safari"),
8110
8111		// isChrome: Number|undefined
8112		//		Version as a Number if client is Chrome browser. undefined otherwise.
8113		isChrome: has("chrome"),
8114
8115		// isMac: Boolean
8116		//		True if the client runs on Mac
8117		isMac: has("mac"),
8118
8119		// isIos: Number|undefined
8120		//		Version as a Number if client is iPhone, iPod, or iPad. undefined otherwise.
8121		isIos: has("ios"),
8122
8123		// isAndroid: Number|undefined
8124		//		Version as a Number if client is android browser. undefined otherwise.
8125		isAndroid: has("android"),
8126
8127		// isWii: Boolean
8128		//		True if client is Wii
8129		isWii: has("wii"),
8130
8131		// isQuirks: Boolean
8132		//		Page is in quirks mode.
8133		isQuirks: has("quirks"),
8134
8135		// isAir: Boolean
8136		//		True if client is Adobe Air
8137		isAir: has("air")
8138	});
8139
8140	return has;
8141});
8142
8143},
8144'dojo/keys':function(){
8145define(["./_base/kernel", "./sniff"], function(dojo, has){
8146
8147	// module:
8148	//		dojo/keys
8149
8150	return dojo.keys = {
8151		// summary:
8152		//		Definitions for common key values.  Client code should test keyCode against these named constants,
8153		//		as the actual codes can vary by browser.
8154
8155		BACKSPACE: 8,
8156		TAB: 9,
8157		CLEAR: 12,
8158		ENTER: 13,
8159		SHIFT: 16,
8160		CTRL: 17,
8161		ALT: 18,
8162		META: has("webkit") ? 91 : 224,		// the apple key on macs
8163		PAUSE: 19,
8164		CAPS_LOCK: 20,
8165		ESCAPE: 27,
8166		SPACE: 32,
8167		PAGE_UP: 33,
8168		PAGE_DOWN: 34,
8169		END: 35,
8170		HOME: 36,
8171		LEFT_ARROW: 37,
8172		UP_ARROW: 38,
8173		RIGHT_ARROW: 39,
8174		DOWN_ARROW: 40,
8175		INSERT: 45,
8176		DELETE: 46,
8177		HELP: 47,
8178		LEFT_WINDOW: 91,
8179		RIGHT_WINDOW: 92,
8180		SELECT: 93,
8181		NUMPAD_0: 96,
8182		NUMPAD_1: 97,
8183		NUMPAD_2: 98,
8184		NUMPAD_3: 99,
8185		NUMPAD_4: 100,
8186		NUMPAD_5: 101,
8187		NUMPAD_6: 102,
8188		NUMPAD_7: 103,
8189		NUMPAD_8: 104,
8190		NUMPAD_9: 105,
8191		NUMPAD_MULTIPLY: 106,
8192		NUMPAD_PLUS: 107,
8193		NUMPAD_ENTER: 108,
8194		NUMPAD_MINUS: 109,
8195		NUMPAD_PERIOD: 110,
8196		NUMPAD_DIVIDE: 111,
8197		F1: 112,
8198		F2: 113,
8199		F3: 114,
8200		F4: 115,
8201		F5: 116,
8202		F6: 117,
8203		F7: 118,
8204		F8: 119,
8205		F9: 120,
8206		F10: 121,
8207		F11: 122,
8208		F12: 123,
8209		F13: 124,
8210		F14: 125,
8211		F15: 126,
8212		NUM_LOCK: 144,
8213		SCROLL_LOCK: 145,
8214		UP_DPAD: 175,
8215		DOWN_DPAD: 176,
8216		LEFT_DPAD: 177,
8217		RIGHT_DPAD: 178,
8218		// virtual key mapping
8219		copyKey: has("mac") && !has("air") ? (has("safari") ? 91 : 224 ) : 17
8220	};
8221});
8222
8223},
8224'dojo/_base/Deferred':function(){
8225define([
8226	"./kernel",
8227	"../Deferred",
8228	"../promise/Promise",
8229	"../errors/CancelError",
8230	"../has",
8231	"./lang",
8232	"../when"
8233], function(dojo, NewDeferred, Promise, CancelError, has, lang, when){
8234	// module:
8235	//		dojo/_base/Deferred
8236
8237	var mutator = function(){};
8238	var freeze = Object.freeze || function(){};
8239	// A deferred provides an API for creating and resolving a promise.
8240	var Deferred = dojo.Deferred = function(/*Function?*/ canceller){
8241		// summary:
8242		//		Deprecated.   This module defines the legacy dojo/_base/Deferred API.
8243		//		New code should use dojo/Deferred instead.
8244		// description:
8245		//		The Deferred API is based on the concept of promises that provide a
8246		//		generic interface into the eventual completion of an asynchronous action.
8247		//		The motivation for promises fundamentally is about creating a
8248		//		separation of concerns that allows one to achieve the same type of
8249		//		call patterns and logical data flow in asynchronous code as can be
8250		//		achieved in synchronous code. Promises allows one
8251		//		to be able to call a function purely with arguments needed for
8252		//		execution, without conflating the call with concerns of whether it is
8253		//		sync or async. One shouldn't need to alter a call's arguments if the
8254		//		implementation switches from sync to async (or vice versa). By having
8255		//		async functions return promises, the concerns of making the call are
8256		//		separated from the concerns of asynchronous interaction (which are
8257		//		handled by the promise).
8258		//
8259		//		The Deferred is a type of promise that provides methods for fulfilling the
8260		//		promise with a successful result or an error. The most important method for
8261		//		working with Dojo's promises is the then() method, which follows the
8262		//		CommonJS proposed promise API. An example of using a Dojo promise:
8263		//
8264		//		|	var resultingPromise = someAsyncOperation.then(function(result){
8265		//		|		... handle result ...
8266		//		|	},
8267		//		|	function(error){
8268		//		|		... handle error ...
8269		//		|	});
8270		//
8271		//		The .then() call returns a new promise that represents the result of the
8272		//		execution of the callback. The callbacks will never affect the original promises value.
8273		//
8274		//		The Deferred instances also provide the following functions for backwards compatibility:
8275		//
8276		//		- addCallback(handler)
8277		//		- addErrback(handler)
8278		//		- callback(result)
8279		//		- errback(result)
8280		//
8281		//		Callbacks are allowed to return promises themselves, so
8282		//		you can build complicated sequences of events with ease.
8283		//
8284		//		The creator of the Deferred may specify a canceller.  The canceller
8285		//		is a function that will be called if Deferred.cancel is called
8286		//		before the Deferred fires. You can use this to implement clean
8287		//		aborting of an XMLHttpRequest, etc. Note that cancel will fire the
8288		//		deferred with a CancelledError (unless your canceller returns
8289		//		another kind of error), so the errbacks should be prepared to
8290		//		handle that error for cancellable Deferreds.
8291		// example:
8292		//	|	var deferred = new Deferred();
8293		//	|	setTimeout(function(){ deferred.callback({success: true}); }, 1000);
8294		//	|	return deferred;
8295		// example:
8296		//		Deferred objects are often used when making code asynchronous. It
8297		//		may be easiest to write functions in a synchronous manner and then
8298		//		split code using a deferred to trigger a response to a long-lived
8299		//		operation. For example, instead of register a callback function to
8300		//		denote when a rendering operation completes, the function can
8301		//		simply return a deferred:
8302		//
8303		//		|	// callback style:
8304		//		|	function renderLotsOfData(data, callback){
8305		//		|		var success = false
8306		//		|		try{
8307		//		|			for(var x in data){
8308		//		|				renderDataitem(data[x]);
8309		//		|			}
8310		//		|			success = true;
8311		//		|		}catch(e){ }
8312		//		|		if(callback){
8313		//		|			callback(success);
8314		//		|		}
8315		//		|	}
8316		//
8317		//		|	// using callback style
8318		//		|	renderLotsOfData(someDataObj, function(success){
8319		//		|		// handles success or failure
8320		//		|		if(!success){
8321		//		|			promptUserToRecover();
8322		//		|		}
8323		//		|	});
8324		//		|	// NOTE: no way to add another callback here!!
8325		// example:
8326		//		Using a Deferred doesn't simplify the sending code any, but it
8327		//		provides a standard interface for callers and senders alike,
8328		//		providing both with a simple way to service multiple callbacks for
8329		//		an operation and freeing both sides from worrying about details
8330		//		such as "did this get called already?". With Deferreds, new
8331		//		callbacks can be added at any time.
8332		//
8333		//		|	// Deferred style:
8334		//		|	function renderLotsOfData(data){
8335		//		|		var d = new Deferred();
8336		//		|		try{
8337		//		|			for(var x in data){
8338		//		|				renderDataitem(data[x]);
8339		//		|			}
8340		//		|			d.callback(true);
8341		//		|		}catch(e){
8342		//		|			d.errback(new Error("rendering failed"));
8343		//		|		}
8344		//		|		return d;
8345		//		|	}
8346		//
8347		//		|	// using Deferred style
8348		//		|	renderLotsOfData(someDataObj).then(null, function(){
8349		//		|		promptUserToRecover();
8350		//		|	});
8351		//		|	// NOTE: addErrback and addCallback both return the Deferred
8352		//		|	// again, so we could chain adding callbacks or save the
8353		//		|	// deferred for later should we need to be notified again.
8354		// example:
8355		//		In this example, renderLotsOfData is synchronous and so both
8356		//		versions are pretty artificial. Putting the data display on a
8357		//		timeout helps show why Deferreds rock:
8358		//
8359		//		|	// Deferred style and async func
8360		//		|	function renderLotsOfData(data){
8361		//		|		var d = new Deferred();
8362		//		|		setTimeout(function(){
8363		//		|			try{
8364		//		|				for(var x in data){
8365		//		|					renderDataitem(data[x]);
8366		//		|				}
8367		//		|				d.callback(true);
8368		//		|			}catch(e){
8369		//		|				d.errback(new Error("rendering failed"));
8370		//		|			}
8371		//		|		}, 100);
8372		//		|		return d;
8373		//		|	}
8374		//
8375		//		|	// using Deferred style
8376		//		|	renderLotsOfData(someDataObj).then(null, function(){
8377		//		|		promptUserToRecover();
8378		//		|	});
8379		//
8380		//		Note that the caller doesn't have to change his code at all to
8381		//		handle the asynchronous case.
8382
8383		var result, finished, canceled, fired, isError, head, nextListener;
8384		var promise = (this.promise = new Promise());
8385
8386		function complete(value){
8387			if(finished){
8388				throw new Error("This deferred has already been resolved");
8389			}
8390			result = value;
8391			finished = true;
8392			notify();
8393		}
8394		function notify(){
8395			var mutated;
8396			while(!mutated && nextListener){
8397				var listener = nextListener;
8398				nextListener = nextListener.next;
8399				if((mutated = (listener.progress == mutator))){ // assignment and check
8400					finished = false;
8401				}
8402
8403				var func = (isError ? listener.error : listener.resolved);
8404				if(has("config-useDeferredInstrumentation")){
8405					if(isError && NewDeferred.instrumentRejected){
8406						NewDeferred.instrumentRejected(result, !!func);
8407					}
8408				}
8409				if(func){
8410					try{
8411						var newResult = func(result);
8412						if (newResult && typeof newResult.then === "function"){
8413							newResult.then(lang.hitch(listener.deferred, "resolve"), lang.hitch(listener.deferred, "reject"), lang.hitch(listener.deferred, "progress"));
8414							continue;
8415						}
8416						var unchanged = mutated && newResult === undefined;
8417						if(mutated && !unchanged){
8418							isError = newResult instanceof Error;
8419						}
8420						listener.deferred[unchanged && isError ? "reject" : "resolve"](unchanged ? result : newResult);
8421					}catch(e){
8422						listener.deferred.reject(e);
8423					}
8424				}else{
8425					if(isError){
8426						listener.deferred.reject(result);
8427					}else{
8428						listener.deferred.resolve(result);
8429					}
8430				}
8431			}
8432		}
8433
8434		this.isResolved = promise.isResolved = function(){
8435			// summary:
8436			//		Checks whether the deferred has been resolved.
8437			// returns: Boolean
8438
8439			return fired == 0;
8440		};
8441
8442		this.isRejected = promise.isRejected = function(){
8443			// summary:
8444			//		Checks whether the deferred has been rejected.
8445			// returns: Boolean
8446
8447			return fired == 1;
8448		};
8449
8450		this.isFulfilled = promise.isFulfilled = function(){
8451			// summary:
8452			//		Checks whether the deferred has been resolved or rejected.
8453			// returns: Boolean
8454
8455			return fired >= 0;
8456		};
8457
8458		this.isCanceled = promise.isCanceled = function(){
8459			// summary:
8460			//		Checks whether the deferred has been canceled.
8461			// returns: Boolean
8462
8463			return canceled;
8464		};
8465
8466		// calling resolve will resolve the promise
8467		this.resolve = this.callback = function(value){
8468			// summary:
8469			//		Fulfills the Deferred instance successfully with the provide value
8470			this.fired = fired = 0;
8471			this.results = [value, null];
8472			complete(value);
8473		};
8474
8475
8476		// calling error will indicate that the promise failed
8477		this.reject = this.errback = function(error){
8478			// summary:
8479			//		Fulfills the Deferred instance as an error with the provided error
8480			isError = true;
8481			this.fired = fired = 1;
8482			if(has("config-useDeferredInstrumentation")){
8483				if(NewDeferred.instrumentRejected){
8484					NewDeferred.instrumentRejected(error, !!nextListener);
8485				}
8486			}
8487			complete(error);
8488			this.results = [null, error];
8489		};
8490		// call progress to provide updates on the progress on the completion of the promise
8491		this.progress = function(update){
8492			// summary:
8493			//		Send progress events to all listeners
8494			var listener = nextListener;
8495			while(listener){
8496				var progress = listener.progress;
8497				progress && progress(update);
8498				listener = listener.next;
8499			}
8500		};
8501		this.addCallbacks = function(callback, errback){
8502			// summary:
8503			//		Adds callback and error callback for this deferred instance.
8504			// callback: Function?
8505			//		The callback attached to this deferred object.
8506			// errback: Function?
8507			//		The error callback attached to this deferred object.
8508			// returns:
8509			//		Returns this deferred object.
8510			this.then(callback, errback, mutator);
8511			return this;	// Deferred
8512		};
8513		// provide the implementation of the promise
8514		promise.then = this.then = function(/*Function?*/resolvedCallback, /*Function?*/errorCallback, /*Function?*/progressCallback){
8515			// summary:
8516			//		Adds a fulfilledHandler, errorHandler, and progressHandler to be called for
8517			//		completion of a promise. The fulfilledHandler is called when the promise
8518			//		is fulfilled. The errorHandler is called when a promise fails. The
8519			//		progressHandler is called for progress events. All arguments are optional
8520			//		and non-function values are ignored. The progressHandler is not only an
8521			//		optional argument, but progress events are purely optional. Promise
8522			//		providers are not required to ever create progress events.
8523			//
8524			//		This function will return a new promise that is fulfilled when the given
8525			//		fulfilledHandler or errorHandler callback is finished. This allows promise
8526			//		operations to be chained together. The value returned from the callback
8527			//		handler is the fulfillment value for the returned promise. If the callback
8528			//		throws an error, the returned promise will be moved to failed state.
8529			//
8530			// returns:
8531			//		Returns a new promise that represents the result of the
8532			//		execution of the callback. The callbacks will never affect the original promises value.
8533			// example:
8534			//		An example of using a CommonJS compliant promise:
8535			//		|	asyncComputeTheAnswerToEverything().
8536			//		|		then(addTwo).
8537			//		|		then(printResult, onError);
8538			//		|	>44
8539			//
8540			var returnDeferred = progressCallback == mutator ? this : new Deferred(promise.cancel);
8541			var listener = {
8542				resolved: resolvedCallback,
8543				error: errorCallback,
8544				progress: progressCallback,
8545				deferred: returnDeferred
8546			};
8547			if(nextListener){
8548				head = head.next = listener;
8549			}
8550			else{
8551				nextListener = head = listener;
8552			}
8553			if(finished){
8554				notify();
8555			}
8556			return returnDeferred.promise; // Promise
8557		};
8558		var deferred = this;
8559		promise.cancel = this.cancel = function(){
8560			// summary:
8561			//		Cancels the asynchronous operation
8562			if(!finished){
8563				var error = canceller && canceller(deferred);
8564				if(!finished){
8565					if (!(error instanceof Error)){
8566						error = new CancelError(error);
8567					}
8568					error.log = false;
8569					deferred.reject(error);
8570				}
8571			}
8572			canceled = true;
8573		};
8574		freeze(promise);
8575	};
8576	lang.extend(Deferred, {
8577		addCallback: function(/*Function*/ callback){
8578			// summary:
8579			//		Adds successful callback for this deferred instance.
8580			// returns:
8581			//		Returns this deferred object.
8582			return this.addCallbacks(lang.hitch.apply(dojo, arguments));	// Deferred
8583		},
8584
8585		addErrback: function(/*Function*/ errback){
8586			// summary:
8587			//		Adds error callback for this deferred instance.
8588			// returns:
8589			//		Returns this deferred object.
8590			return this.addCallbacks(null, lang.hitch.apply(dojo, arguments));	// Deferred
8591		},
8592
8593		addBoth: function(/*Function*/ callback){
8594			// summary:
vendor: 8,083 bytes, lines 8595-8859
8595			//		Add handler as both successful callback and error callback for this deferred instance.
8596			// returns:
8597			//		Returns this deferred object.
8598			var enclosed = lang.hitch.apply(dojo, arguments);
8599			return this.addCallbacks(enclosed, enclosed);	// Deferred
8600		},
8601		fired: -1
8602	});
8603
8604	Deferred.when = dojo.when = when;
8605
8606	return Deferred;
8607});
8608
8609},
8610'dojo/Deferred':function(){
8611define([
8612	"./has",
8613	"./_base/lang",
8614	"./errors/CancelError",
8615	"./promise/Promise",
8616	"require"
8617], function(has, lang, CancelError, Promise, instrumentation){
8618	"use strict";
8619
8620	// module:
8621	//		dojo/Deferred
8622
8623	var PROGRESS = 0,
8624			RESOLVED = 1,
8625			REJECTED = 2;
8626	var FULFILLED_ERROR_MESSAGE = "This deferred has already been fulfilled.";
8627
8628	var freezeObject = Object.freeze || function(){};
8629
8630	var signalWaiting = function(waiting, type, result, rejection, deferred){
8631		if( 0 ){
8632			if(type === REJECTED && Deferred.instrumentRejected && waiting.length === 0){
8633				Deferred.instrumentRejected(result, false, rejection, deferred);
8634			}
8635		}
8636
8637		for(var i = 0; i < waiting.length; i++){
8638			signalListener(waiting[i], type, result, rejection);
8639		}
8640	};
8641
8642	var signalListener = function(listener, type, result, rejection){
8643		var func = listener[type];
8644		var deferred = listener.deferred;
8645		if(func){
8646			try{
8647				var newResult = func(result);
8648				if(type === PROGRESS){
8649					if(typeof newResult !== "undefined"){
8650						signalDeferred(deferred, type, newResult);
8651					}
8652				}else{
8653					if(newResult && typeof newResult.then === "function"){
8654						listener.cancel = newResult.cancel;
8655						newResult.then(
8656								// Only make resolvers if they're actually going to be used
8657								makeDeferredSignaler(deferred, RESOLVED),
8658								makeDeferredSignaler(deferred, REJECTED),
8659								makeDeferredSignaler(deferred, PROGRESS));
8660						return;
8661					}
8662					signalDeferred(deferred, RESOLVED, newResult);
8663				}
8664			}catch(error){
8665				signalDeferred(deferred, REJECTED, error);
8666			}
8667		}else{
8668			signalDeferred(deferred, type, result);
8669		}
8670
8671		if( 0 ){
8672			if(type === REJECTED && Deferred.instrumentRejected){
8673				Deferred.instrumentRejected(result, !!func, rejection, deferred.promise);
8674			}
8675		}
8676	};
8677
8678	var makeDeferredSignaler = function(deferred, type){
8679		return function(value){
8680			signalDeferred(deferred, type, value);
8681		};
8682	};
8683
8684	var signalDeferred = function(deferred, type, result){
8685		if(!deferred.isCanceled()){
8686			switch(type){
8687				case PROGRESS:
8688					deferred.progress(result);
8689					break;
8690				case RESOLVED:
8691					deferred.resolve(result);
8692					break;
8693				case REJECTED:
8694					deferred.reject(result);
8695					break;
8696			}
8697		}
8698	};
8699
8700	var Deferred = function(canceler){
8701		// summary:
8702		//		Creates a new deferred. This API is preferred over
8703		//		`dojo/_base/Deferred`.
8704		// description:
8705		//		Creates a new deferred, as an abstraction over (primarily)
8706		//		asynchronous operations. The deferred is the private interface
8707		//		that should not be returned to calling code. That's what the
8708		//		`promise` is for. See `dojo/promise/Promise`.
8709		// canceler: Function?
8710		//		Will be invoked if the deferred is canceled. The canceler
8711		//		receives the reason the deferred was canceled as its argument.
8712		//		The deferred is rejected with its return value, or a new
8713		//		`dojo/errors/CancelError` instance.
8714
8715		// promise: dojo/promise/Promise
8716		//		The public promise object that clients can add callbacks to. 
8717		var promise = this.promise = new Promise();
8718
8719		var deferred = this;
8720		var fulfilled, result, rejection;
8721		var canceled = false;
8722		var waiting = [];
8723
8724		if( 0  && Error.captureStackTrace){
8725			Error.captureStackTrace(deferred, Deferred);
8726			Error.captureStackTrace(promise, Deferred);
8727		}
8728
8729		this.isResolved = promise.isResolved = function(){
8730			// summary:
8731			//		Checks whether the deferred has been resolved.
8732			// returns: Boolean
8733
8734			return fulfilled === RESOLVED;
8735		};
8736
8737		this.isRejected = promise.isRejected = function(){
8738			// summary:
8739			//		Checks whether the deferred has been rejected.
8740			// returns: Boolean
8741
8742			return fulfilled === REJECTED;
8743		};
8744
8745		this.isFulfilled = promise.isFulfilled = function(){
8746			// summary:
8747			//		Checks whether the deferred has been resolved or rejected.
8748			// returns: Boolean
8749
8750			return !!fulfilled;
8751		};
8752
8753		this.isCanceled = promise.isCanceled = function(){
8754			// summary:
8755			//		Checks whether the deferred has been canceled.
8756			// returns: Boolean
8757
8758			return canceled;
8759		};
8760
8761		this.progress = function(update, strict){
8762			// summary:
8763			//		Emit a progress update on the deferred.
8764			// description:
8765			//		Emit a progress update on the deferred. Progress updates
8766			//		can be used to communicate updates about the asynchronous
8767			//		operation before it has finished.
8768			// update: any
8769			//		The progress update. Passed to progbacks.
8770			// strict: Boolean?
8771			//		If strict, will throw an error if the deferred has already
8772			//		been fulfilled and consequently no progress can be emitted.
8773			// returns: dojo/promise/Promise
8774			//		Returns the original promise for the deferred.
8775
8776			if(!fulfilled){
8777				signalWaiting(waiting, PROGRESS, update, null, deferred);
8778				return promise;
8779			}else if(strict === true){
8780				throw new Error(FULFILLED_ERROR_MESSAGE);
8781			}else{
8782				return promise;
8783			}
8784		};
8785
8786		this.resolve = function(value, strict){
8787			// summary:
8788			//		Resolve the deferred.
8789			// description:
8790			//		Resolve the deferred, putting it in a success state.
8791			// value: any
8792			//		The result of the deferred. Passed to callbacks.
8793			// strict: Boolean?
8794			//		If strict, will throw an error if the deferred has already
8795			//		been fulfilled and consequently cannot be resolved.
8796			// returns: dojo/promise/Promise
8797			//		Returns the original promise for the deferred.
8798
8799			if(!fulfilled){
8800				// Set fulfilled, store value. After signaling waiting listeners unset
8801				// waiting.
8802				signalWaiting(waiting, fulfilled = RESOLVED, result = value, null, deferred);
8803				waiting = null;
8804				return promise;
8805			}else if(strict === true){
8806				throw new Error(FULFILLED_ERROR_MESSAGE);
8807			}else{
8808				return promise;
8809			}
8810		};
8811
8812		var reject = this.reject = function(error, strict){
8813			// summary:
8814			//		Reject the deferred.
8815			// description:
8816			//		Reject the deferred, putting it in an error state.
8817			// error: any
8818			//		The error result of the deferred. Passed to errbacks.
8819			// strict: Boolean?
8820			//		If strict, will throw an error if the deferred has already
8821			//		been fulfilled and consequently cannot be rejected.
8822			// returns: dojo/promise/Promise
8823			//		Returns the original promise for the deferred.
8824
8825			if(!fulfilled){
8826				if( 0  && Error.captureStackTrace){
8827					Error.captureStackTrace(rejection = {}, reject);
8828				}
8829				signalWaiting(waiting, fulfilled = REJECTED, result = error, rejection, deferred);
8830				waiting = null;
8831				return promise;
8832			}else if(strict === true){
8833				throw new Error(FULFILLED_ERROR_MESSAGE);
8834			}else{
8835				return promise;
8836			}
8837		};
8838
8839		this.then = promise.then = function(callback, errback, progback){
8840			// summary:
8841			//		Add new callbacks to the deferred.
8842			// description:
8843			//		Add new callbacks to the deferred. Callbacks can be added
8844			//		before or after the deferred is fulfilled.
8845			// callback: Function?
8846			//		Callback to be invoked when the promise is resolved.
8847			//		Receives the resolution value.
8848			// errback: Function?
8849			//		Callback to be invoked when the promise is rejected.
8850			//		Receives the rejection error.
8851			// progback: Function?
8852			//		Callback to be invoked when the promise emits a progress
8853			//		update. Receives the progress update.
8854			// returns: dojo/promise/Promise
8855			//		Returns a new promise for the result of the callback(s).
8856			//		This can be used for chaining many asynchronous operations.
8857
8858			var listener = [progback, callback, errback];
8859			// Ensure we cancel the promise we're waiting for, or if callback/errback
8860			// have returned a promise, cancel that one.
8861			listener.cancel = promise.cancel;
8862			listener.deferred = new Deferred(function(reason){
8863				// Check whether cancel is really available, returned promises are not
8864				// required to expose `cancel`
8865				return listener.cancel && listener.cancel(reason);
8866			});
8867			if(fulfilled && !waiting){
8868				signalListener(listener, fulfilled, result, rejection);
8869			}else{
8870				waiting.push(listener);
8871			}
8872			return listener.deferred.promise;
8873		};
8874
8875		this.cancel = promise.cancel = function(reason, strict){
8876			// summary:
8877			//		Inform the deferred it may cancel its asynchronous operation.
8878			// description:
8879			//		Inform the deferred it may cancel its asynchronous operation.
8880			//		The deferred's (optional) canceler is invoked and the
8881			//		deferred will be left in a rejected state. Can affect other
8882			//		promises that originate with the same deferred.
8883			// reason: any
8884			//		A message that may be sent to the deferred's canceler,
8885			//		explaining why it's being canceled.
8886			// strict: Boolean?
8887			//		If strict, will throw an error if the deferred has already
8888			//		been fulfilled and consequently cannot be canceled.
8889			// returns: any
8890			//		Returns the rejection reason if the deferred was canceled
8891			//		normally.
8892
8893			if(!fulfilled){
8894				// Cancel can be called even after the deferred is fulfilled
8895				if(canceler){
8896					var returnedReason = canceler(reason);
8897					reason = typeof returnedReason === "undefined" ? reason : returnedReason;
8898				}
8899				canceled = true;
8900				if(!fulfilled){
8901					// Allow canceler to provide its own reason, but fall back to a CancelError
8902					if(typeof reason === "undefined"){
8903						reason = new CancelError();
8904					}
8905					reject(reason);
8906					return reason;
8907				}else if(fulfilled === REJECTED && result === reason){
8908					return reason;
8909				}
8910			}else if(strict === true){
8911				throw new Error(FULFILLED_ERROR_MESSAGE);
8912			}
8913		};
8914
8915		freezeObject(promise);
8916	};
8917
8918	Deferred.prototype.toString = function(){
8919		// returns: String
8920		//		Returns `[object Deferred]`.
8921
8922		return "[object Deferred]";
8923	};
8924
8925	if(instrumentation){
8926		instrumentation(Deferred);
8927	}
8928
8929	return Deferred;
8930});
8931
8932},
8933'dojo/errors/CancelError':function(){
8934define(["./create"], function(create){
8935	// module:
8936	//		dojo/errors/CancelError
8937
8938	/*=====
8939	return function(){
8940		// summary:
8941		//		Default error if a promise is canceled without a reason.
8942	};
8943	=====*/
8944
8945	return create("CancelError", null, null, { dojoType: "cancel" });
8946});
8947
8948},
8949'dojo/errors/create':function(){
8950define(["../_base/lang"], function(lang){
8951	return function(name, ctor, base, props){
8952		base = base || Error;
8953
8954		var ErrorCtor = function(message){
8955			if(base === Error){
8956				if(Error.captureStackTrace){
8957					Error.captureStackTrace(this, ErrorCtor);
8958				}
8959
8960				// Error.call() operates on the returned error
8961				// object rather than operating on |this|
8962				var err = Error.call(this, message),
8963					prop;
8964
8965				// Copy own properties from err to |this|
8966				for(prop in err){
8967					if(err.hasOwnProperty(prop)){
8968						this[prop] = err[prop];
8969					}
8970				}
8971
8972				// messsage is non-enumerable in ES5
8973				this.message = message;
8974				// stack is non-enumerable in at least Firefox
8975				this.stack = err.stack;
8976			}else{
8977				base.apply(this, arguments);
8978			}
8979			if(ctor){
8980				ctor.apply(this, arguments);
8981			}
8982		};
8983
8984		ErrorCtor.prototype = lang.delegate(base.prototype, props);
8985		ErrorCtor.prototype.name = name;
8986		ErrorCtor.prototype.constructor = ErrorCtor;
8987
8988		return ErrorCtor;
8989	};
8990});
8991
8992},
8993'dojo/promise/Promise':function(){
8994define([
8995	"../_base/lang"
8996], function(lang){
8997	"use strict";
8998
8999	// module:
9000	//		dojo/promise/Promise
9001
9002	function throwAbstract(){
9003		throw new TypeError("abstract");
9004	}
9005
9006	return lang.extend(function Promise(){
9007		// summary:
9008		//		The public interface to a deferred.
9009		// description:
9010		//		The public interface to a deferred. All promises in Dojo are
9011		//		instances of this class.
9012	}, {
9013		then: function(callback, errback, progback){
9014			// summary:
9015			//		Add new callbacks to the promise.
9016			// description:
9017			//		Add new callbacks to the deferred. Callbacks can be added
9018			//		before or after the deferred is fulfilled.
9019			// callback: Function?
9020			//		Callback to be invoked when the promise is resolved.
9021			//		Receives the resolution value.
9022			// errback: Function?
9023			//		Callback to be invoked when the promise is rejected.
9024			//		Receives the rejection error.
9025			// progback: Function?
9026			//		Callback to be invoked when the promise emits a progress
9027			//		update. Receives the progress update.
9028			// returns: dojo/promise/Promise
9029			//		Returns a new promise for the result of the callback(s).
9030			//		This can be used for chaining many asynchronous operations.
9031
9032			throwAbstract();
9033		},
9034
9035		cancel: function(reason, strict){
9036			// summary:
9037			//		Inform the deferred it may cancel its asynchronous operation.
9038			// description:
9039			//		Inform the deferred it may cancel its asynchronous operation.
9040			//		The deferred's (optional) canceler is invoked and the
9041			//		deferred will be left in a rejected state. Can affect other
9042			//		promises that originate with the same deferred.
9043			// reason: any
9044			//		A message that may be sent to the deferred's canceler,
9045			//		explaining why it's being canceled.
9046			// strict: Boolean?
9047			//		If strict, will throw an error if the deferred has already
9048			//		been fulfilled and consequently cannot be canceled.
9049			// returns: any
9050			//		Returns the rejection reason if the deferred was canceled
9051			//		normally.
9052
9053			throwAbstract();
9054		},
9055
9056		isResolved: function(){
9057			// summary:
9058			//		Checks whether the promise has been resolved.
9059			// returns: Boolean
9060
9061			throwAbstract();
9062		},
9063
9064		isRejected: function(){
9065			// summary:
9066			//		Checks whether the promise has been rejected.
9067			// returns: Boolean
9068
9069			throwAbstract();
9070		},
9071
9072		isFulfilled: function(){
9073			// summary:
9074			//		Checks whether the promise has been resolved or rejected.
9075			// returns: Boolean
9076
9077			throwAbstract();
9078		},
9079
9080		isCanceled: function(){
9081			// summary:
9082			//		Checks whether the promise has been canceled.
9083			// returns: Boolean
9084
9085			throwAbstract();
9086		},
9087
9088		always: function(callbackOrErrback){
9089			// summary:
9090			//		Add a callback to be invoked when the promise is resolved
9091			//		or rejected.
9092			// callbackOrErrback: Function?
9093			//		A function that is used both as a callback and errback.
9094			// returns: dojo/promise/Promise
9095			//		Returns a new promise for the result of the callback/errback.
9096
9097			return this.then(callbackOrErrback, callbackOrErrback);
9098		},
9099
9100		otherwise: function(errback){
9101			// summary:
9102			//		Add new errbacks to the promise.
9103			// errback: Function?
9104			//		Callback to be invoked when the promise is rejected.
9105			// returns: dojo/promise/Promise
9106			//		Returns a new promise for the result of the errback.
9107
9108			return this.then(null, errback);
9109		},
9110
9111		trace: function(){
9112			return this;
9113		},
9114
9115		traceRejected: function(){
9116			return this;
9117		},
9118
9119		toString: function(){
9120			// returns: string
9121			//		Returns `[object Promise]`.
9122
9123			return "[object Promise]";
9124		}
9125	});
9126});
9127
9128},
9129'dojo/when':function(){
9130define([
9131	"./Deferred",
9132	"./promise/Promise"
9133], function(Deferred, Promise){
9134	"use strict";
9135
9136	// module:
9137	//		dojo/when
9138
9139	return function when(valueOrPromise, callback, errback, progback){
9140		// summary:
9141		//		Transparently applies callbacks to values and/or promises.
9142		// description:
9143		//		Accepts promises but also transparently handles non-promises. If no
9144		//		callbacks are provided returns a promise, regardless of the initial
9145		//		value. Foreign promises are converted.
9146		//
9147		//		If callbacks are provided and the initial value is not a promise,
9148		//		the callback is executed immediately with no error handling. Returns
9149		//		a promise if the initial value is a promise, or the result of the
9150		//		callback otherwise.
9151		// valueOrPromise:
9152		//		Either a regular value or an object with a `then()` method that
9153		//		follows the Promises/A specification.
9154		// callback: Function?
9155		//		Callback to be invoked when the promise is resolved, or a non-promise
9156		//		is received.
9157		// errback: Function?
9158		//		Callback to be invoked when the promise is rejected.
9159		// progback: Function?
9160		//		Callback to be invoked when the promise emits a progress update.
9161		// returns: dojo/promise/Promise
9162		//		Promise, or if a callback is provided, the result of the callback.
9163
9164		var receivedPromise = valueOrPromise && typeof valueOrPromise.then === "function";
9165		var nativePromise = receivedPromise && valueOrPromise instanceof Promise;
9166
9167		if(!receivedPromise){
9168			if(arguments.length > 1){
9169				return callback ? callback(valueOrPromise) : valueOrPromise;
9170			}else{
9171				return new Deferred().resolve(valueOrPromise);
9172			}
9173		}else if(!nativePromise){
9174			var deferred = new Deferred(valueOrPromise.cancel);
9175			valueOrPromise.then(deferred.resolve, deferred.reject, deferred.progress);
9176			valueOrPromise = deferred.promise;
9177		}
9178
9179		if(callback || errback || progback){
9180			return valueOrPromise.then(callback, errback, progback);
9181		}
9182		return valueOrPromise;
9183	};
9184});
9185
9186},
9187'dojo/_base/json':function(){
9188define(["./kernel", "../json"], function(dojo, json){
9189
9190// module:
9191//		dojo/_base/json
9192
9193/*=====
9194return {
9195	// summary:
9196	//		This module defines the dojo JSON API.
9197};
9198=====*/
9199
9200dojo.fromJson = function(/*String*/ js){
9201	// summary:
9202	//		Parses a JavaScript expression and returns a JavaScript value.
9203	// description:
9204	//		Throws for invalid JavaScript expressions. It does not use a strict JSON parser. It
9205	//		always delegates to eval(). The content passed to this method must therefore come
9206	//		from a trusted source.
9207	//		It is recommend that you use dojo/json's parse function for an
9208	//		implementation uses the (faster) native JSON parse when available.
9209	// js:
9210	//		a string literal of a JavaScript expression, for instance:
9211	//		`'{ "foo": [ "bar", 1, { "baz": "thud" } ] }'`
9212
9213	return eval("(" + js + ")"); // Object
9214};
9215
9216/*=====
9217dojo._escapeString = function(){
9218	// summary:
9219	//		Adds escape sequences for non-visual characters, double quote and
9220	//		backslash and surrounds with double quotes to form a valid string
9221	//		literal.
9222};
9223=====*/
9224dojo._escapeString = json.stringify; // just delegate to json.stringify
9225
9226dojo.toJsonIndentStr = "\t";
9227dojo.toJson = function(/*Object*/ it, /*Boolean?*/ prettyPrint){
9228	// summary:
9229	//		Returns a [JSON](http://json.org) serialization of an object.
9230	// description:
9231	//		Returns a [JSON](http://json.org) serialization of an object.
9232	//		Note that this doesn't check for infinite recursion, so don't do that!
9233	//		It is recommend that you use dojo/json's stringify function for an lighter
9234	//		and faster implementation that matches the native JSON API and uses the
9235	//		native JSON serializer when available.
9236	// it:
9237	//		an object to be serialized. Objects may define their own
9238	//		serialization via a special "__json__" or "json" function
9239	//		property. If a specialized serializer has been defined, it will
9240	//		be used as a fallback.
9241	//		Note that in 1.6, toJson would serialize undefined, but this no longer supported
9242	//		since it is not supported by native JSON serializer.
9243	// prettyPrint:
9244	//		if true, we indent objects and arrays to make the output prettier.
9245	//		The variable `dojo.toJsonIndentStr` is used as the indent string --
9246	//		to use something other than the default (tab), change that variable
9247	//		before calling dojo.toJson().
9248	//		Note that if native JSON support is available, it will be used for serialization,
9249	//		and native implementations vary on the exact spacing used in pretty printing.
9250	// returns:
9251	//		A JSON string serialization of the passed-in object.
9252	// example:
9253	//		simple serialization of a trivial object
9254	//		|	var jsonStr = dojo.toJson({ howdy: "stranger!", isStrange: true });
vendor: 6,903 bytes, lines 9255-9448
9255	//		|	doh.is('{"howdy":"stranger!","isStrange":true}', jsonStr);
9256	// example:
9257	//		a custom serializer for an objects of a particular class:
9258	//		|	dojo.declare("Furby", null, {
9259	//		|		furbies: "are strange",
9260	//		|		furbyCount: 10,
9261	//		|		__json__: function(){
9262	//		|		},
9263	//		|	});
9264
9265	// use dojo/json
9266	return json.stringify(it, function(key, value){
9267		if(value){
9268			var tf = value.__json__||value.json;
9269			if(typeof tf == "function"){
9270				return tf.call(value);
9271			}
9272		}
9273		return value;
9274	}, prettyPrint && dojo.toJsonIndentStr);	// String
9275};
9276
9277return dojo;
9278});
9279
9280},
9281'dojo/json':function(){
9282define(["./has"], function(has){
9283	"use strict";
9284	var hasJSON = typeof JSON != "undefined";
9285	has.add("json-parse", hasJSON); // all the parsers work fine
9286		// Firefox 3.5/Gecko 1.9 fails to use replacer in stringify properly https://bugzilla.mozilla.org/show_bug.cgi?id=509184
9287	has.add("json-stringify", hasJSON && JSON.stringify({a:0}, function(k,v){return v||1;}) == '{"a":1}');
9288
9289	/*=====
9290	return {
9291		// summary:
9292		//		Functions to parse and serialize JSON
9293
9294		parse: function(str, strict){
9295			// summary:
9296			//		Parses a [JSON](http://json.org) string to return a JavaScript object.
9297			// description:
9298			//		This function follows [native JSON API](https://developer.mozilla.org/en/JSON)
9299			//		Throws for invalid JSON strings. This delegates to eval() if native JSON
9300			//		support is not available. By default this will evaluate any valid JS expression.
9301			//		With the strict parameter set to true, the parser will ensure that only
9302			//		valid JSON strings are parsed (otherwise throwing an error). Without the strict
9303			//		parameter, the content passed to this method must come
9304			//		from a trusted source.
9305			// str:
9306			//		a string literal of a JSON item, for instance:
9307			//		`'{ "foo": [ "bar", 1, { "baz": "thud" } ] }'`
9308			// strict:
9309			//		When set to true, this will ensure that only valid, secure JSON is ever parsed.
9310			//		Make sure this is set to true for untrusted content. Note that on browsers/engines
9311			//		without native JSON support, setting this to true will run slower.
9312		},
9313		stringify: function(value, replacer, spacer){
9314			// summary:
9315			//		Returns a [JSON](http://json.org) serialization of an object.
9316			// description:
9317			//		Returns a [JSON](http://json.org) serialization of an object.
9318			//		This function follows [native JSON API](https://developer.mozilla.org/en/JSON)
9319			//		Note that this doesn't check for infinite recursion, so don't do that!
9320			// value:
9321			//		A value to be serialized.
9322			// replacer:
9323			//		A replacer function that is called for each value and can return a replacement
9324			// spacer:
9325			//		A spacer string to be used for pretty printing of JSON
9326			// example:
9327			//		simple serialization of a trivial object
9328			//	|	define(["dojo/json"], function(JSON){
9329			// 	|		var jsonStr = JSON.stringify({ howdy: "stranger!", isStrange: true });
9330			//	|		doh.is('{"howdy":"stranger!","isStrange":true}', jsonStr);
9331		}
9332	};
9333	=====*/
9334
9335	if(has("json-stringify")){
9336		return JSON;
9337	}else{
9338		var escapeString = function(/*String*/str){
9339			// summary:
9340			//		Adds escape sequences for non-visual characters, double quote and
9341			//		backslash and surrounds with double quotes to form a valid string
9342			//		literal.
9343			return ('"' + str.replace(/(["\\])/g, '\\$1') + '"').
9344				replace(/[\f]/g, "\\f").replace(/[\b]/g, "\\b").replace(/[\n]/g, "\\n").
9345				replace(/[\t]/g, "\\t").replace(/[\r]/g, "\\r"); // string
9346		};
9347		return {
9348			parse: has("json-parse") ? JSON.parse : function(str, strict){
9349				if(strict && !/^([\s\[\{]*(?:"(?:\\.|[^"])*"|-?\d[\d\.]*(?:[Ee][+-]?\d+)?|null|true|false|)[\s\]\}]*(?:,|:|$))+$/.test(str)){
9350					throw new SyntaxError("Invalid characters in JSON");
9351				}
9352				return eval('(' + str + ')');
9353			},
9354			stringify: function(value, replacer, spacer){
9355				var undef;
9356				if(typeof replacer == "string"){
9357					spacer = replacer;
9358					replacer = null;
9359				}
9360				function stringify(it, indent, key){
9361					if(replacer){
9362						it = replacer(key, it);
9363					}
9364					var val, objtype = typeof it;
9365					if(objtype == "number"){
9366						return isFinite(it) ? it + "" : "null";
9367					}
9368					if(objtype == "boolean"){
9369						return it + "";
9370					}
9371					if(it === null){
9372						return "null";
9373					}
9374					if(typeof it == "string"){
9375						return escapeString(it);
9376					}
9377					if(objtype == "function" || objtype == "undefined"){
9378						return undef; // undefined
9379					}
9380					// short-circuit for objects that support "json" serialization
9381					// if they return "self" then just pass-through...
9382					if(typeof it.toJSON == "function"){
9383						return stringify(it.toJSON(key), indent, key);
9384					}
9385					if(it instanceof Date){
9386						return '"{FullYear}-{Month+}-{Date}T{Hours}:{Minutes}:{Seconds}Z"'.replace(/\{(\w+)(\+)?\}/g, function(t, prop, plus){
9387							var num = it["getUTC" + prop]() + (plus ? 1 : 0);
9388							return num < 10 ? "0" + num : num;
9389						});
9390					}
9391					if(it.valueOf() !== it){
9392						// primitive wrapper, try again unwrapped:
9393						return stringify(it.valueOf(), indent, key);
9394					}
9395					var nextIndent= spacer ? (indent + spacer) : "";
9396					/* we used to test for DOM nodes and throw, but FF serializes them as {}, so cross-browser consistency is probably not efficiently attainable */ 
9397				
9398					var sep = spacer ? " " : "";
9399					var newLine = spacer ? "\n" : "";
9400				
9401					// array
9402					if(it instanceof Array){
9403						var itl = it.length, res = [];
9404						for(key = 0; key < itl; key++){
9405							var obj = it[key];
9406							val = stringify(obj, nextIndent, key);
9407							if(typeof val != "string"){
9408								val = "null";
9409							}
9410							res.push(newLine + nextIndent + val);
9411						}
9412						return "[" + res.join(",") + newLine + indent + "]";
9413					}
9414					// generic object code path
9415					var output = [];
9416					for(key in it){
9417						var keyStr;
9418						if(it.hasOwnProperty(key)){
9419							if(typeof key == "number"){
9420								keyStr = '"' + key + '"';
9421							}else if(typeof key == "string"){
9422								keyStr = escapeString(key);
9423							}else{
9424								// skip non-string or number keys
9425								continue;
9426							}
9427							val = stringify(it[key], nextIndent, key);
9428							if(typeof val != "string"){
9429								// skip non-serializable values
9430								continue;
9431							}
9432							// At this point, the most non-IE browsers don't get in this branch 
9433							// (they have native JSON), so push is definitely the way to
9434							output.push(newLine + nextIndent + keyStr + ":" + sep + val);
9435						}
9436					}
9437					return "{" + output.join(",") + newLine + indent + "}"; // String
9438				}
9439				return stringify(value, "", "");
9440			}
9441		};
9442	}
9443});
9444
9445},
9446'dojo/_base/Color':function(){
9447define(["./kernel", "./lang", "./array", "./config"], function(dojo, lang, ArrayUtil, config){
9448
9449	var Color = dojo.Color = function(/*Array|String|Object*/ color){
9450		// summary:
9451		//		Takes a named string, hex string, array of rgb or rgba values,
9452		//		an object with r, g, b, and a properties, or another `Color` object
9453		//		and creates a new Color instance to work from.
9454		//
9455		// example:
9456		//		Work with a Color instance:
9457		//	|	require(["dojo/_base/color"], function(Color){
9458		//	|		var c = new Color();
9459		//	|		c.setColor([0,0,0]); // black
9460		//	|		var hex = c.toHex(); // #000000
9461		//	|	});
9462		//
9463		// example:
9464		//		Work with a node's color:
9465		//	| 
9466		//	|	require(["dojo/_base/color", "dojo/dom-style"], function(Color, domStyle){
9467		//	|		var color = domStyle("someNode", "backgroundColor");
9468		//	|		var n = new Color(color);
9469		//	|		// adjust the color some
9470		//	|		n.r *= .5;
9471		//	|		console.log(n.toString()); // rgb(128, 255, 255);
9472		//	|	});
9473		if(color){ this.setColor(color); }
9474	};
9475
9476	// FIXME:
9477	// there's got to be a more space-efficient way to encode or discover
9478	// these!! Use hex?
9479	Color.named = {
9480		// summary:
9481		//		Dictionary list of all CSS named colors, by name. Values are 3-item arrays with corresponding RG and B values.
9482		"black":  [0,0,0],
9483		"silver": [192,192,192],
9484		"gray":	  [128,128,128],
9485		"white":  [255,255,255],
9486		"maroon": [128,0,0],
9487		"red":	  [255,0,0],
9488		"purple": [128,0,128],
9489		"fuchsia":[255,0,255],
9490		"green":  [0,128,0],
9491		"lime":	  [0,255,0],
9492		"olive":  [128,128,0],
9493		"yellow": [255,255,0],
9494		"navy":	  [0,0,128],
9495		"blue":	  [0,0,255],
9496		"teal":	  [0,128,128],
9497		"aqua":	  [0,255,255],
9498		"transparent": config.transparentColor || [0,0,0,0]
9499	};
9500
9501	lang.extend(Color, {
9502		r: 255, g: 255, b: 255, a: 1,
9503		_set: function(r, g, b, a){
9504			var t = this; t.r = r; t.g = g; t.b = b; t.a = a;
9505		},
9506		setColor: function(/*Array|String|Object*/ color){
9507			// summary:
9508			//		Takes a named string, hex string, array of rgb or rgba values,
9509			//		an object with r, g, b, and a properties, or another `Color` object
9510			//		and sets this color instance to that value.
9511			//
9512			// example:
9513			//	|	require(["dojo/_base/color"], function(Color){
9514			//	|		var c = new Color(); // no color
9515			//	|		c.setColor("#ededed"); // greyish
9516			//	|	});
9517			if(lang.isString(color)){
9518				Color.fromString(color, this);
9519			}else if(lang.isArray(color)){
9520				Color.fromArray(color, this);
9521			}else{
9522				this._set(color.r, color.g, color.b, color.a);
9523				if(!(color instanceof Color)){ this.sanitize(); }
9524			}
9525			return this;	// Color
9526		},
9527		sanitize: function(){
9528			// summary:
9529			//		Ensures the object has correct attributes
9530			// description:
9531			//		the default implementation does nothing, include dojo.colors to
9532			//		augment it with real checks
9533			return this;	// Color
9534		},
9535		toRgb: function(){
9536			// summary:
9537			//		Returns 3 component array of rgb values
9538			// example:
9539			//	|	require(["dojo/_base/color"], function(Color){
9540			//	|		var c = new Color("#000000");
9541			//	|		console.log(c.toRgb()); // [0,0,0]
9542			//	|	});
9543			var t = this;
9544			return [t.r, t.g, t.b]; // Array
9545		},
9546		toRgba: function(){
9547			// summary:
9548			//		Returns a 4 component array of rgba values from the color
9549			//		represented by this object.
9550			var t = this;
9551			return [t.r, t.g, t.b, t.a];	// Array
9552		},
9553		toHex: function(){
9554			// summary:
9555			//		Returns a CSS color string in hexadecimal representation
9556			// example:
9557			//	|	require(["dojo/_base/color"], function(Color){
9558			//	|		console.log(new Color([0,0,0]).toHex()); // #000000
9559			//	|	});
9560			var arr = ArrayUtil.map(["r", "g", "b"], function(x){
9561				var s = this[x].toString(16);
9562				return s.length < 2 ? "0" + s : s;
9563			}, this);
9564			return "#" + arr.join("");	// String
9565		},
9566		toCss: function(/*Boolean?*/ includeAlpha){
9567			// summary:
9568			//		Returns a css color string in rgb(a) representation
9569			// example:
9570			//	|	require(["dojo/_base/color"], function(Color){
9571			//	|		var c = new Color("#FFF").toCss();
9572			//	|		console.log(c); // rgb('255','255','255')
9573			//	|	});
9574			var t = this, rgb = t.r + ", " + t.g + ", " + t.b;
9575			return (includeAlpha ? "rgba(" + rgb + ", " + t.a : "rgb(" + rgb) + ")";	// String
9576		},
9577		toString: function(){
9578			// summary:
9579			//		Returns a visual representation of the color
9580			return this.toCss(true); // String
9581		}
9582	});
9583
9584	Color.blendColors = dojo.blendColors = function(
9585		/*Color*/ start,
9586		/*Color*/ end,
9587		/*Number*/ weight,
9588		/*Color?*/ obj
9589	){
9590		// summary:
9591		//		Blend colors end and start with weight from 0 to 1, 0.5 being a 50/50 blend,
9592		//		can reuse a previously allocated Color object for the result
9593		var t = obj || new Color();
9594		ArrayUtil.forEach(["r", "g", "b", "a"], function(x){
9595			t[x] = start[x] + (end[x] - start[x]) * weight;
9596			if(x != "a"){ t[x] = Math.round(t[x]); }
9597		});
9598		return t.sanitize();	// Color
9599	};
9600
9601	Color.fromRgb = dojo.colorFromRgb = function(/*String*/ color, /*Color?*/ obj){
9602		// summary:
9603		//		Returns a `Color` instance from a string of the form
9604		//		"rgb(...)" or "rgba(...)". Optionally accepts a `Color`
9605		//		object to update with the parsed value and return instead of
9606		//		creating a new object.
9607		// returns:
9608		//		A Color object. If obj is passed, it will be the return value.
9609		var m = color.toLowerCase().match(/^rgba?\(([\s\.,0-9]+)\)/);
9610		return m && Color.fromArray(m[1].split(/\s*,\s*/), obj);	// Color
9611	};
9612
9613	Color.fromHex = dojo.colorFromHex = function(/*String*/ color, /*Color?*/ obj){
9614		// summary:
9615		//		Converts a hex string with a '#' prefix to a color object.
9616		//		Supports 12-bit #rgb shorthand. Optionally accepts a
9617		//		`Color` object to update with the parsed value.
9618		//
9619		// returns:
9620		//		A Color object. If obj is passed, it will be the return value.
9621		//
9622		// example:
9623		//	|	require(["dojo/_base/color"], function(Color){
9624		//	|		var thing = new Color().fromHex("#ededed"); // grey, longhand
9625		//	|		var thing2 = new Color().fromHex("#000"); // black, shorthand
9626		//	|	});
9627		var t = obj || new Color(),
9628			bits = (color.length == 4) ? 4 : 8,
9629			mask = (1 << bits) - 1;
9630		color = Number("0x" + color.substr(1));
9631		if(isNaN(color)){
9632			return null; // Color
9633		}
9634		ArrayUtil.forEach(["b", "g", "r"], function(x){
9635			var c = color & mask;
9636			color >>= bits;
9637			t[x] = bits == 4 ? 17 * c : c;
9638		});
9639		t.a = 1;
9640		return t;	// Color
9641	};
9642
9643	Color.fromArray = dojo.colorFromArray = function(/*Array*/ a, /*Color?*/ obj){
9644		// summary:
9645		//		Builds a `Color` from a 3 or 4 element array, mapping each
9646		//		element in sequence to the rgb(a) values of the color.
9647		// example:
9648		//		|	require(["dojo/_base/color"], function(Color){
9649		//		|		var myColor = new Color().fromArray([237,237,237,0.5]); // grey, 50% alpha
9650		//		|	});
9651		// returns:
9652		//		A Color object. If obj is passed, it will be the return value.
9653		var t = obj || new Color();
9654		t._set(Number(a[0]), Number(a[1]), Number(a[2]), Number(a[3]));
9655		if(isNaN(t.a)){ t.a = 1; }
9656		return t.sanitize();	// Color
9657	};
9658
9659	Color.fromString = dojo.colorFromString = function(/*String*/ str, /*Color?*/ obj){
9660		// summary:
9661		//		Parses `str` for a color value. Accepts hex, rgb, and rgba
9662		//		style color values.
9663		// description:
9664		//		Acceptable input values for str may include arrays of any form
9665		//		accepted by dojo.colorFromArray, hex strings such as "#aaaaaa", or
9666		//		rgb or rgba strings such as "rgb(133, 200, 16)" or "rgba(10, 10,
9667		//		10, 50)"
9668		// returns:
9669		//		A Color object. If obj is passed, it will be the return value.
9670		var a = Color.named[str];
9671		return a && Color.fromArray(a, obj) || Color.fromRgb(str, obj) || Color.fromHex(str, obj);	// Color
9672	};
9673
9674	return Color;
9675});
9676
9677},
9678'dojo/_base/browser':function(){
9679if(require.has){
9680	require.has.add("config-selectorEngine", "acme");
9681}
9682define([
9683	"../ready",
9684	"./kernel",
9685	"./connect", // until we decide if connect is going back into non-browser environments
9686	"./unload",
9687	"./window",
9688	"./event",
9689	"./html",
9690	"./NodeList",
9691	"../query",
9692	"./xhr",
9693	"./fx"], function(dojo){
9694
9695	// module:
9696	//		dojo/_base/browser
9697
9698	/*=====
9699	return {
9700		// summary:
9701		//		This module causes the browser-only base modules to be loaded.
9702	};
9703	=====*/
9704
9705	return dojo;
9706});
9707
9708},
9709'dojo/_base/unload':function(){
9710define(["./kernel", "./lang", "../on"], function(dojo, lang, on){
9711
9712// module:
9713//		dojo/unload
9714
9715var win = window;
9716
9717var unload = {
9718	// summary:
9719	//		This module contains the document and window unload detection API.
9720	//		This module is deprecated.  Use on(window, "unload", func)
9721	//		and on(window, "beforeunload", func) instead.
9722
9723	addOnWindowUnload: function(/*Object|Function?*/ obj, /*String|Function?*/ functionName){
9724		// summary:
9725		//		Registers a function to be triggered when window.onunload fires.
9726		//		Deprecated, use on(window, "unload", lang.hitch(obj, functionName)) instead.
9727		// description:
9728		//		The first time that addOnWindowUnload is called Dojo
9729		//		will register a page listener to trigger your unload
9730		//		handler with. Note that registering these handlers may
9731		//		destroy "fastback" page caching in browsers that support
9732		//		it. Be careful trying to modify the DOM or access
9733		//		JavaScript properties during this phase of page unloading:
9734		//		they may not always be available. Consider
9735		//		addOnUnload() if you need to modify the DOM or do
9736		//		heavy JavaScript work since it fires at the equivalent of
9737		//		the page's "onbeforeunload" event.
9738		// example:
9739		//	|	var afunc = function() {console.log("global function");};
9740		//	|	require(["dojo/_base/unload"], function(unload) {
9741		//	|		var foo = {bar: function(){ console.log("bar unloading...");}, 
9742		//	|		           data: "mydata"};
9743		//	|		unload.addOnWindowUnload(afunc);
9744		//	|		unload.addOnWindowUnload(foo, "bar");
9745		//	|		unload.addOnWindowUnload(foo, function(){console.log("", this.data);});
9746		//	|	});
9747
9748		if (!dojo.windowUnloaded){
9749			on(win, "unload", (dojo.windowUnloaded = function(){
9750				// summary:
9751				//		signal fired by impending window destruction. You may use
9752				//		dojo.addOnWindowUnload() to register a listener for this
9753				//		event. NOTE: if you wish to dojo.connect() to this method
9754				//		to perform page/application cleanup, be aware that this
9755				//		event WILL NOT fire if no handler has been registered with
9756				//		addOnWindowUnload(). This behavior started in Dojo 1.3.
9757				//		Previous versions always triggered windowUnloaded(). See
9758				//		addOnWindowUnload for more info.
9759			}));
9760		}
9761		on(win, "unload", lang.hitch(obj, functionName));
9762	},
9763
9764	addOnUnload: function(/*Object?|Function?*/ obj, /*String|Function?*/ functionName){
9765		// summary:
9766		//		Registers a function to be triggered when the page unloads.
9767		//		Deprecated, use on(window, "beforeunload", lang.hitch(obj, functionName)) instead.
9768		// description:
9769		//		The first time that addOnUnload is called Dojo will
9770		//		register a page listener to trigger your unload handler
9771		//		with.
9772		//
9773		//		In a browser environment, the functions will be triggered
9774		//		during the window.onbeforeunload event. Be careful of doing
9775		//		too much work in an unload handler. onbeforeunload can be
9776		//		triggered if a link to download a file is clicked, or if
9777		//		the link is a javascript: link. In these cases, the
9778		//		onbeforeunload event fires, but the document is not
9779		//		actually destroyed. So be careful about doing destructive
9780		//		operations in a dojo.addOnUnload callback.
9781		//
9782		//		Further note that calling dojo.addOnUnload will prevent
9783		//		browsers from using a "fast back" cache to make page
9784		//		loading via back button instantaneous.
9785		// example:
9786		//	|	var afunc = function() {console.log("global function");};
9787		//	|	require(["dojo/_base/unload"], function(unload) {
9788		//	|		var foo = {bar: function(){ console.log("bar unloading...");}, 
9789		//	|		           data: "mydata"};
9790		//	|		unload.addOnUnload(afunc);
9791		//	|		unload.addOnUnload(foo, "bar");
9792		//	|		unload.addOnUnload(foo, function(){console.log("", this.data);});
9793		//	|	});
9794
9795		on(win, "beforeunload", lang.hitch(obj, functionName));
9796	}
9797};
9798
9799dojo.addOnWindowUnload = unload.addOnWindowUnload;
9800dojo.addOnUnload = unload.addOnUnload;
9801
9802return unload;
9803
9804});
9805
9806},
9807'dojo/_base/html':function(){
9808define(["./kernel", "../dom", "../dom-style", "../dom-attr", "../dom-prop", "../dom-class", "../dom-construct", "../dom-geometry"], function(dojo, dom, style, attr, prop, cls, ctr, geom){
9809	// module:
9810	//		dojo/dom
9811
9812	/*=====
9813	return {
9814		// summary:
9815		//		This module is a stub for the core dojo DOM API.
9816	};
9817	=====*/
9818
9819	// mix-in dom
9820	dojo.byId = dom.byId;
9821	dojo.isDescendant = dom.isDescendant;
9822	dojo.setSelectable = dom.setSelectable;
9823
9824	// mix-in dom-attr
9825	dojo.getAttr = attr.get;
9826	dojo.setAttr = attr.set;
9827	dojo.hasAttr = attr.has;
9828	dojo.removeAttr = attr.remove;
9829	dojo.getNodeProp = attr.getNodeProp;
9830
9831	dojo.attr = function(node, name, value){
9832		// summary:
9833		//		Gets or sets an attribute on an HTML element.
9834		// description:
9835		//		Handles normalized getting and setting of attributes on DOM
9836		//		Nodes. If 2 arguments are passed, and a the second argument is a
9837		//		string, acts as a getter.
9838		//
9839		//		If a third argument is passed, or if the second argument is a
9840		//		map of attributes, acts as a setter.
9841		//
9842		//		When passing functions as values, note that they will not be
9843		//		directly assigned to slots on the node, but rather the default
9844		//		behavior will be removed and the new behavior will be added
9845		//		using `dojo.connect()`, meaning that event handler properties
9846		//		will be normalized and that some caveats with regards to
9847		//		non-standard behaviors for onsubmit apply. Namely that you
9848		//		should cancel form submission using `dojo.stopEvent()` on the
9849		//		passed event object instead of returning a boolean value from
9850		//		the handler itself.
9851		// node: DOMNode|String
9852		//		id or reference to the element to get or set the attribute on
9853		// name: String|Object
9854		//		the name of the attribute to get or set.
9855		// value: String?
9856		//		The value to set for the attribute
9857		// returns:
9858		//		when used as a getter, the value of the requested attribute
9859		//		or null if that attribute does not have a specified or
9860		//		default value;
9861		//
9862		//		when used as a setter, the DOM node
9863		//
9864		// example:
9865		//	|	// get the current value of the "foo" attribute on a node
9866		//	|	dojo.attr(dojo.byId("nodeId"), "foo");
9867		//	|	// or we can just pass the id:
9868		//	|	dojo.attr("nodeId", "foo");
9869		//
9870		// example:
9871		//	|	// use attr() to set the tab index
9872		//	|	dojo.attr("nodeId", "tabIndex", 3);
9873		//	|
9874		//
9875		// example:
9876		//	Set multiple values at once, including event handlers:
9877		//	|	dojo.attr("formId", {
9878		//	|		"foo": "bar",
9879		//	|		"tabIndex": -1,
9880		//	|		"method": "POST",
9881		//	|		"onsubmit": function(e){
9882		//	|			// stop submitting the form. Note that the IE behavior
9883		//	|			// of returning true or false will have no effect here
9884		//	|			// since our handler is connect()ed to the built-in
9885		//	|			// onsubmit behavior and so we need to use
9886		//	|			// dojo.stopEvent() to ensure that the submission
9887		//	|			// doesn't proceed.
9888		//	|			dojo.stopEvent(e);
9889		//	|
9890		//	|			// submit the form with Ajax
9891		//	|			dojo.xhrPost({ form: "formId" });
9892		//	|		}
9893		//	|	});
9894		//
9895		// example:
9896		//	Style is s special case: Only set with an object hash of styles
9897		//	|	dojo.attr("someNode",{
9898		//	|		id:"bar",
9899		//	|		style:{
9900		//	|			width:"200px", height:"100px", color:"#000"
9901		//	|		}
9902		//	|	});
9903		//
9904		// example:
9905		//	Again, only set style as an object hash of styles:
9906		//	|	var obj = { color:"#fff", backgroundColor:"#000" };
9907		//	|	dojo.attr("someNode", "style", obj);
9908		//	|
9909		//	|	// though shorter to use `dojo.style()` in this case:
9910		//	|	dojo.style("someNode", obj);
9911
9912		if(arguments.length == 2){
9913			return attr[typeof name == "string" ? "get" : "set"](node, name);
9914		}
9915		return attr.set(node, name, value);
9916	};
9917
9918	// mix-in dom-class
9919	dojo.hasClass = cls.contains;
9920	dojo.addClass = cls.add;
9921	dojo.removeClass = cls.remove;
9922	dojo.toggleClass = cls.toggle;
9923	dojo.replaceClass = cls.replace;
9924
9925	// mix-in dom-construct
9926	dojo._toDom = dojo.toDom = ctr.toDom;
9927	dojo.place = ctr.place;
9928	dojo.create = ctr.create;
9929	dojo.empty = function(node){ ctr.empty(node); };
9930	dojo._destroyElement = dojo.destroy = function(node){ ctr.destroy(node); };
9931
9932	// mix-in dom-geometry
9933	dojo._getPadExtents = dojo.getPadExtents = geom.getPadExtents;
9934	dojo._getBorderExtents = dojo.getBorderExtents = geom.getBorderExtents;
9935	dojo._getPadBorderExtents = dojo.getPadBorderExtents = geom.getPadBorderExtents;
9936	dojo._getMarginExtents = dojo.getMarginExtents = geom.getMarginExtents;
9937	dojo._getMarginSize = dojo.getMarginSize = geom.getMarginSize;
9938	dojo._getMarginBox = dojo.getMarginBox = geom.getMarginBox;
9939	dojo.setMarginBox = geom.setMarginBox;
9940	dojo._getContentBox = dojo.getContentBox = geom.getContentBox;
9941	dojo.setContentSize = geom.setContentSize;
9942	dojo._isBodyLtr = dojo.isBodyLtr = geom.isBodyLtr;
9943	dojo._docScroll = dojo.docScroll = geom.docScroll;
9944	dojo._getIeDocumentElementOffset = dojo.getIeDocumentElementOffset = geom.getIeDocumentElementOffset;
9945	dojo._fixIeBiDiScrollLeft = dojo.fixIeBiDiScrollLeft = geom.fixIeBiDiScrollLeft;
9946	dojo.position = geom.position;
9947
9948	dojo.marginBox = function marginBox(/*DomNode|String*/node, /*Object?*/box){
9949		// summary:
9950		//		Getter/setter for the margin-box of node.
9951		// description:
9952		//		Getter/setter for the margin-box of node.
9953		//		Returns an object in the expected format of box (regardless
9954		//		if box is passed). The object might look like:
9955		//		`{ l: 50, t: 200, w: 300: h: 150 }`
9956		//		for a node offset from its parent 50px to the left, 200px from
9957		//		the top with a margin width of 300px and a margin-height of
9958		//		150px.
9959		// node:
9960		//		id or reference to DOM Node to get/set box for
9961		// box:
9962		//		If passed, denotes that dojo.marginBox() should
9963		//		update/set the margin box for node. Box is an object in the
9964		//		above format. All properties are optional if passed.
9965		// example:
9966		//		Retrieve the margin box of a passed node
9967		//	|	var box = dojo.marginBox("someNodeId");
9968		//	|	console.dir(box);
9969		//
9970		// example:
9971		//		Set a node's margin box to the size of another node
9972		//	|	var box = dojo.marginBox("someNodeId");
9973		//	|	dojo.marginBox("someOtherNode", box);
9974		return box ? geom.setMarginBox(node, box) : geom.getMarginBox(node); // Object
9975	};
9976
9977	dojo.contentBox = function contentBox(/*DomNode|String*/node, /*Object?*/box){
9978		// summary:
9979		//		Getter/setter for the content-box of node.
9980		// description:
9981		//		Returns an object in the expected format of box (regardless if box is passed).
9982		//		The object might look like:
9983		//		`{ l: 50, t: 200, w: 300: h: 150 }`
9984		//		for a node offset from its parent 50px to the left, 200px from
9985		//		the top with a content width of 300px and a content-height of
9986		//		150px. Note that the content box may have a much larger border
9987		//		or margin box, depending on the box model currently in use and
9988		//		CSS values set/inherited for node.
9989		//		While the getter will return top and left values, the
9990		//		setter only accepts setting the width and height.
9991		// node:
9992		//		id or reference to DOM Node to get/set box for
9993		// box:
9994		//		If passed, denotes that dojo.contentBox() should
9995		//		update/set the content box for node. Box is an object in the
9996		//		above format, but only w (width) and h (height) are supported.
9997		//		All properties are optional if passed.
9998		return box ? geom.setContentSize(node, box) : geom.getContentBox(node); // Object
9999	};
10000
10001	dojo.coords = function(/*DomNode|String*/node, /*Boolean?*/includeScroll){
10002		// summary:
10003		//		Deprecated: Use position() for border-box x/y/w/h
10004		//		or marginBox() for margin-box w/h/l/t.
10005		//
10006		//		Returns an object that measures margin-box (w)idth/(h)eight
10007		//		and absolute position x/y of the border-box. Also returned
10008		//		is computed (l)eft and (t)op values in pixels from the
10009		//		node's offsetParent as returned from marginBox().
10010		//		Return value will be in the form:
10011		//|			{ l: 50, t: 200, w: 300: h: 150, x: 100, y: 300 }
10012		//		Does not act as a setter. If includeScroll is passed, the x and
10013		//		y params are affected as one would expect in dojo.position().
10014		dojo.deprecated("dojo.coords()", "Use dojo.position() or dojo.marginBox().");
10015		node = dom.byId(node);
10016		var s = style.getComputedStyle(node), mb = geom.getMarginBox(node, s);
10017		var abs = geom.position(node, includeScroll);
10018		mb.x = abs.x;
10019		mb.y = abs.y;
10020		return mb;	// Object
10021	};
10022
10023	// mix-in dom-prop
10024	dojo.getProp = prop.get;
10025	dojo.setProp = prop.set;
10026
10027	dojo.prop = function(/*DomNode|String*/node, /*String|Object*/name, /*String?*/value){
10028		// summary:
10029		//		Gets or sets a property on an HTML element.
10030		// description:
10031		//		Handles normalized getting and setting of properties on DOM
10032		//		Nodes. If 2 arguments are passed, and a the second argument is a
10033		//		string, acts as a getter.
10034		//
10035		//		If a third argument is passed, or if the second argument is a
10036		//		map of attributes, acts as a setter.
10037		//
10038		//		When passing functions as values, note that they will not be
10039		//		directly assigned to slots on the node, but rather the default
10040		//		behavior will be removed and the new behavior will be added
10041		//		using `dojo.connect()`, meaning that event handler properties
10042		//		will be normalized and that some caveats with regards to
10043		//		non-standard behaviors for onsubmit apply. Namely that you
10044		//		should cancel form submission using `dojo.stopEvent()` on the
10045		//		passed event object instead of returning a boolean value from
10046		//		the handler itself.
10047		// node:
10048		//		id or reference to the element to get or set the property on
10049		// name:
10050		//		the name of the property to get or set.
10051		// value:
10052		//		The value to set for the property
10053		// returns:
10054		//		when used as a getter, the value of the requested property
10055		//		or null if that attribute does not have a specified or
10056		//		default value;
10057		//
10058		//		when used as a setter, the DOM node
10059		//
10060		// example:
10061		//	|	// get the current value of the "foo" property on a node
10062		//	|	dojo.prop(dojo.byId("nodeId"), "foo");
10063		//	|	// or we can just pass the id:
10064		//	|	dojo.prop("nodeId", "foo");
10065		//
10066		// example:
10067		//	|	// use prop() to set the tab index
10068		//	|	dojo.prop("nodeId", "tabIndex", 3);
10069		//	|
10070		//
10071		// example:
10072		//	Set multiple values at once, including event handlers:
10073		//	|	dojo.prop("formId", {
10074		//	|		"foo": "bar",
10075		//	|		"tabIndex": -1,
10076		//	|		"method": "POST",
10077		//	|		"onsubmit": function(e){
10078		//	|			// stop submitting the form. Note that the IE behavior
10079		//	|			// of returning true or false will have no effect here
10080		//	|			// since our handler is connect()ed to the built-in
10081		//	|			// onsubmit behavior and so we need to use
10082		//	|			// dojo.stopEvent() to ensure that the submission
10083		//	|			// doesn't proceed.
10084		//	|			dojo.stopEvent(e);
10085		//	|
10086		//	|			// submit the form with Ajax
10087		//	|			dojo.xhrPost({ form: "formId" });
10088		//	|		}
10089		//	|	});
10090		//
10091		// example:
10092		//		Style is s special case: Only set with an object hash of styles
10093		//	|	dojo.prop("someNode",{
10094		//	|		id:"bar",
10095		//	|		style:{
10096		//	|			width:"200px", height:"100px", color:"#000"
10097		//	|		}
10098		//	|	});
10099		//
10100		// example:
10101		//		Again, only set style as an object hash of styles:
10102		//	|	var obj = { color:"#fff", backgroundColor:"#000" };
10103		//	|	dojo.prop("someNode", "style", obj);
10104		//	|
10105		//	|	// though shorter to use `dojo.style()` in this case:
10106		//	|	dojo.style("someNode", obj);
10107
10108		if(arguments.length == 2){
10109			return prop[typeof name == "string" ? "get" : "set"](node, name);
10110		}
10111		// setter
10112		return prop.set(node, name, value);
10113	};
10114
10115	// mix-in dom-style
10116	dojo.getStyle = style.get;
10117	dojo.setStyle = style.set;
10118	dojo.getComputedStyle = style.getComputedStyle;
10119	dojo.__toPixelValue = dojo.toPixelValue = style.toPixelValue;
10120
10121	dojo.style = function(node, name, value){
10122		// summary:
10123		//		Accesses styles on a node. If 2 arguments are
10124		//		passed, acts as a getter. If 3 arguments are passed, acts
10125		//		as a setter.
10126		// description:
10127		//		Getting the style value uses the computed style for the node, so the value
10128		//		will be a calculated value, not just the immediate node.style value.
10129		//		Also when getting values, use specific style names,
10130		//		like "borderBottomWidth" instead of "border" since compound values like
10131		//		"border" are not necessarily reflected as expected.
10132		//		If you want to get node dimensions, use `dojo.marginBox()`,
10133		//		`dojo.contentBox()` or `dojo.position()`.
10134		// node: DOMNode|String
10135		//		id or reference to node to get/set style for
10136		// name: String|Object?
10137		//		the style property to set in DOM-accessor format
10138		//		("borderWidth", not "border-width") or an object with key/value
10139		//		pairs suitable for setting each property.
10140		// value: String?
10141		//		If passed, sets value on the node for style, handling
10142		//		cross-browser concerns.  When setting a pixel value,
10143		//		be sure to include "px" in the value. For instance, top: "200px".
10144		//		Otherwise, in some cases, some browsers will not apply the style.
10145		// returns:
10146		//		when used as a getter, return the computed style of the node if passing in an ID or node,
10147		//		or return the normalized, computed value for the property when passing in a node and a style property
10148		// example:
10149		//		Passing only an ID or node returns the computed style object of
10150		//		the node:
10151		//	|	dojo.style("thinger");
10152		// example:
10153		//		Passing a node and a style property returns the current
10154		//		normalized, computed value for that property:
10155		//	|	dojo.style("thinger", "opacity"); // 1 by default
10156		//
10157		// example:
10158		//		Passing a node, a style property, and a value changes the
10159		//		current display of the node and returns the new computed value
10160		//	|	dojo.style("thinger", "opacity", 0.5); // == 0.5
10161		//
10162		// example:
10163		//		Passing a node, an object-style style property sets each of the values in turn and returns the computed style object of the node:
10164		//	|	dojo.style("thinger", {
10165		//	|		"opacity": 0.5,
10166		//	|		"border": "3px solid black",
10167		//	|		"height": "300px"
10168		//	|	});
10169		//
10170		// example:
10171		//		When the CSS style property is hyphenated, the JavaScript property is camelCased.
10172		//		font-size becomes fontSize, and so on.
10173		//	|	dojo.style("thinger",{
10174		//	|		fontSize:"14pt",
10175		//	|		letterSpacing:"1.2em"
10176		//	|	});
10177		//
10178		// example:
10179		//		dojo/NodeList implements .style() using the same syntax, omitting the "node" parameter, calling
10180		//		dojo.style() on every element of the list. See: `dojo/query` and `dojo/NodeList`
10181		//	|	dojo.query(".someClassName").style("visibility","hidden");
10182		//	|	// or
10183		//	|	dojo.query("#baz > div").style({
10184		//	|		opacity:0.75,
10185		//	|		fontSize:"13pt"
10186		//	|	});
10187
10188		switch(arguments.length){
10189			case 1:
10190				return style.get(node);
10191			case 2:
10192				return style[typeof name == "string" ? "get" : "set"](node, name);
10193		}
10194		// setter
10195		return style.set(node, name, value);
10196	};
10197
10198	return dojo;
10199});
10200
10201},
10202'dojo/dom-attr':function(){
10203define(["exports", "./sniff", "./_base/lang", "./dom", "./dom-style", "./dom-prop"],
10204		function(exports, has, lang, dom, style, prop){
10205	// module:
10206	//		dojo/dom-attr
10207	// summary:
10208	//		This module defines the core dojo DOM attributes API.
10209
10210	// TODOC: summary not showing up in output see https://github.com/csnover/js-doc-parse/issues/42
10211
10212	// =============================
10213	// Element attribute Functions
10214	// =============================
10215
10216	// This module will be obsolete soon. Use dojo/prop instead.
10217
10218	// dojo/dom-attr.get() should conform to http://www.w3.org/TR/DOM-Level-2-Core/
10219
10220	// attribute-related functions (to be obsolete soon)
10221	var forcePropNames = {
10222			innerHTML:	1,
10223			textContent:1,
10224			className:	1,
10225			htmlFor:	has("ie"),
10226			value:		1
10227		},
10228		attrNames = {
10229			// original attribute names
10230			classname: "class",
10231			htmlfor: "for",
10232			// for IE
10233			tabindex: "tabIndex",
10234			readonly: "readOnly"
10235		};
10236
10237	function _hasAttr(node, name){
10238		var attr = node.getAttributeNode && node.getAttributeNode(name);
10239		return !!attr && attr.specified; // Boolean
10240	}
10241	
10242	// There is a difference in the presence of certain properties and their default values
10243	// between browsers. For example, on IE "disabled" is present on all elements,
10244	// but it is value is "false"; "tabIndex" of <div> returns 0 by default on IE, yet other browsers
10245	// can return -1.
10246
10247	exports.has = function hasAttr(/*DOMNode|String*/ node, /*String*/ name){
10248		// summary:
10249		//		Returns true if the requested attribute is specified on the
10250		//		given element, and false otherwise.
10251		// node: DOMNode|String
10252		//		id or reference to the element to check
10253		// name: String
10254		//		the name of the attribute
10255		// returns: Boolean
10256		//		true if the requested attribute is specified on the
10257		//		given element, and false otherwise
10258
10259		var lc = name.toLowerCase();
10260		return forcePropNames[prop.names[lc] || name] || _hasAttr(dom.byId(node), attrNames[lc] || name);	// Boolean
10261	};
10262
10263	exports.get = function getAttr(/*DOMNode|String*/ node, /*String*/ name){
10264		// summary:
10265		//		Gets an attribute on an HTML element.
10266		// description:
10267		//		Handles normalized getting of attributes on DOM Nodes.
10268		// node: DOMNode|String
10269		//		id or reference to the element to get the attribute on
10270		// name: String
10271		//		the name of the attribute to get.
10272		// returns:
10273		//		the value of the requested attribute or null if that attribute does not have a specified or
10274		//		default value;
10275		//
10276		// example:
10277		//	|	// get the current value of the "foo" attribute on a node
10278		//	|	require(["dojo/dom-attr", "dojo/dom"], function(domAttr, dom){
10279		//	|		domAttr.get(dom.byId("nodeId"), "foo");
10280		//	|		// or we can just pass the id:
10281		//	|		domAttr.get("nodeId", "foo");
10282		//	|	});	
10283		//	|	
10284
10285		node = dom.byId(node);
10286		var lc = name.toLowerCase(),
10287			propName = prop.names[lc] || name,
10288			forceProp = forcePropNames[propName],
10289			value = node[propName];		// should we access this attribute via a property or via getAttribute()?
10290
10291		if(forceProp && typeof value != "undefined"){
10292			// node's property
10293			return value;	// Anything
10294		}
10295		
10296		if(propName == "textContent"){
10297			return prop.get(node, propName);
10298		}
10299		
10300		if(propName != "href" && (typeof value == "boolean" || lang.isFunction(value))){
10301			// node's property
10302			return value;	// Anything
10303		}
10304		// node's attribute
10305		// we need _hasAttr() here to guard against IE returning a default value
10306		var attrName = attrNames[lc] || name;
10307		return _hasAttr(node, attrName) ? node.getAttribute(attrName) : null; // Anything
10308	};
10309
10310	exports.set = function setAttr(/*DOMNode|String*/ node, /*String|Object*/ name, /*String?*/ value){
10311		// summary:
10312		//		Sets an attribute on an HTML element.
10313		// description:
10314		//		Handles normalized setting of attributes on DOM Nodes.
10315		//
10316		//		When passing functions as values, note that they will not be
10317		//		directly assigned to slots on the node, but rather the default
10318		//		behavior will be removed and the new behavior will be added
10319		//		using `dojo.connect()`, meaning that event handler properties
10320		//		will be normalized and that some caveats with regards to
10321		//		non-standard behaviors for onsubmit apply. Namely that you
10322		//		should cancel form submission using `dojo.stopEvent()` on the
10323		//		passed event object instead of returning a boolean value from
10324		//		the handler itself.
10325		// node: DOMNode|String
10326		//		id or reference to the element to set the attribute on
10327		// name: String|Object
10328		//		the name of the attribute to set, or a hash of key-value pairs to set.
10329		// value: String?
10330		//		the value to set for the attribute, if the name is a string.
10331		// returns:
10332		//		the DOM node
10333		//
10334		// example:
10335		//	|	// use attr() to set the tab index
10336		//	|	require(["dojo/dom-attr"], function(domAttr){
10337		//	|		domAttr.set("nodeId", "tabIndex", 3);
10338		//	|	});
10339		//
10340		// example:
10341		//	Set multiple values at once, including event handlers:
10342		//	|	require(["dojo/dom-attr"],
10343		//	|	function(domAttr){
10344		//	|		domAttr.set("formId", {
10345		//	|			"foo": "bar",
10346		//	|			"tabIndex": -1,
10347		//	|			"method": "POST"
10348		//	|		}
10349		//	|	});
10350
10351		node = dom.byId(node);
10352		if(arguments.length == 2){ // inline'd type check
10353			// the object form of setter: the 2nd argument is a dictionary
10354			for(var x in name){
10355				exports.set(node, x, name[x]);
10356			}
10357			return node; // DomNode
10358		}
10359		var lc = name.toLowerCase(),
10360			propName = prop.names[lc] || name,
10361			forceProp = forcePropNames[propName];
10362		if(propName == "style" && typeof value != "string"){ // inline'd type check
10363			// special case: setting a style
10364			style.set(node, value);
10365			return node; // DomNode
10366		}
10367		if(forceProp || typeof value == "boolean" || lang.isFunction(value)){
10368			return prop.set(node, name, value);
10369		}
10370		// node's attribute
10371		node.setAttribute(attrNames[lc] || name, value);
10372		return node; // DomNode
10373	};
10374
10375	exports.remove = function removeAttr(/*DOMNode|String*/ node, /*String*/ name){
10376		// summary:
10377		//		Removes an attribute from an HTML element.
10378		// node: DOMNode|String
10379		//		id or reference to the element to remove the attribute from
10380		// name: String
10381		//		the name of the attribute to remove
10382
10383		dom.byId(node).removeAttribute(attrNames[name.toLowerCase()] || name);
10384	};
10385
10386	exports.getNodeProp = function getNodeProp(/*DomNode|String*/ node, /*String*/ name){
10387		// summary:
10388		//		Returns an effective value of a property or an attribute.
10389		// node: DOMNode|String
10390		//		id or reference to the element to remove the attribute from
10391		// name: String
10392		//		the name of the attribute
10393		// returns:
10394		//		the value of the attribute
10395
10396		node = dom.byId(node);
10397		var lc = name.toLowerCase(), propName = prop.names[lc] || name;
10398		if((propName in node) && propName != "href"){
10399			// node's property
10400			return node[propName];	// Anything
10401		}
10402		// node's attribute
10403		var attrName = attrNames[lc] || name;
10404		return _hasAttr(node, attrName) ? node.getAttribute(attrName) : null; // Anything
10405	};
10406});
10407
10408},
10409'dojo/dom-prop':function(){
10410define(["exports", "./_base/kernel", "./sniff", "./_base/lang", "./dom", "./dom-style", "./dom-construct", "./_base/connect"],
10411		function(exports, dojo, has, lang, dom, style, ctr, conn){
10412	// module:
10413	//		dojo/dom-prop
10414	// summary:
10415	//		This module defines the core dojo DOM properties API.
10416
10417	// TODOC: summary not showing up in output, see https://github.com/csnover/js-doc-parse/issues/42
10418
10419	// =============================
10420	// Element properties Functions
10421	// =============================
10422
10423	// helper to connect events
10424	var _evtHdlrMap = {}, _ctr = 0, _attrId = dojo._scopeName + "attrid";
10425	has.add('dom-textContent', function (global, doc, element) { return 'textContent' in element; });
vendor: 6,258 bytes, lines 10426-10628
10426
10427	exports.names = {
10428		// properties renamed to avoid clashes with reserved words
10429		"class": "className",
10430		"for": "htmlFor",
10431		// properties written as camelCase
10432		tabindex: "tabIndex",
10433		readonly: "readOnly",
10434		colspan: "colSpan",
10435		frameborder: "frameBorder",
10436		rowspan: "rowSpan",
10437		textcontent: "textContent",
10438		valuetype: "valueType"
10439	};
10440	
10441	function getText(/*DOMNode*/node){
10442		// summary:
10443		//		recursion method for get('textContent') to use. Gets text value for a node.
10444		// description:
10445		//		Juse uses nodedValue so things like <br/> tags do not end up in
10446		//		the text as any sort of line return.
10447		var text = "", ch = node.childNodes;
10448		for(var i = 0, n; n = ch[i]; i++){
10449			//Skip comments.
10450			if(n.nodeType != 8){
10451				if(n.nodeType == 1){
10452					text += getText(n);
10453				}else{
10454					text += n.nodeValue;
10455				}
10456			}
10457		}
10458		return text;
10459	}
10460
10461	exports.get = function getProp(/*DOMNode|String*/ node, /*String*/ name){
10462		// summary:
10463		//		Gets a property on an HTML element.
10464		// description:
10465		//		Handles normalized getting of properties on DOM nodes.
10466		//
10467		// node: DOMNode|String
10468		//		id or reference to the element to get the property on
10469		// name: String
10470		//		the name of the property to get.
10471		// returns:
10472		//		the value of the requested property or its default value
10473		//
10474		// example:
10475		//	|	// get the current value of the "foo" property on a node
10476		//	|	require(["dojo/dom-prop", "dojo/dom"], function(domProp, dom){
10477		//	|		domProp.get(dom.byId("nodeId"), "foo");
10478		//	|		// or we can just pass the id:
10479		//	|		domProp.get("nodeId", "foo");
10480		//	|	});
10481
10482		node = dom.byId(node);
10483		var lc = name.toLowerCase(), propName = exports.names[lc] || name;
10484		
10485		if(propName == "textContent" && !has("dom-textContent")){
10486			return getText(node);
10487		}
10488		
10489		return node[propName];	// Anything
10490	};
10491
10492	exports.set = function setProp(/*DOMNode|String*/ node, /*String|Object*/ name, /*String?*/ value){
10493		// summary:
10494		//		Sets a property on an HTML element.
10495		// description:
10496		//		Handles normalized setting of properties on DOM nodes.
10497		//
10498		//		When passing functions as values, note that they will not be
10499		//		directly assigned to slots on the node, but rather the default
10500		//		behavior will be removed and the new behavior will be added
10501		//		using `dojo.connect()`, meaning that event handler properties
10502		//		will be normalized and that some caveats with regards to
10503		//		non-standard behaviors for onsubmit apply. Namely that you
10504		//		should cancel form submission using `dojo.stopEvent()` on the
10505		//		passed event object instead of returning a boolean value from
10506		//		the handler itself.
10507		// node: DOMNode|String
10508		//		id or reference to the element to set the property on
10509		// name: String|Object
10510		//		the name of the property to set, or a hash object to set
10511		//		multiple properties at once.
10512		// value: String?
10513		//		The value to set for the property
10514		// returns:
10515		//		the DOM node
10516		//
10517		// example:
10518		//	|	// use prop() to set the tab index
10519		//	|	require(["dojo/dom-prop"], function(domProp){
10520		//	|		domProp.set("nodeId", "tabIndex", 3);
10521		//	|	});
10522		//
10523		// example:
10524		//	Set multiple values at once, including event handlers:
10525		//	|	require(["dojo/dom-prop"], function(domProp){
10526		//	|		domProp.set("formId", {
10527		//	|			"foo": "bar",
10528		//	|			"tabIndex": -1,
10529		//	|			"method": "POST",
10530		//	|		});
10531		//	|	});
10532
10533		node = dom.byId(node);
10534		var l = arguments.length;
10535		if(l == 2 && typeof name != "string"){ // inline'd type check
10536			// the object form of setter: the 2nd argument is a dictionary
10537			for(var x in name){
10538				exports.set(node, x, name[x]);
10539			}
10540			return node; // DomNode
10541		}
10542		var lc = name.toLowerCase(), propName = exports.names[lc] || name;
10543		if(propName == "style" && typeof value != "string"){ // inline'd type check
10544			// special case: setting a style
10545			style.set(node, value);
10546			return node; // DomNode
10547		}
10548		if(propName == "innerHTML"){
10549			// special case: assigning HTML
10550			// the hash lists elements with read-only innerHTML on IE
10551			if(has("ie") && node.tagName.toLowerCase() in {col: 1, colgroup: 1,
10552						table: 1, tbody: 1, tfoot: 1, thead: 1, tr: 1, title: 1}){
10553				ctr.empty(node);
10554				node.appendChild(ctr.toDom(value, node.ownerDocument));
10555			}else{
10556				node[propName] = value;
10557			}
10558			return node; // DomNode
10559		}
10560		if(propName == "textContent" && !has("dom-textContent")) {
10561			ctr.empty(node);
10562			node.appendChild(node.ownerDocument.createTextNode(value));
10563			return node;
10564		}
10565		if(lang.isFunction(value)){
10566			// special case: assigning an event handler
10567			// clobber if we can
10568			var attrId = node[_attrId];
10569			if(!attrId){
10570				attrId = _ctr++;
10571				node[_attrId] = attrId;
10572			}
10573			if(!_evtHdlrMap[attrId]){
10574				_evtHdlrMap[attrId] = {};
10575			}
10576			var h = _evtHdlrMap[attrId][propName];
10577			if(h){
10578				//h.remove();
10579				conn.disconnect(h);
10580			}else{
10581				try{
10582					delete node[propName];
10583				}catch(e){}
10584			}
10585			// ensure that event objects are normalized, etc.
10586			if(value){
10587				//_evtHdlrMap[attrId][propName] = on(node, propName, value);
10588				_evtHdlrMap[attrId][propName] = conn.connect(node, propName, value);
10589			}else{
10590				node[propName] = null;
10591			}
10592			return node; // DomNode
10593		}
10594		node[propName] = value;
10595		return node;	// DomNode
10596	};
10597});
10598
10599},
10600'dojo/dom-construct':function(){
10601define(["exports", "./_base/kernel", "./sniff", "./_base/window", "./dom", "./dom-attr"],
10602		function(exports, dojo, has, win, dom, attr){
10603	// module:
10604	//		dojo/dom-construct
10605	// summary:
10606	//		This module defines the core dojo DOM construction API.
10607
10608	// TODOC: summary not showing up in output, see https://github.com/csnover/js-doc-parse/issues/42
10609
10610	// support stuff for toDom()
10611	var tagWrap = {
10612			option: ["select"],
10613			tbody: ["table"],
10614			thead: ["table"],
10615			tfoot: ["table"],
10616			tr: ["table", "tbody"],
10617			td: ["table", "tbody", "tr"],
10618			th: ["table", "thead", "tr"],
10619			legend: ["fieldset"],
10620			caption: ["table"],
10621			colgroup: ["table"],
10622			col: ["table", "colgroup"],
10623			li: ["ul"]
10624		},
10625		reTag = /<\s*([\w\:]+)/,
10626		masterNode = {}, masterNum = 0,
10627		masterName = "__" + dojo._scopeName + "ToDomId";
10628
vendor: 7,974 bytes, lines 10629-10853
10629	// generate start/end tag strings to use
10630	// for the injection for each special tag wrap case.
10631	for(var param in tagWrap){
10632		if(tagWrap.hasOwnProperty(param)){
10633			var tw = tagWrap[param];
10634			tw.pre = param == "option" ? '<select multiple="multiple">' : "<" + tw.join("><") + ">";
10635			tw.post = "</" + tw.reverse().join("></") + ">";
10636			// the last line is destructive: it reverses the array,
10637			// but we don't care at this point
10638		}
10639	}
10640
10641	var html5domfix;
10642	if(has("ie") <= 8){
10643		html5domfix = function(doc){
10644			doc.__dojo_html5_tested = "yes";
10645			var div = create('div', {innerHTML: "<nav>a</nav>", style: {visibility: "hidden"}}, doc.body);
10646			if(div.childNodes.length !== 1){
10647				('abbr article aside audio canvas details figcaption figure footer header ' +
10648				'hgroup mark meter nav output progress section summary time video').replace(
10649					/\b\w+\b/g, function(n){
10650						doc.createElement(n);
10651					}
10652				);
10653			}
10654			destroy(div);
10655		}
10656	}
10657
10658	function _insertBefore(/*DomNode*/ node, /*DomNode*/ ref){
10659		var parent = ref.parentNode;
10660		if(parent){
10661			parent.insertBefore(node, ref);
10662		}
10663	}
10664
10665	function _insertAfter(/*DomNode*/ node, /*DomNode*/ ref){
10666		// summary:
10667		//		Try to insert node after ref
10668		var parent = ref.parentNode;
10669		if(parent){
10670			if(parent.lastChild == ref){
10671				parent.appendChild(node);
10672			}else{
10673				parent.insertBefore(node, ref.nextSibling);
10674			}
10675		}
10676	}
10677
10678	exports.toDom = function toDom(frag, doc){
10679		// summary:
10680		//		instantiates an HTML fragment returning the corresponding DOM.
10681		// frag: String
10682		//		the HTML fragment
10683		// doc: DocumentNode?
10684		//		optional document to use when creating DOM nodes, defaults to
10685		//		dojo/_base/window.doc if not specified.
10686		// returns:
10687		//		Document fragment, unless it's a single node in which case it returns the node itself
10688		// example:
10689		//		Create a table row:
10690		//	|	require(["dojo/dom-construct"], function(domConstruct){
10691		//	|		var tr = domConstruct.toDom("<tr><td>First!</td></tr>");
10692		//	|	});
10693
10694		doc = doc || win.doc;
10695		var masterId = doc[masterName];
10696		if(!masterId){
10697			doc[masterName] = masterId = ++masterNum + "";
10698			masterNode[masterId] = doc.createElement("div");
10699		}
10700
10701		if(has("ie") <= 8){
10702			if(!doc.__dojo_html5_tested && doc.body){
10703				html5domfix(doc);
10704			}
10705		}
10706
10707		// make sure the frag is a string.
10708		frag += "";
10709
10710		// find the starting tag, and get node wrapper
10711		var match = frag.match(reTag),
10712			tag = match ? match[1].toLowerCase() : "",
10713			master = masterNode[masterId],
10714			wrap, i, fc, df;
10715		if(match && tagWrap[tag]){
10716			wrap = tagWrap[tag];
10717			master.innerHTML = wrap.pre + frag + wrap.post;
10718			for(i = wrap.length; i; --i){
10719				master = master.firstChild;
10720			}
10721		}else{
10722			master.innerHTML = frag;
10723		}
10724
10725		// one node shortcut => return the node itself
10726		if(master.childNodes.length == 1){
10727			return master.removeChild(master.firstChild); // DOMNode
10728		}
10729
10730		// return multiple nodes as a document fragment
10731		df = doc.createDocumentFragment();
10732		while((fc = master.firstChild)){ // intentional assignment
10733			df.appendChild(fc);
10734		}
10735		return df; // DocumentFragment
10736	};
10737
10738	exports.place = function place(node, refNode, position){
10739		// summary:
10740		//		Attempt to insert node into the DOM, choosing from various positioning options.
10741		//		Returns the first argument resolved to a DOM node.
10742		// node: DOMNode|DocumentFragment|String
10743		//		id or node reference, or HTML fragment starting with "<" to place relative to refNode
10744		// refNode: DOMNode|String
10745		//		id or node reference to use as basis for placement
10746		// position: String|Number?
10747		//		string noting the position of node relative to refNode or a
10748		//		number indicating the location in the childNodes collection of refNode.
10749		//		Accepted string values are:
10750		//
10751		//		- before
10752		//		- after
10753		//		- replace
10754		//		- only
10755		//		- first
10756		//		- last
10757		//
10758		//		"first" and "last" indicate positions as children of refNode, "replace" replaces refNode,
10759		//		"only" replaces all children.  position defaults to "last" if not specified
10760		// returns: DOMNode
10761		//		Returned values is the first argument resolved to a DOM node.
10762		//
10763		//		.place() is also a method of `dojo/NodeList`, allowing `dojo/query` node lookups.
10764		// example:
10765		//		Place a node by string id as the last child of another node by string id:
10766		//	|	require(["dojo/dom-construct"], function(domConstruct){
10767		//	|		domConstruct.place("someNode", "anotherNode");
10768		//	|	});
10769		// example:
10770		//		Place a node by string id before another node by string id
10771		//	|	require(["dojo/dom-construct"], function(domConstruct){
10772		//	|		domConstruct.place("someNode", "anotherNode", "before");
10773		//	|	});
10774		// example:
10775		//		Create a Node, and place it in the body element (last child):
10776		//	|	require(["dojo/dom-construct", "dojo/_base/window"
10777		//	|	], function(domConstruct, win){
10778		//	|		domConstruct.place("<div></div>", win.body());
10779		//	|	});
10780		// example:
10781		//		Put a new LI as the first child of a list by id:
10782		//	|	require(["dojo/dom-construct"], function(domConstruct){
10783		//	|		domConstruct.place("<li></li>", "someUl", "first");
10784		//	|	});
10785
10786		refNode = dom.byId(refNode);
10787		if(typeof node == "string"){ // inline'd type check
10788			node = /^\s*</.test(node) ? exports.toDom(node, refNode.ownerDocument) : dom.byId(node);
10789		}
10790		if(typeof position == "number"){ // inline'd type check
10791			var cn = refNode.childNodes;
10792			if(!cn.length || cn.length <= position){
10793				refNode.appendChild(node);
10794			}else{
10795				_insertBefore(node, cn[position < 0 ? 0 : position]);
10796			}
10797		}else{
10798			switch(position){
10799				case "before":
10800					_insertBefore(node, refNode);
10801					break;
10802				case "after":
10803					_insertAfter(node, refNode);
10804					break;
10805				case "replace":
10806					refNode.parentNode.replaceChild(node, refNode);
10807					break;
10808				case "only":
10809					exports.empty(refNode);
10810					refNode.appendChild(node);
10811					break;
10812				case "first":
10813					if(refNode.firstChild){
10814						_insertBefore(node, refNode.firstChild);
10815						break;
10816					}
10817					// else fallthrough...
10818				default: // aka: last
10819					refNode.appendChild(node);
10820			}
10821		}
10822		return node; // DomNode
10823	};
10824
10825	var create = exports.create = function create(/*DOMNode|String*/ tag, /*Object*/ attrs, /*DOMNode|String?*/ refNode, /*String?*/ pos){
10826		// summary:
10827		//		Create an element, allowing for optional attribute decoration
10828		//		and placement.
10829		// description:
10830		//		A DOM Element creation function. A shorthand method for creating a node or
10831		//		a fragment, and allowing for a convenient optional attribute setting step,
10832		//		as well as an optional DOM placement reference.
10833		//
10834		//		Attributes are set by passing the optional object through `dojo/dom-attr.set`.
10835		//		See `dojo/dom-attr.set` for noted caveats and nuances, and API if applicable.
10836		//
10837		//		Placement is done via `dojo/dom-construct.place`, assuming the new node to be
10838		//		the action node, passing along the optional reference node and position.
10839		// tag: DOMNode|String
10840		//		A string of the element to create (eg: "div", "a", "p", "li", "script", "br"),
10841		//		or an existing DOM node to process.
10842		// attrs: Object
10843		//		An object-hash of attributes to set on the newly created node.
10844		//		Can be null, if you don't want to set any attributes/styles.
10845		//		See: `dojo/dom-attr.set` for a description of available attributes.
10846		// refNode: DOMNode|String?
10847		//		Optional reference node. Used by `dojo/dom-construct.place` to place the newly created
10848		//		node somewhere in the dom relative to refNode. Can be a DomNode reference
10849		//		or String ID of a node.
10850		// pos: String?
10851		//		Optional positional reference. Defaults to "last" by way of `dojo/domConstruct.place`,
10852		//		though can be set to "first","after","before","last", "replace" or "only"
10853		//		to further control the placement of the new node relative to the refNode.
10854		//		'refNode' is required if a 'pos' is specified.
10855		// example:
10856		//		Create a DIV:
10857		//	|	require(["dojo/dom-construct"], function(domConstruct){
10858		//	|		var n = domConstruct.create("div");
10859		//	|	});
10860		//
10861		// example:
10862		//		Create a DIV with content:
10863		//	|	require(["dojo/dom-construct"], function(domConstruct){
10864		//	|		var n = domConstruct.create("div", { innerHTML:"<p>hi</p>" });
10865		//	|	});
10866		//
10867		// example:
10868		//		Place a new DIV in the BODY, with no attributes set
10869		//	|	require(["dojo/dom-construct", "dojo/_base/window"], function(domConstruct, win){
10870		//	|		var n = domConstruct.create("div", null, win.body());
10871		//	|	});
10872		//
10873		// example:
10874		//		Create an UL, and populate it with LI's. Place the list as the first-child of a
10875		//		node with id="someId":
10876		//	|	require(["dojo/dom-construct", "dojo/_base/array"],
10877		//	|	function(domConstruct, arrayUtil){
10878		//	|		var ul = domConstruct.create("ul", null, "someId", "first");
10879		//	|		var items = ["one", "two", "three", "four"];
10880		//	|		arrayUtil.forEach(items, function(data){
10881		//	|			domConstruct.create("li", { innerHTML: data }, ul);
10882		//	|		});
10883		//	|	});
10884		//
10885		// example:
10886		//		Create an anchor, with an href. Place in BODY:
10887		//	|	require(["dojo/dom-construct", "dojo/_base/window"], function(domConstruct, win){
10888		//	|		domConstruct.create("a", { href:"foo.html", title:"Goto FOO!" }, win.body());
10889		//	|	});
10890
10891		var doc = win.doc;
10892		if(refNode){
10893			refNode = dom.byId(refNode);
10894			doc = refNode.ownerDocument;
10895		}
10896		if(typeof tag == "string"){ // inline'd type check
10897			tag = doc.createElement(tag);
10898		}
10899		if(attrs){ attr.set(tag, attrs); }
10900		if(refNode){ exports.place(tag, refNode, pos); }
10901		return tag; // DomNode
10902	};
10903
10904	function _empty(/*DomNode*/ node){
10905		// TODO: remove this if() block in 2.0 when we no longer have to worry about IE memory leaks,
10906		// and then uncomment the emptyGrandchildren() test case from html.html.
10907		// Note that besides fixing #16957, using removeChild() is actually faster than setting node.innerHTML,
10908		// see http://jsperf.com/clear-dom-node.
10909		if("innerHTML" in node){
10910			try{
10911				// fast path
10912				node.innerHTML = "";
10913				return;
10914			}catch(e){
10915				// innerHTML is readOnly (e.g. TABLE (sub)elements in quirks mode)
10916				// Fall through (saves bytes)
10917			}
10918		}
10919
10920		// SVG/strict elements don't support innerHTML
10921		for(var c; c = node.lastChild;){ // intentional assignment
10922			node.removeChild(c);
10923		}
10924	}
10925
10926	exports.empty = function empty(/*DOMNode|String*/ node){
10927		// summary:
10928		//		safely removes all children of the node.
10929		// node: DOMNode|String
10930		//		a reference to a DOM node or an id.
10931		// example:
10932		//		Destroy node's children byId:
10933		//	|	require(["dojo/dom-construct"], function(domConstruct){
10934		//	|		domConstruct.empty("someId");
10935		//	|	});
10936
10937		_empty(dom.byId(node));
10938	};
10939
10940
10941	function _destroy(/*DomNode*/ node, /*DomNode*/ parent){
10942		// in IE quirks, node.canHaveChildren can be false but firstChild can be non-null (OBJECT/APPLET)
10943		if(node.firstChild){
10944			_empty(node);
10945		}
10946		if(parent){
10947			// removeNode(false) doesn't leak in IE 6+, but removeChild() and removeNode(true) are known to leak under IE 8- while 9+ is TBD.
10948			// In IE quirks mode, PARAM nodes as children of OBJECT/APPLET nodes have a removeNode method that does nothing and
10949			// the parent node has canHaveChildren=false even though removeChild correctly removes the PARAM children.
10950			// In IE, SVG/strict nodes don't have a removeNode method nor a canHaveChildren boolean.
10951			has("ie") && parent.canHaveChildren && "removeNode" in node ? node.removeNode(false) : parent.removeChild(node);
10952		}
10953	}
10954	var destroy = exports.destroy = function destroy(/*DOMNode|String*/ node){
10955		// summary:
10956		//		Removes a node from its parent, clobbering it and all of its
10957		//		children.
10958		//
10959		// description:
10960		//		Removes a node from its parent, clobbering it and all of its
10961		//		children. Function only works with DomNodes, and returns nothing.
10962		//
10963		// node: DOMNode|String
10964		//		A String ID or DomNode reference of the element to be destroyed
10965		//
10966		// example:
10967		//		Destroy a node byId:
10968		//	|	require(["dojo/dom-construct"], function(domConstruct){
10969		//	|		domConstruct.destroy("someId");
10970		//	|	});
10971
10972		node = dom.byId(node);
10973		if(!node){ return; }
10974		_destroy(node, node.parentNode);
10975	};
10976});
10977
10978},
10979'dojo/dom-class':function(){
10980define(["./_base/lang", "./_base/array", "./dom"], function(lang, array, dom){
10981	// module:
10982	//		dojo/dom-class
10983
10984	var className = "className";
10985
10986	/* Part I of classList-based implementation is preserved here for posterity
10987	var classList = "classList";
10988	has.add("dom-classList", function(){
10989		return classList in document.createElement("p");
10990	});
10991	*/
10992
10993	// =============================
10994	// (CSS) Class Functions
10995	// =============================
10996
10997	var cls, // exports object
10998		spaces = /\s+/, a1 = [""];
10999
11000	function str2array(s){
11001		if(typeof s == "string" || s instanceof String){
11002			if(s && !spaces.test(s)){
11003				a1[0] = s;
11004				return a1;
11005			}
11006			var a = s.split(spaces);
11007			if(a.length && !a[0]){
11008				a.shift();
11009			}
11010			if(a.length && !a[a.length - 1]){
11011				a.pop();
11012			}
11013			return a;
11014		}
11015		// assumed to be an array
11016		if(!s){
11017			return [];
11018		}
11019		return array.filter(s, function(x){ return x; });
11020	}
11021
11022	/* Part II of classList-based implementation is preserved here for posterity
11023	if(has("dom-classList")){
11024		// new classList version
11025		cls = {
11026			contains: function containsClass(node, classStr){
11027				var clslst = classStr && dom.byId(node)[classList];
11028				return clslst && clslst.contains(classStr); // Boolean
11029			},
11030
11031			add: function addClass(node, classStr){
11032				node = dom.byId(node);
11033				classStr = str2array(classStr);
11034				for(var i = 0, len = classStr.length; i < len; ++i){
11035					node[classList].add(classStr[i]);
11036				}
11037			},
11038
11039			remove: function removeClass(node, classStr){
11040				node = dom.byId(node);
11041				if(classStr === undefined){
11042					node[className] = "";
11043				}else{
11044					classStr = str2array(classStr);
11045					for(var i = 0, len = classStr.length; i < len; ++i){
11046						node[classList].remove(classStr[i]);
11047					}
11048				}
11049			},
11050
11051			replace: function replaceClass(node, addClassStr, removeClassStr){
11052				node = dom.byId(node);
11053				if(removeClassStr === undefined){
11054					node[className] = "";
11055				}else{
11056					removeClassStr = str2array(removeClassStr);
11057					for(var i = 0, len = removeClassStr.length; i < len; ++i){
11058						node[classList].remove(removeClassStr[i]);
11059					}
11060				}
11061				addClassStr = str2array(addClassStr);
11062				for(i = 0, len = addClassStr.length; i < len; ++i){
11063					node[classList].add(addClassStr[i]);
11064				}
11065			},
11066
11067			toggle: function toggleClass(node, classStr, condition){
11068				node = dom.byId(node);
11069				if(condition === undefined){
11070					classStr = str2array(classStr);
11071					for(var i = 0, len = classStr.length; i < len; ++i){
11072						node[classList].toggle(classStr[i]);
11073					}
11074				}else{
11075					cls[condition ? "add" : "remove"](node, classStr);
11076				}
11077				return condition;   // Boolean
11078			}
11079		}
11080	}
11081	*/
11082
vendor: 4,359 bytes, lines 11083-11213
11083	// regular DOM version
11084	var fakeNode = {};  // for effective replacement
11085	cls = {
11086		// summary:
11087		//		This module defines the core dojo DOM class API.
11088
11089		contains: function containsClass(/*DomNode|String*/ node, /*String*/ classStr){
11090			// summary:
11091			//		Returns whether or not the specified classes are a portion of the
11092			//		class list currently applied to the node.
11093			// node: String|DOMNode
11094			//		String ID or DomNode reference to check the class for.
11095			// classStr: String
11096			//		A string class name to look for.
11097			// example:
11098			//		Do something if a node with id="someNode" has class="aSillyClassName" present
11099			//	|	if(dojo.hasClass("someNode","aSillyClassName")){ ... }
11100
11101			return ((" " + dom.byId(node)[className] + " ").indexOf(" " + classStr + " ") >= 0); // Boolean
11102		},
11103
11104		add: function addClass(/*DomNode|String*/ node, /*String|Array*/ classStr){
11105			// summary:
11106			//		Adds the specified classes to the end of the class list on the
11107			//		passed node. Will not re-apply duplicate classes.
11108			//
11109			// node: String|DOMNode
11110			//		String ID or DomNode reference to add a class string too
11111			//
11112			// classStr: String|Array
11113			//		A String class name to add, or several space-separated class names,
11114			//		or an array of class names.
11115			//
11116			// example:
11117			//		Add a class to some node:
11118			//	|	require(["dojo/dom-class"], function(domClass){
11119			//	|		domClass.add("someNode", "anewClass");
11120			//	|	});
11121			//
11122			// example:
11123			//		Add two classes at once:
11124			//	|	require(["dojo/dom-class"], function(domClass){
11125			//	|		domClass.add("someNode", "firstClass secondClass");
11126			//	|	});
11127			//
11128			// example:
11129			//		Add two classes at once (using array):
11130			//	|	require(["dojo/dom-class"], function(domClass){
11131			//	|		domClass.add("someNode", ["firstClass", "secondClass"]);
11132			//	|	});
11133			//
11134			// example:
11135			//		Available in `dojo/NodeList` for multiple additions
11136			//	|	require(["dojo/query"], function(query){
11137			//	|		query("ul > li").addClass("firstLevel");
11138			//	|	});
11139
11140			node = dom.byId(node);
11141			classStr = str2array(classStr);
11142			var cls = node[className], oldLen;
11143			cls = cls ? " " + cls + " " : " ";
11144			oldLen = cls.length;
11145			for(var i = 0, len = classStr.length, c; i < len; ++i){
11146				c = classStr[i];
11147				if(c && cls.indexOf(" " + c + " ") < 0){
11148					cls += c + " ";
11149				}
11150			}
11151			if(oldLen < cls.length){
11152				node[className] = cls.substr(1, cls.length - 2);
11153			}
11154		},
11155
11156		remove: function removeClass(/*DomNode|String*/ node, /*String|Array?*/ classStr){
11157			// summary:
11158			//		Removes the specified classes from node. No `contains()`
11159			//		check is required.
11160			//
11161			// node: String|DOMNode
11162			//		String ID or DomNode reference to remove the class from.
11163			//
11164			// classStr: String|Array
11165			//		An optional String class name to remove, or several space-separated
11166			//		class names, or an array of class names. If omitted, all class names
11167			//		will be deleted.
11168			//
11169			// example:
11170			//		Remove a class from some node:
11171			//	|	require(["dojo/dom-class"], function(domClass){
11172			//	|		domClass.remove("someNode", "firstClass");
11173			//	|	});
11174			//
11175			// example:
11176			//		Remove two classes from some node:
11177			//	|	require(["dojo/dom-class"], function(domClass){
11178			//	|		domClass.remove("someNode", "firstClass secondClass");
11179			//	|	});
11180			//
11181			// example:
11182			//		Remove two classes from some node (using array):
11183			//	|	require(["dojo/dom-class"], function(domClass){
11184			//	|		domClass.remove("someNode", ["firstClass", "secondClass"]);
11185			//	|	});
11186			//
11187			// example:
11188			//		Remove all classes from some node:
11189			//	|	require(["dojo/dom-class"], function(domClass){
11190			//	|		domClass.remove("someNode");
11191			//	|	});
11192			//
11193			// example:
11194			//		Available in `dojo/NodeList` for multiple removal
11195			//	|	require(["dojo/query"], function(query){
11196			//	|		query("ul > li").removeClass("foo");
11197			//	|	});
11198
11199			node = dom.byId(node);
11200			var cls;
11201			if(classStr !== undefined){
11202				classStr = str2array(classStr);
11203				cls = " " + node[className] + " ";
11204				for(var i = 0, len = classStr.length; i < len; ++i){
11205					cls = cls.replace(" " + classStr[i] + " ", " ");
11206				}
11207				cls = lang.trim(cls);
11208			}else{
11209				cls = "";
11210			}
11211			if(node[className] != cls){ node[className] = cls; }
11212		},
11213
11214		replace: function replaceClass(/*DomNode|String*/ node, /*String|Array*/ addClassStr, /*String|Array?*/ removeClassStr){
11215			// summary:
11216			//		Replaces one or more classes on a node if not present.
11217			//		Operates more quickly than calling dojo.removeClass and dojo.addClass
11218			//
11219			// node: String|DOMNode
11220			//		String ID or DomNode reference to remove the class from.
11221			//
11222			// addClassStr: String|Array
11223			//		A String class name to add, or several space-separated class names,
11224			//		or an array of class names.
11225			//
11226			// removeClassStr: String|Array?
11227			//		A String class name to remove, or several space-separated class names,
11228			//		or an array of class names.
11229			//
11230			// example:
11231			//	|	require(["dojo/dom-class"], function(domClass){
11232			//	|		domClass.replace("someNode", "add1 add2", "remove1 remove2");
11233			//	|	});
11234			//
11235			// example:
11236			//	Replace all classes with addMe
11237			//	|	require(["dojo/dom-class"], function(domClass){
11238			//	|		domClass.replace("someNode", "addMe");
11239			//	|	});
11240			//
11241			// example:
11242			//	Available in `dojo/NodeList` for multiple toggles
11243			//	|	require(["dojo/query"], function(query){
11244			//	|		query(".findMe").replaceClass("addMe", "removeMe");
11245			//	|	});
11246
11247			node = dom.byId(node);
11248			fakeNode[className] = node[className];
11249			cls.remove(fakeNode, removeClassStr);
11250			cls.add(fakeNode, addClassStr);
11251			if(node[className] !== fakeNode[className]){
11252				node[className] = fakeNode[className];
11253			}
11254		},
11255
11256		toggle: function toggleClass(/*DomNode|String*/ node, /*String|Array*/ classStr, /*Boolean?*/ condition){
11257			// summary:
11258			//		Adds a class to node if not present, or removes if present.
11259			//		Pass a boolean condition if you want to explicitly add or remove.
11260			//		Returns the condition that was specified directly or indirectly.
11261			//
11262			// node: String|DOMNode
11263			//		String ID or DomNode reference to toggle a class string
11264			//
11265			// classStr: String|Array
11266			//		A String class name to toggle, or several space-separated class names,
11267			//		or an array of class names.
11268			//
11269			// condition:
11270			//		If passed, true means to add the class, false means to remove.
11271			//		Otherwise dojo.hasClass(node, classStr) is used to detect the class presence.
11272			//
11273			// example:
11274			//	|	require(["dojo/dom-class"], function(domClass){
11275			//	|		domClass.toggle("someNode", "hovered");
11276			//	|	});
11277			//
11278			// example:
11279			//		Forcefully add a class
11280			//	|	require(["dojo/dom-class"], function(domClass){
11281			//	|		domClass.toggle("someNode", "hovered", true);
11282			//	|	});
11283			//
11284			// example:
11285			//		Available in `dojo/NodeList` for multiple toggles
11286			//	|	require(["dojo/query"], function(query){
11287			//	|		query(".toggleMe").toggleClass("toggleMe");
11288			//	|	});
11289
11290			node = dom.byId(node);
11291			if(condition === undefined){
11292				classStr = str2array(classStr);
11293				for(var i = 0, len = classStr.length, c; i < len; ++i){
11294					c = classStr[i];
11295					cls[cls.contains(node, c) ? "remove" : "add"](node, c);
11296				}
11297			}else{
11298				cls[condition ? "add" : "remove"](node, classStr);
11299			}
11300			return condition;   // Boolean
11301		}
11302	};
11303
11304	return cls;
11305});
11306
11307},
11308'dojo/_base/NodeList':function(){
11309define(["./kernel", "../query", "./array", "./html", "../NodeList-dom"], function(dojo, query, array){
11310	// module:
11311	//		dojo/_base/NodeList
11312
11313	/*=====
11314	return {
11315		// summary:
11316		//		This module extends dojo/NodeList with the legacy connect(), coords(),
11317		//		blur(), focus(), change(), click(), error(), keydown(), keypress(),
11318		//		keyup(), load(), mousedown(), mouseenter(), mouseleave(), mousemove(),
11319		//		mouseout(), mouseover(), mouseup(), and submit() methods.
11320	};
11321	=====*/
11322 
11323	var NodeList = query.NodeList,
11324		nlp = NodeList.prototype;
11325
11326	nlp.connect = NodeList._adaptAsForEach(function(){
11327		// don't bind early to dojo.connect since we no longer explicitly depend on it
11328		return dojo.connect.apply(this, arguments);
11329	});
11330	/*=====
11331	nlp.connect = function(methodName, objOrFunc, funcName){
11332		// summary:
11333		//		Attach event handlers to every item of the NodeList. Uses dojo.connect()
11334		//		so event properties are normalized.
11335		//
11336		//		Application must manually require() "dojo/_base/connect" before using this method.
11337		// methodName: String
11338		//		the name of the method to attach to. For DOM events, this should be
11339		//		the lower-case name of the event
11340		// objOrFunc: Object|Function|String
11341		//		if 2 arguments are passed (methodName, objOrFunc), objOrFunc 
11341should
11342		//		reference a function or be the name of the function in the global
11343		//		namespace to attach. If 3 arguments are provided
11344		//		(methodName, objOrFunc, funcName), objOrFunc must be the scope to
11345		//		locate the bound function in
11346		// funcName: String?
11347		//		optional. A string naming the function in objOrFunc to bind to the
11348		//		event. May also be a function reference.
11349		// example:
11350		//		add an onclick handler to every button on the page
11351		//		|	query("div:nth-child(odd)").connect("onclick", function(e){
11352		//		|		console.log("clicked!");
11353		//		|	});
11354		// example:
11355		//		attach foo.bar() to every odd div's onmouseover
11356		//		|	query("div:nth-child(odd)").connect("onmouseover", foo, "bar");
11357
11358		return null;	// NodeList
11359	};
11360	=====*/
11361
11362	nlp.coords = NodeList._adaptAsMap(dojo.coords);
11363	/*=====
11364	nlp.coords = function(){
11365		// summary:
11366		//		Deprecated: Use position() for border-box x/y/w/h
11367		//		or marginBox() for margin-box w/h/l/t.
11368		//		Returns the box objects of all elements in a node list as
11369		//		an Array (*not* a NodeList). Acts like `domGeom.coords`, though assumes
11370		//		the node passed is each node in this list.
11371
11372		return []; // Array
11373	};
11374	=====*/
11375
11376	NodeList.events = [
11377		// summary:
11378		//		list of all DOM events used in NodeList
11379		"blur", "focus", "change", "click", "error", "keydown", "keypress",
11380		"keyup", "load", "mousedown", "mouseenter", "mouseleave", "mousemove",
11381		"mouseout", "mouseover", "mouseup", "submit"
11382	];
11383
11384	// FIXME: pseudo-doc the above automatically generated on-event functions
11385
11386	// syntactic sugar for DOM events
11387	array.forEach(NodeList.events, function(evt){
11388			var _oe = "on" + evt;
11389			nlp[_oe] = function(a, b){
11390				return this.connect(_oe, a, b);
11391			};
11392				// FIXME: should these events trigger publishes?
11393				/*
11394				return (a ? this.connect(_oe, a, b) :
11395							this.forEach(function(n){
11396								// FIXME:
11397								//		listeners get buried by
11398								//		addEventListener and can't be dug back
11399								//		out to be triggered externally.
11400								// see:
11401								//		http://developer.mozilla.org/en/docs/DOM:element
11402
11403								console.log(n, evt, _oe);
11404
11405								// FIXME: need synthetic event support!
11406								var _e = { target: n, faux: true, type: evt };
11407								// dojo._event_listener._synthesizeEvent({}, { target: n, faux: true, type: evt });
11408								try{ n[evt](_e); }catch(e){ console.log(e); }
11409								try{ n[_oe](_e); }catch(e){ console.log(e); }
11410							})
11411				);
11412				*/
11413		}
11414	);
11415
11416	dojo.NodeList = NodeList;
11417	return NodeList;
11418});
11419
11420},
11421'dojo/query':function(){
11422define(["./_base/kernel", "./has", "./dom", "./on", "./_base/array", "./_base/lang", "./selector/_loader", "./selector/_loader!default"],
11423	function(dojo, has, dom, on, array, lang, loader, defaultEngine){
11424
11425	"use strict";
11426
11427	has.add("array-extensible", function(){
11428		// test to see if we can extend an array (not supported in old IE)
11429		return lang.delegate([], {length: 1}).length == 1 && !has("bug-for-in-skips-shadowed");
11430	});
11431	
11432	var ap = Array.prototype, aps = ap.slice, apc = ap.concat, forEach = array.forEach;
11433
11434	var tnl = function(/*Array*/ a, /*dojo/NodeList?*/ parent, /*Function?*/ NodeListCtor){
11435		// summary:
11436		//		decorate an array to make it look like a `dojo/NodeList`.
11437		// a:
11438		//		Array of nodes to decorate.
11439		// parent:
11440		//		An optional parent NodeList that generated the current
11441		//		list of nodes. Used to call _stash() so the parent NodeList
11442		//		can be accessed via end() later.
11443		// NodeListCtor:
11444		//		An optional constructor function to use for any
11445		//		new NodeList calls. This allows a certain chain of
11446		//		NodeList calls to use a different object than dojo/NodeList.
11447		var nodeList = new (NodeListCtor || this._NodeListCtor || nl)(a);
11448		return parent ? nodeList._stash(parent) : nodeList;
11449	};
11450
11451	var loopBody = function(f, a, o){
11452		a = [0].concat(aps.call(a, 0));
11453		o = o || dojo.global;
11454		return function(node){
11455			a[0] = node;
11456			return f.apply(o, a);
11457		};
11458	};
11459
11460	// adapters
11461
11462	var adaptAsForEach = function(f, o){
11463		// summary:
11464		//		adapts a single node function to be used in the forEach-type
11465		//		actions. The initial object is returned from the specialized
11466		//		function.
11467		// f: Function
11468		//		a function to adapt
11469		// o: Object?
11470		//		an optional context for f
11471		return function(){
11472			this.forEach(loopBody(f, arguments, o));
11473			return this;	// Object
11474		};
11475	};
11476
11477	var adaptAsMap = function(f, o){
11478		// summary:
11479		//		adapts a single node function to be used in the map-type
11480		//		actions. The return is a new array of values, as via `dojo/_base/array.map`
11481		// f: Function
11482		//		a function to adapt
11483		// o: Object?
11484		//		an optional context for f
11485		return function(){
11486			return this.map(loopBody(f, arguments, o));
11487		};
11488	};
11489
11490	var adaptAsFilter = function(f, o){
11491		// summary:
11492		//		adapts a single node function to be used in the filter-type actions
11493		// f: Function
11494		//		a function to adapt
11495		// o: Object?
11496		//		an optional context for f
11497		return function(){
vendor: 18,780 bytes, lines 11498-11972
11498			return this.filter(loopBody(f, arguments, o));
11499		};
11500	};
11501
11502	var adaptWithCondition = function(f, g, o){
11503		// summary:
11504		//		adapts a single node function to be used in the map-type
11505		//		actions, behaves like forEach() or map() depending on arguments
11506		// f: Function
11507		//		a function to adapt
11508		// g: Function
11509		//		a condition function, if true runs as map(), otherwise runs as forEach()
11510		// o: Object?
11511		//		an optional context for f and g
11512		return function(){
11513			var a = arguments, body = loopBody(f, a, o);
11514			if(g.call(o || dojo.global, a)){
11515				return this.map(body);	// self
11516			}
11517			this.forEach(body);
11518			return this;	// self
11519		};
11520	};
11521
11522	var NodeList = function(array){
11523		// summary:
11524		//		Array-like object which adds syntactic
11525		//		sugar for chaining, common iteration operations, animation, and
11526		//		node manipulation. NodeLists are most often returned as the
11527		//		result of dojo/query() calls.
11528		// description:
11529		//		NodeList instances provide many utilities that reflect
11530		//		core Dojo APIs for Array iteration and manipulation, DOM
11531		//		manipulation, and event handling. Instead of needing to dig up
11532		//		functions in the dojo package, NodeLists generally make the
11533		//		full power of Dojo available for DOM manipulation tasks in a
11534		//		simple, chainable way.
11535		// example:
11536		//		create a node list from a node
11537		//		|	require(["dojo/query", "dojo/dom"
11538		//		|	], function(query, dom){
11539		//		|		query.NodeList(dom.byId("foo"));
11540		//		|	});
11541		// example:
11542		//		get a NodeList from a CSS query and iterate on it
11543		//		|	require(["dojo/on", "dojo/dom"
11544		//		|	], function(on, dom){
11545		//		|		var l = query(".thinger");
11546		//		|		l.forEach(function(node, index, nodeList){
11547		//		|			console.log(index, node.innerHTML);
11548		//		|		});
11549		//		|	});
11550		// example:
11551		//		use native and Dojo-provided array methods to manipulate a
11552		//		NodeList without needing to use dojo.* functions explicitly:
11553		//		|	require(["dojo/query", "dojo/dom-construct", "dojo/dom"
11554		//		|	], function(query, domConstruct, dom){
11555		//		|		var l = query(".thinger");
11556		//		|		// since NodeLists are real arrays, they have a length
11557		//		|		// property that is both readable and writable and
11558		//		|		// push/pop/shift/unshift methods
11559		//		|		console.log(l.length);
11560		//		|		l.push(domConstruct.create("span"));
11561		//		|
11562		//		|		// dojo's normalized array methods work too:
11563		//		|		console.log( l.indexOf(dom.byId("foo")) );
11564		//		|		// ...including the special "function as string" shorthand
11565		//		|		console.log( l.every("item.nodeType == 1") );
11566		//		|
11567		//		|		// NodeLists can be [..] indexed, or you can use the at()
11568		//		|		// function to get specific items wrapped in a new NodeList:
11569		//		|		var node = l[3]; // the 4th element
11570		//		|		var newList = l.at(1, 3); // the 2nd and 4th elements
11571		//		|	});
11572		// example:
11573		//		chainability is a key advantage of NodeLists:
11574		//		|	require(["dojo/query", "dojo/NodeList-dom"
11575		//		|	], function(query){
11576		//		|		query(".thinger")
11577		//		|			.onclick(function(e){ /* ... */ })
11578		//		|			.at(1, 3, 8) // get a subset
11579		//		|				.style("padding", "5px")
11580		//		|				.forEach(console.log);
11581		//		|	});
11582
11583		var isNew = this instanceof nl && has("array-extensible");
11584		if(typeof array == "number"){
11585			array = Array(array);
11586		}
11587		var nodeArray = (array && "length" in array) ? array : arguments;
11588		if(isNew || !nodeArray.sort){
11589			// make sure it's a real array before we pass it on to be wrapped 
11590			var target = isNew ? this : [],
11591				l = target.length = nodeArray.length;
11592			for(var i = 0; i < l; i++){
11593				target[i] = nodeArray[i];
11594			}
11595			if(isNew){
11596				// called with new operator, this means we are going to use this instance and push
11597				// the nodes on to it. This is usually much faster since the NodeList properties
11598				//	don't need to be copied (unless the list of nodes is extremely large).
11599				return target;
11600			}
11601			nodeArray = target;
11602		}
11603		// called without new operator, use a real array and copy prototype properties,
11604		// this is slower and exists for back-compat. Should be removed in 2.0.
11605		lang._mixin(nodeArray, nlp);
11606		nodeArray._NodeListCtor = function(array){
11607			// call without new operator to preserve back-compat behavior
11608			return nl(array);
11609		};
11610		return nodeArray;
11611	};
11612	
11613	var nl = NodeList, nlp = nl.prototype = 
11614		has("array-extensible") ? [] : {};// extend an array if it is extensible
11615
11616	// expose adapters and the wrapper as private functions
11617
11618	nl._wrap = nlp._wrap = tnl;
11619	nl._adaptAsMap = adaptAsMap;
11620	nl._adaptAsForEach = adaptAsForEach;
11621	nl._adaptAsFilter  = adaptAsFilter;
11622	nl._adaptWithCondition = adaptWithCondition;
11623
11624	// mass assignment
11625
11626	// add array redirectors
11627	forEach(["slice", "splice"], function(name){
11628		var f = ap[name];
11629		//Use a copy of the this array via this.slice() to allow .end() to work right in the splice case.
11630		// CANNOT apply ._stash()/end() to splice since it currently modifies
11631		// the existing this array -- it would break backward compatibility if we copy the array before
11632		// the splice so that we can use .end(). So only doing the stash option to this._wrap for slice.
11633		nlp[name] = function(){ return this._wrap(f.apply(this, arguments), name == "slice" ? this : null); };
11634	});
11635	// concat should be here but some browsers with native NodeList have problems with it
11636
11637	// add array.js redirectors
11638	forEach(["indexOf", "lastIndexOf", "every", "some"], function(name){
11639		var f = array[name];
11640		nlp[name] = function(){ return f.apply(dojo, [this].concat(aps.call(arguments, 0))); };
11641	});
11642
11643	lang.extend(NodeList, {
11644		// copy the constructors
11645		constructor: nl,
11646		_NodeListCtor: nl,
11647		toString: function(){
11648			// Array.prototype.toString can't be applied to objects, so we use join
11649			return this.join(",");
11650		},
11651		_stash: function(parent){
11652			// summary:
11653			//		private function to hold to a parent NodeList. end() to return the parent NodeList.
11654			//
11655			// example:
11656			//		How to make a `dojo/NodeList` method that only returns the third node in
11657			//		the dojo/NodeList but allows access to the original NodeList by using this._stash:
11658			//	|	require(["dojo/query", "dojo/_base/lang", "dojo/NodeList", "dojo/NodeList-dom"
11659			//	|	], function(query, lang){
11660			//	|		lang.extend(NodeList, {
11661			//	|			third: function(){
11662			//	|				var newNodeList = NodeList(this[2]);
11663			//	|				return newNodeList._stash(this);
11664			//	|			}
11665			//	|		});
11666			//	|		// then see how _stash applies a sub-list, to be .end()'ed out of
11667			//	|		query(".foo")
11668			//	|			.third()
11669			//	|				.addClass("thirdFoo")
11670			//	|			.end()
11671			//	|			// access to the orig .foo list
11672			//	|			.removeClass("foo")
11673			//	|	});
11674			//
11675			this._parent = parent;
11676			return this; // dojo/NodeList
11677		},
11678
11679		on: function(eventName, listener){
11680			// summary:
11681			//		Listen for events on the nodes in the NodeList. Basic usage is:
11682			//
11683			// example:
11684			//		|	require(["dojo/query"
11685			//		|	], function(query){
11686			//		|		query(".my-class").on("click", listener);
11687			//			This supports event delegation by using selectors as the first argument with the event names as
11688			//			pseudo selectors. For example:
11689			//		| 		query("#my-list").on("li:click", listener);
11690			//			This will listen for click events within `<li>` elements that are inside the `#my-list` element.
11691			//			Because on supports CSS selector syntax, we can use comma-delimited events as well:
11692			//		| 		query("#my-list").on("li button:mouseover, li:click", listener);
11693			//		|	});
11694			var handles = this.map(function(node){
11695				return on(node, eventName, listener); // TODO: apply to the NodeList so the same selector engine is used for matches
11696			});
11697			handles.remove = function(){
11698				for(var i = 0; i < handles.length; i++){
11699					handles[i].remove();
11700				}
11701			};
11702			return handles;
11703		},
11704
11705		end: function(){
11706			// summary:
11707			//		Ends use of the current `NodeList` by returning the previous NodeList
11708			//		that generated the current NodeList.
11709			// description:
11710			//		Returns the `NodeList` that generated the current `NodeList`. If there
11711			//		is no parent NodeList, an empty NodeList is returned.
11712			// example:
11713			//	|	require(["dojo/query", "dojo/NodeList-dom"
11714			//	|	], function(query){
11715			//	|		query("a")
11716			//	|			.filter(".disabled")
11717			//	|				// operate on the anchors that only have a disabled class
11718			//	|				.style("color", "grey")
11719			//	|			.end()
11720			//	|			// jump back to the list of anchors
11721			//	|			.style(...)
11722			//	|	});
11723			//
11724			if(this._parent){
11725				return this._parent;
11726			}else{
11727				//Just return empty list.
11728				return new this._NodeListCtor(0);
11729			}
11730		},
11731
11732		// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array#Methods
11733
11734		// FIXME: handle return values for #3244
11735		//		http://trac.dojotoolkit.org/ticket/3244
11736
11737		// FIXME:
11738		//		need to wrap or implement:
11739		//			join (perhaps w/ innerHTML/outerHTML overload for toString() of items?)
11740		//			reduce
11741		//			reduceRight
11742
11743		/*=====
11744		slice: function(begin, end){
11745			// summary:
11746			//		Returns a new NodeList, maintaining this one in place
11747			// description:
11748			//		This method behaves exactly like the Array.slice method
11749			//		with the caveat that it returns a `dojo/NodeList` and not a
11750			//		raw Array. For more details, see Mozilla's [slice
11751			//		documentation](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/slice)
11752			// begin: Integer
11753			//		Can be a positive or negative integer, with positive
11754			//		integers noting the offset to begin at, and negative
11755			//		integers denoting an offset from the end (i.e., to the left
11756			//		of the end)
11757			// end: Integer?
11758			//		Optional parameter to describe what position relative to
11759			//		the NodeList's zero index to end the slice at. Like begin,
11760			//		can be positive or negative.
11761			return this._wrap(a.slice.apply(this, arguments));
11762		},
11763
11764		splice: function(index, howmany, item){
11765			// summary:
11766			//		Returns a new NodeList, manipulating this NodeList based on
11767			//		the arguments passed, potentially splicing in new elements
11768			//		at an offset, optionally deleting elements
11769			// description:
11770			//		This method behaves exactly like the Array.splice method
11771			//		with the caveat that it returns a `dojo/NodeList` and not a
11772			//		raw Array. For more details, see Mozilla's [splice
11773			//		documentation](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice)
11774			//		For backwards compatibility, calling .end() on the spliced NodeList
11775			//		does not return the original NodeList -- splice alters the NodeList in place.
11776			// index: Integer
11777			//		begin can be a positive or negative integer, with positive
11778			//		integers noting the offset to begin at, and negative
11779			//		integers denoting an offset from the end (i.e., to the left
11780			//		of the end)
11781			// howmany: Integer?
11782			//		Optional parameter to describe what position relative to
11783			//		the NodeList's zero index to end the slice at. Like begin,
11784			//		can be positive or negative.
11785			// item: Object...?
11786			//		Any number of optional parameters may be passed in to be
11787			//		spliced into the NodeList
11788			return this._wrap(a.splice.apply(this, arguments));	// dojo/NodeList
11789		},
11790
11791		indexOf: function(value, fromIndex){
11792			// summary:
11793			//		see `dojo/_base/array.indexOf()`. The primary difference is that the acted-on
11794			//		array is implicitly this NodeList
11795			// value: Object
11796			//		The value to search for.
11797			// fromIndex: Integer?
11798			//		The location to start searching from. Optional. Defaults to 0.
11799			// description:
11800			//		For more details on the behavior of indexOf, see Mozilla's
11801			//		[indexOf
11802			//		docs](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf)
11803			// returns:
11804			//		Positive Integer or 0 for a match, -1 of not found.
11805			return d.indexOf(this, value, fromIndex); // Integer
11806		},
11807
11808		lastIndexOf: function(value, fromIndex){
11809			// summary:
11810			//		see `dojo/_base/array.lastIndexOf()`. The primary difference is that the
11811			//		acted-on array is implicitly this NodeList
11812			// description:
11813			//		For more details on the behavior of lastIndexOf, see
11814			//		Mozilla's [lastIndexOf
11815			//		docs](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf)
11816			// value: Object
11817			//		The value to search for.
11818			// fromIndex: Integer?
11819			//		The location to start searching from. Optional. Defaults to 0.
11820			// returns:
11821			//		Positive Integer or 0 for a match, -1 of not found.
11822			return d.lastIndexOf(this, value, fromIndex); // Integer
11823		},
11824
11825		every: function(callback, thisObject){
11826			// summary:
11827			//		see `dojo/_base/array.every()` and the [Array.every
11828			//		docs](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every).
11829			//		Takes the same structure of arguments and returns as
11830			//		dojo/_base/array.every() with the caveat that the passed array is
11831			//		implicitly this NodeList
11832			// callback: Function
11833			//		the callback
11834			// thisObject: Object?
11835			//		the context
11836			return d.every(this, callback, thisObject); // Boolean
11837		},
11838
11839		some: function(callback, thisObject){
11840			// summary:
11841			//		Takes the same structure of arguments and returns as
11842			//		`dojo/_base/array.some()` with the caveat that the passed array is
11843			//		implicitly this NodeList.  See `dojo/_base/array.some()` and Mozilla's
11844			//		[Array.some
11845			//		documentation](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some).
11846			// callback: Function
11847			//		the callback
11848			// thisObject: Object?
11849			//		the context
11850			return d.some(this, callback, thisObject); // Boolean
11851		},
11852		=====*/
11853
11854		concat: function(item){
11855			// summary:
11856			//		Returns a new NodeList comprised of items in this NodeList
11857			//		as well as items passed in as parameters
11858			// description:
11859			//		This method behaves exactly like the Array.concat method
11860			//		with the caveat that it returns a `NodeList` and not a
11861			//		raw Array. For more details, see the [Array.concat
11862			//		docs](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/concat)
11863			// item: Object?
11864			//		Any number of optional parameters may be passed in to be
11865			//		spliced into the NodeList
11866
11867			//return this._wrap(apc.apply(this, arguments));
11868			// the line above won't work for the native NodeList, or for Dojo NodeLists either :-(
11869
11870			// implementation notes:
11871			// Array.concat() doesn't recognize native NodeLists or Dojo NodeLists
11872			// as arrays, and so does not inline them into a unioned array, but
11873			// appends them as single entities. Both the original NodeList and the
11874			// items passed in as parameters must be converted to raw Arrays
11875			// and then the concatenation result may be re-_wrap()ed as a Dojo NodeList.
11876
11877			var t = aps.call(this, 0),
11878				m = array.map(arguments, function(a){
11879					return aps.call(a, 0);
11880				});
11881			return this._wrap(apc.apply(t, m), this);	// dojo/NodeList
11882		},
11883
11884		map: function(/*Function*/ func, /*Function?*/ obj){
11885			// summary:
11886			//		see `dojo/_base/array.map()`. The primary difference is that the acted-on
11887			//		array is implicitly this NodeList and the return is a
11888			//		NodeList (a subclass of Array)
11889			return this._wrap(array.map(this, func, obj), this); // dojo/NodeList
11890		},
11891
11892		forEach: function(callback, thisObj){
11893			// summary:
11894			//		see `dojo/_base/array.forEach()`. The primary difference is that the acted-on
11895			//		array is implicitly this NodeList. If you want the option to break out
11896			//		of the forEach loop, use every() or some() instead.
11897			forEach(this, callback, thisObj);
11898			// non-standard return to allow easier chaining
11899			return this; // dojo/NodeList
11900		},
11901		filter: function(/*String|Function*/ filter){
11902			// summary:
11903			//		"masks" the built-in javascript filter() method (supported
11904			//		in Dojo via `dojo/_base/array.filter`) to support passing a simple
11905			//		string filter in addition to supporting filtering function
11906			//		objects.
11907			// filter:
11908			//		If a string, a CSS rule like ".thinger" or "div > span".
11909			// example:
11910			//		"regular" JS filter syntax as exposed in `dojo/_base/array.filter`:
11911			//		|	require(["dojo/query", "dojo/NodeList-dom"
11912			//		|	], function(query){
11913			//		|		query("*").filter(function(item){
11914			//		|			// highlight every paragraph
11915			//		|			return (item.nodeName == "p");
11916			//		|		}).style("backgroundColor", "yellow");
11917			//		|	});
11918			// example:
11919			//		the same filtering using a CSS selector
11920			//		|	require(["dojo/query", "dojo/NodeList-dom"
11921			//		|	], function(query){
11922			//		|		query("*").filter("p").styles("backgroundColor", "yellow");
11923			//		|	});
11924
11925			var a = arguments, items = this, start = 0;
11926			if(typeof filter == "string"){ // inline'd type check
11927				items = query._filterResult(this, a[0]);
11928				if(a.length == 1){
11929					// if we only got a string query, pass back the filtered results
11930					return items._stash(this); // dojo/NodeList
11931				}
11932				// if we got a callback, run it over the filtered items
11933				start = 1;
11934			}
11935			return this._wrap(array.filter(items, a[start], a[start + 1]), this);	// dojo/NodeList
11936		},
11937		instantiate: function(/*String|Object*/ declaredClass, /*Object?*/ properties){
11938			// summary:
11939			//		Create a new instance of a specified class, using the
11940			//		specified properties and each node in the NodeList as a
11941			//		srcNodeRef.
11942			// example:
11943			//		Grabs all buttons in the page and converts them to dijit/form/Button's.
11944			//	|	var buttons = query("button").instantiate(Button, {showLabel: true});
11945			var c = lang.isFunction(declaredClass) ? declaredClass : lang.getObject(declaredClass);
11946			properties = properties || {};
11947			return this.forEach(function(node){
11948				new c(properties, node);
11949			});	// dojo/NodeList
11950		},
11951		at: function(/*===== index =====*/){
11952			// summary:
11953			//		Returns a new NodeList comprised of items in this NodeList
11954			//		at the given index or indices.
11955			//
11956			// index: Integer...
11957			//		One or more 0-based indices of items in the current
11958			//		NodeList. A negative index will start at the end of the
11959			//		list and go backwards.
11960			//
11961			// example:
11962			//	Shorten the list to the first, second, and third elements
11963			//	|	require(["dojo/query"
11964			//	|	], function(query){
11965			//	|		query("a").at(0, 1, 2).forEach(fn);
11966			//	|	});
11967			//
11968			// example:
11969			//	Retrieve the first and last elements of a unordered list:
11970			//	|	require(["dojo/query"
11971			//	|	], function(query){
11972			//	|		query("ul >
11972 li").at(0, -1).forEach(cb);
11973			//	|	});
11974			//
11975			// example:
11976			//	Do something for the first element only, but end() out back to
11977			//	the original list and continue chaining:
11978			//	|	require(["dojo/query"
11979			//	|	], function(query){
11980			//	|		query("a").at(0).onclick(fn).end().forEach(function(n){
11981			//	|			console.log(n); // all anchors on the page.
11982			//	|	})
11983			//	|	});
11984
11985			var t = new this._NodeListCtor(0);
11986			forEach(arguments, function(i){
11987				if(i < 0){ i = this.length + i; }
11988				if(this[i]){ t.push(this[i]); }
11989			}, this);
11990			return t._stash(this); // dojo/NodeList
11991		}
11992	});
11993
11994	function queryForEngine(engine, NodeList){
11995		var query = function(/*String*/ query, /*String|DOMNode?*/ root){
11996			// summary:
11997			//		Returns nodes which match the given CSS selector, searching the
11998			//		entire document by default but optionally taking a node to scope
11999			//		the search by. Returns an instance of NodeList.
12000			if(typeof root == "string"){
12001				root = dom.byId(root);
12002				if(!root){
12003					return new NodeList([]);
12004				}
12005			}
12006			var results = typeof query == "string" ? engine(query, root) : query ? (query.end && query.on) ? query : [query] : [];
12007			if(results.end && results.on){
12008				// already wrapped
12009				return results;
12010			}
12011			return new NodeList(results);
12012		};
12013		query.matches = engine.match || function(node, selector, root){
12014			// summary:
12015			//		Test to see if a node matches a selector
12016			return query.filter([node], selector, root).length > 0;
12017		};
12018		// the engine provides a filtering function, use it to for matching
12019		query.filter = engine.filter || function(nodes, selector, root){
12020			// summary:
12021			//		Filters an array of nodes. Note that this does not guarantee to return a NodeList, just an array.
12022			return query(selector, root).filter(function(node){
12023				return array.indexOf(nodes, node) > -1;
12024			});
12025		};
12026		if(typeof engine != "function"){
12027			var search = engine.search;
12028			engine = function(selector, root){
12029				// Slick does it backwards (or everyone else does it backwards, probably the latter)
12030				return search(root || document, selector);
12031			};
12032		}
12033		return query;
12034	}
12035	var query = queryForEngine(defaultEngine, NodeList);
12036	/*=====
12037	query = function(selector, context){
12038		// summary:
12039		//		This modules provides DOM querying functionality. The module export is a function
12040		//		that can be used to query for DOM nodes by CSS selector and returns a NodeList
12041		//		representing the matching nodes.
12042		// selector: String
12043		//		A CSS selector to search for.
12044		// context: String|DomNode?
12045		//		An optional context to limit the searching scope. Only nodes under `context` will be
12046		//		scanned.
12047		// example:
12048		//		add an onclick handler to every submit button in the document
12049		//		which causes the form to be sent via Ajax instead:
12050		//	|	require(["dojo/query", "dojo/request", "dojo/dom-form", "dojo/dom-construct", "dojo/dom-style"
12051		//	|	], function(query, request, domForm, domConstruct, domStyle){
12052		//	|		query("input[type='submit']").on("click", function(e){
12053		//	|			e.preventDefault(); // prevent sending the form
12054		//	|			var btn = e.target;
12055		//	|			request.post("http://example.com/", {
12056		//	|				data: domForm.toObject(btn.form)
12057		//	|			}).then(function(response){
12058		//	|				// replace the form with the response
12059		//	|				domConstruct.create(div, {innerHTML: response}, btn.form, "after");
12060		//	|				domStyle.set(btn.form, "display", "none");
12061		//	|			});
12062		//	|		});
12063		//	|	});
12064		//
12065		// description:
12066		//		dojo/query is responsible for loading the appropriate query engine and wrapping
12067		//		its results with a `NodeList`. You can use dojo/query with a specific selector engine
12068		//		by using it as a plugin. For example, if you installed the sizzle package, you could
12069		//		use it as the selector engine with:
12070		//		|	require(["dojo/query!sizzle"], function(query){
12071		//		|		query("div")...
12072		//
12073		//		The id after the ! can be a module id of the selector engine or one of the following values:
12074		//
12075		//		- acme: This is the default engine used by Dojo base, and will ensure that the full
12076		//		Acme engine is always loaded.
12077		//
12078		//		- css2: If the browser has a native selector engine, this will be used, otherwise a
12079		//		very minimal lightweight selector engine will be loaded that can do simple CSS2 selectors
12080		//		(by #id, .class, tag, and [name=value] attributes, with standard child or descendant (>)
12081		//		operators) and nothing more.
12082		//
12083		//		- css2.1: If the browser has a native selector engine, this will be used, otherwise the
12084		//		full Acme engine will be loaded.
12085		//
12086		//		- css3: If the browser has a native selector engine with support for CSS3 pseudo
12087		//		selectors (most modern browsers except IE8), this will be used, otherwise the
12088		//		full Acme engine will be loaded.
12089		//
12090		//		- Or the module id of a selector engine can be used to explicitly choose the selector engine
12091		//
12092		//		For example, if you are using CSS3 pseudo selectors in module, you can specify that
12093		//		you will need support them with:
12094		//		|	require(["dojo/query!css3"], function(query){
12095		//		|		query('#t > h3:nth-child(odd)')...
12096		//
12097		//		You can also choose the selector engine/load configuration by setting the query-selector:
12098		//		For example:
12099		//		|	<script data-dojo-config="query-selector:'css3'" src="dojo.js"></script>
12100		//
12101		return new NodeList(); // dojo/NodeList
12102	 };
12103	 =====*/
12104
12105	// the query that is returned from this module is slightly different than dojo.query,
12106	// because dojo.query has to maintain backwards compatibility with returning a
12107	// true array which has performance problems. The query returned from the module
12108	// does not use true arrays, but rather inherits from Array, making it much faster to
12109	// instantiate.
12110	dojo.query = queryForEngine(defaultEngine, function(array){
12111		// call it without the new operator to invoke the back-compat behavior that returns a true array
12112		return NodeList(array);	// dojo/NodeList
12113	});
12114
12115	query.load = function(id, parentRequire, loaded){
12116		// summary:
12117		//		can be used as AMD plugin to conditionally load new query engine
12118		// example:
12119		//	|	require(["dojo/query!custom"], function(qsa){
12120		//	|		// loaded selector/custom.js as engine
12121		//	|		qsa("#foobar").forEach(...);
12122		//	|	});
12123		loader.load(id, parentRequire, function(engine){
12124			loaded(queryForEngine(engine, NodeList));
12125		});
12126	};
12127
12128	dojo._filterQueryResult = query._filterResult = function(nodes, selector, root){
12129		return new NodeList(query.filter(nodes, selector, root));
12130	};
12131	dojo.NodeList = query.NodeList = NodeList;
12132	return query;
12133});
12134
12135},
12136'dojo/selector/_loader':function(){
12137define(["../has", "require"],
12138		function(has, require){
12139
12140"use strict";
12141var testDiv = document.createElement("div");
12142has.add("dom-qsa2.1", !!testDiv.querySelectorAll);
12143has.add("dom-qsa3", function(){
12144			// test to see if we have a reasonable native selector engine available
12145			try{
12146				testDiv.innerHTML = "<p class='TEST'></p>"; // test kind of from sizzle
12147				// Safari can't handle uppercase or unicode characters when
12148				// in quirks mode, IE8 can't handle pseudos like :empty
12149				return testDiv.querySelectorAll(".TEST:empty").length == 1;
12150			}catch(e){}
12151		});
12152var fullEngine;
12153var acme = "./acme", lite = "./lite";
12154return {
12155	// summary:
12156	//		This module handles loading the appropriate selector engine for the given browser
12157
12158	load: function(id, parentRequire, loaded, config){
12159		var req = require;
12160		// here we implement the default logic for choosing a selector engine
12161		id = id == "default" ? has("config-selectorEngine") || "css3" : id;
12162		id = id == "css2" || id == "lite" ? lite :
12163				id == "css2.1" ? has("dom-qsa2.1") ? lite : acme :
12164				id == "css3" ? has("dom-qsa3") ? lite : acme :
12165				id == "acme" ? acme : (req = parentRequire) && id;
12166		if(id.charAt(id.length-1) == '?'){
12167			id = id.substring(0,id.length - 1);
12168			var optionalLoad = true;
12169		}
12170		// the query engine is optional, only load it if a native one is not available or existing one has not been loaded
12171		if(optionalLoad && (has("dom-compliant-qsa") || fullEngine)){
12172			return loaded(fullEngine);
12173		}
12174		// load the referenced selector engine
12175		req([id], function(engine){
12176			if(id != "./lite"){
12177				fullEngine = engine;
12178			}
12179			loaded(engine);
12180		});
12181	}
12182};
12183});
12184
12185},
12186'dojo/selector/lite':function(){
12187define(["../has", "../_base/kernel"], function(has, dojo){
12188"use strict";
12189
12190var testDiv = document.createElement("div");
12191var matchesSelector = testDiv.matches || testDiv.webkitMatchesSelector || testDiv.mozMatchesSelector || testDiv.msMatchesSelector || testDiv.oMatchesSelector;
12192var querySelectorAll = testDiv.querySelectorAll;
12193var unionSplit = /([^\s,](?:"(?:\\.|[^"])+"|'(?:\\.|[^'])+'|[^,])*)/g;
12194has.add("dom-matches-selector", !!matchesSelector);
12195has.add("dom-qsa", !!querySelectorAll); 
12196
12197// this is a simple query engine. It has handles basic selectors, and for simple
12198// common selectors is extremely fast
12199var liteEngine = function(selector, root){
12200	// summary:
12201	//		A small lightweight query selector engine that implements CSS2.1 selectors
12202	//		minus pseudo-classes and the sibling combinator, plus CSS3 attribute selectors
12203
12204	if(combine && selector.indexOf(',') > -1){
12205		return combine(selector, root);
12206	}
12207	// use the root's ownerDocument if provided, otherwise try to use dojo.doc. Note 
12208	// that we don't use dojo/_base/window's doc to reduce dependencies, and 
12209	// fallback to plain document if dojo.doc hasn't been defined (by dojo/_base/window).
12210	// presumably we will have a better way to do this in 2.0 
12211	var doc = root ? root.ownerDocument || root : dojo.doc || document, 
12212		match = (querySelectorAll ? 
12213			/^([\w]*)#([\w\-]+$)|^(\.)([\w\-\*]+$)|^(\w+$)/ : // this one only matches on simple queries where we can beat qSA with specific methods
12214			/^([\w]*)#([\w\-]+)(?:\s+(.*))?$|(?:^|(>|.+\s+))([\w\-\*]+)(\S*$)/) // this one matches parts of the query that we can use to speed up manual filtering
12215			.exec(selector);
12216	root = root || doc;
12217	if(match){
12218		// fast path regardless of whether or not querySelectorAll exists
12219		if(match[2]){
12220			// an #id
12221			// use dojo.byId if available as it fixes the id retrieval in IE, note that we can't use the dojo namespace in 2.0, but if there is a conditional module use, we will use that
12222			var found = dojo.byId ? dojo.byId(match[2], doc) : doc.getElementById(match[2]);
12223			if(!found || (match[1] && match[1] != found.tagName.toLowerCase())){
12224				// if there is a tag qualifer and it doesn't match, no matches
12225				return [];
12226			}
12227			if(root != doc){
12228				// there is a root element, make sure we are a child of it
12229				var parent = found;
12230				while(parent != root){
12231					parent = parent.parentNode;
12232					if(!parent){
12233						return [];
12234					}
12235				}
12236			}
12237			return match[3] ?
12238					liteEngine(match[3], found) 
12239					: [found];
12240		}
12241		if(match[3] && root.getElementsByClassName){
12242			// a .class
12243			return root.getElementsByClassName(match[4]);
12244		}
12245		var found;
12246		if(match[5]){
12247			// a tag
12248			found = root.getElementsByTagName(match[5]);
12249			if(match[4] || match[6]){
12250				selector = (match[4] || "") + match[6];
12251			}else{
12252				// that was the entirety of the query, return results
12253				return found;
12254			}
12255		}
12256	}
12257	if(querySelectorAll){
12258		// qSA works strangely on Element-rooted queries
12259		// We can work around this by specifying an extra ID on the root
12260		// and working up from there (Thanks to Andrew Dupont for the technique)
12261		// IE 8 doesn't work on object elements
12262		if (root.nodeType === 1 && root.nodeName.toLowerCase() !== "object"){				
12263			return useRoot(root, selector, root.querySelectorAll);
12264		}else{
12265			// we can use the native qSA
12266			return root.querySelectorAll(selector);
12267		}
12268	}else if(!found){
12269		// search all children and then filter
12270		found = root.getElementsByTagName("*");
12271	}
12272	// now we filter the nodes that were found using the matchesSelector
12273	var results = [];
12274	for(var i = 0, l = found.length; i < l; i++){
12275		var node = found[i];
12276		if(node.nodeType == 1 && jsMatchesSelector(node, selector, root)){
12277			// keep the nodes that match the selector
12278			results.push(node);
12279		}
12280	}
12281	return results;
12282};
12283var useRoot = function(context, query, method){
12284	// this function creates a temporary id so we can do rooted qSA queries, this is taken from sizzle
12285	var oldContext = context,
12286		old = context.getAttribute("id"),
12287		nid = old || "__dojo__",
12288		hasParent = context.parentNode,
12289		relativeHierarchySelector = /^\s*[+~]/.test(query);
12290
12291	if(relativeHierarchySelector && !hasParent){
12292		return [];
12293	}
12294	if(!old){
12295		context.setAttribute("id", nid);
12296	}else{
12297		nid = nid.replace(/'/g, "\\$&");
12298	}
12299	if(relativeHierarchySelector && hasParent){
12300		context = context.parentNode;
12301	}
12302	var selectors = query.match(unionSplit);
12303	for(var i = 0; i < selectors.length; i++){
12304		selectors[i] = "[id='" + nid + "'] " + selectors[i];
12305	}
12306	query = selectors.join(",");
12307
12308	try{
12309		return method.call(context, query);
12310	}finally{
12311		if(!old){
12312			oldContext.removeAttribute("id");
12313		}
12314	}
12315};
12316
12317if(!has("dom-matches-selector")){
12318	var jsMatchesSelector = (function(){
12319		// a JS implementation of CSS selector matching, first we start with the various handlers
12320		var caseFix = testDiv.tagName == "div" ? "toLowerCase" : "toUpperCase";
12321		var selectorTypes = {
12322			"": function(tagName){
12323				tagName = tagName[caseFix]();
12324				return function(node){
12325					return node.tagName == tagName;
12326				};
12327			},
12328			".": function(className){
12329				var classNameSpaced = ' ' + className + ' ';
12330				return function(node){
12331					return node.className.indexOf(className) > -1 && (' ' + node.className + ' ').indexOf(classNameSpaced) > -1;
12332				};
12333			},
12334			"#": function(id){
12335				return function(node){
12336					return node.id == id;
12337				};
12338			}
12339		};
12340		var attrComparators = {
12341			"^=": function(attrValue, value){
12342				return attrValue.indexOf(value) == 0;
12343			},
12344			"*=": function(attrValue, value){
12345				return attrValue.indexOf(value) > -1;
12346			},
12347			"$=": function(attrValue, value){
12348				return attrValue.substring(attrValue.length - value.length, attrValue.length) == value;
12349			},
12350			"~=": function(attrValue, value){
12351				return (' ' + attrValue + ' ').indexOf(' ' + value + ' ') > -1;
12352			},
12353			"|=": function(attrValue, value){
12354				return (attrValue + '-').indexOf(value + '-') == 0;
12355			},
12356			"=": function(attrValue, value){
12357				return attrValue == value;
12358			},
12359			"": function(attrValue, value){
12360				return true;
12361			}
12362		};
12363		function attr(name, value, type){
12364			var firstChar = value.charAt(0);
12365			if(firstChar == '"' || firstChar == "'"){
12366				// it is quoted, remove the quotes
12367				value = value.slice(1, -1);
12368			}
12369			value = value.replace(/\\/g,'');
12370			var comparator = attrComparators[type || ""];
12371			return function(node){
12372				var attrValue = node.getAttribute(name);
12373				return attrValue && comparator(attrValue, value);
12374			};
12375		}
12376		function ancestor(matcher){
12377			return function(node, root){
12378				while((node = node.parentNode) != root){
12379					if(matcher(node, root)){
12380						return true;
12381					}
12382				}
12383			};
12384		}
12385		function parent(matcher){
12386			return function(node, root){
12387				node = node.parentNode;
12388				return matcher ? 
12389					node != root && matcher(node, root)
12390					: node == root;
12391			};
12392		}
12393		var cache = {};
12394		function and(matcher, next){
12395			return matcher ?
12396				function(node, root){
12397					return next(node) && matcher(node, root);
12398				}
12399				: next;
12400		}
12401		return function(node, selector, root){
12402			// this returns true or false based on if the node matches the selector (optionally within the given root)
12403			var matcher = cache[selector]; // check to see if we have created a matcher function for the given selector
12404			if(!matcher){
12405				// create a matcher function for the given selector
12406				// parse the selectors
12407				if(selector.replace(/(?:\s*([> ])\s*)|(#|\.)?((?:\\.|[\w-])+)|\[\s*([\w-]+)\s*(.?=)?\s*("(?:\\.|[^"])+"|'(?:\\.|[^'])+'|(?:\\.|[^\]])*)\s*\]/g, function(t, combinator, type, value, attrName, attrType, attrValue){
12408					if(value){
12409						matcher = and(matcher, selectorTypes[type || ""](value.replace(/\\/g, '')));
12410					}
12411					else if(combinator){
12412						matcher = (combinator == " " ? ancestor : parent)(matcher);
12413					}
12414					else if(attrName){
12415						matcher = and(matcher, attr(attrName, attrValue, attrType));
12416					}
12417					return "";
12418				})){
12419					throw new Error("Syntax error in query");
12420				}
12421				if(!matcher){
12422					return true;
12423				}
12424				cache[selector] = matcher;
12425			}
12426			// now run the matcher function on the node
12427			return matcher(node, root);
12428		};
12429	})();
12430}
12431if(!has("dom-qsa")){
12432	var combine = function(selector, root){
12433		// combined queries
12434		var selectors = selector.match(unionSplit);
12435		var indexed = [];
12436		// add all results and keep unique ones, this only runs in IE, so we take advantage 
12437		// of known IE features, particularly sourceIndex which is unique and allows us to 
12438		// order the results 
12439		for(var i = 0; i < selectors.length; i++){
12440			selector = new String(selectors[i].replace(/\s*$/,''));
12441			selector.indexOf = escape; // keep it from recursively entering combine
12442			var results = liteEngine(selector, root);
12443			for(var j = 0, l = results.length; j < l; j++){
12444				var node = results[j];
12445				indexed[node.sourceIndex] = node;
12446			}
12447		}
12448		// now convert from a sparse array to a dense array
12449		var totalResults = [];
12450		for(i in indexed){
12451			totalResults.push(indexed[i]);
12452		}
12453		return totalResults;
12454	};
12455}
12456
12457liteEngine.match = matchesSelector ? function(node, selector, root){
12458	if(root && root.nodeType != 9){
12459		// doesn't support three args, use rooted id trick
12460		return useRoot(root, selector, function(query){
12461			return matchesSelector.call(node, query);
12462		});
12463	}
12464	// we have a native matchesSelector, use that
12465	return matchesSelector.call(node, selector);
12466} : jsMatchesSelector; // otherwise use the JS matches impl
12467
12468return liteEngine;
12469});
12470
12471},
12472'dojo/NodeList-dom':function(){
12473define(["./_base/kernel", "./query", "./_base/array", "./_base/lang", "./dom-class", "./dom-construct", "./dom-geometry", "./dom-attr", "./dom-style"], function(dojo, query, array, lang, domCls, domCtr, domGeom, domAttr, domStyle){
12474
12475	// module:
12476	//		dojo/NodeList-dom.js
12477
12478	/*=====
12479	 return function(){
12480		 // summary:
12481		 //		Adds DOM related methods to NodeList, and returns NodeList constructor.
12482	 };
12483	 =====*/
12484
12485	var magicGuard = function(a){
12486		// summary:
12487		//		the guard function for dojo/dom-attr() and dojo/dom-style()
12488		return a.length == 1 && (typeof a[0] == "string"); // inline'd type check
12489	};
12490
12491	var orphan = function(node){
12492		// summary:
12493		//		function to orphan nodes
12494		var p = node.parentNode;
12495		if(p){
12496			p.removeChild(node);
12497		}
12498	};
12499	// FIXME: should we move orphan() to dojo/_base/html?
12500
12501	var NodeList = query.NodeList,
12502		awc = NodeList._adaptWithCondition,
12503		aafe = NodeList._adaptAsForEach,
12504		aam = NodeList._adaptAsMap;
12505
12506	function getSet(module){
12507		return function(node, name, value){
12508			if(arguments.length == 2){
12509				return module[typeof name == "string" ? "get" : "set"](node, name);
12510			}
12511			// setter
12512			return module.set(node, name, value);
12513		};
12514	}
12515
12516	lang.extend(NodeList, {
12517		_normalize: function(/*String||Element||Object||NodeList*/content, /*DOMNode?*/refNode){
12518			// summary:
12519			//		normalizes data to an array of items to insert.
12520			// description:
12521			//		If content is an object, it can have special properties "template" and
12522			//		"parse". If "template" is defined, then the template value is run through
12523			//		dojo/string.substitute (if dojo/string.substitute() has been required elsewhere),
12524			//		or if templateFunc is a function on the content, that function will be used to
12525			//		transform the template into a final string to be used for for passing to dojo/dom-construct.toDom().
12526			//		If content.parse is true, then it is remembered for later, for when the content
12527			//		nodes are inserted into the DOM. At that point, the nodes will be parsed for widgets
12528			//		(if dojo/parser has been required elsewhere).
12529
12530			//Wanted to just use a DocumentFragment, but for the array/NodeList
vendor: 5,287 bytes, lines 12531-12675
12531			//case that meant using cloneNode, but we may not want that.
12532			//Cloning should only happen if the node operations span
12533			//multiple refNodes. Also, need a real array, not a NodeList from the
12534			//DOM since the node movements could change those NodeLists.
12535
12536			var parse = content.parse === true;
12537
12538			//Do we have an object that needs to be run through a template?
12539			if(typeof content.template == "string"){
12540				var templateFunc = content.templateFunc || (dojo.string && dojo.string.substitute);
12541				content = templateFunc ? templateFunc(content.template, content) : content;
12542			}
12543
12544			var type = (typeof content);
12545			if(type == "string" || type == "number"){
12546				content = domCtr.toDom(content, (refNode && refNode.ownerDocument));
12547				if(content.nodeType == 11){
12548					//DocumentFragment. It cannot handle cloneNode calls, so pull out the children.
12549					content = lang._toArray(content.childNodes);
12550				}else{
12551					content = [content];
12552				}
12553			}else if(!lang.isArrayLike(content)){
12554				content = [content];
12555			}else if(!lang.isArray(content)){
12556				//To get to this point, content is array-like, but
12557				//not an array, which likely means a DOM NodeList. Convert it now.
12558				content = lang._toArray(content);
12559			}
12560
12561			//Pass around the parse info
12562			if(parse){
12563				content._runParse = true;
12564			}
12565			return content; //Array
12566		},
12567
12568		_cloneNode: function(/*DOMNode*/ node){
12569			// summary:
12570			//		private utility to clone a node. Not very interesting in the vanilla
12571			//		dojo/NodeList case, but delegates could do interesting things like
12572			//		clone event handlers if that is derivable from the node.
12573			return node.cloneNode(true);
12574		},
12575
12576		_place: function(/*Array*/ary, /*DOMNode*/refNode, /*String*/position, /*Boolean*/useClone){
12577			// summary:
12578			//		private utility to handle placing an array of nodes relative to another node.
12579			// description:
12580			//		Allows for cloning the nodes in the array, and for
12581			//		optionally parsing widgets, if ary._runParse is true.
12582
12583			//Avoid a disallowed operation if trying to do an innerHTML on a non-element node.
12584			if(refNode.nodeType != 1 && position == "only"){
12585				return;
12586			}
12587			var rNode = refNode, tempNode;
12588
12589			//Always cycle backwards in case the array is really a
12590			//DOM NodeList and the DOM operations take it out of the live collection.
12591			var length = ary.length;
12592			for(var i = length - 1; i >= 0; i--){
12593				var node = (useClone ? this._cloneNode(ary[i]) : ary[i]);
12594
12595				//If need widget parsing, use a temp node, instead of waiting after inserting into
12596				//real DOM because we need to start widget parsing at one node up from current node,
12597				//which could cause some already parsed widgets to be parsed again.
12598				if(ary._runParse && dojo.parser && dojo.parser.parse){
12599					if(!tempNode){
12600						tempNode = rNode.ownerDocument.createElement("div");
12601					}
12602					tempNode.appendChild(node);
12603					dojo.parser.parse(tempNode);
12604					node = tempNode.firstChild;
12605					while(tempNode.firstChild){
12606						tempNode.removeChild(tempNode.firstChild);
12607					}
12608				}
12609
12610				if(i == length - 1){
12611					domCtr.place(node, rNode, position);
12612				}else{
12613					rNode.parentNode.insertBefore(node, rNode);
12614				}
12615				rNode = node;
12616			}
12617		},
12618
12619
12620		position: aam(domGeom.position),
12621		/*=====
12622		position: function(){
12623			// summary:
12624			//		Returns border-box objects (x/y/w/h) of all elements in a node list
12625			//		as an Array (*not* a NodeList). Acts like `dojo/dom-geometry-position`, though
12626			//		assumes the node passed is each node in this list.
12627
12628			return dojo.map(this, dojo.position); // Array
12629		},
12630		=====*/
12631
12632		attr: awc(getSet(domAttr), magicGuard),
12633		/*=====
12634		attr: function(property, value){
12635			// summary:
12636			//		gets or sets the DOM attribute for every element in the
12637			//		NodeList. See also `dojo/dom-attr`
12638			// property: String
12639			//		the attribute to get/set
12640			// value: String?
12641			//		optional. The value to set the property to
12642			// returns:
12643			//		if no value is passed, the result is an array of attribute values
12644			//		If a value is passed, the return is this NodeList
12645			// example:
12646			//		Make all nodes with a particular class focusable:
12647			//	|	require(["dojo/query", "dojo/NodeList-dom"], function(query){
12648			//	|		query(".focusable").attr("tabIndex", -1);
12649			//	|	});
12650			// example:
12651			//		Disable a group of buttons:
12652			//	|	require(["dojo/query", "dojo/NodeList-dom"], function(query){
12653			//	|		query("button.group").attr("disabled", true);
12654			//	|	});
12655			// example:
12656			//		innerHTML can be assigned or retrieved as well:
12657			//	|	// get the innerHTML (as an array) for each list item
12658			//	|	require(["dojo/query", "dojo/NodeList-dom"], function(query){
12659			//	|		var ih = query("li.replaceable").attr("innerHTML");
12660			//	|	});
12661			return; // dojo/NodeList|Array
12662		},
12663		=====*/
12664
12665		style: awc(getSet(domStyle), magicGuard),
12666		/*=====
12667		style: function(property, value){
12668			// summary:
12669			//		gets or sets the CSS property for every element in the NodeList
12670			// property: String
12671			//		the CSS property to get/set, in JavaScript notation
12672			//		("lineHieght" instead of "line-height")
12673			// value: String?
12674			//		optional. The value to set the property to
12675			// returns:
12676			//		if no value is passed, the result is an array of strings.
12677			//		If a value is passed, the return is this NodeList
12678			return; // dojo/NodeList
12679			return; // Array
12680		},
12681		=====*/
12682
12683		addClass: aafe(domCls.add),
12684		/*=====
12685		addClass: function(className){
12686			// summary:
12687			//		adds the specified class to every node in the list
12688			// className: String|Array
12689			//		A String class name to add, or several space-separated class names,
12690			//		or an array of class names.
12691			return; // dojo/NodeList
12692		},
12693		=====*/
12694
12695		removeClass: aafe(domCls.remove),
12696		/*=====
12697		removeClass: function(className){
12698			// summary:
12699			//		removes the specified class from every node in the list
12700			// className: String|Array?
12701			//		An optional String class name to remove, or several space-separated
12702			//		class names, or an array of class names. If omitted, all class names
12703			//		will be deleted.
12704			// returns:
12705			//		this list
12706			return; // dojo/NodeList
12707		},
12708		=====*/
12709
12710		toggleClass: aafe(domCls.toggle),
12711		/*=====
12712		toggleClass: function(className, condition){
12713			// summary:
12714			//		Adds a class to node if not present, or removes if present.
12715			//		Pass a boolean condition if you want to explicitly add or remove.
12716			// condition: Boolean?
12717			//		If passed, true means to add the class, false means to remove.
12718			// className: String
12719			//		the CSS class to add
12720			return; // dojo/NodeList
12721		},
12722		=====*/
12723
12724		replaceClass: aafe(domCls.replace),
12725		/*=====
12726		replaceClass: function(addClassStr, removeClassStr){
12727			// summary:
12728			//		Replaces one or more classes on a node if not present.
12729			//		Operates more quickly than calling `removeClass()` and `addClass()`
12730			// addClassStr: String|Array
12731			//		A String class name to add, or several space-separated class names,
12732			//		or an array of class names.
12733			// removeClassStr: String|Array?
12734			//		A String class name to remove, or several space-separated class names,
12735			//		or an array of class names.
12736			return; // dojo/NodeList
12737		 },
12738		 =====*/
12739
12740		empty: aafe(domCtr.empty),
12741		/*=====
12742		empty: function(){
12743			// summary:
12744			//		clears all content from each node in the list. Effectively
12745			//		equivalent to removing all child nodes from every item in
12746			//		the list.
12747			return this.forEach("item.innerHTML='';"); // dojo/NodeList
12748			// FIXME: should we be checking for and/or disposing of widgets below these nodes?
12749		},
12750		=====*/
12751
12752		removeAttr: aafe(domAttr.remove),
12753		/*=====
12754		 removeAttr: function(name){
12755			// summary:
12756			//		Removes an attribute from each node in the list.
12757			// name: String
12758			//		the name of the attribute to remove
12759			return;		// dojo/NodeList
12760		},
12761		=====*/
12762
12763		marginBox: aam(domGeom.getMarginBox),
12764		/*=====
12765		marginBox: function(){
12766			// summary:
12767			//		Returns margin-box size of nodes
12768		 	return; // dojo/NodeList
12769		 },
12770		 =====*/
12771
12772		// FIXME: connectPublisher()? connectRunOnce()?
12773
12774		/*
12775		destroy: function(){
12776			// summary:
12777			//		destroys every item in the list.
12778			this.forEach(d.destroy);
12779			// FIXME: should we be checking for and/or disposing of widgets below these nodes?
12780		},
12781		*/
12782
12783		place: function(/*String||Node*/ queryOrNode, /*String*/ position){
12784			// summary:
12785			//		places elements of this node list relative to the first element matched
12786			//		by queryOrNode. Returns the original NodeList. See: `dojo/dom-construct.place`
12787			// queryOrNode:
12788			//		may be a string representing any valid CSS3 selector or a DOM node.
12789			//		In the selector case, only the first matching element will be used
12790			//		for relative positioning.
12791			// position:
12792			//		can be one of:
12793			//
12794			//		-	"last" (default)
12795			//		-	"first"
12796			//		-	"before"
12797			//		-	"after"
12798			//		-	"only"
12799			//		-	"replace"
12800			//
12801			//		or an offset in the childNodes property
12802			var item = query(queryOrNode)[0];
12803			return this.forEach(function(node){ domCtr.place(node, item, position); }); // dojo/NodeList
12804		},
12805
12806		orphan: function(/*String?*/ filter){
12807			// summary:
12808			//		removes elements in this list that match the filter
12809			//		from their parents and returns them as a new NodeList.
12810			// filter:
12811			//		CSS selector like ".foo" or "div > span"
12812			// returns:
12813			//		NodeList containing the orphaned elements
12814			return (filter ? query._filterResult(this, filter) : this).forEac
vendor: 4,788 bytes, lines 12814-12939
12814h(orphan); // dojo/NodeList
12815		},
12816
12817		adopt: function(/*String||Array||DomNode*/ queryOrListOrNode, /*String?*/ position){
12818			// summary:
12819			//		places any/all elements in queryOrListOrNode at a
12820			//		position relative to the first element in this list.
12821			//		Returns a dojo/NodeList of the adopted elements.
12822			// queryOrListOrNode:
12823			//		a DOM node or a query string or a query result.
12824			//		Represents the nodes to be adopted relative to the
12825			//		first element of this NodeList.
12826			// position:
12827			//		can be one of:
12828			//
12829			//		-	"last" (default)
12830			//		-	"first"
12831			//		-	"before"
12832			//		-	"after"
12833			//		-	"only"
12834			//		-	"replace"
12835			//
12836			//		or an offset in the childNodes property
12837			return query(queryOrListOrNode).place(this[0], position)._stash(this);	// dojo/NodeList
12838		},
12839
12840		// FIXME: do we need this?
12841		query: function(/*String*/ queryStr){
12842			// summary:
12843			//		Returns a new list whose members match the passed query,
12844			//		assuming elements of the current NodeList as the root for
12845			//		each search.
12846			// example:
12847			//		assume a DOM created by this markup:
12848			//	|	<div id="foo">
12849			//	|		<p>
12850			//	|			bacon is tasty, <span>dontcha think?</span>
12851			//	|		</p>
12852			//	|	</div>
12853			//	|	<div id="bar">
12854			//	|		<p>great comedians may not be funny <span>in person</span></p>
12855			//	|	</div>
12856			//		If we are presented with the following definition for a NodeList:
12857			//	|	require(["dojo/dom", "dojo/query", "dojo/NodeList-dom"
12858			//	|	], function(dom, query){
12859			//	|		var l = new NodeList(dom.byId("foo"), dom.byId("bar"));
12860			//		it's possible to find all span elements under paragraphs
12861			//		contained by these elements with this sub-query:
12862			//	|		var spans = l.query("p span");
12863			//	|	});
12864
12865			// FIXME: probably slow
12866			if(!queryStr){ return this; }
12867			var ret = new NodeList;
12868			this.map(function(node){
12869				// FIXME: why would we ever get undefined here?
12870				query(queryStr, node).forEach(function(subNode){
12871					if(subNode !== undefined){
12872						ret.push(subNode);
12873					}
12874				});
12875			});
12876			return ret._stash(this);	// dojo/NodeList
12877		},
12878
12879		filter: function(/*String|Function*/ filter){
12880			// summary:
12881			//		"masks" the built-in javascript filter() method (supported
12882			//		in Dojo via `dojo.filter`) to support passing a simple
12883			//		string filter in addition to supporting filtering function
12884			//		objects.
12885			// filter:
12886			//		If a string, a CSS rule like ".thinger" or "div > span".
12887			// example:
12888			//		"regular" JS filter syntax as exposed in dojo.filter:
12889			//	|	require(["dojo/query", "dojo/NodeList-dom"
12890			//	|	], function(query){
12891			//	|		query("*").filter(function(item){
12892			//	|			// highlight every paragraph
12893			//	|			return (item.nodeName == "p");
12894			//	|		}).style("backgroundColor", "yellow");
12895			//	|	});
12896			// example:
12897			//	the same filtering using a CSS selector
12898			//	|	require(["dojo/query", "dojo/NodeList-dom"
12899			//	|	], function(query){
12900			//	|		query("*").filter("p").styles("backgroundColor", "yellow");
12901			//	|	});
12902			var a = arguments, items = this, start = 0;
12903			if(typeof filter == "string"){ // inline'd type check
12904				items = query._filterResult(this, a[0]);
12905				if(a.length == 1){
12906					// if we only got a string query, pass back the filtered results
12907					return items._stash(this); // dojo/NodeList
12908				}
12909				// if we got a callback, run it over the filtered items
12910				start = 1;
12911			}
12912			return this._wrap(array.filter(items, a[start], a[start + 1]), this);	// dojo/NodeList
12913		},
12914
12915		/*
12916		// FIXME: should this be "copyTo" and include parenting info?
12917		clone: function(){
12918			// summary:
12919			//		creates node clones of each element of this list
12920			//		and returns a new list containing the clones
12921		},
12922		*/
12923
12924		addContent: function(/*String||DomNode||Object||dojo/NodeList*/ content, /*String||Integer?*/ position){
12925			// summary:
12926			//		add a node, NodeList or some HTML as a string to every item in the
12927			//		list.  Returns the original list.
12928			// description:
12929			//		a copy of the HTML content is added to each item in the
12930			//		list, with an optional position argument. If no position
12931			//		argument is provided, the content is appended to the end of
12932			//		each item.
12933			// content:
12934			//		DOM node, HTML in string format, a NodeList or an Object. If a DOM node or
12935			//		NodeList, the content will be cloned if the current NodeList has more than one
12936			//		element. Only the DOM nodes are cloned, no event handlers. If it is an Object,
12937			//		it should be an object with at "template" String property that has the HTML string
12938			//		to insert. If dojo.string has already been dojo.required, then dojo.string.substitute
12939			//		will be used on the "template" to generate the final HTML 
12939string. Other allowed
12940			//		properties on the object are: "parse" if the HTML
12941			//		string should be parsed for widgets (dojo.require("dojo.parser") to get that
12942			//		option to work), and "templateFunc" if a template function besides dojo.string.substitute
12943			//		should be used to transform the "template".
12944			// position:
12945			//		can be one of:
12946			//
12947			//		-	"last"||"end" (default)
12948			//		-	"first||"start"
12949			//		-	"before"
12950			//		-	"after"
12951			//		-	"replace" (replaces nodes in this NodeList with new content)
12952			//		-	"only" (removes other children of the nodes so new content is the only child)
12953			//
12954			//		or an offset in the childNodes property
12955			// example:
12956			//		appends content to the end if the position is omitted
12957			//	|	require(["dojo/query", "dojo/NodeList-dom"
12958			//	|	], function(query){
12959			//	|		query("h3 > p").addContent("hey there!");
12960			//	|	});
12961			// example:
12962			//		add something to the front of each element that has a
12963			//		"thinger" property:
12964			//	|	require(["dojo/query", "dojo/NodeList-dom"
12965			//	|	], function(query){
12966			//	|		query("[thinger]").addContent("...", "first");
12967			//	|	});
12968			// example:
12969			//		adds a header before each element of the list
12970			//	|	require(["dojo/query", "dojo/NodeList-dom"
12971			//	|	], function(query){
12972			//	|		query(".note").addContent("<h4>NOTE:</h4>", "before");
12973			//	|	});
12974			// example:
12975			//		add a clone of a DOM node to the end of every element in
12976			//		the list, removing it from its existing parent.
12977			//	|	require(["dojo/dom", "dojo/query", "dojo/NodeList-dom"
12978			//	|	], function(dom, query){
12979			//	|		query(".note").addContent(dom.byId("foo"));
12980			//	|	});
12981			// example:
12982			//		Append nodes from a templatized string.
12983			//	|	require(["dojo/string", "dojo/query", "dojo/NodeList-dom"
12984			//	|	], function(string, query){
12985			//	|		query(".note").addContent({
12986			//	|			template: '<b>${id}: </b><span>${name}</span>',
12987			//	|			id: "user332",
12988			//	|			name: "Mr. Anderson"
12989			//	|		});
12990			//	|	});
12991			// example:
12992			//		Append nodes from a templatized string that also has widgets parsed.
12993			//	|	require(["dojo/string", "dojo/parser", "dojo/query", "dojo/NodeList-dom"
12994			//	|	], function(string, parser, query){
12995			//	|		var notes = query(".note").addContent({
12996			//	|			template: '<button dojoType="dijit/form/Button">${text}</button>',
12997			//	|			parse: true,
12998			//	|			text: "Send"
12999			//	|		});
13000			//	|	});
13001			content = this._normalize(content, this[0]);
13002			for(var i = 0, node; (node = this[i]); i++){
13003				if(content.length){
13004					this._place(content, node, position, i > 0);
13005				}else{
13006					// if it is an empty array, we empty the target node
13007					domCtr.empty(node);
13008				}
13009			}
13010			return this; // dojo/NodeList
13011		}
13012	});
13013
13014	return NodeList;
13015});
13016
13017},
13018'dojo/_base/xhr':function(){
13019define([
13020	"./kernel",
13021	"./sniff",
13022	"require",
13023	"../io-query",
13024	/*===== "./declare", =====*/
13025	"../dom",
13026	"../dom-form",
13027	"./Deferred",
13028	"./config",
13029	"./json",
13030	"./lang",
13031	"./array",
13032	"../on",
13033	"../aspect",
13034	"../request/watch",
13035	"../request/xhr",
13036	"../request/util"
13037], function(dojo, has, require, ioq, /*===== declare, =====*/ dom, domForm, Deferred, config, json, lang, array, on, aspect, watch, _xhr, util){
13038	// module:
13039	//		dojo/_base/xhr
13040
13041	/*=====
13042	dojo._xhrObj = function(){
13043		// summary:
13044		//		does the work of portably generating a new XMLHTTPRequest object.
13045	};
13046	=====*/
13047	dojo._xhrObj = _xhr._create;
13048
13049	var cfg = dojo.config;
13050
13051	// mix in io-query and dom-form
13052	dojo.objectToQuery = ioq.objectToQuery;
13053	dojo.queryToObject = ioq.queryToObject;
13054	dojo.fieldToObject = domForm.fieldToObject;
13055	dojo.formToObject = domForm.toObject;
13056	dojo.formToQuery = domForm.toQuery;
13057	dojo.formToJson = domForm.toJson;
13058
13059	// need to block async callbacks from snatching this thread as the result
13060	// of an async callback might call another sync XHR, this hangs khtml forever
13061	// must checked by watchInFlight()
13062
13063	dojo._blockAsync = false;
13064
13065	// MOW: remove dojo._contentHandlers alias in 2.0
13066	var handlers = dojo._contentHandlers = dojo.contentHandlers = {
13067		// summary:
13068		//		A map of available XHR transport handle types. Name matches the
13069		//		`handleAs` attribute passed to XHR calls.
13070		// description:
13071		//		A map of available XHR transport handle types. Name matches the
13072		//		`handleAs` attribute passed to XHR calls. Each contentHandler is
13073		//		called, passing the xhr object for manipulation. The return value
13074		//		from the contentHandler will be passed to the `load` or `handle`
13075		//		functions defined in the original xhr call.
13076		// example:
13077		//		Creating a custom content-handler:
13078		//	|	xhr.contentHandlers.makeCaps = function(xhr){
13079		//	|		return xhr.responseText.toUpperCase();
13080		//	|	}
13081		//	|	// and later:
13082		//	|	dojo.xhrGet({
13083		//	|		url:"foo.txt",
13084		//	|		handleAs:"makeCaps",
13085		//	|		load: function(data){ /* data is a toUpper version of foo.txt */ }
13086		//	|	});
13087
13088		"text": function(xhr){
13089			// summary:
13090			//		A contentHandler which simply returns the plaintext response data
13091			return xhr.responseText;
13092		},
13093		"json": function(xhr){
13094			// summary:
13095			//		A contentHandler which returns a JavaScript object created from the response data
13096			return json.fromJson(xhr.responseText || null);
13097		},
13098		"json-comment-filtered": function(xhr){
13099			// summary:
13100			//		A contentHandler which expects comment-filtered JSON.
13101			// description:
13102			//		A contentHandler which expects comment-filtered JSON.
13103			//		the json-comment-filtered option was implemented to prevent
13104			//		"JavaScript Hijacking", but it is less secure than standard JSON. Use
13105			//		standard JSON instead. JSON prefixing can be used to subvert hijacking.
13106			//
13107			//		Will throw a notice suggesting to use application/json mimetype, as
13108			//		json-commenting can introduce security issues. To decrease the chances of hijacking,
13109			//		use the standard `json` contentHandler, and prefix your "JSON" with: {}&&
13110			//
13111			//		use djConfig.useCommentedJson = true to turn off the notice
13112			if(!config.useCommentedJson){
13113				console.warn("Consider using the standard mimetype:application/json."
13114					+ " json-commenting can introduce security issues. To"
13115					+ " decrease the chances of hijacking, use the standard the 'json' handler and"
13116					+ " prefix your json with: {}&&\n"
13117					+ "Use djConfig.useCommentedJson=true to turn off this message.");
13118			}
13119
13120			var value = xhr.responseText;
13121			var cStartIdx = value.indexOf("\/*");
13122			var cEndIdx = value.lastIndexOf("*\/");
13123			if(cStartIdx == -1 || cEndIdx == -1){
13124				throw new Error("JSON was not comment filtered");
13125			}
13126			return json.fromJson(value.substring(cStartIdx+2, cEndIdx));
13127		},
13128		"javascript": function(xhr){
13129			// summary:
13130			//		A contentHandler which evaluates the response data, expecting it to be valid JavaScript
13131
13132			// FIXME: try Moz and IE specific eval variants?
13133			return dojo.eval(xhr.responseText);
13134		},
13135		"xml": function(xhr){
13136			// summary:
13137			//		A contentHandler returning an XML Document parsed from the response data
13138			var result = xhr.responseXML;
13139
13140			if(result && has("dom-qsa2.1") && !result.querySelectorAll && has("dom-parser")){
13141				// http://bugs.dojotoolkit.org/ticket/15631
13142				// IE9 supports a CSS3 querySelectorAll implementation, but the DOM implementation 
13143				// returned by IE9 xhr.responseXML does not. Manually create the XML DOM to gain 
13144				// the fuller-featured implementation and avoid bugs caused by the inconsistency
13145				result = new DOMParser().parseFromString(xhr.responseText, "application/xml");
13146			}
13147
13148			if(has("ie")){
13149				if((!result || !result.documentElement)){
13150					//WARNING: this branch used by the xml handling in dojo.io.iframe,
13151					//so be sure to test dojo.io.iframe if making changes below.
13152					var ms = function(n){ return "MSXML" + n + ".DOMDocument"; };
13153					var dp = ["Microsoft.XMLDOM", ms(6), ms(4), ms(3), ms(2)];
13154					array.some(dp, function(p){
13155						try{
13156							var dom = new ActiveXObject(p);
13157							dom.async = false;
13158							dom.loadXML(xhr.responseText);
13159							result = dom;
13160						}catch(e){ return false; }
13161						return true;
13162					});
13163				}
13164			}
13165			return result; // DOMDocument
13166		},
13167		"json-comment-optional": function(xhr){
13168			// summary:
13169			//		A contentHandler which checks the presence of comment-filtered JSON and
13170			//		alternates between the `json` and `json-comment-filtered` contentHandlers.
13171			if(xhr.responseText && /^[^{\[]*\/\*/.test(xhr.responseText)){
13172				return handlers["json-comment-filtered"](xhr);
13173			}else{
13174				return handlers["json"](xhr);
13175			}
13176		}
13177	};
13178
13179	/*=====
13180
13181	// kwargs function parameter definitions.   Assigning to dojo namespace rather than making them local variables
13182	// because they are used by dojo/io modules too
13183
13184	dojo.__IoArgs = declare(null, {
13185		// url: String
13186		//		URL to server endpoint.
13187		// content: Object?
13188		//		Contains properties with string values. These
13189		//		properties will be serialized as name1=value2 and
13190		//		passed in the request.
13191		// timeout: Integer?
13192		//		Milliseconds to wait for the response. If this time
13193		//		passes, the then error callbacks are called.
13194		// form: DOMNode?
13195		//		DOM node for a form. Used to extract the form values
13196		//		and send to the server.
13197		// preventCache: Boolean?
13198		//		Default is false. If true, then a
13199		//		"dojo.preventCache" parameter is sent in the request
13200		//		with a value that changes with each request
13201		//		(timestamp). Useful only with GET-type requests.
13202		// handleAs: String?
13203		//		Acceptable values depend on the type of IO
13204		//		transport (see specific IO calls for more information).
13205		// rawBody: String?
13206		//		Sets the raw body for an HTTP request. If this is used, then the content
13207		//		property is ignored. This is mostly useful for HTTP methods that have
13208		//		a body to their requests, like PUT or POST. This property can be used instead
13209		//		of postData and putData for dojo/_base/xhr.rawXhrPost and dojo/_base/xhr.rawXhrPut respectively.
13210		// ioPublish: Boolean?
13211		//		Set this explicitly to false to prevent publishing of topics related to
13212		//		IO operations. Otherwise, if djConfig.ioPublish is set to true, topics
13213		//		will be published via dojo/topic.publish() for different phases of an IO operation.
13214		//		See dojo/main.__IoPublish for a list of topics that are published.
13215
13216		load: function(response, ioArgs){
13217			// summary:
13218			//		This function will be
13219			//		called on a successful HTTP response code.
13220	 		// ioArgs: dojo/main.__IoCallbackArgs
13221			//		Provides additional information about the request.
13222			// response: Object
13223			//		The response in the format as defined with handleAs.
13224		},
13225
13226		error: function(response, ioArgs){
13227			// summary:
13228			//		This function will
13229			//		be called when the request fails due to a network or server error, the url
13230			//		is invalid, etc. It will also be called if the load or handle callback throws an
13231			//		exception, unless djConfig.debugAtAllCosts is true.	 This allows deployed applications
13232			//		to continue to run even when a logic error happens in the callback, while making
13233			//		it easier to troubleshoot while in debug mode.
13234			// ioArgs: dojo/main.__IoCallbackArgs
13235			//		Provides additional information about the request.
13236			// response: Object
13237			//		The response in the format as defined with handleAs.
13238		},
13239
13240		handle: function(loadOrError, response, ioArgs){
13241			// summary:
13242	 		//		This function will
13243	 		//		be called at the end of every request, whether or not an error occurs.
13244			// loadOrError: String
13245			//		Provides a string that tells you whether this function
13246			//		was called because of success (load) or failure (error).
13247			// response: Object
13248			//		The response in the format as defined with handleAs.
13249			// ioArgs: dojo/main.__IoCallbackArgs
13250			//		Provides additional information about the request.
13251		}
13252	});
13253
13254	dojo.__IoCallbackArgs = declare(null, {
13255		// args: Object
13256		//		the original object argument to the IO call.
13257		// xhr: XMLHttpRequest
13258		//		For XMLHttpRequest calls only, the
13259		//		XMLHttpRequest object that was used for the
13260		//		request.
13261		// url: String
13262		//		The final URL used for the call. Many times it
13263		//		will be different than the original args.url
13264		//		value.
13265		// query: String
13266		//		For non-GET requests, the
13267		//		name1=value1&name2=value2 parameters sent up in
13268		//		the request.
13269		// handleAs: String
13270		//		The final indicator on how the response will be
13271		//		handled.
13272		// id: String
13273		//		For dojo/io/script calls only, the internal
13274		//		script ID used for the request.
13275		// canDelete: Boolean
13276		//		For dojo/io/script calls only, indicates
13277		//		whether the script tag that represents the
13278		//		request can be deleted after callbacks have
13279		//		been called. Used internally to know when
13280		//		cleanup can happen on JSONP-type requests.
13281		// json: Object
13282		//		For dojo/io/script calls only: holds the JSON
13283		//		response for JSONP-type requests. Used
13284		//		internally to hold on to the JSON responses.
13285		//		You should not need to access it directly --
13286		//		the same object should be passed to the success
13287		//		callbacks directly.
13288	});
13289
13290	dojo.__IoPublish = declare(null, {
13291		// summary:
13292		//		This is a list of IO topics that can be published
13293		//		if djConfig.ioPublish is set to true. IO topics can be
13294		//		published for any Input/Output, network operation. So,
13295		//		dojo.xhr, dojo.io.script and dojo.io.iframe can all
13296		//		trigger these topics to be published.
13297		// start: String
13298		//		"/dojo/io/start" is sent when there are no outstanding IO
13299		//		requests, and a new IO request is started. No arguments
13300		//		are passed with this topic.
13301		// send: String
13302		//		"/dojo/io/send" is sent whenever a new IO request is started.
13303		//		It passes the dojo.Deferred for the request with the topic.
13304		// load: String
13305		//		"/dojo/io/load" is sent whenever an IO request has loaded
13306		//		successfully. It passes the response and the dojo.Deferred
13307		//		for the request with the topic.
13308		// error: String
13309		//		"/dojo/io/error" is sent whenever an IO request has errored.
13310		//		It passes the error and the dojo.Deferred
13311		//		for the request with the topic.
13312		// done: String
13313		//		"/dojo/io/done" is sent whenever an IO request has completed,
13314		//		either by loading or by erroring. It passes the error and
13315		//		the dojo.Deferred for the request with the topic.
13316		// stop: String
13317		//		"/dojo/io/stop" is sent when all outstanding IO requests have
13318		//		finished. No arguments are passed with this topic.
13319	});
13320	=====*/
13321
13322
13323	dojo._ioSetArgs = function(/*dojo/main.__IoArgs*/args,
13324			/*Function*/canceller,
13325			/*Function*/okHandler,
13326			/*Function*/errHandler){
13327		// summary:
13328		//		sets up the Deferred and ioArgs property on the Deferred so it
13329		//		can be used in an io call.
13330		// args:
13331		//		The args object passed into the public io call. Recognized properties on
13332		//		the args object are:
13333		// canceller:
13334		//		The canceller function used for the Deferred object. The function
13335		//		will receive one argument, the Deferred object that is related to the
13336		//		canceller.
13337		// okHandler:
13338		//		The first OK callback to be registered with Deferred. It has the opportunity
13339		//		to transform the OK response. It will receive one argument -- the Deferred
13340		//		object returned from this function.
13341		// errHandler:
13342		//		The first error callback to be registered with Deferred. It has the opportunity
13343		//		to do cleanup on an error. It will receive two arguments: error (the
13344		//		Error object) and dfd, the Deferred object returned from this function.
13345
13346		var ioArgs = {args: args, url: args.url};
13347
13348		//Get values from form if requested.
13349		var formObject = null;
13350		if(args.form){
13351			var form = dom.byId(args.form);
13352			//IE requires going through getAttributeNode instead of just getAttribute in some form cases,
13353			//so use it for all. See #2844
13354			var actnNode = form.getAttributeNode("action");
13355			ioArgs.url = ioArgs.url || (actnNode ? actnNode.value : null);
13356			formObject = domForm.toObject(form);
13357		}
13358
13359		// set up the query params
13360		var miArgs = [{}];
13361
13362		if(formObject){
13363			// potentially over-ride url-provided params w/ form values
13364			miArgs.push(formObject);
13365		}
13366		if(args.content){
13367			// stuff in content over-rides what's set by form
13368			miArgs.push(args.content);
13369		}
13370		if(args.preventCache){
13371			miArgs.push({"dojo.preventCache": new Date().valueOf()});
13372		}
13373		ioArgs.query = ioq.objectToQuery(lang.mixin.apply(null, miArgs));
13374
13375		// .. and the real work of getting the deferred in order, etc.
13376		ioArgs.handleAs = args.handleAs || "text";
13377		var d = new Deferred(function(dfd){
13378			dfd.canceled = true;
13379			canceller && canceller(dfd);
13380
13381			var err = dfd.ioArgs.error;
13382			if(!err){
13383				err = new Error("request cancelled");
13384				err.dojoType="cancel";
13385				dfd.ioArgs.error = err;
13386			}
13387			return err;
13388		});
13389		d.addCallback(okHandler);
13390
13391		//Support specifying load, error and handle callback functions from the args.
13392		//For those callbacks, the "this" object will be the args object.
13393		//The callbacks will get the deferred result value as the
13394		//first argument and the ioArgs object as the second argument.
13395		var ld = args.load;
13396		if(ld && lang.isFunction(ld)){
13397			d.addCallback(function(value){
13398				return ld.call(args, value, ioArgs);
13399			});
13400		}
13401		var err = args.error;
13402		if(err && lang.isFunction(err)){
13403			d.addErrback(function(value){
13404				return err.call(args, value, ioArgs);
13405			});
13406		}
13407		var handle = args.handle;
13408		if(handle && lang.isFunction(handle)){
13409			d.addBoth(function(value){
13410				return handle.call(args, value, ioArgs);
13411			});
13412		}
13413
13414		// Attach error handler last (not including topic publishing)
13415		// to catch any errors that may have been generated from load
13416		// or handle functions.
13417		d.addErrback(function(error){
13418			return errHandler(error, d);
13419		});
13420
13421		//Plug in topic publishing, if dojo.publish is loaded.
13422		if(cfg.ioPublish && dojo.publish && ioArgs.args.ioPublish !== false){
13423			d.addCallbacks(
13424				function(res){
13425					dojo.publish("/dojo/io/load", [d, res]);
13426					return res;
13427				},
13428				function(res){
13429					dojo.publish("/dojo/io/error", [d, res]);
13430					return res;
13431				}
13432			);
13433			d.addBoth(function(res){
13434				dojo.publish("/dojo/io/done", [d, res]);
13435				return res;
13436			});
13437		}
13438
13439		d.ioArgs = ioArgs;
13440
13441		// FIXME: need to wire up the xhr object's abort method to something
13442		// analogous in the Deferred
13443		return d;
13444	};
13445
13446	var _deferredOk = function(/*Deferred*/dfd){
13447		// summary:
13448		//		okHandler function for dojo._ioSetArgs call.
13449
13450		var ret = handlers[dfd.ioArgs.handleAs](dfd.ioArgs.xhr);
13451		return ret === undefined ? null : ret;
13452	};
13453	var _deferError = function(/*Error*/error, /*Deferred*/dfd){
13454		// summary:
13455		//		errHandler function for dojo._ioSetArgs call.
13456
13457		if(!dfd.ioArgs.args.failOk){
13458			console.error(error);
13459		}
13460		return error;
13461	};
13462
13463	//Use a separate count for knowing if we are starting/stopping io calls.
13464	var _checkPubCount = function(dfd){
13465		if(_pubCount <= 0){
13466			_pubCount = 0;
13467			if(cfg.ioPublish && dojo.publish && (!dfd || dfd && dfd.ioArgs.args.ioPublish !== false)){
13468				dojo.publish("/dojo/io/stop");
13469			}
13470		}
13471	};
13472
13473	var _pubCount = 0;
13474	aspect.after(watch, "_onAction", function(){
13475		_pubCount -= 1;
13476	});
13477	aspect.after(watch, "_onInFlight", _checkPubCount);
13478
13479	dojo._ioCancelAll = watch.cancelAll;
13480	/*=====
13481	dojo._ioCancelAll = function(){
13482		// summary:
13483		//		Cancels all pending IO requests, regardless of IO type
13484		//		(xhr, script, iframe).
13485	};
13486	=====*/
13487
13488	dojo._ioNotifyStart = function(/*Deferred*/dfd){
13489		// summary:
13490		//		If dojo.publish is available, publish topics
13491		//		about the start of a request queue and/or the
13492		//		the beginning of request.
13493		//
13494		//		Used by IO transports. An IO transport should
13495		//		call this method before making the network connection.
13496		if(cfg.ioPublish && dojo.publish && dfd.ioArgs.args.ioPublish !== false){
13497			if(!_pubCount){
13498				dojo.publish("/dojo/io/start");
13499			}
13500			_pubCount += 1;
13501			dojo.publish("/dojo/io/send", [dfd]);
13502		}
13503	};
13504
13505	dojo._ioWatch = function(dfd, validCheck, ioCheck, resHandle){
13506		// summary:
13507		//		Watches the io request represented by dfd to see if it completes.
13508		// dfd: Deferred
13509		//		The Deferred object to watch.
13510		// validCheck: Function
13511		//		Function used to check if the IO request is still valid. Gets the dfd
13512		//		object as its only argument.
13513		// ioCheck: Function
13514		//		Function used to check if basic IO call worked. Gets the dfd
13515		//		object as its only argument.
13516		// resHandle: Function
13517		//		Function used to process response. Gets the dfd
13518		//		object as its only argument.
13519
13520		var args = dfd.ioArgs.options = dfd.ioArgs.args;
13521		lang.mixin(dfd, {
13522			response: dfd.ioArgs,
13523			isValid: function(response){
13524				return validCheck(dfd);
13525			},
13526			isReady: function(response){
13527				return ioCheck(dfd);
13528			},
13529			handleResponse: function(response){
13530				return resHandle(dfd);
13531			}
13532		});
13533		watch(dfd);
13534
13535		_checkPubCount(dfd);
13536	};
13537
13538	var _defaultContentType = "application/x-www-form-urlencoded";
13539
13540	dojo._ioAddQueryToUrl = function(/*dojo.__IoCallbackArgs*/ioArgs){
13541		// summary:
13542		//		Adds query params discovered by the io deferred construction to the URL.
13543		//		Only use this for operations which are fundamentally GET-type operations.
13544		if(ioArgs.query.length){
13545			ioArgs.url += (ioArgs.url.indexOf("?") == -1 ? "?" : "&") + ioArgs.query;
13546			ioArgs.query = null;
13547		}
13548	};
13549
13550	/*=====
13551	dojo.__XhrArgs = declare(dojo.__IoArgs, {
13552		// summary:
13553		//		In addition to the properties listed for the dojo._IoArgs type,
13554		//		the following properties are allowed for dojo.xhr* methods.
13555		// handleAs: String?
13556		//		Acceptable values are: text (default), json, json-comment-optional,
13557		//		json-comment-filtered, javascript, xml. See `dojo/_base/xhr.contentHandlers`
13558	 	// sync: Boolean?
13559		//		false is default. Indicates whether the request should
13560		//		be a synchronous (blocking) request.
13561		// headers: Object?
13562		//		Additional HTTP headers to send in the request.
13563		// failOk: Boolean?
13564		//		false is default. Indicates whether a request should be
13565		//		allowed to fail (and therefore no console error message in
13566		//		the event of a failure)
13567		// contentType: String|Boolean
13568		//		"application/x-www-form-urlencoded" is default. Set to false to
13569		//		prevent a Content-Type header from being sent, or to a string
13570		//		to send a different Content-Type.
13571	 });
13572	=====*/
13573
13574	dojo.xhr = function(/*String*/ method, /*dojo.__XhrArgs*/ args, /*Boolean?*/ hasBody){
13575		// summary:
13576		//		Deprecated.   Use dojo/request instead.
13577		// description:
13578		//		Sends an HTTP request with the given method.
13579		//		See also dojo.xhrGet(), xhrPost(), xhrPut() and dojo.xhrDelete() for shortcuts
13580		//		for those HTTP methods. There are also methods for "raw" PUT and POST methods
13581		//		via dojo.rawXhrPut() and dojo.rawXhrPost() respectively.
13582		// method:
13583		//		HTTP method to be used, such as GET, POST, PUT, DELETE. Should be uppercase.
13584		// hasBody:
13585		//		If the request has an HTTP body, then pass true for hasBody.
13586
13587		var rDfd;
13588		//Make the Deferred object for this xhr request.
13589		var dfd = dojo._ioSetArgs(args, function(dfd){
13590			rDfd && rDfd.cancel();
13591		}, _deferredOk, _deferError);
13592		var ioArgs = dfd.ioArgs;
13593
13594		//Allow for specifying the HTTP body completely.
13595		if("postData" in args){
13596			ioArgs.query = args.postData;
13597		}else if("putData" in args){
13598			ioArgs.query = args.putData;
13599		}else if("rawBody" in args){
13600			ioArgs.query = args.rawBody;
13601		}else if((arguments.length > 2 && !hasBody) || "POST|PUT".indexOf(method.toUpperCase()) === -1){
13602			//Check for hasBody being passed. If no hasBody,
13603			//then only append query string if not a POST or PUT request.
13604			dojo._ioAddQueryToUrl(ioArgs);
13605		}
13606
13607		var options = {
13608			method: method,
13609			handleAs: "text",
13610			timeout: args.timeout,
13611			withCredentials: args.withCredentials,
13612			ioArgs: ioArgs
13613		};
13614
13615		if(typeof args.headers !== 'undefined'){
13616			options.headers = args.headers;
13617		}
13618		if(typeof args.contentType !== 'undefined'){
13619			if(!options.headers){
13620				options.headers = {};
13621			}
13622			options.headers['Content-Type'] = args.contentType;
13623		}
13624		if(typeof ioArgs.query !== 'undefined'){
13625			options.data = ioArgs.query;
13626		}
13627		if(typeof args.sync !== 'undefined'){
13628			options.sync = args.sync;
13629		}
13630
13631		dojo._ioNotifyStart(dfd);
13632		try{
13633			rDfd = _xhr(ioArgs.url, options, true);
13634		}catch(e){
13635			// If XHR creation fails, dojo/request/xhr throws
13636			// When this happens, cancel the deferred
13637			dfd.cancel();
13638			return dfd;
13639		}
13640
13641		// sync ioArgs
13642		dfd.ioArgs.xhr = rDfd.response.xhr;
13643
13644		rDfd.then(function(){
13645			dfd.resolve(dfd);
13646		}).otherwise(function(error){
13647			ioArgs.error = error;
13648			if(error.response){
13649				error.status = error.response.status;
13650				error.responseText = error.response.text;
13651				error.xhr = error.response.xhr;
13652			}
13653			dfd.reject(error);
13654		});
13655		return dfd; // dojo/_base/Deferred
13656	};
13657
13658	dojo.xhrGet = function(/*dojo.__XhrArgs*/ args){
13659		// summary:
13660		//		Sends an HTTP GET request to the server.
13661		return dojo.xhr("GET", args); // dojo/_base/Deferred
13662	};
13663
13664	dojo.rawXhrPost = dojo.xhrPost = function(/*dojo.__XhrArgs*/ args){
13665		// summary:
13666		//		Sends an HTTP POST request to the server. In addition to the properties
13667		//		listed for the dojo.__XhrArgs type, the following property is allowed:
13668		// postData:
13669		//		String. Send raw data in the body of the POST request.
13670		return dojo.xhr("POST", args, true); // dojo/_base/Deferred
13671	};
13672
13673	dojo.rawXhrPut = dojo.xhrPut = function(/*dojo.__XhrArgs*/ args){
13674		// summary:
13675		//		Sends an HTTP PUT request to the server. In addition to the properties
13676		//		listed for the dojo.__XhrArgs type, the following property is allowed:
13677		// putData:
13678		//		String. Send raw data in the body of the PUT request.
13679		return dojo.xhr("PUT", args, true); // dojo/_base/Deferred
13680	};
13681
13682	dojo.xhrDelete = function(/*dojo.__XhrArgs*/ args){
13683		// summary:
13684		//		Sends an HTTP DELETE request to the server.
13685		return dojo.xhr("DELETE", args); // dojo/_base/Deferred
13686	};
13687
13688	/*
13689	dojo.wrapForm = function(formNode){
13690		// summary:
13691		//		A replacement for FormBind, but not implemented yet.
13692
13693		// FIXME: need to think harder about what extensions to this we might
13694		// want. What should we allow folks to do w/ this? What events to
13695		// set/send?
13696		throw new Error("dojo.wrapForm not yet implemented");
13697	}
13698	*/
13699
13700	dojo._isDocumentOk = function(x){
13701		return util.checkStatus(x.status);
13702	};
13703
13704	dojo._getText = function(url){
13705		var result;
13706		dojo.xhrGet({url:url, sync:true, load:function(text){
13707			result = text;
13708		}});
13709		return result;
13710	};
13711
13712	// Add aliases for static functions to dojo.xhr since dojo.xhr is what's returned from this module
13713	lang.mixin(dojo.xhr, {
13714		_xhrObj: dojo._xhrObj,
13715		fieldToObject: domForm.fieldToObject,
13716		formToObject: domForm.toObject,
13717		objectToQuery: ioq.objectToQuery,
13718		formToQuery: domForm.toQuery,
13719		formToJson: domForm.toJson,
13720		queryToObject: ioq.queryToObject,
13721		contentHandlers: handlers,
13722		_ioSetArgs: dojo._ioSetArgs,
13723		_ioCancelAll: dojo._ioCancelAll,
13724		_ioNotifyStart: dojo._ioNotifyStart,
13725		_ioWatch: dojo._ioWatch,
13726		_ioAddQueryToUrl: dojo._ioAddQueryToUrl,
13727		_isDocumentOk: dojo._isDocumentOk,
13728		_getText: dojo._getText,
13729		get: dojo.xhrGet,
13730		post: dojo.xhrPost,
13731		put: dojo.xhrPut,
13732		del: dojo.xhrDelete	// because "delete" is a reserved word
13733	});
13734
13735	return dojo.xhr;
13736});
13737
13738},
13739'dojo/io-query':function(){
13740define(["./_base/lang"], function(lang){
13741
13742// module:
13743//		dojo/io-query
13744
13745var backstop = {};
13746
13747return {
13748// summary:
13749//		This module defines query string processing functions.
13750
13751	objectToQuery: function objectToQuery(/*Object*/ map){
13752		// summary:
13753        //		takes a name/value mapping object and returns a string representing
13754        //		a URL-encoded version of that object.
13755        // example:
13756        //		this object:
13757        //
13758        //	|	{
13759        //	|		blah: "blah",
13760        //	|		multi: [
13761        //	|			"thud",
13762        //	|			"thonk"
13763        //	|		]
13764        //	|	};
13765        //
13766        //		yields the following query string:
13767        //
13768        //	|	"blah=blah&multi=thud&multi=thonk"
13769
13770        // FIXME: need to implement encodeAscii!!
13771        var enc = encodeURIComponent, pairs = [];
13772        for(var name in map){
13773            var value = map[name];
13774            if(value != backstop[name]){
13775                var assign = enc(name) + "=";
13776                if(lang.isArray(value)){
13777                    for(var i = 0, l = value.length; i < l; ++i){
13778                        pairs.push(assign + enc(value[i]));
13779                    }
13780                }else{
13781                    pairs.push(assign + enc(value));
13782                }
13783            }
13784        }
13785        return pairs.join("&"); // String
13786    },
13787
13788	queryToObject: function queryToObject(/*String*/ str){
13789        // summary:
13790        //		Create an object representing a de-serialized query section of a
13791        //		URL. Query keys with multiple values are returned in an array.
13792        //
13793        // example:
13794        //		This string:
13795        //
13796        //	|		"foo=bar&foo=baz&thinger=%20spaces%20=blah&zonk=blarg&"
13797        //
13798        //		results in this object structure:
13799        //
13800        //	|		{
13801        //	|			foo: [ "bar", "baz" ],
13802        //	|			thinger: " spaces =blah",
13803        //	|			zonk: "blarg"
13804        //	|		}
13805        //
13806        //		Note that spaces and other urlencoded entities are correctly
13807        //		handled.
13808
13809        // FIXME: should we grab the URL string if we're not passed one?
13810        var dec = decodeURIComponent, qp = str.split("&"), ret = {}, name, val;
13811        for(var i = 0, l = qp.length, item; i < l; ++i){
13812            item = qp[i];
13813            if(item.length){
13814                var s = item.indexOf("=");
13815                if(s < 0){
13816                    name = dec(item);
13817                    val = "";
13818                }else{
13819                    name = dec(item.slice(0, s));
13820                    val  = dec(item.slice(s + 1));
13821                }
13822                if(typeof ret[name] == "string"){ // inline'd type check
13823                    ret[name] = [ret[name]];
13824                }
13825
13826                if(lang.isArray(ret[name])){
13827                    ret[name].push(val);
13828                }else{
13829                    ret[name] = val;
13830                }
13831            }
13832        }
13833        return ret; // Object
13834    }
13835};
13836});
13837},
13838'dojo/dom-form':function(){
13839define(["./_base/lang", "./dom", "./io-query", "./json"], function(lang, dom, ioq, json){
13840	// module:
13841	//		dojo/dom-form
13842
13843    function setValue(/*Object*/ obj, /*String*/ name, /*String*/ value){
13844        // summary:
13845        //		For the named property in object, set the value. If a value
13846        //		already exists and it is a string, convert the value to be an
13847        //		array of values.
13848
13849        // Skip it if there is no value
13850        if(value === null){
13851            return;
13852        }
13853
13854        var val = obj[name];
13855        if(typeof val == "string"){ // inline'd type check
13856            obj[name] = [val, value];
13857        }else if(lang.isArray(val)){
13858            val.push(value);
13859        }else{
13860            obj[name] = value;
13861        }
13862    }
13863
13864	var exclude = "file|submit|image|reset|button";
13865
13866	var form = {
13867		// summary:
13868		//		This module defines form-processing functions.
13869
13870		fieldToObject: function fieldToObject(/*DOMNode|String*/ inputNode){
13871			// summary:
13872			//		Serialize a form field to a JavaScript object.
13873			// description:
13874			//		Returns the value encoded in a form field as
vendor: 4,148 bytes, lines 13875-14003
13875			//		as a string or an array of strings. Disabled form elements
13876			//		and unchecked radio and checkboxes are skipped.	Multi-select
13877			//		elements are returned as an array of string values.
13878			// inputNode: DOMNode|String
13879			// returns: Object
13880
13881			var ret = null;
13882			inputNode = dom.byId(inputNode);
13883			if(inputNode){
13884				var _in = inputNode.name, type = (inputNode.type || "").toLowerCase();
13885				if(_in && type && !inputNode.disabled){
13886					if(type == "radio" || type == "checkbox"){
13887						if(inputNode.checked){
13888							ret = inputNode.value;
13889						}
13890					}else if(inputNode.multiple){
13891						ret = [];
13892						var nodes = [inputNode.firstChild];
13893						while(nodes.length){
13894							for(var node = nodes.pop(); node; node = node.nextSibling){
13895								if(node.nodeType == 1 && node.tagName.toLowerCase() == "option"){
13896									if(node.selected){
13897										ret.push(node.value);
13898									}
13899								}else{
13900									if(node.nextSibling){
13901										nodes.push(node.nextSibling);
13902									}
13903									if(node.firstChild){
13904										nodes.push(node.firstChild);
13905									}
13906									break;
13907								}
13908							}
13909						}
13910					}else{
13911						ret = inputNode.value;
13912					}
13913				}
13914			}
13915			return ret; // Object
13916		},
13917
13918		toObject: function formToObject(/*DOMNode|String*/ formNode){
13919			// summary:
13920			//		Serialize a form node to a JavaScript object.
13921			// description:
13922			//		Returns the values encoded in an HTML form as
13923			//		string properties in an object which it then returns. Disabled form
13924			//		elements, buttons, and other non-value form elements are skipped.
13925			//		Multi-select elements are returned as an array of string values.
13926			// formNode: DOMNode|String
13927			// example:
13928			//		This form:
13929			//		|	<form id="test_form">
13930			//		|		<input type="text" name="blah" value="blah">
13931			//		|		<input type="text" name="no_value" value="blah" disabled>
13932			//		|		<input type="button" name="no_value2" value="blah">
13933			//		|		<select type="select" multiple name="multi" size="5">
13934			//		|			<option value="blah">blah</option>
13935			//		|			<option value="thud" selected>thud</option>
13936			//		|			<option value="thonk" selected>thonk</option>
13937			//		|		</select>
13938			//		|	</form>
13939			//
13940			//		yields this object structure as the result of a call to
13941			//		formToObject():
13942			//
13943			//		|	{
13944			//		|		blah: "blah",
13945			//		|		multi: [
13946			//		|			"thud",
13947			//		|			"thonk"
13948			//		|		]
13949			//		|	};
13950
13951			var ret = {}, elems = dom.byId(formNode).elements;
13952			for(var i = 0, l = elems.length; i < l; ++i){
13953				var item = elems[i], _in = item.name, type = (item.type || "").toLowerCase();
13954				if(_in && type && exclude.indexOf(type) < 0 && !item.disabled){
13955					setValue(ret, _in, form.fieldToObject(item));
13956					if(type == "image"){
13957						ret[_in + ".x"] = ret[_in + ".y"] = ret[_in].x = ret[_in].y = 0;
13958					}
13959				}
13960			}
13961			return ret; // Object
13962		},
13963
13964		toQuery: function formToQuery(/*DOMNode|String*/ formNode){
13965			// summary:
13966			//		Returns a URL-encoded string representing the form passed as either a
13967			//		node or string ID identifying the form to serialize
13968			// formNode: DOMNode|String
13969			// returns: String
13970
13971			return ioq.objectToQuery(form.toObject(formNode)); // String
13972		},
13973
13974		toJson: function formToJson(/*DOMNode|String*/ formNode, /*Boolean?*/ prettyPrint){
13975			// summary:
13976			//		Create a serialized JSON string from a form node or string
13977			//		ID identifying the form to serialize
13978			// formNode: DOMNode|String
13979			// prettyPrint: Boolean?
13980			// returns: String
13981
13982			return json.stringify(form.toObject(formNode), null, prettyPrint ? 4 : 0); // String
13983		}
13984	};
13985
13986    return form;
13987});
13988
13989},
13990'dojo/request/watch':function(){
13991define([
13992	'./util',
13993	'../errors/RequestTimeoutError',
13994	'../errors/CancelError',
13995	'../_base/array',
13996	'../_base/window',
13997	'../has!host-browser?dom-addeventlistener?:../on:'
13998], function(util, RequestTimeoutError, CancelError, array, win, on){
13999	// avoid setting a timer per request. It degrades performance on IE
14000	// something fierece if we don't use unified loops.
14001	var _inFlightIntvl = null,
14002		_inFlight = [];
14003
14004	function watchInFlight(){
14005		// summary:
14006		//		internal method that checks each inflight XMLHttpRequest to see
14007		//		if it has completed or if the timeout situation applies.
14008
14009		var now = +(new Date);
14010
14011		// we need manual loop because we often modify _inFlight (and therefore 'i') while iterating
14012		for(var i = 0, dfd; i < _inFlight.length && (dfd = _inFlight[i]); i++){
14013			var response = dfd.response,
14014				options = response.options;
14015			if((dfd.isCanceled && dfd.isCanceled()) || (dfd.isValid && !dfd.isValid(response))){
14016				_inFlight.splice(i--, 1);
14017				watch._onAction && watch._onAction();
14018			}else if(dfd.isReady && dfd.isReady(response)){
14019				_inFlight.splice(i--, 1);
14020				dfd.handleResponse(response);
14021				watch._onAction && watch._onAction();
14022			}else if(dfd.startTime){
14023				// did we timeout?
14024				if(dfd.startTime + (options.timeout || 0) < now){
14025					_inFlight.splice(i--, 1);
14026					// Cancel the request so the io module can do appropriate cleanup.
14027					dfd.cancel(new RequestTimeoutError('Timeout exceeded', response));
14028					watch._onAction && watch._onAction();
14029				}
14030			}
14031		}
14032
14033		watch._onInFlight && watch._onInFlight(dfd);
14034
14035		if(!_inFlight.length){
14036			clearInterval(_inFlightIntvl);
14037			_inFlightIntvl = null;
14038		}
14039	}
14040
14041	function watch(dfd){
14042		// summary:
14043		//		Watches the io request represented by dfd to see if it completes.
14044		// dfd: Deferred
14045		//		The Deferred object to watch.
14046		// response: Object
14047		//		The object used as the value of the request promise.
14048		// validCheck: Function
14049		//		Function used to check if the IO request is still valid. Gets the dfd
14050		//		object as its only argument.
14051		// ioCheck: Function
14052		//		Function used to check if basic IO call worked. Gets the dfd
14053		//		object as its only argument.
14054		// resHandle: Function
14055		//		Function used to process response. Gets the dfd
14056		//		object as its only argument.
14057		if(dfd.response.options.timeout){
14058			dfd.startTime = +(new Date);
14059		}
14060
14061		if(dfd.isFulfilled()){
14062			// bail out if the deferred is already fulfilled
14063			return;
14064		}
14065
14066		_inFlight.push(dfd);
14067		if(!_inFlightIntvl){
14068			_inFlightIntvl = setInterval(watchInFlight, 50);
14069		}
14070
14071		// handle sync requests separately from async:
14072		// http://bugs.dojotoolkit.org/ticket/8467
14073		if(dfd.response.options.sync){
14074			watchInFlight();
14075		}
14076	}
14077
14078	watch.cancelAll = function cancelAll(){
14079		// summary:
14080		//		Cancels all pending IO requests, regardless of IO type
14081		try{
14082			array.forEach(_inFlight, function(dfd){
14083				try{
14084					dfd.cancel(new CancelError('All requests canceled.'));
14085				}catch(e){}
14086			});
14087		}catch(e){}
14088	};
14089
14090	if(win && on && win.doc.attachEvent){
14091		// Automatically call cancel all io calls on unload in IE
14092		// http://bugs.dojotoolkit.org/ticket/2357
14093		on(win.global, 'unload', function(){
14094			watch.cancelAll();
14095		});
14096	}
14097
14098	return watch;
14099});
14100
14101},
14102'dojo/request/util':function(){
14103define([
14104	'exports',
14105	'../errors/RequestError',
14106	'../errors/CancelError',
14107	'../Deferred',
14108	'../io-query',
14109	'../_base/array',
14110	'../_base/lang',
14111	'../promise/Promise'
14112], function(exports, RequestError, CancelError, Deferred, ioQuery, array, lang, Promise){
14113	exports.deepCopy = function deepCopy(target, source){
14114		for(var name in source){
14115			var tval = target[name],
14116				sval = source[name];
14117			if(tval !== sval){
14118				if(tval && typeof tval === 'object' && sval && typeof sval === 'object'){
14119					exports.deepCopy(tval, sval);
14120				}else{
14121					target[name] = sval;
14122				}
14123			}
14124		}
14125		return target;
14126	};
14127
14128	exports.deepCreate = function deepCreate(source, properties){
14129		properties = properties || {};
14130		var target = lang.delegate(source),
14131			name, value;
14132
14133		for(name in source){
14134			value = source[name];
14135
14136			if(value && typeof value === 'object'){
14137				target[name] = exports.deepCreate(value, properties[name]);
14138			}
14139		}
14140		return exports.deepCopy(target, properties);
14141	};
14142
14143	var freeze = Object.freeze || function(obj){ return obj; };
14144	function okHandler(response){
14145		return freeze(response);
14146	}
14147	function dataHandler (response) {
14148		return response.data || response.text;
14149	}
14150
14151	exports.deferred = function deferred(response, cancel, isValid, isReady, handleResponse, last){
14152		var def = new Deferred(function(reason){
14153			cancel && cancel(def, response);
14154
14155			if(!reason || !(reason instanceof RequestError) && !(reason instanceof CancelError)){
14156				return new CancelError('Request canceled', response);
14157			}
14158			return reason;
14159		});
14160
14161		def.response = response;
14162		def.isValid = isValid;
14163		def.isReady = isReady;
14164		def.handleResponse = handleResponse;
14165
14166		function errHandler(error){
14167			error.response = response;
14168			throw error;
14169		}
14170		var responsePromise = def.then(okHandler).otherwise(errHandler);
14171
14172		if(exports.notify){
14173			responsePromise.then(
14174				lang.hitch(exports.notify, 'emit', 'load'),
14175				lang.hitch(exports.notify, 'emit', 'error')
14176			);
14177		}
14178
14179		var dataPromise = responsePromise.then(dataHandler);
14180
14181		// http://bugs.dojotoolkit.org/ticket/16794
14182		// The following works around a leak in IE9 through the
14183		// prototype using lang.delegate on dataPromise and
14184		// assigning the result a property with a reference to
14185		// responsePromise.
14186		var promise = new Promise();
14187		for (var prop in dataPromise) {
14188			if (dataPromise.hasOwnProperty(prop)) {
14189				promise[prop] = dataPromise[prop];
14190			}
14191		}
14192		promise.response = responsePromise;
14193		freeze(promise);
14194		// End leak fix
14195
14196
14197		if(last){
14198			def.then(function(response){
14199				last.call(def, response);
14200			}, function(error){
14201				last.call(def, response, error);
14202			});
14203		}
14204
14205		def.promise = promise;
14206		def.then = promise.then;
14207
14208		return def;
14209	};
14210
14211	exports.addCommonMethods = function addCommonMethods(provider, methods){
14212		array.forEach(methods||['GET', 'POST', 'PUT', 'DELETE'], function(method){
14213			provider[(method === 'DELETE' ? 'DEL' : method).toLowerCase()] = function(url, options){
14214				options = lang.delegate(options||{});
14215				options.method = method;
14216				return provider(url, options);
14217			};
14218		});
14219	};
14220
14221	exports.parseArgs = function parseArgs(url, options, skipData){
14222		var data = options.data,
14223			query = options.query;
14224		
14225		if(data && !skipData){
14226			if(typeof data === 'object'){
14227				options.data = ioQuery.objectToQuery(data);
14228			}
14229		}
14230
14231		if(query){
14232			if(typeof query === 'object'){
14233				query = ioQuery.objectToQuery(query);
14234			}
14235			if(options.preventCache){
14236				query += (query ? '&' : '') + 'request.preventCache=' + (+(new Date));
14237			}
14238		}else if(options.preventCache){
14239			query = 'request.preventCache=' + (+(new Date));
14240		}
14241
14242		if(url && query){
14243			url += (~url.indexOf('?') ? '&' : '?') + query;
14244		}
14245
14246		return {
14247			url: url,
14248			options: options,
14249			getHeader: function(headerName){ return null; }
14250		};
14251	};
14252
14253	exports.checkStatus = function(stat){
14254		stat = stat || 0;
14255		return (stat >= 200 && stat < 300) || // allow any 2XX response code
14256			stat === 304 ||                 // or, get it out of the cache
14257			stat === 1223 ||                // or, Internet Explorer mangled the status code
14258			!stat;                         // or, we're Titanium/browser chrome/chrome extension requesting a local file
14259	};
14260});
14261
14262},
14263'dojo/errors/RequestError':function(){
14264define(['./create'], function(create){
14265	// module:
14266	//		dojo/errors/RequestError
14267
14268	/*=====
14269	 return function(){
14270		 // summary:
14271		 //		TODOC
14272	 };
14273	 =====*/
14274
14275	return create("RequestError", function(message, response){
14276		this.response = response;
14277	});
14278});
14279
14280},
14281'dojo/errors/RequestTimeoutError':function(){
14282define(['./create', './RequestError'], function(create, RequestError){
14283	// module:
14284	//		dojo/errors/RequestTimeoutError
14285
14286	/*=====
14287	 return function(){
14288		 // summary:
14289		 //		TODOC
14290	 };
14291	 =====*/
14292
14293	return create("RequestTimeoutError", null, RequestError, {
14294		dojoType: "timeout"
14295	});
14296});
14297
14298},
14299'dojo/request/xhr':function(){
14300define([
14301	'../errors/RequestError',
14302	'./watch',
14303	'./handlers',
14304	'./util',
14305	'../has'/*=====,
14306	'../request',
14307	'../_base/declare' =====*/
14308], function(RequestError, watch, handlers, util, has/*=====, request, declare =====*/){
14309	has.add('native-xhr', function(){
14310		// if true, the environment has a native XHR implementation
14311		return typeof XMLHttpRequest !== 'undefined';
14312	});
14313	has.add('dojo-force-activex-xhr', function(){
14314		return has('activex') && !document.addEventListener && window.location.protocol === 'file:';
14315	});
14316
14317	has.add('native-xhr2', function(){
14318		if(!has('native-xhr')){ return; }
14319		var x = new XMLHttpRequest();
14320		return typeof x['addEventListener'] !== 'undefined' &&
14321			(typeof opera === 'undefined' || typeof x['upload'] !== 'undefined');
14322	});
14323
14324	has.add('native-formdata', function(){
14325		// if true, the environment has a native FormData implementation
14326		return typeof FormData !== 'undefined';
14327	});
14328
14329	has.add('native-response-type', function(){
14330		return has('native-xhr') && typeof new XMLHttpRequest().responseType !== 'undefined';
14331	});
14332
14333	has.add('native-xhr2-blob', function(){
14334		if(!has('native-response-type')){ return; }
14335		var x = new XMLHttpRequest();
14336		x.open('GET', '/', true);
14337		x.responseType = 'blob';
14338		// will not be set if unsupported
14339		var responseType = x.responseType;
14340		x.abort();
14341		return responseType === 'blob';
14342	});
14343
14344	// Google Chrome doesn't support "json" response type
14345	// up to version 30, so it's intentionally not included here
14346	var nativeResponseTypes = {
14347		'blob': has('native-xhr2-blob') ? 'blob' : 'arraybuffer',
14348		'document': 'document',
14349		'arraybuffer': 'arraybuffer'
14350	};
14351
14352	function handleResponse(response, error){
14353		var _xhr = response.xhr;
14354		response.status = response.xhr.status;
14355
14356		try {
14357			// Firefox throws an error when trying to access
14358			// xhr.responseText if response isn't text
14359			response.text = _xhr.responseText;
14360		} catch (e) {}
14361
14362		if(response.options.handleAs === 'xml'){
14363			response.data = _xhr.responseXML;
14364		}
14365
14366		if(!error){
14367			try{
14368				handlers(response);
14369			}catch(e){
14370				error = e;
14371			}
14372		}
14373
14374		if(error){
14375			this.reject(error);
14376		}else if(util.checkStatus(_xhr.status)){
14377			this.resolve(response);
14378		}else{
14379			error = new RequestError('Unable to load ' + response.url + ' status: ' + _xhr.status, response);
14380
14381			this.reject(error);
14382		}
14383	}
14384
14385	var isValid, isReady, addListeners, cancel;
14386	if(has('native-xhr2')){
14387		// Any platform with XHR2 will only use the watch mechanism for timeout.
14388
14389		isValid = function(response){
14390			// summary:
14391			//		Check to see if the request should be taken out of the watch queue
14392			return !this.isFulfilled();
14393		};
14394		cancel = function(dfd, response){
14395			// summary:
14396			//		Canceler for deferred
14397			response.xhr.abort();
14398		};
14399		addListeners = function(_xhr, dfd, response){
14400			// summary:
14401			//		Adds event listeners to the XMLHttpRequest object
14402			function onLoad(evt){
14403				dfd.handleResponse(response);
14404			}
14405			function onError(evt){
14406				var _xhr = evt.target;
14407				var error = new RequestError('Unable to load ' + response.url + ' status: ' + _xhr.status, response);
14408				dfd.handleResponse(response, error);
14409			}
14410
14411			function onProgress(evt){
14412				if(evt.lengthComputable){
14413					response.loaded = evt.loaded;
14414					response.total = evt.total;
14415					dfd.progress(response);
14416				} else if(response.xhr.readyState === 3){
14417					response.loaded = evt.position;
14418					dfd.progress(response);
14419				}
14420			}
14421
14422			_xhr.addEventListener('load', onLoad, false);
14423			_xhr.addEventListener('error', onError, false);
14424			_xhr.addEventListener('progress', onProgress, false);
14425
14426			return function(){
14427				_xhr.removeEventListener('load', onLoad, false);
14428				_xhr.removeEventListener('error', onError, false);
14429				_xhr.removeEventListener('progress', onProgress, false);
14430				_xhr = null;
14431			};
14432		};
14433	}else{
14434		isValid = function(response){
14435			return response.xhr.readyState; //boolean
14436		};
14437		isReady = function(response){
14438			return 4 === response.xhr.readyState; //boolean
14439		};
14440		cancel = function(dfd, response){
14441			// summary:
14442			//		canceller function for util.deferred call.
14443			var xhr = response.xhr;
14444			var _at = typeof xhr.abort;
14445			if(_at === 'function' || _at === 'object' || _at === 'unknown'){
14446				xhr.abort();
14447			}
14448		};
14449	}
14450
14451	function getHeader(headerName){
14452		return this.xhr.getResponseHeader(headerName);
14453	}
14454
14455	var undefined,
14456		defaultOptions = {
14457			data: null,
14458			query: null,
14459			sync: false,
14460			method: 'GET'
14461		};
14462	function xhr(url, options, returnDeferred){
14463		var isFormData = has('native-formdata') && options && options.data && options.data instanceof FormData;
14464		var response = util.parseArgs(
14465			url,
14466			util.deepCreate(defaultOptions, options),
14467			isFormData
14468		);
14469		url = response.url;
14470		options = response.options;
14471
14472		var remover,
14473			last = function(){
14474				remover && remover();
14475			};
14476
14477		//Make the Deferred object for this xhr request.
14478		var dfd = util.deferred(
14479			response,
14480			cancel,
14481			isValid,
14482			isReady,
14483			handleResponse,
14484			last
14485		);
14486		var _xhr = response.xhr = xhr._create();
14487
14488		if(!_xhr){
14489			// If XHR factory somehow returns nothings,
14490			// cancel the deferred.
14491			dfd.cancel(new RequestError('XHR was not created'));
14492			return returnDeferred ? dfd : dfd.promise;
14493		}
14494
14495		response.getHeader = getHeader;
14496
14497		if(addListeners){
14498			remover = addListeners(_xhr, dfd, response);
14499		}
14500
14501		var data = options.data,
14502			async = !options.sync,
14503			method = options.method;
14504
14505		try{
14506			// IE6 won't let you call apply() on the native function.
14507			_xhr.open(method, url, async, options.user || undefined, options.password || undefined);
14508
14509			if(options.withCredentials){
14510				_xhr.withCredentials = options.withCredentials;
14511			}
14512
14513			if(has('native-response-type') && options.handleAs in nativeResponseTypes) {
14514				_xhr.responseType = nativeResponseTypes[options.handleAs];
14515			}
14516
14517			var headers = options.headers,
14518				contentType = isFormData ? false : 'application/x-www-form-urlencoded';
14519			if(headers){
14520				for(var hdr in headers){
14521					if(hdr.toLowerCase() === 'content-type'){
14522						contentType = headers[hdr];
14523					}else if(headers[hdr]){
14524						//Only add header if it has a value. This allows for instance, skipping
14525						//insertion of X-Requested-With by specifying empty value.
14526						_xhr.setRequestHeader(hdr, headers[hdr]);
14527					}
14528				}
14529			}
14530
14531			if(contentType && contentType !== false){
14532				_xhr.setRequestHeader('Content-Type', contentType);
14533			}
14534			if(!headers || !('X-Requested-With' in headers)){
14535				_xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
14536			}
14537
14538			if(util.notify){
14539				util.notify.emit('send', response, dfd.promise.cancel);
14540			}
14541			_xhr.send(data);
14542		}catch(e){
14543			dfd.reject(e);
14544		}
14545
14546		watch(dfd);
14547		_xhr = null;
14548
14549		return returnDeferred ? dfd : dfd.promise;
14550	}
14551
14552	/*=====
14553	xhr = function(url, options){
14554		// summary:
14555		//		Sends a request using XMLHttpRequest with the given URL and options.
14556		// url: String
14557		//		URL to request
14558		// options: dojo/request/xhr.__Options?
14559		//		Options for the request.
14560		// returns: dojo/request.__Promise
14561	};
14562	xhr.__BaseOptions = declare(request.__BaseOptions, {
14563		// sync: Boolean?
14564		//		Whether to make a synchronous request or not. Default
14565		//		is `false` (asynchronous).
14566		// data: String|Object|FormData?
14567		//		Data to transfer. This is ignored for GET and DELETE
14568		//		requests.
14569		// headers: Object?
14570		//		Headers to use for the request.
14571		// user: String?
14572		//		Username to use during the request.
14573		// password: String?
14574		//		Password to use during the request.
14575		// withCredentials: Boolean?
14576		//		For cross-site requests, whether to send credentials
14577		//		or not.
14578	});
14579	xhr.__MethodOptions = declare(null, {
14580		// method: String?
14581		//		The HTTP method to use to make the request. Must be
14582		//		uppercase. Default is `"GET"`.
14583	});
14584	xhr.__Options = declare([xhr.__BaseOptions, xhr.__MethodOptions]);
14585
14586	xhr.get = function(url, options){
14587		// summary:
14588		//		Send an HTTP GET request using XMLHttpRequest with the given URL and options.
14589		// url: String
14590		//		URL to request
14591		// options: dojo/request/xhr.__BaseOptions?
14592		//		Options for the request.
14593		// returns: dojo/request.__Promise
14594	};
14595	xhr.post = function(url, options){
14596		// summary:
14597		//		Send an HTTP POST request using XMLHttpRequest with the given URL and options.
14598		// url: String
14599		//		URL to request
14600		// options: dojo/request/xhr.__BaseOptions?
14601		//		Options for the request.
14602		// returns: dojo/request.__Promise
14603	};
14604	xhr.put = function(url, options){
14605		// summary:
14606		//		Send an HTTP PUT request using XMLHttpRequest with the given URL and options.
14607		// url: String
14608		//		URL to request
14609		// options: dojo/request/xhr.__BaseOptions?
14610		//		Options for the request.
14611		// returns: dojo/request.__Promise
14612	};
14613	xhr.del = function(url, options){
14614		// summary:
14615		//		Send an HTTP DELETE request using XMLHttpRequest with the given URL and options.
14616		// url: String
14617		//		URL to request
14618		// options: dojo/request/xhr.__BaseOptions?
14619		//		Options for the request.
14620		// returns: dojo/request.__Promise
14621	};
14622	=====*/
14623	xhr._create = function(){
14624		// summary:
14625		//		does the work of portably generating a new XMLHTTPRequest object.
14626		throw new Error('XMLHTTP not available');
14627	};
14628	if(has('native-xhr') && !has('dojo-force-activex-xhr')){
14629		xhr._create = function(){
14630			return new XMLHttpRequest();
14631		};
14632	}else if(has('activex')){
14633		try{
14634			new ActiveXObject('Msxml2.XMLHTTP');
14635			xhr._create = function(){
14636				return new ActiveXObject('Msxml2.XMLHTTP');
14637			};
14638		}catch(e){
14639			try{
14640				new ActiveXObject('Microsoft.XMLHTTP');
14641				xhr._create = function(){
14642					return new ActiveXObject('Microsoft.XMLHTTP');
14643				};
14644			}catch(e){}
14645		}
14646	}
14647
14648	util.addCommonMethods(xhr);
14649
14650	return xhr;
14651});
14652
14653},
14654'dojo/request/handlers':function(){
14655define([
14656	'../json',
14657	'../_base/kernel',
14658	'../_base/array',
14659	'../has',
14660	'../selector/_loader' // only included for has() qsa tests
14661], function(JSON, kernel, array, has){
14662	has.add('activex', typeof ActiveXObject !== 'undefined');
14663	has.add('dom-parser', function(global){
14664		return 'DOMParser' in global;
14665	});
14666
14667	var handleXML;
14668	if(has('activex')){
14669		// GUIDs obtained from http://msdn.microsoft.com/en-us/library/ms757837(VS.85).aspx
14670		var dp = [
14671			'Msxml2.DOMDocument.6.0',
14672			'Msxml2.DOMDocument.4.0',
14673			'MSXML2.DOMDocument.3.0',
14674			'MSXML.DOMDocument' // 2.0
14675		];
14676		var lastParser;
14677
14678		handleXML = function(response){
14679			var result = response.data;
14680			var text = response.text;
14681
14682			if(result && has('dom-qsa2.1') && !result.querySelectorAll && has('dom-parser')){
14683				// http://bugs.dojotoolkit.org/ticket/15631
14684				// IE9 supports a CSS3 querySelectorAll implementation, but the DOM implementation
14685				// returned by IE9 xhr.responseXML does not. Manually create the XML DOM to gain
14686				// the fuller-featured implementation and avoid bugs caused by the inconsistency
14687				result = new DOMParser().parseFromString(text, 'application/xml');
14688			}
14689
14690			function createDocument(p) {
14691					try{
14692						var dom = new ActiveXObject(p);
14693						dom.async = false;
14694						dom.loadXML(text);
14695						result = dom;
14696						lastParser = p;
14697					}catch(e){ return false; }
14698					return true;
14699			}
14700
14701			if(!result || !result.documentElement){
14702				// The creation of an ActiveX object is expensive, so we cache the
14703				// parser type to avoid trying all parser types each time we handle a
14704				// document. There is some concern that some parser types might fail
14705				// depending on the document being parsed. If parsing using the cached
14706				// parser type fails, we do the more expensive operation of finding one
14707				// that works for the given document.
14708				// https://bugs.dojotoolkit.org/ticket/15246
14709				if(!lastParser || !createDocument(lastParser)) {
14710					array.some(dp, createDocument);
14711				}
14712			}
14713
14714			return result;
14715		};
14716	}
14717
14718	var handleNativeResponse = function(response) {
14719		if(!has('native-xhr2-blob') && response.options.handleAs === 'blob' && typeof Blob !== 'undefined'){
14720			return new Blob([ response.xhr.response ], { type: response.xhr.getResponseHeader('Content-Type') });
14721		}
14722
14723		return response.xhr.response;
14724	}
14725
14726	var handlers = {
14727		'javascript': function(response){
14728			return kernel.eval(response.text || '');
14729		},
14730		'json': function(response){
14731			return JSON.parse(response.text || null);
14732		},
14733		'xml': handleXML,
14734		'blob': handleNativeResponse,
14735		'arraybuffer': handleNativeResponse,
14736		'document': handleNativeResponse
14737	};
14738
14739	function handle(response){
14740		var handler = handlers[response.options.handleAs];
14741
14742		response.data = handler ? handler(response) : (response.data || response.text);
14743
14744		return response;
14745	}
14746
14747	handle.register = function(name, handler){
14748		handlers[name] = handler;
14749	};
14750
14751	return handle;
14752});
14753
14754},
14755'dojo/_base/fx':function(){
14756define(["./kernel", "./config", /*===== "./declare", =====*/ "./lang", "../Evented", "./Color", "../aspect", "../sniff", "../dom", "../dom-style"],
14757	function(dojo, config, /*===== declare, =====*/ lang, Evented, Color, aspect, has, dom, style){
14758	// module:
14759	//		dojo/_base/fx
14760	// notes:
14761	//		Animation loosely package based on Dan Pupius' work, contributed under CLA; see
14762	//		http://pupius.co.uk/js/Toolkit.Drawing.js
14763
14764	var _mixin = lang.mixin;
14765
14766	// Module export
14767	var basefx = {
14768		// summary:
14769		//		This module defines the base dojo/_base/fx implementation.
14770	};
14771
14772	var _Line = basefx._Line = function(/*int*/ start, /*int*/ end){
14773		// summary:
14774		//		Object used to generate values from a start value to an end value
14775		// start: int
14776		//		Beginning value for range
14777		// end: int
14778		//		Ending value for range
14779		this.start = start;
14780		this.end = end;
14781	};
14782
14783	_Line.prototype.getValue = function(/*float*/ n){
14784		// summary:
14785		//		Returns the point on the line
14786		// n:
14787		//		a floating point number greater than 0 and less than 1
14788		return ((this.end - this.start) * n) + this.start; // Decimal
14789	};
14790
14791	var Animation = basefx.Animation = function(args){
14792		// summary:
14793		//		A generic animation class that fires callbacks into its handlers
14794		//		object at various states.
14795		// description:
14796		//		A generic animation class that fires callbacks into its handlers
14797		//		object at various states. Nearly all dojo animation functions
14798		//		return an instance of this method, usually without calling the
14799		//		.play() method beforehand. Therefore, you will likely need to
14800		//		call .play() on instances of `Animation` when one is
14801		//		returned.
14802		// args: Object
14803		//		The 'magic argument', mixing all the properties into this
14804		//		animation instance.
14805
14806		_mixin(this, args);
14807		if(lang.isArray(this.curve)){
14808			this.curve = new _Line(this.curve[0], this.curve[1]);
14809		}
14810
14811	};
14812	Animation.prototype = new Evented();
14813
14814	lang.extend(Animation, {
14815		// duration: Integer
14816		//		The time in milliseconds the animation will take to run
14817		duration: 350,
14818
14819	/*=====
14820		// curve: _Line|Array
14821		//		A two element array of start and end values, or a `_Line` instance to be
14822		//		used in the Animation.
14823		curve: null,
14824
14825		// easing: Function?
14826		//		A Function to adjust the acceleration (or deceleration) of the progress
14827		//		across a _Line
14828		easing: null,
14829	=====*/
14830
14831		// repeat: Integer?
14832		//		The number of times to loop the animation
14833		repeat: 0,
14834
14835		// rate: Integer?
14836		//		the time in milliseconds to wait before advancing to next frame
14837		//		(used as a fps timer: 1000/rate = fps)
14838		rate: 20 /* 50 fps */,
14839
14840	/*=====
14841		// delay: Integer?
14842		//		The time in milliseconds to wait before starting animation after it
14843		//		has been .play()'ed
14844		delay: null,
14845
14846		// beforeBegin: Event?
14847		//		Synthetic event fired before a Animation begins playing (synchronous)
14848		beforeBegin: null,
14849
14850		// onBegin: Event?
14851		//		Synthetic event fired as a Animation begins playing (useful?)
14852		onBegin: null,
14853
14854		// onAnimate: Event?
14855		//		Synthetic event fired at each interval of the Animation
14856		onAnimate: null,
14857
14858		// onEnd: Event?
14859		//		Synthetic event fired after the final frame of the Animation
14860		onEnd: null,
14861
14862		// onPlay: Event?
14863		//		Synthetic event fired any time the Animation is play()'ed
14864		onPlay: null,
14865
14866		// onPause: Event?
14867		//		Synthetic event fired when the Animation is paused
14868		onPause: null,
14869
14870		// onStop: Event
14871		//		Synthetic event fires when the Animation is stopped
14872		onStop: null,
14873
14874	=====*/
14875
14876		_percent: 0,
14877		_startRepeatCount: 0,
14878
14879		_getStep: function(){
14880			var _p = this._percent,
14881				_e = this.easing
14882			;
14883			return _e ? _e(_p) : _p;
14884		},
14885		_fire: function(/*Event*/ evt, /*Array?*/ args){
14886			// summary:
14887			//		Convenience function.  Fire event "evt" and pass it the
14888			//		arguments specified in "args".
14889			// description:
14890			//		Convenience function.  Fire event "evt" and pass it the
14891			//		arguments specified in "args".
14892			//		Fires the callback in the scope of this Animation
14893			//		instance.
14894			// evt:
14895			//		The event to fire.
14896			// args:
14897			//		The arguments to pass to the event.
14898			var a = args||[];
14899			if(this[evt]){
14900				if(config.debugAtAllCosts){
14901					this[evt].apply(this, a);
14902				}else{
14903					try{
14904						this[evt].apply(this, a);
14905					}catch(e){
14906						// squelch and log because we shouldn't allow exceptions in
14907						// synthetic event handlers to cause the internal timer to run
14908						// amuck, potentially pegging the CPU. I'm not a fan of this
14909						// squelch, but hopefully logging will make it clear what's
14910						// going on
14911						console.error("exception in animation handler for:", evt);
14912						console.error(e);
14913					}
14914				}
14915			}
14916			return this; // Animation
14917		},
14918
14919		play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
14920			// summary:
14921			//		Start the animation.
14922			// delay:
14923			//		How many milliseconds to delay before starting.
14924			// gotoStart:
14925			//		If true, starts the animation from the beginning; otherwise,
14926			//		starts it from its current position.
14927			// returns: Animation
14928			//		The instance to allow chaining.
14929
14930			var _t = this;
14931			if(_t._delayTimer){ _t._clearTimer(); }
14932			if(gotoStart){
14933				_t._stopTimer();
14934				_t._active = _t._paused = false;
14935				_t._percent = 0;
14936			}else if(_t._active && !_t._paused){
14937				return _t;
14938			}
14939
14940			_t._fire("beforeBegin", [_t.node]);
14941
14942			var de = delay || _t.delay,
14943				_p = lang.hitch(_t, "_play", gotoStart);
14944
14945			if(de > 0){
14946				_t._delayTimer = setTimeout(_p, de);
14947				return _t;
14948			}
14949			_p();
14950			return _t;	// Animation
14951		},
14952
14953		_play: function(gotoStart){
14954			var _t = this;
14955			if(_t._delayTimer){ _t._clearTimer(); }
14956			_t._startTime = new Date().valueOf();
14957			if(_t._paused){
14958				_t._startTime -= _t.duration * _t._percent;
14959			}
14960
14961			_t._active = true;
14962			_t._paused = false;
14963			var value = _t.curve.getValue(_t._getStep());
14964			if(!_t._percent){
14965				if(!_t._startRepeatCount){
14966					_t._startRepeatCount = _t.repeat;
14967				}
14968				_t._fire("onBegin", [value]);
14969			}
14970
14971			_t._fire("onPlay", [value]);
14972
14973			_t._cycle();
14974			return _t; // Animation
14975		},
14976
14977		pause: function(){
14978			// summary:
14979			//		Pauses a running animation.
14980			var _t = this;
14981			if(_t._delayTimer){ _t._clearTimer(); }
14982			_t._stopTimer();
14983			if(!_t._active){ return _t; /*Animation*/ }
14984			_t._paused = true;
14985			_t._fire("onPause", [_t.curve.getValue(_t._getStep())]);
14986			return _t; // Animation
14987		},
14988
14989		gotoPercent: function(/*Decimal*/ percent, /*Boolean?*/ andPlay){
14990			// summary:
14991			//		Sets the progress of the animation.
14992			// percent:
14993			//		A percentage in decimal notation (between and including 0.0 and 1.0).
14994			// andPlay:
14995			//		If true, play the animation after setting the progress.
14996			var _t = this;
14997			_t._stopTimer();
14998			_t._active = _t._paused = true;
14999			_t._percent = percent;
15000			if(andPlay){ _t.play(); }
15001			return _t; // Animation
15002		},
15003
15004		stop: function(/*boolean?*/ gotoEnd){
15005			// summary:
15006			//		Stops a running animation.
15007			// gotoEnd:
15008			//		If true, the animation will end.
15009			var _t = this;
15010			if(_t._delayTimer){ _t._clearTimer(); }
15011			if(!_t._timer){ return _t; /* Animation */ }
15012			_t._stopTimer();
15013			if(gotoEnd){
15014				_t._percent = 1;
15015			}
15016			_t._fire("onStop", [_t.curve.getValue(_t._getStep())]);
15017			_t._active = _t._paused = false;
15018			return _t; // Animation
15019		},
15020
15021		destroy: function(){
15022			// summary:
15023			//		cleanup the animation
15024			this.stop();
15025		},
15026
15027		status: function(){
15028			// summary:
15029			//		Returns a string token representation of the status of
15030			//		the animation, one of: "paused", "playing", "stopped"
15031			if(this._active){
15032				return this._paused ? "paused" : "playing"; // String
15033			}
15034			return "stopped"; // String
15035		},
15036
15037		_cycle: function(){
15038			var _t = this;
15039			if(_t._active){
15040				var curr = new Date().valueOf();
15041				// Allow durations of 0 (instant) by setting step to 1 - see #13798
15042				var step = _t.duration === 0 ? 1 : (curr - _t._startTime) / (_t.duration);
15043
15044				if(step >= 1){
15045					step = 1;
15046				}
15047				_t._percent = step;
15048
15049				// Perform easing
15050				if(_t.easing){
15051					step = _t.easing(step);
15052				}
15053
15054				_t._fire("onAnimate", [_t.curve.getValue(step)]);
15055
15056				if(_t._percent < 1){
15057					_t._startTimer();
15058				}else{
15059					_t._active = false;
15060
15061					if(_t.repeat > 0){
15062						_t.repeat--;
15063						_t.play(null, true);
15064					}else if(_t.repeat == -1){
15065						_t.play(null, true);
15066					}else{
15067						if(_t._startRepeatCount){
15068							_t.repeat = _t._startRepeatCount;
15069							_t._startRepeatCount = 0;
15070						}
15071					}
15072					_t._percent = 0;
15073					_t._fire("onEnd", [_t.node]);
15074					!_t.repeat && _t._stopTimer();
15075				}
15076			}
15077			return _t; // Animation
15078		},
15079
15080		_clearTimer: function(){
15081			// summary:
15082			//		Clear the play delay timer
15083			clearTimeout(this._delayTimer);
15084			delete this._delayTimer;
15085		}
15086
15087	});
15088
15089	// the local timer, stubbed into all Animation instances
15090	var ctr = 0,
15091		timer = null,
15092		runner = {
15093			run: function(){}
15094		};
15095
15096	lang.extend(Animation, {
15097
15098		_startTimer: function(){
15099			if(!this._timer){
15100				this._timer = aspect.after(runner, "run", lang.hitch(this, "_cycle"), true);
15101				ctr++;
15102			}
15103			if(!timer){
15104				timer = setInterval(lang.hitch(runner, "run"), this.rate);
15105			}
15106		},
15107
15108		_stopTimer: function(){
15109			if(this._timer){
15110				this._timer.remove();
15111				this._timer = null;
15112				ctr--;
15113			}
15114			if(ctr <= 0){
15115				clearInterval(timer);
15116				timer = null;
15117				ctr = 0;
15118			}
15119		}
15120
15121	});
15122
15123	var _makeFadeable =
15124		has("ie") ? function(node){
15125			// only set the zoom if the "tickle" value would be the same as the
15126			// default
15127			var ns = node.style;
15128			// don't set the width to auto if it didn't already cascade that way.
15129			// We don't want to f anyones designs
15130			if(!ns.width.length && style.get(node, "width") == "auto"){
15131				ns.width = "auto";
15132			}
15133		} :
15134		function(){};
15135
15136	basefx._fade = function(/*Object*/ args){
15137		// summary:
15138		//		Returns an animation that will fade the node defined by
15139		//		args.node from the start to end values passed (args.start
15140		//		args.end) (end is mandatory, start is optional)
15141
15142		args.node = dom.byId(args.node);
15143		var fArgs = _mixin({ properties: {} }, args),
15144			props = (fArgs.properties.opacity = {});
15145
15146		props.start = !("start" in fArgs) ?
15147			function(){
15148				return +style.get(fArgs.node, "opacity")||0;
15149			} : fArgs.start;
15150		props.end = fArgs.end;
15151
15152		var anim = basefx.animateProperty(fArgs);
15153		aspect.after(anim, "beforeBegin", lang.partial(_makeFadeable, fArgs.node), true);
15154
15155		return anim; // Animation
15156	};
15157
15158	/*=====
15159	var __FadeArgs = declare(null, {
15160		// node: DOMNode|String
15161		//		The node referenced in the animation
15162		// duration: Integer?
15163		//		Duration of the animation in milliseconds.
15164		// easing: Function?
15165		//		An easing function.
15166	});
15167	=====*/
15168
15169	basefx.fadeIn = function(/*__FadeArgs*/ args){
15170		// summary:
15171		//		Returns an animation that will fade node defined in 'args' from
15172		//		its current opacity to fully opaque.
15173		return basefx._fade(_mixin({ end: 1 }, args)); // Animation
15174	};
15175
15176	basefx.fadeOut = function(/*__FadeArgs*/ args){
15177		// summary:
15178		//		Returns an animation that will fade node defined in 'args'
15179		//		from its current opacity to fully transparent.
15180		return basefx._fade(_mixin({ end: 0 }, args)); // Animation
15181	};
15182
15183	basefx._defaultEasing = function(/*Decimal?*/ n){
15184		// summary:
15185		//		The default easing function for Animation(s)
15186		return 0.5 + ((Math.sin((n + 1.5) * Math.PI)) / 2);	// Decimal
15187	};
15188
15189	var PropLine = function(properties){
15190		// PropLine is an internal class which is used to model the values of
15191		// an a group of CSS properties across an animation lifecycle. In
15192		// particular, the "getValue" function handles getting interpolated
15193		// values between start and end for a particular CSS value.
15194		this._properties = properties;
15195		for(var p in properties){
15196			var prop = properties[p];
15197			if(prop.start instanceof Color){
15198				// create a reusable temp color object to keep intermediate results
15199				prop.tempColor = new Color();
15200			}
15201		}
15202	};
15203
15204	PropLine.prototype.getValue = function(r){
15205		var ret = {};
15206		for(var p in this._properties){
15207			var prop = this._properties[p],
15208				start = prop.start;
15209			if(start instanceof Color){
15210				ret[p] = Color.blendColors(start, prop.end, r, prop.tempColor).toCss();
15211			}else if(!lang.isArray(start)){
15212				ret[p] = ((prop.end - start) * r) + start + (p != "opacity" ? prop.units || "px" : 0);
15213			}
15214		}
15215		return ret;
15216	};
15217
15218	/*=====
15219	var __AnimArgs = declare(__FadeArgs, {
15220		// properties: Object?
15221		//		A hash map of style properties to Objects describing the transition,
15222		//		such as the properties of _Line with an additional 'units' property
15223		properties: {}
15224
15225		//TODOC: add event callbacks
15226	});
15227	=====*/
15228
15229	basefx.animateProperty = function(/*__AnimArgs*/ args){
15230		// summary:
15231		//		Returns an animation that will transition the properties of
15232		//		node defined in `args` depending how they are defined in
15233		//		`args.properties`
15234		//
15235		// description:
15236		//		Foundation of most `dojo/_base/fx`
15237		//		animations. It takes an object of "properties" corresponding to
15238		//		style properties, and animates them in parallel over a set
15239		//		duration.
15240		//
15241		// example:
15242		//		A simple animation that changes the width of the specified node.
15243		//	|	basefx.animateProperty({
15244		//	|		node: "nodeId",
15245		//	|		properties: { width: 400 },
15246		//	|	}).play();
15247		//		Dojo figures out the start value for the width and converts the
15248		//		integer specified for the width to the more expressive but
15249		//		verbose form `{ width: { end: '400', units: 'px' } }` which you
15250		//		can also specify directly. Defaults to 'px' if omitted.
15251		//
15252		// example:
15253		//		Animate width, height, and padding over 2 seconds... the
15254		//		pedantic way:
15255		//	|	basefx.animateProperty({ node: node, duration:2000,
15256		//	|		properties: {
15257		//	|			width: { start: '200', end: '400', units:"px" },
15258		//	|			height: { start:'200', end: '400', units:"px" },
15259		//	|			paddingTop: { start:'5', end:'50', units:"px" }
15260		//	|		}
15261		//	|	}).play();
15262		//		Note 'paddingTop' is used over 'padding-top'. Multi-name CSS properties
15263		//		are written using "mixed case", as the hyphen is illegal as an object key.
15264		//
15265		// example:
15266		//		Plug in a different easing function and register a callback for
15267		//		when the animation ends. Easing functions accept values between
15268		//		zero and one and return a value on that basis. In this case, an
15269		//		exponential-in curve.
15270		//	|	basefx.animateProperty({
15271		//	|		node: "nodeId",
15272		//	|		// dojo figures out the start value
15273		//	|		properties: { width: { end: 400 } },
15274		//	|		easing: function(n){
15275		//	|			return (n==0) ? 0 : Math.pow(2, 10 * (n - 1));
15276		//	|		},
15277		//	|		onEnd: function(node){
15278		//	|			// called when the animation finishes. The animation
15279		//	|			// target is passed to this function
15280		//	|		}
15281		//	|	}).play(500); // delay playing half a second
15282		//
15283		// example:
15284		//		Like all `Animation`s, animateProperty returns a handle to the
15285		//		Animation instance, which fires the events common to Dojo FX. Use `aspect.after`
15286		//		to access these events outside of the Animation definition:
15287		//	|	var anim = basefx.animateProperty({
15288		//	|		node:"someId",
15289		//	|		properties:{
15290		//	|			width:400, height:500
15291		//	|		}
15292		//	|	});
15293		//	|	aspect.after(anim, "onEnd", function(){
15294		//	|		console.log("animation ended");
15295		//	|	}, true);
15296		//	|	// play the animation now:
15297		//	|	anim.play();
15298		//
15299		// example:
15300		//		Each property can be a function whose return value is substituted along.
15301		//		Additionally, each measurement (eg: start, end) can be a function. The node
15302		//		reference is passed directly to callbacks.
15303		//	|	basefx.animateProperty({
15304		//	|		node:"mine",
15305		//	|		properties:{
15306		//	|			height:function(node){
15307		//	|				// shrink this node by 50%
15308		//	|				return domGeom.position(node).h / 2
15309		//	|			},
15310		//	|			width:{
15311		//	|				start:function(node){ return 100; },
15312		//	|				end:function(node){ return 200; }
15313		//	|			}
15314		//	|		}
15315		//	|	}).play();
15316		//
15317
15318		var n = args.node = dom.byId(args.node);
15319		if(!args.easing){ args.easing = dojo._defaultEasing; }
15320
15321		var anim = new Animation(args);
15322		aspect.after(anim, "beforeBegin", lang.hitch(anim, function(){
15323			var pm = {};
15324			for(var p in this.properties){
15325				// Make shallow copy of properties into pm because we overwrite
15326				// some values below. In particular if start/end are functions
15327				// we don't want to overwrite them or the functions won't be
15328				// called if the animation is reused.
15329				if(p == "width" || p == "height"){
15330					this.node.display = "block";
15331				}
15332				var prop = this.properties[p];
15333				if(lang.isFunction(prop)){
15334					prop = prop(n);
15335				}
15336				prop = pm[p] = _mixin({}, (lang.isObject(prop) ? prop: { end: prop }));
15337
15338				if(lang.isFunction(prop.start)){
15339					prop.start = prop.start(n);
15340				}
15341				if(lang.isFunction(prop.end)){
15342					prop.end = prop.end(n);
15343				}
15344				var isColor = (p.toLowerCase().indexOf("color") >= 0);
15345				function getStyle(node, p){
15346					// domStyle.get(node, "height") can return "auto" or "" on IE; this is more reliable:
15347					var v = { height: node.offsetHeight, width: node.offsetWidth }[p];
15348					if(v !== undefined){ return v; }
15349					v = style.get(node, p);
15350					return (p == "opacity") ? +v : (isColor ? v : parseFloat(v));
15351				}
15352				if(!("end" in prop)){
15353					prop.end = getStyle(n, p);
15354				}else if(!("start" in prop)){
15355					prop.start = getStyle(n, p);
15356				}
15357
15358				if(isColor){
15359					prop.start = new Color(prop.start);
15360					prop.end = new Color(prop.end);
15361				}else{
15362					prop.start = (p == "opacity") ? +prop.start : parseFloat(prop.start);
15363				}
15364			}
15365			this.curve = new PropLine(pm);
15366		}), true);
15367		aspect.after(anim, "onAnimate", lang.hitch(style, "set", anim.node), true);
15368		return anim; // Animation
15369	};
15370
15371	basefx.anim = function(	/*DOMNode|String*/	node,
15372							/*Object*/			properties,
15373							/*Integer?*/		duration,
15374							/*Function?*/		easing,
15375							/*Function?*/		onEnd,
15376							/*Integer?*/		delay){
15377		// summary:
15378		//		A simpler interface to `animateProperty()`, also returns
15379		//		an instance of `Animation` but begins the animation
15380		//		immediately, unlike nearly every other Dojo animation API.
15381		// description:
15382		//		Simpler (but somewhat less powerful) version
15383		//		of `animateProperty`.  It uses defaults for many basic properties
15384		//		and allows for positional parameters to be used in place of the
15385		//		packed "property bag" which is used for other Dojo animation
15386		//		methods.
15387		//
15388		//		The `Animation` object returned will be already playing, so
15389		//		calling play() on it again is (usually) a no-op.
15390		// node:
15391		//		a DOM node or the id of a node to animate CSS properties on
15392		// duration:
15393		//		The number of milliseconds over which the animation
15394		//		should run. Defaults to the global animation default duration
15395		//		(350ms).
15396		// easing:
15397		//		An easing function over which to calculate acceleration
15398		//		and deceleration of the animation through its duration.
15399		//		A default easing algorithm is provided, but you may
15400		//		plug in any you wish. A large selection of easing algorithms
15401		//		are available in `dojo/fx/easing`.
15402		// onEnd:
15403		//		A function to be called when the animation finishes
15404		//		running.
15405		// delay:
15406		//		The number of milliseconds to delay beginning the
15407		//		animation by. The default is 0.
15408		// example:
15409		//		Fade out a node
15410		//	|	basefx.anim("id", { opacity: 0 });
15411		// example:
15412		//		Fade out a node over a full second
15413		//	|	basefx.anim("id", { opacity: 0 }, 1000);
15414		return basefx.animateProperty({ // Animation
15415			node: node,
15416			duration: duration || Animation.prototype.duration,
15417			properties: properties,
15418			easing: easing,
15419			onEnd: onEnd
15420		}).play(delay || 0);
15421	};
15422
15423
15424	if( 1 ){
15425		_mixin(dojo, basefx);
15426		// Alias to drop come 2.0:
15427		dojo._Animation = Animation;
15428	}
15429
15430	return basefx;
15431});
15432
15433}}});
15434require({cache:{
15435'dpage/dpage':function(){
15436define([], 1);
15437
15438},
15439'dpage/modules/LegacyPlaceholder':function(){
15440define([
15441      "dojo/_base/declare"
15442      , "dojo/on"
15443      , "dojo/_base/event"
15444],
15445    function (declare, on, event) {
15446        var theClass = declare("dpage.modules.LegacyPlaceholder", [], {
15447            constructor: function (options) {
15448            }
15449
15450        });
15451
15452        //static method on the class.
15453        theClass.hasNativePlaceholderSupport = function () {
15454            if (theClass._hasNativeSupport == null) {
15455                var test = document.createElement('input');
15456                var nativeSupport = test.placeholder !== void 0;
15457
15458                theClass._hasNativeSupport = nativeSupport;
15459            }
15460            
15461            return theClass._hasNativeSupport;
15462        }
15463        return theClass;
15464    }
15465);
15466},
15467'dpage/modules/TabularModel':function(){
15468define([
15469      "dojo/_base/declare"
15470      , "dojo/on"
15471      , "dojo/_base/event"
15472
15473      , "dpage/modules/Model"
15474],
15475    function (declare, on, event) {
15476        /**
15477        * @namespace dpage
15478        */
15479        /**
15480        * @namespace modules
15481        * @memberOf dpage
15482        */
15483        /**
15484         * Class to provide controlled access to data. This class encapsulates a data structure that mirrors a flat list of columnar data (tabular data). Analogou
15484s
15485         * to a spreadsheet with rows and columns where each value corresponds to the text in each cell. If no model property and no modelProps property is passed
15486         * in, an empty model with a single column name of "default" is created.
15487         * @class TabularModel
15488         * @param {Object} [options] Optional options for the TabularModel. 
15489         * @param {Object} [options.model] Object containing the TabularData.
15490         * forms of the model property object:<br>
15491         * 1) {Columns : [ {DataType : "TEXT|NUMBER|DATE|BOOL" , ColumnName : "TheName"} , {nextColDef}],
15492         *     Rows : [ {TheName : "row1TheNameVal",...} , {TheName : "row2TheNameVal" , ...} , ...]<br>
15493         * <br/>
15494         * This format gives you more flexibility to provide data types and column names.
15495         * <br/><br/>
15496         * 2) [ {"Col1Name" : "Col1Row1Val" , ...} , {"Col1Name" : "Col1Row2Val" , ...} , ...]<br>
15497         * <br/>
15498         * This format cause the class to set the column names to the property names of the first object in the array. The default
15499         * DataType will be set to TEXT.
15500         * If you pass the modelProps object you can set the 
15501         * DataType property for the column name to NUMBER, DATE, BOOL, or TEXT.
15502         * <br/>
15503         * for example modelProps = {c1 : {DataType:"NUMBER"}}
15504         * <br/>
15505         * would set the DataType for column "c1" to NUMBER. This drives validation and column sorting in tables.
15506         * @param {Object} [options.modelProps] Optional properties describing the model including DataType, etc.
15507         *                                      Each property is the name of the column in the model. Each value
15508         *                                      is an object representing a collection of meta-data about the column.
15509         * @param {Object} [options.modelProps.colName]
15510         * @param {String} [options.modelProps.colName.ColumnName] Name of the field in the model (Deprecated).
15511         * @param {String} [options.modelProps.colName.DataType] NUMBER, BOOL, DATE, or TEXT
15512         * @param {String} [options.modelProps.colName.DisplayName] Value used for display of the field to the user.
15513         * @param {String} [options.modelProps.colName.FieldName] Name of the field in the model.
15514         * @param {Number} [options.modelProps.colName.MaxLength] Maximum character length.
15515         * @param {String} [options.modelProps.colName.MaxLengthValidationMessage] Message to display for MaxLength validation failure.
15516         * @param {Number} [options.modelProps.colName.MaxValue] Maximum value for NUMBER type.
15517         * @param {Number} [options.modelProps.colName.MinValue] Minimum value for NUMBER type.
15518         * @param {String} [options.modelProps.colName.NumberValidationMessage] Message to display if the number validation fails.
15519         * @param {Number} [options.modelProps.colName.NumDecimals] Maximum number of decimals for NUMBER type.
15520         * @param {bool}   [options.modelProps.colName.Required] Is a non-blank value required in this field
15521         * @param {String} [options.modelProps.colName.RequiredValidationMessage] Message to display for Required validation failure.
15522         * @param {String} [options.modelProps.colName.ValidationPattern] Javascript regular expression for input validation.
15523         * @param {String} [options.modelProps.colName.ValidationPatternMessage] Custom message to display if ValidationPattern fails.
15524         * @param {String} [options.modelProps.colName.ModificationTaintsModel] Default true. If explicitly set to false, changes to the value in this column will NOT taint the model. You can
15525         *                                                                      determine if the model is tainted by calling the isDirty() method. It will return true for tainted, false for not tainted.
15526         * @memberOf dpage.modules
15527         * @extends {dpage.modules.Model}
15528         */
15529        var theClass = declare("dpage.modules.TabularModel", [dpage.modules.Model], /** @lends dpage.modules.TabularModel.prototype */ {
15530            _model: null,
15531            _dataCallbacks: null,
15532            _lastDataCallbackId: 0,
15533            _dataCallbackRowId: 0,
15534            _modelProps: null,
15535            _colPropLookup:null,
15536            _isDirty: false,
15537            _supressSerialization : false,
15538
15539            constructor: function (options) {
15540                var self = this;
15541
15542                if (options == null || options.model == null) {
15543                    if (options != null && options.defaultColName != null) {
15544                        var row = {};
15545                        row[options.defaultColName] = "";
15546                        this._model = { Columns: [{ ColumnName: options.defaultColName, DataType: "TEXT" }], Rows: [] }; // an empty default model.
15547                        if (options != null && options.blankDataRow)
15548                            this._model.Rows.push(row);
15549                    }
15550                    else {
15551                        this._model = { Columns: [{ ColumnName: "default", DataType: "TEXT" }], Rows: [] }; // an empty default model.
15552                        if(options != null && options.blankDataRow)
15553                            this._model.Rows.push({ "default": "" });
15554                    }
15555                }
15556
15557                this._dataCallbacks = [];
15558                if (options != null)
15559                {
15560                    if (options.modelProps != null)
15561                        this._modelProps = options.modelProps;
15562
15563                    if (options.model != null) {
15564                        this._model = options.model;
15565                        this._validateModel();
15566                    }
15567                }
15568
15569                this._colPropLookup = {};
15570
15571                for(var i=0 ; i<this._model.Columns.length ; i++)
15572                {
15573                    this._colPropLookup[this._model.Columns[i].ColumnName] = this._model.Columns[i];
15574                    if (this._colPropLookup[this._model.Columns[i].ColumnName].ModificationTaintsModel === undefined)
15575                        this._colPropLookup[this._model.Columns[i].ColumnName].ModificationTaintsModel = true;
15576                }
15577            },
15578            /**
15579            * You can gain access to the underlying data by calling this method. Typically used for serialization routines.
15580            * Use at your own risk.
15581            * @return {Object} The raw data.
15582            */
15583            getRawModel: function ()
15584            {
15585                var hasObjectType = false;
15586                var newRows;
15587                var newRow;
15588                var oldRow;
15589
15590                for (var i = 0; i < this._model.Columns.length; i++)
15591                    if (this._model.Columns[i].DataType == "OBJECT")
15592                        hasObjectType = true;
15593
15594                if (hasObjectType) {
15595                    newRows = [];
15596
15597                    //iterate over the rows of the original model. Create a new row object for each one.
15598                    for (var ri = 0 ; ri < this._model.Rows.length ; ri++) {
15599                        oldRow = this._model.Rows[ri];
15600                        newRow = {};
15601                        //populate the row with data.
15602                        for (var i = 0; i < this._model.Columns.length; i++){
15603                            if (this._model.Columns[i].DataType == "OBJECT") {
15604                                if(oldRow[this._model.Columns[i].ColumnName] != null
15605                                    &&
15606                                   oldRow[this._model.Columns[i].ColumnName].isInstanceOf != null
15607                                    &&
15608                                   oldRow[this._model.Columns[i].ColumnName].isInstanceOf(dpage.modules.TabularModel)) {
15609                                    newRow[this._model.Columns[i].ColumnName] = oldRow[this._model.Columns[i].ColumnName].getRawModel();
15610                                }
15611                            }
15612                            else {
15613                                newRow[this._model.Columns[i].ColumnName] = oldRow[this._model.Columns[i].ColumnName];
15614                            }
15615                        }
15616                        newRows.push(newRow);
15617                    }
15618                    return newRows;
15619                    //wow, that was a lot of work!
15620                }
15621                else {
15622                    //much more efficient!
15623                    return this._model.Rows;
15624                }
15625                
15626            },
15627            /**
15628            * @return {Array.<Object>} An array of meta-data objects for each column. See the constructor argument options.modelProps for information 
15629            *                          on supported properties.
15630            */
15631            getColumns: function ()
15632            {
15633                return this._model.Columns;
15634            },
15635            /**
15636            * @param {String} columnName The column name to get info about.
15637            * @return {Object} A reference to the  meta-data object for the column in this model. See the constructor argument options.modelProps for information on supported properties.
15638            *                  Modifying the properties of the returned object causes the properties in the model to be changed as well. Use caution.
15639            */
15640            getColumnInfo: function (columnName)
15641            {
15642                for(var idx = 0; idx < this._model.Columns.length ; idx++)
15643                {
15644                    if (this._model.Columns[idx].ColumnName == columnName)
15645                        return this._model.Columns[idx];
15646                }
15647            },
15648            /**
15649            * Get the row of data from the TabularModel. Do NOT modify this row or its properties directly if you want things to work correctly.
15650            * @param {Number} rowIndex
15651            * @returns {Object} READ ONLY
15652            */
15653            getRow: function(rowIndex)
15654            {
15655                return this._model.Rows[rowIndex];
15656            },
15657            /**
15658            * You can gain direct access to the data by calling this method. Do not use this unless you know what you are doing.
15659            * Do not modify directly.
15660            * @return {Array.<Array>} Give you back an array of rows. Each row of the array is an array of column values.
15661            */
15662            getRows: function ()
15663            {
15664                return this._model.Rows;
15665            },
15666            /** Get a unique number identifier for the data row. This can be usefull for keeping track of the this row in lookups
15667            * @returns {Number} Unique number for the data row passed in (global to this model object).
15668            */
15669            getDataRowId: function (rowObj) {
15670                var rowId;
15671
15672                if (rowObj._getDataRowId == null) {
15673                    rowId = this._dataCallbackRowId++;
15674                    rowObj._getDataRowId = function () { return rowId; }
15675                }
15676                else {
15677                    rowId = rowObj._getDataRowId();
15678                }
15679
15680                return rowId;
15681            },
15682            /**
15683            * You can listen for changes to data by adding your callback routine here. Changes can be listened in on a row level
15684            * or global level only.
15685            * @param {function} funcRef The function to call when data is changed (added/updated/removed). The first parameter passed into the callback will be a string ("CHANGE" , "ADD" , "INS" , "DEL" , "INVALIDATE"), 
15686            *                           The second parameter will be the rowObject that the change was made on, and the third parameter will be the dataField that was changed in the event of a CHANGE.
15687            * @param {rowObj} [rowObj] Optional reference to a particular row. If passed in, the funcRef will only 
15688            * be called if that particular row is changed.
15689            * @returns {Number} The id of the callback. Can be used to remove the callback.
15690            */
15691            addDataCallback: function (funcRef, rowObj) {
15692                var rowId;
15693                var id = ++this._lastDataCallbackId;
15694
15695                //if we are only interested in a particular row, we can pass it in here.
15696                if (rowObj != null) {
15697                    //this is so that a subscriber can determine whether the row is the row they are bound to.
15698                    if (rowObj._getDataRowId == null) {
15699                        rowId = this._dataCallbackRowId++;
15700                        rowObj._getDataRowId = function () { return rowId; }
15701                    }
15702                    else
15703                        rowId = rowObj._getDataRowId();
15704                }
15705                else
15706                    rowId = null;
15707
15708                this._dataCallbacks.push({ id: id, func: funcRef , rowId : rowId});
15709
15710                return id;
15711            },
15712            /**
15713            * @param {Number} id The callback id to remove.
15714            * @returns {void}
15715            */
15716            removeDataCallback: function (id) {
15717                for (idx = 0; idx < this._dataCallbacks.length ; idx++)
15718                {
15719                    if(this._dataCallbacks[idx].id == id)
15720                        this._dataCallbacks.splice(idx , 1);
15721                }
15722            },
15723            /**
15724            * Set a value. The official way to set a value in a TabularModel. Will cause a "CHANGE" change type to be sent to registered callbacks ( callback("CHANGE" , rowObj , dataField) )
15725            * @param {Number} row The index of the row to set the value of (zero based).
15726            * @param {String} propName The property name (column name) to set.
15727            * @param {Object}
15727 value The value to set. Must be a bool, String, or Number
15728            * @returns {void}
15729            *//**
15730            * Set a value. The official way to set a value in a TabularModel. Will cause a "CHANGE" change type to be sent to registered callbacks ( callback("CHANGE" , rowObj , dataField) )
15731            * @param {Object} row The row object to set the value for.
15732            * @param {String} propName The property name (column name) to set.
15733            * @param {Object} value The value to set. Must be a bool, String, or Number
15734            * @returns {void}
15735            */
15736            setValue: function (row, propName, value) {
15737                var rowObj;
15738                var modificationTaints
15739
15740                if (typeof(row) === 'number' || row instanceof Number)
15741                    rowObj = this._model.Rows[row];
15742                else
15743                    rowObj = row;
15744
15745                rowObj[propName] = value;
15746
15747                //make sure that the column exists in the model properties and that we don't ignore it.
15748                if (this._colPropLookup[propName] !== undefined && this._colPropLookup[propName].ModificationTaintsModel)
15749                    this._isDirty = true;
15750
15751                this.doRowCallbacks(rowObj , propName);
15752            },
15753            /**
15754            * A caller can cause the registered callback routines to fire by calling this method directly. Not normally needed. 
15755            * This will cause the callback routines to be called even if data hasn't really been changed.
15756            * Only use this method if you know what you are doing.
15757            * @param {Array} rowObj The row that we want listeners notified of changes on.
15758            * @param {String} propName The name of the property (column name) that we want to notify listeners of
15759            */
15760            doRowCallbacks: function (rowObj, propName) {
15761                var rowHasId = rowObj._getDataRowId != null;
15762
15763                for (var x = 0; x < this._dataCallbacks.length ; x++) {
15764                    var callback = this._dataCallbacks[x].func;
15765                    if (this._dataCallbacks[x].rowId == null)
15766                        callback("CHANGE", rowObj, propName);
15767                    else if(rowHasId && rowObj._getDataRowId() == this._dataCallbacks[x].rowId)
15768                        callback("CHANGE", rowObj, propName);
15769                }
15770            },
15771            /**
15772            * The official way to get a value in a TabularModel.
15773            * @param {Number} row The zero-based row index.
15774            * @param {String} propName The property name (column name).
15775            * @returns {Object} The data. Will be String, Number, or Boolean
15776            *//**
15777            * The official way to get a value in a TabularModel.
15778            * @param {Object} row The row object to get the value of.
15779            * @param {String} propName The property name (column name).
15780            * @returns {Object} The data. Will be String, Number, or Boolean
15781            */
15782            getValue: function (row, propName)
15783            {
15784                var rowObj;
15785
15786                if (typeof (row) === 'number' || row instanceof Number)
15787                    rowObj = this._model.Rows[row];
15788                else
15789                    rowObj = row;
15790
15791                return rowObj[propName];
15792            },
15793            /**
15794            * The official way to set the rows. Will cause a "INVALIDATE" change type to be sent to registered callbacks ( callback("INVALIDATE") )
15795            * @param {Array} rows The row of data to add. Make sure that the number of columns match what is currently contained
15796            * in the model.
15797            * @returns {void}
15798            */
15799            setRows: function (rows) {
15800                this._model.Rows = rows
15801                var self = this;
15802
15803                this._isDirty = true;
15804
15805                for (var x = 0; x < this._dataCallbacks.length ; x++) {
15806                    var callback = this._dataCallbacks[x].func;
15807                    callback("INVALIDATE");
15808                }
15809            },
15810            /**
15811            * The official way to add a new row of data to a TabularModel. Adds the row to the end of the existing rows. Will cause a "ADD" change type to be sent to registered callbacks ( callback("ADD" , rowObj) )
15812            * @param {Object} rowObj The row of data to add. Make sure that the number of columns match what is currently contained
15813            * in the model.
15814            * @returns {void}
15815            */
15816            addRow: function (rowObj) {
15817                this._model.Rows.push(rowObj);
15818
15819                this._isDirty = true;
15820
15821                for (var x = 0; x < this._dataCallbacks.length ; x++)
15822                {
15823                    var callback = this._dataCallbacks[x].func;
15824                    callback("ADD", rowObj);
15825                }
15826            },
15827
15828            /**
15829            * The official way to delete a row of data from a TabularModel. Will cause a "DEL" change type to be sent to registered callbacks ( callback("DEL" , rowObj) )
15830            * @param {Number} row The row index to delete (zero-based)
15831            * @returns {void}
15832            *//**
15833            * The official way to delete a row of data from a TabularModel. Will cause a "DEL" change type to be sent to registered callbacks ( callback("DEL" , rowObj) )
15834            * @param {Object} row The rowObj to delete
15835            * @returns {void}
15836            */
15837            deleteRow: function (row) {
15838                var rowObj;
15839                var idx;
15840
15841                this._isDirty = true;
15842
15843                if (typeof (row) === 'number' || row instanceof Number) {
15844                    if (row >= this._model.Rows.length || row < 0)
15845                        throw new Error("Invalid row index");
15846                    idx = row;
15847                }
15848                else {
15849                    idx = null
15850                    for (var i = 0; i < this._model.Rows.length; i++)
15851                        if (this._model.Rows[i] === row)
15852                            idx = i;
15853                    if (idx == null)
15854                        throw new Error("Invalid row parameter of " + (row == null ? "null" : (row.toString() + " (" + typeof (row) + ")")));
15855                }
15856
15857                rowObj = this._model.Rows[idx];
15858
15859                this._model.Rows.splice(idx, 1);
15860
15861                for (var x = 0; x < this._dataCallbacks.length ; x++) {
15862                    var callback = this._dataCallbacks[x].func;
15863                    callback("DEL", rowObj);
15864                }
15865            },
15866            /**
15867            * The official way to insert a new row of data. The row can be inserted anyw
15867here, unlike the addRow, which adds
15868            * the row to the end of the data. Will cause a "INS" change type to be sent to registered callbacks ( callback("INS" , rowObj) )
15869            * @param {Object} rowObj The row to add.
15870            * @param {Number} idx The row index to add the row into (zero based)
15871            * @returns {void}
15872            */
15873            insertRow: function (rowObj, idx) {
15874                this._model.Rows.splice(idx, 0, rowObj);
15875
15876                this._isDirty = true;
15877
15878                for (var x = 0; x < this._dataCallbacks.length ; x++) {
15879                    var callback = this._dataCallbacks[x].func;
15880                    callback("INS", rowObj);
15881                }
15882            },
15883            /**
15884            * Has the data for the model been updated?
15885            * @returns {bool} true or false.
15886            */
15887            isDirty : function()
15888            {
15889                return this._isDirty;
15890            },
15891            setClean: function () {
15892                this._isDirty = false;
15893            },
15894            /**
15895            * Deletes all of the rows. Will cause an "INVALIDATE" change type to be sent to registered callbacks ( callback("INVALIDATE") ).
15896            * @returns {void}
15897            */
15898            clear : function()
15899            {
15900                this._model.Rows = [];
15901
15902                for (var x = 0; x < this._dataCallbacks.length ; x++) {
15903                    var callback = this._dataCallbacks[x].func;
15904                    callback("INVALIDATE");
15905                }
15906            },
15907            /**
15908            Widgets have a specific structure for a data model.
15909            @private
15910            */
15911            _validateModel: function () {
15912                var self = this;
15913
15914                if (this._model == null)
15915                    throw new Error("Model is null");
15916
15917                //turn a model comprised of just row data into one that has Columns and Rows.
15918                if (this._model instanceof Array)
15919                {
15920                    var modelRows = this._model;
15921                    this._model = {};
15922                    this._model.Rows = modelRows;
15923                    this._model.Columns = [];
15924
15925                    for(var k in this._model.Rows[0])
15926                    {
15927                        if(this._model.Rows[0].hasOwnProperty(k))
15928                        {
15929                            var col = { "DataType": "TEXT", "ColumnName": k };
15930
15931                            if (this._modelProps != null && this._modelProps[k] != null)
15932                            {
15933                                for(var l in this._modelProps[k])
15934                                {
15935                                    if (this._modelProps[k].hasOwnProperty(l))
15936                                        col[l] = this._modelProps[k][l];
15937                                }
15938                            }
15939
15940                            this._model.Columns.push(col);
15941                        }
15942                    }
15943
15944                    //add column definitions.
15945                    if(this._model.Columns.length ==0 && this._modelProps != null)
15946                    {
15947                        for (var k in this._modelProps) {
15948                            if (this._modelProps.hasOwnProperty(k)) {
15949                                this._model.Columns.push(this._modelProps[k]);
15950                            }
15951                        }
15952                    }
15953                }
15954
15955                if (this._model.Columns == null)
15956                    throw new Error("Model.Columns is null");
15957
15958                if (!this._model.Columns instanceof Array)
15959                    throw new Error("Model.Columns must be an array.");
15960
15961                for (var idx = 0; idx < this._model.Columns.length; idx++) {
15962                    if (this._model.Columns[idx].DataType == null
15963                        ||
15964                        this._model.Columns[idx].ColumnName == null) {
15965                        throw new Error("Each Model.Column must contain a DataType and a ColumnName property")
15966                    }
15967
15968                    if (this._model.Columns[idx].DataType != "TEXT"
15969                        && this._model.Columns[idx].DataType != "NUMBER"
15970                        && this._model.Columns[idx].DataType != "DATE"
15971                        && this._model.Columns[idx].DataType != "OBJECT"
15972                        && this._model.Columns[idx].DataType != "BOOL"
15973                        ) {
15974                        throw new Error("Model.Columns[" + idx + "].DataType must be either TEXT or NUMBER or DATE or BOOL or OBJECT");
15975                    }
15976
15977
15978                }
15979                if (this._model.Rows == undefined)
15980                    throw new Error("Model.Rows must be defined");
15981
15982                if (this._model.Rows != null && !this._model.Rows instanceof Array)
15983                    throw new Error("Model.Rows must be an array");
15984
15985            }
15986        });
15987
15988        theClass._currentRowId = 0;
15989
15990        /**Determine if two row references from a TabularModel are the exact same row.
15991        * @memberof dpage.modules.TabularModel
15992        * @name isSameRow
15993        * @function 
15994        * @param {Object} rowObj The first row to compare
15995        * @param {Object} rowObj2 The second row to compare
15996        * @returns {bool} True if the two parameters are the same row, false if not.
15997        */
15998        theClass.isSameRow = function (rowObj, rowObj2) {
15999            return rowObj === rowObj2;
16000        };
16001
16002        return theClass;
16003    }
16004);
16005},
16006'dpage/modules/Model':function(){
16007define([
16008      "dojo/_base/declare"
16009      , "dojo/on"
16010      , "dojo/_base/event"
16011],
16012    function (declare, on, event) {
16013        /**
16014        * @namespace dpage
16015        */
16016        /**
16017        * @namespace modules
16018        * @memberOf dpage
16019        */
16020        /**
16021         * Class to provide controlled access to data. This class encapsulates a single scalar value such as a string, boolean, date, or number.
16022         * @class Model
16023         * @memberOf dpage.modules
16024         */
16025        return declare("dpage.modules.Model", [], /** @lends dpage.modules.Model.prototype */ {
16026            _suppressSerialization: false,
16027
16028            constructor: function (options) {
16029               
16030            },
16031            /**
16032            * You can gain access to the underlying data by calling this method. This is typically used by serialization routines to gain access to the raw data structure.
16033            * @return {Object} 
16034            */
16035            getRawModel: function () {
16036                throw new Error("Subclass must implement this method");
16037            },
16038            /**
16039            * If set to true, the model will be sent back to the server as a null value. Does not affect the data on the page. Use this if you have large
16040            * model values that you don't want sent back to the server on submit.
16041            * @param {bool} val When null, just return the current state. Otherwise, true or false.
16042            * @returns {bool} The current state.
16043            */
16044            suppressSerialization: function (val) {
16045                if (val != null)
16046                    this._suppressSerialization = val;
16047
16048                return this._suppressSerialization;
16049            },
16050
16051            /**
16052            * Returns true if the data in the model has been modified.
16053            * @returns {bool}
16054            */
16055            isDirty : function()
16056            {
16057                throw new Error("Subclass must implement this method");
16058            },
16059
16060            /**
16061            * Will cause calls to isDirty() to return false until the data in the model is updated.
16062            * @returns {void}
16063            */
16064            setClean : function()
16065            {
16066                throw new Error("Subclass must implement this method");
16067            }
16068        });
16069    }
16070);
16071},
16072'dpage/widgets/Anchor':function(){
16073define([
16074      "dojo/_base/event"
16075      ,"dojo/on"
16076      ,"dojo/dom-attr"
16077      ,"dojo/dom-class"
16078      ,"dojo/mouse"
16079      ,"dojo/dom-geometry"
16080      , "dojo/dom-style"
16081      , "dojo/json"
16082
16083      , "dpage/modules/Date"
16084      , "dpage/modules/TabularModel"
16085      , "dojo/request/xhr"
16086      ,"dojox/html/entities"
16087      ,"dojo/_base/declare"
16088      , "dpage/widgets/SingleValueWidget"],
16089function (event, on, domAttr, domClass, mouse, domGeom, style, json) {
16090    /**
16091    * @namespace dpage
16092    */
16093    /**
16094    * @namespace widgets
16095    * @memberOf dpage
16096    */
16097    /**
16098    * Class to encapulate blocks of text on a page. The label can be bound to data which is where it makes the most sense.
16099    * If the datatype of the model is DATE, the default date formatter is used to display it (dpage.modules.Date.formatDate())
16100    * @class Anchor
16101    * @param {Object} [options] Optional options for the widget.
16102    * @param {bool} [options.noHTMLEncode] Dont' html encode the display data if set to true (not recommended).
16103    * @param {Function} [options.formatter] Function that will be used to format the data. The raw value is passed as a single param. Return the value
16104    *                                       to display.
16105    * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget. Controls the text (display) of the href.
16106    * @param {dpage.modules.SingleValueModel} [options.linkModel] Controls the href attribute of the link.
16107    * @param {function} [options.onClick] Click event.
16108    * @param {bool} [options.disableClick] Default false. If set, disables the click event so that the link will not be followed.
16109
16110    * @param {dpage.widgets.Container} [options.container] The container of the widget.
16111    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
16112    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
16113    *                               is created.
16114    * @param {Object} [containerNode] Optional container node to tie the widget to. The only valid node is an HREF node.
16115    * @memberOf dpage.widgets
16116    * @extends {dpage.widgets.SingleValueWidget}
16117     */
16118    return dojo.declare("dpage.widgets.Anchor", [dpage.widgets.SingleValueWidget], /** @lends dpage.widgets.Anchor.prototype */ {
16119        _containerNode: null,
16120        _dataType: null,
16121        _formatter: null,
16122        _htmlEncode: true,
16123        _linkCallbackId: null,
16124        _linkModel: null,
16125        _onClick: null,
16126        _preventClick : false,
16127
16128        constructor: function (options, srcNodeRef)
16129        {
16130            var self = this;
16131            this._containerNode = srcNodeRef;
16132
16133            this._onClick = [];
16134
16135            if (this._containerNode == null) {
16136                this._containerNode = document.createElement("A");
16137            }
16138
16139            if (this._containerNode.nodeName != "A")
16140                throw new Error("Source node for dpage.widgets.Anchor must be an A.");
16141
16142            if (options != null)
16143            {
16144                if (options.formatter != null)
16145                    this._formatter = options.formatter;
16146                if (options.noHTMLEncode)
16147                    this._htmlEncode = false;
16148                if(options.linkModel != null)
16149                    this._linkModel = options.linkModel;
16150                if (options.onClick != null)
16151                    this._onClick.push(options.onClick);
16152                if (options.disableClick != null) {
16153                    this._preventClick = options.disableClick;
16154                    if (this._preventClick)
16155                        this._onClick.push(function (o) { o.event.preventDefault(); });
16156                }
16157            }
16158
16159            if (options == null || options.linkModel == null)
16160                this._linkModel = new dpage.modules.SingleValueModel({ model: "#" });
16161
16162            on(this._containerNode, "click", function (event) { self._doClick(event); });
16163
16164            this._linkCallbackId = this._linkModel.addDataCallback(function (val) { self._linkModel_Callback(val); });
16165        },
16166        postCreate : function()
16167        {
16168            this._updateLink();
16169            return this.inherited(arguments);
16170        },
16171        _linkModel_Callback: function (val) {
16172            this._updateLink();
16173        },
16174        setModel : function(model)
16175        {
16176            this.inherited(arguments);
16177
16178            this._updateView();
16179        },
16180        /** Sets the linkModel property
16181        * @param {dpage.widgets.SingleValueModel} model
16182        * @returns {void}
16183        */
16184        setLinkModel : function(model)
16185        {
16186            this._linkModel.removeDataCallback(this._linkCallbackId);
16187            this._linkModel = model;
16188            model.addDataCallback(function (val) { self._linkModel_Callback(val); });
16189            this._updateLink();
16190        },
16191        _renderText : function(rawValue)
16192        {
16193            var dVal = this.renderText(rawValue);
16194            var eVal;
16195
16196            if (this._htmlEncode) {
16197                eVal = dojox.html.entities.encode(dVal);
16198                eVal = eVal.replace(/ /g, "&nbsp;");
16199                return eVal;
16200            }
16201            else
16202                return dVal;
16203        },
16204        /** Can be overridden by a subclass. formats the text that is displayed.
16205        * @param {String} rawValue the value to render.
16206        * @returns {String} value to display (will be html-encoded unless overridden)
16207        */
16208        renderText : function(rawValue)
16209        {
16210            //if a formatter function is specified, use it to render the text.
16211            if (this._formatter != null)
16212                return this._formatter(rawValue);
16213            else if (this.getModel().getMetadata().DataType == "DATE")
16214                return dpage.modules.Date.formatDate(dpage.modules.Date.parseModelValue(rawValue));
16215            else
16216                return rawValue;
16217        },
16218        _updateView : function()
16219        {
16220            var vtd = this.getValue();
16221
16222            if (vtd == null)
16223                vtd = "";
16224
16225            this._containerNode.innerHTML = this._renderText(vtd.toString());
16226        },
16227        _updateLink : function()
16228        {
16229            this._containerNode.setAttribute("href", this._linkModel.getValue());
16230        },
16231        _doClick : function(evt)
16232        {
16233            //call callbacks in order.
16234            for (var i = 0; i < this._onClick.length; i++)
16235                this._onClick[i]({ event: evt, widget: self });
16236        },
16237        /**
16238        * Set an event handler.
16239        * @param {String} eventName The event to bind to. Only supported events are "click".
16240        * @param {function} functionRef The callback function to call.
16241        * @returns {void}
16242        */
16243        on: function (eventName, functionRef) {
16244            var self = this;
16245
16246            if (eventName != "click")
16247                throw new Error("Supported events are: 'click'.");
16248
16249            this._onClick.push(functionRef);
16250
16251        },
16252        destroy : function()
16253        {
16254            this._linkModel.removeDataCallback(this._linkCallbackId);
16255            return this.inherited(arguments);
16256        }
16257   });
16258});
16259
16260},
16261'dpage/modules/Date':function(){
16262define([
16263      "dojo/date/stamp",
16264      "dojo/_base/declare",
16265      "dojo/date/locale"
16266
16267],
16268    function (stamp , declare , locale) {
16269        /**
16270        * @namespace dpage
16271        */
16272        /**
16273        * @namespace modules
16274        * @memberOf dpage
16275        */
16276        /**
16277         * Provides Date helper functions. Default date format is M/d/yyyy and it can be changed.
16278         * @class Date
16279         * @memberOf dpage.modules
16280         */
16281        var theClass = declare("dpage.modules.Date", [], /** @lends dpage.modules.Date.prototype */ {
16282
16283            constructor: function (options) {
16284                var self = this;
16285
16286            }
16287        });
16288
16289        theClass._currentRowId = 0;
16290
16291        /**Parse an ISO-8601 date string into a javascript Date Object. Only needed because the parsing of
16292        * The ISO-8601 date string is flakey depending on what version of javascript you are running. Some 
16293        * assume local time, others assume GMT if the timezone info is missing on the string. This method
16294        * solves the problem. If the date string has no time zone info, localtime is assumed.
16295        * @memberof dpage.modules.Date
16296        * @name parseModelValue
16297        * @function 
16298        * @param {String} dateStr The date string from the model in ISO-8601 format.
16299        * @returns {Date} Javascript Date Object or null if the date could not be parsed.
16300        */
16301        theClass.parseModelValue = function (dateStr) {
16302            var ds;
16303            var offsetInHours;
16304            var sign;
16305
16306            if (dateStr == null)
16307                return null;
16308
16309            if (dateStr.match(/^\s*$/) != null)
16310                return null;
16311
16312            //dojo's fromISOString provides a more browser agnostic way of parsing an ISO 8601 date string reliably.
16313            return stamp.fromISOString(dateStr);
16314        };
16315
16316        theClass._defaultDateFormat =  "M/d/yyyy";
16317
16318        /**Stringifies a date object for use in a dpage DATE type model value. Uses ISO 8601 format.
16319        * @memberof dpage.modules.Date
16320        * @name toModelValue
16321        * @function 
16322        * @param {Date} jsDateObj The javascript date
16323        * @returns {String} The serialized value to store in the model.
16324        */
16325        theClass.toModelValue = function (jsDateObj) {
16326            return jsDateObj.toISOString();
16327        };
16328
16329        /**Parses a date using the dpage.modules.Date.getDatePattern(), or custom pattern
16330        * @memberof dpage.modules.Date
16331        * @name parseDateString
16332        * @function 
16333        * @param {String} dateStr The date string to parse
16334        * @param {String} optionalDateFormat Optional pattern to use.
16335        * @returns {Date} The parsed date or null if the date could not be parsed.
16336        */
16337        theClass.parseDateString = function (dateStr , optionalDateFormat) {
16338            if (dateStr == null)
16339                return null;
16340
16341            return locale.parse(dateStr, {
16342                datePattern: optionalDateFormat == null ? dpage.modules.Date._defaultDateFormat : optionalDateFormat,
16343                selector : "date"
16344            });
16345        };
16346
16347        /**Sets the default formatter pattern used to format and parse dates in dpage. The format of the 
16348        * string is defined here: <a href='http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns'>http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns</a>
16349        * A good practice is to avoid calling this method anywere other than from the Page that contains the widgets.
16350        * @memberof dpage.modules.Date
16351        * @name setDatePattern
16352        * @function 
16353        * @param {String} dateFormatStr The format string defined here: <a href='http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns'>http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns</a>
16354        * @returns {void}
16355        */
16356        theClass.setDatePattern = function (dateFormatStr) {
16357            dpage.modules.Date._defaultDateFormat = dateFormatStr;
16358        };
16359
16360        /**Get the default formatter pattern used to format and parse dates in dpage. The format of the 
16361        * string is defined here: <a href='http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns'>http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns</a>
16362        * @memberof dpage.modules.Date
16363        * @name getDatePattern
16364        * @function 
16365        * @returns {String} The format string defined here: <a href='http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns'>http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns</a>
16366        */
16367        theClass.getDatePattern = function () {
16368            return dpage.modules.Date._defaultDateFormat;
16369        };
16370
16371        /**Formats a javascript date object according to the current default dpage date format or custom format.
16372        * The default date format can be set by calling dpage.modules.Date.setDatePattern(formatFunc);
16373        * @memberof dpage.modules.Date
16374        * @name formatDate
16375        * @function 
16376        * @param {Date} jsDateObj The js date object.
16377        * @param {String} optionalDateFormat Optional pattern to use.
16378        * @returns {String}
16379        */
16380        theClass.formatDate = function (jsDateObj , optionalDateFormat) {
16381
16382            if (jsDateObj == null)
16383                return "";
16384
16385            return locale.format(jsDateObj, {
16386                datePattern: optionalDateFormat == null ? dpage.modules.Date._defaultDateFormat : optionalDateFormat,
16387                selector : "date"
16388            });
16389        };
16390
16391        return theClass;
16392    }
16393);
16394},
16395'dojo/date/stamp':function(){
16396define(["../_base/lang", "../_base/array"], function(lang, array){
16397
16398// module:
16399//		dojo/date/stamp
16400
16401var stamp = {
16402	// summary:
16403	//		TODOC
16404};
16405lang.setObject("dojo.date.stamp", stamp);
16406
16407// Methods to convert dates to or from a wire (string) format using well-known conventions
16408
16409stamp.fromISOString = function(/*String*/ formattedString, /*Number?*/ defaultTime){
16410	// summary:
16411	//		Returns a Date object given a string formatted according to a subset of the ISO-8601 standard.
16412	//
16413	// description:
16414	//		Accepts a string formatted according to a profile of ISO8601 as defined by
16415	//		[RFC3339](http://www.ietf.org/rfc/rfc3339.txt), except that partial input is allowed.
16416	//		Can also process dates as specified [by the W3C](http://www.w3.org/TR/NOTE-datetime)
16417	//		The following combinations are valid:
16418	//
16419	//		- dates only
16420	//			- yyyy
16421	//			- yyyy-MM
16422	//			- yyyy-MM-dd
16423	//		- times only, with an optional time zone appended
16424	//			- THH:mm
16425	//			- THH:mm:ss
16426	//			- THH:mm:ss.SSS
16427	//		- and "datetimes" which could be any combination of the above
16428	//
16429	//		timezones may be specified as Z (for UTC) or +/- followed by a time expression HH:mm
16430	//		Assumes the local time zone if not specified.  Does not validate.  Improperly formatted
16431	//		input may return null.  Arguments which are out of bounds will be handled
16432	//		by the Date constructor (e.g. January 32nd typically gets resolved to February 1st)
16433	//		Only years between 100 and 9999 are supported.
16434  	// formattedString:
16435	//		A string such as 2005-06-30T08:05:00-07:00 or 2005-06-30 or T08:05:00
16436	// defaultTime:
16437	//		Used for defaults for fields omitted in the formattedString.
16438	//		Uses 1970-01-01T00:00:00.0Z by default.
16439
16440	if(!stamp._isoRegExp){
16441		stamp._isoRegExp =
16442//TODO: could be more restrictive and check for 00-59, etc.
16443			/^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(.\d+)?)?((?:[+-](\d{2}):(\d{2}))|Z)?)?$/;
16444	}
16445
16446	var match = stamp._isoRegExp.exec(formattedString),
16447		result = null;
16448
16449	if(match){
16450		match.shift();
16451		if(match[1]){match[1]--;} // Javascript Date months are 0-based
16452		if(match[6]){match[6] *= 1000;} // Javascript Date expects fractional seconds as milliseconds
16453
16454		if(defaultTime){
16455			// mix in defaultTime.  Relatively expensive, so use || operators for the fast path of defaultTime === 0
16456			defaultTime = new Date(defaultTime);
16457			array.forEach(array.map(["FullYear", "Month", "Date", "Hours", "Minutes", "Seconds", "Milliseconds"], function(prop){
16458				return defaultTime["get" + prop]();
16459			}), function(value, index){
16460				match[index] = match[index] || value;
16461			});
16462		}
16463		result = new Date(match[0]||1970, match[1]||0, match[2]||1, match[3]||0, match[4]||0, match[5]||0, match[6]||0); //TODO: UTC defaults
16464		if(match[0] < 100){
16465			result.setFullYear(match[0] || 1970);
16466		}
16467
16468		var offset = 0,
16469			zoneSign = match[7] && match[7].charAt(0);
16470		if(zoneSign != 'Z'){
16471			offset = ((match[8] || 0) * 60) + (Number(match[9]) || 0);
16472			if(zoneSign != '-'){ offset *= -1; }
16473		}
16474		if(zoneSign){
16475			offset -= result.getTimezoneOffset();
16476		}
16477		if(offset){
16478			result.setTime(result.getTime() + offset * 60000);
16479		}
16480	}
16481
16482	return result; // Date or null
16483};
16484
16485/*=====
16486var __Options = {
16487	// selector: String
16488	//		"date" or "time" for partial formatting of the Date object.
16489	//		Both date and time will be formatted by default.
16490	// zulu: Boolean
16491	//		if true, UTC/GMT is used for a timezone
16492	// milliseconds: Boolean
16493	//		if true, output milliseconds
16494};
16495=====*/
16496
16497stamp.toISOString = function(/*Date*/ dateObject, /*__Options?*/ options){
16498	// summary:
16499	//		Format a Date object as a string according a subset of the ISO-8601 standard
16500	//
16501	// description:
16502	//		When options.selector is omitted, output follows [RFC3339](http://www.ietf.org/rfc/rfc3339.txt)
16503	//		The local time zone is included as an offset from GMT, except when selector=='time' (time without a date)
16504	//		Does not check bounds.  Only years between 100 and 9999 are supported.
16505	//
16506	// dateObject:
16507	//		A Date object
16508
16509	var _ = function(n){ return (n < 10) ? "0" + n : n; };
16510	options = options || {};
16511	var formattedDate = [],
16512		getter = options.zulu ? "getUTC" : "get",
16513		date = "";
16514	if(options.selector != "time"){
16515		var year = dateObject[getter+"FullYear"]();
16516		date = ["0000".substr((year+"").length)+year, _(dateObject[getter+"Month"]()+1), _(dateObject[getter+"Date"]())].join('-');
16517	}
16518	formattedDate.push(date);
16519	if(options.selector != "date"){
16520		var time = [_(dateObject[getter+"Hours"]()), _(dateObject[getter+"Minutes"]()), _(dateObject[getter+"Seconds"]())].join(':');
16521		var millis = dateObject[getter+"Milliseconds"]();
16522		if(options.milliseconds){
16523			time += "."+ (millis < 100 ? "0" : "") + _(millis);
16524		}
16525		if(options.zulu){
16526			time += "Z";
16527		}else if(options.selector != "time"){
16528			var timezoneOffset = dateObject.getTimezoneOffset();
16529			var absOffset = Math.abs(timezoneOffset);
16530			time += (timezoneOffset > 0 ? "-" : "+") +
16531				_(Math.floor(absOffset/60)) + ":" + _(absOffset%60);
16532		}
16533		formattedDate.push(time);
16534	}
16535	return formattedDate.join('T'); // String
16536};
16537
16538return stamp;
16539});
16540
16541},
16542'dojo/date/locale':function(){
16543define([
16544	"../_base/lang",
16545	"../_base/array",
16546	"../date",
16547	/*===== "../_base/declare", =====*/
16548	"../cldr/supplemental",
16549	"../i18n",
16550	"../regexp",
16551	"../string",
16552	"../i18n!../cldr/nls/gregorian",
16553	"module"
16554], function(lang, array, date, /*===== declare, =====*/ supplemental, i18n, regexp, string, gregorian, module){
16555
16556// module:
16557//		dojo/date/locale
16558
16559var exports = {
16560	// summary:
16561	//		This modules defines dojo/date/locale, localization methods for Date.
16562};
16563lang.setObject(module.id.replace(/\//g, "."), exports);
16564
16565// Localization methods for Date.   Honor local customs using locale-dependent dojo.cldr data.
16566
16567// Load the bundles containing localization information for
16568// names and formats
16569
16570//NOTE: Everything in this module assumes Gregorian calendars.
16571// Other calendars will be implemented in separate modules.
16572
16573	// Format a pattern without literals
16574	function formatPattern(dateObject, bundle, options, pattern){
16575		return pattern.replace(/([a-z])\1*/ig, function(match){
16576			var s, pad,
16577				c = match.charAt(0),
16578				l = match.length,
16579				widthList = ["abbr", "wide", "narrow"];
16580			switch(c){
16581				case 'G':
16582					s = bundle[(l < 4) ? "eraAbbr" : "eraNames"][dateObject.getFullYear() < 0 ? 0 : 1];
16583					break;
16584				case 'y':
16585					s = dateObject.getFullYear();
16586					switch(l){
16587						case 1:
16588							break;
16589						case 2:
16590							if(!options.fullYear){
16591								s = String(s); s = s.substr(s.length - 2);
16592								break;
16593							}
16594							// fallthrough
16595						default:
16596							pad = true;
16597					}
16598					break;
16599				case 'Q':
16600				case 'q':
16601					s = Math.ceil((dateObject.getMonth()+1)/3);
16602//					switch(l){
16603//						case 1: case 2:
16604							pad = true;
16605//							break;
16606//						case 3: case 4: // unimplemented
16607//					}
16608					break;
16609				case 'M':
16610				case 'L':
16611					var m = dateObject.getMonth();
16612					if(l<3){
16613						s = m+1; pad = true;
16614					}else{
16615						var propM = [
16616							"months",
16617							c == 'L' ? "standAlone" : "format",
16618							widthList[l-3]
16619						].join("-");
16620						s = bundle[propM][m];
16621					}
16622					break;
16623				case 'w':
16624					var firstDay = 0;
16625					s = exports._getWeekOfYear(dateObject, firstDay); pad = true;
16626					break;
16627				case 'd':
16628					s = dateObject.getDate(); pad = true;
16629					break;
16630				case 'D':
16631					s = exports._getDayOfYear(dateObject); pad = true;
16632					break;
16633				case 'e':
16634				case 'c':
16635					var d = dateObject.getDay();
16636					if(l<2){
16637						s = (d - supplemental.getFirstDayOfWeek(options.locale) + 8) % 7
16638						break;
16639					}
16640					// fallthrough
16641				case 'E':
16642					d = dateObject.getDay();
16643					if(l<3){
16644						s = d+1; pad = true;
16645					}else{
16646						var propD = [
16647							"days",
16648							c == 'c' ? "standAlone" : "format",
16649							widthList[l-3]
16650						].join("-");
16651						s = bundle[propD][d];
16652					}
16653					break;
16654				case 'a':
16655					var timePeriod = dateObject.getHours() < 12 ? 'am' : 'pm';
16656					s = options[timePeriod] || bundle['dayPeriods-format-wide-' + timePeriod];
16657					break;
16658				case 'h':
16659				case 'H':
16660				case 'K':
16661				case 'k':
16662					var h = dateObject.getHours();
16663					// strange choices in the date format make it impossible to write this succinctly
16664					switch (c){
16665						case 'h': // 1-12
16666							s = (h % 12) || 12;
16667							break;
16668						case 'H': // 0-23
16669							s = h;
16670							break;
16671						case 'K': // 0-11
16672							s = (h % 12);
16673							break;
16674						case 'k': // 1-24
16675							s = h || 24;
16676							break;
16677					}
16678					pad = true;
16679					break;
16680				case 'm':
16681					s = dateObject.getMinutes(); pad = true;
16682					break;
16683				case 's':
16684					s = dateObject.getSeconds(); pad = true;
16685					break;
16686				case 'S':
16687					s = Math.round(dateObject.getMilliseconds() * Math.pow(10, l-3)); pad = true;
16688					break;
16689				case 'v': // FIXME: don't know what this is. seems to be same as z?
16690				case 'z':
16691					// We only have one timezone to offer; the one from the browser
16692					s = exports._getZone(dateObject, true, options);
16693					if(s){break;}
16694					l=4;
16695					// fallthrough... use GMT if tz not available
16696				case 'Z':
16697					var offset = exports._getZone(dateObject, false, options);
16698					var tz = [
16699						(offset<=0 ? "+" : "-"),
16700						string.pad(Math.floor(Math.abs(offset)/60), 2),
16701						string.pad(Math.abs(offset)% 60, 2)
16702					];
16703					if(l==4){
16704						tz.splice(0, 0, "GMT");
16705						tz.splice(3, 0, ":");
16706					}
16707					s = tz.join("");
16708					break;
16709//				case 'Y': case 'u': case 'W': case 'F': case 'g': case 'A':
16710//					console.log(match+" modifier unimplemented");
16711				default:
16712					throw new Error("dojo.date.locale.format: invalid pattern char: "+pattern);
16713			}
16714			if(pad){ s = string.pad(s, l); }
16715			return s;
16716		});
16717	}
16718
16719/*=====
16720var __FormatOptions = exports.__FormatOptions = declare(null, {
16721	// selector: String
16722	//		choice of 'time','date' (default: date and time)
16723	// formatLength: String
16724	//		choice of long, short, medium or full (plus any custom additions).  Defaults to 'short'
16725	// datePattern:String
16726	//		override pattern with this string
16727	// timePattern:String
16728	//		override pattern with this string
16729	// am: String
16730	//		override strings for am in times
16731	// pm: String
16732	//		override strings for pm in times
16733	// locale: String
16734	//		override the locale used to determine formatting rules
16735	// fullYear: Boolean
16736	//		(format only) use 4 digit years whenever 2 digit years are called for
16737	// strict: Boolean
16738	//		(parse only) strict parsing, off by default
16739});
16740=====*/
16741
16742exports._getZone = function(/*Date*/ dateObject, /*boolean*/ getName, /*__FormatOptions?*/ options){
16743	// summary:
16744	//		Returns the zone (or offset) for the given date and options.  This
16745	//		is broken out into a separate function so that it can be overridden
16746	//		by timezone-aware code.
16747	//
16748	// dateObject:
16749	//		the date and/or time being formatted.
16750	//
16751	// getName:
16752	//		Whether to return the timezone string (if true), or the offset (if false)
16753	//
16754	// options:
16755	//		The options being used for formatting
16756	if(getName){
16757		return date.getTimezoneName(dateObject);
16758	}else{
16759		return dateObject.getTimezoneOffset();
16760	}
16761};
16762
16763
16764exports.format = function(/*Date*/ dateObject, /*__FormatOptions?*/ options){
16765	// summary:
16766	//		Format a Date object as a String, using locale-specific settings.
16767	//
16768	// description:
16769	//		Create a string from a Date object using a known localized pattern.
16770	//		By default, this method formats both date and time from dateObject.
16771	//		Formatting patterns are chosen appropriate to the locale.  Different
16772	//		formatting lengths may be chosen, with "full" used by default.
16773	//		Custom patterns may be used or registered with translations using
16774	//		the dojo/date/locale.addCustomFormats() method.
16775	//		Formatting patterns are implemented using [the syntax described at
16776	//		unicode.org](http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns)
16777	//
16778	// dateObject:
16779	//		the date and/or time to be formatted.  If a time only is formatted,
16780	//		the values in the year, month, and day fields are irrelevant.  The
16781	//		opposite is true when formatting only dates.
16782
16783	options = options || {};
16784
16785	var locale = i18n.normalizeLocale(options.locale),
16786		formatLength = options.formatLength || 'short',
16787		bundle = exports._getGregorianBundle(locale),
16788		str = [],
16789		sauce = lang.hitch(this, formatPattern, dateObject, bundle, options);
16790	if(options.selector == "year"){
16791		return _processPattern(bundle["dateFormatItem-yyyy"] || "yyyy", sauce);
16792	}
16793	var pattern;
16794	if(options.selector != "date"){
16795		pattern = options.timePattern || bundle["timeFormat-"+formatLength];
16796		if(pattern){str.push(_processPattern(pattern, sauce));}
16797	}
16798	if(options.selector != "time"){
16799		pattern = options.datePattern || bundle["dateFormat-"+formatLength];
16800		if(pattern){str.push(_processPattern(pattern, sauce));}
16801	}
16802
16803	return str.length == 1 ? str[0] : bundle["dateTimeFormat-"+formatLength].replace(/\'/g,'').replace(/\{(\d+)\}/g,
16804		function(match, key){ return str[key]; }); // String
16805};
16806
16807exports.regexp = function(/*__FormatOptions?*/ options){
16808	// summary:
16809	//		Builds the regular needed to parse a localized date
16810
16811	return exports._parseInfo(options).regexp; // String
16812};
16813
16814exports._parseInfo = function(/*__FormatOptions?*/ options){
16815	options = options || {};
16816	var locale = i18n.normalizeLocale(options.locale),
16817		bundle = exports._getGregorianBundle(locale),
16818		formatLength = options.formatLength || 'short',
16819		datePattern = options.datePattern || bundle["dateFormat-" + formatLength],
16820		timePattern = options.timePattern || bundle["timeFormat-" + formatLength],
16821		pattern;
16822	if(options.selector == 'date'){
16823		pattern = datePattern;
16824	}else if(options.selector == 'time'){
16825		pattern = timePattern;
16826	}else{
16827		pattern = bundle["dateTimeFormat-"+formatLength].replace(/\{(\d+)\}/g,
16828			function(match, key){ return [timePattern, datePattern][key]; });
16829	}
16830
16831	var tokens = [],
16832		re = _processPattern(pattern, lang.hitch(this, _buildDateTimeRE, tokens, bundle, options));
16833	return {regexp: re, tokens: tokens, bundle: bundle};
16834};
16835
16836exports.parse = function(/*String*/ value, /*__FormatOptions?*/ options){
16837	// summary:
16838	//		Convert a properly formatted string to a primitive Date object,
16839	//		using locale-specific settings.
16840	//
16841	// description:
16842	//		Create a Date object from a string using a known localized pattern.
16843	//		By default, this method parses looking for both date and time in the string.
16844	//		Formatting patterns are chosen appropriate to the locale.  Different
16845	//		formatting lengths may be chosen, with "full" used by default.
16846	//		Custom patterns may be used or registered with translations using
16847	//		the dojo/date/locale.addCustomFormats() method.
16848	//
16849	//		Formatting patterns are implemented using [the syntax described at
16850	//		unicode.org](http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns)
16851	//		When two digit years are used, a century is chosen according to a sliding
16852	//		window of 80 years before and 20 years after present year, for both `yy` and `yyyy` patterns.
16853	//		year < 100CE requires strict mode.
16854	//
16855	// value:
16856	//		A string representation of a date
16857
16858	// remove non-printing bidi control chars from input and pattern
16859	var controlChars = /[\u200E\u200F\u202A\u202E]/g,
16860		info = exports._parseInfo(options),
16861		tokens = info.tokens, bundle = info.bundle,
16862		re = new RegExp("^" + info.regexp.replace(controlChars, "") + "$",
16863			info.strict ? "" : "i"),
16864		match = re.exec(value && value.replace(controlChars, ""));
16865
16866	if(!match){ return null; } // null
16867
16868	var widthList = ['abbr', 'wide', 'narrow'],
16869		result = [1970,0,1,0,0,0,0], // will get converted to a Date at the end
16870		amPm = "",
16871		valid = array.every(match, function(v, i){
16872		if(!i){return true;}
16873		var token = tokens[i-1],
16874			l = token.length,
16875			c = token.charAt(0);
16876		switch(c){
16877			case 'y':
16878				if(l != 2 && options.strict){
16879					//interpret year literally, so '5' would be 5 A.D.
16880					result[0] = v;
16881				}else{
16882					if(v<100){
16883						v = Number(v);
16884						//choose century to apply, according to a sliding window
16885						//of 80 years before and 20 years after present year
16886						var year = '' + new Date().getFullYear(),
16887							century = year.substring(0, 2) * 100,
16888							cutoff = Math.min(Number(year.substring(2, 4)) + 20, 99);
16889						result[0] = (v < cutoff) ? century + v : century - 100 + v;
16890					}else{
16891						//we expected 2 digits and got more...
16892						if(options.strict){
16893							return false;
16894						}
16895						//interpret literally, so '150' would be 150 A.D.
16896						//also tolerate '1950', if 'yyyy' input passed to 'yy' format
16897						result[0] = v;
16898					}
16899				}
16900				break;
16901			case 'M':
16902			case 'L':
16903				if(l>2){
16904					var months = bundle['months-' +
16905							    (c == 'L' ? 'standAlone' : 'format') +
16906							    '-' + widthList[l-3]].concat();
16907					if(!options.strict){
16908						//Tolerate abbreviating period in month part
16909						//Case-insensitive comparison
16910						v = v.replace(".","").toLowerCase();
16911						months = array.map(months, function(s){ return s.replace(".","").toLowerCase(); } );
16912					}
16913					v = array.indexOf(months, v);
16914					if(v == -1){
16915//						console.log("dojo/date/locale.parse: Could not parse month name: '" + v + "'.");
16916						return false;
16917					}
16918				}else{
16919					v--;
16920				}
16921				result[1] = v;
16922				break;
16923			case 'E':
16924			case 'e':
16925			case 'c':
16926				var days = bundle['days-' +
16927						  (c == 'c' ? 'standAlone' : 'format') +
16928						  '-' + widthList[l-3]].concat();
16929				if(!options.strict){
16930					//Case-insensitive comparison
16931					v = v.toLowerCase();
16932					days = array.map(days, function(d){return d.toLowerCase();});
16933				}
16934				v = array.indexOf(days, v);
16935				if(v == -1){
16936//					console.log("dojo/date/locale.parse: Could not parse weekday name: '" + v + "'.");
16937					return false;
16938				}
16939
16940				//TODO: not sure what to actually do with this input,
16941				//in terms of setting something on the Date obj...?
16942				//without more context, can't affect the actual date
16943				//TODO: just validate?
16944				break;
16945			case 'D':
16946				result[1] = 0;
16947				// fallthrough...
16948			case 'd':
16949				result[2] = v;
16950				break;
16951			case 'a': //am/pm
16952				var am = options.am || bundle['dayPeriods-format-wide-am'],
16953					pm = options.pm || bundle['dayPeriods-format-wide-pm'];
16954				if(!options.strict){
16955					var period = /\./g;
16956					v = v.replace(period,'').toLowerCase();
16957					am = am.replace(period,'').toLowerCase();
16958					pm = pm.replace(period,'').toLowerCase();
16959				}
16960				if(options.strict && v != am && v != pm){
16961//					console.log("dojo/date/locale.parse: Could not parse am/pm part.");
16962					return false;
16963				}
16964
16965				// we might not have seen the hours field yet, so store the state and apply hour change later
16966				amPm = (v == pm) ? 'p' : (v == am) ? 'a' : '';
16967				break;
16968			case 'K': //hour (1-24)
16969				if(v == 24){ v = 0; }
16970				// fallthrough...
16971			case 'h': //hour (1-12)
16972			case 'H': //hour (0-23)
16973			case 'k': //hour (0-11)
16974				//TODO: strict bounds checking, padding
16975				if(v > 23){
16976//					console.log("dojo/date/locale.parse: Illegal hours value");
16977					return false;
16978				}
16979
16980				//in the 12-hour case, adjusting for am/pm requires the 'a' part
16981				//which could come before or after the hour, so we will adju
16981st later
16982				result[3] = v;
16983				break;
16984			case 'm': //minutes
16985				result[4] = v;
16986				break;
16987			case 's': //seconds
16988				result[5] = v;
16989				break;
16990			case 'S': //milliseconds
16991				result[6] = v;
16992//				break;
16993//			case 'w':
16994//TODO				var firstDay = 0;
16995//			default:
16996//TODO: throw?
16997//				console.log("dojo/date/locale.parse: unsupported pattern char=" + token.charAt(0));
16998		}
16999		return true;
17000	});
17001
17002	var hours = +result[3];
17003	if(amPm === 'p' && hours < 12){
17004		result[3] = hours + 12; //e.g., 3pm -> 15
17005	}else if(amPm === 'a' && hours == 12){
17006		result[3] = 0; //12am -> 0
17007	}
17008
17009	//TODO: implement a getWeekday() method in order to test
17010	//validity of input strings containing 'EEE' or 'EEEE'...
17011
17012	var dateObject = new Date(result[0], result[1], result[2], result[3], result[4], result[5], result[6]); // Date
17013	if(options.strict){
17014		dateObject.setFullYear(result[0]);
17015	}
17016
17017	// Check for overflow.  The Date() constructor normalizes things like April 32nd...
17018	//TODO: why isn't this done for times as well?
17019	var allTokens = tokens.join(""),
17020		dateToken = allTokens.indexOf('d') != -1,
17021		monthToken = allTokens.indexOf('M') != -1;
17022
17023	if(!valid ||
17024		(monthToken && dateObject.getMonth() > result[1]) ||
17025		(dateToken && dateObject.getDate() > result[2])){
17026		return null;
17027	}
17028
17029	// Check for underflow, due to DST shifts.  See #9366
17030	// This assumes a 1 hour dst shift correction at midnight
17031	// We could compare the timezone offset after the shift and add the difference instead.
17032	if((monthToken && dateObject.getMonth() < result[1]) ||
17033		(dateToken && dateObject.getDate() < result[2])){
17034		dateObject = date.add(dateObject, "hour", 1);
17035	}
17036
17037	return dateObject; // Date
17038};
17039
17040function _processPattern(pattern, applyPattern, applyLiteral, applyAll){
17041	//summary: Process a pattern with literals in it
17042
17043	// Break up on single quotes, treat every other one as a literal, except '' which becomes '
17044	var identity = function(x){return x;};
17045	applyPattern = applyPattern || identity;
17046	applyLiteral = applyLiteral || identity;
17047	applyAll = applyAll || identity;
17048
17049	//split on single quotes (which escape literals in date format strings)
17050	//but preserve escaped single quotes (e.g., o''clock)
17051	var chunks = pattern.match(/(''|[^'])+/g),
17052		literal = pattern.charAt(0) == "'";
17053
17054	array.forEach(chunks, function(chunk, i){
17055		if(!chunk){
17056			chunks[i]='';
17057		}else{
17058			chunks[i]=(literal ? applyLiteral : applyPattern)(chunk.replace(/''/g, "'"));
17059			literal = !literal;
17060		}
17061	});
17062	return applyAll(chunks.join(''));
17063}
17064
17065function _buildDateTimeRE(tokens, bundle, options, pattern){
17066	pattern = regexp.escapeString(pattern);
17067	if(!options.strict){ pattern = pattern.replace(" a", " ?a"); } // kludge to tolerate no space before am/pm
17068	return pattern.replace(/([a-z])\1*/ig, function(match){
17069		// Build a simple regexp.  Avoid captures, which would ruin the tokens list
17070		var s,
17071			c = match.charAt(0),
17072			l = match.length,
17073			p2 = '', p3 = '';
17074		if(options.strict){
17075			if(l > 1){ p2 = '0' + '{'+(l-1)+'}'; }
17076			if(l > 2){ p3 = '0' + '{'+(l-2)+'}'; }
17077		}else{
17078			p2 = '0?'; p3 = '0{0,2}';
17079		}
17080		switch(c){
17081			case 'y':
17082				s = '\\d{2,4}';
17083				break;
17084			case 'M':
17085			case 'L':
17086				s = (l>2) ? '\\S+?' : '1[0-2]|'+p2+'[1-9]';
17087				break;
17088			case 'D':
17089				s = '[12][0-9][0-9]|3[0-5][0-9]|36[0-6]|'+p2+'[1-9][0-9]|'+p3+'[1-9]';
17090				break;
17091			case 'd':
17092				s = '3[01]|[12]\\d|'+p2+'[1-9]';
17093				break;
17094			case 'w':
17095				s = '[1-4][0-9]|5[0-3]|'+p2+'[1-9]';
17096				break;
17097			case 'E':
17098			case 'e':
17099			case 'c':
17100				s = '.+?'; // match anything including spaces until the first pattern delimiter is found such as a comma or space
17101				break;
17102			case 'h': //hour (1-12)
17103				s = '1[0-2]|'+p2+'[1-9]';
17104				break;
17105			case 'k': //hour (0-11)
17106				s = '1[01]|'+p2+'\\d';
17107				break;
17108			case 'H': //hour (0-23)
17109				s = '1\\d|2[0-3]|'+p2+'\\d';
17110				break;
17111			case 'K': //hour (1-24)
17112				s = '1\\d|2[0-4]|'+p2+'[1-9]';
17113				break;
17114			case 'm':
17115			case 's':
17116				s = '[0-5]\\d';
17117				break;
17118			case 'S':
17119				s = '\\d{'+l+'}';
17120				break;
17121			case 'a':
17122				var am = options.am || bundle['dayPeriods-format-wide-am'],
17123					pm = options.pm || bundle['dayPeriods-format-wide-pm'];
17124					s = am + '|' + pm;
17125				if(!options.strict){
17126					if(am != am.toLowerCase()){ s += '|' + am.toLowerCase(); }
17127					if(pm != pm.toLowerCase()){ s += '|' + pm.toLowerCase(); }
17128					if(s.indexOf('.') != -1){ s += '|' + s.replace(/\./g, ""); }
17129				}
17130				s = s.replace(/\./g, "\\.");
17131				break;
17132			default:
17133			// case 'v':
17134			// case 'z':
17135			// case 'Z':
17136				s = ".*";
17137//				console.log("parse of date format, pattern=" + pattern);
17138		}
17139
17140		if(tokens){ tokens.push(match); }
17141
17142		return "(" + s + ")"; // add capture
17143	}).replace(/[\xa0 ]/g, "[\\s\\xa0]"); // normalize whitespace.  Need explicit handling of \xa0 for IE.
17144}
17145
17146var _customFormats = [];
17147exports.addCustomFormats = function(/*String*/ packageName, /*String*/ bundleName){
17148	// summary:
17149	//		Add a reference to a bundle containing localized custom formats to be
17150	//		used by date/time formatting and parsing routines.
17151	//
17152	// description:
17153	//		The user may add custom localized formats where the bundle has properties following the
17154	//		same naming convention used by dojo.cldr: `dateFormat-xxxx` / `timeFormat-xxxx`
17155	//		The pattern string should match the format used by the CLDR.
17156	//		See dojo/date/locale.format() for details.
17157	//		The resources must be loaded by dojo.requireLocalization() prior to use
17158
17159	_customFormats.push({pkg:packageName,name:bundleName});
17160};
17161
17162exports._getGregorianBundle = function(/*String*/ locale){
17163	var gregorian = {};
17164	array.forEach(_customFormats, function(desc){
17165		var bundle = i18n.getLocalization(desc.pkg, desc.name, locale);
17166		gregorian = lang.mixin(gregorian, bundle);
17167	}, this);
17168	return gregorian; /*Object*/
17169};
17170
17171exports.addCustomFormats(module.id.replace(/\/date\/locale$/, ".cldr"),"gregorian");
17172
17173exports.getNames = function(/*String*/ item, /*String*/ type, /*String?*/ context, /*String?*/ locale){
17174	// summary:
17175	//		Used to get localized strings from dojo.cldr for day or month names.
17176	//
17177	// item:
17178	//	'months' || 'days'
17179	// type:
17180	//	'wide' || 'abbr' || 'narrow' (e.g. "Monday", "Mon", or "M" respectively, in English)
17181	// context:
17182	//	'standAlone' || 'format' (default)
17183	// locale:
17184	//	override locale used to find the names
17185
17186	var label,
17187		lookup = exports._getGregorianBundle(locale),
17188		props = [item, context, type];
17189	if(context == 'standAlone'){
17190		var key = props.join('-');
17191		label = lookup[key];
17192		// Fall back to 'format' flavor of name
17193		if(label[0] == 1){ label = undefined; } // kludge, in the absence of real aliasing support in dojo.cldr
17194	}
17195	props[1] = 'format';
17196
17197	// return by copy so changes won't be made accidentally to the in-memory model
17198	return (label || lookup[props.join('-')]).concat(); /*Array*/
17199};
17200
17201exports.isWeekend = function(/*Date?*/ dateObject, /*String?*/ locale){
17202	// summary:
17203	//	Determines if the date falls on a weekend, according to local custom.
17204
17205	var weekend = supplemental.getWeekend(locale),
17206		day = (dateObject || new Date()).getDay();
17207	if(weekend.end < weekend.start){
17208		weekend.end += 7;
17209		if(day < weekend.start){ day += 7; }
17210	}
17211	return day >= weekend.start && day <= weekend.end; // Boolean
17212};
17213
17214// These are used only by format and strftime.  Do they need to be public?  Which module should they go in?
17215
17216exports._getDayOfYear = function(/*Date*/ dateObject){
17217	// summary:
17218	//		gets the day of the year as represented by dateObject
17219	return date.difference(new Date(dateObject.getFullYear(), 0, 1, dateObject.getHours()), dateObject) + 1; // Number
17220};
17221
17222exports._getWeekOfYear = function(/*Date*/ dateObject, /*Number*/ firstDayOfWeek){
17223	if(arguments.length == 1){ firstDayOfWeek = 0; } // Sunday
17224
17225	var firstDayOfYear = new Date(dateObject.getFullYear(), 0, 1).getDay(),
17226		adj = (firstDayOfYear - firstDayOfWeek + 7) % 7,
17227		week = Math.floor((exports._getDayOfYear(dateObject) + adj - 1) / 7);
17228
17229	// if year starts on the specified day, start counting weeks at 1
17230	if(firstDayOfYear == firstDayOfWeek){ week++; }
17231
17232	return week; // Number
17233};
17234
17235return exports;
17236});
17237
17238},
17239'dojo/date':function(){
17240define(["./has", "./_base/lang"], function(has, lang){
17241// module:
17242//		dojo/date
17243
17244var date = {
17245	// summary:
17246	//		Date manipulation utilities
17247};
17248
17249date.getDaysInMonth = function(/*Date*/dateObject){
17250	// summary:
17251	//		Returns the number of days in the month used by dateObject
17252	var month = dateObject.getMonth();
17253	var days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
17254	if(month == 1 && date.isLeapYear(dateObject)){ return 29; } // Number
17255	return days[month]; // Number
17256};
17257
17258date.isLeapYear = function(/*Date*/dateObject){
17259	// summary:
17260	//		Determines if the year of the dateObject is a leap year
17261	// description:
17262	//		Leap years are years with an additional day YYYY-02-29, where the
17263	//		year number is a multiple of four with the following exception: If
17264	//		a year is a multiple of 100, then it is only a leap year if it is
17265	//		also a multiple of 400. For example, 1900 was not a leap year, but
17266	//		2000 is one.
17267
17268	var year = dateObject.getFullYear();
17269	return !(year%400) || (!(year%4) && !!(year%100)); // Boolean
17270};
17271
17272// FIXME: This is not localized
17273date.getTimezoneName = function(/*Date*/dateObject){
17274	// summary:
17275	//		Get the user's time zone as provided by the browser
17276	// dateObject:
17277	//		Needed because the timezone may vary with time (daylight savings)
17278	// description:
17279	//		Try to get time zone info from toString or toLocaleString method of
17280	//		the Date object -- UTC offset is not a time zone.  See
17281	//		http://www.twinsun.com/tz/tz-link.htm Note: results may be
17282	//		inconsistent across browsers.
17283
17284	var str = dateObject.toString(); // Start looking in toString
17285	var tz = ''; // The result -- return empty string if nothing found
17286	var match;
17287
17288	// First look for something in parentheses -- fast lookup, no regex
17289	var pos = str.indexOf('(');
17290	if(pos > -1){
17291		tz = str.substring(++pos, str.indexOf(')'));
17292	}else{
17293		// If at first you don't succeed ...
17294		// If IE knows about the TZ, it appears before the year
17295		// Capital letters or slash before a 4-digit year
17296		// at the end of string
17297		var pat = /([A-Z\/]+) \d{4}$/;
17298		if((match = str.match(pat))){
17299			tz = match[1];
17300		}else{
17301		// Some browsers (e.g. Safari) glue the TZ on the end
17302		// of toLocaleString instead of putting it in toString
17303			str = dateObject.toLocaleString();
17304			// Capital letters or slash -- end of string,
17305			// after space
17306			pat = / ([A-Z\/]+)$/;
17307			if((match = str.match(pat))){
17308				tz = match[1];
17309			}
17310		}
17311	}
17312
17313	// Make sure it doesn't somehow end up return AM or PM
17314	return (tz == 'AM' || tz == 'PM') ? '' : tz; // String
17315};
17316
17317// Utility methods to do arithmetic calculations with Dates
17318
17319date.compare = function(/*Date*/date1, /*Date?*/date2, /*String?*/portion){
17320	// summary:
17321	//		Compare two date objects by date, time, or both.
17322	// description:
17323	//		Returns 0 if equal, positive if a > b, else negative.
17324	// date1:
17325	//		Date object
17326	// date2:
17327	//		Date object.  If not specified, the current Date is used.
17328	// portion:
vendor: 4,146 bytes, lines 17329-17466
17329	//		A string indicating the "date" or "time" portion of a Date object.
17330	//		Compares both "date" and "time" by default.  One of the following:
17331	//		"date", "time", "datetime"
17332
17333	// Extra step required in copy for IE - see #3112
17334	date1 = new Date(+date1);
17335	date2 = new Date(+(date2 || new Date()));
17336
17337	if(portion == "date"){
17338		// Ignore times and compare dates.
17339		date1.setHours(0, 0, 0, 0);
17340		date2.setHours(0, 0, 0, 0);
17341	}else if(portion == "time"){
17342		// Ignore dates and compare times.
17343		date1.setFullYear(0, 0, 0);
17344		date2.setFullYear(0, 0, 0);
17345	}
17346
17347	if(date1 > date2){ return 1; } // int
17348	if(date1 < date2){ return -1; } // int
17349	return 0; // int
17350};
17351
17352date.add = function(/*Date*/date, /*String*/interval, /*int*/amount){
17353	// summary:
17354	//		Add to a Date in intervals of different size, from milliseconds to years
17355	// date: Date
17356	//		Date object to start with
17357	// interval:
17358	//		A string representing the interval.  One of the following:
17359	//		"year", "month", "day", "hour", "minute", "second",
17360	//		"millisecond", "quarter", "week", "weekday"
17361	// amount:
17362	//		How much to add to the date.
17363
17364	var sum = new Date(+date); // convert to Number before copying to accommodate IE (#3112)
17365	var fixOvershoot = false;
17366	var property = "Date";
17367
17368	switch(interval){
17369		case "day":
17370			break;
17371		case "weekday":
17372			//i18n FIXME: assumes Saturday/Sunday weekend, but this is not always true.  see dojo/cldr/supplemental
17373
17374			// Divide the increment time span into weekspans plus leftover days
17375			// e.g., 8 days is one 5-day weekspan / and two leftover days
17376			// Can't have zero leftover days, so numbers divisible by 5 get
17377			// a days value of 5, and the remaining days make up the number of weeks
17378			var days, weeks;
17379			var mod = amount % 5;
17380			if(!mod){
17381				days = (amount > 0) ? 5 : -5;
17382				weeks = (amount > 0) ? ((amount-5)/5) : ((amount+5)/5);
17383			}else{
17384				days = mod;
17385				weeks = parseInt(amount/5);
17386			}
17387			// Get weekday value for orig date param
17388			var strt = date.getDay();
17389			// Orig date is Sat / positive incrementer
17390			// Jump over Sun
17391			var adj = 0;
17392			if(strt == 6 && amount > 0){
17393				adj = 1;
17394			}else if(strt == 0 && amount < 0){
17395			// Orig date is Sun / negative incrementer
17396			// Jump back over Sat
17397				adj = -1;
17398			}
17399			// Get weekday val for the new date
17400			var trgt = strt + days;
17401			// New date is on Sat or Sun
17402			if(trgt == 0 || trgt == 6){
17403				adj = (amount > 0) ? 2 : -2;
17404			}
17405			// Increment by number of weeks plus leftover days plus
17406			// weekend adjustments
17407			amount = (7 * weeks) + days + adj;
17408			break;
17409		case "year":
17410			property = "FullYear";
17411			// Keep increment/decrement from 2/29 out of March
17412			fixOvershoot = true;
17413			break;
17414		case "week":
17415			amount *= 7;
17416			break;
17417		case "quarter":
17418			// Naive quarter is just three months
17419			amount *= 3;
17420			// fallthrough...
17421		case "month":
17422			// Reset to last day of month if you overshoot
17423			fixOvershoot = true;
17424			property = "Month";
17425			break;
17426//		case "hour":
17427//		case "minute":
17428//		case "second":
17429//		case "millisecond":
17430		default:
17431			property = "UTC"+interval.charAt(0).toUpperCase() + interval.substring(1) + "s";
17432	}
17433
17434	if(property){
17435		sum["set"+property](sum["get"+property]()+amount);
17436	}
17437
17438	if(fixOvershoot && (sum.getDate() < date.getDate())){
17439		sum.setDate(0);
17440	}
17441
17442	return sum; // Date
17443};
17444
17445date.difference = function(/*Date*/date1, /*Date?*/date2, /*String?*/interval){
17446	// summary:
17447	//		Get the difference in a specific unit of time (e.g., number of
17448	//		months, weeks, days, etc.) between two dates, rounded to the
17449	//		nearest integer.
17450	// date1:
17451	//		Date object
17452	// date2:
17453	//		Date object.  If not specified, the current Date is used.
17454	// interval:
17455	//		A string representing the interval.  One of the following:
17456	//		"year", "month", "day", "hour", "minute", "second",
17457	//		"millisecond", "quarter", "week", "weekday"
17458	//
17459	//		Defaults to "day".
17460
17461	date2 = date2 || new Date();
17462	interval = interval || "day";
17463	var yearDiff = date2.getFullYear() - date1.getFullYear();
17464	var delta = 1; // Integer return value
17465
17466	switch(interval){
17467		case "quarter":
17468			var m1 = date1.getMonth();
17469			var m2 = date2.getMonth();
17470			// Figure out which quarter the months are in
17471			var q1 = Math.floor(m1/3) + 1;
17472			var q2 = Math.floor(m2/3) + 1;
17473			// Add quarters for any year difference between the dates
17474			q2 += (yearDiff * 4);
17475			delta = q2 - q1;
17476			break;
17477		case "weekday":
17478			var days = Math.round(date.difference(date1, date2, "day"));
17479			var weeks = parseInt(date.difference(date1, date2, "week"));
17480			var mod = days % 7;
17481
17482			// Even number of weeks
17483			if(mod == 0){
17484				days = weeks*5;
17485			}else{
17486				// Weeks plus spare change (< 7 days)
17487				var adj = 0;
17488				var aDay = date1.getDay();
17489				var bDay = date2.getDay();
17490
17491				weeks = parseInt(days/7);
17492				mod = days % 7;
17493				// Mark the date advanced by the number of
17494				// round weeks (may be zero)
17495				var dtMark = new Date(date1);
17496				dtMark.setDate(dtMark.getDate()+(weeks*7));
17497				var dayMark = dtMark.getDay();
17498
17499				// Spare change days -- 6 or less
17500				if(days > 0){
17501					switch(true){
17502						// Range starts on Sat
17503						case aDay == 6:
17504							adj = -1;
17505							break;
17506						// Range starts on Sun
17507						case aDay == 0:
17508							adj = 0;
17509							break;
17510						// Range ends on Sat
17511						case bDay == 6:
17512							adj = -1;
17513							break;
17514						// Range ends on Sun
17515						case bDay == 0:
17516							adj = -2;
17517							break;
17518						// Range contains weekend
17519						case (dayMark + mod) > 5:
17520							adj = -2;
17521					}
17522				}else if(days < 0){
17523					switch(true){
17524						// Range starts on Sat
17525						case aDay == 6:
17526							adj = 0;
17527							break;
17528						// Range starts on Sun
17529						case aDay == 0:
17530							adj = 1;
17531							break;
17532						// Range ends on Sat
17533						case bDay == 6:
17534							adj = 2;
17535							break;
17536						// Range ends on Sun
17537						case bDay == 0:
17538							adj = 1;
17539							break;
17540						// Range contains weekend
17541						case (dayMark + mod) < 0:
17542							adj = 2;
17543					}
17544				}
17545				days += adj;
17546				days -= (weeks*2);
17547			}
17548			delta = days;
17549			break;
17550		case "year":
17551			delta = yearDiff;
17552			break;
17553		case "month":
17554			delta = (date2.getMonth() - date1.getMonth()) + (yearDiff * 12);
17555			break;
17556		case "week":
17557			// Truncate instead of rounding
17558			// Don't use Math.floor -- value may be negative
17559			delta = parseInt(date.difference(date1, date2, "day")/7);
17560			break;
17561		case "day":
17562			delta /= 24;
17563			// fallthrough
17564		case "hour":
17565			delta /= 60;
17566			// fallthrough
17567		case "minute":
17568			delta /= 60;
17569			// fallthrough
17570		case "second":
17571			delta /= 1000;
17572			// fallthrough
17573		case "millisecond":
17574			delta *= date2.getTime() - date1.getTime();
17575	}
17576
17577	// Round for fractional values and DST leaps
17578	return Math.round(delta); // Number (integer)
17579};
17580
17581// Don't use setObject() because it may overwrite dojo/date/stamp (if that has already been loaded)
17582 1  && lang.mixin(lang.getObject("dojo.date", true), date);
17583
17584return date;
17585});
17586
17587},
17588'dojo/cldr/supplemental':function(){
17589define(["../_base/lang", "../i18n"], function(lang, i18n){
17590
17591// module:
17592//		dojo/cldr/supplemental
17593
17594
17595var supplemental = {
17596	// summary:
17597	//		TODOC
17598};
17599lang.setObject("dojo.cldr.supplemental", supplemental);
17600
17601supplemental.getFirstDayOfWeek = function(/*String?*/locale){
17602	// summary:
17603	//		Returns a zero-based index for first day of the week
17604	// description:
17605	//		Returns a zero-based index for first day of the week, as used by the local (Gregorian) calendar.
17606	//		e.g. Sunday (returns 0), or Monday (returns 1)
17607
17608	// from http://www.unicode.org/cldr/data/common/supplemental/supplementalData.xml:supplementalData/weekData/firstDay
17609	var firstDay = {/*default is 1=Monday*/
17610		bd:5,mv:5,
17611		ae:6,af:6,bh:6,dj:6,dz:6,eg:6,iq:6,ir:6,jo:6,kw:6,
17612		ly:6,ma:6,om:6,qa:6,sa:6,sd:6,sy:6,ye:6,
17613		ag:0,ar:0,as:0,au:0,br:0,bs:0,bt:0,bw:0,by:0,bz:0,ca:0,cn:0,
17614		co:0,dm:0,'do':0,et:0,gt:0,gu:0,hk:0,hn:0,id:0,ie:0,il:0,'in':0,
17615		jm:0,jp:0,ke:0,kh:0,kr:0,la:0,mh:0,mm:0,mo:0,mt:0,mx:0,mz:0,
17616		ni:0,np:0,nz:0,pa:0,pe:0,ph:0,pk:0,pr:0,py:0,sg:0,sv:0,th:0,
17617		tn:0,tt:0,tw:0,um:0,us:0,ve:0,vi:0,ws:0,za:0,zw:0
17618	};
17619
17620	var country = supplemental._region(locale);
17621	var dow = firstDay[country];
17622	return (dow === undefined) ? 1 : dow; /*Number*/
17623};
17624
17625supplemental._region = function(/*String?*/locale){
17626	locale = i18n.normalizeLocale(locale);
17627	var tags = locale.split('-');
17628	var region = tags[1];
17629	if(!region){
17630		// IE often gives language only (#2269)
17631		// Arbitrary mappings of language-only locales to a country:
17632		region = {
17633			aa:"et", ab:"ge", af:"za", ak:"gh", am:"et", ar:"eg", as:"in", av:"ru", ay:"bo", az:"az", ba:"ru",
17634			be:"by", bg:"bg", bi:"vu", bm:"ml", bn:"bd", bo:"cn", br:"fr", bs:"ba", ca:"es", ce:"ru", ch:"gu",
17635			co:"fr", cr:"ca", cs:"cz", cv:"ru", cy:"gb", da:"dk", de:"de", dv:"mv", dz:"bt", ee:"gh", el:"gr",
17636			en:"us", es:"es", et:"ee", eu:"es", fa:"ir", ff:"sn", fi:"fi", fj:"fj", fo:"fo", fr:"fr", fy:"nl",
17637			ga:"ie", gd:"gb", gl:"es", gn:"py", gu:"in", gv:"gb", ha:"ng", he:"il", hi:"in", ho:"pg", hr:"hr",
17638			ht:"ht", hu:"hu", hy:"am", ia:"fr", id:"id", ig:"ng", ii:"cn", ik:"us", "in":"id", is:"is", it:"it",
17639			iu:"ca", iw:"il", ja:"jp", ji:"ua", jv:"id", jw:"id", ka:"ge", kg:"cd", ki:"ke", kj:"na", kk:"kz",
17640			kl:"gl", km:"kh", kn:"in", ko:"kr", ks:"in", ku:"tr", kv:"ru", kw:"gb", ky:"kg", la:"va", lb:"lu",
17641			lg:"ug", li:"nl", ln:"cd", lo:"la", lt:"lt", lu:"cd", lv:"lv", mg:"mg", mh:"mh", mi:"nz", mk:"mk",
17642			ml:"in", mn:"mn", mo:"ro", mr:"in", ms:"my", mt:"mt", my:"mm", na:"nr", nb:"no", nd:"zw", ne:"np",
17643			ng:"na", nl:"nl", nn:"no", no:"no", nr:"za", nv:"us", ny:"mw", oc:"fr", om:"et", or:"in", os:"ge",
17644			pa:"in", pl:"pl", ps:"af", pt:"br", qu:"pe", rm:"ch", rn:"bi", ro:"ro", ru:"ru", rw:"rw", sa:"in",
17645			sd:"in", se:"no", sg:"cf", si:"lk", sk:"sk", sl:"si", sm:"ws", sn:"zw", so:"so", sq:"al", sr:"rs",
17646			ss:"za", st:"za", su:"id", sv:"se", sw:"tz", ta:"in", te:"in", tg:"tj", th:"th", ti:"et", tk:"tm",
17647			tl:"ph", tn:"za", to:"to", tr:"tr", ts:"za", tt:"ru", ty:"pf", ug:"cn", uk:"ua", ur:"pk", uz:"uz",
17648			ve:"za", vi:"vn", wa:"be", wo:"sn", xh:"za", yi:"il", yo:"ng", za:"cn", zh:"cn", zu:"za",
17649			ace:"id", ady:"ru", agq:"cm", alt:"ru", amo:"ng", asa:"tz", ast:"es", awa:"in", bal:"pk",
17650			ban:"id", bas:"cm", bax:"cm", bbc:"id", bem:"zm", bez:"tz", bfq:"in", bft:"pk", bfy:"in",
17651			bhb:"in", bho:"in", bik:"ph", bin:"ng", bjj:"in", bku:"ph", bqv:"ci", bra:"in", brx:"in",
17652			bss:"cm", btv:"pk", bua:"ru", buc:"yt", bug:"id", bya:"id", byn:"er", cch:"ng", ccp:"in",
17653			ceb:"ph", cgg:"ug", chk:"fm", chm:"ru", chp:"ca", chr:"us", cja:"kh", cjm:"vn", ckb:"iq",
17654			crk:"ca", csb:"pl", dar:"ru", dav:"ke", den:"ca", dgr:"ca", dje:"ne", doi:"in", dsb:"de",
17655			dua:"cm", dyo:"sn", dyu:"bf", ebu:"ke", efi:"ng", ewo:"cm", fan:"gq", fil:"ph", fon:"bj",
17656			fur:"it", gaa:"gh", gag:"md", gbm:"in", gcr:"gf", gez:"et", gil:"ki", gon:"in", gor:"id",
17657			grt:"in", gsw:"ch", guz:"ke", gwi:"ca", haw:"us", hil:"ph", hne:"in", hnn:"ph", hoc:"in",
17658			hoj:"in", ibb:"ng", ilo:"ph", inh:"ru", jgo:"cm", jmc:"tz", kaa:"uz", kab:"dz", kaj:"ng",
17659			kam:"ke", kbd:"ru", kcg:"ng", kde:"tz", kdt:"th", kea:"cv", ken:"cm", kfo:"ci", kfr:"in",
17660			kha:"in", khb:"cn", khq:"ml", kht:"in", kkj:"cm", kln:"ke", kmb:"ao", koi:"ru", kok:"in",
17661			kos:"fm", kpe:"lr", krc:"ru", kri:"sl", krl:"ru", kru:"in", ksb:"tz", ksf:"cm", ksh:"de",
17662			kum:"ru", lag:"tz", lah:"pk", lbe:"ru", lcp:"cn", lep:"in", lez:"ru", lif:"np", lis:"cn",
17663			lki:"ir", lmn:"in", lol:"cd", lua:"cd", luo:"ke", luy:"ke", lwl:"th", mad:"id", mag:"in",
17664			mai:"in", mak:"id", man:"gn", mas:"ke", mdf:"ru", mdh:"ph", mdr:"id", men:"sl", mer:"ke",
17665			mfe:"mu", mgh:"mz", mgo:"cm", min:"id", mni:"in", mnk:"gm", mnw:"mm", mos:"bf", mua:"cm",
17666			mwr:"in", myv:"ru", nap:"it", naq:"na", nds:"de", "new":"np", niu:"nu", nmg:"cm", nnh:"cm",
17667			nod:"th", nso:"za", nus:"sd", nym:"tz", nyn:"ug", pag:"ph", pam:"ph", pap:"bq", pau:"pw",
17668			pon:"fm", prd:"ir", raj:"in", rcf:"re", rej:"id", rjs:"np", rkt:"in", rof:"tz", rwk:"tz",
17669			saf:"gh", sah:"ru", saq:"ke", sas:"id", sat:"in", saz:"in", sbp:"tz", scn:"it", sco:"gb",
17670			sdh:"ir", seh:"mz", ses:"ml", shi:"ma", shn:"mm", sid:"et", sma:"se", smj:"se", smn:"fi",
17671			sms:"fi", snk:"ml", srn:"sr", srr:"sn", ssy:"er", suk:"tz", sus:"gn", swb:"yt", swc:"cd",
17672			syl:"bd", syr:"sy", tbw:"ph", tcy:"in", tdd:"cn", tem:"sl", teo:"ug", tet:"tl", tig:"er",
17673			tiv:"ng", tkl:"tk", tmh:"ne", tpi:"pg", trv:"tw", tsg:"ph", tts:"th", tum:"mw", tvl:"tv",
17674			twq:"ne", tyv:"ru", tzm:"ma", udm:"ru", uli:"fm", umb:"ao", unr:"in", unx:"in", vai:"lr",
17675			vun:"tz", wae:"ch", wal:"et", war:"ph", xog:"ug", xsr:"np", yao:"mz", yap:"fm", yav:"cm", zza:"tr"
17676		}[tags[0]];
17677	}else if(region.length == 4){
17678		// The ISO 3166 country code is usually in the second position, unless a
17679		// 4-letter script is given. See http://www.ietf.org/rfc/rfc4646.txt
17680		region = tags[2];
17681	}
17682	return region;
17683};
17684
17685supplemental.getWeekend = function(/*String?*/locale){
17686	// summary:
17687	//		Returns a hash containing the start and end days of the weekend
17688	// description:
17689	//		Returns a hash containing the start and end days of the weekend according to local custom using locale,
17690	//		or by default in the user's locale.
17691	//		e.g. {start:6, end:0}
17692
17693	// from http://www.unicode.org/cldr/data/common/supplemental/supplementalData.xml:supplementalData/weekData/weekend{Start,End}
17694	var weekendStart = {/*default is 6=Saturday*/
17695			'in':0,
17696			af:4,dz:4,ir:4,om:4,sa:4,ye:4,
17697			ae:5,bh:5,eg:5,il:5,iq:5,jo:5,kw:5,ly:5,ma:5,qa:5,sd:5,sy:5,tn:5
17698		},
17699
17700		weekendEnd = {/*default is 0=Sunday*/
17701			af:5,dz:5,ir:5,om:5,sa:5,ye:5,
17702			ae:6,bh:5,eg:6,il:6,iq:6,jo:6,kw:6,ly:6,ma:6,qa:6,sd:6,sy:6,tn:6
17703		},
17704
17705		country = supplemental._region(locale),
17706		start = weekendStart[country],
17707		end = weekendEnd[country];
17708
17709	if(start === undefined){start=6;}
17710	if(end === undefined){end=0;}
17711	return {start:start, end:end}; /*Object {start,end}*/
17712};
17713
17714return supplemental;
17715});
17716
17717},
17718'dojo/i18n':function(){
17719define(["./_base/kernel", "require", "./has", "./_base/array", "./_base/config", "./_base/lang", "./_base/xhr", "./json", "module"],
17720	function(dojo, require, has, array, config, lang, xhr, json, module){
17721
17722	// module:
17723	//		dojo/i18n
17724
17725	has.add("dojo-preload-i18n-Api",
17726		// if true, define the preload localizations machinery
17727		1
17728	);
17729
17730	 1 || has.add("dojo-v1x-i18n-Api",
17731		// if true, define the v1.x i18n functions
17732		1
17733	);
17734
17735	var
17736		thisModule = dojo.i18n =
17737			{
17738				// summary:
17739				//		This module implements the dojo/i18n! plugin and the v1.6- i18n API
17740				// description:
17741				//		We choose to include our own plugin to leverage functionality already contained in dojo
17742				//		and thereby reduce the size of the plugin compared to various loader implementations. Also, this
17743				//		allows foreign AMD loaders to be used without their plugins.
17744			},
17745
17746		nlsRe =
17747			// regexp for reconstructing the master bundle name from parts of the regexp match
17748			// nlsRe.exec("foo/bar/baz/nls/en-ca/foo") gives:
17749			// ["foo/bar/baz/nls/en-ca/foo", "foo/bar/baz/nls/", "/", "/", "en-ca", "foo"]
17750			// nlsRe.exec("foo/bar/baz/nls/foo") gives:
17751			// ["foo/bar/baz/nls/foo", "foo/bar/baz/nls/", "/", "/", "foo", ""]
17752			// so, if match[5] is blank, it means this is the top bundle definition.
17753			// courtesy of http://requirejs.org
17754			/(^.*(^|\/)nls)(\/|$)([^\/]*)\/?([^\/]*)/,
17755
17756		getAvailableLocales = function(
17757			root,
17758			locale,
17759			bundlePath,
17760			bundleName
17761		){
17762			// summary:
17763			//		return a vector of module ids containing all available locales with respect to the target locale
17764			//		For example, assuming:
17765			//
17766			//		- the root bundle indicates specific bundles for "fr" and "fr-ca",
17767			//		-  bundlePath is "myPackage/nls"
17768			//		- bundleName is "myBundle"
17769			//
17770			//		Then a locale argument of "fr-ca" would return
17771			//
17772			//			["myPackage/nls/myBundle", "myPackage/nls/fr/myBundle", "myPackage/nls/fr-ca/myBundle"]
17773			//
17774			//		Notice that bundles are returned least-specific to most-specific, starting with the root.
17775			//
17776			//		If root===false indicates we're working with a pre-AMD i18n bundle that doesn't tell about the available locales;
17777			//		therefore, assume everything is available and get 404 errors that indicate a particular localization is not available
17778
17779			for(var result = [bundlePath + bundleName], localeParts = locale.split("-"), current = "", i = 0; i<localeParts.length; i++){
17780				current += (current ? "-" : "") + localeParts[i];
vendor: 4,976 bytes, lines 17781-17892
17781				if(!root || root[current]){
17782					result.push(bundlePath + current + "/" + bundleName);
17783					result.specificity = current;
17784				}
17785			}
17786			return result;
17787		},
17788
17789		cache = {},
17790
17791		getBundleName = function(moduleName, bundleName, locale){
17792			locale = locale ? locale.toLowerCase() : dojo.locale;
17793			moduleName = moduleName.replace(/\./g, "/");
17794			bundleName = bundleName.replace(/\./g, "/");
17795			return (/root/i.test(locale)) ?
17796				(moduleName + "/nls/" + bundleName) :
17797				(moduleName + "/nls/" + locale + "/" + bundleName);
17798		},
17799
17800		getL10nName = dojo.getL10nName = function(moduleName, bundleName, locale){
17801			return moduleName = module.id + "!" + getBundleName(moduleName, bundleName, locale);
17802		},
17803
17804		doLoad = function(require, bundlePathAndName, bundlePath, bundleName, locale, load){
17805			// summary:
17806			//		get the root bundle which instructs which other bundles are required to construct the localized bundle
17807			require([bundlePathAndName], function(root){
17808				var current = lang.clone(root.root || root.ROOT),// 1.6 built bundle defined ROOT
17809					availableLocales = getAvailableLocales(!root._v1x && root, locale, bundlePath, bundleName);
17810				require(availableLocales, function(){
17811					for (var i = 1; i<availableLocales.length; i++){
17812						current = lang.mixin(lang.clone(current), arguments[i]);
17813					}
17814					// target may not have been resolve (e.g., maybe only "fr" exists when "fr-ca" was requested)
17815					var target = bundlePathAndName + "/" + locale;
17816					cache[target] = current;
17817					current.$locale = availableLocales.specificity;
17818					load();
17819				});
17820			});
17821		},
17822
17823		normalize = function(id, toAbsMid){
17824			// summary:
17825			//		id may be relative.
17826			//		preload has form `*preload*<path>/nls/<module>*<flattened locales>` and
17827			//		therefore never looks like a relative
17828			return /^\./.test(id) ? toAbsMid(id) : id;
17829		},
17830
17831		getLocalesToLoad = function(targetLocale){
17832			var list = config.extraLocale || [];
17833			list = lang.isArray(list) ? list : [list];
17834			list.push(targetLocale);
17835			return list;
17836		},
17837
17838		load = function(id, require, load){
17839			// summary:
17840			//		id is in one of the following formats
17841			//
17842			//		1. <path>/nls/<bundle>
17843			//			=> load the bundle, localized to config.locale; load all bundles localized to
17844			//			config.extraLocale (if any); return the loaded bundle localized to config.locale.
17845			//
17846			//		2. <path>/nls/<locale>/<bundle>
17847			//			=> load then return the bundle localized to <locale>
17848			//
17849			//		3. *preload*<path>/nls/<module>*<JSON array of available locales>
17850			//			=> for config.locale and all config.extraLocale, load all bundles found
17851			//			in the best-matching bundle rollup. A value of 1 is returned, which
17852			//			is meaningless other than to say the plugin is executing the requested
17853			//			preloads
17854			//
17855			//		In cases 1 and 2, <path> is always normalized to an absolute module id upon entry; see
17856			//		normalize. In case 3, it <path> is assumed to be absolute; this is arranged by the builder.
17857			//
17858			//		To load a bundle means to insert the bundle into the plugin's cache and publish the bundle
17859			//		value to the loader. Given <path>, <bundle>, and a particular <locale>, the cache key
17860			//
17861			//			<path>/nls/<bundle>/<locale>
17862			//
17863			//		will hold the value. Similarly, then plugin will publish this value to the loader by
17864			//
17865			//			define("<path>/nls/<bundle>/<locale>", <bundle-value>);
17866			//
17867			//		Given this algorithm, other machinery can provide fast load paths be preplacing
17868			//		values in the plugin's cache, which is public. When a load is demanded the
17869			//		cache is inspected before starting any loading. Explicitly placing values in the plugin
17870			//		cache is an advanced/experimental feature that should not be needed; use at your own risk.
17871			//
17872			//		For the normal AMD algorithm, the root bundle is loaded first, which instructs the
17873			//		plugin what additional localized bundles are required for a particular locale. These
17874			//		additional locales are loaded and a mix of the root and each progressively-specific
17875			//		locale is returned. For example:
17876			//
17877			//		1. The client demands "dojo/i18n!some/path/nls/someBundle
17878			//
17879			//		2. The loader demands load(some/path/nls/someBundle)
17880			//
17881			//		3. This plugin require's "some/path/nls/someBundle", which is the root bundle.
17882			//
17883			//		4. Assuming config.locale is "ab-cd-ef" and the root bundle indicates that localizations
17884			//		are available for "ab" and "ab-cd-ef" (note the missing "ab-cd", then the plugin
17885			//		requires "some/path/nls/ab/someBundle" and "some/path/nls/ab-cd-ef/someBundle"
17886			//
17887			//		5. Upon receiving all required bundles, the plugin constructs the value of the bundle
17888			//		ab-cd-ef as...
17889			//
17890			//				mixin(mixin(mixin({}, require("some/path/nls/someBundle"),
17891			//		  			require("some/path/nls/ab/someBundle")),
17892			//					require("some/path/nls/ab-cd-ef/someBundle"));
17893			//
17894			//		This value is inserted into the cache and published to the loader at the
17895			//		key/module-id some/path/nls/someBundle/ab-cd-ef.
17896			//
17897			//		The special preload signature (case 3) instructs the plugin to stop servicing all normal requests
17898			//		(further preload requests will be serviced) until all ongoing preloading has completed.
17899			//
17900			//		The preload signature instructs the plugin that a special rollup module is available that contains
17901			//		one or more flattened, localized bundles. The JSON array of available locales indicates which locales
17902			//		are available. Here is an example:
17903			//
17904			//			*preload*some/path/nls/someModule*["root", "ab", "ab-cd-ef"]
17905			//
17906			//		This indicates the following rollup modules are available:
17907			//
17908			//			some/path/nls/someModule_ROOT
17909			//			some/path/nls/someModule_ab
17910			//			some/path/nls/someModule_ab-cd-ef
17911			//
17912			//		Each of these modules is a normal AMD module that contains one or more flattened bundles in a hash.
17913			//		For example, assume someModule contained the bundles some/bundle/path/someBundle and
17914			//		some/bundle/path/someOtherBundle, then some/path/nls/someModule_ab would be expressed as follows:
17915			//
17916			//			define({
17917			//				some/bundle/path/someBundle:<value of someBundle, flattened with respect to locale ab>,
17918			//				some/bundle/path/someOtherBundle:<value of someOtherBundle, flattened with respect to locale ab>,
17919			//			});
17920			//
17921			//		E.g., given this design, preloading for locale=="ab" can execute the following algorithm:
17922			//
17923			//			require(["some/path/nls/someModule_ab"], function(rollup){
17924			//				for(var p in rollup){
17925			//					var id = p + "/ab",
17926			//					cache[id] = rollup[p];
17927			//					define(id, rollup[p]);
17928			//				}
17929			//			});
17930			//
17931			//		Similarly, if "ab-cd" is requested, the algorithm can determine that "ab" is the best available and
17932			//		load accordingly.
17933			//
17934			//		The builder will write such rollups for every layer if a non-empty localeList  profile property is
17935			//		provided. Further, the builder will include the following cache entry in the cache associated with
17936			//		any layer.
17937			//
17938			//			"*now":function(r){r(['dojo/i18n!*preload*<path>/nls/<module>*<JSON array of available locales>']);}
17939			//
17940			//		The *now special cache module instructs the loader to apply the provided function to context-require
17941			//		with respect to the particular layer being defined. This causes the plugin to hold all normal service
17942			//		requests until all preloading is complete.
17943			//
17944			//		Notice that this algorithm is rarely better than the standard AMD load algorithm. Consider the normal case
17945			//		where the target locale has a single segment and a layer depends on a single bundle:
17946			//
17947			//		Without Preloads:
17948			//
17949			//		1. Layer loads root bundle.
17950			//		2. bundle is demanded; plugin loads single localized bundle.
17951			//
17952			//		With Preloads:
17953			//
17954			//		1. Layer causes preloading of target bundle.
17955			//		2. bundle is demanded; service is delayed until preloading complete; bundle is returned.
17956			//
17957			//		In each case a single transaction is required to load the target bundle. In cases where multiple bundles
17958			//		are required and/or the locale has multiple segments, preloads still requires a single transaction whereas
17959			//		the normal path requires an additional transaction for each additional bundle/locale-segment. However all
17960			//		of these additional transactions can be done concurrently. Owing to this analysis, the entire preloading
17961			//		algorithm can be discard during a build by setting the has feature dojo-preload-i18n-Api to false.
17962
17963			if(has("dojo-preload-i18n-Api")){
17964				var split = id.split("*"),
17965					preloadDemand = split[1] == "preload";
17966				if(preloadDemand){
17967					if(!cache[id]){
17968						// use cache[id] to prevent multiple preloads of the same preload; this shouldn't happen, but
17969						// who knows what over-aggressive human optimizers may attempt
17970						cache[id] = 1;
17971						preloadL10n(split[2], json.parse(split[3]), 1, require);
17972					}
17973					// don't stall the loader!
17974					load(1);
17975				}
17976				if(preloadDemand || waitForPreloads(id, require, load)){
17977					return;
17978				}
17979			}
17980
17981			var match = nlsRe.exec(id),
17982				bundlePath = match[1] + "/",
17983				bundleName = match[5] || match[4],
17984				bundlePathAndName = bundlePath + bundleName,
17985				localeSpecified = (match[5] && match[4]),
vendor: 7,290 bytes, lines 17986-18161
17986				targetLocale =	localeSpecified || dojo.locale || "",
17987				loadTarget = bundlePathAndName + "/" + targetLocale,
17988				loadList = localeSpecified ? [targetLocale] : getLocalesToLoad(targetLocale),
17989				remaining = loadList.length,
17990				finish = function(){
17991					if(!--remaining){
17992						load(lang.delegate(cache[loadTarget]));
17993					}
17994				};
17995			array.forEach(loadList, function(locale){
17996				var target = bundlePathAndName + "/" + locale;
17997				if(has("dojo-preload-i18n-Api")){
17998					checkForLegacyModules(target);
17999				}
18000				if(!cache[target]){
18001					doLoad(require, bundlePathAndName, bundlePath, bundleName, locale, finish);
18002				}else{
18003					finish();
18004				}
18005			});
18006		};
18007
18008	if(has("dojo-unit-tests")){
18009		var unitTests = thisModule.unitTests = [];
18010	}
18011
18012	if(has("dojo-preload-i18n-Api") ||  1 ){
18013		var normalizeLocale = thisModule.normalizeLocale = function(locale){
18014				var result = locale ? locale.toLowerCase() : dojo.locale;
18015				return result == "root" ? "ROOT" : result;
18016			},
18017
18018			isXd = function(mid, contextRequire){
18019				return ( 0  &&  1 ) ?
18020					contextRequire.isXdUrl(require.toUrl(mid + ".js")) :
18021					true;
18022			},
18023
18024			preloading = 0,
18025
18026			preloadWaitQueue = [],
18027
18028			preloadL10n = thisModule._preloadLocalizations = function(/*String*/bundlePrefix, /*Array*/localesGenerated, /*boolean?*/ guaranteedAmdFormat, /*function?*/ contextRequire){
18029				// summary:
18030				//		Load available flattened resource bundles associated with a particular module for dojo/locale and all dojo/config.extraLocale (if any)
18031				// description:
18032				//		Only called by built layer files. The entire locale hierarchy is loaded. For example,
18033				//		if locale=="ab-cd", then ROOT, "ab", and "ab-cd" are loaded. This is different than v1.6-
18034				//		in that the v1.6- would only load ab-cd...which was *always* flattened.
18035				//
18036				//		If guaranteedAmdFormat is true, then the module can be loaded with require thereby circumventing the detection algorithm
18037				//		and the extra possible extra transaction.
18038
18039				// If this function is called from legacy code, then guaranteedAmdFormat and contextRequire will be undefined. Since the function
18040				// needs a require in order to resolve module ids, fall back to the context-require associated with this dojo/i18n module, which
18041				// itself may have been mapped.
18042				contextRequire = contextRequire || require;
18043
18044				function doRequire(mid, callback){
18045					if(isXd(mid, contextRequire) || guaranteedAmdFormat){
18046						contextRequire([mid], callback);
18047					}else{
18048						syncRequire([mid], callback, contextRequire);
18049					}
18050				}
18051
18052				function forEachLocale(locale, func){
18053					// given locale= "ab-cd-ef", calls func on "ab-cd-ef", "ab-cd", "ab", "ROOT"; stops calling the first time func returns truthy
18054					var parts = locale.split("-");
18055					while(parts.length){
18056						if(func(parts.join("-"))){
18057							return;
18058						}
18059						parts.pop();
18060					}
18061					func("ROOT");
18062				}
18063
18064					function preloadingAddLock(){
18065						preloading++;
18066					}
18067
18068					function preloadingRelLock(){
18069						--preloading;
18070						while(!preloading && preloadWaitQueue.length){
18071							load.apply(null, preloadWaitQueue.shift());
18072						}
18073					}
18074
18075					function cacheId(path, name, loc, require){
18076						// path is assumed to have a trailing "/"
18077						return require.toAbsMid(path + name + "/" + loc)
18078					}
18079
18080					function preload(locale){
18081						locale = normalizeLocale(locale);
18082						forEachLocale(locale, function(loc){
18083							if(array.indexOf(localesGenerated, loc) >= 0){
18084								var mid = bundlePrefix.replace(/\./g, "/") + "_" + loc;
18085								preloadingAddLock();
18086								doRequire(mid, function(rollup){
18087									for(var p in rollup){
18088										var bundle = rollup[p],
18089											match = p.match(/(.+)\/([^\/]+)$/),
18090											bundleName, bundlePath;
18091											
18092											// If there is no match, the bundle is not a regular bundle from an AMD layer.
18093											if (!match){continue;}
18094
18095											bundleName = match[2];
18096											bundlePath = match[1] + "/";
18097
18098										// backcompat
18099										bundle._localized = bundle._localized || {};
18100
18101										var localized;
18102										if(loc === "ROOT"){
18103											var root = localized = bundle._localized;
18104											delete bundle._localized;
18105											root.root = bundle;
18106											cache[require.toAbsMid(p)] = root;
18107										}else{
18108											localized = bundle._localized;
18109											cache[cacheId(bundlePath, bundleName, loc, require)] = bundle;
18110										}
18111
18112										if(loc !== locale){
18113											// capture some locale variables
18114											function improveBundle(bundlePath, bundleName, bundle, localized){
18115												// locale was not flattened and we've fallen back to a less-specific locale that was flattened
18116												// for example, we had a flattened 'fr', a 'fr-ca' is available for at least this bundle, and
18117												// locale==='fr-ca'; therefore, we must improve the bundle as retrieved from the rollup by
18118												// manually loading the fr-ca version of the bundle and mixing this into the already-retrieved 'fr'
18119												// version of the bundle.
18120												//
18121												// Remember, different bundles may have different sets of locales available.
18122												//
18123												// we are really falling back on the regular algorithm here, but--hopefully--starting with most
18124												// of the required bundles already on board as given by the rollup and we need to "manually" load
18125												// only one locale from a few bundles...or even better...we won't find anything better to load.
18126												// This algorithm ensures there is nothing better to load even when we can only load a less-specific rollup.
18127												//
18128												// note: this feature is only available in async mode
18129
18130												// inspect the loaded bundle that came from the rollup to see if something better is available
18131												// for any bundle in a rollup, more-specific available locales are given at localized.
18132												var requiredBundles = [],
18133													cacheIds = [];
18134												forEachLocale(locale, function(loc){
18135													if(localized[loc]){
18136														requiredBundles.push(require.toAbsMid(bundlePath + loc + "/" + bundleName));
18137														cacheIds.push(cacheId(bundlePath, bundleName, loc, require));
18138													}
18139												});
18140
18141												if(requiredBundles.length){
18142													preloadingAddLock();
18143													contextRequire(requiredBundles, function(){
18144														for(var i = 0; i < requiredBundles.length; i++){
18145															bundle = lang.mixin(lang.clone(bundle), arguments[i]);
18146															cache[cacheIds[i]] = bundle;
18147														}
18148														// this is the best possible (maybe a perfect match, maybe not), accept it
18149														cache[cacheId(bundlePath, bundleName, locale, require)] = lang.clone(bundle);
18150														preloadingRelLock();
18151													});
18152												}else{
18153													// this is the best possible (definitely not a perfect match), accept it
18154													cache[cacheId(bundlePath, bundleName, locale, require)] = bundle;
18155												}
18156											}
18157											improveBundle(bundlePath, bundleName, bundle, localized);
18158										}
18159									}
18160									preloadingRelLock();
18161								});
18162								return true;
18163							}
18164							return false;
18165						});
18166					}
18167
18168				preload();
18169				array.forEach(dojo.config.extraLocale, preload);
18170			},
18171
18172			waitForPreloads = function(id, require, load){
18173				if(preloading){
18174					preloadWaitQueue.push([id, require, load]);
18175				}
18176				return preloading;
18177			},
18178
18179			checkForLegacyModules = function()
18180				{};
18181	}
18182
18183	if( 1 ){
18184		// this code path assumes the dojo loader and won't work with a standard AMD loader
18185		var amdValue = {},
18186			evalBundle =
18187				// use the function ctor to keep the minifiers away (also come close to global scope, but this is secondary)
18188				new Function(
18189					"__bundle",				   // the bundle to evalutate
18190					"__checkForLegacyModules", // a function that checks if __bundle defined __mid in the global space
18191					"__mid",				   // the mid that __bundle is intended to define
18192					"__amdValue",
18193
18194					// returns one of:
18195					//		1 => the bundle was an AMD bundle
18196					//		a legacy bundle object that is the value of __mid
18197					//		instance of Error => could not figure out how to evaluate bundle
18198
18199					  // used to detect when __bundle calls define
18200					  "var define = function(mid, factory){define.called = 1; __amdValue.result = factory || mid;},"
18201					+ "	   require = function(){define.called = 1;};"
18202
18203					+ "try{"
18204					+		"define.called = 0;"
18205					+		"eval(__bundle);"
18206					+		"if(define.called==1)"
18207								// bundle called define; therefore signal it's an AMD bundle
18208					+			"return __amdValue;"
18209
18210					+		"if((__checkForLegacyModules = __checkForLegacyModules(__mid)))"
18211								// bundle was probably a v1.6- built NLS flattened NLS bundle that defined __mid in the global space
18212					+			"return __checkForLegacyModules;"
18213
18214					+ "}catch(e){}"
18215					// evaulating the bundle was *neither* an AMD *nor* a legacy flattened bundle
18216					// either way, re-eval *after* surrounding with parentheses
18217
18218					+ "try{"
18219					+		"return eval('('+__bundle+')');"
18220					+ "}catch(e){"
18221					+		"return e;"
18222					+ "}"
18223				),
18224
18225			syncRequire = function(deps, callback, require){
18226				var results = [];
18227				array.forEach(deps, function(mid){
18228					var url = require.toUrl(mid + ".js");
18229
18230					function load(text){
18231						var result = evalBundle(text, checkForLegacyModules, mid, amdValue);
18232						if(result===amdValue){
18233							// the bundle was an AMD module; re-inject it through the normal AMD path
18234							// we gotta do this since it could be an anonymous module and simply evaluating
18235							// the text here won't provide the loader with the context to know what
18236							// module is being defined()'d. With browser caching, this should be free; further
18237							// this entire code path can be circumvented by using the AMD format to begin with
18238							results.push(cache[url] = amdValue.result);
18239						}else{
18240							if(result instanceof Error){
18241								console.error("failed to evaluate i18n bundle; url=" + url, result);
18242								result = {};
18243							}
18244							// nls/<locale>/<bundle-name> indicates not the root.
18245							results.push(cache[url] = (/nls\/[^\/]+\/[^\/]+$/.test(url) ? result : {root:result, _v1x:1}));
18246						}
18247					}
18248
18249					if(cache[url]){
18250						results.push(cache[url]);
18251					}else{
18252						var bundle = require.syncLoadNls(mid);
18253						// don't need to check for legacy since syncLoadNls returns a module if the module
18254						// (1) was already loaded, or (2) was in the cache. In case 1, if syncRequire is called
18255						// from getLocalization --> load, then load will have called checkForLegacyModules() before
18256						// calling syncRequire; if syncRequire is called from preloadLocalizations, then we
18257						// don't care about checkForLegacyModules() because that will be done when a particular
18258						// bundle is actually demanded. In case 2, checkForLegacyModules() is never relevant
18259						// because cached modules are always v1.7+ built modules.
18260						if(bundle){
18261							results.push(bundle);
18262						}else{
18263							if(!xhr){
18264								try{
18265									require.getText(url, true, load);
18266								}catch(e){
18267									results.push(cache[url] = {});
18268								}
18269							}else{
18270								xhr.get({
18271									url:url,
18272									sync:true,
18273									load:load,
18274									error:function(){
18275										results.push(cache[url] = {});
18276									}
18277								});
18278							}
18279						}
18280					}
18281				});
18282				callback && callback.apply(null, results);
18283			};
18284
18285		checkForLegacyModules = function(target){
18286			// legacy code may have already loaded [e.g] the raw bundle x/y/z at x.y.z; when true, push into the cache
18287			for(var result, names = target.split("/"), object = dojo.global[names[0]], i = 1; object && i<names.length-1; object = object[names[i++]]){}
18288			if(object){
18289				result = object[names[i]];
18290				if(!result){
18291					// fallback for incorrect bundle build of 1.6
18292					result = object[names[i].replace(/-/g,"_")];
18293				}
18294				if(result){
18295					cache[target] = result;
18296				}
18297			}
18298			return result;
18299		};
18300
18301		thisModule.getLocalization = function(moduleName, bundleName, locale){
18302			var result,
18303				l10nName = getBundleName(moduleName, bundleName, locale);
18304			load(
18305				l10nName,
18306
18307				// isXd() and syncRequire() need a context-require in order to resolve the mid with respect to a reference module.
18308				// Since this legacy function does not have the concept of a reference module, resolve with respect to this
18309				// dojo/i18n module, which, itself may have been mapped.
18310				(!isXd(l10nName, require) ? function(deps, callback){ syncRequire(deps, callback, require); } : require),
18311
18312				function(result_){ result = result_; }
18313			);
18314			return result;
18315		};
18316
18317		if(has("dojo-unit-tests")){
18318			unitTests.push(function(doh){
18319				doh.register("tests.i18n.unit", function(t){
18320					var check;
18321
18322					check = evalBundle("{prop:1}", checkForLegacyModules, "nonsense", amdValue);
18323					t.is({prop:1}, check); t.is(undefined, check[1]);
18324
18325					check = evalBundle("({prop:1})", checkForLegacyModules, "nonsense", amdValue);
18326					t.is({prop:1}, check); t.is(undefined, check[1]);
18327
18328					check = evalBundle("{'prop-x':1}", checkForLegacyModules, "nonsense", amdValue);
18329					t.is({'prop-x':1}, check); t.is(undefined, check[1]);
18330
18331					check = evalBundle("({'prop-x':1})", checkForLegacyModules, "nonsense", amdValue);
18332					t.is({'prop-x':1}, check); t.is(undefined, check[1]);
18333
18334					check = evalBundle("define({'prop-x':1})", checkForLegacyModules, "nonsense", amdValue);
18335					t.is(amdValue, check); t.is({'prop-x':1}, amdValue.result);
18336
18337					check = evalBundle("define('some/module', {'prop-x':1})", checkForLegacyModules, "nonsense", amdValue);
18338					t.is(amdValue, check); t.is({'prop-x':1}, amdValue.result);
18339
18340					check = evalBundle("this is total nonsense and should throw an error", checkForLegacyModules, "nonsense", amdValue);
18341					t.is(check instanceof Error, true);
18342				});
18343			});
18344		}
18345	}
18346
18347	return lang.mixin(thisModule, {
18348		dynamic:true,
18349		normalize:normalize,
18350		load:load,
18351		cache:cache,
18352		getL10nName: getL10nName
18353	});
18354});
18355
18356},
18357'dojo/regexp':function(){
18358define(["./_base/kernel", "./_base/lang"], function(dojo, lang){
18359
18360// module:
18361//		dojo/regexp
18362
18363var regexp = {
18364	// summary:
18365	//		Regular expressions and Builder resources
18366};
18367lang.setObject("dojo.regexp", regexp);
18368
18369regexp.escapeString = function(/*String*/str, /*String?*/except){
18370	// summary:
18371	//		Adds escape sequences for special characters in regular expressions
18372	// except:
18373	//		a String with special characters to be left unescaped
18374
18375	return str.replace(/([\.$?*|{}\(\)\[\]\\\/\+\-^])/g, function(ch){
18376		if(except && except.indexOf(ch) != -1){
18377			return ch;
18378		}
18379		return "\\" + ch;
18380	}); // String
18381};
18382
18383regexp.buildGroupRE = function(/*Object|Array*/arr, /*Function*/re, /*Boolean?*/nonCapture){
18384	// summary:
18385	//		Builds a regular expression that groups subexpressions
18386	// description:
18387	//		A utility function used by some of the RE generators. The
18388	//		subexpressions are constructed by the function, re, in the second
18389	//		parameter.  re builds one subexpression for each elem in the array
18390	//		a, in the first parameter. Returns a string for a regular
18391	//		expression that groups all the subexpressions.
18392	// arr:
18393	//		A single value or an array of values.
18394	// re:
18395	//		A function. Takes one parameter and converts it to a regular
18396	//		expression.
18397	// nonCapture:
18398	//		If true, uses non-capturing match, otherwise matches are retained
18399	//		by regular expression. Defaults to false
18400
18401	// case 1: a is a single value.
18402	if(!(arr instanceof Array)){
18403		return re(arr); // String
18404	}
18405
18406	// case 2: a is an array
18407	var b = [];
18408	for(var i = 0; i < arr.length; i++){
18409		// convert each elem to a RE
18410		b.push(re(arr[i]));
18411	}
18412
18413	 // join the REs as alternatives in a RE group.
18414	return regexp.group(b.join("|"), nonCapture); // String
18415};
18416
18417regexp.group = function(/*String*/expression, /*Boolean?*/nonCapture){
18418	// summary:
18419	//		adds group match to expression
18420	// nonCapture:
18421	//		If true, uses non-capturing match, otherwise matches are retained
18422	//		by regular expression.
18423	return "(" + (nonCapture ? "?:":"") + expression + ")"; // String
18424};
18425
18426return regexp;
18427});
18428
18429},
18430'dojo/string':function(){
18431define([
18432	"./_base/kernel",	// kernel.global
18433	"./_base/lang"
18434], function(kernel, lang){
18435
18436// module:
18437//		dojo/string
18438var ESCAPE_REGEXP = /[&<>'"\/]/g;
18439var ESCAPE_MAP = {
18440	'&': '&amp;',
18441	'<': '&lt;',
18442	'>': '&gt;',
18443	'"': '&quot;',
18444	"'": '&#x27;',
18445	'/': '&#x2F;'
18446};
18447var string = {
18448	// summary:
18449	//		String utilities for Dojo
18450};
18451lang.setObject("dojo.string", string);
18452
18453string.escape = function(/*String*/str){
18454	// summary:
18455	//		Efficiently escape a string for insertion into HTML (innerHTML or attributes), replacing &, <, >, ", ', and / characters.
18456	// str:
18457	//		the string to escape
18458	if(!str){ return ""; }
18459	return str.replace(ESCAPE_REGEXP, function(c) {
18460		return ESCAPE_MAP[c];
18461	});
18462};
18463
18464string.rep = function(/*String*/str, /*Integer*/num){
18465	// summary:
18466	//		Efficiently replicate a string `n` times.
18467	// str:
18468	//		the string to replicate
18469	// num:
18470	//		number of times to replicate the string
18471
18472	if(num <= 0 || !str){ return ""; }
18473
18474	var buf = [];
18475	for(;;){
18476		if(num & 1){
18477			buf.push(str);
18478		}
18479		if(!(num >>= 1)){ break; }
18480		str += str;
18481	}
18482	return buf.join("");	// String
18483};
18484
18485string.pad = function(/*String*/text, /*Integer*/size, /*String?*/ch, /*Boolean?*/end){
18486	// summary:
18487	//		Pad a string to guarantee that it is at least `size` length by
18488	//		filling with the character `ch` at either the start or end of the
18489	//		string. Pads at the start, by default.
18490	// text:
18491	//		the string to pad
18492	// size:
18493	//		length to provide padding
18494	// ch:
18495	//		character to pad, defaults to '0'
18496	// end:
18497	//		adds padding at the end if true, otherwise pads at start
18498	// example:
18499	//	|	// Fill the string to length 10 with "+" characters on the right.  Yields "Dojo++++++".
18500	//	|	string.pad("Dojo", 10, "+", true);
18501
18502	if(!ch){
18503		ch = '0';
18504	}
18505	var out = String(text),
18506		pad = string.rep(ch, Math.ceil((size - out.length) / ch.length));
18507	return end ? out + pad : pad + out;	// String
18508};
18509
18510string.substitute = function(	/*String*/		template,
18511									/*Object|Array*/map,
18512									/*Function?*/	transform,
18513									/*Object?*/		thisObject){
18514	// summary:
18515	//		Performs parameterized substitutions on a string. Throws an
18516	//		exception if any parameter is unmatched.
18517	// template:
18518	//		a string with expressions in the form `${key}` to be replaced or
18519	//		`${key:format}` which specifies a format function. keys are case-sensitive.
18520	// map:
18521	//		hash to search for substitutions
18522	// transform:
18523	//		a function to process all parameters before substitution takes
18524	//		place, e.g. mylib.encodeXML
18525	// thisObject:
18526	//		where to look for optional format function; default to the global
18527	//		namespace
18528	// example:
18529	//		Substitutes two expressions in a string from an Array or Object
18530	//	|	// returns "File 'foo.html' is not found in directory '/temp'."
18531	//	|	// by providing substitution data in an Array
18532	//	|	string.substitute(
18533	//	|		"File '${0}' is not found in directory '${1}'.",
18534	//	|		["foo.html","/temp"]
18535	//	|	);
18536	//	|
18537	//	|	// also returns "File 'foo.html' is not found in directory '/temp'."
18538	//	|	// but provides substitution data in an Object structure.  Dotted
18539	//	|	// notation may be used to traverse the structure.
18540	//	|	string.substitute(
18541	//	|		"File '${name}' is not found in directory '${info.dir}'.",
18542	//	|		{ name: "foo.html", info: { dir: "/temp" } }
18543	//	|	);
18544	// example:
18545	//		Use a transform function to modify the values:
18546	//	|	// returns "file 'foo.html' is not found in directory '/temp'."
18547	//	|	string.substitute(
18548	//	|		"${0} is not found in ${1}.",
18549	//	|		["foo.html","/temp"],
18550	//	|		function(str){
18551	//	|			// try to figure out the type
18552	//	|			var prefix = (str.charAt(0) == "/") ? "directory": "file";
18553	//	|			return prefix + " '" + str + "'";
18554	//	|		}
18555	//	|	);
18556	// example:
18557	//		Use a formatter
18558	//	|	// returns "thinger -- howdy"
18559	//	|	string.substitute(
18560	//	|		"${0:postfix}", ["thinger"], null, {
18561	//	|			postfix: function(value, key){
18562	//	|				return value + " -- howdy";
18563	//	|			}
18564	//	|		}
18565	//	|	);
18566
18567	thisObject = thisObject || kernel.global;
18568	transform = transform ?
18569		lang.hitch(thisObject, transform) : function(v){ return v; };
18570
18571	return template.replace(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g,
18572		function(match, key, format){
18573			var value = lang.getObject(key, false, map);
18574			if(format){
18575				value = lang.getObject(format, false, thisObject).call(thisObject, value, key);
18576			}
18577			return transform(value, key).toString();
18578		}); // String
18579};
18580
18581string.trim = String.prototype.trim ?
18582	lang.trim : // aliasing to the native function
18583	function(str){
18584		str = str.replace(/^\s+/, '');
18585		for(var i = str.length - 1; i >= 0; i--){
18586			if(/\S/.test(str.charAt(i))){
18587				str = str.substring(0, i + 1);
18588				break;
18589			}
18590		}
18591		return str;
18592	};
18593
18594/*=====
18595 string.trim = function(str){
18596	 // summary:
18597	 //		Trims whitespace from both sides of the string
18598	 // str: String
18599	 //		String to be trimmed
18600	 // returns: String
18601	 //		Returns the trimmed string
18602	 // description:
18603	 //		This version of trim() was taken from [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript).
18604	 //		The short yet performant version of this function is dojo/_base/lang.trim(),
18605	 //		which is part of Dojo base.  Uses String.prototype.trim instead, if available.
18606	 return "";	// String
18607 };
18608 =====*/
18609
18610	return string;
18611});
18612
18613},
18614'dojo/cldr/nls/gregorian':function(){
18615define({ root:
18616
18617//begin v1.x content
18618{
18619	"dateFormatItem-Ehm": "E h:mm a",
18620	"days-standAlone-short": [
18621		"Sun",
18622		"Mon",
18623		"Tue",
18624		"Wed",
18625		"Thu",
18626		"Fri",
18627		"Sat"
18628	],
18629	"months-format-narrow": [
18630		"1",
18631		"2",
18632		"3",
18633		"4",
18634		"5",
18635		"6",
18636		"7",
18637		"8",
18638		"9",
18639		"10",
18640		"11",
18641		"12"
18642	],
18643	"field-second-relative+0": "now",
18644	"quarters-standAlone-narrow": [
18645		"1",
18646		"2",
18647		"3",
18648		"4"
18649	],
18650	"field-weekday": "Day of the Week",
18651	"dateFormatItem-yQQQ": "y QQQ",
18652	"dateFormatItem-yMEd": "y-MM-dd, E",
18653	"field-wed-relative+0": "this Wednesday",
18654	"field-wed-relative+1": "next Wednesday",
18655	"dateFormatItem-GyMMMEd": "G y MMM d, E",
18656	"dateFormatItem-MMMEd": "MMM d, E",
18657	"eraNarrow": [
18658		"BCE",
18659		"CE"
18660	],
18661	"field-tue-relative+-1": "last Tuesday",
18662	"days-format-short": [
18663		"Sun",
18664		"Mon",
18665		"Tue",
18666		"Wed",
18667		"Thu",
18668		"Fri",
18669		"Sat"
18670	],
18671	"dateTimeFormats-appendItem-Day-Of-Week": "{0} {1}",
18672	"dateFormat-long": "y MMMM d",
18673	"field-fri-relative+-1": "last Friday",
18674	"field-wed-relative+-1": "last Wednesday",
18675	"months-format-wide": [
18676		"M01",
18677		"M02",
18678		"M03",
18679		"M04",
18680		"M05",
18681		"M06",
18682		"M07",
18683		"M08",
18684		"M09",
18685		"M10",
18686		"M11",
18687		"M12"
18688	],
18689	"dateTimeFormat-medium": "{1} {0}",
18690	"dayPeriods-format-wide-pm": "PM",
18691	"dateFormat-full": "y MMMM d, EEEE",
18692	"field-thu-relative+-1": "last Thursday",
18693	"dateFormatItem-Md": "MM-dd",
18694	"dayPeriods-format-abbr-am": "AM",
18695	"dateTimeFormats-appendItem-Second": "{0} ({2}: {1})",
18696	"dayPeriods-format-wide-noon": "noon",
18697	"dateFormatItem-yMd": "y-MM-dd",
18698	"field-era": "Era",
18699	"dateFormatItem-yM": "y-MM",
18700	"months-standAlone-wide": [
18701		"M01",
18702		"M02",
18703		"M03",
18704		"M04",
18705		"M05",
18706		"M06",
18707		"M07",
18708		"M08",
18709		"M09",
18710		"M10",
18711		"M11",
18712		"M12"
18713	],
18714	"timeFormat-short": "HH:mm",
18715	"quarters-format-wide": [
18716		"Q1",
18717		"Q2",
18718		"Q3",
18719		"Q4"
18720	],
18721	"dateFormatItem-yQQQQ": "y QQQQ",
18722	"timeFormat-long": "HH:mm:ss z",
18723	"field-year": "Year",
18724	"dateFormatItem-yMMM": "y MMM",
18725	"dateTimeFormats-appendItem-Era": "{1} {0}",
18726	"field-hour": "Hour",
18727	"months-format-abbr": [
18728		"M01",
18729		"M02",
18730		"M03",
18731		"M04",
18732		"M05",
18733		"M06",
18734		"M07",
18735		"M08",
18736		"M09",
18737		"M10",
18738		"M11",
18739		"M12"
18740	],
18741	"field-sat-relative+0": "this Saturday",
18742	"field-sat-relative+1": "next Saturday",
18743	"timeFormat-full": "HH:mm:ss zzzz",
18744	"dateTimeFormats-appendItem-Week": "{0} ({2}: {1})",
18745	"field-day-relative+0": "today",
18746	"field-thu-relative+0": "this Thursday",
18747	"field-day-relative+1": "tomorrow",
18748	"field-thu-relative+1": "next Thursday",
18749	"dateFormatItem-GyMMMd": "G y MMM d",
18750	"dateFormatItem-H": "HH",
18751	"months-standAlone-abbr": [
18752		"M01",
18753		"M02",
18754		"M03",
18755		"M04",
18756		"M05",
18757		"M06",
18758		"M07",
18759		"M08",
18760		"M09",
18761		"M10",
18762		"M11",
18763		"M12"
18764	],
18765	"quarters-format-abbr": [
18766		"Q1",
18767		"Q2",
18768		"Q3",
18769		"Q4"
18770	],
18771	"quarters-standAlone-wide": [
18772		"Q1",
18773		"Q2",
18774		"Q3",
18775		"Q4"
18776	],
18777	"dateFormatItem-Gy": "G y",
18778	"dateFormatItem-M": "L",
18779	"days-standAlone-wide": [
18780		"Sun",
18781		"Mon",
18782		"Tue",
18783		"Wed",
18784		"Thu",
18785		"Fri",
18786		"Sat"
18787	],
18788	"dayPeriods-format-abbr-noon": "noon",
18789	"timeFormat-medium": "HH:mm:ss",
18790	"field-sun-relative+0": "this Sunday",
18791	"dateFormatItem-Hm": "HH:mm",
18792	"field-sun-relative+1": "next Sunday",
18793	"quarters-standAlone-abbr": [
18794		"Q1",
18795		"Q2",
18796		"Q3",
18797		"Q4"
18798	],
18799	"eraAbbr": [
18800		"BCE",
18801		"CE"
18802	],
18803	"field-minute": "Minute",
18804	"field-dayperiod": "Dayperiod",
18805	"days-standAlone-abbr": [
18806		"Sun",
18807		"Mon",
18808		"Tue",
18809		"Wed",
18810		"Thu",
18811		"Fri",
18812		"Sat"
18813	],
18814	"dateFormatItem-d": "d",
18815	"dateFormatItem-ms": "mm:ss",
18816	"quarters-format-narrow": [
18817		"1",
18818		"2",
18819		"3",
18820		"4"
18821	],
18822	"field-day-relative+-1": "yesterday",
18823	"dateTimeFormat-long": "{1} {0}",
18824	"dayPeriods-format-narrow-am": "a",
18825	"dateFormatItem-h": "h a",
18826	"dateFormatItem-MMMd": "MMM d",
18827	"dateFormatItem-MEd": "MM-dd, E",
18828	"dateTimeFormat-full": "{1} {0}",
18829	"field-fri-relative+0": "this Friday",
18830	"field-fri-relative+1": "next Friday",
18831	"field-day": "Day",
18832	"days-format-wide": [
18833		"Sun",
18834		"Mon",
18835		"Tue",
18836		"Wed",
18837		"Thu",
18838		"Fri",
18839		"Sat"
18840	],
18841	"field-zone": "Zone",
18842	"months-standAlone-narrow": [
18843		"1",
18844		"2",
18845		"3",
18846		"4",
18847		"5",
18848		"6",
18849		"7",
18850		"8",
18851		"9",
18852		"10",
18853		"11",
18854		"12"
18855	],
18856	"dateFormatItem-y": "y",
18857	"dateTimeFormats-appendItem-Day": "{0} ({2}: {1})",
18858	"field-year-relative+-1": "last year",
18859	"field-month-relative+-1": "last month",
18860	"dateTimeFormats-appendItem-Year": "{1} {0}",
18861	"dateFormatItem-hm": "h:mm a",
18862	"dateTimeFormats-appendItem-Hour": "{0} ({2}: {1})",
18863	"dayPeriods-format-abbr-pm": "PM",
18864	"days-format-abbr": [
18865		"Sun",
18866		"Mon",
18867		"Tue",
18868		"Wed",
18869		"Thu",
18870		"Fri",
18871		"Sat"
18872	],
18873	"eraNames": [
18874		"BCE",
18875		"CE"
18876	],
18877	"dateFormatItem-yMMMd": "y MMM d",
18878	"days-format-narrow": [
18879		"S",
18880		"M",
18881		"T",
18882		"W",
18883		"T",
18884		"F",
18885		"S"
18886	],
18887	"field-month": "Month",
18888	"days-standAlone-narrow": [
18889		"S",
18890		"M",
18891		"T",
18892		"W",
18893		"T",
18894		"F",
18895		"S"
18896	],
18897	"dateFormatItem-MMM": "LLL",
18898	"field-tue-relative+0": "this Tuesday",
18899	"dateTimeFormats-appendItem-Quarter": "{0} ({2}: {1})",
18900	"field-tue-relative+1": "next Tuesday",
18901	"dayPeriods-format-wide-am": "AM",
18902	"dateTimeFormats-appendItem-Month": "{0} ({2}: {1})",
18903	"dateTimeFormats-appendItem-Minute": "{0} ({2}: {1})",
18904	"dateFormatItem-EHm": "E HH:mm",
18905	"field-mon-relative+0": "this Monday",
18906	"field-mon-relative+1": "next Monday",
18907	"dateFormat-short": "y-MM-dd",
18908	"dateFormatItem-EHms": "E HH:mm:ss",
18909	"dateFormatItem-Ehms": "E h:mm:ss a",
18910	"dayPeriods-format-narrow-noon": "n",
18911	"field-second": "Second",
18912	"field-sat-relative+-1": "last Saturday",
18913	"dateFormatItem-yMMMEd": "y MMM d, E",
18914	"field-sun-relative+-1": "last Sunday",
18915	"field-month-relative+0": "this month",
18916	"field-month-relative+1": "next month",
18917	"dateTimeFormats-appendItem-Timezone": "{0} {1}",
18918	"dateFormatItem-Ed": "d, E",
18919	"field-week": "Week",
18920	"dateFormat-medium": "y MMM d",
18921	"field-week-relative+-1": "last week",
18922	"field-year-relative+0": "this year",
18923	"field-year-relative+1": "next year",
18924	"dayPeriods-format-narrow-pm": "p",
18925	"dateTimeFormat-short": "{1} {0}",
18926	"dateFormatItem-Hms": "HH:mm:ss",
18927	"dateFormatItem-hms": "h:mm:ss a",
18928	"dateFormatItem-GyMMM": "G y MMM",
18929	"field-mon-relative+-1": "last Monday",
18930	"field-week-relative+0": "this week",
18931	"field-week-relative+1": "next week"
18932}
18933//end v1.x content
18934,
18935	"ar": true,
18936	"ca": true,
18937	"cs": true,
18938	"da": true,
18939	"de": true,
18940	"el": true,
18941	"en": true,
18942	"en-au": true,
18943	"en-ca": true,
18944	"en-gb": true,
18945	"es": true,
18946	"fi": true,
18947	"fr": true,
18948	"fr-ch": true,
18949	"he": true,
18950	"hu": true,
18951	"it": true,
18952	"ja": true,
18953	"ko": true,
18954	"nb": true,
18955	"nl": true,
18956	"pl": true,
18957	"pt": true,
18958	"pt-pt": true,
18959	"ro": true,
18960	"ru": true,
18961	"sk": true,
18962	"sl": true,
18963	"sv": true,
18964	"th": true,
18965	"tr": true,
18966	"zh": true,
18967	"zh-hant": true,
18968	"zh-hk": true,
18969	"zh-tw": true
18970});
18971},
18972'dojo/cldr/nls/en/gregorian':function(){
18973define(
18974//begin v1.x content
18975{
18976	"dateFormatItem-Ehm": "E h:mm a",
18977	"days-standAlone-short": [
18978		"Su",
18979		"Mo",
18980		"Tu",
18981		"We",
18982		"Th",
18983		"Fr",
18984		"Sa"
18985	],
18986	"months-format-narrow": [
18987		"J",
18988		"F",
18989		"M",
18990		"A",
18991		"M",
18992		"J",
18993		"J",
18994		"A",
18995		"S",
18996		"O",
18997		"N",
18998		"D"
18999	],
19000	"field-second-relative+0": "now",
19001	"quarters-standAlone-narrow": [
19002		"1",
19003		"2",
19004		"3",
19005		"4"
19006	],
19007	"field-weekday": "Day of the Week",
19008	"dateFormatItem-yQQQ": "QQQ y",
19009	"dateFormatItem-yMEd": "E, M/d/y",
19010	"field-wed-relative+0": "this Wednesday",
19011	"field-wed-relative+1": "next Wednesday",
19012	"dateFormatItem-GyMMMEd": "E, MMM d, y G",
19013	"dateFormatItem-MMMEd": "E, MMM d",
19014	"eraNarrow": [
19015		"B",
19016		"A"
19017	],
19018	"field-tue-relative+-1": "last Tuesday",
19019	"days-format-short": [
19020		"Su",
19021		"Mo",
19022		"Tu",
19023		"We",
19024		"Th",
19025		"Fr",
19026		"Sa"
19027	],
19028	"dateTimeFormats-appendItem-Day-Of-Week": "{0} {1}",
19029	"dateFormat-long": "MMMM d, y",
19030	"field-fri-relative+-1": "last Friday",
19031	"field-wed-relative+-1": "last Wednesday",
19032	"months-format-wide": [
19033		"January",
19034		"February",
19035		"March",
19036		"April",
19037		"May",
19038		"June",
19039		"July",
19040		"August",
19041		"September",
19042		"October",
19043		"November",
19044		"December"
19045	],
19046	"dateTimeFormat-medium": "{1}
19046, {0}",
19047	"dayPeriods-format-wide-pm": "PM",
19048	"dateFormat-full": "EEEE, MMMM d, y",
19049	"field-thu-relative+-1": "last Thursday",
19050	"dateFormatItem-Md": "M/d",
19051	"dateTimeFormats-appendItem-Second": "{0} ({2}: {1})",
19052	"dayPeriods-format-wide-noon": "noon",
19053	"dateFormatItem-yMd": "M/d/y",
19054	"field-era": "Era",
19055	"dateFormatItem-yM": "M/y",
19056	"months-standAlone-wide": [
19057		"January",
19058		"February",
19059		"March",
19060		"April",
19061		"May",
19062		"June",
19063		"July",
19064		"August",
19065		"September",
19066		"October",
19067		"November",
19068		"December"
19069	],
19070	"timeFormat-short": "h:mm a",
19071	"quarters-format-wide": [
19072		"1st quarter",
19073		"2nd quarter",
19074		"3rd quarter",
19075		"4th quarter"
19076	],
19077	"dateFormatItem-yQQQQ": "QQQQ y",
19078	"timeFormat-long": "h:mm:ss a z",
19079	"field-year": "Year",
19080	"dateFormatItem-yMMM": "MMM y",
19081	"dateTimeFormats-appendItem-Era": "{0} {1}",
19082	"field-hour": "Hour",
19083	"months-format-abbr": [
19084		"Jan",
19085		"Feb",
19086		"Mar",
19087		"Apr",
19088		"May",
19089		"Jun",
19090		"Jul",
19091		"Aug",
19092		"Sep",
19093		"Oct",
19094		"Nov",
19095		"Dec"
19096	],
19097	"field-sat-relative+0": "this Saturday",
19098	"field-sat-relative+1": "next Saturday",
19099	"timeFormat-full": "h:mm:ss a zzzz",
19100	"dateTimeFormats-appendItem-Week": "{0} ({2}: {1})",
19101	"field-day-relative+0": "today",
19102	"field-thu-relative+0": "this Thursday",
19103	"field-day-relative+1": "tomorrow",
19104	"field-thu-relative+1": "next Thursday",
19105	"dateFormatItem-GyMMMd": "MMM d, y G",
19106	"dateFormatItem-H": "HH",
19107	"months-standAlone-abbr": [
19108		"Jan",
19109		"Feb",
19110		"Mar",
19111		"Apr",
19112		"May",
19113		"Jun",
19114		"Jul",
19115		"Aug",
19116		"Sep",
19117		"Oct",
19118		"Nov",
19119		"Dec"
19120	],
19121	"quarters-format-abbr": [
19122		"Q1",
19123		"Q2",
19124		"Q3",
19125		"Q4"
19126	],
19127	"quarters-standAlone-wide": [
19128		"1st quarter",
19129		"2nd quarter",
19130		"3rd quarter",
19131		"4th quarter"
19132	],
19133	"dateFormatItem-Gy": "y G",
19134	"dateFormatItem-M": "L",
19135	"days-standAlone-wide": [
19136		"Sunday",
19137		"Monday",
19138		"Tuesday",
19139		"Wednesday",
19140		"Thursday",
19141		"Friday",
19142		"Saturday"
19143	],
19144	"timeFormat-medium": "h:mm:ss a",
19145	"field-sun-relative+0": "this Sunday",
19146	"dateFormatItem-Hm": "HH:mm",
19147	"field-sun-relative+1": "next Sunday",
19148	"eraAbbr": [
19149		"BC",
19150		"AD"
19151	],
19152	"field-minute": "Minute",
19153	"field-dayperiod": "AM/PM",
19154	"dateFormatItem-d": "d",
19155	"dateFormatItem-ms": "mm:ss",
19156	"field-day-relative+-1": "yesterday",
19157	"dateFormatItem-h": "h a",
19158	"dateTimeFormat-long": "{1} 'at' {0}",
19159	"dayPeriods-format-narrow-am": "a",
19160	"dateFormatItem-MMMd": "MMM d",
19161	"dateFormatItem-MEd": "E, M/d",
19162	"dateTimeFormat-full": "{1} 'at' {0}",
19163	"field-fri-relative+0": "this Friday",
19164	"field-fri-relative+1": "next Friday",
19165	"field-day": "Day",
19166	"days-format-wide": [
19167		"Sunday",
19168		"Monday",
19169		"Tuesday",
19170		"Wednesday",
19171		"Thursday",
19172		"Friday",
19173		"Saturday"
19174	],
19175	"field-zone": "Time Zone",
19176	"dateTimeFormats-appendItem-Day": "{0} ({2}: {1})",
19177	"dateFormatItem-y": "y",
19178	"months-standAlone-narrow": [
19179		"J",
19180		"F",
19181		"M",
19182		"A",
19183		"M",
19184		"J",
19185		"J",
19186		"A",
19187		"S",
19188		"O",
19189		"N",
19190		"D"
19191	],
19192	"field-year-relative+-1": "last year",
19193	"field-month-relative+-1": "last month",
19194	"dateFormatItem-hm": "h:mm a",
19195	"dateTimeFormats-appendItem-Year": "{0} {1}",
19196	"dateTimeFormats-appendItem-Hour": "{0} ({2}: {1})",
19197	"days-format-abbr": [
19198		"Sun",
19199		"Mon",
19200		"Tue",
19201		"Wed",
19202		"Thu",
19203		"Fri",
19204		"Sat"
19205	],
19206	"dateFormatItem-yMMMd": "MMM d, y",
19207	"eraNames": [
19208		"Before Christ",
19209		"Anno Domini"
19210	],
19211	"days-standAlone-narrow": [
19212		"S",
19213		"M",
19214		"T",
19215		"W",
19216		"T",
19217		"F",
19218		"S"
19219	],
19220	"dateFormatItem-MMM": "LLL",
19221	"field-month": "Month",
19222	"field-tue-relative+0": "this Tuesday",
19223	"dateTimeFormats-appendItem-Quarter": "{0} ({2}: {1})",
19224	"field-tue-relative+1": "next Tuesday",
19225	"dayPeriods-format-wide-am": "AM",
19226	"dateTimeFormats-appendItem-Month": "{0} ({2}: {1})",
19227	"dateTimeFormats-appendItem-Minute": "{0} ({2}: {1})",
19228	"dateFormatItem-EHm": "E HH:mm",
19229	"field-mon-relative+0": "this Monday",
19230	"field-mon-relative+1": "next Monday",
19231	"dateFormat-short": "M/d/yy",
19232	"dateFormatItem-EHms": "E HH:mm:ss",
19233	"dateFormatItem-Ehms": "E h:mm:ss a",
19234	"dayPeriods-format-narrow-noon": "n",
19235	"field-second": "Second",
19236	"field-sat-relative+-1": "last Saturday",
19237	"dateFormatItem-yMMMEd": "E, MMM d, y",
19238	"field-sun-relative+-1": "last Sunday",
19239	"field-month-relative+0": "this month",
19240	"field-month-relative+1": "next month",
19241	"dateFormatItem-Ed": "d E",
19242	"dateTimeFormats-appendItem-Timezone": "{0} {1}",
19243	"field-week": "Week",
19244	"dateFormat-medium": "MMM d, y",
19245	"field-year-relative+0": "this year",
19246	"field-week-relative+-1": "last week",
19247	"field-year-relative+1": "next year",
19248	"dayPeriods-format-narrow-pm": "p",
19249	"dateTimeFormat-short": "{1}
19249, {0}",
19250	"dateFormatItem-Hms": "HH:mm:ss",
19251	"dateFormatItem-hms": "h:mm:ss a",
19252	"dateFormatItem-GyMMM": "MMM y G",
19253	"field-mon-relative+-1": "last Monday",
19254	"field-week-relative+0": "this week",
19255	"field-week-relative+1": "next week"
19256}
19257//end v1.x content
19258);
19259},
19260'dojox/html/entities':function(){
19261define(["dojo/_base/lang"], function(lang) {
19262	// dojox.html.entities.html [public] Array
19263	//		Entity characters for HTML, represented as an array of
19264	//		character code, entity name (minus & and ; wrapping.
19265	//		The function wrapper is to fix global leking with the build tools.
19266	var dhe = lang.getObject("dojox.html.entities",true);	
19267	
19268	var _applyEncodingMap = function(str, map){
19269		// summary:
19270		//		Private internal function for performing encoding of entity characters.
19271		// tags:
19272		//		private
19273	
19274		// Check to see if we have genned and cached a regexp for this map yet
19275		// If we have, use it, if not, gen it, cache, then use.
19276		var mapper, regexp;
19277		if(map._encCache &&
19278			map._encCache.regexp &&
19279			map._encCache.mapper &&
19280			map.length == map._encCache.length){
19281			mapper = map._encCache.mapper;
19282			regexp = map._encCache.regexp;
19283		}else{
19284			mapper = {};
19285			regexp = ["["];
19286			var i;
19287			for(i = 0; i < map.length; i++){
19288				mapper[map[i][0]] = "&" + map[i][1] + ";";
19289				regexp.push(map[i][0]);
19290			}
19291			regexp.push("]");
19292			regexp = new RegExp(regexp.join(""), "g");
19293			map._encCache = {
19294				mapper: mapper,
19295				regexp: regexp,
19296				length: map.length
19297			};
19298		}
19299		str = str.replace(regexp, function(c){
19300			return mapper[c];
19301		});
19302		return str;
19303	};
19304	
19305	var _applyDecodingMap = function(str, map){
19306		// summary:
19307		//		Private internal function for performing decoding of entity characters.
19308		// tags:
19309		//		private
19310		var mapper, regexp;
19311		if(map._decCache &&
19312			map._decCache.regexp &&
19313			map._decCache.mapper &&
19314			map.length == map._decCache.length){
19315			mapper = map._decCache.mapper;
19316			regexp = map._decCache.regexp;
19317		}else{
19318			mapper = {};
19319			regexp = ["("];
19320			var i;
19321			for(i = 0; i < map.length; i++){
19322				var e = "&" + map[i][1] + ";";
19323				if(i){regexp.push("|");}
19324				mapper[e] = map[i][0];
19325				regexp.push(e);
19326			}
19327			regexp.push(")");
19328			regexp = new RegExp(regexp.join(""), "g");
19329			map._decCache = {
19330				mapper: mapper,
19331				regexp: regexp,
19332				length: map.length
19333			};
19334		}
19335		str = str.replace(regexp, function(c){
19336			return mapper[c];
19337		});
19338		return str;
19339	};
19340
19341	dhe.html = [
19342		["\u0026","amp"], ["\u0022","quot"],["\u003C","lt"], ["\u003E","gt"],
19343		["\u00A0","nbsp"]
19344	];
19345	
19346	// dojox.html.entities.latin [public] Array
19347	//		Entity characters for Latin characters and similar, represented as an array of
19348	//		character code, entity name (minus & and ; wrapping.
19349	dhe.latin = [
19350		["\u00A1","iexcl"],["\u00A2","cent"],["\u00A3","pound"],["\u20AC","euro"],
19351		["\u00A4","curren"],["\u00A5","yen"],["\u00A6","brvbar"],["\u00A7","sect"],
19352		["\u00A8","uml"],["\u00A9","copy"],["\u00AA","ordf"],["\u00AB","laquo"],
19353		["\u00AC","not"],["\u00AD","shy"],["\u00AE","reg"],["\u00AF","macr"],
19354		["\u00B0","deg"],["\u00B1","plusmn"],["\u00B2","sup2"],["\u00B3","sup3"],
19355		["\u00B4","acute"],["\u00B5","micro"],["\u00B6","para"],["\u00B7","middot"],
19356		["\u00B8","cedil"],["\u00B9","sup1"],["\u00BA","ordm"],["\u00BB","raquo"],
19357		["\u00BC","frac14"],["\u00BD","frac12"],["\u00BE","frac34"],["\u00BF","iquest"],
19358		["\u00C0","Agrave"],["\u00C1","Aacute"],["\u00C2","Acirc"],["\u00C3","Atilde"],
19359		["\u00C4","Auml"],["\u00C5","Aring"],["\u00C6","AElig"],["\u00C7","Ccedil"],
19360		["\u00C8","Egrave"],["\u00C9","Eacute"],["\u00CA","Ecirc"],["\u00CB","Euml"],
19361		["\u00CC","Igrave"],["\u00CD","Iacute"],["\u00CE","Icirc"],["\u00CF","Iuml"],
19362		["\u00D0","ETH"],["\u00D1","Ntilde"],["\u00D2","Ograve"],["\u00D3","Oacute"],
19363		["\u00D4","Ocirc"],["\u00D5","Otilde"],["\u00D6","Ouml"],["\u00D7","times"],
19364		["\u00D8","Oslash"],["\u00D9","Ugrave"],["\u00DA","Uacute"],["\u00DB","Ucirc"],
19365		["\u00DC","Uuml"],["\u00DD","Yacute"],["\u00DE","THORN"],["\u00DF","szlig"],
19366		["\u00E0","agrave"],["\u00E1","aacute"],["\u00E2","acirc"],["\u00E3","atilde"],
19367		["\u00E4","auml"],["\u00E5","aring"],["\u00E6","aelig"],["\u00E7","ccedil"],
19368		["\u00E8","egrave"],["\u00E9","eacute"],["\u00EA","ecirc"],["\u00EB","euml"],
19369		["\u00EC","igrave"],["\u00ED","iacute"],["\u00EE","icirc"],["\u00EF","iuml"],
19370		["\u00F0","eth"],["\u00F1","ntilde"],["\u00F2","ograve"],["\u00F3","oacute"],
19371		["\u00F4","ocirc"],["\u00F5","otilde"],["\u00F6","ouml"],["\u00F7","divide"],
19372		["\u00F8","oslash"],["\u00F9","ugrave"],["\u00FA","uacute"],["\u00FB","ucirc"],
19373		["\u00FC","uuml"],["\u00FD","yacute"],["\u00FE","thorn"],["\u00FF","yuml"],
19374		["\u0192","fnof"],["\u0391","Alpha"],["\u0392","Beta"],["\u0393","Gamma"],
19375		["\u0394","Delta"],["\u0395","Epsilon"],["\u0396","Zeta"],["\u0397","Eta"],
19376		["\u0398","Theta"], ["\u0399","Iota"],["\u039A","Kappa"],["\u039B","Lambda"],
19377		["\u039C","Mu"],["\u039D","Nu"],["\u039E","Xi"],["\u039F","Omicron"],
19378		["\u03A0","Pi"],["\u03A1","Rho"],["\u03A3","Sigma"],["\u03A4","Tau"],
19379		["\u03A5","Upsilon"],["\u03A6","Phi"],["\u03A7","Chi"],["\u03A8","Psi"],
19380		["\u03A9","Omega"],["\u03B1","alpha"],["\u03B2","beta"],["\u03B3","gamma"],
19381		["\u03B4","delta"],["\u03B5","epsilon"],["\u03B6","zeta"],["\u03B7","eta"],
19382		["\u03B8","theta"],["\u03B9","iota"],["\u03BA","kappa"],["\u03BB","lambda"],
19383		["\u03BC","mu"],["\u03BD","nu"],["\u03BE","xi"],["\u03BF","omicron"],
19384		["\u03C0","pi"],["\u03C1","rho"],["\u03C2","sigmaf"],["\u03C3","sigma"],
19385		["\u03C4","tau"],["\u03C5","upsilon"],["\u03C6","phi"],["\u03C7","chi"],
19386		["\u03C8","psi"],["\u03C9","omega"],["\u03D1","thetasym"],["\u03D2","upsih"],
19387		["\u03D6","piv"],["\u2022","bull"],["\u2026","hellip"],["\u2032","prime"],
19388		["\u2033","Prime"],["\u203E","oline"],["\u2044","frasl"],["\u2118","weierp"],
19389		["\u2111","image"],["\u211C","real"],["\u2122","trade"],["\u2135","alefsym"],
19390		["\u2190","larr"],["\u2191","uarr"],["\u2192","rarr"],["\u2193","darr"],
19391		["\u2194","harr"],["\u21B5","crarr"],["\u21D0","lArr"],["\u21D1","uArr"],
19392		["\u21D2","rArr"],["\u21D3","dArr"],["\u21D4","hArr"],["\u2200","forall"],
19393		["\u2202","part"],["\u2203","exist"],["\u2205","empty"],["\u2207","nabla"],
19394		["\u2208","isin"],["\u2209","notin"],["\u220B","ni"],["\u220F","prod"],
19395		["\u2211","sum"],["\u2212","minus"],["\u2217","lowast"],["\u221A","radic"],
19396		["\u221D","prop"],["\u221E","infin"],["\u2220","ang"],["\u2227","and"],
19397		["\u2228","or"],["\u2229","cap"],["\u222A","cup"],["\u222B","int"],
19398		["\u2234","there4"],["\u223C","sim"],["\u2245","cong"],["\u2248","asymp"],
19399		["\u2260","ne"],["\u2261","equiv"],["\u2264","le"],["\u2265","ge"],
19400		["\u2282","sub"],["\u2283","sup"],["\u2284","nsub"],["\u2286","sube"],
19401		["\u2287","supe"],["\u2295","oplus"],["\u2297","otimes"],["\u22A5","perp"],
19402		["\u22C5","sdot"],["\u2308","lceil"],["\u2309","rceil"],["\u230A","lfloor"],
19403		["\u230B","rfloor"],["\u2329","lang"],["\u232A","rang"],["\u25CA","loz"],
19404		["\u2660","spades"],["\u2663","clubs"],["\u2665","hearts"],["\u2666","diams"],
19405		["\u0152","OElig"],["\u0153","oelig"],["\u0160","Scaron"],["\u0161","scaron"],
19406		["\u0178","Yuml"],["\u02C6","circ"],["\u02DC","tilde"],["\u2002","ensp"],
19407		["\u2003","emsp"],["\u2009","thinsp"],["\u200C","zwnj"],["\u200D","zwj"],
19408		["\u200E","lrm"],["\u200F","rlm"],["\u2013","ndash"],["\u2014","mdash"],
19409		["\u2018","lsquo"],["\u2019","rsquo"],["\u201A","sbquo"],["\u201C","ldquo"],
19410		["\u201D","rdquo"],["\u201E","bdquo"],["\u2020","dagger"],["\u2021","Dagger"],
19411		["\u2030","permil"],["\u2039","lsaquo"],["\u203A","rsaquo"]
19412	];
19413	
19414	dhe.encode = function(str/*string*/, m /*array?*/){
19415		// summary:
19416		//		Function to obtain an entity encoding for a specified character
19417		// str:
19418		//		The string to process for possible entity encoding.
19419		// m:
19420		//		An optional list of character to entity name mappings (array of
19421		//		arrays).  If not provided, it uses the and Latin entities as the
19422		//		set to map and escape.
19423		// tags:
19424		//		public
19425		if(str){
19426			if(!m){
19427				// Apply the basic mappings.  HTML should always come first when decoding
19428				// as well.
19429				str = _applyEncodingMap(str, dhe.html);
19430				str = _applyEncodingMap(str, dhe.latin);
19431	
19432			}else{
19433				str = _applyEncodingMap(str, m);
19434			}
19435		}
19436		return str;
19437	};
19438	
19439	dhe.decode = function(str/*string*/, m /*array?*/){
19440		// summary:
19441		//		Function to obtain an entity encoding for a specified character
19442		// str:
19443		//		The string to process for possible entity encoding to decode.
19444		// m:
19445		//		An optional list of character to entity name mappings (array of
19446		//		arrays).  If not provided, it uses the HTML and Latin entities as the
19447		//		set to map and decode.
19448		// tags:
19449		//		public
19450		if(str){
19451			if(!m){
19452				// Apply the basic mappings.  HTML should always come first when decoding
19453				// as well.
19454				str = _applyDecodingMap(str, dhe.html);
19455				str = _applyDecodingMap(str, dhe.latin);
19456	
19457			}else{
19458				str = _applyDecodingMap(str, m);
19459			}
19460		}
19461		return str;
19462	};
19463	return dhe;
19464});
19465
19466
19467},
19468'dpage/widgets/SingleValueWidget':function(){
19469define([
19470      "dojo/_base/event"
19471      ,"dojo/on"
19472      ,"dojo/dom-attr"
19473      ,"dojo/dom-class"
19474      ,"dojo/mouse"
19475      ,"dojo/dom-geometry"
19476      , "dojo/dom-style"
19477      , "dojo/json"
19478
19479      , "dpage/modules/SingleValueModel"
19480      , "dojo/request/xhr"
19481      ,"dojox/html/entities"
19482      ,"dojo/_base/declare"
19483      , "dpage/widgets/BaseWidget"],
19484function (event, on, domAttr, domClass, mouse, domGeom, style, json) {
19485    /**
19486    * @namespace dpage
19487    */
19488    /**
19489    * @namespace widgets
19490    * @memberOf dpage
19491    */
19492    /**
19493    * Base class for all widgets intended to display single values, such as single-select controls or TextBoxes, or CheckBoxes. 
19494    * @class SingleValueWidget
19495    * @param {Object} [options] Optional options for the widget.
19496    * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget. 
19497    * @param {dpage.widgets.Container} [options.container] The container of the widget.
19498    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
19499    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
19500    *                               is created.
19501    * @param {Object} [containerNode] Optional container node to tie the widget to.
19502    * @memberOf dpage.widgets
19503    * @extends {dpage.widgets.BaseWidget}
19504    */
19505    return dojo.declare("dpage.widgets.SingleValueWidget", [dpage.widgets.BaseWidget], /** @lends dpage.widgets.SingleValueWidget.prototype */ {
19506        //default to the first row in the model.
19507        _dataIndex: 0,
19508        _modelIsDefault: true,
19509        _model:null,
19510        _doDataSubscriptions: true,
19511        _dataCallbackId: null,
19512        _containerNode:null,
19513
19514        constructor: function (options, srcNodeRef)
19515        {
19516            var self = this;
19517            this._containerNode = srcNodeRef;
19518
19519            //if there is no model, create a blank one.
19520            if (options == null || options.model == null) {
19521                this._model = new dpage.modules.SingleValueModel({ model: null, modelProps: { DataType: "TEXT" } });
19522                this._modelIsDefault = true;
19523            }
19524
19525            if (options != null) {
19526                if (options.model != undefined) {
19527                    this._modelIsDefault = false;
19528                    if (options.model.isInstanceOf == null || !options.model.isInstanceOf(dpage.modules.SingleValueModel))
19529                        throw new Error("The model for a SingleValueWidget must be an instance of a dpage.modules.SingleValueModel for widget id = " + this.getWidgetId());
19530                    this._model = options.model;
19531                }
19532            }
19533
19534            if (this._model != null)
19535                this._dataCallbackId = this._model.addDataCallback(function () { self._modelChangedCallback(); });
19536        },
19537        postCreate: function () {
19538            return this.inherited(arguments);
19539        },
19540        /**
19541        * If no model is passed into the constructor, a default model is constructed with a null value.
19542        * @returns {bool} true or false.
19543        */
19544        isModelDefault : function()
19545        {
19546            return this._modelIsDefault;
19547        },
19548        /**
19549        * Get the model.
19550        * @returns {dpage.modules.SingleValueModel}
19551        */
19552        getModel : function()
19553        {
19554            return this._model;
19555        },
19556        /**
19557        * Set the model for the SingleValueWidget
19558        * @param {dpage.modules.SingleValueModel} model
19559        * @returns {void}
19560        */
19561        setModel: function (model) {
19562            var self = this;
19563
19564            if (this._dataCallbackId != null)
19565                this.getModel().removeDataCallback(this._dataCallbackId);
19566
19567            this._modelIsDefault = false;
19568
19569            if (model.isInstanceOf == null || !model.isInstanceOf(dpage.modules.SingleValueModel))
19570                throw new Error("The model for a SingleValueWidget must be an instance of a dpage.modules.SingleValueModel for widget id = " + this.getWidgetId());
19571
19572            this._model = model;
19573
19574            this._dataCallbackId = this._model.addDataCallback(function () { self._modelChangedCallback(); });
19575        },
19576        /**
19577        * Get the value from the underlying model. This may or not match the value in some controls (if there is a validation error for instance,
19578        * the value in the control may be marked as invalid, and in that case will not be reflected in the model).
19579        * @returns {Object}
19580        */
19581        getValue : function()
19582        {
19583            return this._model.getValue();
19584        },
19585        /**
19586        * Sets the value in the model without causing the control to re-render.
19587        * @param {Object} value The value to set (String/bool/Number, etc)
19588        * @returns {void}
19589        */
19590        setModelValue : function(value)
19591        {
19592            var oldS = this.isSubscribedToModelChanges();
19593
19594            if (oldS)
19595                this.setDataSubscriptions(false);
19596
19597            this.getModel().setValue(value);
19598
19599            this.setDataSubscriptions(oldS);
19600        },
19601        /**
19602        * Set the value for the widget. This will update the value in the model.
19603        * @param {Object} value The value to set. This can be a String, Date, Number, boolean. No arrays or complex objects.
19604        * @returns {void}
19605        */
19606        setValue: function (value)
19607        {
19608            this.setModelValue(value);
19609
19610            this._updateView();
19611        },
19612        /**
19613        * Call this method to turn data subscriptions on or off. If off, the widget will not respond to updates on the model.
19614        * @param {bool} trueOrFalse Do data subscriptions or don't
19615        * @returns {void}
19616        */
19617        setDataSubscriptions: function (trueOrFalse) {
19618            this._doDataSubscriptions = trueOrFalse;
19619        },
19620        /**
19621        * Is this widget responding to changes to the model or not.
19622        * @returns {bool} 
19623        */
19624        isSubscribedToModelChanges : function()
19625        {
19626            return this._doDataSubscriptions;
19627        },
19628        //called after the data gets added
19629        _modelChangedCallback: function () {
19630            if (this._doDataSubscriptions) {
19631                //check to see if the row is our row and the data field is our data field.
19632                this._modelChanged();
19633            }
19634
19635        },
19636        /* Can be overridden to listen to events on the Model.
19637        * @abstract
19638        * @returns {void}
19639        */
19640        _modelChanged: function () {
19641            this._updateView();
19642        },
19643
19644
19645        destroy: function () {
19646            //so we will get garbage collected correctly.
19647            this._model.removeDataCallback(this._dataCallbackId);
19648            this.inherited(arguments);
19649        },
19650
19651        templateString: "<div></div>"
19652   });
19653});
19654
19655},
19656'dpage/modules/SingleValueModel':function(){
19657define([
19658      "dojo/_base/declare"
19659      , "dojo/on"
19660      , "dojo/_base/event"
19661
19662      , "dpage/modules/Date"
19663      , "dpage/modules/Model"
19664],
19665    function (declare, on, event) {
19666        /**
19667        * @namespace dpage
19668        */
19669        /**
19670        * @namespace modules
19671        * @memberOf dpage
19672        */
19673        /**
19674         * Class to provide controlled access to data. This class encapsulates a single scalar value such as a string, boolean, date, or number.
19675         * @class SingleValueModel
19676         * @param {Object} [options] Optional options for the TabularModel. 
19677         * @param {Object} [options.displayName] The display name of this property. This will be used in things like validation messages. If passed, overrides the DisplayName and FieldName properties in the modelProps.
19678         * @param {Object} [options.model] Object containing the data. This has to be a scalar value such as a String, bool, or Number
19679         * @param {Object} [options.modelProps] Optional properties describing the model value including DataType, etc.
19680         * @param {String} [options.modelProps.ColumnName] Name of the field in the model (Deprecated).
19681         * @param {String} [options.modelProps.DataType] NUMBER, BOOL, DATE, or TEXT
19682         * @param {String} [options.modelProps.DisplayName] Value used for display of the field to the user.
19683         * @param {String} [options.modelProps.FieldName] Name of the field in the model.
19684         * @param {Number} [options.modelProps.MaxLength] Maximum character length.
19685         * @param {String} [options.modelProps.MaxLengthValidationMessage] Message to display for MaxLength validation failure.
19686         * @param {Number}
19686 [options.modelProps.MaxValue] Maximum value for NUMBER type.
19687         * @param {Number} [options.modelProps.MinValue] Minimum value for NUMBER type.
19688         * @param {String} [options.modelProps.NumberValidationMessage] Message to display if the number validation fails.
19689         * @param {Number} [options.modelProps.NumDecimals] Maximum number of decimals for NUMBER type.
19690         * @param {bool}   [options.modelProps.Required] Is a non-blank value required in this field
19691         * @param {String} [options.modelProps.RequiredValidationMessage] Message to display for Required validation failure.
19692         * @param {String} [options.modelProps.ValidationPattern] Javascript regular expression for input validation.
19693         * @param {String} [options.modelProps.ValidationPatternMessage] Custom message to display if ValidationPattern fails.
19694         * @memberOf dpage.modules
19695         * @extends {dpage.modules.Model}
19696         */
19697        return declare("dpage.modules.SingleValueModel", [dpage.modules.Model], /** @lends dpage.modules.SingleValueModel.prototype */ {
19698            _model: null,
19699            _dataCallbacks: null,
19700            _lastDataCallbackId: 0,
19701            _dataCallbackRowId: 0,
19702            _modelProps: null,
19703            _isDirty: false,
19704            _displayName:null,
19705
19706            constructor: function (options) {
19707                var self = this;
19708
19709                this._dataCallbacks = [];
19710
19711                if (options != null) {
19712                    if (options.modelProps != null)
19713                        this._modelProps = options.modelProps;
19714
19715                    if (options.model != null) {
19716                        this._model = options.model;
19717                    }
19718
19719                    if (options.displayName != null)
19720                        this._displayName = options.displayName;
19721                }
19722
19723                if (this._modelProps == null) {
19724                    this._modelProps = {FieldName : '' , DataType:'TEXT'};
19725                }
19726            },
19727            getRawModel : function()
19728            {
19729                return this._model;
19730            },
19731            /**
19732            * Get the name of this model property. Used in things like validation message texts. Priority is 1) this._displayName , 2) modelProps.DisplayName, 3) modelProps.FieldName
19733            * @returns {String} 
19734            */
19735            getDisplayName : function()
19736            {
19737                if (this._displayName != null)
19738                    return this._displayName;
19739
19740                else if (this._modelProps != null && this._modelProps.DisplayName != null)
19741                    return this._modelProps.DisplayName;
19742
19743                else if (this._modelProps != null && this._modelProps.FieldName != null)
19744                    return this._modelProps.FieldName;
19745
19746                return "";
19747            },
19748            /**
19749            * You can listen for changes to data by adding your callback routine here. Changes can be listened in on a row level
19750            * or global level only.
19751            * @param {function} funcRef The function to call when data is modified. The callback function will be passed a single parameter containing the new value.
19752            * Will be called if that particular row is changed.
19753            * @returns {Number} The id of the callback. Can be used to remove the callback.
19754            */
19755            addDataCallback: function (funcRef) {
19756                var rowId;
19757                var id = ++this._lastDataCallbackId;
19758
19759                this._dataCallbacks.push({ id: id, func: funcRef});
19760
19761                return id;
19762            },
19763            /**
19764            * @param {Number} id The callback id to remove.
19765            * @returns {void}
19766            */
19767            removeDataCallback: function (id) {
19768                for (idx = 0; idx < this._dataCallbacks.length ; idx++) {
19769                    if (this._dataCallbacks[idx].id == id)
19770                        this._dataCallbacks.splice(idx, 1);
19771                }
19772            },
19773            /**
19774            * Get metadata for the model.
19775            * @returns {Object}
19775 This object contains the meta-data properties. Refer to the constructor's options.modelProps property 
19776            *                   for information on supported properties.
19777            */
19778            getMetadata : function()
19779            {
19780                return this._modelProps;
19781            },
19782            /**
19783            * Set a value. The official way to set a value in a SingleValueModel
19784            * @param {Object} value The value to set. Must be a bool, String, or Number
19785            * @returns {void}
19786            */
19787            setValue: function (value) {
19788                
19789                if (this._modelProps.DataType == "DATE" && value != null && value != "" && dpage.modules.Date.parseModelValue(value) == null)
19790                    throw new Error("Attempting to set a value on a SingleValueModel DataType=='DATE'. Value is: " + value + " but it should be in ISO-8601 format.");
19791
19792                this._model = value;
19793
19794                this._isDirty = true;
19795
19796                this.doCallbacks();
19797            },
19798            /**
19799            * Has the data been updated?
19800            * @returns {bool} true | false.
19801            */
19802            isDirty : function()
19803            {
19804                return this._isDirty;
19805            },
19806            setClean : function()
19807            {
19808                this._isDirty = false;
19809            },
19810            /**
19811            * A caller can cause the registered callback routines to fire by calling this method directly. Not normally needed. 
19812            * This will cause the callback routines to be called even if data hasn't really been changed.
19813            * Only use this method if you know what you are doing.
19814            * @returns {void}
19815            */
19816            doCallbacks: function () {
19817
19818                for (var x = 0; x < this._dataCallbacks.length ; x++) {
19819                    var callback = this._dataCallbacks[x].func;
19820                    callback(this.getValue());
19821                }
19822            },
19823            /**
19824            * The official way to get a value from a SingleValueModel.
19825            * @returns {Object} The data. Will be String, Number, or Boolean
19826            */
19827            getValue: function () {
19828                return this._model;
19829            }
19830            
19831        });
19832    }
19833);
19834},
19835'dpage/widgets/BaseWidget':function(){
19836define(["dojo/on",
19837
19838      "dpage/modules/Date",
19839      "dojo/_base/declare",
19840      "dijit/_WidgetBase",
19841      "dpage/modules/TabularModel"
19842], function (on) {
19843    /**
19844    * @namespace dpage
19845    */
19846    /**
19847    * @namespace widgets
19848    * @memberOf dpage
19849    */
19850    /**
19851    * Class to contain methods common to all UI widgets.
19852    * @class BaseWidget
19853    * @param {Object} [options] Optional options for the widget
19854    * @param {dpage.widgets.Container} [options.container] The container of the widget.
19855    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
19856    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
19857    *                               is created.
19858    * @param {Object} [containerNode] Optional container node to tie the widget to.
19859    * @memberOf dpage.widgets
19860    * @extends {dijit._WidgetBase}
19861    */
19862    var theClass = dojo.declare("dpage.widgets.BaseWidget", [dijit._WidgetBase], /** @lends dpage.widgets.BaseWidget.prototype */ {
19863        _widgetContainer: null,
19864        _widgetId: null,
19865        _validateCallback: null,
19866        _doDataSubscriptions: true,
19867        _overlay: null,
19868        _oldFocusedNode : null,
19869        _containerNode: null, //The root dom node of the widget.
19870        _validationMessage: null,
19871
19872        constructor: function (options, containerNode) {
19873            if (options != null)
19874            {
19875                if(options.container != null)
19876                    this._widgetContainer = options.container;
19877                if (options.validateCallback != null)
19878                {
19879                    this._validateCallback = options.validateCallback;
19880                }
19881                if (options.wid != null)
19882                    this._widgetId = options.wid;
19883                else
19884                    this._widgetId = dpage.widgets.BaseWidget.getAnonWidgetId();
19885            }
19886            
19887            if(this._widgetContainer != null)
19888                this._widgetContainer.addWidget(this);
19889        },
19890         
19891        postCreate : function()
19892        {
19893            this._updateView();
19894        },
19895        //catch-all for dpage widgets.
19896        buildRendering: function () {
19897            this.domNode = this._containerNode;
19898            return this._containerNode;
19899        },
19900        _blurActiveElement : function()
19901        {
19902            if (document.activeElement != null) {
19903                this._oldFocusedNode = document.activeElement;
19904                if (this._oldFocusedNode.blur != null)
19905                    this._oldFocusedNode.blur();
19906            }
19907        },
19908        _focusOldActiveElement: function () {
19909            if (this._oldFocusedNode != null && this._oldFocusedNode.focus != null) {
19910                this._oldFocusedNode.focus();
19911                this._oldFocusedNode = null;
19912            }
19913        },
19914        /**
19915        * Block or un-block user interaction with the widget. 
19916        * @param {bool} trueOrFalse If true, the widget will be blocked out, if false, un-blocked out.
19917        * @returns {void}
19918        */
19919        blockUI : function(trueOrFalse)
19920        {
19921            var self = this;
19922
19923            if(trueOrFalse)
19924            {
19925                if (this._overlay == null) {
19926                    //make sure this is the highest zIndex of any element in the page so it blocks the whole page.
19927                    this._overlay = new dojox.widget.Standby({ target: this.getDomNode(), zIndex: 1001 });
19928                    document.body.appendChild(this._overlay.domNode);
19929                    this._overlay.startup();
19930                }
19931                
19932                //for the case when tab is hit on an element and we call blockUI here, the next element in the tab order is 
19933                //focused after we get here, so we try to overcome this by setting a timeout so that by the time
19934                //_blurActiveElement is called, the next element in the tab order is already focused, so that we can un-focus it.
19935                setTimeout(function () { self._blurActiveElement(); });
19936
19937                this._overlay.show();
19938            }
19939            else
19940            {
19941                if (this._overlay != null)
19942                    this._overlay.hide();
19943
19944                if (this._oldFocusedNode != null) {
19945                    if (this._oldFocusedNode.focus != null) {
19946                        setTimeout(function () {
19947                            self._focusOldActiveElement();
19948                        },0);
19949                    }
19950                }
19951            }
19952        },
19953        /**
19954        * Get a reference to the native browser dom node. 
19955        * @returns {NativeDomNode}
19956        */
19957        getDomNode : function()
19958        {
19959            return this._containerNode;
19960        },
19961
19962        /**
19963            * Gets the widgetId.
19964            * @returns {String}
19965            */
19966        getWidgetId: function () {
19967            return this._widgetId;
19968        },
19969
19970        /**
19971        * Gives you the container of the Widget. Could be a page or a generic container (like a dialog).
19972        * This method will return null if there is no container (container not specified in widget options).
19973        * @returns {dpage.widgets.Container} null for no container, or reference to the Container object.
19974        */
19975        getContainer: function () {
19976            return this._widgetContainer;
19977        },
19978        /**
19979        * Sets the container object for this widget
19980        * @param {dpage.widgets.Container} obj 
19981        */
19982        setContainer:function(obj)
19983        {
19984            if (this._widgetContainer != null)
19985                this._widgetContainer.removeWidget(this.getWidgetId());
19986
19987            this._widgetContainer = obj;
19988
19989            obj.addWidget(this);
19990        },
19991        /*
19992        * This method re-draws the widget in response to model changes. Can be subclassed to do widget specific drawing. All widgets overriding this method should call the base
19993        * class to do common BaseWidget operations such as clearing the validation state.
19994        * @returns {void}
19995        */
19996        _updateView : function()
19997        {
19998            //clear the validation state. Validation is not performed on direct model changes, only on USER INPUT.
19999            this.setValidationMessage(null);
20000        },
20001        /** Perform validation for this one particular BaseWidget.
20002        * @returns {String} Returns null for success. A string message indicating the error if not successfull.
20003        */
20004        validate : function()
20005        {
20006            if (this._validateCallback)
20007                return this._validateCallback(this);
20008        },
20009        /** Set the validation state of the control. 
20010        * @param {String} message The message to display. Pass in null to clear an invalid state. Non-null to set the invalid state. 
20011        * @returns {void}
20012        */
20013        setValidationMessage : function(message){
20014            this._validationMessage = message;
20015        },
20016        /**
20017        * Get the validation state of the control. 
20018        * @returns {String} null for valid state. Non-null for an invalid state and the value will be the message.
20019        */
20020        getValidationMessage : function(){
20021            return this._validationMessage;
20022        },
20023        /**
20024        * This method performs any cleanup needed for the widget and removes it's getDomNode() from the DOM.
20025        * @returns {void}
20026        */
20027        destroy : function()
20028        {
20029            return this.inherited(arguments);
20030        }
20031    });
20032
20033    theClass._awId = 0;
20034
20035    /**
20036    * Get a unique id used to uniquely identify a widget with no named id.
20037    * @memberof dpage.widgets.BaseWidget
20038    * @name getAnonWidgetId
20039    * @function
20040    * @returns {String} 
20041    */
20042    theClass.getAnonWidgetId = function () {
20043        return "aw" + (--theClass._awId);
20044    };
20045
20046    /**
20047    * Return a message indicating the error or null for no validation error.
20048    * @memberof dpage.widgets.BaseWidget
20049    * @name validate
20050    * @function
20051    * @param {Object} value The value to validate.
20052    * @param {Object} metaData The metadata object from the model.
20053    * @param {String} fieldName The name of the field to display in the non-custom error message.
20054    * @returns {String} null for success. non-empty string otherwise.
20055    */
20056    theClass.validate = function (value, metaData , fieldName) {
20057        var ret;
20058        var dataType;
20059
20060        dataType = metaData.DataType;
20061
20062        if (dataType == "NUMBER")
20063            ret = dpage.widgets.BaseWidget.validateNumber(value , metaData , fieldName);
20064        else if (dataType == "TEXT")
20065            ret = dpage.widgets.BaseWidget.validateText(value, metaData, fieldName);
20066        else if (dataType == "DATE")
20067            ret = dpage.widgets.BaseWidget.validateDate(value, metaData, fieldName);
20068
20069        return ret;
20070    };
20071
20072    /**
20073    * Return a message indicating the error or null for no validation error.
20074    * @memberof dpage.widgets.BaseWidget
20075    * @name validateNumber
20076    * @function
20077    * @param {Object} value The value to validate.
20078    * @param {Object} metaData The metadata object from the model.
20079    * @param {String} fieldName The name of the field to display in the non-custom error message.
20080    * @returns {String} null for success. non-empty string otherwise.
20081    */
20082    theClass.validateNumber = function (value , metaData , fieldName)
20083    {
20084        var vMsg;
20085        var numDecimalPlaces;
20086        var minValue;
20087        var maxValue;
20088        var numberPattern;
20089        var re;
20090        var parsedNumber;
20091        var colInfo;
20092        var required;
20093
20094        vMsg = metaData.NumberValidationMessage;
20095        var requiredMessage = metaData.RequiredValidationMessage;
20096        numDecimalPlaces = metaData.NumDecimals;
20097        minValue = metaData.MinValue;
20098        maxValue = metaData.MaxValue;
20099        required = metaData.Required;
20100
20101        if (vMsg == null) {
20102            vMsg = fieldName + " must be a";
20103
20104            if (numDecimalPlaces == 0)
20105                vMsg += " whole number";
20106            else if (numDecimalPlaces == -1 || numDecimalPlaces == null)
20107                vMsg += " decimal number";
20108            else
20109                vMsg += " decimal number (maximum " + numDecimalPlaces + " decimal places)";
20110
20111            if (minValue != null && maxValue != null)
20112                vMsg += " between " + minValue + " and " + maxValue;
20113            else if (minValue != null)
20114                vMsg += " greater than " + minValue;
20115            else if (minValue != null)
20116                vMsg += " less than " + maxValue;
20117
20118            vMsg += ".";
20119        }
20120        
20121        if (fieldName == null)
20122            fieldName = metaData.FieldName;
20123
20124        if (value == null || /^\s*$/.test(value)) {
20125            if (required ) {
20126                if (requiredMessage != null)
20127                    return requiredMessage;
20128                else
20129                    return fieldName + " is required.";
20130            }
20131        }
20132        else {
20133            //we only get here in the case of non-null.
20134            if (numDecimalPlaces == -1 || numDecimalPlaces == null)
20135                numberPattern = "(^\\s*-[0-9]*\\s*\\.[0-9]+\\s*$)|(^\\s*-[0-9]+\\s*$)|(^\\s*[0-9]*\\.[0-9]+\\s*$)|(^\\s*[0-9]+\\s*$)$";
20136            else if(numDecimalPlaces == 0)
20137                numberPattern = "(^\\s*-\\s*[0-9]+\\s*$)|(^\\s*[0-9]*\\s*)$";
20138            else
20139                numberPattern = "(^\\s*-\\s*[0-9]*\\.[0-9]{1," + numDecimalPlaces + "}\\s*$)|(^\\s*-[0-9]+\\s*$)|(^\\s*[0-9]*\\.[0-9]{1," + numDecimalPlaces + "}\\s*$)|(^[0-9]+\\s*$)";
20140
20141            re = new RegExp(numberPattern);
20142
20143            if (!re.exec(value))
20144            {
20145                return vMsg;
20146            }
20147
20148            parsedNumber = new Number(value);
20149
20150            if((maxValue != null && parsedNumber > maxValue)
20151                ||
20152                (minValue != null && parsedNumber < minValue))
20153            {
20154                return vMsg;
20155            }
20156        }
20157
20158        return null;
20159    };
20160
20161    /**
20162    * Return a message indicating the error or null for no validation error.
20163    * @memberof dpage.widgets.BaseWidget
20164    * @name validateText
20165    * @function
20166    * @param {Object} value The value to validate.
20167    * @param {Object} metaData The metadata object from the model.
20168    * @param {String} fieldName The name of the field to display in the non-custom error message.
20169    * @returns {String} null for success. non-empty string otherwise.
20170    */
20171    dpage.widgets.BaseWidget.validateText = function (value, metaData , fieldName) {
20172        var maxLength = metaData.MaxLength;
20173        var required = metaData.Required;
20174        var requiredMessage = metaData.RequiredValidationMessage;
20175        var maxLengthMessage = metaData.MaxLengthValidationMessage;
20176        var patternMessage = metaData.ValidationPatternMessage;
20177        var pattern = metaData.ValidationPattern;
20178
20179        if(fieldName == null)
20180            fieldName = metaData.FieldName;
20181
20182        if (value != null && maxLength != null && value.length > maxLength) {
20183            if (maxLengthMessage != null)
20184                return maxLengthMessage;
20185            else
20186                return fieldName + " must be less than " + (maxLength + 1) + " characters.";
20187        }
20188
20189        if (required && (value == null || /^\s*$/.exec(value))) {
20190            if (requiredMessage != null)
20191                return requiredMessage;
20192            else
20193                return fieldName + " is required.";
20194        }
20195
20196        if (pattern != null) {
20197            var re = new RegExp(pattern);
20198            var nnv = value == null ? "" : value;
20199            if (!re.exec(nnv)) {
20200                if (patternMessage != null)
20201                    return patternMessage;
20202                else
20203                    return fieldName + " must match the pattern: '" + pattern + "'.";
20204            }
20205        }
20206
20207        return null;
20208    };
20209
20210    /**
20211    * Return a message indicating the error or null for no validation error.
20212    * @memberof dpage.widgets.BaseWidget
20213    * @name validateDate
20214    * @function
20215    * @param {Object} value The value to validate.
20216    * @param {Object} metaData The metadata object from the model.
20217    * @param {String} fieldName The name of the field to display in the non-custom error message.
20218    * @returns {String} null for success. non-empty string otherwise.
20219    */
20220    dpage.widgets.BaseWidget.validateDate = function (value, metaData, fieldName) {
20221        var maxLength = metaData.MaxLength;
20222        var required = metaData.Required;
20223        var requiredMessage = metaData.RequiredValidationMessage;
20224        var maxLengthMessage = metaData.MaxLengthValidationMessage;
20225        var patternMessage = metaData.ValidationPatternMessage;
20226        var pattern = metaData.ValidationPattern;
20227
20228        if (fieldName == null)
20229            fieldName = metaData.FieldName;
20230
20231        if (value != null && maxLength != null && value.length > maxLength) {
20232            if (maxLengthMessage != null)
20233                return maxLengthMessage;
20234            else
20235                return fieldName + " must be less than " + (maxLength + 1) + " characters.";
20236        }
20237
20238        if (required && (value == null || /^\s*$/.exec(value))) {
20239            if (requiredMessage != null)
20240                return requiredMessage;
20241            else
20242                return fieldName + " is required.";
20243        }
20244
20245        if (pattern != null) {
20246            var re = new RegExp(pattern);
20247            var nnv = value == null ? "" : value;
20248            if (!re.exec(nnv)) {
20249                if (patternMessage != null)
20250                    return patternMessage;
20251                else
20252                    return fieldName + " must match the pattern: '" + pattern + "'.";
20253            }
20254        }
20255
20256        if (value != null && value != "") {
20257            //attempt to parse the date.
20258            var v = dpage.modules.Date.parseModelValue(value);
20259
20260            if (v == null)
20261                return fieldName + " must be a valid date.";
20262        }
20263
20264        return null;
20265    };
20266
20267    return theClass;
20268});
20269
20270},
20271'dijit/_WidgetBase':function(){
20272define([
20273	"require", // require.toUrl
20274	"dojo/_base/array", // array.forEach array.map
20275	"dojo/aspect",
20276	"dojo/_base/config", // config.blankGif
20277	"dojo/_base/connect", // connect.connect
20278	"dojo/_base/declare", // declare
20279	"dojo/dom", // dom.byId
20280	"dojo/dom-attr", // domAttr.set domAttr.remove
20281	"dojo/dom-class", // domClass.add domClass.replace
20282	"dojo/dom-construct", // domConstruct.destroy domConstruct.place
20283	"dojo/dom-geometry", // isBodyLtr
20284	"dojo/dom-style", // domStyle.set, domStyle.get
20285	"dojo/has",
20286	"dojo/_base/kernel",
20287	"dojo/_base/lang", // mixin(), isArray(), etc.
20288	"dojo/on",
20289	"dojo/ready",
20290	"dojo/Stateful", // Stateful
20291	"dojo/topic",
20292	"dojo/_base/window", // win.body()
20293	"./Destroyable",
20294	"dojo/has!dojo-bidi?./_BidiMixin",
20295	"./registry"    // registry.getUniqueId(), registry.findWidgets()
20296], function(require, array, aspect, config, connect, declare,
20297			dom, domAttr, domClass, domConstruct, domGeometry, domStyle, has, kernel,
20298			lang, on, ready, Stateful, topic, win, Destroyable, _BidiMixin, registry){
20299
20300	// module:
20301	//		dijit/_WidgetBase
20302
20303	// Flag to make dijit load modules the app didn't explicitly request, for backwards compatibility
20304	has.add("dijit-legacy-requires", !kernel.isAsync);
20305
20306	// Flag to enable support for textdir attribute
20307	has.add("dojo-bidi", false);
20308
20309
20310	// For back-compat, remove in 2.0.
20311	if(has("dijit-legacy-requires")){
20312		ready(0, function(){
20313			var requires = ["dijit/_base/manager"];
20314			require(requires);	// use indirection so modules not rolled into a build
20315		});
20316	}
20317
20318	// Nested hash listing attributes for each tag, all strings in lowercase.
20319	// ex: {"div": {"style": true, "tabindex" true}, "form": { ...
20320	var tagAttrs = {};
20321
20322	function getAttrs(obj){
20323		var ret = {};
20324		for(var attr in obj){
20325			ret[attr.toLowerCase()] = true;
20326		}
20327		return ret;
20328	}
20329
20330	function nonEmptyAttrToDom(attr){
20331		// summary:
20332		//		Returns a setter function that copies the attribute to this.domNode,
20333		//		or removes the attribute from this.domNode, depending on whether the
20334		//		value is defined or not.
20335		return function(val){
20336			domAttr[val ? "set" : "remove"](this.domNode, attr, val);
20337			this._set(attr, val);
20338		};
20339	}
20340
20341	function isEqual(a, b){
20342		//	summary:
20343		//		Function that determines whether two values are identical,
20344		//		taking into account that NaN is not normally equal to itself
20345		//		in JS.
20346
20347		return a === b || (/* a is NaN */ a !== a && /* b is NaN */ b !== b);
20348	}
20349
20350	var _WidgetBase = declare("dijit._WidgetBase", [Stateful, Destroyable], {
20351		// summary:
20352		//		Future base class for all Dijit widgets.
20353		// description:
20354		//		Future base class for all Dijit widgets.
20355		//		_Widget extends this class adding support for various features needed by desktop.
20356		//
20357		//		Provides stubs for widget lifecycle methods for subclasses to extend, like postMixInProperties(), buildRendering(),
20358		//		postCreate(), startup(), and destroy(), and also public API methods like set(), get(), and watch().
20359		//
20360		//		Widgets can provide custom setters/getters for widget attributes, which are called automatically by set(name, value).
20361		//		For an attribute XXX, define methods _setXXXAttr() and/or _getXXXAttr().
20362		//
20363		//		_setXXXAttr can also be a string/hash/array mapping from a widget attribute XXX to the widget's DOMNodes:
20364		//
20365		//		- DOM node attribute
20366		// |		_setFocusAttr: {node: "focusNode", type: "attribute"}
20367		// |		_setFocusAttr: "focusNode"	(shorthand)
20368		// |		_setFocusAttr: ""		(shorthand, maps to this.domNode)
20369		//		Maps this.focus to this.focusNode.focus, or (last example) this.domNode.focus
20370		//
20371		//		- DOM node innerHTML
20372		//	|		_setTitleAttr: { node: "titleNode", type: "innerHTML" }
20373		//		Maps this.title to this.titleNode.innerHTML
20374		//
20375		//		- DOM node innerText
20376		//	|		_setTitleAttr: { node: "titleNode", type: "innerText" }
20377		//		Maps this.title to this.titleNode.innerText
20378		//
20379		//		- DOM node CSS class
20380		// |		_setMyClassAttr: { node: "domNode", type: "class" }
20381		//		Maps this.myClass to this.domNode.className
20382		//
20383		//		If the value of _setXXXAttr is an array, then each element in the array matches one of the
20384		//		formats of the above list.
20385		//
20386		//		If the custom setter is null, no action is performed other than saving the new value
20387		//		in the widget (in this).
20388		//
20389		//		If no custom setter is defined for an attribute, then it will be copied
20390		//		to this.focusNode (if the widget defines a focusNode), or this.domNode otherwise.
20391		//		That's only done though for attributes that match DOMNode attributes (title,
20392		//		alt, aria-labelledby, etc.)
20393
20394		// id: [const] String
20395		//		A unique, opaque ID string that can be assigned by users or by the
20396		//		system. If the developer passes an ID which is known not to be
20397		//		unique, the specified ID is ignored and the system-generated ID is
20398		//		used instead.
20399		id: "",
20400		_setIdAttr: "domNode", // to copy to this.domNode even for auto-generated id's
20401
20402		// lang: [const] String
20403		//		Rarely used.  Overrides the default Dojo locale used to render this widget,
20404		//		as defined by the [HTML LANG](http://www.w3.org/TR/html401/struct/dirlang.html#adef-lang) attribute.
20405		//		Value must be among the list of locales specified during by the Dojo bootstrap,
20406		//		formatted according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt) (like en-us).
20407		lang: "",
20408		// set on domNode even when there's a focus node.	but don't set lang="", since that's invalid.
20409		_setLangAttr: nonEmptyAttrToDom("lang"),
20410
20411		// dir: [const] String
20412		//		Bi-directional support, as defined by the [HTML DIR](http://www.w3.org/TR/html401/struct/dirlang.html#adef-dir)
20413		//		attribute. Either left-to-right "ltr" or right-to-left "rtl".  If undefined, widgets renders in page's
20414		//		default direction.
20415		dir: "",
20416		// set on domNode even when there's a focus node.	but don't set dir="", since that's invalid.
20417		_setDirAttr: nonEmptyAttrToDom("dir"), // to set on domNode even when there's a focus node
20418
20419		// class: String
20420		//		HTML class attribute
20421		"class": "",
20422		_setClassAttr: { node: "domNode", type: "class" },
20423
20424		// Override automatic assigning type -->
20424 focusNode, it causes exception on IE6-8.
20425		// Instead, type must be specified as ${type} in the template, as part of the original DOM.
20426		_setTypeAttr: null,
20427
20428		// style: String||Object
20429		//		HTML style attributes as cssText string or name/value hash
20430		style: "",
20431
20432		// title: String
20433		//		HTML title attribute.
20434		//
20435		//		For form widgets this specifies a tooltip to display when hovering over
20436		//		the widget (just like the native HTML title attribute).
20437		//
20438		//		For TitlePane or for when this widget is a child of a TabContainer, AccordionContainer,
20439		//		etc., it's used to specify the tab label, accordion pane title, etc.  In this case it's
20440		//		interpreted as HTML.
20441		title: "",
20442
20443		// tooltip: String
20444		//		When this widget's title attribute is used to for a tab label, accordion pane title, etc.,
20445		//		this specifies the tooltip to appear when the mouse is hovered over that text.
20446		tooltip: "",
20447
20448		// baseClass: [protected] String
20449		//		Root CSS class of the widget (ex: dijitTextBox), used to construct CSS classes to indicate
20450		//		widget state.
20451		baseClass: "",
20452
20453		// srcNodeRef: [readonly] DomNode
20454		//		pointer to original DOM node
20455		srcNodeRef: null,
20456
20457		// domNode: [readonly] DomNode
20458		//		This is our visible representation of the widget! Other DOM
20459		//		Nodes may by assigned to other properties, usually through the
20460		//		template system's data-dojo-attach-point syntax, but the domNode
20461		//		property is the canonical "top level" node in widget UI.
20462		domNode: null,
20463
20464		// containerNode: [readonly] DomNode
20465		//		Designates where children of the source DOM node will be placed.
20466		//		"Children" in this case refers to both DOM nodes and widgets.
20467		//		For example, for myWidget:
20468		//
20469		//		|	<div data-dojo-type=myWidget>
20470		//		|		<b> here's a plain DOM node
20471		//		|		<span data-dojo-type=subWidget>and a widget</span>
20472		//		|		<i> and another plain DOM node </i>
20473		//		|	</div>
20474		//
20475		//		containerNode would point to:
20476		//
20477		//		|		<b> here's a plain DOM node
20478		//		|		<span data-dojo-type=subWidget>and a widget</span>
20479		//		|		<i> and another plain DOM node </i>
20480		//
20481		//		In templated widgets, "containerNode" is set via a
20482		//		data-dojo-attach-point assignment.
20483		//
20484		//		containerNode must be defined for any widget that accepts innerHTML
20485		//		(like ContentPane or BorderContainer or even Button), and conversely
20486		//		is null for widgets that don't, like TextBox.
20487		containerNode: null,
20488
20489		// ownerDocument: [const] Document?
20490		//		The document this widget belongs to.  If not specified to constructor, will default to
20491		//		srcNodeRef.ownerDocument, or if no sourceRef specified, then to the document global
20492		ownerDocument: null,
20493		_setOwnerDocumentAttr: function(val){
20494			// this setter is merely to avoid automatically trying to set this.domNode.ownerDocument
20495			this._set("ownerDocument", val);
20496		},
20497
20498		/*=====
20499		// _started: [readonly] Boolean
20500		//		startup() has completed.
20501		_started: false,
20502		=====*/
20503
20504		// attributeMap: [protected] Object
20505		//		Deprecated.	Instead of attributeMap, widget should have a _setXXXAttr attribute
20506		//		for each XXX attribute to be mapped to the DOM.
20507		//
20508		//		attributeMap sets up a "binding" between attributes (aka properties)
20509		//		of the widget and the widget's DOM.
20510		//		Changes to widget attributes listed in attributeMap will be
20511		//		reflected into the DOM.
20512		//
20513		//		For example, calling set('title', 'hello')
20514		//		on a TitlePane will automatically cause the TitlePane's DOM to update
20515		//		with the new title.
20516		//
20517		//		attributeMap is a hash where the key is an attribute of the widget,
20518		//		and the value reflects a binding to a:
20519		//
20520		//		- DOM node attribute
20521		// |		focus: {node: "focusNode", type: "attribute"}
20522		//		Maps this.focus to this.focusNode.focus
20523		//
20524		//		- DOM node innerHTML
20525		//	|		title: { node: "titleNode", type: "innerHTML" }
20526		//		Maps this.title to this.titleNode.innerHTML
20527		//
20528		//		- DOM node innerText
20529		//	|		title: { node: "titleNode", type: "innerText" }
20530		//		Maps this.title to this.titleNode.innerText
20531		//
20532		//		- DOM node CSS class
20533		// |		myClass: { node: "domNode", type: "class" }
20534		//		Maps this.myClass to this.domNode.className
20535		//
20536		//		If the value is an array, then each element in the array matches one of the
20537		//		formats of the above list.
20538		//
20539		//		There are also some shorthands for backwards compatibility:
20540		//
20541		//		- string --> { node: string, type: "attribute" }, for example:
20542		//
20543		//	|	"focusNode" ---> { node: "focusNode", type: "attribute" }
20544		//
20545		//		- "" --> { node: "domNode", type: "attribute" }
20546		attributeMap: {},
20547
20548		// _blankGif: [protected] String
20549		//		Path to a blank 1x1 image.
20550		//		Used by `<img>` nodes in templates that really get their image via CSS background-image.
20551		_blankGif: config.blankGif || require.toUrl("dojo/resources/blank.gif"),
20552
20553		//////////// INITIALIZATION METHODS ///////////////////////////////////////
20554
20555		/*=====
20556		constructor: function(params, srcNodeRef){
20557			// summary:
20558			//		Create the widget.
20559			// params: Object|null
20560			//		Hash of initialization parameters for widget, including scalar values (like title, duration etc.)
20561			//		and functions, typically callbacks like onClick.
20562			//		The hash can contain any of the widget's properties, excluding read-only properties.
20563			// srcNodeRef: DOMNode|String?
20564			//		If a srcNodeRef (DOM node) is specified:
20565			//
20566			//		- use srcNodeRef.innerHTML as my contents
20567			//		- if this is a behavioral widget then apply behavior to that srcNodeRef
20568			//		- otherwise, replace srcNodeRef with my generated DOM tree
20569		},
20570		=====*/
20571
20572		_introspect: function(){
20573			// summary:
20574			//		Collect metadata about this widget (only once per class, not once per instance):
20575			//
20576			//			- list of attributes with custom setters, storing in this.constructor._setterAttrs
20577			//			- generate this.constructor._onMap, mapping names like "mousedown" to functions like onMouseDown
20578
20579			var ctor = this.constructor;
20580			if(!ctor._setterAttrs){
20581				var proto = ctor.prototype,
20582					attrs = ctor._setterAttrs = [], // attributes with custom setters
20583					onMap = (ctor._onMap = {});
20584
20585				// Items in this.attributeMap are like custom setters.  For back-compat, remove for 2.0.
20586				for(var name in proto.attributeMap){
20587					attrs.push(name);
20588				}
20589
20590				// Loop over widget properties, collecting properties with custom setters and filling in ctor._onMap.
20591				for(name in proto){
20592					if(/^on/.test(name)){
20593						onMap[name.substring(2).toLowerCase()] = name;
20594					}
20595
20596					if(/^_set[A-Z](.*)Attr$/.test(name)){
20597						name = name.charAt(4).toLowerCase() + name.substr(5, name.length - 9);
20598						if(!proto.attributeMap || !(name in proto.attributeMap)){
20599							attrs.push(name);
20600						}
20601					}
20602				}
20603
20604				// Note: this isn't picking up info on properties like aria-label and role, that don't have custom setters
20605				// but that set() maps to attributes on this.domNode or this.focusNode
20606			}
20607		},
20608
20609		postscript: function(/*Object?*/params, /*DomNode|String*/srcNodeRef){
20610			// summary:
20611			//		Kicks off widget instantiation.  See create() for details.
20612			// tags:
20613			//		private
20614
20615			// Note that we skip calling this.inherited(), i.e. dojo/Stateful::postscript(), because 1.x widgets don't
20616			// expect their custom setters to get called until after buildRendering().  Consider changing for 2.0.
20617
20618			this.create(params, srcNodeRef);
20619		},
20620
20621		create: function(params, srcNodeRef){
20622			// summary:
20623			//		Kick off the life-cycle of a widget
20624			// description:
20625			//		Create calls a number of widget methods (postMixInProperties, buildRendering, postCreate,
20626			//		etc.), some of which of you'll want to override. See http://dojotoolkit.org/reference-guide/dijit/_WidgetBase.html
20627			//		for a discussion of the widget creation lifecycle.
20628			//
20629			//		Of course, adventurous developers could override create entirely, but this should
20630			//		only be done as a last resort.
20631			// params: Object|null
20632			//		Hash of initialization parameters for widget, including scalar values (like title, duration etc.)
20633			//		and functions, typically callbacks like onClick.
20634			//		The hash can contain any of the widget's properties, excluding read-only properties.
20635			// srcNodeRef: DOMNode|String?
20636			//		If a srcNodeRef (DOM node) is specified:
20637			//
20638			//		- use srcNodeRef.innerHTML as my contents
20639			//		- if this is a behavioral widget then apply behavior to that srcNodeRef
20640			//		- otherwise, replace srcNodeRef with my generated DOM tree
20641			// tags:
20642			//		private
20643
20644			// First time widget is instantiated, scan prototype to figure out info about custom setters etc.
20645			this._introspect();
20646
20647			// store pointer to original DOM tree
20648			this.srcNodeRef = dom.byId(srcNodeRef);
20649
20650			// No longer used, remove for 2.0.
20651			this._connects = [];
20652			this._supportingWidgets = [];
20653
20654			// this is here for back-compat, remove in 2.0 (but check NodeList-instantiate.html test)
20655			if(this.srcNodeRef && (typeof this.srcNodeRef.id == "string")){
20656				this.id = this.srcNodeRef.id;
20657			}
20658
20659			// mix in our passed parameters
20660			if(params){
20661				this.params = params;
20662				lang.mixin(this, params);
20663			}
20664			this.postMixInProperties();
20665
20666			// Generate an id for the widget if one wasn't specified, or it was specified as id: undefined.
20667			// Do this before buildRendering() because it might expect the id to be there.
20668			if(!this.id){
20669				this.id = registry.getUniqueId(this.declaredClass.replace(/\./g, "_"));
20670				if(this.params){
20671					// if params contains {id: undefined}, prevent _applyAttributes() from processing it
20672					delete this.params.id;
20673				}
20674			}
20675
20676			// The document and <body> node this widget is associated with
20677			this.ownerDocument = this.ownerDocument || (this.srcNodeRef ? this.srcNodeRef.ownerDocument : document);
20678			this.ownerDocumentBody = win.body(this.ownerDocument);
20679
20680			registry.add(this);
20681
20682			this.buildRendering();
20683
20684			var deleteSrcNodeRef;
20685
20686			if(this.domNode){
20687				// Copy attributes listed in attributeMap into the [newly created] DOM for the widget.
20688				// Also calls custom setters for all attributes with custom setters.
20689				this._applyAttributes();
20690
20691				// If srcNodeRef was specified, then swap out original srcNode for this widget's DOM tree.
20692				// For 2.0, move this after postCreate().  postCreate() shouldn't depend on the
20693				// widget being attached to the DOM since it isn't when a widget is created programmatically like
20694				// new MyWidget({}).	See #11635.
20695				var source = this.srcNodeRef;
20696				if(source && source.parentNode && this.domNode !== source){
20697					source.parentNode.replaceChild(this.domNode, source);
20698					deleteSrcNodeRef = true;
20699				}
20700
20701				// Note: for 2.0 may want to rename widgetId to dojo._scopeName + "_widgetId",
20702				// assuming that dojo._scopeName even exists in 2.0
20703				this.domNode.setAttribute("widgetId", this.id);
20704			}
20705			this.postCreate();
20706
20707			// If srcNodeRef has been processed and removed from the DOM (e.g. TemplatedWidget) then delete it to allow GC.
20708			// I think for back-compatibility it isn't deleting srcNodeRef until after postCreate() has run.
20709			if(deleteSrcNodeRef){
20710				delete this.srcNodeRef;
20711			}
20712
20713			this._created = true;
20714		},
20715
20716		_applyAttributes: function(){
20717			// summary:
20718			//		Step during widget creation to copy  widget attributes to the
20719			//		DOM according to attributeMap and _setXXXAttr objects, and also to call
20720			//		custom _setXXXAttr() methods.
20721			//
20722			//		Skips over blank/false attribute values, unless they were explicitly specified
20723			//		as parameters to the widget, since those are the default anyway,
20724			//		and setting tabIndex="" is different than not setting tabIndex at all.
20725			//
20726			//		For backwards-compatibility reasons attributeMap overrides _setXXXAttr when
20727			//		_setXXXAttr is a hash/string/array, but _setXXXAttr as a functions override attributeMap.
20728			// tags:
20729			//		private
20730
20731			// Call this.set() for each property that was either specified as parameter to constructor,
20732			// or is in the list found above.	For correlated properties like value and displayedValue, the one
20733			// specified as a parameter should take precedence.
20734			// Particularly important for new DateTextBox({displayedValue: ...}) since DateTextBox's default value is
20735			// NaN and thus is not ignored like a default value of "".
20736
20737			// Step 1: Save the current values of the widget properties that were specified as parameters to the constructor.
20738			// Generally this.foo == this.params.foo, except if postMixInProperties() changed the value of this.foo.
20739			var params = {};
20740			for(var key in this.params || {}){
20741				params[key] = this._get(key);
20742			}
20743
20744			// Step 2: Call set() for each property with a non-falsy value that wasn't passed as a parameter to the constructor
20745			array.forEach(this.constructor._setterAttrs, function(key){
20746				if(!(key in params)){
20747					var val = this._get(key);
20748					if(val){
20749						this.set(key, val);
20750					}
20751				}
20752			}, this);
20753
20754			// Step 3: Call set() for each property that was specified as parameter to constructor.
20755			// Use params hash created above to ignore side effects from step #2 above.
20756			for(key in params){
20757				this.set(key, params[key]);
20758			}
20759		},
20760
20761		postMixInProperties: function(){
20762			// summary:
20763			//		Called after the parameters to the widget have been read-in,
20764			//		but before the widget template is instantiated. Especially
20765			//		useful to set properties that are referenced in the widget
20766			//		template.
20767			// tags:
20768			//		protected
20769		},
20770
20771		buildRendering: function(){
20772			// summary:
20773			//		Construct the UI for this widget, setting this.domNode.
20774			//		Most widgets will mixin `dijit._TemplatedMixin`, which implements this method.
20775			// tags:
20776			//		protected
20777
20778			if(!this.domNode){
20779				// Create root node if it wasn't created by _TemplatedMixin
20780				this.domNode = this.srcNodeRef || this.ownerDocument.createElement("div");
20781			}
20782
20783			// baseClass is a single class name or occasionally a space-separated list of names.
20784			// Add those classes to the DOMNode.  If RTL mode then also add with Rtl suffix.
20785			// TODO: make baseClass custom setter
20786			if(this.baseClass){
20787				var classes = this.baseClass.split(" ");
20788				if(!this.isLeftToRight()){
20789					classes = classes.concat(array.map(classes, function(name){
20790						return name + "Rtl";
20791					}));
20792				}
20793				domClass.add(this.domNode, classes);
20794			}
20795		},
20796
20797		postCreate: function(){
20798			// summary:
20799			//		Processing after the DOM fragment is created
20800			// description:
20801			//		Called after the DOM fragment has been created, but not necessarily
20802			//		added to the document.  Do not include any operations which rely on
20803			//		node dimensions or placement.
20804			// tags:
20805			//		protected
20806		},
20807
20808		startup: function(){
20809			// summary:
20810			//		Processing after the DOM fragment is added to the document
20811			// description:
20812			//		Called after a widget and its children have been created and added to the page,
20813			//		and all related widgets have finished their create() cycle, up through postCreate().
20814			//
20815			//		Note that startup() may be called while the widget is still hidden, for example if the widget is
20816			//		inside a hidden dijit/Dialog or an unselected tab of a dijit/layout/TabContainer.
20817			//		For widgets that need to do layout, it's best to put that layout code inside resize(), and then
20818			//		extend dijit/layout/_LayoutWidget so that resize() is called when the widget is visible.
20819			if(this._started){
20820				return;
20821			}
20822			this._started = true;
20823			array.forEach(this.getChildren(), function(obj){
20824				if(!obj._started && !obj._destroyed && lang.isFunction(obj.startup)){
20825					obj.startup();
20826					obj._started = true;
20827				}
20828			});
20829		},
20830
20831		//////////// DESTROY FUNCTIONS ////////////////////////////////
20832
20833		destroyRecursive: function(/*Boolean?*/ preserveDom){
20834			// summary:
20835			//		Destroy this widget and its descendants
20836			// description:
20837			//		This is the generic "destructor" function that all widget users
20838			//		should call to cleanly discard with a widget. Once a widget is
20839			//		destroyed, it is removed from the manager object.
20840			// preserveDom:
20841			//		If true, this method will leave the original DOM structure
20842			//		alone of descendant Widgets. Note: This will NOT work with
20843			//		dijit._TemplatedMixin widgets.
20844
20845			this._beingDestroyed = true;
20846			this.destroyDescendants(preserveDom);
20847			this.destroy(preserveDom);
20848		},
20849
20850		destroy: function(/*Boolean*/ preserveDom){
20851			// summary:
20852			//		Destroy this widget, but not its descendants.  Descendants means widgets inside of
20853			//		this.containerNode.   Will also destroy any resources (including widgets) registered via this.own().
20854			//
20855			//		This method will also destroy internal widgets such as those created from a template,
20856			//		assuming those widgets exist inside of this.domNode but outside of this.containerNode.
20857			//
20858			//		For 2.0 it's planned that this method will also destroy descendant widgets, so apps should not
20859			//		depend on the current ability to destroy a widget without destroying its descendants.   Generally
20860			//		they should use destroyRecursive() for widgets with children.
20861			// preserveDom: Boolean
20862			//		If true, this method will leave the original DOM structure alone.
20863			//		Note: This will not yet work with _TemplatedMixin widgets
20864
20865			this._beingDestroyed = true;
20866			this.uninitialize();
20867
20868			function destroy(w){
20869				if(w.destroyRecursive){
20870					w.destroyRecursive(preserveDom);
20871				}else if(w.destroy){
20872					w.destroy(preserveDom);
20873				}
20874			}
20875
20876			// Back-compat, remove for 2.0
20877			array.forEach(this._connects, lang.hitch(this, "disconnect"));
20878			array.forEach(this._supportingWidgets, destroy);
20879
20880			// Destroy supporting widgets, but not child widgets under this.containerNode (for 2.0, destroy child widgets
20881			// here too).   if() statement is to guard against exception if destroy() called multiple times (see #15815).
20882			if(this.domNode){
20883				array.forEach(registry.findWidgets(this.domNode, this.containerNode), destroy);
20884			}
20885
20886			this.destroyRendering(preserveDom);
20887			registry.remove(this.id);
20888			this._destroyed = true;
20889		},
20890
20891		destroyRendering: function(/*Boolean?*/ preserveDom){
20892			// summary:
20893			//		Destroys the DOM nodes associated with this widget.
20894			// preserveDom:
20895			//		If true, this method will leave the original DOM structure alone
20896			//		during tear-down. Note: this will not work with _Templated
20897			//		widgets yet.
20898			// tags:
20899			//		protected
20900
20901			if(this.bgIframe){
20902				this.bgIframe.destroy(preserveDom);
20903				delete this.bgIframe;
20904			}
20905
20906			if(this.domNode){
20907				if(preserveDom){
20908					domAttr.remove(this.domNode, "widgetId");
20909				}else{
20910					domConstruct.destroy(this.domNode);
20911				}
20912				delete this.domNode;
20913			}
20914
20915			if(this.srcNodeRef){
20916				if(!preserveDom){
20917					domConstruct.destroy(this.srcNodeRef);
20918				}
20919				delete this.srcNodeRef;
20920			}
20921		},
20922
20923		destroyDescendants: function(/*Boolean?*/ preserveDom){
20924			// summary:
20925			//		Recursively destroy the children of this widget and their
20926			//		descendants.
20927			// preserveDom:
20928			//		If true, the preserveDom attribute is passed to all descendant
20929			//		widget's .destroy() method. Not for use with _Templated
20930			//		widgets.
20931
20932			// get all direct descendants and destroy them recursively
20933			array.forEach(this.getChildren(), function(widget){
20934				if(widget.destroyRecursive){
20935					widget.destroyRecursive(preserveDom);
20936				}
20937			});
20938		},
20939
20940		uninitialize: function(){
20941			// summary:
20942			//		Deprecated. Override destroy() instead to implement custom widget tear-down
20943			//		behavior.
20944			// tags:
20945			//		protected
20946			return false;
20947		},
20948
20949		////////////////// GET/SET, CUSTOM SETTERS, ETC. ///////////////////
20950
20951		_setStyleAttr: function(/*String||Object*/ value){
20952			// summary:
20953			//		Sets the style attribute of the widget according to value,
20954			//		which is either a hash like {height: "5px", width: "3px"}
20955			//		or a plain string
20956			// description:
20957			//		Determines which node to set the style on based on style setting
20958			//		in attributeMap.
20959			// tags:
20960			//		protected
20961
20962			var mapNode = this.domNode;
20963
20964			// Note: technically we should revert any style setting made in a previous call
20965			// to his method, but that's difficult to keep track of.
20966
20967			if(lang.isObject(value)){
20968				domStyle.set(mapNode, value);
20969			}else{
20970				if(mapNode.style.cssText){
20971					mapNode.style.cssText += "; " + value;
20972				}else{
20973					mapNode.style.cssText = value;
20974				}
20975			}
20976
20977			this._set("style", value);
20978		},
20979
20980		_attrToDom: function(/*String*/ attr, /*String*/ value, /*Object?*/ commands){
20981			// summary:
20982			//		Reflect a widget attribute (title, tabIndex, duration etc.) to
20983			//		the widget DOM, as specified by commands parameter.
20984			//		If commands isn't specified then it's looked up from attributeMap.
20985			//		Note some attributes like "type"
20986			//		cannot be processed this way as they are not mutable.
20987			// attr:
20988			//		Name of member variable (ex: "focusNode" maps to this.focusNode) pointing
20989			//		to DOMNode inside the widget, or alternately pointing to a subwidget
20990			// tags:
20991			//		private
20992
20993			commands = arguments.length >= 3 ? commands : this.attributeMap[attr];
20994
20995			array.forEach(lang.isArray(commands) ? commands : [commands], function(command){
20996
20997				// Get target node and what we are doing to that node
20998				var mapNode = this[command.node || command || "domNode"];	// DOM node
20999				var type = command.type || "attribute";	// class, innerHTML, innerText, or attribute
21000
21001				switch(type){
21002					case "attribute":
21003						if(lang.isFunction(value)){ // functions execute in the context of the widget
21004							value = lang.hitch(this, value);
21005						}
21006
21007						// Get the name of the DOM node attribute; usually it's the same
21008						// as the name of the attribute in the widget (attr), but can be overridden.
21009						// Also maps handler names to lowercase, like onSubmit --> onsubmit
21010						var attrName = command.attribute ? command.attribute :
21011							(/^on[A-Z][a-zA-Z]*$/.test(attr) ? attr.toLowerCase() : attr);
21012
21013						if(mapNode.tagName){
21014							// Normal case, mapping to a DOMNode.  Note that modern browsers will have a mapNode.set()
21015							// method, but for consistency we still call domAttr
21016							domAttr.set(mapNode, attrName, value);
21017						}else{
21018							// mapping to a sub-widget
21019							mapNode.set(attrName, value);
21020						}
21021						break;
21022					case "innerText":
21023						mapNode.innerHTML = "";
21024						mapNode.appendChild(this.ownerDocument.createTextNode(value));
21025						break;
21026					case "innerHTML":
21027						mapNode.innerHTML = value;
21028						break;
21029					case "class":
21030						domClass.replace(mapNode, value, this[attr]);
21031						break;
21032				}
21033			}, this);
21034		},
21035
21036		get: function(name){
21037			// summary:
21038			//		Get a property from a widget.
21039			// name:
21040			//		The property to get.
21041			// description:
21042			//		Get a named property from a widget. The property may
21043			//		potentially be retrieved via a getter method. If no getter is defined, this
21044			//		just retrieves the object's property.
21045			//
21046			//		For example, if the widget has properties `foo` and `bar`
21047			//		and a method named `_getFooAttr()`, calling:
21048			//		`myWidget.get("foo")` would be equivalent to calling
21049			//		`widget._getFooAttr()` and `myWidget.get("bar")`
21050			//		would be equivalent to the expression
21051			//		`widget.bar2`
21052			var names = this._getAttrNames(name);
21053			return this[names.g] ? this[names.g]() : this._get(name);
21054		},
21055
21056		set: function(name, value){
21057			// summary:
21058			//		Set a property on a widget
21059			// name:
21060			//		The property to set.
21061			// value:
21062			//		The value to set in the property.
21063			// description:
21064			//		Sets named properties on a widget which may potentially be handled by a
21065			//		setter in the widget.
21066			//
21067			//		For example, if the widget has properties `foo` and `bar`
21068			//		and a method named `_setFooAttr()`, calling
21069			//		`myWidget.set("foo", "Howdy!")` would be equivalent to calling
21070			//		`widget._setFooAttr("Howdy!")` and `myWidget.set("bar", 3)`
21071			//		would be equivalent to the statement `widget.bar = 3;`
21072			//
21073			//		set() may also be called with a hash of name/value pairs, ex:
21074			//
21075			//	|	myWidget.set({
21076			//	|		foo: "Howdy",
21077			//	|		bar: 3
21078			//	|	});
21079			//
21080			//	This is equivalent to calling `set(foo, "Howdy")` and `set(bar, 3)`
21081
21082			if(typeof name === "object"){
21083				for(var x in name){
21084					this.set(x, name[x]);
21085				}
21086				return this;
21087			}
21088			var names = this._getAttrNames(name),
21089				setter = this[names.s];
21090			if(lang.isFunction(setter)){
21091				// use the explicit setter
21092				var result = setter.apply(this, Array.prototype.slice.call(arguments, 1));
21093			}else{
21094				// Mapping from widget attribute to DOMNode/subwidget attribute/value/etc.
21095				// Map according to:
21096				//		1. attributeMap setting, if one exists (TODO: attributeMap deprecated, remove in 2.0)
21097				//		2. _setFooAttr: {...} type attribute in the widget (if one exists)
21098				//		3. apply to focusNode or domNode if standard attribute name, excluding funcs like onClick.
21099				// Checks if an attribute is a "standard attribute" by whether the DOMNode JS object has a similar
21100				// attribute name (ex: accept-charset attribute matches jsObject.acceptCharset).
21101				// Note also that Tree.focusNode() is a function not a DOMNode, so test for that.
21102				var defaultNode = this.focusNode && !lang.isFunction(this.focusNode) ? "focusNode" : "domNode",
21103					tag = this[defaultNode] && this[defaultNode].tagName,
21104					attrsForTag = tag && (tagAttrs[tag] || (tagAttrs[tag] = getAttrs(this[defaultNode]))),
21105					map = name in this.attributeMap ? this.attributeMap[name] :
21106						names.s in this ? this[names.s] :
21107							((attrsForTag && names.l in attrsForTag && typeof value != "function") ||
21108								/^aria-|^data-|^role$/.test(name)) ? defaultNode : null;
21109				if(map != null){
21110					this._attrToDom(name, value, map);
21111				}
21112				this._set(name, value);
21113			}
21114			return result || this;
21115		},
21116
21117		_attrPairNames: {}, // shared between all widgets
21118		_getAttrNames: function(name){
21119			// summary:
21120			//		Helper function for get() and set().
21121			//		Caches attribute name values so we don't do the string ops every time.
21122			// tags:
21123			//		private
21124
21125			var apn = this._attrPairNames;
21126			if(apn[name]){
21127				return apn[name];
21128			}
21129			var uc = name.replace(/^[a-z]|-[a-zA-Z]/g, function(c){
21130				return c.charAt(c.length - 1).toUpperCase();
21131			});
21132			return (apn[name] = {
21133				n: name + "Node",
21134				s: "_set" + uc + "Attr", // converts dashes to camel case, ex: accept-charset --> _setAcceptCharsetAttr
21135				g: "_get" + uc + "Attr",
21136				l: uc.toLowerCase()        // lowercase name w/out dashes, ex: acceptcharset
21137			});
21138		},
21139
21140		_set: function(/*String*/ name, /*anything*/ value){
21141			// summary:
21142			//		Helper function to set new value for specified property, and call handlers
21143			//		registered with watch() if the value has changed.
21144			var oldValue = this[name];
21145			this[name] = value;
21146			if(this._created && !isEqual(oldValue, value)){
21147				if(this._watchCallbacks){
21148					this._watchCallbacks(name, oldValue, value);
21149				}
21150				this.emit("attrmodified-" + name, {
21151					detail: {
21152						prevValue: oldValue,
21153						newValue: value
21154					}
21155				});
21156			}
21157		},
21158
21159		_get: function(/*String*/ name){
21160			// summary:
21161			//		Helper function to get value for specified property stored by this._set(),
21162			//		i.e. for properties with custom setters.  Used mainly by custom getters.
21163			//
21164			//		For example, CheckBox._getValueAttr() calls this._get("value").
21165
21166			// future: return name in this.props ? this.props[name] : this[name];
21167			return this[name];
21168		},
21169
21170		emit: function(/*String*/ type, /*Object?*/ eventObj, /*Array?*/ callbackArgs){
21171			// summary:
21172			//		Used by widgets to signal that a synthetic event occurred, ex:
21173			//	|	myWidget.emit("attrmodified-selectedChildWidget", {}).
21174			//
21175			//		Emits an event on this.domNode named type.toLowerCase(), based on eventObj.
21176			//		Also calls onType() method, if present, and returns value from that method.
21177			//		By default passes eventObj to callback, but will pass callbackArgs instead, if specified.
21178			//		Modifies eventObj by adding missing parameters (bubbles, c
21178ancelable, widget).
21179			// tags:
21180			//		protected
21181
21182			// Specify fallback values for bubbles, cancelable in case they are not set in eventObj.
21183			// Also set pointer to widget, although since we can't add a pointer to the widget for native events
21184			// (see #14729), maybe we shouldn't do it here?
21185			eventObj = eventObj || {};
21186			if(eventObj.bubbles === undefined){
21187				eventObj.bubbles = true;
21188			}
21189			if(eventObj.cancelable === undefined){
21190				eventObj.cancelable = true;
21191			}
21192			if(!eventObj.detail){
21193				eventObj.detail = {};
21194			}
21195			eventObj.detail.widget = this;
21196
21197			var ret, callback = this["on" + type];
21198			if(callback){
21199				ret = callback.apply(this, callbackArgs ? callbackArgs : [eventObj]);
21200			}
21201
21202			// Emit event, but avoid spurious emit()'s as parent sets properties on child during startup/destroy
21203			if(this._started && !this._beingDestroyed){
21204				on.emit(this.domNode, type.toLowerCase(), eventObj);
21205			}
21206
21207			return ret;
21208		},
21209
21210		on: function(/*String|Function*/ type, /*Function*/ func){
21211			// summary:
21212			//		Call specified function when event occurs, ex: myWidget.on("click", function(){ ... }).
21213			// type:
21214			//		Name of event (ex: "click") or extension event like touch.press.
21215			// description:
21216			//		Call specified function when event `type` occurs, ex: `myWidget.on("click", function(){ ... })`.
21217			//		Note that the function is not run in any particular scope, so if (for example) you want it to run in the
21218			//		widget's scope you must do `myWidget.on("click", lang.hitch(myWidget, func))`.
21219
21220			// For backwards compatibility, if there's an onType() method in the widget then connect to that.
21221			// Remove in 2.0.
21222			var widgetMethod = this._onMap(type);
21223			if(widgetMethod){
21224				return aspect.after(this, widgetMethod, func, true);
21225			}
21226
21227			// Otherwise, just listen for the event on this.domNode.
21228			return this.own(on(this.domNode, type, func))[0];
21229		},
21230
21231		_onMap: function(/*String|Function*/ type){
21232			// summary:
21233			//		Maps on() type parameter (ex: "mousemove") to method name (ex: "onMouseMove").
21234			//		If type is a synthetic event like touch.press then returns undefined.
21235			var ctor = this.constructor, map = ctor._onMap;
21236			if(!map){
21237				map = (ctor._onMap = {});
21238				for(var attr in ctor.prototype){
21239					if(/^on/.test(attr)){
21240						map[attr.replace(/^on/, "").toLowerCase()] = attr;
21241					}
21242				}
21243			}
21244			return map[typeof type == "string" && type.toLowerCase()];	// String
21245		},
21246
21247		toString: function(){
21248			// summary:
21249			//		Returns a string that represents the widget.
21250			// description:
21251			//		When a widget is cast to a string, this method will be used to generate the
21252			//		output. Currently, it does not implement any sort of reversible
21253			//		serialization.
21254			return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String
21255		},
21256
21257		getChildren: function(){
21258			// summary:
21259			//		Returns all direct children of this widget, i.e. all widgets underneath this.containerNode whose parent
21260			//		is this widget.   Note that it does not return all descendants, but rather just direct children.
21261			//		Analogous to [Node.childNodes](https://developer.mozilla.org/en-US/docs/DOM/Node.childNodes),
21262			//		except containing widgets rather than DOMNodes.
21263			//
21264			//		The result intentionally excludes internally created widgets (a.k.a. supporting widgets)
21265			//		outside of this.containerNode.
21266			//
21267			//		Note that the array returned is a simple array.  Application code should not assume
21268			//		existence of methods like forEach().
21269
21270			return this.containerNode ? registry.findWidgets(this.containerNode) : []; // dijit/_WidgetBase[]
21271		},
21272
21273		getParent: function(){
21274			// summary:
21275			//		Returns the parent widget of this widget.
21276
21277			return registry.getEnclosingWidget(this.domNode.parentNode);
21278		},
21279
21280		connect: function(/*Object|null*/ obj, /*String|Function*/ event, /*String|Function*/ method){
21281			// summary:
21282			//		Deprecated, will be removed in 2.0, use this.own(on(...)) or this.own(aspect.after(...)) instead.
21283			//
21284			//		Connects specified obj/event to specified method of this object
21285			//		and registers for disconnect() on widget destroy.
21286			//
21287			//		Provide widget-specific analog to dojo.connect, except with the
21288			//		implicit use of this widget as the target object.
21289			//		Events connected with `this.connect` are disconnected upon
21290			//		destruction.
21291			// returns:
21292			//		A handle that can be passed to `disconnect` in order to disconnect before
21293			//		the widget is destroyed.
21294			// example:
21295			//	|	var btn = new Button();
21296			//	|	// when foo.bar() is called, call the listener we're going to
21297			//	|	// provide in the scope of btn
21298			//	|	btn.connect(foo, "bar", function(){
21299			//	|		console.debug(this.toString());
21300			//	|	});
21301			// tags:
21302			//		protected
21303
21304			return this.own(connect.connect(obj, event, this, method))[0];	// handle
21305		},
21306
21307		disconnect: function(handle){
21308			// summary:
21309			//		Deprecated, will be removed in 2.0, use handle.remove() instead.
21310			//
21311			//		Disconnects handle created by `connect`.
21312			// tags:
21313			//		protected
21314
21315			handle.remove();
21316		},
21317
21318		subscribe: function(t, method){
21319			// summary:
21320			//		Deprecated, will be removed in 2.0, use this.own(topic.subscribe()) instead.
21321			//
21322			//		Subscribes to the specified topic and calls the specified method
21323			//		of this object and registers for unsubscribe() on widget destroy.
21324			//
21325			//		Provide widget-specific analog to dojo.subscribe, except with the
21326			//		implicit use of this widget as the target object.
21327			// t: String
21328			//		The topic
21329			// method: Function
21330			//		The callback
21331			// example:
21332			//	|	var btn = new Button();
21333			//	|	// when /my/topic is published, this button changes its label to
21334			//	|	// be the parameter of the topic.
21335			//	|	btn.subscribe("/my/topic", function(v){
21336			//	|		this.set("label", v);
21337			//	|	});
21338			// tags:
21339			//		protected
21340			return this.own(topic.subscribe(t, lang.hitch(this, method)))[
213400];	// handle
21341		},
21342
21343		unsubscribe: function(/*Object*/ handle){
21344			// summary:
21345			//		Deprecated, will be removed in 2.0, use handle.remove() instead.
21346			//
21347			//		Unsubscribes handle created by this.subscribe.
21348			//		Also removes handle from this widget's list of subscriptions
21349			// tags:
21350			//		protected
21351
21352			handle.remove();
21353		},
21354
21355		isLeftToRight: function(){
21356			// summary:
21357			//		Return this widget's explicit or implicit orientation (true for LTR, false for RTL)
21358			// tags:
21359			//		protected
21360			return this.dir ? (this.dir.toLowerCase() == "ltr") : domGeometry.isBodyLtr(this.ownerDocument); //Boolean
21361		},
21362
21363		isFocusable: function(){
21364			// summary:
21365			//		Return true if this widget can currently be focused
21366			//		and false if not
21367			return this.focus && (domStyle.get(this.domNode, "display") != "none");
21368		},
21369
21370		placeAt: function(/*String|DomNode|DocumentFragment|dijit/_WidgetBase*/ reference, /*String|Int?*/ position){
21371			// summary:
21372			//		Place this widget somewhere in the DOM based
21373			//		on standard domConstruct.place() conventions.
21374			// description:
21375			//		A convenience function provided in all _Widgets, providing a simple
21376			//		shorthand mechanism to put an existing (or newly created) Widget
21377			//		somewhere in the dom, and allow chaining.
21378			// reference:
21379			//		Widget, DOMNode, DocumentFragment, or id of widget or DOMNode
21380			// position:
21381			//		If reference is a widget (or id of widget), and that widget has an ".addChild" method,
21382			//		it will be called passing this widget instance into that method, supplying the optional
21383			//		position index passed.  In this case position (if specified) should be an integer.
21384			//
21385			//		If reference is a DOMNode (or id matching a DOMNode but not a widget),
21386			//		the position argument can be a numeric index or a string
21387			//		"first", "last", "before", or "after", same as dojo/dom-construct::place().
21388			// returns: dijit/_WidgetBase
21389			//		Provides a useful return of the newly created dijit._Widget instance so you
21390			//		can "chain" this function by instantiating, placing, then saving the return value
21391			//		to a variable.
21392			// example:
21393			//	|	// create a Button with no srcNodeRef, and place it in the body:
21394			//	|	var button = new Button({ label:"click" }).placeAt(win.body());
21395			//	|	// now, 'button' is still the widget reference to the newly created button
21396			//	|	button.on("click", function(e){ console.log('click'); }));
21397			// example:
21398			//	|	// create a button out of a node with id="src" and append it to id="wrapper":
21399			//	|	var button = new Button({},"src").placeAt("wrapper");
21400			// example:
21401			//	|	// place a new button as the first element of some div
21402			//	|	var button = new Button({ label:"click" }).placeAt("wrapper","first");
21403			// example:
21404			//	|	// create a contentpane and add it to a TabContainer
21405			//	|	var tc = dijit.byId("myTabs");
21406			//	|	new ContentPane({ href:"foo.html", title:"Wow!" }).placeAt(tc)
21407
21408			var refWidget = !reference.tagName && registry.byId(reference);
21409			if(refWidget && refWidget.addChild && (!position || typeof position === "number")){
21410				// Adding this to refWidget and can use refWidget.addChild() to handle everything.
21411				refWidget.addChild(this, position);
21412			}else{
21413				// "reference" is a plain DOMNode, or we can't use refWidget.addChild().   Use domConstruct.place() and
21414				// target refWidget.containerNode for nested placement (position==number, "first", "last", "only"), and
21415				// refWidget.domNode otherwise ("after"/"before"/"replace").  (But not supported officially, see #14946.)
21416				var ref = refWidget && ("domNode" in refWidget) ?
21417					(refWidget.containerNode && !/after|before|replace/.test(position || "") ?
21418						refWidget.containerNode : refWidget.domNode) : dom.byId(reference, this.ownerDocument);
21419				domConstruct.place(this.domNode, ref, position);
21420
21421				// Start this iff it has a parent widget that's already started.
21422				// TODO: for 2.0 maybe it should also start the widget when this.getParent() returns null??
21423				if(!this._started && (this.getParent() || {})._started){
21424					this.startup();
21425				}
21426			}
21427			return this;
21428		},
21429
21430		defer: function(fcn, delay){
21431			// summary:
21432			//		Wrapper to setTimeout to avoid deferred functions executing
21433			//		after the originating widget has been destroyed.
21434			//		Returns an object handle with a remove method (that returns null) (replaces clearTimeout).
21435			// fcn: Function
21436			//		Function reference.
21437			// delay: Number?
21438			//		Delay, defaults to 0.
21439			// tags:
21440			//		protected
21441
21442			var timer = setTimeout(lang.hitch(this,
21443				function(){
21444					if(!timer){
21445						return;
21446					}
21447					timer = null;
21448					if(!this._destroyed){
21449						lang.hitch(this, fcn)();
21450					}
21451				}),
21452				delay || 0
21453			);
21454			return {
21455				remove: function(){
21456					if(timer){
21457						clearTimeout(timer);
21458						timer = null;
21459					}
21460					return null; // so this works well: handle = handle.remove();
21461				}
21462			};
21463		}
21464	});
21465
21466	if(has("dojo-bidi")){
21467		_WidgetBase.extend(_BidiMixin);
21468	}
21469
21470	return _WidgetBase;
21471});
21472
21473},
21474'dojo/Stateful':function(){
21475define(["./_base/declare", "./_base/lang", "./_base/array", "./when"], function(declare, lang, array, when){
21476	// module:
21477	//		dojo/Stateful
21478
21479return declare("dojo.Stateful", null, {
21480	// summary:
21481	//		Base class for objects that provide named properties with optional getter/setter
21482	//		control and the ability to watch for property changes
21483	//
21484	//		The class also provides the functionality to auto-magically manage getters
21485	//		and setters for object attributes/properties.
21486	//		
21487	//		Getters and Setters should follow the format of _xxxGetter or _xxxSetter where 
21488	//		the xxx is a name of the attribute to handle.  So an attribute of "foo" 
21489	//		would have a custom getter of _fooGetter and a custom setter of _fooSetter.
21490	//
21491	// example:
21492	//	|	require(["dojo/Stateful", function(Stateful) {
21493	//	|		var obj = new Stateful();
21494	//	|		obj.watch("foo", function(){
21495	//	|			console.log("foo changed to " + this.get("foo"));
21496	//	|		});
21497	//	|		obj.set("foo","bar");
21498	//	|	});
21499
21500	// _attrPairNames: Hash
21501	//		Used across all instances a hash to cache attribute names and their getter 
21502	//		and setter names.
21503	_attrPairNames: {},
21504
21505	_getAttrNames: function(name){
21506		// summary:
21507		//		Helper function for get() and set().
21508		//		Caches attribute name values so we don't do the string ops every time.
21509		// tags:
21510		//		private
21511
21512		var apn = this._attrPairNames;
21513		if(apn[name]){ return apn[name]; }
21514		return (apn[name] = {
21515			s: "_" + name + "Setter",
21516			g: "_" + name + "Getter"
21517		});
21518	},
21519
21520	postscript: function(/*Object?*/ params){
21521		// Automatic setting of params during construction
21522		if (params){ this.set(params); }
21523	},
21524
21525	_get: function(name, names){
21526		// summary:
21527		//		Private function that does a get based off a hash of names
21528		// names:
21529		//		Hash of names of custom attributes
21530		return typeof this[names.g] === "function" ? this[names.g]() : this[name];
21531	},
21532	get: function(/*String*/name){
21533		// summary:
21534		//		Get a property on a Stateful instance.
21535		// name:
21536		//		The property to get.
21537		// returns:
21538		//		The property value on this Stateful instance.
21539		// description:
21540		//		Get a named property on a Stateful object. The property may
21541		//		potentially be retrieved via a getter method in subclasses. In the base class
21542		//		this just retrieves the object's property.
21543		// example:
21544		//	|	require(["dojo/Stateful", function(Stateful) {
21545		//	|		var stateful = new Stateful({foo: 3});
21546		//	|		stateful.get("foo") // returns 3
21547		//	|		stateful.foo // returns 3
21548		//	|	});
21549
21550		return this._get(name, this._getAttrNames(name)); //Any
21551	},
21552	set: function(/*String*/name, /*Object*/value){
21553		// summary:
21554		//		Set a property on a Stateful instance
21555		// name:
21556		//		The property to set.
21557		// value:
21558		//		The value to set in the property.
21559		// returns:
21560		//		The function returns this dojo.Stateful instance.
21561		// description:
21562		//		Sets named properties on a stateful object and notifies any watchers of
21563		//		the property. A programmatic setter may be defined in subclasses.
21564		// example:
21565		//	|	require(["dojo/Stateful", function(Stateful) {
21566		//	|		var stateful = new Stateful();
21567		//	|		stateful.watch(function(name, oldValue, value){
21568		//	|			// this will be called on the set below
21569		//	|		}
21570		//	|		stateful.set(foo, 5);
21571		//	set() may also be called with a hash of name/value pairs, ex:
21572		//	|		stateful.set({
21573		//	|			foo: "Howdy",
21574		//	|			bar: 3
21575		//	|		});
21576		//	|	});
21577		//	This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
21578
21579		// If an object is used, iterate through object
21580		if(typeof name === "object"){
21581			for(var x in name){
21582				if(name.hasOwnProperty(x) && x !="_watchCallbacks"){
21583					this.set(x, name[x]);
21584				}
21585			}
21586			return this;
21587		}
21588
21589		var names = this._getAttrNames(name),
21590			oldValue = this._get(name, names),
21591			setter = this[names.s],
21592			result;
21593		if(typeof setter === "function"){
21594			// use the explicit setter
21595			result = setter.apply(this, Array.prototype.slice.call(arguments, 1));
21596		}else{
21597			// no setter so set attribute directly
21598			this[name] = value;
21599		}
21600		if(this._watchCallbacks){
21601			var self = this;
21602			// If setter returned a promise, wait for it to complete, otherwise call watches immediately
21603			when(result, function(){
21604				self._watchCallbacks(name, oldValue, value);
21605			});
21606		}
21607		return this; // dojo/Stateful
21608	},
21609	_changeAttrValue: function(name, value){
21610		// summary:
21611		//		Internal helper for directly changing an attribute value.
21612		//
21613		// name: String
21614		//		The property to set.
21615		// value: Mixed
21616		//		The value to set in the property.
21617		//
21618		// description:
21619		//		Directly change the value of an attribute on an object, bypassing any 
21620		//		accessor setter.  Also handles the calling of watch and emitting events. 
21621		//		It is designed to be used by descendant class when there are two values 
21622		//		of attributes that are linked, but calling .set() is not appropriate.
21623
21624		var oldValue = this.get(name);
21625		this[name] = value;
21626		if(this._watchCallbacks){
21627			this._watchCallbacks(name, oldValue, value);
21628		}
21629		return this; // dojo/Stateful
21630	},
21631	watch: function(/*String?*/name, /*Function*/callback){
21632		// summary:
21633		//		Watches a property for changes
21634		// name:
21635		//		Indicates the property to watch. This is optional (the callback may be the
21636		//		only parameter), and if omitted, all the properties will be watched
21637		// returns:
21638		//		An object handle for the watch. The unwatch method of this object
21639		//		can be used to discontinue watching this property:
21640		//		|	var watchHandle = obj.watch("foo", callback);
21641		//		|	watchHandle.unwatch(); // callback won't be called now
21642		// callback:
21643		//		The function to execute when the property changes. This will be called after
21644		//		the property has been changed. The callback will be called with the |this|
21645		//		set to the instance, the first argument as the name of the property, the
21646		//		second argument as the old value and the third argument as the new value.
21647
21648		var callbacks = this._watchCallbacks;
21649		if(!callbacks){
21650			var self = this;
21651			callbacks = this._watchCallbacks = function(name, oldValue, value, ignoreCatchall){
21652				var notify = function(propertyCallbacks){
21653					if(propertyCallbacks){
21654						propertyCallbacks = propertyCallbacks.slice();
21655						for(var i = 0, l = propertyCallbacks.length; i < l; i++){
21656							propertyCallbacks[i].call(self, name, oldValue, value);
21657						}
21658					}
21659				};
21660				notify(callbacks['_' + name]);
21661				if(!ignoreCatchall){
21662					notify(callbacks["*"]); // the catch-all
21663				}
21664			}; // we use a function instead of an object so it will be ignored by JSON conversion
21665		}
21666		if(!callback && typeof name === "function"){
21667			callback = name;
21668			name = "*";
21669		}else{
21670			// prepend with dash to prevent name conflicts with function (like "name" property)
21671			name = '_' + name;
21672		}
21673		var propertyCallbacks = callbacks[name];
21674		if(typeof propertyCallbacks !== "object"){
21675			propertyCallbacks = callbacks[name] = [];
21676		}
21677		propertyCallbacks.push(callback);
21678
21679		// TODO: Remove unwatch in 2.0
21680		var handle = {};
21681		handle.unwatch = handle.remove = function(){
21682			var index = array.indexOf(propertyCallbacks, callback);
21683			if(index > -1){
21684				propertyCallbacks.splice(index, 1);
21685			}
21686		};
21687		return handle; //Object
21688	}
21689
21690});
21691
21692});
21693
21694},
21695'dijit/Destroyable':function(){
21696define([
21697	"dojo/_base/array", // array.forEach array.map
21698	"dojo/aspect",
21699	"dojo/_base/declare"
21700], function(array, aspect, declare){
21701
21702	// module:
21703	//		dijit/Destroyable
21704
21705	return declare("dijit.Destroyable", null, {
21706		// summary:
21707		//		Mixin to track handles and release them when instance is destroyed.
21708		// description:
21709		//		Call this.own(...) on list of handles (returned from dojo/aspect, dojo/on,
21710		//		dojo/Stateful::watch, or any class (including widgets) with a destroyRecursive() or destroy() method.
21711		//		Then call destroy() later to destroy this instance and release the resources.
21712
21713		destroy: function(/*Boolean*/ preserveDom){
21714			// summary:
21715			//		Destroy this class, releasing any resources registered via own().
21716			this._destroyed = true;
21717		},
21718
21719		own: function(){
21720			// summary:
21721			//		Track specified handles and remove/destroy them when this instance is destroyed, unless they were
21722			//		already removed/destroyed manually.
21723			// tags:
21724			//		protected
21725			// returns:
21726			//		The array of specified handles, so you can do for example:
21727			//	|		var handle = this.own(on(...))[0];
21728
21729			var cleanupMethods = [
21730				"destroyRecursive",
21731				"destroy",
21732				"remove"
21733			];
21734
21735			array.forEach(arguments, function(handle){
21736				// When this.destroy() is called, destroy handle.  Since I'm using aspect.before(),
21737				// the handle will be destroyed before a subclass's destroy() method starts running, before it calls
21738				// this.inherited() or even if it doesn't call this.inherited() at all.  If that's an issue, make an
21739				// onDestroy() method and connect to that instead.
21740				var destroyMethodName;
21741				var odh = aspect.before(this, "destroy", function (preserveDom){
21742					handle[destroyMethodName](preserveDom);
21743				});
21744
21745				// Callback for when handle is manually destroyed.
21746				var hdhs = [];
21747				function onManualDestroy(){
21748					odh.remove();
21749					array.forEach(hdhs, function(hdh){
21750						hdh.remove();
21751					});
21752				}
21753
21754				// Setup listeners for manual destroy of handle.
21755				// Also computes destroyMethodName, used in listener above.
21756				if(handle.then){
21757					// Special path for Promises.  Detect when Promise is resolved, rejected, or
21758					// canceled (nb: cancelling a Promise causes it to be rejected).
21759					destroyMethodName = "cancel";
21760					handle.then(onManualDestroy, onManualDestroy);
21761				}else{
21762					// Path for other handles.  Just use AOP to detect when handle is manually destroyed.
21763					array.forEach(cleanupMethods, function(cleanupMethod){
21764						if(typeof handle[cleanupMethod] === "function"){
21765							if(!destroyMethodName){
21766								// Use first matching method name in above listener (prefer destroyRecursive() to destroy())
21767								destroyMethodName = cleanupMethod;
21768							}
21769							hdhs.push(aspect.after(handle, cleanupMethod, onManualDestroy, true));
21770						}
21771					});
21772				}
21773			}, this);
21774
21775			return arguments;		// handle
21776		}
21777	});
21778});
21779
21780},
21781'dijit/registry':function(){
21782define([
21783	"dojo/_base/array", // array.forEach array.map
21784	"dojo/_base/window", // win.body
21785	"./main"	// dijit._scopeName
21786], function(array, win, dijit){
21787
21788	// module:
21789	//		dijit/registry
21790
21791	var _widgetTypeCtr = {}, hash = {};
21792
21793	var registry =  {
21794		// summary:
21795		//		Registry of existing widget on page, plus some utility methods.
21796
21797		// length: Number
21798		//		Number of registered widgets
21799		length: 0,
21800
21801		add: function(widget){
21802			// summary:
21803			//		Add a widget to the registry. If a duplicate ID is detected, a error is thrown.
21804			// widget: dijit/_WidgetBase
21805			//		Any dijit/_WidgetBase subclass.
21806			if(hash[widget.id]){
21807				throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered");
21808			}
21809			hash[widget.id] = widget;
21810			this.length++;
21811		},
21812
21813		remove: function(/*String*/ id){
21814			// summary:
21815			//		Remove a widget from the registry. Does not destroy the widget; simply
21816			//		removes the reference.
21817			if(hash[id]){
21818				delete hash[id];
21819				this.length--;
21820			}
21821		},
21822
21823		byId: function(/*String|Widget*/ id){
21824			// summary:
21825			//		Find a widget by it's id.
21826			//		If passed a widget then just returns the widget.
21827			return typeof id == "string" ? hash[id] : id;	// dijit/_WidgetBase
21828		},
21829
21830		byNode: function(/*DOMNode*/ node){
21831			// summary:
21832			//		Returns the widget corresponding to the given DOMNode
21833			return hash[node.getAttribute("widgetId")]; // dijit/_WidgetBase
21834		},
21835
21836		toArray: function(){
21837			// summary:
21838			//		Convert registry into a true Array
21839			//
21840			// example:
21841			//		Work with the widget .domNodes in a real Array
21842			//		|	array.map(registry.toArray(), function(w){ return w.domNode; });
21843
21844			var ar = [];
21845			for(var id in hash){
21846				ar.push(hash[id]);
21847			}
21848			return ar;	// dijit/_WidgetBase[]
21849		},
21850
21851		getUniqueId: function(/*String*/widgetType){
21852			// summary:
21853			//		Generates a unique id for a given widgetType
21854
21855			var id;
21856			do{
21857				id = widgetType + "_" +
21858					(widgetType in _widgetTypeCtr ?
21859						++_widgetTypeCtr[widgetType] : _widgetTypeCtr[widgetType] = 0);
21860			}while(hash[id]);
21861			return dijit._scopeName == "dijit" ? id : dijit._scopeName + "_" + id; // String
21862		},
21863
21864		findWidgets: function(root, skipNode){
21865			// summary:
21866			//		Search subtree under root returning widgets found.
21867			//		Doesn't search for nested widgets (ie, widgets inside other widgets).
21868			// root: DOMNode
21869			//		Node to search under.
21870			// skipNode: DOMNode
21871			//		If specified, don't search beneath this node (usually containerNode).
21872
21873			var outAry = [];
21874
21875			function getChildrenHelper(root){
21876				for(var node = root.firstChild; node; node = node.nextSibling){
21877					if(node.nodeType == 1){
21878						var widgetId = node.getAttribute("widgetId");
21879						if(widgetId){
21880							var widget = hash[widgetId];
21881							if(widget){	// may be null on page w/multiple dojo's loaded
21882								outAry.push(widget);
21883							}
21884						}else if(node !== skipNode){
21885							getChildrenHelper(node);
21886						}
21887					}
21888				}
21889			}
21890
21891			getChildrenHelper(root);
21892			return outAry;
21893		},
21894
21895		_destroyAll: function(){
21896			// summary:
21897			//		Code to destroy all widgets and do other cleanup on page unload
21898
21899			// Clean up focus manager lingering references to widgets and nodes
21900			dijit._curFocus = null;
21901			dijit._prevFocus = null;
21902			dijit._activeStack = [];
21903
21904			// Destroy all the widgets, top down
21905			array.forEach(registry.findWidgets(win.body()), function(widget){
21906				// Avoid double destroy of widgets like Menu that are attached to <body>
21907				// even though they are logically children of other widgets.
21908				if(!widget._destroyed){
21909					if(widget.destroyRecursive){
21910						widget.destroyRecursive();
21911					}else if(widget.destroy){
21912						widget.destroy();
21913					}
21914				}
21915			});
21916		},
21917
21918		getEnclosingWidget: function(/*DOMNode*/ node){
21919			// summary:
21920			//		Returns the widget whose DOM tree contains the specified DOMNode, or null if
21921			//		the node is not contained within the DOM tree of any widget
21922			while(node){
21923				var id = node.nodeType == 1 && node.getAttribute("widgetId");
21924				if(id){
21925					return hash[id];
21926				}
21927				node = node.parentNode;
21928			}
21929			return null;
21930		},
21931
21932		// In case someone needs to access hash.
21933		// Actually, this is accessed from WidgetSet back-compatibility code
21934		_hash: hash
21935	};
21936
21937	dijit.registry = registry;
21938
21939	return registry;
21940});
21941
21942},
21943'dijit/main':function(){
21944define([
21945	"dojo/_base/kernel"
21946], function(dojo){
21947	// module:
21948	//		dijit/main
21949
21950/*=====
21951return {
21952	// summary:
21953	//		The dijit package main module.
21954	//		Deprecated.   Users should access individual modules (ex: dijit/registry) directly.
21955};
21956=====*/
21957
21958	return dojo.dijit;
21959});
21960
21961},
21962'dpage/widgets/AlertValidationMessage':function(){
21963define([
21964      "dojo/_base/event"
21965      ,"dojo/on"
21966      ,"dojo/dom-attr"
21967      ,"dojo/dom-class"
21968      ,"dojo/mouse"
21969      ,"dojo/dom-geometry"
21970      , "dojo/dom-style"
21971      , "dojo/json"
21972
21973      , "dojo/request/xhr"
21974      ,"dojox/html/entities"
21975      ,"dojo/_base/declare"
21976      , "dpage/widgets/ValidationMessage"],
21977function (event, on, domAttr, domClass, mouse, domGeom, style, json) {
21978    /**
21979    * @namespace dpage
21980    */
21981    /**
21982    * @namespace widgets
21983    * @memberOf dpage
21984    */
21985    /**
21986    * Implementation of a ValidationMessage that pops up an alert dialog. 
21987    * @class AlertValidationMessage
21988    * @param {Object} [options] Optional options for the widget.
21989    * @param {String} [options.dataField] The field (column name) this widget is bound to.
21990         
21991    * @param {dpage.modules.TabularModel} [options.model] The model to use.
21992    * @param {dpage.widgets.Container} [options.container] The container of the widget.
21993    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
21994    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
21995    *                               is created.
21996    * @param {Object} [containerNode] Optional container node to tie the widget to.
21997    * @memberOf dpage.widgets
21998    * @extends {dpage.widgets.ValidationMessage}
21999    */
22000    return dojo.declare("dpage.widgets.AlertValidationMessage", [dpage.widgets.ValidationMessage], /** @lends dpage.widgets.AlertValidationMessage.prototype */ {
22001        _containerNode : null
22002
22003        ,constructor : function(options , srcNodeRef)
22004        {
22005            var self = this;
22006            this._containerNode = srcNodeRef;
22007        },
22008
22009        _updateView : function(){
22010            var errors = this._errors;
22011            var ul;
22012            var strErrors = [];
22013            
22014            //set up the data.
22015            this.inherited(arguments);
22016
22017            if (errors.length > 0) {
22018                for (var idx = 0; idx < errors.length ; idx++) {
22019                    var obj = errors[idx];
22020
22021                    strErrors.push(obj.message);
22022                }
22023
22024                alert(strErrors.join("\n"));
22025            }
22026        }
22027   });
22028});
22029
22030},
22031'dpage/widgets/ValidationMessage':function(){
22032define([
22033      "dojo/_base/event"
22034      ,"dojo/on"
22035      ,"dojo/dom-attr"
22036      ,"dojo/dom-class"
22037      ,"dojo/dom-geometry"
22038      , "dojo/dom-style"
22039      , "dojo/json"
22040
22041      , "dojo/request/xhr"
22042      ,"dojox/html/entities"
22043      ,"dojo/_base/declare"
22044      , "dpage/widgets/MultiValueWidget"],
22045function (event, on, domAttr, domClass, domGeom, style, json) {
22046    /**
22047    * @namespace dpage
22048    */
22049    /**
22050    * @namespace widgets
22051    * @memberOf dpage
22052    */
22053    /**
22054    * Abstract base class for all ValidationMessage widgets. 
22055    * @class ValidationMessage
22056    * @param {Object} [options] Optional options for the widget.
22057    * @param {String} [options.dataField] The field (column name) this widget is bound to.
22058         
22059    * @param {dpage.modules.TabularModel} [options.model] The model to use.
22060    * @param {dpage.widgets.Container} [options.container] The container of the widget.
22061    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
22062    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
22063    *                               is created.
22064    * @param {Object} [containerNode] Optional container node to tie the widget to.
22065    * @memberOf dpage.widgets
22066    * @extends {dpage.widgets.MultiValueWidget}
22067    */
22068    return dojo.declare("dpage.widgets.ValidationMessage", [dpage.widgets.MultiValueWidget], /** @lends dpage.widgets.ValidationMessage.prototype */ {
22069        _containerNode : null
22070        ,_dataField : null
22071        , _errors : null
22072
22073        ,constructor : function(options , srcNodeRef)
22074        {
22075            this._errors = [];
22076            if (options == null || options.dataField == null) {
22077                this._dataField = "default";//default column name for an empty model.
22078            }
22079            else
22080                this._dataField = options.dataField;
22081        },
22082        templateString: "<div></div>",
22083        postCreate: function ()
22084        {
22085            if(this.getContainer() != null)
22086                this.getContainer().setValidationMessageWidget(this);
22087
22088            return this.inherited(arguments);
22089        },
22090        setContainer : function()
22091        {
22092            //call base method.
22093            this.inherited(arguments);
22094            this.getContainer().setValidationMessageWidget(this);
22095        },
22096        /**
22097        * Clear the error message. Will update the underlying model.
22098        * @returns {void}
22099        */
22100        clearError: function ()
22101        {
22102            //this will cause the _updateView() method to be called.
22103            this.getModel().clear();
22104        },
22105        /**
22106        * Set the list of errors. Clears out any errors that may currently be set. Will update the underlying model.
22107        * @param {Array} errors Array of error Objects.
22108        * @param {String} errors.message The message of the error.
22109        * @param {Number} [errors.widgetId] The widgetId the error is tied to.
22110        * @returns {void}
22111        */
22112        setError: function (errors) {
22113            this._errors = errors;
22114            var modelRows = [];
22115
22116            for (var i = 0; i < errors.length; i++)
22117            {
22118                var modelRow = {};
22119                modelRow[this._dataField] = errors[i].message;
22120
22121                modelRows.push(modelRow);
22122                //keep track of the row.
22123                errors[i].modelRow = modelRow;
22124            }
22125
22126            //causes the control to re-render (_updateView).
22127            this.getModel().setRows(modelRows);
22128        },
22129        /**
22130        * Removes the error for a widgetId. Will update the underlying model.
22131        * @param {Number} widgetID Numeric widget id.
22132        * @returns {void}
22133        */
22134        removeErrorByWidgetID: function (widgetID) {
22135            for (var i = this._errors.length; i-- > 0;) {
22136                if (this._errors[i].widgetId === widgetID) {
22137                    this.getModel().deleteRow(this._errors[i].modelRow);
22138                }
22139            }
22140        },
22141        //Gets called whenever the model changes on us.
22142        _updateView: function ()
22143        {
22144            var oldErrors = this._errors;
22145            this._errors = [];
22146
22147            if(this.getModel() != null)
22148            {
22149                for(var idx = 0; idx<this.getModel().getRows().length;idx++)
22150                {
22151                    var errorObj = { message: this.getModel().getValue(idx, this._dataField) , modelRow : this.getModel().getRows()[idx] };
22152
22153                    //find the old error so we can hook up the correct widgetId.
22154                    for (var i = 0; i < oldErrors.length; i++)
22155                    {
22156                        if (oldErrors[i].widgetId != null
22157                            && dpage.modules.TabularModel.isSameRow(oldErrors[i].modelRow, this.getModel().getRows()[idx]))
22158                        {
22159                            errorObj.widgetId = oldErrors[i].widgetId;
22160                            break;
22161                        }
22162                    }
22163                    this._errors.push(errorObj);
22164                }
22165            }
22166        },
22167        setModel : function()
22168        {
22169            this.inherited(arguments);
22170            this._updateView();
22171        }
22172   });
22173});
22174
22175},
22176'dpage/widgets/MultiValueWidget':function(){
22177define([
22178      "dojo/_base/event"
22179      ,"dojo/on"
22180      ,"dojo/dom-attr"
22181      ,"dojo/dom-class"
22182      ,"dojo/dom-geometry"
22183      , "dojo/dom-style"
22184      , "dojo/json"
22185
22186      , "dpage/modules/TabularModel"
22187      , "dojo/request/xhr"
22188      ,"dojox/html/entities"
22189      ,"dojo/_base/declare"
22190      , "dpage/widgets/BaseWidget"],
22191function (event, on, domAttr, domClass, domGeom, style, json) {
22192    /**
22193    * @namespace dpage
22194    */
22195    /**
22196    * @namespace widgets
22197    * @memberOf dpage
22198    */
22199    /**
22200     * Base class for all widgets intended to display multiple values, such as multi-select controls or Tables of data. 
22201     * @class MultiValueWidget
22202     * @param {Object} [options] Optional options for the widget.
22203     * @param {dpage.modules.TabularModel} [options.model] The model to use.
22204     * @param {dpage.widgets.Container} [options.container] The container of the widget.
22205     * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
22206     * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
22207     *                               is created.
22208     * @param {Object} [containerNode] Optional container node to tie the widget to.
22209     * @memberOf dpage.widgets
22210     * @extends {dpage.widgets.BaseWidget}
22211     */
22212    return dojo.declare("dpage.widgets.MultiValueWidget", [dpage.widgets.BaseWidget], /** @lends dpage.widgets.MultiValueWidget.prototype */ {
22213        _doDataSubscriptions: true,
22214        _dataCallbackId: null,
22215        _model: null,
22216
22217        constructor : function(options , srcNodeRef)
22218        {
22219            var self = this;
22220            this._containerNode = srcNodeRef;
22221
22222            //if there is no model, create a blank one.
22223            if (options == null || options.model == null) {
22224                this._model = new dpage.modules.TabularModel();
22225            }
22226
22227            if (options != null) {
22228                if (options.model != null) {
22229                    if (options.model.isInstanceOf == null || !options.model.isInstanceOf(dpage.modules.TabularModel))
22230                        throw new Error("model must be a dpage.widgets.TabularModel for widget id = " + this.getWidgetId());
22231                    else
22232                        this._model = options.model;
22233                }
22234            }
22235
22236            if(this._model != null)
22237                this._dataCallbackId = this._model.addDataCallback(function (type, rowObj, dataField) { self._modelChangedCallback(type, rowObj, dataField); }, this._dataRow);
22238
22239        },
22240        templateString: "<div></div>",
22241        /**
22242        * Get the TabularModel.
22243        * @returns {dpage.modules.TabularModel}
22244        */
22245        getModel : function()
22246        {
22247            return this._model;
22248        },
22249        /**
22250        * Set the model for the MultiValueWidget
22251        * @param {dpage.modules.TabularModel} model The model to set.
22252        * @returns {void}
22253        */
22254        setModel : function(model)
22255        {
22256            var self = this;
22257
22258            if (this._dataCallbackId != null)
22259                this.getModel().removeDataCallback(this._dataCallbackId);
22260
22261            if (model.isInstanceOf == null || !model.isInstanceOf(dpage.modules.TabularModel))
22262                throw new Error("model must be a dpage.modules.TabularModel for widget id = " + this.getWidgetId());
22263
22264            this._model = model;
22265
22266            this._dataCallbackId = this._model.addDataCallback(function (type, rowObj, dataField) { self._modelChangedCallback(type, rowObj, dataField); }, this._dataRow);
22267        },
22268        /**
22269        * Sets the value in the model without causing the control to re-render.
22270        * @param {Object} dataRow The row to set the value in.
22271        * @param {String} dataField The dataField in the row to set the value of.
22272        * @param {Object} value The value to set (String/bool/Number, etc).
22273        * @returns {void}
22274        */
22275        setModelValue: function (dataRow , dataField , value) {
22276            var oldS = this.isSubscribedToModelChanges();
22277
22278            if (oldS)
22279                this.setDataSubscriptions(false);
22280
22281            this.getModel().setValue(dataRow , dataField , value);
22282
22283            this.setDataSubscriptions(oldS);
22284        },
22285        /**
22286        * Is this widget responding to changes to the model or not.
22287        * @returns {bool} 
22288        */
22289        isSubscribedToModelChanges: function () {
22290            return this._doDataSubscriptions;
22291        },
22292        /**
22293        * Call this method to turn data subscriptions on or off. If off, the widget will not respond to updates on the model.
22294        * @param {bool} trueOrFalse Do data subscriptions or don't
22295        * @returns {void}
22296        */
22297        setDataSubscriptions: function (trueOrFalse) {
22298            this._doDataSubscriptions = trueOrFalse;
22299        },
22300        //called after the data gets added
22301        _modelChangedCallback: function (type, rowObj, dataField) {
22302            if (this._doDataSubscriptions) {
22303                this._modelChanged(type, rowObj, dataField);
22304            }
22305        },
22306        /*
22307        * Can be overridden to listen to events on the Model.
22308        * @param {String} type CHANGE|ADD|DEL|INS|INVALIDATE
22309        * @param {Object} rowObj The row of data that was altered
22310        * @param {String} dataField The column of data that was changed.
22311        * @returns {void}
22312        */
22313        _modelChanged: function (type, rowObj, dataField) {
22314            this._updateView();
22315        },
22316        destroy: function () {
22317            //so we will get garbage collected correctly.
22318            this._model.removeDataCallback(this._dataCallbackId);
22319            this.inherited(arguments);
22320        }
22321   });
22322});
22323
22324},
22325'dpage/widgets/Button':function(){
22326define([
22327      "dojo/_base/event"
22328      ,"dojo/on"
22329      ,"dojo/dom-attr"
22330      ,"dojo/dom-class"
22331      ,"dojo/mouse"
22332      ,"dojo/dom-geometry"
22333      , "dojo/dom-style"
22334      , "dojo/json"
22335
22336      , "dojo/request/xhr"
22337      ,"dojox/html/entities"
22338      ,"dojo/_base/declare"
22339      , "dpage/widgets/SingleValueWidget"],
22340function (event, on, domAttr, domClass, mouse, domGeom, style, json) {
22341    /**
22342    * @namespace dpage
22343    */
22344    /**
22345    * @namespace widgets
22346    * @memberOf dpage
22347    */
22348    /**
22349    * Class to encapulate the functionality of a &lt;button&gt; element. Has added benifits over the native button. For instance, if you include a native &lt;button&gt; element inside of a form without
22350    * the type attribute set to "button", clicking the button will submit a form in some browsers. If you turn your native button elements into dpage.widgets.Button you don't have to remember about this browser quirk.
22351    * @class Button
22352    * @param {Object} [options] Optional options for the widget.
22353    * @param {Function} [options.onClick] callback for click. The callback function will be called with a single parameter with 2 properties (event , and widget). The event property is a reference
22354    *                                     to the click event. The widget property is a reference to the widget that the event was triggered on.
22355    * @param {String} [options.text] The button text.
22356
22357    * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget.
22358    * @param {dpage.widgets.Container} [options.container] The container of the widget.
22359    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
22360    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
22361    *                               is created.
22362    * @param {Object} [containerNode] Optional container node to tie the widget to.
22363    * @memberOf dpage.widgets
22364    * @extends {dpage.widgets.SingleValueWidget}
22365    */
22366    return dojo.declare("dpage.widgets.Button", [dpage.widgets.SingleValueWidget], /** @lends dpage.widgets.Button.prototype */ {
22367        _containerNode: null,
22368
22369        constructor: function (options, srcNodeRef)
22370        {
22371            var self = this;
22372            this._containerNode = srcNodeRef;
22373
22374            if (this._containerNode == null) {
22375                this._containerNode = document.createElement("BUTTON");
22376            }
22377
22378            if (this._containerNode.nodeName != "BUTTON" && this._containerNode.nodeName != "A")
22379            {
22380                if(this._containerNode.nodeName != "INPUT" && domAttr.get(this._containerNode, "type") != "SUBMIT")
22381                    throw new Error("Source node for widgets.Button must be a BUTTON or an A or INPUT[type=submit].");
22382            }
22383
22384            if (this._containerNode.nodeName == "BUTTON")
22385            {
22386                //to prevent the button from submitting forms if it is contained within a form.
22387                domAttr.set(this._containerNode, "type", "button");
22388            }
22389
22390            if(options != null)
22391            {
22392                if (options.onClick != null)
22393                    this.on("click", options.onClick);
22394                if (options.text != null)
22395                    this._containerNode.innerHTML = dojox.html.entities.encode(options.text);
22396            }
22397
22398        },
22399        templateString: "<div></div>",
22400        /**
22401        * Set an event handler.
22402        * @param {String} eventName The event to bind to. Only supported events are "click".
22403        * @param {function} functionRef The callback function to call.
22404        * @returns {void}
22405        */
22406        on : function(eventName , functionRef)
22407        {
22408            var self = this;
22409
22410            if (eventName != "click")
22411                throw new Error("Supported events are: 'click'.");
22412
22413            on(this._containerNode, eventName, function(evt){functionRef({event:evt , widget : self})});
22414        },
22415        /**
22416        * Enable or disable the widget for user interaction.
22417        * @param {bool} val A value of true will enable the widget, a value of false will disable the widget.
22418        * @returns {void}
22419        */
22420        setEnabled: function (val)
22421        {
22422            this.domNode.disabled = !val;
22423        }
22424        
22425   });
22426});
22427
22428},
22429'dpage/widgets/CheckBox':function(){
22430define([
22431      "dojo/_base/event"
22432      ,"dojo/on"
22433      ,"dojo/dom-attr"
22434      ,"dojo/dom-class"
22435      ,"dojo/mouse"
22436      ,"dojo/dom-geometry"
22437      , "dojo/dom-style"
22438      , "dojo/json"
22439
22440      , "dpage/modules/TabularModel"
22441      , "dojo/request/xhr"
22442      ,"dojox/html/entities"
22443      ,"dojo/_base/declare"
22444      , "dpage/widgets/SingleValueWidget"],
22445function (event, on, domAttr, domClass, mouse, domGeom, style, json) {
22446    /**
22447    * @namespace dpage
22448    */
22449    /**
22450    * @namespace widgets
22451    * @memberOf dpage
22452    */
22453    /**
22454    * Class to encapulate the functionality of a &lt;input type="check"&gt; element. To manipulate the value, change the value in the model. The 
22455    * CheckBox is aware of changes to the model and will update accordingly.
22456    * @class CheckBox
22457    * @param {Object} [options] Optional options for the widget.
22458    * @param {Function} [options.onChange] callback function for when widget value changes from user input. May or may not correspond to a model value change in the case of invalid input.
22459    
22460    * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget.
22461    * @param {dpage.widgets.Container} [options.container] The container of the widget.
22462    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
22463    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
22464    *                               is created.
22465    * @param {Object} [containerNode] Optional container node to tie the widget to.
22466    * @memberOf dpage.widgets
22467    * @extends {dpage.widgets.SingleValueWidget}
22468    */
22469    return dojo.declare("dpage.widgets.CheckBox", [dpage.widgets.SingleValueWidget], /** @lends dpage.widgets.CheckBox.prototype */ {
22470        _containerNode: null,
22471        _onChange : null,
22472        constructor: function (options, srcNodeRef)
22473        {
22474            var self = this;
22475            this._containerNode = srcNodeRef;
22476            var dataIndex = 0;
22477
22478            this._onChange = [];
22479            if (this._containerNode == null) {
22480                this._containerNode = document.createElement("INPUT");
22481                domAttr.set(this._containerNode, "type", "checkbox");
22482            }
22483
22484            if (options != null) {
22485                if (options.onChange != null) {
22486                    this.on("change", options.onChange);
22487                }
22488            }
22489
22490            if (this._containerNode.nodeName != "INPUT")
22491                throw new Error("Source node for widgets.CheckBox must be an INPUT type='checkbox'");
22492
22493            on(this._containerNode, "click", function () { self._input_OnChange(event); });
22494        },
22495        postCreate: function () {
22496            //default to unchecked if we were not passed a model.
22497            if (this.isModelDefault())
22498                this.setModelValue(false);
22499            //render the control.
22500            this._updateView();
22501            return this.inherited(arguments);
22502        },
22503        setModel: function (model, dataIndex) {
22504            this.inherited(arguments);
22505
22506            if (!this.isModelDefault() && this._dataType != "BOOL")
22507                throw new Error("Checkbox: " + this.getWidgetId() + ". The model datatype for a CheckBox must be BOOL. The datatype on this column is: " + this._dataType);
22508
22509            this._updateView();
22510        },
22511        _updateView : function()
22512        {
22513            //update the value in the checkbox.
22514            this._containerNode.checked = this.getModel().getValue();
22515        },
22516        _input_OnChange: function (evt)
22517        {
22518            var controlVal;
22519            var self = this;
22520
22521            if (this.validate() == null) {
22522                //set the value in the model.
22523                controlVal = this._containerNode.checked;
22524                this.setModelValue(controlVal);
22525            }
22526
22527            //call callbacks in order.
22528            for (var i = 0; i < this._onChange.length; i++)
22529                this._onChange[i]({ event: evt, widget: self });
22530
22531        },
22532        templateString: "<div></div>",
22533        /**
22534        * Set an event handler.
22535        * @param {String} eventName The event to bind to. Only supported events are "change".
22536        * @param {function} functionRef The callback function to call.
22537        * @returns {void}
22538        */
22539        on: function (eventName, functionRef) {
22540            var self = this;
22541
22542            if (eventName != "change")
22543                throw new Error("Supported events are: 'change'.");
22544
22545            this._onChange.push(functionRef);
22546        }
22547
22548   });
22549});
22550
22551},
22552'dpage/widgets/ClickToEditTextBox':function(){
22553define([
22554      "dojo/_base/event"
22555      ,"dojo/on"
22556      ,"dojo/dom-attr"
22557      ,"dojo/dom-class"
22558      ,"dojo/mouse"
22559      ,"dojo/dom-geometry"
22560      , "dojo/dom-style"
22561      , "dojo/json"
22562
22563      , "dpage/widgets/Anchor"
22564      , "xstyle/css!dpage/widgets/TextBox.css"
22565      , "dpage/modules/LegacyPlaceholder"
22566      , "dpage/modules/TabularModel"
22567      , "dojo/request/xhr"
22568      ,"dojox/html/entities"
22569      ,"dojo/_base/declare"
22570      , "dpage/widgets/SingleValueWidget"],
22571function (event, on, domAttr, domClass, mouse, domGeom, style, json) {
22572    /**
22573    * @namespace dpage
22574    */
22575    /**
22576    * @namespace widgets
22577    * @memberOf dpage
22578    */
22579    /**
22580    * This class is to provide a widget that displays data like a Label, but allows you to edit the data like a TextBox.
22581    * @class ClickToEditTextBox
22582    * @param {Object} [options] Optional options for the widget.
22583    * @param {Number} [options.minTextBoxWidth] Default 40px. Minimum width for texbox. By default this widget sizes the textbox to the size of the area the label occupies.
22584    *                                           If the label has a blank value, it would make it hard to edit the value unless we had a minimum width.
22585    * @param {bool} [options.styleTextBoxBorder] Default true. If true, the border is removed on the textbox.
22586    * @param {bool} [options.styleTextBoxMargin] Default true. If true, the margin is removed on the textbox.
22587    * @param {bool} [options.styleTextBoxPadding] Default true. If true, the padding is removed on the textbox.
22588    * @param {bool} [options.styleTextBoxOutline] Default true. If true, the outline is removed on the textbox.
22589    * @param {bool} [options.styleTextBoxFont] Default true. If true, attempt to style the textbox font to the same font as the label.
22590    * @param {bool} [options.styleTextBoxSize] Default true. If true, the textBox is sized to fit the content of the label.
22591
22592    * @param {String} [options.placeHolder] Optional placeholder text. Backwards compatible on browsers that don't natively support this attribute.
22593    * @param {Function} [options.formatter] string options.formatter(rawValue). Function to call for formatting the text. The formatter will be used 
22594    *                                       to set the value of the input when the input is non-focused. When the input is focused,
22595    *                                       the raw value from the model will be shown. This function returns the value to display in the textbox.
22596    * @param {Function} [options.editFormatter] string options.formatter(rawValue). Function to call for formatting the text when the TextBox is focused. 
22597    *                                       The formatter will be used 
22598    *                                       to set the value of the input when the input is focused.
22599    * @param {Function} [options.inputFilter] string options.inputFilter(rawValue). This function will be called to return the value that is saved to the model.
22600    *                                         Default behavior is to store the value the user types into the TextBox to the model. Passing in this function overrides
22601    *                                         this behavior.
22602    *                                         The function is passed the raw value that the user types into the textbox. The function will return the value
22603    *                                         to store in the model. This function only operates on user input and is meant to be used to coerce different forms of user
22604    *                                         input to the correct model value.
22605    * @param {bool} [options.highlightOnFocus] Default false. Highlight the text when the input is focused.
22606    * @param {Function} [options.onChange] callback function for when widget value changes from user input. May or may not correspond to a model value change in the case of invalid input.
22607     
22608    * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget.
22609    * @param {dpage.widgets.Container} [options.container] The container of the widget.
22610    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
22611    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
22612    *                               is created.
22613    * @param {Object} [containerNode] Optional container node to tie the widget to. The only valid nodes are &lt;input type='text'&gt; and LABEL
22614    * @memberOf dpage.widgets
22615    * @extends {dpage.widgets.SingleValueWidget}
22616    */
22617    return dojo.declare("dpage.widgets.ClickToEditTextBox", [dpage.widgets.SingleValueWidget], /** @lends dpage.widgets.ClickToEditTextBox.prototype */ {
22618        _hrefWidget: null,
22619        _tbWidget: null,
22620        _minTextBoxWidth: 40,
22621        _containsPlaceholder: false,
22622        _styleTextBoxBorder : true,
22623        _styleTextBoxPadding : true,
22624        _styleTextBoxMargin : true,
22625        _styleTextBoxOutline : true,
22626        _styleTextBoxSize: true,
22627        _styleTextBoxFont:true,
22628
22629        constructor : function(options , srcNodeRef)
22630        {
22631            var self = this;
22632            var labelText = null;
22633            var model;
22634
22635            if (srcNodeRef == null)
22636                this._containerNode = document.createElement("SPAN");
22637            else
22638                this._containerNode = srcNodeRef;
22639
22640            if(options != null)
22641            {
22642                if(options.minTextBoxWidth != null)
22643                    this._minTextBoxWidth = options.minTextBoxWidth;
22644                if (options.styleTextBoxBorder !== undefined) {
22645                    this._styleTextBoxBorder = options.styleTextBoxBorder;
22646                }
22647                if (options.styleTextBoxPadding !== undefined) {
22648                    this._styleTextBoxPadding = options.styleTextBoxPadding;
22649                }
22650                if (options.styleTextBoxMargin !== undefined) {
22651                    this._styleTextBoxMargin = options.styleTextBoxMargin;
22652                }
22653                if (options.styleTextBoxOutline !== undefined) {
22654                    this._styleTextBoxOutline = options.styleTextBoxOutline;
22655                }
22656                if (options.styleTextBoxBorder !== undefined) {
22657                    this._styleTextBoxSize = options.styleTextBoxSize;
22658                }
22659                if (options.styleTextBoxFont !== undefined) {
22660                    this._styleTextBoxFont = options.styleTextBoxFont;
22661                }
22662            }
22663
22664            if (srcNodeRef != null) {
22665                if (srcNodeRef.nodeName == "LABEL" | srcNodeRef.nodeName == "DIV" || srcNodeRef.nodeName == "SPAN") {
22666                    labelText = srcNodeRef.innerHTML;
22667                }
22668                else {
22669                    throw new Error("The only support node types for a dpage.widgets.ClickToEditTextBox are label, span, or div");
22670                }
22671            }
22672
22673            this._tbWidget = new dpage.widgets.TextBox(options);
22674
22675            this._hrefWidget = new dpage.widgets.Anchor({ disableClick: true });
22676
22677            if (options != null && options.model != null)
22678                this._hrefWidget.setModel(options.model);
22679                //textbox was already supplied the model in the constructor along with all other options.
22680            else {
22681                if (labelText != null) {
22682                    this._hrefWidget.setValue(labelText);
22683                }
22684                this._tbWidget.setModel(this._hrefWidget.getModel());
22685            }
22686
22687            if (this._tbWidget.getValue() == "")
22688            {
22689                this._containsPlaceholder = true;
22690                this._tbWidget.setValue("   ");
22691            }
22692
22693            var s = getComputedStyle(this._containerNode);
22694
22695            this._hrefWidget.getDomNode().style.color = s.color;
22696            this._hrefWidget.getDomNode().style.textDecoration = s.textDecoration;
22697            this._hrefWidget.getDomNode().style.font = s.font;
22698            this._hrefWidget.getDomNode().style.fontFamily = s.fontFamily;
22699            this._hrefWidget.getDomNode().style.fontSize = s.fontSize;
22700
22701            if (this._styleTextBoxFont) {
22702                this._tbWidget.getDomNode().style.color = s.color;
22703                this._tbWidget.getDomNode().style.textDecoration = s.textDecoration;
22704                this._tbWidget.getDomNode().style.font = s.font;
22705                this._tbWidget.getDomNode().style.fontFamily = s.fontFamily;
22706                this._tbWidget.getDomNode().style.fontSize = s.fontSize;
22707            }
22708
22709            this._tbWidget.getDomNode().style.display = "none";
22710            this._containerNode.innerHTML = "";
22711            this._containerNode.appendChild(this._tbWidget.getDomNode());
22712            this._containerNode.appendChild(this._hrefWidget.getDomNode());
22713
22714            on(this._tbWidget.getDomNode(), "blur", function (event) { self.tbNode_OnBlur(event); });
22715            this._hrefWidget.on("click", function (obj) { self.href_OnClick(obj); });
22716            on(this._hrefWidget.getDomNode(), "focus", function (obj) { self.href_OnClick(obj); });
22717        },
22718        href_OnClick: function (obj) {
22719
22720            if (this._styleTextBoxSize) {
22721                var coords = domGeom.getContentBox(this._hrefWidget.getDomNode());
22722                if (coords.w < this._minTextBoxWidth)
22723                    coords.w = this._minTextBoxWidth;
22724                if (this._containsPlaceholder)
22725                    this._tbWidget.setValue("");
22726                this._tbWidget.getDomNode().style.width = coords.w + "px";
22727                if (coords.h != 0)
22728                    this._tbWidget.getDomNode().style.height = coords.h + "px";
22729            }
22730            
22731            if(this._styleTextBoxBorder)
22732                this._tbWidget.getDomNode().style.border = "0px";
22733            if(this._styleTextBoxMargin)
22734                this._tbWidget.getDomNode().style.margin = "0px";
22735            if(this._styleTextBoxPadding)
22736                this._tbWidget.getDomNode().style.padding = "0px";
22737
22738            this._tbWidget.getDomNode().style.display = "inline";
22739            
22740            if(this._styleTextBoxOutline)
22741                this._tbWidget.getDomNode().style.outline = "none";
22742
22743            this._hrefWidget.getDomNode().style.display = "none";
22744            this._tbWidget.getDomNode().focus();
22745        },
22746        tbNode_OnBlur: function (event) {
22747            if (this._tbWidget.getValue() == "") {
22748                this._containsPlaceholder = true;
22749                this._tbWidget.setValue("   ");
22750            }
22751            else
22752                this._containsPlaceholder = false;
22753
22754            this._tbWidget.getDomNode().style.display = "none";
22755            this._hrefWidget.getDomNode().style.display = "";
22756        }
22757   });
22758});
22759
22760},
22761'xstyle/css':function(){
22762define(["require"], function(moduleRequire){
22763"use strict";
22764/*
22765 * AMD css! plugin
22766 * This plugin will load and wait for css files. This allows JavaScript resources to 
22767 * fully there dependencies on stylesheets. This can also be used when
22768 * loading css files as part of a layer or as a way to apply a run-time theme. This
22769 * module checks to see if the CSS is already loaded before incurring the cost
22770 * of loading the full CSS loader codebase
22771 */
22772 	function testElementStyle(tag, id, property){
22773 		// test an element's style
22774		var docElement = document.documentElement;
22775		var testDiv = docElement.insertBefore(document.createElement(tag), docElement.firstChild);
22776		testDiv.id = id;
22777		var styleValue = (testDiv.currentStyle || getComputedStyle(testDiv, null) || {})[property];
22778		docElement.removeChild(testDiv);
22779 		return styleValue;
22780 	} 
22781 	return {
22782		load: function(resourceDef, require, callback, config) {
22783			var url = require.toUrl(resourceDef);
22784			var options;
22785			if(url.match(/!$/)){
22786				// a final ! can be used to indicate not to wait for the stylesheet to load
22787				options = {
22788					wait: false
22789				};
22790				url = url.slice(0, -1);
22791			}
22792			var cachedCss = require.cache && require.cache['url:' + url];
22793			if(cachedCss){
22794				// we have CSS cached inline in the build
22795				if(cachedCss.xCss){
22796					var parser = cachedCss.parser;
22797					var xCss =cachedCss.xCss;
22798					cachedCss = cachedCss.cssText;
22799				}
22800				moduleRequire(['./core/load-css'],function(load){
22801					checkForParser(load.insertCss(cachedCss));
22802				});
22803				if(xCss){
22804					//require([parsed], callback);
22805				}
22806				return;
22807			}
22808			function checkForParser(styleSheetElement){
22809				var parser = testElementStyle('x-parse', null, 'content');
22810				var sheet = styleSheetElement && 
22811					(styleSheetElement.sheet || styleSheetElement.styleSheet);
22812				if(parser && parser != 'none' && parser != 'normal'){
22813					// TODO: wait for parser to load
22814					require([eval(parser)], function(parser){
22815						if(styleSheetElement){
22816							parser.process(styleSheetElement, callback);
22817						}else{
22818							parser.processAll();
22819							callback(sheet);
22820						}
22821					});
22822				}else{
22823					callback(sheet);
22824				}
22825			}
22826			
22827			// if there is an id test available, see if the referenced rule is already loaded,
22828			// and if so we can completely avoid any dynamic CSS loading. If it is
22829			// not present, we need to use the dynamic CSS loader.
22830			var displayStyle = testElementStyle('div', resourceDef.replace(/\//g,'-').replace(/\..*/,'') + "-loaded", 'display');
22831			if(displayStyle == "none"){
22832				return checkForParser();
22833			}
22834			// use dynamic loader
22835			moduleRequire(["./core/load-css"], function(load){
22836				load(url, checkForParser, options);
22837			});
22838		}
22839	};
22840});
22841
22842},
22843'dpage/widgets/Container':function(){
22844/// <reference path="ExpandCollapse.js" />
22845define([
22846      "dojo/_base/declare"
22847      , "dojo/on"
22848      , "dojo/_base/event"
22849      , "dojo/json"
22850
22851      , "dpage/modules/SingleValueModel"
22852      , "dpage/modules/TabularModel"
22853      , "dpage/modules/Model"
22854      , "dpage/widgets/BaseWidget"
22855      , "dojox/widget/Standby"
22856      , "dojo/parser"
22857],
22858    function (declare, on, event, json) {
22859    /**
22860    * @namespace dpage
22861    */
22862    /**
22863    * @namespace widgets
22864    * @memberOf dpage
22865    */
22866    /**
22867    * Class to contain methods common to all Containers. A container is a concept of a UI widget that contains
22868    * other UI widgets. These can be a {@link dpage.widgets.Page} which encapulates all the javascript for the entire browser window. 
22869    * A container could be a {@link dpage.widgets.Dialog} widget that contains widgets, or a Container could be a widget representing a partial view
22870    * of a Page or Dialog. The model is a javascript object that should contain the data for child widgets. At the moment, widgets can be bound to an instance of 
22871    * {@link dpage.widgets.SingleValueWidget} or {@link dpage.widgets.MultiValueWidget}.
22872    * @class Container
22873    * @param {Object} [options] Optional options for the widget.
22874    * @param {Object} [options.model] Data destined for Container child controls. 
22875    * @param {bool} [options.modelTransform] Default false. If true, parse the model as if it contains meta-data. If false, don't bother parsing. Use it as-is.
22876    * @param {bool} [options.parseNow] (defaults to true) If true, then parse the container for child widgets now. If false, wait for domReady.
22877    * @param {function} [options.widgetsParsedCallback] widgetsParsedCallback(referenceToTheContainer). callback function for when widgets in this container are parsed.
22878    *                                                   a reference to the container is passed into this function.
22879    * @param {String} [options.templateString] Optional template for this container. If provided will instantiate a container with the provided
22880    *                                          markup. As with all containers, the markup can contain widgets that can be accessed through
22881    *                                          getWidget() or getWidgets().
22882    * @param {String} [options.templatePath] Optional server URI that contains the template. If provided, the Container will make a request to the 
22883    *                                          specified server path that contains the template. The container will then instantiate a container with the provided
22884    *                                          markup. As with all containers, the markup can contain widgets that can be accessed through
22885    *                                          getWidget() or getWidgets().
22886    * @param {dpage.widgets.Container} [options.container] The container of the widget.
22887    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
22888    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
22889    *                               is created.
22890    * @param {Object} [containerNode] Optional container node to tie the widget to.
22891    * @memberOf dpage.widgets
22892    * @extends {dpage.widgets.BaseWidget}
22893    */
22894        var theClass = declare("dpage.widgets.Container", [dpage.widgets.BaseWidget], /** @lends dpage.widgets.Container.prototype */ {
22895            _widgets: null,
22896             _widgetContainer: null,
22897             _validationMessageWidget: null,
22898             _overlay: null,
22899             _containerNode: null,
22900             _model: null,
22901             _depsLoading: 0, //used by the parser.
22902             _doneParsing: false,
22903             _widgetsParsedCallback: null,
22904             _parseNow: true,
22905            _modelTransform : false,
22906
22907            constructor: function (options, containerNode) {
22908                var self = this;
22909                var nodeInnerHTML;
22910
22911                this._widgets = [];
22912                this._containerNode = containerNode;
22913
22914                if (this._containerNode == null)
22915                {
22916                    this._containerNode = document.createElement("SPAN");
22917                }
22918
22919                if (options != null) {
22920
22921                    if (options.widgetsParsedCallback != null)
22922                    {
22923                        this._widgetsParsedCallback = options.widgetsParsedCallback;
22924                    }
22925
22926                    if (options.parseNow != undefined && options.parseNow == false)
22927                        this._parseNow = false;
22928
22929                    if (options.templateString)
22930                        this.templateString = options.templateString;
22931                    
22932                    else if (options.templatePath) {
22933                        this.templatePath = options.templatePath;
22934                    }
22935                    else {
22936                        this.templateString = "";
22937                        this.templatePath = "";
22938                    }
22939
22940                    if (options.modelTransform != undefined && options.modelTransform == true)
22941                        this._modelTransform = true;
22942
22943                    //a PageModel
22944                    if (options.model != null)
22945                        this.setModel(options.model , this._modelTransform);
22946
22947                    //a page can have a container too.
22948                    if (options.container != null)
22949                        this._widgetContainer = options.container;
22950                }
22951            },
22952
22953            _widgetsParsed : function(){
22954                if(this._widgetsParsedCallback)
22955                    this._widgetsParsedCallback(this);
22956
22957                //call method that user can override.
22958                this.widgetsParsed();
22959            },
22960            /**Called after the parser finishes. All widgets in the Container will be available at this point.
22961            *  Override this method to hook up events and such to widgets.
22962            * @returns {void}
22963            */
22964            widgetsParsed: function () {
22965
22966
22967            },
22968
22969            //called after a child widget is parsed.
22970            _decrementDepCount : function()
22971            {
22972                --this._depsLoading;
22973
22974                if (this._depsLoading == 0
22975                    && this._doneParsing)
22976                {
22977                    this._widgetsParsed();
22978
22979                    if (this._widgetContainer != null) {
22980                        this._widgetContainer._decrementDepCount();
22981                    }
22982                }
22983            },
22984
22985            parseContent : function()
22986            {
22987                var self = this;
22988
22989                if (this.templateString != null
22990                    && this.templateString.length > 0)
22991                {
22992                    this._containerNode.innerHTML = this.templateString;
22993                    this._parseContent(this, this._containerNode);
22994                }
22995                else if (this.templatePath != null
22996                    && this.templatePath.length > 0)
22997                {
22998                    require(["dojo/text!" + this.templatePath], function (template) {
22999                        self._containerNode.innerHTML = template;
23000                        self._parseContent(self, self._containerNode);
23001                    });
23002                }
23003                else
23004                    this._parseContent(this, this._containerNode);
23005            },
23006
23007            _parseContent: function (containerWidget, nodeToParse) {
23008
23009                if (nodeToParse.firstChild != null)
23010                    this._parseContentRecursive(containerWidget, nodeToParse.firstChild);
23011
23012                this._doneParsing = true;
23013
23014                if (this._depsLoading == 0) {
23015                    this._widgetsParsed();
23016
23017                    if (this._widgetContainer != null) {
23018                        this._widgetContainer._decrementDepCount();
23019                    }
23020                }
23021            },
23022
23023            //This is an intense method.
23024            _parseContentRecursive : function(containerWidget , nodeToParse)
23025            {
23026                var dataDojoType;
23027                var newWidget;
23028                var self = this;
23029                var dataDojoTypeObj;
23030
23031                do
23032                {
23033                    dataDojoType = nodeToParse.getAttribute ? nodeToParse.getAttribute("data-dojo-type") : null;
23034
23035                    if(dataDojoType != null)
23036                        dataDojoType = dataDojoType.replace(/\./g, "/");
23037                    //Only parse the nodes with this attribute. 
23038                    //This will parse just one node. No child nodes will be parsed.
23039                    if (dataDojoType != null)
23040                    {
23041                        ++this._depsLoading;
23042
23043                        (function(cNodeToParse , cContainerWidget, cDataDojoType){
23044                            //auto-require modules in.
23045                            require([cDataDojoType], function () {
23046                                var nodeObj = dojo.parser.instantiate([cNodeToParse], {}, { propsThis: cContainerWidget })[0];//should always return an array of one element unless I am missing something?
23047                                var isContainer = nodeObj.isInstanceOf(dpage.widgets.Container);
23048
23049                                //ensure that the container is set.
23050                                if (nodeObj.getContainer() == null) {
23051                                    cContainerWidget.addWidget(nodeObj);
23052                                    //If the nodeObj is a container and the container for it was not set, the _decrementDepCount will not be called on us,
23053                                    // so we will fire it off manually here.
23054                                    if (isContainer && nodeObj._depsLoading == 0)
23055                                        self._decrementDepCount();
23056                                }
23057
23058                                if (!isContainer) {
23059                                    //A Container will perform it's own parse, and then decrement our count once it finishes loading all widgets asynchronously.
23060                                    if (cNodeToParse.hasChildNodes()) {
23061                                        self._parseContentRecursive(cContainerWidget, cNodeToParse.firstChild);
23062                                    }
23063                                    self._decrementDepCount();
23064                                }
23065                            });
23066                        })(nodeToParse , containerWidget , dataDojoType);
23067                    }
23068                    else
23069                    {
23070                        if (nodeToParse.hasChildNodes()) {
23071                            this._parseContentRecursive(containerWidget, nodeToParse.firstChild);
23072                        }
23073                    }
23074
23075                } while (nodeToParse = nodeToParse.nextSibling);
23076            },
23077            buildRendering: function () {
23078
23079                var self = this;
23080
23081                if (this._parseNow)
23082                    this.parseContent();
23083                else
23084                    dojo.ready(function () {
23085                        self.parseContent();
23086                    });
23087
23088                this.domNode = this._containerNode;
23089            },
23090            /**
23091            * Gets the model for the Container.
23092            * @returns {Object} The model.
23093            */
23094            getModel: function () {
23095                return this._model;
23096            },
23097            
23098            /**
23099            * Sets a model. Use this model for all of the widgets on the page.
23100            * @param {Object} model Javascript object.
23101            * @param [modelTransform] default false. If false, just use the javascript object that was passed in. If true, each property of the javascript object
23102            *                         contains meta-data about the type of data and we will c
23102onstruct those objects here. The passed in model object WILL BE MODIFIED.
23103            *                         Typically used to construct dpage.modules.Model objects from the server.
23104            * @returns {void}
23105            */
23106            setModel: function (val , modelTransform) {
23107                this._model = val;
23108
23109                if (modelTransform == null)
23110                    modelTransform = false;
23111
23112                if (modelTransform) {
23113                    //transform the model here.
23114                    dpage.widgets.Container.parseServerModel(this._model);
23115                }
23116            },
23117            //will attempt to divine out which objects should be SingleValueModels and TabularModels based on the format of the objects coming in.
23118            //The model is not transformed.
23119            _recurseRefreshModel: function (obj, modelObj) {
23120
23121                for (var p in obj) {
23122                    var objHasProps = false;
23123                    if (obj.hasOwnProperty(p)) {
23124                        if (obj[p] == null)
23125                            modelObj[p] = obj[p];
23126                        else if (obj[p].isInstanceOf != null && obj[p].isInstanceOf(dpage.modules.SingleValueModel)) {
23127                            //causes CHANGE event to be called for subscribers (including SingleValue widgets).
23128                            if (modelObj[p] == null || modelObj[p].isInstanceOf == null || !modelObj[p].isInstanceOf(dpage.modules.SingleValueModel))
23129                                throw new Error("Model mismatch. The structure of the existing model must match the new model.");
23130                            modelObj[p].setValue(obj[p].getValue());
23131                            modelObj[p].setClean();
23132                        }
23133                        else if (obj[p].isInstanceOf != null && obj[p].isInstanceOf(dpage.modules.TabularModel)) {
23134                            //causes the INVALIDATE event to be called for subscribers (including MultiValue widgets).
23135                            if (modelObj[p] == null || modelObj[p].isInstanceOf == null || !modelObj[p].isInstanceOf(dpage.modules.TabularModel))
23136                                throw new Error("Model mismatch. The structure of the existing model must match the new model.");
23137                            modelObj[p].setRows(obj[p].getRows());
23138                            modelObj[p].setClean();
23139                        }
23140                        else {
23141                            //recurse.
23142                            if (dpage.widgets.Container._isSimpleType(obj[p])) {
23143                                //just set the value.
23144                                modelObj[p] = obj[p];
23145                            }
23146                            else {
23147                                if (modelObj == null)
23148                                    throw new Error("Model mismatch. The structure of the existing model must match the new model.");
23149                                this._recurseRefreshModel(obj[p], modelObj[p]);
23150                            }
23151                        }
23152                    }
23153                }
23154            },
23155            /**
23156            * Refresh the model. This is usefull to update the data in the entire Container. Calling this method will cause all of the widgets to update as well.
23157            * Very usefull when making async calls to the server and getting back updated data just as it would be when doing a page refresh. The model passed
23158            * in must match the structure of the existing model. Sets the state of all models to clean.
23159            * @param {Object} model Javascript object.
23160            * @param {bool} modelTransform Default false. If true, the model must convorm to a special format returned by the server serializer (or constructed manually). The
23161            *                              model will be transformed (val is changed). If false, just use the raw model passed in.
23162            * @returns {void}
23163            */
23164            refreshModel: function (val, modelTransform) {
23165                if (modelTransform == null)
23166                    modelTransform = false;
23167
23168                if (modelTransform) {
23169                    //transform the model here.
23170                    dpage.widgets.Container.parseServerModel(val);
23171                }
23172
23173                this._recurseRefreshModel(val , this._model);
23174            },
23175            /**
23176            * Returns an array of the widgets registered with this container. To register a widget with this container, 
23177            * you need to include the container property in the widget constructor with the value of the container you want
23178            * to register it with.
23179            * @returns {Array.<dpage.widgets.BaseWidget>} An Array of BaseWidgets.
23180            */
23181            getWidgets: function () {
23182                return this._widgets;
23183            },
23184            /**
23185            * Get a widget by its id
23186            * @param {Number} id The numeric widget id.
23187            * @returns {dpage.widgets.BaseWidget} 
23188            */
23189            getWidget: function (id) {
23190                for (var idx = 0; idx < this._widgets.length ; idx++) {
23191                    if (this._widgets[idx].getWidgetId() == id)
23192                        return this._widgets[idx];
23193                }
23194                return null;
23195            },
23196            /**
23197            * Add a widget to this container.
23198            * @param {dpage.widgets.BaseWidget} widgetRef
23199            * @param {bool}
23199 appendToDom Default false. If true, append as the last child of the containers getDomNode()
23200            * @returns {void}
23201            */
23202            addWidget: function (widgetRef , appendToDom) {
23203                if (widgetRef.isInstanceOf == null || !widgetRef.isInstanceOf(dpage.widgets.BaseWidget))
23204                    throw new Error("Invalid widget detected. All widgets must inherit from WidgetBase.");
23205
23206                if (widgetRef.getContainer() == null || widgetRef.getContainer().getWidgetId() != this.getWidgetId()) {
23207                    widgetRef.setContainer(this);
23208                }
23209                else {
23210                    for (var idx = 0; idx < this._widgets.length ; idx++) {
23211                        if (this._widgets[idx].getWidgetId() == widgetRef.getWidgetId())
23212                            throw new Error("Duplicate widget id of " + widgetRef.getWidgetId())
23213                    }
23214                    this._widgets.push(widgetRef);
23215                }
23216
23217                if (appendToDom)
23218                    this.getDomNode().appendChild(widgetRef.getDomNode());
23219            },
23220            /**
23221            * Remove a widget by its id. To remove the widget from the dom, call the destroy() method on it after removing it from the container.
23222            * @param {Number} widgetId
23223            * @returns {dpage.widgets.BaseWidget} Reference to the removed widget.
23224            */
23225            removeWidget: function (widgetId) {
23226                for (var idx = 0; idx < this._widgets.length ; idx++) {
23227                    if (this._widgets[idx].getWidgetId() == widgetId) {
23228                        this._widgets.splice(idx, 1);
23229                        return this._widgets[idx];
23230                    }
23231                }
23232            },
23233            /**
23234            * Clears the list of widgets for the container. It will also call the destroy() method on each widget.
23235            * @returns {void}
23236            */
23237            clearWidgets: function () {
23238                for (var i = 0; i < this._widgets.length; i++)
23239                    this._widgets[i].destroy();
23240
23241                this._widgets = [];
23242            },
23243            /**
23244            * Set the widget to be used to handle the validation message for this container.
23245            * @param {dpage.widgets.BaseWidget} widget
23246            * @return {void}
23247            */
23248            setValidationMessageWidget: function (widget) {
23249                this._validationMessageWidget = widget;
23250            },
23251            /**
23252            * Get a reference to the validation widget that will be used to display the validation message for this container.
23253            * @returns {dpage.widgets.ValidationMessage}
23254            */
23255            getValidationMessageWidget: function () {
23256                return this._validationMessageWidget;
23257            },
23258            /**
23259            * Validate all the widgets in this container.
23260            * @param {bool} disablePage If true the page will be disabled while the validation is taking place.
23261            * @returns {bool} Returns true if the page is OK. False, if there are validation issues.
23262            */
23263            validateWidgets: function (disablePage) {
23264                var containerWidgets = this.getWidgets();
23265                var validationResults = [];
23266                var result = true;
23267
23268                if (disablePage) {
23269                    this.disablePage();
23270                }
23271
23272                if (this.getValidationMessageWidget != null && this.getValidationMessageWidget() != null) {
23273                    this.getValidationMessageWidget().clearError();
23274                }
23275
23276                for (var idx = 0 ; idx < containerWidgets.length ; idx++) {
23277                    var ret = containerWidgets[idx].validate();
23278                    if (ret != null)
23279                        validationResults.push({ widgetId: containerWidgets[idx].getWidgetId(), message: ret });
23280                }
23281
23282                if (validationResults.length > 0) {
23283                    if (this.getValidationMessageWidget != null && this.getValidationMessageWidget() != null) {
23284                        this.getValidationMessageWidget().setError(validationResults);
23285                    }
23286                    result = false;
23287                }
23288
23289                if (disablePage) {
23290                    this.enablePage();
23291                }
23292
23293                return result;
23294            },
23295            _serializeRecurseObject : function(obj , objCopy)
23296            {
23297                for(var prop in obj)
23298                {
23299                    var objHasProperties = false;
23300
23301                    if(obj.hasOwnProperty(prop))
23302                    {
23303                        if (obj[prop] == null)
23304                            continue;
23305                        if (obj[prop].isInstanceOf != null && obj[prop].isInstanceOf(dpage.modules.Model)) {
23306                            if (obj[prop].suppressSerialization(null))
23307                                objCopy[prop] = null;
23308                            else
23309                                objCopy[prop] = obj[prop].getRawModel();
23310                        }
23311                        else {
23312                            if (obj[prop] instanceof Array) {
23313                                objCopy[prop] = [];
23314                                this._serializeRecurseObject(obj[prop], objCopy[prop]);
23315                            }
23316                            else {
23317                                if(dpage.widgets.Container._isSimpleType(obj[prop])) {
23318                                    //just copy the raw value.
23319                                    objCopy[prop] = obj[prop];
23320                                }
23321                                else {
23322                                    objCopy[prop] = {};
23323                                    this._serializeRecurseObject(obj[prop], objCopy[prop]);
23324                                }
23325                            }
23326                            
23327                        }
23328                    }
23329                }
23330            },
23331            /**
23332            *Stringify the Model so that we can communicate with a server.
23333            * @returns {String} 
23334            */
23335            serializeModel: function () {
23336                var strModel;
23337                var thisModel = this.getModel();
23338                var simplePageModel = {};
23339
23340                if (thisModel != null) {
23341                    this._serializeRecurseObject(thisModel , simplePageModel);
23342
23343                    strModel = json.stringify(simplePageModel);
23344                }
23345                else
23346                    strModel = 'null';
23347
23348                return strModel;
23349            }
23350        });
23351
23352        /**
23353        * Parse the model that comes back from the server. This call will create TabularModels and SingleValueModels automatically based on the 
23354        * format of the message that comes back from the server. This method modifies the object passed in.
23355        * @memberof dpage.widgets.Container
23356        * @name parseServerModel
23357        * @function
23358        * @param {String} Serialized string model from server.
23359        * @returns {Object} Object to use in calls to Container.setModel() or Container.refreshModel()
23360        *//**
23361        * Parse the model that comes back from the server. This call will create TabularModels and SingleValueModels automatically based on the 
23362        * format of the message that comes back from the server. This method modifies the object passed in.
23363        * @memberof dpage.widgets.Container
23364        * @name parseServerModel
23365        * @function
23366        * @param {Object} Object obtained from de-serializing the serialized string model from server.
23367        * @returns {Object} Object to use in calls to Container.setModel() or Container.refreshModel()
23368        */
23369        theClass.parseServerModel = function (modelIn) {
23370            var model;
23371
23372            if (typeof (modelIn) === "string" || modelIn instanceof String)
23373                model = json.parse(modelIn);
23374            else
23375                model = modelIn;
23376
23377            dpage.widgets.Container._recurseParseModel(model);
23378
23379            return model;
23380        };
23381
23382        theClass._isSimpleType = function (obj) {
23383            var t = typeof(obj);
23384
23385            if( t === "string" || obj instanceof String ||
23386                t === "boolean" || obj instanceof Boolean ||
23387                t === "number" || obj instanceof Number){
23388                return true;
23389            }
23390
23391            return false;
23392        };
23393
23394        //will attempt to divine out which objects should be SingleValueModels and TabularModels based on the format of the objects coming in.
23395        theClass._recurseParseModel = function (obj)
23396        {
23397            for(var p in obj)
23398            {
23399                if(obj.hasOwnProperty(p))
23400                {
23401                    if (obj[p] == null)
23402                        continue;
23403                    if (obj[p].dt == null)
23404                        throw new Error("Encountered an anomaly parsing the model. Each model property must contain a 'dt' property. You must pass the modelTransform:false property to disable this. ");
23405
23406                    if (obj[p].dt == "Literal") {
23407                        obj[p] = obj[p].v;
23408                        dpage.widgets.Container._recurseParseModel(obj[p]);
23409                    }
23410                    else if(obj[p].dt == "dpage.modules.SingleValueModel")
23411                        obj[p] = dpage.modules.SingleValueModel.apply(null, obj[p].args);
23412                    else if (obj[p].dt == "dpage.modules.TabularModel") {
23413                        //transform the columns of the TabularModel if they are type=="OBJECT"
23414                        for (var i = 0; i < obj[p].args[0].model.Columns.length; i++) {
23415                            if (obj[p].args[0].model.Columns[i].DataType == "OBJECT") {
23416                                //we only take this hit if we are taking advantage of the funtionality thankfully.
23417                                for (var ri = 0 ; ri < obj[p].args[0].model.Rows.length; ri++)
23418                                {
23419                                    var t = { z: obj[p].args[0].model.Rows[ri][obj[p].args[0].model.Columns[i].ColumnName] };
23420                                    dpage.widgets.Container._recurseParseModel(t);
23421                                    obj[p].args[0].model.Rows[ri][obj[p].args[0].model.Columns[i].ColumnName] = t.z;
23422                                }
23423                            }
23424                        }
23425                        //finally, turn the value into a TabularModel.
23426                        obj[p] = dpage.modules.TabularModel.apply(null, obj[p].args);
23427                    }
23428                    else
23429                        throw new Error("Encountered an anomaly parsing the model. Unexpected dt property of: " + obj[p].dt + ". Supported types are dpage.modules.TabularModel, dpage.modules.SingleValueModel, or Literal. ");
23430                }
23431            }
23432        };
23433        return theClass;
23434    }
23435);
23436},
23437'dojox/widget/Standby':function(){
23438define(["dojo/_base/kernel",
23439	"dojo/_base/declare",
23440	"dojo/_base/array",
23441	"dojo/_base/event",
23442	"dojo/_base/sniff",
23443	"dojo/dom",
23444	"dojo/dom-attr",
23445	"dojo/dom-construct",
23446	"dojo/dom-geometry",
23447	"dojo/dom-style",
23448	"dojo/window",
23449	"dojo/_base/window",
23450	"dojo/_base/fx",
23451	"dojo/fx",
23452	"dijit/_Widget",
23453	"dijit/_TemplatedMixin",
23454	"dijit/registry"],
23455
23456function(kernel,
23457		declare,
23458		array,
23459		event,
23460		has,
23461		dom,
23462		attr,
23463		construct,
23464		geometry,
23465		domStyle,
23466		window,
23467		baseWindow,
23468		baseFx,
23469		fx,
23470		_Widget,
23471		_TemplatedMixin,
23472		registry) {
23473
23474kernel.experimental("dojox.widget.Standby");
23475
23476return declare("dojox.widget.Standby", [_Widget, _TemplatedMixin],{
23477	// summary:
23478	//		A widget designed to act as a Standby/Busy/Disable/Blocking widget to indicate a
23479	//		particular DOM node is processing and cannot be clicked on at this time.
23480	//		This widget uses absolute positioning to apply the overlay and image.
23481
23482	// image: String
23483	//		A URL to an image to center within the blocking overlay.
23484	//		The default is a basic spinner.
23485	image: require.toUrl("dojox/widget/Standby/images/loading.gif").toString(),
23486
23487	// imageText: String
23488	//		Text to set on the ALT tag of the image.
23489	//		The default is 'Please wait...'
23490	imageText: "Please Wait...", // TODO: i18n
23491
23492	// text: String
23493	//		Text/HTML to display in the center of the overlay
23494	//		This is used if image center is disabled.
23495	//		Defaults to 'Please Wait...'
23496	text: "Please wait...",
23497
23498	// centerIndicator: String
23499	//		Property to define if the image and its alt text should be used, or
23500	//		a simple Text/HTML node should be used.  Allowable values are 'image'
23501	//		and 'text'.
23502	//		Default is 'image'.
23503	centerIndicator: "image",
23504	
23505	// target: DOMNode||DOMID(String)||WidgetID(String)
23506	//		The target to overlay when active.  Can be a widget id, a
23507	//		dom id, or a direct node reference.
23508	target: "",
23509
23510	// color:	String
23511	//		The color to set the overlay.  Should be in #XXXXXX form.
23512	//		Default color for the translucent overlay is light gray.
23513	color: "#C0C0C0",
23514
23515	// duration: Integer
23516	//		Integer defining how long the show and hide effects should take in milliseconds.
23517	//		Defaults to 500
23518	duration: 500,
23519	
23520	// zIndex: String
23521	//		Control that lets you specify if the zIndex for the overlay
23522	//		should be auto-computed based off parent zIndex, or should be set
23523	//		to a particular value.  This is useful when you want to overlay
23524	//		things in digit.Dialogs, you can specify a base zIndex to append from.
23525	zIndex: "auto",
23526	
23527	// opacity: float
23528	//		The opacity to make the overlay when it is displayed/faded in.
23529	//		The default is 0.75.  This does not affect the image opacity, only the
23530	//		overlay.
23531	opacity: 0.75,	
23532	
23533	// templateString: [protected] String
23534	//		The template string defining out the basics of the widget.  No need for an external
23535	//		file.
23536	templateString:
23537		"<div>" +
23538			"<div style=\"display: none; opacity: 0; z-index: 9999; " +
23539				"position: absolute; cursor:wait;\" dojoAttachPoint=\"_underlayNode\"></div>" +
23540			"<img src=\"${image}\" style=\"opacity: 0; display: none; z-index: -10000; " +
23541				"position: absolute; top: 0px; left: 0px; cursor:wait;\" "+
23542				"dojoAttachPoint=\"_imageNode\">" +
23543			"<div style=\"opacity: 0; display: none; z-index: -10000; position: absolute; " +
23544				"top: 0px;\" dojoAttachPoint=\"_textNode\"></div>" +
23545		"</div>",
23546
23547	// _underlayNode: [private] DOMNode
23548	//		The node that is the translucent underlay for the
23549	//		image that blocks access to the target.
23550	_underlayNode: null,
23551
23552	// _imageNode: [private] DOMNode
23553	//		The image node where we attach and define the image to display.
23554	_imageNode: null,
23555
23556	// _textNode: [private] DOMNode
23557	//		The div to attach text/HTML in the overlay center item.
23558	_textNode: null,
23559
23560	// _centerNode: [private] DOMNode
23561	//		Which node to use as the center node, the image or the text node.
23562	_centerNode: null,
23563
23564	// _displayed: [private] Boolean
23565	//		Flag to indicate if the overlay is displayed or not.
23566	_displayed: false,
23567
23568	// _resizeCheck: [private] Object
23569	//		Handle to interval function that checks the target for changes.
23570	_resizeCheck: null,
23571
23572	// _started: [private] Boolean
23573	//		Trap flag to ensure startup only processes once.
23574	_started: false,
23575
23576	// _parent: [private] DOMNode
23577	//		Wrapping div for the widget, also used for IE 7 in dealing with the
23578	//		zoom issue.
23579	_parent: null,
23580
23581	startup: function(args){
23582		// summary:
23583		//		Over-ride of the basic widget startup function.
23584		//		Configures the target node and sets the image to use.
23585		if(!this._started){
23586			if(typeof this.target === "string"){
23587				var w = registry.byId(this.target);
23588				this.target = w ? w.domNode : dom.byId(this.target);
23589			}
23590
23591			if(this.text){
23592				this._textNode.innerHTML = this.text;
23593			}
23594			if(this.centerIndicator === "image"){
23595				this._centerNode = this._imageNode;
23596				attr.set(this._imageNode, "src", this.image);
23597				attr.set(this._imageNode, "alt", this.imageText);
23598			}else{
23599				this._centerNode = this._textNode;
23600			}
23601			domStyle.set(this._underlayNode, {
23602				display: "none",
23603				backgroundColor: this.color
23604			});
23605			domStyle.set(this._centerNode, "display", "none");
23606			this.connect(this._underlayNode, "onclick", "_ignore");
23607
23608			//Last thing to do is move the widgets parent, if any, to the current document body.
23609			//Avoids having to deal with parent relative/absolute mess.  Otherwise positioning
23610			//tends to go goofy.
23611			if(this.domNode.parentNode && this.domNode.parentNode != baseWindow.body()){
23612				baseWindow.body().appendChild(this.domNode);
23613			}
23614
23615			//IE 7 has a horrible bug with zoom, so we have to create this node
23616			//to cross-check later.  Sigh.
23617			if(has("ie") == 7){
23618				this._ieFixNode = construct.create("div");
23619				domStyle.set(this._ieFixNode, {
23620					opacity: "0",
23621					zIndex: "-1000",
23622					position: "absolute",
23623					top: "-1000px"
23624				});
23625				baseWindow.body().appendChild(this._ieFixNode);
23626			}
23627			this.inherited(arguments);
23628		}		
23629	},
23630
23631	show: function(){
23632		// summary:
23633		//		Function to display the blocking overlay and busy/status icon or text.
23634		if(!this._displayed){
23635			if(this._anim){
23636				this._anim.stop();
23637				delete this._anim;
23638			}
23639			this._displayed = true;
23640			this._size();
23641			this._disableOverflow();
23642			this._fadeIn();
23643		}
23644	},
23645
23646	hide: function(){
23647		// summary:
23648		//		Function to hide the blocking overlay and status icon or text.
23649		if(this._displayed){
23650			if(this._anim){
23651				this._anim.stop();
23652				delete this._anim;
23653			}
23654			this._size();
23655			this._fadeOut();
23656			this._displayed = false;
23657			if(this._resizeCheck !== null){
23658				clearInterval(this._resizeCheck);
23659				this._resizeCheck = null;
23660			}
23661		}
23662	},
23663
23664	isVisible: function(){
23665		// summary:
23666		//		Helper function so you can test if the widget is already visible or not.
23667		// returns:
23668		//		boolean indicating if the widget is in 'show' state or not.
23669		return this._displayed; // boolean
23670	},
23671
23672	onShow: function(){
23673		// summary:
23674		//		Event that fires when the display of the Standby completes.
23675	},
23676
23677	onHide: function(){
23678		// summary:
23679		//		Event that fires when the display of the Standby completes.
23680	},
23681
23682	uninitialize: function(){
23683		// summary:
23684		//		Over-ride to hide the widget, which clears intervals, before cleanup.
23685		this._displayed = false;
23686		if(this._resizeCheck){
23687			clearInterval(this._resizeCheck);
23688		}
23689		domStyle.set(this._centerNode, "display", "none");
23690		domStyle.set(this._underlayNode, "display", "none");
23691		if(has("ie") == 7 && this._ieFixNode){
23692			baseWindow.body().removeChild(this._ieFixNode);
23693			delete this._ieFixNode;
23694		}
23695		if(this._anim){
23696			this._anim.stop();
23697			delete this._anim;
23698		}
23699		this.target = null;
23700		this._imageNode = null;
23701		this._textNode = null;
23702		this._centerNode = null;
23703		this.inherited(arguments);
23704	},
23705
23706	_size: function(){
23707		// summary:
23708		//		Internal function that handles resizing the overlay and
23709		//		centering of the image on window resizing.
23710		// tags:
23711		//		private
23712		if(this._displayed){
23713			var dir = attr.get(baseWindow.body(), "dir");
23714			if(dir){dir = dir.toLowerCase();}
23715			var _ie7zoom;
23716			var scrollers = this._scrollerWidths();
23717
23718			var target = this.target;
23719
23720			//Show the image and make sure the zIndex is set high.
23721			var curStyle = domStyle.get(this._centerNode, "display");
23722			domStyle.set(this._centerNode, "display", "block");
23723			var box = geometry.position(target, true);
23724			if(target === baseWindow.body() || target === baseWindow.doc){
23725				// Target is the whole doc, so scale to viewport.
23726				box = window.getBox();
23727				box.x = box.l;
23728				box.y = box.t;
23729			}
23730
23731			var cntrIndicator = geometry.getMarginBox(this._centerNode);
23732			domStyle.set(this._centerNode, "display", curStyle);
23733
23734			//IE has a horrible zoom bug.  So, we have to try and account for
23735			//it and fix up the scaling.
23736			if(this._ieFixNode){
23737				_ie7zoom = -this._ieFixNode.offsetTop / 1000;
23738				box.x = Math.floor((box.x + 0.9) / _ie7zoom);
23739				box.y = Math.floor((box.y + 0.9) / _ie7zoom);
23740				box.w = Math.floor((box.w + 0.9) / _ie7zoom);
23741				box.h = Math.floor((box.h + 0.9) / _ie7zoom);
23742			}
23743
23744			//Figure out how to zIndex this thing over the target.
23745			var zi = domStyle.get(target, "zIndex");
23746			var ziUl = zi;
23747			var ziIn = zi;
23748
23749			if(this.zIndex === "auto"){
23750				if(zi != "auto"){
23751					ziUl = parseInt(ziUl, 10) + 1;
23752					ziIn = parseInt(ziIn, 10) + 2;
23753				}else{
23754					//We need to search up the chain to see if there
23755					//are any parent zIndexs to overlay.
23756					var cNode = target;
23757					if(cNode && cNode !== baseWindow.body() && cNode !== baseWindow.doc){
23758						cNode = target.parentNode;
23759						var oldZi = -100000;
23760						while(cNode && cNode !== baseWindow.body()){
23761							zi = domStyle.get(cNode, "zIndex");
23762							if(!zi || zi === "auto"){
23763								cNode = cNode.parentNode;
23764							}else{
23765								var newZi = parseInt(zi, 10);
23766								if(oldZi < newZi){
23767									oldZi = newZi;
23768									ziUl = newZi + 1;
23769									ziIn = newZi + 2;
23770								}
23771								// Keep looking until we run out, we want the highest zIndex.
23772								cNode = cNode.parentNode;
23773							}
23774						}
23775					}
23776				}
23777			}else{
23778				ziUl = parseInt(this.zIndex, 10) + 1;
23779				ziIn = parseInt(this.zIndex, 10) + 2;
23780			}
23781
23782			domStyle.set(this._centerNode, "zIndex", ziIn);
23783			domStyle.set(this._underlayNode, "zIndex", ziUl);
23784
23785
23786			var pn = target.parentNode;
23787			if(pn && pn !== baseWindow.body() &&
23788				target !== baseWindow.body() &&
23789				target !== baseWindow.doc){
23790				
23791				// If the parent is the body tag itself,
23792				// we can avoid all this, the body takes
23793				// care of overflow for me.  Besides, browser
23794				// weirdness with height and width on body causes
23795				// problems with this sort of intersect testing
23796				// anyway.
23797				var obh = box.h;
23798				var obw = box.w;
23799				var pnBox = geometry.position(pn, true);
23800
23801				//More IE zoom corrections.  Grr.
23802				if(this._ieFixNode){
23803					_ie7zoom = -this._ieFixNode.offsetTop / 1000;
23804					pnBox.x = Math.floor((pnBox.x + 0.9) / _ie7zoom);
23805					pnBox.y = Math.floor((pnBox.y + 0.9) / _ie7zoom);
23806					pnBox.w = Math.floor((pnBox.w + 0.9) / _ie7zoom);
23807					pnBox.h = Math.floor((pnBox.h + 0.9) / _ie7zoom);
23808				}
23809				
23810				//Shift the parent width/height a bit if scollers are present.
23811				pnBox.w -= pn.scrollHeight > pn.clientHeight &&
23812					pn.clientHeight > 0 ? scrollers.v: 0;
23813				pnBox.h -= pn.scrollWidth > pn.clientWidth &&
23814					pn.clientWidth > 0 ? scrollers.h: 0;
23815
23816				//RTL requires a bit of massaging in some cases
23817				//(and differently depending on browser, ugh!)
23818				//WebKit and others still need work.
23819				if(dir === "rtl"){
23820					if(has("opera")){
23821						box.x += pn.scrollHeight > pn.clientHeight &&
23822							pn.clientHeight > 0 ? scrollers.v: 0;
23823						pnBox.x += pn.scrollHeight > pn.clientHeight &&
23824							pn.clientHeight > 0 ? scrollers.v: 0;
23825					}else if(has("ie")){
23826						pnBox.x += pn.scrollHeight > pn.clientHeight &&
23827							pn.clientHeight > 0 ? scrollers.v: 0;
23828					}else if(has("webkit")){
23829						//TODO:  FIX THIS!
23830					}
23831				}
23832
23833				//Figure out if we need to adjust the overlay to fit a viewable
23834				//area, then resize it, we saved the original height/width above.
23835				//This is causing issues on IE.  Argh!
23836				if(pnBox.w < box.w){
23837					//Scale down the width if necessary.
23838					box.w = box.w - pnBox.w;
23839				}
23840				if(pnBox.h < box.h){
23841					//Scale down the width if necessary.
23842					box.h = box.h - pnBox.h;
23843				}
23844
23845				//Look at the y positions and see if we intersect with the
23846				//viewport borders.  Will have to do computations off it.
23847				var vpTop = pnBox.y;
23848				var vpBottom = pnBox.y + pnBox.h;
23849				var bTop = box.y;
23850				var bBottom = box.y + obh;
23851				var vpLeft = pnBox.x;
23852				var vpRight = pnBox.x + pnBox.w;
23853				var bLeft = box.x;
23854				var bRight = box.x + obw;
23855				var delta;
23856				//Adjust the height now
23857				if(bBottom > vpTop &&
23858					bTop < vpTop){
23859					box.y = pnBox.y;
23860					//intersecting top, need to do some shifting.
23861					delta = vpTop - bTop;
23862					var visHeight = obh - delta;
23863					//If the visible height < viewport height,
23864					//We need to shift it.
23865					if(visHeight < pnBox.h){
23866						box.h = visHeight;
23867					}else{
23868						//Deal with horizontal scrollbars if necessary.
23869						box.h -= 2*(pn.scrollWidth > pn.clientWidth &&
23870							pn.clientWidth > 0? scrollers.h: 0);
23871					}
23872				}else if(bTop < vpBottom && bBottom > vpBottom){
23873					//Intersecting bottom, just figure out how much
23874					//overlay to show.
23875					box.h = vpBottom - bTop;
23876				}else if(bBottom <= vpTop || bTop >= vpBottom){
23877					//Outside view, hide it.
23878					box.h = 0;
23879				}
23880
23881				//adjust width
23882				if(bRight > vpLeft && bLeft < vpLeft){
23883					box.x = pnBox.x;
23884					//intersecting left, need to do some shifting.
23885					delta = vpLeft - bLeft;
23886					var visWidth = obw - delta;
23887					//If the visible width < viewport width,
23888					//We need to shift it.
23889					if(visWidth < pnBox.w){
23890						box.w = visWidth;
23891					}else{
23892						//Deal with horizontal scrollbars if necessary.
23893						box.w -= 2*(pn.scrollHeight > pn.clientHeight &&
23894							pn.clientHeight > 0? scrollers.w:0);
23895					}
23896				}else if(bLeft < vpRight && bRight > vpRight){
23897					//Intersecting right, just figure out how much
23898					//overlay to show.
23899					box.w = vpRight - bLeft;
23900				}else if(bRight <= vpLeft || bLeft >= vpRight){
23901					//Outside view, hide it.
23902					box.w = 0;
23903				}
23904			}
23905
23906			if(box.h > 0 && box.w > 0){
23907				//Set position and size of the blocking div overlay.
23908				domStyle.set(this._underlayNode, {
23909					display: "block",
23910					width: box.w + "px",
23911					height: box.h + "px",
23912					top: box.y + "px",
23913					left: box.x + "px"
23914				});
23915
23916				var styles = ["borderRadius", "borderTopLeftRadius",
23917					"borderTopRightRadius","borderBottomLeftRadius",
23918					"borderBottomRightRadius"];
23919				this._cloneStyles(styles);
23920				if(!has("ie")){
23921					//Browser specific styles to try and clone if non-IE.
23922					styles = ["MozBorderRadius", "MozBorderRadiusTopleft",
23923						"MozBorderRadiusTopright","MozBorderRadiusBottomleft",
23924						"MozBorderRadiusBottomright","WebkitBorderRadius",
23925						"WebkitBorderTopLeftRadius", "WebkitBorderTopRightRadius",
23926						"WebkitBorderBottomLeftRadius","WebkitBorderBottomRightRadius"
23927					];
23928					this._cloneStyles(styles, this);
23929				}
23930				var cntrIndicatorTop = (box.h/2) - (cntrIndicator.h/2);
23931				var cntrIndicatorLeft = (box.w/2) - (cntrIndicator.w/2);
23932				//Only show the image if there is height and width room.
23933				if(box.h >= cntrIndicator.h && box.w >= cntrIndicator.w){
23934					domStyle.set(this._centerNode, {
23935						top: (cntrIndicatorTop + box.y) + "px",
23936						left: (cntrIndicatorLeft + box.x) + "px",
23937						display: "block"
23938					});
23939				}else{
23940					domStyle.set(this._centerNode, "display", "none");
23941				}
23942			}else{
23943				//Target has no size, display nothing on it!
23944				domStyle.set(this._underlayNode, "display", "none");
23945				domStyle.set(this._centerNode, "display", "none");
23946			}
23947			if(this._resizeCheck === null){
23948				//Set an interval timer that checks the target size and scales as needed.
23949				//Checking every 10th of a second seems to generate a fairly smooth update.
23950				var self = this;
23951				this._resizeCheck = setInterval(function(){self._size();}, 100);
23952			}
23953		}
23954	},
23955
23956	_cloneStyles: function(list){
23957		// summary:
23958		//		Internal function to clone a set of styles from the target to
23959		//		the underlay.
23960		// list: Array
23961		//		An array of style names to clone.
23962		//
23963		// tags:
23964		//		private
23965		array.forEach(list, function(s){
23966			domStyle.set(this._underlayNode, s, domStyle.get(this.target, s));
23967		}, this);
23968	},
23969
23970	_fadeIn: function(){
23971		// summary:
23972		//		Internal function that does the opacity style fade in animation.
23973		// tags:
23974		//		private
23975		var self = this;
23976		var underlayNodeAnim = baseFx.animateProperty({
23977			duration: self.duration,
23978			node: self._underlayNode,
23979			properties: {opacity: {start: 0, end: self.opacity}}
23980		});
23981		var imageAnim = baseFx.animateProperty({
23982			duration: self.duration,
23983			node: self._centerNode,
23984			properties: {opacity: {start: 0, end: 1}},
23985			onEnd: function(){
23986				self.onShow();
23987				delete self._anim;
23988			}
23989		});
23990		this._anim = fx.combine([underlayNodeAnim,imageAnim]);
23991		this._anim.play();
23992	},
23993
23994	_fadeOut: function(){
23995		// summary:
23996		//		Internal function that does the opacity style fade out animation.
23997		// tags:
23998		//		private
23999		var self = this;
24000		var underlayNodeAnim = baseFx.animateProperty({
24001			duration: self.duration,
24002			node: self._underlayNode,
24003			properties: {opacity: {start: self.opacity, end: 0}},
24004			onEnd: function(){
24005				domStyle.set(this.node,{"display":"none", "zIndex": "-1000"});
24006			}
24007		});
24008		var imageAnim = baseFx.animateProperty({
24009			duration: self.duration,
24010			node: self._centerNode,
24011			properties: {opacity: {start: 1, end: 0}},
24012			onEnd: function(){
24013				domStyle.set(this.node,{"display":"none", "zIndex": "-1000"});
24014				self.onHide();
24015				self._enableOverflow();
24016				delete self._anim;
24017			}
24018		});
24019		this._anim = fx.combine([underlayNodeAnim,imageAnim]);
24020		this._anim.play();
24021	},
24022
24023	_ignore: function(e){
24024		// summary:
24025		//		Function to ignore events that occur on the overlay.
24026		// event: Event
24027		//		The event to halt
24028		// tags:
24029		//		private
24030		if(e){
24031			event.stop(e);
24032		}
24033	},
24034
24035	_scrollerWidths: function(){
24036		// summary:
24037		//		This function will calculate the size of the vertical and
24038		//		horizontaol scrollbars.
24039		// returns:
24040		//		Object of form: {v: Number, h: Number} where v is vertical scrollbar width
24041		//		and h is horizontal scrollbar width.
24042		// tags:
24043		//		private
24044		var div = construct.create("div");
24045		domStyle.set(div, {
24046			position: "absolute",
24047			opacity: 0,
24048			overflow: "hidden",
24049			width: "50px",
24050			height: "50px",
24051			zIndex: "-100",
24052			top: "-200px",
24053			padding: "0px",
24054			margin: "0px"
24055		});
24056		var iDiv = construct.create("div");
24057		domStyle.set(iDiv, {
24058			width: "200px",
24059			height: "10px"
24060		});
24061		div.appendChild(iDiv);
24062		baseWindow.body().appendChild(div);
24063
24064		//Figure out content size before and after
24065		//scrollbars are there, then just subtract to
24066		//get width.
24067		var b = geometry.getContentBox(div);
24068		domStyle.set(div, "overflow", "scroll");
24069		var a = geometry.getContentBox(div);
24070		baseWindow.body().removeChild(div);
24071		return { v: b.w - a.w, h: b.h - a.h };
24072	},
24073
24074	/* The following are functions that tie into _Widget.attr() */
24075
24076	_setTextAttr: function(text){
24077		// summary:
24078		//		Function to allow widget.attr to set the text displayed in center
24079		//		if using text display.
24080		// text: String
24081		//		The text to set.
24082		this._textNode.innerHTML = text;
24083		this.text = text;
24084	},
24085
24086	_setColorAttr: function(c){
24087		// summary:
24088		//		Function to allow widget.attr to set the color used for the translucent
24089		//		div overlay.
24090		// c: String
24091		//		The color to set the background underlay to in #XXXXXX format..
24092		domStyle.set(this._underlayNode, "backgroundColor", c);
24093		this.color = c;
24094	},
24095
24096	_setImageTextAttr: function(text){
24097		// summary:
24098		//		Function to allow widget.attr to set the ALT text text displayed for
24099		//		the image (if using image center display).
24100		// text: String
24101		//		The text to set.
24102		attr.set(this._imageNode, "alt", text);
24103		this.imageText = text;
24104	},
24105
24106	_setImageAttr: function(url){
24107		// summary:
24108		//		Function to allow widget.attr to set the url source for the center image
24109		// text: String
24110		//		The url to set for the image.
24111		attr.set(this._imageNode, "src", url);
24112		this.image = url;
24113	},
24114
24115	_setCenterIndicatorAttr: function(indicator){
24116		// summary:
24117		//		Function to allow widget.attr to set the node used for the center indicator,
24118		//		either the image or the text.
24119		// indicator: String
24120		//		The indicator to use, either 'image' or 'text'.
24121		this.centerIndicator = indicator;
24122		if(indicator === "image"){
24123			this._centerNode = this._imageNode;
24124			domStyle.set(this._textNode, "display", "none");
24125		}else{
24126			this._centerNode = this._textNode;
24127			domStyle.set(this._imageNode, "display", "none");
24128		}
24129	},
24130
24131	_disableOverflow: function(){
24132		 // summary:
24133		 //		Function to disable scrollbars on the body.  Only used if the overlay
24134		 //		targets the body or the document.
24135		 if(this.target === baseWindow.body() || this.target === baseWindow.doc){
24136			 // Store the overflow state we have to restore later.
24137			 // IE had issues, so have to check that it's defined.  Ugh.
24138			 this._overflowDisabled = true;
24139			 var body = baseWindow.body();
24140			 if(body.style && body.style.overflow){
24141				 this._oldOverflow = domStyle.get(body, "overflow");
24142			 }else{
24143				 this._oldOverflow = "";
24144			 }
24145			 if(has("ie") && !has("quirks")){
24146				 // IE will put scrollbars in anyway, html (parent of body)
24147				 // also controls them in standards mode, so we have to
24148				 // remove them, argh.
24149				 if(body.parentNode &&
24150					body.parentNode.style &&
24151					body.parentNode.style.overflow){
24152					 this._oldBodyParentOverflow = body.parentNode.style.overflow;
24153				 }else{
24154					 try{
24155						this._oldBodyParentOverflow = domStyle.get(body.parentNode, "overflow");
24156					 }catch(e){
24157						 this._oldBodyParentOverflow = "scroll";
24158					 }
24159				 }
24160				 domStyle.set(body.parentNode, "overflow", "hidden");
24161			 }
24162			 domStyle.set(body, "overflow", "hidden");
24163		 }
24164	},
24165
24166	_enableOverflow: function(){
24167		 // summary:
24168		 //		Function to restore scrollbars on the body.  Only used if the overlay
24169		 //		targets the body or the document.
24170		 if(this._overflowDisabled){
24171			delete this._overflowDisabled;
24172			var body = baseWindow.body();
24173			// Restore all the overflow.
vendor: 7,208 bytes, lines 24174-24355
24174			if(has("ie") && !has("quirks")){
24175				body.parentNode.style.overflow = this._oldBodyParentOverflow;
24176				delete this._oldBodyParentOverflow;
24177			}
24178			domStyle.set(body, "overflow", this._oldOverflow);
24179			if(has("webkit")){
24180				//Gotta poke WebKit, or scrollers don't come back. :-(
24181				var div = construct.create("div", { style: {
24182						height: "2px"
24183					}
24184				});
24185				body.appendChild(div);
24186				setTimeout(function(){
24187					body.removeChild(div);
24188				}, 0);
24189			}
24190			delete this._oldOverflow;
24191		}
24192	}
24193});
24194
24195});
24196
24197},
24198'dojo/window':function(){
24199define(["./_base/lang", "./sniff", "./_base/window", "./dom", "./dom-geometry", "./dom-style", "./dom-construct"],
24200	function(lang, has, baseWindow, dom, geom, style, domConstruct){
24201
24202	// feature detection
24203	/* not needed but included here for future reference
24204	has.add("rtl-innerVerticalScrollBar-on-left", function(win, doc){
24205		var	body = baseWindow.body(doc),
24206			scrollable = domConstruct.create('div', {
24207				style: {overflow:'scroll', overflowX:'hidden', direction:'rtl', visibility:'hidden', position:'absolute', left:'0', width:'64px', height:'64px'}
24208			}, body, "last"),
24209			center = domConstruct.create('center', {
24210				style: {overflow:'hidden', direction:'ltr'}
24211			}, scrollable, "last"),
24212			inner = domConstruct.create('div', {
24213				style: {overflow:'visible', display:'inline' }
24214			}, center, "last");
24215		inner.innerHTML="&nbsp;";
24216		var midPoint = Math.max(inner.offsetLeft, geom.position(inner).x);
24217		var ret = midPoint >= 32;
24218		center.removeChild(inner);
24219		scrollable.removeChild(center);
24220		body.removeChild(scrollable);
24221		return ret;
24222	});
24223	*/
24224	has.add("rtl-adjust-position-for-verticalScrollBar", function(win, doc){
24225		var	body = baseWindow.body(doc),
24226			scrollable = domConstruct.create('div', {
24227				style: {overflow:'scroll', overflowX:'visible', direction:'rtl', visibility:'hidden', position:'absolute', left:'0', top:'0', width:'64px', height:'64px'}
24228			}, body, "last"),
24229			div = domConstruct.create('div', {
24230				style: {overflow:'hidden', direction:'ltr'}
24231			}, scrollable, "last"),
24232			ret = geom.position(div).x != 0;
24233		scrollable.removeChild(div);
24234		body.removeChild(scrollable);
24235		return ret;
24236	});
24237
24238	has.add("position-fixed-support", function(win, doc){
24239		// IE6, IE7+quirks, and some older mobile browsers don't support position:fixed
24240		var	body = baseWindow.body(doc),
24241			outer = domConstruct.create('span', {
24242				style: {visibility:'hidden', position:'fixed', left:'1px', top:'1px'}
24243			}, body, "last"),
24244			inner = domConstruct.create('span', {
24245				style: {position:'fixed', left:'0', top:'0'}
24246			}, outer, "last"),
24247			ret = geom.position(inner).x != geom.position(outer).x;
24248		outer.removeChild(inner);
24249		body.removeChild(outer);
24250		return ret;
24251	});
24252
24253	// module:
24254	//		dojo/window
24255
24256	var window = {
24257		// summary:
24258		//		TODOC
24259
24260		getBox: function(/*Document?*/ doc){
24261			// summary:
24262			//		Returns the dimensions and scroll position of the viewable area of a browser window
24263
24264			doc = doc || baseWindow.doc;
24265
24266			var
24267				scrollRoot = (doc.compatMode == 'BackCompat') ? baseWindow.body(doc) : doc.documentElement,
24268				// get scroll position
24269				scroll = geom.docScroll(doc), // scrollRoot.scrollTop/Left should work
24270				w, h;
24271
24272			if(has("touch")){ // if(scrollbars not supported)
24273				var uiWindow = window.get(doc);   // use UI window, not dojo.global window
24274				// on mobile, scrollRoot.clientHeight <= uiWindow.innerHeight <= scrollRoot.offsetHeight, return uiWindow.innerHeight
24275				w = uiWindow.innerWidth || scrollRoot.clientWidth; // || scrollRoot.clientXXX probably never evaluated
24276				h = uiWindow.innerHeight || scrollRoot.clientHeight;
24277			}else{
24278				// on desktops, scrollRoot.clientHeight <= scrollRoot.offsetHeight <= uiWindow.innerHeight, return scrollRoot.clientHeight
24279				// uiWindow.innerWidth/Height includes the scrollbar and cannot be used
24280				w = scrollRoot.clientWidth;
24281				h = scrollRoot.clientHeight;
24282			}
24283			return {
24284				l: scroll.x,
24285				t: scroll.y,
24286				w: w,
24287				h: h
24288			};
24289		},
24290
24291		get: function(/*Document*/ doc){
24292			// summary:
24293			//		Get window object associated with document doc.
24294			// doc:
24295			//		The document to get the associated window for.
24296
24297			// In some IE versions (at least 6.0), document.parentWindow does not return a
24298			// reference to the real window object (maybe a copy), so we must fix it as well
24299			// We use IE specific execScript to attach the real window reference to
24300			// document._parentWindow for later use
24301			if(has("ie") && window !== document.parentWindow){
24302				/*
24303				In IE 6, only the variable "window" can be used to connect events (others
24304				may be only copies).
24305				*/
24306				doc.parentWindow.execScript("document._parentWindow = window;", "Javascript");
24307				//to prevent memory leak, unset it after use
24308				//another possibility is to add an onUnload handler which seems overkill to me (liucougar)
24309				var win = doc._parentWindow;
24310				doc._parentWindow = null;
24311				return win;	//	Window
24312			}
24313
24314			return doc.parentWindow || doc.defaultView;	//	Window
24315		},
24316
24317		scrollIntoView: function(/*DomNode*/ node, /*Object?*/ pos){
24318			// summary:
24319			//		Scroll the passed node into view using minimal movement, if it is not already.
24320
24321			// Don't rely on node.scrollIntoView working just because the function is there since
24322			// it forces the node to the page's bottom or top (and left or right in IE) without consideration for the minimal movement.
24323			// WebKit's node.scrollIntoViewIfNeeded doesn't work either for inner scrollbars in right-to-left mode
24324			// and when there's a fixed position scrollable element
24325
24326			try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method
24327				node = dom.byId(node);
24328				var	doc = node.ownerDocument || baseWindow.doc,	// TODO: why baseWindow.doc?  Isn't node.ownerDocument always defined?
24329					body = baseWindow.body(doc),
24330					html = doc.documentElement || body.parentNode,
24331					isIE = has("ie"),
24332					isWK = has("webkit");
24333				// if an untested browser, then use the native method
24334				if(node == body || node == html){ return; }
24335				if(!(has("mozilla") || isIE || isWK || has("opera") || has("trident")) && ("scrollIntoView" in node)){
24336					node.scrollIntoView(false); // short-circuit to native if possible
24337					return;
24338				}
24339				var	backCompat = doc.compatMode == 'BackCompat',
24340					rootWidth = Math.min(body.clientWidth || html.clientWidth, html.clientWidth || body.clientWidth),
24341					rootHeight = Math.min(body.clientHeight || html.clientHeight, html.clientHeight || body.clientHeight),
24342					scrollRoot = (isWK || backCompat) ? body : html,
24343					nodePos = pos || geom.position(node),
24344					el = node.parentNode,
24345					isFixed = function(el){
24346						return (isIE <= 6 || (isIE == 7 && backCompat))
24347							? false
24348							: (has("position-fixed-support") && (style.get(el, 'position').toLowerCase() == "fixed"));
24349					},
24350					self = this,
24351					scrollElementBy = function(el, x, y){
24352						if(el.tagName == "BODY" || el.tagName == "HTML"){
24353							self.get(el.ownerDocument).scrollBy(x, y);
24354						}else{
24355							x && (el.scrollLeft += x);
24356							y && (el.scrollTop += y);
24357						}
24358					};
24359				if(isFixed(node)){ return; } // nothing to do
24360				while(el){
24361					if(el == body){ el = scrollRoot; }
24362					var	elPos = geom.position(el),
24363						fixedPos = isFixed(el),
24364						rtl = style.getComputedStyle(el).direction.toLowerCase() == "rtl";
24365
24366					if(el == scrollRoot){
24367						elPos.w = rootWidth; elPos.h = rootHeight;
24368						if(scrollRoot == html && (isIE || has("trident")) && rtl){ elPos.x += scrollRoot.offsetWidth-elPos.w; } // IE workaround where scrollbar causes negative x
24369						if(elPos.x < 0 || !isIE || isIE >= 9 || has("trident")){ elPos.x = 0; } // older IE can have values > 0
24370						if(elPos.y < 0 || !isIE || isIE >= 9 || has("trident")){ elPos.y = 0; }
24371					}else{
24372						var pb = geom.getPadBorderExtents(el);
24373						elPos.w -= pb.w; elPos.h -= pb.h; elPos.x += pb.l; elPos.y += pb.t;
24374						var clientSize = el.clientWidth,
24375							scrollBarSize = elPos.w - clientSize;
24376						if(clientSize > 0 && scrollBarSize > 0){
24377							if(rtl && has("rtl-adjust-position-for-verticalScrollBar")){
24378								elPos.x += scrollBarSize;
24379							}
24380							elPos.w = clientSize;
24381						}
24382						clientSize = el.clientHeight;
24383						scrollBarSize = elPos.h - clientSize;
24384						if(clientSize > 0 && scrollBarSize > 0){
24385							elPos.h = clientSize;
24386						}
24387					}
24388					if(fixedPos){ // bounded by viewport, not parents
24389						if(elPos.y < 0){
24390							elPos.h += elPos.y; elPos.y = 0;
24391						}
24392						if(elPos.x < 0){
24393							elPos.w += elPos.x; elPos.x = 0;
24394						}
24395						if(elPos.y + elPos.h > rootHeight){
24396							elPos.h = rootHeight - elPos.y;
24397						}
24398						if(elPos.x + elPos.w > rootWidth){
24399							elPos.w = rootWidth - elPos.x;
24400						}
24401					}
24402					// calculate overflow in all 4 directions
24403					var	l = nodePos.x - elPos.x, // beyond left: < 0
24404//						t = nodePos.y - Math.max(elPos.y, 0), // beyond top: < 0
24405						t = nodePos.y - elPos.y, // beyond top: < 0
24406						r = l + nodePos.w - elPos.w, // beyond right: > 0
24407						bot = t + nodePos.h - elPos.h; // beyond bottom: > 0
24408					var s, old;
24409					if(r * l > 0 && (!!el.scrollLeft || el == scrollRoot || el.scrollWidth > el.offsetHeight)){
24410						s = Math[l < 0? "max" : "min"](l, r);
24411						if(rtl && ((isIE == 8 && !backCompat) || isIE >= 9 || has("trident"))){ s = -s; }
24412						old = el.scrollLeft;
24413						scrollElementBy(el, s, 0);
24414						s = el.scrollLeft - old;
24415						nodePos.x -= s;
24416					}
24417					if(bot * t > 0 && (!!el.scrollTop || el == scrollRoot || el.scrollHeight > el.offsetHeight)){
24418						s = Math.ceil(Math[t < 0? "max" : "min"](t, bot));
24419						old = el.scrollTop;
24420						scrollElementBy(el, 0, s);
24421						s = el.scrollTop - old;
24422						nodePos.y -= s;
24423					}
24424					el = (el != scrollRoot) && !fixedPos && el.parentNode;
24425				}
24426			}catch(error){
24427				console.error('scrollIntoView: ' + error);
24428				node.scrollIntoView(false);
24429			}
24430		}
24431	};
24432
24433	 1  && lang.setObject("dojo.window", window);
24434
24435	return window;
24436});
24437
24438},
24439'dojo/fx':function(){
24440define([
24441	"./_base/lang",
24442	"./Evented",
24443	"./_base/kernel",
24444	"./_base/array",
24445	"./aspect",
24446	"./_base/fx",
24447	"./dom",
24448	"./dom-style",
24449	"./dom-geometry",
24450	"./ready",
24451	"require" // for context sensitive loading of Toggler
24452], function(lang, Evented, dojo, arrayUtil, aspect, baseFx, dom, domStyle, geom, ready, require){
24453
24454	// module:
24455	//		dojo/fx
24456	
24457	// For back-compat, remove in 2.0.
24458	if(!dojo.isAsync){
24459		ready(0, function(){
24460			var requires = ["./fx/Toggler"];
24461			require(requires);	// use indirection so modules not rolled into a build
24462		});
24463	}
24464
24465	var coreFx = dojo.fx = {
24466		// summary:
24467		//		Effects library on top of Base animations
24468	};
24469
24470	var _baseObj = {
24471			_fire: function(evt, args){
24472				if(this[evt]){
24473					this[evt].apply(this, args||[]);
24474				}
24475				return this;
24476			}
24477		};
24478
24479	var _chain = function(animations){
24480		this._index = -1;
24481		this._animations = animations||[];
24482		this._current = this._onAnimateCtx = this._onEndCtx = null;
24483
24484		this.duration = 0;
24485		arrayUtil.forEach(this._animations, function(a){
24486			this.duration += a.duration;
24487			if(a.delay){ this.duration += a.delay; }
24488		}, this);
24489	};
24490	_chain.prototype = new Evented();
24491	lang.extend(_chain, {
24492		_onAnimate: function(){
24493			this._fire("onAnimate", arguments);
24494		},
24495		_onEnd: function(){
24496			this._onAnimateCtx.remove();
24497			this._onEndCtx.remove();
24498			this._onAnimateCtx = this._onEndCtx = null;
24499			if(this._index + 1 == this._animations.length){
24500				this._fire("onEnd");
24501			}else{
24502				// switch animations
24503				this._current = this._animations[++this._index];
24504				this._onAnimateCtx = aspect.after(this._current, "onAnimate", lang.hitch(this, "_onAnimate"), true);
24505				this._onEndCtx = aspect.after(this._current, "onEnd", lang.hitch(this, "_onEnd"), true);
24506				this._current.play(0, true);
24507			}
24508		},
24509		play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
24510			if(!this._current){ this._current = this._animations[this._index = 0]; }
24511			if(!gotoStart && this._current.status() == "playing"){ return this; }
24512			var beforeBegin = aspect.after(this._current, "beforeBegin", lang.hitch(this, function(){
24513					this._fire("beforeBegin");
24514				}), true),
24515				onBegin = aspect.after(this._current, "onBegin", lang.hitch(this, function(arg){
24516					this._fire("onBegin", arguments);
24517				}), true),
24518				onPlay = aspect.after(this._current, "onPlay", lang.hitch(this, function(arg){
24519					this._fire("onPlay", arguments);
24520					beforeBegin.remove();
24521					onBegin.remove();
24522					onPlay.remove();
24523				}));
24524			if(this._onAnimateCtx){
24525				this._onAnimateCtx.remove();
24526			}
24527			this._onAnimateCtx = aspect.after(this._current, "onAnimate", lang.hitch(this, "_onAnimate"), true);
24528			if(this._onEndCtx){
24529				this._onEndCtx.remove();
24530			}
24531			this._onEndCtx = aspect.after(this._current, "onEnd", lang.hitch(this, "_onEnd"), true);
24532			this._current.play.apply(this._current, arguments);
24533			return this;
24534		},
24535		pause: function(){
24536			if(this._current){
24537				var e = aspect.after(this._current, "onPause", lang.hitch(this, function(arg){
24538						this._fire("onPause", arguments);
24539						e.remove();
24540					}), true);
24541				this._current.pause();
24542			}
24543			return this;
24544		},
24545		gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){
24546			this.pause();
24547			var offset = this.duration * percent;
24548			this._current = null;
24549
24550			arrayUtil.some(this._animations, function(a, index){
24551				if(offset <= a.duration){
24552					this._current = a;
24553					this._index = index;
24554					return true;
24555				}
24556				offset -= a.duration;
24557				return false;
24558			}, this);
24559			if(this._current){
24560				this._current.gotoPercent(offset / this._current.duration);
24561			}
24562			if (andPlay) { this.play(); }
24563			return this;
24564		},
24565		stop: function(/*boolean?*/ gotoEnd){
24566			if(this._current){
24567				if(gotoEnd){
24568					for(; this._index + 1 < this._animations.length; ++this._index){
24569						this._animations[this._index].stop(true);
24570					}
24571					this._current = this._animations[this._index];
24572				}
24573				var e = aspect.after(this._current, "onStop", lang.hitch(this, function(arg){
24574						this._fire("onStop", arguments);
24575						e.remove();
24576					}), true);
24577				this._current.stop();
24578			}
24579			return this;
24580		},
24581		status: function(){
24582			return this._current ? this._current.status() : "stopped";
24583		},
24584		destroy: function(){
24585			this.stop();
24586			if(this._onAnimateCtx){ this._onAnimateCtx.remove(); }
24587			if(this._onEndCtx){ this._onEndCtx.remove(); }
24588		}
24589	});
24590	lang.extend(_chain, _baseObj);
24591
24592	coreFx.chain = function(/*dojo/_base/fx.Animation[]*/ animations){
24593		// summary:
24594		//		Chain a list of `dojo/_base/fx.Animation`s to run in sequence
24595		//
24596		// description:
24597		//		Return a `dojo/_base/fx.Animation` which will play all passed
24598		//		`dojo/_base/fx.Animation` instances in sequence, firing its own
24599		//		synthesized events simulating a single animation. (eg:
24600		//		onEnd of this animation means the end of the chain,
24601		//		not the individual animations within)
24602		//
24603		// example:
24604		//	Once `node` is faded out, fade in `otherNode`
24605		//	|	require(["dojo/fx"], function(fx){
24606		//	|		fx.chain([
24607		//	|			fx.fadeIn({ node:node }),
vendor: 2,906 bytes, lines 24608-24703
24608		//	|			fx.fadeOut({ node:otherNode })
24609		//	|		]).play();
24610		//	|	});
24611		//
24612		return new _chain(animations); // dojo/_base/fx.Animation
24613	};
24614
24615	var _combine = function(animations){
24616		this._animations = animations||[];
24617		this._connects = [];
24618		this._finished = 0;
24619
24620		this.duration = 0;
24621		arrayUtil.forEach(animations, function(a){
24622			var duration = a.duration;
24623			if(a.delay){ duration += a.delay; }
24624			if(this.duration < duration){ this.duration = duration; }
24625			this._connects.push(aspect.after(a, "onEnd", lang.hitch(this, "_onEnd"), true));
24626		}, this);
24627
24628		this._pseudoAnimation = new baseFx.Animation({curve: [0, 1], duration: this.duration});
24629		var self = this;
24630		arrayUtil.forEach(["beforeBegin", "onBegin", "onPlay", "onAnimate", "onPause", "onStop", "onEnd"],
24631			function(evt){
24632				self._connects.push(aspect.after(self._pseudoAnimation, evt,
24633					function(){ self._fire(evt, arguments); },
24634				true));
24635			}
24636		);
24637	};
24638	lang.extend(_combine, {
24639		_doAction: function(action, args){
24640			arrayUtil.forEach(this._animations, function(a){
24641				a[action].apply(a, args);
24642			});
24643			return this;
24644		},
24645		_onEnd: function(){
24646			if(++this._finished > this._animations.length){
24647				this._fire("onEnd");
24648			}
24649		},
24650		_call: function(action, args){
24651			var t = this._pseudoAnimation;
24652			t[action].apply(t, args);
24653		},
24654		play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
24655			this._finished = 0;
24656			this._doAction("play", arguments);
24657			this._call("play", arguments);
24658			return this;
24659		},
24660		pause: function(){
24661			this._doAction("pause", arguments);
24662			this._call("pause", arguments);
24663			return this;
24664		},
24665		gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){
24666			var ms = this.duration * percent;
24667			arrayUtil.forEach(this._animations, function(a){
24668				a.gotoPercent(a.duration < ms ? 1 : (ms / a.duration), andPlay);
24669			});
24670			this._call("gotoPercent", arguments);
24671			return this;
24672		},
24673		stop: function(/*boolean?*/ gotoEnd){
24674			this._doAction("stop", arguments);
24675			this._call("stop", arguments);
24676			return this;
24677		},
24678		status: function(){
24679			return this._pseudoAnimation.status();
24680		},
24681		destroy: function(){
24682			this.stop();
24683			arrayUtil.forEach(this._connects, function(handle){
24684				handle.remove();
24685			});
24686		}
24687	});
24688	lang.extend(_combine, _baseObj);
24689
24690	coreFx.combine = function(/*dojo/_base/fx.Animation[]*/ animations){
24691		// summary:
24692		//		Combine a list of `dojo/_base/fx.Animation`s to run in parallel
24693		//
24694		// description:
24695		//		Combine an array of `dojo/_base/fx.Animation`s to run in parallel,
24696		//		providing a new `dojo/_base/fx.Animation` instance encompasing each
24697		//		animation, firing standard animation events.
24698		//
24699		// example:
24700		//	Fade out `node` while fading in `otherNode` simultaneously
24701		//	|	require(["dojo/fx"], function(fx){
24702		//	|		fx.combine([
24703		//	|			fx.fadeIn({ node:node }),
24704		//	|			fx.fadeOut({ node:otherNode })
24705		//	|		]).play();
24706		//	|	});
24707		//
24708		// example:
24709		//	When the longest animation ends, execute a function:
24710		//	|	require(["dojo/fx"], function(fx){
24711		//	|		var anim = fx.combine([
24712		//	|			fx.fadeIn({ node: n, duration:700 }),
24713		//	|			fx.fadeOut({ node: otherNode, duration: 300 })
24714		//	|		]);
24715		//	|		aspect.after(anim, "onEnd", function(){
24716		//	|			// overall animation is done.
24717		//	|		}, true);
24718		//	|		anim.play(); // play the animation
24719		//	|	});
24720		//
24721		return new _combine(animations); // dojo/_base/fx.Animation
24722	};
24723
24724	coreFx.wipeIn = function(/*Object*/ args){
24725		// summary:
24726		//		Expand a node to it's natural height.
24727		//
24728		// description:
24729		//		Returns an animation that will expand the
24730		//		node defined in 'args' object from it's current height to
24731		//		it's natural height (with no scrollbar).
24732		//		Node must have no margin/border/padding.
24733		//
24734		// args: Object
24735		//		A hash-map of standard `dojo/_base/fx.Animation` constructor properties
24736		//		(such as easing: node: duration: and so on)
24737		//
24738		// example:
24739		//	|	require(["dojo/fx"], function(fx){
24740		//	|		fx.wipeIn({
24741		//	|			node:"someId"
24742		//	|		}).play()
24743		//	|	});
24744
24745		var node = args.node = dom.byId(args.node), s = node.style, o;
24746
24747		var anim = baseFx.animateProperty(lang.mixin({
24748			properties: {
24749				height: {
24750					// wrapped in functions so we wait till the last second to query (in case value has changed)
24751					start: function(){
24752						// start at current [computed] height, but use 1px rather than 0
24753						// because 0 causes IE to display the whole panel
24754						o = s.overflow;
24755						s.overflow = "hidden";
24756						if(s.visibility == "hidden" || s.display == "none"){
24757							s.height = "1px";
24758							s.display = "";
24759							s.visibility = "";
24760							return 1;
24761						}else{
24762							var height = domStyle.get(node, "height");
24763							return Math.max(height, 1);
24764						}
24765					},
24766					end: function(){
24767						return node.scrollHeight;
24768					}
24769				}
24770			}
24771		}, args));
24772
24773		var fini = function(){
24774			s.height = "auto";
24775			s.overflow = o;
24776		};
24777		aspect.after(anim, "onStop", fini, true);
24778		aspect.after(anim, "onEnd", fini, true);
24779
24780		return anim; // dojo/_base/fx.Animation
24781	};
24782
24783	coreFx.wipeOut = function(/*Object*/ args){
24784		// summary:
24785		//		Shrink a node to nothing and hide it.
24786		//
24787		// description:
24788		//		Returns an animation that will shrink node defined in "args"
24789		//		from it's current height to 1px, and then hide it.
24790		//
24791		// args: Object
24792		//		A hash-map of standard `dojo/_base/fx.Animation` constructor properties
24793		//		(such as easing: node: duration: and so on)
24794		//
24795		// example:
24796		//	|	require(["dojo/fx"], function(fx){
24797		//	|		fx.wipeOut({ node:"someId" }).play()
24798		//	|	});
24799
24800		var node = args.node = dom.byId(args.node), s = node.style, o;
24801
24802		var anim = baseFx.animateProperty(lang.mixin({
24803			properties: {
24804				height: {
24805					end: 1 // 0 causes IE to display the whole panel
24806				}
24807			}
24808		}, args));
24809
24810		aspect.after(anim, "beforeBegin", function(){
24811			o = s.overflow;
24812			s.overflow = "hidden";
24813			s.display = "";
24814		}, true);
24815		var fini = function(){
24816			s.overflow = o;
24817			s.height = "auto";
24818			s.display = "none";
24819		};
24820		aspect.after(anim, "onStop", fini, true);
24821		aspect.after(anim, "onEnd", fini, true);
24822
24823		return anim; // dojo/_base/fx.Animation
24824	};
24825
24826	coreFx.slideTo = function(/*Object*/ args){
24827		// summary:
24828		//		Slide a node to a new top/left position
24829		//
24830		// description:
24831		//		Returns an animation that will slide "node"
24832		//		defined in args Object from its current position to
24833		//		the position defined by (args.left, args.top).
24834		//
24835		// args: Object
24836		//		A hash-map of standard `dojo/_base/fx.Animation` constructor properties
24837		//		(such as easing: node: duration: and so on). Special args members
24838		//		are `top` and `left`, which indicate the new position to slide to.
24839		//
24840		// example:
24841		//	|	.slideTo({ node: node, left:"40", top:"50", units:"px" }).play()
24842
24843		var node = args.node = dom.byId(args.node),
24844			top = null, left = null;
24845
24846		var init = (function(n){
24847			return function(){
24848				var cs = domStyle.getComputedStyle(n);
24849				var pos = cs.position;
24850				top = (pos == 'absolute' ? n.offsetTop : parseInt(cs.top) || 0);
24851				left = (pos == 'absolute' ? n.offsetLeft : parseInt(cs.left) || 0);
24852				if(pos != 'absolute' && pos != 'relative'){
24853					var ret = geom.position(n, true);
24854					top = ret.y;
24855					left = ret.x;
24856					n.style.position="absolute";
24857					n.style.top=top+"px";
24858					n.style.left=left+"px";
24859				}
24860			};
24861		})(node);
24862		init();
24863
24864		var anim = baseFx.animateProperty(lang.mixin({
24865			properties: {
24866				top: args.top || 0,
24867				left: args.left || 0
24868			}
24869		}, args));
24870		aspect.after(anim, "beforeBegin", init, true);
24871
24872		return anim; // dojo/_base/fx.Animation
24873	};
24874
24875	return coreFx;
24876});
24877
24878},
24879'dijit/_Widget':function(){
24880define([
24881	"dojo/aspect",	// aspect.around
24882	"dojo/_base/config",	// config.isDebug
24883	"dojo/_base/connect",	// connect.connect
24884	"dojo/_base/declare", // declare
24885	"dojo/has",
24886	"dojo/_base/kernel", // kernel.deprecated
24887	"dojo/_base/lang", // lang.hitch
24888	"dojo/query",
24889	"dojo/ready",
24890	"./registry",	// registry.byNode
24891	"./_WidgetBase",
24892	"./_OnDijitClickMixin",
24893	"./_FocusMixin",
24894	"dojo/uacss",		// browser sniffing (included for back-compat; subclasses may be using)
24895	"./hccss"		// high contrast mode sniffing (included to set CSS classes on <body>, module ret value unused)
24896], function(aspect, config, connect, declare, has, kernel, lang, query, ready,
24897			registry, _WidgetBase, _OnDijitClickMixin, _FocusMixin){
24898
24899
24900// module:
24901//		dijit/_Widget
24902
24903
24904function connectToDomNode(){
24905	// summary:
24906	//		If user connects to a widget method === this function, then they will
24907	//		instead actually be connecting the equivalent event on this.domNode
24908}
24909
24910// Trap dojo.connect() calls to connectToDomNode methods, and redirect to _Widget.on()
24911function aroundAdvice(originalConnect){
24912	return function(obj, event, scope, method){
24913		if(obj && typeof event == "string" && obj[event] == connectToDomNode){
24914			return obj.on(event.substring(2).toLowerCase(), lang.hitch(scope, method));
24915		}
24916		return originalConnect.apply(connect, arguments);
24917	};
24918}
24919aspect.around(connect, "connect", aroundAdvice);
24920if(kernel.connect){
24921	aspect.around(kernel, "connect", aroundAdvice);
24922}
24923
24924var _Widget = declare("dijit._Widget", [_WidgetBase, _OnDijitClickMixin, _FocusMixin], {
24925	// summary:
24926	//		Old base class for widgets.   New widgets should extend `dijit/_WidgetBase` instead
24927	// description:
24928	//		Old Base class for Dijit widgets.
24929	//
24930	//		Extends _WidgetBase, adding support for:
24931	//
24932	//		- declaratively/programatically specifying widget initialization parameters like
24933	//			onMouseMove="foo" that call foo when this.domNode gets a mousemove event
24934	//		- ondijitclick:
24935	//			Support new data-dojo-attach-event="ondijitclick: ..." that is triggered by a mouse click or a SPACE/ENTER keypress
24936	//		- focus related functions:
24937	//			In particular, the onFocus()/onBlur() callbacks.   Driven internally by
24938	//			dijit/_base/focus.js.
24939	//		- deprecated methods
24940	//		- onShow(), onHide(), onClose()
24941	//
24942	//		Also, by loading code in dijit/_base, turns on:
24943	//
24944	//		- browser sniffing (putting browser class like `dj_ie` on `<html>` node)
24945	//		- high contrast mode sniffing (add `dijit_a11y` class to `<body>` if machine is in high contrast mode)
24946
24947
24948	////////////////// DEFERRED CONNECTS ///////////////////
24949
24950	onClick: connectToDomNode,
24951	/*=====
24952	onClick: function(event){
24953		// summary:
24954		//		Connect to this function to receive notifications of mouse click events.
24955		// event:
24956		//		mouse Event
24957		// tags:
24958		//		callback
24959	},
24960	=====*/
24961	onDblClick: connectToDomNode,
24962	/*=====
24963	onDblClick: function(event){
24964		// summary:
24965		//		Connect to this function to receive notifications of mouse double click events.
24966		// event:
24967		//		mouse Event
24968		// tags:
24969		//		callback
24970	},
24971	=====*/
24972	onKeyDown: connectToDomNode,
24973	/*=====
24974	onKeyDown: function(event){
24975		// summary:
24976		//		Connect to this function to receive notifications of keys being pressed down.
24977		// event:
24978		//		key Event
24979		// tags:
24980		//		callback
24981	},
24982	=====*/
24983	onKeyPress: connectToDomNode,
24984	/*=====
24985	onKeyPress: function(event){
24986		// summary:
24987		//		Connect to this function to receive notifications of printable keys being typed.
24988		// event:
24989		//		key Event
24990		// tags:
24991		//		callback
24992	},
24993	=====*/
24994	onKeyUp: connectToDomNode,
24995	/*=====
24996	onKeyUp: function(event){
24997		// summary:
24998		//		Connect to this function to receive notifications of keys being released.
24999		// event:
25000		//		key Event
25001		// tags:
25002		//		callback
25003	},
25004	=====*/
25005	onMouseDown: connectToDomNode,
25006	/*=====
25007	onMouseDown: function(event){
25008		// summary:
25009		//		Connect to this function to receive notifications of when the mouse button is pressed down.
25010		// event:
25011		//		mouse Event
25012		// tags:
25013		//		callback
25014	},
25015	=====*/
25016	onMouseMove: connectToDomNode,
25017	/*=====
25018	onMouseMove: function(event){
25019		// summary:
25020		//		Connect to this function to receive notifications of when the mouse moves over nodes contained within this widget.
25021		// event:
25022		//		mouse Event
25023		// tags:
25024		//		callback
25025	},
25026	=====*/
25027	onMouseOut: connectToDomNode,
25028	/*=====
25029	onMouseOut: function(event){
25030		// summary:
25031		//		Connect to this function to receive notifications of when the mouse moves off of nodes contained within this widget.
25032		// event:
25033		//		mouse Event
25034		// tags:
25035		//		callback
25036	},
25037	=====*/
25038	onMouseOver: connectToDomNode,
25039	/*=====
25040	onMouseOver: function(event){
25041		// summary:
25042		//		Connect to this function to receive notifications of when the mouse moves onto nodes contained within this widget.
25043		// event:
25044		//		mouse Event
25045		// tags:
25046		//		callback
25047	},
25048	=====*/
25049	onMouseLeave: connectToDomNode,
25050	/*=====
25051	onMouseLeave: function(event){
25052		// summary:
25053		//		Connect to this function to receive notifications of when the mouse moves off of this widget.
25054		// event:
25055		//		mouse Event
25056		// tags:
25057		//		callback
25058	},
25059	=====*/
25060	onMouseEnter: connectToDomNode,
25061	/*=====
25062	onMouseEnter: function(event){
25063		// summary:
25064		//		Connect to this function to receive notifications of when the mouse moves onto this widget.
25065		// event:
25066		//		mouse Event
25067		// tags:
25068		//		callback
25069	},
25070	=====*/
25071	onMouseUp: connectToDomNode,
25072	/*=====
25073	onMouseUp: function(event){
25074		// summary:
25075		//		Connect to this function to receive notifications of when the mouse button is released.
25076		// event:
25077		//		mouse Event
25078		// tags:
25079		//		callback
25080	},
25081	=====*/
25082
25083	constructor: function(params /*===== ,srcNodeRef =====*/){
25084		// summary:
25085		//		Create the widget.
25086		// params: Object|null
25087		//		Hash of initialization parameters for widget, including scalar values (like title, duration etc.)
25088		//		and functions, typically callbacks like onClick.
25089		//		The hash can contain any of the widget's properties, excluding read-only properties.
25090		// srcNodeRef: DOMNode|String?
25091		//		If a srcNodeRef (DOM node) is specified:
25092		//
25093		//		- use srcNodeRef.innerHTML as my contents
25094		//		- if this is a behavioral widget then apply behavior to that srcNodeRef
25095		//		- otherwise, replace srcNodeRef with my generated DOM tree
25096
25097		// extract parameters like onMouseMove that should connect directly to this.domNode
25098		this._toConnect = {};
25099		for(var name in params){
25100			if(this[name] === connectToDomNode){
25101				this._toConnect[name.replace(/^on/, "").toLowerCase()] = params[name];
25102				delete params[name];
25103			}
25104		}
25105	},
25106
25107	postCreate: function(){
25108		this.inherited(arguments);
25109
25110		// perform connection from this.domNode to user specified handlers (ex: onMouseMove)
25111		for(var name in this._toConnect){
25112			this.on(name, this._toConnect[name]);
25113		}
25114		delete this._toConnect;
25115	},
25116
25117	on: function(/*String|Function*/ type, /*Function*/ func){
25118		if(this[this._onMap(type)] === connectToDomNode){
25119			// Use connect.connect() rather than on() to get handling for "onmouseenter" on non-IE,
25120			// normalization of onkeypress/onkeydown to behave like firefox, etc.
25121			// Also, need to specify context as "this" rather than the default context of the DOMNode
25122			// Remove in 2.0.
25123			return connect.connect(this.domNode, type.toLowerCase(), this, func);
25124		}
25125		return this.inherited(arguments);
25126	},
25127
25128	_setFocusedAttr: function(val){
25129		// Remove this method in 2.0 (or sooner), just here to set _focused == focused, for back compat
25130		// (but since it's a private variable we aren't required to keep supporting it).
25131		this._focused = val;
25132		this._set("focused", val);
25133	},
25134
25135	////////////////// DEPRECATED METHODS ///////////////////
25136
25137	setAttribute: function(/*String*/ attr, /*anything*/ value){
25138		// summary:
25139		//		Deprecated.  Use set() instead.
25140		// tags:
25141		//		deprecated
25142		kernel.deprecated(this.declaredClass+"::setAttribute(attr, value) is deprecated. Use set() instead.", "", "2.0");
25143		this.set(attr, value);
25144	},
25145
25146	attr: function(/*String|Object*/name, /*Object?*/value){
25147		// summary:
25148		//		This method is deprecated, use get() or set() directly.
25149		// name:
25150		//		The property to get or set. If an object is passed here and not
25151		//		a string, its keys are used as names of attributes to be set
25152		//		and the value of the object as values to set in the widget.
25153		// value:
25154		//		Optional. If provided, attr() operates as a setter. If omitted,
25155		//		the current value of the named property is returned.
25156		// tags:
25157		//		deprecated
25158
25159		var args = arguments.length;
25160		if(args >= 2 || typeof name === "object"){ // setter
25161			return this.set.apply(this, arguments);
25162		}else{ // getter
25163			return this.get(name);
25164		}
25165	},
25166
25167	getDescendants: function(){
25168		// summary:
25169		//		Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode.
25170		//		This method should generally be avoided as it returns widgets declared in templates, which are
25171		//		supposed to be internal/hidden, but it's left here for back-compat reasons.
25172
25173		kernel.deprecated(this.declaredClass+"::getDescendants() is deprecated. Use getChildren() instead.", "", "2.0");
25174		return this.containerNode ? query('[widgetId]', this.containerNode).map(registry.byNode) : []; // dijit/_WidgetBase[]
25175	},
25176
25177	////////////////// MISCELLANEOUS METHODS ///////////////////
25178
25179	_onShow: function(){
25180		// summary:
25181		//		Internal method called when this widget is made visible.
25182		//		See `onShow` for details.
25183		this.onShow();
25184	},
25185
25186	onShow: function(){
25187		// summary:
25188		//		Called when this widget becomes the selected pane in a
25189		//		`dijit/layout/TabContainer`, `dijit/layout/StackContainer`,
25190		//		`dijit/layout/AccordionContainer`, etc.
25191		//
25192		//		Also called to indicate display of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
25193		// tags:
25194		//		callback
25195	},
25196
25197	onHide: function(){
25198		// summary:
25199		//		Called when another widget becomes the selected pane in a
25200		//		`dijit/layout/TabContainer`, `dijit/layout/StackContainer`,
25201		//		`dijit/layout/AccordionContainer`, etc.
25202		//
25203		//		Also called to indicate hide of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
25204		// tags:
25205		//		callback
25206	},
25207
25208	onClose: function(){
25209		// summary:
25210		//		Called when this widget is being displayed as a popup (ex: a Calendar popped
25211		//		up from a DateTextBox), and it is hidden.
25212		//		This is called from the dijit.popup code, and should not be called directly.
25213		//
25214		//		Also used as a parameter for children of `dijit/layout/StackContainer` or subclasses.
25215		//		Callback if a user tries to close the child.   Child will be closed if this function returns true.
25216		// tags:
25217		//		extension
25218
25219		return true;		// Boolean
25220	}
25221});
25222
25223// For back-compat, remove in 2.0.
25224if(has("dijit-legacy-requires")){
25225	ready(0, function(){
25226		var requires = ["dijit/_base"];
25227		require(requires);	// use indirection so modules not rolled into a build
25228	});
25229}
25230return _Widget;
25231});
25232
25233},
25234'dijit/_OnDijitClickMixin':function(){
25235define([
25236	"dojo/on",
25237	"dojo/_base/array", // array.forEach
25238	"dojo/keys", // keys.ENTER keys.SPACE
25239	"dojo/_base/declare", // declare
25240	"dojo/has", // has("dom-addeventlistener")
25241	"./a11yclick"
25242], function(on, array, keys, declare, has, a11yclick){
25243
25244	// module:
25245	//		dijit/_OnDijitClickMixin
25246
25247	var ret = declare("dijit._OnDijitClickMixin", null, {
25248		// summary:
25249		//		Deprecated.   New code should access the dijit/a11yclick event directly, ex:
25250		//		|	this.own(on(node, a11yclick, function(){ ... }));
25251		//
25252		//		Mixing in this class will make _WidgetBase.connect(node, "ondijitclick", ...) work.
25253		//		It also used to be necessary to make templates with ondijitclick work, but now you can just require
25254		//		dijit/a11yclick.
25255
25256		connect: function(obj, event, method){
25257			// override _WidgetBase.connect() to make this.connect(node, "ondijitclick", ...) work
25258			return this.inherited(arguments, [obj, event == "ondijitclick" ? a11yclick : event, method]);
25259		}
25260	});
25261
25262	ret.a11yclick = a11yclick;	// back compat
25263
25264	return ret;
25265});
25266
25267},
25268'dijit/a11yclick':function(){
25269define([
25270	"dojo/keys", // keys.ENTER keys.SPACE
25271	"dojo/mouse",
25272	"dojo/on",
25273	"dojo/touch" // touch support for click is now there
25274], function(keys, mouse, on, touch){
25275
25276	// module:
25277	//		dijit/a11yclick
25278
25279	/*=====
25280	return {
25281		// summary:
25282		//		Custom press, release, and click synthetic events
25283		//		which trigger on a left mouse click, touch, or space/enter keyup.
25284
25285		click: function(node, listener){
25286			// summary:
25287			//		Logical click operation for mouse, touch, or keyboard (space/enter key)
25288		},
25289		press: function(node, listener){
25290			// summary:
25291			//		Mousedown (left button), touchstart, or keydown (space or enter) corresponding to logical click operation.
25292		},
25293		release: function(node, listener){
25294			// summary:
25295			//		Mouseup (left button), touchend, or keyup (space or enter) corresponding to logical click operation.
25296		},
25297		move: function(node, listener){
25298			// summary:
25299			//		Mouse cursor or a finger is dragged over the given node.
25300		}
25301	};
25302	=====*/
25303
25304	function clickKey(/*Event*/ e){
25305		// Test if this keyboard event should be tracked as the start (if keydown) or end (if keyup) of a click event.
25306		// Only track for nodes marked to be tracked, and not for buttons or inputs,
25307		// since buttons handle keyboard click natively, and text inputs should not
25308		// prevent typing spaces or newlines.
25309		if((e.keyCode === keys.ENTER || e.keyCode === keys.SPACE) && !/input|button|textarea/i.test(e.target.nodeName)){
25310
25311			// Test if a node or its ancestor has been marked with the dojoClick property to indicate special processing
25312			for(var node = e.target; node; node = node.parentNode){
25313				if(node.dojoClick){ return true; }
25314			}
25315		}
25316	}
25317
25318	var lastKeyDownNode;
25319
25320	on(document, "keydown", function(e){
25321		//console.log("a11yclick: onkeydown, e.target = ", e.target, ", lastKeyDownNode was ", lastKeyDownNode, ", equality is ", (e.target === lastKeyDownNode));
25322		if(clickKey(e)){
25323			// needed on IE for when focus changes between keydown and keyup - otherwise dropdown menus do not work
25324			lastKeyDownNode = e.target;
25325
25326			// Prevent viewport scrolling on space key in IE<9.
25327			// (Reproducible on test_Button.html on any of the first dijit/form/Button examples)
25328			e.preventDefault();
25329		}else{
25330			lastKeyDownNode = null;
25331		}
25332	});
25333
25334	on(document, "keyup", function(e){
25335		//console.log("a11yclick: onkeyup, e.target = ", e.target, ", lastKeyDownNode was ", lastKeyDownNode, ", equality is ", (e.target === lastKeyDownNode));
25336		if(clickKey(e) && e.target == lastKeyDownNode){	// === breaks greasemonkey
25337			//need reset here or have problems in FF when focus returns to trigger element after closing popup/alert
25338			lastKeyDownNode = null;
25339
25340			on.emit(e.target, "click", {
25341				cancelable: true,
25342				bubbles: true,
25343				ctrlKey: e.ctrlKey,
25344				shiftKey: e.shiftKey,
25345				metaKey: e.metaKey,
25346				altKey: e.altKey,
25347				_origType: e.type
25348			});
25349		}
25350	});
25351
25352	// I want to return a hash of the synthetic events, but for backwards compatibility the main return value
25353	// needs to be the click event.   Change for 2.0.
25354
25355	var click = function(node, listener){
25356		// Set flag on node so that keydown/keyup above emits click event.
25357		// Also enables fast click processing from dojo/touch.
25358		node.dojoClick = true;
25359
25360		return on(node, "click", listener);
25361	};
25362	click.click = click;	// forward compatibility with 2.0
25363
25364	click.press =  function(node, listener){
25365		var touchListener = on(node, touch.press, function(evt){
25366			if(evt.type == "mousedown" && !mouse.isLeft(evt)){
25367				// Ignore right click
25368				return;
25369			}
25370			listener(evt);
25371		}), keyListener = on(node, "keydown", function(evt){
25372			if(evt.keyCode === keys.ENTER || evt.keyCode === keys.SPACE){
25373				listener(evt);
25374			}
25375		});
25376		return {
25377			remove: function(){
25378				touchListener.remove();
25379				keyListener.remove();
25380			}
25381		};
25382	};
25383
25384	click.release =  function(node, listener){
25385		var touchListener = on(node, touch.release, function(evt){
25386			if(evt.type == "mouseup" && !mouse.isLeft(evt)){
25387				// Ignore right click
25388				return;
25389			}
25390			listener(evt);
25391		}), keyListener = on(node, "keyup", function(evt){
25392			if(evt.keyCode === keys.ENTER || evt.keyCode === keys.SPACE){
25393				listener(evt);
25394			}
25395		});
25396		return {
25397			remove: function(){
25398				touchListener.remove();
25399				keyListener.remove();
25400			}
25401		};
25402	};
25403
25404	click.move = touch.move;	// just for convenience
25405
25406	return click;
25407});
25408
25409},
25410'dojo/touch':function(){
25411define(["./_base/kernel", "./aspect", "./dom", "./dom-class", "./_base/lang", "./on", "./has", "./mouse", "./domReady", "./_base/window"],
25412function(dojo, aspect, dom, domClass, lang, on, has, mouse, domReady, win){
25413
25414	// module:
25415	//		dojo/touch
25416
25417	var ios4 = has("ios") < 5;
25418
25419	// Detect if platform supports Pointer Events, and if so, the names of the events (pointerdown vs. MSPointerDown).
25420	var hasPointer = has("pointer-events") || has("MSPointer"),
25421		pointer = (function () {
25422			var pointer = {};
25423			for (var type in { down: 1, move: 1, up: 1, cancel: 1, over: 1, out: 1 }) {
25424				pointer[type] = has("MSPointer") ?
25425					"MSPointer" + type.charAt(0).toUpperCase() + type.slice(1) :
25426					"pointer" + type;
25427			}
25428			return pointer;
25429		})();
25430
25431	// Detect if platform supports the webkit touchstart/touchend/... events
25432	var hasTouch = has("touch-events");
25433
25434	// Click generation variables
25435	var clicksInited, clickTracker, useTarget = false, clickTarget, clickX, clickY, clickDx, clickDy, clickTime;
25436
25437	// Time of most recent touchstart, touchmove, or touchend event
25438	var lastTouch;
25439
25440	function dualEvent(mouseType, touchType, pointerType){
25441		// Returns synthetic event that listens for both the specified mouse event and specified touch event.
25442		// But ignore fake mouse events that were generated due to the user touching the screen.
25443		if(hasPointer && pointerType){
25444			// IE10+: MSPointer* events are designed to handle both mouse and touch in a uniform way,
25445			// so just use that regardless of hasTouch.
25446			return function(node, listener){
25447				return on(node, pointerType, listener);
25448			}
25449		}else if(hasTouch){
25450			return function(node, listener){
25451				var handle1 = on(node, touchType, function(evt){
25452						listener.call(this, evt);
25453
25454						// On slow mobile browsers (see https://bugs.dojotoolkit.org/ticket/17634),
25455						// a handler for a touch event may take >1s to run.  That time shouldn't
25456						// be included in the calculation for lastTouch.
25457						lastTouch = (new Date()).getTime();
25458					}),
25459					handle2 = on(node, mouseType, function(evt){
25460						if(!lastTouch || (new Date()).getTime() > lastTouch + 1000){
25461							listener.call(this, evt);
25462						}
25463					});
vendor: 4,847 bytes, lines 25464-25582
25464				return {
25465					remove: function(){
25466						handle1.remove();
25467						handle2.remove();
25468					}
25469				};
25470			};
25471		}else{
25472			// Avoid creating listeners for touch events on performance sensitive older browsers like IE6
25473			return function(node, listener){
25474				return on(node, mouseType, listener);
25475			}
25476		}
25477	}
25478
25479	function marked(/*DOMNode*/ node){
25480		// Search for node ancestor has been marked with the dojoClick property to indicate special processing.
25481		// Returns marked ancestor.
25482		do{
25483			if(node.dojoClick !== undefined){ return node; }
25484		}while(node = node.parentNode);
25485	}
25486	
25487	function doClicks(e, moveType, endType){
25488		// summary:
25489		//		Setup touch listeners to generate synthetic clicks immediately (rather than waiting for the browser
25490		//		to generate clicks after the double-tap delay) and consistently (regardless of whether event.preventDefault()
25491		//		was called in an event listener. Synthetic clicks are generated only if a node or one of its ancestors has
25492		//		its dojoClick property set to truthy. If a node receives synthetic clicks because one of its ancestors has its
25493		//      dojoClick property set to truthy, you can disable synthetic clicks on this node by setting its own dojoClick property
25494		//      to falsy.
25495		
25496		var markedNode = marked(e.target);
25497		clickTracker  = !e.target.disabled && markedNode && markedNode.dojoClick; // click threshold = true, number, x/y object, or "useTarget"
25498		if(clickTracker){
25499			useTarget = (clickTracker == "useTarget");
25500			clickTarget = (useTarget?markedNode:e.target);
25501			if(useTarget){
25502				// We expect a click, so prevent any other 
25503				// default action on "touchpress"
25504				e.preventDefault();
25505			}
25506			clickX = e.changedTouches ? e.changedTouches[0].pageX - win.global.pageXOffset : e.clientX;
25507			clickY = e.changedTouches ? e.changedTouches[0].pageY - win.global.pageYOffset : e.clientY;
25508			clickDx = (typeof clickTracker == "object" ? clickTracker.x : (typeof clickTracker == "number" ? clickTracker : 0)) || 4;
25509			clickDy = (typeof clickTracker == "object" ? clickTracker.y : (typeof clickTracker == "number" ? clickTracker : 0)) || 4;
25510
25511			// add move/end handlers only the first time a node with dojoClick is seen,
25512			// so we don't add too much overhead when dojoClick is never set.
25513			if(!clicksInited){
25514				clicksInited = true;
25515
25516				function updateClickTracker(e){
25517					if(useTarget){
25518						clickTracker = dom.isDescendant(
25519							win.doc.elementFromPoint(
25520								(e.changedTouches ? e.changedTouches[0].pageX - win.global.pageXOffset : e.clientX),
25521								(e.changedTouches ? e.changedTouches[0].pageY - win.global.pageYOffset : e.clientY)),
25522							clickTarget);
25523					}else{
25524						clickTracker = clickTracker &&
25525							(e.changedTouches ? e.changedTouches[0].target : e.target) == clickTarget &&
25526							Math.abs((e.changedTouches ? e.changedTouches[0].pageX - win.global.pageXOffset : e.clientX) - clickX) <= clickDx &&
25527							Math.abs((e.changedTouches ? e.changedTouches[0].pageY - win.global.pageYOffset : e.clientY) - clickY) <= clickDy;
25528					}
25529				}
25530
25531				win.doc.addEventListener(moveType, function(e){
25532					updateClickTracker(e);
25533					if(useTarget){
25534						// prevent native scroll event and ensure touchend is
25535						// fire after touch moves between press and release.
25536						e.preventDefault();
25537					}
25538				}, true);
25539
25540				win.doc.addEventListener(endType, function(e){
25541					updateClickTracker(e);
25542					if(clickTracker){
25543						clickTime = (new Date()).getTime();
25544						var target = (useTarget?clickTarget:e.target);
25545						if(target.tagName === "LABEL"){
25546							// when clicking on a label, forward click to its associated input if any
25547							target = dom.byId(target.getAttribute("for")) || target;
25548						}
25549						//some attributes can be on the Touch object, not on the Event:
25550						//http://www.w3.org/TR/touch-events/#touch-interface
25551						var src = (e.changedTouches) ? e.changedTouches[0] : e;
25552						//create the synthetic event.
25553						//http://www.w3.org/TR/DOM-Level-3-Events/#widl-MouseEvent-initMouseEvent
25554						var clickEvt = document.createEvent("MouseEvents");
25555						clickEvt._dojo_click = true;
25556						clickEvt.initMouseEvent("click",
25557							true, //bubbles
25558							true, //cancelable
25559							e.view,
25560							e.detail,
25561							src.screenX,
25562							src.screenY,
25563							src.clientX,
25564							src.clientY,
25565							e.ctrlKey,
25566							e.altKey,
25567							e.shiftKey,
25568							e.metaKey,
25569							0, //button
25570							null //related target
25571						);
25572						setTimeout(function(){
25573							on.emit(target, "click", clickEvt);
25574
25575							// refresh clickTime in case app-defined click handler took a long time to run
25576							clickTime = (new Date()).getTime();
25577						}, 0);
25578					}
25579				}, true);
25580
25581				function stopNativeEvents(type){
25582					win.doc.addEventListener(type, function(e){
25583						// Stop native events when we emitted our own click event.  Note that the native click may occur
25584						// on a different node than the synthetic click event was generated on.  For example,
25585						// click on a menu item, causing the menu to disappear, and then (~300ms later) the browser
25586						// sends a click event to the node that was *underneath* the menu.  So stop all native events
25587						// sent shortly after ours, similar to what is done in dualEvent.
25588						// The INPUT.dijitOffScreen test is for offscreen inputs used in dijit/form/Button, on which
25589						// we call click() explicitly, we don't want to stop this event.
25590							if(!e._dojo_click &&
25591								(new Date()).getTime() <= clickTime + 1000 &&
25592								!(e.target.tagName == "INPUT" && domClass.contains(e.target, "dijitOffScreen"))){
25593							e.stopPropagation();
25594							e.stopImmediatePropagation && e.stopImmediatePropagation();
25595							if(type == "click" && (e.target.tagName != "INPUT" || e.target.type == "radio" || e.target.type == "checkbox")
25596								&& e.target.tagName != "TEXTAREA" && e.target.tagName != "AUDIO" && e.target.tagName != "VIDEO"){
25597								 // preventDefault() breaks textual <input>s on android, keyboard doesn't popup,
25598								 // but it is still needed for checkboxes and radio buttons, otherwise in some cases
25599								 // the checked state becomes inconsistent with the widget's state
25600								e.preventDefault();
25601							}
25602						}
25603					}, true);
25604				}
25605
25606				stopNativeEvents("click");
25607
25608				// We also stop mousedown/up since these would be sent well after with our "fast" click (300ms),
25609				// which can confuse some dijit widgets.
25610				stopNativeEvents("mousedown");
25611				stopNativeEvents("mouseup");
25612			}
25613		}
25614	}
25615
25616	var hoveredNode;
25617
25618	if(hasPointer){
25619		 // MSPointer (IE10+) already has support for over and out, so we just need to init click support
25620		domReady(function(){
25621			win.doc.addEventListener(pointer.down, function(evt){
25622				doClicks(evt, pointer.move, pointer.up);
25623			}, true);
25624		});
25625	}else if(hasTouch){
25626		domReady(function(){
25627			// Keep track of currently hovered node
25628			hoveredNode = win.body();	// currently hovered node
25629
25630			win.doc.addEventListener("touchstart", function(evt){
25631					lastTouch = (new Date()).getTime();
25632
25633				// Precede touchstart event with touch.over event.  DnD depends on this.
25634				// Use addEventListener(cb, true) to run cb before any touchstart handlers on node run,
25635				// and to ensure this code runs even if the listener on the node does event.stop().
25636				var oldNode = hoveredNode;
25637				hoveredNode = evt.target;
25638				on.emit(oldNode, "dojotouchout", {
25639					relatedTarget: hoveredNode,
25640					bubbles: true
25641				});
25642				on.emit(hoveredNode, "dojotouchover", {
25643					relatedTarget: oldNode,
25644					bubbles: true
25645				});
25646
25647				doClicks(evt, "touchmove", "touchend"); // init click generation
25648			}, true);
25649
25650			function copyEventProps(evt){
25651				// Make copy of event object and also set bubbles:true.  Used when calling on.emit().
25652				var props = lang.delegate(evt, {
25653					bubbles: true
25654				});
25655
25656				if(has("ios") >= 6){
25657					// On iOS6 "touches" became a non-enumerable property, which
25658					// is not hit by for...in.  Ditto for the other properties below.
25659					props.touches = evt.touches;
25660					props.altKey = evt.altKey;
25661					props.changedTouches = evt.changedTouches;
25662					props.ctrlKey = evt.ctrlKey;
25663					props.metaKey = evt.metaKey;
25664					props.shiftKey = evt.shiftKey;
25665					props.targetTouches = evt.targetTouches;
25666				}
25667
25668				return props;
25669			}
25670
25671			on(win.doc, "touchmove", function(evt){
25672				lastTouch = (new Date()).getTime();
25673
25674				var newNode = win.doc.elementFromPoint(
25675					evt.pageX - (ios4 ? 0 : win.global.pageXOffset), // iOS 4 expects page coords
25676					evt.pageY - (ios4 ? 0 : win.global.pageYOffset)
25677				);
25678
25679				if(newNode){
25680					// Fire synthetic touchover and touchout events on nodes since the browser won't do it natively.
25681					if(hoveredNode !== newNode){
25682						// touch out on the old node
25683						on.emit(hoveredNode, "dojotouchout", {
25684							relatedTarget: newNode,
25685							bubbles: true
25686						});
vendor: 1,748 bytes, lines 25687-25728
25687
25688						// touchover on the new node
25689						on.emit(newNode, "dojotouchover", {
25690							relatedTarget: hoveredNode,
25691							bubbles: true
25692						});
25693
25694						hoveredNode = newNode;
25695					}
25696
25697					// Unlike a listener on "touchmove", on(node, "dojotouchmove", listener) fires when the finger
25698					// drags over the specified node, regardless of which node the touch started on.
25699					if(!on.emit(newNode, "dojotouchmove", copyEventProps(evt))){
25700						// emit returns false when synthetic event "dojotouchmove" is cancelled, so we prevent the
25701						// default behavior of the underlying native event "touchmove".
25702						evt.preventDefault();
25703					}
25704				}
25705			});
25706
25707			// Fire a dojotouchend event on the node where the finger was before it was removed from the screen.
25708			// This is different than the native touchend, which fires on the node where the drag started.
25709			on(win.doc, "touchend", function(evt){
25710					lastTouch = (new Date()).getTime();
25711				var node = win.doc.elementFromPoint(
25712					evt.pageX - (ios4 ? 0 : win.global.pageXOffset), // iOS 4 expects page coords
25713					evt.pageY - (ios4 ? 0 : win.global.pageYOffset)
25714				) || win.body(); // if out of the screen
25715
25716				on.emit(node, "dojotouchend", copyEventProps(evt));
25717			});
25718		});
25719	}
25720
25721	//device neutral events - touch.press|move|release|cancel/over/out
25722	var touch = {
25723		press: dualEvent("mousedown", "touchstart", pointer.down),
25724		move: dualEvent("mousemove", "dojotouchmove", pointer.move),
25725		release: dualEvent("mouseup", "dojotouchend", pointer.up),
25726		cancel: dualEvent(mouse.leave, "touchcancel", hasPointer ? pointer.cancel : null),
25727		over: dualEvent("mouseover", "dojotouchover", pointer.over),
25728		out: dualEvent("mouseout", "dojotouchout", pointer.out),
25729		enter: mouse._eventHandler(dualEvent("mouseover","dojotouchover", pointer.over)),
25730		leave: mouse._eventHandler(dualEvent("mouseout", "dojotouchout", pointer.out))
25731	};
25732
25733	/*=====
25734	touch = {
25735		// summary:
25736		//		This module provides unified touch event handlers by exporting
25737		//		press, move, release and cancel which can also run well on desktop.
25738		//		Based on http://dvcs.w3.org/hg/webevents/raw-file/tip/touchevents.html
25739		//      Also, if the dojoClick property is set to truthy on a DOM node, dojo/touch generates
25740		//      click events immediately for this node and its descendants (except for descendants that
25741		//      have a dojoClick property set to falsy), to avoid the delay before native browser click events,
25742		//      and regardless of whether evt.preventDefault() was called in a touch.press event listener.
25743		//
25744		// example:
25745		//		Used with dojo/on
25746		//		|	define(["dojo/on", "dojo/touch"], function(on, touch){
25747		//		|		on(node, touch.press, function(e){});
25748		//		|		on(node, touch.move, function(e){});
25749		//		|		on(node, touch.release, function(e){});
25750		//		|		on(node, touch.cancel, function(e){});
25751		// example:
25752		//		Used with touch.* directly
25753		//		|	touch.press(node, function(e){});
25754		//		|	touch.move(node, function(e){});
25755		//		|	touch.release(node, function(e){});
25756		//		|	touch.cancel(node, function(e){});
25757		// example:
25758		//		Have dojo/touch generate clicks without delay, with a default move threshold of 4 pixels
25759		//		|	node.dojoClick = true;
25760		// example:
25761		//		Have dojo/touch generate clicks without delay, with a move threshold of 10 pixels horizontally and vertically
25762		//		|	node.dojoClick = 10;
25763		// example:
25764		//		Have dojo/touch generate clicks without delay, with a move threshold of 50 pixels horizontally and 10 pixels vertically
25765		//		|	node.dojoClick = {x:50, y:5};
25766		// example:
25767		//		Disable clicks without delay generated by dojo/touch on a node that has an ancestor with property dojoClick set to truthy
25768		//		|  node.dojoClick = false;
25769
25770		press: function(node, listener){
25771			// summary:
25772			//		Register a listener to 'touchstart'|'mousedown' for the given node
25773			// node: Dom
25774			//		Target node to listen to
25775			// listener: Function
25776			//		Callback function
25777			// returns:
25778			//		A handle which will be used to remove the listener by handle.remove()
25779		},
25780		move: function(node, listener){
25781			// summary:
25782			//		Register a listener that fires when the mouse cursor or a finger is dragged over the given node.
25783			// node: Dom
25784			//		Target node to listen to
25785			// listener: Function
25786			//		Callback function
25787			// returns:
25788			//		A handle which will be used to remove the listener by handle.remove()
25789		},
25790		release: function(node, listener){
25791			// summary:
25792			//		Register a listener to releasing the mouse button while the cursor is over the given node
25793			//		(i.e. "mouseup") or for removing the finger from the screen while touching the given node.
25794			// node: Dom
25795			//		Target node to listen to
25796			// listener: Function
25797			//		Callback function
25798			// returns:
25799			//		A handle which will be used to remove the listener by handle.remove()
25800		},
25801		cancel: function(node, listener){
25802			// summary:
25803			//		Register a listener to 'touchcancel'|'mouseleave' for the given node
25804			// node: Dom
25805			//		Target node to listen to
25806			// listener: Function
25807			//		Callback function
25808			// returns:
25809			//		A handle which will be used to remove the listener by handle.remove()
25810		},
25811		over: function(node, listener){
25812			// summary:
25813			//		Register a listener to 'mouseover' or touch equivalent for the given node
25814			// node: Dom
25815			//		Target node to listen to
25816			// listener: Function
25817			//		Callback function
25818			// returns:
25819			//		A handle which will be used to remove the listener by handle.remove()
25820		},
25821		out: function(node, listener){
25822			// summary:
25823			//		Register a listener to 'mouseout' or touch equivalent for the given node
25824			// node: Dom
25825			//		Target node to listen to
25826			// listener: Function
25827			//		Callback function
25828			// returns:
25829			//		A handle which will be used to remove the listener by handle.remove()
25830		},
25831		enter: function(node, listener){
25832			// summary:
25833			//		Register a listener to mouse.enter or touch equivalent for the given node
25834			// node: Dom
25835			//		Target node to listen to
25836			// listener: Function
25837			//		Callback function
25838			// returns:
25839			//		A handle which will be used to remove the listener by handle.remove()
25840		},
25841		leave: function(node, listener){
25842			// summary:
25843			//		Register a listener to mouse.leave or touch equivalent for the given node
25844			// node: Dom
25845			//		Target node to listen to
25846			// listener: Function
25847			//		Callback function
25848			// returns:
25849			//		A handle which will be used to remove the listener by handle.remove()
25850		}
25851	};
25852	=====*/
25853
25854	 1  && (dojo.touch = touch);
25855
25856	return touch;
25857});
25858
25859},
25860'dijit/_FocusMixin':function(){
25861define([
25862	"./focus",
25863	"./_WidgetBase",
25864	"dojo/_base/declare", // declare
25865	"dojo/_base/lang" // lang.extend
25866], function(focus, _WidgetBase, declare, lang){
25867
25868	// module:
25869	//		dijit/_FocusMixin
25870
25871	// We don't know where _FocusMixin will occur in the inheritance chain, but we need the _onFocus()/_onBlur() below
25872	// to be last in the inheritance chain, so mixin to _WidgetBase.
25873	lang.extend(_WidgetBase, {
25874		// focused: [readonly] Boolean
25875		//		This widget or a widget it contains has focus, or is "active" because
25876		//		it was recently clicked.
25877		focused: false,
25878
25879		onFocus: function(){
25880			// summary:
25881			//		Called when the widget becomes "active" because
25882			//		it or a widget inside of it either has focus, or has recently
25883			//		been clicked.
25884			// tags:
25885			//		callback
25886		},
25887
25888		onBlur: function(){
25889			// summary:
25890			//		Called when the widget stops being "active" because
25891			//		focus moved to something outside of it, or the user
25892			//		clicked somewhere outside of it, or the widget was
25893			//		hidden.
25894			// tags:
25895			//		callback
25896		},
25897
25898		_onFocus: function(){
25899			// summary:
25900			//		This is where widgets do processing for when they are active,
25901			//		such as changing CSS classes.  See onFocus() for more details.
25902			// tags:
25903			//		protected
25904			this.onFocus();
25905		},
25906
25907		_onBlur: function(){
25908			// summary:
25909			//		This is where widgets do processing for when they stop being active,
25910			//		such as changing CSS classes.  See onBlur() for more details.
25911			// tags:
25912			//		protected
25913			this.onBlur();
25914		}
25915	});
25916
25917	return declare("dijit._FocusMixin", null, {
25918		// summary:
25919		//		Mixin to widget to provide _onFocus() and _onBlur() methods that
25920		//		fire when a widget or its descendants get/lose focus
25921
25922		// flag that I want _onFocus()/_onBlur() notifications from focus manager
25923		_focusManager: focus
25924	});
25925
25926});
25927
25928},
25929'dijit/focus':function(){
25930define([
25931	"dojo/aspect",
25932	"dojo/_base/declare", // declare
25933	"dojo/dom", // domAttr.get dom.isDescendant
25934	"dojo/dom-attr", // domAttr.get dom.isDescendant
25935	"dojo/dom-class",
25936	"dojo/dom-construct", // connect to domConstruct.empty, domConstruct.destroy
25937	"dojo/Evented",
25938	"dojo/_base/lang", // lang.hitch
25939	"dojo/on",
25940	"dojo/domReady",
25941	"dojo/sniff", // has("ie")
25942	"dojo/Stateful",
25943	"dojo/_base/window", // win.body
25944	"dojo/window", // winUtils.get
25945	"./a11y",	// a11y.isTabNavigable
25946	"./registry",	// registry.byId
25947	"./main"		// to set dijit.focus
25948], function(aspect, declare, dom, domAttr, domClass, domConstruct, Evented, lang, on, domReady, has, Stateful, win, winUtils,
25949			a11y, registry, dijit){
25950
25951	// module:
25952	//		dijit/focus
25953
25954	// Time of the last focusin event
25955	var lastFocusin;
25956
25957	// Time of the last touch/mousedown or focusin event
25958	var lastTouchOrFocusin;
25959
25960	var FocusManager = declare([Stateful, Evented], {
25961		// summary:
25962		//		Tracks the currently focused node, and which widgets are currently "active".
25963		//		Access via require(["dijit/focus"], function(focus){ ... }).
25964		//
25965		//		A widget is considered active if it or a descendant widget has focus,
25966		//		or if a non-focusable node of this widget or a descendant was recently clicked.
25967		//
25968		//		Call focus.watch("curNode", callback) to track the current focused DOMNode,
25969		//		or focus.watch("activeStack", callback) to track the currently focused stack of widgets.
25970		//
25971		//		Call focus.on("widget-blur", func) or focus.on("widget-focus", ...) to monitor when
25972		//		when widgets become active/inactive
25973		//
25974		//		Finally, focus(node) will focus a node, suppressing errors if the node doesn't exist.
25975
25976		// curNode: DomNode
25977		//		Currently focused item on screen
25978		curNode: null,
25979
25980		// activeStack: dijit/_WidgetBase[]
25981		//		List of currently active widgets (focused widget and it's ancestors)
25982		activeStack: [],
25983
25984		constructor: function(){
25985			// Don't leave curNode/prevNode pointing to bogus elements
25986			var check = lang.hitch(this, function(node){
25987				if(dom.isDescendant(this.curNode, node)){
25988					this.set("curNode", null);
25989				}
25990				if(dom.isDescendant(this.prevNode, node)){
25991					this.set("prevNode", null);
25992				}
25993			});
25994			aspect.before(domConstruct, "empty", check);
25995			aspect.before(domConstruct, "destroy", check);
25996		},
25997
25998		registerIframe: function(/*DomNode*/ iframe){
25999			// summary:
26000			//		Registers listeners on the specified iframe so that any click
26001			//		or focus event on that iframe (or anything in it) is reported
26002			//		as a focus/click event on the `<iframe>` itself.
26003			// description:
26004			//		Currently only used by editor.
26005			// returns:
26006			//		Handle with remove() method to deregister.
26007			return this.registerWin(iframe.contentWindow, iframe);
26008		},
26009
26010		registerWin: function(/*Window?*/targetWindow, /*DomNode?*/ effectiveNode){
26011			// summary:
26012			//		Registers listeners on the specified window (either the main
26013			//		window or an iframe's window) to detect when the user has clicked somewhere
26014			//		or focused somewhere.
26015			// description:
26016			//		Users should call registerIframe() instead of this method.
26017			// targetWindow:
26018			//		If specified this is the window associated with the iframe,
26019			//		i.e. iframe.contentWindow.
26020			// effectiveNode:
26021			//		If specified, report any focus events inside targetWindow as
26022			//		an event on effectiveNode, rather than on evt.target.
26023			// returns:
26024			//		Handle with remove() method to deregister.
26025
26026			// TODO: make this function private in 2.0; Editor/users should call registerIframe(),
26027
26028			// Listen for blur and focus events on targetWindow's document.
26029			var _this = this,
26030				body = targetWindow.document && targetWindow.document.body;
26031
26032			if(body){
26033				// Listen for touches or mousedowns... could also use dojo/touch.press here.
26034				var event = has("pointer-events") ? "pointerdown" : has("MSPointer") ? "MSPointerDown" :
26035					has("touch-events") ? "mousedown, touchstart" : "mousedown";
26036				var mdh = on(targetWindow.document, event, function(evt){
26037					// workaround weird IE bug where the click is on an orphaned node
26038					// (first time clicking a Select/DropDownButton inside a TooltipDialog).
26039					// actually, strangely this is happening on latest chrome too.
26040					if(evt && evt.target && evt.target.parentNode == null){
26041						return;
26042					}
26043
26044					_this._onTouchNode(effectiveNode || evt.target, "mouse");
26045				});
26046
26047				var fih = on(body, 'focusin', function(evt){
26048					// When you refocus the browser window, IE gives an event with an empty srcElement
26049					if(!evt.target.tagName) { return; }
26050
26051					// IE reports that nodes like <body> have gotten focus, even though they have tabIndex=-1,
26052					// ignore those events
26053					var tag = evt.target.tagName.toLowerCase();
26054					if(tag == "#document" || tag == "body"){ return; }
26055
26056					if(a11y.isFocusable(evt.target)){
26057						_this._onFocusNode(effectiveNode || evt.target);
26058					}else{
26059						// Previous code called _onTouchNode() for any activate event on a non-focusable node.   Can
26060						// probably just ignore such an event as it will be handled by onmousedown handler above, but
26061						// leaving the code for now.
26062						_this._onTouchNode(effectiveNode || evt.target);
26063					}
26064				});
26065
26066				var foh = on(body, 'focusout', function(evt){
26067					_this._onBlurNode(effectiveNode || evt.target);
26068				});
26069
26070				return {
26071					remove: function(){
26072						mdh.remove();
26073						fih.remove();
26074						foh.remove();
26075						mdh = fih = foh = null;
26076						body = null;	// prevent memory leak (apparent circular reference via closure)
26077					}
26078				};
26079			}
26080		},
26081
26082		_onBlurNode: function(/*DomNode*/ node){
26083			// summary:
26084			//		Called when focus leaves a node.
26085			//		Usually ignored, _unless_ it *isn't* followed by touching another node,
26086			//		which indicates that we tabbed off the last field on the page,
26087			//		in which case every widget is marked inactive
26088
26089			var now = (new Date()).getTime();
26090
26091			// IE9+ and chrome have a problem where focusout events come after the corresponding focusin event.
26092			// For chrome problem see https://bugs.dojotoolkit.org/ticket/17668.
26093			// IE problem happens when moving focus from the Editor's <iframe> to a normal DOMNode.
26094			if(now < lastFocusin + 100){
26095				return;
26096			}
26097
26098			// If the blur event isn't followed by a focus event, it means the user clicked on something unfocusable,
26099			// so clear focus.
26100			if(this._clearFocusTimer){
26101				clearTimeout(this._clearFocusTimer);
26102			}
26103			this._clearFocusTimer = setTimeout(lang.hitch(this, function(){
26104				this.set("prevNode", this.curNode);
26105				this.set("curNode", null);
26106			}), 0);
26107
26108			// Unset timer to zero-out widget stack; we'll reset it below if appropriate.
26109			if(this._clearActiveWidgetsTimer){
26110				clearTimeout(this._clearActiveWidgetsTimer);
26111			}
26112
26113			if(now < lastTouchOrFocusin + 100){
26114				// This blur event is coming late (after the call to _onTouchNode() rather than before.
26115				// So let _onTouchNode() handle setting the widget stack.
26116				// See https://bugs.dojotoolkit.org/ticket/17668
26117				return;
26118			}
26119
26120			// If the blur event isn't followed (or preceded) by a focus or touch event then mark all widgets as inactive.
26121			this._clearActiveWidgetsTimer = setTimeout(lang.hitch(this, function(){
26122				delete this._clearActiveWidgetsTimer;
26123				this._setStack([]);
26124			}), 0);
26125		},
26126
26127		_onTouchNode: function(/*DomNode*/ node, /*String*/ by){
26128			// summary:
26129			//		Callback when node is focused or touched.
26130			//		Note that _onFocusNode() calls _onTouchNode().
26131			// node:
26132			//		The node that was touched.
26133			// by:
26134			//		"mouse" if the focus/touch was caused by a mouse down event
26135
26136			// Keep track of time of last focusin or touch event.
26137			lastTouchOrFocusin = (new Date()).getTime();
26138
26139			if(this._clearActiveWidgetsTimer){
26140				// forget the recent blur event
26141				clearTimeout(this._clearActiveWidgetsTimer);
26142				delete this._clearActiveWidgetsTimer;
26143			}
26144
26145			// if the click occurred on the scrollbar of a dropdown, treat it as a click on the dropdown,
26146			// even though the scrollbar is technically on the popup wrapper (see #10631)
26147			if(domClass.contains(node, "dijitPopup")){
26148				node = node.firstChild;
26149			}
26150
26151			// compute stack of active widgets (ex: ComboButton --> Menu --> MenuItem)
26152			var newStack=[];
26153			try{
26154				while(node){
26155					var popupParent = domAttr.get(node, "dijitPopupParent");
26156					if(popupParent){
26157						node=registry.byId(popupParent).domNode;
26158					}else if(node.tagName && node.tagName.toLowerCase() == "body"){
26159						// is this the root of the document or just the root of an iframe?
26160						if(node === win.body()){
26161							// node is the root of the main document
26162							break;
26163						}
26164						// otherwise, find the iframe this node refers to (can't access it via parentNode,
26165						// need to do this trick instead). window.frameElement is supported in IE/FF/Webkit
26166						node=winUtils.get(node.ownerDocument).frameElement;
26167					}else{
26168						// if this node is the root node of a widget, then add widget id to stack,
26169						// except ignore clicks on disabled widgets (actually focusing a disabled widget still works,
26170						// to support MenuItem)
26171						var id = node.getAttribute && node.getAttribute("widgetId"),
26172							widget = id && registry.byId(id);
26173						if(widget && !(by == "mouse" && widget.get("disabled"))){
26174							newStack.unshift(id);
26175						}
26176						node=node.parentNode;
26177					}
26178				}
26179			}catch(e){ /* squelch */ }
26180
26181			this._setStack(newStack, by);
26182		},
26183
26184		_onFocusNode: function(/*DomNode*/ node){
26185			// summary:
26186			//		Callback when node is focused
26187
26188			if(!node){
26189				return;
26190			}
26191
26192			if(node.nodeType == 9){
26193				// Ignore focus events on the document itself.  This is here so that
26194				// (for example) clicking the up/down arrows of a spinner
26195				// (which don't get focus) won't cause that widget to blur. (FF issue)
26196				return;
26197			}
26198
26199			// Keep track of time of last focusin event.
26200			lastFocusin = (new Date()).getTime();
26201
26202			// There was probably a blur event right before this event, but since we have a new focu
26202s,
26203			// forget about the blur
26204			if(this._clearFocusTimer){
26205				clearTimeout(this._clearFocusTimer);
26206				delete this._clearFocusTimer;
26207			}
26208
26209			this._onTouchNode(node);
26210
26211			if(node == this.curNode){ return; }
26212			this.set("prevNode", this.curNode);
26213			this.set("curNode", node);
26214		},
26215
26216		_setStack: function(/*String[]*/ newStack, /*String*/ by){
26217			// summary:
26218			//		The stack of active widgets has changed.  Send out appropriate events and records new stack.
26219			// newStack:
26220			//		array of widget id's, starting from the top (outermost) widget
26221			// by:
26222			//		"mouse" if the focus/touch was caused by a mouse down event
26223
26224			var oldStack = this.activeStack, lastOldIdx = oldStack.length - 1, lastNewIdx = newStack.length - 1;
26225
26226			if(newStack[lastNewIdx] == oldStack[lastOldIdx]){
26227				// no changes, return now to avoid spurious notifications about changes to activeStack
26228				return;
26229			}
26230
26231			this.set("activeStack", newStack);
26232
26233			var widget, i;
26234
26235			// for all elements that have gone out of focus, set focused=false
26236			for(i = lastOldIdx; i >= 0 && oldStack[i] != newStack[i]; i--){
26237				widget = registry.byId(oldStack[i]);
26238				if(widget){
26239					widget._hasBeenBlurred = true;		// TODO: used by form widgets, should be moved there
26240					widget.set("focused", false);
26241					if(widget._focusManager == this){
26242						widget._onBlur(by);
26243					}
26244					this.emit("widget-blur", widget, by);
26245				}
26246			}
26247
26248			// for all element that have come into focus, set focused=true
26249			for(i++; i <= lastNewIdx; i++){
26250				widget = registry.byId(newStack[i]);
26251				if(widget){
26252					widget.set("focused", true);
26253					if(widget._focusManager == this){
26254						widget._onFocus(by);
26255					}
26256					this.emit("widget-focus", widget, by);
26257				}
26258			}
26259		},
26260
26261		focus: function(node){
26262			// summary:
26263			//		Focus the specified node, suppressing errors if they occur
26264			if(node){
26265				try{ node.focus(); }catch(e){/*quiet*/}
26266			}
26267		}
26268	});
26269
26270	var singleton = new FocusManager();
26271
26272	// register top window and all the iframes it contains
26273	domReady(function(){
26274		var handle = singleton.registerWin(winUtils.get(document));
26275		if(has("ie")){
26276			on(window, "unload", function(){
26277				if(handle){	// because this gets called twice when doh.robot is running
26278					handle.remove();
26279					handle = null;
26280				}
26281			});
26282		}
26283	});
26284
26285	// Setup dijit.focus as a pointer to the singleton but also (for backwards compatibility)
26286	// as a function to set focus.   Remove for 2.0.
26287	dijit.focus = function(node){
26288		singleton.focus(node);	// indirection here allows dijit/_base/focus.js to override behavior
26289	};
26290	for(var attr in singleton){
26291		if(!/^_/.test(attr)){
26292			dijit.focus[attr] = typeof singleton[attr] == "function" ? lang.hitch(singleton, attr) : singleton[attr];
26293		}
26294	}
26295	singleton.watch(function(attr, oldVal, newVal){
26296		dijit.focus[attr] = newVal;
26297	});
26298
26299	return singleton;
26300});
26301
26302},
26303'dijit/a11y':function(){
26304define([
26305	"dojo/_base/array", // array.forEach array.map
26306	"dojo/dom",			// dom.byId
26307	"dojo/dom-attr", // domAttr.attr domAttr.has
26308	"dojo/dom-style", // domStyle.style
26309	"dojo/_base/lang", // lang.mixin()
26310	"dojo/sniff", // has("ie")  1 
26311	"./main"	// for exporting methods to dijit namespace
26312], function(array, dom, domAttr, domStyle, lang, has, dijit){
26313
26314	// module:
26315	//		dijit/a11y
26316
26317	var undefined;
26318
26319	var a11y = {
26320		// summary:
26321		//		Accessibility utility functions (keyboard, tab stops, etc.)
26322
26323		_isElementShown: function(/*Element*/ elem){
26324			var s = domStyle.get(elem);
26325			return (s.visibility != "hidden")
26326				&& (s.visibility != "collapsed")
26327				&& (s.display != "none")
26328				&& (domAttr.get(elem, "type") != "hidden");
26329		},
26330
26331		hasDefaultTabStop: function(/*Element*/ elem){
26332			// summary:
26333			//		Tests if element is tab-navigable even without an explicit tabIndex setting
26334
26335			// No explicit tabIndex setting, need to investigate node type
26336			switch(elem.nodeName.toLowerCase()){
26337				case "a":
26338					// An <a> w/out a tabindex is only navigable if it has an href
26339					return domAttr.has(elem, "href");
26340				case "area":
26341				case "button":
26342				case "input":
26343				case "object":
26344				case "select":
26345				case "textarea":
26346					// These are navigable by default
26347					return true;
26348				case "iframe":
26349					// If it's an editor <iframe> then it's tab navigable.
26350					var body;
26351					try{
26352						// non-IE
26353						var contentDocument = elem.contentDocument;
26354						if("designMode" in contentDocument && contentDocument.designMode == "on"){
26355							return true;
26356						}
26357						body = contentDocument.body;
26358					}catch(e1){
26359						// contentWindow.document isn't accessible within IE7/8
26360						// if the iframe.src points to a foreign url and this
26361						// page contains an element, that could get focus
26362						try{
26363							body = elem.contentWindow.document.body;
26364						}catch(e2){
26365							return false;
26366						}
26367					}
26368					return body && (body.contentEditable == 'true' ||
26369						(body.firstChild && body.firstChild.contentEditable == 'true'));
26370				default:
26371					return elem.contentEditable == 'true';
26372			}
26373		},
26374
26375		effectiveTabIndex: function(/*Element*/ elem){
26376			// summary:
26377			//		Returns effective tabIndex of an element, either a number, or undefined if element isn't focusable.
26378
26379			if(domAttr.get(elem, "disabled")){
26380				return undefined;
26381			}else if(domAttr.has(elem, "tabIndex")){
26382				// Explicit tab index setting
26383				return +domAttr.get(elem, "tabIndex");// + to convert string --> number
26384			}else{
26385				// No explicit tabIndex setting, so depends on node type
26386				return a11y.hasDefaultTabStop(elem) ? 0 : undefined;
26387			}
26388		},
26389
26390		isTabNavigable: function(/*Element*/ elem){
26391			// summary:
26392			//		Tests if an element is tab-navigable
26393
26394			return a11y.effectiveTabIndex(elem) >= 0;
26395		},
26396
26397		isFocusable: function(/*Element*/ elem){
26398			// summary:
26399			//		Tests if an element is focusable by tabbing to it, or clicking it with the mouse.
26400
26401			return a11y.effectiveTabIndex(elem) >= -1;
26402		},
26403
26404		_getTabNavigable: function(/*DOMNode*/ root){
26405			// summary:
26406			//		Finds descendants of the specified root node.
26407			// description:
26408			//		Finds the following descendants of the specified root node:
26409			//
26410			//		- the first tab-navigable element in document order
26411			//		  without a tabIndex or with tabIndex="0"
26412			//		- the last tab-navigable element in document order
26413			//		  without a tabIndex or with tabIndex="0"
26414			//		- the first element in document order with the lowest
26415			//		  positive tabIndex value
26416			//		- the last element in document order with the highest
26417			//		  positive tabIndex value
26418			var first, last, lowest, lowestTabindex, highest, highestTabindex, radioSelected = {};
26419
26420			function radioName(node){
26421				// If this element is part of a radio button group, return the name for that group.
26422				return node && node.tagName.toLowerCase() == "input" &&
26423					node.type && node.type.toLowerCase() == "radio" &&
26424					node.name && node.name.toLowerCase();
26425			}
26426
26427			var shown = a11y._isElementShown, effectiveTabIndex = a11y.effectiveTabIndex;
26428			var walkTree = function(/*DOMNode*/ parent){
26429				for(var child = parent.firstChild; child; child = child.nextSibling){
26430					// Skip text elements, hidden elements, and also non-HTML elements (those in custom namespaces) in IE,
26431					// since show() invokes getAttribute("type"), which crash on VML nodes in IE.
26432					if(child.nodeType != 1 || (has("ie") <= 9 && child.scopeName !== "HTML") || !shown(child)){
26433						continue;
26434					}
26435
26436					var tabindex = effectiveTabIndex(child);
26437					if(tabindex >= 0){
26438						if(tabindex == 0){
26439							if(!first){
26440								first = child;
26441							}
26442							last = child;
26443						}else if(tabindex > 0){
26444							if(!lowest || tabindex < lowestTabindex){
26445								lowestTabindex = tabindex;
26446								lowest = child;
26447							}
26448							if(!highest || tabindex >= highestTabindex){
26449								highestTabindex = tabindex;
26450								highest = child;
26451							}
26452						}
26453						var rn = radioName(child);
26454						if(domAttr.get(child, "checked") && rn){
26455							radioSelected[rn] = child;
26456						}
26457					}
26458					if(child.nodeName.toUpperCase() != 'SELECT'){
26459						walkTree(child);
26460					}
26461				}
26462			};
26463			if(shown(root)){
26464				walkTree(root);
26465			}
26466			function rs(node){
26467				// substitute checked radio button for unchecked one, if there is a checked one with the same name.
26468				return radioSelected[radioName(node)] || node;
26469			}
26470
26471			return { first: rs(first), last: rs(last), lowest: rs(lowest), highest: rs(highest) };
26472		},
26473
26474		getFirstInTabbingOrder: function(/*String|DOMNode*/ root, /*Document?*/ doc){
26475			// summary:
26476			//		Finds the descendant of the specified root node
26477			//		that is first in the tabbing order
26478			var elems = a11y._getTabNavigable(dom.byId(root, doc));
26479			return elems.lowest ? elems.lowest : elems.first; // DomNode
26480		},
26481
26482		getLastInTabbingOrder: function(/*String|DOMNode*/ root, /*Document?*/ doc){
26483			// summary:
26484			//		Finds the descendant of the specified root node
26485			//		that is last in the tabbing order
26486			var elems = a11y._getTabNavigable(dom.byId(root, doc));
26487			return elems.last ? elems.last : elems.highest; // DomNode
26488		}
26489	};
26490
26491	 1  && lang.mixin(dijit, a11y);
26492
26493	return a11y;
26494});
26495
26496},
26497'dojo/uacss':function(){
26498define(["./dom-geometry", "./_base/lang", "./domReady", "./sniff", "./_base/window"],
26499	function(geometry, lang, domReady, has, baseWindow){
26500
26501	// module:
26502	//		dojo/uacss
26503
26504	/*=====
26505	return {
26506		// summary:
26507		//		Applies pre-set CSS classes to the top-level HTML node, based on:
26508		//
26509		//		- browser (ex: dj_ie)
26510		//		- browser version (ex: dj_ie6)
26511		//		- box model (ex: dj_contentBox)
26512		//		- text direction (ex: dijitRtl)
26513		//
26514		//		In addition, browser, browser version, and box model are
26515		//		combined with an RTL flag when browser text is RTL. ex: dj_ie-rtl.
26516		//
26517		//		Returns the has() method.
26518	};
26519	=====*/
26520
26521	var
26522		html = baseWindow.doc.documentElement,
26523		ie = has("ie"),
26524		opera = has("opera"),
26525		maj = Math.floor,
26526		ff = has("ff"),
26527		boxModel = geometry.boxModel.replace(/-/,''),
26528
26529		classes = {
26530			"dj_quirks": has("quirks"),
26531
26532			// NOTE: Opera not supported by dijit
26533			"dj_opera": opera,
26534
26535			"dj_khtml": has("khtml"),
26536
26537			"dj_webkit": has("webkit"),
26538			"dj_safari": has("safari"),
26539			"dj_chrome": has("chrome"),
26540
26541			"dj_gecko": has("mozilla"),
26542
26543			"dj_ios": has("ios"),
26544			"dj_android": has("android")
26545		}; // no dojo unsupported browsers
26546
26547	if(ie){
26548		classes["dj_ie"] = true;
26549		classes["dj_ie" + maj(ie)] = true;
26550		classes["dj_iequirks"] = has("quirks");
26551	}
26552	if(ff){
26553		classes["dj_ff" + maj(ff)] = true;
26554	}
26555
26556	classes["dj_" + boxModel] = true;
26557
26558	// apply browser, browser version, and box model class names
26559	var classStr = "";
26560	for(var clz in classes){
26561		if(classes[clz]){
26562			classStr += clz + " ";
26563		}
26564	}
26565	html.className = lang.trim(html.className + " " + classStr);
26566
26567	// If RTL mode, then add dj_rtl flag plus repeat existing classes with -rtl extension.
26568	// We can't run the code below until the <body> tag has loaded (so we can check for dir=rtl).
26569	domReady(function(){
26570		if(!geometry.isBodyLtr()){
26571			var rtlClassStr = "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl ");
26572			html.className = lang.trim(html.className + " " + rtlClassStr + "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl "));
26573		}
26574	});
26575	return has;
26576});
26577
26578},
26579'dijit/hccss':function(){
26580define(["dojo/dom-class", "dojo/hccss", "dojo/domReady", "dojo/_base/window"], function(domClass, has, domReady, win){
26581
26582	// module:
26583	//		dijit/hccss
26584
26585	/*=====
26586	return function(){
26587		// summary:
26588		//		Test if computer is in high contrast mode, and sets `dijit_a11y` flag on `<body>` if it is.
26589		//		Deprecated, use ``dojo/hccss`` instead.
26590	};
26591	=====*/
26592
26593	domReady(function(){
26594		if(has("highcontrast")){
26595			domClass.add(win.body(), "dijit_a11y");
26596		}
26597	});
26598
26599	return has;
26600});
26601
26602},
26603'dojo/hccss':function(){
26604define([
26605	"require",			// require, require.toUrl
26606	"./_base/config", // config.blankGif
26607	"./dom-class", // domClass.add
26608	"./dom-style", // domStyle.getComputedStyle
26609	"./has",
26610	"./domReady",
26611	"./_base/window" // win.body
26612], function(require, config, domClass, domStyle, has, domReady, win){
26613
26614	// module:
26615	//		dojo/hccss
26616
26617	/*=====
26618	return function(){
26619		// summary:
26620		//		Test if computer is in high contrast mode (i.e. if browser is not displaying background images).
26621		//		Defines `has("highcontrast")` and sets `dj_a11y` CSS class on `<body>` if machine is in high contrast mode.
26622		//		Returns `has()` method;
26623	};
26624	=====*/
26625
26626	// Has() test for when background images aren't displayed.  Don't call has("highcontrast") before dojo/domReady!.
26627	has.add("highcontrast", function(){
26628		// note: if multiple documents, doesn't matter which one we use
26629		var div = win.doc.createElement("div");
26630		div.style.cssText = "border: 1px solid; border-color:red green; position: absolute; height: 5px; top: -999px;" +
26631			"background-image: url(\"" + (config.blankGif || require.toUrl("./resources/blank.gif")) + "\");";
26632		win.body().appendChild(div);
26633
26634		var cs = domStyle.getComputedStyle(div),
26635			bkImg = cs.backgroundImage,
26636			hc = (cs.borderTopColor == cs.borderRightColor) ||
26637				(bkImg && (bkImg == "none" || bkImg == "url(invalid-url:)" ));
26638
26639		if(has("ie") <= 8){
26640			div.outerHTML = "";		// prevent mixed-content warning, see http://support.microsoft.com/kb/925014
26641		}else{
26642			win.body().removeChild(div);
26643		}
26644
26645		return hc;
26646	});
26647
26648	domReady(function(){
26649		if(has("highcontrast")){
26650			domClass.add(win.body(), "dj_a11y");
26651		}
26652	});
26653
26654	return has;
26655});
26656
26657},
26658'dijit/_TemplatedMixin':function(){
26659define([
26660	"dojo/cache",	// dojo.cache
26661	"dojo/_base/declare", // declare
26662	"dojo/dom-construct", // domConstruct.destroy, domConstruct.toDom
26663	"dojo/_base/lang", // lang.getObject
26664	"dojo/on",
26665	"dojo/sniff", // has("ie")
26666	"dojo/string", // string.substitute string.trim
26667	"./_AttachMixin"
26668], function(cache, declare, domConstruct, lang, on, has, string, _AttachMixin){
26669
26670	// module:
26671	//		dijit/_TemplatedMixin
26672
26673	var _TemplatedMixin = declare("dijit._TemplatedMixin", _AttachMixin, {
26674		// summary:
26675		//		Mixin for widgets that are instantiated from a template
26676
26677		// templateString: [protected] String
26678		//		A string that represents the widget template.
26679		//		Use in conjunction with dojo.cache() to load from a file.
26680		templateString: null,
26681
26682		// templatePath: [protected deprecated] String
26683		//		Path to template (HTML file) for this widget relative to dojo.baseUrl.
26684		//		Deprecated: use templateString with require([... "dojo/text!..."], ...) instead
26685		templatePath: null,
26686
26687		// skipNodeCache: [protected] Boolean
26688		//		If using a cached widget template nodes poses issues for a
26689		//		particular widget class, it can set this property to ensure
26690		//		that its template is always re-built from a string
26691		_skipNodeCache: false,
26692
26693/*=====
26694		// _rendered: Boolean
26695		//		Not normally use, but this flag can be set by the app if the server has already rendered the template,
26696		//		i.e. already inlining the template for the widget into the main page.   Reduces _TemplatedMixin to
26697		//		just function like _AttachMixin.
26698		_rendered: false,
26699=====*/
26700
26701		// Set _AttachMixin.searchContainerNode to true for back-compat for widgets that have data-dojo-attach-point's
26702		// and events inside this.containerNode.   Remove for 2.0.
26703		searchContainerNode: true,
26704
26705		_stringRepl: function(tmpl){
26706			// summary:
26707			//		Does substitution of ${foo} type properties in template string
26708			// tags:
26709			//		private
26710			var className = this.declaredClass, _this = this;
26711			// Cache contains a string because we need to do property replacement
26712			// do the property replacement
26713			return string.substitute(tmpl, this, function(value, key){
26714				if(key.charAt(0) == '!'){ value = lang.getObject(key.substr(1), false, _this); }
26715				if(typeof value == "undefined"){ throw new Error(className+" template:"+key); } // a debugging aide
26716				if(value == null){ return ""; }
26717
26718				// Substitution keys beginning with ! will skip the transform step,
26719				// in case a user wishes to insert unescaped markup, e.g. ${!foo}
26720				return key.charAt(0) == "!" ? value : this._escapeValue("" + value);
26721			}, this);
26722		},
26723
26724		_escapeValue: function(/*String*/ val){
26725			// summary:
26726			//		Escape a value to be inserted into the template, either into an attribute value
26727			//		(ex: foo="${bar}") or as inner text of an element (ex: <span>${foo}</span>)
26728
26729			// Safer substitution, see heading "Attribute values" in
26730			// http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
26731			// and also https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet#RULE_.231_-_HTML_Escape_Before_Inserting_Untrusted_Data_into_HTML_Element_Content
26732			return val.replace(/["'<>&]/g, function(val){
26733				return {
26734					"&": "&amp;",
26735					"<": "&lt;",
26736					">": "&gt;",
26737					"\"": "&quot;",
26738					"'": "&#x27;"
26739				}[val];
26740			});
26741		},
26742
26743		buildRendering: function(){
26744			// summary:
26745			//		Construct the UI for this widget from a template, setting this.domNode.
26746			// tags:
26747			//		protected
26748
26749			if(!this._rendered){
26750				if(!this.templateString){
26751					this.templateString = cache(this.templatePath, {sanitize: true});
26752				}
26753
26754				// Lookup cached version of template, and download to cache if it
26755				// isn't there already.  Returns either a DomNode or a string, depending on
26756				// whether or not the template contains ${foo} replacement parameters.
26757				var cached = _TemplatedMixin.getCachedTemplate(this.templateString, this._skipNodeCache, this.ownerDocument);
26758
26759				var node;
26760				if(lang.isString(cached)){
26761					node = domConstruct.toDom(this._stringRepl(cached), this.ownerDocument);
26762					if(node.nodeType != 1){
26763						// Flag common problems such as templates with multiple top level nodes (nodeType == 11)
26764						throw new Error("Invalid template: " + cached);
26765					}
26766				}else{
26767					// if it's a node, all we have to do is clone it
26768					node = cached.cloneNode(true);
26769				}
26770
26771				this.domNode = node;
26772			}
26773
26774			// Call down to _WidgetBase.buildRendering() to get base classes assigned
26775			// TODO: change the baseClass assignment to _setBaseClassAttr
26776			this.inherited(arguments);
26777
26778			if(!this._rendered){
26779				this._fillContent(this.srcNodeRef);
26780			}
26781
26782			this._rendered = true;
26783		},
26784
26785		_fillContent: function(/*DomNode*/ source){
26786			// summary:
26787			//		Relocate source contents to templated container node.
26788			//		this.containerNode must be able to receive children, or exceptions will be thrown.
26789			// tags:
26790			//		protected
26791			var dest = this.containerNode;
26792			if(source && dest){
26793				while(source.hasChildNodes()){
26794					dest.appendChild(source.firstChild);
26795				}
26796			}
26797		}
26798
26799	});
26800
26801	// key is templateString; object is either string or DOM tree
26802	_TemplatedMixin._templateCache = {};
26803
26804	_TemplatedMixin.getCachedTemplate = function(templateString, alwaysUseString, doc){
26805		// summary:
26806		//		Static method to get a template based on the templatePath or
26807		//		templateString key
26808		// templateString: String
26809		//		The template
26810		// alwaysUseString: Boolean
26811		//		Don't cache the DOM tree for this template, even if it doesn't have any variables
26812		// doc: Document?
26813		//		The target document.   Defaults to document global if unspecified.
26814		// returns: Mixed
26815		//		Either string (if there are ${} variables that need to be replaced) or just
26816		//		a DOM tree (if the node can be cloned directly)
26817
26818		// is it already cached?
26819		var tmplts = _TemplatedMixin._templateCache;
26820		var key = templateString;
26821		var cached = tmplts[key];
26822		if(cached){
26823			try{
26824				// if the cached value is an innerHTML string (no ownerDocument) or a DOM tree created within the
26825				// current document, then use the current cached value
26826				if(!cached.ownerDocument || cached.ownerDocument == (doc || document)){
26827					// string or node of the same document
26828					return cached;
26829				}
26830			}catch(e){ /* squelch */ } // IE can throw an exception if cached.ownerDocument was reloaded
26831			domConstruct.destroy(cached);
26832		}
26833
26834		templateString = string.trim(templateString);
26835
26836		if(alwaysUseString || templateString.match(/\$\{([^\}]+)\}/g)){
26837			// there are variables in the template so all we can do is cache the string
26838			return (tmplts[key] = templateString); //String
26839		}else{
26840			// there are no variables in the template so we can cache the DOM tree
26841			var node = domConstruct.toDom(templateString, doc);
26842			if(node.nodeType != 1){
26843				throw new Error("Invalid template: " + templateString);
26844			}
26845			return (tmplts[key] = node); //Node
26846		}
26847	};
26848
26849	if(has("ie")){
26850		on(window, "unload", function(){
26851			var cache = _TemplatedMixin._templateCache;
26852			for(var key in cache){
26853				var value = cache[key];
26854				if(typeof value == "object"){ // value is either a string or a DOM node template
26855					domConstruct.destroy(value);
26856				}
26857				delete cache[key];
26858			}
26859		});
26860	}
26861
26862	return _TemplatedMixin;
26863});
26864
26865},
26866'dojo/cache':function(){
26867define(["./_base/kernel", "./text"], function(dojo){
26868	// module:
26869	//		dojo/cache
26870
26871	// dojo.cache is defined in dojo/text
26872	return dojo.cache;
26873});
26874
26875},
26876'dojo/text':function(){
26877define(["./_base/kernel", "require", "./has", "./request"], function(dojo, require, has, request){
26878	// module:
26879	//		dojo/text
26880
26881	var getText;
26882	if( 1 ){
26883		getText= function(url, sync, load){
26884			request(url, {sync:!!sync, headers: { 'X-Requested-With': null } }).then(load);
26885		};
26886	}else{
26887		// Path for node.js and rhino, to load from local file system.
26888		// TODO: use node.js native methods rather than depending on a require.getText() method to exist.
26889		if(require.getText){
26890			getText= require.getText;
26891		}else{
26892			console.error("dojo/text plugin failed to load because loader does not support getText");
26893		}
26894	}
26895
26896	var
26897		theCache = {},
26898
26899		strip= function(text){
26900			//Strips <?xml ...?> declarations so that external SVG and XML
26901			//documents can be added to a document without worry. Also, if the string
26902			//is an HTML document, only the part inside the body tag is returned.
26903			if(text){
26904				text= text.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");
26905				var matches= text.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
26906				if(matches){
26907					text= matches[1];
26908				}
26909			}else{
26910				text = "";
26911			}
26912			return text;
26913		},
26914
26915		notFound = {},
26916
26917		pending = {};
26918
26919	dojo.cache = function(/*String||Object*/module, /*String*/url, /*String||Object?*/value){
26920		// summary:
26921		//		A getter and setter for storing the string content associated with the
26922		//		module and url arguments.
26923		// description:
26924		//		If module is a string that contains slashes, then it is interpretted as a fully
26925		//		resolved path (typically a result returned by require.toUrl), and url should not be
26926		//		provided. This is the preferred signature. If module is a string that does not
26927		//		contain slashes, then url must also be provided and module and url are used to
26928		//		call `dojo.moduleUrl()` to generate a module URL. This signature is deprecated.
26929		//		If value is specified, the cache value for the moduleUrl will be set to
26930		//		that value. Otherwise, dojo.cache will fetch the moduleUrl and store it
vendor: 4,197 bytes, lines 26931-27003
26931		//		in its internal cache and return that cached value for the URL. To clear
26932		//		a cache value pass null for value. Since XMLHttpRequest (XHR) is used to fetch the
26933		//		the URL contents, only modules on the same domain of the page can use this capability.
26934		//		The build system can inline the cache values though, to allow for xdomain hosting.
26935		// module: String||Object
26936		//		If a String with slashes, a fully resolved path; if a String without slashes, the
26937		//		module name to use for the base part of the URL, similar to module argument
26938		//		to `dojo.moduleUrl`. If an Object, something that has a .toString() method that
26939		//		generates a valid path for the cache item. For example, a dojo._Url object.
26940		// url: String
26941		//		The rest of the path to append to the path derived from the module argument. If
26942		//		module is an object, then this second argument should be the "value" argument instead.
26943		// value: String||Object?
26944		//		If a String, the value to use in the cache for the module/url combination.
26945		//		If an Object, it can have two properties: value and sanitize. The value property
26946		//		should be the value to use in the cache, and sanitize can be set to true or false,
26947		//		to indicate if XML declarations should be removed from the value and if the HTML
26948		//		inside a body tag in the value should be extracted as the real value. The value argument
26949		//		or the value property on the value argument are usually only used by the build system
26950		//		as it inlines cache content.
26951		// example:
26952		//		To ask dojo.cache to fetch content and store it in the cache (the dojo["cache"] style
26953		//		of call is used to avoid an issue with the build system erroneously trying to intern
26954		//		this example. To get the build system to intern your dojo.cache calls, use the
26955		//		"dojo.cache" style of call):
26956		//		| //If template.html contains "<h1>Hello</h1>" that will be
26957		//		| //the value for the text variable.
26958		//		| //Note: This is pre-AMD, deprecated syntax
26959		//		| var text = dojo["cache"]("my.module", "template.html");
26960		// example:
26961		//		To ask dojo.cache to fetch content and store it in the cache, and sanitize the input
26962		//		 (the dojo["cache"] style of call is used to avoid an issue with the build system
26963		//		erroneously trying to intern this example. To get the build system to intern your
26964		//		dojo.cache calls, use the "dojo.cache" style of call):
26965		//		| //If template.html contains "<html><body><h1>Hello</h1></body></html>", the
26966		//		| //text variable will contain just "<h1>Hello</h1>".
26967		//		| //Note: This is pre-AMD, deprecated syntax
26968		//		| var text = dojo["cache"]("my.module", "template.html", {sanitize: true});
26969		// example:
26970		//		Same example as previous, but demonstrates how an object can be passed in as
26971		//		the first argument, then the value argument can then be the second argument.
26972		//		| //If template.html contains "<html><body><h1>Hello</h1></body></html>", the
26973		//		| //text variable will contain just "<h1>Hello</h1>".
26974		//		| //Note: This is pre-AMD, deprecated syntax
26975		//		| var text = dojo["cache"](new dojo._Url("my/module/template.html"), {sanitize: true});
26976
26977		//	 * (string string [value]) => (module, url, value)
26978		//	 * (object [value])        => (module, value), url defaults to ""
26979		//
26980		//	 * if module is an object, then it must be convertable to a string
26981		//	 * (module, url) module + (url ? ("/" + url) : "") must be a legal argument to require.toUrl
26982		//	 * value may be a string or an object; if an object then may have the properties "value" and/or "sanitize"
26983		var key;
26984		if(typeof module=="string"){
26985			if(/\//.test(module)){
26986				// module is a version 1.7+ resolved path
26987				key = module;
26988				value = url;
26989			}else{
26990				// module is a version 1.6- argument to dojo.moduleUrl
26991				key = require.toUrl(module.replace(/\./g, "/") + (url ? ("/" + url) : ""));
26992			}
26993		}else{
26994			key = module + "";
26995			value = url;
26996		}
26997		var
26998			val = (value != undefined && typeof value != "string") ? value.value : value,
26999			sanitize = value && value.sanitize;
27000
27001		if(typeof val == "string"){
27002			//We have a string, set cache value
27003			theCache[key] = val;
27004			return sanitize ? strip(val) : val;
27005		}else if(val === null){
27006			//Remove cached value
27007			delete theCache[key];
27008			return null;
27009		}else{
27010			//Allow cache values to be empty strings. If key property does
27011			//not exist, fetch it.
27012			if(!(key in theCache)){
27013				getText(key, true, function(text){
27014					theCache[key]= text;
27015				});
27016			}
27017			return sanitize ? strip(theCache[key]) : theCache[key];
27018		}
27019	};
27020
27021	return {
27022		// summary:
27023		//		This module implements the dojo/text! plugin and the dojo.cache API.
27024		// description:
27025		//		We choose to include our own plugin to leverage functionality already contained in dojo
27026		//		and thereby reduce the size of the plugin compared to various foreign loader implementations.
27027		//		Also, this allows foreign AMD loaders to be used without their plugins.
27028		//
27029		//		CAUTION: this module is designed to optionally function synchronously to support the dojo v1.x synchronous
27030		//		loader. This feature is outside the scope of the CommonJS plugins specification.
27031
27032		// the dojo/text caches it's own resources because of dojo.cache
27033		dynamic: true,
27034
27035		normalize: function(id, toAbsMid){
27036			// id is something like (path may be relative):
27037			//
27038			//	 "path/to/text.html"
27039			//	 "path/to/text.html!strip"
27040			var parts= id.split("!"),
27041				url= parts[0];
27042			return (/^\./.test(url) ? toAbsMid(url) : url) + (parts[1] ? "!" + parts[1] : "");
27043		},
27044
27045		load: function(id, require, load){
27046			// id: String
27047			//		Path to the resource.
27048			// require: Function
27049			//		Object that include the function toUrl with given id returns a valid URL from which to load the text.
27050			// load: Function
27051			//		Callback function which will be called, when the loading finished.
27052
27053			// id is something like (path is always absolute):
27054			//
27055			//	 "path/to/text.html"
27056			//	 "path/to/text.html!strip"
27057			var
27058				parts= id.split("!"),
27059				stripFlag= parts.length>1,
27060				absMid= parts[0],
27061				url = require.toUrl(parts[0]),
27062				requireCacheUrl = "url:" + url,
27063				text = notFound,
27064				finish = function(text){
27065					load(stripFlag ? strip(text) : text);
27066				};
27067			if(absMid in theCache){
27068				text = theCache[absMid];
27069			}else if(require.cache && requireCacheUrl in require.cache){
27070				text = require.cache[requireCacheUrl];
27071			}else if(url in theCache){
27072				text = theCache[url];
27073			}
27074			if(text===notFound){
27075				if(pending[url]){
27076					pending[url].push(finish);
27077				}else{
27078					var pendingList = pending[url] = [finish];
27079					getText(url, !require.async, function(text){
27080						theCache[absMid]= theCache[url]= text;
27081						for(var i = 0; i<pendingList.length;){
27082							pendingList[i++](text);
27083						}
27084						delete pending[url];
27085					});
27086				}
27087			}else{
27088				finish(text);
27089			}
27090		}
27091	};
27092
27093});
27094
27095
27096},
27097'dojo/request':function(){
27098define([
27099	'./request/default!'/*=====,
27100	'./_base/declare',
27101	'./promise/Promise' =====*/
27102], function(request/*=====, declare, Promise =====*/){
27103	/*=====
27104	request = function(url, options){
27105		// summary:
27106		//		Send a request using the default transport for the current platform.
27107		// url: String
27108		//		The URL to request.
27109		// options: dojo/request.__Options?
27110		//		Options for the request.
27111		// returns: dojo/request.__Promise
27112	};
27113	request.__Promise = declare(Promise, {
27114		// response: dojo/promise/Promise
27115		//		A promise resolving to an object representing
27116		//		the response from the server.
27117	});
27118	request.__BaseOptions = declare(null, {
27119		// query: String|Object?
27120		//		Query parameters to append to the URL.
27121		// data: String|Object?
27122		//		Data to transfer.  This is ignored for GET and DELETE
27123		//		requests.
27124		// preventCache: Boolean?
27125		//		Whether to append a cache-busting parameter to the URL.
27126		// timeout: Integer?
27127		//		Milliseconds to wait for the response.  If this time
27128		//		passes, the then the promise is rejected.
27129		// handleAs: String?
27130		//		How to handle the response from the server.  Default is
27131		//		'text'.  Other values are 'json', 'javascript', and 'xml'.
27132	});
27133	request.__MethodOptions = declare(null, {
27134		// method: String?
27135		//		The HTTP method to use to make the request.  Must be
27136		//		uppercase.
27137	});
27138	request.__Options = declare([request.__BaseOptions, request.__MethodOptions]);
27139
27140	request.get = function(url, options){
27141		// summary:
27142		//		Send an HTTP GET request using the default transport for the current platform.
27143		// url: String
27144		//		URL to request
27145		// options: dojo/request.__BaseOptions?
27146		//		Options for the request.
27147		// returns: dojo/request.__Promise
27148	};
27149	request.post = function(url, options){
27150		// summary:
27151		//		Send an HTTP POST request using the default transport for the current platform.
27152		// url: String
27153		//		URL to request
27154		// options: dojo/request.__BaseOptions?
27155		//		Options for the request.
27156		// returns: dojo/request.__Promise
27157	};
27158	request.put = function(url, options){
27159		// summary:
27160		//		Send an HTTP POST request using the default transport for the current platform.
27161		// url: String
27162		//		URL to request
27163		// options: dojo/request.__BaseOptions?
27164		//		Options for the request.
27165		// returns: dojo/request.__Promise
27166	};
27167	request.del = function(url, options){
27168		// summary:
27169		//		Send an HTTP DELETE request using the default transport for the current platform.
27170		// url: String
27171		//		URL to request
27172		// options: dojo/request.__BaseOptions?
27173		//		Options for the request.
27174		// returns: dojo/request.__Promise
27175	};
27176	=====*/
27177	return request;
27178});
27179
27180},
27181'dojo/request/default':function(){
27182define([
27183	'exports',
27184	'require',
27185	'../has'
27186], function(exports, require, has){
27187	var defId = has('config-requestProvider'),
27188		platformId;
27189
27190	if( 1  || has('host-webworker')){
27191		platformId = './xhr';
27192	}else if( 0 ){
27193		platformId = './node';
27194	/* TODO:
27195	}else if( 0 ){
27196		platformId = './rhino';
27197   */
27198	}
27199
27200	if(!defId){
27201		defId = platformId;
27202	}
27203
27204	exports.getPlatformDefaultId = function(){
27205		return platformId;
27206	};
27207
27208	exports.load = function(id, parentRequire, loaded, config){
27209		require([id == 'platform' ? platformId : defId], function(provider){
27210			loaded(provider);
27211		});
27212	};
27213});
27214
27215},
27216'dijit/_AttachMixin':function(){
27217define([
27218	"require",
27219	"dojo/_base/array", // array.forEach
27220	"dojo/_base/connect",	// remove for 2.0
27221	"dojo/_base/declare", // declare
27222	"dojo/_base/lang", // lang.getObject
27223	"dojo/mouse",
27224	"dojo/on",
27225	"dojo/touch",
27226	"./_WidgetBase"
27227], function(require, array, connect, declare, lang, mouse, on, touch, _WidgetBase){
27228
27229	// module:
27230	//		dijit/_AttachMixin
27231
27232	// Map from string name like "mouseenter" to synthetic event like mouse.enter
27233	var synthEvents = lang.delegate(touch, {
27234		"mouseenter": mouse.enter,
27235		"mouseleave": mouse.leave,
27236		"keypress": connect._keypress	// remove for 2.0
27237	});
27238
27239	// To be lightweight, _AttachMixin doesn't require() dijit/a11yclick.
27240	// If the subclass has a template using "ondijitclick", it must load dijit/a11yclick itself.
27241	// In that case, the a11yclick variable below will get set to point to that synthetic event.
27242	var a11yclick;
27243
27244	var _AttachMixin = declare("dijit._AttachMixin", null, {
27245		// summary:
27246		//		Mixin for widgets to attach to dom nodes and setup events via
27247		//		convenient data-dojo-attach-point and data-dojo-attach-event DOM attributes.
27248		//
27249		//		Superclass of _TemplatedMixin, and can also be used standalone when templates are pre-rendered on the
27250		//		server.
27251		//
27252		//		Does not [yet] handle widgets like ContentPane with this.containerNode set.   It should skip
27253		//		scanning for data-dojo-attach-point and data-dojo-attach-event inside this.containerNode, but it
27254		//		doesn't.
27255
27256/*=====
27257		// _attachPoints: [private] String[]
27258		//		List of widget attribute names associated with data-dojo-attach-point=... in the
27259		//		template, ex: ["containerNode", "labelNode"]
27260		_attachPoints: [],
27261
27262		// _attachEvents: [private] Handle[]
27263		//		List of connections associated with data-dojo-attach-event=... in the
27264		//		template
27265		_attachEvents: [],
27266
27267		// attachScope: [public] Object
27268		//		Object to which attach points and events will be scoped.  Defaults
27269		//		to 'this'.
27270		attachScope: undefined,
27271
27272		// searchContainerNode: [protected] Boolean
27273		//		Search descendants of this.containerNode for data-dojo-attach-point and data-dojo-attach-event.
27274		//		Should generally be left false (the default value) both for performance and to avoid failures when
27275		//		this.containerNode holds other _AttachMixin instances with their own attach points and events.
27276 		searchContainerNode: false,
27277 =====*/
27278
27279		constructor: function(/*===== params, srcNodeRef =====*/){
27280			// summary:
27281			//		Create the widget.
27282			// params: Object|null
27283			//		Hash of initialization parameters for widget, including scalar values (like title, duration etc.)
27284			//		and functions, typically callbacks like onClick.
27285			//		The hash can contain any of the widget's properties, excluding read-only properties.
27286			// srcNodeRef: DOMNode|String?
27287			//		If a srcNodeRef (DOM node) is specified, replace srcNodeRef with my generated DOM tree.
27288
27289			this._attachPoints = [];
27290			this._attachEvents = [];
27291		},
27292
27293
27294		buildRendering: function(){
27295			// summary:
27296			//		Attach to DOM nodes marked with special attributes.
27297			// tags:
27298			//		protected
27299
27300			this.inherited(arguments);
27301
27302			// recurse through the node, looking for, and attaching to, our
27303			// attachment points and events, which should be defined on the template node.
27304			this._attachTemplateNodes(this.domNode);
27305
27306			this._beforeFillContent();		// hook for _WidgetsInTemplateMixin
27307		},
27308
27309		_beforeFillContent: function(){
27310		},
27311
27312		_attachTemplateNodes: function(rootNode){
27313			// summary:
27314			//		Iterate through the dom nodes and attach functions and nodes accordingly.
27315			// description:
27316			//		Map widget properties and functions to the handlers specified in
27317			//		the dom node and it's descendants. This function iterates over all
27318			//		nodes and looks for these properties:
27319			//
27320			//		- dojoAttachPoint/data-dojo-attach-point
27321			//		- dojoAttachEvent/data-dojo-attach-event
27322			// rootNode: DomNode
27323			//		The node to search for properties. All descendants will be searched.
27324			// tags:
27325			//		private
27326
27327			// DFS to process all nodes except those inside of this.containerNode
27328			var node = rootNode;
27329			while(true){
27330				if(node.nodeType == 1 && (this._processTemplateNode(node, function(n,p){ return n.getAttribute(p); },
27331						this._attach) || this.searchContainerNode) && node.firstChild){
27332					node = node.firstChild;
27333				}else{
27334					if(node == rootNode){ return; }
27335					while(!node.nextSibling){
27336						node = node.parentNode;
27337						if(node == rootNode){ return; }
27338					}
27339					node = node.nextSibling;
27340				}
27341			}
27342		},
27343
27344		_processTemplateNode: function(/*DOMNode|Widget*/ baseNode, getAttrFunc, attachFunc){
27345			// summary:
27346			//		Process data-dojo-attach-point and data-dojo-attach-event for given node or widget.
27347			//		Returns true if caller should process baseNode's children too.
27348
27349			var ret = true;
27350
27351			// Process data-dojo-attach-point
27352			var _attachScope = this.attachScope || this,
27353				attachPoint = getAttrFunc(baseNode, "dojoAttachPoint") || getAttrFunc(baseNode, "data-dojo-attach-point");
27354			if(attachPoint){
27355				var point, points = attachPoint.split(/\s*,\s*/);
27356				while((point = points.shift())){
27357					if(lang.isArray(_attachScope[point])){
27358						_attachScope[point].push(baseNode);
27359					}else{
27360						_attachScope[point] = baseNode;
27361					}
27362					ret = (point != "containerNode");
27363					this._attachPoints.push(point);
27364				}
27365			}
27366
27367			// Process data-dojo-attach-event
27368			var attachEvent = getAttrFunc(baseNode, "dojoAttachEvent") || getAttrFunc(baseNode, "data-dojo-attach-event");
27369			if(attachEvent){
27370				// NOTE: we want to support attributes that have the form
27371				// "domEvent: nativeEvent; ..."
27372				var event, events = attachEvent.split(/\s*,\s*/);
27373				var trim = lang.trim;
27374				while((event = events.shift())){
27375					if(event){
27376						var thisFunc = null;
27377						if(event.indexOf(":") != -1){
27378							// oh, if only JS had tuple assignment
27379							var funcNameArr = event.split(":");
27380							event = trim(funcNameArr[0]);
27381							thisFunc = trim(funcNameArr[1]);
27382						}else{
27383							event = trim(event);
27384						}
27385						if(!thisFunc){
27386							thisFunc = event;
27387						}
27388
27389						this._attachEvents.push(attachFunc(baseNode, event, lang.hitch(_attachScope, thisFunc)));
27390					}
27391				}
27392			}
27393
27394			return ret;
27395		},
27396
27397		_attach: function(node, type, func){
27398			// summary:
27399			//		Roughly corresponding to dojo/on, this is the default function for processing a
27400			//		data-dojo-attach-event.  Meant to attach to DOMNodes, not to widgets.
27401			// node: DOMNode
27402			//		The node to setup a listener on.
27403			// type: String
27404			//		Event name like "click".
27405			// getAttrFunc: Function
27406			//		Function to get the specified property for a given DomNode/Widget.
27407			// attachFunc: Function?
27408			//		Attaches an event handler from the specified node/widget to specified function.
27409
27410			// Map special type names like "mouseenter" to synthetic events.
27411			// Subclasses are responsible to require() dijit/a11yclick if they want to use it.
27412			type = type.replace(/^on/, "").toLowerCase();
27413			if(type == "dijitclick"){
27414				type = a11yclick || (a11yclick = require("./a11yclick"));
27415			}else{
27416				type = synthEvents[type] || type;
27417			}
27418
27419			return on(node, type, func);
27420		},
27421
27422		_detachTemplateNodes: function() {
27423			// summary:
27424			//		Detach and clean up the attachments made in _attachtempalteNodes.
27425
27426			// Delete all attach points to prevent IE6 memory leaks.
27427			var _attachScope = this.attachScope || this;
27428			array.forEach(this._attachPoints, function(point){
27429				delete _attachScope[point];
27430			});
27431			this._attachPoints = [];
27432
27433			// And same for event handlers
27434			array.forEach(this._attachEvents, function(handle){ handle.remove(); });
27435			this._attachEvents = [];
27436		},
27437
27438		destroyRendering: function(){
27439			this._detachTemplateNodes();
27440			this.inherited(arguments);
27441		}
27442	});
27443
27444	// These arguments can be specified for widgets which are used in templates.
27445	// Since any widget can be specified as sub widgets in template, mix it
27446	// into the base widget class.  (This is a hack, but it's effective.).
27447	// Remove for 2.0.   Also, hide from API doc parser.
27448	lang.extend(_WidgetBase, /*===== {} || =====*/ {
27449		dojoAttachEvent: "",
27450		dojoAttachPoint: ""
27451	});
27452	
27453	return _AttachMixin;
27454});
27455
27456},
27457'dojo/parser':function(){
27458define([
27459	"require", "./_base/kernel", "./_base/lang", "./_base/array", "./_base/config", "./dom", "./_base/window",
27460		"./_base/url", "./aspect", "./promise/all", "./date/stamp", "./Deferred", "./has", "./query", "./on", "./ready"
27461], function(require, dojo, dlang, darray, config, dom, dwindow, _Url, aspect, all, dates, Deferred, has, query, don, ready){
27462
27463	// module:
27464	//		dojo/parser
27465
27466	new Date("X"); // workaround for #11279, new Date("") == NaN
27467
27468	// data-dojo-props etc. is not restricted to JSON, it can be any javascript
27469	function myEval(text){
27470		return eval("(" + text + ")");
27471	}
27472
27473	// Widgets like BorderContainer add properties to _Widget via dojo.extend().
27474	// If BorderContainer is loaded after _Widget's parameter list has been cached,
27475	// we need to refresh that parameter list (for _Widget and all widgets that extend _Widget).
27476	var extendCnt = 0;
27477	aspect.after(dlang, "extend", function(){
27478		extendCnt++;
27479	}, true);
27480
27481	function getNameMap(ctor){
27482		// summary:
27483		//		Returns map from lowercase name to attribute name in class, ex: {onclick: "onClick"}
27484		var map = ctor._nameCaseMap, proto = ctor.prototype;
27485
27486		// Create the map if it's undefined.
27487		// Refresh the map if a superclass was possibly extended with new methods since the map was created.
27488		if(!map || map._extendCnt < extendCnt){
27489			map = ctor._nameCaseMap = {};
27490			for(var name in proto){
27491				if(name.charAt(0) === "_"){
27492					continue;
27493				}	// skip internal properties
27494				map[name.toLowerCase()] = name;
27495			}
27496			map._extendCnt = extendCnt;
27497		}
27498		return map;
27499	}
27500
27501	// Map from widget name or list of widget names(ex: "dijit/form/Button,acme/MyMixin") to a constructor.
27502	var _ctorMap = {};
27503
27504	function getCtor(/*String[]*/ types, /*Function?*/ contextRequire){
27505		// summary:
27506		//		Retrieves a constructor.  If the types array contains more than one class/MID then the
27507		//		subsequent classes will be mixed into the first class and a unique constructor will be
27508		//		returned for that array.
27509
27510		var ts = types.join();
27511		if(!_ctorMap[ts]){
27512			var mixins = [];
27513			for(var i = 0, l = types.length; i < l; i++){
27514				var t = types[i];
vendor: 31,491 bytes, lines 27515-28309
27515				// TODO: Consider swapping getObject and require in the future
27516				mixins[mixins.length] = (_ctorMap[t] = _ctorMap[t] || (dlang.getObject(t) || (~t.indexOf('/') &&
27517					(contextRequire ? contextRequire(t) : require(t)))));
27518			}
27519			var ctor = mixins.shift();
27520			_ctorMap[ts] = mixins.length ? (ctor.createSubclass ? ctor.createSubclass(mixins) : ctor.extend.apply(ctor, mixins)) : ctor;
27521		}
27522
27523		return _ctorMap[ts];
27524	}
27525
27526	var parser = {
27527		// summary:
27528		//		The Dom/Widget parsing package
27529
27530		_clearCache: function(){
27531			// summary:
27532			//		Clear cached data.   Used mainly for benchmarking.
27533			extendCnt++;
27534			_ctorMap = {};
27535		},
27536
27537		_functionFromScript: function(script, attrData){
27538			// summary:
27539			//		Convert a `<script type="dojo/method" args="a, b, c"> ... </script>`
27540			//		into a function
27541			// script: DOMNode
27542			//		The `<script>` DOMNode
27543			// attrData: String
27544			//		For HTML5 compliance, searches for attrData + "args" (typically
27545			//		"data-dojo-args") instead of "args"
27546			var preamble = "",
27547				suffix = "",
27548				argsStr = (script.getAttribute(attrData + "args") || script.getAttribute("args")),
27549				withStr = script.getAttribute("with");
27550
27551			// Convert any arguments supplied in script tag into an array to be passed to the
27552			var fnArgs = (argsStr || "").split(/\s*,\s*/);
27553
27554			if(withStr && withStr.length){
27555				darray.forEach(withStr.split(/\s*,\s*/), function(part){
27556					preamble += "with(" + part + "){";
27557					suffix += "}";
27558				});
27559			}
27560
27561			return new Function(fnArgs, preamble + script.innerHTML + suffix);
27562		},
27563
27564		instantiate: function(nodes, mixin, options){
27565			// summary:
27566			//		Takes array of nodes, and turns them into class instances and
27567			//		potentially calls a startup method to allow them to connect with
27568			//		any children.
27569			// nodes: Array
27570			//		Array of DOM nodes
27571			// mixin: Object?
27572			//		An object that will be mixed in with each node in the array.
27573			//		Values in the mixin will override values in the node, if they
27574			//		exist.
27575			// options: Object?
27576			//		An object used to hold kwArgs for instantiation.
27577			//		See parse.options argument for details.
27578			// returns:
27579			//		Array of instances.
27580
27581			mixin = mixin || {};
27582			options = options || {};
27583
27584			var dojoType = (options.scope || dojo._scopeName) + "Type", // typically "dojoType"
27585				attrData = "data-" + (options.scope || dojo._scopeName) + "-", // typically "data-dojo-"
27586				dataDojoType = attrData + "type", // typically "data-dojo-type"
27587				dataDojoMixins = attrData + "mixins";					// typically "data-dojo-mixins"
27588
27589			var list = [];
27590			darray.forEach(nodes, function(node){
27591				var type = dojoType in mixin ? mixin[dojoType] : node.getAttribute(dataDojoType) || node.getAttribute(dojoType);
27592				if(type){
27593					var mixinsValue = node.getAttribute(dataDojoMixins),
27594						types = mixinsValue ? [type].concat(mixinsValue.split(/\s*,\s*/)) : [type];
27595
27596					list.push({
27597						node: node,
27598						types: types
27599					});
27600				}
27601			});
27602
27603			// Instantiate the nodes and return the list of instances.
27604			return this._instantiate(list, mixin, options);
27605		},
27606
27607		_instantiate: function(nodes, mixin, options, returnPromise){
27608			// summary:
27609			//		Takes array of objects representing nodes, and turns them into class instances and
27610			//		potentially calls a startup method to allow them to connect with
27611			//		any children.
27612			// nodes: Array
27613			//		Array of objects like
27614			//	|		{
27615			//	|			ctor: Function (may be null)
27616			//	|			types: ["dijit/form/Button", "acme/MyMixin"] (used if ctor not specified)
27617			//	|			node: DOMNode,
27618			//	|			scripts: [ ... ],	// array of <script type="dojo/..."> children of node
27619			//	|			inherited: { ... }	// settings inherited from ancestors like dir, theme, etc.
27620			//	|		}
27621			// mixin: Object
27622			//		An object that will be mixed in with each node in the array.
27623			//		Values in the mixin will override values in the node, if they
27624			//		exist.
27625			// options: Object
27626			//		An options object used to hold kwArgs for instantiation.
27627			//		See parse.options argument for details.
27628			// returnPromise: Boolean
27629			//		Return a Promise rather than the instance; supports asynchronous widget creation.
27630			// returns:
27631			//		Array of instances, or if returnPromise is true, a promise for array of instances
27632			//		that resolves when instances have finished initializing.
27633
27634			// Call widget constructors.   Some may be asynchronous and return promises.
27635			var thelist = darray.map(nodes, function(obj){
27636				var ctor = obj.ctor || getCtor(obj.types, options.contextRequire);
27637				// If we still haven't resolved a ctor, it is fatal now
27638				if(!ctor){
27639					throw new Error("Unable to resolve constructor for: '" + obj.types.join() + "'");
27640				}
27641				return this.construct(ctor, obj.node, mixin, options, obj.scripts, obj.inherited);
27642			}, this);
27643
27644			// After all widget construction finishes, call startup on each top level instance if it makes sense (as for
27645			// widgets).  Parent widgets will recursively call startup on their (non-top level) children
27646			function onConstruct(thelist){
27647				if(!mixin._started && !options.noStart){
27648					darray.forEach(thelist, function(instance){
27649						if(typeof instance.startup === "function" && !instance._started){
27650							instance.startup();
27651						}
27652					});
27653				}
27654
27655				return thelist;
27656			}
27657
27658			if(returnPromise){
27659				return all(thelist).then(onConstruct);
27660			}else{
27661				// Back-compat path, remove for 2.0
27662				return onConstruct(thelist);
27663			}
27664		},
27665
27666		construct: function(ctor, node, mixin, options, scripts, inherited){
27667			// summary:
27668			//		Calls new ctor(params, node), where params is the hash of parameters specified on the node,
27669			//		excluding data-dojo-type and data-dojo-mixins.   Does not call startup().
27670			// ctor: Function
27671			//		Widget constructor.
27672			// node: DOMNode
27673			//		This node will be replaced/attached to by the widget.  It also specifies the arguments to pass to ctor.
27674			// mixin: Object?
27675			//		Attributes in this object will be passed as parameters to ctor,
27676			//		overriding attributes specified on the node.
27677			// options: Object?
27678			//		An options object used to hold kwArgs for instantiation.   See parse.options argument for details.
27679			// scripts: DomNode[]?
27680			//		Array of `<script type="dojo/*">` DOMNodes.  If not specified, will search for `<script>` tags inside node.
27681			// inherited: Object?
27682			//		Settings from dir=rtl or lang=... on a node above this node.   Overrides options.inherited.
27683			// returns:
27684			//		Instance or Promise for the instance, if markupFactory() itself returned a promise
27685
27686			var proto = ctor && ctor.prototype;
27687			options = options || {};
27688
27689			// Setup hash to hold parameter settings for this widget.	Start with the parameter
27690			// settings inherited from ancestors ("dir" and "lang").
27691			// Inherited setting may later be overridden by explicit settings on node itself.
27692			var params = {};
27693
27694			if(options.defaults){
27695				// settings for the document itself (or whatever subtree is being parsed)
27696				dlang.mixin(params, options.defaults);
27697			}
27698			if(inherited){
27699				// settings from dir=rtl or lang=... on a node above this node
27700				dlang.mixin(params, inherited);
27701			}
27702
27703			// Get list of attributes explicitly listed in the markup
27704			var attributes;
27705			if(has("dom-attributes-explicit")){
27706				// Standard path to get list of user specified attributes
27707				attributes = node.attributes;
27708			}else if(has("dom-attributes-specified-flag")){
27709				// Special processing needed for IE8, to skip a few faux values in attributes[]
27710				attributes = darray.filter(node.attributes, function(a){
27711					return a.specified;
27712				});
27713			}else{
27714				// Special path for IE6-7, avoid (sometimes >100) bogus entries in node.attributes
27715				var clone = /^input$|^img$/i.test(node.nodeName) ? node : node.cloneNode(false),
27716					attrs = clone.outerHTML.replace(/=[^\s"']+|="[^"]*"|='[^']*'/g, "").replace(/^\s*<[a-zA-Z0-9]*\s*/, "").replace(/\s*>.*$/, "");
27717
27718				attributes = darray.map(attrs.split(/\s+/), function(name){
27719					var lcName = name.toLowerCase();
27720					return {
27721						name: name,
27722						// getAttribute() doesn't work for button.value, returns innerHTML of button.
27723						// but getAttributeNode().value doesn't work for the form.encType or li.value
27724						value: (node.nodeName == "LI" && name == "value") || lcName == "enctype" ?
27725							node.getAttribute(lcName) : node.getAttributeNode(lcName).value
27726					};
27727				});
27728			}
27729
27730			// Hash to convert scoped attribute name (ex: data-dojo17-params) to something friendly (ex: data-dojo-params)
27731			// TODO: remove scope for 2.0
27732			var scope = options.scope || dojo._scopeName,
27733				attrData = "data-" + scope + "-", // typically "data-dojo-"
27734				hash = {};
27735			if(scope !== "dojo"){
27736				hash[attrData + "props"] = "data-dojo-props";
27737				hash[attrData + "type"] = "data-dojo-type";
27738				hash[attrData + "mixins"] = "data-dojo-mixins";
27739				hash[scope + "type"] = "dojoType";
27740				hash[attrData + "id"] = "data-dojo-id";
27741			}
27742
27743			// Read in attributes and process them, including data-dojo-props, data-dojo-type,
27744			// dojoAttachPoint, etc., as well as normal foo=bar attributes.
27745			var i = 0, item, funcAttrs = [], jsname, extra;
27746			while(item = attributes[i++]){
27747				var name = item.name,
27748					lcName = name.toLowerCase(),
27749					value = item.value;
27750
27751				switch(hash[lcName] || lcName){
27752				// Already processed, just ignore
27753				case "data-dojo-type":
27754				case "dojotype":
27755				case "data-dojo-mixins":
27756					break;
27757
27758				// Data-dojo-props.   Save for later to make sure it overrides direct foo=bar settings
27759				case "data-dojo-props":
27760					extra = value;
27761					break;
27762
27763				// data-dojo-id or jsId. TODO: drop jsId in 2.0
27764				case "data-dojo-id":
27765				case "jsid":
27766					jsname = value;
27767					break;
27768
27769				// For the benefit of _Templated
27770				case "data-dojo-attach-point":
27771				case "dojoattachpoint":
27772					params.dojoAttachPoint = value;
27773					break;
27774				case "data-dojo-attach-event":
27775				case "dojoattachevent":
27776					params.dojoAttachEvent = value;
27777					break;
27778
27779				// Special parameter handling needed for IE
27780				case "class":
27781					params["class"] = node.className;
27782					break;
27783				case "style":
27784					params["style"] = node.style && node.style.cssText;
27785					break;
27786				default:
27787					// Normal attribute, ex: value="123"
27788
27789					// Find attribute in widget corresponding to specified name.
27790					// May involve case conversion, ex: onclick --> onClick
27791					if(!(name in proto)){
27792						var map = getNameMap(ctor);
27793						name = map[lcName] || name;
27794					}
27795
27796					// Set params[name] to value, doing type conversion
27797					if(name in proto){
27798						switch(typeof proto[name]){
27799						case "string":
27800							params[name] = value;
27801							break;
27802						case "number":
27803							params[name] = value.length ? Number(value) : NaN;
27804							break;
27805						case "boolean":
27806							// for checked/disabled value might be "" or "checked".	 interpret as true.
27807							params[name] = value.toLowerCase() != "false";
27808							break;
27809						case "function":
27810							if(value === "" || value.search(/[^\w\.]+/i) != -1){
27811								// The user has specified some text for a function like "return x+5"
27812								params[name] = new Function(value);
27813							}else{
27814								// The user has specified the name of a global function like "myOnClick"
27815								// or a single word function "return"
27816								params[name] = dlang.getObject(value, false) || new Function(value);
27817							}
27818							funcAttrs.push(name);	// prevent "double connect", see #15026
27819							break;
27820						default:
27821							var pVal = proto[name];
27822							params[name] =
27823								(pVal && "length" in pVal) ? (value ? value.split(/\s*,\s*/) : []) :	// array
27824									(pVal instanceof Date) ?
27825										(value == "" ? new Date("") :	// the NaN of dates
27826										value == "now" ? new Date() :	// current date
27827										dates.fromISOString(value)) :
27828								(pVal instanceof _Url) ? (dojo.baseUrl + value) :
27829								myEval(value);
27830						}
27831					}else{
27832						params[name] = value;
27833					}
27834				}
27835			}
27836
27837			// Remove function attributes from DOMNode to prevent "double connect" problem, see #15026.
27838			// Do this as a separate loop since attributes[] is often a live collection (depends on the browser though).
27839			for(var j = 0; j < funcAttrs.length; j++){
27840				var lcfname = funcAttrs[j].toLowerCase();
27841				node.removeAttribute(lcfname);
27842				node[lcfname] = null;
27843			}
27844
27845			// Mix things found in data-dojo-props into the params, overriding any direct settings
27846			if(extra){
27847				try{
27848					extra = myEval.call(options.propsThis, "{" + extra + "}");
27849					dlang.mixin(params, extra);
27850				}catch(e){
27851					// give the user a pointer to their invalid parameters. FIXME: can we kill this in production?
27852					throw new Error(e.toString() + " in data-dojo-props='" + extra + "'");
27853				}
27854			}
27855
27856			// Any parameters specified in "mixin" override everything else.
27857			dlang.mixin(params, mixin);
27858
27859			// Get <script> nodes associated with this widget, if they weren't specified explicitly
27860			if(!scripts){
27861				scripts = (ctor && (ctor._noScript || proto._noScript) ? [] : query("> script[type^='dojo/']", node));
27862			}
27863
27864			// Process <script type="dojo/*"> script tags
27865			// <script type="dojo/method" data-dojo-event="foo"> tags are added to params, and passed to
27866			// the widget on instantiation.
27867			// <script type="dojo/method"> tags (with no event) are executed after instantiation
27868			// <script type="dojo/connect" data-dojo-event="foo"> tags are dojo.connected after instantiation,
27869			// and likewise with <script type="dojo/aspect" data-dojo-method="foo">
27870			// <script type="dojo/watch" data-dojo-prop="foo"> tags are dojo.watch after instantiation
27871			// <script type="dojo/on" data-dojo-event="foo"> tags are dojo.on after instantiation
27872			// note: dojo/* script tags cannot exist in self closing widgets, like <input />
27873			var aspects = [],	// aspects to connect after instantiation
27874				calls = [],		// functions to call after instantiation
27875				watches = [],  // functions to watch after instantiation
27876				ons = []; // functions to on after instantiation
27877
27878			if(scripts){
27879				for(i = 0; i < scripts.length; i++){
27880					var script = scripts[i];
27881					node.removeChild(script);
27882					// FIXME: drop event="" support in 2.0. use data-dojo-event="" instead
27883					var event = (script.getAttribute(attrData + "event") || script.getAttribute("event")),
27884						prop = script.getAttribute(attrData + "prop"),
27885						method = script.getAttribute(attrData + "method"),
27886						advice = script.getAttribute(attrData + "advice"),
27887						scriptType = script.getAttribute("type"),
27888						nf = this._functionFromScript(script, attrData);
27889					if(event){
27890						if(scriptType == "dojo/connect"){
27891							aspects.push({ method: event, func: nf });
27892						}else if(scriptType == "dojo/on"){
27893							ons.push({ event: event, func: nf });
27894						}else{
27895							// <script type="dojo/method" data-dojo-event="foo">
27896							// TODO for 2.0: use data-dojo-method="foo" instead (also affects dijit/Declaration)
27897							params[event] = nf;
27898						}
27899					}else if(scriptType == "dojo/aspect"){
27900						aspects.push({ method: method, advice: advice, func: nf });
27901					}else if(scriptType == "dojo/watch"){
27902						watches.push({ prop: prop, func: nf });
27903					}else{
27904						calls.push(nf);
27905					}
27906				}
27907			}
27908
27909			// create the instance
27910			var markupFactory = ctor.markupFactory || proto.markupFactory;
27911			var instance = markupFactory ? markupFactory(params, node, ctor) : new ctor(params, node);
27912
27913			function onInstantiate(instance){
27914				// map it to the JS namespace if that makes sense
27915				if(jsname){
27916					dlang.setObject(jsname, instance);
27917				}
27918
27919				// process connections and startup functions
27920				for(i = 0; i < aspects.length; i++){
27921					aspect[aspects[i].advice || "after"](instance, aspects[i].method, dlang.hitch(instance, aspects[i].func), true);
27922				}
27923				for(i = 0; i < calls.length; i++){
27924					calls[i].call(instance);
27925				}
27926				for(i = 0; i < watches.length; i++){
27927					instance.watch(watches[i].prop, watches[i].func);
27928				}
27929				for(i = 0; i < ons.length; i++){
27930					don(instance, ons[i].event, ons[i].func);
27931				}
27932
27933				return instance;
27934			}
27935
27936			if(instance.then){
27937				return instance.then(onInstantiate);
27938			}else{
27939				return onInstantiate(instance);
27940			}
27941		},
27942
27943		scan: function(root, options){
27944			// summary:
27945			//		Scan a DOM tree and return an array of objects representing the DOMNodes
27946			//		that need to be turned into widgets.
27947			// description:
27948			//		Search specified node (or document root node) recursively for class instances
27949			//		and return an array of objects that represent potential widgets to be
27950			//		instantiated. Searches for either data-dojo-type="MID" or dojoType="MID" where
27951			//		"MID" is a module ID like "dijit/form/Button" or a fully qualified Class name
27952			//		like "dijit/form/Button".  If the MID is not currently available, scan will
27953			//		attempt to require() in the module.
27954			//
27955			//		See parser.parse() for details of markup.
27956			// root: DomNode?
27957			//		A default starting root node from which to start the parsing. Can be
27958			//		omitted, defaulting to the entire document. If omitted, the `options`
27959			//		object can be passed in this place. If the `options` object has a
27960			//		`rootNode` member, that is used.
27961			// options: Object
27962			//		a kwArgs options object, see parse() for details
27963			//
27964			// returns: Promise
27965			//		A promise that is resolved with the nodes that have been parsed.
27966
27967			var list = [], // Output List
27968				mids = [], // An array of modules that are not yet loaded
27969				midsHash = {}; // Used to keep the mids array unique
27970
27971			var dojoType = (options.scope || dojo._scopeName) + "Type", // typically "dojoType"
27972				attrData = "data-" + (options.scope || dojo._scopeName) + "-", // typically "data-dojo-"
27973				dataDojoType = attrData + "type", // typically "data-dojo-type"
27974				dataDojoTextDir = attrData + "textdir", // typically "data-dojo-textdir"
27975				dataDojoMixins = attrData + "mixins";					// typically "data-dojo-mixins"
27976
27977			// Info on DOMNode currently being processed
27978			var node = root.firstChild;
27979
27980			// Info on parent of DOMNode currently being processed
27981			//	- inherited: dir, lang, and textDir setting of parent, or inherited by parent
27982			//	- parent: pointer to identical structure for my parent (or null if no parent)
27983			//	- scripts: if specified, collects <script type="dojo/..."> type nodes from children
27984			var inherited = options.inherited;
27985			if(!inherited){
27986				function findAncestorAttr(node, attr){
27987					return (node.getAttribute && node.getAttribute(attr)) ||
27988						(node.parentNode && findAncestorAttr(node.parentNode, attr));
27989				}
27990
27991				inherited = {
27992					dir: findAncestorAttr(root, "dir"),
27993					lang: findAncestorAttr(root, "lang"),
27994					textDir: findAncestorAttr(root, dataDojoTextDir)
27995				};
27996				for(var key in inherited){
27997					if(!inherited[key]){
27998						delete inherited[key];
27999					}
28000				}
28001			}
28002
28003			// Metadata about parent node
28004			var parent = {
28005				inherited: inherited
28006			};
28007
28008			// For collecting <script type="dojo/..."> type nodes (when null, we don't need to collect)
28009			var scripts;
28010
28011			// when true, only look for <script type="dojo/..."> tags, and don't recurse to children
28012			var scriptsOnly;
28013
28014			function getEffective(parent){
28015				// summary:
28016				//		Get effective dir, lang, textDir settings for specified obj
28017				//		(matching "parent" object structure above), and do caching.
28018				//		Take care not to return null entries.
28019				if(!parent.inherited){
28020					parent.inherited = {};
28021					var node = parent.node,
28022						grandparent = getEffective(parent.parent);
28023					var inherited = {
28024						dir: node.getAttribute("dir") || grandparent.dir,
28025						lang: node.getAttribute("lang") || grandparent.lang,
28026						textDir: node.getAttribute(dataDojoTextDir) || grandparent.textDir
28027					};
28028					for(var key in inherited){
28029						if(inherited[key]){
28030							parent.inherited[key] = inherited[key];
28031						}
28032					}
28033				}
28034				return parent.inherited;
28035			}
28036
28037			// DFS on DOM tree, collecting nodes with data-dojo-type specified.
28038			while(true){
28039				if(!node){
28040					// Finished this level, continue to parent's next sibling
28041					if(!parent || !parent.node){
28042						break;
28043					}
28044					node = parent.node.nextSibling;
28045					scriptsOnly = false;
28046					parent = parent.parent;
28047					scripts = parent.scripts;
28048					continue;
28049				}
28050
28051				if(node.nodeType != 1){
28052					// Text or comment node, skip to next sibling
28053					node = node.nextSibling;
28054					continue;
28055				}
28056
28057				if(scripts && node.nodeName.toLowerCase() == "script"){
28058					// Save <script type="dojo/..."> for parent, then continue to next sibling
28059					type = node.getAttribute("type");
28060					if(type && /^dojo\/\w/i.test(type)){
28061						scripts.push(node);
28062					}
28063					node = node.nextSibling;
28064					continue;
28065				}
28066				if(scriptsOnly){
28067					// scriptsOnly flag is set, we have already collected scripts if the parent wants them, so now we shouldn't
28068					// continue further analysis of the node and will continue to the next sibling
28069					node = node.nextSibling;
28070					continue;
28071				}
28072
28073				// Check for data-dojo-type attribute, fallback to backward compatible dojoType
28074				// TODO: Remove dojoType in 2.0
28075				var type = node.getAttribute(dataDojoType) || node.getAttribute(dojoType);
28076
28077				// Short circuit for leaf nodes containing nothing [but text]
28078				var firstChild = node.firstChild;
28079				if(!type && (!firstChild || (firstChild.nodeType == 3 && !firstChild.nextSibling))){
28080					node = node.nextSibling;
28081					continue;
28082				}
28083
28084				// Meta data about current node
28085				var current;
28086
28087				var ctor = null;
28088				if(type){
28089					// If dojoType/data-dojo-type specified, add to output array of nodes to instantiate.
28090					var mixinsValue = node.getAttribute(dataDojoMixins),
28091						types = mixinsValue ? [type].concat(mixinsValue.split(/\s*,\s*/)) : [type];
28092
28093					// Note: won't find classes declared via dojo/Declaration or any modules that haven't been
28094					// loaded yet so use try/catch to avoid throw from require()
28095					try{
28096						ctor = getCtor(types, options.contextRequire);
28097					}catch(e){}
28098
28099					// If the constructor was not found, check to see if it has modules that can be loaded
28100					if(!ctor){
28101						darray.forEach(types, function(t){
28102							if(~t.indexOf('/') && !midsHash[t]){
28103								// If the type looks like a MID and it currently isn't in the array of MIDs to load, add it.
28104								midsHash[t] = true;
28105								mids[mids.length] = t;
28106							}
28107						});
28108					}
28109
28110					var childScripts = ctor && !ctor.prototype._noScript ? [] : null; // <script> nodes that are parent's children
28111
28112					// Setup meta data about this widget node, and save it to list of nodes to instantiate
28113					current = {
28114						types: types,
28115						ctor: ctor,
28116						parent: parent,
28117						node: node,
28118						scripts: childScripts
28119					};
28120					current.inherited = getEffective(current); // dir & lang settings for current node, explicit or inherited
28121					list.push(current);
28122				}else{
28123					// Meta data about this non-widget node
28124					current = {
28125						node: node,
28126						scripts: scripts,
28127						parent: parent
28128					};
28129				}
28130
28131				// Recurse, collecting <script type="dojo/..."> children, and also looking for
28132				// descendant nodes with dojoType specified (unless the widget has the stopParser flag).
28133				// When finished with children, go to my next sibling.
28134				scripts = childScripts;
28135				scriptsOnly = node.stopParser || (ctor && ctor.prototype.stopParser && !(options.template));
28136				parent = current;
28137				node = firstChild;
28138			}
28139
28140			var d = new Deferred();
28141
28142			// If there are modules to load then require them in
28143			if(mids.length){
28144				// Warn that there are modules being auto-required
28145				if( 0 ){
28146					console.warn("WARNING: Modules being Auto-Required: " + mids.join(", "));
28147				}
28148				var r = options.contextRequire || require;
28149				r(mids, function(){
28150					// Go through list of widget nodes, filling in missing constructors, and filtering out nodes that shouldn't
28151					// be instantiated due to a stopParser flag on an ancestor that we belatedly learned about due to
28152					// auto-require of a module like ContentPane.   Assumes list is in DFS order.
28153					d.resolve(darray.filter(list, function(widget){
28154						if(!widget.ctor){
28155							// Attempt to find the constructor again.   Still won't find classes defined via
28156							// dijit/Declaration so need to try/catch.
28157							try{
28158								widget.ctor = getCtor(widget.types, options.contextRequire);
28159							}catch(e){}
28160						}
28161
28162						// Get the parent widget
28163						var parent = widget.parent;
28164						while(parent && !parent.types){
28165							parent = parent.parent;
28166						}
28167
28168						// Return false if this node should be skipped due to stopParser on an ancestor.
28169						// Since list[] is in DFS order, this loop will always set parent.instantiateChildren before
28170						// trying to compute widget.instantiate.
28171						var proto = widget.ctor && widget.ctor.prototype;
28172						widget.instantiateChildren = !(proto && proto.stopParser && !(options.template));
28173						widget.instantiate = !parent || (parent.instantiate && parent.instantiateChildren);
28174						return widget.instantiate;
28175					}));
28176				});
28177			}else{
28178				// There were no modules to load, so just resolve with the parsed nodes.   This separate code path is for
28179				// efficiency, to avoid running the require() and the callback code above.
28180				d.resolve(list);
28181			}
28182
28183			// Return the promise
28184			return d.promise;
28185		},
28186
28187		_require: function(/*DOMNode*/ script, /*Object?*/ options){
28188			// summary:
28189			//		Helper for _scanAMD().  Takes a `<script type=dojo/require>bar: "acme/bar", ...</script>` node,
28190			//		calls require() to load the specified modules and (asynchronously) assign them to the specified global
28191			//		variables, and returns a Promise for when that operation completes.
28192			//
28193			//		In the example above, it is effectively doing a require(["acme/bar", ...], function(a){ bar = a; }).
28194
28195			var hash = myEval("{" + script.innerHTML + "}"), // can't use dojo/json::parse() because maybe no quotes
28196				vars = [],
28197				mids = [],
28198				d = new Deferred();
28199
28200			var contextRequire = (options && options.contextRequire) || require;
28201
28202			for(var name in hash){
28203				vars.push(name);
28204				mids.push(hash[name]);
28205			}
28206
28207			contextRequire(mids, function(){
28208				for(var i = 0; i < vars.length; i++){
28209					dlang.setObject(vars[i], arguments[i]);
28210				}
28211				d.resolve(arguments);
28212			});
28213
28214			return d.promise;
28215		},
28216
28217		_scanAmd: function(root, options){
28218			// summary:
28219			//		Scans the DOM for any declarative requires and returns their values.
28220			// description:
28221			//		Looks for `<script type=dojo/require>bar: "acme/bar", ...</script>` node, calls require() to load the
28222			//		specified modules and (asynchronously) assign them to the specified global variables,
28223			//		and returns a Promise for when those operations complete.
28224			// root: DomNode
28225			//		The node to base the scan from.
28226			// options: Object?
28227			//		a kwArgs options object, see parse() for details
28228
28229			// Promise that resolves when all the <script type=dojo/require> nodes have finished loading.
28230			var deferred = new Deferred(),
28231				promise = deferred.promise;
28232			deferred.resolve(true);
28233
28234			var self = this;
28235			query("script[type='dojo/require']", root).forEach(function(node){
28236				// Fire off require() call for specified modules.  Chain this require to fire after
28237				// any previous requires complete, so that layers can be loaded before individual module require()'s fire.
28238				promise = promise.then(function(){
28239					return self._require(node, options);
28240				});
28241
28242				// Remove from DOM so it isn't seen again
28243				node.parentNode.removeChild(node);
28244			});
28245
28246			return promise;
28247		},
28248
28249		parse: function(rootNode, options){
28250			// summary:
28251			//		Scan the DOM for class instances, and instantiate them.
28252			// description:
28253			//		Search specified node (or root node) recursively for class instances,
28254			//		and instantiate them. Searches for either data-dojo-type="Class" or
28255			//		dojoType="Class" where "Class" is a a fully qualified class name,
28256			//		like `dijit/form/Button`
28257			//
28258			//		Using `data-dojo-type`:
28259			//		Attributes using can be mixed into the parameters used to instantiate the
28260			//		Class by using a `data-dojo-props` attribute on the node being converted.
28261			//		`data-dojo-props` should be a string attribute to be converted from JSON.
28262			//
28263			//		Using `dojoType`:
28264			//		Attributes are read from the original domNode and converted to appropriate
28265			//		types by looking up the Class prototype values. This is the default behavior
28266			//		from Dojo 1.0 to Dojo 1.5. `dojoType` support is deprecated, and will
28267			//		go away in Dojo 2.0.
28268			// rootNode: DomNode?
28269			//		A default starting root node from which to start the parsing. Can be
28270			//		omitted, defaulting to the entire document. If omitted, the `options`
28271			//		object can be passed in this place. If the `options` object has a
28272			//		`rootNode` member, that is used.
28273			// options: Object?
28274			//		A hash of options.
28275			//
28276			//		- noStart: Boolean?:
28277			//			when set will prevent the parser from calling .startup()
28278			//			when locating the nodes.
28279			//		- rootNode: DomNode?:
28280			//			identical to the function's `rootNode` argument, though
28281			//			allowed to be passed in via this `options object.
28282			//		- template: Boolean:
28283			//			If true, ignores ContentPane's stopParser flag and parses contents inside of
28284			//			a ContentPane inside of a template.   This allows dojoAttachPoint on widgets/nodes
28285			//			nested inside the ContentPane to work.
28286			//		- inherited: Object:
28287			//			Hash possibly containing dir and lang settings to be applied to
28288			//			parsed widgets, unless there's another setting on a sub-node that overrides
28289			//		- scope: String:
28290			//			Root for attribute names to search for.   If scopeName is dojo,
28291			//			will search for data-dojo-type (or dojoType).   For backwards compatibility
28292			//			reasons defaults to dojo._scopeName (which is "dojo" except when
28293			//			multi-version support is used, when it will be something like dojo16, dojo20, etc.)
28294			//		- propsThis: Object:
28295			//			If specified, "this" referenced from data-dojo-props will refer to propsThis.
28296			//			Intended for use from the widgets-in-template feature of `dijit._WidgetsInTemplateMixin`
28297			//		- contextRequire: Function:
28298			//			If specified, this require is utilised for looking resolving modules instead of the
28299			//			`dojo/parser` context `require()`.  Intended for use from the widgets-in-template feature of
28300			//			`dijit._WidgetsInTemplateMixin`.
28301			// returns: Mixed
28302			//		Returns a blended object that is an array of the instantiated objects, but also can include
28303			//		a promise that is resolved with the instantiated objects.  This is done for backwards
28304			//		compatibility.  If the parser auto-requires modules, it will always behave in a promise
28305			//		fashion and `parser.parse().then(function(instances){...})` should be used.
28306			// example:
28307			//		Parse all widgets on a page:
28308			//	|		parser.parse();
28309			// example:
28310			//		Parse all classes within the node with id="foo"
28311			//	|		parser.parse(dojo.byId('foo'));
28312			// example:
28313			//		Parse all classes in a page, but do not call .startup() on any
28314			//		child
28315			//	|		parser.parse({ noStart: true })
28316			// example:
28317			//		Parse all classes in a node, but do not call .startup()
28318			//	|		parser.parse(someNode, { noStart:true });
28319			//	|		// or
28320			//	|		parser.parse({ noStart:true, rootNode: someNode });
28321
28322			// determine the root node and options based on the passed arguments.
28323			var root;
28324			if(!options && rootNode && rootNode.rootNode){
28325				options = rootNode;
28326				root = options.rootNode;
28327			}else if(rootNode && dlang.isObject(rootNode) && !("nodeType" in rootNode)){
28328				options = rootNode;
28329			}else{
28330				root = rootNode;
28331			}
28332			root = root ? dom.byId(root) : dwindow.body();
28333
28334			options = options || {};
28335
28336			var mixin = options.template ? { template: true } : {},
28337				instances = [],
28338				self = this;
28339
28340			// First scan for any <script type=dojo/require> nodes, and execute.
28341			// Then scan for all nodes with data-dojo-type, and load any unloaded modules.
28342			// Then build the object instances.  Add instances to already existing (but empty) instances[] array,
28343			// which may already have been returned to caller.  Also, use otherwise to collect and throw any errors
28344			// that occur during the parse().
28345			var p =
28346				this._scanAmd(root, options).then(function(){
28347					return self.scan(root, options);
28348				}).then(function(parsedNodes){
28349					return self._instantiate(parsedNodes, mixin, options, true);
28350				}).then(function(_instances){
28351					// Copy the instances into the instances[] array we declared above, and are accessing as
28352					// our return value.
28353					return instances = instances.concat(_instances);
28354				}).otherwise(function(e){
28355					// TODO Modify to follow better pattern for promise error management when available
28356					console.error("dojo/parser::parse() error", e);
28357					throw e;
28358				});
28359
28360			// Blend the array with the promise
28361			dlang.mixin(instances, p);
28362			return instances;
28363		}
28364	};
28365
28366	if( 1 ){
28367		dojo.parser = parser;
28368	}
28369
28370	// Register the parser callback. It should be the first callback
28371	// after the a11y test.
28372	if(config.parseOnLoad){
28373		ready(100, parser, "parse");
28374	}
28375
28376	return parser;
28377});
28378
28379},
28380'dojo/_base/url':function(){
28381define(["./kernel"], function(dojo){
28382	// module:
28383	//		dojo/url
28384
28385	var
28386		ore = new RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"),
28387		ire = new RegExp("^((([^\\[:]+):)?([^@]+)@)?(\\[([^\\]]+)\\]|([^\\[:]*))(:([0-9]+))?$"),
28388		_Url = function(){
28389			var n = null,
28390				_a = arguments,
28391				uri = [_a[0]];
28392			// resolve uri components relative to each other
28393			for(var i = 1; i<_a.length; i++){
28394				if(!_a[i]){ continue; }
28395
28396				// Safari doesn't support this.constructor so we have to be explicit
28397				// FIXME: Tracked (and fixed) in Webkit bug 3537.
28398				//		http://bugs.webkit.org/show_bug.cgi?id=3537
28399				var relobj = new _Url(_a[i]+""),
28400					uriobj = new _Url(uri[0]+"");
28401
28402				if(
28403					relobj.path == "" &&
28404					!relobj.scheme &&
28405					!relobj.authority &&
28406					!relobj.query
28407				){
28408					if(relobj.fragment != n){
28409						uriobj.fragment = relobj.fragment;
28410					}
28411					relobj = uriobj;
28412				}else if(!relobj.scheme){
28413					relobj.scheme = uriobj.scheme;
28414
28415					if(!relobj.authority){
28416						relobj.authority = uriobj.authority;
28417
28418						if(relobj.path.charAt(0) != "/"){
28419							var path = uriobj.path.substring(0,
28420								uriobj.path.lastIndexOf("/") + 1) + relobj.path;
28421
28422							var segs = path.split("/");
28423							for(var j = 0; j < segs.length; j++){
28424								if(segs[j] == "."){
28425									// flatten "./" references
28426									if(j == segs.length - 1){
28427										segs[j] = "";
28428									}else{
28429										segs.splice(j, 1);
28430										j--;
28431									}
28432								}else if(j > 0 && !(j == 1 && segs[0] == "") &&
28433									segs[j] == ".." && segs[j-1] != ".."){
28434									// flatten "../" references
28435									if(j == (segs.length - 1)){
28436										segs.splice(j, 1);
28437										segs[j - 1] = "";
28438									}else{
28439										segs.splice(j - 1, 2);
28440										j -= 2;
28441									}
28442								}
28443							}
28444							relobj.path = segs.join("/");
28445						}
28446					}
28447				}
28448
28449				uri = [];
28450				if(relobj.scheme){
28451					uri.push(relobj.scheme, ":");
28452				}
28453				if(relobj.authority){
28454					uri.push("//", relobj.authority);
28455				}
28456				uri.push(relobj.path);
28457				if(relobj.query){
28458					uri.push("?", relobj.query);
28459				}
28460				if(relobj.fragment){
28461					uri.push("#", relobj.fragment);
28462				}
28463			}
28464
28465			this.uri = uri.join("");
28466
28467			// break the uri into its main components
28468			var r = this.uri.match(ore);
28469
28470			this.scheme = r[2] || (r[1] ? "" : n);
28471			this.authority = r[4] || (r[3] ? "" : n);
28472			this.path = r[5]; // can never be undefined
28473			this.query = r[7] || (r[6] ? "" : n);
28474			this.fragment	 = r[9] || (r[8] ? "" : n);
28475
28476			if(this.authority != n){
28477				// server based naming authority
28478				r = this.authority.match(ire);
28479
28480				this.user = r[3] || n;
28481				this.password = r[4] || n;
28482				this.host = r[6] || r[7]; // ipv6 || ipv4
28483				this.port = r[9] || n;
28484			}
28485		};
28486	_Url.prototype.toString = function(){ return this.uri; };
28487
28488	return dojo._Url = _Url;
28489});
28490
28491},
28492'dojo/promise/all':function(){
28493define([
28494	"../_base/array",
28495	"../Deferred",
28496	"../when"
28497], function(array, Deferred, when){
28498	"use strict";
28499
28500	// module:
28501	//		dojo/promise/all
28502
28503	var some = array.some;
28504
28505	return function all(objectOrArray){
28506		// summary:
28507		//		Takes multiple promises and returns a new promise that is fulfilled
28508		//		when all promises have been resolved or one has been rejected.
28509		// description:
28510		//		Takes multiple promises and returns a new promise that is fulfilled
28511		//		when all promises have been resolved or one has been rejected. If one of
28512		//		the promises is rejected, the returned promise is also rejected. Canceling
28513		//		the returned promise will *not* cancel any passed promises.
28514		// objectOrArray: Object|Array?
28515		//		The promise will be fulfilled with a list of results if invoked with an
28516		//		array, or an object of results when passed an object (using the same
28517		//		keys). If passed neither an object or array it is resolved with an
28518		//		undefined value.
28519		// returns: dojo/promise/Promise
28520
28521		var object, array;
28522		if(objectOrArray instanceof Array){
28523			array = objectOrArray;
28524		}else if(objectOrArray && typeof objectOrArray === "object"){
28525			object = objectOrArray;
28526		}
28527
28528		var results;
28529		var keyLookup = [];
28530		if(object){
28531			array = [];
28532			for(var key in object){
28533				if(Object.hasOwnProperty.call(object, key)){
28534					keyLookup.push(key);
28535					array.push(object[key]);
28536				}
28537			}
28538			results = {};
28539		}else if(array){
28540			results = [];
28541		}
28542
28543		if(!array || !array.length){
28544			return new Deferred().resolve(results);
28545		}
28546
28547		var deferred = new Deferred();
28548		deferred.promise.always(function(){
28549			results = keyLookup = null;
28550		});
28551		var waiting = array.length;
28552		some(array, function(valueOrPromise, index){
28553			if(!object){
28554				keyLookup.push(index);
28555			}
28556			when(valueOrPromise, function(value){
28557				if(!deferred.isFulfilled()){
28558					results[keyLookup[index]] = value;
28559					if(--waiting === 0){
28560						deferred.resolve(results);
28561					}
28562				}
28563			}, deferred.reject);
28564			return deferred.isFulfilled();
28565		});
28566		return deferred.promise;	// dojo/promise/Promise
28567	};
28568});
28569
28570},
28571'dpage/widgets/Dialog':function(){
28572define([
28573      "dojo/_base/declare"
28574      , "dojo/on"
28575      , "dojo/_base/event"
28576      , "jQueryPrivate"
28577
28578      /*, "xstyle/css!jquery-ui/themes/smoothness/jquery-ui.css", "xstyle/css!dpage/widgets/Dialog.css"*/
28579      , "jquery-ui/ui/dialog"
28580      , "dpage/widgets/Page"
28581],
28582    function (declare, on, event, $) {
28583    /**
28584    * @namespace dpage
28585    */
28586    /**
28587    * @namespace widgets
28588    * @memberOf dpage
28589    */
28590    /**
28591    * Base Class for building or displaying Dialogs
28592    * @class Dialog
28593    * @param {Object} [options] Optional options for the widget
28594    * @param {String} [options.title] The title to display in the title bar of the dialog.
28595    * @param {bool}   [options.noDefaultCSS] Default false. If true, no css will be required in for the widget.
28596    * @param {Number} [options.height] The height of the dialog.
28597    * @param {Number} [options.width] The width of the dialog.
28598    * @param {bool}   [options.OKButton] Display an OK button or not that will close the dialog. Default is false for no button.
28599    * @param {Object} [options.model] Data destined for Container child controls. This is an object where each property value is a dpage.modules.TabularModel *or*
28600    *                                 an object that conforms to the structure that can be used to pass to the dpage.modules.TabularModel constructor in the model property.
28601    * @param {bool} [options.parseNow] (defaults to true) If true, then parse the container for child widgets now. If false, wait for domReady.
28602    * @param {function} [options.widgetsParsedCallback] callback function for when widgets in this container are parsed.
28603    * @param {String} [options.templateString] Optional template for this container. If provided will instantiate a container with the provided
28604    *                                          markup. As with all containers, the markup can contain widgets that can be accessed through
28605    *                                          getWidget() or getWidgets().
28606    * @param {dpage.widgets.Container} [options.container] The container of the widget.
28607    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
28608    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
28609    *                               is created.
28610    * @param {Object} [containerNode] Optional container node to tie the widget to.
28611    * @memberOf dpage.widgets
28612    * @extends {dpage.widgets.Container}
28613    */
28614        return declare("dpage.widgets.Dialog", [dpage.widgets.Container], /** @lends dpage.widgets.Dialog.prototype */ {
28615            _dialog: null,
28616            _height: null,
28617            _width: null,
28618            _displayOKButton : false,
28619            constructor: function (options, srcNodeRef) {
28620
28621                if (options != null) {
28622                    if (options.height != null)
28623                        this._height = options.height;
28624                    if (options.width != null)
28625                        this._width = options.width;
28626                    if (options.templateString != null)
28627                        this.templateString = options.templateString;
28628                    if (options.OKButton)
28629                        this._displayOKButton = true;
28630                    else
28631                        this._displayOKButton = false;
28632                }
28633
28634                if (this._containerNode.nodeName == "SPAN" && this._containerNode.style.display == "" &&
28635                        (this._width != null || this._height != null)) {
28636                    this._containerNode.style.display = "inline-block";
28637                }
28638
28639                if (options == null || !options.noDefaultCSS) {
28640                    //register with the page obj that we have pending css.
28641                    dpage.widgets.Page.setClassCSSLoading("dpage.widgets.Dialog", false);
28642
28643                    require(["xstyle/css!jquery-ui/themes/smoothness/jquery-ui.css", "xstyle/css!dpage/widgets/Dialog.css"], function () {
28644                        //register with the page that we are done loading css.
28645                        dpage.widgets.Page.setClassCSSLoading("dpage.widgets.Dialog", true);
28646                    });
28647                }
28648
28649            },
28650            buildRendering: function () {
28651                return this.inherited(arguments);
28652            },
28653            postCreate: function ()
28654            {
28655                var self = this;
28656                var options = {
28657                    autoOpen: false,
28658                    modal: true,
28659                    buttons: {
28660                    },
28661                    close: function () {
28662                        self.close();
28663                    }
28664                };
28665
28666                if (this._displayOKButton)
28667                    options.buttons.OK =  function () { self.close(); }
28668
28669                if (this._height)
28670                    options.height = this._height;
28671                if (this._width)
28672                    options.width = this._width;
28673
28674                this._dialog = $(this.domNode).dialog(options);
28675            },
28676            /**
28677            * Display the dialog.
28678            * @returns {void}
28679            */
28680            show: function ()
28681            {
28682                this._dialog.dialog("open");
28683                if (this.getDomNode().parentNode.style.zIndex == "")
28684                    this.getDomNode().parentNode.style.zIndex = 101;
28685            },
28686            /**
28687            * Close (hide) the dialog
28688            * @returns {void}
28689            */
28690            close: function ()
28691            {
28692                $(this._dialog).dialog("destroy").remove();
28693                this.clearWidgets();
28694            },
28695            widgetsInTemplate: true
28696        });
28697    }
28698);
28699},
28700'jQueryPrivate/jQueryPrivate':function(){
28701define(['jquery'], function (jq) {
28702    return jq.noConflict(true);
28703});
28704},
28705'jquery/jquery':function(){
28706/*!
28707 * jQuery JavaScript Library v2.1.3
28708 * http://jquery.com/
28709 *
28710 * Includes Sizzle.js
28711 * http://sizzlejs.com/
28712 *
28713 * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
28714 * Released under the MIT license
28715 * http://jquery.org/license
28716 *
28717 * Date: 2014-12-18T15:11Z
28718 */
28719
28720(function( global, factory ) {
28721
28722	if ( typeof module === "object" && typeof module.exports === "object" ) {
28723		// For CommonJS and CommonJS-like environments where a proper `window`
28724		// is present, execute the factory and get jQuery.
28725		// For environments that do not have a `window` with a `document`
28726		// (such as Node.js), expose a factory as module.exports.
28727		// This accentuates the need for the creation of a real `window`.
28728		// e.g. var jQuery = require("jquery")(window);
28729		// See ticket #14549 for more info.
28730		module.exports = global.document ?
28731			factory( global, true ) :
28732			function( w ) {
28733				if ( !w.document ) {
28734					throw new Error( "jQuery requires a window with a document" );
28735				}
28736				return factory( w );
28737			};
28738	} else {
28739		factory( global );
28740	}
28741
28742// Pass this if window is not defined yet
28743}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
28744
28745// Support: Firefox 18+
28746// Can't be in strict mode, several libs including ASP.NET trace
28747// the stack via arguments.caller.callee and Firefox dies if
28748// you try to trace through "use strict" call chains. (#13335)
28749//
28750
28751var arr = [];
28752
28753var slice = arr.slice;
28754
28755var concat = arr.concat;
28756
28757var push = arr.push;
28758
28759var indexOf = arr.indexOf;
28760
28761var class2type = {};
28762
28763var toString = class2type.toString;
28764
28765var hasOwn = class2type.hasOwnProperty;
28766
28767var support = {};
28768
28769
28770
28771var
28772	// Use the correct document accordingly with window argument (sandbox)
28773	document = window.document,
28774
28775	version = "2.1.3",
28776
28777	// Define a local copy of jQuery
28778	jQuery = function( selector, context ) {
28779		// The jQuery object is actually just the init constructor 'enhanced'
28780		// Need init if jQuery is called (just allow error to be thrown if not included)
28781		return new jQuery.fn.init( selector, context );
28782	},
28783
28784	// Support: Android<4.1
28785	// Make sure we trim BOM and NBSP
28786	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
28787
28788	// Matches dashed string for camelizing
28789	rmsPrefix = /^-ms-/,
28790	rdashAlpha = /-([\da-z])/gi,
28791
28792	// Used by jQuery.camelCase as callback to replace()
28793	fcamelCase = function( all, letter ) {
28794		return letter.toUpperCase();
28795	};
28796
28797jQuery.fn = jQuery.prototype = {
28798	// The current version of jQuery being used
28799	jquery: version,
28800
28801	constructor: jQuery,
28802
28803	// Start with an empty selector
28804	selector: "",
28805
28806	// The default length of a jQuery object is 0
28807	length: 0,
28808
28809	toArray: function() {
28810		return slice.call( this );
28811	},
28812
28813	// Get the Nth element in the matched element set OR
28814	// Get the whole matched element set as a clean array
28815	get: function( num ) {
28816		return num != null ?
28817
28818			// Return just the one element from the set
28819			( num < 0 ? this[ num + this.length ] : this[ num ] ) :
28820
28821			// Return all the elements in a clean array
28822			slice.call( this );
28823	},
28824
28825	// Take an array of elements and push it onto the stack
28826	// (returning the new matched element set)
28827	pushStack: function( elems ) {
28828
28829		// Build a new jQuery matched element set
28830		var ret = jQuery.merge( this.constructor(), elems );
28831
28832		// Add the old object onto the stack (as a reference)
28833		ret.prevObject = this;
28834		ret.context = this.context;
28835
28836		// Return the newly-formed element set
28837		return ret;
28838	},
28839
28840	// Execute a callback for every element in the matched set.
28841	// (You can seed the arguments with an array of args, but this is
28842	// only used internally.)
28843	each: function( callback, args ) {
28844		return jQuery.each( this, callback, args );
28845	},
28846
28847	map: function( callback ) {
28848		return this.pushStack( jQuery.map(this, function( elem, i ) {
28849			return callback.call( elem, i, elem );
28850		}));
28851	},
28852
28853	slice: function() {
28854		return this.pushStack( slice.apply( this, arguments ) );
28855	},
28856
28857	first: function() {
28858		return this.eq( 0 );
28859	},
28860
28861	last: function() {
28862		return this.eq( -1 );
28863	},
28864
28865	eq: function( i ) {
28866		var len = this.length,
28867			j = +i + ( i < 0 ? len : 0 );
28868		return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
28869	},
28870
28871	end: function() {
28872		return this.prevObject || this.constructor(null);
28873	},
28874
28875	// For internal use only.
28876	// Behaves like an Array's method, not like a jQuery method.
28877	push: push,
28878	sort: arr.sort,
28879	splice: arr.splice
28880};
28881
28882jQuery.extend = jQuery.fn.extend = function() {
28883	var options, name, src, copy, copyIsArray, clone,
28884		target = arguments[0] || {},
28885		i = 1,
28886		length = arguments.length,
28887		deep = false;
28888
28889	// Handle a deep copy situation
28890	if ( typeof target === "boolean" ) {
28891		deep = target;
28892
28893		// Skip the boolean and the target
28894		target = arguments[ i ] || {};
28895		i++;
28896	}
28897
28898	// Handle case when target is a string or something (possible in deep copy)
28899	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
28900		target = {};
28901	}
28902
28903	// Extend jQuery itself if only one argument is passed
28904	if ( i === length ) {
28905		target = this;
28906		i--;
28907	}
28908
28909	for ( ; i < length; i++ ) {
28910		// Only deal with non-null/undefined values
28911		if ( (options = arguments[ i ]) != null ) {
28912			// Extend the base object
28913			for ( name in options ) {
28914				src = target[ name ];
28915				copy = options[ name ];
28916
28917				// Prevent never-ending loop
28918				if ( target === copy ) {
28919					continue;
28920				}
28921
28922				// Recurse if we're merging plain objects or arrays
28923				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
28924					if ( copyIsArray ) {
28925						copyIsArray = false;
28926						clone = src && jQuery.isArray(src) ? src : [];
28927
28928					} else {
28929						clone = src && jQuery.isPlainObject(src) ? src : {};
28930					}
28931
28932					// Never move original objects, clone them
28933					target[ name ] = jQuery.extend( deep, clone, copy );
28934
28935				// Don't bring in undefined values
28936				} else if ( copy !== undefined ) {
28937					target[ name ] = copy;
28938				}
28939			}
28940		}
28941	}
28942
28943	// Return the modified object
28944	return target;
28945};
28946
28947jQuery.extend({
28948	// Unique for each copy of jQuery on the page
28949	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
28950
28951	// Assume jQuery is ready without the ready module
28952	isReady: true,
28953
28954	error: function( msg ) {
28955		throw new Error( msg );
28956	},
28957
28958	noop: function() {},
28959
28960	isFunction: function( obj ) {
28961		return jQuery.type(obj) === "function";
28962	},
28963
28964	isArray: Array.isArray,
28965
28966	isWindow: function( obj ) {
28967		return obj != null && obj === obj.window;
28968	},
28969
28970	isNumeric: function( obj ) {
28971		// parseFloat NaNs numeric-cast false positives (null|true|false|"")
28972		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
28973		// subtraction forces infinities to NaN
28974		// adding 1 corrects loss of precision from parseFloat (#15100)
28975		return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
28976	},
28977
28978	isPlainObject: function( obj ) {
28979		// Not plain objects:
28980		// - Any object or value whose internal [[Class]] property is not "[object Object]"
28981		// - DOM nodes
28982		// - window
28983		if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
28984			return false;
28985		}
28986
28987		if ( obj.constructor &&
28988				!hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
28989			return false;
28990		}
28991
28992		// If the function hasn't returned already, we're confident that
28993		// |obj| is a plain object, created by {} or constructed with new Object
28994		return true;
28995	},
28996
28997	isEmptyObject: function( obj ) {
28998		var name;
28999		for ( name in obj ) {
29000			return false;
29001		}
29002		return true;
29003	},
29004
29005	type: function( obj ) {
29006		if ( obj == null ) {
29007			return obj + "";
29008		}
29009		// Support: Android<4.0, iOS<6 (functionish RegExp)
29010		return typeof obj === "object" || typeof obj === "function" ?
29011			class2type[ toString.call(obj) ] || "object" :
29012			typeof obj;
29013	},
29014
29015	// Evaluates a script in a global context
29016	globalEval: function( code ) {
29017		var script,
29018			indirect = eval;
29019
29020		code = jQuery.trim( code );
29021
29022		if ( code ) {
29023			// If the code includes a valid, prologue position
29024			// strict mode pragma, execute code by injecting a
29025			// script tag into the document.
29026			if ( code.indexOf("use strict") === 1 ) {
29027				script = document.createElement("script");
29028				script.text = code;
29029				document.head.appendChild( script ).parentNode.removeChild( script );
29030			} else {
29031			// Otherwise, avoid the DOM node creation, insertion
29032			// and removal by using an indirect global eval
29033				indirect( code );
29034			}
29035		}
29036	},
29037
29038	// Convert dashed to camelCase; used by the css and data modules
29039	// Support: IE9-11+
29040	// Microsoft forgot to hump their vendor prefix (#9572)
29041	camelCase: function( string ) {
29042		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
29043	},
29044
29045	nodeName: function( elem, name ) {
29046		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
29047	},
29048
29049	// args is for internal usage only
29050	each: function( obj, callback, args ) {
29051		var value,
29052			i = 0,
29053			length = obj.length,
29054			isArray = isArraylike( obj );
29055
29056		if ( args ) {
29057			if ( isArray ) {
29058				for ( ; i < length; i++ ) {
29059					value = callback.apply( obj[ i ], args );
29060
29061					if ( value === false ) {
29062						break;
29063					}
29064				}
29065			} else {
29066				for ( i in obj ) {
29067					value = callback.apply( obj[ i ], args );
29068
29069					if ( value === false ) {
29070						break;
29071					}
29072				}
29073			}
29074
29075		// A special, fast, case for the most common use of each
29076		} else {
29077			if ( isArray ) {
29078				for ( ; i < length; i++ ) {
29079					value = callback.call( obj[ i ], i, obj[ i ] );
29080
29081					if ( value === false ) {
29082						break;
29083					}
29084				}
29085			} else {
29086				for ( i in obj ) {
29087					value = callback.call( obj[ i ], i, obj[ i ] );
29088
29089					if ( value === false ) {
29090						break;
29091					}
29092				}
29093			}
29094		}
29095
29096		return obj;
29097	},
29098
29099	// Support: Android<4.1
29100	trim: function( text ) {
29101		return text == null ?
29102			"" :
29103			( text + "" ).replace( rtrim, "" );
29104	},
29105
29106	// results is for internal usage only
29107	makeArray: function( arr, results ) {
29108		var ret = results || [];
29109
29110		if ( arr != null ) {
29111			if ( isArraylike( Object(arr) ) ) {
29112				jQuery.merge( ret,
29113					typeof arr === "string" ?
29114					[ arr ] : arr
29115				);
29116			} else {
29117				push.call( ret, arr );
29118			}
29119		}
29120
29121		return ret;
29122	},
29123
29124	inArray: function( elem, arr, i ) {
29125		return arr == null ? -1 : indexOf.call( arr, elem, i );
29126	},
29127
29128	merge: function( first, second ) {
29129		var len = +second.length,
29130			j = 0,
29131			i = first.length;
29132
29133		for ( ; j < len; j++ ) {
29134			first[ i++ ] = second[ j ];
29135		}
29136
29137		first.length = i;
29138
29139		return first;
29140	},
29141
29142	grep: function( elems, callback, invert ) {
29143		var callbackInverse,
29144			matches = [],
29145			i = 0,
29146			length = elems.length,
29147			callbackExpect = !invert;
29148
29149		// Go through the array, only saving the items
29150		// that pass the validator function
29151		for ( ; i < length; i++ ) {
29152			callbackInverse = !callback( elems[ i ], i );
29153			if ( callbackInverse !== callbackExpect ) {
29154				matches.push( elems[ i ] );
29155			}
29156		}
29157
29158		return matches;
29159	},
29160
29161	// arg is for internal usage only
29162	map: function( elems, callback, arg ) {
29163		var value,
29164			i = 0,
29165			length = elems.length,
29166			isArray = isArraylike( elems ),
29167			ret = [];
29168
29169		// Go through the array, translating each of the items to their new values
29170		if ( isArray ) {
29171			for ( ; i < length; i++ ) {
29172				value = callback( elems[ i ], i, arg );
29173
29174				if ( value != null ) {
29175					ret.push( value );
29176				}
29177			}
29178
29179		// Go through every key on the object,
29180		} else {
29181			for ( i in elems ) {
29182				value = callback( elems[ i ], i, arg );
29183
29184				if ( value != null ) {
29185					ret.push( value );
29186				}
29187			}
29188		}
29189
29190		// Flatten any nested arrays
29191		return concat.apply( [], ret );
29192	},
29193
29194	// A global GUID counter for objects
29195	guid: 1,
29196
29197	// Bind a function to a context, optionally partially applying any
29198	// arguments.
29199	proxy: function( fn, context ) {
29200		var tmp, args, proxy;
29201
29202		if ( typeof context === "string" ) {
29203			tmp = fn[ context ];
29204			context = fn;
29205			fn = tmp;
29206		}
29207
29208		// Quick check to determine if target is callable, in the spec
29209		// this throws a TypeError, but we will just return undefined.
29210		if ( !jQuery.isFunction( fn ) ) {
29211			return undefined;
29212		}
29213
29214		// Simulated bind
29215		args = slice.call( arguments, 2 );
29216		proxy = function() {
29217			return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
29218		};
29219
29220		// Set the guid of unique handler to the same of original handler, so it can be removed
29221		proxy.guid = fn.guid = fn.guid || jQuery.guid++;
29222
29223		return proxy;
29224	},
29225
29226	now: Date.now,
29227
29228	// jQuery.support is not used in Core but other projects attach their
29229	// properties to it so it needs to exist.
29230	support: support
29231});
29232
29233// Populate the class2type map
29234jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
29235	class2type[ "[object " + name + "]" ] = name.toLowerCase();
29236});
29237
29238function isArraylike( obj ) {
29239	var length = obj.length,
29240		type = jQuery.type( obj );
29241
29242	if ( type === "function" || jQuery.isWindow( obj ) ) {
29243		return false;
29244	}
29245
29246	if ( obj.nodeType === 1 && length ) {
29247		return true;
29248	}
29249
29250	return type === "array" || length === 0 ||
29251		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
29252}
29253var Sizzle =
29254/*!
29255 * Sizzle CSS Selector Engine v2.2.0-pre
29256 * http://sizzlejs.com/
29257 *
29258 * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors
29259 * Released under the MIT license
29260 * http://jquery.org/license
29261 *
29262 * Date: 2014-12-16
29263 */
29264(function( window ) {
29265
29266var i,
29267	support,
29268	Expr,
29269	getText,
29270	isXML,
29271	tokenize,
29272	compile,
29273	select,
29274	outermostContext,
29275	sortInput,
29276	hasDuplicate,
29277
29278	// Local document vars
29279	setDocument,
29280	document,
29281	docElem,
29282	documentIsHTML,
29283	rbuggyQSA,
29284	rbuggyMatches,
29285	matches,
29286	contains,
29287
29288	// Instance-specific data
29289	expando = "sizzle" + 1 * new Date(),
29290	preferredDoc = window.document,
29291	dirruns = 0,
29292	done = 0,
29293	classCache = createCache(),
29294	tokenCache = createCache(),
29295	compilerCache = createCache(),
29296	sortOrder = function( a, b ) {
29297		if ( a === b ) {
29298			hasDuplicate = true;
29299		}
29300		return 0;
29301	},
29302
29303	// General-purpose constants
29304	MAX_NEGATIVE = 1 << 31,
29305
29306	// Instance methods
29307	hasOwn = ({}).hasOwnProperty,
29308	arr = [],
29309	pop = arr.pop,
29310	push_native = arr.push,
29311	push = arr.push,
29312	slice = arr.slice,
29313	// Use a stripped-down indexOf as it's faster than native
29314	// http://jsperf.com/thor-indexof-vs-for/5
29315	indexOf = function( list, elem ) {
29316		var i = 0,
29317			len = list.length;
29318		for ( ; i < len; i++ ) {
29319			if ( list[i] === elem ) {
29320				return i;
29321			}
29322		}
29323		return -1;
29324	},
29325
29326	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
29327
29328	// Regular expressions
29329
29330	// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
29331	whitespace = "[\\x20\\t\\r\\n\\f]",
29332	// http://www.w3.org/TR/css3-syntax/#characters
29333	characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
29334
29335	// Loosely modeled on CSS identifier characters
29336	// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
29337	// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
29338	identifier = characterEncoding.replace( "w", "w#" ),
29339
29340	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
29341	attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
29342		// Operator (capture 2)
29343		"*([*^$|!~]?=)" + whitespace +
29344		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
29345		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
29346		"*\\]",
29347
29348	pseudos = ":(" + characterEncoding + ")(?:\\((" +
29349		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
29350		// 1. quoted (capture 3; capture 4 or capture 5)
29351		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
29352		// 2. simple (capture 6)
29353		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
29354		// 3. anything else (capture 2)
29355		".*" +
29356		")\\)|)",
29357
29358	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
29359	rwhitespace = new RegExp( whitespace + "+", "g" ),
29360	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
29361
29362	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
29363	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
29364
29365	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
29366
29367	rpseudo = new RegExp( pseudos ),
29368	ridentifier = new RegExp( "^" + identifier + "$" ),
29369
29370	matchExpr = {
29371		"ID": new RegExp( "^#(" + characterEncoding + ")" ),
29372		"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
29373		"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
29374		"ATTR": new RegExp( "^" + attributes ),
29375		"PSEUDO": new RegExp( "^" + pseudos ),
29376		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
29377			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
29378			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
29379		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
29380		// For use in libraries implementing .is()
29381		// We use this for POS matching in `select`
29382		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
29383			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
29384	},
29385
29386	rinputs = /^(?:input|select|textarea|button)$/i,
29387	rheader = /^h\d$/i,
29388
29389	rnative = /^[^{]+\{\s*\[native \w/,
29390
29391	// Easily-parseable/retrievable ID or TAG or CLASS selectors
29392	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
29393
29394	rsibling = /[+~]/,
29395	rescape = /'|\\/g,
29396
29397	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
29398	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
29399	funescape = function( _, escaped, escapedWhitespace ) {
29400		var high = "0x" + escaped - 0x10000;
29401		// NaN means non-codepoint
29402		// Support: Firefox<24
29403		// Workaround erroneous numeric interpretation of +"0x"
29404		return high !== high || escapedWhitespace ?
29405			escaped :
29406			high < 0 ?
29407				// BMP codepoint
29408				String.fromCharCode( high + 0x10000 ) :
29409				// Supplemental Plane codepoint (surrogate pair)
29410				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
29411	},
29412
29413	// Used for iframes
29414	// See setDocument()
29415	// Removing the function wrapper causes a "Permission Denied"
29416	// error in IE
29417	unloadHandler = function() {
29418		setDocument();
29419	};
29420
29421// Optimize for push.apply( _, NodeList )
29422try {
29423	push.apply(
29424		(arr = slice.call( preferredDoc.childNodes )),
29425		preferredDoc.childNodes
29426	);
29427	// Support: Android<4.0
29428	// Detect silently failing push.apply
29429	arr[ preferredDoc.childNodes.length ].nodeType;
29430} catch ( e ) {
29431	push = { apply: arr.length ?
29432
29433		// Leverage slice if possible
29434		function( target, els ) {
29435			push_native.apply( target, slice.call(els) );
29436		} :
29437
29438		// Support: IE<9
29439		// Otherwise append directly
29440		function( target, els ) {
29441			var j = target.length,
29442				i = 0;
29443			// Can't trust NodeList.length
29444			while ( (target[j++] = els[i++]) ) {}
29445			target.length = j - 1;
29446		}
29447	};
29448}
29449
29450function Sizzle( selector, context, results, seed ) {
29451	var match, elem, m, nodeType,
29452		// QSA vars
29453		i, groups, old, nid, newContext, newSelector;
29454
29455	if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
29456		setDocument( context );
29457	}
29458
29459	context = context || document;
29460	results = results || [];
29461	nodeType = context.nodeType;
29462
29463	if ( typeof selector !== "string" || !selector ||
29464		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
29465
29466		return results;
29467	}
29468
29469	if ( !seed && documentIsHTML ) {
29470
29471		// Try to shortcut find operations when possible (e.g., not under DocumentFragment)
29472		if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
29473			// Speed-up: Sizzle("#ID")
29474			if ( (m = match[1]) ) {
29475				if ( nodeType === 9 ) {
29476					elem = context.getElementById( m );
29477					// Check parentNode to catch when Blackberry 4.6 returns
29478					// nodes that are no longer in the document (jQuery #6963)
29479					if ( elem && elem.parentNode ) {
29480						// Handle the case where IE, Opera, and Webkit return items
29481						// by name instead of ID
29482						if ( elem.id === m ) {
29483							results.push( elem );
29484							return results;
29485						}
29486					} else {
29487						return results;
29488					}
29489				} else {
29490					// Context is not a document
29491					if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
29492						contains( context, elem ) && elem.id === m ) {
29493						results.push( elem );
29494						return results;
29495					}
29496				}
29497
29498			// Speed-up: Sizzle("TAG")
29499			} else if ( match[2] ) {
29500				push.apply( results, context.getElementsByTagName( selector ) );
29501				return results;
29502
29503			// Speed-up: Sizzle(".CLASS")
29504			} else if ( (m = match[3]) && support.getElementsByClassName ) {
29505				push.apply( results, context.getElementsByClassName( m ) );
29506				return results;
29507			}
29508		}
29509
29510		// QSA path
29511		if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
29512			nid = old = expando;
29513			newContext = context;
29514			newSelector = nodeType !== 1 && selector;
29515
29516			// qSA works strangely on Element-rooted queries
29517			// We can work around this by specifying an extra ID on the root
29518			// and working up from there (Thanks to Andrew Dupont for the technique)
29519			// IE 8 doesn't work on object elements
29520			if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
29521				groups = tokenize( selector );
29522
29523				if ( (old = context.getAttribute("id")) ) {
29524					nid = old.replace( rescape, "\\$&" );
29525				} else {
29526					context.setAttribute( "id", nid );
29527				}
29528				nid = "[id='" + nid + "'] ";
29529
29530				i = groups.length;
29531				while ( i-- ) {
29532					groups[i] = nid + toSelector( groups[i] );
29533				}
29534				newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
29535				newSelector = groups.join(",");
29536			}
29537
29538			if ( newSelector ) {
29539				try {
29540					push.apply( results,
29541						newContext.querySelectorAll( newSelector )
29542					);
29543					return results;
29544				} catch(qsaError) {
29545				} finally {
29546					if ( !old ) {
29547						context.removeAttribute("id");
29548					}
29549				}
29550			}
29551		}
29552	}
29553
29554	// All others
29555	return select( selector.replace( rtrim, "$1" ), context, results, seed );
29556}
29557
29558/**
29559 * Create key-value caches of limited size
29560 * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
29561 *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
29562 *	deleting the oldest entry
29563 */
29564function createCache() {
29565	var keys = [];
29566
29567	function cache( key, value ) {
29568		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
29569		if ( keys.push( key + " " ) > Expr.cacheLength ) {
29570			// Only keep the most recent entries
29571			delete cache[ keys.shift() ];
29572		}
29573		return (cache[ key + " " ] = value);
29574	}
29575	return cache;
29576}
29577
29578/**
29579 * Mark a function for special use by Sizzle
29580 * @param {Function} fn The function to mark
29581 */
29582function markFunction( fn ) {
29583	fn[ expando ] = true;
29584	return fn;
29585}
29586
29587/**
29588 * Support testing using an element
29589 * @param {Function} fn Passed the created div and expects a boolean result
29590 */
29591function assert( fn ) {
29592	var div = document.createElement("div");
29593
29594	try {
29595		return !!fn( div );
29596	} catch (e) {
29597		return false;
29598	} finally {
29599		// Remove from its parent by default
29600		if ( div.parentNode ) {
29601			div.parentNode.removeChild( div );
29602		}
29603		// release memory in IE
29604		div = null;
29605	}
29606}
29607
29608/**
29609 * Adds the same handler for all of the specified attrs
29610 * @param {String} attrs Pipe-separated list of attributes
29611 * @param {Function} handler The method that will be applied
29612 */
29613function addHandle( attrs, handler ) {
29614	var arr = attrs.split("|"),
29615		i = attrs.length;
29616
29617	while ( i-- ) {
29618		Expr.attrHandle[ arr[i] ] = handler;
29619	}
29620}
29621
29622/**
29623 * Checks document order of two siblings
29624 * @param {Element} a
29625 * @param {Element} b
29626 * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
29627 */
29628function siblingCheck( a, b ) {
29629	var cur = b && a,
29630		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
29631			( ~b.sourceIndex || MAX_NEGATIVE ) -
29632			( ~a.sourceIndex || MAX_NEGATIVE );
29633
29634	// Use IE sourceIndex if available on both nodes
29635	if ( diff ) {
29636		return diff;
29637	}
29638
29639	// Check if b follows a
29640	if ( cur ) {
29641		while ( (cur = cur.nextSibling) ) {
29642			if ( cur === b ) {
29643				return -1;
29644			}
29645		}
29646	}
29647
29648	return a ? 1 : -1;
29649}
29650
29651/**
29652 * Returns a function to use in pseudos for input types
29653 * @param {String} type
29654 */
29655function createInputPseudo( type ) {
29656	return function( elem ) {
29657		var name = elem.nodeName.toLowerCase();
29658		return name === "input" && elem.type === type;
29659	};
29660}
29661
29662/**
29663 * Returns a function to use in pseudos for buttons
29664 * @param {String} type
29665 */
29666function createButtonPseudo( type ) {
29667	return function( elem ) {
29668		var name = elem.nodeName.toLowerCase();
29669		return (name === "input" || name === "button") && elem.type === type;
29670	};
29671}
29672
29673/**
29674 * Returns a function to use in pseudos for positionals
29675 * @param {Function} fn
29676 */
29677function createPositionalPseudo( fn ) {
29678	return markFunction(function( argument ) {
29679		argument = +argument;
29680		return markFunction(function( seed, matches ) {
29681			var j,
29682				matchIndexes = fn( [], seed.length, argument ),
29683				i = matchIndexes.length;
29684
29685			// Match elements found at the specified indexes
29686			while ( i-- ) {
29687				if ( seed[ (j = matchIndexes[i]) ] ) {
29688					seed[j] = !(matches[j] = seed[j]);
29689				}
29690			}
29691		});
29692	});
29693}
29694
29695/**
29696 * Checks a node for validity as a Sizzle context
29697 * @param {Element|Object=} context
29698 * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
29699 */
29700function testContext( context ) {
29701	return context && typeof context.getElementsByTagName !== "undefined" && context;
29702}
29703
29704// Expose support vars for convenience
29705support = Sizzle.support = {};
29706
29707/**
29708 * Detects XML nodes
29709 * @param {Element|Object} elem An element or a document
29710 * @returns {Boolean} True iff elem is a non-HTML XML node
29711 */
29712isXML = Sizzle.isXML = function( elem ) {
29713	// documentElement is verified for cases where it doesn't yet exist
29714	// (such as loading iframes in IE - #4833)
29715	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
29716	return documentElement ? documentElement.nodeName !== "HTML" : false;
29717};
29718
29719/**
29720 * Sets document-related variables once based on the current document
29721 * @param {Element|Object} [doc] An element or document object to use to set the document
29722 * @returns {Object} Returns the current document
29723 */
29724setDocument = Sizzle.setDocument = function( node ) {
29725	var hasCompare, parent,
29726		doc = node ? node.ownerDocument || node : preferredDoc;
29727
29728	// If no document and documentElement is available, return
29729	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
29730		return document;
29731	}
29732
29733	// Set our document
29734	document = doc;
29735	docElem = doc.documentElement;
29736	parent = doc.defaultView;
29737
29738	// Support: IE>8
29739	// If iframe document is assigned to "document" variable and if iframe has been reloaded,
29740	// IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
29741	// IE6-8 do not support the defaultView property so parent will be undefined
29742	if ( parent && parent !== parent.top ) {
29743		// IE11 does not have attachEvent, so all must suffer
29744		if ( parent.addEventListener ) {
29745			parent.addEventListener( "unload", unloadHandler, false );
29746		} else if ( parent.attachEvent ) {
29747			parent.attachEvent( "onunload", unloadHandler );
29748		}
29749	}
29750
29751	/* Support tests
29752	---------------------------------------------------------------------- */
29753	documentIsHTML = !isXML( doc );
29754
29755	/* Attributes
29756	---------------------------------------------------------------------- */
29757
29758	// Support: IE<8
29759	// Verify that getAttribute really returns attributes and not properties
29760	// (excepting IE8 booleans)
29761	support.attributes = assert(function( div ) {
29762		div.className = "i";
29763		return !div.getAttribute("className");
29764	});
29765
29766	/* getElement(s)By*
29767	---------------------------------------------------------------------- */
29768
29769	// Check if getElementsByTagName("*") returns only elements
29770	support.getElementsByTagName = assert(function( div ) {
29771		div.appendChild( doc.createComment("") );
29772		return !div.getElementsByTagName("*").length;
29773	});
29774
29775	// Support: IE<9
29776	support.getElementsByClassName = rnative.test( doc.getElementsByClassName );
29777
29778	// Support: IE<10
29779	// Check if getElementById returns elements by name
29780	// The broken getElementById methods don't pick up programatically-set names,
29781	// so use a roundabout getElementsByName test
29782	support.getById = assert(function( div ) {
29783		docElem.appendChild( div ).id = expando;
29784		return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
29785	});
29786
29787	// ID find and filter
29788	if ( support.getById ) {
29789		Expr.find["ID"] = function( id, context ) {
29790			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
29791				var m = context.getElementById( id );
29792				// Check parentNode to catch when Blackberry 4.6 returns
29793				// nodes that are no longer in the document #6963
29794				return m && m.parentNode ? [ m ] : [];
29795			}
29796		};
29797		Expr.filter["ID"] = function( id ) {
29798			var attrId = id.replace( runescape, funescape );
29799			return function( elem ) {
29800				return elem.getAttribute("id") === attrId;
29801			};
29802		};
29803	} else {
29804		// Support: IE6/7
29805		// getElementById is not reliable as a find shortcut
29806		delete Expr.find["ID"];
29807
29808		Expr.filter["ID"] =  function( id ) {
29809			var attrId = id.replace( runescape, funescape );
29810			return function( elem ) {
29811				var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
29812				return node && node.value === attrId;
29813			};
29814		};
29815	}
29816
29817	// Tag
29818	Expr.find["TAG"] = support.getElementsByTagName ?
29819		function( tag, context ) {
29820			if ( typeof context.getElementsByTagName !== "undefined" ) {
29821				return context.getElementsByTagName( tag );
29822
29823			// DocumentFragment nodes don't have gEBTN
29824			} else if ( support.qsa ) {
29825				return context.querySelectorAll( tag );
29826			}
29827		} :
29828
29829		function( tag, context ) {
29830			var elem,
29831				tmp = [],
29832				i = 0,
29833				// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
29834				results = context.getElementsByTagName( tag );
29835
29836			// Filter out possible comments
29837			if ( tag === "*" ) {
29838				while ( (elem = results[i++]) ) {
29839					if ( elem.nodeType === 1 ) {
29840						tmp.push( elem );
29841					}
29842				}
29843
29844				return tmp;
29845			}
29846			return results;
29847		};
29848
29849	// Class
29850	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
29851		if ( documentIsHTML ) {
29852			return context.getElementsByClassName( className );
29853		}
29854	};
29855
29856	/* QSA/matchesSelector
29857	---------------------------------------------------------------------- */
29858
29859	// QSA and matchesSelector support
29860
29861	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
29862	rbuggyMatches = [];
29863
29864	// qSa(:focus) reports false when true (Chrome 21)
29865	// We allow this because of a bug in IE8/9 that throws an error
29866	// whenever `document.activeElement` is accessed on an iframe
29867	// So, we allow :focus to pass through QSA all the time to avoid the IE error
29868	// See http://bugs.jquery.com/ticket/13378
29869	rbuggyQSA = [];
29870
29871	if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
29872		// Build QSA regex
29873		// Regex strategy adopted from Diego Perini
29874		assert(function( div ) {
29875			// Select is set to empty string on purpose
29876			// This is to test IE's treatment of not explicitly
29877			// setting a boolean content attribute,
29878			// since its presence should be enough
29879			// http://bugs.jquery.com/ticket/12359
29880			docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
29881				"<select id='" + expando + "-\f]' msallowcapture=''>" +
29882				"<option selected=''></option></select>";
29883
29884			// Support: IE8, Opera 11-12.16
29885			// Nothing should be selected when empty strings follow ^= or $= or *=
29886			// The test attribute must be unknown in Opera but "safe" for WinRT
29887			// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
29888			if ( div.querySelectorAll("[msallowcapture^='']").length ) {
29889				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
29890			}
29891
29892			// Support: IE8
29893			// Boolean attributes and "value" are not treated correctly
29894			if ( !div.querySelectorAll("[selected]").length ) {
29895				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
29896			}
29897
29898			// Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+
29899			if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
29900				rbuggyQSA.push("~=");
29901			}
29902
29903			// Webkit/Opera - :checked should return selected option elements
29904			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
29905			// IE8 throws error here and will not see later tests
29906			if ( !div.querySelectorAll(":checked").length ) {
29907				rbuggyQSA.push(":checked");
29908			}
29909
29910			// Support: Safari 8+, iOS 8+
29911			// https://bugs.webkit.org/show_bug.cgi?id=136851
29912			// In-page `selector#id sibing-combinator selector` fails
29913			if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
29914				rbuggyQSA.push(".#.+[+~]");
29915			}
29916		});
29917
29918		assert(function( div ) {
29919			// Support: Windows 8 Native Apps
29920			// The type and name attributes are restricted during .innerHTML assignment
29921			var input = doc.createElement("input");
29922			input.setAttribute( "type", "hidden" );
29923			div.appendChild( input ).setAttribute( "name", "D" );
29924
29925			// Support: IE8
29926			// Enforce case-sensitivity of name attribute
29927			if ( div.querySelectorAll("[name=d]").length ) {
29928				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
29929			}
29930
29931			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
29932			// IE8 throws error here and will not see later tests
29933			if ( !div.querySelectorAll(":enabled").length ) {
29934				rbuggyQSA.push( ":enabled", ":disabled" );
29935			}
29936
29937			// Opera 10-11 does not throw on post-comma invalid pseudos
29938			div.querySelectorAll("*,:x");
29939			rbuggyQSA.push(",.*:");
29940		});
29941	}
29942
29943	if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
29944		docElem.webkitMatchesSelector ||
29945		docElem.mozMatchesSelector ||
29946		docElem.oMatchesSelector ||
29947		docElem.msMatchesSelector) )) ) {
29948
29949		assert(function( div ) {
29950			// Check to see if it's possible to do matchesSelector
29951			// on a disconnected node (IE 9)
29952			support.disconnectedMatch = matches.call( div, "div" );
29953
29954			// This should fail with an exception
29955			// Gecko does not error, returns false instead
29956			matches.call( div, "[s!='']:x" );
29957			rbuggyMatches.push( "!=", pseudos );
29958		});
29959	}
29960
29961	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
29962	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
29963
29964	/* Contains
29965	---------------------------------------------------------------------- */
29966	hasCompare = rnative.test( docElem.compareDocumentPosition );
29967
29968	// Element contains another
29969	// Purposefully does not implement inclusive descendent
29970	// As in, an element does not contain itself
29971	contains = hasCompare || rnative.test( docElem.contains ) ?
29972		function( a, b ) {
29973			var adown = a.nodeType === 9 ? a.documentElement : a,
29974				bup = b && b.parentNode;
29975			return a === bup || !!( bup && bup.nodeType === 1 && (
29976				adown.contains ?
29977					adown.contains( bup ) :
29978					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
29979			));
29980		} :
29981		function( a, b ) {
29982			if ( b ) {
29983				while ( (b = b.parentNode) ) {
29984					if ( b === a ) {
29985						return true;
29986					}
29987				}
29988			}
29989			return false;
29990		};
29991
29992	/* Sorting
29993	---------------------------------------------------------------------- */
29994
29995	// Document order sorting
29996	sortOrder = hasCompare ?
29997	function( a, b ) {
29998
29999		// Flag for duplicate removal
30000		if ( a === b ) {
30001			hasDuplicate = true;
30002			return 0;
30003		}
30004
30005		// Sort on method existence if only one input has compareDocumentPosition
30006		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
30007		if ( compare ) {
30008			return compare;
30009		}
30010
30011		// Calculate position if both inputs belong to the same document
30012		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
30013			a.compareDocumentPosition( b ) :
30014
30015			// Otherwise we know they are disconnected
30016			1;
30017
30018		// Disconnected nodes
30019		if ( compare & 1 ||
30020			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
30021
30022			// Choose the first element that is related to our preferred document
30023			if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
30024				return -1;
30025			}
30026			if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
30027				return 1;
30028			}
30029
30030			// Maintain original order
30031			return sortInput ?
30032				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
30033				0;
30034		}
30035
30036		return compare & 4 ? -1 : 1;
30037	} :
30038	function( a, b ) {
30039		// Exit early if the nodes are identical
30040		if ( a === b ) {
30041			hasDuplicate = true;
30042			return 0;
30043		}
30044
30045		var cur,
30046			i = 0,
30047			aup = a.parentNode,
30048			bup = b.parentNode,
30049			ap = [ a ],
30050			bp = [ b ];
30051
30052		// Parentless nodes are either documents or disconnected
30053		if ( !aup || !bup ) {
30054			return a === doc ? -1 :
30055				b === doc ? 1 :
30056				aup ? -1 :
30057				bup ? 1 :
30058				sortInput ?
30059				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
30060				0;
30061
30062		// If the nodes are siblings, we can do a quick check
30063		} else if ( aup === bup ) {
30064			return siblingCheck( a, b );
30065		}
30066
30067		// Otherwise we need full lists of their ancestors for comparison
30068		cur = a;
30069		while ( (cur = cur.parentNode) ) {
30070			ap.unshift( cur );
30071		}
30072		cur = b;
30073		while ( (cur = cur.parentNode) ) {
30074			bp.unshift( cur );
30075		}
30076
30077		// Walk down the tree looking for a discrepancy
30078		while ( ap[i] === bp[i] ) {
30079			i++;
30080		}
30081
30082		return i ?
30083			// Do a sibling check if the nodes have a common ancestor
30084			siblingCheck( ap[i], bp[i] ) :
30085
30086			// Otherwise nodes in our document sort first
30087			ap[i] === preferredDoc ? -1 :
30088			bp[i] === preferredDoc ? 1 :
30089			0;
30090	};
30091
30092	return doc;
30093};
30094
30095Sizzle.matches = function( expr, elements ) {
30096	return Sizzle( expr, null, null, elements );
30097};
30098
30099Sizzle.matchesSelector = function( elem, expr ) {
30100	// Set document vars if needed
30101	if ( ( elem.ownerDocument || elem ) !== document ) {
30102		setDocument( elem );
30103	}
30104
30105	// Make sure that attribute selectors are quoted
30106	expr = expr.replace( rattributeQuotes, "='$1']" );
30107
30108	if ( support.matchesSelector && documentIsHTML &&
30109		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
30110		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
30111
30112		try {
30113			var ret = matches.call( elem, expr );
30114
30115			// IE 9's matchesSelector returns false on disconnected nodes
30116			if ( ret || support.disconnectedMatch ||
30117					// As well, disconnected nodes are said to be in a document
30118					// fragment in IE 9
30119					elem.document && elem.document.nodeType !== 11 ) {
30120				return ret;
30121			}
30122		} catch (e) {}
30123	}
30124
30125	return Sizzle( expr, document, null, [ elem ] ).length > 0;
30126};
30127
30128Sizzle.contains = function( context, elem ) {
30129	// Set document vars if needed
30130	if ( ( context.ownerDocument || context ) !== document ) {
30131		setDocument( context );
30132	}
30133	return contains( context, elem );
30134};
30135
30136Sizzle.attr = function( elem, name ) {
30137	// Set document vars if needed
30138	if ( ( elem.ownerDocument || elem ) !== document ) {
30139		setDocument( elem );
30140	}
30141
30142	var fn = Expr.attrHandle[ name.toLowerCase() ],
30143		// Don't get fooled by Object.prototype properties (jQuery #13807)
30144		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
30145			fn( elem, name, !documentIsHTML ) :
30146			undefined;
30147
30148	return val !== undefined ?
30149		val :
30150		support.attributes || !documentIsHTML ?
30151			elem.getAttribute( name ) :
30152			(val = elem.getAttributeNode(name)) && val.specified ?
30153				val.value :
30154				null;
30155};
30156
30157Sizzle.error = function( msg ) {
30158	throw new Error( "Syntax error, unrecognized expression: " + msg );
30159};
30160
30161/**
30162 * Document sorting and removing duplicates
30163 * @param {ArrayLike} results
30164 */
30165Sizzle.uniqueSort = function( results ) {
30166	var elem,
30167		duplicates = [],
30168		j = 0,
30169		i = 0;
30170
30171	// Unless we *know* we can detect duplicates, assume their presence
30172	hasDuplicate = !support.detectDuplicates;
30173	sortInput = !support.sortStable && results.slice( 0 );
30174	results.sort( sortOrder );
30175
30176	if ( hasDuplicate ) {
30177		while ( (elem = results[i++]) ) {
30178			if ( elem === results[ i ] ) {
30179				j = duplicates.push( i );
30180			}
30181		}
30182		while ( j-- ) {
30183			results.splice( duplicates[ j ], 1 );
30184		}
30185	}
30186
30187	// Clear input after sorting to release objects
30188	// See https://github.com/jquery/sizzle/pull/225
30189	sortInput = null;
30190
30191	return results;
30192};
30193
30194/**
30195 * Utility function for retrieving the text value of an array of DOM nodes
30196 * @param {Array|Element} elem
30197 */
30198getText = Sizzle.getText = function( elem ) {
30199	var node,
30200		ret = "",
30201		i = 0,
30202		nodeType = elem.nodeType;
30203
30204	if ( !nodeType ) {
30205		// If no nodeType, this is expected to be an array
30206		while ( (node = elem[i++]) ) {
30207			// Do not traverse comment nodes
30208			ret += getText( node );
30209		}
30210	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
30211		// Use textContent for elements
30212		// innerText usage removed for consistency of new lines (jQuery #11153)
30213		if ( typeof elem.textContent === "string" ) {
30214			return elem.textContent;
30215		} else {
30216			// Traverse its children
30217			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
30218				ret += getText( elem );
30219			}
30220		}
30221	} else if ( nodeType === 3 || nodeType === 4 ) {
30222		return elem.nodeValue;
30223	}
30224	// Do not include comment or processing instruction nodes
30225
30226	return ret;
30227};
30228
30229Expr = Sizzle.selectors = {
30230
30231	// Can be adjusted by the user
30232	cacheLength: 50,
30233
30234	createPseudo: markFunction,
30235
30236	match: matchExpr,
30237
30238	attrHandle: {},
30239
30240	find: {},
30241
30242	relative: {
30243		">": { dir: "parentNode", first: true },
30244		" ": { dir: "parentNode" },
30245		"+": { dir: "previousSibling", first: true },
30246		"~": { dir: "previousSibling" }
30247	},
30248
30249	preFilter: {
30250		"ATTR": function( match ) {
30251			match[1] = match[1].replace( runescape, funescape );
30252
30253			// Move the given value to match[3] whether quoted or unquoted
30254			match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
30255
30256			if ( match[2] === "~=" ) {
30257				match[3] = " " + match[3] + " ";
30258			}
30259
30260			return match.slice( 0, 4 );
30261		},
30262
30263		"CHILD": function( match ) {
30264			/* matches from matchExpr["CHILD"]
30265				1 type (only|nth|...)
30266				2 what (child|of-type)
30267				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
30268				4 xn-component of xn+y argument ([+-]?\d*n|)
30269				5 sign of xn-component
30270				6 x of xn-component
30271				7 sign of y-component
30272				8 y of y-component
30273			*/
30274			match[1] = match[1].toLowerCase();
30275
30276			if ( match[1].slice( 0, 3 ) === "nth" ) {
30277				// nth-* requires argument
30278				if ( !match[3] ) {
30279					Sizzle.error( match[0] );
30280				}
30281
30282				// numeric x and y parameters for Expr.filter.CHILD
30283				// remember that false/true cast respectively to 0/1
30284				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
30285				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
30286
30287			// other types prohibit arguments
30288			} else if ( match[3] ) {
30289				Sizzle.error( match[0] );
30290			}
30291
30292			return match;
30293		},
30294
30295		"PSEUDO": function( match ) {
30296			var excess,
30297				unquoted = !match[6] && match[2];
30298
30299			if ( matchExpr["CHILD"].test( match[0] ) ) {
30300				return null;
30301			}
30302
30303			// Accept quoted arguments as-is
30304			if ( match[3] ) {
30305				match[2] = match[4] || match[5] || "";
30306
30307			// Strip excess characters from unquoted arguments
30308			} else if ( unquoted && rpseudo.test( unquoted ) &&
30309				// Get excess from tokenize (recursively)
30310				(excess = tokenize( unquoted, true )) &&
30311				// advance to the next closing parenthesis
30312				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
30313
30314				// excess is a negative index
30315				match[0] = match[0].slice( 0, excess );
30316				match[2] = unquoted.slice( 0, excess );
30317			}
30318
30319			// Return only captures needed by the pseudo filter method (type and argument)
30320			return match.slice( 0, 3 );
30321		}
30322	},
30323
30324	filter: {
30325
30326		"TAG": function( nodeNameSelector ) {
30327			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
30328			return nodeNameSelector === "*" ?
30329				function() { return true; } :
30330				function( elem ) {
30331					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
30332				};
30333		},
30334
30335		"CLASS": function( className ) {
30336			var pattern = classCache[ className + " " ];
30337
30338			return pattern ||
30339				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
30340				classCache( className, function( elem ) {
30341					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
30342				});
30343		},
30344
30345		"ATTR": function( name, operator, check ) {
30346			return function( elem ) {
30347				var result = Sizzle.attr( elem, name );
30348
30349				if ( result == null ) {
30350					return operator === "!=";
30351				}
30352				if ( !operator ) {
30353					return true;
30354				}
30355
30356				result += "";
30357
30358				return operator === "=" ? result === check :
30359					operator === "!=" ? result !== check :
30360					operator === "^=" ? check && result.indexOf( check ) === 0 :
30361					operator === "*=" ? check && result.indexOf( check ) > -1 :
30362					operator === "$=" ? check && result.slice( -check.length ) === check :
30363					operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
30364					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
30365					false;
30366			};
30367		},
30368
30369		"CHILD": function( type, what, argument, first, last ) {
30370			var simple = type.slice( 0, 3 ) !== "nth",
30371				forward = type.slice( -4 ) !== "last",
30372				ofType = what === "of-type";
30373
30374			return first === 1 && last === 0 ?
30375
30376				// Shortcut for :nth-*(n)
30377				function( elem ) {
30378					return !!elem.parentNode;
30379				} :
30380
30381				function( elem, context, xml ) {
30382					var cache, outerCache, node, diff, nodeIndex, start,
30383						dir = simple !== forward ? "nextSibling" : "previousSibling",
30384						parent = elem.parentNode,
30385						name = ofType && elem.nodeName.toLowerCase(),
30386						useCache = !xml && !ofType;
30387
30388					if ( parent ) {
30389
30390						// :(first|last|only)-(child|of-type)
30391						if ( simple ) {
30392							while ( dir ) {
30393								node = elem;
30394								while ( (node = node[ dir ]) ) {
30395									if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
30396										return false;
30397									}
30398								}
30399								// Reverse direction for :only-* (if we haven't yet done so)
30400								start = dir = type === "only" && !start && "nextSibling";
30401							}
30402							return true;
30403						}
30404
30405						start = [ forward ? parent.firstChild : parent.lastChild ];
30406
30407						// non-xml :nth-child(...) stores cache data on `parent`
30408						if ( forward && useCache ) {
30409							// Seek `elem` from a previously-cached index
30410							outerCache = parent[ expando ] || (parent[ expando ] = {});
30411							cache = outerCache[ type ] || [];
30412							nodeIndex = cache[0] === dirruns && cache[1];
30413							diff = cache[0] === dirruns && cache[2];
30414							node = nodeIndex && parent.childNodes[ nodeIndex ];
30415
30416							while ( (node = ++nodeIndex && node && node[ dir ] ||
30417
30418								// Fallback to seeking `elem` from the start
30419								(diff = nodeIndex = 0) || start.pop()) ) {
30420
30421								// When found, cache indexes on `parent` and break
30422								if ( node.nodeType === 1 && ++diff && node === elem ) {
30423									outerCache[ type ] = [ dirruns, nodeIndex, diff ];
30424									break;
30425								}
30426							}
30427
30428						// Use previously-cached element index if available
30429						} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
30430							diff = cache[1];
30431
30432						// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
30433						} else {
30434							// Use the same loop as above to seek `elem` from the start
30435							while ( (node = ++nodeIndex && node && node[ dir ] ||
30436								(diff = nodeIndex = 0) || start.pop()) ) {
30437
30438								if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
30439									// Cache the index of each encountered element
30440									if ( useCache ) {
30441										(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
30442									}
30443
30444									if ( node === elem ) {
30445										break;
30446									}
30447								}
30448							}
30449						}
30450
30451						// Incorporate the offset, then check against cycle size
30452						diff -= last;
30453						return diff === first || ( diff % first === 0 && diff / first >= 0 );
30454					}
30455				};
30456		},
30457
30458		"PSEUDO": function( pseudo, argument ) {
30459			// pseudo-class names are case-insensitive
30460			// http://www.w3.org/TR/selectors/#pseudo-classes
30461			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
30462			// Remember that setFilters inherits from pseudos
30463			var args,
30464				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
30465					Sizzle.error( "unsupported pseudo: " + pseudo );
30466
30467			// The user may use createPseudo to indicate that
30468			// arguments are needed to create the filter function
30469			// just as Sizzle does
30470			if ( fn[ expando ] ) {
30471				return fn( argument );
30472			}
30473
30474			// But maintain support for old signatures
30475			if ( fn.length > 1 ) {
30476				args = [ pseudo, pseudo, "", argument ];
30477				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
30478					markFunction(function( seed, matches ) {
30479						var idx,
30480							matched = fn( seed, argument ),
30481							i = matched.length;
30482						while ( i-- ) {
30483							idx = indexOf( seed, matched[i] );
30484							seed[ idx ] = !( matches[ idx ] = matched[i] );
30485						}
30486					}) :
30487					function( elem ) {
30488						return fn( elem, 0, args );
30489					};
30490			}
30491
30492			return fn;
30493		}
30494	},
30495
30496	pseudos: {
30497		// Potentially complex pseudos
30498		"not": markFunction(function( selector ) {
30499			// Trim the selector passed to compile
30500			// to avoid treating leading and trailing
30501			// spaces as combinators
30502			var input = [],
30503				results = [],
30504				matcher = compile( selector.replace( rtrim, "$1" ) );
30505
30506			return matcher[ expando ] ?
30507				markFunction(function( seed, matches, context, xml ) {
30508					var elem,
30509						unmatched = matcher( seed, null, xml, [] ),
30510						i = seed.length;
30511
30512					// Match elements unmatched by `matcher`
30513					while ( i-- ) {
30514						if ( (elem = unmatched[i]) ) {
30515							seed[i] = !(matches[i] = elem);
30516						}
30517					}
30518				}) :
30519				function( elem, context, xml ) {
30520					input[0] = elem;
30521					matcher( input, null, xml, results );
30522					// Don't keep the element (issue #299)
30523					input[0] = null;
30524					return !results.pop();
30525				};
30526		}),
30527
30528		"has": markFunction(function( selector ) {
30529			return function( elem ) {
30530				return Sizzle( selector, elem ).length > 0;
30531			};
30532		}),
30533
30534		"contains": markFunction(function( text ) {
30535			text = text.replace( runescape, funescape );
30536			return function( elem ) {
30537				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
30538			};
30539		}),
30540
30541		// "Whether an element is represented by a :lang() selector
30542		// is based solely on the element's language value
30543		// being equal to the identifier C,
30544		// or beginning with the identifier C immediately followed by "-".
30545		// The matching of C against the element's language value is performed case-insensitively.
30546		// The identifier C does not have to be a valid language name."
30547		// http://www.w3.org/TR/selectors/#lang-pseudo
30548		"lang": markFunction( function( lang ) {
30549			// lang value must be a valid identifier
30550			if ( !ridentifier.test(lang || "") ) {
30551				Sizzle.error( "unsupported lang: " + lang );
30552			}
30553			lang = lang.replace( runescape, funescape ).toLowerCase();
30554			return function( elem ) {
30555				var elemLang;
30556				do {
30557					if ( (elemLang = documentIsHTML ?
30558						elem.lang :
30559						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
30560
30561						elemLang = elemLang.toLowerCase();
30562						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
30563					}
30564				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
30565				return false;
30566			};
30567		}),
30568
30569		// Miscellaneous
30570		"target": function( elem ) {
30571			var hash = window.location && window.location.hash;
30572			return hash && hash.slice( 1 ) === elem.id;
30573		},
30574
30575		"root": function( elem ) {
30576			return elem === docElem;
30577		},
30578
30579		"focus": function( elem ) {
30580			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
30581		},
30582
30583		// Boolean properties
30584		"enabled": function( elem ) {
30585			return elem.disabled === false;
30586		},
30587
30588		"disabled": function( elem ) {
30589			return elem.disabled === true;
30590		},
30591
30592		"checked": function( elem ) {
30593			// In CSS3, :checked should return both checked and selected elements
30594			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
30595			var nodeName = elem.nodeName.toLowerCase();
30596			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
30597		},
30598
30599		"selected": function( elem ) {
30600			// Accessing this property makes selected-by-default
30601			// options in Safari work properly
30602			if ( elem.parentNode ) {
30603				elem.parentNode.selectedIndex;
30604			}
30605
30606			return elem.selected === true;
30607		},
30608
30609		// Contents
30610		"empty": function( elem ) {
30611			// http://www.w3.org/TR/selectors/#empty-pseudo
30612			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
30613			//   but not by others (comment: 8; processing instruction: 7; etc.)
30614			// nodeType < 6 works because attributes (2) do not appear as children
30615			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
30616				if ( elem.nodeType < 6 ) {
30617					return false;
30618				}
30619			}
30620			return true;
30621		},
30622
30623		"parent": function( elem ) {
30624			return !Expr.pseudos["empty"]( elem );
30625		},
30626
30627		// Element/input types
30628		"header": function( elem ) {
30629			return rheader.test( elem.nodeName );
30630		},
30631
30632		"input": function( elem ) {
30633			return rinputs.test( elem.nodeName );
30634		},
30635
30636		"button": function( elem ) {
30637			var name = elem.nodeName.toLowerCase();
30638			return name === "input" && elem.type === "button" || name === "button";
30639		},
30640
30641		"text": function( elem ) {
30642			var attr;
30643			return elem.nodeName.toLowerCase() === "input" &&
30644				elem.type === "text" &&
30645
30646				// Support: IE<8
30647				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
30648				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
30649		},
30650
30651		// Position-in-collection
30652		"first": createPositionalPseudo(function() {
30653			return [ 0 ];
30654		}),
30655
30656		"last": createPositionalPseudo(function( matchIndexes, length ) {
30657			return [ length - 1 ];
30658		}),
30659
30660		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
30661			return [ argument < 0 ? argument + length : argument ];
30662		}),
30663
30664		"even": createPositionalPseudo(function( matchIndexes, length ) {
30665			var i = 0;
30666			for ( ; i < length; i += 2 ) {
30667				matchIndexes.push( i );
30668			}
30669			return matchIndexes;
30670		}),
30671
30672		"odd": createPositionalPseudo(function( matchIndexes, length ) {
30673			var i = 1;
30674			for ( ; i < length; i += 2 ) {
30675				matchIndexes.push( i );
30676			}
30677			return matchIndexes;
30678		}),
30679
30680		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
30681			var i = argument < 0 ? argument + length : argument;
30682			for ( ; --i >= 0; ) {
30683				matchIndexes.push( i );
30684			}
30685			return matchIndexes;
30686		}),
30687
30688		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
30689			var i = argument < 0 ? argument + length : argument;
30690			for ( ; ++i < length; ) {
30691				matchIndexes.push( i );
30692			}
30693			return matchIndexes;
30694		})
30695	}
30696};
30697
30698Expr.pseudos["nth"] = Expr.pseudos["eq"];
30699
30700// Add button/input type pseudos
30701for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
30702	Expr.pseudos[ i ] = createInputPseudo( i );
30703}
30704for ( i in { submit: true, reset: true } ) {
30705	Expr.pseudos[ i ] = createButtonPseudo( i );
30706}
30707
30708// Easy API for creating new setFilters
30709function setFilters() {}
30710setFilters.prototype = Expr.filters = Expr.pseudos;
30711Expr.setFilters = new setFilters();
30712
30713tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
30714	var matched, match, tokens, type,
30715		soFar, groups, preFilters,
30716		cached = tokenCache[ selector + " " ];
30717
30718	if ( cached ) {
30719		return parseOnly ? 0 : cached.slice( 0 );
30720	}
30721
30722	soFar = selector;
30723	groups = [];
30724	preFilters = Expr.preFilter;
30725
30726	while ( soFar ) {
30727
30728		// Comma and first run
30729		if ( !matched || (match = rcomma.exec( soFar )) ) {
30730			if ( match ) {
30731				// Don't consume trailing commas as valid
30732				soFar = soFar.slice( match[0].length ) || soFar;
30733			}
30734			groups.push( (tokens = []) );
30735		}
30736
30737		matched = false;
30738
30739		// Combinators
30740		if ( (match = rcombinators.exec( soFar )) ) {
30741			matched = match.shift();
30742			tokens.push({
30743				value: matched,
30744				// Cast descendant combinators to space
30745				type: match[0].replace( rtrim, " " )
30746			});
30747			soFar = soFar.slice( matched.length );
30748		}
30749
30750		// Filters
30751		for ( type in Expr.filter ) {
30752			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
30753				(match = preFilters[ type ]( match ))) ) {
30754				matched = match.shift();
30755				tokens.push({
30756					value: matched,
30757					type: type,
30758					matches: match
30759				});
30760				soFar = soFar.slice( matched.length );
30761			}
30762		}
30763
30764		if ( !matched ) {
30765			break;
30766		}
30767	}
30768
30769	// Return the length of the invalid excess
30770	// if we're just parsing
30771	// Otherwise, throw an error or return tokens
30772	return parseOnly ?
30773		soFar.length :
30774		soFar ?
30775			Sizzle.error( selector ) :
30776			// Cache the tokens
30777			tokenCache( selector, groups ).slice( 0 );
30778};
vendor: 11,230 bytes, lines 30779-31165
30779
30780function toSelector( tokens ) {
30781	var i = 0,
30782		len = tokens.length,
30783		selector = "";
30784	for ( ; i < len; i++ ) {
30785		selector += tokens[i].value;
30786	}
30787	return selector;
30788}
30789
30790function addCombinator( matcher, combinator, base ) {
30791	var dir = combinator.dir,
30792		checkNonElements = base && dir === "parentNode",
30793		doneName = done++;
30794
30795	return combinator.first ?
30796		// Check against closest ancestor/preceding element
30797		function( elem, context, xml ) {
30798			while ( (elem = elem[ dir ]) ) {
30799				if ( elem.nodeType === 1 || checkNonElements ) {
30800					return matcher( elem, context, xml );
30801				}
30802			}
30803		} :
30804
30805		// Check against all ancestor/preceding elements
30806		function( elem, context, xml ) {
30807			var oldCache, outerCache,
30808				newCache = [ dirruns, doneName ];
30809
30810			// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
30811			if ( xml ) {
30812				while ( (elem = elem[ dir ]) ) {
30813					if ( elem.nodeType === 1 || checkNonElements ) {
30814						if ( matcher( elem, context, xml ) ) {
30815							return true;
30816						}
30817					}
30818				}
30819			} else {
30820				while ( (elem = elem[ dir ]) ) {
30821					if ( elem.nodeType === 1 || checkNonElements ) {
30822						outerCache = elem[ expando ] || (elem[ expando ] = {});
30823						if ( (oldCache = outerCache[ dir ]) &&
30824							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
30825
30826							// Assign to newCache so results back-propagate to previous elements
30827							return (newCache[ 2 ] = oldCache[ 2 ]);
30828						} else {
30829							// Reuse newcache so results back-propagate to previous elements
30830							outerCache[ dir ] = newCache;
30831
30832							// A match means we're done; a fail means we have to keep checking
30833							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
30834								return true;
30835							}
30836						}
30837					}
30838				}
30839			}
30840		};
30841}
30842
30843function elementMatcher( matchers ) {
30844	return matchers.length > 1 ?
30845		function( elem, context, xml ) {
30846			var i = matchers.length;
30847			while ( i-- ) {
30848				if ( !matchers[i]( elem, context, xml ) ) {
30849					return false;
30850				}
30851			}
30852			return true;
30853		} :
30854		matchers[0];
30855}
30856
30857function multipleContexts( selector, contexts, results ) {
30858	var i = 0,
30859		len = contexts.length;
30860	for ( ; i < len; i++ ) {
30861		Sizzle( selector, contexts[i], results );
30862	}
30863	return results;
30864}
30865
30866function condense( unmatched, map, filter, context, xml ) {
30867	var elem,
30868		newUnmatched = [],
30869		i = 0,
30870		len = unmatched.length,
30871		mapped = map != null;
30872
30873	for ( ; i < len; i++ ) {
30874		if ( (elem = unmatched[i]) ) {
30875			if ( !filter || filter( elem, context, xml ) ) {
30876				newUnmatched.push( elem );
30877				if ( mapped ) {
30878					map.push( i );
30879				}
30880			}
30881		}
30882	}
30883
30884	return newUnmatched;
30885}
30886
30887function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
30888	if ( postFilter && !postFilter[ expando ] ) {
30889		postFilter = setMatcher( postFilter );
30890	}
30891	if ( postFinder && !postFinder[ expando ] ) {
30892		postFinder = setMatcher( postFinder, postSelector );
30893	}
30894	return markFunction(function( seed, results, context, xml ) {
30895		var temp, i, elem,
30896			preMap = [],
30897			postMap = [],
30898			preexisting = results.length,
30899
30900			// Get initial elements from seed or context
30901			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
30902
30903			// Prefilter to get matcher input, preserving a map for seed-results synchronization
30904			matcherIn = preFilter && ( seed || !selector ) ?
30905				condense( elems, preMap, preFilter, context, xml ) :
30906				elems,
30907
30908			matcherOut = matcher ?
30909				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
30910				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
30911
30912					// ...intermediate processing is necessary
30913					[] :
30914
30915					// ...otherwise use results directly
30916					results :
30917				matcherIn;
30918
30919		// Find primary matches
30920		if ( matcher ) {
30921			matcher( matcherIn, matcherOut, context, xml );
30922		}
30923
30924		// Apply postFilter
30925		if ( postFilter ) {
30926			temp = condense( matcherOut, postMap );
30927			postFilter( temp, [], context, xml );
30928
30929			// Un-match failing elements by moving them back to matcherIn
30930			i = temp.length;
30931			while ( i-- ) {
30932				if ( (elem = temp[i]) ) {
30933					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
30934				}
30935			}
30936		}
30937
30938		if ( seed ) {
30939			if ( postFinder || preFilter ) {
30940				if ( postFinder ) {
30941					// Get the final matcherOut by condensing this intermediate into postFinder contexts
30942					temp = [];
30943					i = matcherOut.length;
30944					while ( i-- ) {
30945						if ( (elem = matcherOut[i]) ) {
30946							// Restore matcherIn since elem is not yet a final match
30947							temp.push( (matcherIn[i] = elem) );
30948						}
30949					}
30950					postFinder( null, (matcherOut = []), temp, xml );
30951				}
30952
30953				// Move matched elements from seed to results to keep them synchronized
30954				i = matcherOut.length;
30955				while ( i-- ) {
30956					if ( (elem = matcherOut[i]) &&
30957						(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
30958
30959						seed[temp] = !(results[temp] = elem);
30960					}
30961				}
30962			}
30963
30964		// Add elements to results, through postFinder if defined
30965		} else {
30966			matcherOut = condense(
30967				matcherOut === results ?
30968					matcherOut.splice( preexisting, matcherOut.length ) :
30969					matcherOut
30970			);
30971			if ( postFinder ) {
30972				postFinder( null, results, matcherOut, xml );
30973			} else {
30974				push.apply( results, matcherOut );
30975			}
30976		}
30977	});
30978}
30979
30980function matcherFromTokens( tokens ) {
30981	var checkContext, matcher, j,
30982		len = tokens.length,
30983		leadingRelative = Expr.relative[ tokens[0].type ],
30984		implicitRelative = leadingRelative || Expr.relative[" "],
30985		i = leadingRelative ? 1 : 0,
30986
30987		// The foundational matcher ensures that elements are reachable from top-level context(s)
30988		matchContext = addCombinator( function( elem ) {
30989			return elem === checkContext;
30990		}, implicitRelative, true ),
30991		matchAnyContext = addCombinator( function( elem ) {
30992			return indexOf( checkContext, elem ) > -1;
30993		}, implicitRelative, true ),
30994		matchers = [ function( elem, context, xml ) {
30995			var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
30996				(checkContext = context).nodeType ?
30997					matchContext( elem, context, xml ) :
30998					matchAnyContext( elem, context, xml ) );
30999			// Avoid hanging onto element (issue #299)
31000			checkContext = null;
31001			return ret;
31002		} ];
31003
31004	for ( ; i < len; i++ ) {
31005		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
31006			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
31007		} else {
31008			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
31009
31010			// Return special upon seeing a positional matcher
31011			if ( matcher[ expando ] ) {
31012				// Find the next relative operator (if any) for proper handling
31013				j = ++i;
31014				for ( ; j < len; j++ ) {
31015					if ( Expr.relative[ tokens[j].type ] ) {
31016						break;
31017					}
31018				}
31019				return setMatcher(
31020					i > 1 && elementMatcher( matchers ),
31021					i > 1 && toSelector(
31022						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
31023						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
31024					).replace( rtrim, "$1" ),
31025					matcher,
31026					i < j && matcherFromTokens( tokens.slice( i, j ) ),
31027					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
31028					j < len && toSelector( tokens )
31029				);
31030			}
31031			matchers.push( matcher );
31032		}
31033	}
31034
31035	return elementMatcher( matchers );
31036}
31037
31038function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
31039	var bySet = setMatchers.length > 0,
31040		byElement = elementMatchers.length > 0,
31041		superMatcher = function( seed, context, xml, results, outermost ) {
31042			var elem, j, matcher,
31043				matchedCount = 0,
31044				i = "0",
31045				unmatched = seed && [],
31046				setMatched = [],
31047				contextBackup = outermostContext,
31048				// We must always have either seed elements or outermost context
31049				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
31050				// Use integer dirruns iff this is the outermost matcher
31051				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
31052				len = elems.length;
31053
31054			if ( outermost ) {
31055				outermostContext = context !== document && context;
31056			}
31057
31058			// Add elements passing elementMatchers directly to results
31059			// Keep `i` a string if there are no elements so `matchedCount` will be "00" below
31060			// Support: IE<9, Safari
31061			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
31062			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
31063				if ( byElement && elem ) {
31064					j = 0;
31065					while ( (matcher = elementMatchers[j++]) ) {
31066						if ( matcher( elem, context, xml ) ) {
31067							results.push( elem );
31068							break;
31069						}
31070					}
31071					if ( outermost ) {
31072						dirruns = dirrunsUnique;
31073					}
31074				}
31075
31076				// Track unmatched elements for set filters
31077				if ( bySet ) {
31078					// They will have gone through all possible matchers
31079					if ( (elem = !matcher && elem) ) {
31080						matchedCount--;
31081					}
31082
31083					// Lengthen the array for every element, matched or not
31084					if ( seed ) {
31085						unmatched.push( elem );
31086					}
31087				}
31088			}
31089
31090			// Apply set filters to unmatched elements
31091			matchedCount += i;
31092			if ( bySet && i !== matchedCount ) {
31093				j = 0;
31094				while ( (matcher = setMatchers[j++]) ) {
31095					matcher( unmatched, setMatched, context, xml );
31096				}
31097
31098				if ( seed ) {
31099					// Reintegrate element matches to eliminate the need for sorting
31100					if ( matchedCount > 0 ) {
31101						while ( i-- ) {
31102							if ( !(unmatched[i] || setMatched[i]) ) {
31103								setMatched[i] = pop.call( results );
31104							}
31105						}
31106					}
31107
31108					// Discard index placeholder values to get only actual matches
31109					setMatched = condense( setMatched );
31110				}
31111
31112				// Add matches to results
31113				push.apply( results, setMatched );
31114
31115				// Seedless set matches succeeding multiple successful matchers stipulate sorting
31116				if ( outermost && !seed && setMatched.length > 0 &&
31117					( matchedCount + setMatchers.length ) > 1 ) {
31118
31119					Sizzle.uniqueSort( results );
31120				}
31121			}
31122
31123			// Override manipulation of globals by nested matchers
31124			if ( outermost ) {
31125				dirruns = dirrunsUnique;
31126				outermostContext = contextBackup;
31127			}
31128
31129			return unmatched;
31130		};
31131
31132	return bySet ?
31133		markFunction( superMatcher ) :
31134		superMatcher;
31135}
31136
31137compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
31138	var i,
31139		setMatchers = [],
31140		elementMatchers = [],
31141		cached = compilerCache[ selector + " " ];
31142
31143	if ( !cached ) {
31144		// Generate a function of recursive functions that can be used to check each element
31145		if ( !match ) {
31146			match = tokenize( selector );
31147		}
31148		i = match.length;
31149		while ( i-- ) {
31150			cached = matcherFromTokens( match[i] );
31151			if ( cached[ expando ] ) {
31152				setMatchers.push( cached );
31153			} else {
31154				elementMatchers.push( cached );
31155			}
31156		}
31157
31158		// Cache the compiled function
31159		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
31160
31161		// Save selector and tokenization
31162		cached.selector = selector;
31163	}
31164	return cached;
31165};
31166
31167/**
31168 * A low-level selection function that works with Sizzle's compiled
31169 *  selector functions
31170 * @param {String|Function} selector A selector or a pre-compiled
31171 *  selector function built with Sizzle.compile
31172 * @param {Element} context
31173 * @param {Array} [results]
31174 * @param {Array} [seed] A set of elements to match against
31175 */
31176select = Sizzle.select = function( selector, context, results, seed ) {
31177	var i, tokens, token, type, find,
31178		compiled = typeof selector === "function" && selector,
31179		match = !seed && tokenize( (selector = compiled.selector || selector) );
31180
31181	results = results || [];
31182
31183	// Try to minimize operations if there is no seed and only one group
31184	if ( match.length === 1 ) {
31185
31186		// Take a shortcut and set the context if the root selector is an ID
31187		tokens = match[0] = match[0].slice( 0 );
31188		if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
31189				support.getById && context.nodeType === 9 && documentIsHTML &&
31190				Expr.relative[ tokens[1].type ] ) {
31191
31192			context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
31193			if ( !context ) {
31194				return results;
31195
31196			// Precompiled matchers will still verify ancestry, so step up a level
31197			} else if ( compiled ) {
31198				context = context.parentNode;
31199			}
31200
31201			selector = selector.slice( tokens.shift().value.length );
31202		}
31203
31204		// Fetch a seed set for right-to-left matching
31205		i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
31206		while ( i-- ) {
31207			token = tokens[i];
31208
31209			// Abort if we hit a combinator
31210			if ( Expr.relative[ (type = token.type) ] ) {
31211				break;
31212			}
31213			if ( (find = Expr.find[ type ]) ) {
31214				// Search, expanding context for leading sibling combinators
31215				if ( (seed = find(
31216					token.matches[0].replace( runescape, funescape ),
31217					rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
31218				)) ) {
31219
31220					// If seed is empty or no tokens remain, we can return early
31221					tokens.splice( i, 1 );
31222					selector = seed.length && toSelector( tokens );
31223					if ( !selector ) {
31224						push.apply( results, seed );
31225						return results;
31226					}
31227
31228					break;
31229				}
31230			}
31231		}
31232	}
31233
31234	// Compile and execute a filtering function if one is not provided
31235	// Provide `match` to avoid retokenization if we modified the selector above
31236	( compiled || compile( selector, match ) )(
31237		seed,
31238		context,
31239		!documentIsHTML,
31240		results,
31241		rsibling.test( selector ) && testContext( context.parentNode ) || context
31242	);
31243	return results;
31244};
31245
31246// One-time assignments
31247
31248// Sort stability
31249support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
31250
31251// Support: Chrome 14-35+
31252// Always assume duplicates if they aren't passed to the comparison function
31253support.detectDuplicates = !!hasDuplicate;
31254
31255// Initialize against the default document
31256setDocument();
31257
31258// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
31259// Detached nodes confoundingly follow *each other*
31260support.sortDetached = assert(function( div1 ) {
31261	// Should return 1, but returns 4 (following)
31262	return div1.compareDocumentPosition( document.createElement("div") ) & 1;
31263});
31264
31265// Support: IE<8
31266// Prevent attribute/property "interpolation"
31267// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
31268if ( !assert(function( div ) {
31269	div.innerHTML = "<a href='#'></a>";
31270	return div.firstChild.getAttribute("href") === "#" ;
31271}) ) {
31272	addHandle( "type|href|height|width", function( elem, name, isXML ) {
31273		if ( !isXML ) {
31274			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
31275		}
31276	});
31277}
31278
31279// Support: IE<9
31280// Use defaultValue in place of getAttribute("value")
31281if ( !support.attributes || !assert(function( div ) {
31282	div.innerHTML = "<input/>";
31283	div.firstChild.setAttribute( "value", "" );
31284	return div.firstChild.getAttribute( "value" ) === "";
31285}) ) {
31286	addHandle( "value", function( elem, name, isXML ) {
31287		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
31288			return elem.defaultValue;
31289		}
31290	});
31291}
31292
31293// Support: IE<9
31294// Use getAttributeNode to fetch booleans when getAttribute lies
31295if ( !assert(function( div ) {
31296	return div.getAttribute("disabled") == null;
31297}) ) {
31298	addHandle( booleans, function( elem, name, isXML ) {
31299		var val;
31300		if ( !isXML ) {
31301			return elem[ name ] === true ? name.toLowerCase() :
31302					(val = elem.getAttributeNode( name )) && val.specified ?
31303					val.value :
31304				null;
31305		}
31306	});
31307}
31308
31309return Sizzle;
31310
31311})( window );
31312
31313
31314
31315jQuery.find = Sizzle;
31316jQuery.expr = Sizzle.selectors;
31317jQuery.expr[":"] = jQuery.expr.pseudos;
31318jQuery.unique = Sizzle.uniqueSort;
31319jQuery.text = Sizzle.getText;
31320jQuery.isXMLDoc = Sizzle.isXML;
31321jQuery.contains = Sizzle.contains;
31322
31323
31324
31325var rneedsContext = jQuery.expr.match.needsContext;
31326
31327var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
31328
31329
31330
31331var risSimple = /^.[^:#\[\.,]*$/;
31332
31333// Implement the identical functionality for filter and not
31334function winnow( elements, qualifier, not ) {
31335	if ( jQuery.isFunction( qualifier ) ) {
31336		return jQuery.grep( elements, function( elem, i ) {
31337			/* jshint -W018 */
31338			return !!qualifier.call( elem, i, elem ) !== not;
31339		});
31340
31341	}
31342
31343	if ( qualifier.nodeType ) {
31344		return jQuery.grep( elements, function( elem ) {
31345			return ( elem === qualifier ) !== not;
31346		});
31347
31348	}
31349
31350	if ( typeof qualifier === "string" ) {
31351		if ( risSimple.test( qualifier ) ) {
31352			return jQuery.filter( qualifier, elements, not );
31353		}
31354
31355		qualifier = jQuery.filter( qualifier, elements );
31356	}
31357
31358	return jQuery.grep( elements, function( elem ) {
31359		return ( indexOf.call( qualifier, elem ) >= 0 ) !== not;
31360	});
31361}
31362
31363jQuery.filter = function( expr, elems, not ) {
31364	var elem = elems[ 0 ];
31365
31366	if ( not ) {
31367		expr = ":not(" + expr + ")";
31368	}
31369
31370	return elems.length === 1 && elem.nodeType === 1 ?
31371		jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
31372		jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
31373			return elem.nodeType === 1;
31374		}));
31375};
31376
31377jQuery.fn.extend({
31378	find: function( selector ) {
31379		var i,
31380			len = this.length,
31381			ret = [],
31382			self = this;
31383
31384		if ( typeof selector !== "string" ) {
31385			return this.pushStack( jQuery( selector ).filter(function() {
31386				for ( i = 0; i < len; i++ ) {
31387					if ( jQuery.contains( self[ i ], this ) ) {
31388						return true;
31389					}
31390				}
31391			}) );
31392		}
31393
31394		for ( i = 0; i < len; i++ ) {
31395			jQuery.find( selector, self[ i ], ret );
31396		}
31397
31398		// Needed because $( selector, context ) becomes $( context ).find( selector )
31399		ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
31400		ret.selector = this.selector ? this.selector + " " + selector : selector;
31401		return ret;
31402	},
31403	filter: function( selector ) {
31404		return this.pushStack( winnow(this, selector || [], false) );
31405	},
31406	not: function( selector ) {
31407		return this.pushStack( winnow(this, selector || [], true) );
31408	},
31409	is: function( selector ) {
31410		return !!winnow(
31411			this,
31412
31413			// If this is a positional/relative selector, check membership in the returned set
31414			// so $("p:first").is("p:last") won't return true for a doc with two "p".
31415			typeof selector === "string" && rneedsContext.test( selector ) ?
31416				jQuery( selector ) :
31417				selector || [],
31418			false
31419		).length;
31420	}
31421});
31422
31423
31424// Initialize a jQuery object
31425
31426
31427// A central reference to the root jQuery(document)
31428var rootjQuery,
31429
31430	// A simple way to check for HTML strings
31431	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
31432	// Strict HTML recognition (#11290: must start with <)
31433	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
31434
31435	init = jQuery.fn.init = function( selector, context ) {
31436		var match, elem;
31437
31438		// HANDLE: $(""), $(null), $(undefined), $(false)
31439		if ( !selector ) {
31440			return this;
31441		}
31442
31443		// Handle HTML strings
31444		if ( typeof selector === "string" ) {
31445			if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) {
31446				// Assume that strings that start and end with <> are HTML and skip the regex check
31447				match = [ null, selector, null ];
31448
31449			} else {
31450				match = rquickExpr.exec( selector );
31451			}
31452
31453			// Match html or make sure no context is specified for #id
31454			if ( match && (match[1] || !context) ) {
31455
31456				// HANDLE: $(html) -> $(array)
31457				if ( match[1] ) {
31458					context = context instanceof jQuery ? context[0] : context;
31459
31460					// Option to run scripts is true for back-compat
31461					// Intentionally let the error be thrown if parseHTML is not present
31462					jQuery.merge( this, jQuery.parseHTML(
31463						match[1],
31464						context && context.nodeType ? context.ownerDocument || context : document,
31465						true
31466					) );
31467
31468					// HANDLE: $(html, props)
31469					if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
31470						for ( match in context ) {
31471							// Properties of context are called as methods if possible
31472							if ( jQuery.isFunction( this[ match ] ) ) {
31473								this[ match ]( context[ match ] );
31474
31475							// ...and otherwise set as attributes
31476							} else {
31477								this.attr( match, context[ match ] );
31478							}
31479						}
31480					}
31481
31482					return this;
31483
31484				// HANDLE: $(#id)
31485				} else {
31486					elem = document.getElementById( match[2] );
31487
31488					// Support: Blackberry 4.6
31489					// gEBID returns nodes no longer in the document (#6963)
31490					if ( elem && elem.parentNode ) {
31491						// Inject the element directly into the jQuery object
31492						this.length = 1;
31493						this[0] = elem;
31494					}
31495
31496					this.context = document;
31497					this.selector = selector;
31498					return this;
31499				}
31500
31501			// HANDLE: $(expr, $(...))
31502			} else if ( !context || context.jquery ) {
31503				return ( context || rootjQuery ).find( selector );
31504
31505			// HANDLE: $(expr, context)
31506			// (which is just equivalent to: $(context).find(expr)
31507			} else {
31508				return this.constructor( context ).find( selector );
31509			}
31510
31511		// HANDLE: $(DOMElement)
31512		} else if ( selector.nodeType ) {
31513			this.context = this[0] = selector;
31514			this.length = 1;
31515			return this;
31516
31517		// HANDLE: $(function)
31518		// Shortcut for document ready
31519		} else if ( jQuery.isFunction( selector ) ) {
31520			return typeof rootjQuery.ready !== "undefined" ?
31521				rootjQuery.ready( selector ) :
31522				// Execute immediately if ready is not present
31523				selector( jQuery );
31524		}
31525
31526		if ( selector.selector !== undefined ) {
31527			this.selector = selector.selector;
31528			this.context = selector.context;
31529		}
31530
31531		return jQuery.makeArray( selector, this );
31532	};
31533
31534// Give the init function the jQuery prototype for later instantiation
31535init.prototype = jQuery.fn;
31536
31537// Initialize central reference
31538rootjQuery = jQuery( document );
31539
31540
31541var rparentsprev = /^(?:parents|prev(?:Until|All))/,
31542	// Methods guaranteed to produce a unique set when starting from a unique set
31543	guaranteedUnique = {
31544		children: true,
31545		contents: true,
31546		next: true,
31547		prev: true
31548	};
31549
31550jQuery.extend({
31551	dir: function( elem, dir, until ) {
31552		var matched = [],
31553			truncate = until !== undefined;
31554
31555		while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {
31556			if ( elem.nodeType === 1 ) {
31557				if ( truncate && jQuery( elem ).is( until ) ) {
31558					break;
31559				}
31560				matched.push( elem );
31561			}
31562		}
31563		return matched;
31564	},
31565
31566	sibling: function( n, elem ) {
31567		var matched = [];
31568
31569		for ( ; n; n = n.nextSibling ) {
31570			if ( n.nodeType === 1 && n !== elem ) {
31571				matched.push( n );
31572			}
31573		}
31574
31575		return matched;
31576	}
31577});
31578
31579jQuery.fn.extend({
31580	has: function( target ) {
31581		var targets = jQuery( target, this ),
31582			l = targets.length;
31583
31584		return this.filter(function() {
31585			var i = 0;
31586			for ( ; i < l; i++ ) {
31587				if ( jQuery.contains( this, targets[i] ) ) {
31588					return true;
31589				}
31590			}
31591		});
31592	},
31593
31594	closest: function( selectors, context ) {
31595		var cur,
31596			i = 0,
31597			l = this.length,
31598			matched = [],
31599			pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
31600				jQuery( selectors, context || this.context ) :
31601				0;
31602
31603		for ( ; i < l; i++ ) {
31604			for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
31605				// Always skip document fragments
31606				if ( cur.nodeType < 11 && (pos ?
31607					pos.index(cur) > -1 :
31608
31609					// Don't pass non-elements to Sizzle
31610					cur.nodeType === 1 &&
31611						jQuery.find.matchesSelector(cur, selectors)) ) {
31612
31613					matched.push( cur );
31614					break;
31615				}
31616			}
31617		}
31618
31619		return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
31620	},
31621
31622	// Determine the position of an element within the set
31623	index: function( elem ) {
31624
31625		// No argument, return index in parent
31626		if ( !elem ) {
31627			return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
31628		}
31629
31630		// Index in selector
31631		if ( typeof elem === "string" ) {
31632			return indexOf.call( jQuery( elem ), this[ 0 ] );
31633		}
31634
31635		// Locate the position of the desired element
31636		return indexOf.call( this,
31637
31638			// If it receives a jQuery object, the first element is used
31639			elem.jquery ? elem[ 0 ] : elem
31640		);
31641	},
31642
31643	add: function( selector, context ) {
31644		return this.pushStack(
31645			jQuery.unique(
31646				jQuery.merge( this.get(), jQuery( selector, context ) )
31647			)
31648		);
31649	},
31650
31651	addBack: function( selector ) {
31652		return this.add( selector == null ?
31653			this.prevObject : this.prevObject.filter(selector)
31654		);
31655	}
31656});
31657
31658function sibling( cur, dir ) {
31659	while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}
31660	return cur;
31661}
31662
31663jQuery.each({
31664	parent: function( elem ) {
31665		var parent = elem.parentNode;
31666		return parent && parent.nodeType !== 11 ? parent : null;
31667	},
31668	parents: function( elem ) {
31669		return jQuery.dir( elem, "parentNode" );
31670	},
31671	parentsUntil: function( elem, i, until ) {
31672		return jQuery.dir( elem, "parentNode", until );
31673	},
31674	next: function( elem ) {
31675		return sibling( elem, "nextSibling" );
31676	},
31677	prev: function( elem ) {
31678		return sibling( elem, "previousSibling" );
31679	},
31680	nextAll: function( elem ) {
31681		return jQuery.dir( elem, "nextSibling" );
31682	},
31683	prevAll: function( elem ) {
31684		return jQuery.dir( elem, "previousSibling" );
31685	},
31686	nextUntil: function( elem, i, until ) {
31687		return jQuery.dir( elem, "nextSibling", until );
31688	},
31689	prevUntil: function( elem, i, until ) {
31690		return jQuery.dir( elem, "previousSibling", until );
31691	},
31692	siblings: function( elem ) {
31693		return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
31694	},
31695	children: function( elem ) {
31696		return jQuery.sibling( elem.firstChild );
31697	},
31698	contents: function( elem ) {
31699		return elem.contentDocument || jQuery.merge( [], elem.childNodes );
31700	}
31701}, function( name, fn ) {
31702	jQuery.fn[ name ] = function( until, selector ) {
31703		var matched = jQuery.map( this, fn, until );
31704
31705		if ( name.slice( -5 ) !== "Until" ) {
31706			selector = until;
31707		}
31708
31709		if ( selector && typeof selector === "string" ) {
31710			matched = jQuery.filter( selector, matched );
31711		}
31712
31713		if ( this.length > 1 ) {
31714			// Remove duplicates
31715			if ( !guaranteedUnique[ name ] ) {
31716				jQuery.unique( matched );
31717			}
31718
31719			// Reverse order for parents* and prev-derivatives
31720			if ( rparentsprev.test( name ) ) {
31721				matched.reverse();
31722			}
31723		}
31724
31725		return this.pushStack( matched );
31726	};
31727});
31728var rnotwhite = (/\S+/g);
31729
31730
31731
31732// String to Object options format cache
31733var optionsCache = {};
31734
31735// Convert String-formatted options into Object-formatted ones and store in cache
31736function createOptions( options ) {
31737	var object = optionsCache[ options ] = {};
31738	jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
31739		object[ flag ] = true;
31740	});
31741	return object;
31742}
31743
31744/*
31745 * Create a callback list using the following parameters:
31746 *
31747 *	options: an optional list of space-separated options that will change how
31748 *			the callback list behaves or a more traditional option object
31749 *
31750 * By default a callback list will act like an event callback list and can be
31751 * "fired" multiple times.
31752 *
31753 * Possible options:
31754 *
31755 *	once:			will ensure the callback list can only be fired once (like a Deferred)
31756 *
31757 *	memory:			will keep track of previous values and will call any callback added
31758 *					after the list has been fired right away with the latest "memorized"
31759 *					values (like a Deferred)
31760 *
31761 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
31762 *
31763 *	stopOnFalse:	interrupt callings when a callback returns false
31764 *
31765 */
31766jQuery.Callbacks = function( options ) {
31767
31768	// Convert options from String-formatted to Object-formatted if needed
31769	// (we check in cache first)
31770	options = typeof options === "string" ?
31771		( optionsCache[ options ] || createOptions( options ) ) :
31772		jQuery.extend( {}, options );
31773
31774	var // Last fire value (for non-forgettable lists)
31775		memory,
31776		// Flag to know if list was already fired
31777		fired,
31778		// Flag to know if list is currently firing
31779		firing,
31780		// First callback to fire (used internally by add and fireWith)
31781		firingStart,
31782		// End of the loop when firing
31783		firingLength,
31784		// Index of currently firing callback (modified by remove if needed)
31785		firingIndex,
31786		// Actual callback list
31787		list = [],
31788		// Stack of fire calls for repeatable lists
31789		stack = !options.once && [],
31790		// Fire callbacks
31791		fire = function( data ) {
31792			memory = options.memory && data;
31793			fired = true;
31794			firingIndex = firingStart || 0;
31795			firingStart = 0;
31796			firingLength = list.length;
31797			firing = true;
31798			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
31799				if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
31800					memory = false; // To prevent further calls using add
31801					break;
31802				}
31803			}
31804			firing = false;
31805			if ( list ) {
31806				if ( stack ) {
31807					if ( stack.length ) {
31808						fire( stack.shift() );
31809					}
31810				} else if ( memory ) {
31811					list = [];
31812				} else {
31813					self.disable();
31814				}
31815			}
31816		},
31817		// Actual Callbacks object
31818		self = {
31819			// Add a callback or a collection of callbacks to the list
31820			add: function() {
31821				if ( list ) {
31822					// First, we save the current length
31823					var start = list.length;
31824					(function add( args ) {
31825						jQuery.each( args, function( _, arg ) {
31826							var type = jQuery.type( arg );
31827							if ( type === "function" ) {
31828								if ( !options.unique || !self.has( arg ) ) {
31829									list.push( arg );
31830								}
31831							} else if ( arg && arg.length && type !== "string" ) {
31832								// Inspect recursively
31833								add( arg );
31834							}
31835						});
31836					})( arguments );
31837					// Do we need to add the callbacks to the
31838					// current firing batch?
31839					if ( firing ) {
31840						firingLength = list.length;
31841					// With memory, if we're not firing then
31842					// we should call right away
31843					} else if ( memory ) {
31844						firingStart = start;
31845						fire( memory );
31846					}
31847				}
31848				return this;
31849			},
31850			// Remove a callback from the list
31851			remove: function() {
31852				if ( list ) {
31853					jQuery.each( arguments, function( _, arg ) {
31854						var index;
31855						while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
31856							list.splice( index, 1 );
31857							// Handle firing indexes
31858							if ( firing ) {
31859								if ( index <= firingLength ) {
31860									firingLength--;
31861								}
31862								if ( index <= firingIndex ) {
31863									firingIndex--;
31864								}
31865							}
31866						}
31867					});
31868				}
31869				return this;
31870			},
31871			// Check if a given callback is in the list.
31872			// If no argument is given, return whether or not list has callbacks attached.
31873			has: function( fn ) {
31874				return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
31875			},
31876			// Remove all callbacks from the list
31877			empty: function() {
31878				list = [];
31879				firingLength = 0;
31880				return this;
31881			},
31882			// Have the list do nothing anymore
31883			disable: function() {
31884				list = stack = memory = undefined;
31885				return this;
31886			},
31887			// Is it disabled?
31888			disabled: function() {
31889				return !list;
31890			},
31891			// Lock the list in its current state
31892			lock: function() {
31893				stack = undefined;
31894				if ( !memory ) {
31895					self.disable();
31896				}
31897				return this;
31898			},
31899			// Is it locked?
31900			locked: function() {
31901				return !stack;
31902			},
31903			// Call all callbacks with the given context and arguments
31904			fireWith: function( context, args ) {
31905				if ( list && ( !fired || stack ) ) {
31906					args = args || [];
31907					args = [ context, args.slice ? args.slice() : args ];
31908					if ( firing ) {
31909						stack.push( args );
31910					} else {
31911						fire( args );
31912					}
31913				}
31914				return this;
31915			},
31916			// Call all the callbacks with the given arguments
31917			fire: function() {
31918				self.fireWith( this, arguments );
31919				return this;
31920			},
31921			// To know if the callbacks have already been called at least once
31922			fired: function() {
31923				return !!fired;
31924			}
31925		};
31926
31927	return self;
31928};
31929
31930
31931jQuery.extend({
31932
31933	Deferred: function( func ) {
31934		var tuples = [
31935				// action, add listener, listener list, final state
31936				[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
31937				[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
31938				[ "notify", "progress", jQuery.Callbacks("memory") ]
31939			],
31940			state = "pending",
31941			promise = {
31942				state: function() {
31943					return state;
31944				},
31945				always: function() {
31946					deferred.done( arguments ).fail( arguments );
31947					return this;
31948				},
31949				then: function( /* fnDone, fnFail, fnProgress */ ) {
31950					var fns = arguments;
31951					return jQuery.Deferred(function( newDefer ) {
31952						jQuery.each( tuples, function( i, tuple ) {
31953							var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
31954							// deferred[ done | fail | progress ] for forwarding actions to newDefer
31955							deferred[ tuple[1] ](function() {
31956								var returned = fn && fn.apply( this, arguments );
31957								if ( returned && jQuery.isFunction( returned.promise ) ) {
31958									returned.promise()
31959										.done( newDefer.resolve )
31960										.fail( newDefer.reject )
31961										.progress( newDefer.notify );
31962								} else {
31963									newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
31964								}
31965							});
31966						});
31967						fns = null;
31968					}).promise();
31969				},
31970				// Get a promise for this deferred
31971				// If obj is provided, the promise aspect is added to the object
31972				promise: function( obj ) {
31973					return obj != null ? jQuery.extend( obj, promise ) : promise;
31974				}
31975			},
31976			deferred = {};
31977
31978		// Keep pipe for back-compat
31979		promise.pipe = promise.then;
31980
31981		// Add list-specific methods
31982		jQuery.each( tuples, function( i, tuple ) {
31983			var list = tuple[ 2 ],
31984				stateString = tuple[ 3 ];
31985
31986			// promise[ done | fail | progress ] = list.add
31987			promise[ tuple[1] ] = list.add;
31988
31989			// Handle state
31990			if ( stateString ) {
31991				list.add(function() {
31992					// state = [ resolved | rejected ]
31993					state = stateString;
31994
31995				// [ reject_list | resolve_list ].disable; progress_list.lock
31996				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
31997			}
31998
31999			// deferred[ resolve | reject | notify ]
32000			deferred[ tuple[0] ] = function() {
32001				deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
32002				return this;
32003			};
32004			deferred[ tuple[0] + "With" ] = list.fireWith;
32005		});
32006
32007		// Make the deferred a promise
32008		promise.promise( deferred );
32009
32010		// Call given func if any
32011		if ( func ) {
32012			func.call( deferred, deferred );
32013		}
32014
32015		// All done!
32016		return deferred;
32017	},
32018
32019	// Deferred helper
32020	when: function( subordinate /* , ..., subordinateN */ ) {
32021		var i = 0,
32022			resolveValues = slice.call( arguments ),
32023			length = resolveValues.length,
32024
32025			// the count of uncompleted subordinates
32026			remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
32027
32028			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
32029			deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
32030
32031			// Update function for both resolve and progress values
32032			updateFunc = function( i, contexts, values ) {
32033				return function( value ) {
32034					contexts[ i ] = this;
32035					values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
32036					if ( values === progressValues ) {
32037						deferred.notifyWith( contexts, values );
32038					} else if ( !( --remaining ) ) {
32039						deferred.resolveWith( contexts, values );
32040					}
32041				};
32042			},
32043
32044			progressValues, progressContexts, resolveContexts;
32045
32046		// Add listeners to Deferred subordinates; treat others as resolved
32047		if ( length > 1 ) {
32048			progressValues = new Array( length );
32049			progressContexts = new Array( length );
32050			resolveContexts = new Array( length );
32051			for ( ; i < length; i++ ) {
32052				if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
32053					resolveValues[ i ].promise()
32054						.done( updateFunc( i, resolveContexts, resolveValues ) )
32055						.fail( deferred.reject )
32056						.progress( updateFunc( i, progressContexts, progressValues ) );
32057				} else {
32058					--remaining;
32059				}
32060			}
32061		}
32062
32063		// If we're not waiting on anything, resolve the master
32064		if ( !remaining ) {
32065			deferred.resolveWith( resolveContexts, resolveValues );
32066		}
32067
32068		return deferred.promise();
32069	}
32070});
32071
32072
32073// The deferred used on DOM ready
32074var readyList;
32075
32076jQuery.fn.ready = function( fn ) {
32077	// Add the callback
32078	jQuery.ready.promise().done( fn );
32079
32080	return this;
32081};
32082
32083jQuery.extend({
32084	// Is the DOM ready to be used? Set to true once it occurs.
32085	isReady: false,
32086
32087	// A counter to track how many items to wait for before
32088	// the ready event fires. See #6781
32089	readyWait: 1,
32090
32091	// Hold (or release) the ready event
32092	holdReady: function( hold ) {
32093		if ( hold ) {
32094			jQuery.readyWait++;
32095		} else {
32096			jQuery.ready( true );
32097		}
32098	},
32099
32100	// Handle when the DOM is ready
32101	ready: function( wait ) {
32102
32103		// Abort if there are pending holds or we're already ready
32104		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
32105			return;
32106		}
32107
32108		// Remember that the DOM is ready
32109		jQuery.isReady = true;
32110
32111		// If a normal DOM Ready event fired, decrement, and wait if need be
32112		if ( wait !== true && --jQuery.readyWait > 0 ) {
32113			return;
32114		}
32115
32116		// If there are functions bound, to execute
32117		readyList.resolveWith( document, [ jQuery ] );
32118
32119		// Trigger any bound ready events
32120		if ( jQuery.fn.triggerHandler ) {
32121			jQuery( document ).triggerHandler( "ready" );
32122			jQuery( document ).off( "ready" );
32123		}
32124	}
32125});
32126
32127/**
32128 * The ready event handler and self cleanup method
32129 */
32130function completed() {
32131	document.removeEventListener( "DOMContentLoaded", completed, false );
32132	window.removeEventListener( "load", completed, false );
32133	jQuery.ready();
32134}
32135
32136jQuery.ready.promise = function( obj ) {
32137	if ( !readyList ) {
32138
32139		readyList = jQuery.Deferred();
32140
32141		// Catch cases where $(document).ready() is called after the browser event has already occurred.
32142		// We once tried to use readyState "interactive" here, but it caused issues like the one
32143		// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
32144		if ( document.readyState === "complete" ) {
32145			// Handle it asynchronously to allow scripts the opportunity to delay ready
32146			setTimeout( jQuery.ready );
32147
32148		} else {
32149
32150			// Use the handy event callback
32151			document.addEventListener( "DOMContentLoaded", completed, false );
32152
32153			// A fallback to window.onload, that will always work
32154			window.addEventListener( "load", completed, false );
32155		}
32156	}
32157	return readyList.promise( obj );
32158};
32159
32160// Kick off the DOM ready check even if the user does not
32161jQuery.ready.promise();
32162
32163
32164
32165
32166// Multifunctional method to get and set values of a collection
32167// The value/s can optionally be executed if it's a function
32168var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
32169	var i = 0,
32170		len = elems.length,
32171		bulk = key == null;
32172
32173	// Sets many values
32174	if ( jQuery.type( key ) === "object" ) {
32175		chainable = true;
32176		for ( i in key ) {
32177			jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
32178		}
32179
32180	// Sets one value
32181	} else if ( value !== undefined ) {
32182		chainable = true;
32183
32184		if ( !jQuery.isFunction( value ) ) {
32185			raw = true;
32186		}
32187
32188		if ( bulk ) {
32189			// Bulk operations run against the entire set
32190			if ( raw ) {
32191				fn.call( elems, value );
32192				fn = null;
32193
32194			// ...except when executing function values
32195			} else {
32196				bulk = fn;
32197				fn = function( elem, key, value ) {
32198					return bulk.call( jQuery( elem ), value );
32199				};
32200			}
32201		}
32202
32203		if ( fn ) {
32204			for ( ; i < len; i++ ) {
32205				fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
32206			}
32207		}
32208	}
32209
32210	return chainable ?
32211		elems :
32212
32213		// Gets
32214		bulk ?
32215			fn.call( elems ) :
32216			len ? fn( elems[0], key ) : emptyGet;
32217};
32218
32219
32220/**
32221 * Determines whether an object can have data
32222 */
32223jQuery.acceptData = function( owner ) {
32224	// Accepts only:
32225	//  - Node
32226	//    - Node.ELEMENT_NODE
32227	//    - Node.DOCUMENT_NODE
32228	//  - Object
32229	//    - Any
32230	/* jshint -W018 */
32231	return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
32232};
32233
32234
32235function Data() {
32236	// Support: Android<4,
32237	// Old WebKit does not have Object.preventExtensions/freeze method,
32238	// return new empty object instead with no [[set]] accessor
32239	Object.defineProperty( this.cache = {}, 0, {
32240		get: function() {
32241			return {};
32242		}
32243	});
32244
32245	this.expando = jQuery.expando + Data.uid++;
32246}
32247
32248Data.uid = 1;
32249Data.accepts = jQuery.acceptData;
32250
32251Data.prototype = {
32252	key: function( owner ) {
32253		// We can accept data for non-element nodes in modern browsers,
32254		// but we should not, see #8335.
32255		// Always return the key for a frozen object.
32256		if ( !Data.accepts( owner ) ) {
32257			return 0;
32258		}
32259
32260		var descriptor = {},
32261			// Check if the owner object already has a cache key
32262			unlock = owner[ this.expando ];
32263
32264		// If not, create one
32265		if ( !unlock ) {
32266			unlock = Data.uid++;
32267
32268			// Secure it in a non-enumerable, non-writable property
32269			try {
32270				descriptor[ this.expando ] = { value: unlock };
32271				Object.defineProperties( owner, descriptor );
32272
32273			// Support: Android<4
32274			// Fallback to a less secure definition
32275			} catch ( e ) {
32276				descriptor[ this.expando ] = unlock;
32277				jQuery.extend( owner, descriptor );
32278			}
32279		}
32280
32281		// Ensure the cache object
32282		if ( !this.cache[ unlock ] ) {
32283			this.cache[ unlock ] = {};
32284		}
32285
32286		return unlock;
32287	},
32288	set: function( owner, data, value ) {
32289		var prop,
32290			// There may be an unlock assigned to this node,
32291			// if there is no entry for this "owner", create one inline
32292			// and set the unlock as though an owner entry had always existed
32293			unlock = this.key( owner ),
32294			cache = this.cache[ unlock ];
32295
32296		// Handle: [ owner, key, value ] args
32297		if ( typeof data === "string" ) {
32298			cache[ data ] = value;
32299
32300		// Handle: [ owner, { properties } ] args
32301		} else {
32302			// Fresh assignments by object are shallow copied
32303			if ( jQuery.isEmptyObject( cache ) ) {
32304				jQuery.extend( this.cache[ unlock ], data );
32305			// Otherwise, copy the properties one-by-one to the cache object
32306			} else {
32307				for ( prop in data ) {
32308					cache[ prop ] = data[ prop ];
32309				}
32310			}
32311		}
32312		return cache;
32313	},
32314	get: function( owner, key ) {
32315		// Either a valid cache is found, or will be created.
32316		// New caches will be created and the unlock returned,
32317		// allowing direct access to the newly created
32318		// empty data object. A valid owner object must be provided.
32319		var cache = this.cache[ this.key( owner ) ];
32320
32321		return key === undefined ?
32322			cache : cache[ key ];
32323	},
32324	access: function( owner, key, value ) {
32325		var stored;
32326		// In cases where either:
32327		//
32328		//   1. No key was specified
32329		//   2. A string key was specified, but no value provided
32330		//
32331		// Take the "read" path and allow the get method to determine
32332		// which value to return, respectively either:
32333		//
32334		//   1. The entire cache object
32335		//   2. The data stored at the key
32336		//
32337		if ( key === undefined ||
32338				((key && typeof key === "string") && value === undefined) ) {
32339
32340			stored = this.get( owner, key );
32341
32342			return stored !== undefined ?
32343				stored : this.get( owner, jQuery.camelCase(key) );
32344		}
32345
32346		// [*]When the key is not a string, or both a key and value
32347		// are specified, set or extend (existing objects) with either:
32348		//
32349		//   1. An object of properties
32350		//   2. A key and value
32351		//
32352		this.set( owner, key, value );
32353
32354		// Since the "set" path can have two possible entry points
32355		// return the expected data based on which path was taken[*]
32356		return value !== undefined ? value : key;
32357	},
32358	remove: function( owner, key ) {
32359		var i, name, camel,
32360			unlock = this.key( owner ),
32361			cache = this.cache[ unlock ];
32362
32363		if ( key === undefined ) {
32364			this.cache[ unlock ] = {};
32365
32366		} else {
32367			// Support array or space separated string of keys
32368			if ( jQuery.isArray( key ) ) {
32369				// If "name" is an array of keys...
32370				// When data is initially created, via ("key", "val") signature,
32371				// keys will be converted to camelCase.
32372				// Since there is no way to tell _how_ a key was added, remove
32373				// both plain key and camelCase key. #12786
32374				// This will only penalize the array argument path.
32375				name = key.concat( key.map( jQuery.camelCase ) );
32376			} else {
32377				camel = jQuery.camelCase( key );
32378				// Try the string as a key before any manipulation
32379				if ( key in cache ) {
32380					name = [ key, camel ];
32381				} else {
32382					// If a key with the spaces exists, use it.
32383					// Otherwise, create an array by matching non-whitespace
32384					name = camel;
32385					name = name in cache ?
32386						[ name ] : ( name.match( rnotwhite ) || [] );
32387				}
32388			}
32389
32390			i = name.length;
32391			while ( i-- ) {
32392				delete cache[ name[ i ] ];
32393			}
32394		}
32395	},
32396	hasData: function( owner ) {
32397		return !jQuery.isEmptyObject(
32398			this.cache[ owner[ this.expando ] ] || {}
32399		);
32400	},
32401	discard: function( owner ) {
32402		if ( owner[ this.expando ] ) {
32403			delete this.cache[ owner[ this.expando ] ];
32404		}
32405	}
32406};
32407var data_priv = new Data();
32408
32409var data_user = new Data();
32410
32411
32412
32413//	Implementation Summary
32414//
32415//	1. Enforce API surface and semantic compatibility with 1.9.x branch
32416//	2. Improve the module's maintainability by reducing the storage
32417//		paths to a single mechanism.
32418//	3. Use the same single mechanism to support "private" and "user" data.
32419//	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
32420//	5. Avoid exposing implementation details on user objects (eg. expando properties)
32421//	6. Provide a clear path for implementation upgrade to WeakMap in 2014
32422
32423var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
32424	rmultiDash = /([A-Z])/g;
32425
32426function dataAttr( elem, key, data ) {
32427	var name;
32428
32429	// If nothing was found internally, try to fetch any
32430	// data from the HTML5 data-* attribute
32431	if ( data === undefined && elem.nodeType === 1 ) {
32432		name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
32433		data = elem.getAttribute( name );
32434
32435		if ( typeof data === "string" ) {
32436			try {
32437				data = data === "true" ? true :
32438					data === "false" ? false :
32439					data === "null" ? null :
32440					// Only convert to a number if it doesn't change the string
32441					+data + "" === data ? +data :
32442					rbrace.test( data ) ? jQuery.parseJSON( data ) :
32443					data;
32444			} catch( e ) {}
32445
32446			// Make sure we set the data so it isn't changed later
32447			data_user.set( elem, key, data );
32448		} else {
32449			data = undefined;
32450		}
32451	}
32452	return data;
32453}
32454
32455jQuery.extend({
32456	hasData: function( elem ) {
32457		return data_user.hasData( elem ) || data_priv.hasData( elem );
32458	},
32459
32460	data: function( elem, name, data ) {
32461		return data_user.access( elem, name, data );
32462	},
32463
32464	removeData: function( elem, name ) {
32465		data_user.remove( elem, name );
32466	},
32467
32468	// TODO: Now that all calls to _data and _removeData have been replaced
32469	// with direct calls to data_priv methods, these can be deprecated.
32470	_data: function( elem, name, data ) {
32471		return data_priv.access( elem, name, data );
32472	},
32473
32474	_removeData: function( elem, name ) {
32475		data_priv.remove( elem, name );
32476	}
32477});
32478
32479jQuery.fn.extend({
32480	data: function( key, value ) {
32481		var i, name, data,
32482			elem = this[ 0 ],
32483			attrs = elem && elem.attributes;
32484
32485		// Gets all values
32486		if ( key === undefined ) {
32487			if ( this.length ) {
32488				data = data_user.get( elem );
32489
32490				if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) {
32491					i = attrs.length;
32492					while ( i-- ) {
32493
32494						// Support: IE11+
32495						// The attrs elements can be null (#14894)
32496						if ( attrs[ i ] ) {
32497							name = attrs[ i ].name;
32498							if ( name.indexOf( "data-" ) === 0 ) {
32499								name = jQuery.camelCase( name.slice(5) );
32500								dataAttr( elem, name, data[ name ] );
32501							}
32502						}
32503					}
32504					data_priv.set( elem, "hasDataAttrs", true );
32505				}
32506			}
32507
32508			return data;
32509		}
32510
32511		// Sets multiple values
32512		if ( typeof key === "object" ) {
32513			return this.each(function() {
32514				data_user.set( this, key );
32515			});
32516		}
32517
32518		return access( this, function( value ) {
32519			var data,
32520				camelKey = jQuery.camelCase( key );
32521
32522			// The calling jQuery object (element matches) is not empty
32523			// (and therefore has an element appears at this[ 0 ]) and the
32524			// `value` parameter was not undefined. An empty jQuery object
32525			// will result in `undefined` for elem = this[ 0 ] which will
32526			// throw an exception if an attempt to read a data cache is made.
32527			if ( elem && value === undefined ) {
32528				// Attempt to get data from the cache
32529				// with the key as-is
32530				data = data_user.get( elem, key );
32531				if ( data !== undefined ) {
32532					return data;
32533				}
32534
32535				// Attempt to get data from the cache
32536				// with the key camelized
32537				data = data_user.get( elem, camelKey );
32538				if ( data !== undefined ) {
32539					return data;
32540				}
32541
32542				// Attempt to "discover" the data in
32543				// HTML5 custom data-* attrs
32544				data = dataAttr( elem, camelKey, undefined );
32545				if ( data !== undefined ) {
32546					return data;
32547				}
32548
32549				// We tried really hard, but the data doesn't exist.
32550				return;
32551			}
32552
32553			// Set the data...
32554			this.each(function() {
32555				// First, attempt to store a copy or reference of any
32556				// data that might've been store with a camelCased key.
32557				var data = data_user.get( this, camelKey );
32558
32559				// For HTML5 data-* attribute interop, we have to
32560				// store property names with dashes in a camelCase form.
32561				// This might not apply to all properties...*
32562				data_user.set( this, camelKey, value );
32563
32564				// *... In the case of properties that might _actually_
32565				// have dashes, we need to also store a copy of that
32566				// unchanged property.
32567				if ( key.indexOf("-") !== -1 && data !== undefined ) {
32568					data_user.set( this, key, value );
32569				}
32570			});
32571		}, null, value, arguments.length > 1, null, true );
32572	},
32573
32574	removeData: function( key ) {
32575		return this.each(function() {
32576			data_user.remove( this, key );
32577		});
32578	}
32579});
32580
32581
32582jQuery.extend({
32583	queue: function( elem, type, data ) {
32584		var queue;
32585
32586		if ( elem ) {
32587			type = ( type || "fx" ) + "queue";
32588			queue = data_priv.get( elem, type );
32589
32590			// Speed up dequeue by getting out quickly if this is just a lookup
32591			if ( data ) {
32592				if ( !queue || jQuery.isArray( data ) ) {
32593					queue = data_priv.access( elem, type, jQuery.makeArray(data) );
32594				} else {
32595					queue.push( data );
32596				}
32597			}
32598			return queue || [];
32599		}
32600	},
32601
32602	dequeue: function( elem, type ) {
vendor: 3,566 bytes, lines 32603-32744
32603		type = type || "fx";
32604
32605		var queue = jQuery.queue( elem, type ),
32606			startLength = queue.length,
32607			fn = queue.shift(),
32608			hooks = jQuery._queueHooks( elem, type ),
32609			next = function() {
32610				jQuery.dequeue( elem, type );
32611			};
32612
32613		// If the fx queue is dequeued, always remove the progress sentinel
32614		if ( fn === "inprogress" ) {
32615			fn = queue.shift();
32616			startLength--;
32617		}
32618
32619		if ( fn ) {
32620
32621			// Add a progress sentinel to prevent the fx queue from being
32622			// automatically dequeued
32623			if ( type === "fx" ) {
32624				queue.unshift( "inprogress" );
32625			}
32626
32627			// Clear up the last queue stop function
32628			delete hooks.stop;
32629			fn.call( elem, next, hooks );
32630		}
32631
32632		if ( !startLength && hooks ) {
32633			hooks.empty.fire();
32634		}
32635	},
32636
32637	// Not public - generate a queueHooks object, or return the current one
32638	_queueHooks: function( elem, type ) {
32639		var key = type + "queueHooks";
32640		return data_priv.get( elem, key ) || data_priv.access( elem, key, {
32641			empty: jQuery.Callbacks("once memory").add(function() {
32642				data_priv.remove( elem, [ type + "queue", key ] );
32643			})
32644		});
32645	}
32646});
32647
32648jQuery.fn.extend({
32649	queue: function( type, data ) {
32650		var setter = 2;
32651
32652		if ( typeof type !== "string" ) {
32653			data = type;
32654			type = "fx";
32655			setter--;
32656		}
32657
32658		if ( arguments.length < setter ) {
32659			return jQuery.queue( this[0], type );
32660		}
32661
32662		return data === undefined ?
32663			this :
32664			this.each(function() {
32665				var queue = jQuery.queue( this, type, data );
32666
32667				// Ensure a hooks for this queue
32668				jQuery._queueHooks( this, type );
32669
32670				if ( type === "fx" && queue[0] !== "inprogress" ) {
32671					jQuery.dequeue( this, type );
32672				}
32673			});
32674	},
32675	dequeue: function( type ) {
32676		return this.each(function() {
32677			jQuery.dequeue( this, type );
32678		});
32679	},
32680	clearQueue: function( type ) {
32681		return this.queue( type || "fx", [] );
32682	},
32683	// Get a promise resolved when queues of a certain type
32684	// are emptied (fx is the type by default)
32685	promise: function( type, obj ) {
32686		var tmp,
32687			count = 1,
32688			defer = jQuery.Deferred(),
32689			elements = this,
32690			i = this.length,
32691			resolve = function() {
32692				if ( !( --count ) ) {
32693					defer.resolveWith( elements, [ elements ] );
32694				}
32695			};
32696
32697		if ( typeof type !== "string" ) {
32698			obj = type;
32699			type = undefined;
32700		}
32701		type = type || "fx";
32702
32703		while ( i-- ) {
32704			tmp = data_priv.get( elements[ i ], type + "queueHooks" );
32705			if ( tmp && tmp.empty ) {
32706				count++;
32707				tmp.empty.add( resolve );
32708			}
32709		}
32710		resolve();
32711		return defer.promise( obj );
32712	}
32713});
32714var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
32715
32716var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
32717
32718var isHidden = function( elem, el ) {
32719		// isHidden might be called from jQuery#filter function;
32720		// in that case, element will be second argument
32721		elem = el || elem;
32722		return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
32723	};
32724
32725var rcheckableType = (/^(?:checkbox|radio)$/i);
32726
32727
32728
32729(function() {
32730	var fragment = document.createDocumentFragment(),
32731		div = fragment.appendChild( document.createElement( "div" ) ),
32732		input = document.createElement( "input" );
32733
32734	// Support: Safari<=5.1
32735	// Check state lost if the name is set (#11217)
32736	// Support: Windows Web Apps (WWA)
32737	// `name` and `type` must use .setAttribute for WWA (#14901)
32738	input.setAttribute( "type", "radio" );
32739	input.setAttribute( "checked", "checked" );
32740	input.setAttribute( "name", "t" );
32741
32742	div.appendChild( input );
32743
32744	// Support: Safari<=5.1, Android<4.2
32745	// Older WebKit doesn't clone checked state correctly in fragments
32746	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
32747
32748	// Support: IE<=11+
32749	// Make sure textarea (and checkbox) defaultValue is properly cloned
32750	div.innerHTML = "<textarea>x</textarea>";
32751	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
32752})();
32753var strundefined = typeof undefined;
32754
32755
32756
32757support.focusinBubbles = "onfocusin" in window;
32758
32759
32760var
32761	rkeyEvent = /^key/,
32762	rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
32763	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
32764	rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
32765
32766function returnTrue() {
32767	return true;
32768}
32769
32770function returnFalse() {
32771	return false;
32772}
32773
32774function safeActiveElement() {
32775	try {
32776		return document.activeElement;
32777	} catch ( err ) { }
32778}
32779
32780/*
32781 * Helper functions for managing events -- not part of the public interface.
32782 * Props to Dean Edwards' addEvent library for many of the ideas.
32783 */
32784jQuery.event = {
32785
32786	global: {},
32787
32788	add: function( elem, types, handler, data, selector ) {
32789
32790		var handleObjIn, eventHandle, tmp,
32791			events, t, handleObj,
32792			special, handlers, type, namespaces, origType,
32793			elemData = data_priv.get( elem );
32794
32795		// Don't attach events to noData or text/comment nodes (but allow plain objects)
32796		if ( !elemData ) {
32797			return;
32798		}
32799
32800		// Caller can pass in an object of custom data in lieu of the handler
32801		if ( handler.handler ) {
32802			handleObjIn = handler;
32803			handler = handleObjIn.handler;
32804			selector = handleObjIn.selector;
32805		}
32806
32807		// Make sure that the handler has a unique ID, used to find/remove it later
32808		if ( !handler.guid ) {
32809			handler.guid = jQuery.guid++;
32810		}
32811
32812		// Init the element's event structure and main handler, if this is the first
32813		if ( !(events = elemData.events) ) {
32814			events = elemData.events = {};
32815		}
32816		if ( !(eventHandle = elemData.handle) ) {
32817			eventHandle = elemData.handle = function( e ) {
32818				// Discard the second event of a jQuery.event.trigger() and
32819				// when an event is called after a page has unloaded
32820				return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?
32821					jQuery.event.dispatch.apply( elem, arguments ) : undefined;
32822			};
32823		}
32824
32825		// Handle multiple events separated by a space
32826		types = ( types || "" ).match( rnotwhite ) || [ "" ];
32827		t = types.length;
32828		while ( t-- ) {
32829			tmp = rtypenamespace.exec( types[t] ) || [];
32830			type = origType = tmp[1];
32831			namespaces = ( tmp[2] || "" ).split( "." ).sort();
32832
32833			// There *must* be a type, no attaching namespace-only handlers
32834			if ( !type ) {
32835				continue;
32836			}
32837
32838			// If event changes its type, use the special event handlers for the changed type
32839			special = jQuery.event.special[ type ] || {};
32840
32841			// If selector defined, determine special event api type, otherwise given type
32842			type = ( selector ? special.delegateType : special.bindType ) || type;
32843
32844			// Update special based on newly reset type
32845			special = jQuery.event.special[ type ] || {};
32846
32847			// handleObj is passed to all event handlers
32848			handleObj = jQuery.extend({
32849				type: type,
32850				origType: origType,
32851				data: data,
32852				handler: handler,
32853				guid: handler.guid,
32854				selector: selector,
32855				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
32856				namespace: namespaces.join(".")
32857			}, handleObjIn );
32858
32859			// Init the event handler queue if we're the first
32860			if ( !(handlers = events[ type ]) ) {
32861				handlers = events[ type ] = [];
32862				handlers.delegateCount = 0;
32863
32864				// Only use addEventListener if the special events handler returns false
32865				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
32866					if ( elem.addEventListener ) {
32867						elem.addEventListener( type, eventHandle, false );
32868					}
32869				}
32870			}
32871
32872			if ( special.add ) {
32873				special.add.call( elem, handleObj );
32874
32875				if ( !handleObj.handler.guid ) {
32876					handleObj.handler.guid = handler.guid;
32877				}
32878			}
32879
32880			// Add to the element's handler list, delegates in front
32881			if ( selector ) {
32882				handlers.splice( handlers.delegateCount++, 0, handleObj );
32883			} else {
32884				handlers.push( handleObj );
32885			}
32886
32887			// Keep track of which events have ever been used, for event optimization
32888			jQuery.event.global[ type ] = true;
32889		}
32890
32891	},
32892
32893	// Detach an event or set of events from an element
32894	remove: function( elem, types, handler, selector, mappedTypes ) {
32895
32896		var j, origCount, tmp,
32897			events, t, handleObj,
32898			special, handlers, type, namespaces, origType,
32899			elemData = data_priv.hasData( elem ) && data_priv.get( elem );
32900
32901		if ( !elemData || !(events = elemData.events) ) {
32902			return;
32903		}
32904
vendor: 8,359 bytes, lines 32905-33162
32905		// Once for each type.namespace in types; type may be omitted
32906		types = ( types || "" ).match( rnotwhite ) || [ "" ];
32907		t = types.length;
32908		while ( t-- ) {
32909			tmp = rtypenamespace.exec( types[t] ) || [];
32910			type = origType = tmp[1];
32911			namespaces = ( tmp[2] || "" ).split( "." ).sort();
32912
32913			// Unbind all events (on this namespace, if provided) for the element
32914			if ( !type ) {
32915				for ( type in events ) {
32916					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
32917				}
32918				continue;
32919			}
32920
32921			special = jQuery.event.special[ type ] || {};
32922			type = ( selector ? special.delegateType : special.bindType ) || type;
32923			handlers = events[ type ] || [];
32924			tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
32925
32926			// Remove matching events
32927			origCount = j = handlers.length;
32928			while ( j-- ) {
32929				handleObj = handlers[ j ];
32930
32931				if ( ( mappedTypes || origType === handleObj.origType ) &&
32932					( !handler || handler.guid === handleObj.guid ) &&
32933					( !tmp || tmp.test( handleObj.namespace ) ) &&
32934					( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
32935					handlers.splice( j, 1 );
32936
32937					if ( handleObj.selector ) {
32938						handlers.delegateCount--;
32939					}
32940					if ( special.remove ) {
32941						special.remove.call( elem, handleObj );
32942					}
32943				}
32944			}
32945
32946			// Remove generic event handler if we removed something and no more handlers exist
32947			// (avoids potential for endless recursion during removal of special event handlers)
32948			if ( origCount && !handlers.length ) {
32949				if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
32950					jQuery.removeEvent( elem, type, elemData.handle );
32951				}
32952
32953				delete events[ type ];
32954			}
32955		}
32956
32957		// Remove the expando if it's no longer used
32958		if ( jQuery.isEmptyObject( events ) ) {
32959			delete elemData.handle;
32960			data_priv.remove( elem, "events" );
32961		}
32962	},
32963
32964	trigger: function( event, data, elem, onlyHandlers ) {
32965
32966		var i, cur, tmp, bubbleType, ontype, handle, special,
32967			eventPath = [ elem || document ],
32968			type = hasOwn.call( event, "type" ) ? event.type : event,
32969			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
32970
32971		cur = tmp = elem = elem || document;
32972
32973		// Don't do events on text and comment nodes
32974		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
32975			return;
32976		}
32977
32978		// focus/blur morphs to focusin/out; ensure we're not firing them right now
32979		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
32980			return;
32981		}
32982
32983		if ( type.indexOf(".") >= 0 ) {
32984			// Namespaced trigger; create a regexp to match event type in handle()
32985			namespaces = type.split(".");
32986			type = namespaces.shift();
32987			namespaces.sort();
32988		}
32989		ontype = type.indexOf(":") < 0 && "on" + type;
32990
32991		// Caller can pass in a jQuery.Event object, Object, or just an event type string
32992		event = event[ jQuery.expando ] ?
32993			event :
32994			new jQuery.Event( type, typeof event === "object" && event );
32995
32996		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
32997		event.isTrigger = onlyHandlers ? 2 : 3;
32998		event.namespace = namespaces.join(".");
32999		event.namespace_re = event.namespace ?
33000			new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
33001			null;
33002
33003		// Clean up the event in case it is being reused
33004		event.result = undefined;
33005		if ( !event.target ) {
33006			event.target = elem;
33007		}
33008
33009		// Clone any incoming data and prepend the event, creating the handler arg list
33010		data = data == null ?
33011			[ event ] :
33012			jQuery.makeArray( data, [ event ] );
33013
33014		// Allow special events to draw outside the lines
33015		special = jQuery.event.special[ type ] || {};
33016		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
33017			return;
33018		}
33019
33020		// Determine event propagation path in advance, per W3C events spec (#9951)
33021		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
33022		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
33023
33024			bubbleType = special.delegateType || type;
33025			if ( !rfocusMorph.test( bubbleType + type ) ) {
33026				cur = cur.parentNode;
33027			}
33028			for ( ; cur; cur = cur.parentNode ) {
33029				eventPath.push( cur );
33030				tmp = cur;
33031			}
33032
33033			// Only add window if we got to document (e.g., not plain obj or detached DOM)
33034			if ( tmp === (elem.ownerDocument || document) ) {
33035				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
33036			}
33037		}
33038
33039		// Fire handlers on the event path
33040		i = 0;
33041		while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
33042
33043			event.type = i > 1 ?
33044				bubbleType :
33045				special.bindType || type;
33046
33047			// jQuery handler
33048			handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" );
33049			if ( handle ) {
33050				handle.apply( cur, data );
33051			}
33052
33053			// Native handler
33054			handle = ontype && cur[ ontype ];
33055			if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
33056				event.result = handle.apply( cur, data );
33057				if ( event.result === false ) {
33058					event.preventDefault();
33059				}
33060			}
33061		}
33062		event.type = type;
33063
33064		// If nobody prevented the default action, do it now
33065		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
33066
33067			if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
33068				jQuery.acceptData( elem ) ) {
33069
33070				// Call a native DOM method on the target with the same name name as the event.
33071				// Don't do default actions on window, that's where global variables be (#6170)
33072				if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
33073
33074					// Don't re-trigger an onFOO event when we call its FOO() method
33075					tmp = elem[ ontype ];
33076
33077					if ( tmp ) {
33078						elem[ ontype ] = null;
33079					}
33080
33081					// Prevent re-triggering of the same event, since we already bubbled it above
33082					jQuery.event.triggered = type;
33083					elem[ type ]();
33084					jQuery.event.triggered = undefined;
33085
33086					if ( tmp ) {
33087						elem[ ontype ] = tmp;
33088					}
33089				}
33090			}
33091		}
33092
33093		return event.result;
33094	},
33095
33096	dispatch: function( event ) {
33097
33098		// Make a writable jQuery.Event from the native event object
33099		event = jQuery.event.fix( event );
33100
33101		var i, j, ret, matched, handleObj,
33102			handlerQueue = [],
33103			args = slice.call( arguments ),
33104			handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [],
33105			special = jQuery.event.special[ event.type ] || {};
33106
33107		// Use the fix-ed jQuery.Event rather than the (read-only) native event
33108		args[0] = event;
33109		event.delegateTarget = this;
33110
33111		// Call the preDispatch hook for the mapped type, and let it bail if desired
33112		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
33113			return;
33114		}
33115
33116		// Determine handlers
33117		handlerQueue = jQuery.event.handlers.call( this, event, handlers );
33118
33119		// Run delegates first; they may want to stop propagation beneath us
33120		i = 0;
33121		while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
33122			event.currentTarget = matched.elem;
33123
33124			j = 0;
33125			while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
33126
33127				// Triggered event must either 1) have no namespace, or 2) have namespace(s)
33128				// a subset or equal to those in the bound event (both can have no namespace).
33129				if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
33130
33131					event.handleObj = handleObj;
33132					event.data = handleObj.data;
33133
33134					ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
33135							.apply( matched.elem, args );
33136
33137					if ( ret !== undefined ) {
33138						if ( (event.result = ret) === false ) {
33139							event.preventDefault();
33140							event.stopPropagation();
33141						}
33142					}
33143				}
33144			}
33145		}
33146
33147		// Call the postDispatch hook for the mapped type
33148		if ( special.postDispatch ) {
33149			special.postDispatch.call( this, event );
33150		}
33151
33152		return event.result;
33153	},
33154
33155	handlers: function( event, handlers ) {
33156		var i, matches, sel, handleObj,
33157			handlerQueue = [],
33158			delegateCount = handlers.delegateCount,
33159			cur = event.target;
33160
33161		// Find delegate handlers
33162		// Black-hole SVG <use> instance trees (#13180)
33163		// Avoid non-left-click bubbling in Firefox (#3861)
33164		if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
33165
33166			for ( ; cur !== this; cur = cur.parentNode || this ) {
33167
33168				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
33169				if ( cur.disabled !== true || event.type !== "click" ) {
33170					matches = [];
33171					for ( i = 0; i < delegateCount; i++ ) {
33172						handleObj = handlers[ i ];
33173
33174						// Don't conflict with Object.prototype properties (#13203)
33175						sel = handleObj.selector + " ";
33176
33177						if ( matches[ sel ] === undefined ) {
33178							matches[ sel ] = handleObj.needsContext ?
33179								jQuery( sel, this ).index( cur ) >= 0 :
33180								jQuery.find( sel, this, null, [ cur ] ).length;
33181						}
33182						if ( matches[ sel ] ) {
33183							matches.push( handleObj );
33184						}
33185					}
33186					if ( matches.length ) {
33187						handlerQueue.push({ elem: cur, handlers: matches });
33188					}
33189				}
33190			}
33191		}
33192
33193		// Add the remaining (directly-bound) handlers
33194		if ( delegateCount < handlers.length ) {
33195			handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
33196		}
33197
33198		return handlerQueue;
33199	},
33200
33201	// Includes some event props shared by KeyEvent and MouseEvent
33202	props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
33203
33204	fixHooks: {},
33205
33206	keyHooks: {
33207		props: "char charCode key keyCode".split(" "),
33208		filter: function( event, original ) {
33209
33210			// Add which for key events
33211			if ( event.which == null ) {
33212				event.which = original.charCode != null ? original.charCode : original.keyCode;
33213			}
33214
33215			return event;
33216		}
33217	},
33218
33219	mouseHooks: {
33220		props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
33221		filter: function( event, original ) {
33222			var eventDoc, doc, body,
33223				button = original.button;
33224
33225			// Calculate pageX/Y if missing and clientX/Y available
33226			if ( event.pageX == null && original.clientX != null ) {
33227				eventDoc = event.target.ownerDocument || document;
33228				doc = eventDoc.documentElement;
33229				body = eventDoc.body;
33230
33231				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
33232				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
33233			}
33234
33235			// Add which for click: 1 === left; 2 === middle; 3 === right
33236			// Note: button is not normalized, so don't use it
33237			if ( !event.which && button !== undefined ) {
33238				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
33239			}
33240
33241			return event;
33242		}
33243	},
33244
33245	fix: function( event ) {
33246		if ( event[ jQuery.expando ] ) {
33247			return event;
33248		}
33249
33250		// Create a writable copy of the event object and normalize some properties
33251		var i, prop, copy,
33252			type = event.type,
33253			originalEvent = event,
33254			fixHook = this.fixHooks[ type ];
33255
33256		if ( !fixHook ) {
33257			this.fixHooks[ type ] = fixHook =
33258				rmouseEvent.test( type ) ? this.mouseHooks :
33259				rkeyEvent.test( type ) ? this.keyHooks :
33260				{};
33261		}
33262		copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
33263
33264		event = new jQuery.Event( originalEvent );
33265
33266		i = copy.length;
33267		while ( i-- ) {
33268			prop = copy[ i ];
33269			event[ prop ] = originalEvent[ prop ];
33270		}
33271
33272		// Support: Cordova 2.5 (WebKit) (#13255)
33273		// All events should have a target; Cordova deviceready doesn't
33274		if ( !event.target ) {
33275			event.target = document;
33276		}
33277
33278		// Support: Safari 6.0+, Chrome<28
33279		// Target should not be a text node (#504, #13143)
33280		if ( event.target.nodeType === 3 ) {
33281			event.target = event.target.parentNode;
33282		}
33283
33284		return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
33285	},
33286
33287	special: {
33288		load: {
33289			// Prevent triggered image.load events from bubbling to window.load
33290			noBubble: true
33291		},
33292		focus: {
33293			// Fire native event if possible so blur/focus sequence is correct
33294			trigger: function() {
33295				if ( this !== safeActiveElement() && this.focus ) {
33296					this.focus();
33297					return false;
33298				}
33299			},
33300			delegateType: "focusin"
33301		},
33302		blur: {
33303			trigger: function() {
33304				if ( this === safeActiveElement() && this.blur ) {
33305					this.blur();
33306					return false;
33307				}
33308			},
33309			delegateType: "focusout"
33310		},
33311		click: {
33312			// For checkbox, fire native event so checked state will be right
33313			trigger: function() {
33314				if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
33315					this.click();
33316					return false;
33317				}
33318			},
33319
33320			// For cross-browser consistency, don't fire native .click() on links
33321			_default: function( event ) {
33322				return jQuery.nodeName( event.target, "a" );
33323			}
33324		},
33325
33326		beforeunload: {
33327			postDispatch: function( event ) {
33328
33329				// Support: Firefox 20+
33330				// Firefox doesn't alert if the returnValue field is not set.
33331				if ( event.result !== undefined && event.originalEvent ) {
33332					event.originalEvent.returnValue = event.result;
33333				}
33334			}
33335		}
33336	},
33337
33338	simulate: function( type, elem, event, bubble ) {
33339		// Piggyback on a donor event to simulate a different one.
33340		// Fake originalEvent to avoid donor's stopPropagation, but if the
33341		// simulated event prevents default then we do the same on the donor.
33342		var e = jQuery.extend(
33343			new jQuery.Event(),
33344			event,
33345			{
33346				type: type,
33347				isSimulated: true,
33348				originalEvent: {}
33349			}
33350		);
33351		if ( bubble ) {
33352			jQuery.event.trigger( e, null, elem );
33353		} else {
33354			jQuery.event.dispatch.call( elem, e );
33355		}
33356		if ( e.isDefaultPrevented() ) {
33357			event.preventDefault();
33358		}
33359	}
33360};
33361
33362jQuery.removeEvent = function( elem, type, handle ) {
33363	if ( elem.removeEventListener ) {
33364		elem.removeEventListener( type, handle, false );
33365	}
33366};
33367
33368jQuery.Event = function( src, props ) {
33369	// Allow instantiation without the 'new' keyword
33370	if ( !(this instanceof jQuery.Event) ) {
33371		return new jQuery.Event( src, props );
33372	}
33373
33374	// Event object
33375	if ( src && src.type ) {
33376		this.originalEvent = src;
33377		this.type = src.type;
33378
33379		// Events bubbling up the document may have been marked as prevented
33380		// by a handler lower down the tree; reflect the correct value.
33381		this.isDefaultPrevented = src.defaultPrevented ||
33382				src.defaultPrevented === undefined &&
33383				// Support: Android<4.0
33384				src.returnValue === false ?
33385			returnTrue :
33386			returnFalse;
33387
33388	// Event type
33389	} else {
33390		this.type = src;
33391	}
33392
33393	// Put explicitly provided properties onto the event object
33394	if ( props ) {
33395		jQuery.extend( this, props );
33396	}
33397
33398	// Create a timestamp if incoming event doesn't have one
33399	this.timeStamp = src && src.timeStamp || jQuery.now();
33400
33401	// Mark it as fixed
33402	this[ jQuery.expando ] = true;
33403};
33404
33405// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
33406// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
33407jQuery.Event.prototype = {
33408	isDefaultPrevented: returnFalse,
33409	isPropagationStopped: returnFalse,
33410	isImmediatePropagationStopped: returnFalse,
33411
33412	preventDefault: function() {
33413		var e = this.originalEvent;
33414
33415		this.isDefaultPrevented = returnTrue;
33416
33417		if ( e && e.preventDefault ) {
33418			e.preventDefault();
33419		}
33420	},
33421	stopPropagation: function() {
33422		var e = this.originalEvent;
33423
33424		this.isPropagationStopped = returnTrue;
33425
33426		if ( e && e.stopPropagation ) {
33427			e.stopPropagation();
33428		}
33429	},
33430	stopImmediatePropagation: function() {
33431		var e = this.originalEvent;
33432
33433		this.isImmediatePropagationStopped = returnTrue;
33434
33435		if ( e && e.stopImmediatePropagation ) {
33436			e.stopImmediatePropagation();
33437		}
33438
33439		this.stopPropagation();
33440	}
33441};
33442
33443// Create mouseenter/leave events using mouseover/out and event-time checks
33444// Support: Chrome 15+
33445jQuery.each({
33446	mouseenter: "mouseover",
33447	mouseleave: "mouseout",
33448	pointerenter: "pointerover",
33449	pointerleave: "pointerout"
33450}, function( orig, fix ) {
33451	jQuery.event.special[ orig ] = {
33452		delegateType: fix,
33453		bindType: fix,
33454
33455		handle: function( event ) {
33456			var ret,
33457				target = this,
33458				related = event.relatedTarget,
33459				handleObj = event.handleObj;
33460
33461			// For mousenter/leave call the handler if related is outside the target.
33462			// NB: No relatedTarget if the mouse left/entered the browser window
33463			if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
33464				event.type = handleObj.origType;
33465				ret = handleObj.handler.apply( this, arguments );
33466				event.type = fix;
33467			}
33468			return ret;
33469		}
33470	};
33471});
33472
33473// Support: Firefox, Chrome, Safari
33474// Create "bubbling" focus and blur events
33475if ( !support.focusinBubbles ) {
33476	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
33477
33478		// Attach a single capturing handler on the document while someone wants focusin/focusout
33479		var handler = function( event ) {
33480				jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
33481			};
33482
33483		jQuery.event.special[ fix ] = {
33484			setup: function() {
33485				var doc = this.ownerDocument || this,
33486					attaches = data_priv.access( doc, fix );
33487
33488				if ( !attaches ) {
33489					doc.addEventListener( orig, handler, true );
33490				}
33491				data_priv.access( doc, fix, ( attaches || 0 ) + 1 );
33492			},
33493			teardown: function() {
33494				var doc = this.ownerDocument || this,
33495					attaches = data_priv.access( doc, fix ) - 1;
33496
33497				if ( !attaches ) {
33498					doc.removeEventListener( orig, handler, true );
33499					data_priv.remove( doc, fix );
33500
33501				} else {
33502					data_priv.access( doc, fix, attaches );
33503				}
33504			}
33505		};
33506	});
33507}
33508
33509jQuery.fn.extend({
33510
33511	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
33512		var origFn, type;
33513
33514		// Types can be a map of types/handlers
33515		if ( typeof types === "object" ) {
33516			// ( types-Object, selector, data )
33517			if ( typeof selector !== "string" ) {
33518				// ( types-Object, data )
33519				data = data || selector;
33520				selector = undefined;
33521			}
33522			for ( type in types ) {
33523				this.on( type, selector, data, types[ type ], one );
33524			}
33525			return this;
33526		}
33527
33528		if ( data == null && fn == null ) {
33529			// ( types, fn )
33530			fn = selector;
33531			data = selector = undefined;
33532		} else if ( fn == null ) {
33533			if ( typeof selector === "string" ) {
33534				// ( types, selector, fn )
33535				fn = data;
33536				data = undefined;
33537			} else {
33538				// ( types, data, fn )
33539				fn = data;
33540				data = selector;
33541				selector = undefined;
33542			}
33543		}
33544		if ( fn === false ) {
33545			fn = returnFalse;
33546		} else if ( !fn ) {
33547			return this;
33548		}
33549
33550		if ( one === 1 ) {
33551			origFn = fn;
33552			fn = function( event ) {
33553				// Can use an empty set, since event contains the info
33554				jQuery().off( event );
33555				return origFn.apply( this, arguments );
33556			};
33557			// Use same guid so caller can remove using origFn
33558			fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
33559		}
33560		return this.each( function() {
33561			jQuery.event.add( this, types, fn, data, selector );
33562		});
33563	},
33564	one: function( types, selector, data, fn ) {
33565		return this.on( types, selector, data, fn, 1 );
33566	},
33567	off: function( types, selector, fn ) {
33568		var handleObj, type;
33569		if ( types && types.preventDefault && types.handleObj ) {
33570			// ( event )  dispatched jQuery.Event
33571			handleObj = types.handleObj;
33572			jQuery( types.delegateTarget ).off(
33573				handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
33574				handleObj.selector,
33575				handleObj.handler
33576			);
33577			return this;
33578		}
33579		if ( typeof types === "object" ) {
33580			// ( types-object [, selector] )
33581			for ( type in types ) {
33582				this.off( type, selector, types[ type ] );
33583			}
33584			return this;
33585		}
33586		if ( selector === false || typeof selector === "function" ) {
33587			// ( types [, fn] )
33588			fn = selector;
33589			selector = undefined;
33590		}
33591		if ( fn === false ) {
33592			fn = returnFalse;
33593		}
33594		return this.each(function() {
33595			jQuery.event.remove( this, types, fn, selector );
33596		});
33597	},
33598
33599	trigger: function( type, data ) {
33600		return this.each(function() {
33601			jQuery.event.trigger( type, data, this );
33602		});
33603	},
33604	triggerHandler: function( type, data ) {
33605		var elem = this[0];
33606		if ( elem ) {
33607			return jQuery.event.trigger( type, data, elem, true );
33608		}
33609	}
33610});
33611
33612
33613var
33614	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
33615	rtagName = /<([\w:]+)/,
33616	rhtml = /<|&#?\w+;/,
33617	rnoInnerhtml = /<(?:script|style|link)/i,
33618	// checked="checked" or checked
33619	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
33620	rscriptType = /^$|\/(?:java|ecma)script/i,
33621	rscriptTypeMasked = /^true\/(.*)/,
33622	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
33623
33624	// We have to close these tags to support XHTML (#13200)
33625	wrapMap = {
33626
33627		// Support: IE9
33628		option: [ 1, "<select multiple='multiple'>", "</select>" ],
33629
33630		thead: [ 1, "<table>", "</table>" ],
33631		col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
33632		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
33633		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
33634
33635		_default: [ 0, "", "" ]
33636	};
33637
33638// Support: IE9
33639wrapMap.optgroup = wrapMap.option;
33640
33641wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
33642wrapMap.th = wrapMap.td;
33643
33644// Support: 1.x compatibility
33645// Manipulating tables requires a tbody
33646function manipulationTarget( elem, content ) {
33647	return jQuery.nodeName( elem, "table" ) &&
33648		jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
33649
33650		elem.getElementsByTagName("tbody")[0] ||
33651			elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
33652		elem;
33653}
33654
33655// Replace/restore the type attribute of script elements for safe DOM manipulation
33656function disableScript( elem ) {
33657	elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type;
33658	return elem;
33659}
33660function restoreScript( elem ) {
33661	var match = rscriptTypeMasked.exec( elem.type );
33662
33663	if ( match ) {
33664		elem.type = match[ 1 ];
33665	} else {
33666		elem.removeAttribute("type");
33667	}
33668
33669	return elem;
33670}
33671
33672// Mark scripts as having already been evaluated
33673function setGlobalEval( elems, refElements ) {
33674	var i = 0,
33675		l = elems.length;
33676
33677	for ( ; i < l; i++ ) {
33678		data_priv.set(
33679			elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" )
33680		);
33681	}
33682}
33683
33684function cloneCopyEvent( src, dest ) {
33685	var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
33686
33687	if ( dest.nodeType !== 1 ) {
33688		return;
33689	}
33690
33691	// 1. Copy private data: events, handlers, etc.
33692	if ( data_priv.hasData( src ) ) {
33693		pdataOld = data_priv.access( src );
33694		pdataCur = data_priv.set( dest, pdataOld );
33695		events = pdataOld.events;
33696
33697		if ( events ) {
33698			delete pdataCur.handle;
33699			pdataCur.events = {};
33700
33701			for ( type in events ) {
33702				for ( i = 0, l = events[ type ].length; i < l; i++ ) {
33703					jQuery.event.add( dest, type, events[ type ][ i ] );
33704				}
33705			}
33706		}
33707	}
33708
33709	// 2. Copy user data
33710	if ( data_user.hasData( src ) ) {
33711		udataOld = data_user.access( src );
33712		udataCur = jQuery.extend( {}, udataOld );
33713
33714		data_user.set( dest, udataCur );
33715	}
33716}
33717
33718function getAll( context, tag ) {
33719	var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) :
33720			context.querySelectorAll ? context.querySelectorAll( tag || "*" ) :
33721			[];
33722
33723	return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
33724		jQuery.merge( [ context ], ret ) :
33725		ret;
33726}
33727
33728// Fix IE bugs, see support tests
33729function fixInput( src, dest ) {
33730	var nodeName = dest.nodeName.toLowerCase();
33731
33732	// Fails to persist the checked state of a cloned checkbox or radio button.
33733	if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
33734		dest.checked = src.checked;
33735
33736	// Fails to return the selected option to the default selected state when cloning options
33737	} else if ( nodeName === "input" || nodeName === "textarea" ) {
33738		dest.defaultValue = src.defaultValue;
33739	}
33740}
33741
33742jQuery.extend({
33743	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
33744		var i, l, srcElements, destElements,
33745			clone = elem.cloneNode( true ),
33746			inPage = jQuery.contains( elem.ownerDocument, elem );
33747
33748		// Fix IE cloning issues
33749		if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
33750				!jQuery.isXMLDoc( elem ) ) {
33751
33752			// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
33753			destElements = getAll( clone );
33754			srcElements = getAll( elem );
33755
33756			for ( i = 0, l = srcElements.length; i < l; i++ ) {
33757				fixInput( srcElements[ i ], destElements[ i ] );
33758			}
33759		}
33760
33761		// Copy the events from the original to the clone
33762		if ( dataAndEvents ) {
33763			if ( deepDataAndEvents ) {
33764				srcElements = srcElements || getAll( elem );
33765				destElements = destElements || getAll( clone );
33766
33767				for ( i = 0, l = srcElements.length; i < l; i++ ) {
33768					cloneCopyEvent( srcElements[ i ], destElements[ i ] );
33769				}
33770			} else {
33771				cloneCopyEvent( elem, clone );
33772			}
33773		}
33774
33775		// Preserve script evaluation history
33776		destElements = getAll( clone, "script" );
33777		if ( destElements.length > 0 ) {
33778			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
33779		}
33780
33781		// Return the cloned set
33782		return clone;
33783	},
33784
33785	buildFragment: function( elems, context, scripts, selection ) {
33786		var elem, tmp, tag, wrap, contains, j,
33787			fragment = context.createDocumentFragment(),
33788			nodes = [],
33789			i = 0,
33790			l = elems.length;
33791
33792		for ( ; i < l; i++ ) {
33793			elem = elems[ i ];
33794
33795			if ( elem || elem === 0 ) {
33796
33797				// Add nodes directly
33798				if ( jQuery.type( elem ) === "object" ) {
vendor: 5,747 bytes, lines 33799-34014
33799					// Support: QtWebKit, PhantomJS
33800					// push.apply(_, arraylike) throws on ancient WebKit
33801					jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
33802
33803				// Convert non-html into a text node
33804				} else if ( !rhtml.test( elem ) ) {
33805					nodes.push( context.createTextNode( elem ) );
33806
33807				// Convert html into DOM nodes
33808				} else {
33809					tmp = tmp || fragment.appendChild( context.createElement("div") );
33810
33811					// Deserialize a standard representation
33812					tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
33813					wrap = wrapMap[ tag ] || wrapMap._default;
33814					tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[ 2 ];
33815
33816					// Descend through wrappers to the right content
33817					j = wrap[ 0 ];
33818					while ( j-- ) {
33819						tmp = tmp.lastChild;
33820					}
33821
33822					// Support: QtWebKit, PhantomJS
33823					// push.apply(_, arraylike) throws on ancient WebKit
33824					jQuery.merge( nodes, tmp.childNodes );
33825
33826					// Remember the top-level container
33827					tmp = fragment.firstChild;
33828
33829					// Ensure the created nodes are orphaned (#12392)
33830					tmp.textContent = "";
33831				}
33832			}
33833		}
33834
33835		// Remove wrapper from fragment
33836		fragment.textContent = "";
33837
33838		i = 0;
33839		while ( (elem = nodes[ i++ ]) ) {
33840
33841			// #4087 - If origin and destination elements are the same, and this is
33842			// that element, do not do anything
33843			if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
33844				continue;
33845			}
33846
33847			contains = jQuery.contains( elem.ownerDocument, elem );
33848
33849			// Append to fragment
33850			tmp = getAll( fragment.appendChild( elem ), "script" );
33851
33852			// Preserve script evaluation history
33853			if ( contains ) {
33854				setGlobalEval( tmp );
33855			}
33856
33857			// Capture executables
33858			if ( scripts ) {
33859				j = 0;
33860				while ( (elem = tmp[ j++ ]) ) {
33861					if ( rscriptType.test( elem.type || "" ) ) {
33862						scripts.push( elem );
33863					}
33864				}
33865			}
33866		}
33867
33868		return fragment;
33869	},
33870
33871	cleanData: function( elems ) {
33872		var data, elem, type, key,
33873			special = jQuery.event.special,
33874			i = 0;
33875
33876		for ( ; (elem = elems[ i ]) !== undefined; i++ ) {
33877			if ( jQuery.acceptData( elem ) ) {
33878				key = elem[ data_priv.expando ];
33879
33880				if ( key && (data = data_priv.cache[ key ]) ) {
33881					if ( data.events ) {
33882						for ( type in data.events ) {
33883							if ( special[ type ] ) {
33884								jQuery.event.remove( elem, type );
33885
33886							// This is a shortcut to avoid jQuery.event.remove's overhead
33887							} else {
33888								jQuery.removeEvent( elem, type, data.handle );
33889							}
33890						}
33891					}
33892					if ( data_priv.cache[ key ] ) {
33893						// Discard any remaining `private` data
33894						delete data_priv.cache[ key ];
33895					}
33896				}
33897			}
33898			// Discard any remaining `user` data
33899			delete data_user.cache[ elem[ data_user.expando ] ];
33900		}
33901	}
33902});
33903
33904jQuery.fn.extend({
33905	text: function( value ) {
33906		return access( this, function( value ) {
33907			return value === undefined ?
33908				jQuery.text( this ) :
33909				this.empty().each(function() {
33910					if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
33911						this.textContent = value;
33912					}
33913				});
33914		}, null, value, arguments.length );
33915	},
33916
33917	append: function() {
33918		return this.domManip( arguments, function( elem ) {
33919			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
33920				var target = manipulationTarget( this, elem );
33921				target.appendChild( elem );
33922			}
33923		});
33924	},
33925
33926	prepend: function() {
33927		return this.domManip( arguments, function( elem ) {
33928			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
33929				var target = manipulationTarget( this, elem );
33930				target.insertBefore( elem, target.firstChild );
33931			}
33932		});
33933	},
33934
33935	before: function() {
33936		return this.domManip( arguments, function( elem ) {
33937			if ( this.parentNode ) {
33938				this.parentNode.insertBefore( elem, this );
33939			}
33940		});
33941	},
33942
33943	after: function() {
33944		return this.domManip( arguments, function( elem ) {
33945			if ( this.parentNode ) {
33946				this.parentNode.insertBefore( elem, this.nextSibling );
33947			}
33948		});
33949	},
33950
33951	remove: function( selector, keepData /* Internal Use Only */ ) {
33952		var elem,
33953			elems = selector ? jQuery.filter( selector, this ) : this,
33954			i = 0;
33955
33956		for ( ; (elem = elems[i]) != null; i++ ) {
33957			if ( !keepData && elem.nodeType === 1 ) {
33958				jQuery.cleanData( getAll( elem ) );
33959			}
33960
33961			if ( elem.parentNode ) {
33962				if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
33963					setGlobalEval( getAll( elem, "script" ) );
33964				}
33965				elem.parentNode.removeChild( elem );
33966			}
33967		}
33968
33969		return this;
33970	},
33971
33972	empty: function() {
33973		var elem,
33974			i = 0;
33975
33976		for ( ; (elem = this[i]) != null; i++ ) {
33977			if ( elem.nodeType === 1 ) {
33978
33979				// Prevent memory leaks
33980				jQuery.cleanData( getAll( elem, false ) );
33981
33982				// Remove any remaining nodes
33983				elem.textContent = "";
33984			}
33985		}
33986
33987		return this;
33988	},
33989
33990	clone: function( dataAndEvents, deepDataAndEvents ) {
33991		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
33992		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
33993
33994		return this.map(function() {
33995			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
33996		});
33997	},
33998
33999	html: function( value ) {
34000		return access( this, function( value ) {
34001			var elem = this[ 0 ] || {},
34002				i = 0,
34003				l = this.length;
34004
34005			if ( value === undefined && elem.nodeType === 1 ) {
34006				return elem.innerHTML;
34007			}
34008
34009			// See if we can take a shortcut and just use innerHTML
34010			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
34011				!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
34012
34013				value = value.replace( rxhtmlTag, "<$1></$2>" );
34014
34015				try {
34016					for ( ; i < l; i++ ) {
34017						elem = this[ i ] || {};
34018
34019						// Remove element nodes and prevent memory leaks
34020						if ( elem.nodeType === 1 ) {
34021							jQuery.cleanData( getAll( elem, false ) );
34022							elem.innerHTML = value;
34023						}
34024					}
34025
34026					elem = 0;
34027
34028				// If using innerHTML throws an exception, use the fallback method
34029				} catch( e ) {}
34030			}
34031
34032			if ( elem ) {
34033				this.empty().append( value );
34034			}
34035		}, null, value, arguments.length );
34036	},
34037
34038	replaceWith: function() {
34039		var arg = arguments[ 0 ];
34040
34041		// Make the changes, replacing each context element with the new content
34042		this.domManip( arguments, function( elem ) {
34043			arg = this.parentNode;
34044
34045			jQuery.cleanData( getAll( this ) );
34046
34047			if ( arg ) {
34048				arg.replaceChild( elem, this );
34049			}
34050		});
34051
34052		// Force removal if there was no new content (e.g., from empty arguments)
34053		return arg && (arg.length || arg.nodeType) ? this : this.remove();
34054	},
34055
34056	detach: function( selector ) {
34057		return this.remove( selector, true );
34058	},
34059
34060	domManip: function( args, callback ) {
34061
34062		// Flatten any nested arrays
34063		args = concat.apply( [], args );
34064
34065		var fragment, first, scripts, hasScripts, node, doc,
34066			i = 0,
34067			l = this.length,
34068			set = this,
34069			iNoClone = l - 1,
34070			value = args[ 0 ],
34071			isFunction = jQuery.isFunction( value );
34072
34073		// We can't cloneNode fragments that contain checked, in WebKit
34074		if ( isFunction ||
34075				( l > 1 && typeof value === "string" &&
34076					!support.checkClone && rchecked.test( value ) ) ) {
34077			return this.each(function( index ) {
34078				var self = set.eq( index );
34079				if ( isFunction ) {
34080					args[ 0 ] = value.call( this, index, self.html() );
34081				}
34082				self.domManip( args, callback );
34083			});
34084		}
34085
34086		if ( l ) {
34087			fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
34088			first = fragment.firstChild;
34089
34090			if ( fragment.childNodes.length === 1 ) {
34091				fragment = first;
34092			}
34093
34094			if ( first ) {
34095				scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
34096				hasScripts = scripts.length;
34097
34098				// Use the original fragment for the last item instead of the first because it can end up
34099				// being emptied incorrectly in certain situations (#8070).
34100				for ( ; i < l; i++ ) {
34101					node = fragment;
34102
34103					if ( i !== iNoClone ) {
34104						node = jQuery.clone( node, true, true );
34105
34106						// Keep references to cloned scripts for later restoration
34107						if ( hasScripts ) {
34108							// Support: QtWebKit
34109							// jQuery.merge because push.apply(_, arraylike) throws
34110							jQuery.merge( scripts, getAll( node, "script" ) );
34111						}
34112					}
34113
34114					callback.call( this[ i ], node, i );
34115				}
34116
34117				if ( hasScripts ) {
34118					doc = scripts[ scripts.length - 1 ].ownerDocument;
34119
34120					// Reenable scripts
34121					jQuery.map( scripts, restoreScript );
34122
34123					// Evaluate executable scripts on first document insertion
34124					for ( i = 0; i < hasScripts; i++ ) {
34125						node = scripts[ i ];
34126						if ( rscriptType.test( node.type || "" ) &&
34127							!data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
34128
34129							if ( node.src ) {
34130								// Optional AJAX dependency, but won't run scripts if not present
34131								if ( jQuery._evalUrl ) {
34132									jQuery._evalUrl( node.src );
34133								}
34134							} else {
34135								jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
34136							}
34137						}
34138					}
34139				}
34140			}
34141		}
34142
34143		return this;
34144	}
34145});
34146
34147jQuery.each({
34148	appendTo: "append",
34149	prependTo: "prepend",
34150	insertBefore: "before",
34151	insertAfter: "after",
34152	replaceAll: "replaceWith"
34153}, function( name, original ) {
34154	jQuery.fn[ name ] = function( selector ) {
34155		var elems,
34156			ret = [],
34157			insert = jQuery( selector ),
34158			last = insert.length - 1,
34159			i = 0;
34160
34161		for ( ; i <= last; i++ ) {
34162			elems = i === last ? this : this.clone( true );
34163			jQuery( insert[ i ] )[ original ]( elems );
34164
34165			// Support: QtWebKit
34166			// .get() because push.apply(_, arraylike) throws
34167			push.apply( ret, elems.get() );
34168		}
34169
34170		return this.pushStack( ret );
34171	};
34172});
34173
34174
34175var iframe,
34176	elemdisplay = {};
34177
34178/**
34179 * Retrieve the actual display of a element
34180 * @param {String} name nodeName of the element
34181 * @param {Object} doc Document object
34182 */
34183// Called only from within defaultDisplay
34184function actualDisplay( name, doc ) {
34185	var style,
34186		elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
34187
34188		// getDefaultComputedStyle might be reliably used only on attached element
34189		display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
34190
34191			// Use of this method is a temporary fix (more like optimization) until something better comes along,
34192			// since it was removed from specification and supported only in FF
34193			style.display : jQuery.css( elem[ 0 ], "display" );
34194
34195	// We don't have any data stored on the element,
34196	// so use "detach" method as fast way to get rid of the element
34197	elem.detach();
34198
34199	return display;
34200}
34201
34202/**
34203 * Try to determine the default display value of an element
34204 * @param {String} nodeName
34205 */
34206function defaultDisplay( nodeName ) {
34207	var doc = document,
34208		display = elemdisplay[ nodeName ];
34209
34210	if ( !display ) {
34211		display = actualDisplay( nodeName, doc );
34212
34213		// If the simple way fails, read from inside an iframe
34214		if ( display === "none" || !display ) {
34215
34216			// Use the already-created iframe if possible
34217			iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
34218
34219			// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
34220			doc = iframe[ 0 ].contentDocument;
34221
34222			// Support: IE
34223			doc.write();
34224			doc.close();
34225
34226			display = actualDisplay( nodeName, doc );
34227			iframe.detach();
34228		}
34229
34230		// Store the correct default display
34231		elemdisplay[ nodeName ] = display;
34232	}
34233
34234	return display;
34235}
34236var rmargin = (/^margin/);
34237
34238var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
34239
34240var getStyles = function( elem ) {
34241		// Support: IE<=11+, Firefox<=30+ (#15098, #14150)
34242		// IE throws on elements created in popups
34243		// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
34244		if ( elem.ownerDocument.defaultView.opener ) {
34245			return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
34246		}
34247
34248		return window.getComputedStyle( elem, null );
34249	};
34250
34251
34252
34253function curCSS( elem, name, computed ) {
34254	var width, minWidth, maxWidth, ret,
34255		style = elem.style;
34256
34257	computed = computed || getStyles( elem );
34258
34259	// Support: IE9
34260	// getPropertyValue is only needed for .css('filter') (#12537)
34261	if ( computed ) {
34262		ret = computed.getPropertyValue( name ) || computed[ name ];
34263	}
34264
34265	if ( computed ) {
34266
34267		if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
34268			ret = jQuery.style( elem, name );
34269		}
34270
34271		// Support: iOS < 6
34272		// A tribute to the "awesome hack by Dean Edwards"
34273		// iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
34274		// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
34275		if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
34276
34277			// Remember the original values
34278			width = style.width;
34279			minWidth = style.minWidth;
34280			maxWidth = style.maxWidth;
34281
34282			// Put in the new values to get a computed value out
34283			style.minWidth = style.maxWidth = style.width = ret;
34284			ret = computed.width;
34285
34286			// Revert the changed values
34287			style.width = width;
34288			style.minWidth = minWidth;
34289			style.maxWidth = maxWidth;
34290		}
34291	}
34292
34293	return ret !== undefined ?
34294		// Support: IE
34295		// IE returns zIndex value as an integer.
34296		ret + "" :
34297		ret;
34298}
34299
34300
34301function addGetHookIf( conditionFn, hookFn ) {
34302	// Define the hook, we'll check on the first run if it's really needed.
34303	return {
34304		get: function() {
34305			if ( conditionFn() ) {
34306				// Hook not needed (or it's not possible to use it due
34307				// to missing dependency), remove it.
34308				delete this.get;
34309				return;
34310			}
34311
34312			// Hook needed; redefine it so that the support test is not executed again.
34313			return (this.get = hookFn).apply( this, arguments );
34314		}
34315	};
34316}
34317
34318
34319(function() {
34320	var pixelPositionVal, boxSizingReliableVal,
34321		docElem = document.documentElement,
34322		container = document.createElement( "div" ),
34323		div = document.createElement( "div" );
34324
34325	if ( !div.style ) {
34326		return;
34327	}
34328
34329	// Support: IE9-11+
34330	// Style of cloned element affects source element cloned (#8908)
34331	div.style.backgroundClip = "content-box";
34332	div.cloneNode( true ).style.backgroundClip = "";
34333	support.clearCloneStyle = div.style.backgroundClip === "content-box";
34334
34335	container.style.cssText = "border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;" +
34336		"position:absolute";
34337	container.appendChild( div );
34338
34339	// Executing both pixelPosition & boxSizingReliable tests require only one layout
34340	// so they're executed at the same time to save the second computation.
34341	function computePixelPositionAndBoxSizingReliable() {
34342		div.style.cssText =
34343			// Support: Firefox<29, Android 2.3
34344			// Vendor-prefix box-sizing
34345			"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
34346			"box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
34347			"border:1px;padding:1px;width:4px;position:absolute";
34348		div.innerHTML = "";
34349		docElem.appendChild( container );
34350
34351		var divStyle = window.getComputedStyle( div, null );
34352		pixelPositionVal = divStyle.top !== "1%";
34353		boxSizingReliableVal = divStyle.width === "4px";
34354
34355		docElem.removeChild( container );
34356	}
34357
34358	// Support: node.js jsdom
34359	// Don't assume that getComputedStyle is a property of the global object
34360	if ( window.getComputedStyle ) {
34361		jQuery.extend( support, {
34362			pixelPosition: function() {
34363
34364				// This test is executed only once but we still do memoizing
34365				// since we can use the boxSizingReliable pre-computing.
34366				// No need to check if the test was already performed, though.
34367				computePixelPositionAndBoxSizingReliable();
34368				return pixelPositionVal;
34369			},
34370			boxSizingReliable: function() {
34371				if ( boxSizingReliableVal == null ) {
34372					computePixelPositionAndBoxSizingReliable();
34373				}
34374				return boxSizingReliableVal;
34375			},
34376			reliableMarginRight: function() {
34377
34378				// Support: Android 2.3
34379				// Check if div with explicit width and no margin-right incorrectly
34380				// gets computed margin-right based on width of container. (#3333)
34381				// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
34382				// This support function is only executed once so no memoizing is needed.
34383				var ret,
34384					marginDiv = div.appendChild( document.createElement( "div" ) );
34385
34386				// Reset CSS: box-sizing; display; margin; border; padding
34387				marginDiv.style.cssText = div.style.cssText =
34388					// Support: Firefox<29, Android 2.3
34389					// Vendor-prefix box-sizing
34390					"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
34391					"box-sizing:content-box;display:block;margin:0;border:0;padding:0";
34392				marginDiv.style.marginRight = marginDiv.style.width = "0";
34393				div.style.width = "1px";
34394				docElem.appendChild( container );
34395
34396				ret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight );
34397
34398				docElem.removeChild( container );
34399				div.removeChild( marginDiv );
34400
34401				return ret;
34402			}
34403		});
34404	}
34405})();
34406
34407
34408// A method for quickly swapping in/out CSS properties to get correct calculations.
34409jQuery.swap = function( elem, options, callback, args ) {
34410	var ret, name,
34411		old = {};
34412
34413	// Remember the old values, and insert the new ones
34414	for ( name in options ) {
34415		old[ name ] = elem.style[ name ];
34416		elem.style[ name ] = options[ name ];
34417	}
34418
34419	ret = callback.apply( elem, args || [] );
34420
34421	// Revert the old values
34422	for ( name in options ) {
34423		elem.style[ name ] = old[ name ];
34424	}
34425
34426	return ret;
34427};
34428
34429
34430var
34431	// Swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
34432	// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
34433	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
34434	rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
34435	rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
34436
34437	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
34438	cssNormalTransform = {
34439		letterSpacing: "0",
34440		fontWeight: "400"
34441	},
34442
34443	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
34444
34445// Return a css property mapped to a potentially vendor prefixed property
34446function vendorPropName( style, name ) {
34447
34448	// Shortcut for names that are not vendor prefixed
34449	if ( name in style ) {
34450		return name;
34451	}
34452
34453	// Check for vendor prefixed names
34454	var capName = name[0].toUpperCase() + name.slice(1),
34455		origName = name,
34456		i = cssPrefixes.length;
34457
34458	while ( i-- ) {
34459		name = cssPrefixes[ i ] + capName;
34460		if ( name in style ) {
34461			return name;
34462		}
34463	}
34464
34465	return origName;
34466}
34467
34468function setPositiveNumber( elem, value, subtract ) {
34469	var matches = rnumsplit.exec( value );
34470	return matches ?
34471		// Guard against undefined "subtract", e.g., when used as in cssHooks
34472		Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
34473		value;
34474}
34475
34476function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
34477	var i = extra === ( isBorderBox ? "border" : "content" ) ?
34478		// If we already have the right measurement, avoid augmentation
34479		4 :
34480		// Otherwise initialize for horizontal or vertical properties
34481		name === "width" ? 1 : 0,
34482
34483		val = 0;
34484
34485	for ( ; i < 4; i += 2 ) {
34486		// Both box models exclude margin, so add it if we want it
34487		if ( extra === "margin" ) {
34488			val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
34489		}
34490
34491		if ( isBorderBox ) {
34492			// border-box includes padding, so remove it if we want content
34493			if ( extra === "content" ) {
34494				val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
34495			}
34496
34497			// At this point, extra isn't border nor margin, so remove border
34498			if ( extra !== "margin" ) {
34499				val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
34500			}
34501		} else {
34502			// At this point, extra isn't content, so add padding
34503			val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
34504
34505			// At this point, extra isn't content nor padding, so add border
34506			if ( extra !== "padding" ) {
34507				val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
34508			}
34509		}
34510	}
34511
34512	return val;
34513}
34514
34515function getWidthOrHeight( elem, name, extra ) {
34516
34517	// Start with offset property, which is equivalent to the border-box value
34518	var valueIsBorderBox = true,
34519		val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
34520		styles = getStyles( elem ),
34521		isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
34522
34523	// Some non-html elements return undefined for offsetWidth, so check for null/undefined
34524	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
34525	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
34526	if ( val <= 0 || val == null ) {
34527		// Fall back to computed then uncomputed css if necessary
34528		val = curCSS( elem, name, styles );
34529		if ( val < 0 || val == null ) {
34530			val = elem.style[ name ];
34531		}
34532
34533		// Computed unit is not pixels. Stop here and return.
34534		if ( rnumnonpx.test(val) ) {
34535			return val;
34536		}
34537
34538		// Check for style in case a browser which returns unreliable values
34539		// for getComputedStyle silently falls back to the reliable elem.style
34540		valueIsBorderBox = isBorderBox &&
34541			( support.boxSizingReliable() || val === elem.style[ name ] );
34542
34543		// Normalize "", auto, and prepare for extra
34544		val = parseFloat( val ) || 0;
34545	}
34546
34547	// Use the active box-sizing model to add/subtract irrelevant styles
34548	return ( val +
34549		augmentWidthOrHeight(
34550			elem,
34551			name,
34552			extra || ( isBorderBox ? "border" : "content" ),
34553			valueIsBorderBox,
34554			styles
34555		)
34556	) + "px";
34557}
34558
34559function showHide( elements, show ) {
34560	var display, elem, hidden,
34561		values = [],
34562		index = 0,
34563		length = elements.length;
34564
34565	for ( ; index < length; index++ ) {
34566		elem = elements[ index ];
34567		if ( !elem.style ) {
34568			continue;
34569		}
34570
34571		values[ index ] = data_priv.get( elem, "olddisplay" );
34572		display = elem.style.display;
34573		if ( show ) {
34574			// Reset the inline display of this element to learn if it is
34575			// being hidden by cascaded rules or not
34576			if ( !values[ index ] && display === "none" ) {
34577				elem.style.display = "";
34578			}
34579
34580			// Set elements which have been overridden with display: none
34581			// in a stylesheet to whatever the default browser style is
34582			// for such an element
34583			if ( elem.style.display === "" && isHidden( elem ) ) {
34584				values[ index ] = data_priv.access( elem, "olddisplay", defaultDisplay(elem.nodeName) );
34585			}
34586		} else {
34587			hidden = isHidden( elem );
34588
34589			if ( display !== "none" || !hidden ) {
34590				data_priv.set( elem, "olddisplay", hidden ? display : jQuery.css( elem, "dis
34590play" ) );
34591			}
34592		}
34593	}
34594
34595	// Set the display of most of the elements in a second loop
34596	// to avoid the constant reflow
34597	for ( index = 0; index < length; index++ ) {
34598		elem = elements[ index ];
34599		if ( !elem.style ) {
34600			continue;
34601		}
34602		if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
34603			elem.style.display = show ? values[ index ] || "" : "none";
34604		}
34605	}
34606
34607	return elements;
34608}
34609
34610jQuery.extend({
34611
34612	// Add in style property hooks for overriding the default
34613	// behavior of getting and setting a style property
34614	cssHooks: {
34615		opacity: {
34616			get: function( elem, computed ) {
34617				if ( computed ) {
34618
34619					// We should always get a number back from opacity
34620					var ret = curCSS( elem, "opacity" );
34621					return ret === "" ? "1" : ret;
34622				}
34623			}
34624		}
34625	},
34626
34627	// Don't automatically add "px" to these possibly-unitless properties
34628	cssNumber: {
34629		"columnCount": true,
34630		"fillOpacity": true,
34631		"flexGrow": true,
34632		"flexShrink": true,
34633		"fontWeight": true,
34634		"lineHeight": true,
34635		"opacity": true,
34636		"order": true,
34637		"orphans": true,
34638		"widows": true,
34639		"zIndex": true,
34640		"zoom": true
34641	},
34642
34643	// Add in properties whose names you wish to fix before
34644	// setting or getting the value
34645	cssProps: {
34646		"float": "cssFloat"
34647	},
34648
34649	// Get and set the style property on a DOM Node
34650	style: function( elem, name, value, extra ) {
34651
34652		// Don't set styles on text and comment nodes
34653		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
34654			return;
34655		}
34656
34657		// Make sure that we're working with the right name
34658		var ret, type, hooks,
34659			origName = jQuery.camelCase( name ),
34660			style = elem.style;
34661
34662		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
34663
34664		// Gets hook for the prefixed version, then unprefixed version
34665		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
34666
34667		// Check if we're setting a value
34668		if ( value !== undefined ) {
34669			type = typeof value;
34670
34671			// Convert "+=" or "-=" to relative numbers (#7345)
34672			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
34673				value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
34674				// Fixes bug #9237
34675				type = "number";
34676			}
34677
34678			// Make sure that null and NaN values aren't set (#7116)
34679			if ( value == null || value !== value ) {
34680				return;
34681			}
34682
34683			// If a number, add 'px' to the (except for certain CSS properties)
34684			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
34685				value += "px";
34686			}
34687
34688			// Support: IE9-11+
34689			// background-* props affect original clone's values
34690			if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
34691				style[ name ] = "inherit";
34692			}
34693
34694			// If a hook was provided, use that value, otherwise just set the specified value
34695			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
34696				style[ name ] = value;
34697			}
34698
34699		} else {
34700			// If a hook was provided get the non-computed value from there
34701			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
34702				return ret;
34703			}
34704
34705			// Otherwise just get the value from the style object
34706			return style[ name ];
34707		}
34708	},
34709
34710	css: function( elem, name, extra, styles ) {
34711		var val, num, hooks,
34712			origName = jQuery.camelCase( name );
34713
34714		// Make sure that we're working with the right name
34715		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
34716
34717		// Try prefixed name followed by the unprefixed name
34718		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
34719
34720		// If a hook was provided get the computed value from there
34721		if ( hooks && "get" in hooks ) {
34722			val = hooks.get( elem, true, extra );
34723		}
34724
34725		// Otherwise, if a way to get the computed value exists, use that
34726		if ( val === undefined ) {
34727			val = curCSS( elem, name, styles );
34728		}
34729
34730		// Convert "normal" to computed value
34731		if ( val === "normal" && name in cssNormalTransform ) {
34732			val = cssNormalTransform[ name ];
34733		}
34734
34735		// Make numeric if forced or a qualifier was provided and val looks numeric
34736		if ( extra === "" || extra ) {
34737			num = parseFloat( val );
34738			return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
34739		}
34740		return val;
34741	}
34742});
34743
34744jQuery.each([ "height", "width" ], function( i, name ) {
34745	jQuery.cssHooks[ name ] = {
34746		get: function( elem, computed, extra ) {
34747			if ( computed ) {
34748
34749				// Certain elements can have dimension info if we invisibly show them
34750				// but it must have a current display style that would benefit
34751				return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
34752					jQuery.swap( elem, cssShow, function() {
34753						return getWidthOrHeight( elem, name, extra );
34754					}) :
34755					getWidthOrHeight( elem, name, extra );
34756			}
34757		},
34758
34759		set: function( elem, value, extra ) {
34760			var styles = extra && getStyles( elem );
34761			return setPositiveNumber( elem, value, extra ?
34762				augmentWidthOrHeight(
34763					elem,
34764					name,
34765					extra,
34766					jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
34767					styles
34768				) : 0
34769			);
34770		}
34771	};
34772});
34773
34774// Support: Android 2.3
34775jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
34776	function( elem, computed ) {
34777		if ( computed ) {
34778			return jQuery.swap( elem, { "display": "inline-block" },
34779				curCSS, [ elem, "marginRight" ] );
34780		}
34781	}
34782);
34783
34784// These hooks are used by animate to expand properties
34785jQuery.each({
34786	margin: "",
34787	padding: "",
34788	border: "Width"
34789}, function( prefix, suffix ) {
34790	jQuery.cssHooks[ prefix + suffix ] = {
34791		expand: function( value ) {
34792			var i = 0,
34793				expanded = {},
34794
34795				// Assumes a single number if not a string
34796				parts = typeof value === "string" ? value.split(" ") : [ value ];
34797
34798			for ( ; i < 4; i++ ) {
34799				expanded[ prefix + cssExpand[ i ] + suffix ] =
34800					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
34801			}
34802
34803			return expanded;
34804		}
34805	};
34806
34807	if ( !rmargin.test( prefix ) ) {
34808		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
34809	}
34810});
34811
34812jQuery.fn.extend({
34813	css: function( name, value ) {
34814		return access( this, function( elem, name, value ) {
34815			var styles, len,
34816				map = {},
34817				i = 0;
34818
34819			if ( jQuery.isArray( name ) ) {
34820				styles = getStyles( elem );
34821				len = name.length;
34822
34823				for ( ; i < len; i++ ) {
34824					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
34825				}
34826
34827				return map;
34828			}
34829
34830			return value !== undefined ?
34831				jQuery.style( elem, name, value ) :
34832				jQuery.css( elem, name );
34833		}, name, value, arguments.length > 1 );
34834	},
34835	show: function() {
34836		return showHide( this, true );
34837	},
34838	hide: function() {
34839		return showHide( this );
34840	},
34841	toggle: function( state ) {
34842		if ( typeof state === "boolean" ) {
34843			return state ? this.show() : this.hide();
34844		}
34845
34846		return this.each(function() {
34847			if ( isHidden( this ) ) {
34848				jQuery( this ).show();
34849			} else {
34850				jQuery( this ).hide();
34851			}
34852		});
34853	}
34854});
34855
34856
34857function Tween( elem, options, prop, end, easing ) {
34858	return new Tween.prototype.init( elem, options, prop, end, easing );
34859}
34860jQuery.Tween = Tween;
34861
34862Tween.prototype = {
34863	constructor: Tween,
34864	init: function( elem, options, prop, end, easing, unit ) {
34865		this.elem = elem;
34866		this.prop = prop;
34867		this.easing = easing || "swing";
34868		this.options = options;
34869		this.start = this.now = this.cur();
34870		this.end = end;
34871		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
34872	},
34873	cur: function() {
34874		var hooks = Tween.propHooks[ this.prop ];
34875
34876		return hooks && hooks.get ?
34877			hooks.get( this ) :
34878			Tween.propHooks._default.get( this );
34879	},
34880	run: function( percent ) {
34881		var eased,
34882			hooks = Tween.propHooks[ this.prop ];
34883
34884		if ( this.options.duration ) {
34885			this.pos = eased = jQuery.easing[ this.easing ](
34886				percent, this.options.duration * percent, 0, 1, this.options.duration
34887			);
34888		} else {
34889			this.pos = eased = percent;
34890		}
34891		this.now = ( this.end - this.start ) * eased + this.start;
34892
34893		if ( this.options.step ) {
34894			this.options.step.call( this.elem, this.now, this );
34895		}
34896
34897		if ( hooks && hooks.set ) {
34898			hooks.set( this );
34899		} else {
34900			Tween.propHooks._default.set( this );
34901		}
34902		return this;
34903	}
34904};
34905
34906Tween.prototype.init.prototype = Tween.prototype;
34907
34908Tween.propHooks = {
34909	_default: {
34910		get: function( tween ) {
34911			var result;
34912
34913			if ( tween.elem[ tween.prop ] != null &&
34914				(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
34915				return tween.elem[ tween.prop ];
34916			}
34917
34918			// Passing an empty string as a 3rd parameter to .css will automatically
34919			// attempt a parseFloat and fallback to a string if the parse fails.
34920			// Simple values such as "10px" are parsed to Float;
34921			// complex values such as "rotate(1rad)" are returned as-is.
34922			result = jQuery.css( tween.elem, tween.prop, "" );
34923			// Empty strings, null, undefined and "auto" are converted to 0.
34924			return !result || result === "auto" ? 0 : result;
34925		},
34926		set: function( tween ) {
34927			// Use step hook for back compat.
34928			// Use cssHook if its there.
34929			// Use .style if available and use plain properties where available.
34930			if ( jQuery.fx.step[ tween.prop ] ) {
34931				jQuery.fx.step[ tween.prop ]( tween );
34932			} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
34933				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
34934			} else {
34935				tween.elem[ tween.prop ] = tween.now;
34936			}
34937		}
34938	}
34939};
34940
34941// Support: IE9
34942// Panic based approach to setting things on disconnected nodes
34943Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
34944	set: function( tween ) {
34945		if ( tween.elem.nodeType && tween.elem.parentNode ) {
34946			tween.elem[ tween.prop ] = tween.now;
34947		}
34948	}
34949};
34950
34951jQuery.easing = {
34952	linear: function( p ) {
34953		return p;
34954	},
34955	swing: function( p ) {
34956		return 0.5 - Math.cos( p * Math.PI ) / 2;
34957	}
34958};
34959
34960jQuery.fx = Tween.prototype.init;
34961
34962// Back Compat <1.8 extension point
34963jQuery.fx.step = {};
34964
34965
34966
34967
34968var
34969	fxNow, timerId,
34970	rfxtypes = /^(?:toggle|show|hide)$/,
34971	rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
34972	rrun = /queueHooks$/,
34973	animationPrefilters = [ defaultPrefilter ],
34974	tweeners = {
34975		"*": [ function( prop, value ) {
34976			var tween = this.createTween( prop, value ),
34977				target = tween.cur(),
34978				parts = rfxnum.exec( value ),
34979				unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
34980
34981				// Starting value computation is required for potential unit mismatches
34982				start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
34983					rfxnum.exec( jQuery.css( tween.elem, prop ) ),
34984				scale = 1,
34985				maxIterations = 20;
34986
34987			if ( start && start[ 3 ] !== unit ) {
34988				// Trust units reported by jQuery.css
34989				unit = unit || start[ 3 ];
34990
34991				// Make sure we update the tween properties later on
34992				parts = parts || [];
34993
34994				// Iteratively approximate from a nonzero starting point
34995				start = +target || 1;
34996
34997				do {
34998					// If previous iteration zeroed out, double until we get *something*.
34999					// Use string for doubling so we don't accidentally see scale as unchanged below
35000					scale = scale || ".5";
35001
35002					// Adjust and apply
35003					start = start / scale;
35004					jQuery.style( tween.elem, prop, start + unit );
35005
35006				// Update scale, tolerating zero or NaN from tween.cur(),
35007				// break the loop if scale is unchanged or perfect, or if we've just had enough
35008				} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
35009			}
35010
35011			// Update tween properties
35012			if ( parts ) {
35013				start = tween.start = +start || +target || 0;
35014				tween.unit = unit;
35015				// If a +=/-= token was provided, we're doing a relative animation
35016				tween.end = parts[ 1 ] ?
35017					start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
35018					+parts[ 2 ];
35019			}
35020
35021			return tween;
35022		} ]
35023	};
35024
35025// Animations created synchronously will run synchronously
35026function createFxNow() {
35027	setTimeout(function() {
35028		fxNow = undefined;
35029	});
35030	return ( fxNow = jQuery.now() );
35031}
35032
35033// Generate parameters to create a standard animation
35034function genFx( type, includeWidth ) {
35035	var which,
35036		i = 0,
35037		attrs = { height: type };
35038
35039	// If we include width, step value is 1 to do all cssExpand values,
35040	// otherwise step value is 2 to skip over Left and Right
35041	includeWidth = includeWidth ? 1 : 0;
35042	for ( ; i < 4 ; i += 2 - includeWidth ) {
35043		which = cssExpand[ i ];
35044		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
35045	}
35046
35047	if ( includeWidth ) {
35048		attrs.opacity = attrs.width = type;
35049	}
35050
35051	return attrs;
35052}
35053
35054function createTween( value, prop, animation ) {
35055	var tween,
35056		collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
35057		index = 0,
35058		length = collection.length;
35059	for ( ; index < length; index++ ) {
35060		if ( (tween = collection[ index ].call( animation, prop, value )) ) {
35061
35062			// We're done with this property
35063			return tween;
35064		}
35065	}
35066}
35067
35068function defaultPrefilter( elem, props, opts ) {
35069	/* jshint validthis: true */
35070	var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
35071		anim = this,
35072		orig = {},
35073		style = elem.style,
35074		hidden = elem.nodeType && isHidden( elem ),
35075		dataShow = data_priv.get( elem, "fxshow" );
35076
35077	// Handle queue: false promises
35078	if ( !opts.queue ) {
35079		hooks = jQuery._queueHooks( elem, "fx" );
35080		if ( hooks.unqueued == null ) {
35081			hooks.unqueued = 0;
35082			oldfire = hooks.empty.fire;
35083			hooks.empty.fire = function() {
35084				if ( !hooks.unqueued ) {
35085					oldfire();
35086				}
35087			};
35088		}
35089		hooks.unqueued++;
35090
35091		anim.always(function() {
35092			// Ensure the complete handler is called before this completes
35093			anim.always(function() {
35094				hooks.unqueued--;
35095				if ( !jQuery.queue( elem, "fx" ).length ) {
35096					hooks.empty.fire();
35097				}
35098			});
35099		});
35100	}
35101
35102	// Height/width overflow pass
35103	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
35104		// Make sure that nothing sneaks out
35105		// Record all 3 overflow attributes because IE9-10 do not
35106		// change the overflow attribute when overflowX and
35107		// overflowY are set to the same value
35108		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
35109
35110		// Set display property to inline-block for height/width
35111		// animations on inline elements that are having width/height animated
35112		display = jQuery.css( elem, "display" );
35113
35114		// Test default display if display is currently "none"
35115		checkDisplay = display === "none" ?
35116			data_priv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
35117
35118		if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
35119			style.display = "inline-block";
35120		}
35121	}
35122
35123	if ( opts.overflow ) {
35124		style.overflow = "hidden";
35125		anim.always(function() {
35126			style.overflow = opts.overflow[ 0 ];
35127			style.overflowX = opts.overflow[ 1 ];
35128			style.overflowY = opts.overflow[ 2 ];
35129		});
35130	}
35131
35132	// show/hide pass
35133	for ( prop in props ) {
35134		value = props[ prop ];
35135		if ( rfxtypes.exec( value ) ) {
35136			delete props[ prop ];
35137			toggle = toggle || value === "toggle";
35138			if ( value === ( hidden ? "hide" : "show" ) ) {
35139
35140				// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
35141				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
35142					hidden = true;
35143				} else {
35144					continue;
35145				}
35146			}
35147			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
35148
35149		// Any non-fx value stops us from restoring the original display value
35150		} else {
35151			display = undefined;
35152		}
35153	}
35154
35155	if ( !jQuery.isEmptyObject( orig ) ) {
35156		if ( dataShow ) {
35157			if ( "hidden" in dataShow ) {
35158				hidden = dataShow.hidden;
35159			}
35160		} else {
35161			dataShow = data_priv.access( elem, "fxshow", {} );
35162		}
35163
35164		// Store state if its toggle - enables .stop().toggle() to "reverse"
35165		if ( toggle ) {
35166			dataShow.hidden = !hidden;
35167		}
35168		if ( hidden ) {
35169			jQuery( elem ).show();
35170		} else {
35171			anim.done(function() {
35172				jQuery( elem ).hide();
35173			});
35174		}
35175		anim.done(function() {
35176			var prop;
35177
35178			data_priv.remove( elem, "fxshow" );
35179			for ( prop in orig ) {
35180				jQuery.style( elem, prop, orig[ prop ] );
35181			}
35182		});
35183		for ( prop in orig ) {
35184			tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
35185
35186			if ( !( prop in dataShow ) ) {
35187				dataShow[ prop ] = tween.start;
35188				if ( hidden ) {
35189					tween.end = tween.start;
35190					tween.start = prop === "width" || prop === "height" ? 1 : 0;
35191				}
35192			}
35193		}
35194
35195	// If this is a noop like .hide().hide(), restore an overwritten display value
35196	} else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
35197		style.display = display;
35198	}
35199}
35200
35201function propFilter( props, specialEasing ) {
35202	var index, name, easing, value, hooks;
35203
35204	// camelCase, specialEasing and expand cssHook pass
35205	for ( index in props ) {
35206		name = jQuery.camelCase( index );
35207		easing = specialEasing[ name ];
35208		value = props[ index ];
35209		if ( jQuery.isArray( value ) ) {
35210			easing = value[ 1 ];
35211			value = props[ index ] = value[ 0 ];
35212		}
35213
35214		if ( index !== name ) {
35215			props[ name ] = value;
35216			delete props[ index ];
35217		}
35218
35219		hooks = jQuery.cssHooks[ name ];
35220		if ( hooks && "expand" in hooks ) {
35221			value = hooks.expand( value );
35222			delete props[ name ];
35223
35224			// Not quite $.extend, this won't overwrite existing keys.
35225			// Reusing 'index' because we have the correct "name"
35226			for ( index in value ) {
35227				if ( !( index in props ) ) {
35228					props[ index ] = value[ index ];
35229					specialEasing[ index ] = easing;
35230				}
35231			}
35232		} else {
35233			specialEasing[ name ] = easing;
35234		}
35235	}
35236}
35237
35238function Animation( elem, properties, options ) {
35239	var result,
35240		stopped,
35241		index = 0,
35242		length = animationPrefilters.length,
35243		deferred = jQuery.Deferred().always( function() {
35244			// Don't match elem in the :animated selector
35245			delete tick.elem;
35246		}),
35247		tick = function() {
35248			if ( stopped ) {
35249				return false;
35250			}
35251			var currentTime = fxNow || createFxNow(),
35252				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
vendor: 8,530 bytes, lines 35253-35567
35253				// Support: Android 2.3
35254				// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
35255				temp = remaining / animation.duration || 0,
35256				percent = 1 - temp,
35257				index = 0,
35258				length = animation.tweens.length;
35259
35260			for ( ; index < length ; index++ ) {
35261				animation.tweens[ index ].run( percent );
35262			}
35263
35264			deferred.notifyWith( elem, [ animation, percent, remaining ]);
35265
35266			if ( percent < 1 && length ) {
35267				return remaining;
35268			} else {
35269				deferred.resolveWith( elem, [ animation ] );
35270				return false;
35271			}
35272		},
35273		animation = deferred.promise({
35274			elem: elem,
35275			props: jQuery.extend( {}, properties ),
35276			opts: jQuery.extend( true, { specialEasing: {} }, options ),
35277			originalProperties: properties,
35278			originalOptions: options,
35279			startTime: fxNow || createFxNow(),
35280			duration: options.duration,
35281			tweens: [],
35282			createTween: function( prop, end ) {
35283				var tween = jQuery.Tween( elem, animation.opts, prop, end,
35284						animation.opts.specialEasing[ prop ] || animation.opts.easing );
35285				animation.tweens.push( tween );
35286				return tween;
35287			},
35288			stop: function( gotoEnd ) {
35289				var index = 0,
35290					// If we are going to the end, we want to run all the tweens
35291					// otherwise we skip this part
35292					length = gotoEnd ? animation.tweens.length : 0;
35293				if ( stopped ) {
35294					return this;
35295				}
35296				stopped = true;
35297				for ( ; index < length ; index++ ) {
35298					animation.tweens[ index ].run( 1 );
35299				}
35300
35301				// Resolve when we played the last frame; otherwise, reject
35302				if ( gotoEnd ) {
35303					deferred.resolveWith( elem, [ animation, gotoEnd ] );
35304				} else {
35305					deferred.rejectWith( elem, [ animation, gotoEnd ] );
35306				}
35307				return this;
35308			}
35309		}),
35310		props = animation.props;
35311
35312	propFilter( props, animation.opts.specialEasing );
35313
35314	for ( ; index < length ; index++ ) {
35315		result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
35316		if ( result ) {
35317			return result;
35318		}
35319	}
35320
35321	jQuery.map( props, createTween, animation );
35322
35323	if ( jQuery.isFunction( animation.opts.start ) ) {
35324		animation.opts.start.call( elem, animation );
35325	}
35326
35327	jQuery.fx.timer(
35328		jQuery.extend( tick, {
35329			elem: elem,
35330			anim: animation,
35331			queue: animation.opts.queue
35332		})
35333	);
35334
35335	// attach callbacks from options
35336	return animation.progress( animation.opts.progress )
35337		.done( animation.opts.done, animation.opts.complete )
35338		.fail( animation.opts.fail )
35339		.always( animation.opts.always );
35340}
35341
35342jQuery.Animation = jQuery.extend( Animation, {
35343
35344	tweener: function( props, callback ) {
35345		if ( jQuery.isFunction( props ) ) {
35346			callback = props;
35347			props = [ "*" ];
35348		} else {
35349			props = props.split(" ");
35350		}
35351
35352		var prop,
35353			index = 0,
35354			length = props.length;
35355
35356		for ( ; index < length ; index++ ) {
35357			prop = props[ index ];
35358			tweeners[ prop ] = tweeners[ prop ] || [];
35359			tweeners[ prop ].unshift( callback );
35360		}
35361	},
35362
35363	prefilter: function( callback, prepend ) {
35364		if ( prepend ) {
35365			animationPrefilters.unshift( callback );
35366		} else {
35367			animationPrefilters.push( callback );
35368		}
35369	}
35370});
35371
35372jQuery.speed = function( speed, easing, fn ) {
35373	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
35374		complete: fn || !fn && easing ||
35375			jQuery.isFunction( speed ) && speed,
35376		duration: speed,
35377		easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
35378	};
35379
35380	opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
35381		opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
35382
35383	// Normalize opt.queue - true/undefined/null -> "fx"
35384	if ( opt.queue == null || opt.queue === true ) {
35385		opt.queue = "fx";
35386	}
35387
35388	// Queueing
35389	opt.old = opt.complete;
35390
35391	opt.complete = function() {
35392		if ( jQuery.isFunction( opt.old ) ) {
35393			opt.old.call( this );
35394		}
35395
35396		if ( opt.queue ) {
35397			jQuery.dequeue( this, opt.queue );
35398		}
35399	};
35400
35401	return opt;
35402};
35403
35404jQuery.fn.extend({
35405	fadeTo: function( speed, to, easing, callback ) {
35406
35407		// Show any hidden elements after setting opacity to 0
35408		return this.filter( isHidden ).css( "opacity", 0 ).show()
35409
35410			// Animate to the value specified
35411			.end().animate({ opacity: to }, speed, easing, callback );
35412	},
35413	animate: function( prop, speed, easing, callback ) {
35414		var empty = jQuery.isEmptyObject( prop ),
35415			optall = jQuery.speed( speed, easing, callback ),
35416			doAnimation = function() {
35417				// Operate on a copy of prop so per-property easing won't be lost
35418				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
35419
35420				// Empty animations, or finishing resolves immediately
35421				if ( empty || data_priv.get( this, "finish" ) ) {
35422					anim.stop( true );
35423				}
35424			};
35425			doAnimation.finish = doAnimation;
35426
35427		return empty || optall.queue === false ?
35428			this.each( doAnimation ) :
35429			this.queue( optall.queue, doAnimation );
35430	},
35431	stop: function( type, clearQueue, gotoEnd ) {
35432		var stopQueue = function( hooks ) {
35433			var stop = hooks.stop;
35434			delete hooks.stop;
35435			stop( gotoEnd );
35436		};
35437
35438		if ( typeof type !== "string" ) {
35439			gotoEnd = clearQueue;
35440			clearQueue = type;
35441			type = undefined;
35442		}
35443		if ( clearQueue && type !== false ) {
35444			this.queue( type || "fx", [] );
35445		}
35446
35447		return this.each(function() {
35448			var dequeue = true,
35449				index = type != null && type + "queueHooks",
35450				timers = jQuery.timers,
35451				data = data_priv.get( this );
35452
35453			if ( index ) {
35454				if ( data[ index ] && data[ index ].stop ) {
35455					stopQueue( data[ index ] );
35456				}
35457			} else {
35458				for ( index in data ) {
35459					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
35460						stopQueue( data[ index ] );
35461					}
35462				}
35463			}
35464
35465			for ( index = timers.length; index--; ) {
35466				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
35467					timers[ index ].anim.stop( gotoEnd );
35468					dequeue = false;
35469					timers.splice( index, 1 );
35470				}
35471			}
35472
35473			// Start the next in the queue if the last step wasn't forced.
35474			// Timers currently will call their complete callbacks, which
35475			// will dequeue but only if they were gotoEnd.
35476			if ( dequeue || !gotoEnd ) {
35477				jQuery.dequeue( this, type );
35478			}
35479		});
35480	},
35481	finish: function( type ) {
35482		if ( type !== false ) {
35483			type = type || "fx";
35484		}
35485		return this.each(function() {
35486			var index,
35487				data = data_priv.get( this ),
35488				queue = data[ type + "queue" ],
35489				hooks = data[ type + "queueHooks" ],
35490				timers = jQuery.timers,
35491				length = queue ? queue.length : 0;
35492
35493			// Enable finishing flag on private data
35494			data.finish = true;
35495
35496			// Empty the queue first
35497			jQuery.queue( this, type, [] );
35498
35499			if ( hooks && hooks.stop ) {
35500				hooks.stop.call( this, true );
35501			}
35502
35503			// Look for any active animations, and finish them
35504			for ( index = timers.length; index--; ) {
35505				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
35506					timers[ index ].anim.stop( true );
35507					timers.splice( index, 1 );
35508				}
35509			}
35510
35511			// Look for any animations in the old queue and finish them
35512			for ( index = 0; index < length; index++ ) {
35513				if ( queue[ index ] && queue[ index ].finish ) {
35514					queue[ index ].finish.call( this );
35515				}
35516			}
35517
35518			// Turn off finishing flag
35519			delete data.finish;
35520		});
35521	}
35522});
35523
35524jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
35525	var cssFn = jQuery.fn[ name ];
35526	jQuery.fn[ name ] = function( speed, easing, callback ) {
35527		return speed == null || typeof speed === "boolean" ?
35528			cssFn.apply( this, arguments ) :
35529			this.animate( genFx( name, true ), speed, easing, callback );
35530	};
35531});
35532
35533// Generate shortcuts for custom animations
35534jQuery.each({
35535	slideDown: genFx("show"),
35536	slideUp: genFx("hide"),
35537	slideToggle: genFx("toggle"),
35538	fadeIn: { opacity: "show" },
35539	fadeOut: { opacity: "hide" },
35540	fadeToggle: { opacity: "toggle" }
35541}, function( name, props ) {
35542	jQuery.fn[ name ] = function( speed, easing, callback ) {
35543		return this.animate( props, speed, easing, callback );
35544	};
35545});
35546
35547jQuery.timers = [];
35548jQuery.fx.tick = function() {
35549	var timer,
35550		i = 0,
35551		timers = jQuery.timers;
35552
35553	fxNow = jQuery.now();
35554
35555	for ( ; i < timers.length; i++ ) {
35556		timer = timers[ i ];
35557		// Checks the timer has not already been removed
35558		if ( !timer() && timers[ i ] === timer ) {
35559			timers.splice( i--, 1 );
35560		}
35561	}
35562
35563	if ( !timers.length ) {
35564		jQuery.fx.stop();
35565	}
35566	fxNow = undefined;
35567};
35568
35569jQuery.fx.timer = function( timer ) {
35570	jQuery.timers.push( timer );
35571	if ( timer() ) {
35572		jQuery.fx.start();
35573	} else {
35574		jQuery.timers.pop();
35575	}
35576};
35577
35578jQuery.fx.interval = 13;
35579
35580jQuery.fx.start = function() {
35581	if ( !timerId ) {
35582		timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
35583	}
35584};
35585
35586jQuery.fx.stop = function() {
35587	clearInterval( timerId );
35588	timerId = null;
35589};
35590
35591jQuery.fx.speeds = {
35592	slow: 600,
35593	fast: 200,
35594	// Default speed
35595	_default: 400
35596};
35597
35598
35599// Based off of the plugin by Clint Helfers, with permission.
35600// http://blindsignals.com/index.php/2009/07/jquery-delay/
35601jQuery.fn.delay = function( time, type ) {
35602	time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
35603	type = type || "fx";
35604
35605	return this.queue( type, function( next, hooks ) {
35606		var timeout = setTimeout( next, time );
35607		hooks.stop = function() {
35608			clearTimeout( timeout );
35609		};
35610	});
35611};
35612
35613
35614(function() {
35615	var input = document.createElement( "input" ),
35616		select = document.createElement( "select" ),
35617		opt = select.appendChild( document.createElement( "option" ) );
35618
35619	input.type = "checkbox";
35620
35621	// Support: iOS<=5.1, Android<=4.2+
35622	// Default value for a checkbox should be "on"
35623	support.checkOn = input.value !== "";
35624
35625	// Support: IE<=11+
35626	// Must access selectedIndex to make default options select
35627	support.optSelected = opt.selected;
35628
35629	// Support: Android<=2.3
35630	// Options inside disabled selects are incorrectly marked as disabled
35631	select.disabled = true;
35632	support.optDisabled = !opt.disabled;
35633
35634	// Support: IE<=11+
35635	// An input loses its value after becoming a radio
35636	input = document.createElement( "input" );
35637	input.value = "t";
35638	input.type = "radio";
35639	support.radioValue = input.value === "t";
35640})();
35641
35642
35643var nodeHook, boolHook,
35644	attrHandle = jQuery.expr.attrHandle;
35645
35646jQuery.fn.extend({
35647	attr: function( name, value ) {
35648		return access( this, jQuery.attr, name, value, arguments.length > 1 );
35649	},
35650
35651	removeAttr: function( name ) {
35652		return this.each(function() {
35653			jQuery.removeAttr( this, name );
35654		});
35655	}
35656});
35657
35658jQuery.extend({
35659	attr: function( elem, name, value ) {
35660		var hooks, ret,
35661			nType = elem.nodeType;
35662
35663		// don't get/set attributes on text, comment and attribute nodes
35664		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
35665			return;
35666		}
35667
35668		// Fallback to prop when attributes are not supported
35669		if ( typeof elem.getAttribute === strundefined ) {
35670			return jQuery.prop( elem, name, value );
35671		}
35672
35673		// All attributes are lowercase
35674		// Grab necessary hook if one is defined
35675		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
35676			name = name.toLowerCase();
35677			hooks = jQuery.attrHooks[ name ] ||
35678				( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
35679		}
35680
35681		if ( value !== undefined ) {
35682
35683			if ( value === null ) {
35684				jQuery.removeAttr( elem, name );
35685
35686			} else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
35687				return ret;
35688
35689			} else {
35690				elem.setAttribute( name, value + "" );
35691				return value;
35692			}
35693
35694		} else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
35695			return ret;
35696
35697		} else {
35698			ret = jQuery.find.attr( elem, name );
35699
35700			// Non-existent attributes return null, we normalize to undefined
35701			return ret == null ?
35702				undefined :
35703				ret;
35704		}
35705	},
35706
35707	removeAttr: function( elem, value ) {
35708		var name, propName,
35709			i = 0,
35710			attrNames = value && value.match( rnotwhite );
35711
35712		if ( attrNames && elem.nodeType === 1 ) {
35713			while ( (name = attrNames[i++]) ) {
35714				propName = jQuery.propFix[ name ] || name;
35715
35716				// Boolean attributes get special treatment (#10870)
35717				if ( jQuery.expr.match.bool.test( name ) ) {
35718					// Set corresponding property to false
35719					elem[ propName ] = false;
35720				}
35721
35722				elem.removeAttribute( name );
35723			}
35724		}
35725	},
35726
35727	attrHooks: {
35728		type: {
35729			set: function( elem, value ) {
35730				if ( !support.radioValue && value === "radio" &&
35731					jQuery.nodeName( elem, "input" ) ) {
35732					var val = elem.value;
35733					elem.setAttribute( "type", value );
35734					if ( val ) {
35735						elem.value = val;
35736					}
35737					return value;
35738				}
35739			}
35740		}
35741	}
35742});
35743
35744// Hooks for boolean attributes
35745boolHook = {
35746	set: function( elem, value, name ) {
35747		if ( value === false ) {
35748			// Remove boolean attributes when set to false
35749			jQuery.removeAttr( elem, name );
35750		} else {
35751			elem.setAttribute( name, name );
35752		}
35753		return name;
35754	}
35755};
35756jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
35757	var getter = attrHandle[ name ] || jQuery.find.attr;
35758
35759	attrHandle[ name ] = function( elem, name, isXML ) {
35760		var ret, handle;
35761		if ( !isXML ) {
35762			// Avoid an infinite loop by temporarily removing this function from the getter
35763			handle = attrHandle[ name ];
35764			attrHandle[ name ] = ret;
35765			ret = getter( elem, name, isXML ) != null ?
35766				name.toLowerCase() :
35767				null;
35768			attrHandle[ name ] = handle;
35769		}
35770		return ret;
35771	};
35772});
35773
35774
35775
35776
35777var rfocusable = /^(?:input|select|textarea|button)$/i;
35778
35779jQuery.fn.extend({
35780	prop: function( name, value ) {
35781		return access( this, jQuery.prop, name, value, arguments.length > 1 );
35782	},
35783
35784	removeProp: function( name ) {
35785		return this.each(function() {
35786			delete this[ jQuery.propFix[ name ] || name ];
35787		});
35788	}
35789});
35790
35791jQuery.extend({
35792	propFix: {
35793		"for": "htmlFor",
35794		"class": "className"
35795	},
35796
35797	prop: function( elem, name, value ) {
35798		var ret, hooks, notxml,
35799			nType = elem.nodeType;
35800
35801		// Don't get/set properties on text, comment and attribute nodes
35802		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
35803			return;
35804		}
35805
35806		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
35807
35808		if ( notxml ) {
35809			// Fix name and attach hooks
35810			name = jQuery.propFix[ name ] || name;
35811			hooks = jQuery.propHooks[ name ];
35812		}
35813
35814		if ( value !== undefined ) {
35815			return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
35816				ret :
35817				( elem[ name ] = value );
35818
35819		} else {
35820			return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
35821				ret :
35822				elem[ name ];
35823		}
35824	},
35825
35826	propHooks: {
35827		tabIndex: {
35828			get: function( elem ) {
35829				return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ?
35830					elem.tabIndex :
35831					-1;
35832			}
35833		}
35834	}
35835});
35836
35837if ( !support.optSelected ) {
35838	jQuery.propHooks.selected = {
35839		get: function( elem ) {
35840			var parent = elem.parentNode;
35841			if ( parent && parent.parentNode ) {
35842				parent.parentNode.selectedIndex;
35843			}
35844			return null;
35845		}
35846	};
35847}
35848
35849jQuery.each([
35850	"tabIndex",
35851	"readOnly",
35852	"maxLength",
35853	"cellSpacing",
35854	"cellPadding",
35855	"rowSpan",
35856	"colSpan",
35857	"useMap",
35858	"frameBorder",
35859	"contentEditable"
35860], function() {
35861	jQuery.propFix[ this.toLowerCase() ] = this;
35862});
35863
35864
35865
35866
35867var rclass = /[\t\r\n\f]/g;
35868
35869jQuery.fn.extend({
35870	addClass: function( value ) {
35871		var classes, elem, cur, clazz, j, finalValue,
35872			proceed = typeof value === "string" && value,
35873			i = 0,
35874			len = this.length;
35875
35876		if ( jQuery.isFunction( value ) ) {
35877			return this.each(function( j ) {
35878				jQuery( this ).addClass( value.call( this, j, this.className ) );
35879			});
35880		}
35881
35882		if ( proceed ) {
35883			// The disjunction here is for better compressibility (see removeClass)
35884			classes = ( value || "" ).match( rnotwhite ) || [];
35885
35886			for ( ; i < len; i++ ) {
35887				elem = this[ i ];
35888				cur = elem.nodeType === 1 && ( elem.className ?
35889					( " " + elem.className + " " ).replace( rclass, " " ) :
35890					" "
35891				);
35892
35893				if ( cur ) {
35894					j = 0;
35895					while ( (clazz = classes[j++]) ) {
35896						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
35897							cur += clazz + " ";
35898						}
35899					}
35900
35901					// only assign if different to avoid unneeded rendering.
35902					finalValue = jQuery.trim( cur );
35903					if ( elem.className !== finalValue ) {
35904						elem.className = finalValue;
35905					}
35906				}
35907			}
35908		}
35909
35910		return this;
35911	},
35912
35913	removeClass: function( value ) {
35914		var classes, elem, cur, clazz, j, finalValue,
35915			proceed = arguments.length === 0 || typeof value === "string" && value,
35916			i = 0,
35917			len = this.length;
35918
35919		if ( jQuery.isFunction( value ) ) {
35920			return this.each(function( j ) {
35921				jQuery( this ).removeClass( value.call( this, j, this.className ) );
35922			});
35923		}
35924		if ( proceed ) {
35925			classes = ( value || "" ).match( rnotwhite ) || [];
35926
35927			for ( ; i < len; i++ ) {
35928				elem = this[ i ];
35929				// This expression is here for better compressibility (see addClass)
35930				cur = elem.nodeType === 1 && ( elem.className ?
35931					( " " + elem.className + " " ).replace( rclass, " " ) :
35932					""
35933				);
35934
35935				if ( cur ) {
35936					j = 0;
35937					while ( (clazz = classes[j++]) ) {
35938						// Remove *all* instances
35939						while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
35940							cur = cur.replace( " " + clazz + " ", " " );
35941						}
35942					}
35943
35944					// Only assign if different to avoid unneeded rendering.
35945					finalValue = value ? jQuery.trim( cur ) : "";
35946					if ( elem.className !== finalValue ) {
35947						elem.className = finalValue;
35948					}
35949				}
35950			}
35951		}
35952
35953		return this;
35954	},
35955
35956	toggleClass: function( value, stateVal ) {
35957		var type = typeof value;
35958
35959		if ( typeof stateVal === "boolean" && type === "string" ) {
35960			return stateVal ? this.addClass( value ) : this.removeClass( value );
35961		}
35962
35963		if ( jQuery.isFunction( value ) ) {
35964			return this.each(function( i ) {
35965				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
35966			});
35967		}
35968
35969		return this.each(function() {
35970			if ( type === "string" ) {
35971				// Toggle individual class names
35972				var className,
35973					i = 0,
35974					self = jQuery( this ),
35975					classNames = value.match( rnotwhite ) || [];
35976
35977				while ( (className = classNames[ i++ ]) ) {
35978					// Check each className given, space separated list
35979					if ( self.hasClass( className ) ) {
35980						self.removeClass( className );
35981					} else {
35982						self.addClass( className );
35983					}
35984				}
35985
35986			// Toggle whole class name
35987			} else if ( type === strundefined || type === "boolean" ) {
35988				if ( this.className ) {
35989					// store className if set
35990					data_priv.set( this, "__className__", this.className );
35991				}
35992
35993				// If the element has a class name or if we're passed `false`,
35994				// then remove the whole classname (if there was one, the above saved it).
35995				// Otherwise bring back whatever was previously saved (if anything),
35996				// falling back to the empty string if nothing was stored.
35997				this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || "";
35998			}
35999		});
36000	},
36001
36002	hasClass: function( selector ) {
36003		var className = " " + selector + " ",
36004			i = 0,
36005			l = this.length;
36006		for ( ; i < l; i++ ) {
36007			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
36008				return true;
36009			}
36010		}
36011
36012		return false;
36013	}
36014});
36015
36016
36017
36018
36019var rreturn = /\r/g;
36020
36021jQuery.fn.extend({
36022	val: function( value ) {
36023		var hooks, ret, isFunction,
36024			elem = this[0];
36025
36026		if ( !arguments.length ) {
36027			if ( elem ) {
36028				hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
36029
36030				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
36031					return ret;
36032				}
36033
36034				ret = elem.value;
36035
36036				return typeof ret === "string" ?
36037					// Handle most common string cases
36038					ret.replace(rreturn, "") :
36039					// Handle cases where value is null/undef or number
36040					ret == null ? "" : ret;
36041			}
36042
36043			return;
36044		}
36045
36046		isFunction = jQuery.isFunction( value );
36047
36048		return this.each(function( i ) {
36049			var val;
36050
36051			if ( this.nodeType !== 1 ) {
36052				return;
36053			}
36054
36055			if ( isFunction ) {
36056				val = value.call( this, i, jQuery( this ).val() );
36057			} else {
36058				val = value;
36059			}
36060
36061			// Treat null/undefined as ""; convert numbers to string
36062			if ( val == null ) {
36063				val = "";
36064
36065			} else if ( typeof val === "number" ) {
36066				val += "";
36067
36068			} else if ( jQuery.isArray( val ) ) {
36069				val = jQuery.map( val, function( value ) {
36070					return value == null ? "" : value + "";
36071				});
36072			}
36073
36074			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
36075
36076			// If set returns undefined, fall back to normal setting
36077			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
36078				this.value = val;
36079			}
36080		});
36081	}
36082});
36083
36084jQuery.extend({
36085	valHooks: {
36086		option: {
36087			get: function( elem ) {
36088				var val = jQuery.find.attr( elem, "value" );
36089				return val != null ?
36090					val :
36091					// Support: IE10-11+
36092					// option.text throws exceptions (#14686, #14858)
36093					jQuery.trim( jQuery.text( elem ) );
36094			}
36095		},
36096		select: {
36097			get: function( elem ) {
36098				var value, option,
36099					options = elem.options,
36100					index = elem.selectedIndex,
36101					one = elem.type === "select-one" || index < 0,
36102					values = one ? null : [],
36103					max = one ? index + 1 : options.length,
36104					i = index < 0 ?
36105						max :
36106						one ? index : 0;
36107
36108				// Loop through all the selected options
36109				for ( ; i < max; i++ ) {
36110					option = options[ i ];
36111
36112					// IE6-9 doesn't update selected after form reset (#2551)
36113					if ( ( option.selected || i === index ) &&
36114							// Don't return options that are disabled or in a disabled optgroup
36115							( support.optDisabled ? !option.disabled : option.getAttribute( "disabled" ) === null ) &&
36116							( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
36117
36118						// Get the specific value for the option
36119						value = jQuery( option ).val();
36120
36121						// We don't need an array for one selects
36122						if ( one ) {
36123							return value;
36124						}
36125
36126						// Multi-Selects return an array
36127						values.push( value );
36128					}
36129				}
36130
36131				return values;
36132			},
36133
36134			set: function( elem, value ) {
36135				var optionSet, option,
36136					options = elem.options,
36137					values = jQuery.makeArray( value ),
36138					i = options.length;
36139
36140				while ( i-- ) {
36141					option = options[ i ];
36142					if ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) {
36143						optionSet = true;
36144					}
36145				}
36146
36147				// Force browsers to behave consistently when non-matching value is set
36148				if ( !optionSet ) {
36149					elem.selectedIndex = -1;
36150				}
36151				return values;
36152			}
36153		}
36154	}
36155});
36156
36157// Radios and checkboxes getter/setter
36158jQuery.each([ "radio", "checkbox" ], function() {
36159	jQuery.valHooks[ this ] = {
36160		set: function( elem, value ) {
36161			if ( jQuery.isArray( value ) ) {
36162				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
36163			}
36164		}
36165	};
36166	if ( !support.checkOn ) {
36167		jQuery.valHooks[ this ].get = function( elem ) {
36168			return elem.getAttribute("value") === null ? "on" : elem.value;
36169		};
36170	}
36171});
36172
36173
36174
36175
36176// Return jQuery for attributes-only inclusion
36177
36178
36179jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
36180	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
36181	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
36182
36183	// Handle event binding
36184	jQuery.fn[ name ] = function( data, fn ) {
36185		return arguments.length > 0 ?
36186			this.on( name, null, data, fn ) :
36187			this.trigger( name );
36188	};
36189});
36190
36191jQuery.fn.extend({
36192	hover: function( fnOver, fnOut ) {
36193		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
36194	},
36195
36196	bind: function( types, data, fn ) {
36197		return this.on( types, null, data, fn );
36198	},
36199	unbind: function( types, fn ) {
36200		return this.off( types, null, fn );
36201	},
36202
36203	delegate: function( selector, types, data, fn ) {
36204		return this.on( types, selector, data, fn );
36205	},
36206	undelegate: function( selector, types, fn ) {
36207		// ( namespace ) or ( selector, types [, fn] )
36208		return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
36209	}
36210});
36211
36212
36213var nonce = jQuery.now();
36214
36215var rquery = (/\?/);
36216
36217
36218
36219// Support: Android 2.3
36220// Workaround failure to string-cast null input
36221jQuery.parseJSON = function( data ) {
36222	return JSON.parse( data + "" );
36223};
36224
36225
36226// Cross-browser xml parsing
36227jQuery.parseXML = function( data ) {
36228	var xml, tmp;
36229	if ( !data || typeof data !== "string" ) {
36230		return null;
36231	}
36232
36233	// Support: IE9
36234	try {
36235		tmp = new DOMParser();
36236		xml = tmp.parseFromString( data, "text/xml" );
36237	} catch ( e ) {
36238		xml = undefined;
36239	}
36240
36241	if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
36242		jQuery.error( "Invalid XML: " + data );
36243	}
36244	return xml;
36245};
36246
36247
36248var
36249	rhash = /#.*$/,
36250	rts = /([?&])_=[^&]*/,
36251	rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
vendor: 4,413 bytes, lines 36252-36392
36252	// #7653, #8125, #8152: local protocol detection
36253	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
36254	rnoContent = /^(?:GET|HEAD)$/,
36255	rprotocol = /^\/\//,
36256	rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
36257
36258	/* Prefilters
36259	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
36260	 * 2) These are called:
36261	 *    - BEFORE asking for a transport
36262	 *    - AFTER param serialization (s.data is a string if s.processData is true)
36263	 * 3) key is the dataType
36264	 * 4) the catchall symbol "*" can be used
36265	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
36266	 */
36267	prefilters = {},
36268
36269	/* Transports bindings
36270	 * 1) key is the dataType
36271	 * 2) the catchall symbol "*" can be used
36272	 * 3) selection will start with transport dataType and THEN go to "*" if needed
36273	 */
36274	transports = {},
36275
36276	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
36277	allTypes = "*/".concat( "*" ),
36278
36279	// Document location
36280	ajaxLocation = window.location.href,
36281
36282	// Segment location into parts
36283	ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
36284
36285// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
36286function addToPrefiltersOrTransports( structure ) {
36287
36288	// dataTypeExpression is optional and defaults to "*"
36289	return function( dataTypeExpression, func ) {
36290
36291		if ( typeof dataTypeExpression !== "string" ) {
36292			func = dataTypeExpression;
36293			dataTypeExpression = "*";
36294		}
36295
36296		var dataType,
36297			i = 0,
36298			dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
36299
36300		if ( jQuery.isFunction( func ) ) {
36301			// For each dataType in the dataTypeExpression
36302			while ( (dataType = dataTypes[i++]) ) {
36303				// Prepend if requested
36304				if ( dataType[0] === "+" ) {
36305					dataType = dataType.slice( 1 ) || "*";
36306					(structure[ dataType ] = structure[ dataType ] || []).unshift( func );
36307
36308				// Otherwise append
36309				} else {
36310					(structure[ dataType ] = structure[ dataType ] || []).push( func );
36311				}
36312			}
36313		}
36314	};
36315}
36316
36317// Base inspection function for prefilters and transports
36318function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
36319
36320	var inspected = {},
36321		seekingTransport = ( structure === transports );
36322
36323	function inspect( dataType ) {
36324		var selected;
36325		inspected[ dataType ] = true;
36326		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
36327			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
36328			if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
36329				options.dataTypes.unshift( dataTypeOrTransport );
36330				inspect( dataTypeOrTransport );
36331				return false;
36332			} else if ( seekingTransport ) {
36333				return !( selected = dataTypeOrTransport );
36334			}
36335		});
36336		return selected;
36337	}
36338
36339	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
36340}
36341
36342// A special extend for ajax options
36343// that takes "flat" options (not to be deep extended)
36344// Fixes #9887
36345function ajaxExtend( target, src ) {
36346	var key, deep,
36347		flatOptions = jQuery.ajaxSettings.flatOptions || {};
36348
36349	for ( key in src ) {
36350		if ( src[ key ] !== undefined ) {
36351			( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
36352		}
36353	}
36354	if ( deep ) {
36355		jQuery.extend( true, target, deep );
36356	}
36357
36358	return target;
36359}
36360
36361/* Handles responses to an ajax request:
36362 * - finds the right dataType (mediates between content-type and expected dataType)
36363 * - returns the corresponding response
36364 */
36365function ajaxHandleResponses( s, jqXHR, responses ) {
36366
36367	var ct, type, finalDataType, firstDataType,
36368		contents = s.contents,
36369		dataTypes = s.dataTypes;
36370
36371	// Remove auto dataType and get content-type in the process
36372	while ( dataTypes[ 0 ] === "*" ) {
36373		dataTypes.shift();
36374		if ( ct === undefined ) {
36375			ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
36376		}
36377	}
36378
36379	// Check if we're dealing with a known content-type
36380	if ( ct ) {
36381		for ( type in contents ) {
36382			if ( contents[ type ] && contents[ type ].test( ct ) ) {
36383				dataTypes.unshift( type );
36384				break;
36385			}
36386		}
36387	}
36388
36389	// Check to see if we have a response for the expected dataType
36390	if ( dataTypes[ 0 ] in responses ) {
36391		finalDataType = dataTypes[ 0 ];
36392	} else {
vendor: 4,724 bytes, lines 36393-36583
36393		// Try convertible dataTypes
36394		for ( type in responses ) {
36395			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
36396				finalDataType = type;
36397				break;
36398			}
36399			if ( !firstDataType ) {
36400				firstDataType = type;
36401			}
36402		}
36403		// Or just use first one
36404		finalDataType = finalDataType || firstDataType;
36405	}
36406
36407	// If we found a dataType
36408	// We add the dataType to the list if needed
36409	// and return the corresponding response
36410	if ( finalDataType ) {
36411		if ( finalDataType !== dataTypes[ 0 ] ) {
36412			dataTypes.unshift( finalDataType );
36413		}
36414		return responses[ finalDataType ];
36415	}
36416}
36417
36418/* Chain conversions given the request and the original response
36419 * Also sets the responseXXX fields on the jqXHR instance
36420 */
36421function ajaxConvert( s, response, jqXHR, isSuccess ) {
36422	var conv2, current, conv, tmp, prev,
36423		converters = {},
36424		// Work with a copy of dataTypes in case we need to modify it for conversion
36425		dataTypes = s.dataTypes.slice();
36426
36427	// Create converters map with lowercased keys
36428	if ( dataTypes[ 1 ] ) {
36429		for ( conv in s.converters ) {
36430			converters[ conv.toLowerCase() ] = s.converters[ conv ];
36431		}
36432	}
36433
36434	current = dataTypes.shift();
36435
36436	// Convert to each sequential dataType
36437	while ( current ) {
36438
36439		if ( s.responseFields[ current ] ) {
36440			jqXHR[ s.responseFields[ current ] ] = response;
36441		}
36442
36443		// Apply the dataFilter if provided
36444		if ( !prev && isSuccess && s.dataFilter ) {
36445			response = s.dataFilter( response, s.dataType );
36446		}
36447
36448		prev = current;
36449		current = dataTypes.shift();
36450
36451		if ( current ) {
36452
36453		// There's only work to do if current dataType is non-auto
36454			if ( current === "*" ) {
36455
36456				current = prev;
36457
36458			// Convert response if prev dataType is non-auto and differs from current
36459			} else if ( prev !== "*" && prev !== current ) {
36460
36461				// Seek a direct converter
36462				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
36463
36464				// If none found, seek a pair
36465				if ( !conv ) {
36466					for ( conv2 in converters ) {
36467
36468						// If conv2 outputs current
36469						tmp = conv2.split( " " );
36470						if ( tmp[ 1 ] === current ) {
36471
36472							// If prev can be converted to accepted input
36473							conv = converters[ prev + " " + tmp[ 0 ] ] ||
36474								converters[ "* " + tmp[ 0 ] ];
36475							if ( conv ) {
36476								// Condense equivalence converters
36477								if ( conv === true ) {
36478									conv = converters[ conv2 ];
36479
36480								// Otherwise, insert the intermediate dataType
36481								} else if ( converters[ conv2 ] !== true ) {
36482									current = tmp[ 0 ];
36483									dataTypes.unshift( tmp[ 1 ] );
36484								}
36485								break;
36486							}
36487						}
36488					}
36489				}
36490
36491				// Apply converter (if not an equivalence)
36492				if ( conv !== true ) {
36493
36494					// Unless errors are allowed to bubble, catch and return them
36495					if ( conv && s[ "throws" ] ) {
36496						response = conv( response );
36497					} else {
36498						try {
36499							response = conv( response );
36500						} catch ( e ) {
36501							return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
36502						}
36503					}
36504				}
36505			}
36506		}
36507	}
36508
36509	return { state: "success", data: response };
36510}
36511
36512jQuery.extend({
36513
36514	// Counter for holding the number of active queries
36515	active: 0,
36516
36517	// Last-Modified header cache for next request
36518	lastModified: {},
36519	etag: {},
36520
36521	ajaxSettings: {
36522		url: ajaxLocation,
36523		type: "GET",
36524		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
36525		global: true,
36526		processData: true,
36527		async: true,
36528		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
36529		/*
36530		timeout: 0,
36531		data: null,
36532		dataType: null,
36533		username: null,
36534		password: null,
36535		cache: null,
36536		throws: false,
36537		traditional: false,
36538		headers: {},
36539		*/
36540
36541		accepts: {
36542			"*": allTypes,
36543			text: "text/plain",
36544			html: "text/html",
36545			xml: "application/xml, text/xml",
36546			json: "application/json, text/javascript"
36547		},
36548
36549		contents: {
36550			xml: /xml/,
36551			html: /html/,
36552			json: /json/
36553		},
36554
36555		responseFields: {
36556			xml: "responseXML",
36557			text: "responseText",
36558			json: "responseJSON"
36559		},
36560
36561		// Data converters
36562		// Keys separate source (or catchall "*") and destination types with a single space
36563		converters: {
36564
36565			// Convert anything to text
36566			"* text": String,
36567
36568			// Text to html (true = no transformation)
36569			"text html": true,
36570
36571			// Evaluate text as a json expression
36572			"text json": jQuery.parseJSON,
36573
36574			// Parse text as xml
36575			"text xml": jQuery.parseXML
36576		},
36577
36578		// For options that shouldn't be deep extended:
36579		// you can add your own custom options here if
36580		// and when you create one that shouldn't be
36581		// deep extended (see ajaxExtend)
36582		flatOptions: {
36583			url: true,
36584			context: true
36585		}
36586	},
36587
36588	// Creates a full fledged settings object into target
36589	// with both ajaxSettings and settings fields.
36590	// If target is omitted, writes into ajaxSettings.
36591	ajaxSetup: function( target, settings ) {
36592		return settings ?
36593
36594			// Building a settings object
36595			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
36596
36597			// Extending ajaxSettings
36598			ajaxExtend( jQuery.ajaxSettings, target );
36599	},
36600
36601	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
36602	ajaxTransport: addToPrefiltersOrTransports( transports ),
36603
36604	// Main method
36605	ajax: function( url, options ) {
36606
36607		// If url is an object, simulate pre-1.5 signature
36608		if ( typeof url === "object" ) {
36609			options = url;
36610			url = undefined;
36611		}
36612
36613		// Force options to be an object
36614		options = options || {};
36615
36616		var transport,
36617			// URL without anti-cache param
36618			cacheURL,
36619			// Response headers
36620			responseHeadersString,
36621			responseHeaders,
36622			// timeout handle
36623			timeoutTimer,
36624			// Cross-domain detection vars
36625			parts,
36626			// To know if global events are to be dispatched
36627			fireGlobals,
36628			// Loop variable
36629			i,
36630			// Create the final options object
36631			s = jQuery.ajaxSetup( {}, options ),
36632			// Callbacks context
36633			callbackContext = s.context || s,
36634			// Context for global events is callbackContext if it is a DOM node or jQuery collection
36635			globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
36636				jQuery( callbackContext ) :
36637				jQuery.event,
36638			// Deferreds
36639			deferred = jQuery.Deferred(),
36640			completeDeferred = jQuery.Callbacks("once memory"),
36641			// Status-dependent callbacks
36642			statusCode = s.statusCode || {},
36643			// Headers (they are sent all at once)
36644			requestHeaders = {},
36645			requestHeadersNames = {},
36646			// The jqXHR state
36647			state = 0,
36648			// Default abort message
36649			strAbort = "canceled",
36650			// Fake xhr
36651			jqXHR = {
36652				readyState: 0,
36653
36654				// Builds headers hashtable if needed
36655				getResponseHeader: function( key ) {
36656					var match;
36657					if ( state === 2 ) {
36658						if ( !responseHeaders ) {
36659							responseHeaders = {};
36660							while ( (match = rheaders.exec( responseHeadersString )) ) {
36661								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
36662							}
36663						}
36664						match = responseHeaders[ key.toLowerCase() ];
36665					}
36666					return match == null ? null : match;
36667				},
36668
36669				// Raw string
36670				getAllResponseHeaders: function() {
36671					return state === 2 ? responseHeadersString : null;
36672				},
36673
36674				// Caches the header
36675				setRequestHeader: function( name, value ) {
36676					var lname = name.toLowerCase();
36677					if ( !state ) {
36678						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
36679						requestHeaders[ name ] = value;
36680					}
36681					return this;
36682				},
36683
36684				// Overrides response content-type header
36685				overrideMimeType: function( type ) {
36686					if ( !state ) {
36687						s.mimeType = type;
36688					}
36689					return this;
36690				},
36691
36692				// Status-dependent callbacks
36693				statusCode: function( map ) {
36694					var code;
36695					if ( map ) {
36696						if ( state < 2 ) {
36697							for ( code in map ) {
36698								// Lazy-add the new callback in a way that preserves old ones
36699								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
36700							}
36701						} else {
36702							// Execute the appropriate callbacks
36703							jqXHR.always( map[ jqXHR.status ] );
36704						}
36705					}
36706					return this;
36707				},
36708
36709				// Cancel the request
36710				abort: function( statusText ) {
36711					var finalText = statusText || strAbort;
36712					if ( transport ) {
36713						transport.abort( finalText );
36714					}
36715					done( 0, finalText );
36716					return this;
36717				}
36718			};
36719
36720		// Attach deferreds
36721		deferred.promise( jqXHR ).complete = completeDeferred.add;
36722		jqXHR.success = jqXHR.done;
36723		jqXHR.error = jqXHR.fail;
36724
36725		// Remove hash character (#7531: and string promotion)
36726		// Add protocol if not provided (prefilters might expect it)
36727		// Handle falsy url in the settings object (#10093: consistency with old signature)
36728		// We also use the url parameter if available
36729		s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" )
36730			.replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
36731
36732		// Alias method option to type as per ticket #12004
36733		s.type = options.method || options.type || s.method || s.type;
36734
36735		// Extract dataTypes list
36736		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
36737
36738		// A cross-domain request is in order when we have a protocol:host:port mismatch
36739		if ( s.crossDomain == null ) {
36740			parts = rurl.exec( s.url.toLowerCase() );
36741			s.crossDomain = !!( parts &&
36742				( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
36743					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
36744						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
36745			);
36746		}
36747
36748		// Convert data if not already a string
36749		if ( s.data && s.processData && typeof s.data !== "string" ) {
36750			s.data = jQuery.param( s.data, s.traditional );
36751		}
36752
36753		// Apply prefilters
36754		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
36755
36756		// If request was aborted inside a prefilter, stop there
36757		if ( state === 2 ) {
36758			return jqXHR;
36759		}
36760
36761		// We can fire global events as of now if asked to
36762		// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
36763		fireGlobals = jQuery.event && s.global;
36764
36765		// Watch for a new set of requests
36766		if ( fireGlobals && jQuery.active++ === 0 ) {
36767			jQuery.event.trigger("ajaxStart");
36768		}
36769
36770		// Uppercase the type
36771		s.type = s.type.toUpperCase();
36772
36773		// Determine if request has content
36774		s.hasContent = !rnoContent.test( s.type );
36775
36776		// Save the URL in case we're toying with the If-Modified-Since
36777		// and/or If-None-Match header later on
36778		cacheURL = s.url;
36779
36780		// More options handling for requests with no content
36781		if ( !s.hasContent ) {
36782
36783			// If data is available, append data to url
36784			if ( s.data ) {
36785				cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
36786				// #9682: remove data so that it's not used in an eventual retry
36787				delete s.data;
36788			}
36789
36790			// Add anti-cache in url if needed
36791			if ( s.cache === false ) {
36792				s.url = rts.test( cacheURL ) ?
36793
36794					// If there is already a '_' parameter, set its value
36795					cacheURL.replace( rts, "$1_=" + nonce++ ) :
36796
36797					// Otherwise add one to the end
36798					cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
36799			}
36800		}
36801
36802		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
36803		if ( s.ifModified ) {
36804			if ( jQuery.lastModified[ cacheURL ] ) {
36805				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
36806			}
36807			if ( jQuery.etag[ cacheURL ] ) {
36808				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
36809			}
36810		}
36811
36812		// Set the correct header, if data is being sent
36813		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
36814			jqXHR.setRequestHeader( "Content-Type", s.contentType );
36815		}
36816
36817		// Set the Accepts header for the server, depending on the dataType
36818		jqXHR.setRequestHeader(
36819			"Accept",
36820			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
36821				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
36822				s.accepts[ "*" ]
36823		);
36824
36825		// Check for headers option
36826		for ( i in s.headers ) {
36827			jqXHR.setRequestHeader( i, s.headers[ i ] );
36828		}
36829
36830		// Allow custom headers/mimetypes and early abort
36831		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
36832			// Abort if not done already and return
36833			return jqXHR.abort();
36834		}
36835
36836		// Aborting is no longer a cancellation
36837		strAbort = "abort";
36838
36839		// Install callbacks on deferreds
36840		for ( i in { success: 1, error: 1, complete: 1 } ) {
36841			jqXHR[ i ]( s[ i ] );
36842		}
36843
36844		// Get transport
36845		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
36846
36847		// If no transport, we auto-abort
36848		if ( !transport ) {
36849			done( -1, "No Transport" );
36850		} else {
36851			jqXHR.readyState = 1;
36852
36853			// Send global event
36854			if ( fireGlobals ) {
36855				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
36856			}
36857			// Timeout
36858			if ( s.async && s.timeout > 0 ) {
36859				timeoutTimer = setTimeout(function() {
36860					jqXHR.abort("timeout");
36861				}, s.timeout );
36862			}
36863
36864			try {
36865				state = 1;
36866				transport.send( requestHeaders, done );
36867			} catch ( e ) {
36868				// Propagate exception as error if not done
36869				if ( state < 2 ) {
36870					done( -1, e );
36871				// Simply rethrow otherwise
36872				} else {
36873					throw e;
36874				}
36875			}
36876		}
36877
36878		// Callback for when everything is done
36879		function done( status, nativeStatusText, responses, headers ) {
36880			var isSuccess, success, error, response, modified,
36881				statusText = nativeStatusText;
36882
36883			// Called once
36884			if ( state === 2 ) {
36885				return;
36886			}
36887
36888			// State is "done" now
36889			state = 2;
36890
36891			// Clear timeout if it exists
36892			if ( timeoutTimer ) {
36893				clearTimeout( timeoutTimer );
36894			}
36895
36896			// Dereference transport for early garbage collection
36897			// (no matter how long the jqXHR object will be used)
36898			transport = undefined;
36899
36900			// Cache response headers
36901			responseHeadersString = headers || "";
36902
36903			// Set readyState
36904			jqXHR.readyState = status > 0 ? 4 : 0;
36905
36906			// Determine if successful
36907			isSuccess = status >= 200 && status < 300 || status === 304;
36908
36909			// Get response data
36910			if ( responses ) {
36911				response = ajaxHandleResponses( s, jqXHR, responses );
36912			}
36913
36914			// Convert no matter what (that way responseXXX fields are always set)
36915			response = ajaxConvert( s, response, jqXHR, isSuccess );
36916
36917			// If successful, handle type chaining
36918			if ( isSuccess ) {
36919
36920				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
36921				if ( s.ifModified ) {
36922					modified = jqXHR.getResponseHeader("Last-Modified");
36923					if ( modified ) {
36924						jQuery.lastModified[ cacheURL ] = modified;
36925					}
36926					modified = jqXHR.getResponseHeader("etag");
36927					if ( modified ) {
36928						jQuery.etag[ cacheURL ] = modified;
36929					}
36930				}
36931
36932				// if no content
36933				if ( status === 204 || s.type === "HEAD" ) {
36934					statusText = "nocontent";
36935
36936				// if not modified
36937				} else if ( status === 304 ) {
36938					statusText = "notmodified";
36939
36940				// If we have data, let's convert it
36941				} else {
36942					statusText = response.state;
36943					success = response.data;
36944					error = response.error;
36945					isSuccess = !error;
36946				}
36947			} else {
36948				// Extract error from statusText and normalize for non-aborts
36949				error = statusText;
36950				if ( status || !statusText ) {
36951					statusText = "error";
36952					if ( status < 0 ) {
36953						status = 0;
36954					}
36955				}
36956			}
36957
36958			// Set data for the fake xhr object
36959			jqXHR.status = status;
36960			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
36961
36962			// Success/Error
36963			if ( isSuccess ) {
36964				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
36965			} else {
36966				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
36967			}
36968
36969			// Status-dependent callbacks
36970			jqXHR.statusCode( statusCode );
36971			statusCode = undefined;
36972
36973			if ( fireGlobals ) {
36974				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
36975					[ jqXHR, s, isSuccess ? success : error ] );
36976			}
36977
36978			// Complete
36979			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
36980
36981			if ( fireGlobals ) {
36982				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
36983				// Handle the global AJAX counter
36984				if ( !( --jQuery.active ) ) {
36985					jQuery.event.trigger("ajaxStop");
36986				}
36987			}
36988		}
36989
36990		return jqXHR;
36991	},
36992
36993	getJSON: function( url, data, callback ) {
36994		return jQuery.get( url, data, callback, "json" );
36995	},
36996
36997	getScript: function( url, callback ) {
36998		return jQuery.get( url, undefined, callback, "script" );
36999	}
37000});
37001
37002jQuery.each( [ "get", "post" ], function( i, method ) {
37003	jQuery[ method ] = function( url, data, callback, type ) {
37004		// Shift arguments if data argument was omitted
37005		if ( jQuery.isFunction( data ) ) {
37006			type = type || callback;
37007			callback = data;
37008			data = undefined;
37009		}
37010
37011		return jQuery.ajax({
37012			url: url,
37013			type: method,
37014			dataType: type,
37015			data: data,
37016			success: callback
37017		});
37018	};
37019});
37020
37021
37022jQuery._evalUrl = function( url ) {
37023	return jQuery.ajax({
37024		url: url,
37025		type: "GET",
37026		dataType: "script",
37027		async: false,
37028		global: false,
37029		"throws": true
37030	});
37031};
37032
37033
37034jQuery.fn.extend({
37035	wrapAll: function( html ) {
37036		var wrap;
37037
37038		if ( jQuery.isFunction( html ) ) {
37039			return this.each(function( i ) {
37040				jQuery( this ).wrapAll( html.call(this, i) );
37041			});
37042		}
37043
37044		if ( this[ 0 ] ) {
37045
37046			// The elements to wrap the target around
37047			wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
37048
37049			if ( this[ 0 ].parentNode ) {
37050				wrap.insertBefore( this[ 0 ] );
37051			}
37052
37053			wrap.map(function() {
37054				var elem = this;
37055
37056				while ( elem.firstElementChild ) {
37057					elem = elem.firstElementChild;
37058				}
37059
37060				return elem;
37061			}).append( this );
37062		}
37063
37064		return this;
37065	},
37066
37067	wrapInner: function( html ) {
37068		if ( jQuery.isFunction( html ) ) {
37069			return this.each(function( i ) {
37070				jQuery( this ).wrapInner( html.call(this, i) );
37071			});
37072		}
37073
37074		return this.each(function() {
37075			var self = jQuery( this ),
37076				contents = self.contents();
37077
37078			if ( contents.length ) {
37079				contents.wrapAll( html );
37080
37081			} else {
37082				self.append( html );
37083			}
37084		});
37085	},
37086
37087	wrap: function( html ) {
37088		var isFunction = jQuery.isFunction( html );
37089
37090		return this.each(function( i ) {
37091			jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
37092		});
37093	},
37094
37095	unwrap: function() {
37096		return this.parent().each(function() {
37097			if ( !jQuery.nodeName( this, "body" ) ) {
37098				jQuery( this ).replaceWith( this.childNodes );
37099			}
37100		}).end();
37101	}
37102});
37103
37104
37105jQuery.expr.filters.hidden = function( elem ) {
37106	// Support: Opera <= 12.12
37107	// Opera reports offsetWidths and offsetHeights less than zero on some elements
37108	return elem.offsetWidth <= 0 && elem.offsetHeight <= 0;
37109};
37110jQuery.expr.filters.visible = function( elem ) {
37111	return !jQuery.expr.filters.hidden( elem );
37112};
37113
37114
37115
37116
37117var r20 = /%20/g,
37118	rbracket = /\[\]$/,
37119	rCRLF = /\r?\n/g,
37120	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
37121	rsubmittable = /^(?:input|select|textarea|keygen)/i;
37122
37123function buildParams( prefix, obj, traditional, add ) {
37124	var name;
37125
37126	if ( jQuery.isArray( obj ) ) {
37127		// Serialize array item.
37128		jQuery.each( obj, function( i, v ) {
37129			if ( traditional || rbracket.test( prefix ) ) {
37130				// Treat each array item as a scalar.
37131				add( prefix, v );
37132
37133			} else {
37134				// Item is non-scalar (array or object), encode its numeric index.
37135				buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
37136			}
37137		});
37138
37139	} else if ( !traditional && jQuery.type( obj ) === "object" ) {
37140		// Serialize object item.
37141		for ( name in obj ) {
37142			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
37143		}
37144
37145	} else {
37146		// Serialize scalar item.
37147		add( prefix, obj );
37148	}
37149}
37150
37151// Serialize an array of form elements or a set of
37152// key/values into a query string
37153jQuery.param = function( a, traditional ) {
37154	var prefix,
37155		s = [],
37156		add = function( key, value ) {
37157			// If value is a function, invoke it and return its value
37158			value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
37159			s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
37160		};
37161
37162	// Set traditional to true for jQuery <= 1.3.2 behavior.
37163	if ( traditional === undefined ) {
37164		traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
37165	}
37166
37167	// If an array was passed in, assume that it is an array of form elements.
37168	if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
37169		// Serialize the form elements
37170		jQuery.each( a, function() {
37171			add( this.name, this.value );
37172		});
37173
37174	} else {
37175		// If traditional, encode the "old" way (the way 1.3.2 or older
37176		// did it), otherwise encode params recursively.
37177		for ( prefix in a ) {
37178			buildParams( prefix, a[ prefix ], traditional, add );
37179		}
37180	}
37181
37182	// Return the resulting serialization
37183	return s.join( "&" ).replace( r20, "+" );
37184};
37185
37186jQuery.fn.extend({
37187	serialize: function() {
37188		return jQuery.param( this.serializeArray() );
37189	},
37190	serializeArray: function() {
37191		return this.map(function() {
37192			// Can add propHook for "elements" to filter or add form elements
37193			var elements = jQuery.prop( this, "elements" );
37194			return elements ? jQuery.makeArray( elements ) : this;
37195		})
37196		.filter(function() {
37197			var type = this.type;
37198
37199			// Use .is( ":disabled" ) so that fieldset[disabled] works
37200			return this.name && !jQuery( this ).is( ":disabled" ) &&
37201				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
37202				( this.checked || !rcheckableType.test( type ) );
37203		})
37204		.map(function( i, elem ) {
37205			var val = jQuery( this ).val();
37206
37207			return val == null ?
37208				null :
37209				jQuery.isArray( val ) ?
37210					jQuery.map( val, function( val ) {
37211						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
37212					}) :
37213					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
37214		}).get();
37215	}
37216});
37217
37218
37219jQuery.ajaxSettings.xhr = function() {
37220	try {
37221		return new XMLHttpRequest();
37222	} catch( e ) {}
37223};
37224
37225var xhrId = 0,
37226	xhrCallbacks = {},
37227	xhrSuccessStatus = {
37228		// file protocol always yields status code 0, assume 200
37229		0: 200,
37230		// Support: IE9
37231		// #1450: sometimes IE returns 1223 when it should be 204
37232		1223: 204
37233	},
37234	xhrSupported = jQuery.ajaxSettings.xhr();
37235
37236// Support: IE9
37237// Open requests must be manually aborted on unload (#5280)
37238// See https://support.microsoft.com/kb/2856746 for more info
37239if ( window.attachEvent ) {
37240	window.attachEvent( "onunload", function() {
37241		for ( var key in xhrCallbacks ) {
37242			xhrCallbacks[ key ]();
37243		}
37244	});
37245}
37246
37247support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
37248support.ajax = xhrSupported = !!xhrSupported;
37249
37250jQuery.ajaxTransport(function( options ) {
37251	var callback;
37252
37253	// Cross domain only allowed if supported through XMLHttpRequest
37254	if ( support.cors || xhrSupported && !options.crossDomain ) {
37255		return {
37256			send: function( headers, complete ) {
37257				var i,
37258					xhr = options.xhr(),
37259					id = ++xhrId;
37260
37261				xhr.open( options.type, options.url, options.async, options.username, options.password );
37262
37263				// Apply custom fields if provided
37264				if ( options.xhrFields ) {
37265					for ( i in options.xhrFields ) {
37266						xhr[ i ] = options.xhrFields[ i ];
37267					}
37268				}
37269
37270				// Override mime type if needed
37271				if ( options.mimeType && xhr.overrideMimeType ) {
37272					xhr.overrideMimeType( options.mimeType );
37273				}
37274
37275				// X-Requested-With header
37276				// For cross-domain requests, seeing as conditions for a preflight are
37277				// akin to a jigsaw puzzle, we simply never set it to be sure.
37278				// (it can always be set on a per-request basis or even using ajaxSetup)
37279				// For same-domain requests, won't change header if already provided.
37280				if ( !options.crossDomain && !headers["X-Requested-With"] ) {
37281					headers["X-Requested-With"] = "XMLHttpRequest";
37282				}
37283
37284				// Set headers
37285				for ( i in headers ) {
37286					xhr.setRequestHeader( i, headers[ i ] );
37287				}
37288
37289				// Callback
37290				callback = function( type ) {
37291					return function() {
37292						if ( callback ) {
37293							delete xhrCallbacks[ id ];
37294							callback = xhr.onload = xhr.onerror = null;
37295
37296							if ( type === "abort" ) {
37297								xhr.abort();
37298							} else if ( type === "error" ) {
37299								complete(
37300									// file: protocol always yields status 0; see #8605, #14207
37301									xhr.status,
37302									xhr.statusText
37303								);
37304							} else {
37305								complete(
37306									xhrSuccessStatus[ xhr.status ] || xhr.status,
37307									xhr.statusText,
37308									// Support: IE9
37309									// Accessing binary-data responseText throws an exception
37310									// (#11426)
37311									typeof xhr.responseText === "string" ? {
37312										text: xhr.responseText
37313									} : undefined,
37314									xhr.getAllResponseHeaders()
37315								);
37316							}
37317						}
37318					};
37319				};
37320
37321				// Listen to events
37322				xhr.onload = callback();
37323				xhr.onerror = callback("error");
37324
37325				// Create the abort callback
37326				callback = xhrCallbacks[ id ] = callback("abort");
37327
37328				try {
37329					// Do send the request (this may raise an exception)
37330					xhr.send( options.hasContent && options.data || null );
37331				} catch ( e ) {
37332					// #14683: Only rethrow if this hasn't been notified as an error yet
37333					if ( callback ) {
37334						throw e;
37335					}
37336				}
37337			},
37338
37339			abort: function() {
37340				if ( callback ) {
37341					callback();
37342				}
37343			}
37344		};
37345	}
37346});
37347
37348
37349
37350
37351// Install script dataType
37352jQuery.ajaxSetup({
37353	accepts: {
37354		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
37355	},
37356	contents: {
37357		script: /(?:java|ecma)script/
37358	},
37359	converters: {
37360		"text script": function( text ) {
37361			jQuery.globalEval( text );
37362			return text;
37363		}
37364	}
37365});
37366
37367// Handle cache's special case and crossDomain
37368jQuery.ajaxPrefilter( "script", function( s ) {
37369	if ( s.cache === undefined ) {
37370		s.cache = false;
37371	}
37372	if ( s.crossDomain ) {
37373		s.type = "GET";
37374	}
37375});
37376
37377// Bind script tag hack transport
37378jQuery.ajaxTransport( "script", function( s ) {
37379	// This transport only deals with cross domain requests
37380	if ( s.crossDomain ) {
37381		var script, callback;
37382		return {
37383			send: function( _, complete ) {
37384				script = jQuery("<script>").prop({
37385					async: true,
37386					charset: s.scriptCharset,
37387					src: s.url
37388				}).on(
37389					"load error",
37390					callback = function( evt ) {
37391						script.remove();
37392						callback = null;
37393						if ( evt ) {
37394							complete( evt.type === "error" ? 404 : 200, evt.type );
37395						}
37396					}
37397				);
37398				document.head.appendChild( script[ 0 ] );
37399			},
37400			abort: function() {
37401				if ( callback ) {
37402					callback();
37403				}
37404			}
37405		};
37406	}
37407});
37408
37409
37410
37411
37412var oldCallbacks = [],
37413	rjsonp = /(=)\?(?=&|$)|\?\?/;
37414
37415// Default jsonp settings
37416jQuery.ajaxSetup({
37417	jsonp: "callback",
37418	jsonpCallback: function() {
37419		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
37420		this[ callback ] = true;
37421		return callback;
37422	}
37423});
37424
37425// Detect, normalize options and install callbacks for jsonp requests
37426jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
37427
37428	var callbackName, overwritten, responseContainer,
37429		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
37430			"url" :
37431			typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
37432		);
37433
37434	// Handle iff the expected data type is "jsonp" or we have a parameter to set
37435	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
37436
37437		// Get callback name, remembering preexisting value associated with it
37438		callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
37439			s.jsonpCallback() :
37440			s.jsonpCallback;
37441
37442		// Insert callback into url or form data
37443		if ( jsonProp ) {
37444			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
37445		} else if ( s.jsonp !== false ) {
37446			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
37447		}
37448
37449		// Use data converter to retrieve json after script execution
37450		s.converters["script json"] = function() {
37451			if ( !responseContainer ) {
37452				jQuery.error( callbackName + " was not called" );
37453			}
37454			return responseContainer[ 0 ];
37455		};
37456
37457		// force json dataType
37458		s.dataTypes[ 0 ] = "json";
37459
37460		// Install callback
37461		overwritten = window[ callbackName ];
37462		window[ callbackName ] = function() {
37463			responseContainer = arguments;
37464		};
37465
37466		// Clean-up function (fires after converters)
37467		jqXHR.always(function() {
37468			// Restore preexisting value
37469			window[ callbackName ] = overwritten;
37470
37471			// Save back as free
37472			if ( s[ callbackName ] ) {
37473				// make sure that re-using the options doesn't screw things around
37474				s.jsonpCallback = originalSettings.jsonpCallback;
37475
37476				// save the callback name for future use
37477				oldCallbacks.push( callbackName );
37478			}
37479
37480			// Call if it was a function and we have a response
37481			if ( responseContainer && jQuery.isFunction( overwritten ) ) {
37482				overwritten( responseContainer[ 0 ] );
37483			}
37484
37485			responseContainer = overwritten = undefined;
37486		});
37487
37488		// Delegate to script
37489		return "script";
37490	}
37491});
37492
37493
37494
37495
37496// data: string of html
37497// context (optional): If specified, the fragment will be created in this context, defaults to document
37498// keepScripts (optional): If true, will include scripts passed in the html string
37499jQuery.parseHTML = function( data, context, keepScripts ) {
37500	if ( !data || typeof data !== "string" ) {
37501		return null;
37502	}
37503	if ( typeof context === "boolean" ) {
37504		keepScripts = context;
37505		context = false;
37506	}
37507	context = context || document;
37508
37509	var parsed = rsingleTag.exec( data ),
37510		scripts = !keepScripts && [];
37511
37512	// Single tag
37513	if ( parsed ) {
37514		return [ context.createElement( parsed[1] ) ];
37515	}
37516
37517	parsed = jQuery.buildFragment( [ data ], context, scripts );
37518
37519	if ( scripts && scripts.length ) {
37520		jQuery( scripts ).remove();
37521	}
37522
37523	return jQuery.merge( [], parsed.childNodes );
37524};
37525
37526
37527// Keep a copy of the old load method
37528var _load = jQuery.fn.load;
37529
37530/**
37531 * Load a url into a page
37532 */
37533jQuery.fn.load = function( url, params, callback ) {
37534	if ( typeof url !== "string" && _load ) {
37535		return _load.apply( this, arguments );
37536	}
37537
37538	var selector, type, response,
37539		self = this,
37540		off = url.indexOf(" ");
37541
37542	if ( off >= 0 ) {
37543		selector = jQuery.trim( url.slice( off ) );
37544		url = url.slice( 0, off );
37545	}
37546
37547	// If it's a function
37548	if ( jQuery.isFunction( params ) ) {
37549
37550		// We assume that it's the callback
37551		callback = params;
37552		params = undefined;
37553
37554	// Otherwise, build a param string
37555	} else if ( params && typeof params === "object" ) {
37556		type = "POST";
37557	}
37558
37559	// If we have elements to modify, make the request
37560	if ( self.length > 0 ) {
37561		jQuery.ajax({
37562			url: url,
37563
37564			// if "type" variable is undefined, then "GET" method will be used
37565			type: type,
37566			dataType: "html",
37567			data: params
37568		}).done(function( responseText ) {
37569
37570			// Save response for use in complete callback
37571			response = arguments;
37572
37573			self.html( selector ?
37574
37575				// If a selector was specified, locate the right elements in a dummy div
37576				// Exclude scripts to avoid IE 'Permission Denied' errors
37577				jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
37578
37579				// Otherwise use the full result
37580				responseText );
37581
37582		}).complete( callback && function( jqXHR, status ) {
37583			self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
37584		});
37585	}
37586
37587	return this;
37588};
37589
37590
37591
37592
37593// Attach a bunch of functions for handling common AJAX events
37594jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
37595	jQuery.fn[ type ] = function( fn ) {
37596		return this.on( type, fn );
37597	};
37598});
37599
37600
37601
37602
37603jQuery.expr.filters.animated = function( elem ) {
37604	return jQuery.grep(jQuery.timers, function( fn ) {
37605		return elem === fn.elem;
37606	}).length;
37607};
37608
37609
37610
37611
37612var docElem = window.document.documentElement;
37613
37614/**
37615 * Gets a window from an element
37616 */
37617function getWindow( elem ) {
37618	return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
37619}
37620
37621jQuery.offset = {
37622	setOffset: function( elem, options, i ) {
37623		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
37624			position = jQuery.css( elem, "position" ),
37625			curElem = jQuery( elem ),
37626			props = {};
37627
37628		// Set position first, in-case top/left are set even on static elem
37629		if ( position === "static" ) {
37630			elem.style.position = "relative";
37631		}
37632
37633		curOffset = curElem.offset();
37634		curCSSTop = jQuery.css( elem, "top" );
37635		curCSSLeft = jQuery.css( elem, "left" );
37636		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
37637			( curCSSTop + curCSSLeft ).indexOf("auto") > -1;
37638
37639		// Need to be able to calculate position if either
37640		// top or left is auto and position is either absolute or fixed
37641		if ( calculatePosition ) {
37642			curPosition = curElem.position();
37643			curTop = curPosition.top;
37644			curLeft = curPosition.left;
37645
37646		} else {
37647			curTop = parseFloat( curCSSTop ) || 0;
37648			curLeft = parseFloat( curCSSLeft ) || 0;
37649		}
37650
37651		if ( jQuery.isFunction( options ) ) {
37652			options = options.call( elem, i, curOffset );
37653		}
37654
37655		if ( options.top != null ) {
37656			props.top = ( options.top - curOffset.top ) + curTop;
37657		}
37658		if ( options.left != null ) {
37659			props.left = ( options.left - curOffset.left ) + curLeft;
37660		}
37661
37662		if ( "using" in options ) {
37663			options.using.call( elem, props );
37664
37665		} else {
37666			curElem.css( props );
37667		}
37668	}
37669};
37670
37671jQuery.fn.extend({
37672	offset: function( options ) {
37673		if ( arguments.length ) {
37674			return options === undefined ?
37675				this :
37676				this.each(function( i ) {
37677					jQuery.offset.setOffset( this, options, i );
37678				});
37679		}
37680
37681		var docElem, win,
37682			elem = this[ 0 ],
37683			box = { top: 0, left: 0 },
37684			doc = elem && elem.ownerDocument;
37685
37686		if ( !doc ) {
37687			return;
37688		}
37689
37690		docElem = doc.documentElement;
37691
37692		// Make sure it's not a disconnected DOM node
37693		if ( !jQuery.contains( docElem, elem ) ) {
37694			return box;
37695		}
37696
37697		// Support: BlackBerry 5, iOS 3 (original iPhone)
37698		// If we don't have gBCR, just use 0,0 rather than error
37699		if ( typeof elem.getBoundingClientRect !== strundefined ) {
37700			box = elem.getBoundingClientRect();
37701		}
37702		win = getWindow( doc );
37703		return {
37704			top: box.top + win.pageYOffset - docElem.clientTop,
37705			left: box.left + win.pageXOffset - docElem.clientLeft
37706		};
37707	},
37708
37709	position: function() {
37710		if ( !this[ 0 ] ) {
37711			return;
37712		}
37713
37714		var offsetParent, offset,
37715			elem = this[ 0 ],
37716			parentOffset = { top: 0, left: 0 };
37717
37718		// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
37719		if ( jQuery.css( elem, "position" ) === "fixed" ) {
37720			// Assume getBoundingClientRect is there when computed position is fixed
37721			offset = elem.getBoundingClientRect();
37722
37723		} else {
37724			// Get *real* offsetParent
37725			offsetParent = this.offsetParent();
37726
37727			// Get correct offsets
37728			offset = this.offset();
37729			if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
37730				parentOffset = offsetParent.offset();
37731			}
37732
37733			// Add offsetParent borders
37734			parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
37735			parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
37736		}
37737
37738		// Subtract parent offsets and element margins
37739		return {
37740			top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
37741			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
37742		};
37743	},
37744
37745	offsetParent: function() {
37746		return this.map(function() {
37747			var offsetParent = this.offsetParent || docElem;
37748
37749			while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
37750				offsetParent = offsetParent.offsetParent;
37751			}
37752
37753			return offsetParent || docElem;
37754		});
37755	}
37756});
37757
37758// Create scrollLeft and scrollTop methods
37759jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
37760	var top = "pageYOffset" === prop;
37761
37762	jQuery.fn[ method ] = function( val ) {
37763		return access( this, function( elem, method, val ) {
37764			var win = getWindow( elem );
37765
37766			if ( val === undefined ) {
37767				return win ? win[ prop ] : elem[ method ];
37768			}
37769
37770			if ( win ) {
37771				win.scrollTo(
37772					!top ? val : window.pageXOffset,
37773					top ? val : window.pageYOffset
37774				);
37775
37776			} else {
37777				elem[ method ] = val;
37778			}
37779		}, method, val, arguments.length, null );
37780	};
37781});
37782
37783// Support: Safari<7+, Chrome<37+
37784// Add the top/left cssHooks using jQuery.fn.position
37785// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
37786// Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280
37787// getComputedStyle returns percent when specified for top/left/bottom/right;
37788// rather than make the css module depend on the offset module, just check for it here
37789jQuery.each( [ "top", "left" ], function( i, prop ) {
37790	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
37791		function( elem, computed ) {
37792			if ( computed ) {
37793				computed = curCSS( elem, prop );
37794				// If curCSS returns percentage, fallback to offset
37795				return rnumnonpx.test( computed ) ?
37796					jQuery( elem ).position()[ prop ] + "px" :
37797					computed;
37798			}
37799		}
37800	);
37801});
37802
37803
37804// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
37805jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
37806	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
37807		// Margin is only for outerHeight, outerWidth
37808		jQuery.fn[ funcName ] = function( margin, value ) {
37809			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
37810				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
37811
37812			return access( this, function( elem, type, value ) {
37813				var doc;
37814
37815				if ( jQuery.isWindow( elem ) ) {
37816					// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
37817					// isn't a whole lot we can do. See pull request at this URL for discussion:
37818					// https://github.com/jquery/jquery/pull/764
37819					return elem.document.documentElement[ "client" + name ];
37820				}
37821
37822				// Get document width or height
37823				if ( elem.nodeType === 9 ) {
37824					doc = elem.documentElement;
37825
37826					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
37827					// whichever is greatest
37828					return Math.max(
37829						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
37830						elem.body[ "offset" + name ], doc[ "offset" + name ],
37831						doc[ "client" + name ]
37832					);
37833				}
37834
37835				return value === undefined ?
37836					// Get width or height on the element, requesting but not forcing parseFloat
37837					jQuery.css( elem, type, extra ) :
37838
37839					// Set width or height on the element
37840					jQuery.style( elem, type, value, extra );
37841			}, type, chainable ? margin : undefined, chainable, null );
37842		};
37843	});
37844});
37845
37846
37847// The number of elements contained in the matched element set
37848jQuery.fn.size = function() {
37849	return this.length;
37850};
37851
37852jQuery.fn.andSelf = jQuery.fn.addBack;
37853
37854
37855
37856
37857// Register as a named AMD module, since jQuery can be concatenated with other
37858// files that may use define, but not via a proper concatenation script that
37859// understands anonymous AMD modules. A named AMD is safest and most robust
37860// way to register. Lowercase jquery is used because AMD module names are
37861// derived from file names, and jQuery is normally delivered in a lowercase
37862// file name. Do this after creating the global so that if an AMD module wants
37863// to call noConflict to hide this version of jQuery, it will work.
37864
37865// Note that for maximum portability, libraries that are not jQuery should
37866// declare themselves as anonymous modules, and avoid setting a global if an
37867// AMD loader is present. jQuery is a special case. For more information, see
37868// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
37869
37870if ( typeof define === "function" && define.amd ) {
37871	define( "jquery", [], function() {
37872		return jQuery;
37873	});
37874}
37875
37876
37877
37878
37879var
37880	// Map over jQuery in case of overwrite
37881	_jQuery = window.jQuery,
37882
37883	// Map over the $ in case of overwrite
37884	_$ = window.$;
37885
37886jQuery.noConflict = function( deep ) {
37887	if ( window.$ === jQuery ) {
37888		window.$ = _$;
37889	}
37890
37891	if ( deep && window.jQuery === jQuery ) {
37892		window.jQuery = _jQuery;
37893	}
37894
37895	return jQuery;
37896};
37897
37898// Expose jQuery and $ identifiers, even in AMD
37899// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
37900    // and CommonJS for browser emulators (#13566)
37901    /*
37902if ( typeof noGlobal === strundefined ) {
37903	window.jQuery = window.$ = jQuery;
37904}
37905*/
37906
37907
37908
37909return jQuery;
37910
37911}));
37912
37913},
37914'jquery-ui/ui/dialog':function(){
37915/*!
37916 * jQuery UI Dialog 1.11.2
37917 * http://jqueryui.com
vendor: 20,485 bytes, lines 37918-38700
37918 *
37919 * Copyright 2014 jQuery Foundation and other contributors
37920 * Released under the MIT license.
37921 * http://jquery.org/license
37922 *
37923 * http://api.jqueryui.com/dialog/
37924 */
37925(function( factory ) {
37926	if ( typeof define === "function" && define.amd ) {
37927
37928		// AMD. Register as an anonymous module.
37929		define([
37930			"jquery",
37931			"./core",
37932			"./widget",
37933			"./button",
37934			"./draggable",
37935			"./mouse",
37936			"./position",
37937			"./resizable"
37938		], factory );
37939	} else {
37940
37941		// Browser globals
37942		factory( jQuery );
37943	}
37944}(function( $ ) {
37945
37946return $.widget( "ui.dialog", {
37947	version: "1.11.2",
37948	options: {
37949		appendTo: "body",
37950		autoOpen: true,
37951		buttons: [],
37952		closeOnEscape: true,
37953		closeText: "Close",
37954		dialogClass: "",
37955		draggable: true,
37956		hide: null,
37957		height: "auto",
37958		maxHeight: null,
37959		maxWidth: null,
37960		minHeight: 150,
37961		minWidth: 150,
37962		modal: false,
37963		position: {
37964			my: "center",
37965			at: "center",
37966			of: window,
37967			collision: "fit",
37968			// Ensure the titlebar is always visible
37969			using: function( pos ) {
37970				var topOffset = $( this ).css( pos ).offset().top;
37971				if ( topOffset < 0 ) {
37972					$( this ).css( "top", pos.top - topOffset );
37973				}
37974			}
37975		},
37976		resizable: true,
37977		show: null,
37978		title: null,
37979		width: 300,
37980
37981		// callbacks
37982		beforeClose: null,
37983		close: null,
37984		drag: null,
37985		dragStart: null,
37986		dragStop: null,
37987		focus: null,
37988		open: null,
37989		resize: null,
37990		resizeStart: null,
37991		resizeStop: null
37992	},
37993
37994	sizeRelatedOptions: {
37995		buttons: true,
37996		height: true,
37997		maxHeight: true,
37998		maxWidth: true,
37999		minHeight: true,
38000		minWidth: true,
38001		width: true
38002	},
38003
38004	resizableRelatedOptions: {
38005		maxHeight: true,
38006		maxWidth: true,
38007		minHeight: true,
38008		minWidth: true
38009	},
38010
38011	_create: function() {
38012		this.originalCss = {
38013			display: this.element[ 0 ].style.display,
38014			width: this.element[ 0 ].style.width,
38015			minHeight: this.element[ 0 ].style.minHeight,
38016			maxHeight: this.element[ 0 ].style.maxHeight,
38017			height: this.element[ 0 ].style.height
38018		};
38019		this.originalPosition = {
38020			parent: this.element.parent(),
38021			index: this.element.parent().children().index( this.element )
38022		};
38023		this.originalTitle = this.element.attr( "title" );
38024		this.options.title = this.options.title || this.originalTitle;
38025
38026		this._createWrapper();
38027
38028		this.element
38029			.show()
38030			.removeAttr( "title" )
38031			.addClass( "ui-dialog-content ui-widget-content" )
38032			.appendTo( this.uiDialog );
38033
38034		this._createTitlebar();
38035		this._createButtonPane();
38036
38037		if ( this.options.draggable && $.fn.draggable ) {
38038			this._makeDraggable();
38039		}
38040		if ( this.options.resizable && $.fn.resizable ) {
38041			this._makeResizable();
38042		}
38043
38044		this._isOpen = false;
38045
38046		this._trackFocus();
38047	},
38048
38049	_init: function() {
38050		if ( this.options.autoOpen ) {
38051			this.open();
38052		}
38053	},
38054
38055	_appendTo: function() {
38056		var element = this.options.appendTo;
38057		if ( element && (element.jquery || element.nodeType) ) {
38058			return $( element );
38059		}
38060		return this.document.find( element || "body" ).eq( 0 );
38061	},
38062
38063	_destroy: function() {
38064		var next,
38065			originalPosition = this.originalPosition;
38066
38067		this._destroyOverlay();
38068
38069		this.element
38070			.removeUniqueId()
38071			.removeClass( "ui-dialog-content ui-widget-content" )
38072			.css( this.originalCss )
38073			// Without detaching first, the following becomes really slow
38074			.detach();
38075
38076		this.uiDialog.stop( true, true ).remove();
38077
38078		if ( this.originalTitle ) {
38079			this.element.attr( "title", this.originalTitle );
38080		}
38081
38082		next = originalPosition.parent.children().eq( originalPosition.index );
38083		// Don't try to place the dialog next to itself (#8613)
38084		if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
38085			next.before( this.element );
38086		} else {
38087			originalPosition.parent.append( this.element );
38088		}
38089	},
38090
38091	widget: function() {
38092		return this.uiDialog;
38093	},
38094
38095	disable: $.noop,
38096	enable: $.noop,
38097
38098	close: function( event ) {
38099		var activeElement,
38100			that = this;
38101
38102		if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
38103			return;
38104		}
38105
38106		this._isOpen = false;
38107		this._focusedElement = null;
38108		this._destroyOverlay();
38109		this._untrackInstance();
38110
38111		if ( !this.opener.filter( ":focusable" ).focus().length ) {
38112
38113			// support: IE9
38114			// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
38115			try {
38116				activeElement = this.document[ 0 ].activeElement;
38117
38118				// Support: IE9, IE10
38119				// If the <body> is blurred, IE will switch windows, see #4520
38120				if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) {
38121
38122					// Hiding a focused element doesn't trigger blur in WebKit
38123					// so in case we have nothing to focus on, explicitly blur the active element
38124					// https://bugs.webkit.org/show_bug.cgi?id=47182
38125					$( activeElement ).blur();
38126				}
38127			} catch ( error ) {}
38128		}
38129
38130		this._hide( this.uiDialog, this.options.hide, function() {
38131			that._trigger( "close", event );
38132		});
38133	},
38134
38135	isOpen: function() {
38136		return this._isOpen;
38137	},
38138
38139	moveToTop: function() {
38140		this._moveToTop();
38141	},
38142
38143	_moveToTop: function( event, silent ) {
38144		var moved = false,
38145			zIndicies = this.uiDialog.siblings( ".ui-front:visible" ).map(function() {
38146				return +$( this ).css( "z-index" );
38147			}).get(),
38148			zIndexMax = Math.max.apply( null, zIndicies );
38149
38150		if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
38151			this.uiDialog.css( "z-index", zIndexMax + 1 );
38152			moved = true;
38153		}
38154
38155		if ( moved && !silent ) {
38156			this._trigger( "focus", event );
38157		}
38158		return moved;
38159	},
38160
38161	open: function() {
38162		var that = this;
38163		if ( this._isOpen ) {
38164			if ( this._moveToTop() ) {
38165				this._focusTabbable();
38166			}
38167			return;
38168		}
38169
38170		this._isOpen = true;
38171		this.opener = $( this.document[ 0 ].activeElement );
38172
38173		this._size();
38174		this._position();
38175		this._createOverlay();
38176		this._moveToTop( null, true );
38177
38178		// Ensure the overlay is moved to the top with the dialog, but only when
38179		// opening. The overlay shouldn't move after the dialog is open so that
38180		// modeless dialogs opened after the modal dialog stack properly.
38181		if ( this.overlay ) {
38182			this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
38183		}
38184
38185		this._show( this.uiDialog, this.options.show, function() {
38186			that._focusTabbable();
38187			that._trigger( "focus" );
38188		});
38189
38190		// Track the dialog immediately upon openening in case a focus event
38191		// somehow occurs outside of the dialog before an element inside the
38192		// dialog is focused (#10152)
38193		this._makeFocusTarget();
38194
38195		this._trigger( "open" );
38196	},
38197
38198	_focusTabbable: function() {
38199		// Set focus to the first match:
38200		// 1. An element that was focused previously
38201		// 2. First element inside the dialog matching [autofocus]
38202		// 3. Tabbable element inside the content element
38203		// 4. Tabbable element inside the buttonpane
38204		// 5. The close button
38205		// 6. The dialog itself
38206		var hasFocus = this._focusedElement;
38207		if ( !hasFocus ) {
38208			hasFocus = this.element.find( "[autofocus]" );
38209		}
38210		if ( !hasFocus.length ) {
38211			hasFocus = this.element.find( ":tabbable" );
38212		}
38213		if ( !hasFocus.length ) {
38214			hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
38215		}
38216		if ( !hasFocus.length ) {
38217			hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
38218		}
38219		if ( !hasFocus.length ) {
38220			hasFocus = this.uiDialog;
38221		}
38222		hasFocus.eq( 0 ).focus();
38223	},
38224
38225	_keepFocus: function( event ) {
38226		function checkFocus() {
38227			var activeElement = this.document[0].activeElement,
38228				isActive = this.uiDialog[0] === activeElement ||
38229					$.contains( this.uiDialog[0], activeElement );
38230			if ( !isActive ) {
38231				this._focusTabbable();
38232			}
38233		}
38234		event.preventDefault();
38235		checkFocus.call( this );
38236		// support: IE
38237		// IE <= 8 doesn't prevent moving focus even with event.preventDefault()
38238		// so we check again later
38239		this._delay( checkFocus );
38240	},
38241
38242	_createWrapper: function() {
38243		this.uiDialog = $("<div>")
38244			.addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +
38245				this.options.dialogClass )
38246			.hide()
38247			.attr({
38248				// Setting tabIndex makes the div focusable
38249				tabIndex: -1,
38250				role: "dialog"
38251			})
38252			.appendTo( this._appendTo() );
38253
38254		this._on( this.uiDialog, {
38255			keydown: function( event ) {
38256				if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
38257						event.keyCode === $.ui.keyCode.ESCAPE ) {
38258					event.preventDefault();
38259					this.close( event );
38260					return;
38261				}
38262
38263				// prevent tabbing out of dialogs
38264				if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
38265					return;
38266				}
38267				var tabbables = this.uiDialog.find( ":tabbable" ),
38268					first = tabbables.filter( ":first" ),
38269					last = tabbables.filter( ":last" );
38270
38271				if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
38272					this._delay(function() {
38273						first.focus();
38274					});
38275					event.preventDefault();
38276				} else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
38277					this._delay(function() {
38278						last.focus();
38279					});
38280					event.preventDefault();
38281				}
38282			},
38283			mousedown: function( event ) {
38284				if ( this._moveToTop( event ) ) {
38285					this._focusTabbable();
38286				}
38287			}
38288		});
38289
38290		// We assume that any existing aria-describedby attribute means
38291		// that the dialog content is marked up properly
38292		// otherwise we brute force the content as the description
38293		if ( !this.element.find( "[aria-describedby]" ).length ) {
38294			this.uiDialog.attr({
38295				"aria-describedby": this.element.uniqueId().attr( "id" )
38296			});
38297		}
38298	},
38299
38300	_createTitlebar: function() {
38301		var uiDialogTitle;
38302
38303		this.uiDialogTitlebar = $( "<div>" )
38304			.addClass( "ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix" )
38305			.prependTo( this.uiDialog );
38306		this._on( this.uiDialogTitlebar, {
38307			mousedown: function( event ) {
38308				// Don't prevent click on close button (#8838)
38309				// Focusing a dialog that is partially scrolled out of view
38310				// causes the browser to scroll it into view, preventing the click event
38311				if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
38312					// Dialog isn't getting focus when dragging (#8063)
38313					this.uiDialog.focus();
38314				}
38315			}
38316		});
38317
38318		// support: IE
38319		// Use type="button" to prevent enter keypresses in textboxes from closing the
38320		// dialog in IE (#9312)
38321		this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
38322			.button({
38323				label: this.options.closeText,
38324				icons: {
38325					primary: "ui-icon-closethick"
38326				},
38327				text: false
38328			})
38329			.addClass( "ui-dialog-titlebar-close" )
38330			.appendTo( this.uiDialogTitlebar );
38331		this._on( this.uiDialogTitlebarClose, {
38332			click: function( event ) {
38333				event.preventDefault();
38334				this.close( event );
38335			}
38336		});
38337
38338		uiDialogTitle = $( "<span>" )
38339			.uniqueId()
38340			.addClass( "ui-dialog-title" )
38341			.prependTo( this.uiDialogTitlebar );
38342		this._title( uiDialogTitle );
38343
38344		this.uiDialog.attr({
38345			"aria-labelledby": uiDialogTitle.attr( "id" )
38346		});
38347	},
38348
38349	_title: function( title ) {
38350		if ( !this.options.title ) {
38351			title.html( "&#160;" );
38352		}
38353		title.text( this.options.title );
38354	},
38355
38356	_createButtonPane: function() {
38357		this.uiDialogButtonPane = $( "<div>" )
38358			.addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" );
38359
38360		this.uiButtonSet = $( "<div>" )
38361			.addClass( "ui-dialog-buttonset" )
38362			.appendTo( this.uiDialogButtonPane );
38363
38364		this._createButtons();
38365	},
38366
38367	_createButtons: function() {
38368		var that = this,
38369			buttons = this.options.buttons;
38370
38371		// if we already have a button pane, remove it
38372		this.uiDialogButtonPane.remove();
38373		this.uiButtonSet.empty();
38374
38375		if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) {
38376			this.uiDialog.removeClass( "ui-dialog-buttons" );
38377			return;
38378		}
38379
38380		$.each( buttons, function( name, props ) {
38381			var click, buttonOptions;
38382			props = $.isFunction( props ) ?
38383				{ click: props, text: name } :
38384				props;
38385			// Default to a non-submitting button
38386			props = $.extend( { type: "button" }, props );
38387			// Change the context for the click callback to be the main element
38388			click = props.click;
38389			props.click = function() {
38390				click.apply( that.element[ 0 ], arguments );
38391			};
38392			buttonOptions = {
38393				icons: props.icons,
38394				text: props.showText
38395			};
38396			delete props.icons;
38397			delete props.showText;
38398			$( "<button></button>", props )
38399				.button( buttonOptions )
38400				.appendTo( that.uiButtonSet );
38401		});
38402		this.uiDialog.addClass( "ui-dialog-buttons" );
38403		this.uiDialogButtonPane.appendTo( this.uiDialog );
38404	},
38405
38406	_makeDraggable: function() {
38407		var that = this,
38408			options = this.options;
38409
38410		function filteredUi( ui ) {
38411			return {
38412				position: ui.position,
38413				offset: ui.offset
38414			};
38415		}
38416
38417		this.uiDialog.draggable({
38418			cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
38419			handle: ".ui-dialog-titlebar",
38420			containment: "document",
38421			start: function( event, ui ) {
38422				$( this ).addClass( "ui-dialog-dragging" );
38423				that._blockFrames();
38424				that._trigger( "dragStart", event, filteredUi( ui ) );
38425			},
38426			drag: function( event, ui ) {
38427				that._trigger( "drag", event, filteredUi( ui ) );
38428			},
38429			stop: function( event, ui ) {
38430				var left = ui.offset.left - that.document.scrollLeft(),
38431					top = ui.offset.top - that.document.scrollTop();
38432
38433				options.position = {
38434					my: "left top",
38435					at: "left" + (left >= 0 ? "+" : "") + left + " " +
38436						"top" + (top >= 0 ? "+" : "") + top,
38437					of: that.window
38438				};
38439				$( this ).removeClass( "ui-dialog-dragging" );
38440				that._unblockFrames();
38441				that._trigger( "dragStop", event, filteredUi( ui ) );
38442			}
38443		});
38444	},
38445
38446	_makeResizable: function() {
38447		var that = this,
38448			options = this.options,
38449			handles = options.resizable,
38450			// .ui-resizable has position: relative defined in the stylesheet
38451			// but dialogs have to use absolute or fixed positioning
38452			position = this.uiDialog.css("position"),
38453			resizeHandles = typeof handles === "string" ?
38454				handles	:
38455				"n,e,s,w,se,sw,ne,nw";
38456
38457		function filteredUi( ui ) {
38458			return {
38459				originalPosition: ui.originalPosition,
38460				originalSize: ui.originalSize,
38461				position: ui.position,
38462				size: ui.size
38463			};
38464		}
38465
38466		this.uiDialog.resizable({
38467			cancel: ".ui-dialog-content",
38468			containment: "document",
38469			alsoResize: this.element,
38470			maxWidth: options.maxWidth,
38471			maxHeight: options.maxHeight,
38472			minWidth: options.minWidth,
38473			minHeight: this._minHeight(),
38474			handles: resizeHandles,
38475			start: function( event, ui ) {
38476				$( this ).addClass( "ui-dialog-resizing" );
38477				that._blockFrames();
38478				that._trigger( "resizeStart", event, filteredUi( ui ) );
38479			},
38480			resize: function( event, ui ) {
38481				that._trigger( "resize", event, filteredUi( ui ) );
38482			},
38483			stop: function( event, ui ) {
38484				var offset = that.uiDialog.offset(),
38485					left = offset.left - that.document.scrollLeft(),
38486					top = offset.top - that.document.scrollTop();
38487
38488				options.height = that.uiDialog.height();
38489				options.width = that.uiDialog.width();
38490				options.position = {
38491					my: "left top",
38492					at: "left" + (left >= 0 ? "+" : "") + left + " " +
38493						"top" + (top >= 0 ? "+" : "") + top,
38494					of: that.window
38495				};
38496				$( this ).removeClass( "ui-dialog-resizing" );
38497				that._unblockFrames();
38498				that._trigger( "resizeStop", event, filteredUi( ui ) );
38499			}
38500		})
38501		.css( "position", position );
38502	},
38503
38504	_trackFocus: function() {
38505		this._on( this.widget(), {
38506			focusin: function( event ) {
38507				this._makeFocusTarget();
38508				this._focusedElement = $( event.target );
38509			}
38510		});
38511	},
38512
38513	_makeFocusTarget: function() {
38514		this._untrackInstance();
38515		this._trackingInstances().unshift( this );
38516	},
38517
38518	_untrackInstance: function() {
38519		var instances = this._trackingInstances(),
38520			exists = $.inArray( this, instances );
38521		if ( exists !== -1 ) {
38522			instances.splice( exists, 1 );
38523		}
38524	},
38525
38526	_trackingInstances: function() {
38527		var instances = this.document.data( "ui-dialog-instances" );
38528		if ( !instances ) {
38529			instances = [];
38530			this.document.data( "ui-dialog-instances", instances );
38531		}
38532		return instances;
38533	},
38534
38535	_minHeight: function() {
38536		var options = this.options;
38537
38538		return options.height === "auto" ?
38539			options.minHeight :
38540			Math.min( options.minHeight, options.height );
38541	},
38542
38543	_position: function() {
38544		// Need to show the dialog to get the actual offset in the position plugin
38545		var isVisible = this.uiDialog.is( ":visible" );
38546		if ( !isVisible ) {
38547			this.uiDialog.show();
38548		}
38549		this.uiDialog.position( this.options.position );
38550		if ( !isVisible ) {
38551			this.uiDialog.hide();
38552		}
38553	},
38554
38555	_setOptions: function( options ) {
38556		var that = this,
38557			resize = false,
38558			resizableOptions = {};
38559
38560		$.each( options, function( key, value ) {
38561			that._setOption( key, value );
38562
38563			if ( key in that.sizeRelatedOptions ) {
38564				resize = true;
38565			}
38566			if ( key in that.resizableRelatedOptions ) {
38567				resizableOptions[ key ] = value;
38568			}
38569		});
38570
38571		if ( resize ) {
38572			this._size();
38573			this._position();
38574		}
38575		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
38576			this.uiDialog.resizable( "option", resizableOptions );
38577		}
38578	},
38579
38580	_setOption: function( key, value ) {
38581		var isDraggable, isResizable,
38582			uiDialog = this.uiDialog;
38583
38584		if ( key === "dialogClass" ) {
38585			uiDialog
38586				.removeClass( this.options.dialogClass )
38587				.addClass( value );
38588		}
38589
38590		if ( key === "disabled" ) {
38591			return;
38592		}
38593
38594		this._super( key, value );
38595
38596		if ( key === "appendTo" ) {
38597			this.uiDialog.appendTo( this._appendTo() );
38598		}
38599
38600		if ( key === "buttons" ) {
38601			this._createButtons();
38602		}
38603
38604		if ( key === "closeText" ) {
38605			this.uiDialogTitlebarClose.button({
38606				// Ensure that we always pass a string
38607				label: "" + value
38608			});
38609		}
38610
38611		if ( key === "draggable" ) {
38612			isDraggable = uiDialog.is( ":data(ui-draggable)" );
38613			if ( isDraggable && !value ) {
38614				uiDialog.draggable( "destroy" );
38615			}
38616
38617			if ( !isDraggable && value ) {
38618				this._makeDraggable();
38619			}
38620		}
38621
38622		if ( key === "position" ) {
38623			this._position();
38624		}
38625
38626		if ( key === "resizable" ) {
38627			// currently resizable, becoming non-resizable
38628			isResizable = uiDialog.is( ":data(ui-resizable)" );
38629			if ( isResizable && !value ) {
38630				uiDialog.resizable( "destroy" );
38631			}
38632
38633			// currently resizable, changing handles
38634			if ( isResizable && typeof value === "string" ) {
38635				uiDialog.resizable( "option", "handles", value );
38636			}
38637
38638			// currently non-resizable, becoming resizable
38639			if ( !isResizable && value !== false ) {
38640				this._makeResizable();
38641			}
38642		}
38643
38644		if ( key === "title" ) {
38645			this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
38646		}
38647	},
38648
38649	_size: function() {
38650		// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
38651		// divs will both have width and height set, so we need to reset them
38652		var nonContentHeight, minContentHeight, maxContentHeight,
38653			options = this.options;
38654
38655		// Reset content sizing
38656		this.element.show().css({
38657			width: "auto",
38658			minHeight: 0,
38659			maxHeight: "none",
38660			height: 0
38661		});
38662
38663		if ( options.minWidth > options.width ) {
38664			options.width = options.minWidth;
38665		}
38666
38667		// reset wrapper sizing
38668		// determine the height of all the non-content elements
38669		nonContentHeight = this.uiDialog.css({
38670				height: "auto",
38671				width: options.width
38672			})
38673			.outerHeight();
38674		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
38675		maxContentHeight = typeof options.maxHeight === "number" ?
38676			Math.max( 0, options.maxHeight - nonContentHeight ) :
38677			"none";
38678
38679		if ( options.height === "auto" ) {
38680			this.element.css({
38681				minHeight: minContentHeight,
38682				maxHeight: maxContentHeight,
38683				height: "auto"
38684			});
38685		} else {
38686			this.element.height( Math.max( 0, options.height - nonContentHeight ) );
38687		}
38688
38689		if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
38690			this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
38691		}
38692	},
38693
38694	_blockFrames: function() {
38695		this.iframeBlocks = this.document.find( "iframe" ).map(function() {
38696			var iframe = $( this );
38697
38698			return $( "<div>" )
38699				.css({
38700					position: "absolute",
vendor: 4,490 bytes, lines 38701-38891
38701					width: iframe.outerWidth(),
38702					height: iframe.outerHeight()
38703				})
38704				.appendTo( iframe.parent() )
38705				.offset( iframe.offset() )[0];
38706		});
38707	},
38708
38709	_unblockFrames: function() {
38710		if ( this.iframeBlocks ) {
38711			this.iframeBlocks.remove();
38712			delete this.iframeBlocks;
38713		}
38714	},
38715
38716	_allowInteraction: function( event ) {
38717		if ( $( event.target ).closest( ".ui-dialog" ).length ) {
38718			return true;
38719		}
38720
38721		// TODO: Remove hack when datepicker implements
38722		// the .ui-front logic (#8989)
38723		return !!$( event.target ).closest( ".ui-datepicker" ).length;
38724	},
38725
38726	_createOverlay: function() {
38727		if ( !this.options.modal ) {
38728			return;
38729		}
38730
38731		// We use a delay in case the overlay is created from an
38732		// event that we're going to be cancelling (#2804)
38733		var isOpening = true;
38734		this._delay(function() {
38735			isOpening = false;
38736		});
38737
38738		if ( !this.document.data( "ui-dialog-overlays" ) ) {
38739
38740			// Prevent use of anchors and inputs
38741			// Using _on() for an event handler shared across many instances is
38742			// safe because the dialogs stack and must be closed in reverse order
38743			this._on( this.document, {
38744				focusin: function( event ) {
38745					if ( isOpening ) {
38746						return;
38747					}
38748
38749					if ( !this._allowInteraction( event ) ) {
38750						event.preventDefault();
38751						this._trackingInstances()[ 0 ]._focusTabbable();
38752					}
38753				}
38754			});
38755		}
38756
38757		this.overlay = $( "<div>" )
38758			.addClass( "ui-widget-overlay ui-front" )
38759			.appendTo( this._appendTo() );
38760		this._on( this.overlay, {
38761			mousedown: "_keepFocus"
38762		});
38763		this.document.data( "ui-dialog-overlays",
38764			(this.document.data( "ui-dialog-overlays" ) || 0) + 1 );
38765	},
38766
38767	_destroyOverlay: function() {
38768		if ( !this.options.modal ) {
38769			return;
38770		}
38771
38772		if ( this.overlay ) {
38773			var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
38774
38775			if ( !overlays ) {
38776				this.document
38777					.unbind( "focusin" )
38778					.removeData( "ui-dialog-overlays" );
38779			} else {
38780				this.document.data( "ui-dialog-overlays", overlays );
38781			}
38782
38783			this.overlay.remove();
38784			this.overlay = null;
38785		}
38786	}
38787});
38788
38789}));
38790
38791},
38792'jquery-ui/ui/core':function(){
38793/*!
38794 * jQuery UI Core 1.11.2
38795 * http://jqueryui.com
38796 *
38797 * Copyright 2014 jQuery Foundation and other contributors
38798 * Released under the MIT license.
38799 * http://jquery.org/license
38800 *
38801 * http://api.jqueryui.com/category/ui-core/
38802 */
38803(function( factory ) {
38804	if ( typeof define === "function" && define.amd ) {
38805
38806		// AMD. Register as an anonymous module.
38807		define( [ "jquery" ], factory );
38808	} else {
38809
38810		// Browser globals
38811		factory( jQuery );
38812	}
38813}(function( $ ) {
38814
38815// $.ui might exist from components with no dependencies, e.g., $.ui.position
38816$.ui = $.ui || {};
38817
38818$.extend( $.ui, {
38819	version: "1.11.2",
38820
38821	keyCode: {
38822		BACKSPACE: 8,
38823		COMMA: 188,
38824		DELETE: 46,
38825		DOWN: 40,
38826		END: 35,
38827		ENTER: 13,
38828		ESCAPE: 27,
38829		HOME: 36,
38830		LEFT: 37,
38831		PAGE_DOWN: 34,
38832		PAGE_UP: 33,
38833		PERIOD: 190,
38834		RIGHT: 39,
38835		SPACE: 32,
38836		TAB: 9,
38837		UP: 38
38838	}
38839});
38840
38841// plugins
38842$.fn.extend({
38843	scrollParent: function( includeHidden ) {
38844		var position = this.css( "position" ),
38845			excludeStaticParent = position === "absolute",
38846			overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
38847			scrollParent = this.parents().filter( function() {
38848				var parent = $( this );
38849				if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
38850					return false;
38851				}
38852				return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + parent.css( "overflow-x" ) );
38853			}).eq( 0 );
38854
38855		return position === "fixed" || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent;
38856	},
38857
38858	uniqueId: (function() {
38859		var uuid = 0;
38860
38861		return function() {
38862			return this.each(function() {
38863				if ( !this.id ) {
38864					this.id = "ui-id-" + ( ++uuid );
38865				}
38866			});
38867		};
38868	})(),
38869
38870	removeUniqueId: function() {
38871		return this.each(function() {
38872			if ( /^ui-id-\d+$/.test( this.id ) ) {
38873				$( this ).removeAttr( "id" );
38874			}
38875		});
38876	}
38877});
38878
38879// selectors
38880function focusable( element, isTabIndexNotNaN ) {
38881	var map, mapName, img,
38882		nodeName = element.nodeName.toLowerCase();
38883	if ( "area" === nodeName ) {
38884		map = element.parentNode;
38885		mapName = map.name;
38886		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
38887			return false;
38888		}
38889		img = $( "img[usemap='#" + mapName + "']" )[ 0 ];
38890		return !!img && visible( img );
38891	}
38892	return ( /input|select|textarea|button|object/.test( nodeName ) ?
38893		!element.disabled :
38894		"a" === nodeName ?
38895			element.href || isTabIndexNotNaN :
38896			isTabIndexNotNaN) &&
38897		// the element and all of its ancestors must be visible
38898		visible( element );
38899}
38900
38901function visible( element ) {
38902	return $.expr.filters.visible( element ) &&
38903		!$( element ).parents().addBack().filter(function() {
38904			return $.css( this, "visibility" ) === "hidden";
38905		}).length;
38906}
38907
38908$.extend( $.expr[ ":" ], {
38909	data: $.expr.createPseudo ?
38910		$.expr.createPseudo(function( dataName ) {
38911			return function( elem ) {
38912				return !!$.data( elem, dataName );
38913			};
38914		}) :
38915		// support: jQuery <1.8
38916		function( elem, i, match ) {
38917			return !!$.data( elem, match[ 3 ] );
38918		},
38919
38920	focusable: function( element ) {
38921		return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
38922	},
38923
38924	tabbable: function( element ) {
38925		var tabIndex = $.attr( element, "tabindex" ),
38926			isTabIndexNaN = isNaN( tabIndex );
38927		return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
38928	}
38929});
38930
38931// support: jQuery <1.8
38932if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
38933	$.each( [ "Width", "Height" ], function( i, name ) {
38934		var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
38935			type = name.toLowerCase(),
38936			orig = {
38937				innerWidth: $.fn.innerWidth,
38938				innerHeight: $.fn.innerHeight,
38939				outerWidth: $.fn.outerWidth,
38940				outerHeight: $.fn.outerHeight
38941			};
38942
38943		function reduce( elem, size, border, margin ) {
38944			$.each( side, function() {
38945				size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
38946				if ( border ) {
38947					size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
38948				}
38949				if ( margin ) {
38950					size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
38951				}
38952			});
38953			return size;
38954		}
38955
38956		$.fn[ "inner" + name ] = function( size ) {
38957			if ( size === undefined ) {
38958				return orig[ "inner" + name ].call( this );
38959			}
38960
38961			return this.each(function() {
38962				$( this ).css( type, reduce( this, size ) + "px" );
38963			});
38964		};
38965
38966		$.fn[ "outer" + name] = function( size, margin ) {
38967			if ( typeof size !== "number" ) {
38968				return orig[ "outer" + name ].call( this, size );
38969			}
38970
38971			return this.each(function() {
38972				$( this).css( type, reduce( this, size, true, margin ) + "px" );
38973			});
38974		};
38975	});
38976}
38977
38978// support: jQuery <1.8
38979if ( !$.fn.addBack ) {
38980	$.fn.addBack = function( selector ) {
38981		return this.add( selector == null ?
38982			this.prevObject : this.prevObject.filter( selector )
38983		);
38984	};
38985}
38986
38987// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
38988if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
38989	$.fn.removeData = (function( removeData ) {
38990		return function( key ) {
38991			if ( arguments.length ) {
38992				return removeData.call( this, $.camelCase( key ) );
38993			} else {
38994				return removeData.call( this );
38995			}
38996		};
38997	})( $.fn.removeData );
38998}
38999
39000// deprecated
39001$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
39002
39003$.fn.extend({
39004	focus: (function( orig ) {
39005		return function( delay, fn ) {
39006			return typeof delay === "number" ?
39007				this.each(function() {
39008					var elem = this;
39009					setTimeout(function() {
39010						$( elem ).focus();
39011						if ( fn ) {
39012							fn.call( elem );
39013						}
39014					}, delay );
39015				}) :
39016				orig.apply( this, arguments );
39017		};
39018	})( $.fn.focus ),
39019
39020	disableSelection: (function() {
39021		var eventType = "onselectstart" in document.createElement( "div" ) ?
39022			"selectstart" :
39023			"mousedown";
39024
39025		return function() {
39026			return this.bind( eventType + ".ui-disableSelection", function( event ) {
39027				event.preventDefault();
39028			});
39029		};
39030	})(),
39031
39032	enableSelection: function() {
39033		return this.unbind( ".ui-disableSelection" );
39034	},
39035
39036	zIndex: function( zIndex ) {
39037		if ( zIndex !== undefined ) {
39038			return this.css( "zIndex", zIndex );
39039		}
39040
39041		if ( this.length ) {
39042			var elem = $( this[ 0 ] ), position, value;
39043			while ( elem.length && elem[ 0 ] !== document ) {
39044				// Ignore z-index if position is set to a value where z-index is ignored by the browser
39045				// This makes behavior of this function consistent across browsers
39046				// WebKit always returns auto if the element is positioned
39047				position = elem.css( "position" );
39048				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
39049					// IE returns 0 when zIndex is not specified
39050					// other browsers return a string
39051					// we ignore the case of nested elements with an explicit value of 0
39052					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
39053					value = parseInt( elem.css( "zIndex" ), 10 );
39054					if ( !isNaN( value ) && value !== 0 ) {
39055						return value;
39056					}
39057				}
39058				elem = elem.parent();
39059			}
39060		}
39061
39062		return 0;
39063	}
39064});
39065
39066// $.ui.plugin is deprecated. Use $.widget() extensions instead.
39067$.ui.plugin = {
39068	add: function( module, option, set ) {
39069		var i,
39070			proto = $.ui[ module ].prototype;
39071		for ( i in set ) {
39072			proto.plugins[ i ] = proto.plugins[ i ] || [];
39073			proto.plugins[ i ].push( [ option, set[ i ] ] );
39074		}
39075	},
39076	call: function( instance, name, args, allowDisconnected ) {
39077		var i,
39078			set = instance.plugins[ name ];
39079
39080		if ( !set ) {
39081			return;
39082		}
39083
39084		if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
39085			return;
39086		}
39087
39088		for ( i = 0; i < set.length; i++ ) {
39089			if ( instance.options[ set[ i ][ 0 ] ] ) {
39090				set[ i ][ 1 ].apply( instance.element, args );
39091			}
39092		}
39093	}
39094};
39095
39096}));
39097
39098},
39099'jquery-ui/ui/widget':function(){
39100/*!
39101 * jQuery UI Widget 1.11.2
39102 * http://jqueryui.com
39103 *
39104 * Copyright 2014 jQuery Foundation and other contributors
39105 * Released under the MIT license.
39106 * http://jquery.org/license
39107 *
39108 * http://api.jqueryui.com/jQuery.widget/
39109 */
39110(function( factory ) {
39111	if ( typeof define === "function" && define.amd ) {
39112
39113		// AMD. Register as an anonymous module.
39114		define( [ "jquery" ], factory );
39115	} else {
39116
39117		// Browser globals
39118		factory( jQuery );
39119	}
39120}(function( $ ) {
39121
39122var widget_uuid = 0,
39123	widget_slice = Array.prototype.slice;
39124
39125$.cleanData = (function( orig ) {
39126	return function( elems ) {
39127		var events, elem, i;
39128		for ( i = 0; (elem = elems[i]) != null; i++ ) {
39129			try {
39130
39131				// Only trigger remove when necessary to save time
39132				events = $._data( elem, "events" );
39133				if ( events && events.remove ) {
39134					$( elem ).triggerHandler( "remove" );
39135				}
39136
39137			// http://bugs.jquery.com/ticket/8235
39138			} catch ( e ) {}
39139		}
39140		orig( elems );
39141	};
39142})( $.cleanData );
39143
39144$.widget = function( name, base, prototype ) {
39145	var fullName, existingConstructor, constructor, basePrototype,
39146		// proxiedPrototype allows the provided prototype to remain unmodified
39147		// so that it can be used as a mixin for multiple widgets (#8876)
39148		proxiedPrototype = {},
39149		namespace = name.split( "." )[ 0 ];
39150
39151	name = name.split( "." )[ 1 ];
39152	fullName = namespace + "-" + name;
39153
39154	if ( !prototype ) {
39155		prototype = base;
39156		base = $.Widget;
39157	}
39158
39159	// create selector for plugin
39160	$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
39161		return !!$.data( elem, fullName );
39162	};
39163
39164	$[ namespace ] = $[ namespace ] || {};
39165	existingConstructor = $[ namespace ][ name ];
39166	constructor = $[ namespace ][ name ] = function( options, element ) {
39167		// allow instantiation without "new" keyword
39168		if ( !this._createWidget ) {
39169			return new constructor( options, element );
39170		}
39171
39172		// allow instantiation without initializing for simple inheritance
39173		// must use "new" keyword (the code above always passes args)
39174		if ( arguments.length ) {
39175			this._createWidget( options, element );
39176		}
39177	};
39178	// extend with the existing constructor to carry over any static properties
39179	$.extend( constructor, existingConstructor, {
39180		version: prototype.version,
39181		// copy the object used to create the prototype in case we need to
39182		// redefine the widget later
39183		_proto: $.extend( {}, prototype ),
39184		// track widgets that inherit from this widget in case this widget is
39185		// redefined after a widget inherits from it
39186		_childConstructors: []
39187	});
39188
39189	basePrototype = new base();
39190	// we need to make the options hash a property directly on the new instance
39191	// otherwise we'll modify the options hash on the prototype that we're
39192	// inheriting from
39193	basePrototype.options = $.widget.extend( {}, basePrototype.options );
39194	$.each( prototype, function( prop, value ) {
39195		if ( !$.isFunction( value ) ) {
39196			proxiedPrototype[ prop ] = value;
39197			return;
39198		}
39199		proxiedPrototype[ prop ] = (function() {
39200			var _super = function() {
39201					return base.prototype[ prop ].apply( this, arguments );
39202				},
39203				_superApply = function( args ) {
39204					return base.prototype[ prop ].apply( this, args );
39205				};
39206			return function() {
39207				var __super = this._super,
39208					__superApply = this._superApply,
39209					returnValue;
39210
39211				this._super = _super;
39212				this._superApply = _superApply;
39213
39214				returnValue = value.apply( this, arguments );
39215
39216				this._super = __super;
39217				this._superApply = __superApply;
39218
39219				return returnValue;
39220			};
39221		})();
39222	});
39223	constructor.prototype = $.widget.extend( basePrototype, {
39224		// TODO: remove support for widgetEventPrefix
39225		// always use the name + a colon as the prefix, e.g., draggable:start
39226		// don't prefix for widgets that aren't DOM-based
39227		widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
39228	}, proxiedPrototype, {
39229		constructor: constructor,
39230		namespace: namespace,
39231		widgetName: name,
39232		widgetFullName: fullName
39233	});
39234
39235	// If this widget is being redefined then we need to find all widgets that
39236	// are inheriting from it and redefine all of them so that they inherit from
39237	// the new version of this widget. We're essentially trying to replace one
39238	// level in the prototype chain.
39239	if ( existingConstructor ) {
39240		$.each( existingConstructor._childConstructors, function( i, child ) {
39241			var childPrototype = child.prototype;
39242
39243			// redefine the child widget using the same prototype that was
39244			// originally used, but inherit from the new version of the base
39245			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
39246		});
39247		// remove the list of existing child constructors from the old constructor
39248		// so the old child constructors can be garbage collected
39249		delete existingConstructor._childConstructors;
39250	} else {
39251		base._childConstructors.push( constructor );
39252	}
39253
39254	$.widget.bridge( name, constructor );
39255
39256	return constructor;
39257};
39258
39259$.widget.extend = function( target ) {
39260	var input = widget_slice.call( arguments, 1 ),
39261		inputIndex = 0,
39262		inputLength = input.length,
39263		key,
39264		value;
39265	for ( ; inputIndex < inputLength; inputIndex++ ) {
39266		for ( key in input[ inputIndex ] ) {
39267			value = input[ inputIndex ][ key ];
39268			if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
39269				// Clone objects
39270				if ( $.isPlainObject( value ) ) {
39271					target[ key ] = $.isPlainObject( target[ key ] ) ?
39272						$.widget.extend( {}, target[ key ], value ) :
39273						// Don't extend strings, arrays, etc. with objects
39274						$.widget.extend( {}, value );
39275				// Copy everything else by reference
39276				} else {
39277					target[ key ] = value;
39278				}
39279			}
39280		}
39281	}
39282	return target;
39283};
39284
39285$.widget.bridge = function( name, object ) {
39286	var fullName = object.prototype.widgetFullName || name;
39287	$.fn[ name ] = function( options ) {
39288		var isMethodCall = typeof options === "string",
39289			args = widget_slice.call( arguments, 1 ),
39290			returnValue = this;
39291
39292		// allow multiple hashes to be passed on init
39293		options = !isMethodCall && args.length ?
39294			$.widget.extend.apply( null, [ options ].concat(args) ) :
39295			options;
39296
39297		if ( isMethodCall ) {
39298			this.each(function() {
39299				var methodValue,
39300					instance = $.data( this, fullName );
39301				if ( options === "instance" ) {
39302					returnValue = instance;
39303					return false;
39304				}
39305				if ( !instance ) {
39306					return $.error( "cannot call methods on " + name + " prior to initialization; " +
39307						"attempted to call method '" + options + "'" );
39308				}
39309				if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
39310					return $.error( "no such method '" + options + "' for " + name + " widget instance" );
39311				}
39312				methodValue = instance[ options ].apply( instance, args );
39313				if ( methodValue !== instance && methodValue !== undefined ) {
39314					returnValue = methodValue && methodValue.jquery ?
39315						returnValue.pushStack( methodValue.get() ) :
39316						methodValue;
39317					return false;
39318				}
39319			});
39320		} else {
39321			this.each(function() {
39322				var instance = $.data( this, fullName );
39323				if ( instance ) {
39324					instance.option( options || {} );
39325					if ( instance._init ) {
39326						instance._init();
39327					}
39328				} else {
39329					$.data( this, fullName, new object( options, this ) );
39330				}
39331			});
39332		}
39333
39334		return returnValue;
39335	};
39336};
39337
39338$.Widget = function( /* options, element */ ) {};
39339$.Widget._childConstructors = [];
39340
39341$.Widget.prototype = {
39342	widgetName: "widget",
39343	widgetEventPrefix: "",
39344	defaultElement: "<div>",
39345	options: {
39346		disabled: false,
39347
39348		// callbacks
39349		create: null
39350	},
39351	_createWidget: function( options, element ) {
39352		element = $( element || this.defaultElement || this )[ 0 ];
39353		this.element = $( element );
39354		this.uuid = widget_uuid++;
39355		this.eventNamespace = "." + this.widgetName + this.uuid;
39356
39357		this.bindings = $();
39358		this.hoverable = $();
39359		this.focusable = $();
39360
39361		if ( element !== this ) {
39362			$.data( element, this.widgetFullName, this );
39363			this._on( true, this.element, {
39364				remove: function( event ) {
39365					if ( event.target === element ) {
39366						this.destroy();
39367					}
39368				}
39369			});
39370			this.document = $( element.style ?
39371				// element within the document
39372				element.ownerDocument :
vendor: 7,772 bytes, lines 39373-39640
39373				// element is window or document
39374				element.document || element );
39375			this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
39376		}
39377
39378		this.options = $.widget.extend( {},
39379			this.options,
39380			this._getCreateOptions(),
39381			options );
39382
39383		this._create();
39384		this._trigger( "create", null, this._getCreateEventData() );
39385		this._init();
39386	},
39387	_getCreateOptions: $.noop,
39388	_getCreateEventData: $.noop,
39389	_create: $.noop,
39390	_init: $.noop,
39391
39392	destroy: function() {
39393		this._destroy();
39394		// we can probably remove the unbind calls in 2.0
39395		// all event bindings should go through this._on()
39396		this.element
39397			.unbind( this.eventNamespace )
39398			.removeData( this.widgetFullName )
39399			// support: jquery <1.6.3
39400			// http://bugs.jquery.com/ticket/9413
39401			.removeData( $.camelCase( this.widgetFullName ) );
39402		this.widget()
39403			.unbind( this.eventNamespace )
39404			.removeAttr( "aria-disabled" )
39405			.removeClass(
39406				this.widgetFullName + "-disabled " +
39407				"ui-state-disabled" );
39408
39409		// clean up events and states
39410		this.bindings.unbind( this.eventNamespace );
39411		this.hoverable.removeClass( "ui-state-hover" );
39412		this.focusable.removeClass( "ui-state-focus" );
39413	},
39414	_destroy: $.noop,
39415
39416	widget: function() {
39417		return this.element;
39418	},
39419
39420	option: function( key, value ) {
39421		var options = key,
39422			parts,
39423			curOption,
39424			i;
39425
39426		if ( arguments.length === 0 ) {
39427			// don't return a reference to the internal hash
39428			return $.widget.extend( {}, this.options );
39429		}
39430
39431		if ( typeof key === "string" ) {
39432			// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
39433			options = {};
39434			parts = key.split( "." );
39435			key = parts.shift();
39436			if ( parts.length ) {
39437				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
39438				for ( i = 0; i < parts.length - 1; i++ ) {
39439					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
39440					curOption = curOption[ parts[ i ] ];
39441				}
39442				key = parts.pop();
39443				if ( arguments.length === 1 ) {
39444					return curOption[ key ] === undefined ? null : curOption[ key ];
39445				}
39446				curOption[ key ] = value;
39447			} else {
39448				if ( arguments.length === 1 ) {
39449					return this.options[ key ] === undefined ? null : this.options[ key ];
39450				}
39451				options[ key ] = value;
39452			}
39453		}
39454
39455		this._setOptions( options );
39456
39457		return this;
39458	},
39459	_setOptions: function( options ) {
39460		var key;
39461
39462		for ( key in options ) {
39463			this._setOption( key, options[ key ] );
39464		}
39465
39466		return this;
39467	},
39468	_setOption: function( key, value ) {
39469		this.options[ key ] = value;
39470
39471		if ( key === "disabled" ) {
39472			this.widget()
39473				.toggleClass( this.widgetFullName + "-disabled", !!value );
39474
39475			// If the widget is becoming disabled, then nothing is interactive
39476			if ( value ) {
39477				this.hoverable.removeClass( "ui-state-hover" );
39478				this.focusable.removeClass( "ui-state-focus" );
39479			}
39480		}
39481
39482		return this;
39483	},
39484
39485	enable: function() {
39486		return this._setOptions({ disabled: false });
39487	},
39488	disable: function() {
39489		return this._setOptions({ disabled: true });
39490	},
39491
39492	_on: function( suppressDisabledCheck, element, handlers ) {
39493		var delegateElement,
39494			instance = this;
39495
39496		// no suppressDisabledCheck flag, shuffle arguments
39497		if ( typeof suppressDisabledCheck !== "boolean" ) {
39498			handlers = element;
39499			element = suppressDisabledCheck;
39500			suppressDisabledCheck = false;
39501		}
39502
39503		// no element argument, shuffle and use this.element
39504		if ( !handlers ) {
39505			handlers = element;
39506			element = this.element;
39507			delegateElement = this.widget();
39508		} else {
39509			element = delegateElement = $( element );
39510			this.bindings = this.bindings.add( element );
39511		}
39512
39513		$.each( handlers, function( event, handler ) {
39514			function handlerProxy() {
39515				// allow widgets to customize the disabled handling
39516				// - disabled as an array instead of boolean
39517				// - disabled class as method for disabling individual parts
39518				if ( !suppressDisabledCheck &&
39519						( instance.options.disabled === true ||
39520							$( this ).hasClass( "ui-state-disabled" ) ) ) {
39521					return;
39522				}
39523				return ( typeof handler === "string" ? instance[ handler ] : handler )
39524					.apply( instance, arguments );
39525			}
39526
39527			// copy the guid so direct unbinding works
39528			if ( typeof handler !== "string" ) {
39529				handlerProxy.guid = handler.guid =
39530					handler.guid || handlerProxy.guid || $.guid++;
39531			}
39532
39533			var match = event.match( /^([\w:-]*)\s*(.*)$/ ),
39534				eventName = match[1] + instance.eventNamespace,
39535				selector = match[2];
39536			if ( selector ) {
39537				delegateElement.delegate( selector, eventName, handlerProxy );
39538			} else {
39539				element.bind( eventName, handlerProxy );
39540			}
39541		});
39542	},
39543
39544	_off: function( element, eventName ) {
39545		eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) +
39546			this.eventNamespace;
39547		element.unbind( eventName ).undelegate( eventName );
39548
39549		// Clear the stack to avoid memory leaks (#10056)
39550		this.bindings = $( this.bindings.not( element ).get() );
39551		this.focusable = $( this.focusable.not( element ).get() );
39552		this.hoverable = $( this.hoverable.not( element ).get() );
39553	},
39554
39555	_delay: function( handler, delay ) {
39556		function handlerProxy() {
39557			return ( typeof handler === "string" ? instance[ handler ] : handler )
39558				.apply( instance, arguments );
39559		}
39560		var instance = this;
39561		return setTimeout( handlerProxy, delay || 0 );
39562	},
39563
39564	_hoverable: function( element ) {
39565		this.hoverable = this.hoverable.add( element );
39566		this._on( element, {
39567			mouseenter: function( event ) {
39568				$( event.currentTarget ).addClass( "ui-state-hover" );
39569			},
39570			mouseleave: function( event ) {
39571				$( event.currentTarget ).removeClass( "ui-state-hover" );
39572			}
39573		});
39574	},
39575
39576	_focusable: function( element ) {
39577		this.focusable = this.focusable.add( element );
39578		this._on( element, {
39579			focusin: function( event ) {
39580				$( event.currentTarget ).addClass( "ui-state-focus" );
39581			},
39582			focusout: function( event ) {
39583				$( event.currentTarget ).removeClass( "ui-state-focus" );
39584			}
39585		});
39586	},
39587
39588	_trigger: function( type, event, data ) {
39589		var prop, orig,
39590			callback = this.options[ type ];
39591
39592		data = data || {};
39593		event = $.Event( event );
39594		event.type = ( type === this.widgetEventPrefix ?
39595			type :
39596			this.widgetEventPrefix + type ).toLowerCase();
39597		// the original event may come from any element
39598		// so we need to reset the target on the new event
39599		event.target = this.element[ 0 ];
39600
39601		// copy original event properties over to the new event
39602		orig = event.originalEvent;
39603		if ( orig ) {
39604			for ( prop in orig ) {
39605				if ( !( prop in event ) ) {
39606					event[ prop ] = orig[ prop ];
39607				}
39608			}
39609		}
39610
39611		this.element.trigger( event, data );
39612		return !( $.isFunction( callback ) &&
39613			callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
39614			event.isDefaultPrevented() );
39615	}
39616};
39617
39618$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
39619	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
39620		if ( typeof options === "string" ) {
39621			options = { effect: options };
39622		}
39623		var hasOptions,
39624			effectName = !options ?
39625				method :
39626				options === true || typeof options === "number" ?
39627					defaultEffect :
39628					options.effect || defaultEffect;
39629		options = options || {};
39630		if ( typeof options === "number" ) {
39631			options = { duration: options };
39632		}
39633		hasOptions = !$.isEmptyObject( options );
39634		options.complete = callback;
39635		if ( options.delay ) {
39636			element.delay( options.delay );
39637		}
39638		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
39639			element[ method ]( options );
39640		} else if ( effectName !== method && element[ effectName ] ) {
39641			element[ effectName ]( options.duration, options.easing, callback );
39642		} else {
39643			element.queue(function( next ) {
39644				$( this )[ method ]();
39645				if ( callback ) {
39646					callback.call( element[ 0 ] );
39647				}
39648				next();
39649			});
39650		}
39651	};
39652});
39653
39654return $.widget;
39655
39656}));
39657
39658},
39659'jquery-ui/ui/button':function(){
39660/*!
39661 * jQuery UI Button 1.11.2
39662 * http://jqueryui.com
39663 *
39664 * Copyright 2014 jQuery Foundation and other contributors
39665 * Released under the MIT license.
39666 * http://jquery.org/license
39667 *
39668 * http://api.jqueryui.com/button/
39669 */
39670(function( factory ) {
39671	if ( typeof define === "function" && define.amd ) {
39672
39673		// AMD. Register as an anonymous module.
39674		define([
39675			"jquery",
39676			"./core",
39677			"./widget"
39678		], factory );
39679	} else {
39680
39681		// Browser globals
39682		factory( jQuery );
39683	}
39684}(function( $ ) {
39685
39686var lastActive,
39687	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
39688	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
39689	formResetHandler = function() {
39690		var form = $( this );
39691		setTimeout(function() {
39692			form.find( ":ui-button" ).button( "refresh" );
39693		}, 1 );
39694	},
39695	radioGroup = function( radio ) {
39696		var name = radio.name,
39697			form = radio.form,
39698			radios = $( [] );
39699		if ( name ) {
39700			name = name.replace( /'/g, "\\'" );
39701			if ( form ) {
39702				radios = $( form ).find( "[name='" + name + "'][type=radio]" );
39703			} else {
39704				radios = $( "[name='" + name + "'][type=radio]", radio.ownerDocument )
39705					.filter(function() {
39706						return !this.form;
39707					});
39708			}
39709		}
39710		return radios;
39711	};
39712
39713$.widget( "ui.button", {
39714	version: "1.11.2",
39715	defaultElement: "<button>",
39716	options: {
39717		disabled: null,
39718		text: true,
39719		label: null,
39720		icons: {
39721			primary: null,
39722			secondary: null
39723		}
39724	},
39725	_create: function() {
39726		this.element.closest( "form" )
39727			.unbind( "reset" + this.eventNamespace )
39728			.bind( "reset" + this.eventNamespace, formResetHandler );
39729
39730		if ( typeof this.options.disabled !== "boolean" ) {
39731			this.options.disabled = !!this.element.prop( "disabled" );
39732		} else {
39733			this.element.prop( "disabled", this.options.disabled );
39734		}
39735
39736		this._determineButtonType();
39737		this.hasTitle = !!this.buttonElement.attr( "title" );
39738
39739		var that = this,
39740			options = this.options,
39741			toggleButton = this.type === "checkbox" || this.type === "radio",
39742			activeClass = !toggleButton ? "ui-state-active" : "";
39743
39744		if ( options.label === null ) {
39745			options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
39746		}
39747
39748		this._hoverable( this.buttonElement );
39749
39750		this.buttonElement
39751			.addClass( baseClasses )
39752			.attr( "role", "button" )
39753			.bind( "mouseenter" + this.eventNamespace, function() {
39754				if ( options.disabled ) {
39755					return;
39756				}
39757				if ( this === lastActive ) {
39758					$( this ).addClass( "ui-state-active" );
39759				}
39760			})
39761			.bind( "mouseleave" + this.eventNamespace, function() {
39762				if ( options.disabled ) {
39763					return;
39764				}
39765				$( this ).removeClass( activeClass );
39766			})
39767			.bind( "click" + this.eventNamespace, function( event ) {
39768				if ( options.disabled ) {
39769					event.preventDefault();
39770					event.stopImmediatePropagation();
39771				}
39772			});
39773
39774		// Can't use _focusable() because the element that receives focus
39775		// and the element that gets the ui-state-focus class are different
39776		this._on({
39777			focus: function() {
39778				this.buttonElement.addClass( "ui-state-focus" );
39779			},
39780			blur: function() {
39781				this.buttonElement.removeClass( "ui-state-focus" );
39782			}
39783		});
39784
39785		if ( toggleButton ) {
39786			this.element.bind( "change" + this.eventNamespace, function() {
39787				that.refresh();
39788			});
39789		}
39790
39791		if ( this.type === "checkbox" ) {
39792			this.buttonElement.bind( "click" + this.eventNamespace, function() {
39793				if ( options.disabled ) {
39794					return false;
39795				}
39796			});
39797		} else if ( this.type === "radio" ) {
39798			this.buttonElement.bind( "click" + this.eventNamespace, function() {
39799				if ( options.disabled ) {
39800					return false;
39801				}
39802				$( this ).addClass( "ui-state-active" );
39803				that.buttonElement.attr( "aria-pressed", "true" );
39804
39805				var radio = that.element[ 0 ];
39806				radioGroup( radio )
39807					.not( radio )
39808					.map(function() {
39809						return $( this ).button( "widget" )[ 0 ];
39810					})
39811					.removeClass( "ui-state-active" )
39812					.attr( "aria-pressed", "false" );
39813			});
39814		} else {
39815			this.buttonElement
39816				.bind( "mousedown" + this.eventNamespace, function() {
39817					if ( options.disabled ) {
39818						return false;
39819					}
39820					$( this ).addClass( "ui-state-active" );
39821					lastActive = this;
39822					that.document.one( "mouseup", function() {
39823						lastActive = null;
39824					});
39825				})
39826				.bind( "mouseup" + this.eventNamespace, function() {
39827					if ( options.disabled ) {
39828						return false;
39829					}
39830					$( this ).removeClass( "ui-state-active" );
39831				})
39832				.bind( "keydown" + this.eventNamespace, function(event) {
39833					if ( options.disabled ) {
39834						return false;
39835					}
39836					if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
39837						$( this ).addClass( "ui-state-active" );
39838					}
39839				})
39840				// see #8559, we bind to blur here in case the button element loses
39841				// focus between keydown and keyup, it would be left in an "active" state
39842				.bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
39843					$( this ).removeClass( "ui-state-active" );
39844				});
39845
39846			if ( this.buttonElement.is("a") ) {
39847				this.buttonElement.keyup(function(event) {
39848					if ( event.keyCode === $.ui.keyCode.SPACE ) {
39849						// TODO pass through original event correctly (just as 2nd argument doesn't work)
39850						$( this ).click();
39851					}
39852				});
39853			}
39854		}
39855
39856		this._setOption( "disabled", options.disabled );
39857		this._resetButton();
39858	},
39859
39860	_determineButtonType: function() {
39861		var ancestor, labelSelector, checked;
39862
39863		if ( this.element.is("[type=checkbox]") ) {
39864			this.type = "checkbox";
39865		} else if ( this.element.is("[type=radio]") ) {
39866			this.type = "radio";
39867		} else if ( this.element.is("input") ) {
39868			this.type = "input";
39869		} else {
39870			this.type = "button";
39871		}
39872
39873		if ( this.type === "checkbox" || this.type === "radio" ) {
39874			// we don't search against the document in case the element
39875			// is disconnected from the DOM
39876			ancestor = this.element.parents().last();
39877			labelSelector = "label[for='" + this.element.attr("id") + "']";
39878			this.buttonElement = ancestor.find( labelSelector );
39879			if ( !this.buttonElement.length ) {
39880				ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
39881				this.buttonElement = ancestor.filter( labelSelector );
39882				if ( !this.buttonElement.length ) {
39883					this.buttonElement = ancestor.find( labelSelector );
39884				}
39885			}
39886			this.element.addClass( "ui-helper-hidden-accessible" );
39887
39888			checked = this.element.is( ":checked" );
39889			if ( checked ) {
39890				this.buttonElement.addClass( "ui-state-active" );
39891			}
39892			this.buttonElement.prop( "aria-pressed", checked );
39893		} else {
39894			this.buttonElement = this.element;
39895		}
39896	},
39897
39898	widget: function() {
39899		return this.buttonElement;
39900	},
39901
39902	_destroy: function() {
39903		this.element
39904			.removeClass( "ui-helper-hidden-accessible" );
39905		this.buttonElement
39906			.removeClass( baseClasses + " ui-state-active " + typeClasses )
39907			.removeAttr( "role" )
39908			.removeAttr( "aria-pressed" )
39909			.html( this.buttonElement.find(".ui-button-text").html() );
39910
39911		if ( !this.hasTitle ) {
39912			this.buttonElement.removeAttr( "title" );
39913		}
39914	},
39915
39916	_setOption: function( key, value ) {
39917		this._super( key, value );
39918		if ( key === "disabled" ) {
39919			this.widget().toggleClass( "ui-state-disabled", !!value );
39920			this.element.prop( "disabled", !!value );
39921			if ( value ) {
39922				if ( this.type === "checkbox" || this.type === "radio" ) {
39923					this.buttonElement.removeClass( "ui-state-focus" );
39924				} else {
39925					this.buttonElement.removeClass( "ui-state-focus ui-state-active" );
39926				}
39927			}
39928			return;
39929		}
39930		this._resetButton();
39931	},
39932
39933	refresh: function() {
39934		//See #8237 & #8828
39935		var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
39936
39937		if ( isDisabled !== this.options.disabled ) {
39938			this._setOption( "disabled", isDisabled );
39939		}
39940		if ( this.type === "radio" ) {
39941			radioGroup( this.element[0] ).each(function() {
39942				if ( $( this ).is( ":checked" ) ) {
39943					$( this ).button( "widget" )
39944						.addClass( "ui-state-active" )
39945						.attr( "aria-pressed", "true" );
39946				} else {
39947					$( this ).button( "widget" )
39948						.removeClass( "ui-state-active" )
39949						.attr( "aria-pressed", "false" );
39950				}
39951			});
39952		} else if ( this.type === "checkbox" ) {
39953			if ( this.element.is( ":checked" ) ) {
39954				this.buttonElement
39955					.addClass( "ui-state-active" )
39956					.attr( "aria-pressed", "true" );
39957			} else {
39958				this.buttonElement
39959					.removeClass( "ui-state-active" )
39960					.attr( "aria-pressed", "false" );
39961			}
39962		}
39963	},
39964
39965	_resetButton: function() {
39966		if ( this.type === "input" ) {
39967			if ( this.options.label ) {
39968				this.element.val( this.options.label );
39969			}
39970			return;
39971		}
39972		var buttonElement = this.buttonElement.removeClass( typeClasses ),
39973			buttonText = $( "<span></span>", this.document[0] )
39974				.addClass( "ui-button-text" )
39975				.html( this.options.label )
39976				.appendTo( buttonElement.empty() )
39977				.text(),
39978			icons = this.options.icons,
39979			multipleIcons = icons.primary && icons.secondary,
39980			buttonClasses = [];
39981
39982		if ( icons.primary || icons.secondary ) {
39983			if ( this.options.text ) {
39984				buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
39985			}
39986
39987			if ( icons.primary ) {
39988				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
39989			}
39990
39991			if ( icons.secondary ) {
39992				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
39993			}
39994
39995			if ( !this.options.text ) {
39996				buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
39997
39998				if ( !this.hasTitle ) {
39999					buttonElement.attr( "title", $.trim( buttonText ) );
40000				}
40001			}
40002		} else {
40003			buttonClasses.push( "ui-button-text-only" );
40004		}
40005		buttonElement.addClass( buttonClasses.join( " " ) );
40006	}
40007});
40008
40009$.widget( "ui.buttonset", {
40010	version: "1.11.2",
40011	options: {
40012		items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
40013	},
40014
40015	_create: function() {
40016		this.element.addClass( "ui-buttonset" );
40017	},
40018
40019	_init: function() {
40020		this.refresh();
40021	},
40022
40023	_setOption: function( key, value ) {
40024		if ( key === "disabled" ) {
40025			this.buttons.button( "option", key, value );
40026		}
40027
40028		this._super( key, value );
40029	},
40030
40031	refresh: function() {
40032		var rtl = this.element.css( "direction" ) === "rtl",
40033			allButtons = this.element.find( this.options.items ),
40034			existingButtons = allButtons.filter( ":ui-button" );
40035
40036		// Initialize new buttons
40037		allButtons.not( ":ui-button" ).button();
40038
40039		// Refresh existing buttons
40040		existingButtons.button( "refresh" );
40041
40042		this.buttons = allButtons
40043			.map(function() {
40044				return $( this ).button( "widget" )[ 0 ];
40045			})
40046				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
40047				.filter( ":first" )
40048					.addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
40049				.end()
40050				.filter( ":last" )
40051					.addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
40052				.end()
40053			.end();
40054	},
40055
40056	_destroy: function() {
40057		this.element.removeClass( "ui-buttonset" );
40058		this.buttons
40059			.map(function() {
40060				return $( this ).button( "widget" )[ 0 ];
40061			})
40062				.removeClass( "ui-corner-left ui-corner-right" )
40063			.end()
40064			.button( "destroy" );
40065	}
40066});
40067
40068return $.ui.button;
40069
40070}));
40071
40072},
40073'jquery-ui/ui/draggable':function(){
40074/*!
40075 * jQuery UI Draggable 1.11.2
40076 * http://jqueryui.com
40077 *
40078 * Copyright 2014 jQuery Foundation and other contributors
40079 * Released under the MIT license.
40080 * http://jquery.org/license
40081 *
40082 * http://api.jqueryui.com/draggable/
40083 */
40084(function( factory ) {
40085	if ( typeof define === "function" && define.amd ) {
40086
40087		// AMD. Register as an anonymous module.
40088		define([
40089			"jquery",
40090			"./core",
40091			"./mouse",
40092			"./widget"
40093		], factory );
40094	} else {
40095
40096		// Browser globals
40097		factory( jQuery );
40098	}
40099}(function( $ ) {
40100
40101$.widget("ui.draggable", $.ui.mouse, {
40102	version: "1.11.2",
40103	widgetEventPrefix: "drag",
40104	options: {
40105		addClasses: true,
40106		appendTo: "parent",
40107		axis: false,
40108		connectToSortable: false,
40109		containment: false,
40110		cursor: "auto",
40111		cursorAt: false,
40112		grid: false,
40113		handle: false,
40114		helper: "original",
40115		iframeFix: false,
40116		opacity: false,
40117		refreshPositions: false,
40118		revert: false,
40119		revertDuration: 500,
40120		scope: "default",
40121		scroll: true,
40122		scrollSensitivity: 20,
40123		scrollSpeed: 20,
40124		snap: false,
40125		snapMode: "both",
40126		snapTolerance: 20,
40127		stack: false,
40128		zIndex: false,
40129
40130		// callbacks
40131		drag: null,
40132		start: null,
40133		stop: null
40134	},
40135	_create: function() {
40136
40137		if ( this.options.helper === "original" ) {
40138			this._setPositionRelative();
40139		}
40140		if (this.options.addClasses){
40141			this.element.addClass("ui-draggable");
40142		}
40143		if (this.options.disabled){
40144			this.element.addClass("ui-draggable-disabled");
40145		}
40146		this._setHandleClassName();
40147
40148		this._mouseInit();
40149	},
40150
40151	_setOption: function( key, value ) {
40152		this._super( key, value );
40153		if ( key === "handle" ) {
40154			this._removeHandleClassName();
40155			this._setHandleClassName();
40156		}
40157	},
40158
40159	_destroy: function() {
40160		if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
40161			this.destroyOnClear = true;
40162			return;
40163		}
40164		this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
40165		this._removeHandleClassName();
40166		this._mouseDestroy();
40167	},
40168
40169	_mouseCapture: function(event) {
40170		var o = this.options;
40171
40172		this._blurActiveElement( event );
40173
40174		// among others, prevent a drag on a resizable-handle
40175		if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
40176			return false;
40177		}
40178
40179		//Quit if we're not on a valid handle
40180		this.handle = this._getHandle(event);
40181		if (!this.handle) {
40182			return false;
40183		}
40184
40185		this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
40186
40187		return true;
40188
40189	},
40190
40191	_blockFrames: function( selector ) {
40192		this.iframeBlocks = this.document.find( selector ).map(function() {
40193			var iframe = $( this );
40194
40195			return $( "<div>" )
40196				.css( "position", "absolute" )
40197				.appendTo( iframe.parent() )
40198				.outerWidth( iframe.outerWidth() )
40199				.outerHeight( iframe.outerHeight() )
40200				.offset( iframe.offset() )[ 0 ];
40201		});
40202	},
40203
40204	_unblockFrames: function() {
40205		if ( this.iframeBlocks ) {
40206			this.iframeBlocks.remove();
40207			delete this.iframeBlocks;
40208		}
40209	},
40210
40211	_blurActiveElement: function( event ) {
40212		var document = this.document[ 0 ];
40213
40214		// Only need to blur if the event occurred on the draggable itself, see #10527
40215		if ( !this.handleElement.is( event.target ) ) {
40216			return;
40217		}
40218
40219		// support: IE9
40220		// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
40221		try {
40222
vendor: 32,647 bytes, lines 40223-41207
40223			// Support: IE9, IE10
40224			// If the <body> is blurred, IE will switch windows, see #9520
40225			if ( document.activeElement && document.activeElement.nodeName.toLowerCase() !== "body" ) {
40226
40227				// Blur any element that currently has focus, see #4261
40228				$( document.activeElement ).blur();
40229			}
40230		} catch ( error ) {}
40231	},
40232
40233	_mouseStart: function(event) {
40234
40235		var o = this.options;
40236
40237		//Create and append the visible helper
40238		this.helper = this._createHelper(event);
40239
40240		this.helper.addClass("ui-draggable-dragging");
40241
40242		//Cache the helper size
40243		this._cacheHelperProportions();
40244
40245		//If ddmanager is used for droppables, set the global draggable
40246		if ($.ui.ddmanager) {
40247			$.ui.ddmanager.current = this;
40248		}
40249
40250		/*
40251		 * - Position generation -
40252		 * This block generates everything position related - it's the core of draggables.
40253		 */
40254
40255		//Cache the margins of the original element
40256		this._cacheMargins();
40257
40258		//Store the helper's css position
40259		this.cssPosition = this.helper.css( "position" );
40260		this.scrollParent = this.helper.scrollParent( true );
40261		this.offsetParent = this.helper.offsetParent();
40262		this.hasFixedAncestor = this.helper.parents().filter(function() {
40263				return $( this ).css( "position" ) === "fixed";
40264			}).length > 0;
40265
40266		//The element's absolute position on the page minus margins
40267		this.positionAbs = this.element.offset();
40268		this._refreshOffsets( event );
40269
40270		//Generate the original position
40271		this.originalPosition = this.position = this._generatePosition( event, false );
40272		this.originalPageX = event.pageX;
40273		this.originalPageY = event.pageY;
40274
40275		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
40276		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
40277
40278		//Set a containment if given in the options
40279		this._setContainment();
40280
40281		//Trigger event + callbacks
40282		if (this._trigger("start", event) === false) {
40283			this._clear();
40284			return false;
40285		}
40286
40287		//Recache the helper size
40288		this._cacheHelperProportions();
40289
40290		//Prepare the droppable offsets
40291		if ($.ui.ddmanager && !o.dropBehaviour) {
40292			$.ui.ddmanager.prepareOffsets(this, event);
40293		}
40294
40295		// Reset helper's right/bottom css if they're set and set explicit width/height instead
40296		// as this prevents resizing of elements with right/bottom set (see #7772)
40297		this._normalizeRightBottom();
40298
40299		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
40300
40301		//If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
40302		if ( $.ui.ddmanager ) {
40303			$.ui.ddmanager.dragStart(this, event);
40304		}
40305
40306		return true;
40307	},
40308
40309	_refreshOffsets: function( event ) {
40310		this.offset = {
40311			top: this.positionAbs.top - this.margins.top,
40312			left: this.positionAbs.left - this.margins.left,
40313			scroll: false,
40314			parent: this._getParentOffset(),
40315			relative: this._getRelativeOffset()
40316		};
40317
40318		this.offset.click = {
40319			left: event.pageX - this.offset.left,
40320			top: event.pageY - this.offset.top
40321		};
40322	},
40323
40324	_mouseDrag: function(event, noPropagation) {
40325		// reset any necessary cached properties (see #5009)
40326		if ( this.hasFixedAncestor ) {
40327			this.offset.parent = this._getParentOffset();
40328		}
40329
40330		//Compute the helpers position
40331		this.position = this._generatePosition( event, true );
40332		this.positionAbs = this._convertPositionTo("absolute");
40333
40334		//Call plugins and callbacks and use the resulting position if something is returned
40335		if (!noPropagation) {
40336			var ui = this._uiHash();
40337			if (this._trigger("drag", event, ui) === false) {
40338				this._mouseUp({});
40339				return false;
40340			}
40341			this.position = ui.position;
40342		}
40343
40344		this.helper[ 0 ].style.left = this.position.left + "px";
40345		this.helper[ 0 ].style.top = this.position.top + "px";
40346
40347		if ($.ui.ddmanager) {
40348			$.ui.ddmanager.drag(this, event);
40349		}
40350
40351		return false;
40352	},
40353
40354	_mouseStop: function(event) {
40355
40356		//If we are using droppables, inform the manager about the drop
40357		var that = this,
40358			dropped = false;
40359		if ($.ui.ddmanager && !this.options.dropBehaviour) {
40360			dropped = $.ui.ddmanager.drop(this, event);
40361		}
40362
40363		//if a drop comes from outside (a sortable)
40364		if (this.dropped) {
40365			dropped = this.dropped;
40366			this.dropped = false;
40367		}
40368
40369		if ((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
40370			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
40371				if (that._trigger("stop", event) !== false) {
40372					that._clear();
40373				}
40374			});
40375		} else {
40376			if (this._trigger("stop", event) !== false) {
40377				this._clear();
40378			}
40379		}
40380
40381		return false;
40382	},
40383
40384	_mouseUp: function( event ) {
40385		this._unblockFrames();
40386
40387		//If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
40388		if ( $.ui.ddmanager ) {
40389			$.ui.ddmanager.dragStop(this, event);
40390		}
40391
40392		// Only need to focus if the event occurred on the draggable itself, see #10527
40393		if ( this.handleElement.is( event.target ) ) {
40394			// The interaction is over; whether or not the click resulted in a drag, focus the element
40395			this.element.focus();
40396		}
40397
40398		return $.ui.mouse.prototype._mouseUp.call(this, event);
40399	},
40400
40401	cancel: function() {
40402
40403		if (this.helper.is(".ui-draggable-dragging")) {
40404			this._mouseUp({});
40405		} else {
40406			this._clear();
40407		}
40408
40409		return this;
40410
40411	},
40412
40413	_getHandle: function(event) {
40414		return this.options.handle ?
40415			!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
40416			true;
40417	},
40418
40419	_setHandleClassName: function() {
40420		this.handleElement = this.options.handle ?
40421			this.element.find( this.options.handle ) : this.element;
40422		this.handleElement.addClass( "ui-draggable-handle" );
40423	},
40424
40425	_removeHandleClassName: function() {
40426		this.handleElement.removeClass( "ui-draggable-handle" );
40427	},
40428
40429	_createHelper: function(event) {
40430
40431		var o = this.options,
40432			helperIsFunction = $.isFunction( o.helper ),
40433			helper = helperIsFunction ?
40434				$( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
40435				( o.helper === "clone" ?
40436					this.element.clone().removeAttr( "id" ) :
40437					this.element );
40438
40439		if (!helper.parents("body").length) {
40440			helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
40441		}
40442
40443		// http://bugs.jqueryui.com/ticket/9446
40444		// a helper function can return the original element
40445		// which wouldn't have been set to relative in _create
40446		if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
40447			this._setPositionRelative();
40448		}
40449
40450		if (helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
40451			helper.css("position", "absolute");
40452		}
40453
40454		return helper;
40455
40456	},
40457
40458	_setPositionRelative: function() {
40459		if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
40460			this.element[ 0 ].style.position = "relative";
40461		}
40462	},
40463
40464	_adjustOffsetFromHelper: function(obj) {
40465		if (typeof obj === "string") {
40466			obj = obj.split(" ");
40467		}
40468		if ($.isArray(obj)) {
40469			obj = { left: +obj[0], top: +obj[1] || 0 };
40470		}
40471		if ("left" in obj) {
40472			this.offset.click.left = obj.left + this.margins.left;
40473		}
40474		if ("right" in obj) {
40475			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
40476		}
40477		if ("top" in obj) {
40478			this.offset.click.top = obj.top + this.margins.top;
40479		}
40480		if ("bottom" in obj) {
40481			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
40482		}
40483	},
40484
40485	_isRootNode: function( element ) {
40486		return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
40487	},
40488
40489	_getParentOffset: function() {
40490
40491		//Get the offsetParent and cache its position
40492		var po = this.offsetParent.offset(),
40493			document = this.document[ 0 ];
40494
40495		// This is a special case where we need to modify a offset calculated on start, since the following happened:
40496		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
40497		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
40498		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
40499		if (this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
40500			po.left += this.scrollParent.scrollLeft();
40501			po.top += this.scrollParent.scrollTop();
40502		}
40503
40504		if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
40505			po = { top: 0, left: 0 };
40506		}
40507
40508		return {
40509			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0),
40510			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0)
40511		};
40512
40513	},
40514
40515	_getRelativeOffset: function() {
40516		if ( this.cssPosition !== "relative" ) {
40517			return { top: 0, left: 0 };
40518		}
40519
40520		var p = this.element.position(),
40521			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
40522
40523		return {
40524			top: p.top - ( parseInt(this.helper.css( "top" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
40525			left: p.left - ( parseInt(this.helper.css( "left" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
40526		};
40527
40528	},
40529
40530	_cacheMargins: function() {
40531		this.margins = {
40532			left: (parseInt(this.element.css("marginLeft"), 10) || 0),
40533			top: (parseInt(this.element.css("marginTop"), 10) || 0),
40534			right: (parseInt(this.element.css("marginRight"), 10) || 0),
40535			bottom: (parseInt(this.element.css("marginBottom"), 10) || 0)
40536		};
40537	},
40538
40539	_cacheHelperProportions: function() {
40540		this.helperProportions = {
40541			width: this.helper.outerWidth(),
40542			height: this.helper.outerHeight()
40543		};
40544	},
40545
40546	_setContainment: function() {
40547
40548		var isUserScrollable, c, ce,
40549			o = this.options,
40550			document = this.document[ 0 ];
40551
40552		this.relativeContainer = null;
40553
40554		if ( !o.containment ) {
40555			this.containment = null;
40556			return;
40557		}
40558
40559		if ( o.containment === "window" ) {
40560			this.containment = [
40561				$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
40562				$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
40563				$( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left,
40564				$( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
40565			];
40566			return;
40567		}
40568
40569		if ( o.containment === "document") {
40570			this.containment = [
40571				0,
40572				0,
40573				$( document ).width() - this.helperProportions.width - this.margins.left,
40574				( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top
40575			];
40576			return;
40577		}
40578
40579		if ( o.containment.constructor === Array ) {
40580			this.containment = o.containment;
40581			return;
40582		}
40583
40584		if ( o.containment === "parent" ) {
40585			o.containment = this.helper[ 0 ].parentNode;
40586		}
40587
40588		c = $( o.containment );
40589		ce = c[ 0 ];
40590
40591		if ( !ce ) {
40592			return;
40593		}
40594
40595		isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
40596
40597		this.containment = [
40598			( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
40599			( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
40600			( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
40601				( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
40602				( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
40603				this.helperProportions.width -
40604				this.margins.left -
40605				this.margins.right,
40606			( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
40607				( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
40608				( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
40609				this.helperProportions.height -
40610				this.margins.top -
40611				this.margins.bottom
40612		];
40613		this.relativeContainer = c;
40614	},
40615
40616	_convertPositionTo: function(d, pos) {
40617
40618		if (!pos) {
40619			pos = this.position;
40620		}
40621
40622		var mod = d === "absolute" ? 1 : -1,
40623			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
40624
40625		return {
40626			top: (
40627				pos.top	+																// The absolute mouse position
40628				this.offset.relative.top * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
40629				this.offset.parent.top * mod -										// The offsetParent's offset without borders (offset + border)
40630				( ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod)
40631			),
40632			left: (
40633				pos.left +																// The absolute mouse position
40634				this.offset.relative.left * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
40635				this.offset.parent.left * mod	-										// The offsetParent's offset without borders (offset + border)
40636				( ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod)
40637			)
40638		};
40639
40640	},
40641
40642	_generatePosition: function( event, constrainPosition ) {
40643
40644		var containment, co, top, left,
40645			o = this.options,
40646			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
40647			pageX = event.pageX,
40648			pageY = event.pageY;
40649
40650		// Cache the scroll
40651		if ( !scrollIsRootNode || !this.offset.scroll ) {
40652			this.offset.scroll = {
40653				top: this.scrollParent.scrollTop(),
40654				left: this.scrollParent.scrollLeft()
40655			};
40656		}
40657
40658		/*
40659		 * - Position constraining -
40660		 * Constrain the position to a mix of grid, containment.
40661		 */
40662
40663		// If we are not dragging yet, we won't check for options
40664		if ( constrainPosition ) {
40665			if ( this.containment ) {
40666				if ( this.relativeContainer ){
40667					co = this.relativeContainer.offset();
40668					containment = [
40669						this.containment[ 0 ] + co.left,
40670						this.containment[ 1 ] + co.top,
40671						this.containment[ 2 ] + co.left,
40672						this.containment[ 3 ] + co.top
40673					];
40674				} else {
40675					containment = this.containment;
40676				}
40677
40678				if (event.pageX - this.offset.click.left < containment[0]) {
40679					pageX = containment[0] + this.offset.click.left;
40680				}
40681				if (event.pageY - this.offset.click.top < containment[1]) {
40682					pageY = containment[1] + this.offset.click.top;
40683				}
40684				if (event.pageX - this.offset.click.left > containment[2]) {
40685					pageX = containment[2] + this.offset.click.left;
40686				}
40687				if (event.pageY - this.offset.click.top > containment[3]) {
40688					pageY = containment[3] + this.offset.click.top;
40689				}
40690			}
40691
40692			if (o.grid) {
40693				//Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
40694				top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
40695				pageY = containment ? ((top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3]) ? top : ((top - this.offset.click.top >= containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
40696
40697				left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
40698				pageX = containment ? ((left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2]) ? left : ((left - this.offset.click.left >= containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
40699			}
40700
40701			if ( o.axis === "y" ) {
40702				pageX = this.originalPageX;
40703			}
40704
40705			if ( o.axis === "x" ) {
40706				pageY = this.originalPageY;
40707			}
40708		}
40709
40710		return {
40711			top: (
40712				pageY -																	// The absolute mouse position
40713				this.offset.click.top	-												// Click offset (relative to the element)
40714				this.offset.relative.top -												// Only for relative positioned nodes: Relative offset from element to offset parent
40715				this.offset.parent.top +												// The offsetParent's offset without borders (offset + border)
40716				( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
40717			),
40718			left: (
40719				pageX -																	// The absolute mouse position
40720				this.offset.click.left -												// Click offset (relative to the element)
40721				this.offset.relative.left -												// Only for relative positioned nodes: Relative offset from element to offset parent
40722				this.offset.parent.left +												// The offsetParent's offset without borders (offset + border)
40723				( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
40724			)
40725		};
40726
40727	},
40728
40729	_clear: function() {
40730		this.helper.removeClass("ui-draggable-dragging");
40731		if (this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
40732			this.helper.remove();
40733		}
40734		this.helper = null;
40735		this.cancelHelperRemoval = false;
40736		if ( this.destroyOnClear ) {
40737			this.destroy();
40738		}
40739	},
40740
40741	_normalizeRightBottom: function() {
40742		if ( this.options.axis !== "y" && this.helper.css( "right" ) !== "auto" ) {
40743			this.helper.width( this.helper.width() );
40744			this.helper.css( "right", "auto" );
40745		}
40746		if ( this.options.axis !== "x" && this.helper.css( "bottom" ) !== "auto" ) {
40747			this.helper.height( this.helper.height() );
40748			this.helper.css( "bottom", "auto" );
40749		}
40750	},
40751
40752	// From now on bulk stuff - mainly helpers
40753
40754	_trigger: function( type, event, ui ) {
40755		ui = ui || this._uiHash();
40756		$.ui.plugin.call( this, type, [ event, ui, this ], true );
40757
40758		// Absolute position and offset (see #6884 ) have to be recalculated after plugins
40759		if ( /^(drag|start|stop)/.test( type ) ) {
40760			this.positionAbs = this._convertPositionTo( "absolute" );
40761			ui.offset = this.positionAbs;
40762		}
40763		return $.Widget.prototype._trigger.call( this, type, event, ui );
40764	},
40765
40766	plugins: {},
40767
40768	_uiHash: function() {
40769		return {
40770			helper: this.helper,
40771			position: this.position,
40772			originalPosition: this.originalPosition,
40773			offset: this.positionAbs
40774		};
40775	}
40776
40777});
40778
40779$.ui.plugin.add( "draggable", "connectToSortable", {
40780	start: function( event, ui, draggable ) {
40781		var uiSortable = $.extend( {}, ui, {
40782			item: draggable.element
40783		});
40784
40785		draggable.sortables = [];
40786		$( draggable.options.connectToSortable ).each(function() {
40787			var sortable = $( this ).sortable( "instance" );
40788
40789			if ( sortable && !sortable.options.disabled ) {
40790				draggable.sortables.push( sortable );
40791
40792				// refreshPositions is called at drag start to refresh the containerCache
40793				// which is used in drag. This ensures it's initialized and synchronized
40794				// with any changes that might have happened on the page since initialization.
40795				sortable.refreshPositions();
40796				sortable._trigger("activate", event, uiSortable);
40797			}
40798		});
40799	},
40800	stop: function( event, ui, draggable ) {
40801		var uiSortable = $.extend( {}, ui, {
40802			item: draggable.element
40803		});
40804
40805		draggable.cancelHelperRemoval = false;
40806
40807		$.each( draggable.sortables, function() {
40808			var sortable = this;
40809
40810			if ( sortable.isOver ) {
40811				sortable.isOver = 0;
40812
40813				// Allow this sortable to handle removing the helper
40814				draggable.cancelHelperRemoval = true;
40815				sortable.cancelHelperRemoval = false;
40816
40817				// Use _storedCSS To restore properties in the sortable,
40818				// as this also handles revert (#9675) since the draggable
40819				// may have modified them in unexpected ways (#8809)
40820				sortable._storedCSS = {
40821					position: sortable.placeholder.css( "position" ),
40822					top: sortable.placeholder.css( "top" ),
40823					left: sortable.placeholder.css( "left" )
40824				};
40825
40826				sortable._mouseStop(event);
40827
40828				// Once drag has ended, the sortable should return to using
40829				// its original helper, not the shared helper from draggable
40830				sortable.options.helper = sortable.options._helper;
40831			} else {
40832				// Prevent this Sortable from removing the helper.
40833				// However, don't set the draggable to remove the helper
40834				// either as another connected Sortable may yet handle the removal.
40835				sortable.cancelHelperRemoval = true;
40836
40837				sortable._trigger( "deactivate", event, uiSortable );
40838			}
40839		});
40840	},
40841	drag: function( event, ui, draggable ) {
40842		$.each( draggable.sortables, function() {
40843			var innermostIntersecting = false,
40844				sortable = this;
40845
40846			// Copy over variables that sortable's _intersectsWith uses
40847			sortable.positionAbs = draggable.positionAbs;
40848			sortable.helperProportions = draggable.helperProportions;
40849			sortable.offset.click = draggable.offset.click;
40850
40851			if ( sortable._intersectsWith( sortable.containerCache ) ) {
40852				innermostIntersecting = true;
40853
40854				$.each( draggable.sortables, function() {
40855					// Copy over variables that sortable's _intersectsWith uses
40856					this.positionAbs = draggable.positionAbs;
40857					this.helperProportions = draggable.helperProportions;
40858					this.offset.click = draggable.offset.click;
40859
40860					if ( this !== sortable &&
40861							this._intersectsWith( this.containerCache ) &&
40862							$.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
40863						innermostIntersecting = false;
40864					}
40865
40866					return innermostIntersecting;
40867				});
40868			}
40869
40870			if ( innermostIntersecting ) {
40871				// If it intersects, we use a little isOver variable and set it once,
40872				// so that the move-in stuff gets fired only once.
40873				if ( !sortable.isOver ) {
40874					sortable.isOver = 1;
40875
40876					sortable.currentItem = ui.helper
40877						.appendTo( sortable.element )
40878						.data( "ui-sortable-item", true );
40879
40880					// Store helper option to later restore it
40881					sortable.options._helper = sortable.options.helper;
40882
40883					sortable.options.helper = function() {
40884						return ui.helper[ 0 ];
40885					};
40886
40887					// Fire the start events of the sortable with our passed browser event,
40888					// and our own helper (so it doesn't create a new one)
40889					event.target = sortable.currentItem[ 0 ];
40890					sortable._mouseCapture( event, true );
40891					sortable._mouseStart( event, true, true );
40892
40893					// Because the browser event is way off the new appended portlet,
40894					// modify necessary variables to reflect the changes
40895					sortable.offset.click.top = draggable.offset.click.top;
40896					sortable.offset.click.left = draggable.offset.click.left;
40897					sortable.offset.parent.left -= draggable.offset.parent.left -
40898						sortable.offset.parent.left;
40899					sortable.offset.parent.top -= draggable.offset.parent.top -
40900						sortable.offset.parent.top;
40901
40902					draggable._trigger( "toSortable", event );
40903
40904					// Inform draggable that the helper is in a valid drop zone,
40905					// used solely in the revert option to handle "valid/invalid".
40906					draggable.dropped = sortable.element;
40907
40908					// Need to refreshPositions of all sortables in the case that
40909					// adding to one sortable changes the location of the other sortables (#9675)
40910					$.each( draggable.sortables, function() {
40911						this.refreshPositions();
40912					});
40913
40914					// hack so receive/update callbacks work (mostly)
40915					draggable.currentItem = draggable.element;
40916					sortable.fromOutside = draggable;
40917				}
40918
40919				if ( sortable.currentItem ) {
40920					sortable._mouseDrag( event );
40921					// Copy the sortable's position because the draggable's can potentially reflect
40922					// a relative position, while sortable is always absolute, which the dragged
40923					// element has now become. (#8809)
40924					ui.position = sortable.position;
40925				}
40926			} else {
40927				// If it doesn't intersect with the sortable, and it intersected before,
40928				// we fake the drag stop of the sortable, but make sure it doesn't remove
40929				// the helper by using cancelHelperRemoval.
40930				if ( sortable.isOver ) {
40931
40932					sortable.isOver = 0;
40933					sortable.cancelHelperRemoval = true;
40934
40935					// Calling sortable's mouseStop would trigger a revert,
40936					// so revert must be temporarily false until after mouseStop is called.
40937					sortable.options._revert = sortable.options.revert;
40938					sortable.options.revert = false;
40939
40940					sortable._trigger( "out", event, sortable._uiHash( sortable ) );
40941					sortable._mouseStop( event, true );
40942
40943					// restore sortable behaviors that were modfied
40944					// when the draggable entered the sortable area (#9481)
40945					sortable.options.revert = sortable.options._revert;
40946					sortable.options.helper = sortable.options._helper;
40947
40948					if ( sortable.placeholder ) {
40949						sortable.placeholder.remove();
40950					}
40951
40952					// Recalculate the draggable's offset considering the sortable
40953					// may have modified them in unexpected ways (#8809)
40954					draggable._refreshOffsets( event );
40955					ui.position = draggable._generatePosition( event, true );
40956
40957					draggable._trigger( "fromSortable", event );
40958
40959					// Inform draggable that the helper is no longer in a valid drop zone
40960					draggable.dropped = false;
40961
40962					// Need to refreshPositions of all sortables just in case removing
40963					// from one sortable changes the location of other sortables (#9675)
40964					$.each( draggable.sortables, function() {
40965						this.refreshPositions();
40966					});
40967				}
40968			}
40969		});
40970	}
40971});
40972
40973$.ui.plugin.add("draggable", "cursor", {
40974	start: function( event, ui, instance ) {
40975		var t = $( "body" ),
40976			o = instance.options;
40977
40978		if (t.css("cursor")) {
40979			o._cursor = t.css("cursor");
40980		}
40981		t.css("cursor", o.cursor);
40982	},
40983	stop: function( event, ui, instance ) {
40984		var o = instance.options;
40985		if (o._cursor) {
40986			$("body").css("cursor", o._cursor);
40987		}
40988	}
40989});
40990
40991$.ui.plugin.add("draggable", "opacity", {
40992	start: function( event, ui, instance ) {
40993		var t = $( ui.helper ),
40994			o = instance.options;
40995		if (t.css("opacity")) {
40996			o._opacity = t.css("opacity");
40997		}
40998		t.css("opacity", o.opacity);
40999	},
41000	stop: function( event, ui, instance ) {
41001		var o = instance.options;
41002		if (o._opacity) {
41003			$(ui.helper).css("opacity", o._opacity);
41004		}
41005	}
41006});
41007
41008$.ui.plugin.add("draggable", "scroll", {
41009	start: function( event, ui, i ) {
41010		if ( !i.scrollParentNotHidden ) {
41011			i.scrollParentNotHidden = i.helper.scrollParent( false );
41012		}
41013
41014		if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] && i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
41015			i.overflowOffset = i.scrollParentNotHidden.offset();
41016		}
41017	},
41018	drag: function( event, ui, i  ) {
41019
41020		var o = i.options,
41021			scrolled = false,
41022			scrollParent = i.scrollParentNotHidden[ 0 ],
41023			document = i.document[ 0 ];
41024
41025		if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
41026			if ( !o.axis || o.axis !== "x" ) {
41027				if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY < o.scrollSensitivity ) {
41028					scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
41029				} else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
41030					scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
41031				}
41032			}
41033
41034			if ( !o.axis || o.axis !== "y" ) {
41035				if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX < o.scrollSensitivity ) {
41036					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
41037				} else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
41038					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
41039				}
41040			}
41041
41042		} else {
41043
41044			if (!o.axis || o.axis !== "x") {
41045				if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
41046					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
41047				} else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
41048					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
41049				}
41050			}
41051
41052			if (!o.axis || o.axis !== "y") {
41053				if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
41054					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
41055				} else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
41056					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
41057				}
41058			}
41059
41060		}
41061
41062		if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
41063			$.ui.ddmanager.prepareOffsets(i, event);
41064		}
41065
41066	}
41067});
41068
41069$.ui.plugin.add("draggable", "snap", {
41070	start: function( event, ui, i ) {
41071
41072		var o = i.options;
41073
41074		i.snapElements = [];
41075
41076		$(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
41077			var $t = $(this),
41078				$o = $t.offset();
41079			if (this !== i.element[0]) {
41080				i.snapElements.push({
41081					item: this,
41082					width: $t.outerWidth(), height: $t.outerHeight(),
41083					top: $o.top, left: $o.left
41084				});
41085			}
41086		});
41087
41088	},
41089	drag: function( event, ui, inst ) {
41090
41091		var ts, bs, ls, rs, l, r, t, b, i, first,
41092			o = inst.options,
41093			d = o.snapTolerance,
41094			x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
41095			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
41096
41097		for (i = inst.snapElements.length - 1; i >= 0; i--){
41098
41099			l = inst.snapElements[i].left - inst.margins.left;
41100			r = l + inst.snapElements[i].width;
41101			t = inst.snapElements[i].top - inst.margins.top;
41102			b = t + inst.snapElements[i].height;
41103
41104			if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) {
41105				if (inst.snapElements[i].snapping) {
41106					(inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
41107				}
41108				inst.snapElements[i].snapping = false;
41109				continue;
41110			}
41111
41112			if (o.snapMode !== "inner") {
41113				ts = Math.abs(t - y2) <= d;
41114				bs = Math.abs(b - y1) <= d;
41115				ls = Math.abs(l - x2) <= d;
41116				rs = Math.abs(r - x1) <= d;
41117				if (ts) {
41118					ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top;
41119				}
41120				if (bs) {
41121					ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top;
41122				}
41123				if (ls) {
41124					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left;
41125				}
41126				if (rs) {
41127					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left;
41128				}
41129			}
41130
41131			first = (ts || bs || ls || rs);
41132
41133			if (o.snapMode !== "outer") {
41134				ts = Math.abs(t - y1) <= d;
41135				bs = Math.abs(b - y2) <= d;
41136				ls = Math.abs(l - x1) <= d;
41137				rs = Math.abs(r - x2) <= d;
41138				if (ts) {
41139					ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top;
41140				}
41141				if (bs) {
41142					ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top;
41143				}
41144				if (ls) {
41145					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left;
41146				}
41147				if (rs) {
41148					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left;
41149				}
41150			}
41151
41152			if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
41153				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
41154			}
41155			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
41156
41157		}
41158
41159	}
41160});
41161
41162$.ui.plugin.add("draggable", "stack", {
41163	start: function( event, ui, instance ) {
41164		var min,
41165			o = instance.options,
41166			group = $.makeArray($(o.stack)).sort(function(a, b) {
41167				return (parseInt($(a).css("zIndex"), 10) || 0) - (parseInt($(b).css("zIndex"), 10) || 0);
41168			});
41169
41170		if (!group.length) { return; }
41171
41172		min = parseInt($(group[0]).css("zIndex"), 10) || 0;
41173		$(group).each(function(i) {
41174			$(this).css("zIndex", min + i);
41175		});
41176		this.css("zIndex", (min + group.length));
41177	}
41178});
41179
41180$.ui.plugin.add("draggable", "zIndex", {
41181	start: function( event, ui, instance ) {
41182		var t = $( ui.helper ),
41183			o = instance.options;
41184
41185		if (t.css("zIndex")) {
41186			o._zIndex = t.css("zIndex");
41187		}
41188		t.css("zIndex", o.zIndex);
41189	},
41190	stop: function( event, ui, instance ) {
41191		var o = instance.options;
41192
41193		if (o._zIndex) {
41194			$(ui.helper).css("zIndex", o._zIndex);
41195		}
41196	}
41197});
41198
41199return $.ui.draggable;
41200
41201}));
41202
41203},
41204'jquery-ui/ui/mouse':function(){
41205/*!
41206 * jQuery UI Mouse 1.11.2
41207 * http://jqueryui.com
vendor: 3,606 bytes, lines 41208-41334
41208 *
41209 * Copyright 2014 jQuery Foundation and other contributors
41210 * Released under the MIT license.
41211 * http://jquery.org/license
41212 *
41213 * http://api.jqueryui.com/mouse/
41214 */
41215(function( factory ) {
41216	if ( typeof define === "function" && define.amd ) {
41217
41218		// AMD. Register as an anonymous module.
41219		define([
41220			"jquery",
41221			"./widget"
41222		], factory );
41223	} else {
41224
41225		// Browser globals
41226		factory( jQuery );
41227	}
41228}(function( $ ) {
41229
41230var mouseHandled = false;
41231$( document ).mouseup( function() {
41232	mouseHandled = false;
41233});
41234
41235return $.widget("ui.mouse", {
41236	version: "1.11.2",
41237	options: {
41238		cancel: "input,textarea,button,select,option",
41239		distance: 1,
41240		delay: 0
41241	},
41242	_mouseInit: function() {
41243		var that = this;
41244
41245		this.element
41246			.bind("mousedown." + this.widgetName, function(event) {
41247				return that._mouseDown(event);
41248			})
41249			.bind("click." + this.widgetName, function(event) {
41250				if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
41251					$.removeData(event.target, that.widgetName + ".preventClickEvent");
41252					event.stopImmediatePropagation();
41253					return false;
41254				}
41255			});
41256
41257		this.started = false;
41258	},
41259
41260	// TODO: make sure destroying one instance of mouse doesn't mess with
41261	// other instances of mouse
41262	_mouseDestroy: function() {
41263		this.element.unbind("." + this.widgetName);
41264		if ( this._mouseMoveDelegate ) {
41265			this.document
41266				.unbind("mousemove." + this.widgetName, this._mouseMoveDelegate)
41267				.unbind("mouseup." + this.widgetName, this._mouseUpDelegate);
41268		}
41269	},
41270
41271	_mouseDown: function(event) {
41272		// don't let more than one widget handle mouseStart
41273		if ( mouseHandled ) {
41274			return;
41275		}
41276
41277		this._mouseMoved = false;
41278
41279		// we may have missed mouseup (out of window)
41280		(this._mouseStarted && this._mouseUp(event));
41281
41282		this._mouseDownEvent = event;
41283
41284		var that = this,
41285			btnIsLeft = (event.which === 1),
41286			// event.target.nodeName works around a bug in IE 8 with
41287			// disabled inputs (#7620)
41288			elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
41289		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
41290			return true;
41291		}
41292
41293		this.mouseDelayMet = !this.options.delay;
41294		if (!this.mouseDelayMet) {
41295			this._mouseDelayTimer = setTimeout(function() {
41296				that.mouseDelayMet = true;
41297			}, this.options.delay);
41298		}
41299
41300		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
41301			this._mouseStarted = (this._mouseStart(event) !== false);
41302			if (!this._mouseStarted) {
41303				event.preventDefault();
41304				return true;
41305			}
41306		}
41307
41308		// Click event may never have fired (Gecko & Opera)
41309		if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
41310			$.removeData(event.target, this.widgetName + ".preventClickEvent");
41311		}
41312
41313		// these delegates are required to keep context
41314		this._mouseMoveDelegate = function(event) {
41315			return that._mouseMove(event);
41316		};
41317		this._mouseUpDelegate = function(event) {
41318			return that._mouseUp(event);
41319		};
41320
41321		this.document
41322			.bind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
41323			.bind( "mouseup." + this.widgetName, this._mouseUpDelegate );
41324
41325		event.preventDefault();
41326
41327		mouseHandled = true;
41328		return true;
41329	},
41330
41331	_mouseMove: function(event) {
41332		// Only check for mouseups outside the document if you've moved inside the document
41333		// at least once. This prevents the firing of mouseup in the case of IE<9, which will
41334		// fire a mousemove event if content is placed under the cursor. See #7778
41335		// Support: IE <9
41336		if ( this._mouseMoved ) {
41337			// IE mouseup check - mouseup happened when mouse was out of window
41338			if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
41339				return this._mouseUp(event);
41340
41341			// Iframe mouseup check - mouseup occurred in another document
41342			} else if ( !event.which ) {
41343				return this._mouseUp( event );
41344			}
41345		}
41346
41347		if ( event.which || event.button ) {
41348			this._mouseMoved = true;
41349		}
41350
41351		if (this._mouseStarted) {
41352			this._mouseDrag(event);
41353			return event.preventDefault();
41354		}
41355
41356		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
41357			this._mouseStarted =
41358				(this._mouseStart(this._mouseDownEvent, event) !== false);
41359			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
41360		}
41361
41362		return !this._mouseStarted;
41363	},
41364
41365	_mouseUp: function(event) {
41366		this.document
41367			.unbind( "mousemove." + this.widgetName, this._mouseMoveDelegate )
41368			.unbind( "mouseup." + this.widgetName, this._mouseUpDelegate );
41369
41370		if (this._mouseStarted) {
41371			this._mouseStarted = false;
41372
41373			if (event.target === this._mouseDownEvent.target) {
41374				$.data(event.target, this.widgetName + ".preventClickEvent", true);
41375			}
41376
41377			this._mouseStop(event);
41378		}
41379
41380		mouseHandled = false;
41381		return false;
41382	},
41383
41384	_mouseDistanceMet: function(event) {
41385		return (Math.max(
41386				Math.abs(this._mouseDownEvent.pageX - event.pageX),
41387				Math.abs(this._mouseDownEvent.pageY - event.pageY)
41388			) >= this.options.distance
41389		);
41390	},
41391
41392	_mouseDelayMet: function(/* event */) {
41393		return this.mouseDelayMet;
41394	},
41395
41396	// These are placeholder methods, to be overriden by extending plugin
41397	_mouseStart: function(/* event */) {},
41398	_mouseDrag: function(/* event */) {},
41399	_mouseStop: function(/* event */) {},
41400	_mouseCapture: function(/* event */) { return true; }
41401});
41402
41403}));
41404
41405},
41406'jquery-ui/ui/position':function(){
41407/*!
41408 * jQuery UI Position 1.11.2
41409 * http://jqueryui.com
41410 *
41411 * Copyright 2014 jQuery Foundation and other contributors
41412 * Released under the MIT license.
41413 * http://jquery.org/license
41414 *
41415 * http://api.jqueryui.com/position/
41416 */
41417(function( factory ) {
41418	if ( typeof define === "function" && define.amd ) {
41419
41420		// AMD. Register as an anonymous module.
41421		define( [ "jquery" ], factory );
41422	} else {
41423
41424		// Browser globals
41425		factory( jQuery );
41426	}
41427}(function( $ ) {
41428(function() {
41429
41430$.ui = $.ui || {};
41431
41432var cachedScrollbarWidth, supportsOffsetFractions,
41433	max = Math.max,
41434	abs = Math.abs,
41435	round = Math.round,
41436	rhorizontal = /left|center|right/,
41437	rvertical = /top|center|bottom/,
41438	roffset = /[\+\-]\d+(\.[\d]+)?%?/,
41439	rposition = /^\w+/,
41440	rpercent = /%$/,
41441	_position = $.fn.position;
41442
41443function getOffsets( offsets, width, height ) {
41444	return [
41445		parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
41446		parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
41447	];
41448}
41449
41450function parseCss( element, property ) {
41451	return parseInt( $.css( element, property ), 10 ) || 0;
41452}
41453
41454function getDimensions( elem ) {
41455	var raw = elem[0];
41456	if ( raw.nodeType === 9 ) {
41457		return {
41458			width: elem.width(),
41459			height: elem.height(),
41460			offset: { top: 0, left: 0 }
41461		};
41462	}
41463	if ( $.isWindow( raw ) ) {
41464		return {
41465			width: elem.width(),
41466			height: elem.height(),
41467			offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
41468		};
41469	}
41470	if ( raw.preventDefault ) {
41471		return {
41472			width: 0,
41473			height: 0,
41474			offset: { top: raw.pageY, left: raw.pageX }
41475		};
41476	}
41477	return {
41478		width: elem.outerWidth(),
41479		height: elem.outerHeight(),
41480		offset: elem.offset()
41481	};
41482}
41483
41484$.position = {
41485	scrollbarWidth: function() {
41486		if ( cachedScrollbarWidth !== undefined ) {
41487			return cachedScrollbarWidth;
41488		}
41489		var w1, w2,
41490			div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
41491			innerDiv = div.children()[0];
41492
41493		$( "body" ).append( div );
41494		w1 = innerDiv.offsetWidth;
41495		div.css( "overflow", "scroll" );
41496
41497		w2 = innerDiv.offsetWidth;
41498
41499		if ( w1 === w2 ) {
41500			w2 = div[0].clientWidth;
41501		}
41502
41503		div.remove();
41504
41505		return (cachedScrollbarWidth = w1 - w2);
41506	},
41507	getScrollInfo: function( within ) {
41508		var overflowX = within.isWindow || within.isDocument ? "" :
41509				within.element.css( "overflow-x" ),
41510			overflowY = within.isWindow || within.isDocument ? "" :
41511				within.element.css( "overflow-y" ),
41512			hasOverflowX = overflowX === "scroll" ||
41513				( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
41514			hasOverflowY = overflowY === "scroll" ||
41515				( overflowY === "auto" && within.height < within.element[0].scrollHeight );
41516		return {
41517			width: hasOverflowY ? $.position.scrollbarWidth() : 0,
41518			height: hasOverflowX ? $.position.scrollbarWidth() : 0
41519		};
41520	},
41521	getWithinInfo: function( element ) {
41522		var withinElement = $( element || window ),
41523			isWindow = $.isWindow( withinElement[0] ),
41524			isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9;
41525		return {
41526			element: withinElement,
41527			isWindow: isWindow,
41528			isDocument: isDocument,
vendor: 6,607 bytes, lines 41529-41731
41529			offset: withinElement.offset() || { left: 0, top: 0 },
41530			scrollLeft: withinElement.scrollLeft(),
41531			scrollTop: withinElement.scrollTop(),
41532
41533			// support: jQuery 1.6.x
41534			// jQuery 1.6 doesn't support .outerWidth/Height() on documents or windows
41535			width: isWindow || isDocument ? withinElement.width() : withinElement.outerWidth(),
41536			height: isWindow || isDocument ? withinElement.height() : withinElement.outerHeight()
41537		};
41538	}
41539};
41540
41541$.fn.position = function( options ) {
41542	if ( !options || !options.of ) {
41543		return _position.apply( this, arguments );
41544	}
41545
41546	// make a copy, we don't want to modify arguments
41547	options = $.extend( {}, options );
41548
41549	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
41550		target = $( options.of ),
41551		within = $.position.getWithinInfo( options.within ),
41552		scrollInfo = $.position.getScrollInfo( within ),
41553		collision = ( options.collision || "flip" ).split( " " ),
41554		offsets = {};
41555
41556	dimensions = getDimensions( target );
41557	if ( target[0].preventDefault ) {
41558		// force left top to allow flipping
41559		options.at = "left top";
41560	}
41561	targetWidth = dimensions.width;
41562	targetHeight = dimensions.height;
41563	targetOffset = dimensions.offset;
41564	// clone to reuse original targetOffset later
41565	basePosition = $.extend( {}, targetOffset );
41566
41567	// force my and at to have valid horizontal and vertical positions
41568	// if a value is missing or invalid, it will be converted to center
41569	$.each( [ "my", "at" ], function() {
41570		var pos = ( options[ this ] || "" ).split( " " ),
41571			horizontalOffset,
41572			verticalOffset;
41573
41574		if ( pos.length === 1) {
41575			pos = rhorizontal.test( pos[ 0 ] ) ?
41576				pos.concat( [ "center" ] ) :
41577				rvertical.test( pos[ 0 ] ) ?
41578					[ "center" ].concat( pos ) :
41579					[ "center", "center" ];
41580		}
41581		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
41582		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
41583
41584		// calculate offsets
41585		horizontalOffset = roffset.exec( pos[ 0 ] );
41586		verticalOffset = roffset.exec( pos[ 1 ] );
41587		offsets[ this ] = [
41588			horizontalOffset ? horizontalOffset[ 0 ] : 0,
41589			verticalOffset ? verticalOffset[ 0 ] : 0
41590		];
41591
41592		// reduce to just the positions without the offsets
41593		options[ this ] = [
41594			rposition.exec( pos[ 0 ] )[ 0 ],
41595			rposition.exec( pos[ 1 ] )[ 0 ]
41596		];
41597	});
41598
41599	// normalize collision option
41600	if ( collision.length === 1 ) {
41601		collision[ 1 ] = collision[ 0 ];
41602	}
41603
41604	if ( options.at[ 0 ] === "right" ) {
41605		basePosition.left += targetWidth;
41606	} else if ( options.at[ 0 ] === "center" ) {
41607		basePosition.left += targetWidth / 2;
41608	}
41609
41610	if ( options.at[ 1 ] === "bottom" ) {
41611		basePosition.top += targetHeight;
41612	} else if ( options.at[ 1 ] === "center" ) {
41613		basePosition.top += targetHeight / 2;
41614	}
41615
41616	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
41617	basePosition.left += atOffset[ 0 ];
41618	basePosition.top += atOffset[ 1 ];
41619
41620	return this.each(function() {
41621		var collisionPosition, using,
41622			elem = $( this ),
41623			elemWidth = elem.outerWidth(),
41624			elemHeight = elem.outerHeight(),
41625			marginLeft = parseCss( this, "marginLeft" ),
41626			marginTop = parseCss( this, "marginTop" ),
41627			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
41628			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
41629			position = $.extend( {}, basePosition ),
41630			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
41631
41632		if ( options.my[ 0 ] === "right" ) {
41633			position.left -= elemWidth;
41634		} else if ( options.my[ 0 ] === "center" ) {
41635			position.left -= elemWidth / 2;
41636		}
41637
41638		if ( options.my[ 1 ] === "bottom" ) {
41639			position.top -= elemHeight;
41640		} else if ( options.my[ 1 ] === "center" ) {
41641			position.top -= elemHeight / 2;
41642		}
41643
41644		position.left += myOffset[ 0 ];
41645		position.top += myOffset[ 1 ];
41646
41647		// if the browser doesn't support fractions, then round for consistent results
41648		if ( !supportsOffsetFractions ) {
41649			position.left = round( position.left );
41650			position.top = round( position.top );
41651		}
41652
41653		collisionPosition = {
41654			marginLeft: marginLeft,
41655			marginTop: marginTop
41656		};
41657
41658		$.each( [ "left", "top" ], function( i, dir ) {
41659			if ( $.ui.position[ collision[ i ] ] ) {
41660				$.ui.position[ collision[ i ] ][ dir ]( position, {
41661					targetWidth: targetWidth,
41662					targetHeight: targetHeight,
41663					elemWidth: elemWidth,
41664					elemHeight: elemHeight,
41665					collisionPosition: collisionPosition,
41666					collisionWidth: collisionWidth,
41667					collisionHeight: collisionHeight,
41668					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
41669					my: options.my,
41670					at: options.at,
41671					within: within,
41672					elem: elem
41673				});
41674			}
41675		});
41676
41677		if ( options.using ) {
41678			// adds feedback as second argument to using callback, if present
41679			using = function( props ) {
41680				var left = targetOffset.left - position.left,
41681					right = left + targetWidth - elemWidth,
41682					top = targetOffset.top - position.top,
41683					bottom = top + targetHeight - elemHeight,
41684					feedback = {
41685						target: {
41686							element: target,
41687							left: targetOffset.left,
41688							top: targetOffset.top,
41689							width: targetWidth,
41690							height: targetHeight
41691						},
41692						element: {
41693							element: elem,
41694							left: position.left,
41695							top: position.top,
41696							width: elemWidth,
41697							height: elemHeight
41698						},
41699						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
41700						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
41701					};
41702				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
41703					feedback.horizontal = "center";
41704				}
41705				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
41706					feedback.vertical = "middle";
41707				}
41708				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
41709					feedback.important = "horizontal";
41710				} else {
41711					feedback.important = "vertical";
41712				}
41713				options.using.call( this, props, feedback );
41714			};
41715		}
41716
41717		elem.offset( $.extend( position, { using: using } ) );
41718	});
41719};
41720
41721$.ui.position = {
41722	fit: {
41723		left: function( position, data ) {
41724			var within = data.within,
41725				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
41726				outerWidth = within.width,
41727				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
41728				overLeft = withinOffset - collisionPosLeft,
41729				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
41730				newOverRight;
41731
41732			// element is wider than within
41733			if ( data.collisionWidth > outerWidth ) {
41734				// element is initially over the left side of within
41735				if ( overLeft > 0 && overRight <= 0 ) {
41736					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
41737					position.left += overLeft - newOverRight;
41738				// element is initially over right side of within
41739				} else if ( overRight > 0 && overLeft <= 0 ) {
41740					position.left = withinOffset;
41741				// element is initially over both left and right sides of within
41742				} else {
41743					if ( overLeft > overRight ) {
41744						position.left = withinOffset + outerWidth - data.collisionWidth;
41745					} else {
41746						position.left = withinOffset;
41747					}
41748				}
41749			// too far left -> align with left edge
41750			} else if ( overLeft > 0 ) {
41751				position.left += overLeft;
41752			// too far right -> align with right edge
41753			} else if ( overRight > 0 ) {
41754				position.left -= overRight;
41755			// adjust based on position and margin
41756			} else {
41757				position.left = max( position.left - collisionPosLeft, position.left );
41758			}
41759		},
41760		top: function( position, data ) {
41761			var within = data.within,
41762				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
41763				outerHeight = data.within.height,
41764				collisionPosTop = position.top - data.collisionPosition.marginTop,
41765				overTop = withinOffset - collisionPosTop,
41766				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
41767				newOverBottom;
41768
41769			// element is taller than within
41770			if ( data.collisionHeight > outerHeight ) {
41771				// element is initially over the top of within
41772				if ( overTop > 0 && overBottom <= 0 ) {
41773					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
41774					position.top += overTop - newOverBottom;
41775				// element is initially over bottom of within
41776				} else if ( overBottom > 0 && overTop <= 0 ) {
41777					position.top = withinOffset;
41778				// element is initially over both top and bottom of within
41779				} else {
41780					if ( overTop > overBottom ) {
41781						position.top = withinOffset + outerHeight - data.collisionHeight;
41782					} else {
41783						position.top = withinOffset;
41784					}
41785				}
41786			// too far up -> align with top
41787			} else if ( overTop > 0 ) {
41788				position.top += overTop;
41789			// too far down -> align with bottom edge
41790			} else if ( overBottom > 0 ) {
41791				position.top -= overBottom;
41792			// adjust based on position and margin
41793			} else {
41794				position.top = max( position.top - collisionPosTop, position.top );
41795			}
41796		}
41797	},
41798	flip: {
41799		left: function( position, data ) {
41800			var within = data.within,
41801				withinOffset = within.offset.left + within.scrollLeft,
41802				outerWidth = within.width,
41803				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
41804				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
41805				overLeft = collisionPosLeft - offsetLeft,
41806				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
41807				myOffset = data.my[ 0 ] === "left" ?
41808					-data.elemWidth :
41809					data.my[ 0 ] === "right" ?
41810						data.elemWidth :
41811						0,
41812				atOffset = data.at[ 0 ] === "left" ?
41813					data.targetWidth :
41814					data.at[ 0 ] === "right" ?
41815						-data.targetWidth :
41816						0,
41817				offset = -2 * data.offset[ 0 ],
41818				newOverRight,
41819				newOverLeft;
41820
41821			if ( overLeft < 0 ) {
41822				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
41823				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
41824					position.left += myOffset + atOffset + offset;
41825				}
41826			} else if ( overRight > 0 ) {
41827				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
41828				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
41829					position.left += myOffset + atOffset + offset;
41830				}
41831			}
41832		},
41833		top: function( position, data ) {
41834			var within = data.within,
41835				withinOffset = within.offset.top + within.scrollTop,
41836				outerHeight = within.height,
41837				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
41838				collisionPosTop = position.top - data.collisionPosition.marginTop,
41839				overTop = collisionPosTop - offsetTop,
41840				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
41841				top = data.my[ 1 ] === "top",
41842				myOffset = top ?
41843					-data.elemHeight :
41844					data.my[ 1 ] === "bottom" ?
41845						data.elemHeight :
41846						0,
41847				atOffset = data.at[ 1 ] === "top" ?
41848					data.targetHeight :
41849					data.at[ 1 ] === "bottom" ?
41850						-data.targetHeight :
41851						0,
41852				offset = -2 * data.offset[ 1 ],
41853				newOverTop,
41854				newOverBottom;
41855			if ( overTop < 0 ) {
41856				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
41857				if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
41858					position.top += myOffset + atOffset + offset;
41859				}
41860			} else if ( overBottom > 0 ) {
41861				newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
41862				if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
41863					position.top += myOffset + atOffset + offset;
41864				}
41865			}
41866		}
41867	},
41868	flipfit: {
41869		left: function() {
41870			$.ui.position.flip.left.apply( this, arguments );
41871			$.ui.position.fit.left.apply( this, arguments );
41872		},
41873		top: function() {
41874			$.ui.position.flip.top.apply( this, arguments );
41875			$.ui.position.fit.top.apply( this, arguments );
41876		}
41877	}
41878};
41879
41880// fraction support test
41881(function() {
41882	var testElement, testElementParent, testElementStyle, offsetLeft, i,
41883		body = document.getElementsByTagName( "body" )[ 0 ],
41884		div = document.createElement( "div" );
41885
41886	//Create a "fake body" for testing based on method used in jQuery.support
41887	testElement = document.createElement( body ? "div" : "body" );
41888	testElementStyle = {
41889		visibility: "hidden",
41890		width: 0,
41891		height: 0,
41892		border: 0,
41893		margin: 0,
41894		background: "none"
41895	};
41896	if ( body ) {
41897		$.extend( testElementStyle, {
41898			position: "absolute",
41899			left: "-1000px",
41900			top: "-1000px"
41901		});
41902	}
41903	for ( i in testElementStyle ) {
41904		testElement.style[ i ] = testElementStyle[ i ];
41905	}
41906	testElement.appendChild( div );
41907	testElementParent = body || document.documentElement;
41908	testElementParent.insertBefore( testElement, testElementParent.firstChild );
41909
41910	div.style.cssText = "position: absolute; left: 10.7432222px;";
41911
41912	offsetLeft = $( div ).offset().left;
41913	supportsOffsetFractions = offsetLeft > 10 && offsetLeft < 11;
41914
41915	testElement.innerHTML = "";
41916	testElementParent.removeChild( testElement );
41917})();
41918
41919})();
41920
41921return $.ui.position;
41922
41923}));
41924
41925},
41926'jquery-ui/ui/resizable':function(){
41927/*!
41928 * jQuery UI Resizable 1.11.2
41929 * http://jqueryui.com
41930 *
41931 * Copyright 2014 jQuery Foundation and other contributors
41932 * Released under the MIT license.
41933 * http://jquery.org/license
41934 *
41935 * http://api.jqueryui.com/resizable/
41936 */
41937(function( factory ) {
41938	if ( typeof define === "function" && define.amd ) {
41939
41940		// AMD. Register as an anonymous module.
41941		define([
41942			"jquery",
41943			"./core",
41944			"./mouse",
41945			"./widget"
41946		], factory );
41947	} else {
41948
41949		// Browser globals
41950		factory( jQuery );
41951	}
41952}(function( $ ) {
41953
41954$.widget("ui.resizable", $.ui.mouse, {
41955	version: "1.11.2",
41956	widgetEventPrefix: "resize",
41957	options: {
41958		alsoResize: false,
41959		animate: false,
41960		animateDuration: "slow",
41961		animateEasing: "swing",
41962		aspectRatio: false,
41963		autoHide: false,
41964		containment: false,
41965		ghost: false,
41966		grid: false,
41967		handles: "e,s,se",
41968		helper: false,
41969		maxHeight: null,
41970		maxWidth: null,
41971		minHeight: 10,
41972		minWidth: 10,
41973		// See #7960
41974		zIndex: 90,
41975
41976		// callbacks
41977		resize: null,
41978		start: null,
41979		stop: null
41980	},
41981
41982	_num: function( value ) {
41983		return parseInt( value, 10 ) || 0;
41984	},
41985
41986	_isNumber: function( value ) {
41987		return !isNaN( parseInt( value, 10 ) );
41988	},
41989
41990	_hasScroll: function( el, a ) {
41991
41992		if ( $( el ).css( "overflow" ) === "hidden") {
41993			return false;
41994		}
41995
41996		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
41997			has = false;
41998
41999		if ( el[ scroll ] > 0 ) {
42000			return true;
42001		}
42002
42003		// TODO: determine which cases actually cause this to happen
42004		// if the element doesn't have the scroll set, see if it's possible to
42005		// set the scroll
42006		el[ scroll ] = 1;
42007		has = ( el[ scroll ] > 0 );
42008		el[ scroll ] = 0;
42009		return has;
42010	},
42011
42012	_create: function() {
42013
42014		var n, i, handle, axis, hname,
42015			that = this,
42016			o = this.options;
42017		this.element.addClass("ui-resizable");
42018
42019		$.extend(this, {
42020			_aspectRatio: !!(o.aspectRatio),
42021			aspectRatio: o.aspectRatio,
42022			originalElement: this.element,
42023			_proportionallyResizeElements: [],
42024			_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
42025		});
42026
42027		// Wrap the element if it cannot hold child nodes
42028		if (this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
42029
42030			this.element.wrap(
42031				$("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({
42032					position: this.element.css("position"),
42033					width: this.element.outerWidth(),
42034					height: this.element.outerHeight(),
42035					top: this.element.css("top"),
42036					left: this.element.css("left")
42037				})
42038			);
42039
42040			this.element = this.element.parent().data(
42041				"ui-resizable", this.element.resizable( "instance" )
42042			);
42043
42044			this.elementIsWrapper = true;
42045
42046			this.element.css({
42047				marginLeft: this.originalElement.css("marginLeft"),
42048				marginTop: this.originalElement.css("marginTop"),
42049				marginRight: this.originalElement.css("marginRight"),
42050				marginBottom: this.originalElement.css("marginBottom")
42051			});
42052			this.originalElement.css({
42053				marginLeft: 0,
42054				marginTop: 0,
42055				marginRight: 0,
42056				marginBottom: 0
42057			});
42058			// support: Safari
42059			// Prevent Safari textarea resize
42060			this.originalResizeStyle = this.originalElement.css("resize");
42061			this.originalElement.css("resize", "none");
42062
42063			this._proportionallyResizeElements.push( this.originalElement.css({
42064				position: "static",
42065				zoom: 1,
42066				display: "block"
42067			}) );
42068
42069			// support: IE9
42070			// avoid IE jump (hard set the margin)
42071			this.originalElement.css({ margin: this.originalElement.css("margin") });
42072
42073			this._proportionallyResize();
42074		}
42075
42076		this.handles = o.handles ||
42077			( !$(".ui-resizable-handle", this.element).length ?
42078				"e,s,se" : {
42079					n: ".ui-resizable-n",
42080					e: ".ui-resizable-e",
42081					s: ".ui-resizable-s",
42082					w: ".ui-resizable-w",
42083					se: ".ui-resizable-se",
42084					sw: ".ui-resizable-sw",
42085					ne: ".ui-resizable-ne",
42086					nw: ".ui-resizable-nw"
42087				} );
42088
42089		if (this.handles.constructor === String) {
42090
42091			if ( this.handles === "all") {
42092				this.handles = "n,e,s,w,se,sw,ne,nw";
42093			}
42094
42095			n = this.handles.split(",");
42096			this.handles = {};
42097
42098			for (i = 0; i < n.length; i++) {
42099
42100				handle = $.trim(n[i]);
42101				hname = "ui-resizable-" + handle;
42102				axis = $("<div class='ui-resizable-handle " + hname + "'></div>");
42103
42104				axis.css({ zIndex: o.zIndex });
42105
42106				// TODO : What's going on here?
42107				if ("se" === handle) {
42108					axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
42109				}
42110
42111				this.handles[handle] = ".ui-resizable-" + handle;
42112				this.element.append(axis);
42113			}
42114
42115		}
42116
42117		this._renderAxis = function(target) {
42118
42119			var i, axis, padPos, padWrapper;
42120
42121			target = target || this.element;
42122
42123			for (i in this.handles) {
42124
42125				if (this.handles[i].constructor === String) {
42126					this.handles[i] = this.element.children( this.handles[ i ] ).first().show();
42127				}
42128
42129				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
42130
42131					axis = $(this.handles[i], this.element);
42132
42133					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
42134
42135					padPos = [ "padding",
vendor: 11,791 bytes, lines 42136-42611
42136						/ne|nw|n/.test(i) ? "Top" :
42137						/se|sw|s/.test(i) ? "Bottom" :
42138						/^e$/.test(i) ? "Right" : "Left" ].join("");
42139
42140					target.css(padPos, padWrapper);
42141
42142					this._proportionallyResize();
42143
42144				}
42145
42146				// TODO: What's that good for? There's not anything to be executed left
42147				if (!$(this.handles[i]).length) {
42148					continue;
42149				}
42150			}
42151		};
42152
42153		// TODO: make renderAxis a prototype function
42154		this._renderAxis(this.element);
42155
42156		this._handles = $(".ui-resizable-handle", this.element)
42157			.disableSelection();
42158
42159		this._handles.mouseover(function() {
42160			if (!that.resizing) {
42161				if (this.className) {
42162					axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
42163				}
42164				that.axis = axis && axis[1] ? axis[1] : "se";
42165			}
42166		});
42167
42168		if (o.autoHide) {
42169			this._handles.hide();
42170			$(this.element)
42171				.addClass("ui-resizable-autohide")
42172				.mouseenter(function() {
42173					if (o.disabled) {
42174						return;
42175					}
42176					$(this).removeClass("ui-resizable-autohide");
42177					that._handles.show();
42178				})
42179				.mouseleave(function() {
42180					if (o.disabled) {
42181						return;
42182					}
42183					if (!that.resizing) {
42184						$(this).addClass("ui-resizable-autohide");
42185						that._handles.hide();
42186					}
42187				});
42188		}
42189
42190		this._mouseInit();
42191
42192	},
42193
42194	_destroy: function() {
42195
42196		this._mouseDestroy();
42197
42198		var wrapper,
42199			_destroy = function(exp) {
42200				$(exp)
42201					.removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
42202					.removeData("resizable")
42203					.removeData("ui-resizable")
42204					.unbind(".resizable")
42205					.find(".ui-resizable-handle")
42206						.remove();
42207			};
42208
42209		// TODO: Unwrap at same DOM position
42210		if (this.elementIsWrapper) {
42211			_destroy(this.element);
42212			wrapper = this.element;
42213			this.originalElement.css({
42214				position: wrapper.css("position"),
42215				width: wrapper.outerWidth(),
42216				height: wrapper.outerHeight(),
42217				top: wrapper.css("top"),
42218				left: wrapper.css("left")
42219			}).insertAfter( wrapper );
42220			wrapper.remove();
42221		}
42222
42223		this.originalElement.css("resize", this.originalResizeStyle);
42224		_destroy(this.originalElement);
42225
42226		return this;
42227	},
42228
42229	_mouseCapture: function(event) {
42230		var i, handle,
42231			capture = false;
42232
42233		for (i in this.handles) {
42234			handle = $(this.handles[i])[0];
42235			if (handle === event.target || $.contains(handle, event.target)) {
42236				capture = true;
42237			}
42238		}
42239
42240		return !this.options.disabled && capture;
42241	},
42242
42243	_mouseStart: function(event) {
42244
42245		var curleft, curtop, cursor,
42246			o = this.options,
42247			el = this.element;
42248
42249		this.resizing = true;
42250
42251		this._renderProxy();
42252
42253		curleft = this._num(this.helper.css("left"));
42254		curtop = this._num(this.helper.css("top"));
42255
42256		if (o.containment) {
42257			curleft += $(o.containment).scrollLeft() || 0;
42258			curtop += $(o.containment).scrollTop() || 0;
42259		}
42260
42261		this.offset = this.helper.offset();
42262		this.position = { left: curleft, top: curtop };
42263
42264		this.size = this._helper ? {
42265				width: this.helper.width(),
42266				height: this.helper.height()
42267			} : {
42268				width: el.width(),
42269				height: el.height()
42270			};
42271
42272		this.originalSize = this._helper ? {
42273				width: el.outerWidth(),
42274				height: el.outerHeight()
42275			} : {
42276				width: el.width(),
42277				height: el.height()
42278			};
42279
42280		this.sizeDiff = {
42281			width: el.outerWidth() - el.width(),
42282			height: el.outerHeight() - el.height()
42283		};
42284
42285		this.originalPosition = { left: curleft, top: curtop };
42286		this.originalMousePosition = { left: event.pageX, top: event.pageY };
42287
42288		this.aspectRatio = (typeof o.aspectRatio === "number") ?
42289			o.aspectRatio :
42290			((this.originalSize.width / this.originalSize.height) || 1);
42291
42292		cursor = $(".ui-resizable-" + this.axis).css("cursor");
42293		$("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
42294
42295		el.addClass("ui-resizable-resizing");
42296		this._propagate("start", event);
42297		return true;
42298	},
42299
42300	_mouseDrag: function(event) {
42301
42302		var data, props,
42303			smp = this.originalMousePosition,
42304			a = this.axis,
42305			dx = (event.pageX - smp.left) || 0,
42306			dy = (event.pageY - smp.top) || 0,
42307			trigger = this._change[a];
42308
42309		this._updatePrevProperties();
42310
42311		if (!trigger) {
42312			return false;
42313		}
42314
42315		data = trigger.apply(this, [ event, dx, dy ]);
42316
42317		this._updateVirtualBoundaries(event.shiftKey);
42318		if (this._aspectRatio || event.shiftKey) {
42319			data = this._updateRatio(data, event);
42320		}
42321
42322		data = this._respectSize(data, event);
42323
42324		this._updateCache(data);
42325
42326		this._propagate("resize", event);
42327
42328		props = this._applyChanges();
42329
42330		if ( !this._helper && this._proportionallyResizeElements.length ) {
42331			this._proportionallyResize();
42332		}
42333
42334		if ( !$.isEmptyObject( props ) ) {
42335			this._updatePrevProperties();
42336			this._trigger( "resize", event, this.ui() );
42337			this._applyChanges();
42338		}
42339
42340		return false;
42341	},
42342
42343	_mouseStop: function(event) {
42344
42345		this.resizing = false;
42346		var pr, ista, soffseth, soffsetw, s, left, top,
42347			o = this.options, that = this;
42348
42349		if (this._helper) {
42350
42351			pr = this._proportionallyResizeElements;
42352			ista = pr.length && (/textarea/i).test(pr[0].nodeName);
42353			soffseth = ista && this._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height;
42354			soffsetw = ista ? 0 : that.sizeDiff.width;
42355
42356			s = {
42357				width: (that.helper.width()  - soffsetw),
42358				height: (that.helper.height() - soffseth)
42359			};
42360			left = (parseInt(that.element.css("left"), 10) +
42361				(that.position.left - that.originalPosition.left)) || null;
42362			top = (parseInt(that.element.css("top"), 10) +
42363				(that.position.top - that.originalPosition.top)) || null;
42364
42365			if (!o.animate) {
42366				this.element.css($.extend(s, { top: top, left: left }));
42367			}
42368
42369			that.helper.height(that.size.height);
42370			that.helper.width(that.size.width);
42371
42372			if (this._helper && !o.animate) {
42373				this._proportionallyResize();
42374			}
42375		}
42376
42377		$("body").css("cursor", "auto");
42378
42379		this.element.removeClass("ui-resizable-resizing");
42380
42381		this._propagate("stop", event);
42382
42383		if (this._helper) {
42384			this.helper.remove();
42385		}
42386
42387		return false;
42388
42389	},
42390
42391	_updatePrevProperties: function() {
42392		this.prevPosition = {
42393			top: this.position.top,
42394			left: this.position.left
42395		};
42396		this.prevSize = {
42397			width: this.size.width,
42398			height: this.size.height
42399		};
42400	},
42401
42402	_applyChanges: function() {
42403		var props = {};
42404
42405		if ( this.position.top !== this.prevPosition.top ) {
42406			props.top = this.position.top + "px";
42407		}
42408		if ( this.position.left !== this.prevPosition.left ) {
42409			props.left = this.position.left + "px";
42410		}
42411		if ( this.size.width !== this.prevSize.width ) {
42412			props.width = this.size.width + "px";
42413		}
42414		if ( this.size.height !== this.prevSize.height ) {
42415			props.height = this.size.height + "px";
42416		}
42417
42418		this.helper.css( props );
42419
42420		return props;
42421	},
42422
42423	_updateVirtualBoundaries: function(forceAspectRatio) {
42424		var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
42425			o = this.options;
42426
42427		b = {
42428			minWidth: this._isNumber(o.minWidth) ? o.minWidth : 0,
42429			maxWidth: this._isNumber(o.maxWidth) ? o.maxWidth : Infinity,
42430			minHeight: this._isNumber(o.minHeight) ? o.minHeight : 0,
42431			maxHeight: this._isNumber(o.maxHeight) ? o.maxHeight : Infinity
42432		};
42433
42434		if (this._aspectRatio || forceAspectRatio) {
42435			pMinWidth = b.minHeight * this.aspectRatio;
42436			pMinHeight = b.minWidth / this.aspectRatio;
42437			pMaxWidth = b.maxHeight * this.aspectRatio;
42438			pMaxHeight = b.maxWidth / this.aspectRatio;
42439
42440			if (pMinWidth > b.minWidth) {
42441				b.minWidth = pMinWidth;
42442			}
42443			if (pMinHeight > b.minHeight) {
42444				b.minHeight = pMinHeight;
42445			}
42446			if (pMaxWidth < b.maxWidth) {
42447				b.maxWidth = pMaxWidth;
42448			}
42449			if (pMaxHeight < b.maxHeight) {
42450				b.maxHeight = pMaxHeight;
42451			}
42452		}
42453		this._vBoundaries = b;
42454	},
42455
42456	_updateCache: function(data) {
42457		this.offset = this.helper.offset();
42458		if (this._isNumber(data.left)) {
42459			this.position.left = data.left;
42460		}
42461		if (this._isNumber(data.top)) {
42462			this.position.top = data.top;
42463		}
42464		if (this._isNumber(data.height)) {
42465			this.size.height = data.height;
42466		}
42467		if (this._isNumber(data.width)) {
42468			this.size.width = data.width;
42469		}
42470	},
42471
42472	_updateRatio: function( data ) {
42473
42474		var cpos = this.position,
42475			csize = this.size,
42476			a = this.axis;
42477
42478		if (this._isNumber(data.height)) {
42479			data.width = (data.height * this.aspectRatio);
42480		} else if (this._isNumber(data.width)) {
42481			data.height = (data.width / this.aspectRatio);
42482		}
42483
42484		if (a === "sw") {
42485			data.left = cpos.left + (csize.width - data.width);
42486			data.top = null;
42487		}
42488		if (a === "nw") {
42489			data.top = cpos.top + (csize.height - data.height);
42490			data.left = cpos.left + (csize.width - data.width);
42491		}
42492
42493		return data;
42494	},
42495
42496	_respectSize: function( data ) {
42497
42498		var o = this._vBoundaries,
42499			a = this.axis,
42500			ismaxw = this._isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width),
42501			ismaxh = this._isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
42502			isminw = this._isNumber(data.width) && o.minWidth && (o.minWidth > data.width),
42503			isminh = this._isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
42504			dw = this.originalPosition.left + this.originalSize.width,
42505			dh = this.position.top + this.size.height,
42506			cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
42507		if (isminw) {
42508			data.width = o.minWidth;
42509		}
42510		if (isminh) {
42511			data.height = o.minHeight;
42512		}
42513		if (ismaxw) {
42514			data.width = o.maxWidth;
42515		}
42516		if (ismaxh) {
42517			data.height = o.maxHeight;
42518		}
42519
42520		if (isminw && cw) {
42521			data.left = dw - o.minWidth;
42522		}
42523		if (ismaxw && cw) {
42524			data.left = dw - o.maxWidth;
42525		}
42526		if (isminh && ch) {
42527			data.top = dh - o.minHeight;
42528		}
42529		if (ismaxh && ch) {
42530			data.top = dh - o.maxHeight;
42531		}
42532
42533		// Fixing jump error on top/left - bug #2330
42534		if (!data.width && !data.height && !data.left && data.top) {
42535			data.top = null;
42536		} else if (!data.width && !data.height && !data.top && data.left) {
42537			data.left = null;
42538		}
42539
42540		return data;
42541	},
42542
42543	_getPaddingPlusBorderDimensions: function( element ) {
42544		var i = 0,
42545			widths = [],
42546			borders = [
42547				element.css( "borderTopWidth" ),
42548				element.css( "borderRightWidth" ),
42549				element.css( "borderBottomWidth" ),
42550				element.css( "borderLeftWidth" )
42551			],
42552			paddings = [
42553				element.css( "paddingTop" ),
42554				element.css( "paddingRight" ),
42555				element.css( "paddingBottom" ),
42556				element.css( "paddingLeft" )
42557			];
42558
42559		for ( ; i < 4; i++ ) {
42560			widths[ i ] = ( parseInt( borders[ i ], 10 ) || 0 );
42561			widths[ i ] += ( parseInt( paddings[ i ], 10 ) || 0 );
42562		}
42563
42564		return {
42565			height: widths[ 0 ] + widths[ 2 ],
42566			width: widths[ 1 ] + widths[ 3 ]
42567		};
42568	},
42569
42570	_proportionallyResize: function() {
42571
42572		if (!this._proportionallyResizeElements.length) {
42573			return;
42574		}
42575
42576		var prel,
42577			i = 0,
42578			element = this.helper || this.element;
42579
42580		for ( ; i < this._proportionallyResizeElements.length; i++) {
42581
42582			prel = this._proportionallyResizeElements[i];
42583
42584			// TODO: Seems like a bug to cache this.outerDimensions
42585			// considering that we are in a loop.
42586			if (!this.outerDimensions) {
42587				this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
42588			}
42589
42590			prel.css({
42591				height: (element.height() - this.outerDimensions.height) || 0,
42592				width: (element.width() - this.outerDimensions.width) || 0
42593			});
42594
42595		}
42596
42597	},
42598
42599	_renderProxy: function() {
42600
42601		var el = this.element, o = this.options;
42602		this.elementOffset = el.offset();
42603
42604		if (this._helper) {
42605
42606			this.helper = this.helper || $("<div style='overflow:hidden;'></div>");
42607
42608			this.helper.addClass(this._helper).css({
42609				width: this.element.outerWidth() - 1,
42610				height: this.element.outerHeight() - 1,
42611				position: "absolute",
vendor: 6,496 bytes, lines 42612-42845
42612				left: this.elementOffset.left + "px",
42613				top: this.elementOffset.top + "px",
42614				zIndex: ++o.zIndex //TODO: Don't modify option
42615			});
42616
42617			this.helper
42618				.appendTo("body")
42619				.disableSelection();
42620
42621		} else {
42622			this.helper = this.element;
42623		}
42624
42625	},
42626
42627	_change: {
42628		e: function(event, dx) {
42629			return { width: this.originalSize.width + dx };
42630		},
42631		w: function(event, dx) {
42632			var cs = this.originalSize, sp = this.originalPosition;
42633			return { left: sp.left + dx, width: cs.width - dx };
42634		},
42635		n: function(event, dx, dy) {
42636			var cs = this.originalSize, sp = this.originalPosition;
42637			return { top: sp.top + dy, height: cs.height - dy };
42638		},
42639		s: function(event, dx, dy) {
42640			return { height: this.originalSize.height + dy };
42641		},
42642		se: function(event, dx, dy) {
42643			return $.extend(this._change.s.apply(this, arguments),
42644				this._change.e.apply(this, [ event, dx, dy ]));
42645		},
42646		sw: function(event, dx, dy) {
42647			return $.extend(this._change.s.apply(this, arguments),
42648				this._change.w.apply(this, [ event, dx, dy ]));
42649		},
42650		ne: function(event, dx, dy) {
42651			return $.extend(this._change.n.apply(this, arguments),
42652				this._change.e.apply(this, [ event, dx, dy ]));
42653		},
42654		nw: function(event, dx, dy) {
42655			return $.extend(this._change.n.apply(this, arguments),
42656				this._change.w.apply(this, [ event, dx, dy ]));
42657		}
42658	},
42659
42660	_propagate: function(n, event) {
42661		$.ui.plugin.call(this, n, [ event, this.ui() ]);
42662		(n !== "resize" && this._trigger(n, event, this.ui()));
42663	},
42664
42665	plugins: {},
42666
42667	ui: function() {
42668		return {
42669			originalElement: this.originalElement,
42670			element: this.element,
42671			helper: this.helper,
42672			position: this.position,
42673			size: this.size,
42674			originalSize: this.originalSize,
42675			originalPosition: this.originalPosition
42676		};
42677	}
42678
42679});
42680
42681/*
42682 * Resizable Extensions
42683 */
42684
42685$.ui.plugin.add("resizable", "animate", {
42686
42687	stop: function( event ) {
42688		var that = $(this).resizable( "instance" ),
42689			o = that.options,
42690			pr = that._proportionallyResizeElements,
42691			ista = pr.length && (/textarea/i).test(pr[0].nodeName),
42692			soffseth = ista && that._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height,
42693			soffsetw = ista ? 0 : that.sizeDiff.width,
42694			style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
42695			left = (parseInt(that.element.css("left"), 10) +
42696				(that.position.left - that.originalPosition.left)) || null,
42697			top = (parseInt(that.element.css("top"), 10) +
42698				(that.position.top - that.originalPosition.top)) || null;
42699
42700		that.element.animate(
42701			$.extend(style, top && left ? { top: top, left: left } : {}), {
42702				duration: o.animateDuration,
42703				easing: o.animateEasing,
42704				step: function() {
42705
42706					var data = {
42707						width: parseInt(that.element.css("width"), 10),
42708						height: parseInt(that.element.css("height"), 10),
42709						top: parseInt(that.element.css("top"), 10),
42710						left: parseInt(that.element.css("left"), 10)
42711					};
42712
42713					if (pr && pr.length) {
42714						$(pr[0]).css({ width: data.width, height: data.height });
42715					}
42716
42717					// propagating resize, and updating values for each animation step
42718					that._updateCache(data);
42719					that._propagate("resize", event);
42720
42721				}
42722			}
42723		);
42724	}
42725
42726});
42727
42728$.ui.plugin.add( "resizable", "containment", {
42729
42730	start: function() {
42731		var element, p, co, ch, cw, width, height,
42732			that = $( this ).resizable( "instance" ),
42733			o = that.options,
42734			el = that.element,
42735			oc = o.containment,
42736			ce = ( oc instanceof $ ) ? oc.get( 0 ) : ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
42737
42738		if ( !ce ) {
42739			return;
42740		}
42741
42742		that.containerElement = $( ce );
42743
42744		if ( /document/.test( oc ) || oc === document ) {
42745			that.containerOffset = {
42746				left: 0,
42747				top: 0
42748			};
42749			that.containerPosition = {
42750				left: 0,
42751				top: 0
42752			};
42753
42754			that.parentData = {
42755				element: $( document ),
42756				left: 0,
42757				top: 0,
42758				width: $( document ).width(),
42759				height: $( document ).height() || document.body.parentNode.scrollHeight
42760			};
42761		} else {
42762			element = $( ce );
42763			p = [];
42764			$([ "Top", "Right", "Left", "Bottom" ]).each(function( i, name ) {
42765				p[ i ] = that._num( element.css( "padding" + name ) );
42766			});
42767
42768			that.containerOffset = element.offset();
42769			that.containerPosition = element.position();
42770			that.containerSize = {
42771				height: ( element.innerHeight() - p[ 3 ] ),
42772				width: ( element.innerWidth() - p[ 1 ] )
42773			};
42774
42775			co = that.containerOffset;
42776			ch = that.containerSize.height;
42777			cw = that.containerSize.width;
42778			width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw );
42779			height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;
42780
42781			that.parentData = {
42782				element: ce,
42783				left: co.left,
42784				top: co.top,
42785				width: width,
42786				height: height
42787			};
42788		}
42789	},
42790
42791	resize: function( event ) {
42792		var woset, hoset, isParent, isOffsetRelative,
42793			that = $( this ).resizable( "instance" ),
42794			o = that.options,
42795			co = that.containerOffset,
42796			cp = that.position,
42797			pRatio = that._aspectRatio || event.shiftKey,
42798			cop = {
42799				top: 0,
42800				left: 0
42801			},
42802			ce = that.containerElement,
42803			continueResize = true;
42804
42805		if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
42806			cop = co;
42807		}
42808
42809		if ( cp.left < ( that._helper ? co.left : 0 ) ) {
42810			that.size.width = that.size.width +
42811				( that._helper ?
42812					( that.position.left - co.left ) :
42813					( that.position.left - cop.left ) );
42814
42815			if ( pRatio ) {
42816				that.size.height = that.size.width / that.aspectRatio;
42817				continueResize = false;
42818			}
42819			that.position.left = o.helper ? co.left : 0;
42820		}
42821
42822		if ( cp.top < ( that._helper ? co.top : 0 ) ) {
42823			that.size.height = that.size.height +
42824				( that._helper ?
42825					( that.position.top - co.top ) :
42826					that.position.top );
42827
42828			if ( pRatio ) {
42829				that.size.width = that.size.height * that.aspectRatio;
42830				continueResize = false;
42831			}
42832			that.position.top = that._helper ? co.top : 0;
42833		}
42834
42835		isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
42836		isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
42837
42838		if ( isParent && isOffsetRelative ) {
42839			that.offset.left = that.parentData.left + that.position.left;
42840			that.offset.top = that.parentData.top + that.position.top;
42841		} else {
42842			that.offset.left = that.element.offset().left;
42843			that.offset.top = that.element.offset().top;
42844		}
42845
42846		woset = Math.abs( that.sizeDiff.width +
42847			(that._helper ?
42848				that.offset.left - cop.left :
42849				(that.offset.left - co.left)) );
42850
42851		hoset = Math.abs( that.sizeDiff.height +
42852			(that._helper ?
42853				that.offset.top - cop.top :
42854				(that.offset.top - co.top)) );
42855
42856		if ( woset + that.size.width >= that.parentData.width ) {
42857			that.size.width = that.parentData.width - woset;
42858			if ( pRatio ) {
42859				that.size.height = that.size.width / that.aspectRatio;
42860				continueResize = false;
42861			}
42862		}
42863
42864		if ( hoset + that.size.height >= that.parentData.height ) {
42865			that.size.height = that.parentData.height - hoset;
42866			if ( pRatio ) {
42867				that.size.width = that.size.height * that.aspectRatio;
42868				continueResize = false;
42869			}
42870		}
42871
42872		if ( !continueResize ){
42873			that.position.left = that.prevPosition.left;
42874			that.position.top = that.prevPosition.top;
42875			that.size.width = that.prevSize.width;
42876			that.size.height = that.prevSize.height;
42877		}
42878	},
42879
42880	stop: function() {
42881		var that = $( this ).resizable( "instance" ),
42882			o = that.options,
42883			co = that.containerOffset,
42884			cop = that.containerPosition,
42885			ce = that.containerElement,
42886			helper = $( that.helper ),
42887			ho = helper.offset(),
42888			w = helper.outerWidth() - that.sizeDiff.width,
42889			h = helper.outerHeight() - that.sizeDiff.height;
42890
42891		if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
42892			$( this ).css({
42893				left: ho.left - cop.left - co.left,
42894				width: w,
42895				height: h
42896			});
42897		}
42898
42899		if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
42900			$( this ).css({
42901				left: ho.left - cop.left - co.left,
42902				width: w,
42903				height: h
42904			});
42905		}
42906	}
42907});
42908
42909$.ui.plugin.add("resizable", "alsoResize", {
42910
42911	start: function() {
42912		var that = $(this).resizable( "instance" ),
42913			o = that.options,
42914			_store = function(exp) {
42915				$(exp).each(function() {
42916					var el = $(this);
42917					el.data("ui-resizable-alsoresize", {
42918						width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
42919						left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
42920					});
42921				});
42922			};
42923
42924		if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) {
42925			if (o.alsoResize.length) {
42926				o.alsoResize = o.alsoResize[0];
42927				_store(o.alsoResize);
42928			} else {
42929				$.each(o.alsoResize, function(exp) {
42930					_store(exp);
42931				});
42932			}
42933		} else {
42934			_store(o.alsoResize);
42935		}
42936	},
42937
42938	resize: function(event, ui) {
42939		var that = $(this).resizable( "instance" ),
42940			o = that.options,
42941			os = that.originalSize,
42942			op = that.originalPosition,
42943			delta = {
42944				height: (that.size.height - os.height) || 0,
42945				width: (that.size.width - os.width) || 0,
42946				top: (that.position.top - op.top) || 0,
42947				left: (that.position.left - op.left) || 0
42948			},
42949
42950			_alsoResize = function(exp, c) {
42951				$(exp).each(function() {
42952					var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
42953						css = c && c.length ?
42954							c :
42955							el.parents(ui.originalElement[0]).length ?
42956								[ "width", "height" ] :
42957								[ "width", "height", "top", "left" ];
42958
42959					$.each(css, function(i, prop) {
42960						var sum = (start[prop] || 0) + (delta[prop] || 0);
42961						if (sum && sum >= 0) {
42962							style[prop] = sum || null;
42963						}
42964					});
42965
42966					el.css(style);
42967				});
42968			};
42969
42970		if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) {
42971			$.each(o.alsoResize, function(exp, c) {
42972				_alsoResize(exp, c);
42973			});
42974		} else {
42975			_alsoResize(o.alsoResize);
42976		}
42977	},
42978
42979	stop: function() {
42980		$(this).removeData("resizable-alsoresize");
42981	}
42982});
42983
42984$.ui.plugin.add("resizable", "ghost", {
42985
42986	start: function() {
42987
42988		var that = $(this).resizable( "instance" ), o = that.options, cs = that.size;
42989
42990		that.ghost = that.originalElement.clone();
42991		that.ghost
42992			.css({
42993				opacity: 0.25,
42994				display: "block",
42995				position: "relative",
42996				height: cs.height,
42997				width: cs.width,
42998				margin: 0,
42999				left: 0,
43000				top: 0
43001			})
43002			.addClass("ui-resizable-ghost")
43003			.addClass(typeof o.ghost === "string" ? o.ghost : "");
43004
43005		that.ghost.appendTo(that.helper);
43006
43007	},
43008
43009	resize: function() {
43010		var that = $(this).resizable( "instance" );
43011		if (that.ghost) {
43012			that.ghost.css({
43013				position: "relative",
43014				height: that.size.height,
43015				width: that.size.width
43016			});
43017		}
43018	},
43019
43020	stop: function() {
43021		var that = $(this).resizable( "instance" );
43022		if (that.ghost && that.helper) {
43023			that.helper.get(0).removeChild(that.ghost.get(0));
43024		}
43025	}
43026
43027});
43028
43029$.ui.plugin.add("resizable", "grid", {
43030
43031	resize: function() {
43032		var outerDimensions,
43033			that = $(this).resizable( "instance" ),
43034			o = that.options,
43035			cs = that.size,
43036			os = that.originalSize,
43037			op = that.originalPosition,
43038			a = that.axis,
43039			grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
43040			gridX = (grid[0] || 1),
43041			gridY = (grid[1] || 1),
43042			ox = Math.round((cs.width - os.width) / gridX) * gridX,
43043			oy = Math.round((cs.height - os.height) / gridY) * gridY,
43044			newWidth = os.width + ox,
43045			newHeight = os.height + oy,
43046			isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
43047			isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
43048			isMinWidth = o.minWidth && (o.minWidth > newWidth),
43049			isMinHeight = o.minHeight && (o.minHeight > newHeight);
43050
43051		o.grid = grid;
43052
43053		if (isMinWidth) {
43054			newWidth += gridX;
43055		}
43056		if (isMinHeight) {
43057			newHeight += gridY;
43058		}
43059		if (isMaxWidth) {
43060			newWidth -= gridX;
43061		}
43062		if (isMaxHeight) {
43063			newHeight -= gridY;
43064		}
43065
43066		if (/^(se|s|e)$/.test(a)) {
43067			that.size.width = newWidth;
43068			that.size.height = newHeight;
43069		} else if (/^(ne)$/.test(a)) {
43070			that.size.width = newWidth;
43071			that.size.height = newHeight;
43072			that.position.top = op.top - oy;
43073		} else if (/^(sw)$/.test(a)) {
43074			that.size.width = newWidth;
43075			that.size.height = newHeight;
43076			that.position.left = op.left - ox;
43077		} else {
43078			if ( newHeight - gridY <= 0 || newWidth - gridX <= 0) {
43079				outerDimensions = that._getPaddingPlusBorderDimensions( this );
43080			}
43081
43082			if ( newHeight - gridY > 0 ) {
43083				that.size.height = newHeight;
43084				that.position.top = op.top - oy;
43085			} else {
43086				newHeight = gridY - outerDimensions.height;
43087				that.size.height = newHeight;
43088				that.position.top = op.top + os.height - newHeight;
43089			}
43090			if ( newWidth - gridX > 0 ) {
43091				that.size.width = newWidth;
43092				that.position.left = op.left - ox;
43093			} else {
43094				newWidth = gridY - outerDimensions.height;
43095				that.size.width = newWidth;
43096				that.position.left = op.left + os.width - newWidth;
43097			}
43098		}
43099	}
43100
43101});
43102
43103return $.ui.resizable;
43104
43105}));
43106
43107},
43108'dpage/widgets/Page':function(){
43109define([
43110      "dojo/_base/declare"
43111      , "dojo/on"
43112      , "dojo/_base/event"
43113      , "dojo/json"
43114
43115      , "dpage/widgets/Container"
43116      , "dojox/widget/Standby"
43117],
43118    function (declare, on, event, json) {
43119    /**
43120    * @namespace dpage
43121    */
43122    /**
43123    * @namespace widgets
43124    * @memberOf dpage
43125    */
43126    /**
43127    * Every page in your application inherits from this module. Main DPage app container. Has other benifits such as catching the back-button keystroke event
43128    * which causes the browser to go back one page. Meant to augment the window.document.
43129    * This class is intended to be used as a Singleton. You will get an error if you try to instantiate more than one Page object per browser page.
43130    * @class Page
43131    * @param {Object} [options] Optional options for the widget.
43132    * @param {Object} [options.model] Data destined for Container child controls. 
43133    * @param {bool} [options.modelTransform] Default false. If true, parse the model as if it contains meta-data. If false, don't bother parsing. Use it as-is.
43134    * @param {bool} [options.parseNow] (defaults to true) If true, then parse the container for child widgets now. If false, wait for domReady.
43135    * @param {function} [options.widgetsParsedCallback] callback function for when widgets in this container are parsed.
43136    * @param {String} [options.templateString] Optional template for this container. If provided will instantiate a container with the provided
43137    *                                          markup. As with all containers, the markup can contain widgets that can be accessed through
43138    *                                          getWidget() or getWidgets().
43139    * @param {dpage.widgets.Container} [options.container] The container of the widget.
43140    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
43141    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
43142    *                               is created.
43143    * @param {Object} [containerNode] Optional container node to tie the widget to.
43144    * @memberOf dpage.widgets
43145    * @extends {dpage.widgets.Container}
43146    */
43147        var theClass = declare("dpage.widgets.Page", [dpage.widgets.Container], /** @lends dpage.widgets.Page.prototype */ {
43148            _overlay: null,
43149
43150            constructor: function (options, containerNode) {
43151                var self = this;
43152
43153                if (dpage.widgets.Page.getInstance() != null)
43154                    throw new Error("A dpage.widgets.Page already exists. This class is intended to be used as a Singleton. You can obtain a reference to the existing class using the dpage.widgets.Page.getInstance() method.");
43155
43156                //store a reference to this object.
43157                dpage.widgets.Page._pageObj = this;
43158
43159                if (options != null) {
43160
43161                }
43162
43163                on(document.body, "keydown", function () { return self.docKeyDown(arguments); });
43164                this._containerNode = document.body;
43165            },
43166            _doNextCSSResource : function()
43167            {
43168                var self = this;
43169                var notReady = false;
43170
43171                for (var k in dpage.widgets.Page._cssLoading)
43172                {
43173                    if(dpage.widgets.Page._cssLoading.hasOwnProperty(k))
43174                    {
43175                        if (!dpage.widgets.Page._cssLoading[k]) {
43176                            notReady = true;
43177                            break;
43178                        }
43179                    }
43180                }
43181
43182                //wait until ready.
43183                if (notReady) {
43184                    setTimeout(function () { self._doNextCSSResource(); }, 0);
43185                    return;
43186                }
43187
43188                var nextResource = dpage.widgets.Page._postParseCSS.shift();
43189                if(nextResource != null){
43190                    require(["xstyle/css!"+nextResource], function () { self._doNextCSSResource(); });
43191                }
43192            },
43193            widgetsParsed : function()
43194            {
43195                var self = this;
43196                setTimeout(function () { self._doNextCSSResource(); }, 0);
43197
43198                return this.inherited(arguments);
43199            },
43200            templateString: "<div></div>",
43201            buildRendering: function ()
43202            {
43203                return this.inherited(arguments);
43204            },
43205            docKeyDown: function (e) {
43206                e = e[0];
43207
43208                if (e.keyCode == 8) {
43209                    if (e.target == document.body)
43210                        event.stop(e);
43211                }
43212            },
43213            /**
43214            * Will disable the page so that a user cannot interact with it.
43215            * @returns {void}
43216            */
43217            disablePage: function () {
43218                this.blockUI(true);
43219            },
43220            /**
43221            * Enables the page so that the user can interact with it.
43222            * @returns {void}
43223            */
43224            enablePage: function () {
43225                this.blockUI(false);
43226            }
43227        });
43228
43229        theClass._postParseCSS = [],
43230        theClass._pageObj = null;
43231
43232        /**
43233        * Get the Page singleton obj.
43234        * @memberof dpage.widgets.Page
43235        * @name getInstance
43236        * @function
43237        * @returns {dpage.widgets.Page} 
43238        */
43239        theClass.getInstance = function () {
43240            return theClass._pageObj;
43241        };
43242
43243        theClass._cssLoading = {};
43244
43245        /**
43246        * A class (module) can call this method to inform the page that it has CSS resources pending. This is used by the Page class to control when to load the postParseCSS 
43247        * if specified by a user calling the setPostParseCSS function.
43248        * @memberof dpage.widgets.Page
43249        * @name setClassCSSLoading
43250        * @function
43251        * @param {String} className The name of the class that has CSS pending or not.
43252        * @param {bool} doneLoading A caller will set this to true to indicate that all css for a class is done loading, false, when it begins to load a css resource, but it has
43253        *                           not come back yet.
43254        * @returns {dpage.widgets.Page} 
43255        */
43256        theClass.setClassCSSLoading = function (className, doneLoading) {
43257            theClass._cssLoading[className] = doneLoading;
43258        };
43259
43260        /**
43261        * Set a list of css resources to bring in after the page is done parsing. Each string points to a CSS resource to bring in synchronously. 
43262        * Use this option to control the style a bit more. Can be used to override default widget style with css that is auto-required in by them. 
43263        * Any css resources specified are required in after the page is done instantiating declarative widgets. If the resources are not coming in, 
43264        * see if you are overriding the widgetsParsed() method. If so, make sure that you are calling the base class method this.inherited(arguments) 
43265        * which is where the resources are pulled in.
43266        * @memberof dpage.widgets.Page
43267        * @name setPostParseCSS
43268        * @function
43269        * @param {Array.String} resources List of css resource paths (can use package locations too).
43270        * @returns {void}
43271        */
43272        theClass.setPostParseCSS = function (resources) {
43273            theClass._postParseCSS = resources;
43274        };
43275
43276        return theClass;
43277    }
43278);
43279},
43280'dpage/widgets/DomWrapper':function(){
43281define([
43282      "dojo/_base/event"
43283      , "dojo/on"
43284      , "dojo/dom-attr"
43285      , "dojo/dom-class"
43286      , "dojo/mouse"
43287      , "dojo/dom-geometry"
43288      , "dojo/dom-style"
43289      , "dojo/json"
43290
43291      , "dojo/request/xhr"
43292      , "dojox/html/entities"
43293      , "dojo/_base/declare"
43294      , "dpage/widgets/BaseWidget"],
43295function (event, on, domAttr, domClass, mouse, domGeom, style, json) {
43296    /**
43297    * @namespace dpage
43298    */
43299    /**
43300    * @namespace widgets
43301    * @memberOf dpage
43302    */
43303    /**
43304    * Widget to serve as a wrapper around any dom node. This is so that we can provide access to the dom node without having to set an
43305    * id on the dom node.
43306    * @class DomWrapper
43307    * @param {Object} [options] Optional options for the widget.
43308    * @param {Function} options.onClick Click Handler for the dom node.
43309    * @param {dpage.widgets.Container} [options.container] The container of the widget.
43310    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
43311    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
43312    *                               is created.
43313    * @param {Object} [containerNode] Optional container node to tie the widget to.
43314    * @memberOf dpage.widgets
43315    * @extends {dpage.widgets.BaseWidget}
43316    */
43317    return dojo.declare("dpage.widgets.DomWrapper", [dpage.widgets.BaseWidget], /** @lends dpage.widgets.DomWrapper.prototype */ {
43318        _containerNode: null,
43319        constructor: function (options, srcNodeRef) {
43320            var self = this;
43321            this._containerNode = srcNodeRef;
43322
43323            if (options != null) {
43324                if (options.onClick != null)
43325                    this.on("click", options.onClick);
43326            }
43327
43328        },
43329        templateString: "<div></div>",
43330        buildRendering: function () {
43331            return this._containerNode;
43332        },
43333        postCreate: function () {
43334            return this.inherited(arguments);
43335        },
43336        /**
43337        * Set an event handler for the node. Events are dom and browser specific.
43338        * @param {String} eventName The symbolic name of the event.
43339        * @param {Function} functionRef the callback function to call.
43340        * @returns {void}
43341        */
43342        on: function (eventName, functionRef) {
43343            on(this._containerNode, eventName, functionRef);
43344        },
43345        /**
43346        * @returns {void}
43347        */
43348        getDomNode: function ()
43349        {
43350            return this._containerNode;
43351        }
43352    });
43353});
43354
43355},
43356'dpage/widgets/ExpandCollapse':function(){
43357define([
43358      "dojo/_base/event"
43359      , "dojo/on"
43360      , "dojo/dom-attr"
43361      , "dojo/dom-class"
43362      , "dojo/mouse"
43363      , "dojo/dom-geometry"
43364      , "dojo/dom-style"
43365      , "dojo/json"
43366
43367      , "dojo/request/xhr"
43368      , "dojox/html/entities"
43369      , "dojo/_base/declare"
43370      , "dpage/widgets/BaseWidget"],
43371function (event, on, domAttr, domClass, mouse, domGeom, style, json) {
43372    /**
43373    * @namespace dpage
43374    */
43375    /**
43376    * @namespace widgets
43377    * @memberOf dpage
43378    */
43379    /**
43380    * A Widget to either show or hide content. Attach to a dom node and any children will be shown or hidden.
43381    * @class ExpandCollapse
43382    * @param {Object} [options] Optional options for the widget.
43383    * @param {dpage.widgets.Container} [options.container] The container of the widget.
43384    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
43385    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
43386    *                               is created.
43387    * @param {Object} [containerNode] Optional container node to tie the widget to.
43388    * @memberOf dpage.widgets
43389    * @extends {dpage.widgets.BaseWidget}
43390    */
43391    return dojo.declare("dpage.widgets.ExpandCollapse", [dpage.widgets.BaseWidget], /** @lends dpage.widgets.ExpandCollapse.prototype */ {
43392        _containerNode: null,
43393        _hideStyle: 'none',
43394        _showStyle: 'block',
43395        _hidden: true,
43396        constructor: function (options, srcNodeRef) {
43397            var self = this;
43398            this._containerNode = srcNodeRef;
43399
43400            if (style.get(this._containerNode, "display").toUpperCase() == "NONE")
43401                this._hidden = true;
43402            else
43403                this._hidden = false;
43404
43405        },
43406        templateString: "<div></div>",
43407        buildRendering: function () {
43408            return this._containerNode;
43409        },
43410        postCreate: function () {
43411            return this.inherited(arguments);
43412        },
43413        /**
43414        * @returns {Object} The dom node reference this widget encapsulates.
43415        */
43416        getDomNode: function ()
43417        {
43418            return this._containerNode;
43419        },
43420        /**
43421        * Either shows or hides the content.
43422        * @returns {void}
43423        */
43424        toggle: function ()
43425        {
43426            if (this._hidden) {
43427                this._hidden = false;
43428                style.set(this._containerNode, { display: this._showStyle });
43429            }
43430            else {
43431                this._hidden = true;
43432                style.set(this._containerNode, { display: this._hideStyle });
43433            }
43434        },
43435        /**
43436        * Is the content shown or hidden
43437        * @returns {bool} 
43438        */
43439        isHidden: function ()
43440        {
43441            return this._hidden;
43442        },
43443        /**
43444        * Show the content
43445        * @returns {void}
43446        */
43447        expand: function ()
43448        {
43449            if (this._hidden)
43450                this.toggle();
43451        },
43452        /**
43453        * Hide the content
43454        * @returns {void}
43455        */
43456        collapse: function ()
43457        {
43458            if (!this._hidden)
43459                this.toggle();
43460        }
43461    });
43462});
43463
43464},
43465'dpage/widgets/InlineValidationMessage':function(){
43466define([
43467      "dojo/_base/event"
43468      ,"dojo/on"
43469      ,"dojo/dom-attr"
43470      ,"dojo/dom-class"
43471      ,"dojo/mouse"
43472      ,"dojo/dom-geometry"
43473      , "dojo/dom-style"
43474      , "dojo/json"
43475
43476      , "xstyle/css!dpage/widgets/InlineValidationMessage.css"
43477      , "dojo/request/xhr"
43478      ,"dojox/html/entities"
43479      ,"dojo/_base/declare"
43480      , "dpage/widgets/ValidationMessage"],
43481function (event, on, domAttr, domClass, mouse, domGeom, style, json) {
43482    /**
43483    * @namespace dpage
43484    */
43485    /**
43486    * @namespace widgets
43487    * @memberOf dpage
43488    */
43489    /**
43490    * Implementation of a ValidationMessage that shows messages in-line with the content of the container. 
43491    * @class InlineValidationMessage
43492    * @param {Object} [options] Optional options for the widget.
43493    * @param {String} [options.dataField] The field (column name) this widget is bound to.
43494         
43495    * @param {dpage.modules.TabularModel} [options.model] The model to use.
43496    * @param {dpage.widgets.Container} [options.container] The container of the widget.
43497    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
43498    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
43499    *                               is created.
43500    * @param {Object} [containerNode] Optional container node to tie the widget to.
43501    * @memberOf dpage.widgets
43502    * @extends {dpage.widgets.ValidationMessage}
43503    */
43504    return dojo.declare("dpage.widgets.InlineValidationMessage", [dpage.widgets.ValidationMessage], /** @lends dpage.widgets.InlineValidationMessage.prototype */ {
43505        _containerNode: null,
43506        _errors: null,
43507        constructor: function (options, srcNodeRef)
43508        {
43509            this._errors = [];
43510            var self = this;
43511            this._containerNode = srcNodeRef;
43512        },
43513        _updateView : function()
43514        {
43515            //set up the data.
43516            this.inherited(arguments);
43517
43518            domClass.remove(this._containerNode, "validation-message");
43519            this._containerNode.innerHTML = "";
43520
43521            if (this._errors.length > 0) {
43522                domClass.add(this._containerNode, "validation-message");
43523                ul = document.createElement("UL");
43524                this._containerNode.appendChild(ul);
43525            }
43526
43527            for (var idx = 0; idx < this._errors.length ; idx++) {
43528                var obj = this._errors[idx];
43529
43530                var li = document.createElement("LI");
43531
43532                li.innerHTML = dojox.html.entities.encode(obj.message);
43533
43534                ul.appendChild(li);
43535            }
43536        }
43537   });
43538});
43539
43540},
43541'dpage/widgets/Label':function(){
43542define([
43543      "dojo/_base/event"
43544      ,"dojo/on"
43545      ,"dojo/dom-attr"
43546      ,"dojo/dom-class"
43547      ,"dojo/mouse"
43548      ,"dojo/dom-geometry"
43549      , "dojo/dom-style"
43550      , "dojo/json"
43551
43552      , "dpage/modules/Date"
43553      , "dpage/modules/TabularModel"
43554      , "dojo/request/xhr"
43555      ,"dojox/html/entities"
43556      ,"dojo/_base/declare"
43557      , "dpage/widgets/SingleValueWidget"],
43558function (event, on, domAttr, domClass, mouse, domGeom, style, json) {
43559    /**
43560    * @namespace dpage
43561    */
43562    /**
43563    * @namespace widgets
43564    * @memberOf dpage
43565    */
43566    /**
43567    * Class to encapulate blocks of text on a page. The label can be bound to data which is where it makes the most sense.
43568    * If the datatype of the model is DATE, the default date formatter is used to display it (dpage.modules.Date.formatDate())
43569    * @class Label
43570    * @param {Object} [options] Optional options for the widget.
43571    * @param {bool} [options.noHTMLEncode] Dont' html encode the display data if set to true (not recommended).
43572    * @param {bool} [options.encodeSpace] Default false. If true AND noHTMLEncode==false, encode space characters as &amp;nbsp; so that a user can see the whitespace.
43573    * @param {Function} [options.formatter] Function that will be used to format the data. The raw value is passed as a single param. Return the value
43574    *                                       to display.
43575    * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget.
43576    * @param {dpage.widgets.Container} [options.container] The container of the widget.
43577    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
43578    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
43579    *                               is created.
43580    * @param {Object} [containerNode] Optional container node to tie the widget to.
43581    * @memberOf dpage.widgets
43582    * @extends {dpage.widgets.SingleValueWidget}
43583     */
43584    return dojo.declare("dpage.widgets.Label", [dpage.widgets.SingleValueWidget], /** @lends dpage.widgets.Label.prototype */ {
43585        _containerNode: null,
43586        _dataType: null,
43587        _formatter: null,
43588        _htmlEncode: true,
43589        _encodeSpace:false,
43590
43591        constructor: function (options, srcNodeRef)
43592        {
43593            var self = this;
43594            this._containerNode = srcNodeRef;
43595
43596            if (this._containerNode == null) {
43597                this._containerNode = document.createElement("SPAN");
43598            }
43599
43600            if (this._containerNode.nodeName != "SPAN" && this._containerNode.nodeName != "DIV" && this._containerNode.nodeName != "LABEL")
43601                throw new Error("Source node for dpage.widgets.Label must be an SPAN or a DIV or a LABEL.");
43602
43603            if (options != null)
43604            {
43605                if (options.formatter != null)
43606                    this._formatter = options.formatter;
43607                if (options.noHTMLEncode)
43608                    this._htmlEncode = false;
43609                if (options.encodeSpace !== undefined)
43610                    this._encodeSpace = options.encodeSpace;
43611            }
43612        },
43613        /** HTML encode the model value or not. Default is to encode. Do not pass in a false value unless you know what you are doing.
43614        * @param {bool} trueOrFalse Encode or not.
43615        * @returns {void}
43616        */
43617        setHTMLEncode : function(val){
43618            this._htmlEncode = val;
43619        },
43620        setModel : function(model)
43621        {
43622            this.inherited(arguments);
43623
43624            this._updateView();
43625        },
43626        _renderText : function(rawValue)
43627        {
43628            var dVal = this.renderText(rawValue);
43629
43630            if (dVal == null)
43631                dVal = "";
43632
43633            if (this._htmlEncode) {
43634                dVal = dojox.html.entities.encode(dVal);
43635
43636                if (this._encodeSpace) {
43637                    dVal = dVal.replace(/ /g, "&nbsp;");
43638                }
43639            }
43640
43641            return dVal;
43642        },
43643        /** Can be overridden by a subclass. formats the text that is displayed.
43644        * @param {String} rawValue the value to render.
43645        * @returns {String} value to display (will be html-encoded unless overridden)
43646        */
43647        renderText : function(rawValue)
43648        {
43649            //if a formatter function is specified, use it to render the text.
43650            if (this._formatter != null)
43651                return this._formatter(rawValue);
43652            else if (this.getModel().getMetadata().DataType == "DATE")
43653                return dpage.modules.Date.formatDate(dpage.modules.Date.parseModelValue(rawValue));
43654            else
43655                return rawValue;
43656        },
43657        _updateView : function()
43658        {
43659            var vtd = this.getValue();
43660
43661            if (vtd == null)
43662                vtd = "";
43663
43664            this._containerNode.innerHTML = this._renderText(vtd.toString());
43665        },
43666        templateString: "<div></div>"
43667   });
43668});
43669
43670},
43671'dpage/widgets/OKCancelDialog':function(){
43672define([
43673      "dojo/_base/declare"
43674      , "dojo/on"
43675      , "dojo/_base/event"
43676      , "jQueryPrivate"
43677
43678      , "dojox/html/entities"
43679      , "dpage/widgets/Dialog"
43680],
43681    function (declare, on, event, $) {
43682    /**
43683    * @namespace dpage
43684    */
43685    /**
43686    * @namespace widgets
43687    * @memberOf dpage
43688    */
43689    /**
43690    * An easy way of showing a simple dialog with an OK and Cancel button with some text. Text is html encoded so it is rendered as plain text.
43691    * @class OKCancelDialog
43692    * @param {Object} [options] Optional options for the widget
43693    * @param {String} [options.text] The text to display in the dialog.
43694    * @param {Function} [options.OKCallback] Callback for OK click.
43695
43696    * @param {String} [options.title] The title to display in the title bar of the dialog.
43697    * @param {bool}   [options.noDefaultCSS] Default false. If true, no css will be required in for the widget.
43698    * @param {Number} [options.height] The height of the dialog.
43699    * @param {Number} [options.width] The width of the dialog.
43700    * @param {bool}   [options.OKButton] Display an OK button or not that will close the dialog. Default is false for no button.
43701    * @param {Object} [options.model] Data destined for Container child controls. This is an object where each property value is a dpage.modules.TabularModel *or*
43702    *                                 an object that conforms to the structure that can be used to pass to the dpage.modules.TabularModel constructor in the model property.
43703    * @param {bool} [options.parseNow] (defaults to true) If true, then parse the container for child widgets now. If false, wait for domReady.
43704    * @param {function} [options.widgetsParsedCallback] callback function for when widgets in this container are parsed.
43705    * @param {String} [options.templateString] Optional template for this container. If provided will instantiate a container with the provided
43706    *                                          markup. As with all containers, the markup can contain widgets that can be accessed through
43707    *                                          getWidget() or getWidgets().
43708    * @param {dpage.widgets.Container} [options.container] The container of the widget.
43709    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
43710    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
43711    *                               is created.
43712    * @param {Object} [containerNode] Optional container node to tie the widget to.
43713    * @memberOf dpage.widgets
43714    * @extends {dpage.widgets.Dialog}
43715    */
43716        return declare("dpage.widgets.OKCancelDialog", [dpage.widgets.Dialog], /** @lends dpage.widgets.OKCancelDialog.prototype */ {
43717            _OKCallback : null
43718            , constructor: function (options) {
43719                var title = "";
43720                if(options != null)
43721                {
43722                    if (options.title != null) {
43723                        title = dojox.html.entities.encode(options.title).replace("\"", "&quot;");
43724                    }
43725
43726                    if (options.text != null){
43727                        this.templateString="<DIV title=\"" + title + "\"><p style='text-align:center'>" + dojox.html.entities.encode(options.text.toString()) + "</p></DIV>";
43728                    }
43729
43730                    if (options.OKCallback != null)
43731                        this._OKCallback = options.OKCallback;
43732                }
43733                
43734            }
43735            , templateString: "<div></div>"
43736            , buildRendering: function () {
43737                return this.inherited(arguments);
43738            }
43739            , postCreate : function()
43740            {
43741                var self = this;
43742                var options = {
43743                    autoOpen: false,
43744                    modal: true,
43745                    buttons: {
43746                        "OK": function () { self.close(); self.OKClicked(); }
43747                        , "Cancel": function () { self.close(); }
43748                    }
43749                };
43750
43751                if (this._height)
43752                    options.height = this._height;
43753                if (this._width)
43754                    options.width = this._width;
43755
43756                this._dialog = $(this.domNode).dialog(options);
43757            }
43758            ,OKClicked : function()
43759            {
43760                if (this._OKCallback != null)
43761                    this._OKCallback();
43762            }
43763        });
43764    }
43765);
43766},
43767'dpage/widgets/Select':function(){
43768define([
43769      "dojo/_base/event"
43770      , "dojo/on"
43771      , "dojo/dom-attr"
43772      , "dojo/dom-class"
43773      , "dojo/mouse"
43774      , "dojo/dom-geometry"
43775      , "dojo/dom-style"
43776      , "dojo/json"
43777
43778      , "xstyle/css!dpage/widgets/Select.css"
43779      , "dpage/modules/LegacyPlaceholder"
43780      , "dpage/modules/TabularModel"
43781      , "dojo/request/xhr"
43782      , "dpage/modules/Encoding"
43783      , "dojo/_base/declare"
43784      , "dpage/widgets/SingleValueWidget"],
43785function (event, on, domAttr, domClass, mouse, domGeom, style, json ) {
43786    /**
43787    * @namespace dpage
43788    */
43789    /**
43790    * @namespace widgets
43791    * @memberOf dpage
43792    */
43793    /**
43794    * Widget to provide a drop down list control bound to data.
43795    * @class Select
43796    * @param {Object} [options] Optional options for the widget.
43797    * @param {dpage.modules.TabularModel} [options.optionsModel] Will create a list of &lt;option&gt;'s for the &lt;select&gt;. If passed, will overwrite the existing &lt;options&gt;. If not
43798    *                                                            passed, the existing &lt;option&gt;'s will be used. The options are <b>NOT</b> re-rendered based on model changes. In other words,
43799    *                                                            changes to the optionsModel will not be reflected in the select options.
43800    * @param {String} [options.optionsModelPropValue] Property to use for the value in the options. Valid only when using a options.optionsModel. <b>The property values in the model must be a unique list of values to work properly</b>
43801    *                                                 This is how the model data for the widget is linked to the optionsModel data for the options. 
43802    * @param {String} [options.optionsModelPropText] Property to use for the display value in the options. Valid only when using a options.optionsModel
43803    * @param {Function} [options.onChange] callback function for when widget value changes from user input. May or may not correspond to a model value change in the case of invalid input. This event will fires *after* the validation happens. You cannot cancel at this point.
43804    *                                      The callback function definition is bool callback({event : eventObj , widget : widgetThatFiredEvent})
43805    * @param {Function} [options.onPreChange] callback function for when widget value changes from user input. This event will fire before any validation. The widget (and backing model) will always contain the old value. You can return back a false value from your callback to cancel further processing of the event (including cancelling validation and value setting of the widget (and model)).
43806    *                                      The callback function definition is bool callback({event : eventObj , widget : widgetThatFiredEvent , newValue : theNewValue})
43807    * @param {String} [options.defaultValue] If provided, this will add an option to the top of the list of options with the supplied value. If defaultText is not provided, the display will
43808    *                                        also show this value.
43809    * @param {String} [options.defaultText] Assumes defaultValue was also provided. If supplied, this will be the text of the default option.
43810    * @param {bool} [options.defaultSelectable] default true. Assumes defaultValue was provided. Controls whether the user can select the default option.
43811
43812    * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget.
43813    * @param {dpage.widgets.Container} [options.container] The container of the widget.
43814    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
43815    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
43816    *                               is created.
43817    * @param {Object} [containerNode] Optional container node to tie the widget to.
43818    * @memberOf dpage.widgets
43819    * @extends {dpage.widgets.SingleValueWidget}
43820    */
43821    var theClass = dojo.declare("dpage.widgets.Select", [dpage.widgets.SingleValueWidget], /** @lends dpage.widgets.Select.prototype */ {
43822        _containerNode: null,
43823        _optionsModel: null,
43824        _optionsModelPropValue: null,
43825        _optionsModelPropText: null,
43826        _onChange: null,//must be null here and set in the constructor otherwise it acts like a static var.
43827        _onPreChange: null,
43828        _addDefaultOption: false,
43829        _defaultValue: null,
43830        _defaultText: null,
43831        _defaultSelectable: true,
43832
43833        constructor: function (options, srcNodeRef) {
43834            var self = this;
43835            this._containerNode = srcNodeRef;
43836
43837            this._onChange = [];
43838            this._onPreChange = [];
43839
43840            if (this._containerNode == null) {
43841                this._containerNode = document.createElement("SELECT");
43842            }
43843
43844            if (this._containerNode.nodeName != "SELECT")
43845                throw new Error("Source node for dpage.widgets.Select must be a SELECT.");
43846
43847            if (options != null) {
43848                if (options.optionsModel != null) {
43849                    this._optionsModel = options.optionsModel;
43850                }
43851                if (options.optionsModelPropValue != null)
43852                    this._optionsModelPropValue = options.optionsModelPropValue;
43853                if (options.optionsModelPropText != null)
43854                    this._optionsModelPropText = options.optionsModelPropText;
43855
43856                if (options.onChange != null) {
43857                    this._onChange.push(options.onChange);
43858                }
43859
43860                if (options.onPreChange != null) {
43861                    this._onPreChange.push(options.onPreChange);
43862                }
43863
43864                if (options.defaultValue !== undefined){
43865                    this._defaultValue = options.defaultValue;
43866                    this._addDefaultOption = true;
43867                }
43868
43869                if(options.defaultText !== undefined)
43870                {
43871                    if (!this._addDefaultOption)
43872                        throw new Error("WidgetId: " + this.getWidgetId() + ". To use the defaultText option you must pass the defaultValue option.");
43873                    this._defaultText = options.defaultText;
43874                }
43875                else{
43876                    if(this._addDefaultOption)
43877                        this._defaultText = this._defaultValue;
43878                }
43879
43880                if (options.defaultSelectable !== undefined) {
43881                    if(!this._addDefaultOption)
43882                        throw new Error("WidgetId: " + this.getWidgetId() + ". To use the defaultSelectable option you must pass the defaultValue option.");
43883                    this._defaultSelectable = options.defaultSelectable;
43884                }
43885            }
43886
43887            if (this._optionsModel != null && this._optionsModelPropValue == null)
43888                throw new Error("Must pass in a optionsModelPropValue property to a dpage.widgets.Select.")
43889
43890            //set to the same as value if not passed in.
43891            if (this._optionsModelPropText == null)
43892                this._optionsModelPropText = this._optionsModelPropValue;
43893
43894            if (this._optionsModel != null) {
43895                if (this._optionsModel.isInstanceOf == null || !this._optionsModel.isInstanceOf(dpage.modules.TabularModel))
43896                    throw new Error("The optionsModel property must be of type dpage.modules.TabularModel");
43897            }
43898
43899            on(this._containerNode, "blur", function (event) { self.select_OnBlur(event); });
43900            on(this._containerNode, "focus", function (event) { self.select_OnFocus(event); });
43901            on(this._containerNode, "change", function (event) { self.select_OnChange(event); });
43902            on(this._containerNode, "keydown" , function (event) {return self.select_KeyDown(event);});
43903        },
43904        postCreate : function()
43905        {
43906            //BaseWidget calls _updateView()
43907            this.inherited(arguments);
43908
43909            //_updateView will not highlight the value if _optionsModel == null.
43910            if (this._optionsModel != null)
43911            {
43912                this._highlightValue();
43913            }
43914        },
43915        _highlightValue: function () {
43916            var modelVal;
43917            var foundVal = false;
43918            var newOption;
43919            var self = this;
43920
43921            modelVal = this.getValue();
43922
43923            for (var x = 0; x < this._containerNode.options.length; x++) {
43924                if (
43925                       (modelVal != null && this._containerNode.options[x].value == modelVal
43926                       && (modelVal != "" || this._containerNode.options[x].getAttribute('data-isnull') != 'true'))
43927                    ||
43928                       (modelVal == null && this._containerNode.options[x].getAttribute('data-isnull') == 'true')
43929                    ) {
43930                    this._containerNode.selectedIndex = x;
43931                    foundVal = true;
43932                }
43933            }
43934
43935            if (!foundVal) {
43936                var v = modelVal;
43937
43938                if (v == null) {
43939                    newOption = new Option("", "");
43940                    newOption.setAttribute("data-isnull", "true");
43941                }
43942                else
43943                    newOption = new Option(v, v);
43944
43945                //on(newOption, "keydown", function (event) { return self.select_KeyDown(event); });
43946                this._containerNode.options[this._containerNode.options.length] = newOption;
43947                this._containerNode.selectedIndex = this._containerNode.options.length - 1;
43948            }
43949        },
43950        //Redraws the entire select, highlighting the current value.
43951        // Cross-browser way of redrawing the select FAST.
43952        _updateView : function()
43953        {
43954            var valFound;
43955            var self = this;
43956            var newOption;
43957            var optionArray = [];
43958            var val;
43959            var text;
43960
43961            //call the base class (BaseWidget). This clears the validation state common to all BaseWidget _updateView methods.
43962            this.inherited(arguments);
43963
43964            if (this._optionsModel == null)
43965                return;
43966
43967            //determine whether we have support for innerHTML to set options. If so, use it because it is a much faster
43968            // way of building the options.
43969            if (dpage.widgets.Select._innerHTMLWorks == null)
43970            {
43971                var select = document.createElement("SELECT");
43972                select.innerHTML = "<option></option>";
43973                if (select.options.length == 0)
43974                    dpage.widgets.Select._innerHTMLWorks = false;
43975                else
43976                    dpage.widgets.Select._innerHTMLWorks = true;
43977            }
43978
43979            if (dpage.widgets.Select._innerHTMLWorks) {
43980
43981                //add a default option if needed.
43982                if (this._addDefaultOption) {
43983                    val = this._defaultValue;
43984                    text = this._defaultText;
43985
43986                    if (text == null)
43987                        text = "";
43988
43989                    if (val == this.getValue()) {
43990                        valFound = true;
43991                        if (val == null)
43992                            optionArray.push("<option value=\"\" " + ((this._addDefaultOption && this._defaultSelectable == false) ? " disabled hidden " : "") + " data-isnull='true' selected='selected'>" + dpage.modules.Encoding.htmlEncode(text.toString()) + "</option>");
43993                        else
43994                            optionArray.push("<option value=\"" + dpage.modules.Encoding.htmlEncode(val.toString()) + "\"" + ((this._addDefaultOption && this._defaultSelectable == false) ? " disabled hidden " : "") + " selected='selected'>" + dpage.modules.Encoding.htmlEncode(text.toString()) + "</option>");
43995                    }
43996                    else {
43997                        if (val == null)
43998                            optionArray.push("<option value=\"\"" + ((this._addDefaultOption && this._defaultSelectable == false) ? " disabled hidden " : "") + " data-isnull='true'>" + dpage.modules.Encoding.htmlEncode(text.toString()) + "</option>");
43999                        else
44000                            optionArray.push("<option value=\"" + dpage.modules.Encoding.htmlEncode(val.toString()) + "\" " + ((this._addDefaultOption && this._defaultSelectable == false) ? " disabled hidden " : "") + ">" + dpage.modules.Encoding.htmlEncode(text.toString()) + "</option>");
44001                    }
44002                }
44003
44004                for (var x = 0; x < this._optionsModel.getRows().length ; x++) {
44005                    val = this._optionsModel.getValue(x, this._optionsModelPropValue);
44006                    text = this._optionsModel.getValue(x, this._optionsModelPropText);
44007
44008                    if (text == null)
44009                        text = "";
44010
44011                    if (val == this.getValue()) {
44012                        valFound = true;
44013                        if (val == null)
44014                            optionArray.push("<option value=\"\" data-isnull='true' selected='selected'>" + dpage.modules.Encoding.htmlEncode(text.toString()) + "</option>");
44015                        else
44016                            optionArray.push("<option value=\"" + dpage.modules.Encoding.htmlEncode(val.toString()) + "\" selected='selected'>" + dpage.modules.Encoding.htmlEncode(text.toString()) + "</option>");
44017                    }
44018                    else {
44019                        if (val == null)
44020                            optionArray.push("<option value=\"\" data-isnull='true'>" + dpage.modules.Encoding.htmlEncode(text.toString()) + "</option>");
44021                        else
44022                            optionArray.push("<option value=\"" + dpage.modules.Encoding.htmlEncode(val.toString()) + "\">" + dpage.modules.Encoding.htmlEncode(text.toString()) + "</option>");
44023                    }
44024                }
44025
44026                this._containerNode.innerHTML = optionArray.join("");
44027            }
44028            else
44029            {
44030                //add in the default option if we have one.
44031                if (this._addDefaultOption) {
44032                    val = this._defaultValue;
44033                    text = this._defaultText;
44034                    var o;
44035
44036                    if (text == null)
44037                        text = "";
44038
44039                    if (val == this.getValue()) {
44040                        valFound = true;
44041                        if (val == null) {
44042                            o = new Option(text, "", true, true);
44043                            o.setAttribute('data-isnull', 'true');
44044                        }
44045                        else {
44046                            o = new Option(text, val, true, true);
44047                        }
44048                    }
44049                    else {
44050                        if (val == null) {
44051                            o = new Option(text, val);
44052                            o.setAttribute('data-isnull', 'true');
44053                        }
44054                        else{
44055                            o =new Option(text, val);
44056                        }
44057                    }
44058
44059                    this._containerNode.options[this._containerNode.options.length] = o;
44060                    if (this._addDefaultOption && this._defaultSelectable == false) {
44061                        o.setAttribute("disabled", true);
44062                        o.setAttribute("hidden", true);
44063                    }
44064
44065                }
44066
44067                //pretty much a custom solution for IE9.
44068                this._containerNode.options.length = 0;
44069                for (var x = 0; x < this._optionsModel.getRows().length ; x++) {
44070                    var val = this._optionsModel.getValue(x, this._optionsModelPropValue);
44071                    var text = this._optionsModel.getValue(x, this._optionsModelPropText);
44072
44073                    if (text == null)
44074                        text = "";
44075
44076                    if (val == this.getValue()) {
44077                        valFound = true;
44078                        if (val == null) {
44079                            var o = new Option(text, "", true, true);
44080                            o.setAttribute('data-isnull', 'true');
44081                            this._containerNode.options[this._containerNode.options.length] = o;
44082                        }
44083                        else
44084                            this._containerNode.options[this._containerNode.options.length] = new Option(text, val, true, true);
44085                    }
44086                    else {
44087                        if (val == null) {
44088                            var o = new Option(text, val);
44089                            o.setAttribute('data-isnull', 'true');
44090                            this._containerNode.options[this._containerNode.options.length] = o;
44091                        }
44092                        else
44093                            this._containerNode.options[this._containerNode.options.length] = new Option(text, val);
44094                    }
44095                }
44096            }
44097
44098            if (!valFound) {
44099                var v = this.getValue();
44100
44101                if (v == null) {
44102                    newOption = new Option("", "");
44103                    newOption.setAttribute("data-isnull", "true");
44104                }
44105                else
44106                    newOption = new Option(v, v);
44107
44108                //on(newOption, "keydown", function (event) { return self.select_KeyDown(event); });
44109                this._containerNode.options[this._containerNode.options.length] = newOption;
44110                this._containerNode.selectedIndex = this._containerNode.options.length - 1;
44111            }
44112        },
44113        /**
44114        * Set a TabularModel that contains all of the options for the MultiSelect. Will erase existing options and replace them with the ones in the optionsModel.
44115        * If a value in the model is not contained in the optionsModel, a option is added to the select but not to the optionsModel. The optionsModel is read-only.
44116        * @param {dpage.modules.TabularModel} model
44117        * @param {String} propValue The property name in the TabularModel to use for the value
44118        * @param {String} propText The property name in the TabularModel to use for the text (display)
44119        * @returns {void}
44120        */
44121        setOptionsModel: function (model, propValue, propText) {
44122            this._optionsModel = model;
44123
44124            //TODO: Need to hook up to the optionsModel change events to redraw the select when rows added/removed/changed.
44125
44126            if (propValue != null)
44127                this._optionsModelPropValue = propValue;
44128            if (propText != null)
44129                this._optionsModelPropText = propText;
44130
44131            this._updateView();
44132        },
44133        //set a tabular model.
44134        setModel: function (model) {
44135
44136            this.inherited(arguments);
44137
44138            this._highlightValue();
44139        },
44140        select_OnFocus: function () {
44141
44142        },
44143        select_OnBlur: function () {
44144        },
44145        select_KeyDown: function (e) {
44146            //This event does not fire for some odd reason in Chrome, but works in IE and firefox. Only seems to affect a single select not the multi-select.
44147            if (e.keyCode == 8) {
44148                event.stop(e);
44149            }
44150        },
44151        /**
44152        * Get the current selected value from the control. This method differs from getValue(). getValue() returns the model value. This method returns the selected value which
44153        * won't correspond to the model value if the selected value is not a valid value for the model property. For instance, the field may be required and the user may have 
44154        * selected the null value. In this case, calling this method will return null, whereas calling getValue() will return you the last valid value.
44155        * @returns {Object}
44156        */
44157        getSelectedValue : function() {
44158            return this.getDomNode().value;
44159        },
44160        /**
44161        * Focus the control
44162        * @returns {void}
44163        */
44164        focus: function () {
44165            this.getDomNode().focus();
44166        },
44167        select_OnChange: function (evt) {
44168            var self = this;
44169            var selectVal;
44170
44171            selectVal = this.getDomNode().value;
44172
44173            //check for a null value.
44174            if (selectVal == "" 
44175                &&
44176                this.getDomNode().options[this.getDomNode().selectedIndex].getAttribute('data-isnull') == 'true') {
44177                selectVal = null;
44178            }
44179
44180            //call callbacks in order.
44181            for (var i = 0; i < this._onPreChange.length; i++) {
44182                if (this._onPreChange[i]({ event: evt, widget: self, newValue: selectVal}) == false) {
44183                    //prevent further action.
44184                    evt.preventDefault();
44185                    //select the current (old) value.
44186                    this._highlightValue();
44187                    return false;
44188                }
44189            }
44190
44191            if (this.validate() == null) {
44192                if (this.getContainer()) {
44193                    if (this.getContainer().getValidationMessageWidget()) {
44194                        this.getContainer().getValidationMessageWidget().removeErrorByWidgetID(this.getWidgetId());
44195                    }
44196                }
44197
44198                this.setModelValue(selectVal);
44199            }
44200
44201            //call callbacks in order.
44202            for (var i = 0; i < this._onChange.length; i++)
44203                this._onChange[i]({ event: evt, widget: self });
44204        },
44205        //Override the default action to re-draw the entire widget.
44206        _modelChanged: function () {
44207            this._highlightValue();
44208        },
44209        templateString: "<div></div>",
44210        /**
44211        * Set an event handler. Refer to the constructor options for more information on event types.
44212        * @param {String} eventName The event to bind to. Only supported events are "change" and "prechange".
44213        * @param {function} functionRef The callback function to call.
44214        * @returns {void}
44215        */
44216        on: function (eventName, functionRef) {
44217            var self = this;
44218
44219            if (eventName == "change")
44220                this._onChange.push(functionRef);
44221            else if (eventName == "prechange")
44222                this._onPreChange.push(functionRef);
44223            else
44224                throw new Error("Supported events are: 'change'.");
44225        },
44226        validate: function () {
44227            var value = this._containerNode.value;
44228            var ret;
44229
44230            ret = dpage.widgets.BaseWidget.validate(value, this.getModel().getMetadata(), this.getModel().getDisplayName());
44231
44232            this.setValidationMessage(ret);
44233
44234            return ret;
44235        },
44236        setValidationMessage: function (message) {
44237            this.inherited(arguments);
44238
44239            domClass.remove(this._containerNode, "dpage-widgets-Select-input-invalid");
44240
44241            if (message != null)
44242                domClass.add(this._cont
44242ainerNode, "dpage-widgets-Select-input-invalid");
44243        }
44244
44245    });
44246
44247    theClass._innerHTMLWorks = null;
44248
44249    return theClass;
44250});
44251
44252},
44253'dpage/modules/Encoding':function(){
44254define(["dojo/_base/declare",
44255
44256        "dojox/html/entities"
44257],
44258    function (declare) {
44259        /**
44260        * @namespace dpage
44261        */
44262        /**
44263        * @namespace modules
44264        * @memberOf dpage
44265        */
44266        /**
44267         * Provides common encoding routines.
44268         * @class Encoding
44269         * @memberOf dpage.modules
44270         */
44271        var theClass = declare("dpage.modules.Encoding", [], /** @lends dpage.modules.Encoding.prototype */ {
44272
44273            constructor: function (options) {
44274                var self = this;
44275            }
44276        });
44277
44278        /** Encodes a string encoded for use in an html document, including inside html attributes.
44279        * @memberof dpage.modules.Encoding
44280        * @name htmlEncode
44281        * @function 
44282        * @param {String} strIn The string to encode.
44283        * @returns {String}
44284        */
44285        theClass.htmlEncode = function (strIn) {
44286            return dojox.html.entities.encode(strIn).replace(/'/g , "&#39;").replace(/"/g , "&quot;");
44287        };
44288
44289        return theClass;
44290    }
44291);
44292},
44293'dpage/widgets/MultiSelect':function(){
44294define([
44295      "dojo/_base/event"
44296      , "dojo/on"
44297      , "dojo/dom-attr"
44298      , "dojo/dom-class"
44299      , "dojo/mouse"
44300      , "dojo/dom-geometry"
44301      , "dojo/dom-style"
44302      , "dojo/json"
44303
44304      , "xstyle/css!dpage/widgets/TextBox.css"
44305      , "dpage/modules/LegacyPlaceholder"
44306      , "dpage/modules/TabularModel"
44307      , "dojo/request/xhr"
44308      , "dojox/html/entities"
44309      , "dojo/_base/declare"
44310      , "dpage/widgets/MultiValueWidget"],
44311function (event, on, domAttr, domClass, mouse, domGeom, style, json) {
44312    /**
44313    * @namespace dpage
44314    */
44315    /**
44316    * @namespace widgets
44317    * @memberOf dpage
44318    */
44319    /**
44320     * Widget to provide a multi-select list control bound to data.
44321     * @class MultiSelect
44322     * @param {Object} [options] Optional options for the widget.
44323     * @param {String} [options.dataField] The field (column name) this widget is bound to.
44324     * @param {dpage.modules.TabularModel} [options.optionsModel] Will create a list of &lt;option&gt;'s for the &lt;select&gt;. If passed, will overwrite the existing &lt;options&gt;. If not
44325     *                                                            passed, the existing &lt;option&gt;'s will be used.
44326     * @param {String} [options.optionsModelPropValue] Property to use for the value in the options. Valid only when using a options.optionsModel
44327     * @param {String} [options.optionsModelPropText] Property to use for the display value in the options. Valid only when using a options.optionsModel
44328     * @param {dpage.modules.TabularModel} [options.model] The model to use.
44329     * @param {dpage.widgets.Container} [options.container] The container of the widget.
44330     * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
44331     * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
44332     *                               is created.
44333     * @param {Object} [containerNode] Optional container node to tie the widget to.
44334     * @memberOf dpage.widgets
44335     * @extends {dpage.widgets.MultiValueWidget}
44336     */
44337    return dojo.declare("dpage.widgets.MultiSelect", [dpage.widgets.MultiValueWidget], /** @lends dpage.widgets.MultiSelect.prototype */ {
44338        _containerNode: null,
44339        _optionsModel: null,
44340        _optionsModelPropValue: null,
44341        _optionsModelPropText: null,
44342        _dataField: null,
44343        constructor: function (options, srcNodeRef) {
44344            var self = this;
44345            this._containerNode = srcNodeRef;
44346
44347            if (this._containerNode == null) {
44348                this._containerNode = document.createElement("SELECT");
44349                this._containerNode.setAttribute("multiple" , "multiple");
44350            }
44351
44352            if (this._containerNode.nodeName != "SELECT" || this._containerNode.getAttribute("multiple") == null || this._containerNode.getAttribute("multiple").toUpperCase() != "MULTIPLE")
44353                throw new Error("Source node for dpage.widgets.Select must be a SELECT multiple='multiple'");
44354
44355            if (options != null) {
44356                if (options.placeholder != null) {
44357                    this._placeholder = options.placeholder;
44358                }
44359                if (options.optionsModel != null) {
44360                    if (options.optionsModel.isInstanceOf == null || !options.optionsModel.isInstanceOf(dpage.modules.TabularModel))
44361                        throw new Error("optionsModel must be an instance of dpage.modules.TabularModel.");
44362                    this._optionsModel = options.optionsModel;
44363                }
44364                if (options.optionsModelPropValue != null)
44365                    this._optionsModelPropValue = options.optionsModelPropValue;
44366                if (options.optionsModelPropText != null)
44367                    this._optionsModelPropText = options.optionsModelPropText;
44368                if (options.dataField == null){
44369                    if (options.model == null)
44370                        this._dataField = this.getModel().getColumns()[0].ColumnName;
44371                    else
44372                        throw new Error("Must pass the dataField property to dpage.widgets.MultiSelect. ");
44373                }
44374                else
44375                    this._dataField = options.dataField;
44376            }
44377
44378            if (this._optionsModel != null && this._optionsModelPropValue == null)
44379                throw new Error("Must pass in a optionsModelPropValue property to a dpage.widgets.Select")
44380
44381            //set to the same as value if not passed in.
44382            if (this._optionsModelPropText == null)
44383                this._optionsModelPropText = this._optionsModelPropValue;
44384
44385            on(this._containerNode, "blur", function () { self.select_OnBlur(event); });
44386            on(this._containerNode, "focus", function () { self.select_OnFocus(event); });
44387            on(this._containerNode, "change", function () { self.select_OnChange(event); });
44388        },
44389        postCreate: function () {
44390
44391            this._updateView();
44392        },
44393
44394        _highlightValues: function () {
44395            var valLookup = {};
44396
44397            //used for fast lookup for selection.
44398            for (var i = 0; i < this.getModel().getRows().length; i++) {
44399                valLookup[this.getModel().getValue(i, this._dataField)] = 1;//1 means we need to select an option. 2 means we have selected the option.
44400            }
44401
44402            for (var x = 0; x < this._containerNode.options.length; x++) {
44403                if (valLookup[this._containerNode.options[x].value]) {
44404                    this._containerNode.options[x].selected = true;
44405                    valLookup[this._containerNode.options[x].value] = 2;
44406                }
44407                else
44408                    this._containerNode.options[x].selected = false;
44409            }
44410
44411            //add rows from the model that are not contained in the options model.
44412            for (var i = 0; i < this.getModel().getRows().length; i++) {
44413                if (valLookup[this.getModel().getValue(i, this._dataField)] != 2) {
44414                    this._containerNode.options[this._containerNode.options.length] = new Option(this.getModel().getValue(i, this._dataField), this.getModel().getValue(i, this._dataField), false, true);
44415                }
44416            }
44417        },
44418
44419        _updateView : function(){
44420            var valLookup = {};
44421
44422            if (this._optionsModel == null)
44423                return;
44424
44425            this._containerNode.innerHTML = "";
44426
44427            //used for fast lookup for selection.
44428            for (var i = 0; i < this.getModel().getRows().length; i++) {
44429                valLookup[this.getModel().getValue(i, this._dataField)] = 1;//1 means we need to select an option. 2 means we have selected the option.
44430            }
44431
44432            if (this._optionsModel != null) {
44433                for (var x = 0; x < this._optionsModel.getRows().length ; x++) {
44434                    var val = this._optionsModel.getValue(x, this._optionsModelPropValue);
44435                    var text = this._optionsModel.getValue(x, this._optionsModelPropText);
44436                    var node = document.createElement("OPTION");
44437                    var isSelected = false;
44438
44439                    if (valLookup[val]) {
44440                        isSelected = true;
44441                        valLookup[val] = 2; //1 means we need to select an option. 2 means we have selected the option.
44442                    }
44443                    else
44444                        isSelected = false;
44445
44446                    this._containerNode.options[this._containerNode.length] = new Option(text, val, false, isSelected);
44447                }
44448            }
44449
44450            //add rows from the model that are not contained in the options model.
44451            for (var i = 0; i < this.getModel().getRows().length; i++) {
44452                if (valLookup[this.getModel().getValue(i, this._dataField)] != 2) {
44453                    this._containerNode.options[this._containerNode.options.length] = new Option(this.getModel().getValue(i, this._dataField), this.getModel().getValue(i, this._dataField), false, true);
44454                }
44455            }
44456        },
44457
44458        /**
44459        * Set a TabularModel that contains all of the options for the MultiSelect. Will erase existing options and replace them with the ones in the optionsModel.
44460        * If a value in the model is not contained in the optionsModel, a option is added to the select but not to the optionsModel. The optionsModel is read-only.
44461        * @param {dpage.modules.TabularModel} model
44462        * @param [String] propValue The property name in the TabularModel to use for the value
44463        * @param [String] propText The property name in the TabularModel to use for the text (display)
44464        * @returns {void}
44465        */
44466        setOptionsModel : function(model , propValue, propText)
44467        {
44468            this._optionsModel = model;
44469
44470            if (model.isInstanceOf == null || !model.isInstanceOf(dpage.modules.TabularModel))
44471                throw new Error("optionsModel must be a dpage.modules.TabularModel.");
44472
44473            if(propValue != null)
44474                this._optionsModelPropValue = propValue;
44475
44476            if(propText != null)
44477                this._optionsModelPropText = propText;
44478
44479            this._updateView();
44480        },
44481        /**
44482        * Sets a tabular model and optional dataField to bind the data values to.
44483        * @param {dpage.modules.TabularModel} model
44484        * @param [String] dataField If not passed in, defaults to the same as when constructed.
44485        * @returns {void}
44486        */
44487        setModel: function (model, dataField) {
44488
44489            this.inherited(arguments);
44490
44491            if (dataField != null)
44492                this._dataField = dataField;
44493
44494            this._highlightValues();
44495        },
44496        select_OnFocus: function () {
44497
44498        },
44499        select_OnBlur: function () {
44500        },
44501        /**
44502        * Focus the control
44503        * @returns {void}
44504        */
44505        focus: function () {
44506            this.getDomNode().focus();
44507        },
44508        select_OnChange: function () {
44509            var valLookup = {};
44510            var oldS = this.isSubscribedToModelChanges();
44511
44512            this.setDataSubscriptions(false);
44513
44514            //used for fast lookup for selection.
44515            for (var i = 0; i < this.getModel().getRows().length; i++) {
44516                valLookup[this.getModel().getValue(i, this._dataField)] = 1;//1 means the value exists. 2 means we should NOT delete the value.
44517            }
44518
44519            for (var i = 0; i < this._containerNode.options.length; i++)
44520            {
44521                if(this._containerNode.options[i].selected)
44522                {
44523                    if(!valLookup[this._containerNode.options[i].value])
44524                    {
44525                        var row = {};
44526                        row[this._dataField] = this._containerNode.options[i].value;
44527                        this.getModel().addRow(row);
44528                    }
44529                    valLookup[this._containerNode.options[i].value] = 2;
44530                }
44531            }
44532
44533            for (var i = this.getModel().getRows().length-1; i >=0; i--) {
44534                if (valLookup[this.getModel().getValue(i , this._dataField)] != 2) {
44535                    this.getModel().deleteRow(i);
44536                }
44537            }
44538
44539            this.setDataSubscriptions(true);
44540        },
44541        //overridden
44542        _modelChanged: function (changeType, rowObj, propName) {
44543            this._highlightValues();
44544        },
44545        validate: function () {
44546
44547        }
44548    });
44549});
44550
44551},
44552'dpage/widgets/Submit':function(){
44553define([
44554      "dojo/_base/event"
44555      ,"dojo/on"
44556      ,"dojo/dom-attr"
44557      ,"dojo/dom-class"
44558      ,"dojo/mouse"
44559      ,"dojo/dom-geometry"
44560      , "dojo/dom-style"
44561      , "dojo/json"
44562      , "dojo/request"
44563      , "dojo/dom-form"
44564
44565      , "dpage/widgets/BaseWidget"
44566      , "dpage/widgets/Page"
44567      , "dpage/widgets/Button"
44568      ,"dojox/html/entities"
44569      ,"dojo/_base/declare"
44570      , "dpage/widgets/BaseWidget"],
44571function (event, on, domAttr, domClass, mouse, domGeom, style, json, request, domForm) {
44572    /**
44573    * @namespace dpage
44574    */
44575    /**
44576    * @namespace widgets
44577    * @memberOf dpage
44578    */
44579    /**
44580    * This widget is the basis for how a DPage application communcates with the server and coordinates the validation of
44581    * all of the Container's widgets. When a "submit" is triggered, this widget coordinates all of the validation. If successfull,
44582    * then submits the current model to the server automatically. If a value attribute is defined on the domNode of the Submit, the
44583    * model value of the Submit widget is bound to will be set to this value.
44584    * @class Submit
44585    * @param {Object} [options] Optional options for the widget.
44586    * @param {bool} [options.noValidate] Default false. Flag used to instruct the submit to either call val
44586idate or not. If true, data will be submitted
44587    *                                    regardless of whether data in controls is valid (validation will not be attempted). Default behavior (false) is to call the 
44588    *                                    containers validateWidgets() method.
44589    * @param {String} [options.method] Default "POST". Supported values are "GET" or "POST". Usually "POST" is what you want. GET has request limits that are pretty low.
44590    * @param {bool} [options.doAsynchronous] Default false. Perform the callback either synchronous or asynchronous. Synchronous will submit the Container model to the server and refresh the entire page.
44591    *                                        Asynchronous will submit the Container model to the server. Default behavior is to refresh the Container model with the new model from the server. 
44592    *                                        Page location will not change.  If you pass in a asynchronousPostCallback the default behavior is overridden.
44593    * @param {Function} [options.asynchronousPostCallback] Callback to be called when the server method responds. Works with both GET and POST request methods. function(successOrError , serverResponse){}
44594    * @param {Number} [options.asynchronousTimeout] Default 120 seconds. Timeout in seconds.
44595    * @param {bool} [options.asyncModelTransform] Default true. Applies when using an asynchronousPostCallback method. If set to true, the Submit widget will transform the raw model from the
44596    *                                             server and pass it into your callback function as the second parameter. If set to false, The raw server response will be passed
44597    *                                             as the second parameter to your callback function. If you are not sure what to use here, use the default of true.
44598    * @param {bool} [options.doModelRefresh] Default true. Should the container model be refreshed automatically with the response data. Performs the following code: 
44599    *                                        <pre>this.getContainer().refreshModel(json.parse(serverResponse)); </pre> This only applies in the case
44600    *                                        of an asynchronous call. Does not apply if a asynchronousPostCallback function is specified.
44601    *                                        For this to work properly, the model must be serialized on the server and returned as a raw JSON response.
44602    * @param {String} [options.url] Server endpoint to send data to.
44603    * @param {bool} [options.disablePage] Default true. Flag used to instruct the widget to disable the page when the button is clicked.
44604    * @param {bool} [options.disableContainer] Default false. Disable the container while the submit is in progress.
44605    * @param {bool} [options.enableClickToSubmit] Default true. If false, clicking on the button will not cause a submit. Usefull, if you are hooking
44606    *                                             up a click handler and you want to control the submit yourself.
44607     
44608    * @param {Function} [options.onClick] callback for click.
44609    * @param {String} [options.text] The button text.
44610    * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget.
44611    * @param {dpage.widgets.Container} [options.container] The container of the widget.
44612    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
44613    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
44614    *                               is created.
44615    * @param {Object} [containerNode] Optional container node to tie the widget to.
44616    * @memberOf dpage.widgets
44617    * @extends {dpage.widgets.Button}
44618    */
44619    var theClass = dojo.declare("dpage.widgets.Submit", [dpage.widgets.Button], /** @lends dpage.widgets.Submit.prototype */ {
44620        _doAsynchronous: false,
44621        _method: 'POST',
44622        _asynchronousCallback: null,
44623        _url: null,
44624        _onSubmit: null,
44625        _noValidate: false,
44626        //this is so that you can set a value attribute like this <button value='....' .../>
44627        _nativeValue: null,
44628        _nativeValuePresent: false,
44629        _disablePage: true,
44630        _disableContainer: false,
44631        _enableClickToSubmit: true,
44632        _doModelRefresh: true,
44633        _asynchronousTimeout: 120,
44634        _asyncModelTransform: true,
44635        _tryRawXHRAndBlob : true,
44636
44637        constructor: function (options, srcNodeRef)
44638        {
44639            var self = this;
44640
44641            //The base class button will ensure that this._containerNode is set
44642            if (this._containerNode.nodeName == "INPUT" && domAttr.get(this._containerNode, "type").toUpperCase() == "SUBMIT") {
44643                on(this._containerNode, "click", function (event) { self._button_OnClick(); dojo.stopEvent(event); return false; });
44644            }
44645            else if (this._containerNode.nodeName == "BUTTON") {
44646                on(this._containerNode, "click", function (event) { self._button_OnClick(); dojo.stopEvent(event); return false; });
44647            }
44648            else if (this._containerNode.nodeName == "A") {
44649                on(this._containerNode, "click", function (event) { self._button_OnClick(); dojo.stopEvent(event); return false; });
44650            }
44651            else
44652                throw new Error("Source node for widgets.Submit must be an INPUT[type=button], a BUTTON, or an A");
44653
44654            if (this._containerNode.hasAttribute("value"))
44655            {
44656                this._nativeValue = domAttr.get(this._containerNode, "value");
44657                this._nativeValuePresent = true;
44658            }
44659
44660            if (options == null || options.url == null)
44661            {
44662                throw new Error("A Submit widget needs the url property to function. Pass the url option in.");
44663            }
44664
44665            if(options != null)
44666            {
44667                if (options.disablePage != undefined && options.disablePage == false)
44668                    this._disablePage = false;
44669
44670                if (options.disableContainer)
44671                    this._disableContainer = true;
44672
44673                if (options.noValidate != null)
44674                    this._noValidate = options.noValidate;
44675
44676                if (options.method != null)
44677                    this._method = options.method;
44678
44679                if (options.asynchronousTimeout != null)
44680                    this._asynchronousTimeout = options.asynchronousTimeout;
44681
44682                if (options.enableClickToSubmit != undefined && options.enableClickToSubmit == false)
44683                    this._enableClickToSubmit = false;
44684
44685                if (options.asyncModelTransform != undefined && options.asyncModelTransform == false)
44686                    this._asyncModelTransform = false;
44687
44688                if (options.doAsynchronous != null)
44689                {
44690                    this._doAsynchronous = options.doAsynchronous;
44691
44692                    this._asynchronousCallback = options.asynchronousPost
44692Callback;
44693
44694                    if (options.doModelRefresh != undefined)
44695                        this._doModelRefresh = options.doModelRefresh;
44696                }
44697
44698                if (options.url != null)
44699                    this._url = options.url;
44700
44701                if (options.onSubmit != null)
44702                    this._onSubmit = options.onSubmit;
44703            }
44704        },
44705        templateString: "<div></div>",
44706        _button_OnClick: function ()
44707        {
44708            if (this._enableClickToSubmit)
44709                this.submit();
44710        },
44711        validateContainerWidgets: function ()
44712        {
44713            var pageObj = dpage.widgets.Page.getInstance();
44714
44715            if (this._noValidate) {
44716                this._doSubmit();
44717            }
44718            else {
44719                var valid = this.getContainer().validateWidgets();
44720                if (!valid) {
44721
44722                    if(pageObj != null && this._disablePage)
44723                        pageObj.enablePage();
44724
44725                    if (this.getContainer() != null && this._disableContainer)
44726                        this.getContainer().blockUI(false);
44727
44728                }
44729                else {
44730                    this._doSubmit();
44731                }
44732            }
44733        },
44734        _defaultAsyncCallback : function(status , data)
44735        {
44736            if (dpage.widgets.Page.getInstance() != null && this._disablePage)
44737                dpage.widgets.Page.getInstance().enablePage();
44738
44739            if (this.getContainer() != null && this._disableContainer)
44740                this.getContainer().blockUI(false);
44741
44742            try{
44743
44744                if(this._asynchronousCallback != null)
44745                {
44746                    //transform the data for the callback.
44747                    if (this._asyncModelTransform)
44748                        data = dpage.widgets.Container.parseServerModel(data);
44749
44750                    this._asynchronousCallback(status , data);
44751                    return;
44752                }
44753
44754                //otherwise.
44755                if (status == "SUCCESS")
44756                {
44757                    if(this._doModelRefresh)
44758                    {
44759                        var model = json.parse(data);
44760                        this.getContainer().refreshModel(model , true);
44761                    }
44762                }
44763                else
44764                    throw(new Error(data));
44765            }
44766            catch(e)
44767            {
44768                var c = this.getContainer();
44769                var vw;
44770                if(c != null )
44771                {
44772                    vw = c.getValidationMessageWidget();
44773                }
44774                if (vw != null)
44775                    vw.setError([{ message: e.message }]);
44776                else
44777                    throw e;
44778            }
44779
44780        },
44781        /*Asynchronous call using the XMLHttpRequest object.*/
44782        _doXHRSubmitNoBlob: function (strModel) {
44783            var url = this._url;
44784            var self = this;
44785
44786            if (this._method == "GET") {
44787
44788                if (!/\?/.test(url))
44789                    url += "?";
44790
44791                url += "model=" + encodeURIComponent(strModel);
44792
44793                request.get(url, {
44794                    timeout: this._asynchronousTimeout * 1000
44795                }).then(function (res) {
44796                    self._defaultAsyncCallback("SUCCESS", res);
44797                }, function (res) {
44798                    self._defaultAsyncCallback("ERROR", res);
44799                });
44800            }
44801            else if (this._method == "POST") {
44802                var theForm = document.createElement("FORM");
44803                var theInput = document.createElement("INPUT");
44804                domAttr.set(theInput, "type", "hidden");
44805                domAttr.set(theInput, "name", "model");
44806                domAttr.set(theInput, "value", strModel);
44807
44808                theForm.appendChild(theInput);
44809
44810                domAttr.set(theForm, "action", this._url);
44811                domAttr.set(theForm, "method", "POST");
44812
44813
44814                request.post(this._url, {
44815                    data: domForm.toObject(theForm),
44816                    timeout: this._asynchronousTimeout * 1000
44817                }).then(function (res) {
44818                    self.getContainer().result = res;
44819                    dpage.widgets.Page.getInstance().enablePage();
44820                    //self._defaultAsyncCallback("SUCCESS", res);
44821                }, function (res) {
44822                    self._defaultAsyncCallback("ERROR", res);
44823                });
44824            }
44825        },
44826
44827        _doXHRSubmit : function (strModel){
44828            var req = this._createXMLHTTPObject();
44829            var url = this._url;
44830            var method = this._method;
44831            var self = this;
44832            var postData = null;
44833
44834            if (!req)
44835                throw new Error("Unable to instantiate XMLHttpRequest.");
44836
44837            if (this._method == "GET") {
44838                if (!/\?/.test(url))
44839                    url += "?";
44840
44841                url += "model=" + encodeURIComponent(strModel);
44842            }
44843
44844            req.open(method, url, true);
44845
44846            //timeout has to be *after* the open call in IE.
44847            req.timeout = this._asynchronousTimeout * 1000;
44848
44849            req.responseType = 'text';
44850
44851            //common response handling.
44852            req.onreadystatechange = function () {
44853
44854                if (req.readyState != 4)
44855                    return;
44856                if (req.status != 200 && req.status != 304) {
44857                    var msg = "RequestError: Unable to load " + url + " status: " + req.status;
44858                    self._defaultAsyncCallback("ERROR", msg);
44859                    return;
44860                }
44861
44862                self._defaultAsyncCallback("SUCCESS", req.responseText);
44863            };
44864
44865            if (this._method == "POST") {
44866                req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
44867
44868                var data = encodeURIComponent(strModel);
44869                
44870                postData = "model=" + data;
44871            }
44872
44873            if (postData == null)
44874                req.send();
44875            else
44876                req.send(postData);
44877        },
44878        _getXmlHttpFactories : function(){
44879            return [
44880                function () {return new XMLHttpRequest()},
44881                function () {return new ActiveXObject("Msxml2.XMLHTTP")},
44882                function () {return new ActiveXObject("Msxml3.XMLHTTP")},
44883                function () {return new ActiveXObject("Microsoft.XMLHTTP")}
44884            ];
44885        },
44886
44887        _createXMLHTTPObject : function() {
44888            var xmlhttp = false;
44889            var XMLHttpFactories = this._getXmlHttpFactories();
44890
44891            for (var i=0;i<XMLHttpFactories.length;i++) {
44892                try {
44893                    xmlhttp = XMLHttpFactories[i]();
44894                }
44895                catch (e) {
44896                    continue;
44897                }
44898                break;
44899            }
44900            return xmlhttp;
44901        },
44902        _doSubmit: function ()
44903        {
44904            var self = this;
44905            var url = this._url;
44906
44907            //if you include a value attribute in the dom node, it will get bound to the model here...
44908            // Ex: <button value='hello!' data-dojo-type='dpage/widgets/Submit' data-dojo-props:'container: this , model : this.getModel.Files , dataField : "Prop1"' />
44909            if (this._nativeValuePresent)
44910                this.setModelValue(this._nativeValue);
44911
44912            //get the page model.
44913            var strModel = this.getContainer().serializeModel();
44914
44915            if (this._method != "POST" && this._method != "GET")
44916                throw new Error("Invalid _method of: " + this._method);
44917
44918            if (this._doAsynchronous) {
44919
44920                if (this._tryRawXHRAndBlob)
44921                    this._doXHRSubmit(strModel);
44922                else
44923                    this._doXHRSubmitNoBlob(strModel);
44924            }
44925            else {
44926                //post the page
44927                var theForm = document.createElement("FORM");
44928                var theInput = document.createElement("INPUT");
44929                domAttr.set(theInput, "type", "hidden");
44930                domAttr.set(theInput, "name", "model");
44931                domAttr.set(theInput, "value", strModel);
44932
44933                theForm.appendChild(theInput);
44934
44935                domAttr.set(theForm, "action", this._url);
44936                domAttr.set(theForm, "method", this._method);
44937
44938                document.body.appendChild(theForm);
44939
44940                theForm.submit();
44941            }
44942        },
44943        /**
44944        * Perform the submit action. The Container model (getModel()) is sent to the server seri
44944alized in the model parameter value. In other words,
44945        * to access the serialized model on the server, access the model parameter that was passed in.
44946        * @returns {void}
44947        */
44948        submit : function ()
44949        {
44950            var wid = this.getWidgetId();
44951            var self = this;
44952            var pageObj = dpage.widgets.Page.getInstance();
44953
44954            if (this.getContainer() == null) {
44955                throw new Error("A Submit widget needs a container property to function. Pass the container option in.");
44956            }
44957
44958            if (pageObj != null && this._disablePage)
44959                pageObj.disablePage();
44960
44961
44962            if (this.getContainer() != null && this._disableContainer)
44963                this.getContainer().blockUI(true);
44964
44965            if (this._url == null)
44966                throw new Error("This widgets.Submit widget (id=" + wid + ") has a null url");
44967
44968            //so page will be blocked immediately.
44969            setTimeout(function () { self.validateContainerWidgets(); }, 0);
44970
44971        }
44972    });
44973
44974    return theClass;
44975});
44976
44977},
44978'dpage/widgets/Table':function(){
44979define([
44980      "dojo/_base/event"
44981      , "dojo/on"
44982      , "dojo/dom-attr"
44983      , "dojo/dom-class"
44984      , "dojo/mouse"
44985      , "dojo/dom-geometry"
44986      , "dojo/dom-style"
44987      , "dojo/json"
44988      , "dojo/query"
44989      , "jQueryPrivate"
44990
44991      , "dpage/modules/TabularToSingleValueModel"
44992      , "dpage/modules/Config"
44993      , "xstyle/css!dpage/widgets/Table.css"
44994      , "dpage/modules/TabularModel"
44995      , "dojox/html/entities"
44996      , "dojo/_base/declare"
44997      , "dpage/widgets/MultiValueWidget"],
44998function (event, on, domAttr, domClass, mouse, domGeom, style, json, query, $) {
44999    /**
45000    * @namespace dpage
45001    */
45002    /**
45003    * @namespace widgets
45004    * @memberOf dpage
45005    */
45006    /**
45007    * A usefull data-bound responsive-design enabled table.
45008    * @class Table
45009    * @param {Object} [options] Optional options for the widget.
45010    * @param {bool} [options.noDefaultCSS] If true, don't bring an any default styling.
45011    * @param {bool} [options.useExistingTable] If true, bind the model to the existing table markup. The number of rows in the table, 
45012    *                                          must match number of rows in the model. Default is false. If set to false, any existing 
45013    *                                          table will be overwritten with a table generated from the data in the model.
45014    * @param {bool} [options.paginate] Defaults false. If true, paging will be added.
45015    * @param {bool} [options.pageLinksOnBottom] Default true. Paging links will be added to the bottom of the table. Need to also set options.paginate to true.
45016    * @param {bool} [options.pageLinksOnTop] Default false. Paging links will be added to the bottom of the table. Need to also set options.paginate to true.
45017    * @param {Number} [options.pageSize] Default 10. The number of rows to display per page. If passed, implies options.paginate.
45018    * @param {Number} [options.maxPageLinks] Default 20. The maximum number of paging links to show at the bottom of the table.
45019    * @param {Number} [options.phoneBreakpoint] Default 480. The pixel width where the table will turn to phone mode.
45020    * @param {Number} [options.tabletBreakpoint] Default 800. The pixel width where the table will turn to tablet mode.
45021    * @param {bool} [options.sortableColumns] Default true. If true, then the columns will be marked sortable. Can be overridden on a column basis with the sortable column option.
45022    * @param {Object} [options.caption] String|{@link dpage.widgets.Label}. A string or {@link dpage.widgets.Label} to set as the caption for the table. Write a caption node directly underneath the table node.
45023    *                                                                       Following dpage conventions, if a string is passed in, the value will be property html encoded, so markup will show as text.
45024    * @param {Object} [options.colOptions] Column options. 
45025    * @param {Object} [options.colOptions.colName] The name of the column in the model to set options for.
45026    * @param {dpage.widgets.SingleValueWidget} [options.colOptions.colName.widgetConstructor] Any SingleValueWidget. This widget will be bound to the data for the cell. 
45027    *                                                                                         The table will set the model for this widget so that it is bound to the value of the cell.
45028    *                                                                                         The table does this by adding in the model option for the widget like this:
45029    *                                                                                         <pre>
45030    *new widgetConstructor({model : new TabularToSingleValueModel({
45031    *                                                               tabularModel:this.getModel() , 
45032    *                                                               dataField : currentColName , 
45033    *                                                               dataRow: currentDataRow})})
45034    *                                                                                         </pre>
45035    * @param {Object} [options.colOptions.colName.widgetOptions] The options that will be passed to the constructor of the widgetConstructor class. Use this to control custom cell widgets. 
45036    *                                                            There is no need to pass the model option. The table will override whatever you pass in 
45037    *                                                            since it has to bind the SingleValueWidget to the particular row and column.
45038    * @param {dpage.widgets.TableColumnNameWidget} [options.colOptions.colName.columnNameWidget] Widget to use for displaying the contents of the column header. 
45039    *                                              You can subclass the {@link dpage.widgets.TableColumnNameWidget} to provide custom formatting. The table will
45040    *                                              provide the tableObj and modelFieldName options to the constructor of this widget. The getDomNode() method of this widget
45041    *                                              must be a TH.
45042    * @param {Object} [options.colOptions.colName.columnNameWidgetOptions] Optional extra options for the columnNameWidget. Will be passed to the constructor of the
45043    *                                             columnNameWidget if provided.
45044    * @param {bool} [options.colOptions.colName.dataHidePhone] Hide this column when sized to phone width
45045    * @param {bool} [options.colOptions.colName.dataHideTablet] Hide this column when sized to tablet
45046    * @param {String} [options.colOptions.colName.displayName] Name to display in header. The text is HTML encoded unless you override with encodeDisplayName : false
45047    * @param {bool} [options.colOptions.colName.encodeDisplayName] Default true. If false, it will not HTML encode the display name. Only applies if passing in the displayName column option.
45048    * @param {bool} [options.colOptions.colName.hideColumn] When set to true, hide the column completely.
45049    * @param {bool} [options.colOptions.colName.hideColumnInDownload] When set to true, hide the column when downloading the table data (the downloadData() method). When set to false, show the column in the download.
45050    * @param {String} [options.colOptions.colName.altSortColumn] If set, names the column in the TabularModel whose row value will control the sorting for this column.
45051    * @param {bool} [options.colOptions.colName.sortable] Default true. If true, the column will be marked sortable. Overrides the global sortableColumns o
45051ption if explicitly set.
45052     
45053    * @param {dpage.modules.TabularModel} [options.model] The model to use.
45054    * @param {dpage.widgets.Container} [options.container] The container of the widget.
45055    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
45056    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
45057    *                               is created.
45058    * @param {Object} [containerNode] Optional container node to tie the widget to.
45059    * @memberOf dpage.widgets
45060    * @extends {dpage.widgets.MultiValueWidget}
45061    */
45062    return dojo.declare("dpage.widgets.Table", [dpage.widgets.MultiValueWidget], /** @lends dpage.widgets.Table.prototype */ {
45063        _colConstructors: null,
45064        _containerNode: null,
45065        _useExistingTable: false,
45066        _colOptions: null,
45067        _widgetList: null,
45068        _widgetLookup : null,
45069        _columnWidgets : null,
45070        _modelColNames: null,
45071        _paginate: false,
45072        _pageSize: 10,
45073        _currentPage : 1,
45074        _maxPageLinks : 20,
45075        _phoneBreakpoint: 480,
45076        _tabletBreakpoint: 800,
45077        _renderCNameAr: null,
45078        _sortableColumns: true,
45079        _captionObj: null,
45080        _initialized : false,
45081        _tFootTDNode: null,
45082        _pageLinksOnBottom: true,
45083        _pageLinksOnTop : false,
45084
45085        constructor: function (options, srcNodeRef) {
45086            var self = this;
45087            var modelColumns = null;
45088            var oneColDataType;
45089
45090            this._modelColNames = {};
45091            this._widgetList = [];
45092            this._widgetLookup = {};
45093            this._columnWidgets = [];
45094            this._colOptions = {};
45095            this._colConstructors = {};
45096            this._columnsToHideOnPhone = {};
45097            this._columnsToHideOnTablet = {};
45098
45099            if(srcNodeRef == null)
45100                srcNodeRef = document.createElement("TABLE");
45101
45102            if (srcNodeRef.nodeName != "TABLE")
45103                throw new Error("Source node for widgets.Table must be a TABLE");
45104
45105            this._containerNode = srcNodeRef;
45106
45107            if (options == null || !options.noDefaultCSS) {
45108                //register with the page obj that we have pending css.
45109                dpage.widgets.Page.setClassCSSLoading("dpage.widgets.Table", false);
45110                //use this pattern whenever we need one css to load before another one.
45111                require(["xstyle/css!footable/footable.core.css"], function () {
45112                    require(["xstyle/css!footable/footable.standalone.css"], function () {
45113                        //register with the page that we are done loading css.
45114                        dpage.widgets.Page.setClassCSSLoading("dpage.widgets.Table", true);
45115                    });
45116                });
45117            }
45118
45119            modelColumns = this.getModel().getColumns();
45120
45121            if (options != null) {
45122
45123                if (options.sortableColumns != undefined)
45124                    this._sortableColumns = options.sortableColumns;
45125
45126                if (options.caption != null) {
45127                    if ((options.caption instanceof String || typeof (options.caption) == 'string')
45128                        ||
45129                        (options.caption.isInstanceOf && options.caption.isInstanceOf(dpage.widgets.Label)))
45130                        this._captionObj = options.caption;
45131                    else
45132                        throw new Error("caption table option must be a string or a dpage.widgets.Label object.");
45133                }
45134
45135                if (options.useExistingTable)
45136                    this._useExistingTable = true;
45137
45138                if (options.paginate)
45139                    this._paginate = true;
45140
45141                if (options.pageLinksOnTop !== undefined)
45142                    this._pageLinksOnTop = options.pageLinksOnTop;
45143
45144                if (options.pageLinksOnBottom !== undefined)
45145                    this._pageLinksOnBottom = options.pageLinksOnBottom;
45146
45147                if (options.maxPageLinks)
45148                    this._maxPageLinks = options.maxPageLinks;
45149
45150                if (options.pageSize)
45151                    this._pageSize = options.pageSize;
45152
45153                if (options.phoneBreakpoint)
45154                    this._phoneBreakpoint = options.phoneBreakpoint;
45155
45156                if (options.tabletBreakpoint)
45157                    this._tabletBreakpoint = options.tabletBreakpoint;
45158
45159                if (options.colOptions != null) {
45160                    for (var idx = 0; idx < modelColumns.length; idx++) {
45161                        this._modelColNames[modelColumns[idx].ColumnName] = true;
45162                    }
45163                    for (var idx = 0; idx < modelColumns.length; idx++) {
45164                        if (options.colOptions[modelColumns[idx].ColumnName] != null) {
45165                            var opt = options.colOptions[modelColumns[idx].ColumnName];
45166                            // widgetConstructor : null (can be any SingleValueWidget)
45167                            // widgetOptions : null (the options object passed to the widgetConstructor.
45168                            // dataHidePhone : null
45169                            // dataHideTablet : null
45170                            // displayName : null
45171                            // hideColumn : true|false|null
45172                            // hideColumnInDownload : true|false|null
45173                            // altSortColumn : String
45174                            if (opt.hasOwnProperty("widgetConstructor") && opt.widgetConstructor == null)
45175                                throw new Error("there is a problem with the definition for the widgetConstructor for column " + modelColumns[idx].ColumnName + " on this Table (wid=" + this.getWidgetId() + "). You must require the widget in.")
45176                            if (opt.hasOwnProperty("altSortColumn")) {
45177                                if ((oneColDataType = this.getModel().getColumnInfo(opt.altSortColumn)) == null)
45178                                    throw new Error("Invalid altSortColumn name of: " + opt.altSortColumn + ". It does not exist in the model.");
45179                                else {
45180                                    //for faster reference later when building the table.
45181                                    opt.altColDataType = oneColDataType.DataType;
45182                                }
45183                            }
45184                           this._colOptions[modelColumns[idx].ColumnName] = opt;
45185                        }
45186                        else
45187                            1 == 1;//this._colOptions[modelColumns[idx].ColumnName] = {};
45188                    }
45189
45190                    //check for invalid properties.
45191                    for (var colName in options.colOptions) {
45192                        if (options.colOptions.hasOwnProperty(colName)) {
45193                            if (!this._modelColNames[colName])
45194                                throw new Error("Invalid colOptions model column name of : " + colName);
45195                        }
45196                    }
45197                }
45198            }
45199        },
45200        /**
45201        * Get the SingleValueWidget for the specified table cell. The row is the row index (for row object see overloaded method) in the model for the table.
45202        * null is returned if the column does not have a cell widget or if the specified cell widget is not on the current page or if an invalid fieldName is
45203        * passed in.
45204        * @param {Number} row The index of the row in the table model.
45205        * @param {String} fieldName The field name in the model that identifies the column.
45206        * @returns {dpage.widgets.SingleValueWidget}
45207        *//**
45208        * Get the SingleValueWidget for the specified table cell. The row is the row object (for row index see overloaded method) in the model for the table.
45209        * null is returned if the column does not have a cell widget or if the specified cell widget is not on the current page or if an invalid fieldName is
45210        * passed in.
45211        * @param {Object} row The row object in the table model.
45212        * @param {String} fieldName The field name in the model that identifies the column.
45213        * @returns {dpage.widgets.SingleValueWidget}
45214        */
45215        getCellWidget: function (row , fieldName) {
45216            var rowObj;
45217
45218            if (typeof (row) === 'number' || row instanceof Number)
45219                rowObj = this._model.getRows()[row];
45220            else
45221                rowObj = row;
45222
45223            var w = this._widgetLookup[this.getModel().getDataRowId(rowObj)];
45224
45225            if (w == null)
45226                return null;
45227
45228            w = w[fieldName];
45229
45230            if(w== null)
45231                return null;
45232            else
45233                return w;
45234        },
45235        cleanupColumnNameWidgets : function(){
45236            for (var i = 0; i < this._columnWidgets.length; i++) {
45237                this._columnWidgets[i].destroy();//so we get garbage collected correctly.
45238            }
45239            this._columnWidgets = [];
45240        },
45241        cleanupEditWidgets : function(){
45242            for (var i = 0; i < this._widgetList.length; i++) {
45243                this._widgetList[i].destroy();//so we get garbage collected correctly.
45244            }
45245            this._widgetList = [];
45246            this._widgetLookup = {};
45247        },
45248        destroy : function () {
45249            this.cleanupEditWidgets();
45250            this.cleanupColumnNameWidgets();
45251            this.inherited(arguments);
45252        },
45253        templateString: "<div></div>",
45254        postCreate: function () {
45255            var columns = this.getModel().getColumns();
45256            var column;
45257            var dataType;
45258
45259            if (this._dataField != null) {
45260                for (var idx = 0; idx < columns.length; idx++) {
45261                    if (columns[idx].ColumnName == this._dataField) {
45262                        column = columns[idx];
45263                    }
45264                }
45265
45266                if (column == null)
45267                    throw new Error("Field " + this._dataField + " does not exist in the model.");
45268
45269                this._dataType = column.DataType;
45270            }
45271
45272            this.bindTable();
45273        },
45274        /**
45275        * Get the list of columnNameWidgets (only applies if any custom ones were passed into the constructor). Do not modify this array!
45276        * @returns {dpage.widgets.TableColumnNameWidget[]}
45277        */
45278        getColumnNameWidgets : function(){
45279            return this._columnWidgets;
45280        },
45281        /**
45282        * Downloads data as csv.
45283        * @param {String} fileName The name of the file that will be returned.
45284        * @param {Array} [columnOptions] Optional column options. If passed in, they give you more control on how to format the output. The order
45285        *                                of the columnOptions array determines the order in which the output file columns are written.
45286        * @param {String} columnOptions.ColumnName The column name in the model.
45287        * @param {String} [columnOptions.DisplayName] The value to display as the column header.
45288        * @param {bool} [columnOptions.HideColumn] Default false. Do not show this column if set to true.
45289        * @returns {void} 
45290        */
45291        downloadData : function(fileName , columnOptions)
45292        {
45293            var url = dpage.modules.Config.dpageRoot + "/Download.ashx";
45294            var self = this;
45295            var form = document.createElement("FORM");
45296            var input = document.createElement("TEXTAREA");//can hold more data than input type=text. For some reason chrome was truncating the value on an <input type=text> to about 500kb.
45297            var fileNameInput = document.createElement("INPUT");
45298            var tableModel = {};
45299
45300            tableModel.Rows = this.getModel().getRawModel();
45301
45302            if(columnOptions == null)
45303            {
45304                columnOptions = [];
45305                for(var i=0;i<this.getModel().getColumns().length;i++)
45306                {
45307                    var options = {};
45308
45309                    //DisplayName
45310                    if (this.getModel().getColumns()[i].DisplayName != null)
45311                        options.DisplayName = this.getModel().getColumns()[i].DisplayName;
45312                    if(this._colOptions[this.getModel().getColumns()[i].ColumnName] != null
45313                        &&
45314                        this._colOptions[this.getModel().getColumns()[i].ColumnName].displayName != null)
45315                        options.DisplayName = this._colOptions[this.getModel().getColumns()[i].ColumnName].displayName;
45316
45317                    //HideColumn
45318                    if (this._colOptions[this.getModel().getColumns()[i].ColumnName] != null
45319                        &&
45320                        this._colOptions[this.getModel().getColumns()[i].ColumnName].hideColumn !== undefined)
45321                        options.HideColumn = this._colOptions[this.getModel().getColumns()[i].ColumnName].hideColumn;
45322                    if (this._colOptions[this.getModel().getColumns()[i].ColumnName] != null
45323                        &&
45324                        this._colOptions[this.getModel().getColumns()[i].ColumnName].hideColumnInDownload !== undefined)
45325                        options.HideColumn = this._colOptions[this.getModel().getColumns()[i].ColumnName].hideColumnInDownload;
45326
45327                    options.ColumnName = this.getModel().getColumns()[i].ColumnName;
45328                    columnOptions.push(options);
45329                }
45330            }
45331
45332            tableModel.Columns = columnOptions;
45333
45334            form.setAttribute("style", "display:none");
45335            form.setAttribute("method", "POST");
45336            form.setAttribute("action", url);
45337
45338            fileNameInput.setAttribute("name" , "fileName");
45339            fileNameInput.setAttribute("value", fileName);
45340            form.appendChild(fileNameInput);
45341
45342            input.setAttribute("name", "model");
45343            input.value = json.stringify(tableModel);
45344            form.appendChild(input);
45345
45346            document.body.appendChild(form);
45347
45348            form.submit();
45349
45350            document.body.removeChild(form);
45351        },
45352        //overridden
45353        _modelChanged: function (type, rowObj, dataField) {
45354            if(type != "CHANGE" || type == "INVALIDATE")
45355                this._updateView();
45356        },
45357        _updateView : function()
45358        {
45359            this.renderPage(this.getCurrentPageNumber() , false);
45360        },
45361        _addPagination : function(){
45362            var tfootNode;
45363            var tRowNode;
45364            var tdNode;
45365            var numVisibleColumns;
45366            var self = this;
45367            var lastPage;
45368            var nextSetStartPage;
45369            var prevSetStartPage;
45370            var firstLink;
45371            var pageLinkContainer;
45372            var containerNodes = [];
45373
45374            if (this.getModel().getRows().length > 0)
45375                lastPage = Math.floor((this.getModel().getRows().length-1) / this._pageSize);
45376            else
45377                lastPage = 0;
45378
45379            lastPage += 1;
45380            
45381            firstLink = ( Math.floor((this._currentPage - 1) / this._maxPageLinks) * this._maxPageLinks)+1;
45382
45383            numVisibleColumns = query("THEAD", this._containerNode)[0].lastChild.cells.length;
45384
45385            tfootNode = query("TFOOT", this._containerNode)[0];
45386
45387            if (tfootNode == null) {
45388                tfootNode = document.createElement("TFOOT");
45389                this._containerNode.appendChild(tfootNode);
45390            }
45391
45392            tfootNode.innerHTML = "";
45393
45394            //add paging links as the first row of the header.
45395            if (this._pageLinksOnTop) {
45396                var tHeadNode = query("THEAD", this._containerNode)[0];
45397                var trNodes = query("TR", tHeadNode);
45398                tRowNode = document.createElement("TR");
45399                if (trNodes.length > 1)
45400                    tHeadNode.replaceChild(tRowNode, tHeadNode.firstChild);
45401                else
45402                    tHeadNode.insertBefore(tRowNode, tHeadNode.firstChild);
45403                containerNodes.push(tRowNode);
45404            }
45405
45406            if (this._pageLinksOnBottom) {
45407                tRowNode = document.createElement("TR");
45408                tfootNode.appendChild(tRowNode);
45409                containerNodes.push(tRowNode);
45410            }
45411
45412            for (var cni = 0; cni < containerNodes.length; cni++) {
45413                tRowNode = containerNodes[cni];
45414                tdNode = document.createElement("TD");
45415                tdNode.setAttribute("colspan", numVisibleColumns);
45416                //to control the paging controls. The default style makes these look good.
45417                tRowNode.appendChild(tdNode);
45418
45419                //save so that we can set display:block later.
45420                this._tFootTDNode = tdNode;
45421
45422                pageLinkContainer = document.createElement("DIV");
45423                domClass.add(pageLinkContainer, "pagination");
45424                domClass.add(pageLinkContainer, "pagination-centered");
45425                tdNode.appendChild(pageLinkContainer);
45426
45427                var ulNode = document.createElement("UL");
45428                pageLinkContainer.appendChild(ulNode);
45429
45430                var liNode = document.createElement("LI");
45431                domClass.add(liNode, "footable-page-arrow");//add the disabled class to grey it out.
45432                ulNode.appendChild(liNode);
45433                var aNode = document.createElement("A");
45434                aNode.setAttribute("data-page", "first");
45435                aNode.setAttribute("href", "#first");
45436                aNode.innerHTML = "<<";
45437                on(aNode, "click", function () { self.renderPage(1); });
45438                liNode.appendChild(aNode);
45439
45440                liNode = document.createElement("LI");
45441                ulNode.appendChild(liNode);
45442                aNode = document.createElement("A");
45443                aNode.innerHTML = "<";
45444                on(aNode, "click", function () { self.renderPage(self.getCurrentPageNumber() - 1); });
45445                liNode.appendChild(aNode);
45446
45447                for (var i = firstLink; i < firstLink + this._maxPageLinks; i++) {
45448                    liNode = document.createElement("LI");
45449                    domClass.add(liNode, "footable-page");
45450                    ulNode.appendChild(liNode);
45451                    aNode = document.createElement("A");
45452                    aNode.innerHTML = i;
45453                    if (i == this._currentPage) {
45454                        domClass.add(aNode, "pageLinkActive");
45455                        domClass.add(liNode, "active");
45456                    }
45457                    else
45458                        domClass.add(aNode, "pageLinkInActive");
45459
45460                    on(aNode, "click", (function () { var c = i; return function () { self.renderPage(c); } })());
45461                    liNode.appendChild(aNode);
45462                    if (i == lastPage)
45463                        break;
45464                }
45465
45466                liNode = document.createElement("LI");
45467                ulNode.appendChild(liNode);
45468                aNode = document.createElement("A");
45469                aNode.innerHTML = ">";
45470                on(aNode, "click", function () { self.renderPage(self.getCurrentPageNumber() + 1); });
45471                liNode.appendChild(aNode);
45472
45473                liNode = document.createElement("LI");
45474                ulNode.appendChild(liNode);
45475                var aNode = document.createElement("A");
45476                aNode.setAttribute("data-page", "last");
45477                aNode.setAttribute("href", "#last");
45478                aNode.innerHTML = ">>";
45479                on(aNode, "click", function () { self.renderPage(lastPage); });
45480                liNode.appendChild(aNode);
45481            }
45482        },
45483        //For some reason, the td node under the tfoot gets inline style display:none applied when going into mobile. We always want it shown. This is a hack.
45484        fixHiddenFooterInMobile: function () {
45485            if (this._tFootTDNode != null)
45486                this._tFootTDNode.removeAttribute("style");
45487        },
45488        _doPrivateValidate : function()
45489        {
45490            if (this.getContainer() != null && this.getContainer().getValidationMessageWidget() != null)
45491                this.getContainer().getValidationMessageWidget().removeErrorByWidgetID(this.getWidgetId());
45492
45493            //check for valid things in the table, if not valid, call the containers validate method to show the me
45493ssage.
45494            if (this.validate() != null)
45495            {
45496                if (this.getContainer() != null)
45497                    this.getContainer().validateWidgets();
45498                return false;
45499            }
45500            return true;
45501        },
45502        /**
45503        * Render a page of data.
45504        * @param {Number} pageNumber The page to render, from 1-maxPage. If value is > than the number of pages, the last page will be displayed.
45505        *                            If pageNumber <=0 the first page will be displayed.
45506        * @param {bool} doValidate Default true, perform validation for the table cell widgets.
45507        * @returns {void}
45508        */
45509        renderPage:function(pageNumber , doValidate) {
45510            var columnInfo = this.getModel().getColumns();
45511            var data = this.getModel().getRows();
45512            var endIdx;
45513            var startIdx;
45514            var tbodyNode = query("TBODY", this._containerNode)[0];
45515            var numPages;
45516
45517            if(doValidate == undefined)
45518                doValidate = true;
45519
45520            if (tbodyNode == null) {
45521                tbodyNode = document.createElement("TBODY");
45522                if (this._containerNode.firstChild != null)
45523                    this._containerNode.insertBefore(tbodyNode, this._containerNode.firstChild);
45524                else
45525                    this._containerNode.appendChild(tbodyNode);
45526            }
45527
45528            if (this._paginate) {
45529                if (data.length == 0)
45530                    numPages = 1;
45531                else
45532                    numPages = Math.floor((data.length - 1) / this._pageSize) + 1;
45533            }
45534            else
45535            {
45536                numPages = 1;
45537            }
45538
45539            if (pageNumber > numPages)
45540                pageNumber = numPages;
45541
45542            if(doValidate && !this._doPrivateValidate())
45543                return;
45544
45545            this._curr
45546            if (pageNumber <= 0)
45547                pageNumber = 1;
45548
45549            tbodyNode.innerHTML = "";
45550            
45551            this.cleanupEditWidgets();
45552
45553            if (this._paginate) {
45554                if (data.length > this._pageSize)
45555                    endIdx = (pageNumber - 1)*this._pageSize + this._pageSize;
45556                else
45557                    endIdx = data.length;
45558            }
45559            else
45560                endIdx = data.length;
45561
45562            startIdx = (pageNumber - 1) * this._pageSize;
45563
45564            if (endIdx > data.length)
45565                endIdx = data.length;
45566
45567            if (data.length == 0) {
45568                startIdx = 0;
45569            }
45570
45571            //for each row.
45572            for (var idx = startIdx; idx < endIdx; idx++) {
45573                tbodyNode.appendChild(this._renderRow(data[idx], columnInfo));
45574            }
45575
45576            this._currentPage = pageNumber;
45577
45578            if (this._paginate)
45579                this._addPagination();
45580
45581            //If you are in mobile or phone width it will hide the correct columns for you.
45582            $(this._containerNode).trigger('footable_redraw');
45583        },
45584        /** 
45585        * Get the current page number.
45586        * @returns {Number} The page number.
45587        */
45588        getCurrentPageNumber : function() {
45589            return this._currentPage;
45590        },
45591        renderTable: function () {
45592            var columnInfo = this.getModel().getColumns();
45593            var data = this.getModel().getRows();
45594            var columnNames = [];
45595            var tableNode;
45596            var theadNode;
45597            var tbodyNode;
45598            var td;
45599            var tr;
45600            var dataHideParts = [];
45601            var dataHideStr = "";
45602            var addFooTableClass = false;
45603            var dataHidePhone = false;
45604            var dataHideTab = false;
45605            var self = this;
45606
45607            tableNode = this._containerNode;
45608
45609            var captionNode = query("caption", tableNode)[0];
45610
45611            if (captionNode != null)
45612                tableNode.removeChild(captionNode);
45613
45614            this.cleanupColumnNameWidgets();
45615            this.cleanupEditWidgets();
45616
45617            if (this._captionObj != null) {
45618                captionNode = document.createElement("caption");
45619                tableNode.appendChild(captionNode);
45620
45621                if (this._captionObj.isInstanceOf && this._captionObj.isInstanceOf(dpage.widgets.Label))
45622                    captionNode.appendChild(this._captionObj.getDomNode());
45623                else
45624                    captionNode.innerHTML = dojox.html.entities.encode(this._captionObj.toString());
45625            }
45626
45627            this._renderCNameAr = columnNames;
45628            //we do this because footable doesn't like it when we try to bind it more than once to the same element. We have
45629            // to destroy the existing table first.
45630            if (this._initialized) {
45631                var newTableNode = document.createElement("table");
45632                tableNode.parentNode.insertBefore(newTableNode, tableNode);
45633                tableNode.parentNode.removeChild(tableNode);
45634                tableNode = newTableNode;
45635                this._containerNode = tableNode;
45636            }
45637            this._initialized = true;
45638
45639            theadNode = document.createElement("THEAD");
45640            tbodyNode = document.createElement("TBODY");
45641            tableNode.appendChild(theadNode);
45642            tableNode.appendChild(tbodyNode);
45643
45644            tr = document.createElement("TR");
45645            theadNode.appendChild(tr);
45646
45647            //build the TH section of the table.
45648            for (var idx = 0; idx < columnInfo.length; idx++) {
45649                columnNames.push(columnInfo[idx].ColumnName);
45650
45651                var colOptions = this._colOptions[columnInfo[idx].ColumnName];
45652
45653                if (colOptions == null)
45654                    this._colOptions[columnInfo[idx].ColumnName] = {};
45655                colOptions = this._colOptions[columnInfo[idx].ColumnName];
45656
45657                if (colOptions && colOptions.hideColumn)
45658                    continue;
45659
45660                td = document.createElement("TH");
45661
45662                if (colOptions && colOptions.columnNameWidget) {
45663                    var options;
45664
45665                    if (colOptions.columnNameWidgetOptions != null)
45666                        options = colOptions.columnNameWidgetOptions;
45667                    else
45668                        options = {};
45669
45670                    options.tableObj = this;
45671                    options.modelFieldName = columnNames[idx];
45672
45673                    var cnw = new colOptions.columnNameWidget(options);
45674                    this._columnWidgets.push(cnw);
45675
45676                    if (cnw.getDomNode().nodeName.toUpperCase() != "TH")
45677                        throw new Error("The getDomNode() method of the columnNameWidget must return a TH no
45677de.");
45678
45679                    td = cnw.getDomNode();
45680                }
45681                else if (colOptions && colOptions.displayName) {
45682                    if(colOptions.encodeDisplayName != undefined && colOptions.encodeDisplayName == false)
45683                        td.innerHTML = colOptions.displayName;
45684                    else
45685                        td.innerHTML = dojox.html.entities.encode(colOptions.displayName);
45686                }
45687                else if(columnInfo[idx].DisplayName != null)
45688                    td.innerHTML = dojox.html.entities.encode(columnInfo[idx].DisplayName);
45689                else {
45690                    td.innerHTML = dojox.html.entities.encode(columnNames[idx]);
45691                }
45692
45693                //footable.js stuff.
45694                dataHideParts = [];
45695                if (colOptions != null) {
45696                    dataHidePhone = colOptions.dataHidePhone;
45697                    dataHideTab = colOptions.dataHideTablet;
45698                }
45699                if (dataHidePhone)
45700                    dataHideParts.push("phone");
45701                if (dataHideTab)
45702                    dataHideParts.push("tablet");
45703
45704                if (dataHideParts.length > 0) {
45705                    addFooTableClass = true;
45706                    dataHideStr = dataHideParts.join(",");
45707                    domAttr.set(td, "data-hide", dataHideStr);
45708                }
45709
45710                tr.appendChild(td);
45711
45712                if ((this._sortableColumns && colOptions.sortable == undefined) ||
45713                    colOptions.sortable) {
45714                    //the sort stuff.
45715                    domClass.add(td, "sortableColumn");
45716                    var tdSortSpan = document.createElement("SPAN");
45717                    this._colOptions[columnInfo[idx].ColumnName].thNode = td;
45718                    domClass.add(tdSortSpan, "footable-sort-indicator");
45719                    on(td, "click", (function () { var c = columnInfo[idx].ColumnName; return function () { self.sort(c); } })());
45720                    td.appendChild(tdSortSpan);
45721                }
45722            }
45723
45724            this.renderPage(1);
45725        },
45726        /**
45727        * Sort the data in the table by the specified column name in the model.
45728        * @param {String} columnName The column name in the model to sort by.
45729        * @returns {void}
45730        */
45731        sort : function(columnName)
45732        {
45733            var columnInfo = this.getModel().getColumns();
45734            var sortDir = null;
45735            var cmpFunc;
45736            var thNode;
45737            var colOptions;
45738            var sortColName;
45739
45740            if (!this._doPrivateValidate())
45741                return;
45742
45743            for (var idx = 0; idx < columnInfo.length; idx++) {
45744                if (columnInfo[idx].ColumnName == columnName) {
45745                    colOptions = this._colOptions[columnInfo[idx].ColumnName];
45746                    if (colOptions == null) {
45747                        this._colOptions[columnName] = {};
45748                        colOptions = this._colOptions[columnName];
45749                    }
45750
45751                    thNode = colOptions.thNode;
45752
45753                    if (colOptions.currentSortDir == null)
45754                        colOptions.currentSortDir = 1;
45755                    sortDir = colOptions.currentSortDir;
45756
45757                    if (sortDir == 1) {
45758                        domClass.remove(thNode, "footable-sorted");
45759                        domClass.add(thNode, "footable-sorted-desc");
45760                    }
45761                    else {
45762                        domClass.remove(thNode, "footable-sorted-desc");
45763                        domClass.add(thNode, "footable-sorted");
45764                    }
45765                }
45766                else {
45767                    //remove the sort direction
45768                    if (this._colOptions[columnInfo[idx].ColumnName] != null) {
45769                        if (this._colOptions[columnInfo[idx].ColumnName].thNode != null) {
45770                            domClass.remove(this._colOptions[columnInfo[idx].ColumnName].thNode, "footable-sorted");
45771                            domClass.remove(this._colOptions[columnInfo[idx].ColumnName].thNode, "footable-sorted-desc");
45772                        }
45773                    }
45774                }
45775            }
45776
45777            if (colOptions.altSortColumn != null)
45778                sortColName = colOptions.altSortColumn;
45779            else
45780                sortColName = columnName;
45781
45782            if (sortDir == null)
45783                throw new Error("Invalid sort column name of: " + columnName);
45784
45785            if (colOptions.DataType == "DATE")
45786            {
45787                cmpFunc = function (a, b) {
45788                    var v1 = a[sortColName];
45789                    var v2 = b[sortColName];
45790                    if (v1 == null && v2 == null)
45791                        return 0;
45792                    else if (v1 == null && v2 != null)
45793                        return -sortDir;
45794                    else if (v1 != null && v2 == null)
45795                        return sortDir;
45796                    else {
45797                        v1 = new Date(v1);
45798                        v2 = new Date(v2);
45799                        return v1 > v2 ? sortDir : v1 < v2 ? -sortDir : 0;
45800                    }
45801                };
45802            }
45803            else if (colOptions.DataType == "NUMBER") {
45804                cmpFunc = function (a, b) {
45805                    var v1 = a[sortColName];
45806                    var v2 = b[sortColName];
45807                    if (v1 == null && v2 == null)
45808                        return 0;
45809                    else if (v1 == null && v2 != null)
45810                        return -sortDir;
45811                    else if (v1 != null && v2 == null)
45812                        return sortDir;
45813                    else {
45814                        v1 = new Number(v1);
45815                        v2 = new Number(v2);
45816                        return v1 > v2 ? sortDir : v1 < v2 ? -sortDir : 0;
45817                    }
45818                };
45819            }
45820            else {
45821                cmpFunc = function (a, b) {
45822                    var v1 = a[sortColName];
45823                    var v2 = b[sortColName];
45824                    if (v1 == null && v2 == null)
45825                        return 0;
45826                    else if (v1 == null && v2 != null)
45827                        return -sortDir;
45828                    else if (v1 != null && v2 == null)
45829                        return sortDir;
45830                    else {
45831                        return v1 > v2 ? sortDir : v1 < v2 ? -sortDir : 0;
45832                    }
45833                };
45834            }
45835
45836            this.getModel().getRows().sort(cmpFunc);
45837
45838            this.renderPage(this._currentPage);
45839
45840            //If you are in mobile or phone width it will hide the correct columns for you.
45841            $(this._containerNode).trigger('footable_redraw');
45842
45843            colOptions.currentSortDir *= -1;
45844        },
45845        /*
45846        * Render a row of data. Intended to be used as an internal method in a derived table. 
45847        * Can be overridden to render a row any way you would like. Default behavior
45848        * is to return a fully populated TR node. This is the node that is inserted onto the TBODY
45849        * of the table.
45850        * @param {Object} dataRow The row of data from the model.
45851        * @param {Array} columnInfo The column info for this table.
45852        * @returns {DomNode} The TR node to append to the TBODY for this row.
45853        */
45854        _renderRow: function (dataRow , columnInfo) {
45855            var columnNames = this._renderCNameAr;
45856            var tr = document.createElement("TR");
45857            var td;
45858
45859            for (var cIdx = 0; cIdx < columnNames.length; cIdx++) {
45860                var colOptions = this._colOptions[columnNames[cIdx]];
45861
45862                if (colOptions && colOptions.hideColumn)
45863                    continue;
45864
45865                td = document.createElement("TD");
45866
45867                tr.appendChild(td);
45868                //instantiate a widget?
45869                if (colOptions != null && colOptions.widgetConstructor != null) {
45870                    var widgetOptions = colOptions.widgetOptions;
45871                    if (widgetOptions == null)
45872                        widgetOptions = {};
45873
45874                    //add in options to bind the widget to the ds.
45875                    widgetOptions.model = new dpage.modules.TabularToSingleValueModel({tabularModel : this.getModel() , dataField : columnNames[cIdx] , dataRow : dataRow});
45876
45877                    var w = new colOptions.widgetConstructor(widgetOptions);
45878                    td.appendChild(w.getDomNode());
45879                    this._widgetList.push(w);
45880                    var sl = this._widgetLookup[this.getModel().getDataRowId(dataRow)];
45881                    if (sl == null) {
45882                        sl = {};
45883                        this._widgetLookup[this.getModel().getDataRowId(dataRow)] = sl;
45884                    }
45885                    sl[columnNames[cIdx]] = w;
45886                }
45887                else {
45888                    if (dataRow[columnNames[cIdx]] != null)
45889                        td.innerHTML = dojox.html.entities.encode(dataRow[columnNames[cIdx]].toString());
45890                }
45891
45892                //alternate value to use for sorting.
45893                if (colOptions != null && colOptions.altSortColumn) {
45894
45895                    if (colOptions.altColDataType == "DATE") {
45896                        var dateVal = new Date(dataRow[columnNames[cIdx]]);
45897                        domAttr.set(td, "data-value", dateVal.getTime());
45898                    }
45899                    else {
45900                        domAttr.set(td, "data-value", dataRow[colOptions.altSortColumn]);
45901                    }
45902                }
45903            }
45904
45905            return tr;
45906        },
45907        //either render a new table, or just bind an existing table to data.
45908        bindTable: function () {
45909            var self = this;
45910
45911            if (this._useExistingTable)
45912                this.bindExistingTable();
45913            else
45914                this.renderTable();
45915
45916            domClass.add(this._containerNode, "footable");
45917            domClass.add(this._containerNode, "table");
45918
45919            //Now turn the table into a footable.
45920            //these require jquery to be loaded first which we load in the outter require.
45921            require(["footable/footable"], function () {
45922                $(self._containerNode).footable({ breakpoints: { phone: self._phoneBreakpoint, tablet: self._tabletBreakpoint } });
45923            });
45924
45925            $(self._containerNode).bind({ 'footable_redrawn': function () { self.fixHiddenFooterInMobile(); } });
45926        },
45927        bindExistingTable: function () {
45928            var thead;
45929            var tbody;
45930            var curNode;
45931            var curRowNode;
45932            var modelNames = [];
45933            var self = this;
45934
45935            this._renderCNameAr = [];
45936
45937            for (var i = 0; i < this.getModel().getColumns().length; i++)
45938                this._renderCNameAr.push(this.getModel().getColumns()[i].ColumnName);
45939
45940            thead = query("THEAD", this._containerNode)[0];
45941            if (thead.nodeName != "THEAD")
45942                throw new Error("First child of a widgets.Table must be a thead when specifying to use the existing table.");
45943
45944            tbody = query("TBODY", this._containerNode)[0];
45945
45946            if (tbody.nodeName != "TBODY")
45947                throw new Error("Second child of a widgets.Table must be a tbody when specifying to use the existing table.");
45948
45949            curNode = query("TH", thead);
45950
45951            for (var idx = 0 ; idx < curNode.length ; idx++) {
45952                //look for this attribute on thead nodes so we know to bind this column to a model column.
45953                var modelProp = domAttr.get(curNode[idx], "data-model-prop");
45954
45955                if (modelProp) {
45956                    if (!this._modelColNames[modelProp])
45957                        throw new Error("Invalid model column name of: " + modelProp + " specified in a data-model-prop attribute.");
45958                    modelNames.push(modelProp);
45959                }
45960                else
45961                    modelNames.push(null);
45962            }
45963
45964            //check to see if we have colOptions, that the table has a data-model-prop attribute that corresponds to it to help usability of the control
45965            for (var colName in this._colOptions) {
45966                if (this._colOptions.hasOwnProperty(colName)) {
45967                    var good = false;
45968                    for (var idx = 0; idx < modelNames.length; idx++)
45969                        if (modelNames[idx] == colName)
45970                            good = true;
45971
45972                    if (!good) {
45973                        throw new Error("Table: " + this.getWidgetId() + ". You have specified a colOption for column " + colName + " but have not added a data-model-prop attribute on the <th> node, like this: <th data-model-prop='" + colName + "'>" + colName + " (or custom header content)</th>");
45974                    }
45975                }
45976            }
45977
45978
45979            curRowNode = query("TR", tbody);
45980
45981            //for each row.
45982            for (var idx = 0; idx < curRowNode.length; idx++) {
45983                curNode = query("TD", curRowNode[idx]);
45984                //for each row
45985                for (var idxCol = 0; idxCol < curNode.length; idxCol++) {
45986                    var modelColumn = modelNames[idxCol];
45987
45988                    if (modelColumn != null) {
45989                        if (this._colOptions[modelColumn] != null && this._colOptions[modelColumn].widgetConstructor != null) {
45990                            var widgetOptions = this._colOptions[modelColumn].widgetOptions;
45991                            if (widgetOptions == null)
45992                                widgetOptions = {};
45993
45994                            //add in options to bind the widget to the ds.
45995                            widgetOptions.model = new dpage.modules.TabularToSingleValueModel({ tabularModel: this.getModel(), dataField: modelColumn, dataRow: this.getModel().getRows()[idx] });
45996
45997                            curNode[idxCol].innerHTML = "";
45998                            if (idx >= this.getModel().getRows().length)
45999                                throw new Error("When bound to a model, the number of model rows and table rows must match. Num model rows= " + this.getModel().getRows().length + " num table rows= " + curRowNode.length);
46000                            var w = new this._colOptions[modelColumn].widgetConstructor(widgetOptions);
46001                            curNode[idxCol].appendChild(w.domNode);
46002                            this._widgetList.push(w);
46003                            var sl = this._widgetLookup[this.getModel().getDataRowId(this.getModel().getRows()[idx])];
46004                            if (sl == null) {
46005                                sl = {};
46006                                this._widgetLookup[this.getModel().getDataRowId(this.getModel().getRows()[idx])] = sl;
46007                            }
46008                            sl[modelColumn] = w;
46009                        }
46010                    }
46011                }
46012            }
46013        },
46014        /**
46015        * Set the model for the Table. Will cause the table to be redrawn.
46016        * @param {dpage.modules.TabularModel} model The model to set.
46017        * @param {bool} [dontRenderTable] if true, the table will not be re-drawn to match the data.
46018        * @returns {void}
46019        */
46020        setModel: function (model, dontRenderTable) {
46021            this.inherited(arguments);
46022
46023            if (!dontRenderTable)
46024                this.bindTable();
46025        },
46026        //overridden
46027        validate: function () {
46028            var message;
46029            var ret = "";
46030
46031            for (var idx = 0; idx < this._widgetList.length ; idx++) {
46032                message = this._widgetList[idx].validate();
46033                if (message != null)
46034                    ret += message + " ";
46035            }
46036
46037            if (ret != "")
46038                return ret;
46039            else
46040                return null;
46041        }
46042
46043    });
46044});
46045
46046},
46047'dpage/modules/TabularToSingleValueModel':function(){
46048define([
46049      "dojo/_base/declare"
46050      , "dojo/on"
46051      , "dojo/_base/event"
46052
46053      , "dpage/modules/SingleValueModel"
46054],
46055    function (declare, on, event) {
46056        /**
46057        * @namespace dpage
46058        */
46059        /**
46060        * @namespace modules
46061        * @memberOf dpage
46062        */
46063        /**
46064         * This class is intended to provide a wrapper around a TabularModel so that the multi-column, multi-row TabularModel can look like a
46065         * SingleValueModel. Great for when you need to bind a SingleValueWidget to a particular value in a TabularModel. You have to tell this 
46066         * class which column and row to bind to. Then, this class exposes that value the same as a SingleValueModel would.
46067         * @class TabularToSingleValueModel
46068         * @param {Object} [options] Optional options for the TabularModel. 
46069         * @param {dpage.modules.TabularModel} [options.tabularModel] The TabularModel we are wrapping.
46070         * @param {String} [options.dataField] The dataField in the TabularModel we are binding to. If not specified, will default to the "first" column in the TabularModel.
46071         * @param {Object} [options.dataRow] Number|Object The row object in the TabularModel we are binding to. If not specified, will default to the first row in the TabularModel.
46072         *                                   You can pass in either a row object from the TabularModel or a row index (zero-based).
46073
46074         * @param {Object} [options.displayName] The display name of this property. This will be used in things like validation messages. If passed, overrides the DisplayName and FieldName properties in the modelProps.
46075         * @param {Object} [options.modelProps] Optional properties describing the model value including DataType, etc.
46076         * @param {String} [options.modelProps.ColumnName] Name of the field in the model (Deprecated).
46077         * @param {String} [options.modelProps.DataType] NUMBER, BOOL, or TEXT
46078         * @param {String} [options.modelProps.DisplayName] Value used for display of the field to the user.
46079         * @param {String} [options.modelProps.FieldName] Name of the field in the model.
46080         * @param {Number} [options.modelProps.MaxLength] Maximum character length.
46081         * @param {String} [options.modelProps.MaxLengthValidationMessage] Message to display for MaxLength validation failure.
46082         * @param {Number} [options.modelProps.MaxValue] Maximum value for NUMBER type.
46083         * @param {Number} [options.modelProps.MinValue] Minimum value for NUMBER type.
46084         * @param {String} [options.modelProps.NumberValidationMessage] Message to display if the number validation fails.
46085         * @param {Number} [options.modelProps.NumDecimals] Maximum number of decimals for NUMBER type.
46086         * @param {bool}   [options.modelProps.Required] Is a non-blank value required in this field
46087         * @param {String} [options.modelProps.RequiredValidationMessage] Message to display for Required validation failure.
46088         * @param {String} [options.modelProps.ValidationPattern] Javascript regular expression for input validation.
46089         * @param {String} [options.modelProps.ValidationPatternMessage] Custom message to display if ValidationPattern fails.
46090         * @memberOf dpage.modules
46091         * @extends {dpage.modules.SingleValueModel}
46092         */
46093        return declare("dpage.modules.TabularToSingleValueModel", [dpage.modules.SingleValueModel], /** @lends dpage.modules.TabularToSingleValueModel.prototype */ {
46094            _model: null,
46095            _dataCallbacks: null,
46096            _lastDataCallbackId: 0,
46097            _dataCallbackRowId: 0,
46098            _modelProps: null,
46099            _dataField:null,
46100            _dataRow:null,
46101
46102            constructor: function (options) {
46103                var self = this;
46104
46105                this._dataCallbacks = [];
46106
46107                if (options == null || options.tabularModel == null)
46108                    throw new Error("Must pass in a non-null tabularModel property that is an instance of a dpage.modules.TabularModel");
46109
46110                if (options != null) {
46111
46112                    if (options.tabularModel != null) {
46113                        this._model = options.tabularModel;
46114                    }
46115
46116                    if (options.dataField != null) {
46117                        this._dataField = options.dataField;
46118                    }
46119
46120                    if (options.dataRow != null) {
46121                        if (typeof (options.dataRow) == 'number' || options.dataRow instanceof (Number))
46122                            this._dataRow = this._model.getRow(options.dataRow);
46123                        else
46124                            this._dataRow = options.dataRow;
46125                    }
46126
46127                    if (options.modelProps != null)
46128                        this._modelProps = options.modelProps;
46129                }
46130
46131                if (this._dataRow == null) {
46132                    if (this._model.getRows().length == 0)
46133                        throw new Error("Problem binding to row of a TabularModel. Must pass the dataRow option and the TabularModel must have at least one row of data.");
46134                    this._dataRow = this._model.getRows()[0];
46135                }
46136
46137                if (this._dataField == null)
46138                    this._dataField = this._model.getColumns()[0].ColumnName;
46139
46140                if (options == null || options.modelProps == null)
46141                    this._modelProps = this._model.getColumnInfo(this._dataField);
46142
46143
46144                this._model.addDataCallback(function (changeType, rowObj, propName) { self.tmCallback(changeType, rowObj, propName); }, this._dataRow);
46145            },
46146            /**
46147            * Provides the single scalar value.
46148            * @returns {Object}
46149            */
46150            getRawModel : function()
46151            {
46152                return this.getValue();
46153            },
46154            /**
46155            * Get the dataField from the wrapped TabularModel that we are bound to.
46156            * @returns {String} The dataField.
46157            */
46158            getDataField : function()
46159            {
46160                return this._dataField;
46161            },
46162            /**
46163            * Get the dataRow from the wrapped TabularModel that we are bound to. 
46164            * @returns {Object} The row object from the TabularModel.
46165            */
46166            getDataRow : function()
46167            {
46168                return this._dataRow;
46169            },
46170            //Called whenever the TabularModel changes.
46171            tmCallback : function(changeType , rowObj , propName)
46172            {
46173                if(changeType == "CHANGE" && propName == this._dataField)
46174                {
46175                    this.doCallbacks();
46176                }
46177            },
46178            /**
46179            * Get the TabularModel object that this object is wrapping. This is usefull if you need to get or set the value
46180            * of a different field in the same row of the TabularModel this object is wrapping.
46181            * @returns {dpage.modules.TabularModel}
46182            */
46183            getTabularModel : function()
46184            {
46185                return this._model;
46186            },
46187            /**
46188            * Overrides SingleValueModel.setModel(). Set the value in the row and cell of the 
46189            * TabularModel this object is bound to. The official way to set a value.
46190            * @param {Object} value The value to set. Must be a bool, String, or Number
46191            * @returns {void}
46192            */
46193            setValue: function (value) {
46194
46195                this._model.setValue(this._dataRow , this._dataField , value);
46196            },
46197            //overridden.
46198            isDirty : function()
46199            {
46200                return this._model.isDirty();
46201            },
46202            /**
46203            * Overrides SingleValueModel.getValue(). Gets the value of the row and cell that this object
46204            * is bound to. The official way to get a value.
46205            * @returns {Object} The data. Will be String, Number, or Boolean
46206            */
46207            getValue: function () {
46208                return this._model.getValue(this._dataRow , this._dataField);
46209            }
46210
46211        });
46212    }
46213);
46214},
46215'dpage/modules/Config':function(){
46216define([
46217      "dojo/_base/declare"
46218],
46219    function (declare) {
46220        var c = declare("dpage.modules.Config", [], {
46221        });
46222
46223        c.dpageRoot = "https://svc.mt.gov/itsd/dpage/";
46224        c.dpageScriptRoot = "https://svc.mt.gov/itsd/dpage/Scripts/1.0/";
46225
46226        return c;
46227    }
46228);
46229},
46230'dpage/widgets/TableColumnNameWidget':function(){
46231define([
46232      "dojo/_base/declare",
46233      "dpage/widgets/BaseWidget"],
46234function () {
46235    /**
46236    * @namespace dpage
46237    */
46238    /**
46239    * @namespace widgets
46240    * @memberOf dpage
46241    */
46242    /**
46243    * Class for creating a custom column header for the dpage.widgets.Table class. Use this class to control how the TH node of the table looks.
46244    * @class TableColumnNameWidget
46245    * @param {Object} [options] Optional options for the widget
46246    *
46247    * @param {dpage.widgets.Table} options.tableObj The table object this widget is in.
46248    * @param {String} options.modelFieldName The name of the model field this cell is bound to.
46249    *
46250    * @param {dpage.widgets.Container} [options.container] The container of the widget.
46251    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
46252    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
46253    *                               is created.
46254    * @param {Object} [containerNode] Optional container node to tie the widget to.
46255    * @memberOf dpage.widgets
46256    * @extends {dpage.widgets.BaseWidget}
46257    */
46258    return dojo.declare("dpage.widgets.TableColumnNameWidget", [dpage.widgets.BaseWidget], /** @lends dpage.widgets.TableColumnNameWidget.prototype */ {
46259        _tableObj: null,
46260        _modelFieldName : null,
46261
46262        constructor: function (options, srcNodeRef) {
46263            if (options == null || options.tableObj == null || options.modelFieldName == null)
46264                throw new Exception("Must define options.tableObj and options.modelFieldName");
46265
46266            this._containerNode = srcNodeRef;
46267
46268            if (this._containerNode == null)
46269                this._containerNode = document.createElement("th");
46270
46271            this._tableObj = options.tableObj;
46272            this._modelFieldName = options.modelFieldName;
46273        },
46274        postCreate : function(){
46275            this._updateView();
46276        },
46277        //The default view.
46278        _updateView : function(){
46279            var meta = this._tableObj.getModel().getColumnInfo(this._modelFieldName);
46280            var text;
46281
46282            if (meta.DisplayName != null)
46283                text = dojox.html.entities.encode(meta.DisplayName);
46284            else
46285                text = dojox.html.entities.encode(this._modelFieldName);
46286
46287            this._containerNode.innerHTML = text;
46288        },
46289        getTableObj : function()
46290        {
46291            return this._tableObj;
46292        },
46293        getModelFieldName: function () {
46294            return this._modelFieldName;
46295        },
46296        destroy: function () {
46297            this._tableObj = null;
46298            this._modelFieldName = null;
46299            return this.inherited(arguments);
46300        }
46301
46302    });
46303});
46304
46305},
46306'dpage/widgets/DateTextBox':function(){
46307define([
46308      "dojo/_base/event"
46309      , "dojo/on"
46310      , "dojo/dom-attr"
46311      , "dojo/dom-class"
46312      , "dojo/mouse"
46313      , "dojo/dom-geometry"
46314      , "dojo/dom-style"
46315      , "dojo/json"
46316      , "dojo/_base/declare"
46317      , "jQueryPrivate"
46318      , "dojo/date/locale"
46319
46320      , "xstyle/css!//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css"
46321      , "dpage/widgets/TextBox"
46322      , "jquery-ui/ui/datepicker"
46323      , "dpage/modules/Date"
46324      , "dpage/widgets/SingleValueWidget"],
46325function (event, on, domAttr, domClass, mouse, domGeom, style, json, declare, $, locale) {
46326    /**
46327    * @namespace dpage
46328    */
46329    /**
46330    * @namespace widgets
46331    * @memberOf dpage
46332    */
46333    /**
46334    * Specialized TextBox for dates. Uses the default date format specified in dpage.modules.Date.getDatePattern() unless you specify a custom one in the options.
46335    * @class DateTextBox
46336    * @param {Object} [options] Optional options for the widget.
46337    * @param {bool} [options.datePicker] Default true. Add a date picker to the textbox.
46338    * @param {string} [options.dateFormatString] Default null. If null, defaults to the dpage.modules.Date.getDatePattern() string. This string contains the pattern used to 
46339    *                                            parse and format the dates. This string conforms to the specification here:
46340    *                                             <a href='http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns'>http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns</a>
46341
46342    * @param {String} [options.placeHolder] Optional placeholder text. Backwards compatible on browsers that don't natively support this attribute.
46343    * @param {Function} [options.formatter] string options.formatter(rawValue). Function to call for formatting the text. The formatter will be used 
46344    *                                       to set the value of the input when the input is non-focused. When the input is focused,
46345    *                                       the raw value from the model will be shown. This function returns the value to display in the textbox.
46346    * @param {Function} [options.editFormatter] string options.formatter(rawValue). Function to call for formatting the text when the TextBox is focused. 
46347    *                                       The formatter will be used 
46348    *                                       to set the value of the input when the input is focused.
46349    * @param {Function} [options.inputFilter] string options.inputFilter(rawValue). This function will be called to return the value that is saved to the model.
46350    *                                         Default behavior is to store the value the user types into the TextBox to the model. Passing in this function overrides
46351    *                                         this behavior.
46352    *                                         The function is passed the raw value that the user types into the textbox. The function will return the value
46353    *                                         to store in the model. This function only operates on user input and is meant to be used to coerce different forms of user
46354    *                                         input to the correct model value.
46355    * @param {bool} [options.highlightOnFocus] Default false. Highlight the text when the input is focused.
46356    * @param {Function} [options.onChange] callback function for when widget value changes from user input. May or may not correspond to a model value change in the case of invalid input.
46357     
46358    * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget.
46359    * @param {dpage.widgets.Container} [options.container] The container of the widget.
46360    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
46361    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
46362    *                               is created.
46363    * @param {Object} [containerNode] Optional container node to tie the widget to. 
46364    * @memberOf dpage.widgets
46365    * @extends {dpage.widgets.SingleValueWidget}
46366    */
46367    return declare("dpage.widgets.DateTextBox", [dpage.widgets.TextBox], /** @lends dpage.widgets.DateTextBox.prototype */ {
46368        _datePicker: true,
46369        _dateFormatString: null,
46370
46371        constructor: function (options, srcNodeRef) {
46372            var self=this;
46373
46374            if(options == null)
46375                options = {};
46376
46377            if (options.dateFormatString != null)
46378                this._dateFormatString = options.dateFormatString;
46379            if(options.formatter == null)
46380                this._formatter = function (v) { return self.formatDate(v); };
46381            if (options.editFormatter == null)
46382                this._editFormatter = function (v) { return self.formatDate(v); };
46383            if (options.inputFilter == null)
46384                this._inputFilter = function (v) { return self.inputFilter(v); };
46385            if (options.datePicker != undefined && options.datePicker == false)
46386                this._datePicker = false;
46387            if (options.model != null && options.model.getMetadata().DataType != "DATE")
46388                throw new Error("The DataType for a DateTextBox must be DATE. WidgetId: " + this.getWidgetId());
46389        },
46390        postCreate : function(){
46391            var self = this;
46392            if (this._datePicker) {
46393                $(this.getDomNode()).datepicker({
46394                    onSelect: function (dateText) { self.datePicker_OnChange(dateText); },
46395                    beforeShow : function(inputElement , instance) { return self.datePicker_BeforeShow(inputElement , instance);},
46396                    constrainInput:false
46397                });
46398            }
46399            return this.inherited(arguments);
46400        },
46401        setModel: function (model) {
46402            //validate the model and all.
46403            this.inherited(arguments);
46404
46405            if (model != null && model.getMetadata().DataType != "DATE")
46406                throw new Error("The DataType for a DateTextBox must be DATE. WidgetId: " + this.getWidgetId());
46407        },
46408        datePicker_BeforeShow: function (inputElement, instance) {
46409            var d = dpage.modules.Date.parseDateString(inputElement.value , this._dateFormatString);
46410            var oldInputText = inputElement.value;
46411            //causes the input to be updated.
46412            $(this.getDomNode()).datepicker("setDate", d);
46413
46414            setTimeout(function () { inputElement.value = oldInputText; }, 0);
46415        },
46416        datePicker_OnChange : function(dateText)
46417        {
46418            var prevDate = dpage.modules.Date.parseModelValue(this.getValue());
46419            var newDate = $(this.getDomNode()).datepicker("getDate");
46420
46421            //We want to keep the minutes/seconds/milliseconds parts.
46422            if (isFinite(newDate) && prevDate != null){
46423                //possibly change the value to keep the minutes/seconds.
46424                newDate.setSeconds(prevDate.getSeconds());
46425                newDate.setMinutes(prevDate.getMinutes());
46426                newDate.setMilliseconds(prevDate.getMilliseconds());
46427                newDate.setHours(prevDate.getHours());
46428            }
46429
46430            this.setValue(dpage.modules.Date.toModelValue(newDate));
46431        },
46432        //default date formatter
46433        formatDate : function(strVal){
46434            var v;
46435
46436            if (strVal == null)
46437                return "";
46438            
46439            v = dpage.modules.Date.parseModelValue(strVal);
46440
46441            if (v == null)
46442                return strVal;
46443            else {
46444                var str;
46445                
46446                if(this._dateFormatString == null)
46447                    str = dpage.modules.Date.formatDate(v);
46448                else
46449                    str = locale.format(v, {
46450                        datePattern: this._dateFormatString,
46451                        selector: "date"
46452                    });
46453
46454                return str;
46455            }
46456        },
46457        inputFilter: function (strVal) {
46458            var d;
46459
46460            if (strVal == null || strVal.match(/^\s*$/) != null)
46461                return null;
46462            
46463            if(this._dateFormatString == null)
46464                d = dpage.modules.Date.parseDateString(strVal);
46465            else
46466                d = locale.parse(strVal, {
46467                    datePattern: this._dateFormatString,
46468                    selector: "date"
46469                });
46470
46471            if (d!=null)
46472                return dpage.modules.Date.toModelValue(d);
46473            else
46474                return strVal;
46475        },
46476        //get the displayed value from the textbox and validate that.
46477        validate: function () {
46478            var value = this.getTextValue(); //get the value displayed in the textbox.
46479            var ret;
46480
46481            domClass.remove(this._containerNode, "input-invalid");
46482
46483            ret = this._validateDate(value, this.getModel().getMetadata(), this.getModel().getDisplayName());
46484
46485            if (ret != null)
46486                domClass.add(this._containerNode, "input-invalid");
46487
46488            return ret;
46489        },
46490        /*
46491        * Return a message indicating the error or null for no validation error.
46492        * @param {Object} value The value to validate.
46493        * @param {Object} metaData The metadata object from the model.
46494        * @param {String} fieldName The name of the field to display in the non-custom error message.
46495        * @returns {String} null for success. non-empty string otherwise.
46496        */
46497        _validateDate : function (value, metaData, fieldName) {
46498            var maxLength = metaData.MaxLength;
46499            var required = metaData.Required;
46500            var requiredMessage = metaData.RequiredValidationMessage;
46501            var maxLengthMessage = metaData.MaxLengthValidationMessage;
46502            var patternMessage = metaData.ValidationPatternMessage;
46503            var pattern = metaData.ValidationPattern;
46504
46505            if (fieldName == null)
46506                fieldName = metaData.FieldName;
46507
46508            if (maxLength != null && value.length > maxLength) {
46509                if (maxLengthMessage != null)
46510                    return maxLengthMessage;
46511                else
46512                    return fieldName + " must be less than " + (maxLength + 1) + " characters.";
46513            }
46514
46515            if (required && (value == null || /^\s*$/.exec(value))) {
46516                if (requiredMessage != null)
46517                    return requiredMessage;
46518                else
46519                    return fieldName + " is required.";
46520            }
46521
46522            if (pattern != null) {
46523                var re = new RegExp(pattern);
46524                if (!re.exec(value)) {
46525                    if (patternMessage != null)
46526                        return patternMessage;
46527                    else
46528                        return fieldName + " must match the pattern: '" + pattern + "'.";
46529                }
46530            }
46531
46532            if (value != null && value != "") {
46533                //attempt to parse the date.
46534                var v = dpage.modules.Date.parseDateString(value , this._dateFormatString);
46535
46536                if (v == null) {
46537                    var pString;
46538
46539                    if (this._dateFormatString == null)
46540                        pString = dpage.modules.Date.getDatePattern();
46541                    else
46542                        pString = this._dateFormatString;
46543
46544                    return fieldName + " must be a valid date in the format of: " + pString;
46545                }
46546            }
46547
46548            return null;
46549        }
46550
46551    });
46552});
46553
46554},
46555'dpage/widgets/TextBox':function(){
46556define([
46557      "dojo/_base/event"
46558      ,"dojo/on"
46559      ,"dojo/dom-attr"
46560      ,"dojo/dom-class"
46561      ,"dojo/mouse"
46562      ,"dojo/dom-geometry"
46563      , "dojo/dom-style"
46564      , "dojo/json"
46565
46566      , "xstyle/css!dpage/widgets/TextBox.css"
46567      , "dpage/modules/LegacyPlaceholder"
46568      , "dpage/modules/TabularModel"
46569      , "dojo/request/xhr"
46570      ,"dojox/html/entities"
46571      ,"dojo/_base/declare"
46572      , "dpage/widgets/SingleValueWidget"],
46573function (event, on, domAttr, domClass, mouse, domGeom, style, json) {
46574    /**
46575    * @namespace dpage
46576    */
46577    /**
46578    * @namespace widgets
46579    * @memberOf dpage
46580    */
46581    /**
46582    * Class to encapulate the functionality of a &lt;input type="text"&gt; element. Supports containerNode type 
46583    * of either an INPUT type='text' or a TEXTAREA. INPUT's have a known
46584    *size limitation in the browser that cannot be overcome. Use a TEXTAREA for large amounts > .5MB. of data.
46585    * @class TextBox
46586    * @param {Object} [options] Optional options for the widget.
46587    * @param {String} [options.placeHolder] Optional placeholder text. Backwards compatible on browsers that don't natively support this attribute.
46588    * @param {Function} [options.formatter] string options.formatter(rawValue). Function to call for formatting the text. The formatter will be used 
46589    *                                       to set the value of the input when the input is non-focused. When the input is focused,
46590    *                                       the raw value from the model will be shown (or the value returned from editFormatter(). This function returns the value to display in the textbox.
46591    * @param {Function} [options.editFormatter] string options.formatter(rawValue). Function to call for formatting the text when the TextBox is focused. Either the model value
46592    *                                           will be passed in, or the last user inputted value. In an inputFilter() is specified, the last user input is fed to that function first.
46593    * @param {Function} [options.inputFilter] string options.inputFilter(rawValue). This function will be called to return the value that is saved to the model.
46594    *                                         Default behavior is to store the value the user types into the TextBox to the model. Passing in this function overrides
46595    *                                         this behavior.
46596    *                                         The function is passed the raw value that the user types into the textbox. The function will return the value
46597    *                                         to store in the model. This function only operates on user input and is meant to be used to coerce different forms of user
46598    *                                         input to the correct model value.
46599    * @param {bool} [options.highlightOnFocus] Default false. Highlight the text when the input is focused.
46600    * @param {Function} [options.onChange] callback function for when widget value changes from user input. May or may not correspond to a model value change in the case of invalid input.
46601     
46602    * @param {dpage.modules.SingleValueModel} [options.model] The model for the widget.
46603    * @param {dpage.widgets.Container} [options.container] The container of the widget.
46604    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
46605    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
46606    *                               is created.
46607    * @param {Object} [containerNode] Optional container node to tie the widget to. 
46608    * @memberOf dpage.widgets
46609    * @extends {dpage.widgets.SingleValueWidget}
46610    */
46611    return dojo.declare("dpage.widgets.TextBox", [dpage.widgets.SingleValueWidget], /** @lends dpage.widgets.TextBox.prototype */ {
46612        _containerNode: null,
46613        _placeholder: null,
46614        _emulatePlaceholder: false, //support for IE9 placeholder.
46615        _onChange: null, //needs to be null here an initialized in the constructor otherwise it acts like a static member.
46616        _formatter: null,
46617        _editFormatter: null,
46618        _inputFilter:null,
46619        _lastUserInput: null, //This gets populated when the user focuses into or out of the input.
46620        _focused: false,
46621        _highlightOnFocus: false,
46622
46623        constructor : function(options , srcNodeRef)
46624        {
46625            var self = this;
46626            this._containerNode = srcNodeRef;
46627
46628            this._onChange = [];
46629
46630            if (this._containerNode == null) {
46631                this._containerNode = document.createElement("INPUT");
46632            }
46633
46634            if (this._containerNode.nodeName != "INPUT" && this._containerNode.nodeName != "TEXTAREA")
46635                throw new Error("Source node for widgets.TextBox must be an INPUT or a TEXTAREA");
46636
46637            if (options != null)
46638            {
46639                if (options.placeholder != null) {
46640                    this._placeholder = options.placeholder;
46641                }
46642                if (options.onChange != null) {
46643                    this.on("change", options.onChange);
46644                }
46645                if (options.formatter != null) {
46646                    this._formatter = options.formatter;
46647                }
46648                if (options.editFormatter != null) {
46649                    this._editFormatter = options.editFormatter;
46650                }
46651                if (options.inputFilter != null) {
46652                    this._inputFilter = options.inputFilter;
46653                }
46654                if (options.highlightOnFocus)
46655                    this._highlightOnFocus = options.highlightOnFocus;
46656            }
46657
46658            on(this._containerNode, "blur", function (event) { self.input_OnBlur(event); });
46659            on(this._containerNode, "focus", function (event) { self.input_OnFocus(event); });
46660            on(this._containerNode, "change", function (event) { self.input_OnChange(event); });
46661            on(this._containerNode, mouse.enter, function (event) { self._item_OnMouseEnter(event); });
46662            on(this._containerNode, mouse.leave, function (event) { self._item_OnMouseLeave(event); });
46663        },
46664        postCreate: function ()
46665        {
46666            //initialize from the dom node.
46667            if (domAttr.get(this.domNode, "placeholder") != null)
46668                this._placeholder = domAttr.get(this.domNode, "placeholder");
46669
46670            if (this._placeholder != null) {
46671                if (dpage.modules.LegacyPlaceholder.hasNativePlaceholderSupport())
46672                    domAttr.set(this.domNode, "placeholder", this._placeholder);
46673                else {
46674                    this._emulatePlaceholder = true;
46675                }
46676            }
46677
46678            //support setting the model value based on a value in the markup.
46679            if (this._containerNode.getAttribute("value") != null) {
46680                this.setModelValue(this._containerNode.getAttribute("value"));
46681            }
46682
46683            return this.inherited(arguments);
46684        },
46685
46686        setModel : function(model)
46687        {
46688            this.inherited(arguments);
46689            this._updateView();
46690        },
46691        input_OnFocus: function ()
46692        {
46693            var self = this;
46694            var nonFormattedValue;
46695
46696            if (this._lastUserInput != null) {
46697                if(this.getDomNode().value != this._lastUserInput)
46698                    this.getDomNode().value = this._lastUserInput;
46699            }
46700            else {
46701                if (this._editFormatter != null) {
46702                    if (this.getDomNode().value != this._editFormatter(this.getValue()))
46703                        this.getDomNode().value = this._editFormatter(this.getValue());
46704                }
46705                else {
46706                    if (this.getDomNode().value != this.getValue())
46707                        this.getDomNode().value = this.getValue() == null ? "" : this.getValue();
46708                }
46709            }
46710
46711            if(this._emulatePlaceholder)
46712            {
46713                if(this.domNode.value == this._placeholder)
46714                {
46715                    this.domNode.value = "";
46716                    domClass.remove(this.getDomNode(), "placeholder");
46717                }
46718            }
46719
46720            if(this._highlightOnFocus){
46721                setTimeout(function () {
46722                    self._containerNode.setSelectionRange(0, self._containerNode.value.length);
46723                });
46724            }
46725
46726            this._focused = true;
46727        },
46728        /**
46729        * This method returns the same value as getValue(), except in the case of bad user input. In that case, it will return back the user input value with the inputFilter() function 
46730        * applied (if applicable). With no inputFilter, formatter, or editFormatter applied, this function, and the getTextValue() function should return the same value.
46731        * @returns {Object} 
46732        */
46733        getCandidateValue: function () {
46734            var v;
46735
46736            //if for some reason, we get here and we have focus, we need to update the _lastUserInput var.
46737            if (this._focused)
46738                this._lastUserInput = this.getDomNode().value;
46739
46740            v = this._lastUserInput;
46741
46742            //if the control hasn't been focused since the last _updateView.
46743            if (v == null)
46744                return this.getValue();
46745
46746            //if we are a non-text datatype, we need to set the value to null on empty input.
46747            if (this._lastUserInput.match(/^\s*$/) != null &&
46748                (this.getModel().getMetadata().DataType == "NUMBER" ||
46749                this.getModel().getMetadata().DataType == "BOOL" ||
46750                this.getModel().getMetadata().DataType == "DATE")) {
46751                v = null;
46752            }
46753
46754            if (this._inputFilter != null)
46755                v = this._inputFilter(this._lastUserInput);
46756
46757            return v;
46758        },
46759        /*
46760        * Defined in TextBox. This method is designed to *ONLY* be called when the blur event fires. At this point, the value in the input is raw user input.
46761        */
46762        _doValueChanged: function (evt) {
46763            var cleansedValue;
46764
46765            if (this.validate() == null) {
46766                if (this.getContainer()) {
46767                    if (this.getContainer().getValidationMessageWidget()) {
46768                        this.getContainer().getValidationMessageWidget().removeErrorByWidgetID(this.getWidgetId());
46769                    }
46770                }
46771
46772                //only set the value if it is changed. Otherwise we taint the model.
46773                if (this.getCandidateValue() != this.getValue()) {
46774                    this.setModelValue(this.getCandidateValue());
46775                    //call callbacks in order.
46776                    for (var i = 0; i < this._onChange.length; i++)
46777                        this._onChange[i]({ event: evt, widget: this });
46778                }
46779            }
46780
46781            //we are moving out of focused and into a non-focused state.
46782            if (this._formatter != null) {
46783                //Q: Why do we do this instead of getting the value from the model? A: because the value in the textbox may be invalid input and in that case is not
46784                // saved to the model.
46785
46786                this.getDomNode().value = this._formatter(this.getCandidateValue());
46787            }
46788
46789            //ie9 support.
46790            if (this._emulatePlaceholder) {
46791                if (this.domNode.value == "") {
46792                    this.domNode.value = this._placeholder;
46793                    domClass.add(this.getDomNode(), "placeholder");
46794                }
46795                else {
46796                    domClass.remove(this.getDomNode(), "placeholder");
46797                }
46798            }
46799        },
46800        input_OnBlur: function (evt) {
46801            var self = this;
46802
46803            //store the value the user entered in.
46804            this._lastUserInput = this._containerNode.value;
46805
46806            this._doValueChanged(evt);
46807
46808            this._focused = false;
46809        },
46810        input_OnChange: function (evt)
46811        {
46812
46813        },
46814        /**
46815        * Focus the widget for user input.
46816        * @returns {void}
46817        */
46818        focus: function () {
46819            this.getDomNode().focus();
46820            this._focused = true;
46821        },
46822        /**
46823        * Get the raw value displayed in the control. This may not match the value returned from getValue() because the input could be invalid. There could also be formatter routines.
46824        * @returns {string}
46825        */
46826        getTextValue: function () {
46827            if (this._emulatePlaceholder && this.domNode.value == this._placeholder)
46828                return "";
46829            
46830            return this.getDomNode().value;
46831        },
46832        /*
46833        * Update the view based on model changes. This will also clear any invali
46833d state. Direct model changes should not be validated.
46834        */
46835        _updateView : function()
46836        {
46837            //call the base class (BaseWidget). This clears the validation state common to all BaseWidget _updateView methods.
46838            this.inherited(arguments);
46839
46840            var val = this.getValue();
46841
46842            //update the value in the textbox.
46843            if (val == null)
46844                val = "";
46845
46846            this._lastUserInput = null;
46847
46848            if (this._focused) {
46849                if (this._editFormatter != null)
46850                    this.getDomNode().value = this._editFormatter(val);
46851                else
46852                    this.getDomNode().value = val;
46853            }
46854            else {
46855                var valToSet;
46856                if (this._formatter != null)
46857                    valToSet = this._formatter(val);
46858                else
46859                    valToSet = val;
46860
46861                if (this._emulatePlaceholder && valToSet == "") {
46862                    domClass.add(this.getDomNode(), "placeholder");
46863                    this.getDomNode().value = this._placeholder;
46864                }
46865                else {
46866                    if (this._emulatePlaceholder)
46867                        domClass.remove(this.getDomNode(), "placeholder");
46868
46869                    this.getDomNode().value = valToSet;
46870                }
46871            }
46872        },
46873        templateString: "<div></div>",
46874        /**
46875        * Set an event handler.
46876        * @param {String} eventName The event to bind to. Only supported events are "change".
46877        * @param {function} functionRef The callback function to call.
46878        * @returns {void}
46879        */
46880        on: function (eventName, functionRef) {
46881            var self = this;
46882
46883            if (eventName != "change")
46884                throw new Error("Supported events are: 'change'.");
46885
46886            this._onChange.push(functionRef);
46887
46888        },
46889        /*
46890        * Make sure that this works when the control is focused and non-focused with an inputFormatter and without. When an inputFilter is specified, 
46891        */
46892        validate: function ()
46893        {
46894            var value = this.getCandidateValue();
46895            var ret;
46896
46897            ret = dpage.widgets.BaseWidget.validate(value, this.getModel().getMetadata(), this.getModel().getDisplayName());
46898
46899            this.setValidationMessage(ret);
46900
46901            return ret;
46902        },
46903        setValidationMessage: function (message) {
46904
46905            //call the base class.
46906            this.inherited(arguments);
46907
46908            domClass.remove(this._containerNode, "input-invalid");
46909
46910            if (message != null)
46911                domClass.add(this._containerNode, "input-invalid");
46912        },
46913        _item_OnMouseEnter: function (newLookupItem) {
46914            
46915        },
46916        _item_OnMouseLeave: function (newLookupItem) {
46917            
46918        }
46919   });
46920});
46921
46922},
46923'jquery-ui/ui/datepicker':function(){
46924/*!
46925 * jQuery UI Datepicker 1.11.2
46926 * http://jqueryui.com
46927 *
46928 * Copyright 2014 jQuery Foundation and other contributors
46929 * Released under the MIT license.
46930 * http://jquery.org/license
46931 *
46932 * http://api.jqueryui.com/datepicker/
46933 */
46934(function( factory ) {
46935	if ( typeof define === "function" && define.amd ) {
46936
46937		// AMD. Register as an anonymous module.
46938		define([
46939			"jquery",
46940			"./core"
46941		], factory );
46942	} else {
46943
46944		// Browser globals
46945		factory( jQuery );
46946	}
46947}(function( $ ) {
46948
46949$.extend($.ui, { datepicker: { version: "1.11.2" } });
46950
46951var datepicker_instActive;
46952
46953function datepicker_getZindex( elem ) {
46954	var position, value;
46955	while ( elem.length && elem[ 0 ] !== document ) {
46956		// Ignore z-index if position is set to a value where z-index is ignored by the browser
46957		// This makes behavior of this function consistent across browsers
46958		// WebKit always returns auto if the element is positioned
46959		position = elem.css( "position" );
46960		if ( position === "absolute" || position === "relative" || position === "fixed" ) {
46961			// IE returns 0 when zIndex is not specified
46962			// other browsers return a string
46963			// we ignore the case of nested elements with an explicit value of 0
46964			// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
46965			value = parseInt( elem.css( "zIndex" ), 10 );
46966			if ( !isNaN( value ) && value !== 0 ) {
46967				return value;
46968			}
46969		}
46970		elem = elem.parent();
46971	}
46972
46973	return 0;
46974}
46975/* Date picker manager.
46976   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
46977   Settings for (groups of) date pickers are maintained in an instance object,
46978   allowing multiple different settings on the same page. */
46979
46980function Datepicker() {
46981	this._curInst = null; // The current instance in use
46982	this._keyEvent = false; // If the last event was a key event
46983	this._disabledInputs = []; // List of date picker inputs that have been disabled
46984	this._datepickerShowing = false; // True if the popup picker is showing , false if not
46985	this._inDialog = false; // True if showing within a "dialog", false if not
46986	this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
46987	this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
46988	this._appendClass = "ui-datepicker-append"; // The name of the append marker class
46989	this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
46990	this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
46991	this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
46992	this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
46993	this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
46994	this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
46995	this.regional = []; // Available regional settings, indexed by language code
46996	this.regional[""] = { // Default regional settings
46997		closeText: "Done", // Display text for close link
46998		prevText: "Prev", // Display text for previous month link
46999		nextText: "Next", // Display text for next month link
47000		currentText: "Today", // Display text for current month link
47001		monthNames: ["January","February","March","April","May","June",
47002			"July","August","September","October","November","December"], // Names of months for drop-down and formatting
47003		monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
47004		dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
47005		dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
47006		dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
47007		weekHeader: "Wk", // Column header for week of the year
47008		dateFormat: "mm/dd/yy", // See format options on parseDate
47009		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
47010		isRTL: false, // True if right-to-left language, false if left-to-right
47011		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
47012		yearSuffix: "" // Additional text to append to the year in the month headers
47013	};
47014	this._defaults = { // Global defaults for all the date picker instances
47015		showOn: "focus", // "focus" for popup on focus,
47016			// "button" for trigger button, or "both" for either
47017		showAnim: "fadeIn", // Name of jQuery animation for popup
47018		showOptions: {}, // Options for enhanced animations
47019		defaultDate: null, // Used when field is blank: actual date,
47020			// +/-number for offset from today, null for today
47021		appendText: "", // Display text following the input box, e.g. showing the format
47022		buttonText: "...", // Text for trigger button
47023		buttonImage: "", // URL for trigger button image
47024		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
47025		hideIfNoPrevNext: false, // True to hide next/previous month links
47026			// if not applicable, false to just disable them
47027		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
47028		gotoCurrent: false, // True if today link goes back to current selection instead
47029		changeMonth: false, // True if month can be selected directly, false if only prev/next
47030		changeYear: false, // True if year can be selected directly, false if only prev/next
47031		yearRange: "c-10:c+10", // Range of years to display in drop-down,
47032			// either relative to today's year (-nn:+nn), relative to currently displayed year
47033			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
vendor: 27,281 bytes, lines 47034-47754
47034		showOtherMonths: false, // True to show dates in other months, false to leave blank
47035		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
47036		showWeek: false, // True to show week of the year, false to not show it
47037		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
47038			// takes a Date and returns the number of the week for it
47039		shortYearCutoff: "+10", // Short year values < this are in the current century,
47040			// > this are in the previous century,
47041			// string value starting with "+" for current year + value
47042		minDate: null, // The earliest selectable date, or null for no limit
47043		maxDate: null, // The latest selectable date, or null for no limit
47044		duration: "fast", // Duration of display/closure
47045		beforeShowDay: null, // Function that takes a date and returns an array with
47046			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
47047			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
47048		beforeShow: null, // Function that takes an input field and
47049			// returns a set of custom settings for the date picker
47050		onSelect: null, // Define a callback function when a date is selected
47051		onChangeMonthYear: null, // Define a callback function when the month or year is changed
47052		onClose: null, // Define a callback function when the datepicker is closed
47053		numberOfMonths: 1, // Number of months to show at a time
47054		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
47055		stepMonths: 1, // Number of months to step back/forward
47056		stepBigMonths: 12, // Number of months to step back/forward for the big links
47057		altField: "", // Selector for an alternate field to store selected dates into
47058		altFormat: "", // The date format to use for the alternate field
47059		constrainInput: true, // The input is constrained by the current date format
47060		showButtonPanel: false, // True to show button panel, false to not show it
47061		autoSize: false, // True to size the input for the date format, false to leave as is
47062		disabled: false // The initial disabled state
47063	};
47064	$.extend(this._defaults, this.regional[""]);
47065	this.regional.en = $.extend( true, {}, this.regional[ "" ]);
47066	this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
47067	this.dpDiv = datepicker_bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
47068}
47069
47070$.extend(Datepicker.prototype, {
47071	/* Class name added to elements to indicate already configured with a date picker. */
47072	markerClassName: "hasDatepicker",
47073
47074	//Keep track of the maximum number of rows displayed (see #7043)
47075	maxRows: 4,
47076
47077	// TODO rename to "widget" when switching to widget factory
47078	_widgetDatepicker: function() {
47079		return this.dpDiv;
47080	},
47081
47082	/* Override the default settings for all instances of the date picker.
47083	 * @param  settings  object - the new settings to use as defaults (anonymous object)
47084	 * @return the manager object
47085	 */
47086	setDefaults: function(settings) {
47087		datepicker_extendRemove(this._defaults, settings || {});
47088		return this;
47089	},
47090
47091	/* Attach the date picker to a jQuery selection.
47092	 * @param  target	element - the target input field or division or span
47093	 * @param  settings  object - the new settings to use for this date picker instance (anonymous)
47094	 */
47095	_attachDatepicker: function(target, settings) {
47096		var nodeName, inline, inst;
47097		nodeName = target.nodeName.toLowerCase();
47098		inline = (nodeName === "div" || nodeName === "span");
47099		if (!target.id) {
47100			this.uuid += 1;
47101			target.id = "dp" + this.uuid;
47102		}
47103		inst = this._newInst($(target), inline);
47104		inst.settings = $.extend({}, settings || {});
47105		if (nodeName === "input") {
47106			this._connectDatepicker(target, inst);
47107		} else if (inline) {
47108			this._inlineDatepicker(target, inst);
47109		}
47110	},
47111
47112	/* Create a new instance object. */
47113	_newInst: function(target, inline) {
47114		var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
47115		return {id: id, input: target, // associated target
47116			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
47117			drawMonth: 0, drawYear: 0, // month being drawn
47118			inline: inline, // is datepicker inline or not
47119			dpDiv: (!inline ? this.dpDiv : // presentation div
47120			datepicker_bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
47121	},
47122
47123	/* Attach the date picker to an input field. */
47124	_connectDatepicker: function(target, inst) {
47125		var input = $(target);
47126		inst.append = $([]);
47127		inst.trigger = $([]);
47128		if (input.hasClass(this.markerClassName)) {
47129			return;
47130		}
47131		this._attachments(input, inst);
47132		input.addClass(this.markerClassName).keydown(this._doKeyDown).
47133			keypress(this._doKeyPress).keyup(this._doKeyUp);
47134		this._autoSize(inst);
47135		$.data(target, "datepicker", inst);
47136		//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
47137		if( inst.settings.disabled ) {
47138			this._disableDatepicker( target );
47139		}
47140	},
47141
47142	/* Make attachments based on settings. */
47143	_attachments: function(input, inst) {
47144		var showOn, buttonText, buttonImage,
47145			appendText = this._get(inst, "appendText"),
47146			isRTL = this._get(inst, "isRTL");
47147
47148		if (inst.append) {
47149			inst.append.remove();
47150		}
47151		if (appendText) {
47152			inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
47153			input[isRTL ? "before" : "after"](inst.append);
47154		}
47155
47156		input.unbind("focus", this._showDatepicker);
47157
47158		if (inst.trigger) {
47159			inst.trigger.remove();
47160		}
47161
47162		showOn = this._get(inst, "showOn");
47163		if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
47164			input.focus(this._showDatepicker);
47165		}
47166		if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
47167			buttonText = this._get(inst, "buttonText");
47168			buttonImage = this._get(inst, "buttonImage");
47169			inst.trigger = $(this._get(inst, "buttonImageOnly") ?
47170				$("<img/>").addClass(this._triggerClass).
47171					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
47172				$("<button type='button'></button>").addClass(this._triggerClass).
47173					html(!buttonImage ? buttonText : $("<img/>").attr(
47174					{ src:buttonImage, alt:buttonText, title:buttonText })));
47175			input[isRTL ? "before" : "after"](inst.trigger);
47176			inst.trigger.click(function() {
47177				if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
47178					$.datepicker._hideDatepicker();
47179				} else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
47180					$.datepicker._hideDatepicker();
47181					$.datepicker._showDatepicker(input[0]);
47182				} else {
47183					$.datepicker._showDatepicker(input[0]);
47184				}
47185				return false;
47186			});
47187		}
47188	},
47189
47190	/* Apply the maximum length for the date format. */
47191	_autoSize: function(inst) {
47192		if (this._get(inst, "autoSize") && !inst.inline) {
47193			var findMax, max, maxI, i,
47194				date = new Date(2009, 12 - 1, 20), // Ensure double digits
47195				dateFormat = this._get(inst, "dateFormat");
47196
47197			if (dateFormat.match(/[DM]/)) {
47198				findMax = function(names) {
47199					max = 0;
47200					maxI = 0;
47201					for (i = 0; i < names.length; i++) {
47202						if (names[i].length > max) {
47203							max = names[i].length;
47204							maxI = i;
47205						}
47206					}
47207					return maxI;
47208				};
47209				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
47210					"monthNames" : "monthNamesShort"))));
47211				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
47212					"dayNames" : "dayNamesShort"))) + 20 - date.getDay());
47213			}
47214			inst.input.attr("size", this._formatDate(inst, date).length);
47215		}
47216	},
47217
47218	/* Attach an inline date picker to a div. */
47219	_inlineDatepicker: function(target, inst) {
47220		var divSpan = $(target);
47221		if (divSpan.hasClass(this.markerClassName)) {
47222			return;
47223		}
47224		divSpan.addClass(this.markerClassName).append(inst.dpDiv);
47225		$.data(target, "datepicker", inst);
47226		this._setDate(inst, this._getDefaultDate(inst), true);
47227		this._updateDatepicker(inst);
47228		this._updateAlternate(inst);
47229		//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
47230		if( inst.settings.disabled ) {
47231			this._disableDatepicker( target );
47232		}
47233		// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
47234		// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
47235		inst.dpDiv.css( "display", "block" );
47236	},
47237
47238	/* Pop-up the date picker in a "dialog" box.
47239	 * @param  input element - ignored
47240	 * @param  date	string or Date - the initial date to display
47241	 * @param  onSelect  function - the function to call when a date is selected
47242	 * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
47243	 * @param  pos int[2] - coordinates for the dialog's position within the screen or
47244	 *					event - with x/y coordinates or
47245	 *					leave empty for default (screen centre)
47246	 * @return the manager object
47247	 */
47248	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
47249		var id, browserWidth, browserHeight, scrollX, scrollY,
47250			inst = this._dialogInst; // internal instance
47251
47252		if (!inst) {
47253			this.uuid += 1;
47254			id = "dp" + this.uuid;
47255			this._dialogInput = $("<input type='text' id='" + id +
47256				"' style='position: absolute; top: -100px; width: 0px;'/>");
47257			this._dialogInput.keydown(this._doKeyDown);
47258			$("body").append(this._dialogInput);
47259			inst = this._dialogInst = this._newInst(this._dialogInput, false);
47260			inst.settings = {};
47261			$.data(this._dialogInput[0], "datepicker", inst);
47262		}
47263		datepicker_extendRemove(inst.settings, settings || {});
47264		date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
47265		this._dialogInput.val(date);
47266
47267		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
47268		if (!this._pos) {
47269			browserWidth = document.documentElement.clientWidth;
47270			browserHeight = document.documentElement.clientHeight;
47271			scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
47272			scrollY = document.documentElement.scrollTop || document.body.scrollTop;
47273			this._pos = // should use actual width/height below
47274				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
47275		}
47276
47277		// move input on screen for focus, but hidden behind dialog
47278		this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
47279		inst.settings.onSelect = onSelect;
47280		this._inDialog = true;
47281		this.dpDiv.addClass(this._dialogClass);
47282		this._showDatepicker(this._dialogInput[0]);
47283		if ($.blockUI) {
47284			$.blockUI(this.dpDiv);
47285		}
47286		$.data(this._dialogInput[0], "datepicker", inst);
47287		return this;
47288	},
47289
47290	/* Detach a datepicker from its control.
47291	 * @param  target	element - the target input field or division or span
47292	 */
47293	_destroyDatepicker: function(target) {
47294		var nodeName,
47295			$target = $(target),
47296			inst = $.data(target, "datepicker");
47297
47298		if (!$target.hasClass(this.markerClassName)) {
47299			return;
47300		}
47301
47302		nodeName = target.nodeName.toLowerCase();
47303		$.removeData(target, "datepicker");
47304		if (nodeName === "input") {
47305			inst.append.remove();
47306			inst.trigger.remove();
47307			$target.removeClass(this.markerClassName).
47308				unbind("focus", this._showDatepicker).
47309				unbind("keydown", this._doKeyDown).
47310				unbind("keypress", this._doKeyPress).
47311				unbind("keyup", this._doKeyUp);
47312		} else if (nodeName === "div" || nodeName === "span") {
47313			$target.removeClass(this.markerClassName).empty();
47314		}
47315	},
47316
47317	/* Enable the date picker to a jQuery selection.
47318	 * @param  target	element - the target input field or division or span
47319	 */
47320	_enableDatepicker: function(target) {
47321		var nodeName, inline,
47322			$target = $(target),
47323			inst = $.data(target, "datepicker");
47324
47325		if (!$target.hasClass(this.markerClassName)) {
47326			return;
47327		}
47328
47329		nodeName = target.nodeName.toLowerCase();
47330		if (nodeName === "input") {
47331			target.disabled = false;
47332			inst.trigger.filter("button").
47333				each(function() { this.disabled = false; }).end().
47334				filter("img").css({opacity: "1.0", cursor: ""});
47335		} else if (nodeName === "div" || nodeName === "span") {
47336			inline = $target.children("." + this._inlineClass);
47337			inline.children().removeClass("ui-state-disabled");
47338			inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
47339				prop("disabled", false);
47340		}
47341		this._disabledInputs = $.map(this._disabledInputs,
47342			function(value) { return (value === target ? null : value); }); // delete entry
47343	},
47344
47345	/* Disable the date picker to a jQuery selection.
47346	 * @param  target	element - the target input field or division or span
47347	 */
47348	_disableDatepicker: function(target) {
47349		var nodeName, inline,
47350			$target = $(target),
47351			inst = $.data(target, "datepicker");
47352
47353		if (!$target.hasClass(this.markerClassName)) {
47354			return;
47355		}
47356
47357		nodeName = target.nodeName.toLowerCase();
47358		if (nodeName === "input") {
47359			target.disabled = true;
47360			inst.trigger.filter("button").
47361				each(function() { this.disabled = true; }).end().
47362				filter("img").css({opacity: "0.5", cursor: "default"});
47363		} else if (nodeName === "div" || nodeName === "span") {
47364			inline = $target.children("." + this._inlineClass);
47365			inline.children().addClass("ui-state-disabled");
47366			inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
47367				prop("disabled", true);
47368		}
47369		this._disabledInputs = $.map(this._disabledInputs,
47370			function(value) { return (value === target ? null : value); }); // delete entry
47371		this._disabledInputs[this._disabledInputs.length] = target;
47372	},
47373
47374	/* Is the first field in a jQuery collection disabled as a datepicker?
47375	 * @param  target	element - the target input field or division or span
47376	 * @return boolean - true if disabled, false if enabled
47377	 */
47378	_isDisabledDatepicker: function(target) {
47379		if (!target) {
47380			return false;
47381		}
47382		for (var i = 0; i < this._disabledInputs.length; i++) {
47383			if (this._disabledInputs[i] === target) {
47384				return true;
47385			}
47386		}
47387		return false;
47388	},
47389
47390	/* Retrieve the instance data for the target control.
47391	 * @param  target  element - the target input field or division or span
47392	 * @return  object - the associated instance data
47393	 * @throws  error if a jQuery problem getting data
47394	 */
47395	_getInst: function(target) {
47396		try {
47397			return $.data(target, "datepicker");
47398		}
47399		catch (err) {
47400			throw "Missing instance data for this datepicker";
47401		}
47402	},
47403
47404	/* Update or retrieve the settings for a date picker attached to an input field or division.
47405	 * @param  target  element - the target input field or division or span
47406	 * @param  name	object - the new settings to update or
47407	 *				string - the name of the setting to change or retrieve,
47408	 *				when retrieving also "all" for all instance settings or
47409	 *				"defaults" for all global defaults
47410	 * @param  value   any - the new value for the setting
47411	 *				(omit if above is an object or to retrieve a value)
47412	 */
47413	_optionDatepicker: function(target, name, value) {
47414		var settings, date, minDate, maxDate,
47415			inst = this._getInst(target);
47416
47417		if (arguments.length === 2 && typeof name === "string") {
47418			return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
47419				(inst ? (name === "all" ? $.extend({}, inst.settings) :
47420				this._get(inst, name)) : null));
47421		}
47422
47423		settings = name || {};
47424		if (typeof name === "string") {
47425			settings = {};
47426			settings[name] = value;
47427		}
47428
47429		if (inst) {
47430			if (this._curInst === inst) {
47431				this._hideDatepicker();
47432			}
47433
47434			date = this._getDateDatepicker(target, true);
47435			minDate = this._getMinMaxDate(inst, "min");
47436			maxDate = this._getMinMaxDate(inst, "max");
47437			datepicker_extendRemove(inst.settings, settings);
47438			// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
47439			if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
47440				inst.settings.minDate = this._formatDate(inst, minDate);
47441			}
47442			if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
47443				inst.settings.maxDate = this._formatDate(inst, maxDate);
47444			}
47445			if ( "disabled" in settings ) {
47446				if ( settings.disabled ) {
47447					this._disableDatepicker(target);
47448				} else {
47449					this._enableDatepicker(target);
47450				}
47451			}
47452			this._attachments($(target), inst);
47453			this._autoSize(inst);
47454			this._setDate(inst, date);
47455			this._updateAlternate(inst);
47456			this._updateDatepicker(inst);
47457		}
47458	},
47459
47460	// change method deprecated
47461	_changeDatepicker: function(target, name, value) {
47462		this._optionDatepicker(target, name, value);
47463	},
47464
47465	/* Redraw the date picker attached to an input field or division.
47466	 * @param  target  element - the target input field or division or span
47467	 */
47468	_refreshDatepicker: function(target) {
47469		var inst = this._getInst(target);
47470		if (inst) {
47471			this._updateDatepicker(inst);
47472		}
47473	},
47474
47475	/* Set the dates for a jQuery selection.
47476	 * @param  target element - the target input field or division or span
47477	 * @param  date	Date - the new date
47478	 */
47479	_setDateDatepicker: function(target, date) {
47480		var inst = this._getInst(target);
47481		if (inst) {
47482			this._setDate(inst, date);
47483			this._updateDatepicker(inst);
47484			this._updateAlternate(inst);
47485		}
47486	},
47487
47488	/* Get the date(s) for the first entry in a jQuery selection.
47489	 * @param  target element - the target input field or division or span
47490	 * @param  noDefault boolean - true if no default date is to be used
47491	 * @return Date - the current date
47492	 */
47493	_getDateDatepicker: function(target, noDefault) {
47494		var inst = this._getInst(target);
47495		if (inst && !inst.inline) {
47496			this._setDateFromField(inst, noDefault);
47497		}
47498		return (inst ? this._getDate(inst) : null);
47499	},
47500
47501	/* Handle keystrokes. */
47502	_doKeyDown: function(event) {
47503		var onSelect, dateStr, sel,
47504			inst = $.datepicker._getInst(event.target),
47505			handled = true,
47506			isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
47507
47508		inst._keyEvent = true;
47509		if ($.datepicker._datepickerShowing) {
47510			switch (event.keyCode) {
47511				case 9: $.datepicker._hideDatepicker();
47512						handled = false;
47513						break; // hide on tab out
47514				case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
47515									$.datepicker._currentClass + ")", inst.dpDiv);
47516						if (sel[0]) {
47517							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
47518						}
47519
47520						onSelect = $.datepicker._get(inst, "onSelect");
47521						if (onSelect) {
47522							dateStr = $.datepicker._formatDate(inst);
47523
47524							// trigger custom callback
47525							onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
47526						} else {
47527							$.datepicker._hideDatepicker();
47528						}
47529
47530						return false; // don't submit the form
47531				case 27: $.datepicker._hideDatepicker();
47532						break; // hide on escape
47533				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
47534							-$.datepicker._get(inst, "stepBigMonths") :
47535							-$.datepicker._get(inst, "stepMonths")), "M");
47536						break; // previous month/year on page up/+ ctrl
47537				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
47538							+$.datepicker._get(inst, "stepBigMonths") :
47539							+$.datepicker._get(inst, "stepMonths")), "M");
47540						break; // next month/year on page down/+ ctrl
47541				case 35: if (event.ctrlKey || event.metaKey) {
47542							$.datepicker._clearDate(event.target);
47543						}
47544						handled = event.ctrlKey || event.metaKey;
47545						break; // clear on ctrl or command +end
47546				case 36: if (event.ctrlKey || event.metaKey) {
47547							$.datepicker._gotoToday(event.target);
47548						}
47549						handled = event.ctrlKey || event.metaKey;
47550						break; // current on ctrl or command +home
47551				case 37: if (event.ctrlKey || event.metaKey) {
47552							$.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
47553						}
47554						handled = event.ctrlKey || event.metaKey;
47555						// -1 day on ctrl or command +left
47556						if (event.originalEvent.altKey) {
47557							$.datepicker._adjustDate(event.target, (event.ctrlKey ?
47558								-$.datepicker._get(inst, "stepBigMonths") :
47559								-$.datepicker._get(inst, "stepMonths")), "M");
47560						}
47561						// next month/year on alt +left on Mac
47562						break;
47563				case 38: if (event.ctrlKey || event.metaKey) {
47564							$.datepicker._adjustDate(event.target, -7, "D");
47565						}
47566						handled = event.ctrlKey || event.metaKey;
47567						break; // -1 week on ctrl or command +up
47568				case 39: if (event.ctrlKey || event.metaKey) {
47569							$.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
47570						}
47571						handled = event.ctrlKey || event.metaKey;
47572						// +1 day on ctrl or command +right
47573						if (event.originalEvent.altKey) {
47574							$.datepicker._adjustDate(event.target, (event.ctrlKey ?
47575								+$.datepicker._get(inst, "stepBigMonths") :
47576								+$.datepicker._get(inst, "stepMonths")), "M");
47577						}
47578						// next month/year on alt +right
47579						break;
47580				case 40: if (event.ctrlKey || event.metaKey) {
47581							$.datepicker._adjustDate(event.target, +7, "D");
47582						}
47583						handled = event.ctrlKey || event.metaKey;
47584						break; // +1 week on ctrl or command +down
47585				default: handled = false;
47586			}
47587		} else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
47588			$.datepicker._showDatepicker(this);
47589		} else {
47590			handled = false;
47591		}
47592
47593		if (handled) {
47594			event.preventDefault();
47595			event.stopPropagation();
47596		}
47597	},
47598
47599	/* Filter entered characters - based on date format. */
47600	_doKeyPress: function(event) {
47601		var chars, chr,
47602			inst = $.datepicker._getInst(event.target);
47603
47604		if ($.datepicker._get(inst, "constrainInput")) {
47605			chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
47606			chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
47607			return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
47608		}
47609	},
47610
47611	/* Synchronise manual entry and field/alternate field. */
47612	_doKeyUp: function(event) {
47613		var date,
47614			inst = $.datepicker._getInst(event.target);
47615
47616		if (inst.input.val() !== inst.lastVal) {
47617			try {
47618				date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
47619					(inst.input ? inst.input.val() : null),
47620					$.datepicker._getFormatConfig(inst));
47621
47622				if (date) { // only if valid
47623					$.datepicker._setDateFromField(inst);
47624					$.datepicker._updateAlternate(inst);
47625					$.datepicker._updateDatepicker(inst);
47626				}
47627			}
47628			catch (err) {
47629			}
47630		}
47631		return true;
47632	},
47633
47634	/* Pop-up the date picker for a given input field.
47635	 * If false returned from beforeShow event handler do not show.
47636	 * @param  input  element - the input field attached to the date picker or
47637	 *					event - if triggered by focus
47638	 */
47639	_showDatepicker: function(input) {
47640		input = input.target || input;
47641		if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
47642			input = $("input", input.parentNode)[0];
47643		}
47644
47645		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
47646			return;
47647		}
47648
47649		var inst, beforeShow, beforeShowSettings, isFixed,
47650			offset, showAnim, duration;
47651
47652		inst = $.datepicker._getInst(input);
47653		if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
47654			$.datepicker._curInst.dpDiv.stop(true, true);
47655			if ( inst && $.datepicker._datepickerShowing ) {
47656				$.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
47657			}
47658		}
47659
47660		beforeShow = $.datepicker._get(inst, "beforeShow");
47661		beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
47662		if(beforeShowSettings === false){
47663			return;
47664		}
47665		datepicker_extendRemove(inst.settings, beforeShowSettings);
47666
47667		inst.lastVal = null;
47668		$.datepicker._lastInput = input;
47669		$.datepicker._setDateFromField(inst);
47670
47671		if ($.datepicker._inDialog) { // hide cursor
47672			input.value = "";
47673		}
47674		if (!$.datepicker._pos) { // position below input
47675			$.datepicker._pos = $.datepicker._findPos(input);
47676			$.datepicker._pos[1] += input.offsetHeight; // add the height
47677		}
47678
47679		isFixed = false;
47680		$(input).parents().each(function() {
47681			isFixed |= $(this).css("position") === "fixed";
47682			return !isFixed;
47683		});
47684
47685		offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
47686		$.datepicker._pos = null;
47687		//to avoid flashes on Firefox
47688		inst.dpDiv.empty();
47689		// determine sizing offscreen
47690		inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
47691		$.datepicker._updateDatepicker(inst);
47692		// fix width for dynamic number of date pickers
47693		// and adjust position before showing
47694		offset = $.datepicker._checkOffset(inst, offset, isFixed);
47695		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
47696			"static" : (isFixed ? "fixed" : "absolute")), display: "none",
47697			left: offset.left + "px", top: offset.top + "px"});
47698
47699		if (!inst.inline) {
47700			showAnim = $.datepicker._get(inst, "showAnim");
47701			duration = $.datepicker._get(inst, "duration");
47702			inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
47703			$.datepicker._datepickerShowing = true;
47704
47705			if ( $.effects && $.effects.effect[ showAnim ] ) {
47706				inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
47707			} else {
47708				inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
47709			}
47710
47711			if ( $.datepicker._shouldFocusInput( inst ) ) {
47712				inst.input.focus();
47713			}
47714
47715			$.datepicker._curInst = inst;
47716		}
47717	},
47718
47719	/* Generate the date picker content. */
47720	_updateDatepicker: function(inst) {
47721		this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
47722		datepicker_instActive = inst; // for delegate hover events
47723		inst.dpDiv.empty().append(this._generateHTML(inst));
47724		this._attachHandlers(inst);
47725
47726		var origyearshtml,
47727			numMonths = this._getNumberOfMonths(inst),
47728			cols = numMonths[1],
47729			width = 17,
47730			activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" );
47731
47732		if ( activeCell.length > 0 ) {
47733			datepicker_handleMouseover.apply( activeCell.get( 0 ) );
47734		}
47735
47736		inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
47737		if (cols > 1) {
47738			inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
47739		}
47740		inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
47741			"Class"]("ui-datepicker-multi");
47742		inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
47743			"Class"]("ui-datepicker-rtl");
47744
47745		if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
47746			inst.input.focus();
47747		}
47748
47749		// deffered render of the years select (to avoid flashes on Firefox)
47750		if( inst.yearshtml ){
47751			origyearshtml = inst.yearshtml;
47752			setTimeout(function(){
47753				//assure that inst.yearshtml didn't change.
47754				if( origyearshtml === inst.yearshtml && inst.yearshtml ){
vendor: 5,457 bytes, lines 47755-47911
47755					inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
47756				}
47757				origyearshtml = inst.yearshtml = null;
47758			}, 0);
47759		}
47760	},
47761
47762	// #6694 - don't focus the input if it's already focused
47763	// this breaks the change event in IE
47764	// Support: IE and jQuery <1.9
47765	_shouldFocusInput: function( inst ) {
47766		return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
47767	},
47768
47769	/* Check positioning to remain on screen. */
47770	_checkOffset: function(inst, offset, isFixed) {
47771		var dpWidth = inst.dpDiv.outerWidth(),
47772			dpHeight = inst.dpDiv.outerHeight(),
47773			inputWidth = inst.input ? inst.input.outerWidth() : 0,
47774			inputHeight = inst.input ? inst.input.outerHeight() : 0,
47775			viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
47776			viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
47777
47778		offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
47779		offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
47780		offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
47781
47782		// now check if datepicker is showing outside window viewport - move to a better place if so.
47783		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
47784			Math.abs(offset.left + dpWidth - viewWidth) : 0);
47785		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
47786			Math.abs(dpHeight + inputHeight) : 0);
47787
47788		return offset;
47789	},
47790
47791	/* Find an object's position on the screen. */
47792	_findPos: function(obj) {
47793		var position,
47794			inst = this._getInst(obj),
47795			isRTL = this._get(inst, "isRTL");
47796
47797		while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
47798			obj = obj[isRTL ? "previousSibling" : "nextSibling"];
47799		}
47800
47801		position = $(obj).offset();
47802		return [position.left, position.top];
47803	},
47804
47805	/* Hide the date picker from view.
47806	 * @param  input  element - the input field attached to the date picker
47807	 */
47808	_hideDatepicker: function(input) {
47809		var showAnim, duration, postProcess, onClose,
47810			inst = this._curInst;
47811
47812		if (!inst || (input && inst !== $.data(input, "datepicker"))) {
47813			return;
47814		}
47815
47816		if (this._datepickerShowing) {
47817			showAnim = this._get(inst, "showAnim");
47818			duration = this._get(inst, "duration");
47819			postProcess = function() {
47820				$.datepicker._tidyDialog(inst);
47821			};
47822
47823			// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
47824			if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
47825				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
47826			} else {
47827				inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
47828					(showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
47829			}
47830
47831			if (!showAnim) {
47832				postProcess();
47833			}
47834			this._datepickerShowing = false;
47835
47836			onClose = this._get(inst, "onClose");
47837			if (onClose) {
47838				onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
47839			}
47840
47841			this._lastInput = null;
47842			if (this._inDialog) {
47843				this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
47844				if ($.blockUI) {
47845					$.unblockUI();
47846					$("body").append(this.dpDiv);
47847				}
47848			}
47849			this._inDialog = false;
47850		}
47851	},
47852
47853	/* Tidy up after a dialog display. */
47854	_tidyDialog: function(inst) {
47855		inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
47856	},
47857
47858	/* Close date picker if clicked elsewhere. */
47859	_checkExternalClick: function(event) {
47860		if (!$.datepicker._curInst) {
47861			return;
47862		}
47863
47864		var $target = $(event.target),
47865			inst = $.datepicker._getInst($target[0]);
47866
47867		if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
47868				$target.parents("#" + $.datepicker._mainDivId).length === 0 &&
47869				!$target.hasClass($.datepicker.markerClassName) &&
47870				!$target.closest("." + $.datepicker._triggerClass).length &&
47871				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
47872			( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
47873				$.datepicker._hideDatepicker();
47874		}
47875	},
47876
47877	/* Adjust one of the date sub-fields. */
47878	_adjustDate: function(id, offset, period) {
47879		var target = $(id),
47880			inst = this._getInst(target[0]);
47881
47882		if (this._isDisabledDatepicker(target[0])) {
47883			return;
47884		}
47885		this._adjustInstDate(inst, offset +
47886			(period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
47887			period);
47888		this._updateDatepicker(inst);
47889	},
47890
47891	/* Action for current link. */
47892	_gotoToday: function(id) {
47893		var date,
47894			target = $(id),
47895			inst = this._getInst(target[0]);
47896
47897		if (this._get(inst, "gotoCurrent") && inst.currentDay) {
47898			inst.selectedDay = inst.currentDay;
47899			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
47900			inst.drawYear = inst.selectedYear = inst.currentYear;
47901		} else {
47902			date = new Date();
47903			inst.selectedDay = date.getDate();
47904			inst.drawMonth = inst.selectedMonth = date.getMonth();
47905			inst.drawYear = inst.selectedYear = date.getFullYear();
47906		}
47907		this._notifyChange(inst);
47908		this._adjustDate(target);
47909	},
47910
47911	/* Action for selecting a new month/year. */
vendor: 45,146 bytes, lines 47912-49069
47912	_selectMonthYear: function(id, select, period) {
47913		var target = $(id),
47914			inst = this._getInst(target[0]);
47915
47916		inst["selected" + (period === "M" ? "Month" : "Year")] =
47917		inst["draw" + (period === "M" ? "Month" : "Year")] =
47918			parseInt(select.options[select.selectedIndex].value,10);
47919
47920		this._notifyChange(inst);
47921		this._adjustDate(target);
47922	},
47923
47924	/* Action for selecting a day. */
47925	_selectDay: function(id, month, year, td) {
47926		var inst,
47927			target = $(id);
47928
47929		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
47930			return;
47931		}
47932
47933		inst = this._getInst(target[0]);
47934		inst.selectedDay = inst.currentDay = $("a", td).html();
47935		inst.selectedMonth = inst.currentMonth = month;
47936		inst.selectedYear = inst.currentYear = year;
47937		this._selectDate(id, this._formatDate(inst,
47938			inst.currentDay, inst.currentMonth, inst.currentYear));
47939	},
47940
47941	/* Erase the input field and hide the date picker. */
47942	_clearDate: function(id) {
47943		var target = $(id);
47944		this._selectDate(target, "");
47945	},
47946
47947	/* Update the input field with the selected date. */
47948	_selectDate: function(id, dateStr) {
47949		var onSelect,
47950			target = $(id),
47951			inst = this._getInst(target[0]);
47952
47953		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
47954		if (inst.input) {
47955			inst.input.val(dateStr);
47956		}
47957		this._updateAlternate(inst);
47958
47959		onSelect = this._get(inst, "onSelect");
47960		if (onSelect) {
47961			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
47962		} else if (inst.input) {
47963			inst.input.trigger("change"); // fire the change event
47964		}
47965
47966		if (inst.inline){
47967			this._updateDatepicker(inst);
47968		} else {
47969			this._hideDatepicker();
47970			this._lastInput = inst.input[0];
47971			if (typeof(inst.input[0]) !== "object") {
47972				inst.input.focus(); // restore focus
47973			}
47974			this._lastInput = null;
47975		}
47976	},
47977
47978	/* Update any alternate field to synchronise with the main field. */
47979	_updateAlternate: function(inst) {
47980		var altFormat, date, dateStr,
47981			altField = this._get(inst, "altField");
47982
47983		if (altField) { // update alternate field too
47984			altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
47985			date = this._getDate(inst);
47986			dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
47987			$(altField).each(function() { $(this).val(dateStr); });
47988		}
47989	},
47990
47991	/* Set as beforeShowDay function to prevent selection of weekends.
47992	 * @param  date  Date - the date to customise
47993	 * @return [boolean, string] - is this date selectable?, what is its CSS class?
47994	 */
47995	noWeekends: function(date) {
47996		var day = date.getDay();
47997		return [(day > 0 && day < 6), ""];
47998	},
47999
48000	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
48001	 * @param  date  Date - the date to get the week for
48002	 * @return  number - the number of the week within the year that contains this date
48003	 */
48004	iso8601Week: function(date) {
48005		var time,
48006			checkDate = new Date(date.getTime());
48007
48008		// Find Thursday of this week starting on Monday
48009		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
48010
48011		time = checkDate.getTime();
48012		checkDate.setMonth(0); // Compare with Jan 1
48013		checkDate.setDate(1);
48014		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
48015	},
48016
48017	/* Parse a string value into a date object.
48018	 * See formatDate below for the possible formats.
48019	 *
48020	 * @param  format string - the expected format of the date
48021	 * @param  value string - the date in the above format
48022	 * @param  settings Object - attributes include:
48023	 *					shortYearCutoff  number - the cutoff year for determining the century (optional)
48024	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
48025	 *					dayNames		string[7] - names of the days from Sunday (optional)
48026	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
48027	 *					monthNames		string[12] - names of the months (optional)
48028	 * @return  Date - the extracted date value or null if value is blank
48029	 */
48030	parseDate: function (format, value, settings) {
48031		if (format == null || value == null) {
48032			throw "Invalid arguments";
48033		}
48034
48035		value = (typeof value === "object" ? value.toString() : value + "");
48036		if (value === "") {
48037			return null;
48038		}
48039
48040		var iFormat, dim, extra,
48041			iValue = 0,
48042			shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
48043			shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
48044				new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
48045			dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
48046			dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
48047			monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
48048			monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
48049			year = -1,
48050			month = -1,
48051			day = -1,
48052			doy = -1,
48053			literal = false,
48054			date,
48055			// Check whether a format character is doubled
48056			lookAhead = function(match) {
48057				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
48058				if (matches) {
48059					iFormat++;
48060				}
48061				return matches;
48062			},
48063			// Extract a number from the string value
48064			getNumber = function(match) {
48065				var isDoubled = lookAhead(match),
48066					size = (match === "@" ? 14 : (match === "!" ? 20 :
48067					(match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
48068					minSize = (match === "y" ? size : 1),
48069					digits = new RegExp("^\\d{" + minSize + "," + size + "}"),
48070					num = value.substring(iValue).match(digits);
48071				if (!num) {
48072					throw "Missing number at position " + iValue;
48073				}
48074				iValue += num[0].length;
48075				return parseInt(num[0], 10);
48076			},
48077			// Extract a name from the string value and convert to an index
48078			getName = function(match, shortNames, longNames) {
48079				var index = -1,
48080					names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
48081						return [ [k, v] ];
48082					}).sort(function (a, b) {
48083						return -(a[1].length - b[1].length);
48084					});
48085
48086				$.each(names, function (i, pair) {
48087					var name = pair[1];
48088					if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
48089						index = pair[0];
48090						iValue += name.length;
48091						return false;
48092					}
48093				});
48094				if (index !== -1) {
48095					return index + 1;
48096				} else {
48097					throw "Unknown name at position " + iValue;
48098				}
48099			},
48100			// Confirm that a literal character matches the string value
48101			checkLiteral = function() {
48102				if (value.charAt(iValue) !== format.charAt(iFormat)) {
48103					throw "Unexpected literal at position " + iValue;
48104				}
48105				iValue++;
48106			};
48107
48108		for (iFormat = 0; iFormat < format.length; iFormat++) {
48109			if (literal) {
48110				if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
48111					literal = false;
48112				} else {
48113					checkLiteral();
48114				}
48115			} else {
48116				switch (format.charAt(iFormat)) {
48117					case "d":
48118						day = getNumber("d");
48119						break;
48120					case "D":
48121						getName("D", dayNamesShort, dayNames);
48122						break;
48123					case "o":
48124						doy = getNumber("o");
48125						break;
48126					case "m":
48127						month = getNumber("m");
48128						break;
48129					case "M":
48130						month = getName("M", monthNamesShort, monthNames);
48131						break;
48132					case "y":
48133						year = getNumber("y");
48134						break;
48135					case "@":
48136						date = new Date(getNumber("@"));
48137						year = date.getFullYear();
48138						month = date.getMonth() + 1;
48139						day = date.getDate();
48140						break;
48141					case "!":
48142						date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
48143						year = date.getFullYear();
48144						month = date.getMonth() + 1;
48145						day = date.getDate();
48146						break;
48147					case "'":
48148						if (lookAhead("'")){
48149							checkLiteral();
48150						} else {
48151							literal = true;
48152						}
48153						break;
48154					default:
48155						checkLiteral();
48156				}
48157			}
48158		}
48159
48160		if (iValue < value.length){
48161			extra = value.substr(iValue);
48162			if (!/^\s+/.test(extra)) {
48163				throw "Extra/unparsed characters found in date: " + extra;
48164			}
48165		}
48166
48167		if (year === -1) {
48168			year = new Date().getFullYear();
48169		} else if (year < 100) {
48170			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
48171				(year <= shortYearCutoff ? 0 : -100);
48172		}
48173
48174		if (doy > -1) {
48175			month = 1;
48176			day = doy;
48177			do {
48178				dim = this._getDaysInMonth(year, month - 1);
48179				if (day <= dim) {
48180					break;
48181				}
48182				month++;
48183				day -= dim;
48184			} while (true);
48185		}
48186
48187		date = this._daylightSavingAdjust(new Date(year, month - 1, day));
48188		if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
48189			throw "Invalid date"; // E.g. 31/02/00
48190		}
48191		return date;
48192	},
48193
48194	/* Standard date formats. */
48195	ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
48196	COOKIE: "D, dd M yy",
48197	ISO_8601: "yy-mm-dd",
48198	RFC_822: "D, d M y",
48199	RFC_850: "DD, dd-M-y",
48200	RFC_1036: "D, d M y",
48201	RFC_1123: "D, d M yy",
48202	RFC_2822: "D, d M yy",
48203	RSS: "D, d M y", // RFC 822
48204	TICKS: "!",
48205	TIMESTAMP: "@",
48206	W3C: "yy-mm-dd", // ISO 8601
48207
48208	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
48209		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
48210
48211	/* Format a date object into a string value.
48212	 * The format can be combinations of the following:
48213	 * d  - day of month (no leading zero)
48214	 * dd - day of month (two digit)
48215	 * o  - day of year (no leading zeros)
48216	 * oo - day of year (three digit)
48217	 * D  - day name short
48218	 * DD - day name long
48219	 * m  - month of year (no leading zero)
48220	 * mm - month of year (two digit)
48221	 * M  - month name short
48222	 * MM - month name long
48223	 * y  - year (two digit)
48224	 * yy - year (four digit)
48225	 * @ - Unix timestamp (ms since 01/01/1970)
48226	 * ! - Windows ticks (100ns since 01/01/0001)
48227	 * "..." - literal text
48228	 * '' - single quote
48229	 *
48230	 * @param  format string - the desired format of the date
48231	 * @param  date Date - the date value to format
48232	 * @param  settings Object - attributes include:
48233	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
48234	 *					dayNames		string[7] - names of the days from Sunday (optional)
48235	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
48236	 *					monthNames		string[12] - names of the months (optional)
48237	 * @return  string - the date in the above format
48238	 */
48239	formatDate: function (format, date, settings) {
48240		if (!date) {
48241			return "";
48242		}
48243
48244		var iFormat,
48245			dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
48246			dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
48247			monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
48248			monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
48249			// Check whether a format character is doubled
48250			lookAhead = function(match) {
48251				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
48252				if (matches) {
48253					iFormat++;
48254				}
48255				return matches;
48256			},
48257			// Format a number, with leading zero if necessary
48258			formatNumber = function(match, value, len) {
48259				var num = "" + value;
48260				if (lookAhead(match)) {
48261					while (num.length < len) {
48262						num = "0" + num;
48263					}
48264				}
48265				return num;
48266			},
48267			// Format a name, short or long as requested
48268			formatName = function(match, value, shortNames, longNames) {
48269				return (lookAhead(match) ? longNames[value] : shortNames[value]);
48270			},
48271			output = "",
48272			literal = false;
48273
48274		if (date) {
48275			for (iFormat = 0; iFormat < format.length; iFormat++) {
48276				if (literal) {
48277					if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
48278						literal = false;
48279					} else {
48280						output += format.charAt(iFormat);
48281					}
48282				} else {
48283					switch (format.charAt(iFormat)) {
48284						case "d":
48285							output += formatNumber("d", date.getDate(), 2);
48286							break;
48287						case "D":
48288							output += formatName("D", date.getDay(), dayNamesShort, dayNames);
48289							break;
48290						case "o":
48291							output += formatNumber("o",
48292								Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
48293							break;
48294						case "m":
48295							output += formatNumber("m", date.getMonth() + 1, 2);
48296							break;
48297						case "M":
48298							output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
48299							break;
48300						case "y":
48301							output += (lookAhead("y") ? date.getFullYear() :
48302								(date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
48303							break;
48304						case "@":
48305							output += date.getTime();
48306							break;
48307						case "!":
48308							output += date.getTime() * 10000 + this._ticksTo1970;
48309							break;
48310						case "'":
48311							if (lookAhead("'")) {
48312								output += "'";
48313							} else {
48314								literal = true;
48315							}
48316							break;
48317						default:
48318							output += format.charAt(iFormat);
48319					}
48320				}
48321			}
48322		}
48323		return output;
48324	},
48325
48326	/* Extract all possible characters from the date format. */
48327	_possibleChars: function (format) {
48328		var iFormat,
48329			chars = "",
48330			literal = false,
48331			// Check whether a format character is doubled
48332			lookAhead = function(match) {
48333				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
48334				if (matches) {
48335					iFormat++;
48336				}
48337				return matches;
48338			};
48339
48340		for (iFormat = 0; iFormat < format.length; iFormat++) {
48341			if (literal) {
48342				if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
48343					literal = false;
48344				} else {
48345					chars += format.charAt(iFormat);
48346				}
48347			} else {
48348				switch (format.charAt(iFormat)) {
48349					case "d": case "m": case "y": case "@":
48350						chars += "0123456789";
48351						break;
48352					case "D": case "M":
48353						return null; // Accept anything
48354					case "'":
48355						if (lookAhead("'")) {
48356							chars += "'";
48357						} else {
48358							literal = true;
48359						}
48360						break;
48361					default:
48362						chars += format.charAt(iFormat);
48363				}
48364			}
48365		}
48366		return chars;
48367	},
48368
48369	/* Get a setting value, defaulting if necessary. */
48370	_get: function(inst, name) {
48371		return inst.settings[name] !== undefined ?
48372			inst.settings[name] : this._defaults[name];
48373	},
48374
48375	/* Parse existing date and initialise date picker. */
48376	_setDateFromField: function(inst, noDefault) {
48377		if (inst.input.val() === inst.lastVal) {
48378			return;
48379		}
48380
48381		var dateFormat = this._get(inst, "dateFormat"),
48382			dates = inst.lastVal = inst.input ? inst.input.val() : null,
48383			defaultDate = this._getDefaultDate(inst),
48384			date = defaultDate,
48385			settings = this._getFormatConfig(inst);
48386
48387		try {
48388			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
48389		} catch (event) {
48390			dates = (noDefault ? "" : dates);
48391		}
48392		inst.selectedDay = date.getDate();
48393		inst.drawMonth = inst.selectedMonth = date.getMonth();
48394		inst.drawYear = inst.selectedYear = date.getFullYear();
48395		inst.currentDay = (dates ? date.getDate() : 0);
48396		inst.currentMonth = (dates ? date.getMonth() : 0);
48397		inst.currentYear = (dates ? date.getFullYear() : 0);
48398		this._adjustInstDate(inst);
48399	},
48400
48401	/* Retrieve the default date shown on opening. */
48402	_getDefaultDate: function(inst) {
48403		return this._restrictMinMax(inst,
48404			this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
48405	},
48406
48407	/* A date may be specified as an exact value or a relative one. */
48408	_determineDate: function(inst, date, defaultDate) {
48409		var offsetNumeric = function(offset) {
48410				var date = new Date();
48411				date.setDate(date.getDate() + offset);
48412				return date;
48413			},
48414			offsetString = function(offset) {
48415				try {
48416					return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
48417						offset, $.datepicker._getFormatConfig(inst));
48418				}
48419				catch (e) {
48420					// Ignore
48421				}
48422
48423				var date = (offset.toLowerCase().match(/^c/) ?
48424					$.datepicker._getDate(inst) : null) || new Date(),
48425					year = date.getFullYear(),
48426					month = date.getMonth(),
48427					day = date.getDate(),
48428					pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
48429					matches = pattern.exec(offset);
48430
48431				while (matches) {
48432					switch (matches[2] || "d") {
48433						case "d" : case "D" :
48434							day += parseInt(matches[1],10); break;
48435						case "w" : case "W" :
48436							day += parseInt(matches[1],10) * 7; break;
48437						case "m" : case "M" :
48438							month += parseInt(matches[1],10);
48439							day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
48440							break;
48441						case "y": case "Y" :
48442							year += parseInt(matches[1],10);
48443							day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
48444							break;
48445					}
48446					matches = pattern.exec(offset);
48447				}
48448				return new Date(year, month, day);
48449			},
48450			newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
48451				(typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
48452
48453		newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
48454		if (newDate) {
48455			newDate.setHours(0);
48456			newDate.setMinutes(0);
48457			newDate.setSeconds(0);
48458			newDate.setMilliseconds(0);
48459		}
48460		return this._daylightSavingAdjust(newDate);
48461	},
48462
48463	/* Handle switch to/from daylight saving.
48464	 * Hours may be non-zero on daylight saving cut-over:
48465	 * > 12 when midnight changeover, but then cannot generate
48466	 * midnight datetime, so jump to 1AM, otherwise reset.
48467	 * @param  date  (Date) the date to check
48468	 * @return  (Date) the corrected date
48469	 */
48470	_daylightSavingAdjust: function(date) {
48471		if (!date) {
48472			return null;
48473		}
48474		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
48475		return date;
48476	},
48477
48478	/* Set the date(s) directly. */
48479	_setDate: function(inst, date, noChange) {
48480		var clear = !date,
48481			origMonth = inst.selectedMonth,
48482			origYear = inst.selectedYear,
48483			newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
48484
48485		inst.selectedDay = inst.currentDay = newDate.getDate();
48486		inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
48487		inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
48488		if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
48489			this._notifyChange(inst);
48490		}
48491		this._adjustInstDate(inst);
48492		if (inst.input) {
48493			inst.input.val(clear ? "" : this._formatDate(inst));
48494		}
48495	},
48496
48497	/* Retrieve the date(s) directly. */
48498	_getDate: function(inst) {
48499		var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
48500			this._daylightSavingAdjust(new Date(
48501			inst.currentYear, inst.currentMonth, inst.currentDay)));
48502			return startDate;
48503	},
48504
48505	/* Attach the onxxx handlers.  These are declared statically so
48506	 * they work with static code transformers like Caja.
48507	 */
48508	_attachHandlers: function(inst) {
48509		var stepMonths = this._get(inst, "stepMonths"),
48510			id = "#" + inst.id.replace( /\\\\/g, "\\" );
48511		inst.dpDiv.find("[data-handler]").map(function () {
48512			var handler = {
48513				prev: function () {
48514					$.datepicker._adjustDate(id, -stepMonths, "M");
48515				},
48516				next: function () {
48517					$.datepicker._adjustDate(id, +stepMonths, "M");
48518				},
48519				hide: function () {
48520					$.datepicker._hideDatepicker();
48521				},
48522				today: function () {
48523					$.datepicker._gotoToday(id);
48524				},
48525				selectDay: function () {
48526					$.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
48527					return false;
48528				},
48529				selectMonth: function () {
48530					$.datepicker._selectMonthYear(id, this, "M");
48531					return false;
48532				},
48533				selectYear: function () {
48534					$.datepicker._selectMonthYear(id, this, "Y");
48535					return false;
48536				}
48537			};
48538			$(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
48539		});
48540	},
48541
48542	/* Generate the HTML for the current state of the date picker. */
48543	_generateHTML: function(inst) {
48544		var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
48545			controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
48546			monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
48547			selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
48548			cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
48549			printDate, dRow, tbody, daySettings, otherMonth, unselectable,
48550			tempDate = new Date(),
48551			today = this._daylightSavingAdjust(
48552				new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
48553			isRTL = this._get(inst, "isRTL"),
48554			showButtonPanel = this._get(inst, "showButtonPanel"),
48555			hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
48556			navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
48557			numMonths = this._getNumberOfMonths(inst),
48558			showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
48559			stepMonths = this._get(inst, "stepMonths"),
48560			isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
48561			currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
48562				new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
48563			minDate = this._getMinMaxDate(inst, "min"),
48564			maxDate = this._getMinMaxDate(inst, "max"),
48565			drawMonth = inst.drawMonth - showCurrentAtPos,
48566			drawYear = inst.drawYear;
48567
48568		if (drawMonth < 0) {
48569			drawMonth += 12;
48570			drawYear--;
48571		}
48572		if (maxDate) {
48573			maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
48574				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
48575			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
48576			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
48577				drawMonth--;
48578				if (drawMonth < 0) {
48579					drawMonth = 11;
48580					drawYear--;
48581				}
48582			}
48583		}
48584		inst.drawMonth = drawMonth;
48585		inst.drawYear = drawYear;
48586
48587		prevText = this._get(inst, "prevText");
48588		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
48589			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
48590			this._getFormatConfig(inst)));
48591
48592		prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
48593			"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
48594			" title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
48595			(hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+ prevText +"'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>"));
48596
48597		nextText = this._get(inst, "nextText");
48598		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
48599			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
48600			this._getFormatConfig(inst)));
48601
48602		next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
48603			"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
48604			" title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
48605			(hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+ nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>"));
48606
48607		currentText = this._get(inst, "currentText");
48608		gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
48609		currentText = (!navigationAsDateFormat ? currentText :
48610			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
48611
48612		controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" +
48613			this._get(inst, "closeText") + "</button>" : "");
48614
48615		buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
48616			(this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" +
48617			">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";
48618
48619		firstDay = parseInt(this._get(inst, "firstDay"),10);
48620		firstDay = (isNaN(firstDay) ? 0 : firstDay);
48621
48622		showWeek = this._get(inst, "showWeek");
48623		dayNames = this._get(inst, "dayNames");
48624		dayNamesMin = this._get(inst, "dayNamesMin");
48625		monthNames = this._get(inst, "monthNames");
48626		monthNamesShort = this._get(inst, "monthNamesShort");
48627		beforeShowDay = this._get(inst, "beforeShowDay");
48628		showOtherMonths = this._get(inst, "showOtherMonths");
48629		selectOtherMonths = this._get(inst, "selectOtherMonths");
48630		defaultDate = this._getDefaultDate(inst);
48631		html = "";
48632		dow;
48633		for (row = 0; row < numMonths[0]; row++) {
48634			group = "";
48635			this.maxRows = 4;
48636			for (col = 0; col < numMonths[1]; col++) {
48637				selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
48638				cornerClass = " ui-corner-all";
48639				calender = "";
48640				if (isMultiMonth) {
48641					calender += "<div class='ui-datepicker-group";
48642					if (numMonths[1] > 1) {
48643						switch (col) {
48644							case 0: calender += " ui-datepicker-group-first";
48645								cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
48646							case numMonths[1]-1: calender += " ui-datepicker-group-last";
48647								cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
48648							default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
48649						}
48650					}
48651					calender += "'>";
48652				}
48653				calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
48654					(/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
48655					(/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
48656					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
48657					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
48658					"</div><table class='ui-datepicker-calendar'><thead>" +
48659					"<tr>";
48660				thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
48661				for (dow = 0; dow < 7; dow++) { // days of the week
48662					day = (dow + firstDay) % 7;
48663					thead += "<th scope='col'" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
48664						"<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
48665				}
48666				calender += thead + "</tr></thead><tbody>";
48667				daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
48668				if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
48669					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
48670				}
48671				leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
48672				curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
48673				numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
48674				this.maxRows = numRows;
48675				printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
48676				for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
48677					calender += "<tr>";
48678					tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
48679						this._get(inst, "calculateWeek")(printDate) + "</td>");
48680					for (dow = 0; dow < 7; dow++) { // create date picker days
48681						daySettings = (beforeShowDay ?
48682							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
48683						otherMonth = (printDate.getMonth() !== drawMonth);
48684						unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
48685							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
48686						tbody += "<td class='" +
48687							((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
48688							(otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
48689							((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
48690							(defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
48691							// or defaultDate is current printedDate and defaultDate is selectedDate
48692							" " + this._dayOverClass : "") + // highlight selected day
48693							(unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") +  // highlight unselectable days
48694							(otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
48695							(printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
48696							(printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
48697							((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "&#39;") + "'" : "") + // cell title
48698							(unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
48699							(otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
48700							(unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
48701							(printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
48702							(printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
48703							(otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
48704							"' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
48705						printDate.setDate(printDate.getDate() + 1);
48706						printDate = this._daylightSavingAdjust(printDate);
48707					}
48708					calender += tbody + "</tr>";
48709				}
48710				drawMonth++;
48711				if (drawMonth > 11) {
48712					drawMonth = 0;
48713					drawYear++;
48714				}
48715				calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
48716							((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
48717				group += calender;
48718			}
48719			html += group;
48720		}
48721		html += buttonPanel;
48722		inst._keyEvent = false;
48723		return html;
48724	},
48725
48726	/* Generate the month and year header. */
48727	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
48728			secondary, monthNames, monthNamesShort) {
48729
48730		var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
48731			changeMonth = this._get(inst, "changeMonth"),
48732			changeYear = this._get(inst, "changeYear"),
48733			showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
48734			html = "<div class='ui-datepicker-title'>",
48735			monthHtml = "";
48736
48737		// month selection
48738		if (secondary || !changeMonth) {
48739			monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
48740		} else {
48741			inMinYear = (minDate && minDate.getFullYear() === drawYear);
48742			inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
48743			monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
48744			for ( month = 0; month < 12; month++) {
48745				if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
48746					monthHtml += "<option value='" + month + "'" +
48747						(month === drawMonth ? " selected='selected'" : "") +
48748						">" + monthNamesShort[month] + "</option>";
48749				}
48750			}
48751			monthHtml += "</select>";
48752		}
48753
48754		if (!showMonthAfterYear) {
48755			html += monthHtml + (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "");
48756		}
48757
48758		// year selection
48759		if ( !inst.yearshtml ) {
48760			inst.yearshtml = "";
48761			if (secondary || !changeYear) {
48762				html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
48763			} else {
48764				// determine range of years to display
48765				years = this._get(inst, "yearRange").split(":");
48766				thisYear = new Date().getFullYear();
48767				determineYear = function(value) {
48768					var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
48769						(value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
48770						parseInt(value, 10)));
48771					return (isNaN(year) ? thisYear : year);
48772				};
48773				year = determineYear(years[0]);
48774				endYear = Math.max(year, determineYear(years[1] || ""));
48775				year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
48776				endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
48777				inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
48778				for (; year <= endYear; year++) {
48779					inst.yearshtml += "<option value='" + year + "'" +
48780						(year === drawYear ? " selected='selected'" : "") +
48781						">" + year + "</option>";
48782				}
48783				inst.yearshtml += "</select>";
48784
48785				html += inst.yearshtml;
48786				inst.yearshtml = null;
48787			}
48788		}
48789
48790		html += this._get(inst, "yearSuffix");
48791		if (showMonthAfterYear) {
48792			html += (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "") + monthHtml;
48793		}
48794		html += "</div>"; // Close datepicker_header
48795		return html;
48796	},
48797
48798	/* Adjust one of the date sub-fields. */
48799	_adjustInstDate: function(inst, offset, period) {
48800		var year = inst.drawYear + (period === "Y" ? offset : 0),
48801			month = inst.drawMonth + (period === "M" ? offset : 0),
48802			day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
48803			date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
48804
48805		inst.selectedDay = date.getDate();
48806		inst.drawMonth = inst.selectedMonth = date.getMonth();
48807		inst.drawYear = inst.selectedYear = date.getFullYear();
48808		if (period === "M" || period === "Y") {
48809			this._notifyChange(inst);
48810		}
48811	},
48812
48813	/* Ensure a date is within any min/max bounds. */
48814	_restrictMinMax: function(inst, date) {
48815		var minDate = this._getMinMaxDate(inst, "min"),
48816			maxDate = this._getMinMaxDate(inst, "max"),
48817			newDate = (minDate && date < minDate ? minDate : date);
48818		return (maxDate && newDate > maxDate ? maxDate : newDate);
48819	},
48820
48821	/* Notify change of month/year. */
48822	_notifyChange: function(inst) {
48823		var onChange = this._get(inst, "onChangeMonthYear");
48824		if (onChange) {
48825			onChange.apply((inst.input ? inst.input[0] : null),
48826				[inst.selectedYear, inst.selectedMonth + 1, inst]);
48827		}
48828	},
48829
48830	/* Determine the number of months to show. */
48831	_getNumberOfMonths: function(inst) {
48832		var numMonths = this._get(inst, "numberOfMonths");
48833		return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
48834	},
48835
48836	/* Determine the current maximum date - ensure no time components are set. */
48837	_getMinMaxDate: function(inst, minMax) {
48838		return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
48839	},
48840
48841	/* Find the number of days in a given month. */
48842	_getDaysInMonth: function(year, month) {
48843		return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
48844	},
48845
48846	/* Find the day of the week of the first of a month. */
48847	_getFirstDayOfMonth: function(year, month) {
48848		return new Date(year, month, 1).getDay();
48849	},
48850
48851	/* Determines if we should allow a "next/prev" month display change. */
48852	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
48853		var numMonths = this._getNumberOfMonths(inst),
48854			date = this._daylightSavingAdjust(new Date(curYear,
48855			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
48856
48857		if (offset < 0) {
48858			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
48859		}
48860		return this._isInRange(inst, date);
48861	},
48862
48863	/* Is the given date in the accepted range? */
48864	_isInRange: function(inst, date) {
48865		var yearSplit, currentYear,
48866			minDate = this._getMinMaxDate(inst, "min"),
48867			maxDate = this._getMinMaxDate(inst, "max"),
48868			minYear = null,
48869			maxYear = null,
48870			years = this._get(inst, "yearRange");
48871			if (years){
48872				yearSplit = years.split(":");
48873				currentYear = new Date().getFullYear();
48874				minYear = parseInt(yearSplit[0], 10);
48875				maxYear = parseInt(yearSplit[1], 10);
48876				if ( yearSplit[0].match(/[+\-].*/) ) {
48877					minYear += currentYear;
48878				}
48879				if ( yearSplit[1].match(/[+\-].*/) ) {
48880					maxYear += currentYear;
48881				}
48882			}
48883
48884		return ((!minDate || date.getTime() >= minDate.getTime()) &&
48885			(!maxDate || date.getTime() <= maxDate.getTime()) &&
48886			(!minYear || date.getFullYear() >= minYear) &&
48887			(!maxYear || date.getFullYear() <= maxYear));
48888	},
48889
48890	/* Provide the configuration settings for formatting/parsing. */
48891	_getFormatConfig: function(inst) {
48892		var shortYearCutoff = this._get(inst, "shortYearCutoff");
48893		shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
48894			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
48895		return {shortYearCutoff: shortYearCutoff,
48896			dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
48897			monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
48898	},
48899
48900	/* Format the given date for display. */
48901	_formatDate: function(inst, day, month, year) {
48902		if (!day) {
48903			inst.currentDay = inst.selectedDay;
48904			inst.currentMonth = inst.selectedMonth;
48905			inst.currentYear = inst.selectedYear;
48906		}
48907		var date = (day ? (typeof day === "object" ? day :
48908			this._daylightSavingAdjust(new Date(year, month, day))) :
48909			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
48910		return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
48911	}
48912});
48913
48914/*
48915 * Bind hover events for datepicker elements.
48916 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
48917 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
48918 */
48919function datepicker_bindHover(dpDiv) {
48920	var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
48921	return dpDiv.delegate(selector, "mouseout", function() {
48922			$(this).removeClass("ui-state-hover");
48923			if (this.className.indexOf("ui-datepicker-prev") !== -1) {
48924				$(this).removeClass("ui-datepicker-prev-hover");
48925			}
48926			if (this.className.indexOf("ui-datepicker-next") !== -1) {
48927				$(this).removeClass("ui-datepicker-next-hover");
48928			}
48929		})
48930		.delegate( selector, "mouseover", datepicker_handleMouseover );
48931}
48932
48933function datepicker_handleMouseover() {
48934	if (!$.datepicker._isDisabledDatepicker( datepicker_instActive.inline? datepicker_instActive.dpDiv.parent()[0] : datepicker_instActive.input[0])) {
48935		$(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
48936		$(this).addClass("ui-state-hover");
48937		if (this.className.indexOf("ui-datepicker-prev") !== -1) {
48938			$(this).addClass("ui-datepicker-prev-hover");
48939		}
48940		if (this.className.indexOf("ui-datepicker-next") !== -1) {
48941			$(this).addClass("ui-datepicker-next-hover");
48942		}
48943	}
48944}
48945
48946/* jQuery extend now ignores nulls! */
48947function datepicker_extendRemove(target, props) {
48948	$.extend(target, props);
48949	for (var name in props) {
48950		if (props[name] == null) {
48951			target[name] = props[name];
48952		}
48953	}
48954	return target;
48955}
48956
48957/* Invoke the datepicker functionality.
48958   @param  options  string - a command, optionally followed by additional parameters or
48959					Object - settings for attaching new datepicker functionality
48960   @return  jQuery object */
48961$.fn.datepicker = function(options){
48962
48963	/* Verify an empty collection wasn't passed - Fixes #6976 */
48964	if ( !this.length ) {
48965		return this;
48966	}
48967
48968	/* Initialise the date picker. */
48969	if (!$.datepicker.initialized) {
48970		$(document).mousedown($.datepicker._checkExternalClick);
48971		$.datepicker.initialized = true;
48972	}
48973
48974	/* Append datepicker main container to body if not exist. */
48975	if ($("#"+$.datepicker._mainDivId).length === 0) {
48976		$("body").append($.datepicker.dpDiv);
48977	}
48978
48979	var otherArgs = Array.prototype.slice.call(arguments, 1);
48980	if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
48981		return $.datepicker["_" + options + "Datepicker"].
48982			apply($.datepicker, [this[0]].concat(otherArgs));
48983	}
48984	if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
48985		return $.datepicker["_" + options + "Datepicker"].
48986			apply($.datepicker, [this[0]].concat(otherArgs));
48987	}
48988	return this.each(function() {
48989		typeof options === "string" ?
48990			$.datepicker["_" + options + "Datepicker"].
48991				apply($.datepicker, [this].concat(otherArgs)) :
48992			$.datepicker._attachDatepicker(this, options);
48993	});
48994};
48995
48996$.datepicker = new Datepicker(); // singleton instance
48997$.datepicker.initialized = false;
48998$.datepicker.uuid = new Date().getTime();
48999$.datepicker.version = "1.11.2";
49000
49001return $.datepicker;
49002
49003}));
49004
49005},
49006'dpage/widgets/TokenizedInput':function(){
49007define([
49008      "dojo/_base/event"
49009      , "dojo/on"
49010      , "dojo/dom-attr"
49011      , "dojo/dom-class"
49012      , "dojo/mouse"
49013      , "dojo/dom-geometry"
49014      , "dojo/dom-style"
49015
49016      , "dpage/widgets/MultiValueWidget"
49017      , "dojox/html/entities"
49018      , "dpage/modules/LegacyPlaceholder"
49019      , "dojo/_base/declare"
49020      , "dijit/_WidgetBase"
49021      , "dpage/widgets/BaseWidget"
49022      , "dijit/_TemplatedMixin"
49023      , "dijit/_Container"],
49024function (event, on, domAttr, domClass, mouse, domGeom, style) {
49025    /**
49026    * @namespace dpage
49027    */
49028    /**
49029    * @namespace widgets
49030    * @memberOf dpage
49031    */
49032    /**
49033    * Implementation of a structured input box. Use for things like address pickers.
49034    * @class TokenizedInput
49035    * @param {Object} [options] Optional options for the widget.
49036    * @param {dpage.modules.TabularModel} [options.model] The model for the widget.
49037    * @param {bool} [options.noDefaultCSS] If true, won't bring in any default styling. Use this only if you will creating your own styles.
49038    * @param {String} [options.css] url path to user defined css for this widget.
49039    * @param {bool} [options.stayFocusedOnTab] If true, focus won't be lost when the tab key is pressed.
49040    * @param {String} [options.separaterPattern] The pattern used to split the input up into items.
49041    * @param {String} [options.validItemPattern] The pattern used to verify if an item is valid or not.
49042    * @param {bool} [options.trimWhitespace] If true, trim any whitespace off of item names.
49043    * @param {bool} [options.allowBlanks] Allow blank values in.
49044    * @param {String} [options.dataDisplayField] The field used to display the item text.
49045    * @param {String} [options.captionDisplayField] The field used to display the caption.
49046    * @param {bool} [options.captionFieldIsHTML] Default false. If true, the caption field will not be html-encoded. You open up yourself to XSS attacks if set to true.
49047    * @param {bool} [options.backspaceDeletesItem] If true, a backspace will delete the last item.
49048    * @param {Function} [options.dataAddCallback] Very powerfull way of controlling whether items get added, what gets added, and if they are valid.
49049    * @param {bool} [options.disabled] Default=false. 
49050    * @param {String} [options.placeholder] Placeholder text to display in input.
49051
49052    * @param {dpage.widgets.Container} [options.container] The container of the widget.
49053    * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
49054    * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
49055    *                               is created.
49056    * @param {Object} [containerNode] Optional container node to tie the widget to.
49057    * @memberOf dpage.widgets
49058    * @extends {dpage.widgets.MultiValueWidget}
49059    */
49060    return dojo.declare("dpage.widgets.TokenizedInput", [dpage.widgets.MultiValueWidget], /** @lends dpage.widgets.TokenizedInput.prototype */ {
49061        _itemLookup: [], //[ {dataIdx : idx , parentDiv: div , captionDiv : div} ] 
49062        _data: null,
49063        _stayFocusedOnTab: false,
49064        _inputNode: null, //
49065        _separaterPattern: new RegExp("\\s+"), //the default pattern. Separate items based on whitespace
49066        _validItemPattern: new RegExp(".*"), //all items are valid.
49067        _trimWhitespace: true,
49068        _allowBlanks: false, //allow whitespace only data?
49069        _dataDisplayField: "value", //if set will add a row to data with this field set when a token is matched. The field in the ds MUST BE HTML ENCODED.
49070        _dataFieldIsHTML: false,
49071        _captionDisplayField: "value", //field in the dataset that holds the caption.  The field in the ds MUST BE HTML ENCODED.
49072        _captionFieldIsHTML: false,
49073        _ulNode: null,
49074        _dataAddCallback: null,
49075        _backspaceDeletesItem: true,
49076        _invalidMessage: 'Invalid Item',
49077        _disabled: false,
49078        _placeholder: null, //placeholder text for the input.
49079        _emulatePlaceholder: false, //support for IE9 placeholder.
49080        _containerNode : null,
49081
49082        constructor: function (options , containerNode) {
49083            var self = this;
49084            var defaultCSSLoaded = false;
49085            var userCSS = null;
49086
49087            this._containerNode = containerNode;
49088
49089            if (containerNode == null)
49090                this._containerNode = document.createElement("DIV");
49091
49092            //load the default CSS, unless user specified not to.
49093            if (options == null || !options.noDefaultCSS)
49094            {
49095                defaultCSSLoaded = true;
49096                require(["xstyle/css!dpage/widgets/TokenizedInput.css"], function () {
49097                    if (userCSS) {
49098                        //load user css after the default css.
49099                        require(["xstyle/css!" + userCSS], function () { });
49100                    }
49101                });
49102            }
49103
49104            if (options != null) {
49105
49106                //amd path to optional css to style the widget.
49107                if (options.css != null)
49108                {
49109                    if(defaultCSSLoaded)
49110                        userCSS = options.css;
49111                    else
49112                        require(["xstyle/css!" + options.css], function () { });
49113                }
49114                if (options.stayFocusedOnTab != null)
49115                    this._stayFocusedOnTab = options.stayFocusedOnTab;
49116
49117                if (options.separaterPattern != null)
49118                    this._separaterPattern = options.separaterPattern;
49119                if (options.validItemPattern != null)
49120                    this._validItemPattern = options.validItemPattern;
49121
49122                if (options.trimWhitespace != null)
49123                    this._trimWhitespace = options.trimWhitespace;
49124
49125                if (options.allowBlanks != null)
49126                    this._allowBlanks = options.allowBlanks;
49127
49128                if (options.dataDisplayField != null)
49129                    this._dataDisplayField = options.dataDisplayField;
49130
49131                if (options.dataFieldIsHTML != null)
49132                    this._dataFieldIsHTML = options.dataFieldIsHTML;
49133
49134                if (options.captionDisplayField != null)
49135                    this._captionDisplayField = options.captionDisplayField;
49136
49137                if (options.captionFieldIsHTML != null)
49138                    this._captionFieldIsHTML = options.captionFieldIsHTML;
49139
49140                if (options.backspaceDeletesItem != null)
49141                    this._backspaceDeletesItem = options.backspaceDeletesItem;
49142
49143                if (options.dataAddCallback != null)
49144                    this._dataAddCallback = options.dataAddCallback;
49145
49146                if (options.invalidMessage != null)
49147                    this._invalidMessage = options.invalidMessage;
49148
49149                if (options.disabled != null)
49150                    this._disabled = options.disabled;
49151
49152                if (options.model != null) {
49153                    if (options.dataDisplayField == null)
49154                        throw new Error("If passing in a model to a TokenizedInput, you must also specify the dataDisplayField property");
49155
49156                    if (options.captionDisplayField == null) {
49157                        this._captionDisplayField = this._dataDisplayField;
49158                        this._captionFieldIsHTML = this._dataFieldIsHTML;
49159                    }
49160
49161                    this._model = options.model;
49162                }
49163                if (options.placeholder != null) {
49164                    this._placeholder = options.placeholder;
49165                }
49166
49167            }
49168
49169            if(options == null || options.model == null)
49170                this._model = new dpage.modules.TabularModel({ defaultColName: this._dataDisplayField });
49171        },
49172        buildRendering : function()
49173        {
49174            this.inherited(arguments);
49175            return this._containerNode;
49176        },
49177        /**
49178        * Turn a model into a {@link dpage.modules.TabularModel} if it isn't already. Some fuzzy logic going on here. If the 
49179        * passed in modelObj doesn't look like a {@link dpage.modules.TabularModel}, the Object is passed to the
49180        * {@link dpage.modules.TabularModel} constructor in the "model" property. Refer to the documentation for {@link dpage.modules.TabularModel} 
49181        * for information regarding the structure of the modelObj param (or just pass in a {@link dpage.modules.TabularModel}).
49182        * @param {Object} modelObj
49183        * @param {bool} excludeDomRender if true don't re-render the widget.
49184        * @returns {void}
49185        */
49186        setModel: function (model, excludeDomRender) {
49187            this.inherited(arguments);
49188            this._data = this.getModel().getRows();
49189
49190            this._updateView();
49191        }
49192        , _buildDomStructure : function()
49193        {
49194            //build up the dom structure.
49195            for (var idx = 0; idx < this._data.length ; idx++) {
49196                var value;
49197
49198                value = this._data[idx][this._dataDisplayField];
49199
49200                var newLookupItem = this._addDomNodeForItem(dojox.html.entities.encode(value) , true);
49201
49202                newLookupItem.dataIdx = idx;
49203
49204                this._itemLookup.push(newLookupItem);
49205            }
49206        }
49207        , templateString: "<div></div>"
49208        , postCreate: function () {
49209            if(this.getModel() != null)
49210                this._data = this.getModel().getRows();
49211
49212            this._updateView();
49213        },
49214        _updateView : function()
49215        {
49216            var inputNode = document.createElement("INPUT");
49217            var inputContainer = document.createElement("LI");
49218            var ulNode = document.createElement("UL");
49219            var containerNode = this._containerNode;
49220            var domNode = this.domNode;
49221            var self = this;
49222            var classes;
49223            //take the style from the parent div.
49224
49225            //re-initialize.
49226            domNode.innerHTML = "";
49227
49228            domClass.add(inputNode, "mt-tok-input");
49229            domClass.add(domNode, "mt-tok-container");
49230
49231            if (!this._disabled) {
49232                domClass.add(ulNode, "mt-tok-items-container");
49233            }
49234            else {
49235                domClass.add(ulNode, "mt-tok-items-container-disabled");
49236                domAttr.set(inputNode, "disabled", true);
49237            }
49238            domClass.add(inputContainer, "mt-tok-item-input-container");
49239
49240            if (containerNode.nodeName != "DIV")
49241                throw new Error("The parent node for a TokenizedInput must be a DIV element");
49242
49243            domAttr.set(domNode, "style", domAttr.get(containerNode, "style"));
49244
49245            classes = containerNode.className;
49246            if (classes != null)
49247                classes = classes.split(/\s+/);
49248            else
49249                classes = [];
49250            for (var i = 0; i < classes.length; i++)
49251                domClass.add(domNode, classes[i]);
49252
49253            domNode.appendChild(ulNode);
49254            ulNode.appendChild(inputContainer);
49255            inputContainer.appendChild(inputNode);
49256
49257            this._ulNode = ulNode;
49258            this._inputNode = inputNode;
49259
49260            if (this._placeholder != null)
49261            {
49262                if(dpage.modules.LegacyPlaceholder.hasNativePlaceholderSupport())
49263                    domAttr.set(this._inputNode, "placeholder", this._placeholder);
49264                else
49265                {
49266                    this._emulatePlaceholder = true;
49267                    domClass.add(this._inputNode, "placeholder");
49268                    this._inputNode.value = this._placeholder;
49269                }
49270            }
49271
49272            on(inputNode, "keypress", function () { self._onInputKeyPress(arguments); });
49273            on(inputNode, "keydown", function () { self._onInputKeyDown(arguments); });
49274            on(inputNode, "keyup", function () { self._onInputKeyUp(arguments); });
49275            on(inputNode, "blur", function () { self._onInputBlur(arguments); });
49276            on(inputNode, "focus", function () { self._onInputFocus(arguments); });
49277            on(this.domNode, "click", function () { self._input_OnClick(arguments); });
49278
49279            if (this._data.length != 0)
49280                this._buildDomStructure();
49281        },
49282        //ie9 support
49283        _onInputFocus: function (e) {
49284            if(this._emulatePlaceholder)
49285            {
49286                if(this._inputNode.value == this._placeholder)
49287                {
49288                    this._inputNode.value = "";
49289                }
49290            }
49291        }
49292        , _onInputBlur: function (e) {
49293            this._doInputChange(this._inputNode.value , true);
49294            
49295            this._autoSizeInput();
49296
49297            //ie9 support.
49298            if (this._emulatePlaceholder) {
49299                if (this._inputNode.value == "") {
49300                    this._inputNode.value = this._placeholder;
49301                }
49302            }
49303
49304        }
49305        , _input_OnClick: function (e) {
49306            this._inputNode.focus();
49307        }
49308        , _onInputKeyPress: function (e) {
49309            //value "before" the keypress
49310            var value = this._inputNode.value;
49311            var currentChar;
49312            var tokens;
49313
49314            e = e[0];
49315
49316            //special case for CR because it doesn't seem to work with String.fromCharCode
49317            if (e.charCode == 13)
49318            {
49319                currentChar = "\n";
49320            }
49321            //the key just pressed.
49322            else
49323                currentChar = String.fromCharCode(e.charCode);
49324
49325            if (this._doInputChange(value + currentChar, false))
49326                event.stop(e);
49327
49328            this._autoSizeInput();
49329        }
49330        , _onInputKeyDown: function (e) {
49331            e = e[0];
49332            //the key that is pressed.
49333            var c = e.keyCode;
49334            var val;
49335            var inputDimensions;
49336            var testerDimensions;
49337            var tokens;
49338            var ourLookupItem;
49339            var self = this;
49340
49341            //the value of the input "before" the keypress.
49342            val = this._inputNode.value;
49343
49344            if (c == 9 && this._stayFocusedOnTab) {
49345                //stop the event. We would otherwise loose focus.
49346                event.stop(e);
49347
49348                //assume that the tab was the last char typed (at the end of the input).
49349                this._doInputChange(this._inputNode.value + '\t' , false);
49350            }
49351
49352            if (c == 8 && this._backspaceDeletesItem && this._itemLookup.length > 0 && this._inputNode.value.length == 0)
49353            {
49354                ourLookupItem = this._itemLookup[0];
49355
49356                for(var idx = 0; idx < this._itemLookup.length ; idx++)
49357                {
49358                    var lookupItem = this._itemLookup[idx];
49359
49360                    if (lookupItem.dataIdx > ourLookupItem.dataIdx)
49361                        ourLookupItem = lookupItem;
49362                }
49363
49364                this._removeItem(ourLookupItem);
49365            }
49366
49367            this._autoSizeInput();
49368        }
49369        //make min width the width of the container - items, otherwise size to content width.
49370        , _autoSizeInput: function () {
49371            var inputStyleProps;
49372            //resize the input based on width of text
49373            var domEl = document.createElement("SPAN");
49374            var strVal;
49375            var contentWidth;
49376            var widthToFill;
49377            var domNodeDimensions;
49378            var testerDimensions;
49379            var inputNodeDimensions;
49380            var newInputWidth;
49381            var lastItemDimensions;
49382            var lastListItem;
49383            var referenceLeft;
49384
49385            inputStyleProps = style.getComputedStyle(this._inputNode);
49386
49387            style.set(domEl, {
49388                top: "-9999px"
49389                                , left: "-9999px"
49390                                , padding: "1em"
49391                                , position: "absolute"
49392                                , whiteSpace: "nowrap"
49393                                , fontSize: inputStyleProps.fontSize
49394                                , fontFamily: inputStyleProps.fontFamily
49395                                , fontWeight: inputStyleProps.fontWeight
49396                                , letterSpacing: inputStyleProps.letterSpacing
49397            });
49398
49399            strVal = this._inputNode.value;
49400
49401            strVal = strVal.replace(new RegExp("\\s", "g"), "&nbsp;");
49402            document.body.appendChild(domEl);
49403            domEl.innerHTML = strVal;
49404
49405            testerDimensions = domGeom.position(domEl);
49406            domNodeDimensions = domGeom.position(this.domNode);
49407            inputNodeDimensions = domGeom.position(this._inputNode);
49408
49409            lastListItem = this._ulNode.lastChild;
49410
49411            if (lastListItem != null) {
49412                lastItemDimensions = domGeom.position(lastListItem);
49413                referenceLeft = lastItemDimensions.x + lastItemDimensions.w;
49414            }
49415            else
49416                referenceLeft = inputNodeDimensions.x;
49417
49418            contentWidth = testerDimensions.w;
49419
49420            widthToFill = domNodeDimensions.w - (referenceLeft - domNodeDimensions.x) - 20;
49421
49422            if (widthToFill > contentWidth)
49423                newInputWidth = widthToFill;
49424            else
49425                newInputWidth = contentWidth;
49426
49427            document.body.removeChild(domEl);
49428            style.set(this._inputNode, { width: (newInputWidth) + "px" });
49429        }
49430        , _onInputKeyUp: function (e) {
49431            var x = e[0].keyCode;
49432        }
49433        , _removeItem: function (lookupItem) {
49434            var containerDiv = lookupItem.parentDiv;
49435            var dataIdx = lookupItem.dataIdx;
49436
49437            containerDiv.parentNode.removeChild(containerDiv);
49438
49439            if (lookupItem.captionDiv != null) {
49440                document.body.removeChild(lookupItem.captionDiv);
49441                lookupItem.captionDiv = null;
49442            }
49443
49444            //remove the data record.
49445            this._data.splice(dataIdx, 1);
49446            //remove the item lookup record.
49447            this._itemLookup.splice(dataIdx, 1);
49448
49449            for (var idx = 0; idx < this._itemLookup.length; idx++) {
49450                var item = this._itemLookup[idx];
49451                //normalize the indexes.
49452                if (item.dataIdx > dataIdx)
49453                    item.dataIdx--;
49454            }
49455        }
49456        , _itemClose_OnClick: function (lookupItem) {
49457            this._removeItem(lookupItem);
49458        }
49459        //raw input value. This gets called by the control.
49460        , _doInputChange: function (value , loosingFocusFlag) {
49461            var self = this;
49462            var newLookupItem;
49463            var item;
49464            var parseOutput;
49465            var items;
49466
49467            parseOutput = this.parseInput(value, loosingFocusFlag);
49468
49469            items = parseOutput.parsedItems;
49470
49471            for (var idx = 0; idx < items.length ; idx++) {
49472                item = items[idx];
49473                var dataRow = item.data;
49474                var valid = item.valid;
49475                var valueToDisplay = dataRow[this._dataDisplayField];
49476                var newLookupItem = this._addDomNodeForItem(dojox.html.entities.encode(valueToDisplay) , valid);
49477
49478                newLookupItem.dataIdx = self._data.length;
49479                newLookupItem.valid = valid;
49480                this._data.push(dataRow);
49481                this._itemLookup.push(newLookupItem);
49482            }
49483
49484            this.validate();
49485
49486            if (parseOutput.newText != null) {
49487                this._inputNode.value = parseOutput.newText;
49488                //input text was changed
49489                return true;
49490            }
49491
49492            if (this._emulatePlaceholder)
49493            {
49494                if(value == "")
49495                {
49496                    this._inputNode.value = this._placeholder;
49497                }
49498            }
49499
49500            //input text was not changed
49501            return false;
49502        },
49503        /**
49504        * Can be called from an external consumer.
49505        * @param {Object} value A row of data to add.
49506        * @returns {void}
49507        */
49508        addDataRow: function (value) {
49509            var valueToDisplay;
49510            var self = this;
49511
49512            valueToDisplay = value[this._dataDisplayField];
49513
49514            if (!this._dataFieldIsHTML)
49515                valueToDisplay = dojox.html.entities.encode(valueToDisplay);
49516
49517            var newLookupItem = this._addDomNodeForItem(valueToDisplay , true);
49518
49519            newLookupItem.dataIdx = self._data.length;
49520            newLookupItem.valid = true;//assume valid if called external.
49521
49522            this._data.push(value);
49523
49524            this._itemLookup.push(newLookupItem);
49525            this._autoSizeInput();
49526            this.validate();
49527        },
49528        //method is called whenever the input value changes. It parses the input into items and returns back the new text
49529        // to display in the input or null for no change.
49530        /*
49531            var returnVal =
49532                {
49533                    newText: "new text to put in input" | null
49534                    ,parsedItems : 
49535                    [
49536                        {
49537                            valid: true | false
49538                            , data : 
49539                                {
49540                                //dataset row here.
49541                                }
49542                        }
49543                    ]
49544                }
49545                */
49546        parseInput: function (rawData, loosingFocusFlag) {
49547            var ret = { newText: null, parsedItems: [] };
49548            var re = this._separaterPattern;
49549            var tokens;
49550            var checkValue;
49551            var newItem;
49552            var separaterPatternMatches;
49553
49554            tokens = rawData.split(re);
49555            separaterPatternMatches = rawData.match(re);
49556
49557            //special case for one item and input loosing focus.
49558            if (!separaterPatternMatches && loosingFocusFlag) {
49559                checkValue = rawData;
49560                if (!this._allowBlanks) {
49561                    checkValue = checkValue.replace(/\s+$/, "");
49562                    checkValue = checkValue.replace(/^\s+/, "");
49563                    if (!checkValue)
49564                        return ret;
49565                }
49566
49567                if (checkValue.match(this._validItemPattern) != null) {
49568
49569                    newItem = this.buildDataRow(checkValue);
49570
49571                    if(newItem != null)
49572                        ret.parsedItems.push(newItem);
49573
49574                    ret.newText = "";
49575                    return ret;
49576                }
49577                //invalid item
49578                else {
49579
49580                    if (this._trimWhitespace) {
49581                        checkValue = checkValue.replace(/\s+$/, "");
49582                        checkValue = checkValue.replace(/^\s+$/, "");
49583                    }
49584
49585                    newItem = this.buildDataRow(checkValue, true);
49586
49587                    if (newItem != null)
49588                        ret.parsedItems.push(newItem);
49589                }
49590            }
49591
49592            if (!separaterPatternMatches)
49593                return ret;
49594
49595            for (var idx = 0; idx < tokens.length; idx++) {
49596                checkValue = tokens[idx];
49597
49598                if (!this._allowBlanks) {
49599                    checkValue = checkValue.replace(/\s+$/, "");
49600                    checkValue = checkValue.replace(/^\s+/, "");
49601                    if (!checkValue)
49602                        continue;
49603                }
49604
49605                //valid item.
49606                if (checkValue.match(this._validItemPattern) != null) {
49607
49608                    if (this._trimWhitespace) {
49609                        checkValue = checkValue.replace(/\s+$/, "");
49610                        checkValue = checkValue.replace(/^\s+$/, "");
49611                    }
49612
49613                    newItem = this.buildDataRow(checkValue);
49614
49615                    if(newItem != null)
49616                        ret.parsedItems.push(newItem);
49617                }
49618                //invalid item
49619                else
49620                {
49621
49622                    if (this._trimWhitespace) {
49623                        checkValue = checkValue.replace(/\s+$/, "");
49624                        checkValue = checkValue.replace(/^\s+$/, "");
49625                    }
49626
49627                    newItem = this.buildDataRow(checkValue , true);
49628
49629                    if (newItem != null)
49630                        ret.parsedItems.push(newItem);
49631                }
49632            }
49633
49634            //so the input will be cleared out.
49635            ret.newText = "";
49636
49637            return ret;
49638        },
49639        //override this method to build a custom dataset row when a value is input. Called when an item is added.
49640        //return back null to stop the item from being added.
49641        buildDataRow: function (rawData , isBad) {
49642            var cookedValue;
49643
49644            //if someone has set a callback, use that instead.
49645            if (this._dataAddCallback != null)
49646                return this._dataAddCallback(rawData , isBad);
49647
49648            var dataObj = {};
49649            dataObj[this._dataDisplayField] = rawData;
49650
49651            dataObj[this._captionDisplayField] = rawData;
49652            cookedValue.data = dataObj;
49653            cookedValue.valid = !isBad;
49654
49655            return cookedValue;
49656        },
49657        //return the correct data for the caption.
49658        _getCaptionContent: function (lookupItem) {
49659            var value;
49660
49661            value = this._data[lookupItem.dataIdx];
49662
49663            value = value[this._captionDisplayField];
49664
49665            if (!this._captionFieldIsHTML)
49666                value = dojox.html.entities.encode(value);
49667
49668            return value;
49669        },
49670        _item_OnMouseEnter: function (newLookupItem) {
49671            var titleDiv = document.createElement("DIV");
49672            var tailDiv = document.createElement("DIV");
49673            var captionDimensions;
49674            var itemObjDimensions;
49675            var tailDimensions;
49676
49677
49678            titleDiv.innerHTML = this._getCaptionContent(newLookupItem);
49679            titleDiv.appendChild(tailDiv);
49680
49681            domClass.add(titleDiv, "mt-tok-caption");
49682            domClass.add(tailDiv, "mt-tok-down-arrow");
49683
49684            document.body.appendChild(titleDiv);
49685
49686            //get the width of the caption
49687            captionDimensions = domGeom.position(titleDiv);
49688            itemObjDimensions = domGeom.position(newLookupItem.parentDiv);
49689            tailDimensions = domGeom.position(tailDiv);
49690
49691            newLookupItem.captionDiv = titleDiv;
49692
49693            style.set(titleDiv, {
49694                left: (itemObjDimensions.x + (itemObjDimensions.w / 2) - (captionDimensions.w / 2)) + "px"
49695                                    , top: (itemObjDimensions.y - 10 - (captionDimensions.h)) + "px"
49696            });
49697        },
49698        _item_OnMouseLeave: function (newLookupItem) {
49699            if (newLookupItem.captionDiv != null) {
49700                document.body.removeChild(newLookupItem.captionDiv);
49701                newLookupItem.captionDiv = null;
49702            }
49703        },
49704        _addDomNodeForItem: function (value, valid) {
49705            var self = this;
49706            var itemContainer = document.createElement("LI");
49707            var itemContentContainer = document.createElement("SPAN");
49708            var itemIconContainer = document.createElement("SPAN");
49709            var closeContainer = document.createElement("A");
49710            var newLookupItem = { dataIdx: null, parentDiv: itemContainer };
49711
49712            on(itemContainer, mouse.enter, function () { self._item_O
49712nMouseEnter(newLookupItem); });
49713            on(itemContainer, mouse.leave, function () { self._item_OnMouseLeave(newLookupItem); });
49714
49715            itemIconContainer.innerHTML = "&nbsp;";
49716            itemContainer.appendChild(itemIconContainer);
49717            itemContainer.appendChild(itemContentContainer);
49718            itemContainer.appendChild(closeContainer);
49719
49720            on(closeContainer, "click", function () { self._itemClose_OnClick(newLookupItem); });
49721
49722            domClass.add(itemContainer, "mt-tok-item-container");
49723            domClass.add(itemIconContainer, "mt-tok-icon-container");
49724            domClass.add(itemContentContainer, "mt-tok-item-content");
49725            domClass.add(closeContainer, "mt-tok-close-container");
49726
49727            if(!valid)
49728                domClass.add(itemContainer, "mt-tok-item-invalid");
49729
49730            //html encoded value
49731            itemContentContainer.innerHTML = value;
49732            this._ulNode.insertBefore(itemContainer, this._inputNode.parentNode);
49733            this._inputNode.value = "";
49734
49735            return newLookupItem;
49736        },
49737        validate: function ()
49738        {
49739            var valid = this.inherited(arguments);
49740            if (valid === null) {
49741                if (this.getContainer()) {
49742                    if (this.getContainer().getValidationMessageWidget()) {
49743                        this.getContainer().getValidationMessageWidget().removeErrorByWidgetID(this.getWidgetId());
49744                    }
49745                }
49746            }
49747            return valid;
49748        },
49749        /**
49750        * Call this to see if the widget contains invalid items.
49751        * @returns {bool}
49752        */
49753        containsInvalidItems: function ()
49754        {
49755            for(var idx=0;idx<this._itemLookup.length;idx++)
49756            {
49757                var lookupItem = this._itemLookup[idx];
49758
49759                if (!lookupItem.valid)
49760                    return true;
49761            }
49762            return false;
49763        }
49764    });
49765});
49766
49767},
49768'dijit/_Container':function(){
49769define([
49770	"dojo/_base/array", // array.forEach array.indexOf
49771	"dojo/_base/declare", // declare
49772	"dojo/dom-construct", // domConstruct.place
49773	"dojo/_base/kernel" // kernel.deprecated
49774], function(array, declare, domConstruct, kernel){
49775
49776	// module:
49777	//		dijit/_Container
49778
49779	return declare("dijit._Container", null, {
49780		// summary:
49781		//		Mixin for widgets that contain HTML and/or a set of widget children.
49782
49783		buildRendering: function(){
49784			this.inherited(arguments);
49785			if(!this.containerNode){
49786				// All widgets with descendants must set containerNode.
49787				// NB: this code doesn't quite work right because for TabContainer it runs before
49788				// _TemplatedMixin::buildRendering(), and thus
49789				// sets this.containerNode to this.domNode, later to be overridden by the assignment in the template.
49790				this.containerNode = this.domNode;
49791			}
49792		},
49793
49794		addChild: function(/*dijit/_WidgetBase*/ widget, /*int?*/ insertIndex){
49795			// summary:
49796			//		Makes the given widget a child of this widget.
49797			// description:
49798			//		Inserts specified child widget's dom node as a child of this widget's
49799			//		container node, and possibly does other processing (such as layout).
49800
49801			// I want to just call domConstruct.place(widget.domNode, this.containerNode, insertIndex), but the counting
49802			// is thrown off by text nodes and comment nodes that show up when constructed by markup.
49803			// In the future consider stripping those nodes on construction, either in the parser or this widget code.
49804			var refNode = this.containerNode;
49805			if(insertIndex > 0){
49806				// Old-school way to get nth child; dojo.query would be easier but _Container was weened from dojo.query
49807				// in #10087 to minimize download size.   Not sure if that's still and issue with new smaller dojo/query.
49808				refNode = refNode.firstChild;
49809				while(insertIndex > 0){
49810					if(refNode.nodeType == 1){ insertIndex--; }
49811					refNode = refNode.nextSibling;
49812				}
49813				if(refNode){
49814					insertIndex = "before";
49815				}else{
49816					// to support addChild(child, n-1) where there are n children (should add child at end)
49817					refNode = this.containerNode;
49818					insertIndex = "last";
49819				}
49820			}
49821
49822			domConstruct.place(widget.domNode, refNode, insertIndex);
49823
49824			// If I've been started but the child widget hasn't been started,
49825			// start it now.  Make sure to do this after widget has been
49826			// inserted into the DOM tree, so it can see that it's being controlled by me,
49827			// so it doesn't try to size itself.
49828			if(this._started && !widget._started){
49829				widget.startup();
49830			}
49831		},
49832
49833		removeChild: function(/*Widget|int*/ widget){
49834			// summary:
49835			//		Removes the passed widget instance from this widget but does
49836			//		not destroy it.  You can also pass in an integer indicating
49837			//		the index within the container to remove (ie, removeChild(5) removes the sixth widget).
49838
49839			if(typeof widget == "number"){
49840				widget = this.getChildren()[widget];
49841			}
49842
49843			if(widget){
49844				var node = widget.domNode;
49845				if(node && node.parentNode){
49846					node.parentNode.removeChild(node); // detach but don't destroy
49847				}
49848			}
49849		},
49850
49851		hasChildren: function(){
49852			// summary:
49853			//		Returns true if widget has child widgets, i.e. if this.containerNode 
49853contains widgets.
49854			return this.getChildren().length > 0;	// Boolean
49855		},
49856
49857		_getSiblingOfChild: function(/*dijit/_WidgetBase*/ child, /*int*/ dir){
49858			// summary:
49859			//		Get the next or previous widget sibling of child
49860			// dir:
49861			//		if 1, get the next sibling
49862			//		if -1, get the previous sibling
49863			// tags:
49864			//		private
49865			kernel.deprecated(this.declaredClass+"::_getSiblingOfChild() is deprecated. Use _KeyNavMixin::_getNext() instead.", "", "2.0");
49866			var children = this.getChildren(),
49867				idx = array.indexOf(children, child);	// int
49868			return children[idx + dir];
49869		},
49870
49871		getIndexOfChild: function(/*dijit/_WidgetBase*/ child){
49872			// summary:
49873			//		Gets the index of the child in this container or -1 if not found
49874			return array.indexOf(this.getChildren(), child);	// int
49875		}
49876	});
49877});
49878
49879},
49880'dpage/widgets/Tree':function(){
49881define([
49882      "jquery",
49883      "dojo/on",
49884
49885      "dpage/modules/Config",
49886      "dojo/_base/declare",
49887      "xstyle/css!dpage/3p/jstree/style.css",
49888      "dpage/widgets/MultiValueWidget"],
49889function ($, on) {
49890    /**
49891    * @namespace dpage
49892    */
49893    /**
49894    * @namespace widgets
49895    * @memberOf dpage
49896    */
49897    /**
49898     * Tree view control. 
49899     * @class Tree
49900     * @param {Object} [options] Optional options for the widget.
49901     * @param {String} options.propId The field in the model that holds the value of the tree node id. This has to be unique in the model.
49902     * @param {String} options.propParent The field in the model that holds the value of the id of the nodes parent node.
49903     * @param {String} options.propText The field in the model that holds the value of the text of the node.
49904     * @param {bool} [options.enableDragAndDrop] Default false. If true, a user can drag and drop nodes to different parent nodes.
49905     * @param {function} [options.itemMoveCallback] void itemMoveCallback(modelRowMoved , modelRowParent) If passed in, this function will be called when an item is moved via drag-and-drop.
49906     * @param {function} [options.itemCheckCallback] bool itemCheckCallback(modelRowToMove , modelRowNewParent) If passed in, the return value of this function determines whether a node can be moved to a particular parent node.
49907     * @param {function} [options.itemSelectCallback] void itemSelectCallback(modelRow) If passed in, this is called whenever a node is selected.
49908
49909     * @param {dpage.modules.TabularModel} [options.model] The model to use.
49910     * @param {dpage.widgets.Container} [options.container] The container of the widget.
49911     * @param {Function} [options.validateCallback] A callback to be used when the validate() method is called.
49912     * @param {String} [options.wid] The widget id you can use to identify this widget. If not passed, a unique one
49913     *                               is created.
49914     * @param {Object} [containerNode] Optional container node to tie the widget to.
49915     * @memberOf dpage.widgets
49916     * @extends {dpage.widgets.MultiValueWidget}
49917     */
49918    return dojo.declare("dpage.widgets.Tree", [dpage.widgets.MultiValueWidget], /** @lends dpage.widgets.Tree.prototype */{
49919        _initialized: false,
49920        _scriptReady: false,
49921        _jsTreeData: null,
49922        _propId: null,
49923        _propParent: null,
49924        _propText: null,
49925        _enableDragAndDrop: false,
49926        _itemMoveCallback: null,
49927        _itemCheckCallback: null,
49928        _itemSelectCallback: null,
49929        _skipEventOnce: false,
49930        _modelRowLookup: null,
49931        _allIds : null,
49932
49933        constructor: function (options, srcNodeRef) {
49934            var self = this;
49935
49936            if (this._containerNode == null)
49937                this._containerNode = document.createElement("DIV");
49938
49939            if (options != null) {
49940                if (options.propId != null)
49941                    this._propId = options.propId;
49942
49943                if (options.propParent != null)
49944                    this._propParent = options.propParent;
49945
49946                if (options.propText != null)
49947                    this._propText = options.propText;
49948
49949                if (options.enableDragAndDrop != undefined)
49950                    this._enableDragAndDrop = options.enableDragAndDrop;
49951
49952                if (options.itemMoveCallback != undefined)
49953                    this._itemMoveCallback = options.itemMoveCallback;
49954
49955                if (options.itemCheckCallback != undefined)
49956                    this._itemCheckCallback = options.itemCheckCallback;
49957
49958                if (options.itemSelectCallback != undefined)
49959                    this._itemSelectCallback = options.itemSelectCallback;
49960
49961            }
49962
49963            if (this._propId == null || this._propParent == null || this._propText == null) {
49964                throw new Error("You must pass in the propId, propParent, and propText config options.");
49965            }
49966
49967            require([dpage.modules.Config.dpageScriptRoot + "dpage/3p/jstree/jstree.js"], function () { self._jsTreeLoaded(); });
49968        },
49969        /*
49970        * Can be overridden to listen to events on the Model.
49971        * @param {String} type CHANGE|ADD|DEL|INS|INVALIDATE
49972        * @param {Object} rowObj The row of data that was altered
49973        * @param {String} dataField The column of data that was changed.
49974        * @returns {void}
49975        */
49976        _modelChanged: function (type, rowObj, dataField) {
49977            var tree;
49978            var treeNode;
49979            var oldParent;
49980            var newParent;
49981            var treeKey;
49982
49983            treeKey = rowObj[this._propId];
49984            parentKey = rowObj[this._propParent];
49985
49986            tree = $(this._containerNode);
49987
49988            if (treeKey == null)
49989                treeKey = "#";
49990            if (parentKey == null)
49991                parentKey = "#";
49992
49993            treeNode = tree.jstree('get_node', treeKey);
49994
49995            if (type == "CHANGE") {
49996                if (dataField == this._propId) {
49997                    throw new Error("You can't change the id property on a row of a TabularModel when bound to a dpage.widgets.Tree for widget id: " + this.getWidgetId());
49998                }
49999                if (dataField == this._propParent) {
50000                    newParent = tree.jstree('get_node', parentKey);
50001                    this._skipEventOnce = true;
50002                    tree.jstree('move_node' , treeNode , newParent);
50003                }
50004                else if (dataField == this._propText) {
50005                    tree.jstree('rename_node',treeNode , rowObj[this._propText]);
50006                }
50007            }
50008            else if (type == "DEL") {
50009                //will not cause a cascading delete, so be aware.
50010                if (treeNode.children.length > 0)
50011                    throw new Error("Row that was deleted from model corresponds to a tree node that contains children. This is an error. Delete the children rows first. Tree id: " + this.getWidgetId());
50012                this._allIds[rowObj[this._propId]] = undefined;
50013                this._modelRowLookup[this.getModel().getDataRowId(rowObj)] = undefined;
50014                tree.jstree('delete_node', treeNode);
50015            }
50016            else if (type == "INS" || type == "ADD") {
50017
50018                //Don't add again. Someone added a row that already exists to the model.
50019                if (this._modelRowLookup[this.getModel().getDataRowId(rowObj)] != null)
50020                    return;
50021
50022                if (this._allIds[rowObj[this._propId]] != null)
50023                    throw new Error("The " + this._propId + " field on a data row must be unique when bound to a dpage.widgets.Tree for widget id: " + this.getWidgetId());
50024
50025                this._allIds[rowObj[this._propId]] = 1;
50026                this._modelRowLookup[this.getModel().getDataRowId(rowObj)] = rowObj;
50027
50028                //will not cause a cascading insert. Parent must exist.
50029                var treeDataRow = {
50030                    id: rowObj[this._propId],
50031                    parent: rowObj[this._propParent] == null ? "#" : rowObj[this._propParent],
50032                    text: rowObj[this._propText]
50033                };
50034
50035                treeDataRow.modelRowId = this.getModel().getDataRowId(rowObj);
50036                newParent = tree.jstree('get_node', parentKey);
50037                tree.jstree('create_node', newParent, treeDataRow);
50038            }
50039            else if (type == "INVALIDATE") {
50040                //at some point we could make this smarter. Right now it redraws the whole tree causing it to collapse and de-select whatever was selected.
50041                this._updateView();
50042            }
50043        },
50044        //overridden method on BaseWidget. Gets called when the model is updated on the MultiValueWidget.
50045        _updateView: function () {
50046            var self = this;
50047
50048            if (!this._scriptReady)
50049                return;
50050
50051            if (this._initialized)
50052                $(this._containerNode).jstree('destroy');
50053
50054            
50055            this._bindModelData();
50056            var config = {};
50057
50058            config.core = { data: this._jsTreeData };
50059
50060            config.core.multiple = false;
50061            if (this._enableDragAndDrop) {
50062                config.core.check_callback = function (operation, node, node_parent, node_position, more) { return self._treeCheckCallback(operation, node, node_parent, node_position, more); };
50063                if (config.plugins == null)
50064                    config.plugins = [];
50065                config.plugins.push("dnd");
50066            }
50067
50068            $(this._containerNode).jstree(config);
50069
50070            $(this._containerNode).bind("select_node.jstree", function (evt, data) { self._itemSelectCallbackInternal(evt, data); });
50071
50072            this._initialized = true;
50073
50074        },
50075        //Not meant to be overridden.
50076        _itemSelectCallbackInternal : function(evt , data){
50077            //call the callback function with the row of data from the item that was selected.
50078            var modelRow = this._modelRowLookup[data.node.original.modelRowId];
50079            
50080            if (this._itemSelectCallback != null)
50081                this._itemSelectCallback(modelRow);
50082            else
50083                this._itemSelected(modelRow);
50084        },
50085        _treeCheckCallback: function (operation, node, node_parent, node_position, more) {
50086            var parentRow = null;
50087            var itemRow = null;
50088            var ret;
50089
50090            if (this._skipEventOnce) {
50091                this._skipEventOnce = false;
50092                return;
50093            }
50094
50095            if (node_parent.parent != null)
50096                parentRow = this._modelRowLookup[node_parent.original.modelRowId];
50097
50098            //seems to be the case when moving a node programatically.
50099            if (operation != "move_node")
50100                return true;
50101
50102            itemRow = this._modelRowLookup[node.original.modelRowId];
50103
50104            if (more.pos == undefined) {
50105                //update the model. This will cause notifications to go out just like they should.
50106                if (parentRow == null)
50107                    this.setModelValue(itemRow, this._propParent, null);
50108                else
50109                    this.setModelValue(itemRow, this._propParent, parentRow[this._propId]);
50110
50111                //Move.
50112                if (this._itemMoveCallback != null)
50113                    return this._itemMoveCallback(itemRow, parentRow);
50114                else
50115                    return this._treeItemMoved(itemRow, parentRow);
50116            }
50117            else {
50118                //Check Move.
50119                if (this._itemCheckCallback != null) {
50120                    ret = this._itemCheckCallback(itemRow, parentRow);
50121                    return ret;
50122                }
50123                else
50124                    return this._isTreeItemMoveValid(itemRow, parentRow);
50125            }
50126        },
50127        //Can be overridden in a sub-class
50128        _itemSelected: function (dataRow) {
50129
50130        },
50131        _treeItemMoved: function (movingRow, newParentRow) {
50132        },
50133        _isTreeItemMoveValid: function (movingRow, newParentRow) {
50134            return true;
50135        },
50136        _bindModelData: function () {
50137            this._jsTreeData = [];
50138            var treeDataRow;
50139
50140            this._modelRowLookup = {};
50141            this._allIds = {};
50142
50143            if (this.getModel() == null)
50144                return;
50145
50146            for (var i = 0; i < this.getModel().getRows().length; i++) {
50147                var row = this.getModel().getRows()[i];
50148
50149                if (this._allIds[row[this._propId]] != null)
50150                    throw new Error("Id's must be unique. Found a duplicate value of '" + row[this._propId] + "' in the propId field of '" + this._propId + "' of widget '" + this.getWidgetId()+"'");
50151
50152                this._allIds[row[this._propId]] = 1;
50153
50154                treeDataRow = {
50155                    id: row[this._propId],
50156                    parent: row[this._propParent] == null ? "#" : row[this._propParent],
50157                    text: row[this._propText]
50158                };
50159
50160                //store the model row so that we can look it up and access it based on a tree item.
50161                this._modelRowLookup[this.getModel().getDataRowId(row)] = row;
50162                //store the unique model id for the row so that we can access it.
50163                treeDataRow.modelRowId = this.getModel().getDataRowId(row);
50164                
50165                this._jsTreeData.push(treeDataRow);
50166            }
50167        },
50168
50169        _jsTreeLoaded: function () {
50170            this._scriptReady = true;
50171
50172            this._updateView();
50173        },
50174
50175        destroy: function () {
50176            if (this._initialized) {
50177                $(this._containerNode).jstree('destroy');
50178                this._jsTreeData = null;
50179                this._modelRowLookup = null;
50180                this._allIds = null;
50181            }
50182        }
50183
50184    });
50185});
50186
50187},
50188'*now':function(r){r(['dojo/i18n!*preload*dpage/nls/dpage*["ar","ca","cs","da","de","el","en-gb","es-es","fi-fi","fr-fr","he-il","hu","it-it","ja-jp","ko-kr","nl-nl","nb","pl","pt-br","pt-pt","ru","sk","sl","sv","th","tr","zh-tw","zh-cn"]']);}
50189}});
50190(function(){
50191	// must use this.require to make this work in node.js
50192	var require = this.require;
50193	// consume the cached dojo layer
50194	require({cache:{}});
50195	!require.async && require(["dojo"]);
50196	require.boot && require.apply(null, require.boot);
50197})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.