Home | History | Annotate | Download | only in lib
      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 
     62 djConfig = {
     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 /*=====
    242 dojo.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 /*=====
   1360 dojo.isBrowser = {
   1361         //      example:
   1362         //      |       if(dojo.isBrowser){ ... }
   1363 };
   1364 
   1365 dojo.isFF = {
   1366         //      example:
   1367         //      |       if(dojo.isFF > 1){ ... }
   1368 };
   1369 
   1370 dojo.isIE = {
   1371         // example:
   1372         //      |       if(dojo.isIE > 6){
   1373         //      |               // we are IE7
   1374         //      |       }
   1375 };
   1376 
   1377 dojo.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 
   1387 dojo = {
   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 =====*/
   1425 if(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.
   1816 if(dojo.config.isDebug){
   1817         dojo.require("dojo._firebug.firebug");
   1818 }
   1819 
   1820 if(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 
   1830 if(!dojo._hasResource["dojo._base.lang"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
   1831 dojo._hasResource["dojo._base.lang"] = true;
   1832 dojo.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 
   2221 if(!dojo._hasResource["dojo._base.array"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
   2222 dojo._hasResource["dojo._base.array"] = true;
   2223 dojo.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 
   2478 if(!dojo._hasResource["dojo._base.declare"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
   2479 dojo._hasResource["dojo._base.declare"] = true;
   2480 dojo.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 
   3520 if(!dojo._hasResource["dojo._base.connect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
   3521 dojo._hasResource["dojo._base.connect"] = true;
   3522 dojo.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
   3529 dojo._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 
   3605 dojo.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
   3721 dojo._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 
   3726 dojo.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 
   3740 dojo._disconnect = function(obj, event, handle, listener){
   3741         listener.remove(obj, event, handle);
   3742 };
   3743 
   3744 // topic publish/subscribe
   3745 
   3746 dojo._topics = {};
   3747 
   3748 dojo.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 
   3766 dojo.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 
   3780 dojo.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 
   3801 dojo.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 
   3825 if(!dojo._hasResource["dojo._base.Deferred"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
   3826 dojo._hasResource["dojo._base.Deferred"] = true;
   3827 dojo.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 })();
   4134 dojo.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 
   4165 if(!dojo._hasResource["dojo._base.json"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
   4166 dojo._hasResource["dojo._base.json"] = true;
   4167 dojo.provide("dojo._base.json");
   4168 
   4169 
   4170 dojo.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 
   4184 dojo._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 
   4194 dojo.toJsonIndentStr = "\t";
   4195 dojo.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 
   4314 if(!dojo._hasResource["dojo._base.Color"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
   4315 dojo._hasResource["dojo._base.Color"] = true;
   4316 dojo.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 
   4536 if(!dojo._hasResource["dojo._base.window"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
   4537 dojo._hasResource["dojo._base.window"] = true;
   4538 dojo.provide("dojo._base.window");
   4539 
   4540 
   4541 /*=====
   4542 dojo.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 =====*/
   4554 dojo.doc = window["document"] || null;
   4555 
   4556 dojo.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 
   4568 dojo.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 
   4579 dojo.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 
   4602 dojo.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 
   4638 if(!dojo._hasResource["dojo._base.event"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
   4639 dojo._hasResource["dojo._base.event"] = true;
   4640 dojo.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 
   5245 if(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 
   5281 if(!dojo._hasResource["dojo._base.html"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
   5282 dojo._hasResource["dojo._base.html"] = true;
   5283 dojo.provide("dojo._base.html");
   5284 
   5285 
   5286 
   5287 // FIXME: need to add unit tests for all the semi-public methods
   5288 
   5289 try{
   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 /*=====
   5300 dojo.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 
   5330 if(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 
   7111 if(!dojo._hasResource["dojo._base.NodeList"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
   7112 dojo._hasResource["dojo._base.NodeList"] = true;
   7113 dojo.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 
   8118 if(!dojo._hasResource["dojo._base.query"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
   8119 dojo._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 
   8154 var 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 
   9632 var 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 
   9713 if(!dojo._hasResource["dojo._base.xhr"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
   9714 dojo._hasResource["dojo._base.xhr"] = true;
   9715 dojo.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 
   10649 if(!dojo._hasResource["dojo._base.fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
   10650 dojo._hasResource["dojo._base.fx"] = true;
   10651 dojo.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 
   11313 if(!dojo._hasResource["dojo._base.browser"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
   11314 dojo._hasResource["dojo._base.browser"] = true;
   11315 dojo.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 
   11335 if(!dojo._hasResource["dojo._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
   11336 dojo._hasResource["dojo._base"] = true;
   11337 dojo.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