1/*
2        Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
3        Available via Academic Free License >= 2.1 OR the modified BSD license.
4        see: http://dojotoolkit.org/license for details
5*/
6
7/*
8        This is an optimized version of Dojo, built for deployment and not for
9        development. To get sources and documentation, please visit:
10
11                http://dojotoolkit.org
12*/
13
14;(function(){
15
16        /*
17        dojo, dijit, and dojox must always be the first three, and in that order.
18        djConfig.scopeMap = [
19                ["dojo", "fojo"],
20                ["dijit", "fijit"],
21                ["dojox", "fojox"]
22
23        ]
24        */
25
26        /**Build will replace this comment with a scoped djConfig **/
27
28        //The null below can be relaced by a build-time value used instead of djConfig.scopeMap.
29        var sMap = null;
30
31        //See if new scopes need to be defined.
32        if((sMap || (typeof djConfig != "undefined" && djConfig.scopeMap)) && (typeof window != "undefined")){
33                var scopeDef = "", scopePrefix = "", scopeSuffix = "", scopeMap = {}, scopeMapRev = {};
34                sMap = sMap || djConfig.scopeMap;
35                for(var i = 0; i < sMap.length; i++){
36                        //Make local variables, then global variables that use the locals.
37                        var newScope = sMap[i];
38                        scopeDef += "var " + newScope[0] + " = {}; " + newScope[1] + " = " + newScope[0] + ";" + newScope[1] + "._scopeName = '" + newScope[1] + "';";
39                        scopePrefix += (i == 0 ? "" : ",") + newScope[0];
40                        scopeSuffix += (i == 0 ? "" : ",") + newScope[1];
41                        scopeMap[newScope[0]] = newScope[1];
42                        scopeMapRev[newScope[1]] = newScope[0];
43                }
44
45                eval(scopeDef + "dojo._scopeArgs = [" + scopeSuffix + "];");
46
47                dojo._scopePrefixArgs = scopePrefix;
48                dojo._scopePrefix = "(function(" + scopePrefix + "){";
49                dojo._scopeSuffix = "})(" + scopeSuffix + ")";
50                dojo._scopeMap = scopeMap;
51                dojo._scopeMapRev = scopeMapRev;
52        }
53
54/*=====
55// note:
56//              'djConfig' does not exist under 'dojo.*' so that it can be set before the
57//              'dojo' variable exists.
58// note:
59//              Setting any of these variables *after* the library has loaded does
60//              nothing at all.
61
62djConfig = {
63        // summary:
64        //              Application code can set the global 'djConfig' prior to loading
65        //              the library to override certain global settings for how dojo works.
66        //
67        // isDebug: Boolean
68        //              Defaults to `false`. If set to `true`, ensures that Dojo provides
69        //              extended debugging feedback via Firebug. If Firebug is not available
70        //              on your platform, setting `isDebug` to `true` will force Dojo to
71        //              pull in (and display) the version of Firebug Lite which is
72        //              integrated into the Dojo distribution, thereby always providing a
73        //              debugging/logging console when `isDebug` is enabled. Note that
74        //              Firebug's `console.*` methods are ALWAYS defined by Dojo. If
75        //              `isDebug` is false and you are on a platform without Firebug, these
76        //              methods will be defined as no-ops.
77        isDebug: false,
78        // debugAtAllCosts: Boolean
79        //              Defaults to `false`. If set to `true`, this triggers an alternate
80        //              mode of the package system in which dependencies are detected and
81        //              only then are resources evaluated in dependency order via
82        //              `<script>` tag inclusion. This may double-request resources and
83        //              cause problems with scripts which expect `dojo.require()` to
84        //              preform synchronously. `debugAtAllCosts` can be an invaluable
85        //              debugging aid, but when using it, ensure that all code which
86        //              depends on Dojo modules is wrapped in `dojo.addOnLoad()` handlers.
87        //              Due to the somewhat unpredictable side-effects of using
88        //              `debugAtAllCosts`, it is strongly recommended that you enable this
89        //              flag as a last resort. `debugAtAllCosts` has no effect when loading
90        //              resources across domains. For usage information, see the
91        //              [Dojo Book](http://dojotoolkit.org/book/book-dojo/part-4-meta-dojo-making-your-dojo-code-run-faster-and-better/debugging-facilities/deb)
92        debugAtAllCosts: false,
93        // locale: String
94        //              The locale to assume for loading localized resources in this page,
95        //              specified according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt).
96        //              Must be specified entirely in lowercase, e.g. `en-us` and `zh-cn`.
97        //              See the documentation for `dojo.i18n` and `dojo.requireLocalization`
98        //              for details on loading localized resources. If no locale is specified,
99        //              Dojo assumes the locale of the user agent, according to `navigator.userLanguage`
100        //              or `navigator.language` properties.
101        locale: undefined,
102        // extraLocale: Array
103        //              No default value. Specifies additional locales whose
104        //              resources should also be loaded alongside the default locale when
105        //              calls to `dojo.requireLocalization()` are processed.
106        extraLocale: undefined,
107        // baseUrl: String
108        //              The directory in which `dojo.js` is located. Under normal
109        //              conditions, Dojo auto-detects the correct location from which it
110        //              was loaded. You may need to manually configure `baseUrl` in cases
111        //              where you have renamed `dojo.js` or in which `<base>` tags confuse
112        //              some browsers (e.g. IE 6). The variable `dojo.baseUrl` is assigned
113        //              either the value of `djConfig.baseUrl` if one is provided or the
114        //              auto-detected root if not. Other modules are located relative to
115        //              this path. The path should end in a slash.
116        baseUrl: undefined,
117        // modulePaths: Object
118        //              A map of module names to paths relative to `dojo.baseUrl`. The
119        //              key/value pairs correspond directly to the arguments which
120        //              `dojo.registerModulePath` accepts. Specifiying
121        //              `djConfig.modulePaths = { "foo": "../../bar" }` is the equivalent
122        //              of calling `dojo.registerModulePath("foo", "../../bar");`. Multiple
123        //              modules may be configured via `djConfig.modulePaths`.
124        modulePaths: {},
125        // afterOnLoad: Boolean
126        //              Indicates Dojo was added to the page after the page load. In this case
127        //              Dojo will not wait for the page DOMContentLoad/load events and fire
128        //              its dojo.addOnLoad callbacks after making sure all outstanding
129        //              dojo.required modules have loaded. Only works with a built dojo.js,
130        //              it does not work the dojo.js directly from source control.
131        afterOnLoad: false,
132        // addOnLoad: Function or Array
133        //              Adds a callback via dojo.addOnLoad. Useful when Dojo is added after
134        //              the page loads and djConfig.afterOnLoad is true. Supports the same
135        //              arguments as dojo.addOnLoad. When using a function reference, use
136        //              `djConfig.addOnLoad = function(){};`. For object with function name use
137        //              `djConfig.addOnLoad = [myObject, "functionName"];` and for object with
138        //              function reference use
139        //              `djConfig.addOnLoad = [myObject, function(){}];`
140        addOnLoad: null,
141        // require: Array
142        //              An array of module names to be loaded immediately after dojo.js has been included
143        //              in a page.
144        require: [],
145        // defaultDuration: Array
146        //              Default duration, in milliseconds, for wipe and fade animations within dijits.
147        //              Assigned to dijit.defaultDuration.
148        defaultDuration: 200,
149        // dojoBlankHtmlUrl: String
150        //              Used by some modules to configure an empty iframe. Used by dojo.io.iframe and
151        //              dojo.back, and dijit popup support in IE where an iframe is needed to make sure native
152        //              controls do not bleed through the popups. Normally this configuration variable
153        //              does not need to be set, except when using cross-domain/CDN Dojo builds.
154        //              Save dojo/resources/blank.html to your domain and set `djConfig.dojoBlankHtmlUrl`
155        //              to the path on your domain your copy of blank.html.
156        dojoBlankHtmlUrl: undefined,
157        //      ioPublish: Boolean?
158        //              Set this to true to enable publishing of topics for the different phases of
159        //              IO operations. Publishing is done via dojo.publish. See dojo.__IoPublish for a list
160        //              of topics that are published.
161        ioPublish: false,
162        //  useCustomLogger: Anything?
163        //              If set to a value that evaluates to true such as a string or array and
164        //              isDebug is true and Firebug is not available or running, then it bypasses
165        //              the creation of Firebug Lite allowing you to define your own console object.
166        useCustomLogger: undefined,
167        // transparentColor: Array
168        //              Array containing the r, g, b components used as transparent color in dojo.Color;
169        //              if undefined, [255,255,255] (white) will be used.
170        transparentColor: undefined,
171        // skipIeDomLoaded: Boolean
172        //              For IE only, skip the DOMContentLoaded hack used. Sometimes it can cause an Operation
173        //              Aborted error if the rest of the page triggers script defers before the DOM is ready.
174        //              If this is config value is set to true, then dojo.addOnLoad callbacks will not be
175        //              triggered until the page load event, which is after images and iframes load. If you
176        //              want to trigger the callbacks sooner, you can put a script block in the bottom of
177        //              your HTML that calls dojo._loadInit();. If you are using multiversion support, change
178        //              "dojo." to the appropriate scope name for dojo.
179        skipIeDomLoaded: false
180}
181=====*/
182
183(function(){
184        // firebug stubs
185
186        if(typeof this["loadFirebugConsole"] == "function"){
187                // for Firebug 1.2
188                this["loadFirebugConsole"]();
189        }else{
190                this.console = this.console || {};
191
192                //      Be careful to leave 'log' always at the end
193                var cn = [
194                        "assert", "count", "debug", "dir", "dirxml", "error", "group",
195                        "groupEnd", "info", "profile", "profileEnd", "time", "timeEnd",
196                        "trace", "warn", "log"
197                ];
198                var i = 0, tn;
199                while((tn=cn[i++])){
200                        if(!console[tn]){
201                                (function(){
202                                        var tcn = tn+"";
203                                        console[tcn] = ('log' in console) ? function(){
204                                                var a = Array.apply({}, arguments);
205                                                a.unshift(tcn+":");
206                                                console["log"](a.join(" "));
207                                        } : function(){}
208                                        console[tcn]._fake = true;
209                                })();
210                        }
211                }
212        }
213
214        //TODOC:  HOW TO DOC THIS?
215        // dojo is the root variable of (almost all) our public symbols -- make sure it is defined.
216        if(typeof dojo == "undefined"){
217                dojo = {
218                        _scopeName: "dojo",
219                        _scopePrefix: "",
220                        _scopePrefixArgs: "",
221                        _scopeSuffix: "",
222                        _scopeMap: {},
223                        _scopeMapRev: {}
224                };
225        }
226
227        var d = dojo;
228
229        //Need placeholders for dijit and dojox for scoping code.
230        if(typeof dijit == "undefined"){
231                dijit = {_scopeName: "dijit"};
232        }
233        if(typeof dojox == "undefined"){
234                dojox = {_scopeName: "dojox"};
235        }
236
237        if(!d._scopeArgs){
238                d._scopeArgs = [dojo, dijit, dojox];
239        }
240
241/*=====
242dojo.global = {
243        //      summary:
244        //              Alias for the global scope
245        //              (e.g. the window object in a browser).
246        //      description:
247        //              Refer to 'dojo.global' rather than referring to window to ensure your
248        //              code runs correctly in contexts other than web browsers (e.g. Rhino on a server).
249}
250=====*/
251        d.global = this;
252
253        d.config =/*===== djConfig = =====*/{
254                isDebug: false,
255                debugAtAllCosts: false
256        };
257
258        // FIXME: 2.0, drop djConfig support. Use dojoConfig exclusively for global config.
259        var cfg = typeof djConfig != "undefined" ? djConfig :
260                typeof dojoConfig != "undefined" ? dojoConfig : null;
261
262        if(cfg){
263                for(var c in cfg){
264                        d.config[c] = cfg[c];
265                }
266        }
267
268/*=====
269        // Override locale setting, if specified
270        dojo.locale = {
271                // summary: the locale as defined by Dojo (read-only)
272        };
273=====*/
274        dojo.locale = d.config.locale;
275
276        var rev = "$Rev: 24595 $".match(/\d+/);
277
278/*=====
279        dojo.version = function(){
280                // summary:
281                //              Version number of the Dojo Toolkit
282                // major: Integer
283                //              Major version. If total version is "1.2.0beta1", will be 1
284                // minor: Integer
285                //              Minor version. If total version is "1.2.0beta1", will be 2
286                // patch: Integer
287                //              Patch version. If total version is "1.2.0beta1", will be 0
288                // flag: String
289                //              Descriptor flag. If total version is "1.2.0beta1", will be "beta1"
290                // revision: Number
291                //              The SVN rev from which dojo was pulled
292                this.major = 0;
293                this.minor = 0;
294                this.patch = 0;
295                this.flag = "";
296                this.revision = 0;
297        }
298=====*/
299        dojo.version = {
300                major: 1, minor: 6, patch: 1, flag: "",
301                revision: rev ? +rev[0] : NaN,
302                toString: function(){
303                        with(d.version){
304                                return major + "." + minor + "." + patch + flag + " (" + revision + ")";        // String
305                        }
306                }
307        }
308
309                // Register with the OpenAjax hub
310        if(typeof OpenAjax != "undefined"){
311                OpenAjax.hub.registerLibrary(dojo._scopeName, "http://dojotoolkit.org", d.version.toString());
312        }
313
314        var extraNames, extraLen, empty = {};
315        for(var i in {toString: 1}){ extraNames = []; break; }
316        dojo._extraNames = extraNames = extraNames || ["hasOwnProperty", "valueOf", "isPrototypeOf",
317                "propertyIsEnumerable", "toLocaleString", "toString", "constructor"];
318        extraLen = extraNames.length;
319
320        dojo._mixin = function(/*Object*/ target, /*Object*/ source){
321                // summary:
322                //              Adds all properties and methods of source to target. This addition
323                //              is "prototype extension safe", so that instances of objects
324                //              will not pass along prototype defaults.
325                var name, s, i;
326                for(name in source){
327                        // the "tobj" condition avoid copying properties in "source"
328                        // inherited from Object.prototype.  For example, if target has a custom
329                        // toString() method, don't overwrite it with the toString() method
330                        // that source inherited from Object.prototype
331                        s = source[name];
332                        if(!(name in target) || (target[name] !== s && (!(name in empty) || empty[name] !== s))){
333                                target[name] = s;
334                        }
335                }
336                                // IE doesn't recognize some custom functions in for..in
337                if(extraLen && source){
338                        for(i = 0; i < extraLen; ++i){
339                                name = extraNames[i];
340                                s = source[name];
341                                if(!(name in target) || (target[name] !== s && (!(name in empty) || empty[name] !== s))){
342                                        target[name] = s;
343                                }
344                        }
345                }
346                                return target; // Object
347        }
348
349        dojo.mixin = function(/*Object*/obj, /*Object...*/props){
350                // summary:
351                //              Adds all properties and methods of props to obj and returns the
352                //              (now modified) obj.
353                //      description:
354                //              `dojo.mixin` can mix multiple source objects into a
355                //              destination object which is then returned. Unlike regular
356                //              `for...in` iteration, `dojo.mixin` is also smart about avoiding
357                //              extensions which other toolkits may unwisely add to the root
358                //              object prototype
359                //      obj:
360                //              The object to mix properties into. Also the return value.
361                //      props:
362                //              One or more objects whose values are successively copied into
363                //              obj. If more than one of these objects contain the same value,
364                //              the one specified last in the function call will "win".
365                //      example:
366                //              make a shallow copy of an object
367                //      |       var copy = dojo.mixin({}, source);
368                //      example:
369                //              many class constructors often take an object which specifies
370                //              values to be configured on the object. In this case, it is
371                //              often simplest to call `dojo.mixin` on the `this` object:
372                //      |       dojo.declare("acme.Base", null, {
373                //      |               constructor: function(properties){
374                //      |                       // property configuration:
375                //      |                       dojo.mixin(this, properties);
376                //      |
377                //      |                       console.log(this.quip);
378                //      |                       //  ...
379                //      |               },
380                //      |               quip: "I wasn't born yesterday, you know - I've seen movies.",
381                //      |               // ...
382                //      |       });
383                //      |
384                //      |       // create an instance of the class and configure it
385                //      |       var b = new acme.Base({quip: "That's what it does!" });
386                //      example:
387                //              copy in properties from multiple objects
388                //      |       var flattened = dojo.mixin(
389                //      |               {
390                //      |                       name: "Frylock",
391                //      |                       braces: true
392                //      |               },
393                //      |               {
394                //      |                       name: "Carl Brutanananadilewski"
395                //      |               }
396                //      |       );
397                //      |
398                //      |       // will print "Carl Brutanananadilewski"
399                //      |       console.log(flattened.name);
400                //      |       // will print "true"
401                //      |       console.log(flattened.braces);
402                if(!obj){ obj = {}; }
403                for(var i=1, l=arguments.length; i<l; i++){
404                        d._mixin(obj, arguments[i]);
405                }
406                return obj; // Object
407        }
408
409        dojo._getProp = function(/*Array*/parts, /*Boolean*/create, /*Object*/context){
410                var obj=context || d.global;
411                for(var i=0, p; obj && (p=parts[i]); i++){
412                        if(i == 0 && d._scopeMap[p]){
413                                p = d._scopeMap[p];
414                        }
415                        obj = (p in obj ? obj[p] : (create ? obj[p]={} : undefined));
416                }
417                return obj; // mixed
418        }
419
420        dojo.setObject = function(/*String*/name, /*Object*/value, /*Object?*/context){
421                // summary:
422                //              Set a property from a dot-separated string, such as "A.B.C"
423                //      description:
424                //              Useful for longer api chains where you have to test each object in
425                //              the chain, or when you have an object reference in string format.
426                //              Objects are created as needed along `path`. Returns the passed
427                //              value if setting is successful or `undefined` if not.
428                //      name:
429                //              Path to a property, in the form "A.B.C".
430                //      context:
431                //              Optional. Object to use as root of path. Defaults to
432                //              `dojo.global`.
433                //      example:
434                //              set the value of `foo.bar.baz`, regardless of whether
435                //              intermediate objects already exist:
436                //      |       dojo.setObject("foo.bar.baz", value);
437                //      example:
438                //              without `dojo.setObject`, we often see code like this:
439                //      |       // ensure that intermediate objects are available
440                //      |       if(!obj["parent"]){ obj.parent = {}; }
441                //      |       if(!obj.parent["child"]){ obj.parent.child= {}; }
442                //      |       // now we can safely set the property
443                //      |       obj.parent.child.prop = "some value";
444                //              wheras with `dojo.setObject`, we can shorten that to:
445                //      |       dojo.setObject("parent.child.prop", "some value", obj);
446                var parts=name.split("."), p=parts.pop(), obj=d._getProp(parts, true, context);
447                return obj && p ? (obj[p]=value) : undefined; // Object
448        }
449
450        dojo.getObject = function(/*String*/name, /*Boolean?*/create, /*Object?*/context){
451                // summary:
452                //              Get a property from a dot-separated string, such as "A.B.C"
453                //      description:
454                //              Useful for longer api chains where you have to test each object in
455                //              the chain, or when you have an object reference in string format.
456                //      name:
457                //              Path to an property, in the form "A.B.C".
458                //      create:
459                //              Optional. Defaults to `false`. If `true`, Objects will be
460                //              created at any point along the 'path' that is undefined.
461                //      context:
462                //              Optional. Object to use as root of path. Defaults to
463                //              'dojo.global'. Null may be passed.
464                return d._getProp(name.split("."), create, context); // Object
465        }
466
467        dojo.exists = function(/*String*/name, /*Object?*/obj){
468                //      summary:
469                //              determine if an object supports a given method
470                //      description:
471                //              useful for longer api chains where you have to test each object in
472                //              the chain. Useful for object and method detection.
473                //      name:
474                //              Path to an object, in the form "A.B.C".
475                //      obj:
476                //              Object to use as root of path. Defaults to
477                //              'dojo.global'. Null may be passed.
478                //      example:
479                //      |       // define an object
480                //      |       var foo = {
481                //      |               bar: { }
482                //      |       };
483                //      |
484                //      |       // search the global scope
485                //      |       dojo.exists("foo.bar"); // true
486                //      |       dojo.exists("foo.bar.baz"); // false
487                //      |
488                //      |       // search from a particular scope
489                //      |       dojo.exists("bar", foo); // true
490                //      |       dojo.exists("bar.baz", foo); // false
491                return d.getObject(name, false, obj) !== undefined; // Boolean
492        }
493
494        dojo["eval"] = function(/*String*/ scriptFragment){
495                //      summary:
496                //              A legacy method created for use exclusively by internal Dojo methods. Do not use
497                //              this method directly, the behavior of this eval will differ from the normal
498                //              browser eval.
499                //      description:
500                //              Placed in a separate function to minimize size of trapped
501                //              exceptions. Calling eval() directly from some other scope may
502                //              complicate tracebacks on some platforms.
503                //      returns:
504                //              The result of the evaluation. Often `undefined`
505                return d.global.eval ? d.global.eval(scriptFragment) : eval(scriptFragment);    // Object
506        }
507
508        /*=====
509                dojo.deprecated = function(behaviour, extra, removal){
510                        //      summary:
511                        //              Log a debug message to indicate that a behavior has been
512                        //              deprecated.
513                        //      behaviour: String
514                        //              The API or behavior being deprecated. Usually in the form
515                        //              of "myApp.someFunction()".
516                        //      extra: String?
517                        //              Text to append to the message. Often provides advice on a
518                        //              new function or facility to achieve the same goal during
519                        //              the deprecation period.
520                        //      removal: String?
521                        //              Text to indicate when in the future the behavior will be
522                        //              removed. Usually a version number.
523                        //      example:
524                        //      |       dojo.deprecated("myApp.getTemp()", "use myApp.getLocaleTemp() instead", "1.0");
525                }
526
527                dojo.experimental = function(moduleName, extra){
528                        //      summary: Marks code as experimental.
529                        //      description:
530                        //              This can be used to mark a function, file, or module as
531                        //              experimental.  Experimental code is not ready to be used, and the
532                        //              APIs are subject to change without notice.  Experimental code may be
533                        //              completed deleted without going through the normal deprecation
534                        //              process.
535                        //      moduleName: String
536                        //              The name of a module, or the name of a module file or a specific
537                        //              function
538                        //      extra: String?
539                        //              some additional message for the user
540                        //      example:
541                        //      |       dojo.experimental("dojo.data.Result");
542                        //      example:
543                        //      |       dojo.experimental("dojo.weather.toKelvin()", "PENDING approval from NOAA");
544                }
545        =====*/
546
547        //Real functions declared in dojo._firebug.firebug.
548        d.deprecated = d.experimental = function(){};
549
550})();
551// vim:ai:ts=4:noet
552
553/*
554 * loader.js - A bootstrap module.  Runs before the hostenv_*.js file. Contains
555 * all of the package loading methods.
556 */
557(function(){
558        var d = dojo, currentModule;
559
560        d.mixin(d, {
561                _loadedModules: {},
562                _inFlightCount: 0,
563                _hasResource: {},
564
565                _modulePrefixes: {
566                        dojo:   {       name: "dojo", value: "." },
567                        // dojox:       {       name: "dojox", value: "../dojox" },
568                        // dijit:       {       name: "dijit", value: "../dijit" },
569                        doh:    {       name: "doh", value: "../util/doh" },
570                        tests:  {       name: "tests", value: "tests" }
571                },
572
573                _moduleHasPrefix: function(/*String*/module){
574                        // summary: checks to see if module has been established
575                        var mp = d._modulePrefixes;
576                        return !!(mp[module] && mp[module].value); // Boolean
577                },
578
579                _getModulePrefix: function(/*String*/module){
580                        // summary: gets the prefix associated with module
581                        var mp = d._modulePrefixes;
582                        if(d._moduleHasPrefix(module)){
583                                return mp[module].value; // String
584                        }
585                        return module; // String
586                },
587
588                _loadedUrls: [],
589
590                //WARNING:
591                //              This variable is referenced by packages outside of bootstrap:
592                //              FloatingPane.js and undo/browser.js
593                _postLoad: false,
594
595                //Egad! Lots of test files push on this directly instead of using dojo.addOnLoad.
596                _loaders: [],
597                _unloaders: [],
598                _loadNotifying: false
599        });
600
601
602                dojo._loadPath = function(/*String*/relpath, /*String?*/module, /*Function?*/cb){
603                //      summary:
604                //              Load a Javascript module given a relative path
605                //
606                //      description:
607                //              Loads and interprets the script located at relpath, which is
608                //              relative to the script root directory.  If the script is found but
609                //              its interpretation causes a runtime exception, that exception is
610                //              not caught by us, so the caller will see it.  We return a true
611                //              value if and only if the script is found.
612                //
613                // relpath:
614                //              A relative path to a script (no leading '/', and typically ending
615                //              in '.js').
616                // module:
617                //              A module whose existance to check for after loading a path.  Can be
618                //              used to determine success or failure of the load.
619                // cb:
620                //              a callback function to pass the result of evaluating the script
621
622                var uri = ((relpath.charAt(0) == '/' || relpath.match(/^\w+:/)) ? "" : d.baseUrl) + relpath;
623                try{
624                        currentModule = module;
625                        return !module ? d._loadUri(uri, cb) : d._loadUriAndCheck(uri, module, cb); // Boolean
626                }catch(e){
627                        console.error(e);
628                        return false; // Boolean
629                }finally{
630                        currentModule = null;
631                }
632        }
633
634        dojo._loadUri = function(/*String*/uri, /*Function?*/cb){
635                //      summary:
636                //              Loads JavaScript from a URI
637                //      description:
638                //              Reads the contents of the URI, and evaluates the contents.  This is
639                //              used to load modules as well as resource bundles. Returns true if
640                //              it succeeded. Returns false if the URI reading failed.  Throws if
641                //              the evaluation throws.
642                //      uri: a uri which points at the script to be loaded
643                //      cb:
644                //              a callback function to process the result of evaluating the script
645                //              as an expression, typically used by the resource bundle loader to
646                //              load JSON-style resources
647
648                if(d._loadedUrls[uri]){
649                        return true; // Boolean
650                }
651                d._inFlightCount++; // block addOnLoad calls that arrive while we're busy downloading
652                var contents = d._getText(uri, true);
653                if(contents){ // not 404, et al
654                        d._loadedUrls[uri] = true;
655                        d._loadedUrls.push(uri);
656                        if(cb){
657                                //conditional to support script-inject i18n bundle format
658                                contents = /^define\(/.test(contents) ? contents : '('+contents+')';
659                        }else{
660                                //Only do the scoping if no callback. If a callback is specified,
661                                //it is most likely the i18n bundle stuff.
662                                contents = d._scopePrefix + contents + d._scopeSuffix;
663                        }
664                        if(!d.isIE){ contents += "\r\n//@ sourceURL=" + uri; } // debugging assist for Firebug
665                        var value = d["eval"](contents);
666                        if(cb){ cb(value); }
667                }
668                // Check to see if we need to call _callLoaded() due to an addOnLoad() that arrived while we were busy downloading
669                if(--d._inFlightCount == 0 && d._postLoad && d._loaders.length){
670                        // We shouldn't be allowed to get here but Firefox allows an event
671                        // (mouse, keybd, async xhrGet) to interrupt a synchronous xhrGet.
672                        // If the current script block contains multiple require() statements, then after each
673                        // require() returns, inFlightCount == 0, but we want to hold the _callLoaded() until
674                        // all require()s are done since the out-of-sequence addOnLoad() presumably needs them all.
675                        // setTimeout allows the next require() to start (if needed), and then we check this again.
676                        setTimeout(function(){
677                                // If inFlightCount > 0, then multiple require()s are running sequentially and
678                                // the next require() started after setTimeout() was executed but before we got here.
679                                if(d._inFlightCount == 0){
680                                        d._callLoaded();
681                                }
682                        }, 0);
683                }
684                return !!contents; // Boolean: contents? true : false
685        }
686
687        // FIXME: probably need to add logging to this method
688        dojo._loadUriAndCheck = function(/*String*/uri, /*String*/moduleName, /*Function?*/cb){
689                // summary: calls loadUri then findModule and returns true if both succeed
690                var ok = false;
691                try{
692                        ok = d._loadUri(uri, cb);
693                }catch(e){
694                        console.error("failed loading " + uri + " with error: " + e);
695                }
696                return !!(ok && d._loadedModules[moduleName]); // Boolean
697        }
698
699        dojo.loaded = function(){
700                // summary:
701                //              signal fired when initial environment and package loading is
702                //              complete. You should use dojo.addOnLoad() instead of doing a
703                //              direct dojo.connect() to this method in order to handle
704                //              initialization tasks that require the environment to be
705                //              initialized. In a browser host, declarative widgets will
706                //              be constructed when this function finishes runing.
707                d._loadNotifying = true;
708                d._postLoad = true;
709                var mll = d._loaders;
710
711                //Clear listeners so new ones can be added
712                //For other xdomain package loads after the initial load.
713                d._loaders = [];
714
715                for(var x = 0; x < mll.length; x++){
716                        mll[x]();
717                }
718
719                d._loadNotifying = false;
720
721                //Make sure nothing else got added to the onload queue
722                //after this first run. If something did, and we are not waiting for any
723                //more inflight resources, run again.
724                if(d._postLoad && d._inFlightCount == 0 && mll.length){
725                        d._callLoaded();
726                }
727        }
728
729        dojo.unloaded = function(){
730                // summary:
731                //              signal fired by impending environment destruction. You should use
732                //              dojo.addOnUnload() instead of doing a direct dojo.connect() to this
733                //              method to perform page/application cleanup methods. See
734                //              dojo.addOnUnload for more info.
735                var mll = d._unloaders;
736                while(mll.length){
737                        (mll.pop())();
738                }
739        }
740
741        d._onto = function(arr, obj, fn){
742                if(!fn){
743                        arr.push(obj);
744                }else if(fn){
745                        var func = (typeof fn == "string") ? obj[fn] : fn;
746                        arr.push(function(){ func.call(obj); });
747                }
748        }
749
750        dojo.ready = dojo.addOnLoad = function(/*Object*/obj, /*String|Function?*/functionName){
751                // summary:
752                //              Registers a function to be triggered after the DOM and dojo.require() calls
753                //              have finished loading.
754                //
755                // description:
756                //              Registers a function to be triggered after the DOM has finished
757                //              loading and `dojo.require` modules have loaded. Widgets declared in markup
758                //              have been instantiated if `djConfig.parseOnLoad` is true when this fires.
759                //
760                //              Images and CSS files may or may not have finished downloading when
761                //              the specified function is called.  (Note that widgets' CSS and HTML
762                //              code is guaranteed to be downloaded before said widgets are
763                //              instantiated, though including css resouces BEFORE any script elements
764                //              is highly recommended).
765                //
766                // example:
767                //      Register an anonymous function to run when everything is ready
768                //      |       dojo.addOnLoad(function(){ doStuff(); });
769                //
770                // example:
771                //      Register a function to run when everything is ready by pointer:
772                //      |       var init = function(){ doStuff(); }
773                //      |       dojo.addOnLoad(init);
774                //
775                // example:
776                //      Register a function to run scoped to `object`, either by name or anonymously:
777                //      |       dojo.addOnLoad(object, "functionName");
778                //      |       dojo.addOnLoad(object, function(){ doStuff(); });
779
780                d._onto(d._loaders, obj, functionName);
781
782                //Added for xdomain loading. dojo.addOnLoad is used to
783                //indicate callbacks after doing some dojo.require() statements.
784                //In the xdomain case, if all the requires are loaded (after initial
785                //page load), then immediately call any listeners.
786                if(d._postLoad && d._inFlightCount == 0 && !d._loadNotifying){
787                        d._callLoaded();
788                }
789        }
790
791        //Support calling dojo.addOnLoad via djConfig.addOnLoad. Support all the
792        //call permutations of dojo.addOnLoad. Mainly useful when dojo is added
793        //to the page after the page has loaded.
794        var dca = d.config.addOnLoad;
795        if(dca){
796                d.addOnLoad[(dca instanceof Array ? "apply" : "call")](d, dca);
797        }
798
799        dojo._modulesLoaded = function(){
800                if(d._postLoad){ return; }
801                if(d._inFlightCount > 0){
802                        console.warn("files still in flight!");
803                        return;
804                }
805                d._callLoaded();
806        }
807
808        dojo._callLoaded = function(){
809
810                // The "object" check is for IE, and the other opera check fixes an
811                // issue in Opera where it could not find the body element in some
812                // widget test cases.  For 0.9, maybe route all browsers through the
813                // setTimeout (need protection still for non-browser environments
814                // though). This might also help the issue with FF 2.0 and freezing
815                // issues where we try to do sync xhr while background css images are
816                // being loaded (trac #2572)? Consider for 0.9.
817                if(typeof setTimeout == "object" || (d.config.useXDomain && d.isOpera)){
818                        setTimeout(
819                                d.isAIR ? function(){ d.loaded(); } : d._scopeName + ".loaded();",
820                                0);
821                }else{
822                        d.loaded();
823                }
824        }
825
826        dojo._getModuleSymbols = function(/*String*/modulename){
827                // summary:
828                //              Converts a module name in dotted JS notation to an array
829                //              representing the path in the source tree
830                var syms = modulename.split(".");
831                for(var i = syms.length; i>0; i--){
832                        var parentModule = syms.slice(0, i).join(".");
833                        if(i == 1 && !d._moduleHasPrefix(parentModule)){
834                                // Support default module directory (sibling of dojo) for top-level modules
835                                syms[0] = "../" + syms[0];
836                        }else{
837                                var parentModulePath = d._getModulePrefix(parentModule);
838                                if(parentModulePath != parentModule){
839                                        syms.splice(0, i, parentModulePath);
840                                        break;
841                                }
842                        }
843                }
844                return syms; // Array
845        }
846
847        dojo._global_omit_module_check = false;
848
849        dojo.loadInit = function(/*Function*/init){
850                //      summary:
851                //              Executes a function that needs to be executed for the loader's dojo.requireIf
852                //              resolutions to work. This is needed mostly for the xdomain loader case where
853                //              a function needs to be executed to set up the possible values for a dojo.requireIf
854                //              call.
855                //      init:
856                //              a function reference. Executed immediately.
857                //      description: This function is mainly a marker for the xdomain loader to know parts of
858                //              code that needs be executed outside the function wrappper that is placed around modules.
859                //              The init function could be executed more than once, and it should make no assumptions
860                //              on what is loaded, or what modules are available. Only the functionality in Dojo Base
861                //              is allowed to be used. Avoid using this method. For a valid use case,
862                //              see the source for dojox.gfx.
863                init();
864        }
865
866        dojo._loadModule = dojo.require = function(/*String*/moduleName, /*Boolean?*/omitModuleCheck){
867                //      summary:
868                //              loads a Javascript module from the appropriate URI
869                //
870                //      moduleName: String
871                //              module name to load, using periods for separators,
872                //               e.g. "dojo.date.locale".  Module paths are de-referenced by dojo's
873                //              internal mapping of locations to names and are disambiguated by
874                //              longest prefix. See `dojo.registerModulePath()` for details on
875                //              registering new modules.
876                //
877                //      omitModuleCheck: Boolean?
878                //              if `true`, omitModuleCheck skips the step of ensuring that the
879                //              loaded file actually defines the symbol it is referenced by.
880                //              For example if it called as `dojo.require("a.b.c")` and the
881                //              file located at `a/b/c.js` does not define an object `a.b.c`,
882                //              and exception will be throws whereas no exception is raised
883                //              when called as `dojo.require("a.b.c", true)`
884                //
885                //      description:
886                //              Modules are loaded via dojo.require by using one of two loaders: the normal loader
887                //              and the xdomain loader. The xdomain loader is used when dojo was built with a
888                //              custom build that specified loader=xdomain and the module lives on a modulePath
889                //              that is a whole URL, with protocol and a domain. The versions of Dojo that are on
890                //              the Google and AOL CDNs use the xdomain loader.
891                //
892                //              If the module is loaded via the xdomain loader, it is an asynchronous load, since
893                //              the module is added via a dynamically created script tag. This
894                //              means that dojo.require() can return before the module has loaded. However, this
895                //              should only happen in the case where you do dojo.require calls in the top-level
896                //              HTML page, or if you purposely avoid the loader checking for dojo.require
897                //              dependencies in your module by using a syntax like dojo["require"] to load the module.
898                //
899                //              Sometimes it is useful to not have the loader detect the dojo.require calls in the
900                //              module so that you can dynamically load the modules as a result of an action on the
901                //              page, instead of right at module load time.
902                //
903                //              Also, for script blocks in an HTML page, the loader does not pre-process them, so
904                //              it does not know to download the modules before the dojo.require calls occur.
905                //
906                //              So, in those two cases, when you want on-the-fly module loading or for script blocks
907                //              in the HTML page, special care must be taken if the dojo.required code is loaded
908                //              asynchronously. To make sure you can execute code that depends on the dojo.required
909                //              modules, be sure to add the code that depends on the modules in a dojo.addOnLoad()
910                //              callback. dojo.addOnLoad waits for all outstanding modules to finish loading before
911                //              executing.
912                //
913                //              This type of syntax works with both xdomain and normal loaders, so it is good
914                //              practice to always use this idiom for on-the-fly code loading and in HTML script
915                //              blocks. If at some point you change loaders and where the code is loaded from,
916                //              it will all still work.
917                //
918                //              More on how dojo.require
919                //              `dojo.require("A.B")` first checks to see if symbol A.B is
920                //              defined. If it is, it is simply returned (nothing to do).
921                //
922                //              If it is not defined, it will look for `A/B.js` in the script root
923                //              directory.
924                //
925                //              `dojo.require` throws an exception if it cannot find a file
926                //              to load, or if the symbol `A.B` is not defined after loading.
927                //
928                //              It returns the object `A.B`, but note the caveats above about on-the-fly loading and
929                //              HTML script blocks when the xdomain loader is loading a module.
930                //
931                //              `dojo.require()` does nothing about importing symbols into
932                //              the current namespace.  It is presumed that the caller will
933                //              take care of that.
934                //
935                //      example:
936                //              To use dojo.require in conjunction with dojo.ready:
937                //
938                //              |       dojo.require("foo");
939                //              |       dojo.require("bar");
940                //              |       dojo.addOnLoad(function(){
941                //              |               //you can now safely do something with foo and bar
942                //              |       });
943                //
944                //      example:
945                //              For example, to import all symbols into a local block, you might write:
946                //
947                //              |       with (dojo.require("A.B")) {
948                //              |               ...
949                //              |       }
950                //
951                //              And to import just the leaf symbol to a local variable:
952                //
953                //              |       var B = dojo.require("A.B");
954                //              |       ...
955                //
956                //      returns:
957                //              the required namespace object
958                omitModuleCheck = d._global_omit_module_check || omitModuleCheck;
959
960                //Check if it is already loaded.
961                var module = d._loadedModules[moduleName];
962                if(module){
963                        return module;
964                }
965
966                // convert periods to slashes
967                var relpath = d._getModuleSymbols(moduleName).join("/") + '.js';
968                var modArg = !omitModuleCheck ? moduleName : null;
969                var ok = d._loadPath(relpath, modArg);
970                if(!ok && !omitModuleCheck){
971                        throw new Error("Could not load '" + moduleName + "'; last tried '" + relpath + "'");
972                }
973
974                // check that the symbol was defined
975                // Don't bother if we're doing xdomain (asynchronous) loading.
976                if(!omitModuleCheck && !d._isXDomain){
977                        // pass in false so we can give better error
978                        module = d._loadedModules[moduleName];
979                        if(!module){
980                                throw new Error("symbol '" + moduleName + "' is not defined after loading '" + relpath + "'");
981                        }
982                }
983
984                return module;
985        }
986
987        dojo.provide = function(/*String*/ resourceName){
988                //      summary:
989                //              Register a resource with the package system. Works in conjunction with `dojo.require`
990                //
991                //      description:
992                //              Each javascript source file is called a resource.  When a
993                //              resource is loaded by the browser, `dojo.provide()` registers
994                //              that it has been loaded.
995                //
996                //              Each javascript source file must have at least one
997                //              `dojo.provide()` call at the top of the file, corresponding to
998                //              the file name.  For example, `js/dojo/foo.js` must have
999                //              `dojo.provide("dojo.foo");` before any calls to
1000                //              `dojo.require()` are made.
1001                //
1002                //              For backwards compatibility reasons, in addition to registering
1003                //              the resource, `dojo.provide()` also ensures that the javascript
1004                //              object for the module exists.  For example,
1005                //              `dojo.provide("dojox.data.FlickrStore")`, in addition to
1006                //              registering that `FlickrStore.js` is a resource for the
1007                //              `dojox.data` module, will ensure that the `dojox.data`
1008                //              javascript object exists, so that calls like
1009                //              `dojo.data.foo = function(){ ... }` don't fail.
1010                //
1011                //              In the case of a build where multiple javascript source files
1012                //              are combined into one bigger file (similar to a .lib or .jar
1013                //              file), that file may contain multiple dojo.provide() calls, to
1014                //              note that it includes multiple resources.
1015                //
1016                // resourceName: String
1017                //              A dot-sperated string identifying a resource.
1018                //
1019                // example:
1020                //      Safely create a `my` object, and make dojo.require("my.CustomModule") work
1021                //      |       dojo.provide("my.CustomModule");
1022
1023                //Make sure we have a string.
1024                resourceName = resourceName + "";
1025                return (d._loadedModules[resourceName] = d.getObject(resourceName, true)); // Object
1026        }
1027
1028        //Start of old bootstrap2:
1029
1030        dojo.platformRequire = function(/*Object*/modMap){
1031                //      summary:
1032                //              require one or more modules based on which host environment
1033                //              Dojo is currently operating in
1034                //      description:
1035                //              This method takes a "map" of arrays which one can use to
1036                //              optionally load dojo modules. The map is indexed by the
1037                //              possible dojo.name_ values, with two additional values:
1038                //              "default" and "common". The items in the "default" array will
1039                //              be loaded if none of the other items have been choosen based on
1040                //              dojo.name_, set by your host environment. The items in the
1041                //              "common" array will *always* be loaded, regardless of which
1042                //              list is chosen.
1043                //      example:
1044                //              |       dojo.platformRequire({
1045                //              |               browser: [
1046                //              |                       "foo.sample", // simple module
1047                //              |                       "foo.test",
1048                //              |                       ["foo.bar.baz", true] // skip object check in _loadModule (dojo.require)
1049                //              |               ],
1050                //              |               default: [ "foo.sample._base" ],
1051                //              |               common: [ "important.module.common" ]
1052                //              |       });
1053
1054                var common = modMap.common || [];
1055                var result = common.concat(modMap[d._name] || modMap["default"] || []);
1056
1057                for(var x=0; x<result.length; x++){
1058                        var curr = result[x];
1059                        if(curr.constructor == Array){
1060                                d._loadModule.apply(d, curr);
1061                        }else{
1062                                d._loadModule(curr);
1063                        }
1064                }
1065        }
1066
1067        dojo.requireIf = function(/*Boolean*/ condition, /*String*/ resourceName){
1068                // summary:
1069                //              If the condition is true then call `dojo.require()` for the specified
1070                //              resource
1071                //
1072                // example:
1073                //      |       dojo.requireIf(dojo.isBrowser, "my.special.Module");
1074
1075                if(condition === true){
1076                        // FIXME: why do we support chained require()'s here? does the build system?
1077                        var args = [];
1078                        for(var i = 1; i < arguments.length; i++){
1079                                args.push(arguments[i]);
1080                        }
1081                        d.require.apply(d, args);
1082                }
1083        }
1084
1085        dojo.requireAfterIf = d.requireIf;
1086
1087        dojo.registerModulePath = function(/*String*/module, /*String*/prefix){
1088                //      summary:
1089                //              Maps a module name to a path
1090                //      description:
1091                //              An unregistered module is given the default path of ../[module],
1092                //              relative to Dojo root. For example, module acme is mapped to
1093                //              ../acme.  If you want to use a different module name, use
1094                //              dojo.registerModulePath.
1095                //      example:
1096                //              If your dojo.js is located at this location in the web root:
1097                //      |       /myapp/js/dojo/dojo/dojo.js
1098                //              and your modules are located at:
1099                //      |       /myapp/js/foo/bar.js
1100                //      |       /myapp/js/foo/baz.js
1101                //      |       /myapp/js/foo/thud/xyzzy.js
1102                //              Your application can tell Dojo to locate the "foo" namespace by calling:
1103                //      |       dojo.registerModulePath("foo", "../../foo");
1104                //              At which point you can then use dojo.require() to load the
1105                //              modules (assuming they provide() the same things which are
1106                //              required). The full code might be:
1107                //      |       <script type="text/javascript"
1108                //      |               src="/myapp/js/dojo/dojo/dojo.js"></script>
1109                //      |       <script type="text/javascript">
1110                //      |               dojo.registerModulePath("foo", "../../foo");
1111                //      |               dojo.require("foo.bar");
1112                //      |               dojo.require("foo.baz");
1113                //      |               dojo.require("foo.thud.xyzzy");
1114                //      |       </script>
1115                d._modulePrefixes[module] = { name: module, value: prefix };
1116        };
1117
1118        dojo.requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String?*/availableFlatLocales){
1119                // summary:
1120                //              Declares translated resources and loads them if necessary, in the
1121                //              same style as dojo.require.  Contents of the resource bundle are
1122                //              typically strings, but may be any name/value pair, represented in
1123                //              JSON format.  See also `dojo.i18n.getLocalization`.
1124                //
1125                // description:
1126                //              Load translated resource bundles provided underneath the "nls"
1127                //              directory within a package.  Translated resources may be located in
1128                //              different packages throughout the source tree.
1129                //
1130                //              Each directory is named for a locale as specified by RFC 3066,
1131                //              (http://www.ietf.org/rfc/rfc3066.txt), normalized in lowercase.
1132                //              Note that the two bundles in the example do not define all the
1133                //              same variants.  For a given locale, bundles will be loaded for
1134                //              that locale and all more general locales above it, including a
1135                //              fallback at the root directory.  For example, a declaration for
1136                //              the "de-at" locale will first load `nls/de-at/bundleone.js`,
1137                //              then `nls/de/bundleone.js` and finally `nls/bundleone.js`.  The
1138                //              data will be flattened into a single Object so that lookups
1139                //              will follow this cascading pattern.  An optional build step can
1140                //              preload the bundles to avoid data redundancy and the multiple
1141                //              network hits normally required to load these resources.
1142                //
1143                // moduleName:
1144                //              name of the package containing the "nls" directory in which the
1145                //              bundle is found
1146                //
1147                // bundleName:
1148                //              bundle name, i.e. the filename without the '.js' suffix. Using "nls" as a
1149                //              a bundle name is not supported, since "nls" is the name of the folder
1150                //              that holds bundles. Using "nls" as the bundle name will cause problems
1151                //              with the custom build.
1152                //
1153                // locale:
1154                //              the locale to load (optional)  By default, the browser's user
1155                //              locale as defined by dojo.locale
1156                //
1157                // availableFlatLocales:
1158                //              A comma-separated list of the available, flattened locales for this
1159                //              bundle. This argument should only be set by the build process.
1160                //
1161                //      example:
1162                //              A particular widget may define one or more resource bundles,
1163                //              structured in a program as follows, where moduleName is
1164                //              mycode.mywidget and bundleNames available include bundleone and
1165                //              bundletwo:
1166                //      |               ...
1167                //      |       mycode/
1168                //      |               mywidget/
1169                //      |                       nls/
1170                //      |                               bundleone.js (the fallback translation, English in this example)
1171                //      |                               bundletwo.js (also a fallback translation)
1172                //      |                               de/
1173                //      |                                       bundleone.js
1174                //      |                                       bundletwo.js
1175                //      |                               de-at/
1176                //      |                                       bundleone.js
1177                //      |                               en/
1178                //      |                                       (empty; use the fallback translation)
1179                //      |                               en-us/
1180                //      |                                       bundleone.js
1181                //      |                               en-gb/
1182                //      |                                       bundleone.js
1183                //      |                               es/
1184                //      |                                       bundleone.js
1185                //      |                                       bundletwo.js
1186                //      |                                 ...etc
1187                //      |                               ...
1188                //
1189
1190                d.require("dojo.i18n");
1191                d.i18n._requireLocalization.apply(d.hostenv, arguments);
1192        };
1193
1194
1195        var ore = new RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"),
1196                ire = new RegExp("^((([^\\[:]+):)?([^@]+)@)?(\\[([^\\]]+)\\]|([^\\[:]*))(:([0-9]+))?$");
1197
1198        dojo._Url = function(/*dojo._Url|String...*/){
1199                // summary:
1200                //              Constructor to create an object representing a URL.
1201                //              It is marked as private, since we might consider removing
1202                //              or simplifying it.
1203                // description:
1204                //              Each argument is evaluated in order relative to the next until
1205                //              a canonical uri is produced. To get an absolute Uri relative to
1206                //              the current document use:
1207                //              new dojo._Url(document.baseURI, url)
1208
1209                var n = null,
1210                        _a = arguments,
1211                        uri = [_a[0]];
1212                // resolve uri components relative to each other
1213                for(var i = 1; i<_a.length; i++){
1214                        if(!_a[i]){ continue; }
1215
1216                        // Safari doesn't support this.constructor so we have to be explicit
1217                        // FIXME: Tracked (and fixed) in Webkit bug 3537.
1218                        //              http://bugs.webkit.org/show_bug.cgi?id=3537
1219                        var relobj = new d._Url(_a[i]+""),
1220                                uriobj = new d._Url(uri[0]+"");
1221
1222                        if(
1223                                relobj.path == "" &&
1224                                !relobj.scheme &&
1225                                !relobj.authority &&
1226                                !relobj.query
1227                        ){
1228                                if(relobj.fragment != n){
1229                                        uriobj.fragment = relobj.fragment;
1230                                }
1231                                relobj = uriobj;
1232                        }else if(!relobj.scheme){
1233                                relobj.scheme = uriobj.scheme;
1234
1235                                if(!relobj.authority){
1236                                        relobj.authority = uriobj.authority;
1237
1238                                        if(relobj.path.charAt(0) != "/"){
1239                                                var path = uriobj.path.substring(0,
1240                                                        uriobj.path.lastIndexOf("/") + 1) + relobj.path;
1241
1242                                                var segs = path.split("/");
1243                                                for(var j = 0; j < segs.length; j++){
1244                                                        if(segs[j] == "."){
1245                                                                // flatten "./" references
1246                                                                if(j == segs.length - 1){
1247                                                                        segs[j] = "";
1248                                                                }else{
1249                                                                        segs.splice(j, 1);
1250                                                                        j--;
1251                                                                }
1252                                                        }else if(j > 0 && !(j == 1 && segs[0] == "") &&
1253                                                                segs[j] == ".." && segs[j-1] != ".."){
1254                                                                // flatten "../" references
1255                                                                if(j == (segs.length - 1)){
1256                                                                        segs.splice(j, 1);
1257                                                                        segs[j - 1] = "";
1258                                                                }else{
1259                                                                        segs.splice(j - 1, 2);
1260                                                                        j -= 2;
1261                                                                }
1262                                                        }
1263                                                }
1264                                                relobj.path = segs.join("/");
1265                                        }
1266                                }
1267                        }
1268
1269                        uri = [];
1270                        if(relobj.scheme){
1271                                uri.push(relobj.scheme, ":");
1272                        }
1273                        if(relobj.authority){
1274                                uri.push("//", relobj.authority);
1275                        }
1276                        uri.push(relobj.path);
1277                        if(relobj.query){
1278                                uri.push("?", relobj.query);
1279                        }
1280                        if(relobj.fragment){
1281                                uri.push("#", relobj.fragment);
1282                        }
1283                }
1284
1285                this.uri = uri.join("");
1286
1287                // break the uri into its main components
1288                var r = this.uri.match(ore);
1289
1290                this.scheme = r[2] || (r[1] ? "" : n);
1291                this.authority = r[4] || (r[3] ? "" : n);
1292                this.path = r[5]; // can never be undefined
1293                this.query = r[7] || (r[6] ? "" : n);
1294                this.fragment  = r[9] || (r[8] ? "" : n);
1295
1296                if(this.authority != n){
1297                        // server based naming authority
1298                        r = this.authority.match(ire);
1299
1300                        this.user = r[3] || n;
1301                        this.password = r[4] || n;
1302                        this.host = r[6] || r[7]; // ipv6 || ipv4
1303                        this.port = r[9] || n;
1304                }
1305        }
1306
1307        dojo._Url.prototype.toString = function(){ return this.uri; };
1308
1309        dojo.moduleUrl = function(/*String*/module, /*dojo._Url||String*/url){
1310                //      summary:
1311                //              Returns a `dojo._Url` object relative to a module.
1312                //      example:
1313                //      |       var pngPath = dojo.moduleUrl("acme","images/small.png");
1314                //      |       console.dir(pngPath); // list the object properties
1315                //      |       // create an image and set it's source to pngPath's value:
1316                //      |       var img = document.createElement("img");
1317                //      |       // NOTE: we assign the string representation of the url object
1318                //      |       img.src = pngPath.toString();
1319                //      |       // add our image to the document
1320                //      |       dojo.body().appendChild(img);
1321                //      example:
1322                //              you may de-reference as far as you like down the package
1323                //              hierarchy.  This is sometimes handy to avoid lenghty relative
1324                //              urls or for building portable sub-packages. In this example,
1325                //              the `acme.widget` and `acme.util` directories may be located
1326                //              under different roots (see `dojo.registerModulePath`) but the
1327                //              the modules which reference them can be unaware of their
1328                //              relative locations on the filesystem:
1329                //      |       // somewhere in a configuration block
1330                //      |       dojo.registerModulePath("acme.widget", "../../acme/widget");
1331                //      |       dojo.registerModulePath("acme.util", "../../util");
1332                //      |
1333                //      |       // ...
1334                //      |
1335                //      |       // code in a module using acme resources
1336                //      |       var tmpltPath = dojo.moduleUrl("acme.widget","templates/template.html");
1337                //      |       var dataPath = dojo.moduleUrl("acme.util","resources/data.json");
1338
1339                var loc = d._getModuleSymbols(module).join('/');
1340                if(!loc){ return null; }
1341                if(loc.lastIndexOf("/") != loc.length-1){
1342                        loc += "/";
1343                }
1344
1345                //If the path is an absolute path (starts with a / or is on another
1346                //domain/xdomain) then don't add the baseUrl.
1347                var colonIndex = loc.indexOf(":");
1348                if(loc.charAt(0) != "/" && (colonIndex == -1 || colonIndex > loc.indexOf("/"))){
1349                        loc = d.baseUrl + loc;
1350                }
1351
1352                return new d._Url(loc, url); // dojo._Url
1353        };
1354
1355
1356
1357})();
1358
1359/*=====
1360dojo.isBrowser = {
1361        //      example:
1362        //      |       if(dojo.isBrowser){ ... }
1363};
1364
1365dojo.isFF = {
1366        //      example:
1367        //      |       if(dojo.isFF > 1){ ... }
1368};
1369
1370dojo.isIE = {
1371        // example:
1372        //      |       if(dojo.isIE > 6){
1373        //      |               // we are IE7
1374        //      |       }
1375};
1376
1377dojo.isSafari = {
1378        //      example:
1379        //      |       if(dojo.isSafari){ ... }
1380        //      example:
1381        //              Detect iPhone:
1382        //      |       if(dojo.isSafari && navigator.userAgent.indexOf("iPhone") != -1){
1383        //      |               // we are iPhone. Note, iPod touch reports "iPod" above and fails this test.
1384        //      |       }
1385};
1386
1387dojo = {
1388        // isBrowser: Boolean
1389        //              True if the client is a web-browser
1390        isBrowser: true,
1391        //      isFF: Number | undefined
1392        //              Version as a Number if client is FireFox. undefined otherwise. Corresponds to
1393        //              major detected FireFox version (1.5, 2, 3, etc.)
1394        isFF: 2,
1395        //      isIE: Number | undefined
1396        //              Version as a Number if client is MSIE(PC). undefined otherwise. Corresponds to
1397        //              major detected IE version (6, 7, 8, etc.)
1398        isIE: 6,
1399        //      isKhtml: Number | undefined
1400        //              Version as a Number if client is a KHTML browser. undefined otherwise. Corresponds to major
1401        //              detected version.
1402        isKhtml: 0,
1403        //      isWebKit: Number | undefined
1404        //              Version as a Number if client is a WebKit-derived browser (Konqueror,
1405        //              Safari, Chrome, etc.). undefined otherwise.
1406        isWebKit: 0,
1407        //      isMozilla: Number | undefined
1408        //              Version as a Number if client is a Mozilla-based browser (Firefox,
1409        //              SeaMonkey). undefined otherwise. Corresponds to major detected version.
1410        isMozilla: 0,
1411        //      isOpera: Number | undefined
1412        //              Version as a Number if client is Opera. undefined otherwise. Corresponds to
1413        //              major detected version.
1414        isOpera: 0,
1415        //      isSafari: Number | undefined
1416        //              Version as a Number if client is Safari or iPhone. undefined otherwise.
1417        isSafari: 0,
1418        //      isChrome: Number | undefined
1419        //              Version as a Number if client is Chrome browser. undefined otherwise.
1420        isChrome: 0
1421        //      isMac: Boolean
1422        //              True if the client runs on Mac
1423}
1424=====*/
1425if(typeof window != 'undefined'){
1426        dojo.isBrowser = true;
1427        dojo._name = "browser";
1428
1429
1430        // attempt to figure out the path to dojo if it isn't set in the config
1431        (function(){
1432                var d = dojo;
1433
1434                // this is a scope protection closure. We set browser versions and grab
1435                // the URL we were loaded from here.
1436
1437                // grab the node we were loaded from
1438                if(document && document.getElementsByTagName){
1439                        var scripts = document.getElementsByTagName("script");
1440                        var rePkg = /dojo(\.xd)?\.js(\W|$)/i;
1441                        for(var i = 0; i < scripts.length; i++){
1442                                var src = scripts[i].getAttribute("src");
1443                                if(!src){ continue; }
1444                                var m = src.match(rePkg);
1445                                if(m){
1446                                        // find out where we came from
1447                                        if(!d.config.baseUrl){
1448                                                d.config.baseUrl = src.substring(0, m.index);
1449                                        }
1450                                        // and find out if we need to modify our behavior
1451                                        var cfg = (scripts[i].getAttribute("djConfig") || scripts[i].getAttribute("data-dojo-config"));
1452                                        if(cfg){
1453                                                var cfgo = eval("({ "+cfg+" })");
1454                                                for(var x in cfgo){
1455                                                        dojo.config[x] = cfgo[x];
1456                                                }
1457                                        }
1458                                        break; // "first Dojo wins"
1459                                }
1460                        }
1461                }
1462                d.baseUrl = d.config.baseUrl;
1463
1464                // fill in the rendering support information in dojo.render.*
1465                var n = navigator;
1466                var dua = n.userAgent,
1467                        dav = n.appVersion,
1468                        tv = parseFloat(dav);
1469
1470                if(dua.indexOf("Opera") >= 0){ d.isOpera = tv; }
1471                if(dua.indexOf("AdobeAIR") >= 0){ d.isAIR = 1; }
1472                d.isKhtml = (dav.indexOf("Konqueror") >= 0) ? tv : 0;
1473                d.isWebKit = parseFloat(dua.split("WebKit/")[1]) || undefined;
1474                d.isChrome = parseFloat(dua.split("Chrome/")[1]) || undefined;
1475                d.isMac = dav.indexOf("Macintosh") >= 0;
1476
1477                // safari detection derived from:
1478                //              http://developer.apple.com/internet/safari/faq.html#anchor2
1479                //              http://developer.apple.com/internet/safari/uamatrix.html
1480                var index = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0);
1481                if(index && !dojo.isChrome){
1482                        // try to grab the explicit Safari version first. If we don't get
1483                        // one, look for less than 419.3 as the indication that we're on something
1484                        // "Safari 2-ish".
1485                        d.isSafari = parseFloat(dav.split("Version/")[1]);
1486                        if(!d.isSafari || parseFloat(dav.substr(index + 7)) <= 419.3){
1487                                d.isSafari = 2;
1488                        }
1489                }
1490
1491                                if(dua.indexOf("Gecko") >= 0 && !d.isKhtml && !d.isWebKit){ d.isMozilla = d.isMoz = tv; }
1492                if(d.isMoz){
1493                        //We really need to get away from this. Consider a sane isGecko approach for the future.
1494                        d.isFF = parseFloat(dua.split("Firefox/")[1] || dua.split("Minefield/")[1]) || undefined;
1495                }
1496                if(document.all && !d.isOpera){
1497                        d.isIE = parseFloat(dav.split("MSIE ")[1]) || undefined;
1498                        //In cases where the page has an HTTP header or META tag with
1499                        //X-UA-Compatible, then it is in emulation mode.
1500                        //Make sure isIE reflects the desired version.
1501                        //document.documentMode of 5 means quirks mode.
1502                        //Only switch the value if documentMode's major version
1503                        //is different from isIE's major version.
1504                        var mode = document.documentMode;
1505                        if(mode && mode != 5 && Math.floor(d.isIE) != mode){
1506                                d.isIE = mode;
1507                        }
1508                }
1509
1510                //Workaround to get local file loads of dojo to work on IE 7
1511                //by forcing to not use native xhr.
1512                if(dojo.isIE && window.location.protocol === "file:"){
1513                        dojo.config.ieForceActiveXXhr=true;
1514                }
1515
1516                d.isQuirks = document.compatMode == "BackCompat";
1517
1518                // TODO: is the HTML LANG attribute relevant?
1519                d.locale = dojo.config.locale || (d.isIE ? n.userLanguage : n.language).toLowerCase();
1520
1521                // These are in order of decreasing likelihood; this will change in time.
1522                                d._XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'];
1523
1524                d._xhrObj = function(){
1525                        // summary:
1526                        //              does the work of portably generating a new XMLHTTPRequest object.
1527                        var http, last_e;
1528                                                if(!dojo.isIE || !dojo.config.ieForceActiveXXhr){
1529                                                        try{ http = new XMLHttpRequest(); }catch(e){}
1530                                                }
1531                        if(!http){
1532                                for(var i=0; i<3; ++i){
1533                                        var progid = d._XMLHTTP_PROGIDS[i];
1534                                        try{
1535                                                http = new ActiveXObject(progid);
1536                                        }catch(e){
1537                                                last_e = e;
1538                                        }
1539
1540                                        if(http){
1541                                                d._XMLHTTP_PROGIDS = [progid];  // so faster next time
1542                                                break;
1543                                        }
1544                                }
1545                        }
1546
1547                        if(!http){
1548                                throw new Error("XMLHTTP not available: "+last_e);
1549                        }
1550
1551                        return http; // XMLHTTPRequest instance
1552                }
1553
1554                d._isDocumentOk = function(http){
1555                        var stat = http.status || 0,
1556                                lp = location.protocol;
1557                        return (stat >= 200 && stat < 300) ||   // Boolean
1558                                stat == 304 ||                  // allow any 2XX response code
1559                                stat == 1223 ||                 // get it out of the cache
1560                                                                // Internet Explorer mangled the status code
1561                                // Internet Explorer mangled the status code OR we're Titanium/browser chrome/chrome extension requesting a local file
1562                                (!stat && (lp == "file:" || lp == "chrome:" || lp == "chrome-extension:" || lp == "app:"));
1563                }
1564
1565                //See if base tag is in use.
1566                //This is to fix http://trac.dojotoolkit.org/ticket/3973,
1567                //but really, we need to find out how to get rid of the dojo._Url reference
1568                //below and still have DOH work with the dojo.i18n test following some other
1569                //test that uses the test frame to load a document (trac #2757).
1570                //Opera still has problems, but perhaps a larger issue of base tag support
1571                //with XHR requests (hasBase is true, but the request is still made to document
1572                //path, not base path).
1573                var owloc = window.location+"";
1574                var base = document.getElementsByTagName("base");
1575                var hasBase = (base && base.length > 0);
1576
1577                d._getText = function(/*URI*/ uri, /*Boolean*/ fail_ok){
1578                        // summary: Read the contents of the specified uri and return those contents.
1579                        // uri:
1580                        //              A relative or absolute uri. If absolute, it still must be in
1581                        //              the same "domain" as we are.
1582                        // fail_ok:
1583                        //              Default false. If fail_ok and loading fails, return null
1584                        //              instead of throwing.
1585                        // returns: The response text. null is returned when there is a
1586                        //              failure and failure is okay (an exception otherwise)
1587
1588                        // NOTE: must be declared before scope switches ie. this._xhrObj()
1589                        var http = d._xhrObj();
1590
1591                        if(!hasBase && dojo._Url){
1592                                uri = (new dojo._Url(owloc, uri)).toString();
1593                        }
1594
1595                        if(d.config.cacheBust){
1596                                //Make sure we have a string before string methods are used on uri
1597                                uri += "";
1598                                uri += (uri.indexOf("?") == -1 ? "?" : "&") + String(d.config.cacheBust).replace(/\W+/g,"");
1599                        }
1600
1601                        http.open('GET', uri, false);
1602                        try{
1603                                http.send(null);
1604                                if(!d._isDocumentOk(http)){
1605                                        var err = Error("Unable to load "+uri+" status:"+ http.status);
1606                                        err.status = http.status;
1607                                        err.responseText = http.responseText;
1608                                        throw err;
1609                                }
1610                        }catch(e){
1611                                if(fail_ok){ return null; } // null
1612                                // rethrow the exception
1613                                throw e;
1614                        }
1615                        return http.responseText; // String
1616                }
1617
1618
1619                var _w = window;
1620                var _handleNodeEvent = function(/*String*/evtName, /*Function*/fp){
1621                        // summary:
1622                        //              non-destructively adds the specified function to the node's
1623                        //              evtName handler.
1624                        // evtName: should be in the form "onclick" for "onclick" handlers.
1625                        // Make sure you pass in the "on" part.
1626                        var _a = _w.attachEvent || _w.addEventListener;
1627                        evtName = _w.attachEvent ? evtName : evtName.substring(2);
1628                        _a(evtName, function(){
1629                                fp.apply(_w, arguments);
1630                        }, false);
1631                };
1632
1633
1634                d._windowUnloaders = [];
1635
1636                d.windowUnloaded = function(){
1637                        // summary:
1638                        //              signal fired by impending window destruction. You may use
1639                        //              dojo.addOnWindowUnload() to register a listener for this
1640                        //              event. NOTE: if you wish to dojo.connect() to this method
1641                        //              to perform page/application cleanup, be aware that this
1642                        //              event WILL NOT fire if no handler has been registered with
1643                        //              dojo.addOnWindowUnload. This behavior started in Dojo 1.3.
1644                        //              Previous versions always triggered dojo.windowUnloaded. See
1645                        //              dojo.addOnWindowUnload for more info.
1646                        var mll = d._windowUnloaders;
1647                        while(mll.length){
1648                                (mll.pop())();
1649                        }
1650                        d = null;
1651                };
1652
1653                var _onWindowUnloadAttached = 0;
1654                d.addOnWindowUnload = function(/*Object?|Function?*/obj, /*String|Function?*/functionName){
1655                        // summary:
1656                        //              registers a function to be triggered when window.onunload
1657                        //              fires.
1658                        //      description:
1659                        //              The first time that addOnWindowUnload is called Dojo
1660                        //              will register a page listener to trigger your unload
1661                        //              handler with. Note that registering these handlers may
1662                        //              destory "fastback" page caching in browsers that support
1663                        //              it. Be careful trying to modify the DOM or access
1664                        //              JavaScript properties during this phase of page unloading:
1665                        //              they may not always be available. Consider
1666                        //              dojo.addOnUnload() if you need to modify the DOM or do
1667                        //              heavy JavaScript work since it fires at the eqivalent of
1668                        //              the page's "onbeforeunload" event.
1669                        // example:
1670                        //      |       dojo.addOnWindowUnload(functionPointer)
1671                        //      |       dojo.addOnWindowUnload(object, "functionName");
1672                        //      |       dojo.addOnWindowUnload(object, function(){ /* ... */});
1673
1674                        d._onto(d._windowUnloaders, obj, functionName);
1675                        if(!_onWindowUnloadAttached){
1676                                _onWindowUnloadAttached = 1;
1677                                _handleNodeEvent("onunload", d.windowUnloaded);
1678                        }
1679                };
1680
1681                var _onUnloadAttached = 0;
1682                d.addOnUnload = function(/*Object?|Function?*/obj, /*String|Function?*/functionName){
1683                        // summary:
1684                        //              registers a function to be triggered when the page unloads.
1685                        //      description:
1686                        //              The first time that addOnUnload is called Dojo will
1687                        //              register a page listener to trigger your unload handler
1688                        //              with.
1689                        //
1690                        //              In a browser enviroment, the functions will be triggered
1691                        //              during the window.onbeforeunload event. Be careful of doing
1692                        //              too much work in an unload handler. onbeforeunload can be
1693                        //              triggered if a link to download a file is clicked, or if
1694                        //              the link is a javascript: link. In these cases, the
1695                        //              onbeforeunload event fires, but the document is not
1696                        //              actually destroyed. So be careful about doing destructive
1697                        //              operations in a dojo.addOnUnload callback.
1698                        //
1699                        //              Further note that calling dojo.addOnUnload will prevent
1700                        //              browsers from using a "fast back" cache to make page
1701                        //              loading via back button instantaneous.
1702                        // example:
1703                        //      |       dojo.addOnUnload(functionPointer)
1704                        //      |       dojo.addOnUnload(object, "functionName")
1705                        //      |       dojo.addOnUnload(object, function(){ /* ... */});
1706
1707                        d._onto(d._unloaders, obj, functionName);
1708                        if(!_onUnloadAttached){
1709                                _onUnloadAttached = 1;
1710                                _handleNodeEvent("onbeforeunload", dojo.unloaded);
1711                        }
1712                };
1713
1714        })();
1715
1716        //START DOMContentLoaded
1717        dojo._initFired = false;
1718        dojo._loadInit = function(e){
1719                if(dojo._scrollIntervalId){
1720                        clearInterval(dojo._scrollIntervalId);
1721                        dojo._scrollIntervalId = 0;
1722                }
1723
1724                if(!dojo._initFired){
1725                        dojo._initFired = true;
1726
1727                        //Help out IE to avoid memory leak.
1728                        if(!dojo.config.afterOnLoad && window.detachEvent){
1729                                window.detachEvent("onload", dojo._loadInit);
1730                        }
1731
1732                        if(dojo._inFlightCount == 0){
1733                                dojo._modulesLoaded();
1734                        }
1735                }
1736        }
1737
1738        if(!dojo.config.afterOnLoad){
1739                if(document.addEventListener){
1740                        //Standards. Hooray! Assumption here that if standards based,
1741                        //it knows about DOMContentLoaded. It is OK if it does not, the fall through
1742                        //to window onload should be good enough.
1743                        document.addEventListener("DOMContentLoaded", dojo._loadInit, false);
1744                        window.addEventListener("load", dojo._loadInit, false);
1745                }else if(window.attachEvent){
1746                        window.attachEvent("onload", dojo._loadInit);
1747
1748                        //DOMContentLoaded approximation. Diego Perini found this MSDN article
1749                        //that indicates doScroll is available after DOM ready, so do a setTimeout
1750                        //to check when it is available.
1751                        //http://msdn.microsoft.com/en-us/library/ms531426.aspx
1752                        if(!dojo.config.skipIeDomLoaded && self === self.top){
1753                                dojo._scrollIntervalId = setInterval(function (){
1754                                        try{
1755                                                //When dojo is loaded into an iframe in an IE HTML Application
1756                                                //(HTA), such as in a selenium test, javascript in the iframe
1757                                                //can't see anything outside of it, so self===self.top is true,
1758                                                //but the iframe is not the top window and doScroll will be
1759                                                //available before document.body is set. Test document.body
1760                                                //before trying the doScroll trick
1761                                                if(document.body){
1762                                                        document.documentElement.doScroll("left");
1763                                                        dojo._loadInit();
1764                                                }
1765                                        }catch (e){}
1766                                }, 30);
1767                        }
1768                }
1769        }
1770
1771                if(dojo.isIE){
1772                try{
1773                        (function(){
1774                                document.namespaces.add("v", "urn:schemas-microsoft-com:vml");
1775                                var vmlElems = ["*", "group", "roundrect", "oval", "shape", "rect", "imagedata", "path", "textpath", "text"],
1776                                        i = 0, l = 1, s = document.createStyleSheet();
1777                                if(dojo.isIE >= 8){
1778                                        i = 1;
1779                                        l = vmlElems.length;
1780                                }
1781                                for(; i < l; ++i){
1782                                        s.addRule("v\\:" + vmlElems[i], "behavior:url(#default#VML); display:inline-block");
1783                                }
1784                        })();
1785                }catch(e){}
1786        }
1787                //END DOMContentLoaded
1788
1789
1790        /*
1791        OpenAjax.subscribe("OpenAjax", "onload", function(){
1792                if(dojo._inFlightCount == 0){
1793                        dojo._modulesLoaded();
1794                }
1795        });
1796
1797        OpenAjax.subscribe("OpenAjax", "onunload", function(){
1798                dojo.unloaded();
1799        });
1800        */
1801} //if (typeof window != 'undefined')
1802
1803//Register any module paths set up in djConfig. Need to do this
1804//in the hostenvs since hostenv_browser can read djConfig from a
1805//script tag's attribute.
1806(function(){
1807        var mp = dojo.config["modulePaths"];
1808        if(mp){
1809                for(var param in mp){
1810                        dojo.registerModulePath(param, mp[param]);
1811                }
1812        }
1813})();
1814
1815//Load debug code if necessary.
1816if(dojo.config.isDebug){
1817        dojo.require("dojo._firebug.firebug");
1818}
1819
1820if(dojo.config.debugAtAllCosts){
1821        // this breaks the new AMD based module loader. The XDomain won't be necessary
1822        // anyway if you switch to the asynchronous loader
1823        //dojo.config.useXDomain = true;
1824        //dojo.require("dojo._base._loader.loader_xd");
1825        dojo.require("dojo._base._loader.loader_debug");
1826        dojo.require("dojo.i18n");
1827}
1828
1829
1830if(!dojo._hasResource["dojo._base.lang"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
1831dojo._hasResource["dojo._base.lang"] = true;
1832dojo.provide("dojo._base.lang");
1833
1834
1835(function(){
1836        var d = dojo, opts = Object.prototype.toString;
1837
1838        // Crockford (ish) functions
1839
1840        dojo.isString = function(/*anything*/ it){
1841                //      summary:
1842                //              Return true if it is a String
1843                return (typeof it == "string" || it instanceof String); // Boolean
1844        };
1845
1846        dojo.isArray = function(/*anything*/ it){
1847                //      summary:
1848                //              Return true if it is an Array.
1849                //              Does not work on Arrays created in other windows.
1850                return it && (it instanceof Array || typeof it == "array"); // Boolean
1851        };
1852
1853        dojo.isFunction = function(/*anything*/ it){
1854                // summary:
1855                //              Return true if it is a Function
1856                return opts.call(it) === "[object Function]";
1857        };
1858
1859        dojo.isObject = function(/*anything*/ it){
1860                // summary:
1861                //              Returns true if it is a JavaScript object (or an Array, a Function
1862                //              or null)
1863                return it !== undefined &&
1864                        (it === null || typeof it == "object" || d.isArray(it) || d.isFunction(it)); // Boolean
1865        };
1866
1867        dojo.isArrayLike = function(/*anything*/ it){
1868                //      summary:
1869                //              similar to dojo.isArray() but more permissive
1870                //      description:
1871                //              Doesn't strongly test for "arrayness".  Instead, settles for "isn't
1872                //              a string or number and has a length property". Arguments objects
1873                //              and DOM collections will return true when passed to
1874                //              dojo.isArrayLike(), but will return false when passed to
1875                //              dojo.isArray().
1876                //      returns:
1877                //              If it walks like a duck and quacks like a duck, return `true`
1878                return it && it !== undefined && // Boolean
1879                        // keep out built-in constructors (Number, String, ...) which have length
1880                        // properties
1881                        !d.isString(it) && !d.isFunction(it) &&
1882                        !(it.tagName && it.tagName.toLowerCase() == 'form') &&
1883                        (d.isArray(it) || isFinite(it.length));
1884        };
1885
1886        dojo.isAlien = function(/*anything*/ it){
1887                // summary:
1888                //              Returns true if it is a built-in function or some other kind of
1889                //              oddball that *should* report as a function but doesn't
1890                return it && !d.isFunction(it) && /\{\s*\[native code\]\s*\}/.test(String(it)); // Boolean
1891        };
1892
1893        dojo.extend = function(/*Object*/ constructor, /*Object...*/ props){
1894                // summary:
1895                //              Adds all properties and methods of props to constructor's
1896                //              prototype, making them available to all instances created with
1897                //              constructor.
1898                for(var i=1, l=arguments.length; i<l; i++){
1899                        d._mixin(constructor.prototype, arguments[i]);
1900                }
1901                return constructor; // Object
1902        };
1903
1904        dojo._hitchArgs = function(scope, method /*,...*/){
1905                var pre = d._toArray(arguments, 2);
1906                var named = d.isString(method);
1907                return function(){
1908                        // arrayify arguments
1909                        var args = d._toArray(arguments);
1910                        // locate our method
1911                        var f = named ? (scope||d.global)[method] : method;
1912                        // invoke with collected args
1913                        return f && f.apply(scope || this, pre.concat(args)); // mixed
1914                }; // Function
1915        };
1916
1917        dojo.hitch = function(/*Object*/scope, /*Function|String*/method /*,...*/){
1918                //      summary:
1919                //              Returns a function that will only ever execute in the a given scope.
1920                //              This allows for easy use of object member functions
1921                //              in callbacks and other places in which the "this" keyword may
1922                //              otherwise not reference the expected scope.
1923                //              Any number of default positional arguments may be passed as parameters
1924                //              beyond "method".
1925                //              Each of these values will be used to "placehold" (similar to curry)
1926                //              for the hitched function.
1927                //      scope:
1928                //              The scope to use when method executes. If method is a string,
1929                //              scope is also the object containing method.
1930                //      method:
1931                //              A function to be hitched to scope, or the name of the method in
1932                //              scope to be hitched.
1933                //      example:
1934                //      |       dojo.hitch(foo, "bar")();
1935                //              runs foo.bar() in the scope of foo
1936                //      example:
1937                //      |       dojo.hitch(foo, myFunction);
1938                //              returns a function that runs myFunction in the scope of foo
1939                //      example:
1940                //              Expansion on the default positional arguments passed along from
1941                //              hitch. Passed args are mixed first, additional args after.
1942                //      |       var foo = { bar: function(a, b, c){ console.log(a, b, c); } };
1943                //      |       var fn = dojo.hitch(foo, "bar", 1, 2);
1944                //      |       fn(3); // logs "1, 2, 3"
1945                //      example:
1946                //      |       var foo = { bar: 2 };
1947                //      |       dojo.hitch(foo, function(){ this.bar = 10; })();
1948                //              execute an anonymous function in scope of foo
1949
1950                if(arguments.length > 2){
1951                        return d._hitchArgs.apply(d, arguments); // Function
1952                }
1953                if(!method){
1954                        method = scope;
1955                        scope = null;
1956                }
1957                if(d.isString(method)){
1958                        scope = scope || d.global;
1959                        if(!scope[method]){ throw(['dojo.hitch: scope["', method, '"] is null (scope="', scope, '")'].join('')); }
1960                        return function(){ return scope[method].apply(scope, arguments || []); }; // Function
1961                }
1962                return !scope ? method : function(){ return method.apply(scope, arguments || []); }; // Function
1963        };
1964
1965        /*=====
1966        dojo.delegate = function(obj, props){
1967                //      summary:
1968                //              Returns a new object which "looks" to obj for properties which it
1969                //              does not have a value for. Optionally takes a bag of properties to
1970                //              seed the returned object with initially.
1971                //      description:
1972                //              This is a small implementaton of the Boodman/Crockford delegation
1973                //              pattern in JavaScript. An intermediate object constructor mediates
1974                //              the prototype chain for the returned object, using it to delegate
1975                //              down to obj for property lookup when object-local lookup fails.
1976                //              This can be thought of similarly to ES4's "wrap", save that it does
1977                //              not act on types but rather on pure objects.
1978                //      obj:
1979                //              The object to delegate to for properties not found directly on the
1980                //              return object or in props.
1981                //      props:
1982                //              an object containing properties to assign to the returned object
1983                //      returns:
1984                //              an Object of anonymous type
1985                //      example:
1986                //      |       var foo = { bar: "baz" };
1987                //      |       var thinger = dojo.delegate(foo, { thud: "xyzzy"});
1988                //      |       thinger.bar == "baz"; // delegated to foo
1989                //      |       foo.thud == undefined; // by definition
1990                //      |       thinger.thud == "xyzzy"; // mixed in from props
1991                //      |       foo.bar = "thonk";
1992                //      |       thinger.bar == "thonk"; // still delegated to foo's bar
1993        }
1994        =====*/
1995
1996        dojo.delegate = dojo._delegate = (function(){
1997                // boodman/crockford delegation w/ cornford optimization
1998                function TMP(){}
1999                return function(obj, props){
2000                        TMP.prototype = obj;
2001                        var tmp = new TMP();
2002                        TMP.prototype = null;
2003                        if(props){
2004                                d._mixin(tmp, props);
2005                        }
2006                        return tmp; // Object
2007                };
2008        })();
2009
2010        /*=====
2011        dojo._toArray = function(obj, offset, startWith){
2012                //      summary:
2013                //              Converts an array-like object (i.e. arguments, DOMCollection) to an
2014                //              array. Returns a new Array with the elements of obj.
2015                //      obj: Object
2016                //              the object to "arrayify". We expect the object to have, at a
2017                //              minimum, a length property which corresponds to integer-indexed
2018                //              properties.
2019                //      offset: Number?
2020                //              the location in obj to start iterating from. Defaults to 0.
2021                //              Optional.
2022                //      startWith: Array?
2023                //              An array to pack with the properties of obj. If provided,
2024                //              properties in obj are appended at the end of startWith and
2025                //              startWith is the returned array.
2026        }
2027        =====*/
2028
2029        var efficient = function(obj, offset, startWith){
2030                return (startWith||[]).concat(Array.prototype.slice.call(obj, offset||0));
2031        };
2032
2033                var slow = function(obj, offset, startWith){
2034                var arr = startWith||[];
2035                for(var x = offset || 0; x < obj.length; x++){
2036                        arr.push(obj[x]);
2037                }
2038                return arr;
2039        };
2040
2041        dojo._toArray =
2042                                d.isIE ?  function(obj){
2043                        return ((obj.item) ? slow : efficient).apply(this, arguments);
2044                } :
2045                                efficient;
2046
2047        dojo.partial = function(/*Function|String*/method /*, ...*/){
2048                //      summary:
2049                //              similar to hitch() except that the scope object is left to be
2050                //              whatever the execution context eventually becomes.
2051                //      description:
2052                //              Calling dojo.partial is the functional equivalent of calling:
2053                //              |       dojo.hitch(null, funcName, ...);
2054                var arr = [ null ];
2055                return d.hitch.apply(d, arr.concat(d._toArray(arguments))); // Function
2056        };
2057
2058        var extraNames = d._extraNames, extraLen = extraNames.length, empty = {};
2059
2060        dojo.clone = function(/*anything*/ o){
2061                // summary:
2062                //              Clones objects (including DOM nodes) and all children.
2063                //              Warning: do not clone cyclic structures.
2064                if(!o || typeof o != "object" || d.isFunction(o)){
2065                        // null, undefined, any non-object, or function
2066                        return o;       // anything
2067                }
2068                if(o.nodeType && "cloneNode" in o){
2069                        // DOM Node
2070                        return o.cloneNode(true); // Node
2071                }
2072                if(o instanceof Date){
2073                        // Date
2074                        return new Date(o.getTime());   // Date
2075                }
2076                if(o instanceof RegExp){
2077                        // RegExp
2078                        return new RegExp(o);   // RegExp
2079                }
2080                var r, i, l, s, name;
2081                if(d.isArray(o)){
2082                        // array
2083                        r = [];
2084                        for(i = 0, l = o.length; i < l; ++i){
2085                                if(i in o){
2086                                        r.push(d.clone(o[i]));
2087                                }
2088                        }
2089// we don't clone functions for performance reasons
2090//              }else if(d.isFunction(o)){
2091//                      // function
2092//                      r = function(){ return o.apply(this, arguments); };
2093                }else{
2094                        // generic objects
2095                        r = o.constructor ? new o.constructor() : {};
2096                }
2097                for(name in o){
2098                        // the "tobj" condition avoid copying properties in "source"
2099                        // inherited from Object.prototype.  For example, if target has a custom
2100                        // toString() method, don't overwrite it with the toString() method
2101                        // that source inherited from Object.prototype
2102                        s = o[name];
2103                        if(!(name in r) || (r[name] !== s && (!(name in empty) || empty[name] !== s))){
2104                                r[name] = d.clone(s);
2105                        }
2106                }
2107                                // IE doesn't recognize some custom functions in for..in
2108                if(extraLen){
2109                        for(i = 0; i < extraLen; ++i){
2110                                name = extraNames[i];
2111                                s = o[name];
2112                                if(!(name in r) || (r[name] !== s && (!(name in empty) || empty[name] !== s))){
2113                                        r[name] = s; // functions only, we don't clone them
2114                                }
2115                        }
2116                }
2117                                return r; // Object
2118        };
2119
2120        /*=====
2121        dojo.trim = function(str){
2122                //      summary:
2123                //              Trims whitespace from both sides of the string
2124                //      str: String
2125                //              String to be trimmed
2126                //      returns: String
2127                //              Returns the trimmed string
2128                //      description:
2129                //              This version of trim() was selected for inclusion into the base due
2130                //              to its compact size and relatively good performance
2131                //              (see [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript)
2132                //              Uses String.prototype.trim instead, if available.
2133                //              The fastest but longest version of this function is located at
2134                //              dojo.string.trim()
2135                return "";      // String
2136        }
2137        =====*/
2138
2139        dojo.trim = String.prototype.trim ?
2140                function(str){ return str.trim(); } :
2141                function(str){ return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); };
2142
2143        /*=====
2144        dojo.replace = function(tmpl, map, pattern){
2145                //      summary:
2146                //              Performs parameterized substitutions on a string. Throws an
2147                //              exception if any parameter is unmatched.
2148                //      tmpl: String
2149                //              String to be used as a template.
2150                //      map: Object|Function
2151                //              If an object, it is used as a dictionary to look up substitutions.
2152                //              If a function, it is called for every substitution with following
2153                //              parameters: a whole match, a name, an offset, and the whole template
2154                //              string (see https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/replace
2155                //              for more details).
2156                //      pattern: RegEx?
2157                //              Optional regular expression objects that overrides the default pattern.
2158                //              Must be global and match one item. The default is: /\{([^\}]+)\}/g,
2159                //              which matches patterns like that: "{xxx}", where "xxx" is any sequence
2160                //              of characters, which doesn't include "}".
2161                //      returns: String
2162                //              Returns the substituted string.
2163                //      example:
2164                //      |       // uses a dictionary for substitutions:
2165                //      |       dojo.replace("Hello, {name.first} {name.last} AKA {nick}!",
2166                //      |         {
2167                //      |           nick: "Bob",
2168                //      |           name: {
2169                //      |             first:  "Robert",
2170                //      |             middle: "X",
2171                //      |             last:   "Cringely"
2172                //      |           }
2173                //      |         });
2174                //      |       // returns: Hello, Robert Cringely AKA Bob!
2175                //      example:
2176                //      |       // uses an array for substitutions:
2177                //      |       dojo.replace("Hello, {0} {2}!",
2178                //      |         ["Robert", "X", "Cringely"]);
2179                //      |       // returns: Hello, Robert Cringely!
2180                //      example:
2181                //      |       // uses a function for substitutions:
2182                //      |       function sum(a){
2183                //      |         var t = 0;
2184                //      |         dojo.forEach(a, function(x){ t += x; });
2185                //      |         return t;
2186                //      |       }
2187                //      |       dojo.replace(
2188                //      |         "{count} payments averaging {avg} USD per payment.",
2189                //      |         dojo.hitch(
2190                //      |           { payments: [11, 16, 12] },
2191                //      |           function(_, key){
2192                //      |             switch(key){
2193                //      |               case "count": return this.payments.length;
2194                //      |               case "min":   return Math.min.apply(Math, this.payments);
2195                //      |               case "max":   return Math.max.apply(Math, this.payments);
2196                //      |               case "sum":   return sum(this.payments);
2197                //      |               case "avg":   return sum(this.payments) / this.payments.length;
2198                //      |             }
2199                //      |           }
2200                //      |         )
2201                //      |       );
2202                //      |       // prints: 3 payments averaging 13 USD per payment.
2203                //      example:
2204                //      |       // uses an alternative PHP-like pattern for substitutions:
2205                //      |       dojo.replace("Hello, ${0} ${2}!",
2206                //      |         ["Robert", "X", "Cringely"], /\$\{([^\}]+)\}/g);
2207                //      |       // returns: Hello, Robert Cringely!
2208                return "";      // String
2209        }
2210        =====*/
2211
2212        var _pattern = /\{([^\}]+)\}/g;
2213        dojo.replace = function(tmpl, map, pattern){
2214                return tmpl.replace(pattern || _pattern, d.isFunction(map) ?
2215                        map : function(_, k){ return d.getObject(k, false, map); });
2216        };
2217})();
2218
2219}
2220
2221if(!dojo._hasResource["dojo._base.array"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2222dojo._hasResource["dojo._base.array"] = true;
2223dojo.provide("dojo._base.array");
2224
2225
2226
2227(function(){
2228        var _getParts = function(arr, obj, cb){
2229                return [
2230                        (typeof arr == "string") ? arr.split("") : arr,
2231                        obj || dojo.global,
2232                        // FIXME: cache the anonymous functions we create here?
2233                        (typeof cb == "string") ? new Function("item", "index", "array", cb) : cb
2234                ];
2235        };
2236
2237        var everyOrSome = function(/*Boolean*/every, /*Array|String*/arr, /*Function|String*/callback, /*Object?*/thisObject){
2238                var _p = _getParts(arr, thisObject, callback); arr = _p[0];
2239                for(var i=0,l=arr.length; i<l; ++i){
2240                        var result = !!_p[2].call(_p[1], arr[i], i, arr);
2241                        if(every ^ result){
2242                                return result; // Boolean
2243                        }
2244                }
2245                return every; // Boolean
2246        };
2247
2248        dojo.mixin(dojo, {
2249                indexOf: function(      /*Array*/               array,
2250                                                        /*Object*/              value,
2251                                                        /*Integer?*/    fromIndex,
2252                                                        /*Boolean?*/    findLast){
2253                        // summary:
2254                        //              locates the first index of the provided value in the
2255                        //              passed array. If the value is not found, -1 is returned.
2256                        // description:
2257                        //              This method corresponds to the JavaScript 1.6 Array.indexOf method, with one difference: when
2258                        //              run over sparse arrays, the Dojo function invokes the callback for every index whereas JavaScript
2259                        //              1.6's indexOf skips the holes in the sparse array.
2260                        //              For details on this method, see:
2261                        //                      https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/indexOf
2262
2263                        var step = 1, end = array.length || 0, i = 0;
2264                        if(findLast){
2265                                i = end - 1;
2266                                step = end = -1;
2267                        }
2268                        if(fromIndex != undefined){ i = fromIndex; }
2269                        if((findLast && i > end) || i < end){
2270                                for(; i != end; i += step){
2271                                        if(array[i] == value){ return i; }
2272                                }
2273                        }
2274                        return -1;      // Number
2275                },
2276
2277                lastIndexOf: function(/*Array*/array, /*Object*/value, /*Integer?*/fromIndex){
2278                        // summary:
2279                        //              locates the last index of the provided value in the passed
2280                        //              array. If the value is not found, -1 is returned.
2281                        // description:
2282                        //              This method corresponds to the JavaScript 1.6 Array.lastIndexOf method, with one difference: when
2283                        //              run over sparse arrays, the Dojo function invokes the callback for every index whereas JavaScript
2284                        //              1.6's lastIndexOf skips the holes in the sparse array.
2285                        //              For details on this method, see:
2286                        //                      https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/lastIndexOf
2287                        return dojo.indexOf(array, value, fromIndex, true); // Number
2288                },
2289
2290                forEach: function(/*Array|String*/arr, /*Function|String*/callback, /*Object?*/thisObject){
2291                        //      summary:
2292                        //              for every item in arr, callback is invoked. Return values are ignored.
2293                        //              If you want to break out of the loop, consider using dojo.every() or dojo.some().
2294                        //              forEach does not allow breaking out of the loop over the items in arr.
2295                        //      arr:
2296                        //              the array to iterate over. If a string, operates on individual characters.
2297                        //      callback:
2298                        //              a function is invoked with three arguments: item, index, and array
2299                        //      thisObject:
2300                        //              may be used to scope the call to callback
2301                        //      description:
2302                        //              This function corresponds to the JavaScript 1.6 Array.forEach() method, with one difference: when
2303                        //              run over sparse arrays, this implemenation passes the "holes" in the sparse array to
2304                        //              the callback function with a value of undefined. JavaScript 1.6's forEach skips the holes in the sparse array.
2305                        //              For more details, see:
2306                        //                      https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/forEach
2307                        //      example:
2308                        //      |       // log out all members of the array:
2309                        //      |       dojo.forEach(
2310                        //      |               [ "thinger", "blah", "howdy", 10 ],
2311                        //      |               function(item){
2312                        //      |                       console.log(item);
2313                        //      |               }
2314                        //      |       );
2315                        //      example:
2316                        //      |       // log out the members and their indexes
2317                        //      |       dojo.forEach(
2318                        //      |               [ "thinger", "blah", "howdy", 10 ],
2319                        //      |               function(item, idx, arr){
2320                        //      |                       console.log(item, "at index:", idx);
2321                        //      |               }
2322                        //      |       );
2323                        //      example:
2324                        //      |       // use a scoped object member as the callback
2325                        //      |
2326                        //      |       var obj = {
2327                        //      |               prefix: "logged via obj.callback:",
2328                        //      |               callback: function(item){
2329                        //      |                       console.log(this.prefix, item);
2330                        //      |               }
2331                        //      |       };
2332                        //      |
2333                        //      |       // specifying the scope function executes the callback in that scope
2334                        //      |       dojo.forEach(
2335                        //      |               [ "thinger", "blah", "howdy", 10 ],
2336                        //      |               obj.callback,
2337                        //      |               obj
2338                        //      |       );
2339                        //      |
2340                        //      |       // alternately, we can accomplish the same thing with dojo.hitch()
2341                        //      |       dojo.forEach(
2342                        //      |               [ "thinger", "blah", "howdy", 10 ],
2343                        //      |               dojo.hitch(obj, "callback")
2344                        //      |       );
2345
2346                        // match the behavior of the built-in forEach WRT empty arrs
2347                        if(!arr || !arr.length){ return; }
2348
2349                        // FIXME: there are several ways of handilng thisObject. Is
2350                        // dojo.global always the default context?
2351                        var _p = _getParts(arr, thisObject, callback); arr = _p[0];
2352                        for(var i=0,l=arr.length; i<l; ++i){
2353                                _p[2].call(_p[1], arr[i], i, arr);
2354                        }
2355                },
2356
2357                every: function(/*Array|String*/arr, /*Function|String*/callback, /*Object?*/thisObject){
2358                        // summary:
2359                        //              Determines whether or not every item in arr satisfies the
2360                        //              condition implemented by callback.
2361                        // arr:
2362                        //              the array to iterate on. If a string, operates on individual characters.
2363                        // callback:
2364                        //              a function is invoked with three arguments: item, index,
2365                        //              and array and returns true if the condition is met.
2366                        // thisObject:
2367                        //              may be used to scope the call to callback
2368                        // description:
2369                        //              This function corresponds to the JavaScript 1.6 Array.every() method, with one difference: when
2370                        //              run over sparse arrays, this implemenation passes the "holes" in the sparse array to
2371                        //              the callback function with a value of undefined. JavaScript 1.6's every skips the holes in the sparse array.
2372                        //              For more details, see:
2373                        //                      https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/every
2374                        // example:
2375                        //      |       // returns false
2376                        //      |       dojo.every([1, 2, 3, 4], function(item){ return item>1; });
2377                        // example:
2378                        //      |       // returns true
2379                        //      |       dojo.every([1, 2, 3, 4], function(item){ return item>0; });
2380                        return everyOrSome(true, arr, callback, thisObject); // Boolean
2381                },
2382
2383                some: function(/*Array|String*/arr, /*Function|String*/callback, /*Object?*/thisObject){
2384                        // summary:
2385                        //              Determines whether or not any item in arr satisfies the
2386                        //              condition implemented by callback.
2387                        // arr:
2388                        //              the array to iterate over. If a string, operates on individual characters.
2389                        // callback:
2390                        //              a function is invoked with three arguments: item, index,
2391                        //              and array and returns true if the condition is met.
2392                        // thisObject:
2393                        //              may be used to scope the call to callback
2394                        // description:
2395                        //              This function corresponds to the JavaScript 1.6 Array.some() method, with one difference: when
2396                        //              run over sparse arrays, this implemenation passes the "holes" in the sparse array to
2397                        //              the callback function with a value of undefined. JavaScript 1.6's some skips the holes in the sparse array.
2398                        //              For more details, see:
2399                        //                      https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/some
2400                        // example:
2401                        //      |       // is true
2402                        //      |       dojo.some([1, 2, 3, 4], function(item){ return item>1; });
2403                        // example:
2404                        //      |       // is false
2405                        //      |       dojo.some([1, 2, 3, 4], function(item){ return item<1; });
2406                        return everyOrSome(false, arr, callback, thisObject); // Boolean
2407                },
2408
2409                map: function(/*Array|String*/arr, /*Function|String*/callback, /*Function?*/thisObject){
2410                        // summary:
2411                        //              applies callback to each element of arr and returns
2412                        //              an Array with the results
2413                        // arr:
2414                        //              the array to iterate on. If a string, operates on
2415                        //              individual characters.
2416                        // callback:
2417                        //              a function is invoked with three arguments, (item, index,
2418                        //              array),  and returns a value
2419                        // thisObject:
2420                        //              may be used to scope the call to callback
2421                        // description:
2422                        //              This function corresponds to the JavaScript 1.6 Array.map() method, with one difference: when
2423                        //              run over sparse arrays, this implemenation passes the "holes" in the sparse array to
2424                        //              the callback function with a value of undefined. JavaScript 1.6's map skips the holes in the sparse array.
2425                        //              For more details, see:
2426                        //                      https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
2427                        // example:
2428                        //      |       // returns [2, 3, 4, 5]
2429                        //      |       dojo.map([1, 2, 3, 4], function(item){ return item+1 });
2430
2431                        var _p = _getParts(arr, thisObject, callback); arr = _p[0];
2432                        var outArr = (arguments[3] ? (new arguments[3]()) : []);
2433                        for(var i=0,l=arr.length; i<l; ++i){
2434                                outArr.push(_p[2].call(_p[1], arr[i], i, arr));
2435                        }
2436                        return outArr; // Array
2437                },
2438
2439                filter: function(/*Array*/arr, /*Function|String*/callback, /*Object?*/thisObject){
2440                        // summary:
2441                        //              Returns a new Array with those items from arr that match the
2442                        //              condition implemented by callback.
2443                        // arr:
2444                        //              the array to iterate over.
2445                        // callback:
2446                        //              a function that is invoked with three arguments (item,
2447                        //              index, array). The return of this function is expected to
2448                        //              be a boolean which determines whether the passed-in item
2449                        //              will be included in the returned array.
2450                        // thisObject:
2451                        //              may be used to scope the call to callback
2452                        // description:
2453                        //              This function corresponds to the JavaScript 1.6 Array.filter() method, with one difference: when
2454                        //              run over sparse arrays, this implemenation passes the "holes" in the sparse array to
2455                        //              the callback function with a value of undefined. JavaScript 1.6's filter skips the holes in the sparse array.
2456                        //              For more details, see:
2457                        //                      https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
2458                        // example:
2459                        //      |       // returns [2, 3, 4]
2460                        //      |       dojo.filter([1, 2, 3, 4], function(item){ return item>1; });
2461
2462                        var _p = _getParts(arr, thisObject, callback); arr = _p[0];
2463                        var outArr = [];
2464                        for(var i=0,l=arr.length; i<l; ++i){
2465                                if(_p[2].call(_p[1], arr[i], i, arr)){
2466                                        outArr.push(arr[i]);
2467                                }
2468                        }
2469                        return outArr; // Array
2470                }
2471        });
2472})();
2473/*
2474*/
2475
2476}
2477
2478if(!dojo._hasResource["dojo._base.declare"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2479dojo._hasResource["dojo._base.declare"] = true;
2480dojo.provide("dojo._base.declare");
2481
2482
2483
2484
2485(function(){
2486        var d = dojo, mix = d._mixin, op = Object.prototype, opts = op.toString,
2487                xtor = new Function, counter = 0, cname = "constructor";
2488
2489        function err(msg, cls){ throw new Error("declare" + (cls ? " " + cls : "") + ": " + msg); }
2490
2491        // C3 Method Resolution Order (see http://www.python.org/download/releases/2.3/mro/)
2492        function c3mro(bases, className){
2493                var result = [], roots = [{cls: 0, refs: []}], nameMap = {}, clsCount = 1,
2494                        l = bases.length, i = 0, j, lin, base, top, proto, rec, name, refs;
2495
2496                // build a list of bases naming them if needed
2497                for(; i < l; ++i){
2498                        base = bases[i];
2499                        if(!base){
2500                                err("mixin #" + i + " is unknown. Did you use dojo.require to pull it in?", className);
2501                        }else if(opts.call(base) != "[object Function]"){
2502                                err("mixin #" + i + " is not a callable constructor.", className);
2503                        }
2504                        lin = base._meta ? base._meta.bases : [base];
2505                        top = 0;
2506                        // add bases to the name map
2507                        for(j = lin.length - 1; j >= 0; --j){
2508                                proto = lin[j].prototype;
2509                                if(!proto.hasOwnProperty("declaredClass")){
2510                                        proto.declaredClass = "uniqName_" + (counter++);
2511                                }
2512                                name = proto.declaredClass;
2513                                if(!nameMap.hasOwnProperty(name)){
2514                                        nameMap[name] = {count: 0, refs: [], cls: lin[j]};
2515                                        ++clsCount;
2516                                }
2517                                rec = nameMap[name];
2518                                if(top && top !== rec){
2519                                        rec.refs.push(top);
2520                                        ++top.count;
2521                                }
2522                                top = rec;
2523                        }
2524                        ++top.count;
2525                        roots[0].refs.push(top);
2526                }
2527
2528                // remove classes without external references recursively
2529                while(roots.length){
2530                        top = roots.pop();
2531                        result.push(top.cls);
2532                        --clsCount;
2533                        // optimization: follow a single-linked chain
2534                        while(refs = top.refs, refs.length == 1){
2535                                top = refs[0];
2536                                if(!top || --top.count){
2537                                        // branch or end of chain => do not end to roots
2538                                        top = 0;
2539                                        break;
2540                                }
2541                                result.push(top.cls);
2542                                --clsCount;
2543                        }
2544                        if(top){
2545                                // branch
2546                                for(i = 0, l = refs.length; i < l; ++i){
2547                                        top = refs[i];
2548                                        if(!--top.count){
2549                                                roots.push(top);
2550                                        }
2551                                }
2552                        }
2553                }
2554                if(clsCount){
2555                        err("can't build consistent linearization", className);
2556                }
2557
2558                // calculate the superclass offset
2559                base = bases[0];
2560                result[0] = base ?
2561                        base._meta && base === result[result.length - base._meta.bases.length] ?
2562                                base._meta.bases.length : 1 : 0;
2563
2564                return result;
2565        }
2566
2567        function inherited(args, a, f){
2568                var name, chains, bases, caller, meta, base, proto, opf, pos,
2569                        cache = this._inherited = this._inherited || {};
2570
2571                // crack arguments
2572                if(typeof args == "string"){
2573                        name = args;
2574                        args = a;
2575                        a = f;
2576                }
2577                f = 0;
2578
2579                caller = args.callee;
2580                name = name || caller.nom;
2581                if(!name){
2582                        err("can't deduce a name to call inherited()", this.declaredClass);
2583                }
2584
2585                meta = this.constructor._meta;
2586                bases = meta.bases;
2587
2588                pos = cache.p;
2589                if(name != cname){
2590                        // method
2591                        if(cache.c !== caller){
2592                                // cache bust
2593                                pos = 0;
2594                                base = bases[0];
2595                                meta = base._meta;
2596                                if(meta.hidden[name] !== caller){
2597                                        // error detection
2598                                        chains = meta.chains;
2599                                        if(chains && typeof chains[name] == "string"){
2600                                                err("calling chained method with inherited: " + name, this.declaredClass);
2601                                        }
2602                                        // find caller
2603                                        do{
2604                                                meta = base._meta;
2605                                                proto = base.prototype;
2606                                                if(meta && (proto[name] === caller && proto.hasOwnProperty(name) || meta.hidden[name] === caller)){
2607                                                        break;
2608                                                }
2609                                        }while(base = bases[++pos]); // intentional assignment
2610                                        pos = base ? pos : -1;
2611                                }
2612                        }
2613                        // find next
2614                        base = bases[++pos];
2615                        if(base){
2616                                proto = base.prototype;
2617                                if(base._meta && proto.hasOwnProperty(name)){
2618                                        f = proto[name];
2619                                }else{
2620                                        opf = op[name];
2621                                        do{
2622                                                proto = base.prototype;
2623                                                f = proto[name];
2624                                                if(f && (base._meta ? proto.hasOwnProperty(name) : f !== opf)){
2625                                                        break;
2626                                                }
2627                                        }while(base = bases[++pos]); // intentional assignment
2628                                }
2629                        }
2630                        f = base && f || op[name];
2631                }else{
2632                        // constructor
2633                        if(cache.c !== caller){
2634                                // cache bust
2635                                pos = 0;
2636                                meta = bases[0]._meta;
2637                                if(meta && meta.ctor !== caller){
2638                                        // error detection
2639                                        chains = meta.chains;
2640                                        if(!chains || chains.constructor !== "manual"){
2641                                                err("calling chained constructor with inherited", this.declaredClass);
2642                                        }
2643                                        // find caller
2644                                        while(base = bases[++pos]){ // intentional assignment
2645                                                meta = base._meta;
2646                                                if(meta && meta.ctor === caller){
2647                                                        break;
2648                                                }
2649                                        }
2650                                        pos = base ? pos : -1;
2651                                }
2652                        }
2653                        // find next
2654                        while(base = bases[++pos]){     // intentional assignment
2655                                meta = base._meta;
2656                                f = meta ? meta.ctor : base;
2657                                if(f){
2658                                        break;
2659                                }
2660                        }
2661                        f = base && f;
2662                }
2663
2664                // cache the found super method
2665                cache.c = f;
2666                cache.p = pos;
2667
2668                // now we have the result
2669                if(f){
2670                        return a === true ? f : f.apply(this, a || args);
2671                }
2672                // intentionally if a super method was not found
2673        }
2674
2675        function getInherited(name, args){
2676                if(typeof name == "string"){
2677                        return this.inherited(name, args, true);
2678                }
2679                return this.inherited(name, true);
2680        }
2681
2682        // emulation of "instanceof"
2683        function isInstanceOf(cls){
2684                var bases = this.constructor._meta.bases;
2685                for(var i = 0, l = bases.length; i < l; ++i){
2686                        if(bases[i] === cls){
2687                                return true;
2688                        }
2689                }
2690                return this instanceof cls;
2691        }
2692
2693        function mixOwn(target, source){
2694                var name, i = 0, l = d._extraNames.length;
2695                // add props adding metadata for incoming functions skipping a constructor
2696                for(name in source){
2697                        if(name != cname && source.hasOwnProperty(name)){
2698                                target[name] = source[name];
2699                        }
2700                }
2701                // process unenumerable methods on IE
2702                for(; i < l; ++i){
2703                        name = d._extraNames[i];
2704                        if(name != cname && source.hasOwnProperty(name)){
2705                                target[name] = source[name];
2706                        }
2707                }
2708        }
2709
2710        // implementation of safe mixin function
2711        function safeMixin(target, source){
2712                var name, t, i = 0, l = d._extraNames.length;
2713                // add props adding metadata for incoming functions skipping a constructor
2714                for(name in source){
2715                        t = source[name];
2716                        if((t !== op[name] || !(name in op)) && name != cname){
2717                                if(opts.call(t) == "[object Function]"){
2718                                        // non-trivial function method => attach its name
2719                                        t.nom = name;
2720                                }
2721                                target[name] = t;
2722                        }
2723                }
2724                // process unenumerable methods on IE
2725                for(; i < l; ++i){
2726                        name = d._extraNames[i];
2727                        t = source[name];
2728                        if((t !== op[name] || !(name in op)) && name != cname){
2729                                if(opts.call(t) == "[object Function]"){
2730                                        // non-trivial function method => attach its name
2731                                        t.nom = name;
2732                                }
2733                                target[name] = t;
2734                        }
2735                }
2736                return target;
2737        }
2738
2739        function extend(source){
2740                safeMixin(this.prototype, source);
2741                return this;
2742        }
2743
2744        // chained constructor compatible with the legacy dojo.declare()
2745        function chainedConstructor(bases, ctorSpecial){
2746                return function(){
2747                        var a = arguments, args = a, a0 = a[0], f, i, m,
2748                                l = bases.length, preArgs;
2749
2750                        if(!(this instanceof a.callee)){
2751                                // not called via new, so force it
2752                                return applyNew(a);
2753                        }
2754
2755                        //this._inherited = {};
2756                        // perform the shaman's rituals of the original dojo.declare()
2757                        // 1) call two types of the preamble
2758                        if(ctorSpecial && (a0 && a0.preamble || this.preamble)){
2759                                // full blown ritual
2760                                preArgs = new Array(bases.length);
2761                                // prepare parameters
2762                                preArgs[0] = a;
2763                                for(i = 0;;){
2764                                        // process the preamble of the 1st argument
2765                                        a0 = a[0];
2766                                        if(a0){
2767                                                f = a0.preamble;
2768                                                if(f){
2769                                                        a = f.apply(this, a) || a;
2770                                                }
2771                                        }
2772                                        // process the preamble of this class
2773                                        f = bases[i].prototype;
2774                                        f = f.hasOwnProperty("preamble") && f.preamble;
2775                                        if(f){
2776                                                a = f.apply(this, a) || a;
2777                                        }
2778                                        // one peculiarity of the preamble:
2779                                        // it is called if it is not needed,
2780                                        // e.g., there is no constructor to call
2781                                        // let's watch for the last constructor
2782                                        // (see ticket #9795)
2783                                        if(++i == l){
2784                                                break;
2785                                        }
2786                                        preArgs[i] = a;
2787                                }
2788                        }
2789                        // 2) call all non-trivial constructors using prepared arguments
2790                        for(i = l - 1; i >= 0; --i){
2791                                f = bases[i];
2792                                m = f._meta;
2793                                f = m ? m.ctor : f;
2794                                if(f){
2795                                        f.apply(this, preArgs ? preArgs[i] : a);
2796                                }
2797                        }
2798                        // 3) continue the original ritual: call the postscript
2799                        f = this.postscript;
2800                        if(f){
2801                                f.apply(this, args);
2802                        }
2803                };
2804        }
2805
2806
2807        // chained constructor compatible with the legacy dojo.declare()
2808        function singleConstructor(ctor, ctorSpecial){
2809                return function(){
2810                        var a = arguments, t = a, a0 = a[0], f;
2811
2812                        if(!(this instanceof a.callee)){
2813                                // not called via new, so force it
2814                                return applyNew(a);
2815                        }
2816
2817                        //this._inherited = {};
2818                        // perform the shaman's rituals of the original dojo.declare()
2819                        // 1) call two types of the preamble
2820                        if(ctorSpecial){
2821                                // full blown ritual
2822                                if(a0){
2823                                        // process the preamble of the 1st argument
2824                                        f = a0.preamble;
2825                                        if(f){
2826                                                t = f.apply(this, t) || t;
2827                                        }
2828                                }
2829                                f = this.preamble;
2830                                if(f){
2831                                        // process the preamble of this class
2832                                        f.apply(this, t);
2833                                        // one peculiarity of the preamble:
2834                                        // it is called even if it is not needed,
2835                                        // e.g., there is no constructor to call
2836                                        // let's watch for the last constructor
2837                                        // (see ticket #9795)
2838                                }
2839                        }
2840                        // 2) call a constructor
2841                        if(ctor){
2842                                ctor.apply(this, a);
2843                        }
2844                        // 3) continue the original ritual: call the postscript
2845                        f = this.postscript;
2846                        if(f){
2847                                f.apply(this, a);
2848                        }
2849                };
2850        }
2851
2852        // plain vanilla constructor (can use inherited() to call its base constructor)
2853        function simpleConstructor(bases){
2854                return function(){
2855                        var a = arguments, i = 0, f, m;
2856
2857                        if(!(this instanceof a.callee)){
2858                                // not called via new, so force it
2859                                return applyNew(a);
2860                        }
2861
2862                        //this._inherited = {};
2863                        // perform the shaman's rituals of the original dojo.declare()
2864                        // 1) do not call the preamble
2865                        // 2) call the top constructor (it can use this.inherited())
2866                        for(; f = bases[i]; ++i){ // intentional assignment
2867                                m = f._meta;
2868                                f = m ? m.ctor : f;
2869                                if(f){
2870                                        f.apply(this, a);
2871                                        break;
2872                                }
2873                        }
2874                        // 3) call the postscript
2875                        f = this.postscript;
2876                        if(f){
2877                                f.apply(this, a);
2878                        }
2879                };
2880        }
2881
2882        function chain(name, bases, reversed){
2883                return function(){
2884                        var b, m, f, i = 0, step = 1;
2885                        if(reversed){
2886                                i = bases.length - 1;
2887                                step = -1;
2888                        }
2889                        for(; b = bases[i]; i += step){ // intentional assignment
2890                                m = b._meta;
2891                                f = (m ? m.hidden : b.prototype)[name];
2892                                if(f){
2893                                        f.apply(this, arguments);
2894                                }
2895                        }
2896                };
2897        }
2898
2899        // forceNew(ctor)
2900        // return a new object that inherits from ctor.prototype but
2901        // without actually running ctor on the object.
2902        function forceNew(ctor){
2903                // create object with correct prototype using a do-nothing
2904                // constructor
2905                xtor.prototype = ctor.prototype;
2906                var t = new xtor;
2907                xtor.prototype = null;  // clean up
2908                return t;
2909        }
2910
2911        // applyNew(args)
2912        // just like 'new ctor()' except that the constructor and its arguments come
2913        // from args, which must be an array or an arguments object
2914        function applyNew(args){
2915                // create an object with ctor's prototype but without
2916                // calling ctor on it.
2917                var ctor = args.callee, t = forceNew(ctor);
2918                // execute the real constructor on the new object
2919                ctor.apply(t, args);
2920                return t;
2921        }
2922
2923        d.declare = function(className, superclass, props){
2924                // crack parameters
2925                if(typeof className != "string"){
2926                        props = superclass;
2927                        superclass = className;
2928                        className = "";
2929                }
2930                props = props || {};
2931
2932                var proto, i, t, ctor, name, bases, chains, mixins = 1, parents = superclass;
2933
2934                // build a prototype
2935                if(opts.call(superclass) == "[object Array]"){
2936                        // C3 MRO
2937                        bases = c3mro(superclass, className);
2938                        t = bases[0];
2939                        mixins = bases.length - t;
2940                        superclass = bases[mixins];
2941                }else{
2942                        bases = [0];
2943                        if(superclass){
2944                                if(opts.call(superclass) == "[object Function]"){
2945                                        t = superclass._meta;
2946                                        bases = bases.concat(t ? t.bases : superclass);
2947                                }else{
2948                                        err("base class is not a callable constructor.", className);
2949                                }
2950                        }else if(superclass !== null){
2951                                err("unknown base class. Did you use dojo.require to pull it in?", className);
2952                        }
2953                }
2954                if(superclass){
2955                        for(i = mixins - 1;; --i){
2956                                proto = forceNew(superclass);
2957                                if(!i){
2958                                        // stop if nothing to add (the last base)
2959                                        break;
2960                                }
2961                                // mix in properties
2962                                t = bases[i];
2963                                (t._meta ? mixOwn : mix)(proto, t.prototype);
2964                                // chain in new constructor
2965                                ctor = new Function;
2966                                ctor.superclass = superclass;
2967                                ctor.prototype = proto;
2968                                superclass = proto.constructor = ctor;
2969                        }
2970                }else{
2971                        proto = {};
2972                }
2973                // add all properties
2974                safeMixin(proto, props);
2975                // add constructor
2976                t = props.constructor;
2977                if(t !== op.constructor){
2978                        t.nom = cname;
2979                        proto.constructor = t;
2980                }
2981
2982                // collect chains and flags
2983                for(i = mixins - 1; i; --i){ // intentional assignment
2984                        t = bases[i]._meta;
2985                        if(t && t.chains){
2986                                chains = mix(chains || {}, t.chains);
2987                        }
2988                }
2989                if(proto["-chains-"]){
2990                        chains = mix(chains || {}, proto["-chains-"]);
2991                }
2992
2993                // build ctor
2994                t = !chains || !chains.hasOwnProperty(cname);
2995                bases[0] = ctor = (chains && chains.constructor === "manual") ? simpleConstructor(bases) :
2996                        (bases.length == 1 ? singleConstructor(props.constructor, t) : chainedConstructor(bases, t));
2997
2998                // add meta information to the constructor
2999                ctor._meta  = {bases: bases, hidden: props, chains: chains,
3000                        parents: parents, ctor: props.constructor};
3001                ctor.superclass = superclass && superclass.prototype;
3002                ctor.extend = extend;
3003                ctor.prototype = proto;
3004                proto.constructor = ctor;
3005
3006                // add "standard" methods to the prototype
3007                proto.getInherited = getInherited;
3008                proto.inherited = inherited;
3009                proto.isInstanceOf = isInstanceOf;
3010
3011                // add name if specified
3012                if(className){
3013                        proto.declaredClass = className;
3014                        d.setObject(className, ctor);
3015                }
3016
3017                // build chains and add them to the prototype
3018                if(chains){
3019                        for(name in chains){
3020                                if(proto[name] && typeof chains[name] == "string" && name != cname){
3021                                        t = proto[name] = chain(name, bases, chains[name] === "after");
3022                                        t.nom = name;
3023                                }
3024                        }
3025                }
3026                // chained methods do not return values
3027                // no need to chain "invisible" functions
3028
3029                return ctor;    // Function
3030        };
3031
3032        d.safeMixin = safeMixin;
3033
3034        /*=====
3035        dojo.declare = function(className, superclass, props){
3036                //      summary:
3037                //              Create a feature-rich constructor from compact notation.
3038                //      className: String?:
3039                //              The optional name of the constructor (loosely, a "class")
3040                //              stored in the "declaredClass" property in the created prototype.
3041                //              It will be used as a global name for a created constructor.
3042                //      superclass: Function|Function[]:
3043                //              May be null, a Function, or an Array of Functions. This argument
3044                //              specifies a list of bases (the left-most one is the most deepest
3045                //              base).
3046                //      props: Object:
3047                //              An object whose properties are copied to the created prototype.
3048                //              Add an instance-initialization function by making it a property
3049                //              named "constructor".
3050                //      returns:
3051                //              New constructor function.
3052                //      description:
3053                //              Create a constructor using a compact notation for inheritance and
3054                //              prototype extension.
3055                //
3056                //              Mixin ancestors provide a type of multiple inheritance.
3057                //              Prototypes of mixin ancestors are copied to the new class:
3058                //              changes to mixin prototypes will not affect classes to which
3059                //              they have been mixed in.
3060                //
3061                //              Ancestors can be compound classes created by this version of
3062                //              dojo.declare. In complex cases all base classes are going to be
3063                //              linearized according to C3 MRO algorithm
3064                //              (see http://www.python.org/download/releases/2.3/mro/ for more
3065                //              details).
3066                //
3067                //              "className" is cached in "declaredClass" property of the new class,
3068                //              if it was supplied. The immediate super class will be cached in
3069                //              "superclass" property of the new class.
3070                //
3071                //              Methods in "props" will be copied and modified: "nom" property
3072                //              (the declared name of the method) will be added to all copied
3073                //              functions to help identify them for the internal machinery. Be
3074                //              very careful, while reusing methods: if you use the same
3075                //              function under different names, it can produce errors in some
3076                //              cases.
3077                //
3078                //              It is possible to use constructors created "manually" (without
3079                //              dojo.declare) as bases. They will be called as usual during the
3080                //              creation of an instance, their methods will be chained, and even
3081                //              called by "this.inherited()".
3082                //
3083                //              Special property "-chains-" governs how to chain methods. It is
3084                //              a dictionary, which uses method names as keys, and hint strings
3085                //              as values. If a hint string is "after", this method will be
3086                //              called after methods of its base classes. If a hint string is
3087                //              "before", this method will be called before methods of its base
3088                //              classes.
3089                //
3090                //              If "constructor" is not mentioned in "-chains-" property, it will
3091                //              be chained using the legacy mode: using "after" chaining,
3092                //              calling preamble() method before each constructor, if available,
3093                //              and calling postscript() after all constructors were executed.
3094                //              If the hint is "after", it is chained as a regular method, but
3095                //              postscript() will be called after the chain of constructors.
3096                //              "constructor" cannot be chained "before", but it allows
3097                //              a special hint string: "manual", which means that constructors
3098                //              are not going to be chained in any way, and programmer will call
3099                //              them manually using this.inherited(). In the latter case
3100                //              postscript() will be called after the construction.
3101                //
3102                //              All chaining hints are "inherited" from base classes and
3103                //              potentially can be overridden. Be very careful when overriding
3104                //              hints! Make sure that all chained methods can work in a proposed
3105                //              manner of chaining.
3106                //
3107                //              Once a method was chained, it is impossible to unchain it. The
3108                //              only exception is "constructor". You don't need to define a
3109                //              method in order to supply a chaining hint.
3110                //
3111                //              If a method is chained, it cannot use this.inherited() because
3112                //              all other methods in the hierarchy will be called automatically.
3113                //
3114                //              Usually constructors and initializers of any kind are chained
3115                //              using "after" and destructors of any kind are chained as
3116                //              "before". Note that chaining assumes that chained methods do not
3117                //              return any value: any returned value will be discarded.
3118                //
3119                //      example:
3120                //      |       dojo.declare("my.classes.bar", my.classes.foo, {
3121                //      |               // properties to be added to the class prototype
3122                //      |               someValue: 2,
3123                //      |               // initialization function
3124                //      |               constructor: function(){
3125                //      |                       this.myComplicatedObject = new ReallyComplicatedObject();
3126                //      |               },
3127                //      |               // other functions
3128                //      |               someMethod: function(){
3129                //      |                       doStuff();
3130                //      |               }
3131                //      |       });
3132                //
3133                //      example:
3134                //      |       var MyBase = dojo.declare(null, {
3135                //      |               // constructor, properties, and methods go here
3136                //      |               // ...
3137                //      |       });
3138                //      |       var MyClass1 = dojo.declare(MyBase, {
3139                //      |               // constructor, properties, and methods go here
3140                //      |               // ...
3141                //      |       });
3142                //      |       var MyClass2 = dojo.declare(MyBase, {
3143                //      |               // constructor, properties, and methods go here
3144                //      |               // ...
3145                //      |       });
3146                //      |       var MyDiamond = dojo.declare([MyClass1, MyClass2], {
3147                //      |               // constructor, properties, and methods go here
3148                //      |               // ...
3149                //      |       });
3150                //
3151                //      example:
3152                //      |       var F = function(){ console.log("raw constructor"); };
3153                //      |       F.prototype.method = function(){
3154                //      |               console.log("raw method");
3155                //      |       };
3156                //      |       var A = dojo.declare(F, {
3157                //      |               constructor: function(){
3158                //      |                       console.log("A.constructor");
3159                //      |               },
3160                //      |               method: function(){
3161                //      |                       console.log("before calling F.method...");
3162                //      |                       this.inherited(arguments);
3163                //      |                       console.log("...back in A");
3164                //      |               }
3165                //      |       });
3166                //      |       new A().method();
3167                //      |       // will print:
3168                //      |       // raw constructor
3169                //      |       // A.constructor
3170                //      |       // before calling F.method...
3171                //      |       // raw method
3172                //      |       // ...back in A
3173                //
3174                //      example:
3175                //      |       var A = dojo.declare(null, {
3176                //      |               "-chains-": {
3177                //      |                       destroy: "before"
3178                //      |               }
3179                //      |       });
3180                //      |       var B = dojo.declare(A, {
3181                //      |               constructor: function(){
3182                //      |                       console.log("B.constructor");
3183                //      |               },
3184                //      |               destroy: function(){
3185                //      |                       console.log("B.destroy");
3186                //      |               }
3187                //      |       });
3188                //      |       var C = dojo.declare(B, {
3189                //      |               constructor: function(){
3190                //      |                       console.log("C.constructor");
3191                //      |               },
3192                //      |               destroy: function(){
3193                //      |                       console.log("C.destroy");
3194                //      |               }
3195                //      |       });
3196                //      |       new C().destroy();
3197                //      |       // prints:
3198                //      |       // B.constructor
3199                //      |       // C.constructor
3200                //      |       // C.destroy
3201                //      |       // B.destroy
3202                //
3203                //      example:
3204                //      |       var A = dojo.declare(null, {
3205                //      |               "-chains-": {
3206                //      |                       constructor: "manual"
3207                //      |               }
3208                //      |       });
3209                //      |       var B = dojo.declare(A, {
3210                //      |               constructor: function(){
3211                //      |                       // ...
3212                //      |                       // call the base constructor with new parameters
3213                //      |                       this.inherited(arguments, [1, 2, 3]);
3214                //      |                       // ...
3215                //      |               }
3216                //      |       });
3217                //
3218                //      example:
3219                //      |       var A = dojo.declare(null, {
3220                //      |               "-chains-": {
3221                //      |                       m1: "before"
3222                //      |               },
3223                //      |               m1: function(){
3224                //      |                       console.log("A.m1");
3225                //      |               },
3226                //      |               m2: function(){
3227                //      |                       console.log("A.m2");
3228                //      |               }
3229                //      |       });
3230                //      |       var B = dojo.declare(A, {
3231                //      |               "-chains-": {
3232                //      |                       m2: "after"
3233                //      |               },
3234                //      |               m1: function(){
3235                //      |                       console.log("B.m1");
3236                //      |               },
3237                //      |               m2: function(){
3238                //      |                       console.log("B.m2");
3239                //      |               }
3240                //      |       });
3241                //      |       var x = new B();
3242                //      |       x.m1();
3243                //      |       // prints:
3244                //      |       // B.m1
3245                //      |       // A.m1
3246                //      |       x.m2();
3247                //      |       // prints:
3248                //      |       // A.m2
3249                //      |       // B.m2
3250                return new Function(); // Function
3251        };
3252        =====*/
3253
3254        /*=====
3255        dojo.safeMixin = function(target, source){
3256                //      summary:
3257                //              Mix in properties skipping a constructor and decorating functions
3258                //              like it is done by dojo.declare.
3259                //      target: Object
3260                //              Target object to accept new properties.
3261                //      source: Object
3262                //              Source object for new properties.
3263                //      description:
3264                //              This function is used to mix in properties like dojo._mixin does,
3265                //              but it skips a constructor property and decorates functions like
3266                //              dojo.declare does.
3267                //
3268                //              It is meant to be used with classes and objects produced with
3269                //              dojo.declare. Functions mixed in with dojo.safeMixin can use
3270                //              this.inherited() like normal methods.
3271                //
3272                //              This function is used to implement extend() method of a constructor
3273                //              produced with dojo.declare().
3274                //
3275                //      example:
3276                //      |       var A = dojo.declare(null, {
3277                //      |               m1: function(){
3278                //      |                       console.log("A.m1");
3279                //      |               },
3280                //      |               m2: function(){
3281                //      |                       console.log("A.m2");
3282                //      |               }
3283                //      |       });
3284                //      |       var B = dojo.declare(A, {
3285                //      |               m1: function(){
3286                //      |                       this.inherited(arguments);
3287                //      |                       console.log("B.m1");
3288                //      |               }
3289                //      |       });
3290                //      |       B.extend({
3291                //      |               m2: function(){
3292                //      |                       this.inherited(arguments);
3293                //      |                       console.log("B.m2");
3294                //      |               }
3295                //      |       });
3296                //      |       var x = new B();
3297                //      |       dojo.safeMixin(x, {
3298                //      |               m1: function(){
3299                //      |                       this.inherited(arguments);
3300                //      |                       console.log("X.m1");
3301                //      |               },
3302                //      |               m2: function(){
3303                //      |                       this.inherited(arguments);
3304                //      |                       console.log("X.m2");
3305                //      |               }
3306                //      |       });
3307                //      |       x.m2();
3308                //      |       // prints:
3309                //      |       // A.m1
3310                //      |       // B.m1
3311                //      |       // X.m1
3312        };
3313        =====*/
3314
3315        /*=====
3316        Object.inherited = function(name, args, newArgs){
3317                //      summary:
3318                //              Calls a super method.
3319                //      name: String?
3320                //              The optional method name. Should be the same as the caller's
3321                //              name. Usually "name" is specified in complex dynamic cases, when
3322                //              the calling method was dynamically added, undecorated by
3323                //              dojo.declare, and it cannot be determined.
3324                //      args: Arguments
3325                //              The caller supply this argument, which should be the original
3326                //              "arguments".
3327                //      newArgs: Object?
3328                //              If "true", the found function will be returned without
3329                //              executing it.
3330                //              If Array, it will be used to call a super method. Otherwise
3331                //              "args" will be used.
3332                //      returns:
3333                //              Whatever is returned by a super method, or a super method itself,
3334                //              if "true" was specified as newArgs.
3335                //      description:
3336                //              This method is used inside method of classes produced with
3337                //              dojo.declare to call a super method (next in the chain). It is
3338                //              used for manually controlled chaining. Consider using the regular
3339                //              chaining, because it is faster. Use "this.inherited()" only in
3340                //              complex cases.
3341                //
3342                //              This method cannot me called from automatically chained
3343                //              constructors including the case of a special (legacy)
3344                //              constructor chaining. It cannot be called from chained methods.
3345                //
3346                //              If "this.inherited()" cannot find the next-in-chain method, it
3347                //              does nothing and returns "undefined". The last method in chain
3348                //              can be a default method implemented in Object, which will be
3349                //              called last.
3350                //
3351                //              If "name" is specified, it is assumed that the method that
3352                //              received "args" is the parent method for this call. It is looked
3353                //              up in the chain list and if it is found the next-in-chain method
3354                //              is called. If it is not found, the first-in-chain method is
3355                //              called.
3356                //
3357                //              If "name" is not specified, it will be derived from the calling
3358                //              method (using a methoid property "nom").
3359                //
3360                //      example:
3361                //      |       var B = dojo.declare(A, {
3362                //      |               method1: function(a, b, c){
3363                //      |                       this.inherited(arguments);
3364                //      |               },
3365                //      |               method2: function(a, b){
3366                //      |                       return this.inherited(arguments, [a + b]);
3367                //      |               }
3368                //      |       });
3369                //      |       // next method is not in the chain list because it is added
3370                //      |       // manually after the class was created.
3371                //      |       B.prototype.method3 = function(){
3372                //      |               console.log("This is a dynamically-added method.");
3373                //      |               this.inherited("method3", arguments);
3374                //      |       };
3375                //      example:
3376                //      |       var B = dojo.declare(A, {
3377                //      |               method: function(a, b){
3378                //      |                       var super = this.inherited(arguments, true);
3379                //      |                       // ...
3380                //      |                       if(!super){
3381                //      |                               console.log("there is no super method");
3382                //      |                               return 0;
3383                //      |                       }
3384                //      |                       return super.apply(this, arguments);
3385                //      |               }
3386                //      |       });
3387                return  {};     // Object
3388        }
3389        =====*/
3390
3391        /*=====
3392        Object.getInherited = function(name, args){
3393                //      summary:
3394                //              Returns a super method.
3395                //      name: String?
3396                //              The optional method name. Should be the same as the caller's
3397                //              name. Usually "name" is specified in complex dynamic cases, when
3398                //              the calling method was dynamically added, undecorated by
3399                //              dojo.declare, and it cannot be determined.
3400                //      args: Arguments
3401                //              The caller supply this argument, which should be the original
3402                //              "arguments".
3403                //      returns:
3404                //              Returns a super method (Function) or "undefined".
3405                //      description:
3406                //              This method is a convenience method for "this.inherited()".
3407                //              It uses the same algorithm but instead of executing a super
3408                //              method, it returns it, or "undefined" if not found.
3409                //
3410                //      example:
3411                //      |       var B = dojo.declare(A, {
3412                //      |               method: function(a, b){
3413                //      |                       var super = this.getInherited(arguments);
3414                //      |                       // ...
3415                //      |                       if(!super){
3416                //      |                               console.log("there is no super method");
3417                //      |                               return 0;
3418                //      |                       }
3419                //      |                       return super.apply(this, arguments);
3420                //      |               }
3421                //      |       });
3422                return  {};     // Object
3423        }
3424        =====*/
3425
3426        /*=====
3427        Object.isInstanceOf = function(cls){
3428                //      summary:
3429                //              Checks the inheritance chain to see if it is inherited from this
3430                //              class.
3431                //      cls: Function
3432                //              Class constructor.
3433                //      returns:
3434                //              "true", if this object is inherited from this class, "false"
3435                //              otherwise.
3436                //      description:
3437                //              This method is used with instances of classes produced with
3438                //              dojo.declare to determine of they support a certain interface or
3439                //              not. It models "instanceof" operator.
3440                //
3441                //      example:
3442                //      |       var A = dojo.declare(null, {
3443                //      |               // constructor, properties, and methods go here
3444                //      |               // ...
3445                //      |       });
3446                //      |       var B = dojo.declare(null, {
3447                //      |               // constructor, properties, and methods go here
3448                //      |               // ...
3449                //      |       });
3450                //      |       var C = dojo.declare([A, B], {
3451                //      |               // constructor, properties, and methods go here
3452                //      |               // ...
3453                //      |       });
3454                //      |       var D = dojo.declare(A, {
3455                //      |               // constructor, properties, and methods go here
3456                //      |               // ...
3457                //      |       });
3458                //      |
3459                //      |       var a = new A(), b = new B(), c = new C(), d = new D();
3460                //      |
3461                //      |       console.log(a.isInstanceOf(A)); // true
3462                //      |       console.log(b.isInstanceOf(A)); // false
3463                //      |       console.log(c.isInstanceOf(A)); // true
3464                //      |       console.log(d.isInstanceOf(A)); // true
3465                //      |
3466                //      |       console.log(a.isInstanceOf(B)); // false
3467                //      |       console.log(b.isInstanceOf(B)); // true
3468                //      |       console.log(c.isInstanceOf(B)); // true
3469                //      |       console.log(d.isInstanceOf(B)); // false
3470                //      |
3471                //      |       console.log(a.isInstanceOf(C)); // false
3472                //      |       console.log(b.isInstanceOf(C)); // false
3473                //      |       console.log(c.isInstanceOf(C)); // true
3474                //      |       console.log(d.isInstanceOf(C)); // false
3475                //      |
3476                //      |       console.log(a.isInstanceOf(D)); // false
3477                //      |       console.log(b.isInstanceOf(D)); // false
3478                //      |       console.log(c.isInstanceOf(D)); // false
3479                //      |       console.log(d.isInstanceOf(D)); // true
3480                return  {};     // Object
3481        }
3482        =====*/
3483
3484        /*=====
3485        Object.extend = function(source){
3486                //      summary:
3487                //              Adds all properties and methods of source to constructor's
3488                //              prototype, making them available to all instances created with
3489                //              constructor. This method is specific to constructors created with
3490                //              dojo.declare.
3491                //      source: Object
3492                //              Source object which properties are going to be copied to the
3493                //              constructor's prototype.
3494                //      description:
3495                //              Adds source properties to the constructor's prototype. It can
3496                //              override existing properties.
3497                //
3498                //              This method is similar to dojo.extend function, but it is specific
3499                //              to constructors produced by dojo.declare. It is implemented
3500                //              using dojo.safeMixin, and it skips a constructor property,
3501                //              and properly decorates copied functions.
3502                //
3503                //      example:
3504                //      |       var A = dojo.declare(null, {
3505                //      |               m1: function(){},
3506                //      |               s1: "Popokatepetl"
3507                //      |       });
3508                //      |       A.extend({
3509                //      |               m1: function(){},
3510                //      |               m2: function(){},
3511                //      |               f1: true,
3512                //      |               d1: 42
3513                //      |       });
3514        };
3515        =====*/
3516})();
3517
3518}
3519
3520if(!dojo._hasResource["dojo._base.connect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
3521dojo._hasResource["dojo._base.connect"] = true;
3522dojo.provide("dojo._base.connect");
3523
3524
3525
3526// this file courtesy of the TurboAjax Group, licensed under a Dojo CLA
3527
3528// low-level delegation machinery
3529dojo._listener = {
3530        // create a dispatcher function
3531        getDispatcher: function(){
3532                // following comments pulled out-of-line to prevent cloning them
3533                // in the returned function.
3534                // - indices (i) that are really in the array of listeners (ls) will
3535                //   not be in Array.prototype. This is the 'sparse array' trick
3536                //   that keeps us safe from libs that take liberties with built-in
3537                //   objects
3538                // - listener is invoked with current scope (this)
3539                return function(){
3540                        var ap = Array.prototype, c = arguments.callee, ls = c._listeners, t = c.target,
3541                        // return value comes from original target function
3542                                r = t && t.apply(this, arguments),
3543                        // make local copy of listener array so it is immutable during processing
3544                                i, lls = [].concat(ls)
3545                        ;
3546
3547                        // invoke listeners after target function
3548                        for(i in lls){
3549                                if(!(i in ap)){
3550                                        lls[i].apply(this, arguments);
3551                                }
3552                        }
3553                        // return value comes from original target function
3554                        return r;
3555                };
3556        },
3557        // add a listener to an object
3558        add: function(/*Object*/ source, /*String*/ method, /*Function*/ listener){
3559                // Whenever 'method' is invoked, 'listener' will have the same scope.
3560                // Trying to supporting a context object for the listener led to
3561                // complexity.
3562                // Non trivial to provide 'once' functionality here
3563                // because listener could be the result of a dojo.hitch call,
3564                // in which case two references to the same hitch target would not
3565                // be equivalent.
3566                source = source || dojo.global;
3567                // The source method is either null, a dispatcher, or some other function
3568                var f = source[method];
3569                // Ensure a dispatcher
3570                if(!f || !f._listeners){
3571                        var d = dojo._listener.getDispatcher();
3572                        // original target function is special
3573                        d.target = f;
3574                        // dispatcher holds a list of listeners
3575                        d._listeners = [];
3576                        // redirect source to dispatcher
3577                        f = source[method] = d;
3578                }
3579                // The contract is that a handle is returned that can
3580                // identify this listener for disconnect.
3581                //
3582                // The type of the handle is private. Here is it implemented as Integer.
3583                // DOM event code has this same contract but handle is Function
3584                // in non-IE browsers.
3585                //
3586                // We could have separate lists of before and after listeners.
3587                return f._listeners.push(listener); /*Handle*/
3588        },
3589        // remove a listener from an object
3590        remove: function(/*Object*/ source, /*String*/ method, /*Handle*/ handle){
3591                var f = (source || dojo.global)[method];
3592                // remember that handle is the index+1 (0 is not a valid handle)
3593                if(f && f._listeners && handle--){
3594                        delete f._listeners[handle];
3595                }
3596        }
3597};
3598
3599// Multiple delegation for arbitrary methods.
3600
3601// This unit knows nothing about DOM, but we include DOM aware documentation
3602// and dontFix argument here to help the autodocs. Actual DOM aware code is in
3603// event.js.
3604
3605dojo.connect = function(/*Object|null*/ obj,
3606                                                /*String*/ event,
3607                                                /*Object|null*/ context,
3608                                                /*String|Function*/ method,
3609                                                /*Boolean?*/ dontFix){
3610        // summary:
3611        //              `dojo.connect` is the core event handling and delegation method in
3612        //              Dojo. It allows one function to "listen in" on the execution of
3613        //              any other, triggering the second whenever the first is called. Many
3614        //              listeners may be attached to a function, and source functions may
3615        //              be either regular function calls or DOM events.
3616        //
3617        // description:
3618        //              Connects listeners to actions, so that after event fires, a
3619        //              listener is called with the same arguments passed to the original
3620        //              function.
3621        //
3622        //              Since `dojo.connect` allows the source of events to be either a
3623        //              "regular" JavaScript function or a DOM event, it provides a uniform
3624        //              interface for listening to all the types of events that an
3625        //              application is likely to deal with though a single, unified
3626        //              interface. DOM programmers may want to think of it as
3627        //              "addEventListener for everything and anything".
3628        //
3629        //              When setting up a connection, the `event` parameter must be a
3630        //              string that is the name of the method/event to be listened for. If
3631        //              `obj` is null, `dojo.global` is assumed, meaning that connections
3632        //              to global methods are supported but also that you may inadvertently
3633        //              connect to a global by passing an incorrect object name or invalid
3634        //              reference.
3635        //
3636        //              `dojo.connect` generally is forgiving. If you pass the name of a
3637        //              function or method that does not yet exist on `obj`, connect will
3638        //              not fail, but will instead set up a stub method. Similarly, null
3639        //              arguments may simply be omitted such that fewer than 4 arguments
3640        //              may be required to set up a connection See the examples for details.
3641        //
3642        //              The return value is a handle that is needed to
3643        //              remove this connection with `dojo.disconnect`.
3644        //
3645        // obj:
3646        //              The source object for the event function.
3647        //              Defaults to `dojo.global` if null.
3648        //              If obj is a DOM node, the connection is delegated
3649        //              to the DOM event manager (unless dontFix is true).
3650        //
3651        // event:
3652        //              String name of the event function in obj.
3653        //              I.e. identifies a property `obj[event]`.
3654        //
3655        // context:
3656        //              The object that method will receive as "this".
3657        //
3658        //              If context is null and method is a function, then method
3659        //              inherits the context of event.
3660        //
3661        //              If method is a string then context must be the source
3662        //              object object for method (context[method]). If context is null,
3663        //              dojo.global is used.
3664        //
3665        // method:
3666        //              A function reference, or name of a function in context.
3667        //              The function identified by method fires after event does.
3668        //              method receives the same arguments as the event.
3669        //              See context argument comments for information on method's scope.
3670        //
3671        // dontFix:
3672        //              If obj is a DOM node, set dontFix to true to prevent delegation
3673        //              of this connection to the DOM event manager.
3674        //
3675        // example:
3676        //              When obj.onchange(), do ui.update():
3677        //      |       dojo.connect(obj, "onchange", ui, "update");
3678        //      |       dojo.connect(obj, "onchange", ui, ui.update); // same
3679        //
3680        // example:
3681        //              Using return value for disconnect:
3682        //      |       var link = dojo.connect(obj, "onchange", ui, "update");
3683        //      |       ...
3684        //      |       dojo.disconnect(link);
3685        //
3686        // example:
3687        //              When onglobalevent executes, watcher.handler is invoked:
3688        //      |       dojo.connect(null, "onglobalevent", watcher, "handler");
3689        //
3690        // example:
3691        //              When ob.onCustomEvent executes, customEventHandler is invoked:
3692        //      |       dojo.connect(ob, "onCustomEvent", null, "customEventHandler");
3693        //      |       dojo.connect(ob, "onCustomEvent", "customEventHandler"); // same
3694        //
3695        // example:
3696        //              When ob.onCustomEvent executes, customEventHandler is invoked
3697        //              with the same scope (this):
3698        //      |       dojo.connect(ob, "onCustomEvent", null, customEventHandler);
3699        //      |       dojo.connect(ob, "onCustomEvent", customEventHandler); // same
3700        //
3701        // example:
3702        //              When globalEvent executes, globalHandler is invoked
3703        //              with the same scope (this):
3704        //      |       dojo.connect(null, "globalEvent", null, globalHandler);
3705        //      |       dojo.connect("globalEvent", globalHandler); // same
3706
3707        // normalize arguments
3708        var a=arguments, args=[], i=0;
3709        // if a[0] is a String, obj was omitted
3710        args.push(dojo.isString(a[0]) ? null : a[i++], a[i++]);
3711        // if the arg-after-next is a String or Function, context was NOT omitted
3712        var a1 = a[i+1];
3713        args.push(dojo.isString(a1)||dojo.isFunction(a1) ? a[i++] : null, a[i++]);
3714        // absorb any additional arguments
3715        for(var l=a.length; i<l; i++){  args.push(a[i]); }
3716        // do the actual work
3717        return dojo._connect.apply(this, args); /*Handle*/
3718}
3719
3720// used by non-browser hostenvs. always overriden by event.js
3721dojo._connect = function(obj, event, context, method){
3722        var l=dojo._listener, h=l.add(obj, event, dojo.hitch(context, method));
3723        return [obj, event, h, l]; // Handle
3724};
3725
3726dojo.disconnect = function(/*Handle*/ handle){
3727        // summary:
3728        //              Remove a link created by dojo.connect.
3729        // description:
3730        //              Removes the connection between event and the method referenced by handle.
3731        // handle:
3732        //              the return value of the dojo.connect call that created the connection.
3733        if(handle && handle[0] !== undefined){
3734                dojo._disconnect.apply(this, handle);
3735                // let's not keep this reference
3736                delete handle[0];
3737        }
3738};
3739
3740dojo._disconnect = function(obj, event, handle, listener){
3741        listener.remove(obj, event, handle);
3742};
3743
3744// topic publish/subscribe
3745
3746dojo._topics = {};
3747
3748dojo.subscribe = function(/*String*/ topic, /*Object|null*/ context, /*String|Function*/ method){
3749        //      summary:
3750        //              Attach a listener to a named topic. The listener function is invoked whenever the
3751        //              named topic is published (see: dojo.publish).
3752        //              Returns a handle which is needed to unsubscribe this listener.
3753        //      context:
3754        //              Scope in which method will be invoked, or null for default scope.
3755        //      method:
3756        //              The name of a function in context, or a function reference. This is the function that
3757        //              is invoked when topic is published.
3758        //      example:
3759        //      |       dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); });
3760        //      |       dojo.publish("alerts", [ "read this", "hello world" ]);
3761
3762        // support for 2 argument invocation (omitting context) depends on hitch
3763        return [topic, dojo._listener.add(dojo._topics, topic, dojo.hitch(context, method))]; /*Handle*/
3764};
3765
3766dojo.unsubscribe = function(/*Handle*/ handle){
3767        //      summary:
3768        //              Remove a topic listener.
3769        //      handle:
3770        //              The handle returned from a call to subscribe.
3771        //      example:
3772        //      |       var alerter = dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); };
3773        //      |       ...
3774        //      |       dojo.unsubscribe(alerter);
3775        if(handle){
3776                dojo._listener.remove(dojo._topics, handle[0], handle[1]);
3777        }
3778};
3779
3780dojo.publish = function(/*String*/ topic, /*Array*/ args){
3781        //      summary:
3782        //              Invoke all listener method subscribed to topic.
3783        //      topic:
3784        //              The name of the topic to publish.
3785        //      args:
3786        //              An array of arguments. The arguments will be applied
3787        //              to each topic subscriber (as first class parameters, via apply).
3788        //      example:
3789        //      |       dojo.subscribe("alerts", null, function(caption, message){ alert(caption + "\n" + message); };
3790        //      |       dojo.publish("alerts", [ "read this", "hello world" ]);
3791
3792        // Note that args is an array, which is more efficient vs variable length
3793        // argument list.  Ideally, var args would be implemented via Array
3794        // throughout the APIs.
3795        var f = dojo._topics[topic];
3796        if(f){
3797                f.apply(this, args||[]);
3798        }
3799};
3800
3801dojo.connectPublisher = function(       /*String*/ topic,
3802                                                                        /*Object|null*/ obj,
3803                                                                        /*String*/ event){
3804        //      summary:
3805        //              Ensure that every time obj.event() is called, a message is published
3806        //              on the topic. Returns a handle which can be passed to
3807        //              dojo.disconnect() to disable subsequent automatic publication on
3808        //              the topic.
3809        //      topic:
3810        //              The name of the topic to publish.
3811        //      obj:
3812        //              The source object for the event function. Defaults to dojo.global
3813        //              if null.
3814        //      event:
3815        //              The name of the event function in obj.
3816        //              I.e. identifies a property obj[event].
3817        //      example:
3818        //      |       dojo.connectPublisher("/ajax/start", dojo, "xhrGet");
3819        var pf = function(){ dojo.publish(topic, arguments); }
3820        return event ? dojo.connect(obj, event, pf) : dojo.connect(obj, pf); //Handle
3821};
3822
3823}
3824
3825if(!dojo._hasResource["dojo._base.Deferred"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
3826dojo._hasResource["dojo._base.Deferred"] = true;
3827dojo.provide("dojo._base.Deferred");
3828
3829
3830
3831(function(){
3832        var mutator = function(){};
3833        var freeze = Object.freeze || function(){};
3834        // A deferred provides an API for creating and resolving a promise.
3835        dojo.Deferred = function(/*Function?*/canceller){
3836        // summary:
3837        //              Deferreds provide a generic means for encapsulating an asynchronous
3838        //              operation and notifying users of the completion and result of the operation.
3839        // description:
3840        //              The dojo.Deferred API is based on the concept of promises that provide a
3841        //              generic interface into the eventual completion of an asynchronous action.
3842        //              The motivation for promises fundamentally is about creating a
3843        //              separation of concerns that allows one to achieve the same type of
3844        //              call patterns and logical data flow in asynchronous code as can be
3845        //              achieved in synchronous code. Promises allows one
3846        //              to be able to call a function purely with arguments needed for
3847        //              execution, without conflating the call with concerns of whether it is
3848        //              sync or async. One shouldn't need to alter a call's arguments if the
3849        //              implementation switches from sync to async (or vice versa). By having
3850        //              async functions return promises, the concerns of making the call are
3851        //              separated from the concerns of asynchronous interaction (which are
3852        //              handled by the promise).
3853        //
3854        //      The dojo.Deferred is a type of promise that provides methods for fulfilling the
3855        //              promise with a successful result or an error. The most important method for
3856        //              working with Dojo's promises is the then() method, which follows the
3857        //              CommonJS proposed promise API. An example of using a Dojo promise:
3858        //
3859        //              |       var resultingPromise = someAsyncOperation.then(function(result){
3860        //              |               ... handle result ...
3861        //              |       },
3862        //              |       function(error){
3863        //              |               ... handle error ...
3864        //              |       });
3865        //
3866        //              The .then() call returns a new promise that represents the result of the
3867        //              execution of the callback. The callbacks will never affect the original promises value.
3868        //
3869        //              The dojo.Deferred instances also provide the following functions for backwards compatibility:
3870        //
3871        //                      * addCallback(handler)
3872        //                      * addErrback(handler)
3873        //                      * callback(result)
3874        //                      * errback(result)
3875        //
3876        //              Callbacks are allowed to return promises themselves, so
3877        //              you can build complicated sequences of events with ease.
3878        //
3879        //              The creator of the Deferred may specify a canceller.  The canceller
3880        //              is a function that will be called if Deferred.cancel is called
3881        //              before the Deferred fires. You can use this to implement clean
3882        //              aborting of an XMLHttpRequest, etc. Note that cancel will fire the
3883        //              deferred with a CancelledError (unless your canceller returns
3884        //              another kind of error), so the errbacks should be prepared to
3885        //              handle that error for cancellable Deferreds.
3886        // example:
3887        //      |       var deferred = new dojo.Deferred();
3888        //      |       setTimeout(function(){ deferred.callback({success: true}); }, 1000);
3889        //      |       return deferred;
3890        // example:
3891        //              Deferred objects are often used when making code asynchronous. It
3892        //              may be easiest to write functions in a synchronous manner and then
3893        //              split code using a deferred to trigger a response to a long-lived
3894        //              operation. For example, instead of register a callback function to
3895        //              denote when a rendering operation completes, the function can
3896        //              simply return a deferred:
3897        //
3898        //              |       // callback style:
3899        //              |       function renderLotsOfData(data, callback){
3900        //              |               var success = false
3901        //              |               try{
3902        //              |                       for(var x in data){
3903        //              |                               renderDataitem(data[x]);
3904        //              |                       }
3905        //              |                       success = true;
3906        //              |               }catch(e){ }
3907        //              |               if(callback){
3908        //              |                       callback(success);
3909        //              |               }
3910        //              |       }
3911        //
3912        //              |       // using callback style
3913        //              |       renderLotsOfData(someDataObj, function(success){
3914        //              |               // handles success or failure
3915        //              |               if(!success){
3916        //              |                       promptUserToRecover();
3917        //              |               }
3918        //              |       });
3919        //              |       // NOTE: no way to add another callback here!!
3920        // example:
3921        //              Using a Deferred doesn't simplify the sending code any, but it
3922        //              provides a standard interface for callers and senders alike,
3923        //              providing both with a simple way to service multiple callbacks for
3924        //              an operation and freeing both sides from worrying about details
3925        //              such as "did this get called already?". With Deferreds, new
3926        //              callbacks can be added at any time.
3927        //
3928        //              |       // Deferred style:
3929        //              |       function renderLotsOfData(data){
3930        //              |               var d = new dojo.Deferred();
3931        //              |               try{
3932        //              |                       for(var x in data){
3933        //              |                               renderDataitem(data[x]);
3934        //              |                       }
3935        //              |                       d.callback(true);
3936        //              |               }catch(e){
3937        //              |                       d.errback(new Error("rendering failed"));
3938        //              |               }
3939        //              |               return d;
3940        //              |       }
3941        //
3942        //              |       // using Deferred style
3943        //              |       renderLotsOfData(someDataObj).then(null, function(){
3944        //              |               promptUserToRecover();
3945        //              |       });
3946        //              |       // NOTE: addErrback and addCallback both return the Deferred
3947        //              |       // again, so we could chain adding callbacks or save the
3948        //              |       // deferred for later should we need to be notified again.
3949        // example:
3950        //              In this example, renderLotsOfData is synchronous and so both
3951        //              versions are pretty artificial. Putting the data display on a
3952        //              timeout helps show why Deferreds rock:
3953        //
3954        //              |       // Deferred style and async func
3955        //              |       function renderLotsOfData(data){
3956        //              |               var d = new dojo.Deferred();
3957        //              |               setTimeout(function(){
3958        //              |                       try{
3959        //              |                               for(var x in data){
3960        //              |                                       renderDataitem(data[x]);
3961        //              |                               }
3962        //              |                               d.callback(true);
3963        //              |                       }catch(e){
3964        //              |                               d.errback(new Error("rendering failed"));
3965        //              |                       }
3966        //              |               }, 100);
3967        //              |               return d;
3968        //              |       }
3969        //
3970        //              |       // using Deferred style
3971        //              |       renderLotsOfData(someDataObj).then(null, function(){
3972        //              |               promptUserToRecover();
3973        //              |       });
3974        //
3975        //              Note that the caller doesn't have to change his code at all to
3976        //              handle the asynchronous case.
3977                var result, finished, isError, head, nextListener;
3978                var promise = (this.promise = {});
3979
3980                function complete(value){
3981                        if(finished){
3982                                throw new Error("This deferred has already been resolved");
3983                        }
3984                        result = value;
3985                        finished = true;
3986                        notify();
3987                }
3988                function notify(){
3989                        var mutated;
3990                        while(!mutated && nextListener){
3991                                var listener = nextListener;
3992                                nextListener = nextListener.next;
3993                                if((mutated = (listener.progress == mutator))){ // assignment and check
3994                                        finished = false;
3995                                }
3996                                var func = (isError ? listener.error : listener.resolved);
3997                                if (func) {
3998                                        try {
3999                                                var newResult = func(result);
4000                                                if (newResult && typeof newResult.then === "function") {
4001                                                        newResult.then(dojo.hitch(listener.deferred, "resolve"), dojo.hitch(listener.deferred, "reject"));
4002                                                        continue;
4003                                                }
4004                                                var unchanged = mutated && newResult === undefined;
4005                                                if(mutated && !unchanged){
4006                                                        isError = newResult instanceof Error;
4007                                                }
4008                                                listener.deferred[unchanged && isError ? "reject" : "resolve"](unchanged ? result : newResult);
4009                                        }
4010                                        catch (e) {
4011                                                listener.deferred.reject(e);
4012                                        }
4013                                }else {
4014                                        if(isError){
4015                                                listener.deferred.reject(result);
4016                                        }else{
4017                                                listener.deferred.resolve(result);
4018                                        }
4019                                }
4020                        }
4021                }
4022                // calling resolve will resolve the promise
4023                this.resolve = this.callback = function(value){
4024                        // summary:
4025                        //              Fulfills the Deferred instance successfully with the provide value
4026                        this.fired = 0;
4027                        this.results = [value, null];
4028                        complete(value);
4029                };
4030
4031
4032                // calling error will indicate that the promise failed
4033                this.reject = this.errback = function(error){
4034                        // summary:
4035                        //              Fulfills the Deferred instance as an error with the provided error
4036                        isError = true;
4037                        this.fired = 1;
4038                        complete(error);
4039                        this.results = [null, error];
4040                        if(!error || error.log !== false){
4041                                (dojo.config.deferredOnError || function(x){ console.error(x); })(error);
4042                        }
4043                };
4044                // call progress to provide updates on the progress on the completion of the promise
4045                this.progress = function(update){
4046                        // summary
4047                        //              Send progress events to all listeners
4048                        var listener = nextListener;
4049                        while(listener){
4050                                var progress = listener.progress;
4051                                progress && progress(update);
4052                                listener = listener.next;
4053                        }
4054                };
4055                this.addCallbacks = function(/*Function?*/callback, /*Function?*/errback){
4056                        this.then(callback, errback, mutator);
4057                        return this;
4058                };
4059                // provide the implementation of the promise
4060                this.then = promise.then = function(/*Function?*/resolvedCallback, /*Function?*/errorCallback, /*Function?*/progressCallback){
4061                        // summary:
4062                        //              Adds a fulfilledHandler, errorHandler, and progressHandler to be called for
4063                        //              completion of a promise. The fulfilledHandler is called when the promise
4064                        //              is fulfilled. The errorHandler is called when a promise fails. The
4065                        //              progressHandler is called for progress events. All arguments are optional
4066                        //              and non-function values are ignored. The progressHandler is not only an
4067                        //              optional argument, but progress events are purely optional. Promise
4068                        //              providers are not required to ever create progress events.
4069                        //
4070                        //              This function will return a new promise that is fulfilled when the given
4071                        //              fulfilledHandler or errorHandler callback is finished. This allows promise
4072                        //              operations to be chained together. The value returned from the callback
4073                        //              handler is the fulfillment value for the returned promise. If the callback
4074                        //              throws an error, the returned promise will be moved to failed state.
4075                        //
4076                        // example:
4077                        //              An example of using a CommonJS compliant promise:
4078                        //              |       asyncComputeTheAnswerToEverything().
4079                        //              |               then(addTwo).
4080                        //              |               then(printResult, onError);
4081                        //              |       >44
4082                        //
4083                        var returnDeferred = progressCallback == mutator ? this : new dojo.Deferred(promise.cancel);
4084                        var listener = {
4085                                resolved: resolvedCallback,
4086                                error: errorCallback,
4087                                progress: progressCallback,
4088                                deferred: returnDeferred
4089                        };
4090                        if(nextListener){
4091                                head = head.next = listener;
4092                        }
4093                        else{
4094                                nextListener = head = listener;
4095                        }
4096                        if(finished){
4097                                notify();
4098                        }
4099                        return returnDeferred.promise;
4100                };
4101                var deferred = this;
4102                this.cancel = promise.cancel = function () {
4103                        // summary:
4104                        //              Cancels the asynchronous operation
4105                        if(!finished){
4106                                var error = canceller && canceller(deferred);
4107                                if(!finished){
4108                                        if (!(error instanceof Error)) {
4109                                                error = new Error(error);
4110                                        }
4111                                        error.log = false;
4112                                        deferred.reject(error);
4113                                }
4114                        }
4115                };
4116                freeze(promise);
4117        };
4118        dojo.extend(dojo.Deferred, {
4119                addCallback: function (/*Function*/callback) {
4120                        return this.addCallbacks(dojo.hitch.apply(dojo, arguments));
4121                },
4122
4123                addErrback: function (/*Function*/errback) {
4124                        return this.addCallbacks(null, dojo.hitch.apply(dojo, arguments));
4125                },
4126
4127                addBoth: function (/*Function*/callback) {
4128                        var enclosed = dojo.hitch.apply(dojo, arguments);
4129                        return this.addCallbacks(enclosed, enclosed);
4130                },
4131                fired: -1
4132        });
4133})();
4134dojo.when = function(promiseOrValue, /*Function?*/callback, /*Function?*/errback, /*Function?*/progressHandler){
4135        // summary:
4136        //              This provides normalization between normal synchronous values and
4137        //              asynchronous promises, so you can interact with them in a common way
4138        //      example:
4139        //              |       function printFirstAndList(items){
4140        //              |               dojo.when(findFirst(items), console.log);
4141        //              |               dojo.when(findLast(items), console.log);
4142        //              |       }
4143        //              |       function findFirst(items){
4144        //              |               return dojo.when(items, function(items){
4145        //              |                       return items[0];
4146        //              |               });
4147        //              |       }
4148        //              |       function findLast(items){
4149        //              |               return dojo.when(items, function(items){
4150        //              |                       return items[items.length];
4151        //              |               });
4152        //              |       }
4153        //              And now all three of his functions can be used sync or async.
4154        //              |       printFirstAndLast([1,2,3,4]) will work just as well as
4155        //              |       printFirstAndLast(dojo.xhrGet(...));
4156
4157        if(promiseOrValue && typeof promiseOrValue.then === "function"){
4158                return promiseOrValue.then(callback, errback, progressHandler);
4159        }
4160        return callback(promiseOrValue);
4161};
4162
4163}
4164
4165if(!dojo._hasResource["dojo._base.json"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
4166dojo._hasResource["dojo._base.json"] = true;
4167dojo.provide("dojo._base.json");
4168
4169
4170dojo.fromJson = function(/*String*/ json){
4171        // summary:
4172        //              Parses a [JSON](http://json.org) string to return a JavaScript object.
4173        // description:
4174        //              Throws for invalid JSON strings, but it does not use a strict JSON parser. It
4175        //              delegates to eval().  The content passed to this method must therefore come
4176        //              from a trusted source.
4177        // json:
4178        //              a string literal of a JSON item, for instance:
4179        //                      `'{ "foo": [ "bar", 1, { "baz": "thud" } ] }'`
4180
4181        return eval("(" + json + ")"); // Object
4182};
4183
4184dojo._escapeString = function(/*String*/str){
4185        //summary:
4186        //              Adds escape sequences for non-visual characters, double quote and
4187        //              backslash and surrounds with double quotes to form a valid string
4188        //              literal.
4189        return ('"' + str.replace(/(["\\])/g, '\\$1') + '"').
4190                replace(/[\f]/g, "\\f").replace(/[\b]/g, "\\b").replace(/[\n]/g, "\\n").
4191                replace(/[\t]/g, "\\t").replace(/[\r]/g, "\\r"); // string
4192};
4193
4194dojo.toJsonIndentStr = "\t";
4195dojo.toJson = function(/*Object*/ it, /*Boolean?*/ prettyPrint, /*String?*/ _indentStr){
4196        //      summary:
4197        //              Returns a [JSON](http://json.org) serialization of an object.
4198        //      description:
4199        //              Returns a [JSON](http://json.org) serialization of an object.
4200        //              Note that this doesn't check for infinite recursion, so don't do that!
4201        //      it:
4202        //              an object to be serialized. Objects may define their own
4203        //              serialization via a special "__json__" or "json" function
4204        //              property. If a specialized serializer has been defined, it will
4205        //              be used as a fallback.
4206        //      prettyPrint:
4207        //              if true, we indent objects and arrays to make the output prettier.
4208        //              The variable `dojo.toJsonIndentStr` is used as the indent string --
4209        //              to use something other than the default (tab), change that variable
4210        //              before calling dojo.toJson().
4211        //      _indentStr:
4212        //              private variable for recursive calls when pretty printing, do not use.
4213        //      example:
4214        //              simple serialization of a trivial object
4215        //              |       var jsonStr = dojo.toJson({ howdy: "stranger!", isStrange: true });
4216        //              |       doh.is('{"howdy":"stranger!","isStrange":true}', jsonStr);
4217        //      example:
4218        //              a custom serializer for an objects of a particular class:
4219        //              |       dojo.declare("Furby", null, {
4220        //              |               furbies: "are strange",
4221        //              |               furbyCount: 10,
4222        //              |               __json__: function(){
4223        //              |               },
4224        //              |       });
4225
4226        if(it === undefined){
4227                return "undefined";
4228        }
4229        var objtype = typeof it;
4230        if(objtype == "number" || objtype == "boolean"){
4231                return it + "";
4232        }
4233        if(it === null){
4234                return "null";
4235        }
4236        if(dojo.isString(it)){
4237                return dojo._escapeString(it);
4238        }
4239        // recurse
4240        var recurse = arguments.callee;
4241        // short-circuit for objects that support "json" serialization
4242        // if they return "self" then just pass-through...
4243        var newObj;
4244        _indentStr = _indentStr || "";
4245        var nextIndent = prettyPrint ? _indentStr + dojo.toJsonIndentStr : "";
4246        var tf = it.__json__||it.json;
4247        if(dojo.isFunction(tf)){
4248                newObj = tf.call(it);
4249                if(it !== newObj){
4250                        return recurse(newObj, prettyPrint, nextIndent);
4251                }
4252        }
4253        if(it.nodeType && it.cloneNode){ // isNode
4254                // we can't seriailize DOM nodes as regular objects because they have cycles
4255                // DOM nodes could be serialized with something like outerHTML, but
4256                // that can be provided by users in the form of .json or .__json__ function.
4257                throw new Error("Can't serialize DOM nodes");
4258        }
4259
4260        var sep = prettyPrint ? " " : "";
4261        var newLine = prettyPrint ? "\n" : "";
4262
4263        // array
4264        if(dojo.isArray(it)){
4265                var res = dojo.map(it, function(obj){
4266                        var val = recurse(obj, prettyPrint, nextIndent);
4267                        if(typeof val != "string"){
4268                                val = "undefined";
4269                        }
4270                        return newLine + nextIndent + val;
4271                });
4272                return "[" + res.join("," + sep) + newLine + _indentStr + "]";
4273        }
4274        /*
4275        // look in the registry
4276        try {
4277                window.o = it;
4278                newObj = dojo.json.jsonRegistry.match(it);
4279                return recurse(newObj, prettyPrint, nextIndent);
4280        }catch(e){
4281                // console.log(e);
4282        }
4283        // it's a function with no adapter, skip it
4284        */
4285        if(objtype == "function"){
4286                return null; // null
4287        }
4288        // generic object code path
4289        var output = [], key;
4290        for(key in it){
4291                var keyStr, val;
4292                if(typeof key == "number"){
4293                        keyStr = '"' + key + '"';
4294                }else if(typeof key == "string"){
4295                        keyStr = dojo._escapeString(key);
4296                }else{
4297                        // skip non-string or number keys
4298                        continue;
4299                }
4300                val = recurse(it[key], prettyPrint, nextIndent);
4301                if(typeof val != "string"){
4302                        // skip non-serializable values
4303                        continue;
4304                }
4305                // FIXME: use += on Moz!!
4306                //       MOW NOTE: using += is a pain because you have to account for the dangling comma...
4307                output.push(newLine + nextIndent + keyStr + ":" + sep + val);
4308        }
4309        return "{" + output.join("," + sep) + newLine + _indentStr + "}"; // String
4310};
4311
4312}
4313
4314if(!dojo._hasResource["dojo._base.Color"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
4315dojo._hasResource["dojo._base.Color"] = true;
4316dojo.provide("dojo._base.Color");
4317
4318
4319
4320
4321(function(){
4322
4323        var d = dojo;
4324
4325        dojo.Color = function(/*Array|String|Object*/ color){
4326                // summary:
4327                //              Takes a named string, hex string, array of rgb or rgba values,
4328                //              an object with r, g, b, and a properties, or another `dojo.Color` object
4329                //              and creates a new Color instance to work from.
4330                //
4331                // example:
4332                //              Work with a Color instance:
4333                //       | var c = new dojo.Color();
4334                //       | c.setColor([0,0,0]); // black
4335                //       | var hex = c.toHex(); // #000000
4336                //
4337                // example:
4338                //              Work with a node's color:
4339                //       | var color = dojo.style("someNode", "backgroundColor");
4340                //       | var n = new dojo.Color(color);
4341                //       | // adjust the color some
4342                //       | n.r *= .5;
4343                //       | console.log(n.toString()); // rgb(128, 255, 255);
4344                if(color){ this.setColor(color); }
4345        };
4346
4347        // FIXME:
4348        //      there's got to be a more space-efficient way to encode or discover
4349        //      these!!  Use hex?
4350        dojo.Color.named = {
4351                black:      [0,0,0],
4352                silver:     [192,192,192],
4353                gray:       [128,128,128],
4354                white:      [255,255,255],
4355                maroon:         [128,0,0],
4356                red:        [255,0,0],
4357                purple:         [128,0,128],
4358                fuchsia:        [255,0,255],
4359                green:      [0,128,0],
4360                lime:       [0,255,0],
4361                olive:          [128,128,0],
4362                yellow:         [255,255,0],
4363                navy:       [0,0,128],
4364                blue:       [0,0,255],
4365                teal:           [0,128,128],
4366                aqua:           [0,255,255],
4367                transparent: d.config.transparentColor || [255,255,255]
4368        };
4369
4370        dojo.extend(dojo.Color, {
4371                r: 255, g: 255, b: 255, a: 1,
4372                _set: function(r, g, b, a){
4373                        var t = this; t.r = r; t.g = g; t.b = b; t.a = a;
4374                },
4375                setColor: function(/*Array|String|Object*/ color){
4376                        // summary:
4377                        //              Takes a named string, hex string, array of rgb or rgba values,
4378                        //              an object with r, g, b, and a properties, or another `dojo.Color` object
4379                        //              and sets this color instance to that value.
4380                        //
4381                        // example:
4382                        //      |       var c = new dojo.Color(); // no color
4383                        //      |       c.setColor("#ededed"); // greyish
4384                        if(d.isString(color)){
4385                                d.colorFromString(color, this);
4386                        }else if(d.isArray(color)){
4387                                d.colorFromArray(color, this);
4388                        }else{
4389                                this._set(color.r, color.g, color.b, color.a);
4390                                if(!(color instanceof d.Color)){ this.sanitize(); }
4391                        }
4392                        return this;    // dojo.Color
4393                },
4394                sanitize: function(){
4395                        // summary:
4396                        //              Ensures the object has correct attributes
4397                        // description:
4398                        //              the default implementation does nothing, include dojo.colors to
4399                        //              augment it with real checks
4400                        return this;    // dojo.Color
4401                },
4402                toRgb: function(){
4403                        // summary:
4404                        //              Returns 3 component array of rgb values
4405                        // example:
4406                        //      |       var c = new dojo.Color("#000000");
4407                        //      |       console.log(c.toRgb()); // [0,0,0]
4408                        var t = this;
4409                        return [t.r, t.g, t.b]; // Array
4410                },
4411                toRgba: function(){
4412                        // summary:
4413                        //              Returns a 4 component array of rgba values from the color
4414                        //              represented by this object.
4415                        var t = this;
4416                        return [t.r, t.g, t.b, t.a];    // Array
4417                },
4418                toHex: function(){
4419                        // summary:
4420                        //              Returns a CSS color string in hexadecimal representation
4421                        // example:
4422                        //      |       console.log(new dojo.Color([0,0,0]).toHex()); // #000000
4423                        var arr = d.map(["r", "g", "b"], function(x){
4424                                var s = this[x].toString(16);
4425                                return s.length < 2 ? "0" + s : s;
4426                        }, this);
4427                        return "#" + arr.join("");      // String
4428                },
4429                toCss: function(/*Boolean?*/ includeAlpha){
4430                        // summary:
4431                        //              Returns a css color string in rgb(a) representation
4432                        // example:
4433                        //      |       var c = new dojo.Color("#FFF").toCss();
4434                        //      |       console.log(c); // rgb('255','255','255')
4435                        var t = this, rgb = t.r + ", " + t.g + ", " + t.b;
4436                        return (includeAlpha ? "rgba(" + rgb + ", " + t.a : "rgb(" + rgb) + ")";        // String
4437                },
4438                toString: function(){
4439                        // summary:
4440                        //              Returns a visual representation of the color
4441                        return this.toCss(true); // String
4442                }
4443        });
4444
4445        dojo.blendColors = function(
4446                /*dojo.Color*/ start,
4447                /*dojo.Color*/ end,
4448                /*Number*/ weight,
4449                /*dojo.Color?*/ obj
4450        ){
4451                // summary:
4452                //              Blend colors end and start with weight from 0 to 1, 0.5 being a 50/50 blend,
4453                //              can reuse a previously allocated dojo.Color object for the result
4454                var t = obj || new d.Color();
4455                d.forEach(["r", "g", "b", "a"], function(x){
4456                        t[x] = start[x] + (end[x] - start[x]) * weight;
4457                        if(x != "a"){ t[x] = Math.round(t[x]); }
4458                });
4459                return t.sanitize();    // dojo.Color
4460        };
4461
4462        dojo.colorFromRgb = function(/*String*/ color, /*dojo.Color?*/ obj){
4463                // summary:
4464                //              Returns a `dojo.Color` instance from a string of the form
4465                //              "rgb(...)" or "rgba(...)". Optionally accepts a `dojo.Color`
4466                //              object to update with the parsed value and return instead of
4467                //              creating a new object.
4468                // returns:
4469                //              A dojo.Color object. If obj is passed, it will be the return value.
4470                var m = color.toLowerCase().match(/^rgba?\(([\s\.,0-9]+)\)/);
4471                return m && dojo.colorFromArray(m[1].split(/\s*,\s*/), obj);    // dojo.Color
4472        };
4473
4474        dojo.colorFromHex = function(/*String*/ color, /*dojo.Color?*/ obj){
4475                // summary:
4476                //              Converts a hex string with a '#' prefix to a color object.
4477                //              Supports 12-bit #rgb shorthand. Optionally accepts a
4478                //              `dojo.Color` object to update with the parsed value.
4479                //
4480                // returns:
4481                //              A dojo.Color object. If obj is passed, it will be the return value.
4482                //
4483                // example:
4484                //       | var thing = dojo.colorFromHex("#ededed"); // grey, longhand
4485                //
4486                // example:
4487                //      | var thing = dojo.colorFromHex("#000"); // black, shorthand
4488                var t = obj || new d.Color(),
4489                        bits = (color.length == 4) ? 4 : 8,
4490                        mask = (1 << bits) - 1;
4491                color = Number("0x" + color.substr(1));
4492                if(isNaN(color)){
4493                        return null; // dojo.Color
4494                }
4495                d.forEach(["b", "g", "r"], function(x){
4496                        var c = color & mask;
4497                        color >>= bits;
4498                        t[x] = bits == 4 ? 17 * c : c;
4499                });
4500                t.a = 1;
4501                return t;       // dojo.Color
4502        };
4503
4504        dojo.colorFromArray = function(/*Array*/ a, /*dojo.Color?*/ obj){
4505                // summary:
4506                //              Builds a `dojo.Color` from a 3 or 4 element array, mapping each
4507                //              element in sequence to the rgb(a) values of the color.
4508                // example:
4509                //              | var myColor = dojo.colorFromArray([237,237,237,0.5]); // grey, 50% alpha
4510                // returns:
4511                //              A dojo.Color object. If obj is passed, it will be the return value.
4512                var t = obj || new d.Color();
4513                t._set(Number(a[0]), Number(a[1]), Number(a[2]), Number(a[3]));
4514                if(isNaN(t.a)){ t.a = 1; }
4515                return t.sanitize();    // dojo.Color
4516        };
4517
4518        dojo.colorFromString = function(/*String*/ str, /*dojo.Color?*/ obj){
4519                // summary:
4520                //              Parses `str` for a color value. Accepts hex, rgb, and rgba
4521                //              style color values.
4522                // description:
4523                //              Acceptable input values for str may include arrays of any form
4524                //              accepted by dojo.colorFromArray, hex strings such as "#aaaaaa", or
4525                //              rgb or rgba strings such as "rgb(133, 200, 16)" or "rgba(10, 10,
4526                //              10, 50)"
4527                // returns:
4528                //              A dojo.Color object. If obj is passed, it will be the return value.
4529                var a = d.Color.named[str];
4530                return a && d.colorFromArray(a, obj) || d.colorFromRgb(str, obj) || d.colorFromHex(str, obj);
4531        };
4532})();
4533
4534}
4535
4536if(!dojo._hasResource["dojo._base.window"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
4537dojo._hasResource["dojo._base.window"] = true;
4538dojo.provide("dojo._base.window");
4539
4540
4541/*=====
4542dojo.doc = {
4543        // summary:
4544        //              Alias for the current document. 'dojo.doc' can be modified
4545        //              for temporary context shifting. Also see dojo.withDoc().
4546        // description:
4547        //    Refer to dojo.doc rather
4548        //    than referring to 'window.document' to ensure your code runs
4549        //    correctly in managed contexts.
4550        // example:
4551        //      |       n.appendChild(dojo.doc.createElement('div'));
4552}
4553=====*/
4554dojo.doc = window["document"] || null;
4555
4556dojo.body = function(){
4557        // summary:
4558        //              Return the body element of the document
4559        //              return the body object associated with dojo.doc
4560        // example:
4561        //      |       dojo.body().appendChild(dojo.doc.createElement('div'));
4562
4563        // Note: document.body is not defined for a strict xhtml document
4564        // Would like to memoize this, but dojo.doc can change vi dojo.withDoc().
4565        return dojo.doc.body || dojo.doc.getElementsByTagName("body")[0]; // Node
4566};
4567
4568dojo.setContext = function(/*Object*/globalObject, /*DocumentElement*/globalDocument){
4569        // summary:
4570        //              changes the behavior of many core Dojo functions that deal with
4571        //              namespace and DOM lookup, changing them to work in a new global
4572        //              context (e.g., an iframe). The varibles dojo.global and dojo.doc
4573        //              are modified as a result of calling this function and the result of
4574        //              `dojo.body()` likewise differs.
4575        dojo.global = globalObject;
4576        dojo.doc = globalDocument;
4577};
4578
4579dojo.withGlobal = function(     /*Object*/globalObject,
4580                                                        /*Function*/callback,
4581                                                        /*Object?*/thisObject,
4582                                                        /*Array?*/cbArguments){
4583        // summary:
4584        //              Invoke callback with globalObject as dojo.global and
4585        //              globalObject.document as dojo.doc.
4586        // description:
4587        //              Invoke callback with globalObject as dojo.global and
4588        //              globalObject.document as dojo.doc. If provided, globalObject
4589        //              will be executed in the context of object thisObject
4590        //              When callback() returns or throws an error, the dojo.global
4591        //              and dojo.doc will be restored to its previous state.
4592
4593        var oldGlob = dojo.global;
4594        try{
4595                dojo.global = globalObject;
4596                return dojo.withDoc.call(null, globalObject.document, callback, thisObject, cbArguments);
4597        }finally{
4598                dojo.global = oldGlob;
4599        }
4600};
4601
4602dojo.withDoc = function(        /*DocumentElement*/documentObject,
4603                                                        /*Function*/callback,
4604                                                        /*Object?*/thisObject,
4605                                                        /*Array?*/cbArguments){
4606        // summary:
4607        //              Invoke callback with documentObject as dojo.doc.
4608        // description:
4609        //              Invoke callback with documentObject as dojo.doc. If provided,
4610        //              callback will be executed in the context of object thisObject
4611        //              When callback() returns or throws an error, the dojo.doc will
4612        //              be restored to its previous state.
4613
4614        var oldDoc = dojo.doc,
4615                oldLtr = dojo._bodyLtr,
4616                oldQ = dojo.isQuirks;
4617
4618        try{
4619                dojo.doc = documentObject;
4620                delete dojo._bodyLtr; // uncache
4621                dojo.isQuirks = dojo.doc.compatMode == "BackCompat"; // no need to check for QuirksMode which was Opera 7 only
4622
4623                if(thisObject && typeof callback == "string"){
4624                        callback = thisObject[callback];
4625                }
4626
4627                return callback.apply(thisObject, cbArguments || []);
4628        }finally{
4629                dojo.doc = oldDoc;
4630                delete dojo._bodyLtr; // in case it was undefined originally, and set to true/false by the alternate document
4631                if(oldLtr !== undefined){ dojo._bodyLtr = oldLtr; }
4632                dojo.isQuirks = oldQ;
4633        }
4634};
4635
4636}
4637
4638if(!dojo._hasResource["dojo._base.event"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
4639dojo._hasResource["dojo._base.event"] = true;
4640dojo.provide("dojo._base.event");
4641
4642
4643
4644// this file courtesy of the TurboAjax Group, licensed under a Dojo CLA
4645
4646(function(){
4647        // DOM event listener machinery
4648        var del = (dojo._event_listener = {
4649                add: function(/*DOMNode*/ node, /*String*/ name, /*Function*/ fp){
4650                        if(!node){return;}
4651                        name = del._normalizeEventName(name);
4652                        fp = del._fixCallback(name, fp);
4653                        if(
4654                                                                !dojo.isIE &&
4655                                                                (name == "mouseenter" || name == "mouseleave")
4656                        ){
4657                                var ofp = fp;
4658                                name = (name == "mouseenter") ? "mouseover" : "mouseout";
4659                                fp = function(e){
4660                                        if(!dojo.isDescendant(e.relatedTarget, node)){
4661                                                // e.type = oname; // FIXME: doesn't take? SJM: event.type is generally immutable.
4662                                                return ofp.call(this, e);
4663                                        }
4664                                }
4665                        }
4666                        node.addEventListener(name, fp, false);
4667                        return fp; /*Handle*/
4668                },
4669                remove: function(/*DOMNode*/ node, /*String*/ event, /*Handle*/ handle){
4670                        // summary:
4671                        //              clobbers the listener from the node
4672                        // node:
4673                        //              DOM node to attach the event to
4674                        // event:
4675                        //              the name of the handler to remove the function from
4676                        // handle:
4677                        //              the handle returned from add
4678                        if(node){
4679                                event = del._normalizeEventName(event);
4680                                if(!dojo.isIE && (event == "mouseenter" || event == "mouseleave")){
4681                                        event = (event == "mouseenter") ? "mouseover" : "mouseout";
4682                                }
4683
4684                                node.removeEventListener(event, handle, false);
4685                        }
4686                },
4687                _normalizeEventName: function(/*String*/ name){
4688                        // Generally, name should be lower case, unless it is special
4689                        // somehow (e.g. a Mozilla DOM event).
4690                        // Remove 'on'.
4691                        return name.slice(0,2) =="on" ? name.slice(2) : name;
4692                },
4693                _fixCallback: function(/*String*/ name, fp){
4694                        // By default, we only invoke _fixEvent for 'keypress'
4695                        // If code is added to _fixEvent for other events, we have
4696                        // to revisit this optimization.
4697                        // This also applies to _fixEvent overrides for Safari and Opera
4698                        // below.
4699                        return name != "keypress" ? fp : function(e){ return fp.call(this, del._fixEvent(e, this)); };
4700                },
4701                _fixEvent: function(evt, sender){
4702                        // _fixCallback only attaches us to keypress.
4703                        // Switch on evt.type anyway because we might
4704                        // be called directly from dojo.fixEvent.
4705                        switch(evt.type){
4706                                case "keypress":
4707                                        del._setKeyChar(evt);
4708                                        break;
4709                        }
4710                        return evt;
4711                },
4712                _setKeyChar: function(evt){
4713                        evt.keyChar = evt.charCode >= 32 ? String.fromCharCode(evt.charCode) : '';
4714                        evt.charOrCode = evt.keyChar || evt.keyCode;
4715                },
4716                // For IE and Safari: some ctrl-key combinations (mostly w/punctuation) do not emit a char code in IE
4717                // we map those virtual key codes to ascii here
4718                // not valid for all (non-US) keyboards, so maybe we shouldn't bother
4719                _punctMap: {
4720                        106:42,
4721                        111:47,
4722                        186:59,
4723                        187:43,
4724                        188:44,
4725                        189:45,
4726                        190:46,
4727                        191:47,
4728                        192:96,
4729                        219:91,
4730                        220:92,
4731                        221:93,
4732                        222:39
4733                }
4734        });
4735
4736        // DOM events
4737
4738        dojo.fixEvent = function(/*Event*/ evt, /*DOMNode*/ sender){
4739                // summary:
4740                //              normalizes properties on the event object including event
4741                //              bubbling methods, keystroke normalization, and x/y positions
4742                // evt: Event
4743                //              native event object
4744                // sender: DOMNode
4745                //              node to treat as "currentTarget"
4746                return del._fixEvent(evt, sender);
4747        };
4748
4749        dojo.stopEvent = function(/*Event*/ evt){
4750                // summary:
4751                //              prevents propagation and clobbers the default action of the
4752                //              passed event
4753                // evt: Event
4754                //              The event object. If omitted, window.event is used on IE.
4755                evt.preventDefault();
4756                evt.stopPropagation();
4757                // NOTE: below, this method is overridden for IE
4758        };
4759
4760        // the default listener to use on dontFix nodes, overriden for IE
4761        var node_listener = dojo._listener;
4762
4763        // Unify connect and event listeners
4764        dojo._connect = function(obj, event, context, method, dontFix){
4765                // FIXME: need a more strict test
4766                var isNode = obj && (obj.nodeType||obj.attachEvent||obj.addEventListener);
4767                // choose one of three listener options: raw (connect.js), DOM event on a Node, custom event on a Node
4768                // we need the third option to provide leak prevention on broken browsers (IE)
4769                var lid = isNode ? (dontFix ? 2 : 1) : 0, l = [dojo._listener, del, node_listener][lid];
4770                // create a listener
4771                var h = l.add(obj, event, dojo.hitch(context, method));
4772                // formerly, the disconnect package contained "l" directly, but if client code
4773                // leaks the disconnect package (by connecting it to a node), referencing "l"
4774                // compounds the problem.
4775                // instead we return a listener id, which requires custom _disconnect below.
4776                // return disconnect package
4777                return [ obj, event, h, lid ];
4778        };
4779
4780        dojo._disconnect = function(obj, event, handle, listener){
4781                ([dojo._listener, del, node_listener][listener]).remove(obj, event, handle);
4782        };
4783
4784        // Constants
4785
4786        // Public: client code should test
4787        // keyCode against these named constants, as the
4788        // actual codes can vary by browser.
4789        dojo.keys = {
4790                // summary:
4791                //              Definitions for common key values
4792                BACKSPACE: 8,
4793                TAB: 9,
4794                CLEAR: 12,
4795                ENTER: 13,
4796                SHIFT: 16,
4797                CTRL: 17,
4798                ALT: 18,
4799                META: dojo.isSafari ? 91 : 224,         // the apple key on macs
4800                PAUSE: 19,
4801                CAPS_LOCK: 20,
4802                ESCAPE: 27,
4803                SPACE: 32,
4804                PAGE_UP: 33,
4805                PAGE_DOWN: 34,
4806                END: 35,
4807                HOME: 36,
4808                LEFT_ARROW: 37,
4809                UP_ARROW: 38,
4810                RIGHT_ARROW: 39,
4811                DOWN_ARROW: 40,
4812                INSERT: 45,
4813                DELETE: 46,
4814                HELP: 47,
4815                LEFT_WINDOW: 91,
4816                RIGHT_WINDOW: 92,
4817                SELECT: 93,
4818                NUMPAD_0: 96,
4819                NUMPAD_1: 97,
4820                NUMPAD_2: 98,
4821                NUMPAD_3: 99,
4822                NUMPAD_4: 100,
4823                NUMPAD_5: 101,
4824                NUMPAD_6: 102,
4825                NUMPAD_7: 103,
4826                NUMPAD_8: 104,
4827                NUMPAD_9: 105,
4828                NUMPAD_MULTIPLY: 106,
4829                NUMPAD_PLUS: 107,
4830                NUMPAD_ENTER: 108,
4831                NUMPAD_MINUS: 109,
4832                NUMPAD_PERIOD: 110,
4833                NUMPAD_DIVIDE: 111,
4834                F1: 112,
4835                F2: 113,
4836                F3: 114,
4837                F4: 115,
4838                F5: 116,
4839                F6: 117,
4840                F7: 118,
4841                F8: 119,
4842                F9: 120,
4843                F10: 121,
4844                F11: 122,
4845                F12: 123,
4846                F13: 124,
4847                F14: 125,
4848                F15: 126,
4849                NUM_LOCK: 144,
4850                SCROLL_LOCK: 145,
4851                // virtual key mapping
4852                copyKey: dojo.isMac && !dojo.isAIR ? (dojo.isSafari ? 91 : 224 ) : 17
4853        };
4854
4855        var evtCopyKey = dojo.isMac ? "metaKey" : "ctrlKey";
4856
4857        dojo.isCopyKey = function(e){
4858                // summary:
4859                //              Checks an event for the copy key (meta on Mac, and ctrl anywhere else)
4860                // e: Event
4861                //              Event object to examine
4862                return e[evtCopyKey];   // Boolean
4863        };
4864
4865        // Public: decoding mouse buttons from events
4866
4867/*=====
4868        dojo.mouseButtons = {
4869                // LEFT: Number
4870                //              Numeric value of the left mouse button for the platform.
4871                LEFT:   0,
4872                // MIDDLE: Number
4873                //              Numeric value of the middle mouse button for the platform.
4874                MIDDLE: 1,
4875                // RIGHT: Number
4876                //              Numeric value of the right mouse button for the platform.
4877                RIGHT:  2,
4878
4879                isButton: function(e, button){
4880                        // summary:
4881                        //              Checks an event object for a pressed button
4882                        // e: Event
4883                        //              Event object to examine
4884                        // button: Number
4885                        //              The button value (example: dojo.mouseButton.LEFT)
4886                        return e.button == button; // Boolean
4887                },
4888                isLeft: function(e){
4889                        // summary:
4890                        //              Checks an event object for the pressed left button
4891                        // e: Event
4892                        //              Event object to examine
4893                        return e.button == 0; // Boolean
4894                },
4895                isMiddle: function(e){
4896                        // summary:
4897                        //              Checks an event object for the pressed middle button
4898                        // e: Event
4899                        //              Event object to examine
4900                        return e.button == 1; // Boolean
4901                },
4902                isRight: function(e){
4903                        // summary:
4904                        //              Checks an event object for the pressed right button
4905                        // e: Event
4906                        //              Event object to examine
4907                        return e.button == 2; // Boolean
4908                }
4909        };
4910=====*/
4911
4912                if(dojo.isIE < 9 || (dojo.isIE && dojo.isQuirks)){
4913                dojo.mouseButtons = {
4914                        LEFT:   1,
4915                        MIDDLE: 4,
4916                        RIGHT:  2,
4917                        // helper functions
4918                        isButton: function(e, button){ return e.button & button; },
4919                        isLeft:   function(e){ return e.button & 1; },
4920                        isMiddle: function(e){ return e.button & 4; },
4921                        isRight:  function(e){ return e.button & 2; }
4922                };
4923        }else{
4924                        dojo.mouseButtons = {
4925                        LEFT:   0,
4926                        MIDDLE: 1,
4927                        RIGHT:  2,
4928                        // helper functions
4929                        isButton: function(e, button){ return e.button == button; },
4930                        isLeft:   function(e){ return e.button == 0; },
4931                        isMiddle: function(e){ return e.button == 1; },
4932                        isRight:  function(e){ return e.button == 2; }
4933                };
4934                }
4935
4936                // IE event normalization
4937        if(dojo.isIE){
4938                var _trySetKeyCode = function(e, code){
4939                        try{
4940                                // squelch errors when keyCode is read-only
4941                                // (e.g. if keyCode is ctrl or shift)
4942                                return (e.keyCode = code);
4943                        }catch(e){
4944                                return 0;
4945                        }
4946                };
4947
4948                // by default, use the standard listener
4949                var iel = dojo._listener;
4950                var listenersName = (dojo._ieListenersName = "_" + dojo._scopeName + "_listeners");
4951                // dispatcher tracking property
4952                if(!dojo.config._allow_leaks){
4953                        // custom listener that handles leak protection for DOM events
4954                        node_listener = iel = dojo._ie_listener = {
4955                                // support handler indirection: event handler functions are
4956                                // referenced here. Event dispatchers hold only indices.
4957                                handlers: [],
4958                                // add a listener to an object
4959                                add: function(/*Object*/ source, /*String*/ method, /*Function*/ listener){
4960                                        source = source || dojo.global;
4961                                        var f = source[method];
4962                                        if(!f||!f[listenersName]){
4963                                                var d = dojo._getIeDispatcher();
4964                                                // original target function is special
4965                                                d.target = f && (ieh.push(f) - 1);
4966                                                // dispatcher holds a list of indices into handlers table
4967                                                d[listenersName] = [];
4968                                                // redirect source to dispatcher
4969                                                f = source[method] = d;
4970                                        }
4971                                        return f[listenersName].push(ieh.push(listener) - 1) ; /*Handle*/
4972                                },
4973                                // remove a listener from an object
4974                                remove: function(/*Object*/ source, /*String*/ method, /*Handle*/ handle){
4975                                        var f = (source||dojo.global)[method], l = f && f[listenersName];
4976                                        if(f && l && handle--){
4977                                                delete ieh[l[handle]];
4978                                                delete l[handle];
4979                                        }
4980                                }
4981                        };
4982                        // alias used above
4983                        var ieh = iel.handlers;
4984                }
4985
4986                dojo.mixin(del, {
4987                        add: function(/*DOMNode*/ node, /*String*/ event, /*Function*/ fp){
4988                                if(!node){return;} // undefined
4989                                event = del._normalizeEventName(event);
4990                                if(event=="onkeypress"){
4991                                        // we need to listen to onkeydown to synthesize
4992                                        // keypress events that otherwise won't fire
4993                                        // on IE
4994                                        var kd = node.onkeydown;
4995                                        if(!kd || !kd[listenersName] || !kd._stealthKeydownHandle){
4996                                                var h = del.add(node, "onkeydown", del._stealthKeyDown);
4997                                                kd = node.onkeydown;
4998                                                kd._stealthKeydownHandle = h;
4999                                                kd._stealthKeydownRefs = 1;
5000                                        }else{
5001                                                kd._stealthKeydownRefs++;
5002                                        }
5003                                }
5004                                return iel.add(node, event, del._fixCallback(fp));
5005                        },
5006                        remove: function(/*DOMNode*/ node, /*String*/ event, /*Handle*/ handle){
5007                                event = del._normalizeEventName(event);
5008                                iel.remove(node, event, handle);
5009                                if(event=="onkeypress"){
5010                                        var kd = node.onkeydown;
5011                                        if(--kd._stealthKeydownRefs <= 0){
5012                                                iel.remove(node, "onkeydown", kd._stealthKeydownHandle);
5013                                                delete kd._stealthKeydownHandle;
5014                                        }
5015                                }
5016                        },
5017                        _normalizeEventName: function(/*String*/ eventName){
5018                                // Generally, eventName should be lower case, unless it is
5019                                // special somehow (e.g. a Mozilla event)
5020                                // ensure 'on'
5021                                return eventName.slice(0,2) != "on" ? "on" + eventName : eventName;
5022                        },
5023                        _nop: function(){},
5024                        _fixEvent: function(/*Event*/ evt, /*DOMNode*/ sender){
5025                                // summary:
5026                                //              normalizes properties on the event object including event
5027                                //              bubbling methods, keystroke normalization, and x/y positions
5028                                // evt:
5029                                //              native event object
5030                                // sender:
5031                                //              node to treat as "currentTarget"
5032                                if(!evt){
5033                                        var w = sender && (sender.ownerDocument || sender.document || sender).parentWindow || window;
5034                                        evt = w.event;
5035                                }
5036                                if(!evt){return(evt);}
5037                                evt.target = evt.srcElement;
5038                                evt.currentTarget = (sender || evt.srcElement);
5039                                evt.layerX = evt.offsetX;
5040                                evt.layerY = evt.offsetY;
5041                                // FIXME: scroll position query is duped from dojo.html to
5042                                // avoid dependency on that entire module. Now that HTML is in
5043                                // Base, we should convert back to something similar there.
5044                                var se = evt.srcElement, doc = (se && se.ownerDocument) || document;
5045                                // DO NOT replace the following to use dojo.body(), in IE, document.documentElement should be used
5046                                // here rather than document.body
5047                                var docBody = ((dojo.isIE < 6) || (doc["compatMode"] == "BackCompat")) ? doc.body : doc.documentElement;
5048                                var offset = dojo._getIeDocumentElementOffset();
5049                                evt.pageX = evt.clientX + dojo._fixIeBiDiScrollLeft(docBody.scrollLeft || 0) - offset.x;
5050                                evt.pageY = evt.clientY + (docBody.scrollTop || 0) - offset.y;
5051                                if(evt.type == "mouseover"){
5052                                        evt.relatedTarget = evt.fromElement;
5053                                }
5054                                if(evt.type == "mouseout"){
5055                                        evt.relatedTarget = evt.toElement;
5056                                }
5057                                if (dojo.isIE < 9 || dojo.isQuirks) {
5058                                        evt.stopPropagation = del._stopPropagation;
5059                                        evt.preventDefault = del._preventDefault;
5060                                }
5061                                return del._fixKeys(evt);
5062                        },
5063                        _fixKeys: function(evt){
5064                                switch(evt.type){
5065                                        case "keypress":
5066                                                var c = ("charCode" in evt ? evt.charCode : evt.keyCode);
5067                                                if (c==10){
5068                                                        // CTRL-ENTER is CTRL-ASCII(10) on IE, but CTRL-ENTER on Mozilla
5069                                                        c=0;
5070                                                        evt.keyCode = 13;
5071                                                }else if(c==13||c==27){
5072                                                        c=0; // Mozilla considers ENTER and ESC non-printable
5073                                                }else if(c==3){
5074                                                        c=99; // Mozilla maps CTRL-BREAK to CTRL-c
5075                                                }
5076                                                // Mozilla sets keyCode to 0 when there is a charCode
5077                                                // but that stops the event on IE.
5078                                                evt.charCode = c;
5079                                                del._setKeyChar(evt);
5080                                                break;
5081                                }
5082                                return evt;
5083                        },
5084                        _stealthKeyDown: function(evt){
5085                                // IE doesn't fire keypress for most non-printable characters.
5086                                // other browsers do, we simulate it here.
5087                                var kp = evt.currentTarget.onkeypress;
5088                                // only works if kp exists and is a dispatcher
5089                                if(!kp || !kp[listenersName]){ return; }
5090                                // munge key/charCode
5091                                var k=evt.keyCode;
5092                                // These are Windows Virtual Key Codes
5093                                // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp
5094                                var unprintable = (k!=13 || (dojo.isIE >= 9 && !dojo.isQuirks)) && k!=32 && k!=27 && (k<48||k>90) && (k<96||k>111) && (k<186||k>192) && (k<219||k>222);
5095
5096                                // synthesize keypress for most unprintables and CTRL-keys
5097                                if(unprintable||evt.ctrlKey){
5098                                        var c = unprintable ? 0 : k;
5099                                        if(evt.ctrlKey){
5100                                                if(k==3 || k==13){
5101                                                        return; // IE will post CTRL-BREAK, CTRL-ENTER as keypress natively
5102                                                }else if(c>95 && c<106){
5103                                                        c -= 48; // map CTRL-[numpad 0-9] to ASCII
5104                                                }else if((!evt.shiftKey)&&(c>=65&&c<=90)){
5105                                                        c += 32; // map CTRL-[A-Z] to lowercase
5106                                                }else{
5107                                                        c = del._punctMap[c] || c; // map other problematic CTRL combinations to ASCII
5108                                                }
5109                                        }
5110                                        // simulate a keypress event
5111                                        var faux = del._synthesizeEvent(evt, {type: 'keypress', faux: true, charCode: c});
5112                                        kp.call(evt.currentTarget, faux);
5113                                        if(dojo.isIE < 9 || (dojo.isIE && dojo.isQuirks)){
5114                                                evt.cancelBubble = faux.cancelBubble;
5115                                        }
5116                                        evt.returnValue = faux.returnValue;
5117                                        _trySetKeyCode(evt, faux.keyCode);
5118                                }
5119                        },
5120                        // Called in Event scope
5121                        _stopPropagation: function(){
5122                                this.cancelBubble = true;
5123                        },
5124                        _preventDefault: function(){
5125                                // Setting keyCode to 0 is the only way to prevent certain keypresses (namely
5126                                // ctrl-combinations that correspond to menu accelerator keys).
5127                                // Otoh, it prevents upstream listeners from getting this information
5128                                // Try to split the difference here by clobbering keyCode only for ctrl
5129                                // combinations. If you still need to access the key upstream, bubbledKeyCode is
5130                                // provided as a workaround.
5131                                this.bubbledKeyCode = this.keyCode;
5132                                if(this.ctrlKey){_trySetKeyCode(this, 0);}
5133                                this.returnValue = false;
5134                        }
5135                });
5136
5137                // override stopEvent for IE
5138                dojo.stopEvent = (dojo.isIE < 9 || dojo.isQuirks) ? function(evt){
5139                        evt = evt || window.event;
5140                        del._stopPropagation.call(evt);
5141                        del._preventDefault.call(evt);
5142                } : dojo.stopEvent;
5143        }
5144
5145        del._synthesizeEvent = function(evt, props){
5146                        var faux = dojo.mixin({}, evt, props);
5147                        del._setKeyChar(faux);
5148                        // FIXME: would prefer to use dojo.hitch: dojo.hitch(evt, evt.preventDefault);
5149                        // but it throws an error when preventDefault is invoked on Safari
5150                        // does Event.preventDefault not support "apply" on Safari?
5151                        faux.preventDefault = function(){ evt.preventDefault(); };
5152                        faux.stopPropagation = function(){ evt.stopPropagation(); };
5153                        return faux;
5154        };
5155
5156                // Opera event normalization
5157        if(dojo.isOpera){
5158                dojo.mixin(del, {
5159                        _fixEvent: function(evt, sender){
5160                                switch(evt.type){
5161                                        case "keypress":
5162                                                var c = evt.which;
5163                                                if(c==3){
5164                                                        c=99; // Mozilla maps CTRL-BREAK to CTRL-c
5165                                                }
5166                                                // can't trap some keys at all, like INSERT and DELETE
5167                                                // there is no differentiating info between DELETE and ".", or INSERT and "-"
5168                                                c = c<41 && !evt.shiftKey ? 0 : c;
5169                                                if(evt.ctrlKey && !evt.shiftKey && c>=65 && c<=90){
5170                                                        // lowercase CTRL-[A-Z] keys
5171                                                        c += 32;
5172                                                }
5173                                                return del._synthesizeEvent(evt, { charCode: c });
5174                                }
5175                                return evt;
5176                        }
5177                });
5178        }
5179
5180                // Webkit event normalization
5181        if(dojo.isWebKit){
5182                                del._add = del.add;
5183                del._remove = del.remove;
5184
5185                dojo.mixin(del, {
5186                        add: function(/*DOMNode*/ node, /*String*/ event, /*Function*/ fp){
5187                                if(!node){return;} // undefined
5188                                var handle = del._add(node, event, fp);
5189                                if(del._normalizeEventName(event) == "keypress"){
5190                                        // we need to listen to onkeydown to synthesize
5191                                        // keypress events that otherwise won't fire
5192                                        // in Safari 3.1+: https://lists.webkit.org/pipermail/webkit-dev/2007-December/002992.html
5193                                        handle._stealthKeyDownHandle = del._add(node, "keydown", function(evt){
5194                                                //A variation on the IE _stealthKeydown function
5195                                                //Synthesize an onkeypress event, but only for unprintable characters.
5196                                                var k=evt.keyCode;
5197                                                // These are Windows Virtual Key Codes
5198                                                // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp
5199                                                var unprintable = k!=13 && k!=32 && (k<48 || k>90) && (k<96 || k>111) && (k<186 || k>192) && (k<219 || k>222);
5200                                                // synthesize keypress for most unprintables and CTRL-keys
5201                                                if(unprintable || evt.ctrlKey){
5202                                                        var c = unprintable ? 0 : k;
5203                                                        if(evt.ctrlKey){
5204                                                                if(k==3 || k==13){
5205                                                                        return; // IE will post CTRL-BREAK, CTRL-ENTER as keypress natively
5206                                                                }else if(c>95 && c<106){
5207                                                                        c -= 48; // map CTRL-[numpad 0-9] to ASCII
5208                                                                }else if(!evt.shiftKey && c>=65 && c<=90){
5209                                                                        c += 32; // map CTRL-[A-Z] to lowercase
5210                                                                }else{
5211                                                                        c = del._punctMap[c] || c; // map other problematic CTRL combinations to ASCII
5212                                                                }
5213                                                        }
5214                                                        // simulate a keypress event
5215                                                        var faux = del._synthesizeEvent(evt, {type: 'keypress', faux: true, charCode: c});
5216                                                        fp.call(evt.currentTarget, faux);
5217                                                }
5218                                        });
5219                                }
5220                                return handle; /*Handle*/
5221                        },
5222
5223                        remove: function(/*DOMNode*/ node, /*String*/ event, /*Handle*/ handle){
5224                                if(node){
5225                                        if(handle._stealthKeyDownHandle){
5226                                                del._remove(node, "keydown", handle._stealthKeyDownHandle);
5227                                        }
5228                                        del._remove(node, event, handle);
5229                                }
5230                        },
5231                        _fixEvent: function(evt, sender){
5232                                switch(evt.type){
5233                                        case "keypress":
5234                                                if(evt.faux){ return evt; }
5235                                                var c = evt.charCode;
5236                                                c = c>=32 ? c : 0;
5237                                                return del._synthesizeEvent(evt, {charCode: c, faux: true});
5238                                }
5239                                return evt;
5240                        }
5241                });
5242                }
5243        })();
5244
5245if(dojo.isIE){
5246        // keep this out of the closure
5247        // closing over 'iel' or 'ieh' b0rks leak prevention
5248        // ls[i] is an index into the master handler array
5249        dojo._ieDispatcher = function(args, sender){
5250                var ap = Array.prototype,
5251                        h = dojo._ie_listener.handlers,
5252                        c = args.callee,
5253                        ls = c[dojo._ieListenersName],
5254                        t = h[c.target];
5255                // return value comes from original target function
5256                var r = t && t.apply(sender, args);
5257                // make local copy of listener array so it's immutable during processing
5258                var lls = [].concat(ls);
5259                // invoke listeners after target function
5260                for(var i in lls){
5261                        var f = h[lls[i]];
5262                        if(!(i in ap) && f){
5263                                f.apply(sender, args);
5264                        }
5265                }
5266                return r;
5267        };
5268        dojo._getIeDispatcher = function(){
5269                // ensure the returned function closes over nothing ("new Function" apparently doesn't close)
5270                return new Function(dojo._scopeName + "._ieDispatcher(arguments, this)"); // function
5271        };
5272        // keep this out of the closure to reduce RAM allocation
5273        dojo._event_listener._fixCallback = function(fp){
5274                var f = dojo._event_listener._fixEvent;
5275                return function(e){ return fp.call(this, f(e, this)); };
5276        };
5277}
5278
5279}
5280
5281if(!dojo._hasResource["dojo._base.html"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
5282dojo._hasResource["dojo._base.html"] = true;
5283dojo.provide("dojo._base.html");
5284
5285
5286
5287// FIXME: need to add unit tests for all the semi-public methods
5288
5289try{
5290        document.execCommand("BackgroundImageCache", false, true);
5291}catch(e){
5292        // sane browsers don't have cache "issues"
5293}
5294
5295// =============================
5296// DOM Functions
5297// =============================
5298
5299/*=====
5300dojo.byId = function(id, doc){
5301        //      summary:
5302        //              Returns DOM node with matching `id` attribute or `null`
5303        //              if not found. If `id` is a DomNode, this function is a no-op.
5304        //
5305        //      id: String|DOMNode
5306        //              A string to match an HTML id attribute or a reference to a DOM Node
5307        //
5308        //      doc: Document?
5309        //              Document to work in. Defaults to the current value of
5310        //              dojo.doc.  Can be used to retrieve
5311        //              node references from other documents.
5312        //
5313        //      example:
5314        //      Look up a node by ID:
5315        //      |       var n = dojo.byId("foo");
5316        //
5317        //      example:
5318        //      Check if a node exists, and use it.
5319        //      |       var n = dojo.byId("bar");
5320        //      |       if(n){ doStuff() ... }
5321        //
5322        //      example:
5323        //      Allow string or DomNode references to be passed to a custom function:
5324        //      |       var foo = function(nodeOrId){
5325        //      |               nodeOrId = dojo.byId(nodeOrId);
5326        //      |               // ... more stuff
5327        //      |       }
5328=====*/
5329
5330if(dojo.isIE){
5331        dojo.byId = function(id, doc){
5332                if(typeof id != "string"){
5333                        return id;
5334                }
5335                var _d = doc || dojo.doc, te = _d.getElementById(id);
5336                // attributes.id.value is better than just id in case the
5337                // user has a name=id inside a form
5338                if(te && (te.attributes.id.value == id || te.id == id)){
5339                        return te;
5340                }else{
5341                        var eles = _d.all[id];
5342                        if(!eles || eles.nodeName){
5343                                eles = [eles];
5344                        }
5345                        // if more than 1, choose first with the correct id
5346                        var i=0;
5347                        while((te=eles[i++])){
5348                                if((te.attributes && te.attributes.id && te.attributes.id.value == id)
5349                                        || te.id == id){
5350                                        return te;
5351                                }
5352                        }
5353                }
5354        };
5355}else{
5356        dojo.byId = function(id, doc){
5357                // inline'd type check.
5358                // be sure to return null per documentation, to match IE branch.
5359                return ((typeof id == "string") ? (doc || dojo.doc).getElementById(id) : id) || null; // DomNode
5360        };
5361}
5362/*=====
5363};
5364=====*/
5365
5366(function(){
5367        var d = dojo;
5368        var byId = d.byId;
5369
5370        var _destroyContainer = null,
5371                _destroyDoc;
5372                d.addOnWindowUnload(function(){
5373                _destroyContainer = null; //prevent IE leak
5374        });
5375
5376/*=====
5377        dojo._destroyElement = function(node){
5378                // summary:
5379                //              Existing alias for `dojo.destroy`. Deprecated, will be removed
5380                //              in 2.0
5381        }
5382=====*/
5383        dojo._destroyElement = dojo.destroy = function(/*String|DomNode*/node){
5384                //      summary:
5385                //              Removes a node from its parent, clobbering it and all of its
5386                //              children.
5387                //
5388                //      description:
5389                //              Removes a node from its parent, clobbering it and all of its
5390                //              children. Function only works with DomNodes, and returns nothing.
5391                //
5392                //      node:
5393                //              A String ID or DomNode reference of the element to be destroyed
5394                //
5395                //      example:
5396                //      Destroy a node byId:
5397                //      |       dojo.destroy("someId");
5398                //
5399                //      example:
5400                //      Destroy all nodes in a list by reference:
5401                //      |       dojo.query(".someNode").forEach(dojo.destroy);
5402
5403                node = byId(node);
5404                try{
5405                        var doc = node.ownerDocument;
5406                        // cannot use _destroyContainer.ownerDocument since this can throw an exception on IE
5407                        if(!_destroyContainer || _destroyDoc != doc){
5408                                _destroyContainer = doc.createElement("div");
5409                                _destroyDoc = doc;
5410                        }
5411                        _destroyContainer.appendChild(node.parentNode ? node.parentNode.removeChild(node) : node);
5412                        // NOTE: see http://trac.dojotoolkit.org/ticket/2931. This may be a bug and not a feature
5413                        _destroyContainer.innerHTML = "";
5414                }catch(e){
5415                        /* squelch */
5416                }
5417        };
5418
5419        dojo.isDescendant = function(/*DomNode|String*/node, /*DomNode|String*/ancestor){
5420                //      summary:
5421                //              Returns true if node is a descendant of ancestor
5422                //      node: string id or node reference to test
5423                //      ancestor: string id or node reference of potential parent to test against
5424                //
5425                // example:
5426                //      Test is node id="bar" is a descendant of node id="foo"
5427                //      |       if(dojo.isDescendant("bar", "foo")){ ... }
5428                try{
5429                        node = byId(node);
5430                        ancestor = byId(ancestor);
5431                        while(node){
5432                                if(node == ancestor){
5433                                        return true; // Boolean
5434                                }
5435                                node = node.parentNode;
5436                        }
5437                }catch(e){ /* squelch, return false */ }
5438                return false; // Boolean
5439        };
5440
5441        dojo.setSelectable = function(/*DomNode|String*/node, /*Boolean*/selectable){
5442                //      summary:
5443                //              Enable or disable selection on a node
5444                //      node:
5445                //              id or reference to node
5446                //      selectable:
5447                //              state to put the node in. false indicates unselectable, true
5448                //              allows selection.
5449                //      example:
5450                //      Make the node id="bar" unselectable
5451                //      |       dojo.setSelectable("bar");
5452                //      example:
5453                //      Make the node id="bar" selectable
5454                //      |       dojo.setSelectable("bar", true);
5455                node = byId(node);
5456                                if(d.isMozilla){
5457                        node.style.MozUserSelect = selectable ? "" : "none";
5458                }else if(d.isKhtml || d.isWebKit){
5459                                        node.style.KhtmlUserSelect = selectable ? "auto" : "none";
5460                                }else if(d.isIE){
5461                        var v = (node.unselectable = selectable ? "" : "on");
5462                        d.query("*", node).forEach("item.unselectable = '"+v+"'");
5463                }
5464                                //FIXME: else?  Opera?
5465        };
5466
5467        var _insertBefore = function(/*DomNode*/node, /*DomNode*/ref){
5468                var parent = ref.parentNode;
5469                if(parent){
5470                        parent.insertBefore(node, ref);
5471                }
5472        };
5473
5474        var _insertAfter = function(/*DomNode*/node, /*DomNode*/ref){
5475                //      summary:
5476                //              Try to insert node after ref
5477                var parent = ref.parentNode;
5478                if(parent){
5479                        if(parent.lastChild == ref){
5480                                parent.appendChild(node);
5481                        }else{
5482                                parent.insertBefore(node, ref.nextSibling);
5483                        }
5484                }
5485        };
5486
5487        dojo.place = function(node, refNode, position){
5488                //      summary:
5489                //              Attempt to insert node into the DOM, choosing from various positioning options.
5490                //              Returns the first argument resolved to a DOM node.
5491                //
5492                //      node: String|DomNode
5493                //              id or node reference, or HTML fragment starting with "<" to place relative to refNode
5494                //
5495                //      refNode: String|DomNode
5496                //              id or node reference to use as basis for placement
5497                //
5498                //      position: String|Number?
5499                //              string noting the position of node relative to refNode or a
5500                //              number indicating the location in the childNodes collection of refNode.
5501                //              Accepted string values are:
5502                //      |       * before
5503                //      |       * after
5504                //      |       * replace
5505                //      |       * only
5506                //      |       * first
5507                //      |       * last
5508                //              "first" and "last" indicate positions as children of refNode, "replace" replaces refNode,
5509                //              "only" replaces all children.  position defaults to "last" if not specified
5510                //
5511                //      returns: DomNode
5512                //              Returned values is the first argument resolved to a DOM node.
5513                //
5514                //              .place() is also a method of `dojo.NodeList`, allowing `dojo.query` node lookups.
5515                //
5516                // example:
5517                //              Place a node by string id as the last child of another node by string id:
5518                //      |       dojo.place("someNode", "anotherNode");
5519                //
5520                // example:
5521                //              Place a node by string id before another node by string id
5522                //      |       dojo.place("someNode", "anotherNode", "before");
5523                //
5524                // example:
5525                //              Create a Node, and place it in the body element (last child):
5526                //      |       dojo.place("<div></div>", dojo.body());
5527                //
5528                // example:
5529                //              Put a new LI as the first child of a list by id:
5530                //      |       dojo.place("<li></li>", "someUl", "first");
5531
5532                refNode = byId(refNode);
5533                if(typeof node == "string"){ // inline'd type check
5534                        node = /^\s*</.test(node) ? d._toDom(node, refNode.ownerDocument) : byId(node);
5535                }
5536                if(typeof position == "number"){ // inline'd type check
5537                        var cn = refNode.childNodes;
5538                        if(!cn.length || cn.length <= position){
5539                                refNode.appendChild(node);
5540                        }else{
5541                                _insertBefore(node, cn[position < 0 ? 0 : position]);
5542                        }
5543                }else{
5544                        switch(position){
5545                                case "before":
5546                                        _insertBefore(node, refNode);
5547                                        break;
5548                                case "after":
5549                                        _insertAfter(node, refNode);
5550                                        break;
5551                                case "replace":
5552                                        refNode.parentNode.replaceChild(node, refNode);
5553                                        break;
5554                                case "only":
5555                                        d.empty(refNode);
5556                                        refNode.appendChild(node);
5557                                        break;
5558                                case "first":
5559                                        if(refNode.firstChild){
5560                                                _insertBefore(node, refNode.firstChild);
5561                                                break;
5562                                        }
5563                                        // else fallthrough...
5564                                default: // aka: last
5565                                        refNode.appendChild(node);
5566                        }
5567                }
5568                return node; // DomNode
5569        };
5570
5571        // Box functions will assume this model.
5572        // On IE/Opera, BORDER_BOX will be set if the primary document is in quirks mode.
5573        // Can be set to change behavior of box setters.
5574
5575        // can be either:
5576        //      "border-box"
5577        //      "content-box" (default)
5578        dojo.boxModel = "content-box";
5579
5580        // We punt per-node box mode testing completely.
5581        // If anybody cares, we can provide an additional (optional) unit
5582        // that overrides existing code to include per-node box sensitivity.
5583
5584        // Opera documentation claims that Opera 9 uses border-box in BackCompat mode.
5585        // but experiments (Opera 9.10.8679 on Windows Vista) indicate that it actually continues to use content-box.
5586        // IIRC, earlier versions of Opera did in fact use border-box.
5587        // Opera guys, this is really confusing. Opera being broken in quirks mode is not our fault.
5588
5589                if(d.isIE /*|| dojo.isOpera*/){
5590                // client code may have to adjust if compatMode varies across iframes
5591                d.boxModel = document.compatMode == "BackCompat" ? "border-box" : "content-box";
5592        }
5593
5594        // =============================
5595        // Style Functions
5596        // =============================
5597
5598        // getComputedStyle drives most of the style code.
5599        // Wherever possible, reuse the returned object.
5600        //
5601        // API functions below that need to access computed styles accept an
5602        // optional computedStyle parameter.
5603        // If this parameter is omitted, the functions will call getComputedStyle themselves.
5604        // This way, calling code can access computedStyle once, and then pass the reference to
5605        // multiple API functions.
5606
5607/*=====
5608        dojo.getComputedStyle = function(node){
5609                //      summary:
5610                //              Returns a "computed style" object.
5611                //
5612                //      description:
5613                //              Gets a "computed style" object which can be used to gather
5614                //              information about the current state of the rendered node.
5615                //
5616                //              Note that this may behave differently on different browsers.
5617                //              Values may have different formats and value encodings across
5618                //              browsers.
5619                //
5620                //              Note also that this method is expensive.  Wherever possible,
5621                //              reuse the returned object.
5622                //
5623                //              Use the dojo.style() method for more consistent (pixelized)
5624                //              return values.
5625                //
5626                //      node: DOMNode
5627                //              A reference to a DOM node. Does NOT support taking an
5628                //              ID string for speed reasons.
5629                //      example:
5630                //      |       dojo.getComputedStyle(dojo.byId('foo')).borderWidth;
5631                //
5632                //      example:
5633                //      Reusing the returned object, avoiding multiple lookups:
5634                //      |       var cs = dojo.getComputedStyle(dojo.byId("someNode"));
5635                //      |       var w = cs.width, h = cs.height;
5636                return; // CSS2Properties
5637        }
5638=====*/
5639
5640        // Although we normally eschew argument validation at this
5641        // level, here we test argument 'node' for (duck)type,
5642        // by testing nodeType, ecause 'document' is the 'parentNode' of 'body'
5643        // it is frequently sent to this function even
5644        // though it is not Element.
5645        var gcs;
5646                if(d.isWebKit){
5647                        gcs = function(/*DomNode*/node){
5648                        var s;
5649                        if(node.nodeType == 1){
5650                                var dv = node.ownerDocument.defaultView;
5651                                s = dv.getComputedStyle(node, null);
5652                                if(!s && node.style){
5653                                        node.style.display = "";
5654                                        s = dv.getComputedStyle(node, null);
5655                                }
5656                        }
5657                        return s || {};
5658                };
5659                }else if(d.isIE){
5660                gcs = function(node){
5661                        // IE (as of 7) doesn't expose Element like sane browsers
5662                        return node.nodeType == 1 /* ELEMENT_NODE*/ ? node.currentStyle : {};
5663                };
5664        }else{
5665                gcs = function(node){
5666                        return node.nodeType == 1 ?
5667                                node.ownerDocument.defaultView.getComputedStyle(node, null) : {};
5668                };
5669        }
5670                dojo.getComputedStyle = gcs;
5671
5672                if(!d.isIE){
5673                        d._toPixelValue = function(element, value){
5674                        // style values can be floats, client code may want
5675                        // to round for integer pixels.
5676                        return parseFloat(value) || 0;
5677                };
5678                }else{
5679                d._toPixelValue = function(element, avalue){
5680                        if(!avalue){ return 0; }
5681                        // on IE7, medium is usually 4 pixels
5682                        if(avalue == "medium"){ return 4; }
5683                        // style values can be floats, client code may
5684                        // want to round this value for integer pixels.
5685                        if(avalue.slice && avalue.slice(-2) == 'px'){ return parseFloat(avalue); }
5686                        with(element){
5687                                var sLeft = style.left;
5688                                var rsLeft = runtimeStyle.left;
5689                                runtimeStyle.left = currentStyle.left;
5690                                try{
5691                                        // 'avalue' may be incompatible with style.left, which can cause IE to throw
5692                                        // this has been observed for border widths using "thin", "medium", "thick" constants
5693                                        // those particular constants could be trapped by a lookup
5694                                        // but perhaps there are more
5695                                        style.left = avalue;
5696                                        avalue = style.pixelLeft;
5697                                }catch(e){
5698                                        avalue = 0;
5699                                }
5700                                style.left = sLeft;
5701                                runtimeStyle.left = rsLeft;
5702                        }
5703                        return avalue;
5704                };
5705        }
5706                var px = d._toPixelValue;
5707
5708        // FIXME: there opacity quirks on FF that we haven't ported over. Hrm.
5709        /*=====
5710        dojo._getOpacity = function(node){
5711                        //      summary:
5712                        //              Returns the current opacity of the passed node as a
5713                        //              floating-point value between 0 and 1.
5714                        //      node: DomNode
5715                        //              a reference to a DOM node. Does NOT support taking an
5716                        //              ID string for speed reasons.
5717                        //      returns: Number between 0 and 1
5718                        return; // Number
5719        }
5720        =====*/
5721
5722                var astr = "DXImageTransform.Microsoft.Alpha";
5723        var af = function(n, f){
5724                try{
5725                        return n.filters.item(astr);
5726                }catch(e){
5727                        return f ? {} : null;
5728                }
5729        };
5730
5731                dojo._getOpacity =
5732                        d.isIE < 9 ? function(node){
5733                        try{
5734                                return af(node).Opacity / 100; // Number
5735                        }catch(e){
5736                                return 1; // Number
5737                        }
5738                } :
5739                        function(node){
5740                        return gcs(node).opacity;
5741                };
5742
5743        /*=====
5744        dojo._setOpacity = function(node, opacity){
5745                        //      summary:
5746                        //              set the opacity of the passed node portably. Returns the
5747                        //              new opacity of the node.
5748                        //      node: DOMNode
5749                        //              a reference to a DOM node. Does NOT support taking an
5750                        //              ID string for performance reasons.
5751                        //      opacity: Number
5752                        //              A Number between 0 and 1. 0 specifies transparent.
5753                        //      returns: Number between 0 and 1
5754                        return; // Number
5755        }
5756        =====*/
5757
5758        dojo._setOpacity =
5759                                d.isIE < 9 ? function(/*DomNode*/node, /*Number*/opacity){
5760                        var ov = opacity * 100, opaque = opacity == 1;
5761                        node.style.zoom = opaque ? "" : 1;
5762
5763                        if(!af(node)){
5764                                if(opaque){
5765                                        return opacity;
5766                                }
5767                                node.style.filter += " progid:" + astr + "(Opacity=" + ov + ")";
5768                        }else{
5769                                af(node, 1).Opacity = ov;
5770                        }
5771
5772                        // on IE7 Alpha(Filter opacity=100) makes text look fuzzy so disable it altogether (bug #2661),
5773                        //but still update the opacity value so we can get a correct reading if it is read later.
5774                        af(node, 1).Enabled = !opaque;
5775
5776                        if(node.nodeName.toLowerCase() == "tr"){
5777                                d.query("> td", node).forEach(function(i){
5778                                        d._setOpacity(i, opacity);
5779                                });
5780                        }
5781                        return opacity;
5782                } :
5783                                function(node, opacity){
5784                        return node.style.opacity = opacity;
5785                };
5786
5787        var _pixelNamesCache = {
5788                left: true, top: true
5789        };
5790        var _pixelRegExp = /margin|padding|width|height|max|min|offset/;  // |border
5791        var _toStyleValue = function(node, type, value){
5792                type = type.toLowerCase(); // FIXME: should we really be doing string case conversion here? Should we cache it? Need to profile!
5793                                if(d.isIE){
5794                        if(value == "auto"){
5795                                if(type == "height"){ return node.offsetHeight; }
5796                                if(type == "width"){ return node.offsetWidth; }
5797                        }
5798                        if(type == "fontweight"){
5799                                switch(value){
5800                                        case 700: return "bold";
5801                                        case 400:
5802                                        default: return "normal";
5803                                }
5804                        }
5805                }
5806                                if(!(type in _pixelNamesCache)){
5807                        _pixelNamesCache[type] = _pixelRegExp.test(type);
5808                }
5809                return _pixelNamesCache[type] ? px(node, value) : value;
5810        };
5811
5812        var _floatStyle = d.isIE ? "styleFloat" : "cssFloat",
5813                _floatAliases = { "cssFloat": _floatStyle, "styleFloat": _floatStyle, "float": _floatStyle }
5814        ;
5815
5816        // public API
5817
5818        dojo.style = function(  /*DomNode|String*/ node,
5819                                                        /*String?|Object?*/ style,
5820                                                        /*String?*/ value){
5821                //      summary:
5822                //              Accesses styles on a node. If 2 arguments are
5823                //              passed, acts as a getter. If 3 arguments are passed, acts
5824                //              as a setter.
5825                //      description:
5826                //              Getting the style value uses the computed style for the node, so the value
5827                //              will be a calculated value, not just the immediate node.style value.
5828                //              Also when getting values, use specific style names,
5829                //              like "borderBottomWidth" instead of "border" since compound values like
5830                //              "border" are not necessarily reflected as expected.
5831                //              If you want to get node dimensions, use `dojo.marginBox()`,
5832                //              `dojo.contentBox()` or `dojo.position()`.
5833                //      node:
5834                //              id or reference to node to get/set style for
5835                //      style:
5836                //              the style property to set in DOM-accessor format
5837                //              ("borderWidth", not "border-width") or an object with key/value
5838                //              pairs suitable for setting each property.
5839                //      value:
5840                //              If passed, sets value on the node for style, handling
5841                //              cross-browser concerns.  When setting a pixel value,
5842                //              be sure to include "px" in the value. For instance, top: "200px".
5843                //              Otherwise, in some cases, some browsers will not apply the style.
5844                //      example:
5845                //              Passing only an ID or node returns the computed style object of
5846                //              the node:
5847                //      |       dojo.style("thinger");
5848                //      example:
5849                //              Passing a node and a style property returns the current
5850                //              normalized, computed value for that property:
5851                //      |       dojo.style("thinger", "opacity"); // 1 by default
5852                //
5853                //      example:
5854                //              Passing a node, a style property, and a value changes the
5855                //              current display of the node and returns the new computed value
5856                //      |       dojo.style("thinger", "opacity", 0.5); // == 0.5
5857                //
5858                //      example:
5859                //              Passing a node, an object-style style property sets each of the values in turn and returns the computed style object of the node:
5860                //      |       dojo.style("thinger", {
5861                //      |               "opacity": 0.5,
5862                //      |               "border": "3px solid black",
5863                //      |               "height": "300px"
5864                //      |       });
5865                //
5866                //      example:
5867                //              When the CSS style property is hyphenated, the JavaScript property is camelCased.
5868                //              font-size becomes fontSize, and so on.
5869                //      |       dojo.style("thinger",{
5870                //      |               fontSize:"14pt",
5871                //      |               letterSpacing:"1.2em"
5872                //      |       });
5873                //
5874                //      example:
5875                //              dojo.NodeList implements .style() using the same syntax, omitting the "node" parameter, calling
5876                //              dojo.style() on every element of the list. See: `dojo.query()` and `dojo.NodeList()`
5877                //      |       dojo.query(".someClassName").style("visibility","hidden");
5878                //      |       // or
5879                //      |       dojo.query("#baz > div").style({
5880                //      |               opacity:0.75,
5881                //      |               fontSize:"13pt"
5882                //      |       });
5883
5884                var n = byId(node), args = arguments.length, op = (style == "opacity");
5885                style = _floatAliases[style] || style;
5886                if(args == 3){
5887                        return op ? d._setOpacity(n, value) : n.style[style] = value; /*Number*/
5888                }
5889                if(args == 2 && op){
5890                        return d._getOpacity(n);
5891                }
5892                var s = gcs(n);
5893                if(args == 2 && typeof style != "string"){ // inline'd type check
5894                        for(var x in style){
5895                                d.style(node, x, style[x]);
5896                        }
5897                        return s;
5898                }
5899                return (args == 1) ? s : _toStyleValue(n, style, s[style] || n.style[style]); /* CSS2Properties||String||Number */
5900        };
5901
5902        // =============================
5903        // Box Functions
5904        // =============================
5905
5906        dojo._getPadExtents = function(/*DomNode*/n, /*Object*/computedStyle){
5907                //      summary:
5908                //              Returns object with special values specifically useful for node
5909                //              fitting.
5910                //      description:
5911                //              Returns an object with `w`, `h`, `l`, `t` properties:
5912                //      |               l/t = left/top padding (respectively)
5913                //      |               w = the total of the left and right padding
5914                //      |               h = the total of the top and bottom padding
5915                //              If 'node' has position, l/t forms the origin for child nodes.
5916                //              The w/h are used for calculating boxes.
5917                //              Normally application code will not need to invoke this
5918                //              directly, and will use the ...box... functions instead.
5919                var
5920                        s = computedStyle||gcs(n),
5921                        l = px(n, s.paddingLeft),
5922                        t = px(n, s.paddingTop);
5923                return {
5924                        l: l,
5925                        t: t,
5926                        w: l+px(n, s.paddingRight),
5927                        h: t+px(n, s.paddingBottom)
5928                };
5929        };
5930
5931        dojo._getBorderExtents = function(/*DomNode*/n, /*Object*/computedStyle){
5932                //      summary:
5933                //              returns an object with properties useful for noting the border
5934                //              dimensions.
5935                //      description:
5936                //              * l/t = the sum of left/top border (respectively)
5937                //              * w = the sum of the left and right border
5938                //              * h = the sum of the top and bottom border
5939                //
5940                //              The w/h are used for calculating boxes.
5941                //              Normally application code will not need to invoke this
5942                //              directly, and will use the ...box... functions instead.
5943                var
5944                        ne = "none",
5945                        s = computedStyle||gcs(n),
5946                        bl = (s.borderLeftStyle != ne ? px(n, s.borderLeftWidth) : 0),
5947                        bt = (s.borderTopStyle != ne ? px(n, s.borderTopWidth) : 0);
5948                return {
5949                        l: bl,
5950                        t: bt,
5951                        w: bl + (s.borderRightStyle!=ne ? px(n, s.borderRightWidth) : 0),
5952                        h: bt + (s.borderBottomStyle!=ne ? px(n, s.borderBottomWidth) : 0)
5953                };
5954        };
5955
5956        dojo._getPadBorderExtents = function(/*DomNode*/n, /*Object*/computedStyle){
5957                //      summary:
5958                //              Returns object with properties useful for box fitting with
5959                //              regards to padding.
5960                // description:
5961                //              * l/t = the sum of left/top padding and left/top border (respectively)
5962                //              * w = the sum of the left and right padding and border
5963                //              * h = the sum of the top and bottom padding and border
5964                //
5965                //              The w/h are used for calculating boxes.
5966                //              Normally application code will not need to invoke this
5967                //              directly, and will use the ...box... functions instead.
5968                var
5969                        s = computedStyle||gcs(n),
5970                        p = d._getPadExtents(n, s),
5971                        b = d._getBorderExtents(n, s);
5972                return {
5973                        l: p.l + b.l,
5974                        t: p.t + b.t,
5975                        w: p.w + b.w,
5976                        h: p.h + b.h
5977                };
5978        };
5979
5980        dojo._getMarginExtents = function(n, computedStyle){
5981                //      summary:
5982                //              returns object with properties useful for box fitting with
5983                //              regards to box margins (i.e., the outer-box).
5984                //
5985                //              * l/t = marginLeft, marginTop, respectively
5986                //              * w = total width, margin inclusive
5987                //              * h = total height, margin inclusive
5988                //
5989                //              The w/h are used for calculating boxes.
5990                //              Normally application code will not need to invoke this
5991                //              directly, and will use the ...box... functions instead.
5992                var
5993                        s = computedStyle||gcs(n),
5994                        l = px(n, s.marginLeft),
5995                        t = px(n, s.marginTop),
5996                        r = px(n, s.marginRight),
5997                        b = px(n, s.marginBottom);
5998                if(d.isWebKit && (s.position != "absolute")){
5999                        // FIXME: Safari's version of the computed right margin
6000                        // is the space between our right edge and the right edge
6001                        // of our offsetParent.
6002                        // What we are looking for is the actual margin value as
6003                        // determined by CSS.
6004                        // Hack solution is to assume left/right margins are the same.
6005                        r = l;
6006                }
6007                return {
6008                        l: l,
6009                        t: t,
6010                        w: l+r,
6011                        h: t+b
6012                };
6013        };
6014
6015        // Box getters work in any box context because offsetWidth/clientWidth
6016        // are invariant wrt box context
6017        //
6018        // They do *not* work for display: inline objects that have padding styles
6019        // because the user agent ignores padding (it's bogus styling in any case)
6020        //
6021        // Be careful with IMGs because they are inline or block depending on
6022        // browser and browser mode.
6023
6024        // Although it would be easier to read, there are not separate versions of
6025        // _getMarginBox for each browser because:
6026        // 1. the branching is not expensive
6027        // 2. factoring the shared code wastes cycles (function call overhead)
6028        // 3. duplicating the shared code wastes bytes
6029
6030        dojo._getMarginBox = function(/*DomNode*/node, /*Object*/computedStyle){
6031                // summary:
6032                //              returns an object that encodes the width, height, left and top
6033                //              positions of the node's margin box.
6034                var s = computedStyle || gcs(node), me = d._getMarginExtents(node, s);
6035                var l = node.offsetLeft - me.l, t = node.offsetTop - me.t, p = node.parentNode;
6036                                if(d.isMoz){
6037                        // Mozilla:
6038                        // If offsetParent has a computed overflow != visible, the offsetLeft is decreased
6039                        // by the parent's border.
6040                        // We don't want to compute the parent's style, so instead we examine node's
6041                        // computed left/top which is more stable.
6042                        var sl = parseFloat(s.left), st = parseFloat(s.top);
6043                        if(!isNaN(sl) && !isNaN(st)){
6044                                l = sl, t = st;
6045                        }else{
6046                                // If child's computed left/top are not parseable as a number (e.g. "auto"), we
6047                                // have no choice but to examine the parent's computed style.
6048                                if(p && p.style){
6049                                        var pcs = gcs(p);
6050                                        if(pcs.overflow != "visible"){
6051                                                var be = d._getBorderExtents(p, pcs);
6052                                                l += be.l, t += be.t;
6053                                        }
6054                                }
6055                        }
6056                }else if(d.isOpera || (d.isIE > 7 && !d.isQuirks)){
6057                        // On Opera and IE 8, offsetLeft/Top includes the parent's border
6058                        if(p){
6059                                be = d._getBorderExtents(p);
6060                                l -= be.l;
6061                                t -= be.t;
6062                        }
6063                }
6064                                return {
6065                        l: l,
6066                        t: t,
6067                        w: node.offsetWidth + me.w,
6068                        h: node.offsetHeight + me.h
6069                };
6070        }
6071
6072        dojo._getMarginSize = function(/*DomNode*/node, /*Object*/computedStyle){
6073                // summary:
6074                //      returns an object that encodes the width and height of
6075                //      the node's margin box
6076                node = byId(node);
6077                var me = d._getMarginExtents(node, computedStyle || gcs(node));
6078
6079                var size = node.getBoundingClientRect();
6080                return {
6081                        w: (size.right - size.left) + me.w,
6082                        h: (size.bottom - size.top) + me.h
6083                }
6084        }
6085
6086        dojo._getContentBox = function(node, computedStyle){
6087                // summary:
6088                //              Returns an object that encodes the width, height, left and top
6089                //              positions of the node's content box, irrespective of the
6090                //              current box model.
6091
6092                // clientWidth/Height are important since the automatically account for scrollbars
6093                // fallback to offsetWidth/Height for special cases (see #3378)
6094                var s = computedStyle || gcs(node),
6095                        pe = d._getPadExtents(node, s),
6096                        be = d._getBorderExtents(node, s),
6097                        w = node.clientWidth,
6098                        h
6099                ;
6100                if(!w){
6101                        w = node.offsetWidth, h = node.offsetHeight;
6102                }else{
6103                        h = node.clientHeight, be.w = be.h = 0;
6104                }
6105                // On Opera, offsetLeft includes the parent's border
6106                                if(d.isOpera){ pe.l += be.l; pe.t += be.t; };
6107                                return {
6108                        l: pe.l,
6109                        t: pe.t,
6110                        w: w - pe.w - be.w,
6111                        h: h - pe.h - be.h
6112                };
6113        };
6114
6115        dojo._getBorderBox = function(node, computedStyle){
6116                var s = computedStyle || gcs(node),
6117                        pe = d._getPadExtents(node, s),
6118                        cb = d._getContentBox(node, s)
6119                ;
6120                return {
6121                        l: cb.l - pe.l,
6122                        t: cb.t - pe.t,
6123                        w: cb.w + pe.w,
6124                        h: cb.h + pe.h
6125                };
6126        };
6127
6128        // Box setters depend on box context because interpretation of width/height styles
6129        // vary wrt box context.
6130        //
6131        // The value of dojo.boxModel is used to determine box context.
6132        // dojo.boxModel can be set directly to change behavior.
6133        //
6134        // Beware of display: inline objects that have padding styles
6135        // because the user agent ignores padding (it's a bogus setup anyway)
6136        //
6137        // Be careful with IMGs because they are inline or block depending on
6138        // browser and browser mode.
6139        //
6140        // Elements other than DIV may have special quirks, like built-in
6141        // margins or padding, or values not detectable via computedStyle.
6142        // In particular, margins on TABLE do not seems to appear
6143        // at all in computedStyle on Mozilla.
6144
6145        dojo._setBox = function(/*DomNode*/node, /*Number?*/l, /*Number?*/t, /*Number?*/w, /*Number?*/h, /*String?*/u){
6146                //      summary:
6147                //              sets width/height/left/top in the current (native) box-model
6148                //              dimentions. Uses the unit passed in u.
6149                //      node:
6150                //              DOM Node reference. Id string not supported for performance
6151                //              reasons.
6152                //      l:
6153                //              left offset from parent.
6154                //      t:
6155                //              top offset from parent.
6156                //      w:
6157                //              width in current box model.
6158                //      h:
6159                //              width in current box model.
6160                //      u:
6161                //              unit measure to use for other measures. Defaults to "px".
6162                u = u || "px";
6163                var s = node.style;
6164                if(!isNaN(l)){ s.left = l + u; }
6165                if(!isNaN(t)){ s.top = t + u; }
6166                if(w >= 0){ s.width = w + u; }
6167                if(h >= 0){ s.height = h + u; }
6168        };
6169
6170        dojo._isButtonTag = function(/*DomNode*/node) {
6171                // summary:
6172                //              True if the node is BUTTON or INPUT.type="button".
6173                return node.tagName == "BUTTON"
6174                        || node.tagName=="INPUT" && (node.getAttribute("type")||'').toUpperCase() == "BUTTON"; // boolean
6175        };
6176
6177        dojo._usesBorderBox = function(/*DomNode*/node){
6178                //      summary:
6179                //              True if the node uses border-box layout.
6180
6181                // We could test the computed style of node to see if a particular box
6182                // has been specified, but there are details and we choose not to bother.
6183
6184                // TABLE and BUTTON (and INPUT type=button) are always border-box by default.
6185                // If you have assigned a different box to either one via CSS then
6186                // box functions will break.
6187
6188                var n = node.tagName;
6189                return d.boxModel=="border-box" || n=="TABLE" || d._isButtonTag(node); // boolean
6190        };
6191
6192        dojo._setContentSize = function(/*DomNode*/node, /*Number*/widthPx, /*Number*/heightPx, /*Object*/computedStyle){
6193                //      summary:
6194                //              Sets the size of the node's contents, irrespective of margins,
6195                //              padding, or borders.
6196                if(d._usesBorderBox(node)){
6197                        var pb = d._getPadBorderExtents(node, computedStyle);
6198                        if(widthPx >= 0){ widthPx += pb.w; }
6199                        if(heightPx >= 0){ heightPx += pb.h; }
6200                }
6201                d._setBox(node, NaN, NaN, widthPx, heightPx);
6202        };
6203
6204        dojo._setMarginBox = function(/*DomNode*/node,  /*Number?*/leftPx, /*Number?*/topPx,
6205                                                                                                        /*Number?*/widthPx, /*Number?*/heightPx,
6206                                                                                                        /*Object*/computedStyle){
6207                //      summary:
6208                //              sets the size of the node's margin box and placement
6209                //              (left/top), irrespective of box model. Think of it as a
6210                //              passthrough to dojo._setBox that handles box-model vagaries for
6211                //              you.
6212
6213                var s = computedStyle || gcs(node),
6214                // Some elements have special padding, margin, and box-model settings.
6215                // To use box functions you may need to set padding, margin explicitly.
6216                // Controlling box-model is harder, in a pinch you might set dojo.boxModel.
6217                        bb = d._usesBorderBox(node),
6218                        pb = bb ? _nilExtents : d._getPadBorderExtents(node, s)
6219                ;
6220                if(d.isWebKit){
6221                        // on Safari (3.1.2), button nodes with no explicit size have a default margin
6222                        // setting an explicit size eliminates the margin.
6223                        // We have to swizzle the width to get correct margin reading.
6224                        if(d._isButtonTag(node)){
6225                                var ns = node.style;
6226                                if(widthPx >= 0 && !ns.width) { ns.width = "4px"; }
6227                                if(heightPx >= 0 && !ns.height) { ns.height = "4px"; }
6228                        }
6229                }
6230                var mb = d._getMarginExtents(node, s);
6231                if(widthPx >= 0){ widthPx = Math.max(widthPx - pb.w - mb.w, 0); }
6232                if(heightPx >= 0){ heightPx = Math.max(heightPx - pb.h - mb.h, 0); }
6233                d._setBox(node, leftPx, topPx, widthPx, heightPx);
6234        };
6235
6236        var _nilExtents = { l:0, t:0, w:0, h:0 };
6237
6238        // public API
6239
6240        dojo.marginBox = function(/*DomNode|String*/node, /*Object?*/box){
6241                //      summary:
6242                //              Getter/setter for the margin-box of node.
6243                //      description:
6244                //              Getter/setter for the margin-box of node.
6245                //              Returns an object in the expected format of box (regardless
6246                //              if box is passed). The object might look like:
6247                //                      `{ l: 50, t: 200, w: 300: h: 150 }`
6248                //              for a node offset from its parent 50px to the left, 200px from
6249                //              the top with a margin width of 300px and a margin-height of
6250                //              150px.
6251                //      node:
6252                //              id or reference to DOM Node to get/set box for
6253                //      box:
6254                //              If passed, denotes that dojo.marginBox() should
6255                //              update/set the margin box for node. Box is an object in the
6256                //              above format. All properties are optional if passed.
6257                //      example:
6258                //      Retrieve the marginbox of a passed node
6259                //      |       var box = dojo.marginBox("someNodeId");
6260                //      |       console.dir(box);
6261                //
6262                //      example:
6263                //      Set a node's marginbox to the size of another node
6264                //      |       var box = dojo.marginBox("someNodeId");
6265                //      |       dojo.marginBox("someOtherNode", box);
6266
6267                var n = byId(node), s = gcs(n), b = box;
6268                return !b ? d._getMarginBox(n, s) : d._setMarginBox(n, b.l, b.t, b.w, b.h, s); // Object
6269        };
6270
6271        dojo.contentBox = function(/*DomNode|String*/node, /*Object?*/box){
6272                //      summary:
6273                //              Getter/setter for the content-box of node.
6274                //      description:
6275                //              Returns an object in the expected format of box (regardless if box is passed).
6276                //              The object might look like:
6277                //                      `{ l: 50, t: 200, w: 300: h: 150 }`
6278                //              for a node offset from its parent 50px to the left, 200px from
6279                //              the top with a content width of 300px and a content-height of
6280                //              150px. Note that the content box may have a much larger border
6281                //              or margin box, depending on the box model currently in use and
6282                //              CSS values set/inherited for node.
6283                //              While the getter will return top and left values, the
6284                //              setter only accepts setting the width and height.
6285                //      node:
6286                //              id or reference to DOM Node to get/set box for
6287                //      box:
6288                //              If passed, denotes that dojo.contentBox() should
6289                //              update/set the content box for node. Box is an object in the
6290                //              above format, but only w (width) and h (height) are supported.
6291                //              All properties are optional if passed.
6292                var n = byId(node), s = gcs(n), b = box;
6293                return !b ? d._getContentBox(n, s) : d._setContentSize(n, b.w, b.h, s); // Object
6294        };
6295
6296        // =============================
6297        // Positioning
6298        // =============================
6299
6300        var _sumAncestorProperties = function(node, prop){
6301                if(!(node = (node||0).parentNode)){return 0;}
6302                var val, retVal = 0, _b = d.body();
6303                while(node && node.style){
6304                        if(gcs(node).position == "fixed"){
6305                                return 0;
6306                        }
6307                        val = node[prop];
6308                        if(val){
6309                                retVal += val - 0;
6310                                // opera and khtml #body & #html has the same values, we only
6311                                // need one value
6312                                if(node == _b){ break; }
6313                        }
6314                        node = node.parentNode;
6315                }
6316                return retVal;  //      integer
6317        };
6318
6319        dojo._docScroll = function(){
6320                var n = d.global;
6321                return "pageXOffset" in n
6322                        ? { x:n.pageXOffset, y:n.pageYOffset }
6323                        : (n = d.isQuirks? d.doc.body : d.doc.documentElement, { x:d._fixIeBiDiScrollLeft(n.scrollLeft || 0), y:n.scrollTop || 0 });
6324        };
6325
6326        dojo._isBodyLtr = function(){
6327                return "_bodyLtr" in d? d._bodyLtr :
6328                        d._bodyLtr = (d.body().dir || d.doc.documentElement.dir || "ltr").toLowerCase() == "ltr"; // Boolean
6329        };
6330
6331                dojo._getIeDocumentElementOffset = function(){
6332                //      summary:
6333                //              returns the offset in x and y from the document body to the
6334                //              visual edge of the page
6335                //      description:
6336                // The following values in IE contain an offset:
6337                //      |               event.clientX
6338                //      |               event.clientY
6339                //      |               node.getBoundingClientRect().left
6340                //      |               node.getBoundingClientRect().top
6341                //              But other position related values do not contain this offset,
6342                //              such as node.offsetLeft, node.offsetTop, node.style.left and
6343                //              node.style.top. The offset is always (2, 2) in LTR direction.
6344                //              When the body is in RTL direction, the offset counts the width
6345                //              of left scroll bar's width.  This function computes the actual
6346                //              offset.
6347
6348                //NOTE: assumes we're being called in an IE browser
6349
6350                var de = d.doc.documentElement; // only deal with HTML element here, _abs handles body/quirks
6351
6352                if(d.isIE < 8){
6353                        var r = de.getBoundingClientRect(); // works well for IE6+
6354                        //console.debug('rect left,top = ' + r.left+','+r.top + ', html client left/top = ' + de.clientLeft+','+de.clientTop + ', rtl = ' + (!d._isBodyLtr()) + ', quirks = ' + d.isQuirks);
6355                        var l = r.left,
6356                            t = r.top;
6357                        if(d.isIE < 7){
6358                                l += de.clientLeft;     // scrollbar size in strict/RTL, or,
6359                                t += de.clientTop;      // HTML border size in strict
6360                        }
6361                        return {
6362                                x: l < 0? 0 : l, // FRAME element border size can lead to inaccurate negative values
6363                                y: t < 0? 0 : t
6364                        };
6365                }else{
6366                        return {
6367                                x: 0,
6368                                y: 0
6369                        };
6370                }
6371
6372        };
6373
6374        dojo._fixIeBiDiScrollLeft = function(/*Integer*/ scrollLeft){
6375                // In RTL direction, scrollLeft should be a negative value, but IE
6376                // returns a positive one. All codes using documentElement.scrollLeft
6377                // must call this function to fix this error, otherwise the position
6378                // will offset to right when there is a horizontal scrollbar.
6379
6380                                var ie = d.isIE;
6381                if(ie && !d._isBodyLtr()){
6382                        var qk = d.isQuirks,
6383                                de = qk ? d.doc.body : d.doc.documentElement;
6384                        if(ie == 6 && !qk && d.global.frameElement && de.scrollHeight > de.clientHeight){
6385                                scrollLeft += de.clientLeft; // workaround ie6+strict+rtl+iframe+vertical-scrollbar bug where clientWidth is too small by clientLeft pixels
6386                        }
6387                        return (ie < 8 || qk) ? (scrollLeft + de.clientWidth - de.scrollWidth) : -scrollLeft; // Integer
6388                }
6389                                return scrollLeft; // Integer
6390        };
6391
6392        // FIXME: need a setter for coords or a moveTo!!
6393        dojo._abs = dojo.position = function(/*DomNode*/node, /*Boolean?*/includeScroll){
6394                //      summary:
6395                //              Gets the position and size of the passed element relative to
6396                //              the viewport (if includeScroll==false), or relative to the
6397                //              document root (if includeScroll==true).
6398                //
6399                //      description:
6400                //              Returns an object of the form:
6401                //                      { x: 100, y: 300, w: 20, h: 15 }
6402                //              If includeScroll==true, the x and y values will include any
6403                //              document offsets that may affect the position relative to the
6404                //              viewport.
6405                //              Uses the border-box model (inclusive of border and padding but
6406                //              not margin).  Does not act as a setter.
6407
6408                node = byId(node);
6409                var     db = d.body(),
6410                        dh = db.parentNode,
6411                        ret = node.getBoundingClientRect();
6412                        ret = { x: ret.left, y: ret.top, w: ret.right - ret.left, h: ret.bottom - ret.top };
6413                                        if(d.isIE){
6414                                // On IE there's a 2px offset that we need to adjust for, see _getIeDocumentElementOffset()
6415                                var offset = d._getIeDocumentElementOffset();
6416
6417                                // fixes the position in IE, quirks mode
6418                                ret.x -= offset.x + (d.isQuirks ? db.clientLeft+db.offsetLeft : 0);
6419                                ret.y -= offset.y + (d.isQuirks ? db.clientTop+db.offsetTop : 0);
6420                        }else if(d.isFF == 3){
6421                                // In FF3 you have to subtract the document element margins.
6422                                // Fixed in FF3.5 though.
6423                                var cs = gcs(dh);
6424                                ret.x -= px(dh, cs.marginLeft) + px(dh, cs.borderLeftWidth);
6425                                ret.y -= px(dh, cs.marginTop) + px(dh, cs.borderTopWidth);
6426                        }
6427                                // account for document scrolling
6428                if(includeScroll){
6429                        var scroll = d._docScroll();
6430                        ret.x += scroll.x;
6431                        ret.y += scroll.y;
6432                }
6433
6434                return ret; // Object
6435        };
6436
6437        dojo.coords = function(/*DomNode|String*/node, /*Boolean?*/includeScroll){
6438                //      summary:
6439                //              Deprecated: Use position() for border-box x/y/w/h
6440                //              or marginBox() for margin-box w/h/l/t.
6441                //              Returns an object representing a node's size and position.
6442                //
6443                //      description:
6444                //              Returns an object that measures margin-box (w)idth/(h)eight
6445                //              and absolute position x/y of the border-box. Also returned
6446                //              is computed (l)eft and (t)op values in pixels from the
6447                //              node's offsetParent as returned from marginBox().
6448                //              Return value will be in the form:
6449                //|                     { l: 50, t: 200, w: 300: h: 150, x: 100, y: 300 }
6450                //              Does not act as a setter. If includeScroll is passed, the x and
6451                //              y params are affected as one would expect in dojo.position().
6452                var n = byId(node), s = gcs(n), mb = d._getMarginBox(n, s);
6453                var abs = d.position(n, includeScroll);
6454                mb.x = abs.x;
6455                mb.y = abs.y;
6456                return mb;
6457        };
6458
6459        // =============================
6460        // Element attribute Functions
6461        // =============================
6462
6463        // dojo.attr() should conform to http://www.w3.org/TR/DOM-Level-2-Core/
6464
6465        var _propNames = {
6466                        // properties renamed to avoid clashes with reserved words
6467                        "class":   "className",
6468                        "for":     "htmlFor",
6469                        // properties written as camelCase
6470                        tabindex:  "tabIndex",
6471                        readonly:  "readOnly",
6472                        colspan:   "colSpan",
6473                        frameborder: "frameBorder",
6474                        rowspan:   "rowSpan",
6475                        valuetype: "valueType"
6476                },
6477                _attrNames = {
6478                        // original attribute names
6479                        classname: "class",
6480                        htmlfor:   "for",
6481                        // for IE
6482                        tabindex:  "tabIndex",
6483                        readonly:  "readOnly"
6484                },
6485                _forcePropNames = {
6486                        innerHTML: 1,
6487                        className: 1,
6488                        htmlFor:   d.isIE,
6489                        value:     1
6490                };
6491
6492        var _fixAttrName = function(/*String*/ name){
6493                return _attrNames[name.toLowerCase()] || name;
6494        };
6495
6496        var _hasAttr = function(node, name){
6497                var attr = node.getAttributeNode && node.getAttributeNode(name);
6498                return attr && attr.specified; // Boolean
6499        };
6500
6501        // There is a difference in the presence of certain properties and their default values
6502        // between browsers. For example, on IE "disabled" is present on all elements,
6503        // but it is value is "false"; "tabIndex" of <div> returns 0 by default on IE, yet other browsers
6504        // can return -1.
6505
6506        dojo.hasAttr = function(/*DomNode|String*/node, /*String*/name){
6507                //      summary:
6508                //              Returns true if the requested attribute is specified on the
6509                //              given element, and false otherwise.
6510                //      node:
6511                //              id or reference to the element to check
6512                //      name:
6513                //              the name of the attribute
6514                //      returns:
6515                //              true if the requested attribute is specified on the
6516                //              given element, and false otherwise
6517                var lc = name.toLowerCase();
6518                return _forcePropNames[_propNames[lc] || name] || _hasAttr(byId(node), _attrNames[lc] || name); // Boolean
6519        };
6520
6521        var _evtHdlrMap = {}, _ctr = 0,
6522                _attrId = dojo._scopeName + "attrid",
6523                // the next dictionary lists elements with read-only innerHTML on IE
6524                _roInnerHtml = {col: 1, colgroup: 1,
6525                        // frameset: 1, head: 1, html: 1, style: 1,
6526                        table: 1, tbody: 1, tfoot: 1, thead: 1, tr: 1, title: 1};
6527
6528        dojo.attr = function(/*DomNode|String*/node, /*String|Object*/name, /*String?*/value){
6529                //      summary:
6530                //              Gets or sets an attribute on an HTML element.
6531                //      description:
6532                //              Handles normalized getting and setting of attributes on DOM
6533                //              Nodes. If 2 arguments are passed, and a the second argumnt is a
6534                //              string, acts as a getter.
6535                //
6536                //              If a third argument is passed, or if the second argument is a
6537                //              map of attributes, acts as a setter.
6538                //
6539                //              When passing functions as values, note that they will not be
6540                //              directly assigned to slots on the node, but rather the default
6541                //              behavior will be removed and the new behavior will be added
6542                //              using `dojo.connect()`, meaning that event handler properties
6543                //              will be normalized and that some caveats with regards to
6544                //              non-standard behaviors for onsubmit apply. Namely that you
6545                //              should cancel form submission using `dojo.stopEvent()` on the
6546                //              passed event object instead of returning a boolean value from
6547                //              the handler itself.
6548                //      node:
6549                //              id or reference to the element to get or set the attribute on
6550                //      name:
6551                //              the name of the attribute to get or set.
6552                //      value:
6553                //              The value to set for the attribute
6554                //      returns:
6555                //              when used as a getter, the value of the requested attribute
6556                //              or null if that attribute does not have a specified or
6557                //              default value;
6558                //
6559                //              when used as a setter, the DOM node
6560                //
6561                //      example:
6562                //      |       // get the current value of the "foo" attribute on a node
6563                //      |       dojo.attr(dojo.byId("nodeId"), "foo");
6564                //      |       // or we can just pass the id:
6565                //      |       dojo.attr("nodeId", "foo");
6566                //
6567                //      example:
6568                //      |       // use attr() to set the tab index
6569                //      |       dojo.attr("nodeId", "tabIndex", 3);
6570                //      |
6571                //
6572                //      example:
6573                //      Set multiple values at once, including event handlers:
6574                //      |       dojo.attr("formId", {
6575                //      |               "foo": "bar",
6576                //      |               "tabIndex": -1,
6577                //      |               "method": "POST",
6578                //      |               "onsubmit": function(e){
6579                //      |                       // stop submitting the form. Note that the IE behavior
6580                //      |                       // of returning true or false will have no effect here
6581                //      |                       // since our handler is connect()ed to the built-in
6582                //      |                       // onsubmit behavior and so we need to use
6583                //      |                       // dojo.stopEvent() to ensure that the submission
6584                //      |                       // doesn't proceed.
6585                //      |                       dojo.stopEvent(e);
6586                //      |
6587                //      |                       // submit the form with Ajax
6588                //      |                       dojo.xhrPost({ form: "formId" });
6589                //      |               }
6590                //      |       });
6591                //
6592                //      example:
6593                //      Style is s special case: Only set with an object hash of styles
6594                //      |       dojo.attr("someNode",{
6595                //      |               id:"bar",
6596                //      |               style:{
6597                //      |                       width:"200px", height:"100px", color:"#000"
6598                //      |               }
6599                //      |       });
6600                //
6601                //      example:
6602                //      Again, only set style as an object hash of styles:
6603                //      |       var obj = { color:"#fff", backgroundColor:"#000" };
6604                //      |       dojo.attr("someNode", "style", obj);
6605                //      |
6606                //      |       // though shorter to use `dojo.style()` in this case:
6607                //      |       dojo.style("someNode", obj);
6608
6609                node = byId(node);
6610                var args = arguments.length, prop;
6611                if(args == 2 && typeof name != "string"){ // inline'd type check
6612                        // the object form of setter: the 2nd argument is a dictionary
6613                        for(var x in name){
6614                                d.attr(node, x, name[x]);
6615                        }
6616                        return node; // DomNode
6617                }
6618                var lc = name.toLowerCase(),
6619                        propName = _propNames[lc] || name,
6620                        forceProp = _forcePropNames[propName],
6621                        attrName = _attrNames[lc] || name;
6622                if(args == 3){
6623                        // setter
6624                        do{
6625                                if(propName == "style" && typeof value != "string"){ // inline'd type check
6626                                        // special case: setting a style
6627                                        d.style(node, value);
6628                                        break;
6629                                }
6630                                if(propName == "innerHTML"){
6631                                        // special case: assigning HTML
6632                                                                                if(d.isIE && node.tagName.toLowerCase() in _roInnerHtml){
6633                                                d.empty(node);
6634                                                node.appendChild(d._toDom(value, node.ownerDocument));
6635                                        }else{
6636                                                                                        node[propName] = value;
6637                                                                                }
6638                                                                                break;
6639                                }
6640                                if(d.isFunction(value)){
6641                                        // special case: assigning an event handler
6642                                        // clobber if we can
6643                                        var attrId = d.attr(node, _attrId);
6644                                        if(!attrId){
6645                                                attrId = _ctr++;
6646                                                d.attr(node, _attrId, attrId);
6647                                        }
6648                                        if(!_evtHdlrMap[attrId]){
6649                                                _evtHdlrMap[attrId] = {};
6650                                        }
6651                                        var h = _evtHdlrMap[attrId][propName];
6652                                        if(h){
6653                                                d.disconnect(h);
6654                                        }else{
6655                                                try{
6656                                                        delete node[propName];
6657                                                }catch(e){}
6658                                        }
6659                                        // ensure that event objects are normalized, etc.
6660                                        _evtHdlrMap[attrId][propName] = d.connect(node, propName, value);
6661                                        break;
6662                                }
6663                                if(forceProp || typeof value == "boolean"){
6664                                        // special case: forcing assignment to the property
6665                                        // special case: setting boolean to a property instead of attribute
6666                                        node[propName] = value;
6667                                        break;
6668                                }
6669                                // node's attribute
6670                                node.setAttribute(attrName, value);
6671                        }while(false);
6672                        return node; // DomNode
6673                }
6674                // getter
6675                // should we access this attribute via a property or
6676                // via getAttribute()?
6677                value = node[propName];
6678                if(forceProp && typeof value != "undefined"){
6679                        // node's property
6680                        return value;   // Anything
6681                }
6682                if(propName != "href" && (typeof value == "boolean" || d.isFunction(value))){
6683                        // node's property
6684                        return value;   // Anything
6685                }
6686                // node's attribute
6687                // we need _hasAttr() here to guard against IE returning a default value
6688                return _hasAttr(node, attrName) ? node.getAttribute(attrName) : null; // Anything
6689        };
6690
6691        dojo.removeAttr = function(/*DomNode|String*/ node, /*String*/ name){
6692                //      summary:
6693                //              Removes an attribute from an HTML element.
6694                //      node:
6695                //              id or reference to the element to remove the attribute from
6696                //      name:
6697                //              the name of the attribute to remove
6698                byId(node).removeAttribute(_fixAttrName(name));
6699        };
6700
6701        dojo.getNodeProp = function(/*DomNode|String*/ node, /*String*/ name){
6702                //      summary:
6703                //              Returns an effective value of a property or an attribute.
6704                //      node:
6705                //              id or reference to the element to remove the attribute from
6706                //      name:
6707                //              the name of the attribute
6708                node = byId(node);
6709                var lc = name.toLowerCase(),
6710                        propName = _propNames[lc] || name;
6711                if((propName in node) && propName != "href"){
6712                        // node's property
6713                        return node[propName];  // Anything
6714                }
6715                // node's attribute
6716                var attrName = _attrNames[lc] || name;
6717                return _hasAttr(node, attrName) ? node.getAttribute(attrName) : null; // Anything
6718        };
6719
6720        dojo.create = function(tag, attrs, refNode, pos){
6721                //      summary:
6722                //              Create an element, allowing for optional attribute decoration
6723                //              and placement.
6724                //
6725                // description:
6726                //              A DOM Element creation function. A shorthand method for creating a node or
6727                //              a fragment, and allowing for a convenient optional attribute setting step,
6728                //              as well as an optional DOM placement reference.
6729                //|
6730                //              Attributes are set by passing the optional object through `dojo.attr`.
6731                //              See `dojo.attr` for noted caveats and nuances, and API if applicable.
6732                //|
6733                //              Placement is done via `dojo.place`, assuming the new node to be the action
6734                //              node, passing along the optional reference node and position.
6735                //
6736                // tag: String|DomNode
6737                //              A string of the element to create (eg: "div", "a", "p", "li", "script", "br"),
6738                //              or an existing DOM node to process.
6739                //
6740                // attrs: Object
6741                //              An object-hash of attributes to set on the newly created node.
6742                //              Can be null, if you don't want to set any attributes/styles.
6743                //              See: `dojo.attr` for a description of available attributes.
6744                //
6745                // refNode: String?|DomNode?
6746                //              Optional reference node. Used by `dojo.place` to place the newly created
6747                //              node somewhere in the dom relative to refNode. Can be a DomNode reference
6748                //              or String ID of a node.
6749                //
6750                // pos: String?
6751                //              Optional positional reference. Defaults to "last" by way of `dojo.place`,
6752                //              though can be set to "first","after","before","last", "replace" or "only"
6753                //              to further control the placement of the new node relative to the refNode.
6754                //              'refNode' is required if a 'pos' is specified.
6755                //
6756                // returns: DomNode
6757                //
6758                // example:
6759                //      Create a DIV:
6760                //      |       var n = dojo.create("div");
6761                //
6762                // example:
6763                //      Create a DIV with content:
6764                //      |       var n = dojo.create("div", { innerHTML:"<p>hi</p>" });
6765                //
6766                // example:
6767                //      Place a new DIV in the BODY, with no attributes set
6768                //      |       var n = dojo.create("div", null, dojo.body());
6769                //
6770                // example:
6771                //      Create an UL, and populate it with LI's. Place the list as the first-child of a
6772                //      node with id="someId":
6773                //      |       var ul = dojo.create("ul", null, "someId", "first");
6774                //      |       var items = ["one", "two", "three", "four"];
6775                //      |       dojo.forEach(items, function(data){
6776                //      |               dojo.create("li", { innerHTML: data }, ul);
6777                //      |       });
6778                //
6779                // example:
6780                //      Create an anchor, with an href. Place in BODY:
6781                //      |       dojo.create("a", { href:"foo.html", title:"Goto FOO!" }, dojo.body());
6782                //
6783                // example:
6784                //      Create a `dojo.NodeList()` from a new element (for syntatic sugar):
6785                //      |       dojo.query(dojo.create('div'))
6786                //      |               .addClass("newDiv")
6787                //      |               .onclick(function(e){ console.log('clicked', e.target) })
6788                //      |               .place("#someNode"); // redundant, but cleaner.
6789
6790                var doc = d.doc;
6791                if(refNode){
6792                        refNode = byId(refNode);
6793                        doc = refNode.ownerDocument;
6794                }
6795                if(typeof tag == "string"){ // inline'd type check
6796                        tag = doc.createElement(tag);
6797                }
6798                if(attrs){ d.attr(tag, attrs); }
6799                if(refNode){ d.place(tag, refNode, pos); }
6800                return tag; // DomNode
6801        };
6802
6803        /*=====
6804        dojo.empty = function(node){
6805                        //      summary:
6806                        //              safely removes all children of the node.
6807                        //      node: DOMNode|String
6808                        //              a reference to a DOM node or an id.
6809                        //      example:
6810                        //      Destroy node's children byId:
6811                        //      |       dojo.empty("someId");
6812                        //
6813                        //      example:
6814                        //      Destroy all nodes' children in a list by reference:
6815                        //      |       dojo.query(".someNode").forEach(dojo.empty);
6816        }
6817        =====*/
6818
6819        d.empty =
6820                                d.isIE ?  function(node){
6821                        node = byId(node);
6822                        for(var c; c = node.lastChild;){ // intentional assignment
6823                                d.destroy(c);
6824                        }
6825                } :
6826                                function(node){
6827                        byId(node).innerHTML = "";
6828                };
6829
6830        /*=====
6831        dojo._toDom = function(frag, doc){
6832                        //      summary:
6833                        //              instantiates an HTML fragment returning the corresponding DOM.
6834                        //      frag: String
6835                        //              the HTML fragment
6836                        //      doc: DocumentNode?
6837                        //              optional document to use when creating DOM nodes, defaults to
6838                        //              dojo.doc if not specified.
6839                        //      returns: DocumentFragment
6840                        //
6841                        //      example:
6842                        //      Create a table row:
6843                        //      |       var tr = dojo._toDom("<tr><td>First!</td></tr>");
6844        }
6845        =====*/
6846
6847        // support stuff for dojo._toDom
6848        var tagWrap = {
6849                        option: ["select"],
6850                        tbody: ["table"],
6851                        thead: ["table"],
6852                        tfoot: ["table"],
6853                        tr: ["table", "tbody"],
6854                        td: ["table", "tbody", "tr"],
6855                        th: ["table", "thead", "tr"],
6856                        legend: ["fieldset"],
6857                        caption: ["table"],
6858                        colgroup: ["table"],
6859                        col: ["table", "colgroup"],
6860                        li: ["ul"]
6861                },
6862                reTag = /<\s*([\w\:]+)/,
6863                masterNode = {}, masterNum = 0,
6864                masterName = "__" + d._scopeName + "ToDomId";
6865
6866        // generate start/end tag strings to use
6867        // for the injection for each special tag wrap case.
6868        for(var param in tagWrap){
6869                if(tagWrap.hasOwnProperty(param)){
6870                        var tw = tagWrap[param];
6871                        tw.pre  = param == "option" ? '<select multiple="multiple">' : "<" + tw.join("><") + ">";
6872                        tw.post = "</" + tw.reverse().join("></") + ">";
6873                        // the last line is destructive: it reverses the array,
6874                        // but we don't care at this point
6875                }
6876        }
6877
6878        d._toDom = function(frag, doc){
6879                //      summary:
6880                //              converts HTML string into DOM nodes.
6881
6882                doc = doc || d.doc;
6883                var masterId = doc[masterName];
6884                if(!masterId){
6885                        doc[masterName] = masterId = ++masterNum + "";
6886                        masterNode[masterId] = doc.createElement("div");
6887                }
6888
6889                // make sure the frag is a string.
6890                frag += "";
6891
6892                // find the starting tag, and get node wrapper
6893                var match = frag.match(reTag),
6894                        tag = match ? match[1].toLowerCase() : "",
6895                        master = masterNode[masterId],
6896                        wrap, i, fc, df;
6897                if(match && tagWrap[tag]){
6898                        wrap = tagWrap[tag];
6899                        master.innerHTML = wrap.pre + frag + wrap.post;
6900                        for(i = wrap.length; i; --i){
6901                                master = master.firstChild;
6902                        }
6903                }else{
6904                        master.innerHTML = frag;
6905                }
6906
6907                // one node shortcut => return the node itself
6908                if(master.childNodes.length == 1){
6909                        return master.removeChild(master.firstChild); // DOMNode
6910                }
6911
6912                // return multiple nodes as a document fragment
6913                df = doc.createDocumentFragment();
6914                while(fc = master.firstChild){ // intentional assignment
6915                        df.appendChild(fc);
6916                }
6917                return df; // DOMNode
6918        };
6919
6920        // =============================
6921        // (CSS) Class Functions
6922        // =============================
6923        var _className = "className";
6924
6925        dojo.hasClass = function(/*DomNode|String*/node, /*String*/classStr){
6926                //      summary:
6927                //              Returns whether or not the specified classes are a portion of the
6928                //              class list currently applied to the node.
6929                //
6930                //      node:
6931                //              String ID or DomNode reference to check the class for.
6932                //
6933                //      classStr:
6934                //              A string class name to look for.
6935                //
6936                //      example:
6937                //      Do something if a node with id="someNode" has class="aSillyClassName" present
6938                //      |       if(dojo.hasClass("someNode","aSillyClassName")){ ... }
6939
6940                return ((" "+ byId(node)[_className] +" ").indexOf(" " + classStr + " ") >= 0);  // Boolean
6941        };
6942
6943        var spaces = /\s+/, a1 = [""],
6944                fakeNode = {},
6945                str2array = function(s){
6946                        if(typeof s == "string" || s instanceof String){
6947                                if(s.indexOf(" ") < 0){
6948                                        a1[0] = s;
6949                                        return a1;
6950                                }else{
6951                                        return s.split(spaces);
6952                                }
6953                        }
6954                        // assumed to be an array
6955                        return s || "";
6956                };
6957
6958        dojo.addClass = function(/*DomNode|String*/node, /*String|Array*/classStr){
6959                //      summary:
6960                //              Adds the specified classes to the end of the class list on the
6961                //              passed node. Will not re-apply duplicate classes.
6962                //
6963                //      node:
6964                //              String ID or DomNode reference to add a class string too
6965                //
6966                //      classStr:
6967                //              A String class name to add, or several space-separated class names,
6968                //              or an array of class names.
6969                //
6970                // example:
6971                //      Add a class to some node:
6972                //      |       dojo.addClass("someNode", "anewClass");
6973                //
6974                // example:
6975                //      Add two classes at once:
6976                //      |       dojo.addClass("someNode", "firstClass secondClass");
6977                //
6978                // example:
6979                //      Add two classes at once (using array):
6980                //      |       dojo.addClass("someNode", ["firstClass", "secondClass"]);
6981                //
6982                // example:
6983                //      Available in `dojo.NodeList` for multiple additions
6984                //      |       dojo.query("ul > li").addClass("firstLevel");
6985
6986                node = byId(node);
6987                classStr = str2array(classStr);
6988                var cls = node[_className], oldLen;
6989                cls = cls ? " " + cls + " " : " ";
6990                oldLen = cls.length;
6991                for(var i = 0, len = classStr.length, c; i < len; ++i){
6992                        c = classStr[i];
6993                        if(c && cls.indexOf(" " + c + " ") < 0){
6994                                cls += c + " ";
6995                        }
6996                }
6997                if(oldLen < cls.length){
6998                        node[_className] = cls.substr(1, cls.length - 2);
6999                }
7000        };
7001
7002        dojo.removeClass = function(/*DomNode|String*/node, /*String|Array?*/classStr){
7003                // summary:
7004                //              Removes the specified classes from node. No `dojo.hasClass`
7005                //              check is required.
7006                //
7007                // node:
7008                //              String ID or DomNode reference to remove the class from.
7009                //
7010                // classStr:
7011                //              An optional String class name to remove, or several space-separated
7012                //              class names, or an array of class names. If omitted, all class names
7013                //              will be deleted.
7014                //
7015                // example:
7016                //      Remove a class from some node:
7017                //      |       dojo.removeClass("someNode", "firstClass");
7018                //
7019                // example:
7020                //      Remove two classes from some node:
7021                //      |       dojo.removeClass("someNode", "firstClass secondClass");
7022                //
7023                // example:
7024                //      Remove two classes from some node (using array):
7025                //      |       dojo.removeClass("someNode", ["firstClass", "secondClass"]);
7026                //
7027                // example:
7028                //      Remove all classes from some node:
7029                //      |       dojo.removeClass("someNode");
7030                //
7031                // example:
7032                //      Available in `dojo.NodeList()` for multiple removal
7033                //      |       dojo.query(".foo").removeClass("foo");
7034
7035                node = byId(node);
7036                var cls;
7037                if(classStr !== undefined){
7038                        classStr = str2array(classStr);
7039                        cls = " " + node[_className] + " ";
7040                        for(var i = 0, len = classStr.length; i < len; ++i){
7041                                cls = cls.replace(" " + classStr[i] + " ", " ");
7042                        }
7043                        cls = d.trim(cls);
7044                }else{
7045                        cls = "";
7046                }
7047                if(node[_className] != cls){ node[_className] = cls; }
7048        };
7049
7050        dojo.replaceClass = function(/*DomNode|String*/node, /*String|Array*/addClassStr, /*String|Array?*/removeClassStr){
7051                // summary:
7052                //              Replaces one or more classes on a node if not present.
7053                //              Operates more quickly than calling dojo.removeClass and dojo.addClass
7054                // node:
7055                //              String ID or DomNode reference to remove the class from.
7056                // addClassStr:
7057                //              A String class name to add, or several space-separated class names,
7058                //              or an array of class names.
7059                // removeClassStr:
7060                //              A String class name to remove, or several space-separated class names,
7061                //              or an array of class names.
7062                //
7063                // example:
7064                //      |       dojo.replaceClass("someNode", "add1 add2", "remove1 remove2");
7065                //
7066                // example:
7067                //      Replace all classes with addMe
7068                //      |       dojo.replaceClass("someNode", "addMe");
7069                //
7070                // example:
7071                //      Available in `dojo.NodeList()` for multiple toggles
7072                //      |       dojo.query(".findMe").replaceClass("addMe", "removeMe");
7073
7074        node = byId(node);
7075                fakeNode.className = node.className;
7076                dojo.removeClass(fakeNode, removeClassStr);
7077                dojo.addClass(fakeNode, addClassStr);
7078                if(node.className !== fakeNode.className){
7079                        node.className = fakeNode.className;
7080                }
7081        };
7082
7083        dojo.toggleClass = function(/*DomNode|String*/node, /*String|Array*/classStr, /*Boolean?*/condition){
7084                //      summary:
7085                //              Adds a class to node if not present, or removes if present.
7086                //              Pass a boolean condition if you want to explicitly add or remove.
7087                //      condition:
7088                //              If passed, true means to add the class, false means to remove.
7089                //
7090                // example:
7091                //      |       dojo.toggleClass("someNode", "hovered");
7092                //
7093                // example:
7094                //      Forcefully add a class
7095                //      |       dojo.toggleClass("someNode", "hovered", true);
7096                //
7097                // example:
7098                //      Available in `dojo.NodeList()` for multiple toggles
7099                //      |       dojo.query(".toggleMe").toggleClass("toggleMe");
7100
7101                if(condition === undefined){
7102                        condition = !d.hasClass(node, classStr);
7103                }
7104                d[condition ? "addClass" : "removeClass"](node, classStr);
7105        };
7106
7107})();
7108
7109}
7110
7111if(!dojo._hasResource["dojo._base.NodeList"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
7112dojo._hasResource["dojo._base.NodeList"] = true;
7113dojo.provide("dojo._base.NodeList");
7114
7115
7116
7117
7118
7119
7120(function(){
7121
7122        var d = dojo;
7123
7124        var ap = Array.prototype, aps = ap.slice, apc = ap.concat;
7125
7126        var tnl = function(/*Array*/ a, /*dojo.NodeList?*/ parent, /*Function?*/ NodeListCtor){
7127                // summary:
7128                //              decorate an array to make it look like a `dojo.NodeList`.
7129                // a:
7130                //              Array of nodes to decorate.
7131                // parent:
7132                //              An optional parent NodeList that generated the current
7133                //              list of nodes. Used to call _stash() so the parent NodeList
7134                //              can be accessed via end() later.
7135                // NodeListCtor:
7136                //              An optional constructor function to use for any
7137                //              new NodeList calls. This allows a certain chain of
7138                //              NodeList calls to use a different object than dojo.NodeList.
7139                if(!a.sort){
7140                        // make sure it's a real array before we pass it on to be wrapped
7141                        a = aps.call(a, 0);
7142                }
7143                var ctor = NodeListCtor || this._NodeListCtor || d._NodeListCtor;
7144                a.constructor = ctor;
7145                dojo._mixin(a, ctor.prototype);
7146                a._NodeListCtor = ctor;
7147                return parent ? a._stash(parent) : a;
7148        };
7149
7150        var loopBody = function(f, a, o){
7151                a = [0].concat(aps.call(a, 0));
7152                o = o || d.global;
7153                return function(node){
7154                        a[0] = node;
7155                        return f.apply(o, a);
7156                };
7157        };
7158
7159        // adapters
7160
7161        var adaptAsForEach = function(f, o){
7162                //      summary:
7163                //              adapts a single node function to be used in the forEach-type
7164                //              actions. The initial object is returned from the specialized
7165                //              function.
7166                //      f: Function
7167                //              a function to adapt
7168                //      o: Object?
7169                //              an optional context for f
7170                return function(){
7171                        this.forEach(loopBody(f, arguments, o));
7172                        return this;    // Object
7173                };
7174        };
7175
7176        var adaptAsMap = function(f, o){
7177                //      summary:
7178                //              adapts a single node function to be used in the map-type
7179                //              actions. The return is a new array of values, as via `dojo.map`
7180                //      f: Function
7181                //              a function to adapt
7182                //      o: Object?
7183                //              an optional context for f
7184                return function(){
7185                        return this.map(loopBody(f, arguments, o));
7186                };
7187        };
7188
7189        var adaptAsFilter = function(f, o){
7190                //      summary:
7191                //              adapts a single node function to be used in the filter-type actions
7192                //      f: Function
7193                //              a function to adapt
7194                //      o: Object?
7195                //              an optional context for f
7196                return function(){
7197                        return this.filter(loopBody(f, arguments, o));
7198                };
7199        };
7200
7201        var adaptWithCondition = function(f, g, o){
7202                //      summary:
7203                //              adapts a single node function to be used in the map-type
7204                //              actions, behaves like forEach() or map() depending on arguments
7205                //      f: Function
7206                //              a function to adapt
7207                //      g: Function
7208                //              a condition function, if true runs as map(), otherwise runs as forEach()
7209                //      o: Object?
7210                //              an optional context for f and g
7211                return function(){
7212                        var a = arguments, body = loopBody(f, a, o);
7213                        if(g.call(o || d.global, a)){
7214                                return this.map(body);  // self
7215                        }
7216                        this.forEach(body);
7217                        return this;    // self
7218                };
7219        };
7220
7221        var magicGuard = function(a){
7222                //      summary:
7223                //              the guard function for dojo.attr() and dojo.style()
7224                return a.length == 1 && (typeof a[0] == "string"); // inline'd type check
7225        };
7226
7227        var orphan = function(node){
7228                //      summary:
7229                //              function to orphan nodes
7230                var p = node.parentNode;
7231                if(p){
7232                        p.removeChild(node);
7233                }
7234        };
7235        // FIXME: should we move orphan() to dojo.html?
7236
7237        dojo.NodeList = function(){
7238                //      summary:
7239                //              dojo.NodeList is an of Array subclass which adds syntactic
7240                //              sugar for chaining, common iteration operations, animation, and
7241                //              node manipulation. NodeLists are most often returned as the
7242                //              result of dojo.query() calls.
7243                //      description:
7244                //              dojo.NodeList instances provide many utilities that reflect
7245                //              core Dojo APIs for Array iteration and manipulation, DOM
7246                //              manipulation, and event handling. Instead of needing to dig up
7247                //              functions in the dojo.* namespace, NodeLists generally make the
7248                //              full power of Dojo available for DOM manipulation tasks in a
7249                //              simple, chainable way.
7250                //      example:
7251                //              create a node list from a node
7252                //              |       new dojo.NodeList(dojo.byId("foo"));
7253                //      example:
7254                //              get a NodeList from a CSS query and iterate on it
7255                //              |       var l = dojo.query(".thinger");
7256                //              |       l.forEach(function(node, index, nodeList){
7257                //              |               console.log(index, node.innerHTML);
7258                //              |       });
7259                //      example:
7260                //              use native and Dojo-provided array methods to manipulate a
7261                //              NodeList without needing to use dojo.* functions explicitly:
7262                //              |       var l = dojo.query(".thinger");
7263                //              |       // since NodeLists are real arrays, they have a length
7264                //              |       // property that is both readable and writable and
7265                //              |       // push/pop/shift/unshift methods
7266                //              |       console.log(l.length);
7267                //              |       l.push(dojo.create("span"));
7268                //              |
7269                //              |       // dojo's normalized array methods work too:
7270                //              |       console.log( l.indexOf(dojo.byId("foo")) );
7271                //              |       // ...including the special "function as string" shorthand
7272                //              |       console.log( l.every("item.nodeType == 1") );
7273                //              |
7274                //              |       // NodeLists can be [..] indexed, or you can use the at()
7275                //              |       // function to get specific items wrapped in a new NodeList:
7276                //              |       var node = l[3]; // the 4th element
7277                //              |       var newList = l.at(1, 3); // the 2nd and 4th elements
7278                //      example:
7279                //              the style functions you expect are all there too:
7280                //              |       // style() as a getter...
7281                //              |       var borders = dojo.query(".thinger").style("border");
7282                //              |       // ...and as a setter:
7283                //              |       dojo.query(".thinger").style("border", "1px solid black");
7284                //              |       // class manipulation
7285                //              |       dojo.query("li:nth-child(even)").addClass("even");
7286                //              |       // even getting the coordinates of all the items
7287                //              |       var coords = dojo.query(".thinger").coords();
7288                //      example:
7289                //              DOM manipulation functions from the dojo.* namespace area also
7290                //              available:
7291                //              |       // remove all of the elements in the list from their
7292                //              |       // parents (akin to "deleting" them from the document)
7293                //              |       dojo.query(".thinger").orphan();
7294                //              |       // place all elements in the list at the front of #foo
7295                //              |       dojo.query(".thinger").place("foo", "first");
7296                //      example:
7297                //              Event handling couldn't be easier. `dojo.connect` is mapped in,
7298                //              and shortcut handlers are provided for most DOM events:
7299                //              |       // like dojo.connect(), but with implicit scope
7300                //              |       dojo.query("li").connect("onclick", console, "log");
7301                //              |
7302                //              |       // many common event handlers are already available directly:
7303                //              |       dojo.query("li").onclick(console, "log");
7304                //              |       var toggleHovered = dojo.hitch(dojo, "toggleClass", "hovered");
7305                //              |       dojo.query("p")
7306                //              |               .onmouseenter(toggleHovered)
7307                //              |               .onmouseleave(toggleHovered);
7308                //      example:
7309                //              chainability is a key advantage of NodeLists:
7310                //              |       dojo.query(".thinger")
7311                //              |               .onclick(function(e){ /* ... */ })
7312                //              |               .at(1, 3, 8) // get a subset
7313                //              |                       .style("padding", "5px")
7314                //              |                       .forEach(console.log);
7315
7316                return tnl(Array.apply(null, arguments));
7317        };
7318
7319        //Allow things that new up a NodeList to use a delegated or alternate NodeList implementation.
7320        d._NodeListCtor = d.NodeList;
7321
7322        var nl = d.NodeList, nlp = nl.prototype;
7323
7324        // expose adapters and the wrapper as private functions
7325
7326        nl._wrap = nlp._wrap = tnl;
7327        nl._adaptAsMap = adaptAsMap;
7328        nl._adaptAsForEach = adaptAsForEach;
7329        nl._adaptAsFilter  = adaptAsFilter;
7330        nl._adaptWithCondition = adaptWithCondition;
7331
7332        // mass assignment
7333
7334        // add array redirectors
7335        d.forEach(["slice", "splice"], function(name){
7336                var f = ap[name];
7337                //Use a copy of the this array via this.slice() to allow .end() to work right in the splice case.
7338                // CANNOT apply ._stash()/end() to splice since it currently modifies
7339                // the existing this array -- it would break backward compatibility if we copy the array before
7340                // the splice so that we can use .end(). So only doing the stash option to this._wrap for slice.
7341                nlp[name] = function(){ return this._wrap(f.apply(this, arguments), name == "slice" ? this : null); };
7342        });
7343        // concat should be here but some browsers with native NodeList have problems with it
7344
7345        // add array.js redirectors
7346        d.forEach(["indexOf", "lastIndexOf", "every", "some"], function(name){
7347                var f = d[name];
7348                nlp[name] = function(){ return f.apply(d, [this].concat(aps.call(arguments, 0))); };
7349        });
7350
7351        // add conditional methods
7352        d.forEach(["attr", "style"], function(name){
7353                nlp[name] = adaptWithCondition(d[name], magicGuard);
7354        });
7355
7356        // add forEach actions
7357        d.forEach(["connect", "addClass", "removeClass", "replaceClass", "toggleClass", "empty", "removeAttr"], function(name){
7358                nlp[name] = adaptAsForEach(d[name]);
7359        });
7360
7361        dojo.extend(dojo.NodeList, {
7362                _normalize: function(/*String||Element||Object||NodeList*/content, /*DOMNode?*/refNode){
7363                        // summary:
7364                        //              normalizes data to an array of items to insert.
7365                        // description:
7366                        //              If content is an object, it can have special properties "template" and
7367                        //              "parse". If "template" is defined, then the template value is run through
7368                        //              dojo.string.substitute (if dojo.string.substitute has been dojo.required elsewhere),
7369                        //              or if templateFunc is a function on the content, that function will be used to
7370                        //              transform the template into a final string to be used for for passing to dojo._toDom.
7371                        //              If content.parse is true, then it is remembered for later, for when the content
7372                        //              nodes are inserted into the DOM. At that point, the nodes will be parsed for widgets
7373                        //              (if dojo.parser has been dojo.required elsewhere).
7374
7375                        //Wanted to just use a DocumentFragment, but for the array/NodeList
7376                        //case that meant  using cloneNode, but we may not want that.
7377                        //Cloning should only happen if the node operations span
7378                        //multiple refNodes. Also, need a real array, not a NodeList from the
7379                        //DOM since the node movements could change those NodeLists.
7380
7381                        var parse = content.parse === true ? true : false;
7382
7383                        //Do we have an object that needs to be run through a template?
7384                        if(typeof content.template == "string"){
7385                                var templateFunc = content.templateFunc || (dojo.string && dojo.string.substitute);
7386                                content = templateFunc ? templateFunc(content.template, content) : content;
7387                        }
7388
7389                        var type = (typeof content);
7390                        if(type == "string" || type == "number"){
7391                                content = dojo._toDom(content, (refNode && refNode.ownerDocument));
7392                                if(content.nodeType == 11){
7393                                        //DocumentFragment. It cannot handle cloneNode calls, so pull out the children.
7394                                        content = dojo._toArray(content.childNodes);
7395                                }else{
7396                                        content = [content];
7397                                }
7398                        }else if(!dojo.isArrayLike(content)){
7399                                content = [content];
7400                        }else if(!dojo.isArray(content)){
7401                                //To get to this point, content is array-like, but
7402                                //not an array, which likely means a DOM NodeList. Convert it now.
7403                                content = dojo._toArray(content);
7404                        }
7405
7406                        //Pass around the parse info
7407                        if(parse){
7408                                content._runParse = true;
7409                        }
7410                        return content; //Array
7411                },
7412
7413                _cloneNode: function(/*DOMNode*/ node){
7414                        // summary:
7415                        //              private utility to clone a node. Not very interesting in the vanilla
7416                        //              dojo.NodeList case, but delegates could do interesting things like
7417                        //              clone event handlers if that is derivable from the node.
7418                        return node.cloneNode(true);
7419                },
7420
7421                _place: function(/*Array*/ary, /*DOMNode*/refNode, /*String*/position, /*Boolean*/useClone){
7422                        // summary:
7423                        //              private utility to handle placing an array of nodes relative to another node.
7424                        // description:
7425                        //              Allows for cloning the nodes in the array, and for
7426                        //              optionally parsing widgets, if ary._runParse is true.
7427
7428                        //Avoid a disallowed operation if trying to do an innerHTML on a non-element node.
7429                        if(refNode.nodeType != 1 && position == "only"){
7430                                return;
7431                        }
7432                        var rNode = refNode, tempNode;
7433
7434                        //Always cycle backwards in case the array is really a
7435                        //DOM NodeList and the DOM operations take it out of the live collection.
7436                        var length = ary.length;
7437                        for(var i = length - 1; i >= 0; i--){
7438                                var node = (useClone ? this._cloneNode(ary[i]) : ary[i]);
7439
7440                                //If need widget parsing, use a temp node, instead of waiting after inserting into
7441                                //real DOM because we need to start widget parsing at one node up from current node,
7442                                //which could cause some already parsed widgets to be parsed again.
7443                                if(ary._runParse && dojo.parser && dojo.parser.parse){
7444                                        if(!tempNode){
7445                                                tempNode = rNode.ownerDocument.createElement("div");
7446                                        }
7447                                        tempNode.appendChild(node);
7448                                        dojo.parser.parse(tempNode);
7449                                        node = tempNode.firstChild;
7450                                        while(tempNode.firstChild){
7451                                                tempNode.removeChild(tempNode.firstChild);
7452                                        }
7453                                }
7454
7455                                if(i == length - 1){
7456                                        dojo.place(node, rNode, position);
7457                                }else{
7458                                        rNode.parentNode.insertBefore(node, rNode);
7459                                }
7460                                rNode = node;
7461                        }
7462                },
7463
7464                _stash: function(parent){
7465                        // summary:
7466                        //              private function to hold to a parent NodeList. end() to return the parent NodeList.
7467                        //
7468                        // example:
7469                        // How to make a `dojo.NodeList` method that only returns the third node in
7470                        // the dojo.NodeList but allows access to the original NodeList by using this._stash:
7471                        //      |       dojo.extend(dojo.NodeList, {
7472                        //      |               third: function(){
7473                        //  |                   var newNodeList = dojo.NodeList(this[2]);
7474                        //      |                       return newNodeList._stash(this);
7475                        //      |               }
7476                        //      |       });
7477                        //      |       // then see how _stash applies a sub-list, to be .end()'ed out of
7478                        //      |       dojo.query(".foo")
7479                        //      |               .third()
7480                        //      |                       .addClass("thirdFoo")
7481                        //      |               .end()
7482                        //      |               // access to the orig .foo list
7483                        //      |               .removeClass("foo")
7484                        //      |
7485                        //
7486                        this._parent = parent;
7487                        return this; //dojo.NodeList
7488                },
7489
7490                end: function(){
7491                        // summary:
7492                        //              Ends use of the current `dojo.NodeList` by returning the previous dojo.NodeList
7493                        //              that generated the current dojo.NodeList.
7494                        // description:
7495                        //              Returns the `dojo.NodeList` that generated the current `dojo.NodeList`. If there
7496                        //              is no parent dojo.NodeList, an empty dojo.NodeList is returned.
7497                        // example:
7498                        //      |       dojo.query("a")
7499                        //      |               .filter(".disabled")
7500                        //      |                       // operate on the anchors that only have a disabled class
7501                        //      |                       .style("color", "grey")
7502                        //      |               .end()
7503                        //      |               // jump back to the list of anchors
7504                        //      |               .style(...)
7505                        //
7506                        if(this._parent){
7507                                return this._parent;
7508                        }else{
7509                                //Just return empty list.
7510                                return new this._NodeListCtor();
7511                        }
7512                },
7513
7514                // http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array#Methods
7515
7516                // FIXME: handle return values for #3244
7517                //              http://trac.dojotoolkit.org/ticket/3244
7518
7519                // FIXME:
7520                //              need to wrap or implement:
7521                //                      join (perhaps w/ innerHTML/outerHTML overload for toString() of items?)
7522                //                      reduce
7523                //                      reduceRight
7524
7525                /*=====
7526                slice: function(begin, end){
7527                        // summary:
7528                        //              Returns a new NodeList, maintaining this one in place
7529                        // description:
7530                        //              This method behaves exactly like the Array.slice method
7531                        //              with the caveat that it returns a dojo.NodeList and not a
7532                        //              raw Array. For more details, see Mozilla's (slice
7533                        //              documentation)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:slice]
7534                        // begin: Integer
7535                        //              Can be a positive or negative integer, with positive
7536                        //              integers noting the offset to begin at, and negative
7537                        //              integers denoting an offset from the end (i.e., to the left
7538                        //              of the end)
7539                        // end: Integer?
7540                        //              Optional parameter to describe what position relative to
7541                        //              the NodeList's zero index to end the slice at. Like begin,
7542                        //              can be positive or negative.
7543                        return this._wrap(a.slice.apply(this, arguments));
7544                },
7545
7546                splice: function(index, howmany, item){
7547                        // summary:
7548                        //              Returns a new NodeList, manipulating this NodeList based on
7549                        //              the arguments passed, potentially splicing in new elements
7550                        //              at an offset, optionally deleting elements
7551                        // description:
7552                        //              This method behaves exactly like the Array.splice method
7553                        //              with the caveat that it returns a dojo.NodeList and not a
7554                        //              raw Array. For more details, see Mozilla's (splice
7555                        //              documentation)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:splice]
7556                        //              For backwards compatibility, calling .end() on the spliced NodeList
7557                        //              does not return the original NodeList -- splice alters the NodeList in place.
7558                        // index: Integer
7559                        //              begin can be a positive or negative integer, with positive
7560                        //              integers noting the offset to begin at, and negative
7561                        //              integers denoting an offset from the end (i.e., to the left
7562                        //              of the end)
7563                        // howmany: Integer?
7564                        //              Optional parameter to describe what position relative to
7565                        //              the NodeList's zero index to end the slice at. Like begin,
7566                        //              can be positive or negative.
7567                        // item: Object...?
7568                        //              Any number of optional parameters may be passed in to be
7569                        //              spliced into the NodeList
7570                        // returns:
7571                        //              dojo.NodeList
7572                        return this._wrap(a.splice.apply(this, arguments));
7573                },
7574
7575                indexOf: function(value, fromIndex){
7576                        //      summary:
7577                        //              see dojo.indexOf(). The primary difference is that the acted-on
7578                        //              array is implicitly this NodeList
7579                        // value: Object:
7580                        //              The value to search for.
7581                        // fromIndex: Integer?:
7582                        //              The location to start searching from. Optional. Defaults to 0.
7583                        //      description:
7584                        //              For more details on the behavior of indexOf, see Mozilla's
7585                        //              (indexOf
7586                        //              docs)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:indexOf]
7587                        //      returns:
7588                        //              Positive Integer or 0 for a match, -1 of not found.
7589                        return d.indexOf(this, value, fromIndex); // Integer
7590                },
7591
7592                lastIndexOf: function(value, fromIndex){
7593                        // summary:
7594                        //              see dojo.lastIndexOf(). The primary difference is that the
7595                        //              acted-on array is implicitly this NodeList
7596                        //      description:
7597                        //              For more details on the behavior of lastIndexOf, see
7598                        //              Mozilla's (lastIndexOf
7599                        //              docs)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:lastIndexOf]
7600                        // value: Object
7601                        //              The value to search for.
7602                        // fromIndex: Integer?
7603                        //              The location to start searching from. Optional. Defaults to 0.
7604                        // returns:
7605                        //              Positive Integer or 0 for a match, -1 of not found.
7606                        return d.lastIndexOf(this, value, fromIndex); // Integer
7607                },
7608
7609                every: function(callback, thisObject){
7610                        //      summary:
7611                        //              see `dojo.every()` and the (Array.every
7612                        //              docs)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:every].
7613                        //              Takes the same structure of arguments and returns as
7614                        //              dojo.every() with the caveat that the passed array is
7615                        //              implicitly this NodeList
7616                        // callback: Function: the callback
7617                        // thisObject: Object?: the context
7618                        return d.every(this, callback, thisObject); // Boolean
7619                },
7620
7621                some: function(callback, thisObject){
7622                        //      summary:
7623                        //              Takes the same structure of arguments and returns as
7624                        //              `dojo.some()` with the caveat that the passed array is
7625                        //              implicitly this NodeList.  See `dojo.some()` and Mozilla's
7626                        //              (Array.some
7627                        //              documentation)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:some].
7628                        // callback: Function: the callback
7629                        // thisObject: Object?: the context
7630                        return d.some(this, callback, thisObject); // Boolean
7631                },
7632                =====*/
7633
7634                concat: function(item){
7635                        // summary:
7636                        //              Returns a new NodeList comprised of items in this NodeList
7637                        //              as well as items passed in as parameters
7638                        // description:
7639                        //              This method behaves exactly like the Array.concat method
7640                        //              with the caveat that it returns a `dojo.NodeList` and not a
7641                        //              raw Array. For more details, see the (Array.concat
7642                        //              docs)[http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:concat]
7643                        // item: Object?
7644                        //              Any number of optional parameters may be passed in to be
7645                        //              spliced into the NodeList
7646                        // returns:
7647                        //              dojo.NodeList
7648
7649                        //return this._wrap(apc.apply(this, arguments));
7650                        // the line above won't work for the native NodeList :-(
7651
7652                        // implementation notes:
7653                        // 1) Native NodeList is not an array, and cannot be used directly
7654                        // in concat() --- the latter doesn't recognize it as an array, and
7655                        // does not inline it, but append as a single entity.
7656                        // 2) On some browsers (e.g., Safari) the "constructor" property is
7657                        // read-only and cannot be changed. So we have to test for both
7658                        // native NodeList and dojo.NodeList in this property to recognize
7659                        // the node list.
7660
7661                        var t = d.isArray(this) ? this : aps.call(this, 0),
7662                                m = d.map(arguments, function(a){
7663                                        return a && !d.isArray(a) &&
7664                                                (typeof NodeList != "undefined" && a.constructor === NodeList || a.constructor === this._NodeListCtor) ?
7665                                                        aps.call(a, 0) : a;
7666                                });
7667                        return this._wrap(apc.apply(t, m), this);       // dojo.NodeList
7668                },
7669
7670                map: function(/*Function*/ func, /*Function?*/ obj){
7671                        //      summary:
7672                        //              see dojo.map(). The primary difference is that the acted-on
7673                        //              array is implicitly this NodeList and the return is a
7674                        //              dojo.NodeList (a subclass of Array)
7675                        ///return d.map(this, func, obj, d.NodeList); // dojo.NodeList
7676                        return this._wrap(d.map(this, func, obj), this); // dojo.NodeList
7677                },
7678
7679                forEach: function(callback, thisObj){
7680                        //      summary:
7681                        //              see `dojo.forEach()`. The primary difference is that the acted-on
7682                        //              array is implicitly this NodeList. If you want the option to break out
7683                        //              of the forEach loop, use every() or some() instead.
7684                        d.forEach(this, callback, thisObj);
7685                        // non-standard return to allow easier chaining
7686                        return this; // dojo.NodeList
7687                },
7688
7689                /*=====
7690                coords: function(){
7691                        //      summary:
7692                        //              Returns the box objects of all elements in a node list as
7693                        //              an Array (*not* a NodeList). Acts like `dojo.coords`, though assumes
7694                        //              the node passed is each node in this list.
7695
7696                        return d.map(this, d.coords); // Array
7697                },
7698
7699                position: function(){
7700                        //      summary:
7701                        //              Returns border-box objects (x/y/w/h) of all elements in a node list
7702                        //              as an Array (*not* a NodeList). Acts like `dojo.position`, though
7703                        //              assumes the node passed is each node in this list.
7704
7705                        return d.map(this, d.position); // Array
7706                },
7707
7708                attr: function(property, value){
7709                        //      summary:
7710                        //              gets or sets the DOM attribute for every element in the
7711                        //              NodeList. See also `dojo.attr`
7712                        //      property: String
7713                        //              the attribute to get/set
7714                        //      value: String?
7715                        //              optional. The value to set the property to
7716                        //      returns:
7717                        //              if no value is passed, the result is an array of attribute values
7718                        //              If a value is passed, the return is this NodeList
7719                        //      example:
7720                        //              Make all nodes with a particular class focusable:
7721                        //      |       dojo.query(".focusable").attr("tabIndex", -1);
7722                        //      example:
7723                        //              Disable a group of buttons:
7724                        //      |       dojo.query("button.group").attr("disabled", true);
7725                        //      example:
7726                        //              innerHTML can be assigned or retrieved as well:
7727                        //      |       // get the innerHTML (as an array) for each list item
7728                        //      |       var ih = dojo.query("li.replaceable").attr("innerHTML");
7729                        return; // dojo.NodeList
7730                        return; // Array
7731                },
7732
7733                style: function(property, value){
7734                        //      summary:
7735                        //              gets or sets the CSS property for every element in the NodeList
7736                        //      property: String
7737                        //              the CSS property to get/set, in JavaScript notation
7738                        //              ("lineHieght" instead of "line-height")
7739                        //      value: String?
7740                        //              optional. The value to set the property to
7741                        //      returns:
7742                        //              if no value is passed, the result is an array of strings.
7743                        //              If a value is passed, the return is this NodeList
7744                        return; // dojo.NodeList
7745                        return; // Array
7746                },
7747
7748                addClass: function(className){
7749                        //      summary:
7750                        //              adds the specified class to every node in the list
7751                        //      className: String|Array
7752                        //              A String class name to add, or several space-separated class names,
7753                        //              or an array of class names.
7754                        return; // dojo.NodeList
7755                },
7756
7757                removeClass: function(className){
7758                        //      summary:
7759                        //              removes the specified class from every node in the list
7760                        //      className: String|Array?
7761                        //              An optional String class name to remove, or several space-separated
7762                        //              class names, or an array of class names. If omitted, all class names
7763                        //              will be deleted.
7764                        //      returns:
7765                        //              dojo.NodeList, this list
7766                        return; // dojo.NodeList
7767                },
7768
7769                toggleClass: function(className, condition){
7770                        //      summary:
7771                        //              Adds a class to node if not present, or removes if present.
7772                        //              Pass a boolean condition if you want to explicitly add or remove.
7773                        //      condition: Boolean?
7774                        //              If passed, true means to add the class, false means to remove.
7775                        //      className: String
7776                        //              the CSS class to add
7777                        return; // dojo.NodeList
7778                },
7779
7780                connect: function(methodName, objOrFunc, funcName){
7781                        //      summary:
7782                        //              attach event handlers to every item of the NodeList. Uses dojo.connect()
7783                        //              so event properties are normalized
7784                        //      methodName: String
7785                        //              the name of the method to attach to. For DOM events, this should be
7786                        //              the lower-case name of the event
7787                        //      objOrFunc: Object|Function|String
7788                        //              if 2 arguments are passed (methodName, objOrFunc), objOrFunc should
7789                        //              reference a function or be the name of the function in the global
7790                        //              namespace to attach. If 3 arguments are provided
7791                        //              (methodName, objOrFunc, funcName), objOrFunc must be the scope to
7792                        //              locate the bound function in
7793                        //      funcName: String?
7794                        //              optional. A string naming the function in objOrFunc to bind to the
7795                        //              event. May also be a function reference.
7796                        //      example:
7797                        //              add an onclick handler to every button on the page
7798                        //              |       dojo.query("div:nth-child(odd)").connect("onclick", function(e){
7799                        //              |               console.log("clicked!");
7800                        //              |       });
7801                        // example:
7802                        //              attach foo.bar() to every odd div's onmouseover
7803                        //              |       dojo.query("div:nth-child(odd)").connect("onmouseover", foo, "bar");
7804                },
7805
7806                empty: function(){
7807                        //      summary:
7808                        //              clears all content from each node in the list. Effectively
7809                        //              equivalent to removing all child nodes from every item in
7810                        //              the list.
7811                        return this.forEach("item.innerHTML='';"); // dojo.NodeList
7812                        // FIXME: should we be checking for and/or disposing of widgets below these nodes?
7813                },
7814                =====*/
7815
7816                // useful html methods
7817                coords: adaptAsMap(d.coords),
7818                position: adaptAsMap(d.position),
7819
7820                // FIXME: connectPublisher()? connectRunOnce()?
7821
7822                /*
7823                destroy: function(){
7824                        //      summary:
7825                        //              destroys every item in  the list.
7826                        this.forEach(d.destroy);
7827                        // FIXME: should we be checking for and/or disposing of widgets below these nodes?
7828                },
7829                */
7830
7831                place: function(/*String||Node*/ queryOrNode, /*String*/ position){
7832                        //      summary:
7833                        //              places elements of this node list relative to the first element matched
7834                        //              by queryOrNode. Returns the original NodeList. See: `dojo.place`
7835                        //      queryOrNode:
7836                        //              may be a string representing any valid CSS3 selector or a DOM node.
7837                        //              In the selector case, only the first matching element will be used
7838                        //              for relative positioning.
7839                        //      position:
7840                        //              can be one of:
7841                        //              |       "last" (default)
7842                        //              |       "first"
7843                        //              |       "before"
7844                        //              |       "after"
7845                        //              |       "only"
7846                        //              |       "replace"
7847                        //              or an offset in the childNodes property
7848                        var item = d.query(queryOrNode)[0];
7849                        return this.forEach(function(node){ d.place(node, item, position); }); // dojo.NodeList
7850                },
7851
7852                orphan: function(/*String?*/ filter){
7853                        //      summary:
7854                        //              removes elements in this list that match the filter
7855                        //              from their parents and returns them as a new NodeList.
7856                        //      filter:
7857                        //              CSS selector like ".foo" or "div > span"
7858                        //      returns:
7859                        //              `dojo.NodeList` containing the orphaned elements
7860                        return (filter ? d._filterQueryResult(this, filter) : this).forEach(orphan); // dojo.NodeList
7861                },
7862
7863                adopt: function(/*String||Array||DomNode*/ queryOrListOrNode, /*String?*/ position){
7864                        //      summary:
7865                        //              places any/all elements in queryOrListOrNode at a
7866                        //              position relative to the first element in this list.
7867                        //              Returns a dojo.NodeList of the adopted elements.
7868                        //      queryOrListOrNode:
7869                        //              a DOM node or a query string or a query result.
7870                        //              Represents the nodes to be adopted relative to the
7871                        //              first element of this NodeList.
7872                        //      position:
7873                        //              can be one of:
7874                        //              |       "last" (default)
7875                        //              |       "first"
7876                        //              |       "before"
7877                        //              |       "after"
7878                        //              |       "only"
7879                        //              |       "replace"
7880                        //              or an offset in the childNodes property
7881                        return d.query(queryOrListOrNode).place(this[0], position)._stash(this);        // dojo.NodeList
7882                },
7883
7884                // FIXME: do we need this?
7885                query: function(/*String*/ queryStr){
7886                        //      summary:
7887                        //              Returns a new list whose members match the passed query,
7888                        //              assuming elements of the current NodeList as the root for
7889                        //              each search.
7890                        //      example:
7891                        //              assume a DOM created by this markup:
7892                        //      |       <div id="foo">
7893                        //      |               <p>
7894                        //      |                       bacon is tasty, <span>dontcha think?</span>
7895                        //      |               </p>
7896                        //      |       </div>
7897                        //      |       <div id="bar">
7898                        //      |               <p>great comedians may not be funny <span>in person</span></p>
7899                        //      |       </div>
7900                        //              If we are presented with the following definition for a NodeList:
7901                        //      |       var l = new dojo.NodeList(dojo.byId("foo"), dojo.byId("bar"));
7902                        //              it's possible to find all span elements under paragraphs
7903                        //              contained by these elements with this sub-query:
7904                        //      |       var spans = l.query("p span");
7905
7906                        // FIXME: probably slow
7907                        if(!queryStr){ return this; }
7908                        var ret = this.map(function(node){
7909                                // FIXME: why would we ever get undefined here?
7910                                return d.query(queryStr, node).filter(function(subNode){ return subNode !== undefined; });
7911                        });
7912                        return this._wrap(apc.apply([], ret), this);    // dojo.NodeList
7913                },
7914
7915                filter: function(/*String|Function*/ filter){
7916                        //      summary:
7917                        //              "masks" the built-in javascript filter() method (supported
7918                        //              in Dojo via `dojo.filter`) to support passing a simple
7919                        //              string filter in addition to supporting filtering function
7920                        //              objects.
7921                        //      filter:
7922                        //              If a string, a CSS rule like ".thinger" or "div > span".
7923                        //      example:
7924                        //              "regular" JS filter syntax as exposed in dojo.filter:
7925                        //              |       dojo.query("*").filter(function(item){
7926                        //              |               // highlight every paragraph
7927                        //              |               return (item.nodeName == "p");
7928                        //              |       }).style("backgroundColor", "yellow");
7929                        // example:
7930                        //              the same filtering using a CSS selector
7931                        //              |       dojo.query("*").filter("p").styles("backgroundColor", "yellow");
7932
7933                        var a = arguments, items = this, start = 0;
7934                        if(typeof filter == "string"){ // inline'd type check
7935                                items = d._filterQueryResult(this, a[0]);
7936                                if(a.length == 1){
7937                                        // if we only got a string query, pass back the filtered results
7938                                        return items._stash(this); // dojo.NodeList
7939                                }
7940                                // if we got a callback, run it over the filtered items
7941                                start = 1;
7942                        }
7943                        return this._wrap(d.filter(items, a[start], a[start + 1]), this);       // dojo.NodeList
7944                },
7945
7946                /*
7947                // FIXME: should this be "copyTo" and include parenting info?
7948                clone: function(){
7949                        // summary:
7950                        //              creates node clones of each element of this list
7951                        //              and returns a new list containing the clones
7952                },
7953                */
7954
7955                addContent: function(/*String||DomNode||Object||dojo.NodeList*/ content, /*String||Integer?*/ position){
7956                        //      summary:
7957                        //              add a node, NodeList or some HTML as a string to every item in the
7958                        //              list.  Returns the original list.
7959                        //      description:
7960                        //              a copy of the HTML content is added to each item in the
7961                        //              list, with an optional position argument. If no position
7962                        //              argument is provided, the content is appended to the end of
7963                        //              each item.
7964                        //      content:
7965                        //              DOM node, HTML in string format, a NodeList or an Object. If a DOM node or
7966                        //              NodeList, the content will be cloned if the current NodeList has more than one
7967                        //              element. Only the DOM nodes are cloned, no event handlers. If it is an Object,
7968                        //              it should be an object with at "template" String property that has the HTML string
7969                        //              to insert. If dojo.string has already been dojo.required, then dojo.string.substitute
7970                        //              will be used on the "template" to generate the final HTML string. Other allowed
7971                        //              properties on the object are: "parse" if the HTML
7972                        //              string should be parsed for widgets (dojo.require("dojo.parser") to get that
7973                        //              option to work), and "templateFunc" if a template function besides dojo.string.substitute
7974                        //              should be used to transform the "template".
7975                        //      position:
7976                        //              can be one of:
7977                        //              |       "last"||"end" (default)
7978                        //              |       "first||"start"
7979                        //              |       "before"
7980                        //              |       "after"
7981                        //              |       "replace" (replaces nodes in this NodeList with new content)
7982                        //              |       "only" (removes other children of the nodes so new content is the only child)
7983                        //              or an offset in the childNodes property
7984                        //      example:
7985                        //              appends content to the end if the position is omitted
7986                        //      |       dojo.query("h3 > p").addContent("hey there!");
7987                        //      example:
7988                        //              add something to the front of each element that has a
7989                        //              "thinger" property:
7990                        //      |       dojo.query("[thinger]").addContent("...", "first");
7991                        //      example:
7992                        //              adds a header before each element of the list
7993                        //      |       dojo.query(".note").addContent("<h4>NOTE:</h4>", "before");
7994                        //      example:
7995                        //              add a clone of a DOM node to the end of every element in
7996                        //              the list, removing it from its existing parent.
7997                        //      |       dojo.query(".note").addContent(dojo.byId("foo"));
7998                        //  example:
7999                        //      Append nodes from a templatized string.
8000                        //              dojo.require("dojo.string");
8001                        //              dojo.query(".note").addContent({
8002                        //              template: '<b>${id}: </b><span>${name}</span>',
8003                        //                      id: "user332",
8004                        //              name: "Mr. Anderson"
8005                        //      });
8006                        //  example:
8007                        //      Append nodes from a templatized string that also has widgets parsed.
8008                        //      dojo.require("dojo.string");
8009                        //      dojo.require("dojo.parser");
8010                        //      var notes = dojo.query(".note").addContent({
8011                        //              template: '<button dojoType="dijit.form.Button">${text}</button>',
8012                        //              parse: true,
8013                        //              text: "Send"
8014                        //      });
8015                        content = this._normalize(content, this[0]);
8016                        for(var i = 0, node; (node = this[i]); i++){
8017                                this._place(content, node, position, i > 0);
8018                        }
8019                        return this; //dojo.NodeList
8020                },
8021
8022                instantiate: function(/*String|Object*/ declaredClass, /*Object?*/ properties){
8023                        //      summary:
8024                        //              Create a new instance of a specified class, using the
8025                        //              specified properties and each node in the nodeList as a
8026                        //              srcNodeRef.
8027                        //      example:
8028                        //              Grabs all buttons in the page and converts them to diji.form.Buttons.
8029                        //      |       var buttons = dojo.query("button").instantiate("dijit.form.Button", {showLabel: true});
8030                        var c = d.isFunction(declaredClass) ? declaredClass : d.getObject(declaredClass);
8031                        properties = properties || {};
8032                        return this.forEach(function(node){
8033                                new c(properties, node);
8034                        });     // dojo.NodeList
8035                },
8036
8037                at: function(/*===== index =====*/){
8038                        //      summary:
8039                        //              Returns a new NodeList comprised of items in this NodeList
8040                        //              at the given index or indices.
8041                        //
8042                        //      index: Integer...
8043                        //              One or more 0-based indices of items in the current
8044                        //              NodeList. A negative index will start at the end of the
8045                        //              list and go backwards.
8046                        //
8047                        //      example:
8048                        //      Shorten the list to the first, second, and third elements
8049                        //      |       dojo.query("a").at(0, 1, 2).forEach(fn);
8050                        //
8051                        //      example:
8052                        //      Retrieve the first and last elements of a unordered list:
8053                        //      |       dojo.query("ul > li").at(0, -1).forEach(cb);
8054                        //
8055                        //      example:
8056                        //      Do something for the first element only, but end() out back to
8057                        //      the original list and continue chaining:
8058                        //      |       dojo.query("a").at(0).onclick(fn).end().forEach(function(n){
8059                        //      |               console.log(n); // all anchors on the page.
8060                        //      |       })
8061                        //
8062                        //      returns:
8063                        //              dojo.NodeList
8064                        var t = new this._NodeListCtor();
8065                        d.forEach(arguments, function(i){
8066                                if(i < 0){ i = this.length + i }
8067                                if(this[i]){ t.push(this[i]); }
8068                        }, this);
8069                        return t._stash(this); // dojo.NodeList
8070                }
8071
8072        });
8073
8074        nl.events = [
8075                // summary:
8076                //              list of all DOM events used in NodeList
8077                "blur", "focus", "change", "click", "error", "keydown", "keypress",
8078                "keyup", "load", "mousedown", "mouseenter", "mouseleave", "mousemove",
8079                "mouseout", "mouseover", "mouseup", "submit"
8080        ];
8081
8082        // FIXME: pseudo-doc the above automatically generated on-event functions
8083
8084        // syntactic sugar for DOM events
8085        d.forEach(nl.events, function(evt){
8086                        var _oe = "on" + evt;
8087                        nlp[_oe] = function(a, b){
8088                                return this.connect(_oe, a, b);
8089                        };
8090                                // FIXME: should these events trigger publishes?
8091                                /*
8092                                return (a ? this.connect(_oe, a, b) :
8093                                                        this.forEach(function(n){
8094                                                                // FIXME:
8095                                                                //              listeners get buried by
8096                                                                //              addEventListener and can't be dug back
8097                                                                //              out to be triggered externally.
8098                                                                // see:
8099                                                                //              http://developer.mozilla.org/en/docs/DOM:element
8100
8101                                                                console.log(n, evt, _oe);
8102
8103                                                                // FIXME: need synthetic event support!
8104                                                                var _e = { target: n, faux: true, type: evt };
8105                                                                // dojo._event_listener._synthesizeEvent({}, { target: n, faux: true, type: evt });
8106                                                                try{ n[evt](_e); }catch(e){ console.log(e); }
8107                                                                try{ n[_oe](_e); }catch(e){ console.log(e); }
8108                                                        })
8109                                );
8110                                */
8111                }
8112        );
8113
8114})();
8115
8116}
8117
8118if(!dojo._hasResource["dojo._base.query"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
8119dojo._hasResource["dojo._base.query"] = true;
8120(function(){
8121
8122/*
8123        dojo.query() architectural overview:
8124
8125                dojo.query is a relatively full-featured CSS3 query library. It is
8126                designed to take any valid CSS3 selector and return the nodes matching
8127                the selector. To do this quickly, it processes queries in several
8128                steps, applying caching where profitable.
8129
8130                The steps (roughly in reverse order of the way they appear in the code):
8131                        1.) check to see if we already have a "query dispatcher"
8132                                - if so, use that with the given parameterization. Skip to step 4.
8133                        2.) attempt to determine which branch to dispatch the query to:
8134                                - JS (optimized DOM iteration)
8135                                - native (FF3.1+, Safari 3.1+, IE 8+)
8136                        3.) tokenize and convert to executable "query dispatcher"
8137                                - this is where the lion's share of the complexity in the
8138                                  system lies. In the DOM version, the query dispatcher is
8139                                  assembled as a chain of "yes/no" test functions pertaining to
8140                                  a section of a simple query statement (".blah:nth-child(odd)"
8141                                  but not "div div", which is 2 simple statements). Individual
8142                                  statement dispatchers are cached (to prevent re-definition)
8143                                  as are entire dispatch chains (to make re-execution of the
8144                                  same query fast)
8145                        4.) the resulting query dispatcher is called in the passed scope
8146                            (by default the top-level document)
8147                                - for DOM queries, this results in a recursive, top-down
8148                                  evaluation of nodes based on each simple query section
8149                                - for native implementations, this may mean working around spec
8150                                  bugs. So be it.
8151                        5.) matched nodes are pruned to ensure they are unique (if necessary)
8152*/
8153
8154var defineQuery= function(d){
8155        // define everything in a closure for compressability reasons. "d" is an
8156        // alias to "dojo" (or the toolkit alias object, e.g., "acme").
8157
8158        ////////////////////////////////////////////////////////////////////////
8159        // Toolkit aliases
8160        ////////////////////////////////////////////////////////////////////////
8161
8162        // if you are extracting dojo.query for use in your own system, you will
8163        // need to provide these methods and properties. No other porting should be
8164        // necessary, save for configuring the system to use a class other than
8165        // dojo.NodeList as the return instance instantiator
8166        var trim =                      d.trim;
8167        var each =                      d.forEach;
8168        //                                      d.isIE; // float
8169        //                                      d.isSafari; // float
8170        //                                      d.isOpera; // float
8171        //                                      d.isWebKit; // float
8172        //                                      d.doc ; // document element
8173        var qlc = (d._NodeListCtor =            d.NodeList);
8174
8175        var getDoc = function(){ return d.doc; };
8176        // NOTE(alex): the spec is idiotic. CSS queries should ALWAYS be case-sensitive, but nooooooo
8177        var cssCaseBug = ((d.isWebKit||d.isMozilla) && ((getDoc().compatMode) == "BackCompat"));
8178
8179        ////////////////////////////////////////////////////////////////////////
8180        // Global utilities
8181        ////////////////////////////////////////////////////////////////////////
8182
8183
8184        // on browsers that support the "children" collection we can avoid a lot of
8185        // iteration on chaff (non-element) nodes.
8186        // why.
8187        var childNodesName = !!getDoc().firstChild["children"] ? "children" : "childNodes";
8188
8189        var specials = ">~+";
8190
8191        // global thunk to determine whether we should treat the current query as
8192        // case sensitive or not. This switch is flipped by the query evaluator
8193        // based on the document passed as the context to search.
8194        var caseSensitive = false;
8195
8196        // how high?
8197        var yesman = function(){ return true; };
8198
8199        ////////////////////////////////////////////////////////////////////////
8200        // Tokenizer
8201        ////////////////////////////////////////////////////////////////////////
8202
8203        var getQueryParts = function(query){
8204                //      summary:
8205                //              state machine for query tokenization
8206                //      description:
8207                //              instead of using a brittle and slow regex-based CSS parser,
8208                //              dojo.query implements an AST-style query representation. This
8209                //              representation is only generated once per query. For example,
8210                //              the same query run multiple times or under different root nodes
8211                //              does not re-parse the selector expression but instead uses the
8212                //              cached data structure. The state machine implemented here
8213                //              terminates on the last " " (space) character and returns an
8214                //              ordered array of query component structures (or "parts"). Each
8215                //              part represents an operator or a simple CSS filtering
8216                //              expression. The structure for parts is documented in the code
8217                //              below.
8218
8219
8220                // NOTE:
8221                //              this code is designed to run fast and compress well. Sacrifices
8222                //              to readability and maintainability have been made.  Your best
8223                //              bet when hacking the tokenizer is to put The Donnas on *really*
8224                //              loud (may we recommend their "Spend The Night" release?) and
8225                //              just assume you're gonna make mistakes. Keep the unit tests
8226                //              open and run them frequently. Knowing is half the battle ;-)
8227                if(specials.indexOf(query.slice(-1)) >= 0){
8228                        // if we end with a ">", "+", or "~", that means we're implicitly
8229                        // searching all children, so make it explicit
8230                        query += " * "
8231                }else{
8232                        // if you have not provided a terminator, one will be provided for
8233                        // you...
8234                        query += " ";
8235                }
8236
8237                var ts = function(/*Integer*/ s, /*Integer*/ e){
8238                        // trim and slice.
8239
8240                        // take an index to start a string slice from and an end position
8241                        // and return a trimmed copy of that sub-string
8242                        return trim(query.slice(s, e));
8243                }
8244
8245                // the overall data graph of the full query, as represented by queryPart objects
8246                var queryParts = [];
8247
8248
8249                // state keeping vars
8250                var inBrackets = -1, inParens = -1, inMatchFor = -1,
8251                        inPseudo = -1, inClass = -1, inId = -1, inTag = -1,
8252                        lc = "", cc = "", pStart;
8253
8254                // iteration vars
8255                var x = 0, // index in the query
8256                        ql = query.length,
8257                        currentPart = null, // data structure representing the entire clause
8258                        _cp = null; // the current pseudo or attr matcher
8259
8260                // several temporary variables are assigned to this structure during a
8261                // potential sub-expression match:
8262                //              attr:
8263                //                      a string representing the current full attribute match in a
8264                //                      bracket expression
8265                //              type:
8266                //                      if there's an operator in a bracket expression, this is
8267                //                      used to keep track of it
8268                //              value:
8269                //                      the internals of parenthetical expression for a pseudo. for
8270                //                      :nth-child(2n+1), value might be "2n+1"
8271
8272                var endTag = function(){
8273                        // called when the tokenizer hits the end of a particular tag name.
8274                        // Re-sets state variables for tag matching and sets up the matcher
8275                        // to handle the next type of token (tag or operator).
8276                        if(inTag >= 0){
8277                                var tv = (inTag == x) ? null : ts(inTag, x); // .toLowerCase();
8278                                currentPart[ (specials.indexOf(tv) < 0) ? "tag" : "oper" ] = tv;
8279                                inTag = -1;
8280                        }
8281                }
8282
8283                var endId = function(){
8284                        // called when the tokenizer might be at the end of an ID portion of a match
8285                        if(inId >= 0){
8286                                currentPart.id = ts(inId, x).replace(/\\/g, "");
8287                                inId = -1;
8288                        }
8289                }
8290
8291                var endClass = function(){
8292                        // called when the tokenizer might be at the end of a class name
8293                        // match. CSS allows for multiple classes, so we augment the
8294                        // current item with another class in its list
8295                        if(inClass >= 0){
8296                                currentPart.classes.push(ts(inClass+1, x).replace(/\\/g, ""));
8297                                inClass = -1;
8298                        }
8299                }
8300
8301                var endAll = function(){
8302                        // at the end of a simple fragment, so wall off the matches
8303                        endId(); endTag(); endClass();
8304                }
8305
8306                var endPart = function(){
8307                        endAll();
8308                        if(inPseudo >= 0){
8309                                currentPart.pseudos.push({ name: ts(inPseudo+1, x) });
8310                        }
8311                        // hint to the selector engine to tell it whether or not it
8312                        // needs to do any iteration. Many simple selectors don't, and
8313                        // we can avoid significant construction-time work by advising
8314                        // the system to skip them
8315                        currentPart.loops = (
8316                                        currentPart.pseudos.length ||
8317                                        currentPart.attrs.length ||
8318                                        currentPart.classes.length      );
8319
8320                        currentPart.oquery = currentPart.query = ts(pStart, x); // save the full expression as a string
8321
8322
8323                        // otag/tag are hints to suggest to the system whether or not
8324                        // it's an operator or a tag. We save a copy of otag since the
8325                        // tag name is cast to upper-case in regular HTML matches. The
8326                        // system has a global switch to figure out if the current
8327                        // expression needs to be case sensitive or not and it will use
8328                        // otag or tag accordingly
8329                        currentPart.otag = currentPart.tag = (currentPart["oper"]) ? null : (currentPart.tag || "*");
8330
8331                        if(currentPart.tag){
8332                                // if we're in a case-insensitive HTML doc, we likely want
8333                                // the toUpperCase when matching on element.tagName. If we
8334                                // do it here, we can skip the string op per node
8335                                // comparison
8336                                currentPart.tag = currentPart.tag.toUpperCase();
8337                        }
8338
8339                        // add the part to the list
8340                        if(queryParts.length && (queryParts[queryParts.length-1].oper)){
8341                                // operators are always infix, so we remove them from the
8342                                // list and attach them to the next match. The evaluator is
8343                                // responsible for sorting out how to handle them.
8344                                currentPart.infixOper = queryParts.pop();
8345                                currentPart.query = currentPart.infixOper.query + " " + currentPart.query;
8346                                /*
8347                                console.debug(  "swapping out the infix",
8348                                                                currentPart.infixOper,
8349                                                                "and attaching it to",
8350                                                                currentPart);
8351                                */
8352                        }
8353                        queryParts.push(currentPart);
8354
8355                        currentPart = null;
8356                }
8357
8358                // iterate over the query, character by character, building up a
8359                // list of query part objects
8360                for(; lc=cc, cc=query.charAt(x), x < ql; x++){
8361                        //              cc: the current character in the match
8362                        //              lc: the last character (if any)
8363
8364                        // someone is trying to escape something, so don't try to match any
8365                        // fragments. We assume we're inside a literal.
8366                        if(lc == "\\"){ continue; }
8367                        if(!currentPart){ // a part was just ended or none has yet been created
8368                                // NOTE: I hate all this alloc, but it's shorter than writing tons of if's
8369                                pStart = x;
8370                                //      rules describe full CSS sub-expressions, like:
8371                                //              #someId
8372                                //              .className:first-child
8373                                //      but not:
8374                                //              thinger > div.howdy[type=thinger]
8375                                //      the indidual components of the previous query would be
8376                                //      split into 3 parts that would be represented a structure
8377                                //      like:
8378                                //              [
8379                                //                      {
8380                                //                              query: "thinger",
8381                                //                              tag: "thinger",
8382                                //                      },
8383                                //                      {
8384                                //                              query: "div.howdy[type=thinger]",
8385                                //                              classes: ["howdy"],
8386                                //                              infixOper: {
8387                                //                                      query: ">",
8388                                //                                      oper: ">",
8389                                //                              }
8390                                //                      },
8391                                //              ]
8392                                currentPart = {
8393                                        query: null, // the full text of the part's rule
8394                                        pseudos: [], // CSS supports multiple pseud-class matches in a single rule
8395                                        attrs: [],      // CSS supports multi-attribute match, so we need an array
8396                                        classes: [], // class matches may be additive, e.g.: .thinger.blah.howdy
8397                                        tag: null,      // only one tag...
8398                                        oper: null, // ...or operator per component. Note that these wind up being exclusive.
8399                                        id: null,       // the id component of a rule
8400                                        getTag: function(){
8401                                                return (caseSensitive) ? this.otag : this.tag;
8402                                        }
8403                                };
8404
8405                                // if we don't have a part, we assume we're going to start at
8406                                // the beginning of a match, which should be a tag name. This
8407                                // might fault a little later on, but we detect that and this
8408                                // iteration will still be fine.
8409                                inTag = x;
8410                        }
8411
8412                        if(inBrackets >= 0){
8413                                // look for a the close first
8414                                if(cc == "]"){ // if we're in a [...] clause and we end, do assignment
8415                                        if(!_cp.attr){
8416                                                // no attribute match was previously begun, so we
8417                                                // assume this is an attribute existence match in the
8418                                                // form of [someAttributeName]
8419                                                _cp.attr = ts(inBrackets+1, x);
8420                                        }else{
8421                                                // we had an attribute already, so we know that we're
8422                                                // matching some sort of value, as in [attrName=howdy]
8423                                                _cp.matchFor = ts((inMatchFor||inBrackets+1), x);
8424                                        }
8425                                        var cmf = _cp.matchFor;
8426                                        if(cmf){
8427                                                // try to strip quotes from the matchFor value. We want
8428                                                // [attrName=howdy] to match the same
8429                                                //      as [attrName = 'howdy' ]
8430                                                if(     (cmf.charAt(0) == '"') || (cmf.charAt(0)  == "'") ){
8431                                                        _cp.matchFor = cmf.slice(1, -1);
8432                                                }
8433                                        }
8434                                        // end the attribute by adding it to the list of attributes.
8435                                        currentPart.attrs.push(_cp);
8436                                        _cp = null; // necessary?
8437                                        inBrackets = inMatchFor = -1;
8438                                }else if(cc == "="){
8439                                        // if the last char was an operator prefix, make sure we
8440                                        // record it along with the "=" operator.
8441                                        var addToCc = ("|~^$*".indexOf(lc) >=0 ) ? lc : "";
8442                                        _cp.type = addToCc+cc;
8443                                        _cp.attr = ts(inBrackets+1, x-addToCc.length);
8444                                        inMatchFor = x+1;
8445                                }
8446                                // now look for other clause parts
8447                        }else if(inParens >= 0){
8448                                // if we're in a parenthetical expression, we need to figure
8449                                // out if it's attached to a pseudo-selector rule like
8450                                // :nth-child(1)
8451                                if(cc == ")"){
8452                                        if(inPseudo >= 0){
8453                                                _cp.value = ts(inParens+1, x);
8454                                        }
8455                                        inPseudo = inParens = -1;
8456                                }
8457                        }else if(cc == "#"){
8458                                // start of an ID match
8459                                endAll();
8460                                inId = x+1;
8461                        }else if(cc == "."){
8462                                // start of a class match
8463                                endAll();
8464                                inClass = x;
8465                        }else if(cc == ":"){
8466                                // start of a pseudo-selector match
8467                                endAll();
8468                                inPseudo = x;
8469                        }else if(cc == "["){
8470                                // start of an attribute match.
8471                                endAll();
8472                                inBrackets = x;
8473                                // provide a new structure for the attribute match to fill-in
8474                                _cp = {
8475                                        /*=====
8476                                        attr: null, type: null, matchFor: null
8477                                        =====*/
8478                                };
8479                        }else if(cc == "("){
8480                                // we really only care if we've entered a parenthetical
8481                                // expression if we're already inside a pseudo-selector match
8482                                if(inPseudo >= 0){
8483                                        // provide a new structure for the pseudo match to fill-in
8484                                        _cp = {
8485                                                name: ts(inPseudo+1, x),
8486                                                value: null
8487                                        }
8488                                        currentPart.pseudos.push(_cp);
8489                                }
8490                                inParens = x;
8491                        }else if(
8492                                (cc == " ") &&
8493                                // if it's a space char and the last char is too, consume the
8494                                // current one without doing more work
8495                                (lc != cc)
8496                        ){
8497                                endPart();
8498                        }
8499                }
8500                return queryParts;
8501        };
8502
8503
8504        ////////////////////////////////////////////////////////////////////////
8505        // DOM query infrastructure
8506        ////////////////////////////////////////////////////////////////////////
8507
8508        var agree = function(first, second){
8509                // the basic building block of the yes/no chaining system. agree(f1,
8510                // f2) generates a new function which returns the boolean results of
8511                // both of the passed functions to a single logical-anded result. If
8512                // either are not passed, the other is used exclusively.
8513                if(!first){ return second; }
8514                if(!second){ return first; }
8515
8516                return function(){
8517                        return first.apply(window, arguments) && second.apply(window, arguments);
8518                }
8519        };
8520
8521        var getArr = function(i, arr){
8522                // helps us avoid array alloc when we don't need it
8523                var r = arr||[]; // FIXME: should this be 'new d._NodeListCtor()' ?
8524                if(i){ r.push(i); }
8525                return r;
8526        };
8527
8528        var _isElement = function(n){ return (1 == n.nodeType); };
8529
8530        // FIXME: need to coalesce _getAttr with defaultGetter
8531        var blank = "";
8532        var _getAttr = function(elem, attr){
8533                if(!elem){ return blank; }
8534                if(attr == "class"){
8535                        return elem.className || blank;
8536                }
8537                if(attr == "for"){
8538                        return elem.htmlFor || blank;
8539                }
8540                if(attr == "style"){
8541                        return elem.style.cssText || blank;
8542                }
8543                return (caseSensitive ? elem.getAttribute(attr) : elem.getAttribute(attr, 2)) || blank;
8544        };
8545
8546        var attrs = {
8547                "*=": function(attr, value){
8548                        return function(elem){
8549                                // E[foo*="bar"]
8550                                //              an E element whose "foo" attribute value contains
8551                                //              the substring "bar"
8552                                return (_getAttr(elem, attr).indexOf(value)>=0);
8553                        }
8554                },
8555                "^=": function(attr, value){
8556                        // E[foo^="bar"]
8557                        //              an E element whose "foo" attribute value begins exactly
8558                        //              with the string "bar"
8559                        return function(elem){
8560                                return (_getAttr(elem, attr).indexOf(value)==0);
8561                        }
8562                },
8563                "$=": function(attr, value){
8564                        // E[foo$="bar"]
8565                        //              an E element whose "foo" attribute value ends exactly
8566                        //              with the string "bar"
8567                        var tval = " "+value;
8568                        return function(elem){
8569                                var ea = " "+_getAttr(elem, attr);
8570                                return (ea.lastIndexOf(value)==(ea.length-value.length));
8571                        }
8572                },
8573                "~=": function(attr, value){
8574                        // E[foo~="bar"]
8575                        //              an E element whose "foo" attribute value is a list of
8576                        //              space-separated values, one of which is exactly equal
8577                        //              to "bar"
8578
8579                        // return "[contains(concat(' ',@"+attr+",' '), ' "+ value +" ')]";
8580                        var tval = " "+value+" ";
8581                        return function(elem){
8582                                var ea = " "+_getAttr(elem, attr)+" ";
8583                                return (ea.indexOf(tval)>=0);
8584                        }
8585                },
8586                "|=": function(attr, value){
8587                        // E[hreflang|="en"]
8588                        //              an E element whose "hreflang" attribute has a
8589                        //              hyphen-separated list of values beginning (from the
8590                        //              left) with "en"
8591                        var valueDash = " "+value+"-";
8592                        return function(elem){
8593                                var ea = " "+_getAttr(elem, attr);
8594                                return (
8595                                        (ea == value) ||
8596                                        (ea.indexOf(valueDash)==0)
8597                                );
8598                        }
8599                },
8600                "=": function(attr, value){
8601                        return function(elem){
8602                                return (_getAttr(elem, attr) == value);
8603                        }
8604                }
8605        };
8606
8607        // avoid testing for node type if we can. Defining this in the negative
8608        // here to avoid negation in the fast path.
8609        var _noNES = (typeof getDoc().firstChild.nextElementSibling == "undefined");
8610        var _ns = !_noNES ? "nextElementSibling" : "nextSibling";
8611        var _ps = !_noNES ? "previousElementSibling" : "previousSibling";
8612        var _simpleNodeTest = (_noNES ? _isElement : yesman);
8613
8614        var _lookLeft = function(node){
8615                // look left
8616                while(node = node[_ps]){
8617                        if(_simpleNodeTest(node)){ return false; }
8618                }
8619                return true;
8620        };
8621
8622        var _lookRight = function(node){
8623                // look right
8624                while(node = node[_ns]){
8625                        if(_simpleNodeTest(node)){ return false; }
8626                }
8627                return true;
8628        };
8629
8630        var getNodeIndex = function(node){
8631                var root = node.parentNode;
8632                var i = 0,
8633                        tret = root[childNodesName],
8634                        ci = (node["_i"]||-1),
8635                        cl = (root["_l"]||-1);
8636
8637                if(!tret){ return -1; }
8638                var l = tret.length;
8639
8640                // we calculate the parent length as a cheap way to invalidate the
8641                // cache. It's not 100% accurate, but it's much more honest than what
8642                // other libraries do
8643                if( cl == l && ci >= 0 && cl >= 0 ){
8644                        // if it's legit, tag and release
8645                        return ci;
8646                }
8647
8648                // else re-key things
8649                root["_l"] = l;
8650                ci = -1;
8651                for(var te = root["firstElementChild"]||root["firstChild"]; te; te = te[_ns]){
8652                        if(_simpleNodeTest(te)){
8653                                te["_i"] = ++i;
8654                                if(node === te){
8655                                        // NOTE:
8656                                        //      shortcutting the return at this step in indexing works
8657                                        //      very well for benchmarking but we avoid it here since
8658                                        //      it leads to potential O(n^2) behavior in sequential
8659                                        //      getNodexIndex operations on a previously un-indexed
8660                                        //      parent. We may revisit this at a later time, but for
8661                                        //      now we just want to get the right answer more often
8662                                        //      than not.
8663                                        ci = i;
8664                                }
8665                        }
8666                }
8667                return ci;
8668        };
8669
8670        var isEven = function(elem){
8671                return !((getNodeIndex(elem)) % 2);
8672        };
8673
8674        var isOdd = function(elem){
8675                return ((getNodeIndex(elem)) % 2);
8676        };
8677
8678        var pseudos = {
8679                "checked": function(name, condition){
8680                        return function(elem){
8681                                return !!("checked" in elem ? elem.checked : elem.selected);
8682                        }
8683                },
8684                "first-child": function(){ return _lookLeft; },
8685                "last-child": function(){ return _lookRight; },
8686                "only-child": function(name, condition){
8687                        return function(node){
8688                                if(!_lookLeft(node)){ return false; }
8689                                if(!_lookRight(node)){ return false; }
8690                                return true;
8691                        };
8692                },
8693                "empty": function(name, condition){
8694                        return function(elem){
8695                                // DomQuery and jQuery get this wrong, oddly enough.
8696                                // The CSS 3 selectors spec is pretty explicit about it, too.
8697                                var cn = elem.childNodes;
8698                                var cnl = elem.childNodes.length;
8699                                // if(!cnl){ return true; }
8700                                for(var x=cnl-1; x >= 0; x--){
8701                                        var nt = cn[x].nodeType;
8702                                        if((nt === 1)||(nt == 3)){ return false; }
8703                                }
8704                                return true;
8705                        }
8706                },
8707                "contains": function(name, condition){
8708                        var cz = condition.charAt(0);
8709                        if( cz == '"' || cz == "'" ){ //remove quote
8710                                condition = condition.slice(1, -1);
8711                        }
8712                        return function(elem){
8713                                return (elem.innerHTML.indexOf(condition) >= 0);
8714                        }
8715                },
8716                "not": function(name, condition){
8717                        var p = getQueryParts(condition)[0];
8718                        var ignores = { el: 1 };
8719                        if(p.tag != "*"){
8720                                ignores.tag = 1;
8721                        }
8722                        if(!p.classes.length){
8723                                ignores.classes = 1;
8724                        }
8725                        var ntf = getSimpleFilterFunc(p, ignores);
8726                        return function(elem){
8727                                return (!ntf(elem));
8728                        }
8729                },
8730                "nth-child": function(name, condition){
8731                        var pi = parseInt;
8732                        // avoid re-defining function objects if we can
8733                        if(condition == "odd"){
8734                                return isOdd;
8735                        }else if(condition == "even"){
8736                                return isEven;
8737                        }
8738                        // FIXME: can we shorten this?
8739                        if(condition.indexOf("n") != -1){
8740                                var tparts = condition.split("n", 2);
8741                                var pred = tparts[0] ? ((tparts[0] == '-') ? -1 : pi(tparts[0])) : 1;
8742                                var idx = tparts[1] ? pi(tparts[1]) : 0;
8743                                var lb = 0, ub = -1;
8744                                if(pred > 0){
8745                                        if(idx < 0){
8746                                                idx = (idx % pred) && (pred + (idx % pred));
8747                                        }else if(idx>0){
8748                                                if(idx >= pred){
8749                                                        lb = idx - idx % pred;
8750                                                }
8751                                                idx = idx % pred;
8752                                        }
8753                                }else if(pred<0){
8754                                        pred *= -1;
8755                                        // idx has to be greater than 0 when pred is negative;
8756                                        // shall we throw an error here?
8757                                        if(idx > 0){
8758                                                ub = idx;
8759                                                idx = idx % pred;
8760                                        }
8761                                }
8762                                if(pred > 0){
8763                                        return function(elem){
8764                                                var i = getNodeIndex(elem);
8765                                                return (i>=lb) && (ub<0 || i<=ub) && ((i % pred) == idx);
8766                                        }
8767                                }else{
8768                                        condition = idx;
8769                                }
8770                        }
8771                        var ncount = pi(condition);
8772                        return function(elem){
8773                                return (getNodeIndex(elem) == ncount);
8774                        }
8775                }
8776        };
8777
8778        var defaultGetter = (d.isIE < 9 || (dojo.isIE && dojo.isQuirks)) ? function(cond){
8779                var clc = cond.toLowerCase();
8780                if(clc == "class"){ cond = "className"; }
8781                return function(elem){
8782                        return (caseSensitive ? elem.getAttribute(cond) : elem[cond]||elem[clc]);
8783                }
8784        } : function(cond){
8785                return function(elem){
8786                        return (elem && elem.getAttribute && elem.hasAttribute(cond));
8787                }
8788        };
8789
8790        var getSimpleFilterFunc = function(query, ignores){
8791                // generates a node tester function based on the passed query part. The
8792                // query part is one of the structures generated by the query parser
8793                // when it creates the query AST. The "ignores" object specifies which
8794                // (if any) tests to skip, allowing the system to avoid duplicating
8795                // work where it may have already been taken into account by other
8796                // factors such as how the nodes to test were fetched in the first
8797                // place
8798                if(!query){ return yesman; }
8799                ignores = ignores||{};
8800
8801                var ff = null;
8802
8803                if(!("el" in ignores)){
8804                        ff = agree(ff, _isElement);
8805                }
8806
8807                if(!("tag" in ignores)){
8808                        if(query.tag != "*"){
8809                                ff = agree(ff, function(elem){
8810                                        return (elem && (elem.tagName == query.getTag()));
8811                                });
8812                        }
8813                }
8814
8815                if(!("classes" in ignores)){
8816                        each(query.classes, function(cname, idx, arr){
8817                                // get the class name
8818                                /*
8819                                var isWildcard = cname.charAt(cname.length-1) == "*";
8820                                if(isWildcard){
8821                                        cname = cname.substr(0, cname.length-1);
8822                                }
8823                                // I dislike the regex thing, even if memoized in a cache, but it's VERY short
8824                                var re = new RegExp("(?:^|\\s)" + cname + (isWildcard ? ".*" : "") + "(?:\\s|$)");
8825                                */
8826                                var re = new RegExp("(?:^|\\s)" + cname + "(?:\\s|$)");
8827                                ff = agree(ff, function(elem){
8828                                        return re.test(elem.className);
8829                                });
8830                                ff.count = idx;
8831                        });
8832                }
8833
8834                if(!("pseudos" in ignores)){
8835                        each(query.pseudos, function(pseudo){
8836                                var pn = pseudo.name;
8837                                if(pseudos[pn]){
8838                                        ff = agree(ff, pseudos[pn](pn, pseudo.value));
8839                                }
8840                        });
8841                }
8842
8843                if(!("attrs" in ignores)){
8844                        each(query.attrs, function(attr){
8845                                var matcher;
8846                                var a = attr.attr;
8847                                // type, attr, matchFor
8848                                if(attr.type && attrs[attr.type]){
8849                                        matcher = attrs[attr.type](a, attr.matchFor);
8850                                }else if(a.length){
8851                                        matcher = defaultGetter(a);
8852                                }
8853                                if(matcher){
8854                                        ff = agree(ff, matcher);
8855                                }
8856                        });
8857                }
8858
8859                if(!("id" in ignores)){
8860                        if(query.id){
8861                                ff = agree(ff, function(elem){
8862                                        return (!!elem && (elem.id == query.id));
8863                                });
8864                        }
8865                }
8866
8867                if(!ff){
8868                        if(!("default" in ignores)){
8869                                ff = yesman;
8870                        }
8871                }
8872                return ff;
8873        };
8874
8875        var _nextSibling = function(filterFunc){
8876                return function(node, ret, bag){
8877                        while(node = node[_ns]){
8878                                if(_noNES && (!_isElement(node))){ continue; }
8879                                if(
8880                                        (!bag || _isUnique(node, bag)) &&
8881                                        filterFunc(node)
8882                                ){
8883                                        ret.push(node);
8884                                }
8885                                break;
8886                        }
8887                        return ret;
8888                }
8889        };
8890
8891        var _nextSiblings = function(filterFunc){
8892                return function(root, ret, bag){
8893                        var te = root[_ns];
8894                        while(te){
8895                                if(_simpleNodeTest(te)){
8896                                        if(bag && !_isUnique(te, bag)){
8897                                                break;
8898                                        }
8899                                        if(filterFunc(te)){
8900                                                ret.push(te);
8901                                        }
8902                                }
8903                                te = te[_ns];
8904                        }
8905                        return ret;
8906                }
8907        };
8908
8909        // get an array of child *elements*, skipping text and comment nodes
8910        var _childElements = function(filterFunc){
8911                filterFunc = filterFunc||yesman;
8912                return function(root, ret, bag){
8913                        // get an array of child elements, skipping text and comment nodes
8914                        var te, x = 0, tret = root[childNodesName];
8915                        while(te = tret[x++]){
8916                                if(
8917                                        _simpleNodeTest(te) &&
8918                                        (!bag || _isUnique(te, bag)) &&
8919                                        (filterFunc(te, x))
8920                                ){
8921                                        ret.push(te);
8922                                }
8923                        }
8924                        return ret;
8925                };
8926        };
8927
8928        /*
8929        // thanks, Dean!
8930        var itemIsAfterRoot = d.isIE ? function(item, root){
8931                return (item.sourceIndex > root.sourceIndex);
8932        } : function(item, root){
8933                return (item.compareDocumentPosition(root) == 2);
8934        };
8935        */
8936
8937        // test to see if node is below root
8938        var _isDescendant = function(node, root){
8939                var pn = node.parentNode;
8940                while(pn){
8941                        if(pn == root){
8942                                break;
8943                        }
8944                        pn = pn.parentNode;
8945                }
8946                return !!pn;
8947        };
8948
8949        var _getElementsFuncCache = {};
8950
8951        var getElementsFunc = function(query){
8952                var retFunc = _getElementsFuncCache[query.query];
8953                // if we've got a cached dispatcher, just use that
8954                if(retFunc){ return retFunc; }
8955                // else, generate a new on
8956
8957                // NOTE:
8958                //              this function returns a function that searches for nodes and
8959                //              filters them.  The search may be specialized by infix operators
8960                //              (">", "~", or "+") else it will default to searching all
8961                //              descendants (the " " selector). Once a group of children is
8962                //              found, a test function is applied to weed out the ones we
8963                //              don't want. Many common cases can be fast-pathed. We spend a
8964                //              lot of cycles to create a dispatcher that doesn't do more work
8965                //              than necessary at any point since, unlike this function, the
8966                //              dispatchers will be called every time. The logic of generating
8967                //              efficient dispatchers looks like this in pseudo code:
8968                //
8969                //              # if it's a purely descendant query (no ">", "+", or "~" modifiers)
8970                //              if infixOperator == " ":
8971                //                      if only(id):
8972                //                              return def(root):
8973                //                                      return d.byId(id, root);
8974                //
8975                //                      elif id:
8976                //                              return def(root):
8977                //                                      return filter(d.byId(id, root));
8978                //
8979                //                      elif cssClass && getElementsByClassName:
8980                //                              return def(root):
8981                //                                      return filter(root.getElementsByClassName(cssClass));
8982                //
8983                //                      elif only(tag):
8984                //                              return def(root):
8985                //                                      return root.getElementsByTagName(tagName);
8986                //
8987                //                      else:
8988                //                              # search by tag name, then filter
8989                //                              return def(root):
8990                //                                      return filter(root.getElementsByTagName(tagName||"*"));
8991                //
8992                //              elif infixOperator == ">":
8993                //                      # search direct children
8994                //                      return def(root):
8995                //                              return filter(root.children);
8996                //
8997                //              elif infixOperator == "+":
8998                //                      # search next sibling
8999                //                      return def(root):
9000                //                              return filter(root.nextElementSibling);
9001                //
9002                //              elif infixOperator == "~":
9003                //                      # search rightward siblings
9004                //                      return def(root):
9005                //                              return filter(nextSiblings(root));
9006
9007                var io = query.infixOper;
9008                var oper = (io ? io.oper : "");
9009                // the default filter func which tests for all conditions in the query
9010                // part. This is potentially inefficient, so some optimized paths may
9011                // re-define it to test fewer things.
9012                var filterFunc = getSimpleFilterFunc(query, { el: 1 });
9013                var qt = query.tag;
9014                var wildcardTag = ("*" == qt);
9015                var ecs = getDoc()["getElementsByClassName"];
9016
9017                if(!oper){
9018                        // if there's no infix operator, then it's a descendant query. ID
9019                        // and "elements by class name" variants can be accelerated so we
9020                        // call them out explicitly:
9021                        if(query.id){
9022                                // testing shows that the overhead of yesman() is acceptable
9023                                // and can save us some bytes vs. re-defining the function
9024                                // everywhere.
9025                                filterFunc = (!query.loops && wildcardTag) ?
9026                                        yesman :
9027                                        getSimpleFilterFunc(query, { el: 1, id: 1 });
9028
9029                                retFunc = function(root, arr){
9030                                        var te = d.byId(query.id, (root.ownerDocument||root));
9031                                        if(!te || !filterFunc(te)){ return; }
9032                                        if(9 == root.nodeType){ // if root's a doc, we just return directly
9033                                                return getArr(te, arr);
9034                                        }else{ // otherwise check ancestry
9035                                                if(_isDescendant(te, root)){
9036                                                        return getArr(te, arr);
9037                                                }
9038                                        }
9039                                }
9040                        }else if(
9041                                ecs &&
9042                                // isAlien check. Workaround for Prototype.js being totally evil/dumb.
9043                                /\{\s*\[native code\]\s*\}/.test(String(ecs)) &&
9044                                query.classes.length &&
9045                                !cssCaseBug
9046                        ){
9047                                // it's a class-based query and we've got a fast way to run it.
9048
9049                                // ignore class and ID filters since we will have handled both
9050                                filterFunc = getSimpleFilterFunc(query, { el: 1, classes: 1, id: 1 });
9051                                var classesString = query.classes.join(" ");
9052                                retFunc = function(root, arr, bag){
9053                                        var ret = getArr(0, arr), te, x=0;
9054                                        var tret = root.getElementsByClassName(classesString);
9055                                        while((te = tret[x++])){
9056                                                if(filterFunc(te, root) && _isUnique(te, bag)){
9057                                                        ret.push(te);
9058                                                }
9059                                        }
9060                                        return ret;
9061                                };
9062
9063                        }else if(!wildcardTag && !query.loops){
9064                                // it's tag only. Fast-path it.
9065                                retFunc = function(root, arr, bag){
9066                                        var ret = getArr(0, arr), te, x=0;
9067                                        var tret = root.getElementsByTagName(query.getTag());
9068                                        while((te = tret[x++])){
9069                                                if(_isUnique(te, bag)){
9070                                                        ret.push(te);
9071                                                }
9072                                        }
9073                                        return ret;
9074                                };
9075                        }else{
9076                                // the common case:
9077                                //              a descendant selector without a fast path. By now it's got
9078                                //              to have a tag selector, even if it's just "*" so we query
9079                                //              by that and filter
9080                                filterFunc = getSimpleFilterFunc(query, { el: 1, tag: 1, id: 1 });
9081                                retFunc = function(root, arr, bag){
9082                                        var ret = getArr(0, arr), te, x=0;
9083                                        // we use getTag() to avoid case sensitivity issues
9084                                        var tret = root.getElementsByTagName(query.getTag());
9085                                        while((te = tret[x++])){
9086                                                if(filterFunc(te, root) && _isUnique(te, bag)){
9087                                                        ret.push(te);
9088                                                }
9089                                        }
9090                                        return ret;
9091                                };
9092                        }
9093                }else{
9094                        // the query is scoped in some way. Instead of querying by tag we
9095                        // use some other collection to find candidate nodes
9096                        var skipFilters = { el: 1 };
9097                        if(wildcardTag){
9098                                skipFilters.tag = 1;
9099                        }
9100                        filterFunc = getSimpleFilterFunc(query, skipFilters);
9101                        if("+" == oper){
9102                                retFunc = _nextSibling(filterFunc);
9103                        }else if("~" == oper){
9104                                retFunc = _nextSiblings(filterFunc);
9105                        }else if(">" == oper){
9106                                retFunc = _childElements(filterFunc);
9107                        }
9108                }
9109                // cache it and return
9110                return _getElementsFuncCache[query.query] = retFunc;
9111        };
9112
9113        var filterDown = function(root, queryParts){
9114                // NOTE:
9115                //              this is the guts of the DOM query system. It takes a list of
9116                //              parsed query parts and a root and finds children which match
9117                //              the selector represented by the parts
9118                var candidates = getArr(root), qp, x, te, qpl = queryParts.length, bag, ret;
9119
9120                for(var i = 0; i < qpl; i++){
9121                        ret = [];
9122                        qp = queryParts[i];
9123                        x = candidates.length - 1;
9124                        if(x > 0){
9125                                // if we have more than one root at this level, provide a new
9126                                // hash to use for checking group membership but tell the
9127                                // system not to post-filter us since we will already have been
9128                                // gauranteed to be unique
9129                                bag = {};
9130                                ret.nozip = true;
9131                        }
9132                        var gef = getElementsFunc(qp);
9133                        for(var j = 0; (te = candidates[j]); j++){
9134                                // for every root, get the elements that match the descendant
9135                                // selector, adding them to the "ret" array and filtering them
9136                                // via membership in this level's bag. If there are more query
9137                                // parts, then this level's return will be used as the next
9138                                // level's candidates
9139                                gef(te, ret, bag);
9140                        }
9141                        if(!ret.length){ break; }
9142                        candidates = ret;
9143                }
9144                return ret;
9145        };
9146
9147        ////////////////////////////////////////////////////////////////////////
9148        // the query runner
9149        ////////////////////////////////////////////////////////////////////////
9150
9151        // these are the primary caches for full-query results. The query
9152        // dispatcher functions are generated then stored here for hash lookup in
9153        // the future
9154        var _queryFuncCacheDOM = {},
9155                _queryFuncCacheQSA = {};
9156
9157        // this is the second level of spliting, from full-length queries (e.g.,
9158        // "div.foo .bar") into simple query expressions (e.g., ["div.foo",
9159        // ".bar"])
9160        var getStepQueryFunc = function(query){
9161                var qparts = getQueryParts(trim(query));
9162
9163                // if it's trivial, avoid iteration and zipping costs
9164                if(qparts.length == 1){
9165                        // we optimize this case here to prevent dispatch further down the
9166                        // chain, potentially slowing things down. We could more elegantly
9167                        // handle this in filterDown(), but it's slower for simple things
9168                        // that need to be fast (e.g., "#someId").
9169                        var tef = getElementsFunc(qparts[0]);
9170                        return function(root){
9171                                var r = tef(root, new qlc());
9172                                if(r){ r.nozip = true; }
9173                                return r;
9174                        }
9175                }
9176
9177                // otherwise, break it up and return a runner that iterates over the parts recursively
9178                return function(root){
9179                        return filterDown(root, qparts);
9180                }
9181        };
9182
9183        // NOTES:
9184        //      * we can't trust QSA for anything but document-rooted queries, so
9185        //        caching is split into DOM query evaluators and QSA query evaluators
9186        //      * caching query results is dirty and leak-prone (or, at a minimum,
9187        //        prone to unbounded growth). Other toolkits may go this route, but
9188        //        they totally destroy their own ability to manage their memory
9189        //        footprint. If we implement it, it should only ever be with a fixed
9190        //        total element reference # limit and an LRU-style algorithm since JS
9191        //        has no weakref support. Caching compiled query evaluators is also
9192        //        potentially problematic, but even on large documents the size of the
9193        //        query evaluators is often < 100 function objects per evaluator (and
9194        //        LRU can be applied if it's ever shown to be an issue).
9195        //      * since IE's QSA support is currently only for HTML documents and even
9196        //        then only in IE 8's "standards mode", we have to detect our dispatch
9197        //        route at query time and keep 2 separate caches. Ugg.
9198
9199        // we need to determine if we think we can run a given query via
9200        // querySelectorAll or if we'll need to fall back on DOM queries to get
9201        // there. We need a lot of information about the environment and the query
9202        // to make the determiniation (e.g. does it support QSA, does the query in
9203        // question work in the native QSA impl, etc.).
9204        var nua = navigator.userAgent;
9205        // some versions of Safari provided QSA, but it was buggy and crash-prone.
9206        // We need te detect the right "internal" webkit version to make this work.
9207        var wk = "WebKit/";
9208        var is525 = (
9209                d.isWebKit &&
9210                (nua.indexOf(wk) > 0) &&
9211                (parseFloat(nua.split(wk)[1]) > 528)
9212        );
9213
9214        // IE QSA queries may incorrectly include comment nodes, so we throw the
9215        // zipping function into "remove" comments mode instead of the normal "skip
9216        // it" which every other QSA-clued browser enjoys
9217        var noZip = d.isIE ? "commentStrip" : "nozip";
9218
9219        var qsa = "querySelectorAll";
9220        var qsaAvail = (
9221                !!getDoc()[qsa] &&
9222                // see #5832
9223                (!d.isSafari || (d.isSafari > 3.1) || is525 )
9224        );
9225
9226        //Don't bother with n+3 type of matches, IE complains if we modify those.
9227        var infixSpaceRe = /n\+\d|([^ ])?([>~+])([^ =])?/g;
9228        var infixSpaceFunc = function(match, pre, ch, post) {
9229                return ch ? (pre ? pre + " " : "") + ch + (post ? " " + post : "") : /*n+3*/ match;
9230        };
9231
9232        var getQueryFunc = function(query, forceDOM){
9233                //Normalize query. The CSS3 selectors spec allows for omitting spaces around
9234                //infix operators, >, ~ and +
9235                //Do the work here since detection for spaces is used as a simple "not use QSA"
9236                //test below.
9237                query = query.replace(infixSpaceRe, infixSpaceFunc);
9238
9239                if(qsaAvail){
9240                        // if we've got a cached variant and we think we can do it, run it!
9241                        var qsaCached = _queryFuncCacheQSA[query];
9242                        if(qsaCached && !forceDOM){ return qsaCached; }
9243                }
9244
9245                // else if we've got a DOM cached variant, assume that we already know
9246                // all we need to and use it
9247                var domCached = _queryFuncCacheDOM[query];
9248                if(domCached){ return domCached; }
9249
9250                // TODO:
9251                //              today we're caching DOM and QSA branches separately so we
9252                //              recalc useQSA every time. If we had a way to tag root+query
9253                //              efficiently, we'd be in good shape to do a global cache.
9254
9255                var qcz = query.charAt(0);
9256                var nospace = (-1 == query.indexOf(" "));
9257
9258                // byId searches are wicked fast compared to QSA, even when filtering
9259                // is required
9260                if( (query.indexOf("#") >= 0) && (nospace) ){
9261                        forceDOM = true;
9262                }
9263
9264                var useQSA = (
9265                        qsaAvail && (!forceDOM) &&
9266                        // as per CSS 3, we can't currently start w/ combinator:
9267                        //              http://www.w3.org/TR/css3-selectors/#w3cselgrammar
9268                        (specials.indexOf(qcz) == -1) &&
9269                        // IE's QSA impl sucks on pseudos
9270                        (!d.isIE || (query.indexOf(":") == -1)) &&
9271
9272                        (!(cssCaseBug && (query.indexOf(".") >= 0))) &&
9273
9274                        // FIXME:
9275                        //              need to tighten up browser rules on ":contains" and "|=" to
9276                        //              figure out which aren't good
9277                        //              Latest webkit (around 531.21.8) does not seem to do well with :checked on option
9278                        //              elements, even though according to spec, selected options should
9279                        //              match :checked. So go nonQSA for it:
9280                        //              http://bugs.dojotoolkit.org/ticket/5179
9281                        (query.indexOf(":contains") == -1) && (query.indexOf(":checked") == -1) &&
9282                        (query.indexOf("|=") == -1) // some browsers don't grok it
9283                );
9284
9285                // TODO:
9286                //              if we've got a descendant query (e.g., "> .thinger" instead of
9287                //              just ".thinger") in a QSA-able doc, but are passed a child as a
9288                //              root, it should be possible to give the item a synthetic ID and
9289                //              trivially rewrite the query to the form "#synid > .thinger" to
9290                //              use the QSA branch
9291
9292
9293                if(useQSA){
9294                        var tq = (specials.indexOf(query.charAt(query.length-1)) >= 0) ?
9295                                                (query + " *") : query;
9296                        return _queryFuncCacheQSA[query] = function(root){
9297                                try{
9298                                        // the QSA system contains an egregious spec bug which
9299                                        // limits us, effectively, to only running QSA queries over
9300                                        // entire documents.  See:
9301                                        //              http://ejohn.org/blog/thoughts-on-queryselectorall/
9302                                        //      despite this, we can also handle QSA runs on simple
9303                                        //      selectors, but we don't want detection to be expensive
9304                                        //      so we're just checking for the presence of a space char
9305                                        //      right now. Not elegant, but it's cheaper than running
9306                                        //      the query parser when we might not need to
9307                                        if(!((9 == root.nodeType) || nospace)){ throw ""; }
9308                                        var r = root[qsa](tq);
9309                                        // skip expensive duplication checks and just wrap in a NodeList
9310                                        r[noZip] = true;
9311                                        return r;
9312                                }catch(e){
9313                                        // else run the DOM branch on this query, ensuring that we
9314                                        // default that way in the future
9315                                        return getQueryFunc(query, true)(root);
9316                                }
9317                        }
9318                }else{
9319                        // DOM branch
9320                        var parts = query.split(/\s*,\s*/);
9321                        return _queryFuncCacheDOM[query] = ((parts.length < 2) ?
9322                                // if not a compound query (e.g., ".foo, .bar"), cache and return a dispatcher
9323                                getStepQueryFunc(query) :
9324                                // if it *is* a complex query, break it up into its
9325                                // constituent parts and return a dispatcher that will
9326                                // merge the parts when run
9327                                function(root){
9328                                        var pindex = 0, // avoid array alloc for every invocation
9329                                                ret = [],
9330                                                tp;
9331                                        while((tp = parts[pindex++])){
9332                                                ret = ret.concat(getStepQueryFunc(tp)(root));
9333                                        }
9334                                        return ret;
9335                                }
9336                        );
9337                }
9338        };
9339
9340        var _zipIdx = 0;
9341
9342        // NOTE:
9343        //              this function is Moo inspired, but our own impl to deal correctly
9344        //              with XML in IE
9345        var _nodeUID = d.isIE ? function(node){
9346                if(caseSensitive){
9347                        // XML docs don't have uniqueID on their nodes
9348                        return (node.getAttribute("_uid") || node.setAttribute("_uid", ++_zipIdx) || _zipIdx);
9349
9350                }else{
9351                        return node.uniqueID;
9352                }
9353        } :
9354        function(node){
9355                return (node._uid || (node._uid = ++_zipIdx));
9356        };
9357
9358        // determine if a node in is unique in a "bag". In this case we don't want
9359        // to flatten a list of unique items, but rather just tell if the item in
9360        // question is already in the bag. Normally we'd just use hash lookup to do
9361        // this for us but IE's DOM is busted so we can't really count on that. On
9362        // the upside, it gives us a built in unique ID function.
9363        var _isUnique = function(node, bag){
9364                if(!bag){ return 1; }
9365                var id = _nodeUID(node);
9366                if(!bag[id]){ return bag[id] = 1; }
9367                return 0;
9368        };
9369
9370        // attempt to efficiently determine if an item in a list is a dupe,
9371        // returning a list of "uniques", hopefully in doucment order
9372        var _zipIdxName = "_zipIdx";
9373        var _zip = function(arr){
9374                if(arr && arr.nozip){
9375                        return (qlc._wrap) ? qlc._wrap(arr) : arr;
9376                }
9377                // var ret = new d._NodeListCtor();
9378                var ret = new qlc();
9379                if(!arr || !arr.length){ return ret; }
9380                if(arr[0]){
9381                        ret.push(arr[0]);
9382                }
9383                if(arr.length < 2){ return ret; }
9384
9385                _zipIdx++;
9386
9387                // we have to fork here for IE and XML docs because we can't set
9388                // expandos on their nodes (apparently). *sigh*
9389                if(d.isIE && caseSensitive){
9390                        var szidx = _zipIdx+"";
9391                        arr[0].setAttribute(_zipIdxName, szidx);
9392                        for(var x = 1, te; te = arr[x]; x++){
9393                                if(arr[x].getAttribute(_zipIdxName) != szidx){
9394                                        ret.push(te);
9395                                }
9396                                te.setAttribute(_zipIdxName, szidx);
9397                        }
9398                }else if(d.isIE && arr.commentStrip){
9399                        try{
9400                                for(var x = 1, te; te = arr[x]; x++){
9401                                        if(_isElement(te)){
9402                                                ret.push(te);
9403                                        }
9404                                }
9405                        }catch(e){ /* squelch */ }
9406                }else{
9407                        if(arr[0]){ arr[0][_zipIdxName] = _zipIdx; }
9408                        for(var x = 1, te; te = arr[x]; x++){
9409                                if(arr[x][_zipIdxName] != _zipIdx){
9410                                        ret.push(te);
9411                                }
9412                                te[_zipIdxName] = _zipIdx;
9413                        }
9414                }
9415                return ret;
9416        };
9417
9418        // the main executor
9419        d.query = function(/*String*/ query, /*String|DOMNode?*/ root){
9420                //      summary:
9421                //              Returns nodes which match the given CSS3 selector, searching the
9422                //              entire document by default but optionally taking a node to scope
9423                //              the search by. Returns an instance of dojo.NodeList.
9424                //      description:
9425                //              dojo.query() is the swiss army knife of DOM node manipulation in
9426                //              Dojo. Much like Prototype's "$$" (bling-bling) function or JQuery's
9427                //              "$" function, dojo.query provides robust, high-performance
9428                //              CSS-based node selector support with the option of scoping searches
9429                //              to a particular sub-tree of a document.
9430                //
9431                //              Supported Selectors:
9432                //              --------------------
9433                //
9434                //              dojo.query() supports a rich set of CSS3 selectors, including:
9435                //
9436                //                      * class selectors (e.g., `.foo`)
9437                //                      * node type selectors like `span`
9438                //                      * ` ` descendant selectors
9439                //                      * `>` child element selectors
9440                //                      * `#foo` style ID selectors
9441                //                      * `*` universal selector
9442                //                      * `~`, the preceded-by sibling selector
9443                //                      * `+`, the immediately preceded-by sibling selector
9444                //                      * attribute queries:
9445                //                      |       * `[foo]` attribute presence selector
9446                //                      |       * `[foo='bar']` attribute value exact match
9447                //                      |       * `[foo~='bar']` attribute value list item match
9448                //                      |       * `[foo^='bar']` attribute start match
9449                //                      |       * `[foo$='bar']` attribute end match
9450                //                      |       * `[foo*='bar']` attribute substring match
9451                //                      * `:first-child`, `:last-child`, and `:only-child` positional selectors
9452                //                      * `:empty` content emtpy selector
9453                //                      * `:checked` pseudo selector
9454                //                      * `:nth-child(n)`, `:nth-child(2n+1)` style positional calculations
9455                //                      * `:nth-child(even)`, `:nth-child(odd)` positional selectors
9456                //                      * `:not(...)` negation pseudo selectors
9457                //
9458                //              Any legal combination of these selectors will work with
9459                //              `dojo.query()`, including compound selectors ("," delimited).
9460                //              Very complex and useful searches can be constructed with this
9461                //              palette of selectors and when combined with functions for
9462                //              manipulation presented by dojo.NodeList, many types of DOM
9463                //              manipulation operations become very straightforward.
9464                //
9465                //              Unsupported Selectors:
9466                //              ----------------------
9467                //
9468                //              While dojo.query handles many CSS3 selectors, some fall outside of
9469                //              what's reasonable for a programmatic node querying engine to
9470                //              handle. Currently unsupported selectors include:
9471                //
9472                //                      * namespace-differentiated selectors of any form
9473                //                      * all `::` pseduo-element selectors
9474                //                      * certain pseduo-selectors which don't get a lot of day-to-day use:
9475                //                      |       * `:root`, `:lang()`, `:target`, `:focus`
9476                //                      * all visual and state selectors:
9477                //                      |       * `:root`, `:active`, `:hover`, `:visisted`, `:link`,
9478                //                                `:enabled`, `:disabled`
9479                //                      * `:*-of-type` pseudo selectors
9480                //
9481                //              dojo.query and XML Documents:
9482                //              -----------------------------
9483                //
9484                //              `dojo.query` (as of dojo 1.2) supports searching XML documents
9485                //              in a case-sensitive manner. If an HTML document is served with
9486                //              a doctype that forces case-sensitivity (e.g., XHTML 1.1
9487                //              Strict), dojo.query() will detect this and "do the right
9488                //              thing". Case sensitivity is dependent upon the document being
9489                //              searched and not the query used. It is therefore possible to
9490                //              use case-sensitive queries on strict sub-documents (iframes,
9491                //              etc.) or XML documents while still assuming case-insensitivity
9492                //              for a host/root document.
9493                //
9494                //              Non-selector Queries:
9495                //              ---------------------
9496                //
9497                //              If something other than a String is passed for the query,
9498                //              `dojo.query` will return a new `dojo.NodeList` instance
9499                //              constructed from that parameter alone and all further
9500                //              processing will stop. This means that if you have a reference
9501                //              to a node or NodeList, you can quickly construct a new NodeList
9502                //              from the original by calling `dojo.query(node)` or
9503                //              `dojo.query(list)`.
9504                //
9505                //      query:
9506                //              The CSS3 expression to match against. For details on the syntax of
9507                //              CSS3 selectors, see <http://www.w3.org/TR/css3-selectors/#selectors>
9508                //      root:
9509                //              A DOMNode (or node id) to scope the search from. Optional.
9510                //      returns: dojo.NodeList
9511                //              An instance of `dojo.NodeList`. Many methods are available on
9512                //              NodeLists for searching, iterating, manipulating, and handling
9513                //              events on the matched nodes in the returned list.
9514                //      example:
9515                //              search the entire document for elements with the class "foo":
9516                //      |       dojo.query(".foo");
9517                //              these elements will match:
9518                //      |       <span class="foo"></span>
9519                //      |       <span class="foo bar"></span>
9520                //      |       <p class="thud foo"></p>
9521                //      example:
9522                //              search the entire document for elements with the classes "foo" *and* "bar":
9523                //      |       dojo.query(".foo.bar");
9524                //              these elements will match:
9525                //      |       <span class="foo bar"></span>
9526                //              while these will not:
9527                //      |       <span class="foo"></span>
9528                //      |       <p class="thud foo"></p>
9529                //      example:
9530                //              find `<span>` elements which are descendants of paragraphs and
9531                //              which have a "highlighted" class:
9532                //      |       dojo.query("p span.highlighted");
9533                //              the innermost span in this fragment matches:
9534                //      |       <p class="foo">
9535                //      |               <span>...
9536                //      |                       <span class="highlighted foo bar">...</span>
9537                //      |               </span>
9538                //      |       </p>
9539                //      example:
9540                //              set an "odd" class on all odd table rows inside of the table
9541                //              `#tabular_data`, using the `>` (direct child) selector to avoid
9542                //              affecting any nested tables:
9543                //      |       dojo.query("#tabular_data > tbody > tr:nth-child(odd)").addClass("odd");
9544                //      example:
9545                //              remove all elements with the class "error" from the document
9546                //              and store them in a list:
9547                //      |       var errors = dojo.query(".error").orphan();
9548                //      example:
9549                //              add an onclick handler to every submit button in the document
9550                //              which causes the form to be sent via Ajax instead:
9551                //      |       dojo.query("input[type='submit']").onclick(function(e){
9552                //      |               dojo.stopEvent(e); // prevent sending the form
9553                //      |               var btn = e.target;
9554                //      |               dojo.xhrPost({
9555                //      |                       form: btn.form,
9556                //      |                       load: function(data){
9557                //      |                               // replace the form with the response
9558                //      |                               var div = dojo.doc.createElement("div");
9559                //      |                               dojo.place(div, btn.form, "after");
9560                //      |                               div.innerHTML = data;
9561                //      |                               dojo.style(btn.form, "display", "none");
9562                //      |                       }
9563                //      |               });
9564                //      |       });
9565
9566                //Set list constructor to desired value. This can change
9567                //between calls, so always re-assign here.
9568                qlc = d._NodeListCtor;
9569
9570                if(!query){
9571                        return new qlc();
9572                }
9573
9574                if(query.constructor == qlc){
9575                        return query;
9576                }
9577                if(typeof query != "string"){ // inline'd type check
9578                        return new qlc(query); // dojo.NodeList
9579                }
9580                if(typeof root == "string"){ // inline'd type check
9581                        root = d.byId(root);
9582                        if(!root){ return new qlc(); }
9583                }
9584
9585                root = root||getDoc();
9586                var od = root.ownerDocument||root.documentElement;
9587
9588                // throw the big case sensitivity switch
9589
9590                // NOTE:
9591                //              Opera in XHTML mode doesn't detect case-sensitivity correctly
9592                //              and it's not clear that there's any way to test for it
9593                caseSensitive = (root.contentType && root.contentType=="application/xml") ||
9594                                                (d.isOpera && (root.doctype || od.toString() == "[object XMLDocument]")) ||
9595                                                (!!od) &&
9596                                                (d.isIE ? od.xml : (root.xmlVersion||od.xmlVersion));
9597
9598                // NOTE:
9599                //              adding "true" as the 2nd argument to getQueryFunc is useful for
9600                //              testing the DOM branch without worrying about the
9601                //              behavior/performance of the QSA branch.
9602                var r = getQueryFunc(query)(root);
9603
9604                // FIXME:
9605                //              need to investigate this branch WRT #8074 and #8075
9606                if(r && r.nozip && !qlc._wrap){
9607                        return r;
9608                }
9609                return _zip(r); // dojo.NodeList
9610        }
9611
9612        // FIXME: need to add infrastructure for post-filtering pseudos, ala :last
9613        d.query.pseudos = pseudos;
9614
9615        // function for filtering a NodeList based on a selector, optimized for simple selectors
9616        d._filterQueryResult = function(/*NodeList*/ nodeList, /*String*/ filter, /*String|DOMNode?*/ root){
9617                var tmpNodeList = new d._NodeListCtor(),
9618                        parts = getQueryParts(filter),
9619                        filterFunc =
9620                                (parts.length == 1 && !/[^\w#\.]/.test(filter)) ?
9621                                getSimpleFilterFunc(parts[0]) :
9622                                function(node) {
9623                                        return dojo.query(filter, root).indexOf(node) != -1;
9624                                };
9625                for(var x = 0, te; te = nodeList[x]; x++){
9626                        if(filterFunc(te)){ tmpNodeList.push(te); }
9627                }
9628                return tmpNodeList;
9629        }
9630};//end defineQuery
9631
9632var defineAcme= function(){
9633        // a self-sufficient query impl
9634        acme = {
9635                trim: function(/*String*/ str){
9636                        // summary:
9637                        //              trims whitespaces from both sides of the string
9638                        str = str.replace(/^\s+/, '');
9639                        for(var i = str.length - 1; i >= 0; i--){
9640                                if(/\S/.test(str.charAt(i))){
9641                                        str = str.substring(0, i + 1);
9642                                        break;
9643                                }
9644                        }
9645                        return str;     // String
9646                },
9647                forEach: function(/*String*/ arr, /*Function*/ callback, /*Object?*/ thisObject){
9648                        //      summary:
9649                        //              an iterator function that passes items, indexes,
9650                        //              and the array to a callback
9651                        if(!arr || !arr.length){ return; }
9652                        for(var i=0,l=arr.length; i<l; ++i){
9653                                callback.call(thisObject||window, arr[i], i, arr);
9654                        }
9655                },
9656                byId: function(id, doc){
9657                        //      summary:
9658                        //              a function that return an element by ID, but also
9659                        //              accepts nodes safely
9660                        if(typeof id == "string"){
9661                                return (doc||document).getElementById(id); // DomNode
9662                        }else{
9663                                return id; // DomNode
9664                        }
9665                },
9666                // the default document to search
9667                doc: document,
9668                // the constructor for node list objects returned from query()
9669                NodeList: Array
9670        };
9671
9672        // define acme.isIE, acme.isSafari, acme.isOpera, etc.
9673        var n = navigator;
9674        var dua = n.userAgent;
9675        var dav = n.appVersion;
9676        var tv = parseFloat(dav);
9677        acme.isOpera = (dua.indexOf("Opera") >= 0) ? tv: undefined;
9678        acme.isKhtml = (dav.indexOf("Konqueror") >= 0) ? tv : undefined;
9679        acme.isWebKit = parseFloat(dua.split("WebKit/")[1]) || undefined;
9680        acme.isChrome = parseFloat(dua.split("Chrome/")[1]) || undefined;
9681        var index = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0);
9682        if(index && !acme.isChrome){
9683                acme.isSafari = parseFloat(dav.split("Version/")[1]);
9684                if(!acme.isSafari || parseFloat(dav.substr(index + 7)) <= 419.3){
9685                        acme.isSafari = 2;
9686                }
9687        }
9688        if(document.all && !acme.isOpera){
9689                acme.isIE = parseFloat(dav.split("MSIE ")[1]) || undefined;
9690        }
9691
9692        Array._wrap = function(arr){ return arr; };
9693  return acme;
9694};
9695
9696        //prefers queryPortability, then acme, then dojo
9697        if(this["dojo"]){
9698                dojo.provide("dojo._base.query");
9699
9700
9701                defineQuery(this["queryPortability"]||this["acme"]||dojo);
9702        }else{
9703                defineQuery(this["queryPortability"]||this["acme"]||defineAcme());
9704        }
9705
9706})();
9707
9708/*
9709*/
9710
9711}
9712
9713if(!dojo._hasResource["dojo._base.xhr"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
9714dojo._hasResource["dojo._base.xhr"] = true;
9715dojo.provide("dojo._base.xhr");
9716
9717
9718
9719
9720
9721
9722(function(){
9723        var _d = dojo, cfg = _d.config;
9724
9725        function setValue(/*Object*/obj, /*String*/name, /*String*/value){
9726                //summary:
9727                //              For the named property in object, set the value. If a value
9728                //              already exists and it is a string, convert the value to be an
9729                //              array of values.
9730
9731                //Skip it if there is no value
9732                if(value === null){
9733                        return;
9734                }
9735
9736                var val = obj[name];
9737                if(typeof val == "string"){ // inline'd type check
9738                        obj[name] = [val, value];
9739                }else if(_d.isArray(val)){
9740                        val.push(value);
9741                }else{
9742                        obj[name] = value;
9743                }
9744        }
9745
9746        dojo.fieldToObject = function(/*DOMNode||String*/ inputNode){
9747                // summary:
9748                //              Serialize a form field to a JavaScript object.
9749                //
9750                // description:
9751                //              Returns the value encoded in a form field as
9752                //              as a string or an array of strings. Disabled form elements
9753                //              and unchecked radio and checkboxes are skipped. Multi-select
9754                //              elements are returned as an array of string values.
9755                var ret = null;
9756                var item = _d.byId(inputNode);
9757                if(item){
9758                        var _in = item.name;
9759                        var type = (item.type||"").toLowerCase();
9760                        if(_in && type && !item.disabled){
9761                                if(type == "radio" || type == "checkbox"){
9762                                        if(item.checked){ ret = item.value; }
9763                                }else if(item.multiple){
9764                                        ret = [];
9765                                        _d.query("option", item).forEach(function(opt){
9766                                                if(opt.selected){
9767                                                        ret.push(opt.value);
9768                                                }
9769                                        });
9770                                }else{
9771                                        ret = item.value;
9772                                }
9773                        }
9774                }
9775                return ret; // Object
9776        };
9777
9778        dojo.formToObject = function(/*DOMNode||String*/ formNode){
9779                // summary:
9780                //              Serialize a form node to a JavaScript object.
9781                // description:
9782                //              Returns the values encoded in an HTML form as
9783                //              string properties in an object which it then returns. Disabled form
9784                //              elements, buttons, and other non-value form elements are skipped.
9785                //              Multi-select elements are returned as an array of string values.
9786                //
9787                // example:
9788                //              This form:
9789                //              |       <form id="test_form">
9790                //              |               <input type="text" name="blah" value="blah">
9791                //              |               <input type="text" name="no_value" value="blah" disabled>
9792                //              |               <input type="button" name="no_value2" value="blah">
9793                //              |               <select type="select" multiple name="multi" size="5">
9794                //              |                       <option value="blah">blah</option>
9795                //              |                       <option value="thud" selected>thud</option>
9796                //              |                       <option value="thonk" selected>thonk</option>
9797                //              |               </select>
9798                //              |       </form>
9799                //
9800                //              yields this object structure as the result of a call to
9801                //              formToObject():
9802                //
9803                //              |       {
9804                //              |               blah: "blah",
9805                //              |               multi: [
9806                //              |                       "thud",
9807                //              |                       "thonk"
9808                //              |               ]
9809                //              |       };
9810
9811                var ret = {};
9812                var exclude = "file|submit|image|reset|button|";
9813                _d.forEach(dojo.byId(formNode).elements, function(item){
9814                        var _in = item.name;
9815                        var type = (item.type||"").toLowerCase();
9816                        if(_in && type && exclude.indexOf(type) == -1 && !item.disabled){
9817                                setValue(ret, _in, _d.fieldToObject(item));
9818                                if(type == "image"){
9819                                        ret[_in+".x"] = ret[_in+".y"] = ret[_in].x = ret[_in].y = 0;
9820                                }
9821                        }
9822                });
9823                return ret; // Object
9824        };
9825
9826        dojo.objectToQuery = function(/*Object*/ map){
9827                //      summary:
9828                //              takes a name/value mapping object and returns a string representing
9829                //              a URL-encoded version of that object.
9830                //      example:
9831                //              this object:
9832                //
9833                //              |       {
9834                //              |               blah: "blah",
9835                //              |               multi: [
9836                //              |                       "thud",
9837                //              |                       "thonk"
9838                //              |               ]
9839                //              |       };
9840                //
9841                //      yields the following query string:
9842                //
9843                //      |       "blah=blah&multi=thud&multi=thonk"
9844
9845                // FIXME: need to implement encodeAscii!!
9846                var enc = encodeURIComponent;
9847                var pairs = [];
9848                var backstop = {};
9849                for(var name in map){
9850                        var value = map[name];
9851                        if(value != backstop[name]){
9852                                var assign = enc(name) + "=";
9853                                if(_d.isArray(value)){
9854                                        for(var i=0; i < value.length; i++){
9855                                                pairs.push(assign + enc(value[i]));
9856                                        }
9857                                }else{
9858                                        pairs.push(assign + enc(value));
9859                                }
9860                        }
9861                }
9862                return pairs.join("&"); // String
9863        };
9864
9865        dojo.formToQuery = function(/*DOMNode||String*/ formNode){
9866                // summary:
9867                //              Returns a URL-encoded string representing the form passed as either a
9868                //              node or string ID identifying the form to serialize
9869                return _d.objectToQuery(_d.formToObject(formNode)); // String
9870        };
9871
9872        dojo.formToJson = function(/*DOMNode||String*/ formNode, /*Boolean?*/prettyPrint){
9873                // summary:
9874                //              Create a serialized JSON string from a form node or string
9875                //              ID identifying the form to serialize
9876                return _d.toJson(_d.formToObject(formNode), prettyPrint); // String
9877        };
9878
9879        dojo.queryToObject = function(/*String*/ str){
9880                // summary:
9881                //              Create an object representing a de-serialized query section of a
9882                //              URL. Query keys with multiple values are returned in an array.
9883                //
9884                // example:
9885                //              This string:
9886                //
9887                //      |               "foo=bar&foo=baz&thinger=%20spaces%20=blah&zonk=blarg&"
9888                //
9889                //              results in this object structure:
9890                //
9891                //      |               {
9892                //      |                       foo: [ "bar", "baz" ],
9893                //      |                       thinger: " spaces =blah",
9894                //      |                       zonk: "blarg"
9895                //      |               }
9896                //
9897                //              Note that spaces and other urlencoded entities are correctly
9898                //              handled.
9899
9900                // FIXME: should we grab the URL string if we're not passed one?
9901                var ret = {};
9902                var qp = str.split("&");
9903                var dec = decodeURIComponent;
9904                _d.forEach(qp, function(item){
9905                        if(item.length){
9906                                var parts = item.split("=");
9907                                var name = dec(parts.shift());
9908                                var val = dec(parts.join("="));
9909                                if(typeof ret[name] == "string"){ // inline'd type check
9910                                        ret[name] = [ret[name]];
9911                                }
9912
9913                                if(_d.isArray(ret[name])){
9914                                        ret[name].push(val);
9915                                }else{
9916                                        ret[name] = val;
9917                                }
9918                        }
9919                });
9920                return ret; // Object
9921        };
9922
9923        // need to block async callbacks from snatching this thread as the result
9924        // of an async callback might call another sync XHR, this hangs khtml forever
9925        // must checked by watchInFlight()
9926
9927        dojo._blockAsync = false;
9928
9929        // MOW: remove dojo._contentHandlers alias in 2.0
9930        var handlers = _d._contentHandlers = dojo.contentHandlers = {
9931                // summary:
9932                //              A map of availble XHR transport handle types. Name matches the
9933                //              `handleAs` attribute passed to XHR calls.
9934                //
9935                // description:
9936                //              A map of availble XHR transport handle types. Name matches the
9937                //              `handleAs` attribute passed to XHR calls. Each contentHandler is
9938                //              called, passing the xhr object for manipulation. The return value
9939                //              from the contentHandler will be passed to the `load` or `handle`
9940                //              functions defined in the original xhr call.
9941                //
9942                // example:
9943                //              Creating a custom content-handler:
9944                //      |       dojo.contentHandlers.makeCaps = function(xhr){
9945                //      |               return xhr.responseText.toUpperCase();
9946                //      |       }
9947                //      |       // and later:
9948                //      |       dojo.xhrGet({
9949                //      |               url:"foo.txt",
9950                //      |               handleAs:"makeCaps",
9951                //      |               load: function(data){ /* data is a toUpper version of foo.txt */ }
9952                //      |       });
9953
9954                text: function(xhr){
9955                        // summary: A contentHandler which simply returns the plaintext response data
9956                        return xhr.responseText;
9957                },
9958                json: function(xhr){
9959                        // summary: A contentHandler which returns a JavaScript object created from the response data
9960                        return _d.fromJson(xhr.responseText || null);
9961                },
9962                "json-comment-filtered": function(xhr){
9963                        // summary: A contentHandler which expects comment-filtered JSON.
9964                        // description:
9965                        //              A contentHandler which expects comment-filtered JSON.
9966                        //              the json-comment-filtered option was implemented to prevent
9967                        //              "JavaScript Hijacking", but it is less secure than standard JSON. Use
9968                        //              standard JSON instead. JSON prefixing can be used to subvert hijacking.
9969                        //
9970                        //              Will throw a notice suggesting to use application/json mimetype, as
9971                        //              json-commenting can introduce security issues. To decrease the chances of hijacking,
9972                        //              use the standard `json` contentHandler, and prefix your "JSON" with: {}&&
9973                        //
9974                        //              use djConfig.useCommentedJson = true to turn off the notice
9975                        if(!dojo.config.useCommentedJson){
9976                                console.warn("Consider using the standard mimetype:application/json."
9977                                        + " json-commenting can introduce security issues. To"
9978                                        + " decrease the chances of hijacking, use the standard the 'json' handler and"
9979                                        + " prefix your json with: {}&&\n"
9980                                        + "Use djConfig.useCommentedJson=true to turn off this message.");
9981                        }
9982
9983                        var value = xhr.responseText;
9984                        var cStartIdx = value.indexOf("\/*");
9985                        var cEndIdx = value.lastIndexOf("*\/");
9986                        if(cStartIdx == -1 || cEndIdx == -1){
9987                                throw new Error("JSON was not comment filtered");
9988                        }
9989                        return _d.fromJson(value.substring(cStartIdx+2, cEndIdx));
9990                },
9991                javascript: function(xhr){
9992                        // summary: A contentHandler which evaluates the response data, expecting it to be valid JavaScript
9993
9994                        // FIXME: try Moz and IE specific eval variants?
9995                        return _d.eval(xhr.responseText);
9996                },
9997                xml: function(xhr){
9998                        // summary: A contentHandler returning an XML Document parsed from the response data
9999                        var result = xhr.responseXML;
10000                                                if(_d.isIE && (!result || !result.documentElement)){
10001                                //WARNING: this branch used by the xml handling in dojo.io.iframe,
10002                                //so be sure to test dojo.io.iframe if making changes below.
10003                                var ms = function(n){ return "MSXML" + n + ".DOMDocument"; };
10004                                var dp = ["Microsoft.XMLDOM", ms(6), ms(4), ms(3), ms(2)];
10005                                _d.some(dp, function(p){
10006                                        try{
10007                                                var dom = new ActiveXObject(p);
10008                                                dom.async = false;
10009                                                dom.loadXML(xhr.responseText);
10010                                                result = dom;
10011                                        }catch(e){ return false; }
10012                                        return true;
10013                                });
10014                        }
10015                                                return result; // DOMDocument
10016                },
10017                "json-comment-optional": function(xhr){
10018                        // summary: A contentHandler which checks the presence of comment-filtered JSON and
10019                        //              alternates between the `json` and `json-comment-filtered` contentHandlers.
10020                        if(xhr.responseText && /^[^{\[]*\/\*/.test(xhr.responseText)){
10021                                return handlers["json-comment-filtered"](xhr);
10022                        }else{
10023                                return handlers["json"](xhr);
10024                        }
10025                }
10026        };
10027
10028        /*=====
10029        dojo.__IoArgs = function(){
10030                //      url: String
10031                //              URL to server endpoint.
10032                //      content: Object?
10033                //              Contains properties with string values. These
10034                //              properties will be serialized as name1=value2 and
10035                //              passed in the request.
10036                //      timeout: Integer?
10037                //              Milliseconds to wait for the response. If this time
10038                //              passes, the then error callbacks are called.
10039                //      form: DOMNode?
10040                //              DOM node for a form. Used to extract the form values
10041                //              and send to the server.
10042                //      preventCache: Boolean?
10043                //              Default is false. If true, then a
10044                //              "dojo.preventCache" parameter is sent in the request
10045                //              with a value that changes with each request
10046                //              (timestamp). Useful only with GET-type requests.
10047                //      handleAs: String?
10048                //              Acceptable values depend on the type of IO
10049                //              transport (see specific IO calls for more information).
10050                //      rawBody: String?
10051                //              Sets the raw body for an HTTP request. If this is used, then the content
10052                //              property is ignored. This is mostly useful for HTTP methods that have
10053                //              a body to their requests, like PUT or POST. This property can be used instead
10054                //              of postData and putData for dojo.rawXhrPost and dojo.rawXhrPut respectively.
10055                //      ioPublish: Boolean?
10056                //              Set this explicitly to false to prevent publishing of topics related to
10057                //              IO operations. Otherwise, if djConfig.ioPublish is set to true, topics
10058                //              will be published via dojo.publish for different phases of an IO operation.
10059                //              See dojo.__IoPublish for a list of topics that are published.
10060                //      load: Function?
10061                //              This function will be
10062                //              called on a successful HTTP response code.
10063                //      error: Function?
10064                //              This function will
10065                //              be called when the request fails due to a network or server error, the url
10066                //              is invalid, etc. It will also be called if the load or handle callback throws an
10067                //              exception, unless djConfig.debugAtAllCosts is true.  This allows deployed applications
10068                //              to continue to run even when a logic error happens in the callback, while making
10069                //              it easier to troubleshoot while in debug mode.
10070                //      handle: Function?
10071                //              This function will
10072                //              be called at the end of every request, whether or not an error occurs.
10073                this.url = url;
10074                this.content = content;
10075                this.timeout = timeout;
10076                this.form = form;
10077                this.preventCache = preventCache;
10078                this.handleAs = handleAs;
10079                this.ioPublish = ioPublish;
10080                this.load = function(response, ioArgs){
10081                        // ioArgs: dojo.__IoCallbackArgs
10082                        //              Provides additional information about the request.
10083                        // response: Object
10084                        //              The response in the format as defined with handleAs.
10085                }
10086                this.error = function(response, ioArgs){
10087                        // ioArgs: dojo.__IoCallbackArgs
10088                        //              Provides additional information about the request.
10089                        // response: Object
10090                        //              The response in the format as defined with handleAs.
10091                }
10092                this.handle = function(loadOrError, response, ioArgs){
10093                        // loadOrError: String
10094                        //              Provides a string that tells you whether this function
10095                        //              was called because of success (load) or failure (error).
10096                        // response: Object
10097                        //              The response in the format as defined with handleAs.
10098                        // ioArgs: dojo.__IoCallbackArgs
10099                        //              Provides additional information about the request.
10100                }
10101        }
10102        =====*/
10103
10104        /*=====
10105        dojo.__IoCallbackArgs = function(args, xhr, url, query, handleAs, id, canDelete, json){
10106                //      args: Object
10107                //              the original object argument to the IO call.
10108                //      xhr: XMLHttpRequest
10109                //              For XMLHttpRequest calls only, the
10110                //              XMLHttpRequest object that was used for the
10111                //              request.
10112                //      url: String
10113                //              The final URL used for the call. Many times it
10114                //              will be different than the original args.url
10115                //              value.
10116                //      query: String
10117                //              For non-GET requests, the
10118                //              name1=value1&name2=value2 parameters sent up in
10119                //              the request.
10120                //      handleAs: String
10121                //              The final indicator on how the response will be
10122                //              handled.
10123                //      id: String
10124                //              For dojo.io.script calls only, the internal
10125                //              script ID used for the request.
10126                //      canDelete: Boolean
10127                //              For dojo.io.script calls only, indicates
10128                //              whether the script tag that represents the
10129                //              request can be deleted after callbacks have
10130                //              been called. Used internally to know when
10131                //              cleanup can happen on JSONP-type requests.
10132                //      json: Object
10133                //              For dojo.io.script calls only: holds the JSON
10134                //              response for JSONP-type requests. Used
10135                //              internally to hold on to the JSON responses.
10136                //              You should not need to access it directly --
10137                //              the same object should be passed to the success
10138                //              callbacks directly.
10139                this.args = args;
10140                this.xhr = xhr;
10141                this.url = url;
10142                this.query = query;
10143                this.handleAs = handleAs;
10144                this.id = id;
10145                this.canDelete = canDelete;
10146                this.json = json;
10147        }
10148        =====*/
10149
10150
10151        /*=====
10152        dojo.__IoPublish = function(){
10153                //      summary:
10154                //              This is a list of IO topics that can be published
10155                //              if djConfig.ioPublish is set to true. IO topics can be
10156                //              published for any Input/Output, network operation. So,
10157                //              dojo.xhr, dojo.io.script and dojo.io.iframe can all
10158                //              trigger these topics to be published.
10159                //      start: String
10160                //              "/dojo/io/start" is sent when there are no outstanding IO
10161                //              requests, and a new IO request is started. No arguments
10162                //              are passed with this topic.
10163                //      send: String
10164                //              "/dojo/io/send" is sent whenever a new IO request is started.
10165                //              It passes the dojo.Deferred for the request with the topic.
10166                //      load: String
10167                //              "/dojo/io/load" is sent whenever an IO request has loaded
10168                //              successfully. It passes the response and the dojo.Deferred
10169                //              for the request with the topic.
10170                //      error: String
10171                //              "/dojo/io/error" is sent whenever an IO request has errored.
10172                //              It passes the error and the dojo.Deferred
10173                //              for the request with the topic.
10174                //      done: String
10175                //              "/dojo/io/done" is sent whenever an IO request has completed,
10176                //              either by loading or by erroring. It passes the error and
10177                //              the dojo.Deferred for the request with the topic.
10178                //      stop: String
10179                //              "/dojo/io/stop" is sent when all outstanding IO requests have
10180                //              finished. No arguments are passed with this topic.
10181                this.start = "/dojo/io/start";
10182                this.send = "/dojo/io/send";
10183                this.load = "/dojo/io/load";
10184                this.error = "/dojo/io/error";
10185                this.done = "/dojo/io/done";
10186                this.stop = "/dojo/io/stop";
10187        }
10188        =====*/
10189
10190
10191        dojo._ioSetArgs = function(/*dojo.__IoArgs*/args,
10192                        /*Function*/canceller,
10193                        /*Function*/okHandler,
10194                        /*Function*/errHandler){
10195                //      summary:
10196                //              sets up the Deferred and ioArgs property on the Deferred so it
10197                //              can be used in an io call.
10198                //      args:
10199                //              The args object passed into the public io call. Recognized properties on
10200                //              the args object are:
10201                //      canceller:
10202                //              The canceller function used for the Deferred object. The function
10203                //              will receive one argument, the Deferred object that is related to the
10204                //              canceller.
10205                //      okHandler:
10206                //              The first OK callback to be registered with Deferred. It has the opportunity
10207                //              to transform the OK response. It will receive one argument -- the Deferred
10208                //              object returned from this function.
10209                //      errHandler:
10210                //              The first error callback to be registered with Deferred. It has the opportunity
10211                //              to do cleanup on an error. It will receive two arguments: error (the
10212                //              Error object) and dfd, the Deferred object returned from this function.
10213
10214                var ioArgs = {args: args, url: args.url};
10215
10216                //Get values from form if requestd.
10217                var formObject = null;
10218                if(args.form){
10219                        var form = _d.byId(args.form);
10220                        //IE requires going through getAttributeNode instead of just getAttribute in some form cases,
10221                        //so use it for all.  See #2844
10222                        var actnNode = form.getAttributeNode("action");
10223                        ioArgs.url = ioArgs.url || (actnNode ? actnNode.value : null);
10224                        formObject = _d.formToObject(form);
10225                }
10226
10227                // set up the query params
10228                var miArgs = [{}];
10229
10230                if(formObject){
10231                        // potentially over-ride url-provided params w/ form values
10232                        miArgs.push(formObject);
10233                }
10234                if(args.content){
10235                        // stuff in content over-rides what's set by form
10236                        miArgs.push(args.content);
10237                }
10238                if(args.preventCache){
10239                        miArgs.push({"dojo.preventCache": new Date().valueOf()});
10240                }
10241                ioArgs.query = _d.objectToQuery(_d.mixin.apply(null, miArgs));
10242
10243                // .. and the real work of getting the deferred in order, etc.
10244                ioArgs.handleAs = args.handleAs || "text";
10245                var d = new _d.Deferred(canceller);
10246                d.addCallbacks(okHandler, function(error){
10247                        return errHandler(error, d);
10248                });
10249
10250                //Support specifying load, error and handle callback functions from the args.
10251                //For those callbacks, the "this" object will be the args object.
10252                //The callbacks will get the deferred result value as the
10253                //first argument and the ioArgs object as the second argument.
10254                var ld = args.load;
10255                if(ld && _d.isFunction(ld)){
10256                        d.addCallback(function(value){
10257                                return ld.call(args, value, ioArgs);
10258                        });
10259                }
10260                var err = args.error;
10261                if(err && _d.isFunction(err)){
10262                        d.addErrback(function(value){
10263                                return err.call(args, value, ioArgs);
10264                        });
10265                }
10266                var handle = args.handle;
10267                if(handle && _d.isFunction(handle)){
10268                        d.addBoth(function(value){
10269                                return handle.call(args, value, ioArgs);
10270                        });
10271                }
10272
10273                //Plug in topic publishing, if dojo.publish is loaded.
10274                if(cfg.ioPublish && _d.publish && ioArgs.args.ioPublish !== false){
10275                        d.addCallbacks(
10276                                function(res){
10277                                        _d.publish("/dojo/io/load", [d, res]);
10278                                        return res;
10279                                },
10280                                function(res){
10281                                        _d.publish("/dojo/io/error", [d, res]);
10282                                        return res;
10283                                }
10284                        );
10285                        d.addBoth(function(res){
10286                                _d.publish("/dojo/io/done", [d, res]);
10287                                return res;
10288                        });
10289                }
10290
10291                d.ioArgs = ioArgs;
10292
10293                // FIXME: need to wire up the xhr object's abort method to something
10294                // analagous in the Deferred
10295                return d;
10296        };
10297
10298        var _deferredCancel = function(/*Deferred*/dfd){
10299                // summary: canceller function for dojo._ioSetArgs call.
10300
10301                dfd.canceled = true;
10302                var xhr = dfd.ioArgs.xhr;
10303                var _at = typeof xhr.abort;
10304                if(_at == "function" || _at == "object" || _at == "unknown"){
10305                        xhr.abort();
10306                }
10307                var err = dfd.ioArgs.error;
10308                if(!err){
10309                        err = new Error("xhr cancelled");
10310                        err.dojoType="cancel";
10311                }
10312                return err;
10313        };
10314        var _deferredOk = function(/*Deferred*/dfd){
10315                // summary: okHandler function for dojo._ioSetArgs call.
10316
10317                var ret = handlers[dfd.ioArgs.handleAs](dfd.ioArgs.xhr);
10318                return ret === undefined ? null : ret;
10319        };
10320        var _deferError = function(/*Error*/error, /*Deferred*/dfd){
10321                // summary: errHandler function for dojo._ioSetArgs call.
10322
10323                if(!dfd.ioArgs.args.failOk){
10324                        console.error(error);
10325                }
10326                return error;
10327        };
10328
10329        // avoid setting a timer per request. It degrades performance on IE
10330        // something fierece if we don't use unified loops.
10331        var _inFlightIntvl = null;
10332        var _inFlight = [];
10333
10334
10335        //Use a separate count for knowing if we are starting/stopping io calls.
10336        //Cannot use _inFlight.length since it can change at a different time than
10337        //when we want to do this kind of test. We only want to decrement the count
10338        //after a callback/errback has finished, since the callback/errback should be
10339        //considered as part of finishing a request.
10340        var _pubCount = 0;
10341        var _checkPubCount = function(dfd){
10342                if(_pubCount <= 0){
10343                        _pubCount = 0;
10344                        if(cfg.ioPublish && _d.publish && (!dfd || dfd && dfd.ioArgs.args.ioPublish !== false)){
10345                                _d.publish("/dojo/io/stop");
10346                        }
10347                }
10348        };
10349
10350        var _watchInFlight = function(){
10351                //summary:
10352                //              internal method that checks each inflight XMLHttpRequest to see
10353                //              if it has completed or if the timeout situation applies.
10354
10355                var now = (new Date()).getTime();
10356                // make sure sync calls stay thread safe, if this callback is called
10357                // during a sync call and this results in another sync call before the
10358                // first sync call ends the browser hangs
10359                if(!_d._blockAsync){
10360                        // we need manual loop because we often modify _inFlight (and therefore 'i') while iterating
10361                        // note: the second clause is an assigment on purpose, lint may complain
10362                        for(var i = 0, tif; i < _inFlight.length && (tif = _inFlight[i]); i++){
10363                                var dfd = tif.dfd;
10364                                var func = function(){
10365                                        if(!dfd || dfd.canceled || !tif.validCheck(dfd)){
10366                                                _inFlight.splice(i--, 1);
10367                                                _pubCount -= 1;
10368                                        }else if(tif.ioCheck(dfd)){
10369                                                _inFlight.splice(i--, 1);
10370                                                tif.resHandle(dfd);
10371                                                _pubCount -= 1;
10372                                        }else if(dfd.startTime){
10373                                                //did we timeout?
10374                                                if(dfd.startTime + (dfd.ioArgs.args.timeout || 0) < now){
10375                                                        _inFlight.splice(i--, 1);
10376                                                        var err = new Error("timeout exceeded");
10377                                                        err.dojoType = "timeout";
10378                                                        dfd.errback(err);
10379                                                        //Cancel the request so the io module can do appropriate cleanup.
10380                                                        dfd.cancel();
10381                                                        _pubCount -= 1;
10382                                                }
10383                                        }
10384                                };
10385                                if(dojo.config.debugAtAllCosts){
10386                                        func.call(this);
10387                                }else{
10388                                        try{
10389                                                func.call(this);
10390                                        }catch(e){
10391                                                dfd.errback(e);
10392                                        }
10393                                }
10394                        }
10395                }
10396
10397                _checkPubCount(dfd);
10398
10399                if(!_inFlight.length){
10400                        clearInterval(_inFlightIntvl);
10401                        _inFlightIntvl = null;
10402                        return;
10403                }
10404        };
10405
10406        dojo._ioCancelAll = function(){
10407                //summary: Cancels all pending IO requests, regardless of IO type
10408                //(xhr, script, iframe).
10409                try{
10410                        _d.forEach(_inFlight, function(i){
10411                                try{
10412                                        i.dfd.cancel();
10413                                }catch(e){/*squelch*/}
10414                        });
10415                }catch(e){/*squelch*/}
10416        };
10417
10418        //Automatically call cancel all io calls on unload
10419        //in IE for trac issue #2357.
10420                if(_d.isIE){
10421                _d.addOnWindowUnload(_d._ioCancelAll);
10422        }
10423
10424        _d._ioNotifyStart = function(/*Deferred*/dfd){
10425                // summary:
10426                //              If dojo.publish is available, publish topics
10427                //              about the start of a request queue and/or the
10428                //              the beginning of request.
10429                // description:
10430                //              Used by IO transports. An IO transport should
10431                //              call this method before making the network connection.
10432                if(cfg.ioPublish && _d.publish && dfd.ioArgs.args.ioPublish !== false){
10433                        if(!_pubCount){
10434                                _d.publish("/dojo/io/start");
10435                        }
10436                        _pubCount += 1;
10437                        _d.publish("/dojo/io/send", [dfd]);
10438                }
10439        };
10440
10441        _d._ioWatch = function(dfd, validCheck, ioCheck, resHandle){
10442                // summary:
10443                //              Watches the io request represented by dfd to see if it completes.
10444                // dfd: Deferred
10445                //              The Deferred object to watch.
10446                // validCheck: Function
10447                //              Function used to check if the IO request is still valid. Gets the dfd
10448                //              object as its only argument.
10449                // ioCheck: Function
10450                //              Function used to check if basic IO call worked. Gets the dfd
10451                //              object as its only argument.
10452                // resHandle: Function
10453                //              Function used to process response. Gets the dfd
10454                //              object as its only argument.
10455                var args = dfd.ioArgs.args;
10456                if(args.timeout){
10457                        dfd.startTime = (new Date()).getTime();
10458                }
10459
10460                _inFlight.push({dfd: dfd, validCheck: validCheck, ioCheck: ioCheck, resHandle: resHandle});
10461                if(!_inFlightIntvl){
10462                        _inFlightIntvl = setInterval(_watchInFlight, 50);
10463                }
10464                // handle sync requests
10465                //A weakness: async calls in flight
10466                //could have their handlers called as part of the
10467                //_watchInFlight call, before the sync's callbacks
10468                // are called.
10469                if(args.sync){
10470                        _watchInFlight();
10471                }
10472        };
10473
10474        var _defaultContentType = "application/x-www-form-urlencoded";
10475
10476        var _validCheck = function(/*Deferred*/dfd){
10477                return dfd.ioArgs.xhr.readyState; //boolean
10478        };
10479        var _ioCheck = function(/*Deferred*/dfd){
10480                return 4 == dfd.ioArgs.xhr.readyState; //boolean
10481        };
10482        var _resHandle = function(/*Deferred*/dfd){
10483                var xhr = dfd.ioArgs.xhr;
10484                if(_d._isDocumentOk(xhr)){
10485                        dfd.callback(dfd);
10486                }else{
10487                        var err = new Error("Unable to load " + dfd.ioArgs.url + " status:" + xhr.status);
10488                        err.status = xhr.status;
10489                        err.responseText = xhr.responseText;
10490                        dfd.errback(err);
10491                }
10492        };
10493
10494        dojo._ioAddQueryToUrl = function(/*dojo.__IoCallbackArgs*/ioArgs){
10495                //summary: Adds query params discovered by the io deferred construction to the URL.
10496                //Only use this for operations which are fundamentally GET-type operations.
10497                if(ioArgs.query.length){
10498                        ioArgs.url += (ioArgs.url.indexOf("?") == -1 ? "?" : "&") + ioArgs.query;
10499                        ioArgs.query = null;
10500                }
10501        };
10502
10503        /*=====
10504        dojo.declare("dojo.__XhrArgs", dojo.__IoArgs, {
10505                constructor: function(){
10506                        //      summary:
10507                        //              In addition to the properties listed for the dojo._IoArgs type,
10508                        //              the following properties are allowed for dojo.xhr* methods.
10509                        //      handleAs: String?
10510                        //              Acceptable values are: text (default), json, json-comment-optional,
10511                        //              json-comment-filtered, javascript, xml. See `dojo.contentHandlers`
10512                        //      sync: Boolean?
10513                        //              false is default. Indicates whether the request should
10514                        //              be a synchronous (blocking) request.
10515                        //      headers: Object?
10516                        //              Additional HTTP headers to send in the request.
10517                        //      failOk: Boolean?
10518                        //              false is default. Indicates whether a request should be
10519                        //              allowed to fail (and therefore no console error message in
10520                        //              the event of a failure)
10521                        this.handleAs = handleAs;
10522                        this.sync = sync;
10523                        this.headers = headers;
10524                        this.failOk = failOk;
10525                }
10526        });
10527        =====*/
10528
10529        dojo.xhr = function(/*String*/ method, /*dojo.__XhrArgs*/ args, /*Boolean?*/ hasBody){
10530                //      summary:
10531                //              Sends an HTTP request with the given method.
10532                //      description:
10533                //              Sends an HTTP request with the given method.
10534                //              See also dojo.xhrGet(), xhrPost(), xhrPut() and dojo.xhrDelete() for shortcuts
10535                //              for those HTTP methods. There are also methods for "raw" PUT and POST methods
10536                //              via dojo.rawXhrPut() and dojo.rawXhrPost() respectively.
10537                //      method:
10538                //              HTTP method to be used, such as GET, POST, PUT, DELETE.  Should be uppercase.
10539                //      hasBody:
10540                //              If the request has an HTTP body, then pass true for hasBody.
10541
10542                //Make the Deferred object for this xhr request.
10543                var dfd = _d._ioSetArgs(args, _deferredCancel, _deferredOk, _deferError);
10544                var ioArgs = dfd.ioArgs;
10545
10546                //Pass the args to _xhrObj, to allow alternate XHR calls based specific calls, like
10547                //the one used for iframe proxies.
10548                var xhr = ioArgs.xhr = _d._xhrObj(ioArgs.args);
10549                //If XHR factory fails, cancel the deferred.
10550                if(!xhr){
10551                        dfd.cancel();
10552                        return dfd;
10553                }
10554
10555                //Allow for specifying the HTTP body completely.
10556                if("postData" in args){
10557                        ioArgs.query = args.postData;
10558                }else if("putData" in args){
10559                        ioArgs.query = args.putData;
10560                }else if("rawBody" in args){
10561                        ioArgs.query = args.rawBody;
10562                }else if((arguments.length > 2 && !hasBody) || "POST|PUT".indexOf(method.toUpperCase()) == -1){
10563                        //Check for hasBody being passed. If no hasBody,
10564                        //then only append query string if not a POST or PUT request.
10565                        _d._ioAddQueryToUrl(ioArgs);
10566                }
10567
10568                // IE 6 is a steaming pile. It won't let you call apply() on the native function (xhr.open).
10569                // workaround for IE6's apply() "issues"
10570                xhr.open(method, ioArgs.url, args.sync !== true, args.user || undefined, args.password || undefined);
10571                if(args.headers){
10572                        for(var hdr in args.headers){
10573                                if(hdr.toLowerCase() === "content-type" && !args.contentType){
10574                                        args.contentType = args.headers[hdr];
10575                                }else if(args.headers[hdr]){
10576                                        //Only add header if it has a value. This allows for instnace, skipping
10577                                        //insertion of X-Requested-With by specifying empty value.
10578                                        xhr.setRequestHeader(hdr, args.headers[hdr]);
10579                                }
10580                        }
10581                }
10582                // FIXME: is this appropriate for all content types?
10583                xhr.setRequestHeader("Content-Type", args.contentType || _defaultContentType);
10584                if(!args.headers || !("X-Requested-With" in args.headers)){
10585                        xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
10586                }
10587                // FIXME: set other headers here!
10588                _d._ioNotifyStart(dfd);
10589                if(dojo.config.debugAtAllCosts){
10590                        xhr.send(ioArgs.query);
10591                }else{
10592                        try{
10593                                xhr.send(ioArgs.query);
10594                        }catch(e){
10595                                ioArgs.error = e;
10596                                dfd.cancel();
10597                        }
10598                }
10599                _d._ioWatch(dfd, _validCheck, _ioCheck, _resHandle);
10600                xhr = null;
10601                return dfd; // dojo.Deferred
10602        };
10603
10604        dojo.xhrGet = function(/*dojo.__XhrArgs*/ args){
10605                //      summary:
10606                //              Sends an HTTP GET request to the server.
10607                return _d.xhr("GET", args); // dojo.Deferred
10608        };
10609
10610        dojo.rawXhrPost = dojo.xhrPost = function(/*dojo.__XhrArgs*/ args){
10611                //      summary:
10612                //              Sends an HTTP POST request to the server. In addtion to the properties
10613                //              listed for the dojo.__XhrArgs type, the following property is allowed:
10614                //      postData:
10615                //              String. Send raw data in the body of the POST request.
10616                return _d.xhr("POST", args, true); // dojo.Deferred
10617        };
10618
10619        dojo.rawXhrPut = dojo.xhrPut = function(/*dojo.__XhrArgs*/ args){
10620                //      summary:
10621                //              Sends an HTTP PUT request to the server. In addtion to the properties
10622                //              listed for the dojo.__XhrArgs type, the following property is allowed:
10623                //      putData:
10624                //              String. Send raw data in the body of the PUT request.
10625                return _d.xhr("PUT", args, true); // dojo.Deferred
10626        };
10627
10628        dojo.xhrDelete = function(/*dojo.__XhrArgs*/ args){
10629                //      summary:
10630                //              Sends an HTTP DELETE request to the server.
10631                return _d.xhr("DELETE", args); //dojo.Deferred
10632        };
10633
10634        /*
10635        dojo.wrapForm = function(formNode){
10636                //summary:
10637                //              A replacement for FormBind, but not implemented yet.
10638
10639                // FIXME: need to think harder about what extensions to this we might
10640                // want. What should we allow folks to do w/ this? What events to
10641                // set/send?
10642                throw new Error("dojo.wrapForm not yet implemented");
10643        }
10644        */
10645})();
10646
10647}
10648
10649if(!dojo._hasResource["dojo._base.fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
10650dojo._hasResource["dojo._base.fx"] = true;
10651dojo.provide("dojo._base.fx");
10652
10653
10654
10655
10656
10657
10658/*
10659        Animation loosely package based on Dan Pupius' work, contributed under CLA:
10660                http://pupius.co.uk/js/Toolkit.Drawing.js
10661*/
10662(function(){
10663        var d = dojo;
10664        var _mixin = d._mixin;
10665
10666        dojo._Line = function(/*int*/ start, /*int*/ end){
10667                //      summary:
10668                //              dojo._Line is the object used to generate values from a start value
10669                //              to an end value
10670                //      start: int
10671                //              Beginning value for range
10672                //      end: int
10673                //              Ending value for range
10674                this.start = start;
10675                this.end = end;
10676        };
10677
10678        dojo._Line.prototype.getValue = function(/*float*/ n){
10679                //      summary: Returns the point on the line
10680                //      n: a floating point number greater than 0 and less than 1
10681                return ((this.end - this.start) * n) + this.start; // Decimal
10682        };
10683
10684        dojo.Animation = function(args){
10685                //      summary:
10686                //              A generic animation class that fires callbacks into its handlers
10687                //              object at various states.
10688                //      description:
10689                //              A generic animation class that fires callbacks into its handlers
10690                //              object at various states. Nearly all dojo animation functions
10691                //              return an instance of this method, usually without calling the
10692                //              .play() method beforehand. Therefore, you will likely need to
10693                //              call .play() on instances of `dojo.Animation` when one is
10694                //              returned.
10695                // args: Object
10696                //              The 'magic argument', mixing all the properties into this
10697                //              animation instance.
10698
10699                _mixin(this, args);
10700                if(d.isArray(this.curve)){
10701                        this.curve = new d._Line(this.curve[0], this.curve[1]);
10702                }
10703
10704        };
10705
10706        // Alias to drop come 2.0:
10707        d._Animation = d.Animation;
10708
10709        d.extend(dojo.Animation, {
10710                // duration: Integer
10711                //              The time in milliseonds the animation will take to run
10712                duration: 350,
10713
10714        /*=====
10715                // curve: dojo._Line|Array
10716                //              A two element array of start and end values, or a `dojo._Line` instance to be
10717                //              used in the Animation.
10718                curve: null,
10719
10720                // easing: Function?
10721                //              A Function to adjust the acceleration (or deceleration) of the progress
10722                //              across a dojo._Line
10723                easing: null,
10724        =====*/
10725
10726                // repeat: Integer?
10727                //              The number of times to loop the animation
10728                repeat: 0,
10729
10730                // rate: Integer?
10731                //              the time in milliseconds to wait before advancing to next frame
10732                //              (used as a fps timer: 1000/rate = fps)
10733                rate: 20 /* 50 fps */,
10734
10735        /*=====
10736                // delay: Integer?
10737                //              The time in milliseconds to wait before starting animation after it
10738                //              has been .play()'ed
10739                delay: null,
10740
10741                // beforeBegin: Event?
10742                //              Synthetic event fired before a dojo.Animation begins playing (synchronous)
10743                beforeBegin: null,
10744
10745                // onBegin: Event?
10746                //              Synthetic event fired as a dojo.Animation begins playing (useful?)
10747                onBegin: null,
10748
10749                // onAnimate: Event?
10750                //              Synthetic event fired at each interval of a `dojo.Animation`
10751                onAnimate: null,
10752
10753                // onEnd: Event?
10754                //              Synthetic event fired after the final frame of a `dojo.Animation`
10755                onEnd: null,
10756
10757                // onPlay: Event?
10758                //              Synthetic event fired any time a `dojo.Animation` is play()'ed
10759                onPlay: null,
10760
10761                // onPause: Event?
10762                //              Synthetic event fired when a `dojo.Animation` is paused
10763                onPause: null,
10764
10765                // onStop: Event
10766                //              Synthetic event fires when a `dojo.Animation` is stopped
10767                onStop: null,
10768
10769        =====*/
10770
10771                _percent: 0,
10772                _startRepeatCount: 0,
10773
10774                _getStep: function(){
10775                        var _p = this._percent,
10776                                _e = this.easing
10777                        ;
10778                        return _e ? _e(_p) : _p;
10779                },
10780                _fire: function(/*Event*/ evt, /*Array?*/ args){
10781                        //      summary:
10782                        //              Convenience function.  Fire event "evt" and pass it the
10783                        //              arguments specified in "args".
10784                        //      description:
10785                        //              Convenience function.  Fire event "evt" and pass it the
10786                        //              arguments specified in "args".
10787                        //              Fires the callback in the scope of the `dojo.Animation`
10788                        //              instance.
10789                        //      evt:
10790                        //              The event to fire.
10791                        //      args:
10792                        //              The arguments to pass to the event.
10793                        var a = args||[];
10794                        if(this[evt]){
10795                                if(d.config.debugAtAllCosts){
10796                                        this[evt].apply(this, a);
10797                                }else{
10798                                        try{
10799                                                this[evt].apply(this, a);
10800                                        }catch(e){
10801                                                // squelch and log because we shouldn't allow exceptions in
10802                                                // synthetic event handlers to cause the internal timer to run
10803                                                // amuck, potentially pegging the CPU. I'm not a fan of this
10804                                                // squelch, but hopefully logging will make it clear what's
10805                                                // going on
10806                                                console.error("exception in animation handler for:", evt);
10807                                                console.error(e);
10808                                        }
10809                                }
10810                        }
10811                        return this; // dojo.Animation
10812                },
10813
10814                play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
10815                        // summary:
10816                        //              Start the animation.
10817                        // delay:
10818                        //              How many milliseconds to delay before starting.
10819                        // gotoStart:
10820                        //              If true, starts the animation from the beginning; otherwise,
10821                        //              starts it from its current position.
10822                        // returns: dojo.Animation
10823                        //              The instance to allow chaining.
10824
10825                        var _t = this;
10826                        if(_t._delayTimer){ _t._clearTimer(); }
10827                        if(gotoStart){
10828                                _t._stopTimer();
10829                                _t._active = _t._paused = false;
10830                                _t._percent = 0;
10831                        }else if(_t._active && !_t._paused){
10832                                return _t;
10833                        }
10834
10835                        _t._fire("beforeBegin", [_t.node]);
10836
10837                        var de = delay || _t.delay,
10838                                _p = dojo.hitch(_t, "_play", gotoStart);
10839
10840                        if(de > 0){
10841                                _t._delayTimer = setTimeout(_p, de);
10842                                return _t;
10843                        }
10844                        _p();
10845                        return _t;
10846                },
10847
10848                _play: function(gotoStart){
10849                        var _t = this;
10850                        if(_t._delayTimer){ _t._clearTimer(); }
10851                        _t._startTime = new Date().valueOf();
10852                        if(_t._paused){
10853                                _t._startTime -= _t.duration * _t._percent;
10854                        }
10855
10856                        _t._active = true;
10857                        _t._paused = false;
10858                        var value = _t.curve.getValue(_t._getStep());
10859                        if(!_t._percent){
10860                                if(!_t._startRepeatCount){
10861                                        _t._startRepeatCount = _t.repeat;
10862                                }
10863                                _t._fire("onBegin", [value]);
10864                        }
10865
10866                        _t._fire("onPlay", [value]);
10867
10868                        _t._cycle();
10869                        return _t; // dojo.Animation
10870                },
10871
10872                pause: function(){
10873                        // summary: Pauses a running animation.
10874                        var _t = this;
10875                        if(_t._delayTimer){ _t._clearTimer(); }
10876                        _t._stopTimer();
10877                        if(!_t._active){ return _t; /*dojo.Animation*/ }
10878                        _t._paused = true;
10879                        _t._fire("onPause", [_t.curve.getValue(_t._getStep())]);
10880                        return _t; // dojo.Animation
10881                },
10882
10883                gotoPercent: function(/*Decimal*/ percent, /*Boolean?*/ andPlay){
10884                        //      summary:
10885                        //              Sets the progress of the animation.
10886                        //      percent:
10887                        //              A percentage in decimal notation (between and including 0.0 and 1.0).
10888                        //      andPlay:
10889                        //              If true, play the animation after setting the progress.
10890                        var _t = this;
10891                        _t._stopTimer();
10892                        _t._active = _t._paused = true;
10893                        _t._percent = percent;
10894                        if(andPlay){ _t.play(); }
10895                        return _t; // dojo.Animation
10896                },
10897
10898                stop: function(/*boolean?*/ gotoEnd){
10899                        // summary: Stops a running animation.
10900                        // gotoEnd: If true, the animation will end.
10901                        var _t = this;
10902                        if(_t._delayTimer){ _t._clearTimer(); }
10903                        if(!_t._timer){ return _t; /* dojo.Animation */ }
10904                        _t._stopTimer();
10905                        if(gotoEnd){
10906                                _t._percent = 1;
10907                        }
10908                        _t._fire("onStop", [_t.curve.getValue(_t._getStep())]);
10909                        _t._active = _t._paused = false;
10910                        return _t; // dojo.Animation
10911                },
10912
10913                status: function(){
10914                        // summary:
10915                        //              Returns a string token representation of the status of
10916                        //              the animation, one of: "paused", "playing", "stopped"
10917                        if(this._active){
10918                                return this._paused ? "paused" : "playing"; // String
10919                        }
10920                        return "stopped"; // String
10921                },
10922
10923                _cycle: function(){
10924                        var _t = this;
10925                        if(_t._active){
10926                                var curr = new Date().valueOf();
10927                                var step = (curr - _t._startTime) / (_t.duration);
10928
10929                                if(step >= 1){
10930                                        step = 1;
10931                                }
10932                                _t._percent = step;
10933
10934                                // Perform easing
10935                                if(_t.easing){
10936                                        step = _t.easing(step);
10937                                }
10938
10939                                _t._fire("onAnimate", [_t.curve.getValue(step)]);
10940
10941                                if(_t._percent < 1){
10942                                        _t._startTimer();
10943                                }else{
10944                                        _t._active = false;
10945
10946                                        if(_t.repeat > 0){
10947                                                _t.repeat--;
10948                                                _t.play(null, true);
10949                                        }else if(_t.repeat == -1){
10950                                                _t.play(null, true);
10951                                        }else{
10952                                                if(_t._startRepeatCount){
10953                                                        _t.repeat = _t._startRepeatCount;
10954                                                        _t._startRepeatCount = 0;
10955                                                }
10956                                        }
10957                                        _t._percent = 0;
10958                                        _t._fire("onEnd", [_t.node]);
10959                                        !_t.repeat && _t._stopTimer();
10960                                }
10961                        }
10962                        return _t; // dojo.Animation
10963                },
10964
10965                _clearTimer: function(){
10966                        // summary: Clear the play delay timer
10967                        clearTimeout(this._delayTimer);
10968                        delete this._delayTimer;
10969                }
10970
10971        });
10972
10973        // the local timer, stubbed into all Animation instances
10974        var ctr = 0,
10975                timer = null,
10976                runner = {
10977                        run: function(){}
10978                };
10979
10980        d.extend(d.Animation, {
10981
10982                _startTimer: function(){
10983                        if(!this._timer){
10984                                this._timer = d.connect(runner, "run", this, "_cycle");
10985                                ctr++;
10986                        }
10987                        if(!timer){
10988                                timer = setInterval(d.hitch(runner, "run"), this.rate);
10989                        }
10990                },
10991
10992                _stopTimer: function(){
10993                        if(this._timer){
10994                                d.disconnect(this._timer);
10995                                this._timer = null;
10996                                ctr--;
10997                        }
10998                        if(ctr <= 0){
10999                                clearInterval(timer);
11000                                timer = null;
11001                                ctr = 0;
11002                        }
11003                }
11004
11005        });
11006
11007        var _makeFadeable =
11008                                d.isIE ? function(node){
11009                        // only set the zoom if the "tickle" value would be the same as the
11010                        // default
11011                        var ns = node.style;
11012                        // don't set the width to auto if it didn't already cascade that way.
11013                        // We don't want to f anyones designs
11014                        if(!ns.width.length && d.style(node, "width") == "auto"){
11015                                ns.width = "auto";
11016                        }
11017                } :
11018                                function(){};
11019
11020        dojo._fade = function(/*Object*/ args){
11021                //      summary:
11022                //              Returns an animation that will fade the node defined by
11023                //              args.node from the start to end values passed (args.start
11024                //              args.end) (end is mandatory, start is optional)
11025
11026                args.node = d.byId(args.node);
11027                var fArgs = _mixin({ properties: {} }, args),
11028                        props = (fArgs.properties.opacity = {});
11029
11030                props.start = !("start" in fArgs) ?
11031                        function(){
11032                                return +d.style(fArgs.node, "opacity")||0;
11033                        } : fArgs.start;
11034                props.end = fArgs.end;
11035
11036                var anim = d.animateProperty(fArgs);
11037                d.connect(anim, "beforeBegin", d.partial(_makeFadeable, fArgs.node));
11038
11039                return anim; // dojo.Animation
11040        };
11041
11042        /*=====
11043        dojo.__FadeArgs = function(node, duration, easing){
11044                //      node: DOMNode|String
11045                //              The node referenced in the animation
11046                //      duration: Integer?
11047                //              Duration of the animation in milliseconds.
11048                //      easing: Function?
11049                //              An easing function.
11050                this.node = node;
11051                this.duration = duration;
11052                this.easing = easing;
11053        }
11054        =====*/
11055
11056        dojo.fadeIn = function(/*dojo.__FadeArgs*/ args){
11057                // summary:
11058                //              Returns an animation that will fade node defined in 'args' from
11059                //              its current opacity to fully opaque.
11060                return d._fade(_mixin({ end: 1 }, args)); // dojo.Animation
11061        };
11062
11063        dojo.fadeOut = function(/*dojo.__FadeArgs*/  args){
11064                // summary:
11065                //              Returns an animation that will fade node defined in 'args'
11066                //              from its current opacity to fully transparent.
11067                return d._fade(_mixin({ end: 0 }, args)); // dojo.Animation
11068        };
11069
11070        dojo._defaultEasing = function(/*Decimal?*/ n){
11071                // summary: The default easing function for dojo.Animation(s)
11072                return 0.5 + ((Math.sin((n + 1.5) * Math.PI)) / 2);
11073        };
11074
11075        var PropLine = function(properties){
11076                // PropLine is an internal class which is used to model the values of
11077                // an a group of CSS properties across an animation lifecycle. In
11078                // particular, the "getValue" function handles getting interpolated
11079                // values between start and end for a particular CSS value.
11080                this._properties = properties;
11081                for(var p in properties){
11082                        var prop = properties[p];
11083                        if(prop.start instanceof d.Color){
11084                                // create a reusable temp color object to keep intermediate results
11085                                prop.tempColor = new d.Color();
11086                        }
11087                }
11088        };
11089
11090        PropLine.prototype.getValue = function(r){
11091                var ret = {};
11092                for(var p in this._properties){
11093                        var prop = this._properties[p],
11094                                start = prop.start;
11095                        if(start instanceof d.Color){
11096                                ret[p] = d.blendColors(start, prop.end, r, prop.tempColor).toCss();
11097                        }else if(!d.isArray(start)){
11098                                ret[p] = ((prop.end - start) * r) + start + (p != "opacity" ? prop.units || "px" : 0);
11099                        }
11100                }
11101                return ret;
11102        };
11103
11104        /*=====
11105        dojo.declare("dojo.__AnimArgs", [dojo.__FadeArgs], {
11106                // Properties: Object?
11107                //      A hash map of style properties to Objects describing the transition,
11108                //      such as the properties of dojo._Line with an additional 'units' property
11109                properties: {}
11110
11111                //TODOC: add event callbacks
11112        });
11113        =====*/
11114
11115        dojo.animateProperty = function(/*dojo.__AnimArgs*/ args){
11116                // summary:
11117                //              Returns an animation that will transition the properties of
11118                //              node defined in `args` depending how they are defined in
11119                //              `args.properties`
11120                //
11121                // description:
11122                //              `dojo.animateProperty` is the foundation of most `dojo.fx`
11123                //              animations. It takes an object of "properties" corresponding to
11124                //              style properties, and animates them in parallel over a set
11125                //              duration.
11126                //
11127                // example:
11128                //              A simple animation that changes the width of the specified node.
11129                //      |       dojo.animateProperty({
11130                //      |               node: "nodeId",
11131                //      |               properties: { width: 400 },
11132                //      |       }).play();
11133                //              Dojo figures out the start value for the width and converts the
11134                //              integer specified for the width to the more expressive but
11135                //              verbose form `{ width: { end: '400', units: 'px' } }` which you
11136                //              can also specify directly. Defaults to 'px' if ommitted.
11137                //
11138                // example:
11139                //              Animate width, height, and padding over 2 seconds... the
11140                //              pedantic way:
11141                //      |       dojo.animateProperty({ node: node, duration:2000,
11142                //      |               properties: {
11143                //      |                       width: { start: '200', end: '400', units:"px" },
11144                //      |                       height: { start:'200', end: '400', units:"px" },
11145                //      |                       paddingTop: { start:'5', end:'50', units:"px" }
11146                //      |               }
11147                //      |       }).play();
11148                //              Note 'paddingTop' is used over 'padding-top'. Multi-name CSS properties
11149                //              are written using "mixed case", as the hyphen is illegal as an object key.
11150                //
11151                // example:
11152                //              Plug in a different easing function and register a callback for
11153                //              when the animation ends. Easing functions accept values between
11154                //              zero and one and return a value on that basis. In this case, an
11155                //              exponential-in curve.
11156                //      |       dojo.animateProperty({
11157                //      |               node: "nodeId",
11158                //      |               // dojo figures out the start value
11159                //      |               properties: { width: { end: 400 } },
11160                //      |               easing: function(n){
11161                //      |                       return (n==0) ? 0 : Math.pow(2, 10 * (n - 1));
11162                //      |               },
11163                //      |               onEnd: function(node){
11164                //      |                       // called when the animation finishes. The animation
11165                //      |                       // target is passed to this function
11166                //      |               }
11167                //      |       }).play(500); // delay playing half a second
11168                //
11169                // example:
11170                //              Like all `dojo.Animation`s, animateProperty returns a handle to the
11171                //              Animation instance, which fires the events common to Dojo FX. Use `dojo.connect`
11172                //              to access these events outside of the Animation definiton:
11173                //      |       var anim = dojo.animateProperty({
11174                //      |               node:"someId",
11175                //      |               properties:{
11176                //      |                       width:400, height:500
11177                //      |               }
11178                //      |       });
11179                //      |       dojo.connect(anim,"onEnd", function(){
11180                //      |               console.log("animation ended");
11181                //      |       });
11182                //      |       // play the animation now:
11183                //      |       anim.play();
11184                //
11185                // example:
11186                //              Each property can be a function whose return value is substituted along.
11187                //              Additionally, each measurement (eg: start, end) can be a function. The node
11188                //              reference is passed direcly to callbacks.
11189                //      |       dojo.animateProperty({
11190                //      |               node:"mine",
11191                //      |               properties:{
11192                //      |                       height:function(node){
11193                //      |                               // shrink this node by 50%
11194                //      |                               return dojo.position(node).h / 2
11195                //      |                       },
11196                //      |                       width:{
11197                //      |                               start:function(node){ return 100; },
11198                //      |                               end:function(node){ return 200; }
11199                //      |                       }
11200                //      |               }
11201                //      |       }).play();
11202                //
11203
11204                var n = args.node = d.byId(args.node);
11205                if(!args.easing){ args.easing = d._defaultEasing; }
11206
11207                var anim = new d.Animation(args);
11208                d.connect(anim, "beforeBegin", anim, function(){
11209                        var pm = {};
11210                        for(var p in this.properties){
11211                                // Make shallow copy of properties into pm because we overwrite
11212                                // some values below. In particular if start/end are functions
11213                                // we don't want to overwrite them or the functions won't be
11214                                // called if the animation is reused.
11215                                if(p == "width" || p == "height"){
11216                                        this.node.display = "block";
11217                                }
11218                                var prop = this.properties[p];
11219                                if(d.isFunction(prop)){
11220                                        prop = prop(n);
11221                                }
11222                                prop = pm[p] = _mixin({}, (d.isObject(prop) ? prop: { end: prop }));
11223
11224                                if(d.isFunction(prop.start)){
11225                                        prop.start = prop.start(n);
11226                                }
11227                                if(d.isFunction(prop.end)){
11228                                        prop.end = prop.end(n);
11229                                }
11230                                var isColor = (p.toLowerCase().indexOf("color") >= 0);
11231                                function getStyle(node, p){
11232                                        // dojo.style(node, "height") can return "auto" or "" on IE; this is more reliable:
11233                                        var v = { height: node.offsetHeight, width: node.offsetWidth }[p];
11234                                        if(v !== undefined){ return v; }
11235                                        v = d.style(node, p);
11236                                        return (p == "opacity") ? +v : (isColor ? v : parseFloat(v));
11237                                }
11238                                if(!("end" in prop)){
11239                                        prop.end = getStyle(n, p);
11240                                }else if(!("start" in prop)){
11241                                        prop.start = getStyle(n, p);
11242                                }
11243
11244                                if(isColor){
11245                                        prop.start = new d.Color(prop.start);
11246                                        prop.end = new d.Color(prop.end);
11247                                }else{
11248                                        prop.start = (p == "opacity") ? +prop.start : parseFloat(prop.start);
11249                                }
11250                        }
11251                        this.curve = new PropLine(pm);
11252                });
11253                d.connect(anim, "onAnimate", d.hitch(d, "style", anim.node));
11254                return anim; // dojo.Animation
11255        };
11256
11257        dojo.anim = function(   /*DOMNode|String*/      node,
11258                                                        /*Object*/                      properties,
11259                                                        /*Integer?*/            duration,
11260                                                        /*Function?*/           easing,
11261                                                        /*Function?*/           onEnd,
11262                                                        /*Integer?*/            delay){
11263                //      summary:
11264                //              A simpler interface to `dojo.animateProperty()`, also returns
11265                //              an instance of `dojo.Animation` but begins the animation
11266                //              immediately, unlike nearly every other Dojo animation API.
11267                //      description:
11268                //              `dojo.anim` is a simpler (but somewhat less powerful) version
11269                //              of `dojo.animateProperty`.  It uses defaults for many basic properties
11270                //              and allows for positional parameters to be used in place of the
11271                //              packed "property bag" which is used for other Dojo animation
11272                //              methods.
11273                //
11274                //              The `dojo.Animation` object returned from `dojo.anim` will be
11275                //              already playing when it is returned from this function, so
11276                //              calling play() on it again is (usually) a no-op.
11277                //      node:
11278                //              a DOM node or the id of a node to animate CSS properties on
11279                //      duration:
11280                //              The number of milliseconds over which the animation
11281                //              should run. Defaults to the global animation default duration
11282                //              (350ms).
11283                //      easing:
11284                //              An easing function over which to calculate acceleration
11285                //              and deceleration of the animation through its duration.
11286                //              A default easing algorithm is provided, but you may
11287                //              plug in any you wish. A large selection of easing algorithms
11288                //              are available in `dojo.fx.easing`.
11289                //      onEnd:
11290                //              A function to be called when the animation finishes
11291                //              running.
11292                //      delay:
11293                //              The number of milliseconds to delay beginning the
11294                //              animation by. The default is 0.
11295                //      example:
11296                //              Fade out a node
11297                //      |       dojo.anim("id", { opacity: 0 });
11298                //      example:
11299                //              Fade out a node over a full second
11300                //      |       dojo.anim("id", { opacity: 0 }, 1000);
11301                return d.animateProperty({ // dojo.Animation
11302                        node: node,
11303                        duration: duration || d.Animation.prototype.duration,
11304                        properties: properties,
11305                        easing: easing,
11306                        onEnd: onEnd
11307                }).play(delay || 0);
11308        };
11309})();
11310
11311}
11312
11313if(!dojo._hasResource["dojo._base.browser"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
11314dojo._hasResource["dojo._base.browser"] = true;
11315dojo.provide("dojo._base.browser");
11316
11317
11318
11319
11320
11321
11322
11323
11324
11325        //Need this to be the last code segment in base, so do not place any
11326        //dojo/requireIf calls in this file/ Otherwise, due to how the build system
11327        //puts all requireIf dependencies after the current file, the require calls
11328        //could be called before all of base is defined/
11329        dojo.forEach(dojo.config.require, function(i){
11330                dojo["require"](i);
11331        });
11332
11333}
11334
11335if(!dojo._hasResource["dojo._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
11336dojo._hasResource["dojo._base"] = true;
11337dojo.provide("dojo._base");
11338
11339
11340
11341
11342
11343
11344
11345
11346
11347
11348
11349}
11350
11351        //INSERT dojo.i18n._preloadLocalizations HERE
11352
11353        //Check if document already complete, and if so, just trigger page load
11354        //listeners. NOTE: does not work with Firefox before 3.6. To support
11355        //those browsers, set djConfig.afterOnLoad = true when you know Dojo is added
11356        //after page load. Using a timeout so the rest of this
11357        //script gets evaluated properly. This work needs to happen after the
11358        //dojo.config.require work done in dojo._base.
11359        if(dojo.isBrowser && (document.readyState === "complete" || dojo.config.afterOnLoad)){
11360                window.setTimeout(dojo._loadInit, 100);
11361        }
11362})();
11363
11364