diff --git a/docz/docs/02-getting-started/01-installation/04-amd.md b/docz/docs/02-getting-started/01-installation/04-amd.md
index dc83a4d6..2400deee 100644
--- a/docz/docs/02-getting-started/01-installation/04-amd.md
+++ b/docz/docs/02-getting-started/01-installation/04-amd.md
@@ -17,7 +17,7 @@ Each standalone release script is available at .
-:::note
+:::note pass
When referencing by file name, AMD loaders typically omit the file extension.
@@ -63,7 +63,7 @@ sap.ui.define([
})
```
-:::warning
+:::warning pass
**Copy and pasting code does not work** for SheetJS scripts as they contain
Unicode characters that may be mangled. The standalone script should be
@@ -73,7 +73,7 @@ downloaded and manually uploaded to the project.
## RequireJS
-:::caution
+:::caution pass
The standalone script must be aliased to the path `xlsx`.
@@ -100,11 +100,11 @@ require(['xlsx'], function(XLSX) {
## Dojo Toolkit
Dojo has changed module loading strategies over the years. These examples were
-tested with Dojo `1.10.4` and are not guaranteed to work with other versions.
+tested with Dojo `1.17.3`. They are not guaranteed to work with other versions.
Live demos are included in ["Dojo Toolkit"](/docs/demos/frontend/legacy#dojo-toolkit)
-:::caution
+:::caution pass
The standalone scripts add `window.XLSX`, so it is recommended to use `_XLSX`
in the function arguments and access the library with `XLSX` in the callback:
@@ -127,7 +127,7 @@ When `async` is set to `false` or `0`, the scripts can be directly referenced in
`require` calls.
{`\
-
+
-
+
-
+
```
-Pages should use `ContentRenderer` to reference the data:
+Pages should use `ContentRenderer` to reference the data. The `data` variable
+from the script setup will be shaped like the return value from the transformer.
+`data.body` is an array of objects that holds the worksheet name and data.
-```html title="Page"
-
-
-
+
+
```
### Nuxt Content 2 Demo
-:::caution
+:::caution pass
-When the demo was last tested, parts of the Nuxt dependency tree did not support
+For some older versions, parts of the Nuxt dependency tree did not support
NodeJS version 20. If the `yarn install` step fails with a message like
```
@@ -434,47 +579,14 @@ The server is listening on that URL. Open the link in a web browser.
curl -L -o content/pres.xlsx https://sheetjs.com/pres.xlsx
```
-4) Create the transformer.
+4) Create the transformer. Two files must be saved at the root of the project:
-Two files must be written at the root of the project:
+- [`sheetformer.ts`](https://docs.sheetjs.com/nuxt/3/sheetformer.ts) (raw transformer module)
+- [`sheetmodule.ts`](https://docs.sheetjs.com/nuxt/3/sheetmodule.ts) (Nuxt configuration module)
-- `sheetformer.ts` (the raw transformer module):
-
-```ts title="sheetformer.ts"
-// @ts-ignore
-import { defineTransformer } from "@nuxt/content/transformers/utils";
-import { read, utils } from "xlsx";
-import { readFileSync } from "node:fs";
-import { resolve } from 'node:path';
-
-export default defineTransformer({
- name: 'sheetformer',
- extensions: ['.xlsx'],
- parse (_id: string, rawContent: string) {
- const wb = read(readFileSync(resolve("./content/" + _id.slice(8))));
- const body = wb.SheetNames.map(name => ({ name, data: utils.sheet_to_json(wb.Sheets[name])}));
- return { _id, body };
- }
-});
-```
-
-- `sheetmodule.ts` (the Nuxt configuration module):
-
-```ts title="sheetmodule.ts"
-import { resolve } from 'path'
-import { defineNuxtModule } from '@nuxt/kit'
-
-export default defineNuxtModule({
- setup (_options, nuxt) {
- nuxt.options.nitro.externals = nuxt.options.nitro.externals || {}
- nuxt.options.nitro.externals.inline = nuxt.options.nitro.externals.inline || []
- nuxt.options.nitro.externals.inline.push(resolve('./sheetmodule'))
- // @ts-ignore
- nuxt.hook('content:context', (contentContext) => {
- contentContext.transformers.push(resolve('./sheetformer.ts'))
- })
- }
-})
+```bash
+curl -O https://docs.sheetjs.com/nuxt/3/sheetformer.ts
+curl -O https://docs.sheetjs.com/nuxt/3/sheetmodule.ts
```
After creating the source files, the module must be added to `nuxt.config.ts`:
@@ -490,7 +602,7 @@ export default defineNuxtConfig({
'@nuxt/content'
],
content: {}
-})
+});
```
Restart the dev server by exiting the process (Control+C) and running:
@@ -520,25 +632,11 @@ Loading `http://localhost:3000/pres` should show some JSON data:
},
```
-5) Create a page. Save the following content to `pages/pres.vue`:
+5) Download [`pres.vue`](pathname:///nuxt/3/pres.vue) and save to `pages`:
-```html title="pages/pres.vue"
-
-
-
-
{{ item.name }}
-
Name
Index
-
-
{{ row.Name }}
-
{{ row.Index }}
-
-
-
-
+```bash
+curl -o pages/pres.vue https://docs.sheetjs.com/nuxt/3/pres.vue
```
-
Restart the dev server by exiting the process (Control+C) and running:
```bash
@@ -568,3 +666,12 @@ npx -y http-server .output/public
Accessing `http://localhost:8080/pres` will show the page contents. Verifying
the static nature is trivial: make another change in Excel and save. The page
will not change.
+
+[^1]: See [`readFile` in "Reading Files"](/docs/api/parse-options)
+[^2]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
+[^3]: See [`extendParser`](https://content.nuxtjs.org/v1/getting-started/configuration#extendparser) in the NuxtJS documentation.
+[^4]: See ["Array of Objects" in the VueJS demo](/docs/demos/frontend/vue#array-of-objects)
+[^5]: See [`resolve`](https://nodejs.org/api/path.html#pathresolvepaths) in the NodeJS `node:path` documentation
+[^6]: See [`readFileSync`](https://nodejs.org/api/fs.html#fsreadfilesyncpath-options) in the NodeJS `node:fs` documentation
+[^7]: See [`read` in "Reading Files"](/docs/api/parse-options)
+[^8]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
diff --git a/docz/docs/08-api/05-write-options.md b/docz/docs/08-api/05-write-options.md
index 2305567c..e2205b37 100644
--- a/docz/docs/08-api/05-write-options.md
+++ b/docz/docs/08-api/05-write-options.md
@@ -177,7 +177,7 @@ XLSX.writeFile(wb, "textport.numbers", {numbers: XLSX_ZAHL_PAYLOAD, compression:
After installing the package:
{`\
-npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
+bun i https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
The scripts will be available at `xlsx/dist/xlsx.zahl` (CommonJS) and
@@ -226,33 +226,33 @@ XLSX.writeFile(wb, "textport.numbers", {numbers: XLSX_ZAHL_PAYLOAD, compression:
For broad compatibility with third-party tools, this library supports many
output formats. The specific file type is controlled with `bookType` option:
-| `bookType` | file ext | container | sheets | Description |
-| :--------- | -------: | :-------: | :----- |:------------------------------- |
-| `xlsx` | `.xlsx` | ZIP | multi | Excel 2007+ XML Format |
-| `xlsm` | `.xlsm` | ZIP | multi | Excel 2007+ Macro XML Format |
-| `xlsb` | `.xlsb` | ZIP | multi | Excel 2007+ Binary Format |
-| `biff8` | `.xls` | CFB | multi | Excel 97-2004 Workbook Format |
-| `biff5` | `.xls` | CFB | multi | Excel 5.0/95 Workbook Format |
-| `biff4` | `.xls` | none | single | Excel 4.0 Worksheet Format |
-| `biff3` | `.xls` | none | single | Excel 3.0 Worksheet Format |
-| `biff2` | `.xls` | none | single | Excel 2.0 Worksheet Format |
-| `xlml` | `.xls` | none | multi | Excel 2003-2004 (SpreadsheetML) |
-| `numbers` |`.numbers`| ZIP | single | Numbers 3.0+ Spreadsheet |
-| `ods` | `.ods` | ZIP | multi | OpenDocument Spreadsheet |
-| `fods` | `.fods` | none | multi | Flat OpenDocument Spreadsheet |
-| `wk3` | `.wk3` | none | multi | Lotus Workbook (WK3) |
-| `csv` | `.csv` | none | single | Comma Separated Values |
-| `txt` | `.txt` | none | single | UTF-16 Unicode Text (TXT) |
-| `sylk` | `.sylk` | none | single | Symbolic Link (SYLK) |
-| `html` | `.html` | none | single | HTML Document |
-| `dif` | `.dif` | none | single | Data Interchange Format (DIF) |
-| `dbf` | `.dbf` | none | single | dBASE II + VFP Extensions (DBF) |
-| `wk1` | `.wk1` | none | single | Lotus Worksheet (WK1) |
-| `rtf` | `.rtf` | none | single | Rich Text Format (RTF) |
-| `prn` | `.prn` | none | single | Lotus Formatted Text |
-| `eth` | `.eth` | none | single | Ethercalc Record Format (ETH) |
+| `bookType` | extension | sheets | Description |
+|:-----------|:-----------|:-------|:--------------------------------|
+| `xlsx` | `.xlsx` | multi | Excel 2007+ XML Format |
+| `xlsm` | `.xlsm` | multi | Excel 2007+ Macro XML Format |
+| `xlsb` | `.xlsb` | multi | Excel 2007+ Binary Format |
+| `biff8` | `.xls` | multi | Excel 97-2004 Workbook Format |
+| `biff5` | `.xls` | multi | Excel 5.0/95 Workbook Format |
+| `biff4` | `.xls` | single | Excel 4.0 Worksheet Format |
+| `biff3` | `.xls` | single | Excel 3.0 Worksheet Format |
+| `biff2` | `.xls` | single | Excel 2.0 Worksheet Format |
+| `xlml` | `.xls` | multi | Excel 2003-2004 (SpreadsheetML) |
+| `numbers` | `.numbers` | multi | Numbers 3.0+ Spreadsheet |
+| `ods` | `.ods` | multi | OpenDocument Spreadsheet |
+| `fods` | `.fods` | multi | Flat OpenDocument Spreadsheet |
+| `wk3` | `.wk3` | multi | Lotus Workbook (WK3) |
+| `csv` | `.csv` | single | Comma Separated Values |
+| `txt` | `.txt` | single | UTF-16 Unicode Text (TXT) |
+| `sylk` | `.sylk` | single | Symbolic Link (SYLK) |
+| `html` | `.html` | single | HTML Document |
+| `dif` | `.dif` | single | Data Interchange Format (DIF) |
+| `dbf` | `.dbf` | single | dBASE II + VFP Extensions (DBF) |
+| `wk1` | `.wk1` | single | Lotus Worksheet (WK1) |
+| `rtf` | `.rtf` | single | Rich Text Format (RTF) |
+| `prn` | `.prn` | single | Lotus Formatted Text |
+| `eth` | `.eth` | single | Ethercalc Record Format (ETH) |
-- `compression` only applies to formats with ZIP containers.
+- `compression` applies to ZIP-based formats (XLSX, XLSM, XLSB, NUMBERS, ODS)
- Formats that only support a single sheet require a `sheet` option specifying
the worksheet. If the string is empty, the first worksheet is used.
- `writeFile` will automatically guess the output file format based on the file
diff --git a/docz/static/dojo/dojo.js b/docz/static/dojo/dojo.js
new file mode 100644
index 00000000..9ea3d48e
--- /dev/null
+++ b/docz/static/dojo/dojo.js
@@ -0,0 +1,18979 @@
+/*
+ Copyright (c) 2004-2016, The JS Foundation All Rights Reserved.
+ Available via Academic Free License >= 2.1 OR the modified BSD license.
+ see: http://dojotoolkit.org/license for details
+*/
+
+/*
+ This is an optimized version of Dojo, built for deployment and not for
+ development. To get sources and documentation, please visit:
+
+ http://dojotoolkit.org
+*/
+
+(function(
+ userConfig,
+ defaultConfig
+){
+ // summary:
+ // This is the "source loader" and is the entry point for Dojo during development. You may also load Dojo with
+ // any AMD-compliant loader via the package main module dojo/main.
+ // description:
+ // This is the "source loader" for Dojo. It provides an AMD-compliant loader that can be configured
+ // to operate in either synchronous or asynchronous modes. After the loader is defined, dojo is loaded
+ // IAW the package main module dojo/main. In the event you wish to use a foreign loader, you may load dojo as a package
+ // via the package main module dojo/main and this loader is not required; see dojo/package.json for details.
+ //
+ // In order to keep compatibility with the v1.x line, this loader includes additional machinery that enables
+ // the dojo.provide, dojo.require et al API. This machinery is loaded by default, but may be dynamically removed
+ // via the has.js API and statically removed via the build system.
+ //
+ // This loader includes sniffing machinery to determine the environment; the following environments are supported:
+ //
+ // - browser
+ // - node.js
+ // - rhino
+ //
+ // This is the so-called "source loader". As such, it includes many optional features that may be discarded by
+ // building a customized version with the build system.
+
+ // Design and Implementation Notes
+ //
+ // This is a dojo-specific adaption of bdLoad, donated to the dojo foundation by Altoviso LLC.
+ //
+ // This function defines an AMD-compliant (http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition)
+ // loader that can be configured to operate in either synchronous or asynchronous modes.
+ //
+ // Since this machinery implements a loader, it does not have the luxury of using a load system and/or
+ // leveraging a utility library. This results in an unpleasantly long file; here is a road map of the contents:
+ //
+ // 1. Small library for use implementing the loader.
+ // 2. Define the has.js API; this is used throughout the loader to bracket features.
+ // 3. Define the node.js and rhino sniffs and sniff.
+ // 4. Define the loader's data.
+ // 5. Define the configuration machinery.
+ // 6. Define the script element sniffing machinery and sniff for configuration data.
+ // 7. Configure the loader IAW the provided user, default, and sniffing data.
+ // 8. Define the global require function.
+ // 9. Define the module resolution machinery.
+ // 10. Define the module and plugin module definition machinery
+ // 11. Define the script injection machinery.
+ // 12. Define the window load detection.
+ // 13. Define the logging API.
+ // 14. Define the tracing API.
+ // 16. Define the AMD define function.
+ // 17. Define the dojo v1.x provide/require machinery--so called "legacy" modes.
+ // 18. Publish global variables.
+ //
+ // Language and Acronyms and Idioms
+ //
+ // moduleId: a CJS module identifier, (used for public APIs)
+ // mid: moduleId (used internally)
+ // packageId: a package identifier (used for public APIs)
+ // pid: packageId (used internally); the implied system or default package has pid===""
+ // pack: package is used internally to reference a package object (since javascript has reserved words including "package")
+ // prid: plugin resource identifier
+ // The integer constant 1 is used in place of true and 0 in place of false.
+ //
+ // The "foreign-loader" has condition is defined if another loader is being used (e.g. webpack) and this code is only
+ // needed for resolving module identifiers based on the config. In this case, only the functions require.toUrl and
+ // require.toAbsMid are supported. The require and define functions are not supported.
+
+ // define global
+ var globalObject = (function(){
+ if (typeof global !== 'undefined' && typeof global !== 'function') {
+ // global spec defines a reference to the global object called 'global'
+ // https://github.com/tc39/proposal-global
+ // `global` is also defined in NodeJS
+ return global;
+ }
+ else if (typeof window !== 'undefined') {
+ // window is defined in browsers
+ return window;
+ }
+ else if (typeof self !== 'undefined') {
+ // self is defined in WebWorkers
+ return self;
+ }
+ return this;
+ })();
+
+ // define a minimal library to help build the loader
+ var noop = function(){
+ },
+
+ isEmpty = function(it){
+ for(var p in it){
+ return 0;
+ }
+ return 1;
+ },
+
+ toString = {}.toString,
+
+ isFunction = function(it){
+ return toString.call(it) == "[object Function]";
+ },
+
+ isString = function(it){
+ return toString.call(it) == "[object String]";
+ },
+
+ isArray = function(it){
+ return toString.call(it) == "[object Array]";
+ },
+
+ forEach = function(vector, callback){
+ if(vector){
+ for(var i = 0; i < vector.length;){
+ callback(vector[i++]);
+ }
+ }
+ },
+
+ mix = function(dest, src){
+ for(var p in src){
+ dest[p] = src[p];
+ }
+ return dest;
+ },
+
+ makeError = function(error, info){
+ return mix(new Error(error), {src:"dojoLoader", info:info});
+ },
+
+ uidSeed = 1,
+
+ uid = function(){
+ // Returns a unique identifier (within the lifetime of the document) of the form /_d+/.
+ return "_" + uidSeed++;
+ },
+
+ // FIXME: how to doc window.require() api
+
+ // this will be the global require function; define it immediately so we can start hanging things off of it
+ req = function(
+ config, //(object, optional) hash of configuration properties
+ dependencies, //(array of commonjs.moduleId, optional) list of modules to be loaded before applying callback
+ callback //(function, optional) lambda expression to apply to module values implied by dependencies
+ ){
+ return contextRequire(config, dependencies, callback, 0, req);
+ },
+
+ // the loader uses the has.js API to control feature inclusion/exclusion; define then use throughout
+ global = globalObject,
+
+ doc = global.document,
+
+ element = doc && doc.createElement("DiV"),
+
+ has = req.has = function(name){
+ return isFunction(hasCache[name]) ? (hasCache[name] = hasCache[name](global, doc, element)) : hasCache[name];
+ },
+
+ hasCache = has.cache = defaultConfig.hasCache;
+
+ if (isFunction(userConfig)) {
+ userConfig = userConfig(globalObject);
+ }
+
+ has.add = function(name, test, now, force){
+ (hasCache[name]===undefined || force) && (hasCache[name] = test);
+ return now && has(name);
+ };
+
+ 0 && has.add("host-node", userConfig.has && "host-node" in userConfig.has ?
+ userConfig.has["host-node"] :
+ (typeof process == "object" && process.versions && process.versions.node && process.versions.v8));
+ if( 0 ){
+ // fixup the default config for node.js environment
+ require("./_base/configNode.js").config(defaultConfig);
+ // remember node's require (with respect to baseUrl==dojo's root)
+ defaultConfig.loaderPatch.nodeRequire = require;
+ }
+
+ 0 && has.add("host-rhino", userConfig.has && "host-rhino" in userConfig.has ?
+ userConfig.has["host-rhino"] :
+ (typeof load == "function" && (typeof Packages == "function" || typeof Packages == "object")));
+ if( 0 ){
+ // owing to rhino's lame feature that hides the source of the script, give the user a way to specify the baseUrl...
+ for(var baseUrl = userConfig.baseUrl || ".", arg, rhinoArgs = this.arguments, i = 0; i < rhinoArgs.length;){
+ arg = (rhinoArgs[i++] + "").split("=");
+ if(arg[0] == "baseUrl"){
+ baseUrl = arg[1];
+ break;
+ }
+ }
+ load(baseUrl + "/_base/configRhino.js");
+ rhinoDojoConfig(defaultConfig, baseUrl, rhinoArgs);
+ }
+
+ has.add("host-webworker", ((typeof WorkerGlobalScope !== 'undefined') && (self instanceof WorkerGlobalScope)));
+ if(has("host-webworker")){
+ mix(defaultConfig.hasCache, {
+ "host-browser": 0,
+ "dom": 0,
+ "dojo-dom-ready-api": 0,
+ "dojo-sniff": 0,
+ "dojo-inject-api": 1,
+ "host-webworker": 1,
+ "dojo-guarantee-console": 0 // console is immutable in FF30+, see https://bugs.dojotoolkit.org/ticket/18100
+ });
+
+ defaultConfig.loaderPatch = {
+ injectUrl: function(url, callback){
+ // TODO:
+ // This is not async, nor can it be in Webworkers. It could be made better by passing
+ // the entire require array into importScripts at. This way the scripts are loaded in
+ // async mode; even if the callbacks are ran in sync. It is not a major issue as webworkers
+ // tend to be long running where initial startup is not a major factor.
+
+ try{
+ importScripts(url);
+ callback();
+ }catch(e){
+ console.info("failed to load resource (" + url + ")");
+ console.error(e);
+ }
+ }
+ };
+ }
+
+ // userConfig has tests override defaultConfig has tests; do this after the environment detection because
+ // the environment detection usually sets some has feature values in the hasCache.
+ for(var p in userConfig.has){
+ has.add(p, userConfig.has[p], 0, 1);
+ }
+
+ //
+ // define the loader data
+ //
+
+ // the loader will use these like symbols if the loader has the traceApi; otherwise
+ // define magic numbers so that modules can be provided as part of defaultConfig
+ var requested = 1,
+ arrived = 2,
+ nonmodule = 3,
+ executing = 4,
+ executed = 5;
+
+ if( 0 ){
+ // these make debugging nice; but using strings for symbols is a gross rookie error; don't do it for production code
+ requested = "requested";
+ arrived = "arrived";
+ nonmodule = "not-a-module";
+ executing = "executing";
+ executed = "executed";
+ }
+
+ var legacyMode = 0,
+ sync = "sync",
+ xd = "xd",
+ syncExecStack = [],
+ dojoRequirePlugin = 0,
+ checkDojoRequirePlugin = noop,
+ transformToAmd = noop,
+ getXhr;
+ if( 1 ){
+ req.isXdUrl = noop;
+
+ req.initSyncLoader = function(dojoRequirePlugin_, checkDojoRequirePlugin_, transformToAmd_){
+ // the first dojo/_base/loader loaded gets to define these variables; they are designed to work
+ // in the presence of zero to many mapped dojo/_base/loaders
+ if(!dojoRequirePlugin){
+ dojoRequirePlugin = dojoRequirePlugin_;
+ checkDojoRequirePlugin = checkDojoRequirePlugin_;
+ transformToAmd = transformToAmd_;
+ }
+
+ return {
+ sync:sync,
+ requested:requested,
+ arrived:arrived,
+ nonmodule:nonmodule,
+ executing:executing,
+ executed:executed,
+ syncExecStack:syncExecStack,
+ modules:modules,
+ execQ:execQ,
+ getModule:getModule,
+ injectModule:injectModule,
+ setArrived:setArrived,
+ signal:signal,
+ finishExec:finishExec,
+ execModule:execModule,
+ dojoRequirePlugin:dojoRequirePlugin,
+ getLegacyMode:function(){return legacyMode;},
+ guardCheckComplete:guardCheckComplete
+ };
+ };
+
+ if( 1 || has("host-webworker")){
+ // in legacy sync mode, the loader needs a minimal XHR library
+
+ var locationProtocol = location.protocol,
+ locationHost = location.host;
+ req.isXdUrl = function(url){
+ if(/^\./.test(url)){
+ // begins with a dot is always relative to page URL; therefore not xdomain
+ return false;
+ }
+ if(/^\/\//.test(url)){
+ // for v1.6- backcompat, url starting with // indicates xdomain
+ return true;
+ }
+ // get protocol and host
+ // \/+ takes care of the typical file protocol that looks like file:///drive/path/to/file
+ // locationHost is falsy if file protocol => if locationProtocol matches and is "file:", || will return false
+ var match = url.match(/^([^\/\:]+\:)\/+([^\/]+)/);
+ return match && (match[1] != locationProtocol || (locationHost && match[2] != locationHost));
+ };
+
+
+ // note: to get the file:// protocol to work in FF, you must set security.fileuri.strict_origin_policy to false in about:config
+ 1 || has.add("dojo-xhr-factory", 1);
+ has.add("dojo-force-activex-xhr", 1 && !doc.addEventListener && window.location.protocol == "file:");
+ has.add("native-xhr", typeof XMLHttpRequest != "undefined");
+ if(has("native-xhr") && !has("dojo-force-activex-xhr")){
+ getXhr = function(){
+ return new XMLHttpRequest();
+ };
+ }else{
+ // if in the browser an old IE; find an xhr
+ for(var XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'], progid, i = 0; i < 3;){
+ try{
+ progid = XMLHTTP_PROGIDS[i++];
+ if(new ActiveXObject(progid)){
+ // this progid works; therefore, use it from now on
+ break;
+ }
+ }catch(e){
+ // squelch; we're just trying to find a good ActiveX progid
+ // if they all fail, then progid ends up as the last attempt and that will signal the error
+ // the first time the client actually tries to exec an xhr
+ }
+ }
+ getXhr = function(){
+ return new ActiveXObject(progid);
+ };
+ }
+ req.getXhr = getXhr;
+
+ has.add("dojo-gettext-api", 1);
+ req.getText = function(url, async, onLoad){
+ var xhr = getXhr();
+ xhr.open('GET', fixupUrl(url), false);
+ xhr.send(null);
+ if(xhr.status == 200 || (!location.host && !xhr.status)){
+ if(onLoad){
+ onLoad(xhr.responseText, async);
+ }
+ }else{
+ throw makeError("xhrFailed", xhr.status);
+ }
+ return xhr.responseText;
+ };
+ }
+ }else{
+ req.async = 1;
+ }
+
+ //
+ // loader eval
+ //
+ var eval_ = has("csp-restrictions") ?
+ // noop eval if there are csp restrictions
+ function(){} :
+ // use the function constructor so our eval is scoped close to (but not in) in the global space with minimal pollution
+ new Function('return eval(arguments[0]);');
+
+ req.eval =
+ function(text, hint){
+ return eval_(text + "\r\n//# sourceURL=" + hint);
+ };
+
+ //
+ // loader micro events API
+ //
+ var listenerQueues = {},
+ error = "error",
+ signal = req.signal = function(type, args){
+ var queue = listenerQueues[type];
+ // notice we run a copy of the queue; this allows listeners to add/remove
+ // other listeners without affecting this particular signal
+ forEach(queue && queue.slice(0), function(listener){
+ listener.apply(null, isArray(args) ? args : [args]);
+ });
+ },
+ on = req.on = function(type, listener){
+ // notice a queue is not created until a client actually connects
+ var queue = listenerQueues[type] || (listenerQueues[type] = []);
+ queue.push(listener);
+ return {
+ remove:function(){
+ for(var i = 0; i (alias, actual)
+ = [],
+
+ paths
+ // CommonJS paths
+ = {},
+
+ pathsMapProg
+ // list of (from-path, to-path, regex, length) derived from paths;
+ // a "program" to apply paths; see computeMapProg
+ = [],
+
+ packs
+ // a map from packageId to package configuration object; see fixupPackageInfo
+ = {},
+
+ map = req.map
+ // AMD map config variable; dojo/_base/kernel needs req.map to figure out the scope map
+ = {},
+
+ mapProgs
+ // vector of quads as described by computeMapProg; map-key is AMD map key, map-value is AMD map value
+ = [],
+
+ modules
+ // A hash:(mid) --> (module-object) the module namespace
+ //
+ // pid: the package identifier to which the module belongs (e.g., "dojo"); "" indicates the system or default package
+ // mid: the fully-resolved (i.e., mappings have been applied) module identifier without the package identifier (e.g., "dojo/io/script")
+ // url: the URL from which the module was retrieved
+ // pack: the package object of the package to which the module belongs
+ // executed: 0 => not executed; executing => in the process of traversing deps and running factory; executed => factory has been executed
+ // deps: the dependency vector for this module (vector of modules objects)
+ // def: the factory for this module
+ // result: the result of the running the factory for this module
+ // injected: (0 | requested | arrived) the status of the module; nonmodule means the resource did not call define
+ // load: plugin load function; applicable only for plugins
+ //
+ // Modules go through several phases in creation:
+ //
+ // 1. Requested: some other module's definition or a require application contained the requested module in
+ // its dependency vector or executing code explicitly demands a module via req.require.
+ //
+ // 2. Injected: a script element has been appended to the insert-point element demanding the resource implied by the URL
+ //
+ // 3. Loaded: the resource injected in [2] has been evaluated.
+ //
+ // 4. Defined: the resource contained a define statement that advised the loader about the module. Notice that some
+ // resources may just contain a bundle of code and never formally define a module via define
+ //
+ // 5. Evaluated: the module was defined via define and the loader has evaluated the factory and computed a result.
+ = {},
+
+ cacheBust
+ // query string to append to module URLs to bust browser cache
+ = "",
+
+ cache
+ // hash:(mid | url)-->(function | string)
+ //
+ // A cache of resources. The resources arrive via a config.cache object, which is a hash from either mid --> function or
+ // url --> string. The url key is distinguished from the mid key by always containing the prefix "url:". url keys as provided
+ // by config.cache always have a string value that represents the contents of the resource at the given url. mid keys as provided
+ // by configl.cache always have a function value that causes the same code to execute as if the module was script injected.
+ //
+ // Both kinds of key-value pairs are entered into cache via the function consumePendingCache, which may relocate keys as given
+ // by any mappings *iff* the config.cache was received as part of a module resource request.
+ //
+ // Further, for mid keys, the implied url is computed and the value is entered into that key as well. This allows mapped modules
+ // to retrieve cached items that may have arrived consequent to another namespace.
+ //
+ = {},
+
+ urlKeyPrefix
+ // the prefix to prepend to a URL key in the cache.
+ = "url:",
+
+ pendingCacheInsert
+ // hash:(mid)-->(function)
+ //
+ // Gives a set of cache modules pending entry into cache. When cached modules are published to the loader, they are
+ // entered into pendingCacheInsert; modules are then pressed into cache upon (1) AMD define or (2) upon receiving another
+ // independent set of cached modules. (1) is the usual case, and this case allows normalizing mids given in the pending
+ // cache for the local configuration, possibly relocating modules.
+ = {},
+
+ dojoSniffConfig
+ // map of configuration variables
+ // give the data-dojo-config as sniffed from the document (if any)
+ = {},
+
+ insertPointSibling
+ // the nodes used to locate where scripts are injected into the document
+ = 0;
+
+ if( 1 ){
+ if (!has("foreign-loader")) {
+ var consumePendingCacheInsert = function(referenceModule, clear){
+ clear = clear !== false;
+ var p, item, match, now, m;
+ for(p in pendingCacheInsert){
+ item = pendingCacheInsert[p];
+ match = p.match(/^url\:(.+)/);
+ if(match){
+ cache[urlKeyPrefix + toUrl(match[1], referenceModule)] = item;
+ }else if(p=="*now"){
+ now = item;
+ }else if(p!="*noref"){
+ m = getModuleInfo(p, referenceModule, true);
+ cache[m.mid] = cache[urlKeyPrefix + m.url] = item;
+ }
+ }
+ if(now){
+ now(createRequire(referenceModule));
+ }
+ if(clear){
+ pendingCacheInsert = {};
+ }
+ };
+ }
+ var escapeString = function(s){
+ return s.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, function(c){ return "\\" + c; });
+ },
+
+ computeMapProg = function(map, dest){
+ // This routine takes a map as represented by a JavaScript object and initializes dest, a vector of
+ // quads of (map-key, map-value, refex-for-map-key, length-of-map-key), sorted decreasing by length-
+ // of-map-key. The regex looks for the map-key followed by either "/" or end-of-string at the beginning
+ // of a the search source. Notice the map-value is irrelevant to the algorithm
+ dest.splice(0, dest.length);
+ for(var p in map){
+ dest.push([
+ p,
+ map[p],
+ new RegExp("^" + escapeString(p) + "(\/|$)"),
+ p.length]);
+ }
+ dest.sort(function(lhs, rhs){ return rhs[3] - lhs[3]; });
+ return dest;
+ },
+
+ computeAliases = function(config, dest){
+ forEach(config, function(pair){
+ // take a fixed-up copy...
+ dest.push([isString(pair[0]) ? new RegExp("^" + escapeString(pair[0]) + "$") : pair[0], pair[1]]);
+ });
+ },
+
+
+ fixupPackageInfo = function(packageInfo){
+ // calculate the precise (name, location, main, mappings) for a package
+ var name = packageInfo.name;
+ if(!name){
+ // packageInfo must be a string that gives the name
+ name = packageInfo;
+ packageInfo = {name:name};
+ }
+ packageInfo = mix({main:"main"}, packageInfo);
+ packageInfo.location = packageInfo.location ? packageInfo.location : name;
+
+ // packageMap is deprecated in favor of AMD map
+ if(packageInfo.packageMap){
+ map[name] = packageInfo.packageMap;
+ }
+
+ if(!packageInfo.main.indexOf("./")){
+ packageInfo.main = packageInfo.main.substring(2);
+ }
+
+ // now that we've got a fully-resolved package object, push it into the configuration
+ packs[name] = packageInfo;
+ },
+
+ delayedModuleConfig
+ // module config cannot be consumed until the loader is completely initialized; therefore, all
+ // module config detected during booting is memorized and applied at the end of loader initialization
+ // TODO: this is a bit of a kludge; all config should be moved to end of loader initialization, but
+ // we'll delay this chore and do it with a final loader 1.x cleanup after the 2.x loader prototyping is complete
+ = [],
+
+
+ config = function(config, booting, referenceModule){
+ for(var p in config){
+ if(p=="waitSeconds"){
+ req.waitms = (config[p] || 0) * 1000;
+ }
+ if(p=="cacheBust"){
+ cacheBust = config[p] ? (isString(config[p]) ? config[p] : (new Date()).getTime() + "") : "";
+ }
+ if(p=="baseUrl" || p=="combo"){
+ req[p] = config[p];
+ }
+ if( 1 && p=="async"){
+ // falsy or "sync" => legacy sync loader
+ // "xd" => sync but loading xdomain tree and therefore loading asynchronously (not configurable, set automatically by the loader)
+ // "legacyAsync" => permanently in "xd" by choice
+ // "debugAtAllCosts" => trying to load everything via script injection (not implemented)
+ // otherwise, must be truthy => AMD
+ // legacyMode: sync | legacyAsync | xd | false
+ var mode = config[p];
+ req.legacyMode = legacyMode = (isString(mode) && /sync|legacyAsync/.test(mode) ? mode : (!mode ? sync : false));
+ req.async = !legacyMode;
+ }
+ if(config[p]!==hasCache){
+ // accumulate raw config info for client apps which can use this to pass their own config
+ req.rawConfig[p] = config[p];
+ p!="has" && has.add("config-"+p, config[p], 0, booting);
+ }
+ }
+
+ // make sure baseUrl exists
+ if(!req.baseUrl){
+ req.baseUrl = "./";
+ }
+ // make sure baseUrl ends with a slash
+ if(!/\/$/.test(req.baseUrl)){
+ req.baseUrl += "/";
+ }
+
+ // now do the special work for has, packages, packagePaths, paths, aliases, and cache
+
+ for(p in config.has){
+ has.add(p, config.has[p], 0, booting);
+ }
+
+ // for each package found in any packages config item, augment the packs map owned by the loader
+ forEach(config.packages, fixupPackageInfo);
+
+ // for each packagePath found in any packagePaths config item, augment the packageConfig
+ // packagePaths is deprecated; remove in 2.0
+ for(var baseUrl in config.packagePaths){
+ forEach(config.packagePaths[baseUrl], function(packageInfo){
+ var location = baseUrl + "/" + packageInfo;
+ if(isString(packageInfo)){
+ packageInfo = {name:packageInfo};
+ }
+ packageInfo.location = location;
+ fixupPackageInfo(packageInfo);
+ });
+ }
+
+ // notice that computeMapProg treats the dest as a reference; therefore, if/when that variable
+ // is published (see dojo-publish-privates), the published variable will always hold a valid value.
+
+ // this must come after all package processing since package processing may mutate map
+ computeMapProg(mix(map, config.map), mapProgs);
+ forEach(mapProgs, function(item){
+ item[1] = computeMapProg(item[1], []);
+ if(item[0]=="*"){
+ mapProgs.star = item;
+ }
+ });
+
+ // push in any paths and recompute the internal pathmap
+ computeMapProg(mix(paths, config.paths), pathsMapProg);
+
+ // aliases
+ computeAliases(config.aliases, aliases);
+
+ if (!has("foreign-loader")) {
+ if(booting){
+ delayedModuleConfig.push({config:config.config});
+ }else{
+ for(p in config.config){
+ var module = getModule(p, referenceModule);
+ module.config = mix(module.config || {}, config.config[p]);
+ }
+ }
+
+ // push in any new cache values
+ if(config.cache){
+ consumePendingCacheInsert();
+ pendingCacheInsert = config.cache;
+ //inject now all depencies so cache is available for mapped module
+ consumePendingCacheInsert(0, !!config.cache["*noref"]);
+ }
+ }
+ signal("config", [config, req.rawConfig]);
+ };
+
+ //
+ // execute the various sniffs; userConfig can override and value
+ //
+
+ if(has("dojo-cdn") || 1 ){
+ // the sniff regex looks for a src attribute ending in dojo.js, optionally preceded with a path.
+ // match[3] returns the path to dojo.js (if any) without the trailing slash. This is used for the
+ // dojo location on CDN deployments and baseUrl when either/both of these are not provided
+ // explicitly in the config data; this is the 1.6- behavior.
+
+ var scripts = doc.getElementsByTagName("script"),
+ i = 0,
+ script, dojoDir, src, match;
+ while(i < scripts.length){
+ script = scripts[i++];
+ if((src = script.getAttribute("src")) && (match = src.match(/(((.*)\/)|^)dojo\.js(\W|$)/i))){
+ // sniff dojoDir and baseUrl
+ dojoDir = match[3] || "";
+ defaultConfig.baseUrl = defaultConfig.baseUrl || dojoDir;
+
+ // remember an insertPointSibling
+ insertPointSibling = script;
+ }
+
+ // sniff configuration on attribute in script element
+ if((src = (script.getAttribute("data-dojo-config") || script.getAttribute("djConfig")))){
+ dojoSniffConfig = req.eval("({ " + src + " })", "data-dojo-config");
+
+ // remember an insertPointSibling
+ insertPointSibling = script;
+ }
+
+ // sniff requirejs attribute
+ if( 0 ){
+ if((src = script.getAttribute("data-main"))){
+ dojoSniffConfig.deps = dojoSniffConfig.deps || [src];
+ }
+ }
+ }
+ }
+
+ if( 0 ){
+ // pass down doh.testConfig from parent as if it were a data-dojo-config
+ try{
+ if(window.parent != window && window.parent.require){
+ var doh = window.parent.require("doh");
+ doh && mix(dojoSniffConfig, doh.testConfig);
+ }
+ }catch(e){}
+ }
+
+ // configure the loader; let the user override defaults
+ req.rawConfig = {};
+ config(defaultConfig, 1);
+
+ // do this before setting userConfig/sniffConfig to allow userConfig/sniff overrides
+ if(has("dojo-cdn")){
+ packs.dojo.location = dojoDir;
+ if(dojoDir){
+ dojoDir += "/";
+ }
+ packs.dijit.location = dojoDir + "../dijit/";
+ packs.dojox.location = dojoDir + "../dojox/";
+ }
+
+ config(userConfig, 1);
+ config(dojoSniffConfig, 1);
+
+ }else{
+ // no config API, assume defaultConfig has everything the loader needs...for the entire lifetime of the application
+ paths = defaultConfig.paths;
+ pathsMapProg = defaultConfig.pathsMapProg;
+ packs = defaultConfig.packs;
+ aliases = defaultConfig.aliases;
+ mapProgs = defaultConfig.mapProgs;
+ modules = defaultConfig.modules;
+ cache = defaultConfig.cache;
+ cacheBust = defaultConfig.cacheBust;
+
+ // remember the default config for other processes (e.g., dojo/config)
+ req.rawConfig = defaultConfig;
+ }
+
+
+ if (!has("foreign-loader")) {
+ if( 0 ){
+ req.combo = req.combo || {add:noop};
+ var comboPending = 0,
+ combosPending = [],
+ comboPendingTimer = null;
+ }
+
+
+ // build the loader machinery iaw configuration, including has feature tests
+ var injectDependencies = function(module){
+ // checkComplete!=0 holds the idle signal; we're not idle if we're injecting dependencies
+ guardCheckComplete(function(){
+ forEach(module.deps, injectModule);
+ if( 0 && comboPending && !comboPendingTimer){
+ comboPendingTimer = setTimeout(function() {
+ comboPending = 0;
+ comboPendingTimer = null;
+ req.combo.done(function(mids, url) {
+ var onLoadCallback= function(){
+ // defQ is a vector of module definitions 1-to-1, onto mids
+ runDefQ(0, mids);
+ checkComplete();
+ };
+ combosPending.push(mids);
+ injectingModule = mids;
+ req.injectUrl(url, onLoadCallback, mids);
+ injectingModule = 0;
+ }, req);
+ }, 0);
+ }
+ });
+ },
+
+ contextRequire = function(a1, a2, a3, referenceModule, contextRequire){
+ var module, syntheticMid;
+ if(isString(a1)){
+ // signature is (moduleId)
+ module = getModule(a1, referenceModule, true);
+ if(module && module.executed){
+ return module.result;
+ }
+ throw makeError("undefinedModule", a1);
+ }
+ if(!isArray(a1)){
+ // a1 is a configuration
+ config(a1, 0, referenceModule);
+
+ // juggle args; (a2, a3) may be (dependencies, callback)
+ a1 = a2;
+ a2 = a3;
+ }
+ if(isArray(a1)){
+ // signature is (requestList [,callback])
+ if(!a1.length){
+ a2 && a2();
+ }else{
+ syntheticMid = "require*" + uid();
+
+ // resolve the request list with respect to the reference module
+ for(var mid, deps = [], i = 0; i < a1.length;){
+ mid = a1[i++];
+ deps.push(getModule(mid, referenceModule));
+ }
+
+ // construct a synthetic module to control execution of the requestList, and, optionally, callback
+ module = mix(makeModuleInfo("", syntheticMid, 0, ""), {
+ injected: arrived,
+ deps: deps,
+ def: a2 || noop,
+ require: referenceModule ? referenceModule.require : req,
+ gc: 1 //garbage collect
+ });
+ modules[module.mid] = module;
+
+ // checkComplete!=0 holds the idle signal; we're not idle if we're injecting dependencies
+ injectDependencies(module);
+
+ // try to immediately execute
+ // if already traversing a factory tree, then strict causes circular dependency to abort the execution; maybe
+ // it's possible to execute this require later after the current traversal completes and avoid the circular dependency.
+ // ...but *always* insist on immediate in synch mode
+ var strict = checkCompleteGuard && legacyMode!=sync;
+ guardCheckComplete(function(){
+ execModule(module, strict);
+ });
+ if(!module.executed){
+ // some deps weren't on board or circular dependency detected and strict; therefore, push into the execQ
+ execQ.push(module);
+ }
+ checkComplete();
+ }
+ }
+ return contextRequire;
+ },
+
+ createRequire = function(module){
+ if(!module){
+ return req;
+ }
+ var result = module.require;
+ if(!result){
+ result = function(a1, a2, a3){
+ return contextRequire(a1, a2, a3, module, result);
+ };
+ module.require = mix(result, req);
+ result.module = module;
+ result.toUrl = function(name){
+ return toUrl(name, module);
+ };
+ result.toAbsMid = function(mid){
+ return toAbsMid(mid, module);
+ };
+ if( 0 ){
+ result.undef = function(mid){
+ req.undef(mid, module);
+ };
+ }
+ if( 1 ){
+ result.syncLoadNls = function(mid){
+ var nlsModuleInfo = getModuleInfo(mid, module),
+ nlsModule = modules[nlsModuleInfo.mid];
+ if(!nlsModule || !nlsModule.executed){
+ cached = cache[nlsModuleInfo.mid] || cache[urlKeyPrefix + nlsModuleInfo.url];
+ if(cached){
+ evalModuleText(cached);
+ nlsModule = modules[nlsModuleInfo.mid];
+ }
+ }
+ return nlsModule && nlsModule.executed && nlsModule.result;
+ };
+ }
+
+ }
+ return result;
+ },
+
+ execQ =
+ // The list of modules that need to be evaluated.
+ [],
+
+ defQ =
+ // The queue of define arguments sent to loader.
+ [],
+
+ waiting =
+ // The set of modules upon which the loader is waiting for definition to arrive
+ {},
+
+ setRequested = function(module){
+ module.injected = requested;
+ waiting[module.mid] = 1;
+ if(module.url){
+ waiting[module.url] = module.pack || 1;
+ }
+ startTimer();
+ },
+
+ setArrived = function(module){
+ module.injected = arrived;
+ delete waiting[module.mid];
+ if(module.url){
+ delete waiting[module.url];
+ }
+ if(isEmpty(waiting)){
+ clearTimer();
+ 1 && legacyMode==xd && (legacyMode = sync);
+ }
+ },
+
+ execComplete = req.idle =
+ // says the loader has completed (or not) its work
+ function(){
+ return !defQ.length && isEmpty(waiting) && !execQ.length && !checkCompleteGuard;
+ };
+ }
+
+ var runMapProg = function(targetMid, map){
+ // search for targetMid in map; return the map item if found; falsy otherwise
+ if(map){
+ for(var i = 0; i < map.length; i++){
+ if(map[i][2].test(targetMid)){
+ return map[i];
+ }
+ }
+ }
+ return 0;
+ },
+
+ compactPath = function(path){
+ var result = [],
+ segment, lastSegment;
+ path = path.replace(/\\/g, '/').split('/');
+ while(path.length){
+ segment = path.shift();
+ if(segment==".." && result.length && lastSegment!=".."){
+ result.pop();
+ lastSegment = result[result.length - 1];
+ }else if(segment!="."){
+ result.push(lastSegment= segment);
+ } // else ignore "."
+ }
+ return result.join("/");
+ },
+
+ makeModuleInfo = function(pid, mid, pack, url){
+ if( 1 ){
+ var xd= req.isXdUrl(url);
+ return {pid:pid, mid:mid, pack:pack, url:url, executed:0, def:0, isXd:xd, isAmd:!!(xd || (packs[pid] && packs[pid].isAmd))};
+ }else{
+ return {pid:pid, mid:mid, pack:pack, url:url, executed:0, def:0};
+ }
+ },
+
+ getModuleInfo_ = function(mid, referenceModule, packs, modules, baseUrl, mapProgs, pathsMapProg, aliases, alwaysCreate, fromPendingCache){
+ // arguments are passed instead of using lexical variables so that this function my be used independent of the loader (e.g., the builder)
+ // alwaysCreate is useful in this case so that getModuleInfo never returns references to real modules owned by the loader
+ var pid, pack, midInPackage, mapItem, url, result, isRelative, requestedMid;
+ requestedMid = mid;
+ isRelative = /^\./.test(mid);
+ if(/(^\/)|(\:)|(\.js$)/.test(mid) || (isRelative && !referenceModule)){
+ // absolute path or protocol of .js filetype, or relative path but no reference module and therefore relative to page
+ // whatever it is, it's not a module but just a URL of some sort
+ // note: pid===0 indicates the routine is returning an unmodified mid
+
+ return makeModuleInfo(0, mid, 0, mid);
+ }else{
+ // relative module ids are relative to the referenceModule; get rid of any dots
+ mid = compactPath(isRelative ? (referenceModule.mid + "/../" + mid) : mid);
+ if(/^\./.test(mid)){
+ throw makeError("irrationalPath", mid);
+ }
+ // at this point, mid is an absolute mid
+
+ // map the mid
+ if(!fromPendingCache && !isRelative && mapProgs.star){
+ mapItem = runMapProg(mid, mapProgs.star[1]);
+ }
+ if(!mapItem && referenceModule){
+ mapItem = runMapProg(referenceModule.mid, mapProgs);
+ mapItem = mapItem && runMapProg(mid, mapItem[1]);
+ }
+
+ if(mapItem){
+ mid = mapItem[1] + mid.substring(mapItem[3]);
+ }
+
+ match = mid.match(/^([^\/]+)(\/(.+))?$/);
+ pid = match ? match[1] : "";
+ if((pack = packs[pid])){
+ mid = pid + "/" + (midInPackage = (match[3] || pack.main));
+ }else{
+ pid = "";
+ }
+
+ // search aliases
+ var candidateLength = 0,
+ candidate = 0;
+ forEach(aliases, function(pair){
+ var match = mid.match(pair[0]);
+ if(match && match.length>candidateLength){
+ candidate = isFunction(pair[1]) ? mid.replace(pair[0], pair[1]) : pair[1];
+ }
+ });
+ if(candidate){
+ return getModuleInfo_(candidate, 0, packs, modules, baseUrl, mapProgs, pathsMapProg, aliases, alwaysCreate);
+ }
+
+ result = modules[mid];
+ if(result){
+ return alwaysCreate ? makeModuleInfo(result.pid, result.mid, result.pack, result.url) : modules[mid];
+ }
+ }
+ // get here iff the sought-after module does not yet exist; therefore, we need to compute the URL given the
+ // fully resolved (i.e., all relative indicators and package mapping resolved) module id
+
+ // note: pid!==0 indicates the routine is returning a url that has .js appended unmodified mid
+ mapItem = runMapProg(mid, pathsMapProg);
+ if(mapItem){
+ url = mapItem[1] + mid.substring(mapItem[3]);
+ }else if(pid){
+ url = (pack.location.slice(-1) === '/' ? pack.location.slice(0, -1) : pack.location) + "/" + midInPackage;
+ }else if(has("config-tlmSiblingOfDojo")){
+ url = "../" + mid;
+ }else{
+ url = mid;
+ }
+ // if result is not absolute, add baseUrl
+ if(!(/(^\/)|(\:)/.test(url))){
+ url = baseUrl + url;
+ }
+ url += ".js";
+ return makeModuleInfo(pid, mid, pack, compactPath(url));
+ },
+
+ getModuleInfo = function(mid, referenceModule, fromPendingCache){
+ return getModuleInfo_(mid, referenceModule, packs, modules, req.baseUrl, mapProgs, pathsMapProg, aliases, undefined, fromPendingCache);
+ };
+
+ if (!has("foreign-loader")) {
+ var resolvePluginResourceId = function(plugin, prid, referenceModule){
+ return plugin.normalize ? plugin.normalize(prid, function(mid){return toAbsMid(mid, referenceModule);}) : toAbsMid(prid, referenceModule);
+ },
+
+ dynamicPluginUidGenerator = 0,
+
+ getModule = function(mid, referenceModule, immediate){
+ // compute and optionally construct (if necessary) the module implied by the mid with respect to referenceModule
+ var match, plugin, prid, result;
+ match = mid.match(/^(.+?)\!(.*)$/);
+ if(match){
+ // name was !
+ plugin = getModule(match[1], referenceModule, immediate);
+
+ if( 1 && legacyMode == sync && !plugin.executed){
+ injectModule(plugin);
+ if(plugin.injected===arrived && !plugin.executed){
+ guardCheckComplete(function(){
+ execModule(plugin);
+ });
+ }
+ if(plugin.executed){
+ promoteModuleToPlugin(plugin);
+ }else{
+ // we are in xdomain mode for some reason
+ execQ.unshift(plugin);
+ }
+ }
+
+
+
+ if(plugin.executed === executed && !plugin.load){
+ // executed the module not knowing it was a plugin
+ promoteModuleToPlugin(plugin);
+ }
+
+ // if the plugin has not been loaded, then can't resolve the prid and must assume this plugin is dynamic until we find out otherwise
+ if(plugin.load){
+ prid = resolvePluginResourceId(plugin, match[2], referenceModule);
+ mid = (plugin.mid + "!" + (plugin.dynamic ? ++dynamicPluginUidGenerator + "!" : "") + prid);
+ }else{
+ prid = match[2];
+ mid = plugin.mid + "!" + (++dynamicPluginUidGenerator) + "!waitingForPlugin";
+ }
+ result = {plugin:plugin, mid:mid, req:createRequire(referenceModule), prid:prid};
+ }else{
+ result = getModuleInfo(mid, referenceModule);
+ }
+ return modules[result.mid] || (!immediate && (modules[result.mid] = result));
+ };
+ }
+
+ var toAbsMid = req.toAbsMid = function(mid, referenceModule){
+ return getModuleInfo(mid, referenceModule).mid;
+ },
+
+ toUrl = req.toUrl = function(name, referenceModule){
+ var moduleInfo = getModuleInfo(name+"/x", referenceModule),
+ url= moduleInfo.url;
+ return fixupUrl(moduleInfo.pid===0 ?
+ // if pid===0, then name had a protocol or absolute path; either way, toUrl is the identify function in such cases
+ name :
+ // "/x.js" since getModuleInfo automatically appends ".js" and we appended "/x" to make name look like a module id
+ url.substring(0, url.length-5)
+ );
+ };
+
+ if (!has("foreign-loader")) {
+ var nonModuleProps = {
+ injected: arrived,
+ executed: executed,
+ def: nonmodule,
+ result: nonmodule
+ },
+
+ makeCjs = function(mid){
+ return modules[mid] = mix({mid:mid}, nonModuleProps);
+ },
+
+ cjsRequireModule = makeCjs("require"),
+ cjsExportsModule = makeCjs("exports"),
+ cjsModuleModule = makeCjs("module"),
+
+ runFactory = function(module, args){
+ req.trace("loader-run-factory", [module.mid]);
+ var factory = module.def,
+ result;
+ 1 && syncExecStack.unshift(module);
+ if(has("config-dojo-loader-catches")){
+ try{
+ result= isFunction(factory) ? factory.apply(null, args) : factory;
+ }catch(e){
+ signal(error, module.result = makeError("factoryThrew", [module, e]));
+ }
+ }else{
+ result= isFunction(factory) ? factory.apply(null, args) : factory;
+ }
+ module.result = result===undefined && module.cjs ? module.cjs.exports : result;
+ 1 && syncExecStack.shift(module);
+ },
+
+ abortExec = {},
+
+ defOrder = 0,
+
+ promoteModuleToPlugin = function(pluginModule){
+ var plugin = pluginModule.result;
+ pluginModule.dynamic = plugin.dynamic;
+ pluginModule.normalize = plugin.normalize;
+ pluginModule.load = plugin.load;
+ return pluginModule;
+ },
+
+ resolvePluginLoadQ = function(plugin){
+ // plugins is a newly executed module that has a loadQ waiting to run
+
+ // step 1: traverse the loadQ and fixup the mid and prid; remember the map from original mid to new mid
+ // recall the original mid was created before the plugin was on board and therefore it was impossible to
+ // compute the final mid; accordingly, prid may or may not change, but the mid will definitely change
+ var map = {};
+ forEach(plugin.loadQ, function(pseudoPluginResource){
+ // manufacture and insert the real module in modules
+ var prid = resolvePluginResourceId(plugin, pseudoPluginResource.prid, pseudoPluginResource.req.module),
+ mid = plugin.dynamic ? pseudoPluginResource.mid.replace(/waitingForPlugin$/, prid) : (plugin.mid + "!" + prid),
+ pluginResource = mix(mix({}, pseudoPluginResource), {mid:mid, prid:prid, injected:0});
+ if(!modules[mid] || !modules[mid].injected /*for require.undef*/){
+ // create a new (the real) plugin resource and inject it normally now that the plugin is on board
+ injectPlugin(modules[mid] = pluginResource);
+ } // else this was a duplicate request for the same (plugin, rid) for a nondynamic plugin
+
+ // pluginResource is really just a placeholder with the wrong mid (because we couldn't calculate it until the plugin was on board)
+ // mark is as arrived and delete it from modules; the real module was requested above
+ map[pseudoPluginResource.mid] = modules[mid];
+ setArrived(pseudoPluginResource);
+ delete modules[pseudoPluginResource.mid];
+ });
+ plugin.loadQ = 0;
+
+ // step2: replace all references to any placeholder modules with real modules
+ var substituteModules = function(module){
+ for(var replacement, deps = module.deps || [], i = 0; i")]);
+ return (!module.def || strict) ? abortExec : (module.cjs && module.cjs.exports);
+ }
+ // at this point the module is either not executed or fully executed
+
+
+ if(!module.executed){
+ if(!module.def){
+ return abortExec;
+ }
+ var mid = module.mid,
+ deps = module.deps || [],
+ arg, argResult,
+ args = [],
+ i = 0;
+
+ if( 0 ){
+ circleTrace.push(mid);
+ req.trace("loader-exec-module", ["exec", circleTrace.length, mid]);
+ }
+
+ // for circular dependencies, assume the first module encountered was executed OK
+ // modules that circularly depend on a module that has not run its factory will get
+ // the pre-made cjs.exports===module.result. They can take a reference to this object and/or
+ // add properties to it. When the module finally runs its factory, the factory can
+ // read/write/replace this object. Notice that so long as the object isn't replaced, any
+ // reference taken earlier while walking the deps list is still valid.
+ module.executed = executing;
+ while((arg = deps[i++])){
+ argResult = ((arg === cjsRequireModule) ? createRequire(module) :
+ ((arg === cjsExportsModule) ? module.cjs.exports :
+ ((arg === cjsModuleModule) ? module.cjs :
+ execModule(arg, strict))));
+ if(argResult === abortExec){
+ module.executed = 0;
+ req.trace("loader-exec-module", ["abort", mid]);
+ 0 && circleTrace.pop();
+ return abortExec;
+ }
+ args.push(argResult);
+ }
+ runFactory(module, args);
+ finishExec(module);
+ 0 && circleTrace.pop();
+ }
+ // at this point the module is guaranteed fully executed
+
+ return module.result;
+ },
+
+
+ checkCompleteGuard = 0,
+
+ guardCheckComplete = function(proc){
+ try{
+ checkCompleteGuard++;
+ proc();
+ }catch(e){
+ // https://bugs.dojotoolkit.org/ticket/16617
+ throw e;
+ }finally{
+ checkCompleteGuard--;
+ }
+ if(execComplete()){
+ signal("idle", []);
+ }
+ },
+
+ checkComplete = function(){
+ // keep going through the execQ as long as at least one factory is executed
+ // plugins, recursion, cached modules all make for many execution path possibilities
+ if(checkCompleteGuard){
+ return;
+ }
+ guardCheckComplete(function(){
+ checkDojoRequirePlugin();
+ for(var currentDefOrder, module, i = 0; i < execQ.length;){
+ currentDefOrder = defOrder;
+ module = execQ[i];
+ execModule(module);
+ if(currentDefOrder!=defOrder){
+ // defOrder was bumped one or more times indicating something was executed (note, this indicates
+ // the execQ was modified, maybe a lot (for example a later module causes an earlier module to execute)
+ checkDojoRequirePlugin();
+ i = 0;
+ }else{
+ // nothing happened; check the next module in the exec queue
+ i++;
+ }
+ }
+ });
+ };
+ }
+
+ var fixupUrl= typeof userConfig.fixupUrl == "function" ? userConfig.fixupUrl : function(url){
+ url += ""; // make sure url is a Javascript string (some paths may be a Java string)
+ return url + (cacheBust ? ((/\?/.test(url) ? "&" : "?") + cacheBust) : "");
+ };
+
+
+
+ if( 0 ){
+ req.undef = function(moduleId, referenceModule){
+ // In order to reload a module, it must be undefined (this routine) and then re-requested.
+ // This is useful for testing frameworks (at least).
+ var module = getModule(moduleId, referenceModule);
+ setArrived(module);
+ mix(module, {def:0, executed:0, injected:0, node:0, load:0});
+ };
+ }
+
+ if( 1 ){
+ if(has("dojo-loader-eval-hint-url")===undefined){
+ has.add("dojo-loader-eval-hint-url", 1);
+ }
+
+ var injectPlugin = function(
+ module
+ ){
+ // injects the plugin module given by module; may have to inject the plugin itself
+ var plugin = module.plugin;
+
+ if(plugin.executed === executed && !plugin.load){
+ // executed the module not knowing it was a plugin
+ promoteModuleToPlugin(plugin);
+ }
+
+ var onLoad = function(def){
+ module.result = def;
+ setArrived(module);
+ finishExec(module);
+ checkComplete();
+ };
+
+ if(plugin.load){
+ plugin.load(module.prid, module.req, onLoad);
+ }else if(plugin.loadQ){
+ plugin.loadQ.push(module);
+ }else{
+ // the unshift instead of push is important: we don't want plugins to execute as
+ // dependencies of some other module because this may cause circles when the plugin
+ // loadQ is run; also, generally, we want plugins to run early since they may load
+ // several other modules and therefore can potentially unblock many modules
+ plugin.loadQ = [module];
+ execQ.unshift(plugin);
+ injectModule(plugin);
+ }
+ },
+
+ // for IE, injecting a module may result in a recursive execution if the module is in the cache
+
+ cached = 0,
+
+ injectingModule = 0,
+
+ injectingCachedModule = 0,
+
+ evalModuleText = function(text, module){
+ // see def() for the injectingCachedModule bracket; it simply causes a short, safe circuit
+ if(has("config-stripStrict")){
+ text = text.replace(/(["'])use strict\1/g, '');
+ }
+ injectingCachedModule = 1;
+ if(has("config-dojo-loader-catches")){
+ try{
+ if(text===cached){
+ cached.call(null);
+ }else{
+ req.eval(text, has("dojo-loader-eval-hint-url") ? module.url : module.mid);
+ }
+ }catch(e){
+ signal(error, makeError("evalModuleThrew", module));
+ }
+ }else{
+ if(text===cached){
+ cached.call(null);
+ }else{
+ req.eval(text, has("dojo-loader-eval-hint-url") ? module.url : module.mid);
+ }
+ }
+ injectingCachedModule = 0;
+ },
+
+ injectModule = function(module){
+ // Inject the module. In the browser environment, this means appending a script element into
+ // the document; in other environments, it means loading a file.
+ //
+ // If in synchronous mode, then get the module synchronously if it's not xdomainLoading.
+
+ var mid = module.mid,
+ url = module.url;
+ if(module.executed || module.injected || waiting[mid] || (module.url && ((module.pack && waiting[module.url]===module.pack) || waiting[module.url]==1))){
+ return;
+ }
+ setRequested(module);
+
+ if( 0 ){
+ var viaCombo = 0;
+ if(module.plugin && module.plugin.isCombo){
+ // a combo plugin; therefore, must be handled by combo service
+ // the prid should have already been converted to a URL (if required by the plugin) during
+ // the normalize process; in any event, there is no way for the loader to know how to
+ // to the conversion; therefore the third argument is zero
+ req.combo.add(module.plugin.mid, module.prid, 0, req);
+ viaCombo = 1;
+ }else if(!module.plugin){
+ viaCombo = req.combo.add(0, module.mid, module.url, req);
+ }
+ if(viaCombo){
+ comboPending= 1;
+ return;
+ }
+ }
+
+ if(module.plugin){
+ injectPlugin(module);
+ return;
+ } // else a normal module (not a plugin)
+
+
+ var onLoadCallback = function(){
+ runDefQ(module);
+ if(module.injected !== arrived){
+ // the script that contained the module arrived and has been executed yet
+ // nothing was added to the defQ (so it wasn't an AMD module) and the module
+ // wasn't marked as arrived by dojo.provide (so it wasn't a v1.6- module);
+ // therefore, it must not have been a module; adjust state accordingly
+ if(has("dojo-enforceDefine")){
+ signal(error, makeError("noDefine", module));
+ return;
+ }
+ setArrived(module);
+ mix(module, nonModuleProps);
+ req.trace("loader-define-nonmodule", [module.url]);
+ }
+
+ if( 1 && legacyMode){
+ // must call checkComplete even in for sync loader because we may be in xdomainLoading mode;
+ // but, if xd loading, then don't call checkComplete until out of the current sync traversal
+ // in order to preserve order of execution of the dojo.required modules
+ !syncExecStack.length && checkComplete();
+ }else{
+ checkComplete();
+ }
+ };
+ cached = cache[mid] || cache[urlKeyPrefix + module.url];
+ if(cached){
+ req.trace("loader-inject", ["cache", module.mid, url]);
+ evalModuleText(cached, module);
+ onLoadCallback();
+ return;
+ }
+ if( 1 && legacyMode){
+ if(module.isXd){
+ // switch to async mode temporarily; if current legacyMode!=sync, then is must be one of {legacyAsync, xd, false}
+ legacyMode==sync && (legacyMode = xd);
+ // fall through and load via script injection
+ }else if(module.isAmd && legacyMode!=sync){
+ // fall through and load via script injection
+ }else{
+ // mode may be sync, xd/legacyAsync, or async; module may be AMD or legacy; but module is always located on the same domain
+ var xhrCallback = function(text){
+ if(legacyMode==sync){
+ // the top of syncExecStack gives the current synchronously executing module; the loader needs
+ // to know this if it has to switch to async loading in the middle of evaluating a legacy module
+ // this happens when a modules dojo.require's a module that must be loaded async because it's xdomain
+ // (using unshift/shift because there is no back() methods for Javascript arrays)
+ syncExecStack.unshift(module);
+ evalModuleText(text, module);
+ syncExecStack.shift();
+
+ // maybe the module was an AMD module
+ runDefQ(module);
+
+ // legacy modules never get to defineModule() => cjs and injected never set; also evaluation implies executing
+ if(!module.cjs){
+ setArrived(module);
+ finishExec(module);
+ }
+
+ if(module.finish){
+ // while synchronously evaluating this module, dojo.require was applied referencing a module
+ // that had to be loaded async; therefore, the loader stopped answering all dojo.require
+ // requests so they could be answered completely in the correct sequence; module.finish gives
+ // the list of dojo.requires that must be re-applied once all target modules are available;
+ // make a synthetic module to execute the dojo.require's in the correct order
+
+ // compute a guaranteed-unique mid for the synthetic finish module; remember the finish vector; remove it from the reference module
+ // TODO: can we just leave the module.finish...what's it hurting?
+ var finishMid = mid + "*finish",
+ finish = module.finish;
+ delete module.finish;
+
+ def(finishMid, ["dojo", ("dojo/require!" + finish.join(",")).replace(/\./g, "/")], function(dojo){
+ forEach(finish, function(mid){ dojo.require(mid); });
+ });
+ // unshift, not push, which causes the current traversal to be reattempted from the top
+ execQ.unshift(getModule(finishMid));
+ }
+ onLoadCallback();
+ }else{
+ text = transformToAmd(module, text);
+ if(text){
+ evalModuleText(text, module);
+ onLoadCallback();
+ }else{
+ // if transformToAmd returned falsy, then the module was already AMD and it can be script-injected
+ // do so to improve debugability(even though it means another download...which probably won't happen with a good browser cache)
+ injectingModule = module;
+ req.injectUrl(fixupUrl(url), onLoadCallback, module);
+ injectingModule = 0;
+ }
+ }
+ };
+
+ req.trace("loader-inject", ["xhr", module.mid, url, legacyMode!=sync]);
+ if(has("config-dojo-loader-catches")){
+ try{
+ req.getText(url, legacyMode!=sync, xhrCallback);
+ }catch(e){
+ signal(error, makeError("xhrInjectFailed", [module, e]));
+ }
+ }else{
+ req.getText(url, legacyMode!=sync, xhrCallback);
+ }
+ return;
+ }
+ } // else async mode or fell through in xdomain loading mode; either way, load by script injection
+ req.trace("loader-inject", ["script", module.mid, url]);
+ injectingModule = module;
+ req.injectUrl(fixupUrl(url), onLoadCallback, module);
+ injectingModule = 0;
+ },
+
+ defineModule = function(module, deps, def){
+ req.trace("loader-define-module", [module.mid, deps]);
+
+ if( 0 && module.plugin && module.plugin.isCombo){
+ // the module is a plugin resource loaded by the combo service
+ // note: check for module.plugin should be enough since normal plugin resources should
+ // not follow this path; module.plugin.isCombo is future-proofing belt and suspenders
+ module.result = isFunction(def) ? def() : def;
+ setArrived(module);
+ finishExec(module);
+ return module;
+ }
+
+ var mid = module.mid;
+ if(module.injected === arrived){
+ signal(error, makeError("multipleDefine", module));
+ return module;
+ }
+ mix(module, {
+ deps: deps,
+ def: def,
+ cjs: {
+ id: module.mid,
+ uri: module.url,
+ exports: (module.result = {}),
+ setExports: function(exports){
+ module.cjs.exports = exports;
+ },
+ config:function(){
+ return module.config;
+ }
+ }
+ });
+
+ // resolve deps with respect to this module
+ for(var i = 0; deps[i]; i++){
+ deps[i] = getModule(deps[i], module);
+ }
+
+ if( 1 && legacyMode && !waiting[mid]){
+ // the module showed up without being asked for; it was probably in a
+ // |
+
+ var paths = {};
+ paths[moduleName.replace(/\./g, "/")] = prefix;
+ require({paths:paths});
+ };
+
+ dojo.platformRequire = function(/*Object*/modMap){
+ // summary:
+ // require one or more modules based on which host environment
+ // Dojo is currently operating in
+ // description:
+ // This method takes a "map" of arrays which one can use to
+ // optionally load dojo modules. The map is indexed by the
+ // possible dojo.name_ values, with two additional values:
+ // "default" and "common". The items in the "default" array will
+ // be loaded if none of the other items have been chosen based on
+ // dojo.name_, set by your host environment. The items in the
+ // "common" array will *always* be loaded, regardless of which
+ // list is chosen.
+ // example:
+ // | dojo.platformRequire({
+ // | browser: [
+ // | "foo.sample", // simple module
+ // | "foo.test",
+ // | ["foo.bar.baz", true] // skip object check in _loadModule (dojo.require)
+ // | ],
+ // | default: [ "foo.sample._base" ],
+ // | common: [ "important.module.common" ]
+ // | });
+
+ var result = (modMap.common || []).concat(modMap[dojo._name] || modMap["default"] || []),
+ temp;
+ while(result.length){
+ if(lang.isArray(temp = result.shift())){
+ dojo.require.apply(dojo, temp);
+ }else{
+ dojo.require(temp);
+ }
+ }
+ };
+
+ dojo.requireIf = dojo.requireAfterIf = function(/*Boolean*/ condition, /*String*/ moduleName, /*Boolean?*/omitModuleCheck){
+ // summary:
+ // If the condition is true then call `dojo.require()` for the specified
+ // resource
+ //
+ // example:
+ // | dojo.requireIf(dojo.isBrowser, "my.special.Module");
+
+ if(condition){
+ dojo.require(moduleName, omitModuleCheck);
+ }
+ };
+
+ dojo.requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale){
+ require(["../i18n"], function(i18n){
+ i18n.getLocalization(moduleName, bundleName, locale);
+ });
+ };
+
+ return {
+ // summary:
+ // This module defines the v1.x synchronous loader API.
+
+ extractLegacyApiApplications:extractLegacyApiApplications,
+ require:dojoRequirePlugin,
+ loadInit:dojoLoadInitPlugin
+ };
+});
+
+},
+'dojo/_base/kernel':function(){
+define(["../global", "../has", "./config", "require", "module"], function(global, has, config, require, module){
+ // module:
+ // dojo/_base/kernel
+
+ // This module is the foundational module of the dojo boot sequence; it defines the dojo object.
+
+ var
+ // loop variables for this module
+ i, p,
+
+ // create dojo, dijit, and dojox
+ // FIXME: in 2.0 remove dijit, dojox being created by dojo
+ dijit = {},
+ dojox = {},
+ dojo = {
+ // summary:
+ // This module is the foundational module of the dojo boot sequence; it defines the dojo object.
+
+ // notice dojo takes ownership of the value of the config module
+ config:config,
+ global:global,
+ dijit:dijit,
+ dojox:dojox
+ };
+
+
+ // Configure the scope map. For a 100% AMD application, the scope map is not needed other than to provide
+ // a _scopeName property for the dojo, dijit, and dojox root object so those packages can create
+ // unique names in the global space.
+ //
+ // Built, legacy modules use the scope map to allow those modules to be expressed as if dojo, dijit, and dojox,
+ // where global when in fact they are either global under different names or not global at all. In v1.6-, the
+ // config variable "scopeMap" was used to map names as used within a module to global names. This has been
+ // subsumed by the AMD map configuration variable which can relocate packages to different names. For backcompat,
+ // only the "*" mapping is supported. See http://livedocs.dojotoolkit.org/developer/design/loader#legacy-cross-domain-mode for details.
+ //
+ // The following computations contort the packageMap for this dojo instance into a scopeMap.
+ var scopeMap =
+ // a map from a name used in a legacy module to the (global variable name, object addressed by that name)
+ // always map dojo, dijit, and dojox
+ {
+ dojo:["dojo", dojo],
+ dijit:["dijit", dijit],
+ dojox:["dojox", dojox]
+ },
+
+ packageMap =
+ // the package map for this dojo instance; note, a foreign loader or no pacakgeMap results in the above default config
+ (require.map && require.map[module.id.match(/[^\/]+/)[0]]),
+
+ item;
+
+
+ // process all mapped top-level names for this instance of dojo
+ for(p in packageMap){
+ if(scopeMap[p]){
+ // mapped dojo, dijit, or dojox
+ scopeMap[p][0] = packageMap[p];
+ }else{
+ // some other top-level name
+ scopeMap[p] = [packageMap[p], {}];
+ }
+ }
+
+ // publish those names to _scopeName and, optionally, the global namespace
+ for(p in scopeMap){
+ item = scopeMap[p];
+ item[1]._scopeName = item[0];
+ if(!config.noGlobals){
+ global[item[0]] = item[1];
+ }
+ }
+ dojo.scopeMap = scopeMap;
+
+ /*===== dojo.__docParserConfigureScopeMap(scopeMap); =====*/
+
+ // FIXME: dojo.baseUrl and dojo.config.baseUrl should be deprecated
+ dojo.baseUrl = dojo.config.baseUrl = require.baseUrl;
+ dojo.isAsync = ! 1 || require.async;
+ dojo.locale = config.locale;
+
+ var rev = "$Rev:$".match(/[0-9a-f]{7,}/);
+ dojo.version = {
+ // summary:
+ // Version number of the Dojo Toolkit
+ // description:
+ // Hash about the version, including
+ //
+ // - major: Integer: Major version. If total version is "1.2.0beta1", will be 1
+ // - minor: Integer: Minor version. If total version is "1.2.0beta1", will be 2
+ // - patch: Integer: Patch version. If total version is "1.2.0beta1", will be 0
+ // - flag: String: Descriptor flag. If total version is "1.2.0beta1", will be "beta1"
+ // - revision: Number: The Git rev from which dojo was pulled
+
+ major: 1, minor: 17, patch: 3, flag: "",
+ revision: rev ? rev[0] : NaN,
+ toString: function(){
+ var v = dojo.version;
+ return v.major + "." + v.minor + "." + v.patch + v.flag + " (" + v.revision + ")"; // String
+ }
+ };
+
+ // If 1 is truthy, then as a dojo module is defined it should push it's definitions
+ // into the dojo object, and conversely. In 2.0, it will likely be unusual to augment another object
+ // as a result of defining a module. This has feature gives a way to force 2.0 behavior as the code
+ // is migrated. Absent specific advice otherwise, set extend-dojo to truthy.
+ 1 || has.add("extend-dojo", 1);
+
+ if(!has("csp-restrictions")){
+ (Function("d", "d.eval = function(){return d.global.eval ? d.global.eval(arguments[0]) : eval(arguments[0]);}"))(dojo);
+ }
+ /*=====
+ dojo.eval = function(scriptText){
+ // summary:
+ // A legacy method created for use exclusively by internal Dojo methods. Do not use this method
+ // directly unless you understand its possibly-different implications on the platforms your are targeting.
+ // description:
+ // Makes an attempt to evaluate scriptText in the global scope. The function works correctly for browsers
+ // that support indirect eval.
+ //
+ // As usual, IE does not. On IE, the only way to implement global eval is to
+ // use execScript. Unfortunately, execScript does not return a value and breaks some current usages of dojo.eval.
+ // This implementation uses the technique of executing eval in the scope of a function that is a single scope
+ // frame below the global scope; thereby coming close to the global scope. Note carefully that
+ //
+ // dojo.eval("var pi = 3.14;");
+ //
+ // will define global pi in non-IE environments, but define pi only in a temporary local scope for IE. If you want
+ // to define a global variable using dojo.eval, write something like
+ //
+ // dojo.eval("window.pi = 3.14;")
+ // scriptText:
+ // The text to evaluation.
+ // returns:
+ // The result of the evaluation. Often `undefined`
+ };
+ =====*/
+
+
+ if( 0 ){
+ dojo.exit = function(exitcode){
+ quit(exitcode);
+ };
+ }else{
+ dojo.exit = function(){
+ };
+ }
+
+ if(!has("host-webworker")){
+ // console is immutable in FF30+, https://bugs.dojotoolkit.org/ticket/18100
+ 1 || has.add("dojo-guarantee-console",
+ // ensure that console.log, console.warn, etc. are defined
+ 1
+ );
+ }
+
+ if( 1 ){
+ // IE 9 bug: https://bugs.dojotoolkit.org/ticket/18197
+ has.add("console-as-object", function () {
+ return Function.prototype.bind && console && typeof console.log === "object";
+ });
+
+ typeof console != "undefined" || (console = {}); // intentional assignment
+ // Be careful to leave 'log' always at the end
+ var cn = [
+ "assert", "count", "debug", "dir", "dirxml", "error", "group",
+ "groupEnd", "info", "profile", "profileEnd", "time", "timeEnd",
+ "trace", "warn", "log"
+ ];
+ var tn;
+ i = 0;
+ while((tn = cn[i++])){
+ if(!console[tn]){
+ (function(){
+ var tcn = tn + "";
+ console[tcn] = ('log' in console) ? function(){
+ var a = Array.prototype.slice.call(arguments);
+ a.unshift(tcn + ":");
+ console["log"](a.join(" "));
+ } : function(){};
+ console[tcn]._fake = true;
+ })();
+ }else if(has("console-as-object")){
+ console[tn] = Function.prototype.bind.call(console[tn], console);
+ }
+ }
+ }
+
+ has.add("dojo-debug-messages",
+ // include dojo.deprecated/dojo.experimental implementations
+ !!config.isDebug
+ );
+ dojo.deprecated = dojo.experimental = function(){};
+ if(has("dojo-debug-messages")){
+ dojo.deprecated = function(/*String*/ behaviour, /*String?*/ extra, /*String?*/ removal){
+ // summary:
+ // Log a debug message to indicate that a behavior has been
+ // deprecated.
+ // behaviour: String
+ // The API or behavior being deprecated. Usually in the form
+ // of "myApp.someFunction()".
+ // extra: String?
+ // Text to append to the message. Often provides advice on a
+ // new function or facility to achieve the same goal during
+ // the deprecation period.
+ // removal: String?
+ // Text to indicate when in the future the behavior will be
+ // removed. Usually a version number.
+ // example:
+ // | dojo.deprecated("myApp.getTemp()", "use myApp.getLocaleTemp() instead", "1.0");
+
+ var message = "DEPRECATED: " + behaviour;
+ if(extra){ message += " " + extra; }
+ if(removal){ message += " -- will be removed in version: " + removal; }
+ console.warn(message);
+ };
+
+ dojo.experimental = function(/* String */ moduleName, /* String? */ extra){
+ // summary:
+ // Marks code as experimental.
+ // description:
+ // This can be used to mark a function, file, or module as
+ // experimental. Experimental code is not ready to be used, and the
+ // APIs are subject to change without notice. Experimental code may be
+ // completed deleted without going through the normal deprecation
+ // process.
+ // moduleName: String
+ // The name of a module, or the name of a module file or a specific
+ // function
+ // extra: String?
+ // some additional message for the user
+ // example:
+ // | dojo.experimental("dojo.data.Result");
+ // example:
+ // | dojo.experimental("dojo.weather.toKelvin()", "PENDING approval from NOAA");
+
+ var message = "EXPERIMENTAL: " + moduleName + " -- APIs subject to change without notice.";
+ if(extra){ message += " " + extra; }
+ console.warn(message);
+ };
+ }
+
+ 1 || has.add("dojo-modulePaths",
+ // consume dojo.modulePaths processing
+ 1
+ );
+ if( 1 ){
+ // notice that modulePaths won't be applied to any require's before the dojo/_base/kernel factory is run;
+ // this is the v1.6- behavior.
+ if(config.modulePaths){
+ dojo.deprecated("dojo.modulePaths", "use paths configuration");
+ var paths = {};
+ for(p in config.modulePaths){
+ paths[p.replace(/\./g, "/")] = config.modulePaths[p];
+ }
+ require({paths:paths});
+ }
+ }
+
+ 1 || has.add("dojo-moduleUrl",
+ // include dojo.moduleUrl
+ 1
+ );
+ if( 1 ){
+ dojo.moduleUrl = function(/*String*/module, /*String?*/url){
+ // summary:
+ // Returns a URL relative to a module.
+ // example:
+ // | var pngPath = dojo.moduleUrl("acme","images/small.png");
+ // | console.dir(pngPath); // list the object properties
+ // | // create an image and set it's source to pngPath's value:
+ // | var img = document.createElement("img");
+ // | img.src = pngPath;
+ // | // add our image to the document
+ // | dojo.body().appendChild(img);
+ // example:
+ // you may de-reference as far as you like down the package
+ // hierarchy. This is sometimes handy to avoid lengthy relative
+ // urls or for building portable sub-packages. In this example,
+ // the `acme.widget` and `acme.util` directories may be located
+ // under different roots (see `dojo.registerModulePath`) but the
+ // the modules which reference them can be unaware of their
+ // relative locations on the filesystem:
+ // | // somewhere in a configuration block
+ // | dojo.registerModulePath("acme.widget", "../../acme/widget");
+ // | dojo.registerModulePath("acme.util", "../../util");
+ // |
+ // | // ...
+ // |
+ // | // code in a module using acme resources
+ // | var tmpltPath = dojo.moduleUrl("acme.widget","templates/template.html");
+ // | var dataPath = dojo.moduleUrl("acme.util","resources/data.json");
+
+ dojo.deprecated("dojo.moduleUrl()", "use require.toUrl", "2.0");
+
+ // require.toUrl requires a filetype; therefore, just append the suffix "/*.*" to guarantee a filetype, then
+ // remove the suffix from the result. This way clients can request a url w/out a filetype. This should be
+ // rare, but it maintains backcompat for the v1.x line (note: dojo.moduleUrl will be removed in v2.0).
+ // Notice * is an illegal filename so it won't conflict with any real path map that may exist the paths config.
+ var result = null;
+ if(module){
+ result = require.toUrl(module.replace(/\./g, "/") + (url ? ("/" + url) : "") + "/*.*").replace(/\/\*\.\*/, "") + (url ? "" : "/");
+ }
+ return result;
+ };
+ }
+
+ dojo._hasResource = {}; // for backward compatibility with layers built with 1.6 tooling
+
+ return dojo;
+});
+
+},
+'dojo/global':function(){
+define(function(){
+ if (typeof global !== 'undefined' && typeof global !== 'function') {
+ // global spec defines a reference to the global object called 'global'
+ // https://github.com/tc39/proposal-global
+ // `global` is also defined in NodeJS
+ return global;
+ }
+ else if (typeof window !== 'undefined') {
+ // window is defined in browsers
+ return window;
+ }
+ else if (typeof self !== 'undefined') {
+ // self is defined in WebWorkers
+ return self;
+ }
+ return this;
+});
+
+},
+'dojo/has':function(){
+define(["./global", "require", "module"], function(global, require, module){
+ // module:
+ // dojo/has
+ // summary:
+ // Defines the has.js API and several feature tests used by dojo.
+ // description:
+ // This module defines the has API as described by the project has.js with the following additional features:
+ //
+ // - the has test cache is exposed at has.cache.
+ // - the method has.add includes a forth parameter that controls whether or not existing tests are replaced
+ // - the loader's has cache may be optionally copied into this module's has cahce.
+ //
+ // This module adopted from https://github.com/phiggins42/has.js; thanks has.js team!
+
+ // try to pull the has implementation from the loader; both the dojo loader and bdLoad provide one
+ // if using a foreign loader, then the has cache may be initialized via the config object for this module
+ // WARNING: if a foreign loader defines require.has to be something other than the has.js API, then this implementation fail
+ var has = require.has || function(){};
+ if(! 1 ){
+ var
+ isBrowser =
+ // the most fundamental decision: are we in the browser?
+ typeof window != "undefined" &&
+ typeof location != "undefined" &&
+ typeof document != "undefined" &&
+ window.location == location && window.document == document,
+
+ // has API variables
+ doc = isBrowser && document,
+ element = doc && doc.createElement("DiV"),
+ cache = (module.config && module.config()) || {};
+
+ has = function(name){
+ // summary:
+ // Return the current value of the named feature.
+ //
+ // name: String|Integer
+ // The name (if a string) or identifier (if an integer) of the feature to test.
+ //
+ // description:
+ // Returns the value of the feature named by name. The feature must have been
+ // previously added to the cache by has.add.
+
+ return typeof cache[name] == "function" ? (cache[name] = cache[name](global, doc, element)) : cache[name]; // Boolean
+ };
+
+ has.cache = cache;
+
+ has.add = function(name, test, now, force){
+ // summary:
+ // Register a new feature test for some named feature.
+ // name: String|Integer
+ // The name (if a string) or identifier (if an integer) of the feature to test.
+ // test: Function
+ // A test function to register. If a function, queued for testing until actually
+ // needed. The test function should return a boolean indicating
+ // the presence of a feature or bug.
+ // now: Boolean?
+ // Optional. Omit if `test` is not a function. Provides a way to immediately
+ // run the test and cache the result.
+ // force: Boolean?
+ // Optional. If the test already exists and force is truthy, then the existing
+ // test will be replaced; otherwise, add does not replace an existing test (that
+ // is, by default, the first test advice wins).
+ // example:
+ // A redundant test, testFn with immediate execution:
+ // | has.add("javascript", function(){ return true; }, true);
+ //
+ // example:
+ // Again with the redundantness. You can do this in your tests, but we should
+ // not be doing this in any internal has.js tests
+ // | has.add("javascript", true);
+ //
+ // example:
+ // Three things are passed to the testFunction. `global`, `document`, and a generic element
+ // from which to work your test should the need arise.
+ // | has.add("bug-byid", function(g, d, el){
+ // | // g == global, typically window, yadda yadda
+ // | // d == document object
+ // | // el == the generic element. a `has` element.
+ // | return false; // fake test, byid-when-form-has-name-matching-an-id is slightly longer
+ // | });
+
+ (typeof cache[name]=="undefined" || force) && (cache[name]= test);
+ return now && has(name);
+ };
+
+ // since we're operating under a loader that doesn't provide a has API, we must explicitly initialize
+ // has as it would have otherwise been initialized by the dojo loader; use has.add to the builder
+ // can optimize these away iff desired
+ 1 || has.add("host-browser", isBrowser);
+ 0 && has.add("host-node", (typeof process == "object" && process.versions && process.versions.node && process.versions.v8));
+ 0 && has.add("host-rhino", (typeof load == "function" && (typeof Packages == "function" || typeof Packages == "object")));
+ 1 || has.add("dom", isBrowser);
+ 1 || has.add("dojo-dom-ready-api", 1);
+ 1 || has.add("dojo-sniff", 1);
+ }
+
+ if( 1 ){
+ // Common application level tests
+ has.add("dom-addeventlistener", !!document.addEventListener);
+
+ // Do the device and browser have touch capability?
+ has.add("touch", "ontouchstart" in document
+ || ("onpointerdown" in document && navigator.maxTouchPoints > 0)
+ || window.navigator.msMaxTouchPoints);
+
+ // Touch events support
+ has.add("touch-events", "ontouchstart" in document);
+
+ // Test if pointer events are supported and enabled, with either standard names ("pointerdown" etc.) or
+ // IE specific names ("MSPointerDown" etc.). Tests are designed to work on embedded C# WebBrowser Controls
+ // in addition to IE, Edge, and future versions of Firefox and Chrome.
+ // Note that on IE11, has("pointer-events") and has("MSPointer") are both true.
+ has.add("pointer-events", "pointerEnabled" in window.navigator ?
+ window.navigator.pointerEnabled : "PointerEvent" in window);
+ has.add("MSPointer", window.navigator.msPointerEnabled);
+ // The "pointermove"" event is only continuously emitted in a touch environment if
+ // the target node's "touch-action"" CSS property is set to "none"
+ // https://www.w3.org/TR/pointerevents/#the-touch-action-css-property
+ has.add("touch-action", has("touch") && has("pointer-events"));
+
+ // I don't know if any of these tests are really correct, just a rough guess
+ has.add("device-width", screen.availWidth || innerWidth);
+
+ // Tests for DOMNode.attributes[] behavior:
+ // - dom-attributes-explicit - attributes[] only lists explicitly user specified attributes
+ // - dom-attributes-specified-flag (IE8) - need to check attr.specified flag to skip attributes user didn't specify
+ // - Otherwise, in IE6-7. attributes[] will list hundreds of values, so need to do outerHTML to get attrs instead.
+ var form = document.createElement("form");
+ has.add("dom-attributes-explicit", form.attributes.length == 0); // W3C
+ has.add("dom-attributes-specified-flag", form.attributes.length > 0 && form.attributes.length < 40); // IE8
+ }
+
+ has.clearElement = function(element){
+ // summary:
+ // Deletes the contents of the element passed to test functions.
+ element.innerHTML= "";
+ return element;
+ };
+
+ has.normalize = function(id, toAbsMid){
+ // summary:
+ // Resolves id into a module id based on possibly-nested tenary expression that branches on has feature test value(s).
+ //
+ // toAbsMid: Function
+ // Resolves a relative module id into an absolute module id
+ var
+ tokens = id.match(/[\?:]|[^:\?]*/g), i = 0,
+ get = function(skip){
+ var term = tokens[i++];
+ if(term == ":"){
+ // empty string module name, resolves to 0
+ return 0;
+ }else{
+ // postfixed with a ? means it is a feature to branch on, the term is the name of the feature
+ if(tokens[i++] == "?"){
+ if(!skip && has(term)){
+ // matched the feature, get the first value from the options
+ return get();
+ }else{
+ // did not match, get the second value, passing over the first
+ get(true);
+ return get(skip);
+ }
+ }
+ // a module
+ return term || 0;
+ }
+ };
+ id = get();
+ return id && toAbsMid(id);
+ };
+
+ has.load = function(id, parentRequire, loaded){
+ // summary:
+ // Conditional loading of AMD modules based on a has feature test value.
+ // id: String
+ // Gives the resolved module id to load.
+ // parentRequire: Function
+ // The loader require function with respect to the module that contained the plugin resource in it's
+ // dependency list.
+ // loaded: Function
+ // Callback to loader that consumes result of plugin demand.
+
+ if(id){
+ parentRequire([id], loaded);
+ }else{
+ loaded();
+ }
+ };
+
+ return has;
+});
+
+},
+'dojo/_base/config':function(){
+define(["../global", "../has", "require"], function(global, has, require){
+ // module:
+ // dojo/_base/config
+
+/*=====
+return {
+ // summary:
+ // This module defines the user configuration during bootstrap.
+ // description:
+ // By defining user configuration as a module value, an entire configuration can be specified in a build,
+ // thereby eliminating the need for sniffing and or explicitly setting in the global variable dojoConfig.
+ // Also, when multiple instances of dojo exist in a single application, each will necessarily be located
+ // at an unique absolute module identifier as given by the package configuration. Implementing configuration
+ // as a module allows for specifying unique, per-instance configurations.
+ // example:
+ // Create a second instance of dojo with a different, instance-unique configuration (assume the loader and
+ // dojo.js are already loaded).
+ // | // specify a configuration that creates a new instance of dojo at the absolute module identifier "myDojo"
+ // | require({
+ // | packages:[{
+ // | name:"myDojo",
+ // | location:".", //assume baseUrl points to dojo.js
+ // | }]
+ // | });
+ // |
+ // | // specify a configuration for the myDojo instance
+ // | define("myDojo/config", {
+ // | // normal configuration variables go here, e.g.,
+ // | locale:"fr-ca"
+ // | });
+ // |
+ // | // load and use the new instance of dojo
+ // | require(["myDojo"], function(dojo){
+ // | // dojo is the new instance of dojo
+ // | // use as required
+ // | });
+
+ // isDebug: Boolean
+ // Defaults to `false`. If set to `true`, ensures that Dojo provides
+ // extended debugging feedback to the console.
+ isDebug: false,
+
+ // locale: String
+ // The locale to assume for loading localized resources in this page,
+ // specified according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt).
+ // Must be specified entirely in lowercase, e.g. `en-us` and `zh-cn`.
+ // See the documentation for `dojo.i18n` and `dojo.requireLocalization`
+ // for details on loading localized resources. If no locale is specified,
+ // Dojo assumes the locale of the user agent, according to `navigator.userLanguage`
+ // or `navigator.language` properties.
+ locale: undefined,
+
+ // extraLocale: Array
+ // No default value. Specifies additional locales whose
+ // resources should also be loaded alongside the default locale when
+ // calls to `dojo.requireLocalization()` are processed.
+ extraLocale: undefined,
+
+ // baseUrl: String
+ // The directory in which `dojo.js` is located. Under normal
+ // conditions, Dojo auto-detects the correct location from which it
+ // was loaded. You may need to manually configure `baseUrl` in cases
+ // where you have renamed `dojo.js` or in which `` tags confuse
+ // some browsers (e.g. IE 6). The variable `dojo.baseUrl` is assigned
+ // either the value of `djConfig.baseUrl` if one is provided or the
+ // auto-detected root if not. Other modules are located relative to
+ // this path. The path should end in a slash.
+ baseUrl: undefined,
+
+ // modulePaths: [deprecated] Object
+ // A map of module names to paths relative to `dojo.baseUrl`. The
+ // key/value pairs correspond directly to the arguments which
+ // `dojo.registerModulePath` accepts. Specifying
+ // `djConfig.modulePaths = { "foo": "../../bar" }` is the equivalent
+ // of calling `dojo.registerModulePath("foo", "../../bar");`. Multiple
+ // modules may be configured via `djConfig.modulePaths`.
+ modulePaths: {},
+
+ // addOnLoad: Function|Array
+ // Adds a callback via dojo/ready. Useful when Dojo is added after
+ // the page loads and djConfig.afterOnLoad is true. Supports the same
+ // arguments as dojo/ready. When using a function reference, use
+ // `djConfig.addOnLoad = function(){};`. For object with function name use
+ // `djConfig.addOnLoad = [myObject, "functionName"];` and for object with
+ // function reference use
+ // `djConfig.addOnLoad = [myObject, function(){}];`
+ addOnLoad: null,
+
+ // parseOnLoad: Boolean
+ // Run the parser after the page is loaded
+ parseOnLoad: false,
+
+ // require: String[]
+ // An array of module names to be loaded immediately after dojo.js has been included
+ // in a page.
+ require: [],
+
+ // defaultDuration: Number
+ // Default duration, in milliseconds, for wipe and fade animations within dijits.
+ // Assigned to dijit.defaultDuration.
+ defaultDuration: 200,
+
+ // dojoBlankHtmlUrl: String
+ // Used by some modules to configure an empty iframe. Used by dojo/io/iframe and
+ // dojo/back, and dijit/popup support in IE where an iframe is needed to make sure native
+ // controls do not bleed through the popups. Normally this configuration variable
+ // does not need to be set, except when using cross-domain/CDN Dojo builds.
+ // Save dojo/resources/blank.html to your domain and set `djConfig.dojoBlankHtmlUrl`
+ // to the path on your domain your copy of blank.html.
+ dojoBlankHtmlUrl: undefined,
+
+ // ioPublish: Boolean?
+ // Set this to true to enable publishing of topics for the different phases of
+ // IO operations. Publishing is done via dojo/topic.publish(). See dojo/main.__IoPublish for a list
+ // of topics that are published.
+ ioPublish: false,
+
+ // transparentColor: Array
+ // Array containing the r, g, b components used as transparent color in dojo.Color;
+ // if undefined, [255,255,255] (white) will be used.
+ transparentColor: undefined,
+
+ // deps: Function|Array
+ // Defines dependencies to be used before the loader has been loaded.
+ // When provided, they cause the loader to execute require(deps, callback)
+ // once it has finished loading. Should be used with callback.
+ deps: undefined,
+
+ // callback: Function|Array
+ // Defines a callback to be used when dependencies are defined before
+ // the loader has been loaded. When provided, they cause the loader to
+ // execute require(deps, callback) once it has finished loading.
+ // Should be used with deps.
+ callback: undefined,
+
+ // deferredInstrumentation: Boolean
+ // Whether deferred instrumentation should be loaded or included
+ // in builds.
+ deferredInstrumentation: true,
+
+ // useDeferredInstrumentation: Boolean|String
+ // Whether the deferred instrumentation should be used.
+ //
+ // * `"report-rejections"`: report each rejection as it occurs.
+ // * `true` or `1` or `"report-unhandled-rejections"`: wait 1 second
+ // in an attempt to detect unhandled rejections.
+ useDeferredInstrumentation: "report-unhandled-rejections"
+};
+=====*/
+
+ var result = {};
+ if( 1 ){
+ // must be the dojo loader; take a shallow copy of require.rawConfig
+ var src = require.rawConfig, p;
+ for(p in src){
+ result[p] = src[p];
+ }
+ }else{
+ var adviseHas = function(featureSet, prefix, booting){
+ for(p in featureSet){
+ p!="has" && has.add(prefix + p, featureSet[p], 0, booting);
+ }
+ };
+ result = 1 ?
+ // must be a built version of the dojo loader; all config stuffed in require.rawConfig
+ require.rawConfig :
+ // a foreign loader
+ global.dojoConfig || global.djConfig || {};
+ adviseHas(result, "config", 1);
+ adviseHas(result.has, "", 1);
+ }
+
+ if(!result.locale && typeof navigator != "undefined"){
+ // Default locale for browsers (ensure it's read from user-settings not download locale).
+ var language = (navigator.languages && navigator.languages.length) ? navigator.languages[0] :
+ (navigator.language || navigator.userLanguage);
+ if(language){
+ result.locale = language.toLowerCase();
+ }
+ }
+
+ return result;
+});
+
+
+},
+'dojo/json':function(){
+define(["./has"], function(has){
+ "use strict";
+ var hasJSON = typeof JSON != "undefined";
+ has.add("json-parse", hasJSON); // all the parsers work fine
+ // Firefox 3.5/Gecko 1.9 fails to use replacer in stringify properly https://bugzilla.mozilla.org/show_bug.cgi?id=509184
+ has.add("json-stringify", hasJSON && JSON.stringify({a:0}, function(k,v){return v||1;}) == '{"a":1}');
+
+ /*=====
+ return {
+ // summary:
+ // Functions to parse and serialize JSON
+
+ parse: function(str, strict){
+ // summary:
+ // Parses a [JSON](http://json.org) string to return a JavaScript object.
+ // description:
+ // This function follows [native JSON API](https://developer.mozilla.org/en/JSON)
+ // Throws for invalid JSON strings. This delegates to eval() if native JSON
+ // support is not available. By default this will evaluate any valid JS expression.
+ // With the strict parameter set to true, the parser will ensure that only
+ // valid JSON strings are parsed (otherwise throwing an error). Without the strict
+ // parameter, the content passed to this method must come
+ // from a trusted source.
+ // str:
+ // a string literal of a JSON item, for instance:
+ // `'{ "foo": [ "bar", 1, { "baz": "thud" } ] }'`
+ // strict:
+ // When set to true, this will ensure that only valid, secure JSON is ever parsed.
+ // Make sure this is set to true for untrusted content. Note that on browsers/engines
+ // without native JSON support, setting this to true will run slower.
+ },
+ stringify: function(value, replacer, spacer){
+ // summary:
+ // Returns a [JSON](http://json.org) serialization of an object.
+ // description:
+ // Returns a [JSON](http://json.org) serialization of an object.
+ // This function follows [native JSON API](https://developer.mozilla.org/en/JSON)
+ // Note that this doesn't check for infinite recursion, so don't do that!
+ // value:
+ // A value to be serialized.
+ // replacer:
+ // A replacer function that is called for each value and can return a replacement
+ // spacer:
+ // A spacer string to be used for pretty printing of JSON
+ // example:
+ // simple serialization of a trivial object
+ // | define(["dojo/json"], function(JSON){
+ // | var jsonStr = JSON.stringify({ howdy: "stranger!", isStrange: true });
+ // | doh.is('{"howdy":"stranger!","isStrange":true}', jsonStr);
+ }
+ };
+ =====*/
+
+ if(has("json-stringify")){
+ return JSON;
+ }else{
+ var escapeString = function(/*String*/str){
+ // summary:
+ // Adds escape sequences for non-visual characters, double quote and
+ // backslash and surrounds with double quotes to form a valid string
+ // literal.
+ return ('"' + str.replace(/(["\\])/g, '\\$1') + '"').
+ replace(/[\f]/g, "\\f").replace(/[\b]/g, "\\b").replace(/[\n]/g, "\\n").
+ replace(/[\t]/g, "\\t").replace(/[\r]/g, "\\r"); // string
+ };
+ return {
+ parse: has("json-parse") ? JSON.parse : function(str, strict){
+ if(strict && !/^([\s\[\{]*(?:"(?:\\.|[^"])*"|-?\d[\d\.]*(?:[Ee][+-]?\d+)?|null|true|false|)[\s\]\}]*(?:,|:|$))+$/.test(str)){
+ throw new SyntaxError("Invalid characters in JSON");
+ }
+ return eval('(' + str + ')');
+ },
+ stringify: function(value, replacer, spacer){
+ var undef;
+ if(typeof replacer == "string"){
+ spacer = replacer;
+ replacer = null;
+ }
+ function stringify(it, indent, key){
+ if(replacer){
+ it = replacer(key, it);
+ }
+ var val, objtype = typeof it;
+ if(objtype == "number"){
+ return isFinite(it) ? it + "" : "null";
+ }
+ if(objtype == "boolean"){
+ return it + "";
+ }
+ if(it === null){
+ return "null";
+ }
+ if(typeof it == "string"){
+ return escapeString(it);
+ }
+ if(objtype == "function" || objtype == "undefined"){
+ return undef; // undefined
+ }
+ // short-circuit for objects that support "json" serialization
+ // if they return "self" then just pass-through...
+ if(typeof it.toJSON == "function"){
+ return stringify(it.toJSON(key), indent, key);
+ }
+ if(it instanceof Date){
+ return '"{FullYear}-{Month+}-{Date}T{Hours}:{Minutes}:{Seconds}Z"'.replace(/\{(\w+)(\+)?\}/g, function(t, prop, plus){
+ var num = it["getUTC" + prop]() + (plus ? 1 : 0);
+ return num < 10 ? "0" + num : num;
+ });
+ }
+ if(it.valueOf() !== it){
+ // primitive wrapper, try again unwrapped:
+ return stringify(it.valueOf(), indent, key);
+ }
+ var nextIndent= spacer ? (indent + spacer) : "";
+ /* we used to test for DOM nodes and throw, but FF serializes them as {}, so cross-browser consistency is probably not efficiently attainable */
+
+ var sep = spacer ? " " : "";
+ var newLine = spacer ? "\n" : "";
+
+ // array
+ if(it instanceof Array){
+ var itl = it.length, res = [];
+ for(key = 0; key < itl; key++){
+ var obj = it[key];
+ val = stringify(obj, nextIndent, key);
+ if(typeof val != "string"){
+ val = "null";
+ }
+ res.push(newLine + nextIndent + val);
+ }
+ return "[" + res.join(",") + newLine + indent + "]";
+ }
+ // generic object code path
+ var output = [];
+ for(key in it){
+ var keyStr;
+ if(it.hasOwnProperty(key)){
+ if(typeof key == "number"){
+ keyStr = '"' + key + '"';
+ }else if(typeof key == "string"){
+ keyStr = escapeString(key);
+ }else{
+ // skip non-string or number keys
+ continue;
+ }
+ val = stringify(it[key], nextIndent, key);
+ if(typeof val != "string"){
+ // skip non-serializable values
+ continue;
+ }
+ // At this point, the most non-IE browsers don't get in this branch
+ // (they have native JSON), so push is definitely the way to
+ output.push(newLine + nextIndent + keyStr + ":" + sep + val);
+ }
+ }
+ return "{" + output.join(",") + newLine + indent + "}"; // String
+ }
+ return stringify(value, "", "");
+ }
+ };
+ }
+});
+
+},
+'dojo/_base/lang':function(){
+define(["./kernel", "../has", "../sniff"], function(dojo, has){
+ // module:
+ // dojo/_base/lang
+
+ has.add("bug-for-in-skips-shadowed", function(){
+ // if true, the for-in iterator skips object properties that exist in Object's prototype (IE 6 - ?)
+ for(var i in {toString: 1}){
+ return 0;
+ }
+ return 1;
+ });
+
+ // Helper methods
+ var _extraNames =
+ has("bug-for-in-skips-shadowed") ?
+ "hasOwnProperty.valueOf.isPrototypeOf.propertyIsEnumerable.toLocaleString.toString.constructor".split(".") : [],
+
+ _extraLen = _extraNames.length,
+
+ getProp = function(/*Array*/parts, /*Boolean*/create, /*Object*/context){
+ if(!context){
+ if(parts[0] && dojo.scopeMap[parts[0]]) {
+ // Voodoo code from the old days where "dojo" or "dijit" maps to some special object
+ // rather than just window.dojo
+ context = dojo.scopeMap[parts.shift()][1];
+ }else{
+ context = dojo.global;
+ }
+ }
+
+ try{
+ for(var i = 0; i < parts.length; i++){
+ var p = parts[i];
+ // Fix for prototype pollution CVE-2021-23450
+ if (p === '__proto__' || p === 'constructor') {
+ return;
+ }
+ if(!(p in context)){
+ if(create){
+ context[p] = {};
+ }else{
+ return; // return undefined
+ }
+ }
+ context = context[p];
+ }
+ return context; // mixed
+ }catch(e){
+ // "p in context" throws an exception when context is a number, boolean, etc. rather than an object,
+ // so in that corner case just return undefined (by having no return statement)
+ }
+ },
+
+ opts = Object.prototype.toString,
+
+ efficient = function(obj, offset, startWith){
+ return (startWith||[]).concat(Array.prototype.slice.call(obj, offset||0));
+ },
+
+ _pattern = /\{([^\}]+)\}/g;
+
+ // Module export
+ var lang = {
+ // summary:
+ // This module defines Javascript language extensions.
+
+ // _extraNames: String[]
+ // Lists property names that must be explicitly processed during for-in iteration
+ // in environments that have has("bug-for-in-skips-shadowed") true.
+ _extraNames:_extraNames,
+
+ _mixin: function(dest, source, copyFunc){
+ // summary:
+ // Copies/adds all properties of source to dest; returns dest.
+ // dest: Object
+ // The object to which to copy/add all properties contained in source.
+ // source: Object
+ // The object from which to draw all properties to copy into dest.
+ // copyFunc: Function?
+ // The process used to copy/add a property in source; defaults to the Javascript assignment operator.
+ // returns:
+ // dest, as modified
+ // description:
+ // All properties, including functions (sometimes termed "methods"), excluding any non-standard extensions
+ // found in Object.prototype, are copied/added to dest. Copying/adding each particular property is
+ // delegated to copyFunc (if any); copyFunc defaults to the Javascript assignment operator if not provided.
+ // Notice that by default, _mixin executes a so-called "shallow copy" and aggregate types are copied/added by reference.
+ var name, s, i, empty = {};
+ for(name in source){
+ // the (!(name in empty) || empty[name] !== s) condition avoids copying properties in "source"
+ // inherited from Object.prototype. For example, if dest has a custom toString() method,
+ // don't overwrite it with the toString() method that source inherited from Object.prototype
+ s = source[name];
+ if(!(name in dest) || (dest[name] !== s && (!(name in empty) || empty[name] !== s))){
+ dest[name] = copyFunc ? copyFunc(s) : s;
+ }
+ }
+
+ if(has("bug-for-in-skips-shadowed")){
+ if(source){
+ for(i = 0; i < _extraLen; ++i){
+ name = _extraNames[i];
+ s = source[name];
+ if(!(name in dest) || (dest[name] !== s && (!(name in empty) || empty[name] !== s))){
+ dest[name] = copyFunc ? copyFunc(s) : s;
+ }
+ }
+ }
+ }
+
+ return dest; // Object
+ },
+
+ mixin: function(dest, sources){
+ // summary:
+ // Copies/adds all properties of one or more sources to dest; returns dest.
+ // dest: Object
+ // The object to which to copy/add all properties contained in source. If dest is falsy, then
+ // a new object is manufactured before copying/adding properties begins.
+ // sources: Object...
+ // One of more objects from which to draw all properties to copy into dest. sources are processed
+ // left-to-right and if more than one of these objects contain the same property name, the right-most
+ // value "wins".
+ // returns: Object
+ // dest, as modified
+ // description:
+ // All properties, including functions (sometimes termed "methods"), excluding any non-standard extensions
+ // found in Object.prototype, are copied/added from sources to dest. sources are processed left to right.
+ // The Javascript assignment operator is used to copy/add each property; therefore, by default, mixin
+ // executes a so-called "shallow copy" and aggregate types are copied/added by reference.
+ // example:
+ // make a shallow copy of an object
+ // | var copy = lang.mixin({}, source);
+ // example:
+ // many class constructors often take an object which specifies
+ // values to be configured on the object. In this case, it is
+ // often simplest to call `lang.mixin` on the `this` object:
+ // | declare("acme.Base", null, {
+ // | constructor: function(properties){
+ // | // property configuration:
+ // | lang.mixin(this, properties);
+ // |
+ // | console.log(this.quip);
+ // | // ...
+ // | },
+ // | quip: "I wasn't born yesterday, you know - I've seen movies.",
+ // | // ...
+ // | });
+ // |
+ // | // create an instance of the class and configure it
+ // | var b = new acme.Base({quip: "That's what it does!" });
+ // example:
+ // copy in properties from multiple objects
+ // | var flattened = lang.mixin(
+ // | {
+ // | name: "Frylock",
+ // | braces: true
+ // | },
+ // | {
+ // | name: "Carl Brutanananadilewski"
+ // | }
+ // | );
+ // |
+ // | // will print "Carl Brutanananadilewski"
+ // | console.log(flattened.name);
+ // | // will print "true"
+ // | console.log(flattened.braces);
+
+ if(!dest){ dest = {}; }
+ for(var i = 1, l = arguments.length; i < l; i++){
+ lang._mixin(dest, arguments[i]);
+ }
+ return dest; // Object
+ },
+
+ setObject: function(name, value, context){
+ // summary:
+ // Set a property from a dot-separated string, such as "A.B.C"
+ // description:
+ // Useful for longer api chains where you have to test each object in
+ // the chain, or when you have an object reference in string format.
+ // Objects are created as needed along `path`. Returns the passed
+ // value if setting is successful or `undefined` if not.
+ // name: String
+ // Path to a property, in the form "A.B.C".
+ // value: anything
+ // value or object to place at location given by name
+ // context: Object?
+ // Optional. Object to use as root of path. Defaults to
+ // `dojo.global`.
+ // example:
+ // set the value of `foo.bar.baz`, regardless of whether
+ // intermediate objects already exist:
+ // | lang.setObject("foo.bar.baz", value);
+ // example:
+ // without `lang.setObject`, we often see code like this:
+ // | // ensure that intermediate objects are available
+ // | if(!obj["parent"]){ obj.parent = {}; }
+ // | if(!obj.parent["child"]){ obj.parent.child = {}; }
+ // | // now we can safely set the property
+ // | obj.parent.child.prop = "some value";
+ // whereas with `lang.setObject`, we can shorten that to:
+ // | lang.setObject("parent.child.prop", "some value", obj);
+
+ var parts = name.split("."), p = parts.pop(), obj = getProp(parts, true, context);
+ return obj && p ? (obj[p] = value) : undefined; // Object
+ },
+
+ getObject: function(name, create, context){
+ // summary:
+ // Get a property from a dot-separated string, such as "A.B.C"
+ // description:
+ // Useful for longer api chains where you have to test each object in
+ // the chain, or when you have an object reference in string format.
+ // name: String
+ // Path to an property, in the form "A.B.C".
+ // create: Boolean?
+ // Optional. Defaults to `false`. If `true`, Objects will be
+ // created at any point along the 'path' that is undefined.
+ // context: Object?
+ // Optional. Object to use as root of path. Defaults to
+ // 'dojo.global'. Null may be passed.
+ return !name ? context : getProp(name.split("."), create, context); // Object
+ },
+
+ exists: function(name, obj){
+ // summary:
+ // determine if an object supports a given method
+ // description:
+ // useful for longer api chains where you have to test each object in
+ // the chain. Useful for object and method detection.
+ // name: String
+ // Path to an object, in the form "A.B.C".
+ // obj: Object?
+ // Object to use as root of path. Defaults to
+ // 'dojo.global'. Null may be passed.
+ // example:
+ // | // define an object
+ // | var foo = {
+ // | bar: { }
+ // | };
+ // |
+ // | // search the global scope
+ // | lang.exists("foo.bar"); // true
+ // | lang.exists("foo.bar.baz"); // false
+ // |
+ // | // search from a particular scope
+ // | lang.exists("bar", foo); // true
+ // | lang.exists("bar.baz", foo); // false
+ return lang.getObject(name, false, obj) !== undefined; // Boolean
+ },
+
+ // Crockford (ish) functions
+
+ isString: function(it){
+ // summary:
+ // Return true if it is a String
+ // it: anything
+ // Item to test.
+ return (typeof it == "string" || it instanceof String); // Boolean
+ },
+
+ isArray: Array.isArray || function(it){
+ // summary:
+ // Return true if it is an Array.
+ // it: anything
+ // Item to test.
+ return opts.call(it) == "[object Array]"; // Boolean
+ },
+
+ isFunction: function(it){
+ // summary:
+ // Return true if it is a Function
+ // it: anything
+ // Item to test.
+ return opts.call(it) === "[object Function]";
+ },
+
+ isObject: function(it){
+ // summary:
+ // Returns true if it is a JavaScript object (or an Array, a Function
+ // or null)
+ // it: anything
+ // Item to test.
+ return it !== undefined &&
+ (it === null || typeof it == "object" || lang.isArray(it) || lang.isFunction(it)); // Boolean
+ },
+
+ isArrayLike: function(it){
+ // summary:
+ // similar to isArray() but more permissive
+ // it: anything
+ // Item to test.
+ // returns:
+ // If it walks like a duck and quacks like a duck, return `true`
+ // description:
+ // Doesn't strongly test for "arrayness". Instead, settles for "isn't
+ // a string or number and has a length property". Arguments objects
+ // and DOM collections will return true when passed to
+ // isArrayLike(), but will return false when passed to
+ // isArray().
+ return !!it && // Boolean
+ // keep out built-in constructors (Number, String, ...) which have length
+ // properties
+ !lang.isString(it) && !lang.isFunction(it) &&
+ !(it.tagName && it.tagName.toLowerCase() == 'form') &&
+ (lang.isArray(it) || isFinite(it.length));
+ },
+
+ isAlien: function(it){
+ // summary:
+ // Returns true if it is a built-in function or some other kind of
+ // oddball that *should* report as a function but doesn't
+ return it && !lang.isFunction(it) && /\{\s*\[native code\]\s*\}/.test(String(it)); // Boolean
+ },
+
+ extend: function(ctor, props){
+ // summary:
+ // Adds all properties and methods of props to constructor's
+ // prototype, making them available to all instances created with
+ // constructor.
+ // ctor: Object
+ // Target constructor to extend.
+ // props: Object
+ // One or more objects to mix into ctor.prototype
+ for(var i=1, l=arguments.length; i 2){
+ return lang._hitchArgs.apply(dojo, arguments); // Function
+ }
+ if(!method){
+ method = scope;
+ scope = null;
+ }
+ if(lang.isString(method)){
+ scope = scope || dojo.global;
+ if(!scope[method]){ throw(['lang.hitch: scope["', method, '"] is null (scope="', scope, '")'].join('')); }
+ return function(){ return scope[method].apply(scope, arguments || []); }; // Function
+ }
+ return !scope ? method : function(){ return method.apply(scope, arguments || []); }; // Function
+ },
+
+ delegate: (function(){
+ // boodman/crockford delegation w/ cornford optimization
+ function TMP(){}
+ return function(obj, props){
+ TMP.prototype = obj;
+ var tmp = new TMP();
+ TMP.prototype = null;
+ if(props){
+ lang._mixin(tmp, props);
+ }
+ return tmp; // Object
+ };
+ })(),
+ /*=====
+ delegate: function(obj, props){
+ // summary:
+ // Returns a new object which "looks" to obj for properties which it
+ // does not have a value for. Optionally takes a bag of properties to
+ // seed the returned object with initially.
+ // description:
+ // This is a small implementation of the Boodman/Crockford delegation
+ // pattern in JavaScript. An intermediate object constructor mediates
+ // the prototype chain for the returned object, using it to delegate
+ // down to obj for property lookup when object-local lookup fails.
+ // This can be thought of similarly to ES4's "wrap", save that it does
+ // not act on types but rather on pure objects.
+ // obj: Object
+ // The object to delegate to for properties not found directly on the
+ // return object or in props.
+ // props: Object...
+ // an object containing properties to assign to the returned object
+ // returns:
+ // an Object of anonymous type
+ // example:
+ // | var foo = { bar: "baz" };
+ // | var thinger = lang.delegate(foo, { thud: "xyzzy"});
+ // | thinger.bar == "baz"; // delegated to foo
+ // | foo.thud == undefined; // by definition
+ // | thinger.thud == "xyzzy"; // mixed in from props
+ // | foo.bar = "thonk";
+ // | thinger.bar == "thonk"; // still delegated to foo's bar
+ },
+ =====*/
+
+ _toArray: has("ie") ?
+ (function(){
+ function slow(obj, offset, startWith){
+ var arr = startWith||[];
+ for(var x = offset || 0; x < obj.length; x++){
+ arr.push(obj[x]);
+ }
+ return arr;
+ }
+ return function(obj){
+ return ((obj.item) ? slow : efficient).apply(this, arguments);
+ };
+ })() : efficient,
+ /*=====
+ _toArray: function(obj, offset, startWith){
+ // summary:
+ // Converts an array-like object (i.e. arguments, DOMCollection) to an
+ // array. Returns a new Array with the elements of obj.
+ // obj: Object
+ // the object to "arrayify". We expect the object to have, at a
+ // minimum, a length property which corresponds to integer-indexed
+ // properties.
+ // offset: Number?
+ // the location in obj to start iterating from. Defaults to 0.
+ // Optional.
+ // startWith: Array?
+ // An array to pack with the properties of obj. If provided,
+ // properties in obj are appended at the end of startWith and
+ // startWith is the returned array.
+ },
+ =====*/
+
+ partial: function(/*Function|String*/ method /*, ...*/){
+ // summary:
+ // similar to hitch() except that the scope object is left to be
+ // whatever the execution context eventually becomes.
+ // description:
+ // Calling lang.partial is the functional equivalent of calling:
+ // | lang.hitch(null, funcName, ...);
+ // method:
+ // The function to "wrap"
+ var arr = [ null ];
+ return lang.hitch.apply(dojo, arr.concat(lang._toArray(arguments))); // Function
+ },
+
+ clone: function(/*anything*/ src){
+ // summary:
+ // Clones objects (including DOM nodes) and all children.
+ // Warning: do not clone cyclic structures.
+ // src:
+ // The object to clone
+ if(!src || typeof src != "object" || lang.isFunction(src)){
+ // null, undefined, any non-object, or function
+ return src; // anything
+ }
+ if(src.nodeType && "cloneNode" in src){
+ // DOM Node
+ return src.cloneNode(true); // Node
+ }
+ if(src instanceof Date){
+ // Date
+ return new Date(src.getTime()); // Date
+ }
+ if(src instanceof RegExp){
+ // RegExp
+ return new RegExp(src); // RegExp
+ }
+ var r, i, l;
+ if(lang.isArray(src)){
+ // array
+ r = [];
+ for(i = 0, l = src.length; i < l; ++i){
+ if(i in src){
+ r[i] = lang.clone(src[i]);
+ }
+ }
+ // we don't clone functions for performance reasons
+ // }else if(d.isFunction(src)){
+ // // function
+ // r = function(){ return src.apply(this, arguments); };
+ }else{
+ // generic objects
+ r = src.constructor ? new src.constructor() : {};
+ }
+ return lang._mixin(r, src, lang.clone);
+ },
+
+
+ trim: String.prototype.trim ?
+ function(str){ return str.trim(); } :
+ function(str){ return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); },
+ /*=====
+ trim: function(str){
+ // summary:
+ // Trims whitespace from both sides of the string
+ // str: String
+ // String to be trimmed
+ // returns: String
+ // Returns the trimmed string
+ // description:
+ // This version of trim() was selected for inclusion into the base due
+ // to its compact size and relatively good performance
+ // (see [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript)
+ // Uses String.prototype.trim instead, if available.
+ // The fastest but longest version of this function is located at
+ // lang.string.trim()
+ },
+ =====*/
+
+ replace: function(tmpl, map, pattern){
+ // summary:
+ // Performs parameterized substitutions on a string. Throws an
+ // exception if any parameter is unmatched.
+ // tmpl: String
+ // String to be used as a template.
+ // map: Object|Function
+ // If an object, it is used as a dictionary to look up substitutions.
+ // If a function, it is called for every substitution with following parameters:
+ // a whole match, a name, an offset, and the whole template
+ // string (see https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/String/replace
+ // for more details).
+ // pattern: RegEx?
+ // Optional regular expression objects that overrides the default pattern.
+ // Must be global and match one item. The default is: /\{([^\}]+)\}/g,
+ // which matches patterns like that: "{xxx}", where "xxx" is any sequence
+ // of characters, which doesn't include "}".
+ // returns: String
+ // Returns the substituted string.
+ // example:
+ // | // uses a dictionary for substitutions:
+ // | lang.replace("Hello, {name.first} {name.last} AKA {nick}!",
+ // | {
+ // | nick: "Bob",
+ // | name: {
+ // | first: "Robert",
+ // | middle: "X",
+ // | last: "Cringely"
+ // | }
+ // | });
+ // | // returns: Hello, Robert Cringely AKA Bob!
+ // example:
+ // | // uses an array for substitutions:
+ // | lang.replace("Hello, {0} {2}!",
+ // | ["Robert", "X", "Cringely"]);
+ // | // returns: Hello, Robert Cringely!
+ // example:
+ // | // uses a function for substitutions:
+ // | function sum(a){
+ // | var t = 0;
+ // | arrayforEach(a, function(x){ t += x; });
+ // | return t;
+ // | }
+ // | lang.replace(
+ // | "{count} payments averaging {avg} USD per payment.",
+ // | lang.hitch(
+ // | { payments: [11, 16, 12] },
+ // | function(_, key){
+ // | switch(key){
+ // | case "count": return this.payments.length;
+ // | case "min": return Math.min.apply(Math, this.payments);
+ // | case "max": return Math.max.apply(Math, this.payments);
+ // | case "sum": return sum(this.payments);
+ // | case "avg": return sum(this.payments) / this.payments.length;
+ // | }
+ // | }
+ // | )
+ // | );
+ // | // prints: 3 payments averaging 13 USD per payment.
+ // example:
+ // | // uses an alternative PHP-like pattern for substitutions:
+ // | lang.replace("Hello, ${0} ${2}!",
+ // | ["Robert", "X", "Cringely"], /\$\{([^\}]+)\}/g);
+ // | // returns: Hello, Robert Cringely!
+
+ return tmpl.replace(pattern || _pattern, lang.isFunction(map) ?
+ map : function(_, k){ return lang.getObject(k, false, map); });
+ }
+ };
+
+ 1 && lang.mixin(dojo, lang);
+
+ return lang;
+});
+
+},
+'dojo/sniff':function(){
+define(["./has"], function(has){
+ // module:
+ // dojo/sniff
+
+ /*=====
+ return function(){
+ // summary:
+ // This module sets has() flags based on the current browser.
+ // It returns the has() function.
+ };
+ =====*/
+
+ if( 1 ){
+ var n = navigator,
+ dua = n.userAgent,
+ dav = n.appVersion,
+ tv = parseFloat(dav);
+ has.add("air", dua.indexOf("AdobeAIR") >= 0);
+ has.add("wp", parseFloat(dua.split("Windows Phone")[1]) || undefined);
+ has.add("msapp", parseFloat(dua.split("MSAppHost/")[1]) || undefined);
+ has.add("khtml", dav.indexOf("Konqueror") >= 0 ? tv : undefined);
+ has.add("edge", parseFloat(dua.split("Edge/")[1]) || undefined);
+ has.add("opr", parseFloat(dua.split("OPR/")[1]) || undefined);
+ // NOTE: https://dev.opera.com/blog/opera-user-agent-strings-opera-15-and-beyond/
+ has.add("webkit", !has("wp") // NOTE: necessary since Windows Phone 8.1 Update 1, see #18540
+ && !has("edge") && parseFloat(dua.split("WebKit/")[1]) || undefined);
+ has.add("chrome", !has("edge") && !has("opr")
+ && parseFloat(dua.split("Chrome/")[1]) || undefined);
+ has.add("android", !has("wp") // NOTE: necessary since Windows Phone 8.1 Update 1, see #18528
+ && parseFloat(dua.split("Android ")[1]) || undefined);
+ has.add("safari", dav.indexOf("Safari") >= 0
+ && !has("wp") // NOTE: necessary since Windows Phone 8.1 Update 1, see #18540
+ && !has("chrome") && !has("android") && !has("edge") && !has("opr") ?
+ parseFloat(dav.split("Version/")[1]) : undefined);
+ has.add("mac", dav.indexOf("Macintosh") >= 0);
+ has.add("quirks", document.compatMode == "BackCompat");
+ if(!has("wp") // NOTE: necessary since Windows Phone 8.1 Update 1, see #18528
+ && dua.match(/(iPhone|iPod|iPad)/)){
+ var p = RegExp.$1.replace(/P/, "p");
+ var v = dua.match(/OS ([\d_]+)/) ? RegExp.$1 : "1";
+ var os = parseFloat(v.replace(/_/, ".").replace(/_/g, ""));
+ has.add(p, os); // "iphone", "ipad" or "ipod"
+ has.add("ios", os);
+ }
+ has.add("bb", (dua.indexOf("BlackBerry") >= 0 || dua.indexOf("BB10") >= 0) && parseFloat(dua.split("Version/")[1]) || undefined);
+ has.add("trident", parseFloat(dav.split("Trident/")[1]) || undefined);
+
+ has.add("svg", typeof SVGAngle !== "undefined");
+
+ if(!has("webkit")){
+ // Opera
+ if(dua.indexOf("Opera") >= 0){
+ // see http://dev.opera.com/articles/view/opera-ua-string-changes and http://www.useragentstring.com/pages/Opera/
+ // 9.8 has both styles; <9.8, 9.9 only old style
+ has.add("opera", tv >= 9.8 ? parseFloat(dua.split("Version/")[1]) || tv : tv);
+ }
+
+ // Mozilla and firefox
+ if(dua.indexOf("Gecko") >= 0 && !has("wp") // NOTE: necessary since Windows Phone 8.1 Update 1
+ && !has("khtml") && !has("trident") && !has("edge")){
+ has.add("mozilla", tv);
+ }
+ if(has("mozilla")){
+ //We really need to get away from this. Consider a sane isGecko approach for the future.
+ has.add("ff", parseFloat(dua.split("Firefox/")[1] || dua.split("Minefield/")[1]) || undefined);
+ }
+
+ // IE
+ if(document.all && !has("opera")){
+ var isIE = parseFloat(dav.split("MSIE ")[1]) || undefined;
+
+ //In cases where the page has an HTTP header or META tag with
+ //X-UA-Compatible, then it is in emulation mode.
+ //Make sure isIE reflects the desired version.
+ //document.documentMode of 5 means quirks mode.
+ //Only switch the value if documentMode's major version
+ //is different from isIE's major version.
+ var mode = document.documentMode;
+ if(mode && mode != 5 && Math.floor(isIE) != mode){
+ isIE = mode;
+ }
+
+ has.add("ie", isIE);
+ }
+
+ // Wii
+ has.add("wii", typeof opera != "undefined" && opera.wiiremote);
+ }
+ }
+
+ return has;
+});
+
+},
+'dojo/_base/array':function(){
+define(["./kernel", "../has", "./lang"], function(dojo, has, lang){
+ // module:
+ // dojo/_base/array
+
+ // our old simple function builder stuff
+ var cache = {}, u;
+
+ var buildFn;
+ if(!has("csp-restrictions")){
+ buildFn = function (fn){
+ return cache[fn] = new Function("item", "index", "array", fn); // Function
+ };
+ }
+
+ // magic snippet: if(typeof fn == "string") fn = cache[fn] || buildFn(fn);
+
+ // every & some
+
+ function everyOrSome(some){
+ var every = !some;
+ return function(a, fn, o){
+ var i = 0, l = a && a.length || 0, result;
+ if(l && typeof a == "string") a = a.split("");
+ if(typeof fn == "string"){
+ if(has("csp-restrictions")){
+ throw new TypeError("callback must be a function");
+ }
+ else{
+ fn = cache[fn] || buildFn(fn);
+ }
+ }
+ if(o){
+ for(; i < l; ++i){
+ result = !fn.call(o, a[i], i, a);
+ if(some ^ result){
+ return !result;
+ }
+ }
+ }else{
+ for(; i < l; ++i){
+ result = !fn(a[i], i, a);
+ if(some ^ result){
+ return !result;
+ }
+ }
+ }
+ return every; // Boolean
+ };
+ }
+
+ // indexOf, lastIndexOf
+
+ function index(up){
+ var delta = 1, lOver = 0, uOver = 0;
+ if(!up){
+ delta = lOver = uOver = -1;
+ }
+ return function(a, x, from, last){
+ if(last && delta > 0){
+ // TODO: why do we use a non-standard signature? why do we need "last"?
+ return array.lastIndexOf(a, x, from);
+ }
+ var l = a && a.length || 0, end = up ? l + uOver : lOver, i;
+ if(from === u){
+ i = up ? lOver : l + uOver;
+ }else{
+ if(from < 0){
+ i = l + from;
+ if(i < 0){
+ i = lOver;
+ }
+ }else{
+ i = from >= l ? l + uOver : from;
+ }
+ }
+ if(l && typeof a == "string") a = a.split("");
+ for(; i != end; i += delta){
+ if(a[i] == x){
+ return i; // Number
+ }
+ }
+ return -1; // Number
+ };
+ }
+
+ var array = {
+ // summary:
+ // The Javascript v1.6 array extensions.
+
+ every: everyOrSome(false),
+ /*=====
+ every: function(arr, callback, thisObject){
+ // summary:
+ // Determines whether or not every item in arr satisfies the
+ // condition implemented by callback.
+ // arr: Array|String
+ // the array to iterate on. If a string, operates on individual characters.
+ // callback: Function|String
+ // a function is invoked with three arguments: item, index,
+ // and array and returns true if the condition is met.
+ // thisObject: Object?
+ // may be used to scope the call to callback
+ // returns: Boolean
+ // description:
+ // This function corresponds to the JavaScript 1.6 Array.every() method, with one difference: when
+ // run over sparse arrays, this implementation passes the "holes" in the sparse array to
+ // the callback function with a value of undefined. JavaScript 1.6's every skips the holes in the sparse array.
+ // For more details, see:
+ // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/every
+ // example:
+ // | // returns false
+ // | array.every([1, 2, 3, 4], function(item){ return item>1; });
+ // example:
+ // | // returns true
+ // | array.every([1, 2, 3, 4], function(item){ return item>0; });
+ },
+ =====*/
+
+ some: everyOrSome(true),
+ /*=====
+ some: function(arr, callback, thisObject){
+ // summary:
+ // Determines whether or not any item in arr satisfies the
+ // condition implemented by callback.
+ // arr: Array|String
+ // the array to iterate over. If a string, operates on individual characters.
+ // callback: Function|String
+ // a function is invoked with three arguments: item, index,
+ // and array and returns true if the condition is met.
+ // thisObject: Object?
+ // may be used to scope the call to callback
+ // returns: Boolean
+ // description:
+ // This function corresponds to the JavaScript 1.6 Array.some() method, with one difference: when
+ // run over sparse arrays, this implementation passes the "holes" in the sparse array to
+ // the callback function with a value of undefined. JavaScript 1.6's some skips the holes in the sparse array.
+ // For more details, see:
+ // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/some
+ // example:
+ // | // is true
+ // | array.some([1, 2, 3, 4], function(item){ return item>1; });
+ // example:
+ // | // is false
+ // | array.some([1, 2, 3, 4], function(item){ return item<1; });
+ },
+ =====*/
+
+ indexOf: index(true),
+ /*=====
+ indexOf: function(arr, value, fromIndex, findLast){
+ // summary:
+ // locates the first index of the provided value in the
+ // passed array. If the value is not found, -1 is returned.
+ // description:
+ // This method corresponds to the JavaScript 1.6 Array.indexOf method, with two differences:
+ //
+ // 1. when run over sparse arrays, the Dojo function invokes the callback for every index
+ // whereas JavaScript 1.6's indexOf skips the holes in the sparse array.
+ // 2. uses equality (==) rather than strict equality (===)
+ //
+ // For details on this method, see:
+ // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/indexOf
+ // arr: Array
+ // value: Object
+ // fromIndex: Integer?
+ // findLast: Boolean?
+ // Makes indexOf() work like lastIndexOf(). Used internally; not meant for external usage.
+ // returns: Number
+ },
+ =====*/
+
+ lastIndexOf: index(false),
+ /*=====
+ lastIndexOf: function(arr, value, fromIndex){
+ // summary:
+ // locates the last index of the provided value in the passed
+ // array. If the value is not found, -1 is returned.
+ // description:
+ // This method corresponds to the JavaScript 1.6 Array.lastIndexOf method, with two differences:
+ //
+ // 1. when run over sparse arrays, the Dojo function invokes the callback for every index
+ // whereas JavaScript 1.6's lasIndexOf skips the holes in the sparse array.
+ // 2. uses equality (==) rather than strict equality (===)
+ //
+ // For details on this method, see:
+ // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/lastIndexOf
+ // arr: Array,
+ // value: Object,
+ // fromIndex: Integer?
+ // returns: Number
+ },
+ =====*/
+
+ forEach: function(arr, callback, thisObject){
+ // summary:
+ // for every item in arr, callback is invoked. Return values are ignored.
+ // If you want to break out of the loop, consider using array.every() or array.some().
+ // forEach does not allow breaking out of the loop over the items in arr.
+ // arr:
+ // the array to iterate over. If a string, operates on individual characters.
+ // callback:
+ // a function is invoked with three arguments: item, index, and array
+ // thisObject:
+ // may be used to scope the call to callback
+ // description:
+ // This function corresponds to the JavaScript 1.6 Array.forEach() method, with one difference: when
+ // run over sparse arrays, this implementation passes the "holes" in the sparse array to
+ // the callback function with a value of undefined. JavaScript 1.6's forEach skips the holes in the sparse array.
+ // For more details, see:
+ // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/forEach
+ // example:
+ // | // log out all members of the array:
+ // | array.forEach(
+ // | [ "thinger", "blah", "howdy", 10 ],
+ // | function(item){
+ // | console.log(item);
+ // | }
+ // | );
+ // example:
+ // | // log out the members and their indexes
+ // | array.forEach(
+ // | [ "thinger", "blah", "howdy", 10 ],
+ // | function(item, idx, arr){
+ // | console.log(item, "at index:", idx);
+ // | }
+ // | );
+ // example:
+ // | // use a scoped object member as the callback
+ // |
+ // | var obj = {
+ // | prefix: "logged via obj.callback:",
+ // | callback: function(item){
+ // | console.log(this.prefix, item);
+ // | }
+ // | };
+ // |
+ // | // specifying the scope function executes the callback in that scope
+ // | array.forEach(
+ // | [ "thinger", "blah", "howdy", 10 ],
+ // | obj.callback,
+ // | obj
+ // | );
+ // |
+ // | // alternately, we can accomplish the same thing with lang.hitch()
+ // | array.forEach(
+ // | [ "thinger", "blah", "howdy", 10 ],
+ // | lang.hitch(obj, "callback")
+ // | );
+ // arr: Array|String
+ // callback: Function|String
+ // thisObject: Object?
+
+ var i = 0, l = arr && arr.length || 0;
+ if(l && typeof arr == "string") arr = arr.split("");
+ if(typeof callback == "string"){
+ if(has("csp-restrictions")){
+ throw new TypeError("callback must be a function");
+ }
+ else{
+ callback = cache[callback] || buildFn(callback);
+ }
+ }
+ if(thisObject){
+ for(; i < l; ++i){
+ callback.call(thisObject, arr[i], i, arr);
+ }
+ }else{
+ for(; i < l; ++i){
+ callback(arr[i], i, arr);
+ }
+ }
+ },
+
+ map: function(arr, callback, thisObject, Ctr){
+ // summary:
+ // applies callback to each element of arr and returns
+ // an Array with the results
+ // arr: Array|String
+ // the array to iterate on. If a string, operates on
+ // individual characters.
+ // callback: Function|String
+ // a function is invoked with three arguments, (item, index,
+ // array), and returns a value
+ // thisObject: Object?
+ // may be used to scope the call to callback
+ // returns: Array
+ // description:
+ // This function corresponds to the JavaScript 1.6 Array.map() method, with one difference: when
+ // run over sparse arrays, this implementation passes the "holes" in the sparse array to
+ // the callback function with a value of undefined. JavaScript 1.6's map skips the holes in the sparse array.
+ // For more details, see:
+ // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
+ // example:
+ // | // returns [2, 3, 4, 5]
+ // | array.map([1, 2, 3, 4], function(item){ return item+1 });
+
+ // TODO: why do we have a non-standard signature here? do we need "Ctr"?
+ var i = 0, l = arr && arr.length || 0, out = new (Ctr || Array)(l);
+ if(l && typeof arr == "string") arr = arr.split("");
+ if(typeof callback == "string"){
+ if(has("csp-restrictions")){
+ throw new TypeError("callback must be a function");
+ }
+ else{
+ callback = cache[callback] || buildFn(callback);
+ }
+ }
+ if(thisObject){
+ for(; i < l; ++i){
+ out[i] = callback.call(thisObject, arr[i], i, arr);
+ }
+ }else{
+ for(; i < l; ++i){
+ out[i] = callback(arr[i], i, arr);
+ }
+ }
+ return out; // Array
+ },
+
+ filter: function(arr, callback, thisObject){
+ // summary:
+ // Returns a new Array with those items from arr that match the
+ // condition implemented by callback.
+ // arr: Array
+ // the array to iterate over.
+ // callback: Function|String
+ // a function that is invoked with three arguments (item,
+ // index, array). The return of this function is expected to
+ // be a boolean which determines whether the passed-in item
+ // will be included in the returned array.
+ // thisObject: Object?
+ // may be used to scope the call to callback
+ // returns: Array
+ // description:
+ // This function corresponds to the JavaScript 1.6 Array.filter() method, with one difference: when
+ // run over sparse arrays, this implementation passes the "holes" in the sparse array to
+ // the callback function with a value of undefined. JavaScript 1.6's filter skips the holes in the sparse array.
+ // For more details, see:
+ // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
+ // example:
+ // | // returns [2, 3, 4]
+ // | array.filter([1, 2, 3, 4], function(item){ return item>1; });
+
+ // TODO: do we need "Ctr" here like in map()?
+ var i = 0, l = arr && arr.length || 0, out = [], value;
+ if(l && typeof arr == "string") arr = arr.split("");
+ if(typeof callback == "string"){
+ if(has("csp-restrictions")){
+ throw new TypeError("callback must be a function");
+ }
+ else{
+ callback = cache[callback] || buildFn(callback);
+ }
+ }
+ if(thisObject){
+ for(; i < l; ++i){
+ value = arr[i];
+ if(callback.call(thisObject, value, i, arr)){
+ out.push(value);
+ }
+ }
+ }else{
+ for(; i < l; ++i){
+ value = arr[i];
+ if(callback(value, i, arr)){
+ out.push(value);
+ }
+ }
+ }
+ return out; // Array
+ },
+
+ clearCache: function(){
+ cache = {};
+ }
+ };
+
+
+ 1 && lang.mixin(dojo, array);
+
+ return array;
+});
+
+},
+'dojo/text':function(){
+define(["./_base/kernel", "require", "./has", "./request"], function(dojo, require, has, request){
+ // module:
+ // dojo/text
+
+ var getText;
+ if( 1 ){
+ getText= function(url, sync, load){
+ request(url, {sync:!!sync, headers: { 'X-Requested-With': null } }).then(load);
+ };
+ }else{
+ // Path for node.js and rhino, to load from local file system.
+ // TODO: use node.js native methods rather than depending on a require.getText() method to exist.
+ if(require.getText){
+ getText= require.getText;
+ }else{
+ console.error("dojo/text plugin failed to load because loader does not support getText");
+ }
+ }
+
+ var
+ theCache = {},
+
+ strip= function(text){
+ //Strips declarations so that external SVG and XML
+ //documents can be added to a document without worry. Also, if the string
+ //is an HTML document, only the part inside the body tag is returned.
+ if(text){
+ text= text.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");
+ var matches= text.match(/]*>\s*([\s\S]+)\s*<\/body>/im);
+ if(matches){
+ text= matches[1];
+ }
+ }else{
+ text = "";
+ }
+ return text;
+ },
+
+ notFound = {},
+
+ pending = {};
+
+ dojo.cache = function(/*String||Object*/module, /*String*/url, /*String||Object?*/value){
+ // summary:
+ // A getter and setter for storing the string content associated with the
+ // module and url arguments.
+ // description:
+ // If module is a string that contains slashes, then it is interpretted as a fully
+ // resolved path (typically a result returned by require.toUrl), and url should not be
+ // provided. This is the preferred signature. If module is a string that does not
+ // contain slashes, then url must also be provided and module and url are used to
+ // call `dojo.moduleUrl()` to generate a module URL. This signature is deprecated.
+ // If value is specified, the cache value for the moduleUrl will be set to
+ // that value. Otherwise, dojo.cache will fetch the moduleUrl and store it
+ // in its internal cache and return that cached value for the URL. To clear
+ // a cache value pass null for value. Since XMLHttpRequest (XHR) is used to fetch the
+ // the URL contents, only modules on the same domain of the page can use this capability.
+ // The build system can inline the cache values though, to allow for xdomain hosting.
+ // module: String||Object
+ // If a String with slashes, a fully resolved path; if a String without slashes, the
+ // module name to use for the base part of the URL, similar to module argument
+ // to `dojo.moduleUrl`. If an Object, something that has a .toString() method that
+ // generates a valid path for the cache item. For example, a dojo._Url object.
+ // url: String
+ // The rest of the path to append to the path derived from the module argument. If
+ // module is an object, then this second argument should be the "value" argument instead.
+ // value: String||Object?
+ // If a String, the value to use in the cache for the module/url combination.
+ // If an Object, it can have two properties: value and sanitize. The value property
+ // should be the value to use in the cache, and sanitize can be set to true or false,
+ // to indicate if XML declarations should be removed from the value and if the HTML
+ // inside a body tag in the value should be extracted as the real value. The value argument
+ // or the value property on the value argument are usually only used by the build system
+ // as it inlines cache content.
+ // example:
+ // To ask dojo.cache to fetch content and store it in the cache (the dojo["cache"] style
+ // of call is used to avoid an issue with the build system erroneously trying to intern
+ // this example. To get the build system to intern your dojo.cache calls, use the
+ // "dojo.cache" style of call):
+ // | //If template.html contains "
Hello
" that will be
+ // | //the value for the text variable.
+ // | //Note: This is pre-AMD, deprecated syntax
+ // | var text = dojo["cache"]("my.module", "template.html");
+ // example:
+ // To ask dojo.cache to fetch content and store it in the cache, and sanitize the input
+ // (the dojo["cache"] style of call is used to avoid an issue with the build system
+ // erroneously trying to intern this example. To get the build system to intern your
+ // dojo.cache calls, use the "dojo.cache" style of call):
+ // | //If template.html contains "
Hello
", the
+ // | //text variable will contain just "
Hello
".
+ // | //Note: This is pre-AMD, deprecated syntax
+ // | var text = dojo["cache"]("my.module", "template.html", {sanitize: true});
+ // example:
+ // Same example as previous, but demonstrates how an object can be passed in as
+ // the first argument, then the value argument can then be the second argument.
+ // | //If template.html contains "
Hello
", the
+ // | //text variable will contain just "
Hello
".
+ // | //Note: This is pre-AMD, deprecated syntax
+ // | var text = dojo["cache"](new dojo._Url("my/module/template.html"), {sanitize: true});
+
+ // * (string string [value]) => (module, url, value)
+ // * (object [value]) => (module, value), url defaults to ""
+ //
+ // * if module is an object, then it must be convertable to a string
+ // * (module, url) module + (url ? ("/" + url) : "") must be a legal argument to require.toUrl
+ // * value may be a string or an object; if an object then may have the properties "value" and/or "sanitize"
+ var key;
+ if(typeof module=="string"){
+ if(/\//.test(module)){
+ // module is a version 1.7+ resolved path
+ key = module;
+ value = url;
+ }else{
+ // module is a version 1.6- argument to dojo.moduleUrl
+ key = require.toUrl(module.replace(/\./g, "/") + (url ? ("/" + url) : ""));
+ }
+ }else{
+ key = module + "";
+ value = url;
+ }
+ var
+ val = (value != undefined && typeof value != "string") ? value.value : value,
+ sanitize = value && value.sanitize;
+
+ if(typeof val == "string"){
+ //We have a string, set cache value
+ theCache[key] = val;
+ return sanitize ? strip(val) : val;
+ }else if(val === null){
+ //Remove cached value
+ delete theCache[key];
+ return null;
+ }else{
+ //Allow cache values to be empty strings. If key property does
+ //not exist, fetch it.
+ if(!(key in theCache)){
+ getText(key, true, function(text){
+ theCache[key]= text;
+ });
+ }
+ return sanitize ? strip(theCache[key]) : theCache[key];
+ }
+ };
+
+ return {
+ // summary:
+ // This module implements the dojo/text! plugin and the dojo.cache API.
+ // description:
+ // We choose to include our own plugin to leverage functionality already contained in dojo
+ // and thereby reduce the size of the plugin compared to various foreign loader implementations.
+ // Also, this allows foreign AMD loaders to be used without their plugins.
+ //
+ // CAUTION: this module is designed to optionally function synchronously to support the dojo v1.x synchronous
+ // loader. This feature is outside the scope of the CommonJS plugins specification.
+
+ // the dojo/text caches it's own resources because of dojo.cache
+ dynamic: true,
+
+ normalize: function(id, toAbsMid){
+ // id is something like (path may be relative):
+ //
+ // "path/to/text.html"
+ // "path/to/text.html!strip"
+ var parts= id.split("!"),
+ url= parts[0];
+ return (/^\./.test(url) ? toAbsMid(url) : url) + (parts[1] ? "!" + parts[1] : "");
+ },
+
+ load: function(id, require, load){
+ // id: String
+ // Path to the resource.
+ // require: Function
+ // Object that include the function toUrl with given id returns a valid URL from which to load the text.
+ // load: Function
+ // Callback function which will be called, when the loading finished.
+
+ // id is something like (path is always absolute):
+ //
+ // "path/to/text.html"
+ // "path/to/text.html!strip"
+ var
+ parts= id.split("!"),
+ stripFlag= parts.length>1,
+ absMid= parts[0],
+ url = require.toUrl(parts[0]),
+ requireCacheUrl = "url:" + url,
+ text = notFound,
+ finish = function(text){
+ load(stripFlag ? strip(text) : text);
+ };
+ if(absMid in theCache){
+ text = theCache[absMid];
+ }else if(require.cache && requireCacheUrl in require.cache){
+ text = require.cache[requireCacheUrl];
+ }else if(url in theCache){
+ text = theCache[url];
+ }
+ if(text===notFound){
+ if(pending[url]){
+ pending[url].push(finish);
+ }else{
+ var pendingList = pending[url] = [finish];
+ getText(url, !require.async, function(text){
+ theCache[absMid]= theCache[url]= text;
+ for(var i = 0; i/nls/*` and
+ // therefore never looks like a relative
+ return /^\./.test(id) ? toAbsMid(id) : id;
+ },
+
+ getLocalesToLoad = function(targetLocale){
+ var list = config.extraLocale || [];
+ list = lang.isArray(list) ? list : [list];
+ list.push(targetLocale);
+ return list;
+ },
+
+ load = function(id, require, load){
+ // summary:
+ // id is in one of the following formats
+ //
+ // 1. /nls/
+ // => load the bundle, localized to config.locale; load all bundles localized to
+ // config.extraLocale (if any); return the loaded bundle localized to config.locale.
+ //
+ // 2. /nls//
+ // => load then return the bundle localized to
+ //
+ // 3. *preload*/nls/*
+ // => for config.locale and all config.extraLocale, load all bundles found
+ // in the best-matching bundle rollup. A value of 1 is returned, which
+ // is meaningless other than to say the plugin is executing the requested
+ // preloads
+ //
+ // In cases 1 and 2, is always normalized to an absolute module id upon entry; see
+ // normalize. In case 3, it is assumed to be absolute; this is arranged by the builder.
+ //
+ // To load a bundle means to insert the bundle into the plugin's cache and publish the bundle
+ // value to the loader. Given , , and a particular , the cache key
+ //
+ // /nls//
+ //
+ // will hold the value. Similarly, then plugin will publish this value to the loader by
+ //
+ // define("/nls//", );
+ //
+ // Given this algorithm, other machinery can provide fast load paths be preplacing
+ // values in the plugin's cache, which is public. When a load is demanded the
+ // cache is inspected before starting any loading. Explicitly placing values in the plugin
+ // cache is an advanced/experimental feature that should not be needed; use at your own risk.
+ //
+ // For the normal AMD algorithm, the root bundle is loaded first, which instructs the
+ // plugin what additional localized bundles are required for a particular locale. These
+ // additional locales are loaded and a mix of the root and each progressively-specific
+ // locale is returned. For example:
+ //
+ // 1. The client demands "dojo/i18n!some/path/nls/someBundle
+ //
+ // 2. The loader demands load(some/path/nls/someBundle)
+ //
+ // 3. This plugin require's "some/path/nls/someBundle", which is the root bundle.
+ //
+ // 4. Assuming config.locale is "ab-cd-ef" and the root bundle indicates that localizations
+ // are available for "ab" and "ab-cd-ef" (note the missing "ab-cd", then the plugin
+ // requires "some/path/nls/ab/someBundle" and "some/path/nls/ab-cd-ef/someBundle"
+ //
+ // 5. Upon receiving all required bundles, the plugin constructs the value of the bundle
+ // ab-cd-ef as...
+ //
+ // mixin(mixin(mixin({}, require("some/path/nls/someBundle"),
+ // require("some/path/nls/ab/someBundle")),
+ // require("some/path/nls/ab-cd-ef/someBundle"));
+ //
+ // This value is inserted into the cache and published to the loader at the
+ // key/module-id some/path/nls/someBundle/ab-cd-ef.
+ //
+ // The special preload signature (case 3) instructs the plugin to stop servicing all normal requests
+ // (further preload requests will be serviced) until all ongoing preloading has completed.
+ //
+ // The preload signature instructs the plugin that a special rollup module is available that contains
+ // one or more flattened, localized bundles. The JSON array of available locales indicates which locales
+ // are available. Here is an example:
+ //
+ // *preload*some/path/nls/someModule*["root", "ab", "ab-cd-ef"]
+ //
+ // This indicates the following rollup modules are available:
+ //
+ // some/path/nls/someModule_ROOT
+ // some/path/nls/someModule_ab
+ // some/path/nls/someModule_ab-cd-ef
+ //
+ // Each of these modules is a normal AMD module that contains one or more flattened bundles in a hash.
+ // For example, assume someModule contained the bundles some/bundle/path/someBundle and
+ // some/bundle/path/someOtherBundle, then some/path/nls/someModule_ab would be expressed as follows:
+ //
+ // define({
+ // some/bundle/path/someBundle:,
+ // some/bundle/path/someOtherBundle:,
+ // });
+ //
+ // E.g., given this design, preloading for locale=="ab" can execute the following algorithm:
+ //
+ // require(["some/path/nls/someModule_ab"], function(rollup){
+ // for(var p in rollup){
+ // var id = p + "/ab",
+ // cache[id] = rollup[p];
+ // define(id, rollup[p]);
+ // }
+ // });
+ //
+ // Similarly, if "ab-cd" is requested, the algorithm can determine that "ab" is the best available and
+ // load accordingly.
+ //
+ // The builder will write such rollups for every layer if a non-empty localeList profile property is
+ // provided. Further, the builder will include the following cache entry in the cache associated with
+ // any layer.
+ //
+ // "*now":function(r){r(['dojo/i18n!*preload*/nls/*']);}
+ //
+ // The *now special cache module instructs the loader to apply the provided function to context-require
+ // with respect to the particular layer being defined. This causes the plugin to hold all normal service
+ // requests until all preloading is complete.
+ //
+ // Notice that this algorithm is rarely better than the standard AMD load algorithm. Consider the normal case
+ // where the target locale has a single segment and a layer depends on a single bundle:
+ //
+ // Without Preloads:
+ //
+ // 1. Layer loads root bundle.
+ // 2. bundle is demanded; plugin loads single localized bundle.
+ //
+ // With Preloads:
+ //
+ // 1. Layer causes preloading of target bundle.
+ // 2. bundle is demanded; service is delayed until preloading complete; bundle is returned.
+ //
+ // In each case a single transaction is required to load the target bundle. In cases where multiple bundles
+ // are required and/or the locale has multiple segments, preloads still requires a single transaction whereas
+ // the normal path requires an additional transaction for each additional bundle/locale-segment. However all
+ // of these additional transactions can be done concurrently. Owing to this analysis, the entire preloading
+ // algorithm can be discard during a build by setting the has feature dojo-preload-i18n-Api to false.
+
+ var match = nlsRe.exec(id),
+ bundlePath = match[1] + "/",
+ bundleName = match[5] || match[4],
+ bundlePathAndName = bundlePath + bundleName,
+ localeSpecified = (match[5] && match[4]),
+ targetLocale = localeSpecified || dojo.locale || "",
+ loadTarget = bundlePathAndName + "/" + targetLocale,
+ loadList = localeSpecified ? [targetLocale] : getLocalesToLoad(targetLocale),
+ remaining = loadList.length,
+ finish = function(){
+ if(!--remaining){
+ load(lang.delegate(cache[loadTarget]));
+ }
+ },
+ split = id.split("*"),
+ preloadDemand = split[1] == "preload";
+
+ if(has("dojo-preload-i18n-Api")){
+ if(preloadDemand){
+ if(!cache[id]){
+ // use cache[id] to prevent multiple preloads of the same preload; this shouldn't happen, but
+ // who knows what over-aggressive human optimizers may attempt
+ cache[id] = 1;
+ preloadL10n(split[2], json.parse(split[3]), 1, require);
+ }
+ // don't stall the loader!
+ load(1);
+ }
+ if(preloadDemand || (waitForPreloads(id, require, load) && !cache[loadTarget])){
+ return;
+ }
+ }
+ else if (preloadDemand) {
+ // If a build is created with nls resources and 'dojo-preload-i18n-Api' has not been set to false,
+ // the built file will include a preload in the cache (which looks about like so:)
+ // '*now':function(r){r(['dojo/i18n!*preload*dojo/nls/dojo*["ar","ca","cs","da","de","el","en-gb","en-us","es-es","fi-fi","fr-fr","he-il","hu","it-it","ja-jp","ko-kr","nl-nl","nb","pl","pt-br","pt-pt","ru","sk","sl","sv","th","tr","zh-tw","zh-cn","ROOT"]']);}
+ // If the consumer of the build sets 'dojo-preload-i18n-Api' to false in the Dojo config, the cached
+ // preload will not be parsed and will result in an attempt to call 'require' passing it the unparsed
+ // preload, which is not a valid module id.
+ // In this case we should skip this request.
+ load(1);
+
+ return;
+ }
+
+ array.forEach(loadList, function(locale){
+ var target = bundlePathAndName + "/" + locale;
+ if(has("dojo-preload-i18n-Api")){
+ checkForLegacyModules(target);
+ }
+ if(!cache[target]){
+ doLoad(require, bundlePathAndName, bundlePath, bundleName, locale, finish);
+ }else{
+ finish();
+ }
+ });
+ };
+
+ if(has("dojo-preload-i18n-Api") || 1 ){
+ var normalizeLocale = thisModule.normalizeLocale = function(locale){
+ var result = locale ? locale.toLowerCase() : dojo.locale;
+ return result == "root" ? "ROOT" : result;
+ },
+
+ isXd = function(mid, contextRequire){
+ return ( 1 && 1 ) ?
+ contextRequire.isXdUrl(require.toUrl(mid + ".js")) :
+ true;
+ },
+
+ preloading = 0,
+
+ preloadWaitQueue = [],
+
+ preloadL10n = thisModule._preloadLocalizations = function(/*String*/bundlePrefix, /*Array*/localesGenerated, /*boolean?*/ guaranteedAmdFormat, /*function?*/ contextRequire){
+ // summary:
+ // Load available flattened resource bundles associated with a particular module for dojo/locale and all dojo/config.extraLocale (if any)
+ // description:
+ // Only called by built layer files. The entire locale hierarchy is loaded. For example,
+ // if locale=="ab-cd", then ROOT, "ab", and "ab-cd" are loaded. This is different than v1.6-
+ // in that the v1.6- would only load ab-cd...which was *always* flattened.
+ //
+ // If guaranteedAmdFormat is true, then the module can be loaded with require thereby circumventing the detection algorithm
+ // and the extra possible extra transaction.
+
+ // If this function is called from legacy code, then guaranteedAmdFormat and contextRequire will be undefined. Since the function
+ // needs a require in order to resolve module ids, fall back to the context-require associated with this dojo/i18n module, which
+ // itself may have been mapped.
+ contextRequire = contextRequire || require;
+
+ function doRequire(mid, callback){
+ if(isXd(mid, contextRequire) || guaranteedAmdFormat){
+ contextRequire([mid], callback);
+ }else{
+ syncRequire([mid], callback, contextRequire);
+ }
+ }
+
+ function forEachLocale(locale, func){
+ // given locale= "ab-cd-ef", calls func on "ab-cd-ef", "ab-cd", "ab", "ROOT"; stops calling the first time func returns truthy
+ var parts = locale.split("-");
+ while(parts.length){
+ if(func(parts.join("-"))){
+ return;
+ }
+ parts.pop();
+ }
+ func("ROOT");
+ }
+
+ function preloadingAddLock(){
+ preloading++;
+ }
+
+ function preloadingRelLock(){
+ --preloading;
+ while(!preloading && preloadWaitQueue.length){
+ load.apply(null, preloadWaitQueue.shift());
+ }
+ }
+
+ function cacheId(path, name, loc, require){
+ // path is assumed to have a trailing "/"
+ return require.toAbsMid(path + name + "/" + loc)
+ }
+
+ function preload(locale){
+ locale = normalizeLocale(locale);
+ forEachLocale(locale, function(loc){
+ if(array.indexOf(localesGenerated, loc) >= 0){
+ var mid = bundlePrefix.replace(/\./g, "/") + "_" + loc;
+ preloadingAddLock();
+ doRequire(mid, function(rollup){
+ for(var p in rollup){
+ var bundle = rollup[p],
+ match = p.match(/(.+)\/([^\/]+)$/),
+ bundleName, bundlePath;
+
+ // If there is no match, the bundle is not a regular bundle from an AMD layer.
+ if (!match){continue;}
+
+ bundleName = match[2];
+ bundlePath = match[1] + "/";
+
+ // backcompat
+ if(!bundle._localized){continue;}
+
+ var localized;
+ if(loc === "ROOT"){
+ var root = localized = bundle._localized;
+ delete bundle._localized;
+ root.root = bundle;
+ cache[require.toAbsMid(p)] = root;
+ }else{
+ localized = bundle._localized;
+ cache[cacheId(bundlePath, bundleName, loc, require)] = bundle;
+ }
+
+ if(loc !== locale){
+ // capture some locale variables
+ var improveBundle = function improveBundle(bundlePath, bundleName, bundle, localized){
+ // locale was not flattened and we've fallen back to a less-specific locale that was flattened
+ // for example, we had a flattened 'fr', a 'fr-ca' is available for at least this bundle, and
+ // locale==='fr-ca'; therefore, we must improve the bundle as retrieved from the rollup by
+ // manually loading the fr-ca version of the bundle and mixing this into the already-retrieved 'fr'
+ // version of the bundle.
+ //
+ // Remember, different bundles may have different sets of locales available.
+ //
+ // we are really falling back on the regular algorithm here, but--hopefully--starting with most
+ // of the required bundles already on board as given by the rollup and we need to "manually" load
+ // only one locale from a few bundles...or even better...we won't find anything better to load.
+ // This algorithm ensures there is nothing better to load even when we can only load a less-specific rollup.
+ //
+ // note: this feature is only available in async mode
+
+ // inspect the loaded bundle that came from the rollup to see if something better is available
+ // for any bundle in a rollup, more-specific available locales are given at localized.
+ var requiredBundles = [],
+ cacheIds = [];
+ forEachLocale(locale, function(loc){
+ if(localized[loc]){
+ requiredBundles.push(require.toAbsMid(bundlePath + loc + "/" + bundleName));
+ cacheIds.push(cacheId(bundlePath, bundleName, loc, require));
+ }
+ });
+
+ if(requiredBundles.length){
+ preloadingAddLock();
+ contextRequire(requiredBundles, function(){
+ // requiredBundles was constructed by forEachLocale so it contains locales from
+ // less specific to most specific.
+ // the loop starts with the most specific locale, the last one.
+ for(var i = requiredBundles.length - 1; i >= 0 ; i--){
+ bundle = lang.mixin(lang.clone(bundle), arguments[i]);
+ cache[cacheIds[i]] = bundle;
+ }
+ // this is the best possible (maybe a perfect match, maybe not), accept it
+ cache[cacheId(bundlePath, bundleName, locale, require)] = lang.clone(bundle);
+ preloadingRelLock();
+ });
+ }else{
+ // this is the best possible (definitely not a perfect match), accept it
+ cache[cacheId(bundlePath, bundleName, locale, require)] = bundle;
+ }
+ };
+ improveBundle(bundlePath, bundleName, bundle, localized);
+ }
+ }
+ preloadingRelLock();
+ });
+ return true;
+ }
+ return false;
+ });
+ }
+
+ preload();
+ array.forEach(dojo.config.extraLocale, preload);
+ },
+
+ waitForPreloads = function(id, require, load){
+ if(preloading){
+ preloadWaitQueue.push([id, require, load]);
+ }
+ return preloading;
+ },
+
+ checkForLegacyModules = function()
+ {};
+ }
+
+ if( 1 ){
+ // this code path assumes the dojo loader and won't work with a standard AMD loader
+ var amdValue = {},
+ l10nCache = {},
+ evalBundle,
+
+ syncRequire = function(deps, callback, require){
+ var results = [];
+ array.forEach(deps, function(mid){
+ var url = require.toUrl(mid + ".js");
+
+ function load(text){
+ if (!evalBundle) {
+ // use the function ctor to keep the minifiers away (also come close to global scope, but this is secondary)
+ evalBundle = new Function(
+ "__bundle", // the bundle to evalutate
+ "__checkForLegacyModules", // a function that checks if __bundle defined __mid in the global space
+ "__mid", // the mid that __bundle is intended to define
+ "__amdValue",
+
+ // returns one of:
+ // 1 => the bundle was an AMD bundle
+ // a legacy bundle object that is the value of __mid
+ // instance of Error => could not figure out how to evaluate bundle
+
+ // used to detect when __bundle calls define
+ "var define = function(mid, factory){define.called = 1; __amdValue.result = factory || mid;},"
+ + " require = function(){define.called = 1;};"
+
+ + "try{"
+ + "define.called = 0;"
+ + "eval(__bundle);"
+ + "if(define.called==1)"
+ // bundle called define; therefore signal it's an AMD bundle
+ + "return __amdValue;"
+
+ + "if((__checkForLegacyModules = __checkForLegacyModules(__mid)))"
+ // bundle was probably a v1.6- built NLS flattened NLS bundle that defined __mid in the global space
+ + "return __checkForLegacyModules;"
+
+ + "}catch(e){}"
+ // evaulating the bundle was *neither* an AMD *nor* a legacy flattened bundle
+ // either way, re-eval *after* surrounding with parentheses
+
+ + "try{"
+ + "return eval('('+__bundle+')');"
+ + "}catch(e){"
+ + "return e;"
+ + "}"
+ );
+ }
+ var result = evalBundle(text, checkForLegacyModules, mid, amdValue);
+ if(result===amdValue){
+ // the bundle was an AMD module; re-inject it through the normal AMD path
+ // we gotta do this since it could be an anonymous module and simply evaluating
+ // the text here won't provide the loader with the context to know what
+ // module is being defined()'d. With browser caching, this should be free; further
+ // this entire code path can be circumvented by using the AMD format to begin with
+ results.push(cache[url] = amdValue.result);
+ }else{
+ if(result instanceof Error){
+ console.error("failed to evaluate i18n bundle; url=" + url, result);
+ result = {};
+ }
+ // nls// indicates not the root.
+ results.push(cache[url] = (/nls\/[^\/]+\/[^\/]+$/.test(url) ? result : {root:result, _v1x:1}));
+ }
+ }
+
+ if(cache[url]){
+ results.push(cache[url]);
+ }else{
+ var bundle = require.syncLoadNls(mid);
+ // need to check for legacy module here because there might be a legacy module for a
+ // less specific locale (which was not looked up during the first checkForLegacyModules
+ // call in load()).
+ // Also need to reverse the locale and the module name in the mid because syncRequire
+ // deps parameters uses the AMD style package/nls/locale/module while legacy code uses
+ // package/nls/module/locale.
+ if(!bundle){
+ bundle = checkForLegacyModules(mid.replace(/nls\/([^\/]*)\/([^\/]*)$/, "nls/$2/$1"));
+ }
+ if(bundle){
+ results.push(bundle);
+ }else{
+ if(!xhr){
+ try{
+ require.getText(url, true, load);
+ }catch(e){
+ results.push(cache[url] = {});
+ }
+ }else{
+ xhr.get({
+ url:url,
+ sync:true,
+ load:load,
+ error:function(){
+ results.push(cache[url] = {});
+ }
+ });
+ }
+ }
+ }
+ });
+ callback && callback.apply(null, results);
+ };
+
+ checkForLegacyModules = function(target){
+ // legacy code may have already loaded [e.g] the raw bundle x/y/z at x.y.z; when true, push into the cache
+ for(var result, names = target.split("/"), object = dojo.global[names[0]], i = 1; object && i 2 && !hasBody) || "POST|PUT".indexOf(method.toUpperCase()) === -1){
+ //Check for hasBody being passed. If no hasBody,
+ //then only append query string if not a POST or PUT request.
+ dojo._ioAddQueryToUrl(ioArgs);
+ }
+
+ var options = {
+ method: method,
+ handleAs: "text",
+ timeout: args.timeout,
+ withCredentials: args.withCredentials,
+ ioArgs: ioArgs
+ };
+
+ if(typeof args.headers !== 'undefined'){
+ options.headers = args.headers;
+ }
+ if(typeof args.contentType !== 'undefined'){
+ if(!options.headers){
+ options.headers = {};
+ }
+ options.headers['Content-Type'] = args.contentType;
+ }
+ if(typeof ioArgs.query !== 'undefined'){
+ options.data = ioArgs.query;
+ }
+ if(typeof args.sync !== 'undefined'){
+ options.sync = args.sync;
+ }
+
+ dojo._ioNotifyStart(dfd);
+ try{
+ rDfd = _xhr(ioArgs.url, options, true);
+ }catch(e){
+ // If XHR creation fails, dojo/request/xhr throws
+ // When this happens, cancel the deferred
+ dfd.cancel();
+ return dfd;
+ }
+
+ // sync ioArgs
+ dfd.ioArgs.xhr = rDfd.response.xhr;
+
+ rDfd.then(function(){
+ dfd.resolve(dfd);
+ }).otherwise(function(error){
+ ioArgs.error = error;
+ if(error.response){
+ error.status = error.response.status;
+ error.responseText = error.response.text;
+ error.xhr = error.response.xhr;
+ }
+ dfd.reject(error);
+ });
+ return dfd; // dojo/_base/Deferred
+ };
+
+ dojo.xhrGet = function(/*dojo.__XhrArgs*/ args){
+ // summary:
+ // Sends an HTTP GET request to the server.
+ return dojo.xhr("GET", args); // dojo/_base/Deferred
+ };
+
+ dojo.rawXhrPost = dojo.xhrPost = function(/*dojo.__XhrArgs*/ args){
+ // summary:
+ // Sends an HTTP POST request to the server. In addition to the properties
+ // listed for the dojo.__XhrArgs type, the following property is allowed:
+ // postData:
+ // String. Send raw data in the body of the POST request.
+ return dojo.xhr("POST", args, true); // dojo/_base/Deferred
+ };
+
+ dojo.rawXhrPut = dojo.xhrPut = function(/*dojo.__XhrArgs*/ args){
+ // summary:
+ // Sends an HTTP PUT request to the server. In addition to the properties
+ // listed for the dojo.__XhrArgs type, the following property is allowed:
+ // putData:
+ // String. Send raw data in the body of the PUT request.
+ return dojo.xhr("PUT", args, true); // dojo/_base/Deferred
+ };
+
+ dojo.xhrDelete = function(/*dojo.__XhrArgs*/ args){
+ // summary:
+ // Sends an HTTP DELETE request to the server.
+ return dojo.xhr("DELETE", args); // dojo/_base/Deferred
+ };
+
+ /*
+ dojo.wrapForm = function(formNode){
+ // summary:
+ // A replacement for FormBind, but not implemented yet.
+
+ // FIXME: need to think harder about what extensions to this we might
+ // want. What should we allow folks to do w/ this? What events to
+ // set/send?
+ throw new Error("dojo.wrapForm not yet implemented");
+ }
+ */
+
+ dojo._isDocumentOk = function(x){
+ return util.checkStatus(x.status);
+ };
+
+ dojo._getText = function(url){
+ var result;
+ dojo.xhrGet({url:url, sync:true, load:function(text){
+ result = text;
+ }});
+ return result;
+ };
+
+ // Add aliases for static functions to dojo.xhr since dojo.xhr is what's returned from this module
+ lang.mixin(dojo.xhr, {
+ _xhrObj: dojo._xhrObj,
+ fieldToObject: domForm.fieldToObject,
+ formToObject: domForm.toObject,
+ objectToQuery: ioq.objectToQuery,
+ formToQuery: domForm.toQuery,
+ formToJson: domForm.toJson,
+ queryToObject: ioq.queryToObject,
+ contentHandlers: handlers,
+ _ioSetArgs: dojo._ioSetArgs,
+ _ioCancelAll: dojo._ioCancelAll,
+ _ioNotifyStart: dojo._ioNotifyStart,
+ _ioWatch: dojo._ioWatch,
+ _ioAddQueryToUrl: dojo._ioAddQueryToUrl,
+ _isDocumentOk: dojo._isDocumentOk,
+ _getText: dojo._getText,
+ get: dojo.xhrGet,
+ post: dojo.xhrPost,
+ put: dojo.xhrPut,
+ del: dojo.xhrDelete // because "delete" is a reserved word
+ });
+
+ return dojo.xhr;
+});
+
+},
+'dojo/_base/sniff':function(){
+define(["./kernel", "./lang", "../sniff"], function(dojo, lang, has){
+ // module:
+ // dojo/_base/sniff
+
+ /*=====
+ return {
+ // summary:
+ // Deprecated. New code should use dojo/sniff.
+ // This module populates the dojo browser version sniffing properties like dojo.isIE.
+ };
+ =====*/
+
+ if(! 1 ){
+ return has;
+ }
+
+ // no idea what this is for, or if it's used
+ dojo._name = "browser";
+
+ lang.mixin(dojo, {
+ // isBrowser: Boolean
+ // True if the client is a web-browser
+ isBrowser: true,
+
+ // isFF: Number|undefined
+ // Version as a Number if client is FireFox. undefined otherwise. Corresponds to
+ // major detected FireFox version (1.5, 2, 3, etc.)
+ isFF: has("ff"),
+
+ // isIE: Number|undefined
+ // Version as a Number if client is MSIE(PC). undefined otherwise. Corresponds to
+ // major detected IE version (6, 7, 8, etc.)
+ isIE: has("ie"),
+
+ // isKhtml: Number|undefined
+ // Version as a Number if client is a KHTML browser. undefined otherwise. Corresponds to major
+ // detected version.
+ isKhtml: has("khtml"),
+
+ // isWebKit: Number|undefined
+ // Version as a Number if client is a WebKit-derived browser (Konqueror,
+ // Safari, Chrome, etc.). undefined otherwise.
+ isWebKit: has("webkit"),
+
+ // isMozilla: Number|undefined
+ // Version as a Number if client is a Mozilla-based browser (Firefox,
+ // SeaMonkey). undefined otherwise. Corresponds to major detected version.
+ isMozilla: has("mozilla"),
+ // isMoz: Number|undefined
+ // Version as a Number if client is a Mozilla-based browser (Firefox,
+ // SeaMonkey). undefined otherwise. Corresponds to major detected version.
+ isMoz: has("mozilla"),
+
+ // isOpera: Number|undefined
+ // Version as a Number if client is Opera. undefined otherwise. Corresponds to
+ // major detected version.
+ isOpera: has("opera"),
+
+ // isSafari: Number|undefined
+ // Version as a Number if client is Safari or iPhone. undefined otherwise.
+ isSafari: has("safari"),
+
+ // isChrome: Number|undefined
+ // Version as a Number if client is Chrome browser. undefined otherwise.
+ isChrome: has("chrome"),
+
+ // isMac: Boolean
+ // True if the client runs on Mac
+ isMac: has("mac"),
+
+ // isIos: Number|undefined
+ // Version as a Number if client is iPhone, iPod, or iPad. undefined otherwise.
+ isIos: has("ios"),
+
+ // isAndroid: Number|undefined
+ // Version as a Number if client is android browser. undefined otherwise.
+ isAndroid: has("android"),
+
+ // isWii: Boolean
+ // True if client is Wii
+ isWii: has("wii"),
+
+ // isQuirks: Boolean
+ // Page is in quirks mode.
+ isQuirks: has("quirks"),
+
+ // isAir: Boolean
+ // True if client is Adobe Air
+ isAir: has("air")
+ });
+
+ return has;
+});
+
+},
+'dojo/io-query':function(){
+define(["./_base/lang"], function(lang){
+
+ // module:
+ // dojo/io-query
+
+ var backstop = {};
+
+ return {
+ // summary:
+ // This module defines query string processing functions.
+
+ objectToQuery: function objectToQuery(/*Object*/ map){
+ // summary:
+ // takes a name/value mapping object and returns a string representing
+ // a URL-encoded version of that object.
+ // example:
+ // this object:
+ //
+ // | {
+ // | blah: "blah",
+ // | multi: [
+ // | "thud",
+ // | "thonk"
+ // | ]
+ // | };
+ //
+ // yields the following query string:
+ //
+ // | "blah=blah&multi=thud&multi=thonk"
+
+ // FIXME: need to implement encodeAscii!!
+ var enc = encodeURIComponent, pairs = [];
+ for(var name in map){
+ var value = map[name];
+ if(value != backstop[name]){
+ var assign = enc(name) + "=";
+ if(lang.isArray(value)){
+ for(var i = 0, l = value.length; i < l; ++i){
+ pairs.push(assign + enc(value[i]));
+ }
+ }else{
+ pairs.push(assign + enc(value));
+ }
+ }
+ }
+ return pairs.join("&"); // String
+ },
+
+ queryToObject: function queryToObject(/*String*/ str){
+ // summary:
+ // Create an object representing a de-serialized query section of a
+ // URL. Query keys with multiple values are returned in an array.
+ //
+ // example:
+ // This string:
+ //
+ // | "foo=bar&foo=baz&thinger=%20spaces%20=blah&zonk=blarg&"
+ //
+ // results in this object structure:
+ //
+ // | {
+ // | foo: [ "bar", "baz" ],
+ // | thinger: " spaces =blah",
+ // | zonk: "blarg"
+ // | }
+ //
+ // Note that spaces and other urlencoded entities are correctly
+ // handled.
+
+ var dec = decodeURIComponent, qp = str.split("&"), ret = {}, name, val;
+ for(var i = 0, l = qp.length, item; i < l; ++i){
+ item = qp[i];
+ if(item.length){
+ var s = item.indexOf("=");
+ if(s < 0){
+ name = dec(item);
+ val = "";
+ }else{
+ name = dec(item.slice(0, s));
+ val = dec(item.slice(s + 1));
+ }
+ if(typeof ret[name] == "string"){ // inline'd type check
+ ret[name] = [ret[name]];
+ }
+
+ if(lang.isArray(ret[name])){
+ ret[name].push(val);
+ }else{
+ ret[name] = val;
+ }
+ }
+ }
+ return ret; // Object
+ }
+ };
+});
+},
+'dojo/dom':function(){
+define(["./sniff", "./_base/window", "./_base/kernel"],
+ function(has, win, kernel){
+ // module:
+ // dojo/dom
+
+ // FIXME: need to add unit tests for all the semi-public methods
+
+ if(has("ie") <= 7){
+ try{
+ document.execCommand("BackgroundImageCache", false, true);
+ }catch(e){
+ // sane browsers don't have cache "issues"
+ }
+ }
+
+ // =============================
+ // DOM Functions
+ // =============================
+
+ // the result object
+ var dom = {
+ // summary:
+ // This module defines the core dojo DOM API.
+ };
+
+ if(has("ie")){
+ dom.byId = function(id, doc){
+ if(typeof id != "string"){
+ return id || null;
+ }
+ var _d = doc || win.doc, te = id && _d.getElementById(id);
+ // attributes.id.value is better than just id in case the
+ // user has a name=id inside a form
+ if(te && (te.attributes.id.value == id || te.id == id)){
+ return te;
+ }else{
+ var eles = _d.all[id];
+ if(!eles || eles.nodeName){
+ eles = [eles];
+ }
+ // if more than 1, choose first with the correct id
+ var i = 0;
+ while((te = eles[i++])){
+ if((te.attributes && te.attributes.id && te.attributes.id.value == id) || te.id == id){
+ return te;
+ }
+ }
+ }
+ return null;
+ };
+ }else{
+ dom.byId = function(id, doc){
+ // inline'd type check.
+ // be sure to return null per documentation, to match IE branch.
+ return ((typeof id == "string") ? (doc || win.doc).getElementById(id) : id) || null; // DOMNode
+ };
+ }
+ /*=====
+ dom.byId = function(id, doc){
+ // summary:
+ // Returns DOM node with matching `id` attribute or falsy value (ex: null or undefined)
+ // if not found. If `id` is a DomNode, this function is a no-op.
+ //
+ // id: String|DOMNode
+ // A string to match an HTML id attribute or a reference to a DOM Node
+ //
+ // doc: Document?
+ // Document to work in. Defaults to the current value of
+ // dojo/_base/window.doc. Can be used to retrieve
+ // node references from other documents.
+ //
+ // example:
+ // Look up a node by ID:
+ // | require(["dojo/dom"], function(dom){
+ // | var n = dom.byId("foo");
+ // | });
+ //
+ // example:
+ // Check if a node exists, and use it.
+ // | require(["dojo/dom"], function(dom){
+ // | var n = dom.byId("bar");
+ // | if(n){ doStuff() ... }
+ // | });
+ //
+ // example:
+ // Allow string or DomNode references to be passed to a custom function:
+ // | require(["dojo/dom"], function(dom){
+ // | var foo = function(nodeOrId){
+ // | nodeOrId = dom.byId(nodeOrId);
+ // | // ... more stuff
+ // | }
+ // | });
+ };
+ =====*/
+
+ // Test for DOMNode.contains() method, available everywhere except FF8-
+ // and IE8-, where it's available in general, but not on document itself,
+ // and also problems when either ancestor or node are text nodes.
+
+ var doc = kernel.global["document"] || null;
+ has.add("dom-contains", !!(doc && doc.contains));
+ dom.isDescendant = has("dom-contains") ?
+ // FF9+, IE9+, webkit, opera, iOS, Android, Edge, etc.
+ function(/*DOMNode|String*/ node, /*DOMNode|String*/ ancestor){
+ return !!( (ancestor = dom.byId(ancestor)) && ancestor.contains(dom.byId(node)) );
+ } :
+ function(/*DOMNode|String*/ node, /*DOMNode|String*/ ancestor){
+ // summary:
+ // Returns true if node is a descendant of ancestor
+ // node: DOMNode|String
+ // string id or node reference to test
+ // ancestor: DOMNode|String
+ // string id or node reference of potential parent to test against
+ //
+ // example:
+ // Test is node id="bar" is a descendant of node id="foo"
+ // | require(["dojo/dom"], function(dom){
+ // | if(dom.isDescendant("bar", "foo")){ ... }
+ // | });
+
+ try{
+ node = dom.byId(node);
+ ancestor = dom.byId(ancestor);
+ while(node){
+ if(node == ancestor){
+ return true; // Boolean
+ }
+ node = node.parentNode;
+ }
+ }catch(e){ /* squelch, return false */ }
+ return false; // Boolean
+ };
+
+ // TODO: do we need setSelectable in the base?
+
+ // Add feature test for user-select CSS property
+ // (currently known to work in all but IE < 10 and Opera)
+ // TODO: The user-select CSS property as of May 2014 is no longer part of
+ // any CSS specification. In IE, -ms-user-select does not do the same thing
+ // as the unselectable attribute on elements; namely, dijit Editor buttons
+ // do not properly prevent the content of the editable content frame from
+ // unblurring. As a result, the -ms- prefixed version is omitted here.
+ has.add("css-user-select", function(global, doc, element){
+ // Avoid exception when dom.js is loaded in non-browser environments
+ if(!element){ return false; }
+
+ var style = element.style;
+ var prefixes = ["Khtml", "O", "Moz", "Webkit"],
+ i = prefixes.length,
+ name = "userSelect",
+ prefix;
+
+ // Iterate prefixes from most to least likely
+ do{
+ if(typeof style[name] !== "undefined"){
+ // Supported; return property name
+ return name;
+ }
+ }while(i-- && (name = prefixes[i] + "UserSelect"));
+
+ // Not supported if we didn't return before now
+ return false;
+ });
+
+ /*=====
+ dom.setSelectable = function(node, selectable){
+ // summary:
+ // Enable or disable selection on a node
+ // node: DOMNode|String
+ // id or reference to node
+ // selectable: Boolean
+ // state to put the node in. false indicates unselectable, true
+ // allows selection.
+ // example:
+ // Make the node id="bar" unselectable
+ // | require(["dojo/dom"], function(dom){
+ // | dom.setSelectable("bar");
+ // | });
+ // example:
+ // Make the node id="bar" selectable
+ // | require(["dojo/dom"], function(dom){
+ // | dom.setSelectable("bar", true);
+ // | });
+ };
+ =====*/
+
+ var cssUserSelect = has("css-user-select");
+ dom.setSelectable = cssUserSelect ? function(node, selectable){
+ // css-user-select returns a (possibly vendor-prefixed) CSS property name
+ dom.byId(node).style[cssUserSelect] = selectable ? "" : "none";
+ } : function(node, selectable){
+ node = dom.byId(node);
+
+ // (IE < 10 / Opera) Fall back to setting/removing the
+ // unselectable attribute on the element and all its children
+ var nodes = node.getElementsByTagName("*"),
+ i = nodes.length;
+
+ if(selectable){
+ node.removeAttribute("unselectable");
+ while(i--){
+ nodes[i].removeAttribute("unselectable");
+ }
+ }else{
+ node.setAttribute("unselectable", "on");
+ while(i--){
+ nodes[i].setAttribute("unselectable", "on");
+ }
+ }
+ };
+
+ return dom;
+});
+
+},
+'dojo/_base/window':function(){
+define(["./kernel", "./lang", "../sniff"], function(dojo, lang, has){
+// module:
+// dojo/_base/window
+
+var ret = {
+ // summary:
+ // API to save/set/restore the global/document scope.
+
+ global: dojo.global,
+ /*=====
+ global: {
+ // summary:
+ // Alias for the current window. 'global' can be modified
+ // for temporary context shifting. See also withGlobal().
+ // description:
+ // Use this rather than referring to 'window' to ensure your code runs
+ // correctly in managed contexts.
+ },
+ =====*/
+
+ doc: dojo.global["document"] || null,
+ /*=====
+ doc: {
+ // summary:
+ // Alias for the current document. 'doc' can be modified
+ // for temporary context shifting. See also withDoc().
+ // description:
+ // Use this rather than referring to 'window.document' to ensure your code runs
+ // correctly in managed contexts.
+ // example:
+ // | n.appendChild(dojo.doc.createElement('div'));
+ },
+ =====*/
+
+ body: function(/*Document?*/ doc){
+ // summary:
+ // Return the body element of the specified document or of dojo/_base/window::doc.
+ // example:
+ // | win.body().appendChild(dojo.doc.createElement('div'));
+
+ // Note: document.body is not defined for a strict xhtml document
+ // Would like to memoize this, but dojo.doc can change vi dojo.withDoc().
+ doc = doc || dojo.doc;
+ return doc.body || doc.getElementsByTagName("body")[0]; // Node
+ },
+
+ setContext: function(/*Object*/ globalObject, /*DocumentElement*/ globalDocument){
+ // summary:
+ // changes the behavior of many core Dojo functions that deal with
+ // namespace and DOM lookup, changing them to work in a new global
+ // context (e.g., an iframe). The varibles dojo.global and dojo.doc
+ // are modified as a result of calling this function and the result of
+ // `dojo.body()` likewise differs.
+ dojo.global = ret.global = globalObject;
+ dojo.doc = ret.doc = globalDocument;
+ },
+
+ withGlobal: function( /*Object*/ globalObject,
+ /*Function*/ callback,
+ /*Object?*/ thisObject,
+ /*Array?*/ cbArguments){
+ // summary:
+ // Invoke callback with globalObject as dojo.global and
+ // globalObject.document as dojo.doc.
+ // description:
+ // Invoke callback with globalObject as dojo.global and
+ // globalObject.document as dojo.doc. If provided, globalObject
+ // will be executed in the context of object thisObject
+ // When callback() returns or throws an error, the dojo.global
+ // and dojo.doc will be restored to its previous state.
+
+ var oldGlob = dojo.global;
+ try{
+ dojo.global = ret.global = globalObject;
+ return ret.withDoc.call(null, globalObject.document, callback, thisObject, cbArguments);
+ }finally{
+ dojo.global = ret.global = oldGlob;
+ }
+ },
+
+ withDoc: function( /*DocumentElement*/ documentObject,
+ /*Function*/ callback,
+ /*Object?*/ thisObject,
+ /*Array?*/ cbArguments){
+ // summary:
+ // Invoke callback with documentObject as dojo/_base/window::doc.
+ // description:
+ // Invoke callback with documentObject as dojo/_base/window::doc. If provided,
+ // callback will be executed in the context of object thisObject
+ // When callback() returns or throws an error, the dojo/_base/window::doc will
+ // be restored to its previous state.
+
+ var oldDoc = ret.doc,
+ oldQ = has("quirks"),
+ oldIE = has("ie"), isIE, mode, pwin;
+
+ try{
+ dojo.doc = ret.doc = documentObject;
+ // update dojo.isQuirks and the value of the has feature "quirks".
+ // remove setting dojo.isQuirks and dojo.isIE for 2.0
+ dojo.isQuirks = has.add("quirks", dojo.doc.compatMode == "BackCompat", true, true); // no need to check for QuirksMode which was Opera 7 only
+
+ if(has("ie")){
+ if((pwin = documentObject.parentWindow) && pwin.navigator){
+ // re-run IE detection logic and update dojo.isIE / has("ie")
+ // (the only time parentWindow/navigator wouldn't exist is if we were not
+ // passed an actual legitimate document object)
+ isIE = parseFloat(pwin.navigator.appVersion.split("MSIE ")[1]) || undefined;
+ mode = documentObject.documentMode;
+ if(mode && mode != 5 && Math.floor(isIE) != mode){
+ isIE = mode;
+ }
+ dojo.isIE = has.add("ie", isIE, true, true);
+ }
+ }
+
+ if(thisObject && typeof callback == "string"){
+ callback = thisObject[callback];
+ }
+
+ return callback.apply(thisObject, cbArguments || []);
+ }finally{
+ dojo.doc = ret.doc = oldDoc;
+ dojo.isQuirks = has.add("quirks", oldQ, true, true);
+ dojo.isIE = has.add("ie", oldIE, true, true);
+ }
+ }
+};
+
+ 1 && lang.mixin(dojo, ret);
+
+return ret;
+
+});
+
+},
+'dojo/dom-form':function(){
+define(["./_base/lang", "./dom", "./io-query", "./json"], function(lang, dom, ioq, json){
+ // module:
+ // dojo/dom-form
+
+ function setValue(/*Object*/ obj, /*String*/ name, /*String*/ value){
+ // summary:
+ // For the named property in object, set the value. If a value
+ // already exists and it is a string, convert the value to be an
+ // array of values.
+
+ // Skip it if there is no value
+ if(value === null){
+ return;
+ }
+
+ var val = obj[name];
+ if(typeof val == "string"){ // inline'd type check
+ obj[name] = [val, value];
+ }else if(lang.isArray(val)){
+ val.push(value);
+ }else{
+ obj[name] = value;
+ }
+ }
+
+ var exclude = "file|submit|image|reset|button";
+
+ var form = {
+ // summary:
+ // This module defines form-processing functions.
+
+ fieldToObject: function fieldToObject(/*DOMNode|String*/ inputNode){
+ // summary:
+ // Serialize a form field to a JavaScript object.
+ // description:
+ // Returns the value encoded in a form field as
+ // as a string or an array of strings. Disabled form elements
+ // and unchecked radio and checkboxes are skipped. Multi-select
+ // elements are returned as an array of string values.
+ // inputNode: DOMNode|String
+ // returns: Object
+
+ var ret = null;
+ inputNode = dom.byId(inputNode);
+ if(inputNode){
+ var _in = inputNode.name, type = (inputNode.type || "").toLowerCase();
+ if(_in && type && !inputNode.disabled){
+ if(type == "radio" || type == "checkbox"){
+ if(inputNode.checked){
+ ret = inputNode.value;
+ }
+ }else if(inputNode.multiple){
+ ret = [];
+ var nodes = [inputNode.firstChild];
+ while(nodes.length){
+ for(var node = nodes.pop(); node; node = node.nextSibling){
+ if(node.nodeType == 1 && node.tagName.toLowerCase() == "option"){
+ if(node.selected){
+ ret.push(node.value);
+ }
+ }else{
+ if(node.nextSibling){
+ nodes.push(node.nextSibling);
+ }
+ if(node.firstChild){
+ nodes.push(node.firstChild);
+ }
+ break;
+ }
+ }
+ }
+ }else{
+ ret = inputNode.value;
+ }
+ }
+ }
+ return ret; // Object
+ },
+
+ toObject: function formToObject(/*DOMNode|String*/ formNode){
+ // summary:
+ // Serialize a form node to a JavaScript object.
+ // description:
+ // Returns the values encoded in an HTML form as
+ // string properties in an object which it then returns. Disabled form
+ // elements, buttons, and other non-value form elements are skipped.
+ // Multi-select elements are returned as an array of string values.
+ // formNode: DOMNode|String
+ // example:
+ // This form:
+ // |
+ //
+ // yields this object structure as the result of a call to
+ // formToObject():
+ //
+ // | {
+ // | blah: "blah",
+ // | multi: [
+ // | "thud",
+ // | "thonk"
+ // | ]
+ // | };
+
+ var ret = {}, elems = dom.byId(formNode).elements;
+ for(var i = 0, l = elems.length; i < l; ++i){
+ var item = elems[i], _in = item.name, type = (item.type || "").toLowerCase();
+ if(_in && type && exclude.indexOf(type) < 0 && !item.disabled){
+ setValue(ret, _in, form.fieldToObject(item));
+ if(type == "image"){
+ ret[_in + ".x"] = ret[_in + ".y"] = ret[_in].x = ret[_in].y = 0;
+ }
+ }
+ }
+ return ret; // Object
+ },
+
+ toQuery: function formToQuery(/*DOMNode|String*/ formNode){
+ // summary:
+ // Returns a URL-encoded string representing the form passed as either a
+ // node or string ID identifying the form to serialize
+ // formNode: DOMNode|String
+ // returns: String
+
+ return ioq.objectToQuery(form.toObject(formNode)); // String
+ },
+
+ toJson: function formToJson(/*DOMNode|String*/ formNode, /*Boolean?*/ prettyPrint){
+ // summary:
+ // Create a serialized JSON string from a form node or string
+ // ID identifying the form to serialize
+ // formNode: DOMNode|String
+ // prettyPrint: Boolean?
+ // returns: String
+
+ return json.stringify(form.toObject(formNode), null, prettyPrint ? 4 : 0); // String
+ }
+ };
+
+ return form;
+});
+
+},
+'dojo/_base/Deferred':function(){
+define([
+ "./kernel",
+ "../Deferred",
+ "../promise/Promise",
+ "../errors/CancelError",
+ "../has",
+ "./lang",
+ "../when"
+], function(dojo, NewDeferred, Promise, CancelError, has, lang, when){
+ // module:
+ // dojo/_base/Deferred
+
+ var mutator = function(){};
+ var freeze = Object.freeze || function(){};
+ // A deferred provides an API for creating and resolving a promise.
+ var Deferred = dojo.Deferred = function(/*Function?*/ canceller){
+ // summary:
+ // Deprecated. This module defines the legacy dojo/_base/Deferred API.
+ // New code should use dojo/Deferred instead.
+ // description:
+ // The Deferred API is based on the concept of promises that provide a
+ // generic interface into the eventual completion of an asynchronous action.
+ // The motivation for promises fundamentally is about creating a
+ // separation of concerns that allows one to achieve the same type of
+ // call patterns and logical data flow in asynchronous code as can be
+ // achieved in synchronous code. Promises allows one
+ // to be able to call a function purely with arguments needed for
+ // execution, without conflating the call with concerns of whether it is
+ // sync or async. One shouldn't need to alter a call's arguments if the
+ // implementation switches from sync to async (or vice versa). By having
+ // async functions return promises, the concerns of making the call are
+ // separated from the concerns of asynchronous interaction (which are
+ // handled by the promise).
+ //
+ // The Deferred is a type of promise that provides methods for fulfilling the
+ // promise with a successful result or an error. The most important method for
+ // working with Dojo's promises is the then() method, which follows the
+ // CommonJS proposed promise API. An example of using a Dojo promise:
+ //
+ // | var resultingPromise = someAsyncOperation.then(function(result){
+ // | ... handle result ...
+ // | },
+ // | function(error){
+ // | ... handle error ...
+ // | });
+ //
+ // The .then() call returns a new promise that represents the result of the
+ // execution of the callback. The callbacks will never affect the original promises value.
+ //
+ // The Deferred instances also provide the following functions for backwards compatibility:
+ //
+ // - addCallback(handler)
+ // - addErrback(handler)
+ // - callback(result)
+ // - errback(result)
+ //
+ // Callbacks are allowed to return promises themselves, so
+ // you can build complicated sequences of events with ease.
+ //
+ // The creator of the Deferred may specify a canceller. The canceller
+ // is a function that will be called if Deferred.cancel is called
+ // before the Deferred fires. You can use this to implement clean
+ // aborting of an XMLHttpRequest, etc. Note that cancel will fire the
+ // deferred with a CancelledError (unless your canceller returns
+ // another kind of error), so the errbacks should be prepared to
+ // handle that error for cancellable Deferreds.
+ // example:
+ // | var deferred = new Deferred();
+ // | setTimeout(function(){ deferred.callback({success: true}); }, 1000);
+ // | return deferred;
+ // example:
+ // Deferred objects are often used when making code asynchronous. It
+ // may be easiest to write functions in a synchronous manner and then
+ // split code using a deferred to trigger a response to a long-lived
+ // operation. For example, instead of register a callback function to
+ // denote when a rendering operation completes, the function can
+ // simply return a deferred:
+ //
+ // | // callback style:
+ // | function renderLotsOfData(data, callback){
+ // | var success = false
+ // | try{
+ // | for(var x in data){
+ // | renderDataitem(data[x]);
+ // | }
+ // | success = true;
+ // | }catch(e){ }
+ // | if(callback){
+ // | callback(success);
+ // | }
+ // | }
+ //
+ // | // using callback style
+ // | renderLotsOfData(someDataObj, function(success){
+ // | // handles success or failure
+ // | if(!success){
+ // | promptUserToRecover();
+ // | }
+ // | });
+ // | // NOTE: no way to add another callback here!!
+ // example:
+ // Using a Deferred doesn't simplify the sending code any, but it
+ // provides a standard interface for callers and senders alike,
+ // providing both with a simple way to service multiple callbacks for
+ // an operation and freeing both sides from worrying about details
+ // such as "did this get called already?". With Deferreds, new
+ // callbacks can be added at any time.
+ //
+ // | // Deferred style:
+ // | function renderLotsOfData(data){
+ // | var d = new Deferred();
+ // | try{
+ // | for(var x in data){
+ // | renderDataitem(data[x]);
+ // | }
+ // | d.callback(true);
+ // | }catch(e){
+ // | d.errback(new Error("rendering failed"));
+ // | }
+ // | return d;
+ // | }
+ //
+ // | // using Deferred style
+ // | renderLotsOfData(someDataObj).then(null, function(){
+ // | promptUserToRecover();
+ // | });
+ // | // NOTE: addErrback and addCallback both return the Deferred
+ // | // again, so we could chain adding callbacks or save the
+ // | // deferred for later should we need to be notified again.
+ // example:
+ // In this example, renderLotsOfData is synchronous and so both
+ // versions are pretty artificial. Putting the data display on a
+ // timeout helps show why Deferreds rock:
+ //
+ // | // Deferred style and async func
+ // | function renderLotsOfData(data){
+ // | var d = new Deferred();
+ // | setTimeout(function(){
+ // | try{
+ // | for(var x in data){
+ // | renderDataitem(data[x]);
+ // | }
+ // | d.callback(true);
+ // | }catch(e){
+ // | d.errback(new Error("rendering failed"));
+ // | }
+ // | }, 100);
+ // | return d;
+ // | }
+ //
+ // | // using Deferred style
+ // | renderLotsOfData(someDataObj).then(null, function(){
+ // | promptUserToRecover();
+ // | });
+ //
+ // Note that the caller doesn't have to change his code at all to
+ // handle the asynchronous case.
+
+ var result, finished, canceled, fired, isError, head, nextListener;
+ var promise = (this.promise = new Promise());
+
+ function complete(value){
+ if(finished){
+ throw new Error("This deferred has already been resolved");
+ }
+ result = value;
+ finished = true;
+ notify();
+ }
+ function notify(){
+ var mutated;
+ while(!mutated && nextListener){
+ var listener = nextListener;
+ nextListener = nextListener.next;
+ if((mutated = (listener.progress == mutator))){ // assignment and check
+ finished = false;
+ }
+
+ var func = (isError ? listener.error : listener.resolved);
+ if(has("config-useDeferredInstrumentation")){
+ if(isError && NewDeferred.instrumentRejected){
+ NewDeferred.instrumentRejected(result, !!func);
+ }
+ }
+ if(func){
+ try{
+ var newResult = func(result);
+ if (newResult && typeof newResult.then === "function"){
+ newResult.then(lang.hitch(listener.deferred, "resolve"), lang.hitch(listener.deferred, "reject"), lang.hitch(listener.deferred, "progress"));
+ continue;
+ }
+ var unchanged = mutated && newResult === undefined;
+ if(mutated && !unchanged){
+ isError = newResult instanceof Error;
+ }
+ listener.deferred[unchanged && isError ? "reject" : "resolve"](unchanged ? result : newResult);
+ }catch(e){
+ listener.deferred.reject(e);
+ }
+ }else{
+ if(isError){
+ listener.deferred.reject(result);
+ }else{
+ listener.deferred.resolve(result);
+ }
+ }
+ }
+ }
+
+ this.isResolved = promise.isResolved = function(){
+ // summary:
+ // Checks whether the deferred has been resolved.
+ // returns: Boolean
+
+ return fired == 0;
+ };
+
+ this.isRejected = promise.isRejected = function(){
+ // summary:
+ // Checks whether the deferred has been rejected.
+ // returns: Boolean
+
+ return fired == 1;
+ };
+
+ this.isFulfilled = promise.isFulfilled = function(){
+ // summary:
+ // Checks whether the deferred has been resolved or rejected.
+ // returns: Boolean
+
+ return fired >= 0;
+ };
+
+ this.isCanceled = promise.isCanceled = function(){
+ // summary:
+ // Checks whether the deferred has been canceled.
+ // returns: Boolean
+
+ return canceled;
+ };
+
+ // calling resolve will resolve the promise
+ this.resolve = this.callback = function(value){
+ // summary:
+ // Fulfills the Deferred instance successfully with the provide value
+ this.fired = fired = 0;
+ this.results = [value, null];
+ complete(value);
+ };
+
+
+ // calling error will indicate that the promise failed
+ this.reject = this.errback = function(error){
+ // summary:
+ // Fulfills the Deferred instance as an error with the provided error
+ isError = true;
+ this.fired = fired = 1;
+ if(has("config-useDeferredInstrumentation")){
+ if(NewDeferred.instrumentRejected){
+ NewDeferred.instrumentRejected(error, !!nextListener);
+ }
+ }
+ complete(error);
+ this.results = [null, error];
+ };
+ // call progress to provide updates on the progress on the completion of the promise
+ this.progress = function(update){
+ // summary:
+ // Send progress events to all listeners
+ var listener = nextListener;
+ while(listener){
+ var progress = listener.progress;
+ progress && progress(update);
+ listener = listener.next;
+ }
+ };
+ this.addCallbacks = function(callback, errback){
+ // summary:
+ // Adds callback and error callback for this deferred instance.
+ // callback: Function?
+ // The callback attached to this deferred object.
+ // errback: Function?
+ // The error callback attached to this deferred object.
+ // returns:
+ // Returns this deferred object.
+ this.then(callback, errback, mutator);
+ return this; // Deferred
+ };
+ // provide the implementation of the promise
+ promise.then = this.then = function(/*Function?*/resolvedCallback, /*Function?*/errorCallback, /*Function?*/progressCallback){
+ // summary:
+ // Adds a fulfilledHandler, errorHandler, and progressHandler to be called for
+ // completion of a promise. The fulfilledHandler is called when the promise
+ // is fulfilled. The errorHandler is called when a promise fails. The
+ // progressHandler is called for progress events. All arguments are optional
+ // and non-function values are ignored. The progressHandler is not only an
+ // optional argument, but progress events are purely optional. Promise
+ // providers are not required to ever create progress events.
+ //
+ // This function will return a new promise that is fulfilled when the given
+ // fulfilledHandler or errorHandler callback is finished. This allows promise
+ // operations to be chained together. The value returned from the callback
+ // handler is the fulfillment value for the returned promise. If the callback
+ // throws an error, the returned promise will be moved to failed state.
+ //
+ // returns:
+ // Returns a new promise that represents the result of the
+ // execution of the callback. The callbacks will never affect the original promises value.
+ // example:
+ // An example of using a CommonJS compliant promise:
+ // | asyncComputeTheAnswerToEverything().
+ // | then(addTwo).
+ // | then(printResult, onError);
+ // | >44
+ //
+ var returnDeferred = progressCallback == mutator ? this : new Deferred(promise.cancel);
+ var listener = {
+ resolved: resolvedCallback,
+ error: errorCallback,
+ progress: progressCallback,
+ deferred: returnDeferred
+ };
+ if(nextListener){
+ head = head.next = listener;
+ }
+ else{
+ nextListener = head = listener;
+ }
+ if(finished){
+ notify();
+ }
+ return returnDeferred.promise; // Promise
+ };
+ var deferred = this;
+ promise.cancel = this.cancel = function(){
+ // summary:
+ // Cancels the asynchronous operation
+ if(!finished){
+ var error = canceller && canceller(deferred);
+ if(!finished){
+ if (!(error instanceof Error)){
+ error = new CancelError(error);
+ }
+ error.log = false;
+ deferred.reject(error);
+ }
+ }
+ canceled = true;
+ };
+ freeze(promise);
+ };
+ lang.extend(Deferred, {
+ addCallback: function(/*Function*/ callback){
+ // summary:
+ // Adds successful callback for this deferred instance.
+ // returns:
+ // Returns this deferred object.
+ return this.addCallbacks(lang.hitch.apply(dojo, arguments)); // Deferred
+ },
+
+ addErrback: function(/*Function*/ errback){
+ // summary:
+ // Adds error callback for this deferred instance.
+ // returns:
+ // Returns this deferred object.
+ return this.addCallbacks(null, lang.hitch.apply(dojo, arguments)); // Deferred
+ },
+
+ addBoth: function(/*Function*/ callback){
+ // summary:
+ // Add handler as both successful callback and error callback for this deferred instance.
+ // returns:
+ // Returns this deferred object.
+ var enclosed = lang.hitch.apply(dojo, arguments);
+ return this.addCallbacks(enclosed, enclosed); // Deferred
+ },
+ fired: -1
+ });
+
+ Deferred.when = dojo.when = when;
+
+ return Deferred;
+});
+
+},
+'dojo/Deferred':function(){
+define([
+ "./has",
+ "./_base/lang",
+ "./errors/CancelError",
+ "./promise/Promise",
+ "./promise/instrumentation"
+], function(has, lang, CancelError, Promise, instrumentation){
+ "use strict";
+
+ // module:
+ // dojo/Deferred
+
+ var PROGRESS = 0,
+ RESOLVED = 1,
+ REJECTED = 2;
+ var FULFILLED_ERROR_MESSAGE = "This deferred has already been fulfilled.";
+
+ var freezeObject = Object.freeze || function(){};
+
+ var signalWaiting = function(waiting, type, result, rejection, deferred){
+ if( 1 ){
+ if(type === REJECTED && Deferred.instrumentRejected && waiting.length === 0){
+ Deferred.instrumentRejected(result, false, rejection, deferred);
+ }
+ }
+
+ for(var i = 0; i < waiting.length; i++){
+ signalListener(waiting[i], type, result, rejection);
+ }
+ };
+
+ var signalListener = function(listener, type, result, rejection){
+ var func = listener[type];
+ var deferred = listener.deferred;
+ if(func){
+ try{
+ var newResult = func(result);
+ if(type === PROGRESS){
+ if(typeof newResult !== "undefined"){
+ signalDeferred(deferred, type, newResult);
+ }
+ }else{
+ if(newResult && typeof newResult.then === "function"){
+ listener.cancel = newResult.cancel;
+ newResult.then(
+ // Only make resolvers if they're actually going to be used
+ makeDeferredSignaler(deferred, RESOLVED),
+ makeDeferredSignaler(deferred, REJECTED),
+ makeDeferredSignaler(deferred, PROGRESS));
+ return;
+ }
+ signalDeferred(deferred, RESOLVED, newResult);
+ }
+ }catch(error){
+ signalDeferred(deferred, REJECTED, error);
+ }
+ }else{
+ signalDeferred(deferred, type, result);
+ }
+
+ if( 1 ){
+ if(type === REJECTED && Deferred.instrumentRejected){
+ Deferred.instrumentRejected(result, !!func, rejection, deferred.promise);
+ }
+ }
+ };
+
+ var makeDeferredSignaler = function(deferred, type){
+ return function(value){
+ signalDeferred(deferred, type, value);
+ };
+ };
+
+ var signalDeferred = function(deferred, type, result){
+ if(!deferred.isCanceled()){
+ switch(type){
+ case PROGRESS:
+ deferred.progress(result);
+ break;
+ case RESOLVED:
+ deferred.resolve(result);
+ break;
+ case REJECTED:
+ deferred.reject(result);
+ break;
+ }
+ }
+ };
+
+ var Deferred = function(canceler){
+ // summary:
+ // Creates a new deferred. This API is preferred over
+ // `dojo/_base/Deferred`.
+ // description:
+ // Creates a new deferred, as an abstraction over (primarily)
+ // asynchronous operations. The deferred is the private interface
+ // that should not be returned to calling code. That's what the
+ // `promise` is for. See `dojo/promise/Promise`.
+ // canceler: Function?
+ // Will be invoked if the deferred is canceled. The canceler
+ // receives the reason the deferred was canceled as its argument.
+ // The deferred is rejected with its return value, or a new
+ // `dojo/errors/CancelError` instance.
+
+ // promise: dojo/promise/Promise
+ // The public promise object that clients can add callbacks to.
+ var promise = this.promise = new Promise();
+
+ var deferred = this;
+ var fulfilled, result, rejection;
+ var canceled = false;
+ var waiting = [];
+
+ if( 1 && Error.captureStackTrace){
+ Error.captureStackTrace(deferred, Deferred);
+ Error.captureStackTrace(promise, Deferred);
+ }
+
+ this.isResolved = promise.isResolved = function(){
+ // summary:
+ // Checks whether the deferred has been resolved.
+ // returns: Boolean
+
+ return fulfilled === RESOLVED;
+ };
+
+ this.isRejected = promise.isRejected = function(){
+ // summary:
+ // Checks whether the deferred has been rejected.
+ // returns: Boolean
+
+ return fulfilled === REJECTED;
+ };
+
+ this.isFulfilled = promise.isFulfilled = function(){
+ // summary:
+ // Checks whether the deferred has been resolved or rejected.
+ // returns: Boolean
+
+ return !!fulfilled;
+ };
+
+ this.isCanceled = promise.isCanceled = function(){
+ // summary:
+ // Checks whether the deferred has been canceled.
+ // returns: Boolean
+
+ return canceled;
+ };
+
+ this.progress = function(update, strict){
+ // summary:
+ // Emit a progress update on the deferred.
+ // description:
+ // Emit a progress update on the deferred. Progress updates
+ // can be used to communicate updates about the asynchronous
+ // operation before it has finished.
+ // update: any
+ // The progress update. Passed to progbacks.
+ // strict: Boolean?
+ // If strict, will throw an error if the deferred has already
+ // been fulfilled and consequently no progress can be emitted.
+ // returns: dojo/promise/Promise
+ // Returns the original promise for the deferred.
+
+ if(!fulfilled){
+ signalWaiting(waiting, PROGRESS, update, null, deferred);
+ return promise;
+ }else if(strict === true){
+ throw new Error(FULFILLED_ERROR_MESSAGE);
+ }else{
+ return promise;
+ }
+ };
+
+ this.resolve = function(value, strict){
+ // summary:
+ // Resolve the deferred.
+ // description:
+ // Resolve the deferred, putting it in a success state.
+ // value: any
+ // The result of the deferred. Passed to callbacks.
+ // strict: Boolean?
+ // If strict, will throw an error if the deferred has already
+ // been fulfilled and consequently cannot be resolved.
+ // returns: dojo/promise/Promise
+ // Returns the original promise for the deferred.
+
+ if(!fulfilled){
+ // Set fulfilled, store value. After signaling waiting listeners unset
+ // waiting.
+ signalWaiting(waiting, fulfilled = RESOLVED, result = value, null, deferred);
+ waiting = null;
+ return promise;
+ }else if(strict === true){
+ throw new Error(FULFILLED_ERROR_MESSAGE);
+ }else{
+ return promise;
+ }
+ };
+
+ var reject = this.reject = function(error, strict){
+ // summary:
+ // Reject the deferred.
+ // description:
+ // Reject the deferred, putting it in an error state.
+ // error: any
+ // The error result of the deferred. Passed to errbacks.
+ // strict: Boolean?
+ // If strict, will throw an error if the deferred has already
+ // been fulfilled and consequently cannot be rejected.
+ // returns: dojo/promise/Promise
+ // Returns the original promise for the deferred.
+
+ if(!fulfilled){
+ if( 1 && Error.captureStackTrace){
+ Error.captureStackTrace(rejection = {}, reject);
+ }
+ signalWaiting(waiting, fulfilled = REJECTED, result = error, rejection, deferred);
+ waiting = null;
+ return promise;
+ }else if(strict === true){
+ throw new Error(FULFILLED_ERROR_MESSAGE);
+ }else{
+ return promise;
+ }
+ };
+
+ this.then = promise.then = function(callback, errback, progback){
+ // summary:
+ // Add new callbacks to the deferred.
+ // description:
+ // Add new callbacks to the deferred. Callbacks can be added
+ // before or after the deferred is fulfilled.
+ // callback: Function?
+ // Callback to be invoked when the promise is resolved.
+ // Receives the resolution value.
+ // errback: Function?
+ // Callback to be invoked when the promise is rejected.
+ // Receives the rejection error.
+ // progback: Function?
+ // Callback to be invoked when the promise emits a progress
+ // update. Receives the progress update.
+ // returns: dojo/promise/Promise
+ // Returns a new promise for the result of the callback(s).
+ // This can be used for chaining many asynchronous operations.
+
+ var listener = [progback, callback, errback];
+ // Ensure we cancel the promise we're waiting for, or if callback/errback
+ // have returned a promise, cancel that one.
+ listener.cancel = promise.cancel;
+ listener.deferred = new Deferred(function(reason){
+ // Check whether cancel is really available, returned promises are not
+ // required to expose `cancel`
+ return listener.cancel && listener.cancel(reason);
+ });
+ if(fulfilled && !waiting){
+ signalListener(listener, fulfilled, result, rejection);
+ }else{
+ waiting.push(listener);
+ }
+ return listener.deferred.promise;
+ };
+
+ this.cancel = promise.cancel = function(reason, strict){
+ // summary:
+ // Inform the deferred it may cancel its asynchronous operation.
+ // description:
+ // Inform the deferred it may cancel its asynchronous operation.
+ // The deferred's (optional) canceler is invoked and the
+ // deferred will be left in a rejected state. Can affect other
+ // promises that originate with the same deferred.
+ // reason: any
+ // A message that may be sent to the deferred's canceler,
+ // explaining why it's being canceled.
+ // strict: Boolean?
+ // If strict, will throw an error if the deferred has already
+ // been fulfilled and consequently cannot be canceled.
+ // returns: any
+ // Returns the rejection reason if the deferred was canceled
+ // normally.
+
+ if(!fulfilled){
+ // Cancel can be called even after the deferred is fulfilled
+ if(canceler){
+ var returnedReason = canceler(reason);
+ reason = typeof returnedReason === "undefined" ? reason : returnedReason;
+ }
+ canceled = true;
+ if(!fulfilled){
+ // Allow canceler to provide its own reason, but fall back to a CancelError
+ if(typeof reason === "undefined"){
+ reason = new CancelError();
+ }
+ reject(reason);
+ return reason;
+ }else if(fulfilled === REJECTED && result === reason){
+ return reason;
+ }
+ }else if(strict === true){
+ throw new Error(FULFILLED_ERROR_MESSAGE);
+ }
+ };
+
+ freezeObject(promise);
+ };
+
+ Deferred.prototype.toString = function(){
+ // returns: String
+ // Returns `[object Deferred]`.
+
+ return "[object Deferred]";
+ };
+
+ if(instrumentation){
+ instrumentation(Deferred);
+ }
+
+ return Deferred;
+});
+
+},
+'dojo/errors/CancelError':function(){
+define(["./create"], function(create){
+ // module:
+ // dojo/errors/CancelError
+
+ /*=====
+ return function(){
+ // summary:
+ // Default error if a promise is canceled without a reason.
+ };
+ =====*/
+
+ return create("CancelError", null, null, { dojoType: "cancel", log: false });
+});
+
+},
+'dojo/errors/create':function(){
+define(["../_base/lang"], function(lang){
+ return function(name, ctor, base, props){
+ base = base || Error;
+
+ var ErrorCtor = function(message){
+ if(base === Error){
+ if(Error.captureStackTrace){
+ Error.captureStackTrace(this, ErrorCtor);
+ }
+
+ // Error.call() operates on the returned error
+ // object rather than operating on |this|
+ var err = Error.call(this, message),
+ prop;
+
+ // Copy own properties from err to |this|
+ for(prop in err){
+ if(err.hasOwnProperty(prop)){
+ this[prop] = err[prop];
+ }
+ }
+
+ // messsage is non-enumerable in ES5
+ this.message = message;
+ // stack is non-enumerable in at least Firefox
+ this.stack = err.stack;
+ }else{
+ base.apply(this, arguments);
+ }
+ if(ctor){
+ ctor.apply(this, arguments);
+ }
+ };
+
+ ErrorCtor.prototype = lang.delegate(base.prototype, props);
+ ErrorCtor.prototype.name = name;
+ ErrorCtor.prototype.constructor = ErrorCtor;
+
+ return ErrorCtor;
+ };
+});
+
+},
+'dojo/promise/Promise':function(){
+define([
+ "../_base/lang"
+], function(lang){
+ "use strict";
+
+ // module:
+ // dojo/promise/Promise
+
+ function throwAbstract(){
+ throw new TypeError("abstract");
+ }
+
+ return lang.extend(function Promise(){
+ // summary:
+ // The public interface to a deferred.
+ // description:
+ // The public interface to a deferred. All promises in Dojo are
+ // instances of this class.
+ }, {
+ then: function(callback, errback, progback){
+ // summary:
+ // Add new callbacks to the promise.
+ // description:
+ // Add new callbacks to the deferred. Callbacks can be added
+ // before or after the deferred is fulfilled.
+ // callback: Function?
+ // Callback to be invoked when the promise is resolved.
+ // Receives the resolution value.
+ // errback: Function?
+ // Callback to be invoked when the promise is rejected.
+ // Receives the rejection error.
+ // progback: Function?
+ // Callback to be invoked when the promise emits a progress
+ // update. Receives the progress update.
+ // returns: dojo/promise/Promise
+ // Returns a new promise for the result of the callback(s).
+ // This can be used for chaining many asynchronous operations.
+
+ throwAbstract();
+ },
+
+ cancel: function(reason, strict){
+ // summary:
+ // Inform the deferred it may cancel its asynchronous operation.
+ // description:
+ // Inform the deferred it may cancel its asynchronous operation.
+ // The deferred's (optional) canceler is invoked and the
+ // deferred will be left in a rejected state. Can affect other
+ // promises that originate with the same deferred.
+ // reason: any
+ // A message that may be sent to the deferred's canceler,
+ // explaining why it's being canceled.
+ // strict: Boolean?
+ // If strict, will throw an error if the deferred has already
+ // been fulfilled and consequently cannot be canceled.
+ // returns: any
+ // Returns the rejection reason if the deferred was canceled
+ // normally.
+
+ throwAbstract();
+ },
+
+ isResolved: function(){
+ // summary:
+ // Checks whether the promise has been resolved.
+ // returns: Boolean
+
+ throwAbstract();
+ },
+
+ isRejected: function(){
+ // summary:
+ // Checks whether the promise has been rejected.
+ // returns: Boolean
+
+ throwAbstract();
+ },
+
+ isFulfilled: function(){
+ // summary:
+ // Checks whether the promise has been resolved or rejected.
+ // returns: Boolean
+
+ throwAbstract();
+ },
+
+ isCanceled: function(){
+ // summary:
+ // Checks whether the promise has been canceled.
+ // returns: Boolean
+
+ throwAbstract();
+ },
+
+ "finally": function(callback) {
+ // summary:
+ // Add a callback to the promise that will fire whether it
+ // resolves or rejects.
+ // description:
+ // Conforms to ES2018's `Promise.prototype.finally`.
+ // Add a callback to the promise that will fire whether it
+ // resolves or rejects. No value is passed to the callback.
+ // Returns a promise that reflects the state of the original promise,
+ // with two exceptions:
+ // - If the callback return a promise, the outer promise will wait
+ // until the returned promise is resolved, then it will resolve
+ // with the original value.
+ // - If the callback throws an exception or returns a promise that
+ // is rejected (or rejects later), the outer promise will reject
+ // with the inner promise's rejection reason.
+ // callback: Function?
+ // Callback to be invoked when the promise is resolved
+ // or rejected. Doesn't receive any value.
+ // returns: dojo/promise/Promise
+ // Returns a new promise that reflects the state of the original promise,
+ // with two small exceptions (see description).
+ //
+
+ return this.then(function (value){
+ var valueOrPromise = callback();
+ if (valueOrPromise && typeof valueOrPromise.then === "function"){
+ return valueOrPromise.then(function (){
+ return value;
+ });
+ }
+ return value;
+ }, function(reason) {
+ var valueOrPromise = callback();
+ if (valueOrPromise && typeof valueOrPromise.then === "function"){
+ return valueOrPromise.then(function (){
+ throw reason;
+ });
+ }
+ throw reason;
+ });
+ },
+
+ always: function(callbackOrErrback){
+ // summary:
+ // Add a callback to be invoked when the promise is resolved
+ // or rejected.
+ // callbackOrErrback: Function?
+ // A function that is used both as a callback and errback.
+ // returns: dojo/promise/Promise
+ // Returns a new promise for the result of the callback/errback.
+
+ return this.then(callbackOrErrback, callbackOrErrback);
+ },
+
+ "catch": function(errback){
+ // summary:
+ // Add new errbacks to the promise. Follows ECMA specification naming.
+ // errback: Function?
+ // Callback to be invoked when the promise is rejected.
+ // returns: dojo/promise/Promise
+ // Returns a new promise for the result of the errback.
+
+ return this.then(null, errback);
+ },
+
+ otherwise: function(errback){
+ // summary:
+ // Add new errbacks to the promise.
+ // errback: Function?
+ // Callback to be invoked when the promise is rejected.
+ // returns: dojo/promise/Promise
+ // Returns a new promise for the result of the errback.
+
+ return this.then(null, errback);
+ },
+
+ trace: function(){
+ return this;
+ },
+
+ traceRejected: function(){
+ return this;
+ },
+
+ toString: function(){
+ // returns: string
+ // Returns `[object Promise]`.
+
+ return "[object Promise]";
+ }
+ });
+});
+
+},
+'dojo/promise/instrumentation':function(){
+define([
+ "./tracer",
+ "../has",
+ "../_base/lang",
+ "../_base/array"
+], function(tracer, has, lang, arrayUtil){
+ has.add("config-useDeferredInstrumentation", "report-unhandled-rejections");
+
+ function logError(error, rejection, deferred){
+ if(error && error.log === false){
+ return;
+ }
+ var stack = "";
+ if(error && error.stack){
+ stack += error.stack;
+ }
+ if(rejection && rejection.stack){
+ stack += "\n ----------------------------------------\n rejected" + rejection.stack.split("\n").slice(1).join("\n").replace(/^\s+/, " ");
+ }
+ if(deferred && deferred.stack){
+ stack += "\n ----------------------------------------\n" + deferred.stack;
+ }
+ console.error(error, stack);
+ }
+
+ function reportRejections(error, handled, rejection, deferred){
+ if(!handled){
+ logError(error, rejection, deferred);
+ }
+ }
+
+ var errors = [];
+ var activeTimeout = false;
+ var unhandledWait = 1000;
+ function trackUnhandledRejections(error, handled, rejection, deferred){
+ // try to find the existing tracking object
+ if(!arrayUtil.some(errors, function(obj){
+ if(obj.error === error){
+ // found the tracking object for this error
+ if(handled){
+ // if handled, update the state
+ obj.handled = true;
+ }
+ return true;
+ }
+ })){
+ // no tracking object has been setup, create one
+ errors.push({
+ error: error,
+ rejection: rejection,
+ handled: handled,
+ deferred: deferred,
+ timestamp: new Date().getTime()
+ });
+ }
+
+ if(!activeTimeout){
+ activeTimeout = setTimeout(logRejected, unhandledWait);
+ }
+ }
+
+ function logRejected(){
+ var now = new Date().getTime();
+ var reportBefore = now - unhandledWait;
+ errors = arrayUtil.filter(errors, function(obj){
+ // only report the error if we have waited long enough and
+ // it hasn't been handled
+ if(obj.timestamp < reportBefore){
+ if(!obj.handled){
+ logError(obj.error, obj.rejection, obj.deferred);
+ }
+ return false;
+ }
+ return true;
+ });
+
+ if(errors.length){
+ activeTimeout = setTimeout(logRejected, errors[0].timestamp + unhandledWait - now);
+ }else{
+ activeTimeout = false;
+ }
+ }
+
+ return function(Deferred){
+ // summary:
+ // Initialize instrumentation for the Deferred class.
+ // description:
+ // Initialize instrumentation for the Deferred class.
+ // Done automatically by `dojo/Deferred` if the
+ // `deferredInstrumentation` and `useDeferredInstrumentation`
+ // config options are set.
+ //
+ // Sets up `dojo/promise/tracer` to log to the console.
+ //
+ // Sets up instrumentation of rejected deferreds so unhandled
+ // errors are logged to the console.
+
+ var usage = has("config-useDeferredInstrumentation");
+ if(usage){
+ tracer.on("resolved", lang.hitch(console, "log", "resolved"));
+ tracer.on("rejected", lang.hitch(console, "log", "rejected"));
+ tracer.on("progress", lang.hitch(console, "log", "progress"));
+
+ var args = [];
+ if(typeof usage === "string"){
+ args = usage.split(",");
+ usage = args.shift();
+ }
+ if(usage === "report-rejections"){
+ Deferred.instrumentRejected = reportRejections;
+ }else if(usage === "report-unhandled-rejections" || usage === true || usage === 1){
+ Deferred.instrumentRejected = trackUnhandledRejections;
+ unhandledWait = parseInt(args[0], 10) || unhandledWait;
+ }else{
+ throw new Error("Unsupported instrumentation usage <" + usage + ">");
+ }
+ }
+ };
+});
+
+},
+'dojo/promise/tracer':function(){
+define([
+ "../_base/lang",
+ "./Promise",
+ "../Evented"
+], function(lang, Promise, Evented){
+ "use strict";
+
+ // module:
+ // dojo/promise/tracer
+
+ /*=====
+ return {
+ // summary:
+ // Trace promise fulfillment.
+ // description:
+ // Trace promise fulfillment. Calling `.trace()` or `.traceError()` on a
+ // promise enables tracing. Will emit `resolved`, `rejected` or `progress`
+ // events.
+
+ on: function(type, listener){
+ // summary:
+ // Subscribe to traces.
+ // description:
+ // See `dojo/Evented#on()`.
+ // type: String
+ // `resolved`, `rejected`, or `progress`
+ // listener: Function
+ // The listener is passed the traced value and any arguments
+ // that were used with the `.trace()` call.
+ }
+ };
+ =====*/
+
+ var evented = new Evented;
+ var emit = evented.emit;
+ evented.emit = null;
+ // Emit events asynchronously since they should not change the promise state.
+ function emitAsync(args){
+ setTimeout(function(){
+ emit.apply(evented, args);
+ }, 0);
+ }
+
+ Promise.prototype.trace = function(){
+ // summary:
+ // Trace the promise.
+ // description:
+ // Tracing allows you to transparently log progress,
+ // resolution and rejection of promises, without affecting the
+ // promise itself. Any arguments passed to `trace()` are
+ // emitted in trace events. See `dojo/promise/tracer` on how
+ // to handle traces.
+ // returns: dojo/promise/Promise
+ // The promise instance `trace()` is called on.
+
+ var args = lang._toArray(arguments);
+ this.then(
+ function(value){ emitAsync(["resolved", value].concat(args)); },
+ function(error){ emitAsync(["rejected", error].concat(args)); },
+ function(update){ emitAsync(["progress", update].concat(args)); }
+ );
+ return this;
+ };
+
+ Promise.prototype.traceRejected = function(){
+ // summary:
+ // Trace rejection of the promise.
+ // description:
+ // Tracing allows you to transparently log progress,
+ // resolution and rejection of promises, without affecting the
+ // promise itself. Any arguments passed to `trace()` are
+ // emitted in trace events. See `dojo/promise/tracer` on how
+ // to handle traces.
+ // returns: dojo/promise/Promise
+ // The promise instance `traceRejected()` is called on.
+
+ var args = lang._toArray(arguments);
+ this.otherwise(function(error){
+ emitAsync(["rejected", error].concat(args));
+ });
+ return this;
+ };
+
+ return evented;
+});
+
+},
+'dojo/Evented':function(){
+define(["./aspect", "./on"], function(aspect, on){
+ // module:
+ // dojo/Evented
+
+ "use strict";
+ var after = aspect.after;
+ function Evented(){
+ // summary:
+ // A class that can be used as a mixin or base class,
+ // to add on() and emit() methods to a class
+ // for listening for events and emitting events:
+ // example:
+ // | define(["dojo/Evented", "dojo/_base/declare", "dojo/Stateful"
+ // | ], function(Evented, declare, Stateful){
+ // | var EventedStateful = declare([Evented, Stateful], {...});
+ // | var instance = new EventedStateful();
+ // | instance.on("open", function(event){
+ // | ... do something with event
+ // | });
+ // |
+ // | instance.emit("open", {name:"some event", ...});
+ }
+ Evented.prototype = {
+ on: function(type, listener){
+ return on.parse(this, type, listener, function(target, type){
+ return after(target, 'on' + type, listener, true);
+ });
+ },
+ emit: function(type, event){
+ var args = [this];
+ args.push.apply(args, arguments);
+ return on.emit.apply(on, args);
+ }
+ };
+ return Evented;
+});
+
+},
+'dojo/aspect':function(){
+define([], function(){
+
+ // module:
+ // dojo/aspect
+
+ "use strict";
+ var undefined;
+ function advise(dispatcher, type, advice, receiveArguments){
+ var previous = dispatcher[type];
+ var around = type == "around";
+ var signal;
+ if(around){
+ var advised = advice(function(){
+ return previous.advice(this, arguments);
+ });
+ signal = {
+ remove: function(){
+ if(advised){
+ advised = dispatcher = advice = null;
+ }
+ },
+ advice: function(target, args){
+ return advised ?
+ advised.apply(target, args) : // called the advised function
+ previous.advice(target, args); // cancelled, skip to next one
+ }
+ };
+ }else{
+ // create the remove handler
+ signal = {
+ remove: function(){
+ if(signal.advice){
+ var previous = signal.previous;
+ var next = signal.next;
+ if(!next && !previous){
+ delete dispatcher[type];
+ }else{
+ if(previous){
+ previous.next = next;
+ }else{
+ dispatcher[type] = next;
+ }
+ if(next){
+ next.previous = previous;
+ }
+ }
+
+ // remove the advice to signal that this signal has been removed
+ dispatcher = advice = signal.advice = null;
+ }
+ },
+ id: dispatcher.nextId++,
+ advice: advice,
+ receiveArguments: receiveArguments
+ };
+ }
+ if(previous && !around){
+ if(type == "after"){
+ // add the listener to the end of the list
+ // note that we had to change this loop a little bit to workaround a bizarre IE10 JIT bug
+ while(previous.next && (previous = previous.next)){}
+ previous.next = signal;
+ signal.previous = previous;
+ }else if(type == "before"){
+ // add to beginning
+ dispatcher[type] = signal;
+ signal.next = previous;
+ previous.previous = signal;
+ }
+ }else{
+ // around or first one just replaces
+ dispatcher[type] = signal;
+ }
+ return signal;
+ }
+ function aspect(type){
+ return function(target, methodName, advice, receiveArguments){
+ var existing = target[methodName], dispatcher;
+ if(!existing || existing.target != target){
+ // no dispatcher in place
+ target[methodName] = dispatcher = function(){
+ var executionId = dispatcher.nextId;
+ // before advice
+ var args = arguments;
+ var before = dispatcher.before;
+ while(before){
+ if(before.advice){
+ args = before.advice.apply(this, args) || args;
+ }
+ before = before.next;
+ }
+ // around advice
+ if(dispatcher.around){
+ var results = dispatcher.around.advice(this, args);
+ }
+ // after advice
+ var after = dispatcher.after;
+ while(after && after.id < executionId){
+ if(after.advice){
+ if(after.receiveArguments){
+ var newResults = after.advice.apply(this, args);
+ // change the return value only if a new value was returned
+ results = newResults === undefined ? results : newResults;
+ }else{
+ results = after.advice.call(this, results, args);
+ }
+ }
+ after = after.next;
+ }
+ return results;
+ };
+ if(existing){
+ dispatcher.around = {advice: function(target, args){
+ return existing.apply(target, args);
+ }};
+ }
+ dispatcher.target = target;
+ dispatcher.nextId = dispatcher.nextId || 0;
+ }
+ var results = advise((dispatcher || existing), type, advice, receiveArguments);
+ advice = null;
+ return results;
+ };
+ }
+
+ // TODOC: after/before/around return object
+
+ var after = aspect("after");
+ /*=====
+ after = function(target, methodName, advice, receiveArguments){
+ // summary:
+ // The "after" export of the aspect module is a function that can be used to attach
+ // "after" advice to a method. This function will be executed after the original method
+ // is executed. By default the function will be called with a single argument, the return
+ // value of the original method, or the the return value of the last executed advice (if a previous one exists).
+ // The fourth (optional) argument can be set to true to so the function receives the original
+ // arguments (from when the original method was called) rather than the return value.
+ // If there are multiple "after" advisors, they are executed in the order they were registered.
+ // target: Object
+ // This is the target object
+ // methodName: String
+ // This is the name of the method to attach to.
+ // advice: Function
+ // This is function to be called after the original method
+ // receiveArguments: Boolean?
+ // If this is set to true, the advice function receives the original arguments (from when the original mehtod
+ // was called) rather than the return value of the original/previous method.
+ // returns:
+ // A signal object that can be used to cancel the advice. If remove() is called on this signal object, it will
+ // stop the advice function from being executed.
+ };
+ =====*/
+
+ var before = aspect("before");
+ /*=====
+ before = function(target, methodName, advice){
+ // summary:
+ // The "before" export of the aspect module is a function that can be used to attach
+ // "before" advice to a method. This function will be executed before the original method
+ // is executed. This function will be called with the arguments used to call the method.
+ // This function may optionally return an array as the new arguments to use to call
+ // the original method (or the previous, next-to-execute before advice, if one exists).
+ // If the before method doesn't return anything (returns undefined) the original arguments
+ // will be preserved.
+ // If there are multiple "before" advisors, they are executed in the reverse order they were registered.
+ // target: Object
+ // This is the target object
+ // methodName: String
+ // This is the name of the method to attach to.
+ // advice: Function
+ // This is function to be called before the original method
+ };
+ =====*/
+
+ var around = aspect("around");
+ /*=====
+ around = function(target, methodName, advice){
+ // summary:
+ // The "around" export of the aspect module is a function that can be used to attach
+ // "around" advice to a method. The advisor function is immediately executed when
+ // the around() is called, is passed a single argument that is a function that can be
+ // called to continue execution of the original method (or the next around advisor).
+ // The advisor function should return a function, and this function will be called whenever
+ // the method is called. It will be called with the arguments used to call the method.
+ // Whatever this function returns will be returned as the result of the method call (unless after advise changes it).
+ // example:
+ // If there are multiple "around" advisors, the most recent one is executed first,
+ // which can then delegate to the next one and so on. For example:
+ // | around(obj, "foo", function(originalFoo){
+ // | return function(){
+ // | var start = new Date().getTime();
+ // | var results = originalFoo.apply(this, arguments); // call the original
+ // | var end = new Date().getTime();
+ // | console.log("foo execution took " + (end - start) + " ms");
+ // | return results;
+ // | };
+ // | });
+ // target: Object
+ // This is the target object
+ // methodName: String
+ // This is the name of the method to attach to.
+ // advice: Function
+ // This is function to be called around the original method
+ };
+ =====*/
+
+ return {
+ // summary:
+ // provides aspect oriented programming functionality, allowing for
+ // one to add before, around, or after advice on existing methods.
+ // example:
+ // | define(["dojo/aspect"], function(aspect){
+ // | var signal = aspect.after(targetObject, "methodName", function(someArgument){
+ // | this will be called when targetObject.methodName() is called, after the original function is called
+ // | });
+ //
+ // example:
+ // The returned signal object can be used to cancel the advice.
+ // | signal.remove(); // this will stop the advice from being executed anymore
+ // | aspect.before(targetObject, "methodName", function(someArgument){
+ // | // this will be called when targetObject.methodName() is called, before the original function is called
+ // | });
+
+ before: before,
+ around: around,
+ after: after
+ };
+});
+
+},
+'dojo/on':function(){
+define(["./has!dom-addeventlistener?:./aspect", "./_base/kernel", "./sniff"], function(aspect, dojo, has){
+
+ "use strict";
+ if( 1 ){ // check to make sure we are in a browser, this module should work anywhere
+ var major = window.ScriptEngineMajorVersion;
+ has.add("jscript", major && (major() + ScriptEngineMinorVersion() / 10));
+ has.add("event-orientationchange", has("touch") && !has("android")); // TODO: how do we detect this?
+ has.add("event-stopimmediatepropagation", window.Event && !!window.Event.prototype && !!window.Event.prototype.stopImmediatePropagation);
+ has.add("event-focusin", function(global, doc, element){
+ return 'onfocusin' in element;
+ });
+
+ if(has("touch")){
+ has.add("touch-can-modify-event-delegate", function(){
+ // This feature test checks whether deleting a property of an event delegate works
+ // for a touch-enabled device. If it works, event delegation can be used as fallback
+ // for browsers such as Safari in older iOS where deleting properties of the original
+ // event does not work.
+ var EventDelegate = function(){};
+ EventDelegate.prototype =
+ document.createEvent("MouseEvents"); // original event
+ // Attempt to modify a property of an event delegate and check if
+ // it succeeds. Depending on browsers and on whether dojo/on's
+ // strict mode is stripped in a Dojo build, there are 3 known behaviors:
+ // it may either succeed, or raise an error, or fail to set the property
+ // without raising an error.
+ try{
+ var eventDelegate = new EventDelegate;
+ eventDelegate.target = null;
+ return eventDelegate.target === null;
+ }catch(e){
+ return false; // cannot use event delegation
+ }
+ });
+ }
+ }
+ var on = function(target, type, listener, dontFix){
+ // summary:
+ // A function that provides core event listening functionality. With this function
+ // you can provide a target, event type, and listener to be notified of
+ // future matching events that are fired.
+ // target: Element|Object
+ // This is the target object or DOM element that to receive events from
+ // type: String|Function
+ // This is the name of the event to listen for or an extension event type.
+ // listener: Function
+ // This is the function that should be called when the event fires.
+ // returns: Object
+ // An object with a remove() method that can be used to stop listening for this
+ // event.
+ // description:
+ // To listen for "click" events on a button node, we can do:
+ // | define(["dojo/on"], function(on){
+ // | on(button, "click", clickHandler);
+ // | ...
+ // Evented JavaScript objects can also have their own events.
+ // | var obj = new Evented;
+ // | on(obj, "foo", fooHandler);
+ // And then we could publish a "foo" event:
+ // | on.emit(obj, "foo", {key: "value"});
+ // We can use extension events as well. For example, you could listen for a tap gesture:
+ // | define(["dojo/on", "dojo/gesture/tap", function(on, tap){
+ // | on(button, tap, tapHandler);
+ // | ...
+ // which would trigger fooHandler. Note that for a simple object this is equivalent to calling:
+ // | obj.onfoo({key:"value"});
+ // If you use on.emit on a DOM node, it will use native event dispatching when possible.
+
+ if(typeof target.on == "function" && typeof type != "function" && !target.nodeType){
+ // delegate to the target's on() method, so it can handle it's own listening if it wants (unless it
+ // is DOM node and we may be dealing with jQuery or Prototype's incompatible addition to the
+ // Element prototype
+ return target.on(type, listener);
+ }
+ // delegate to main listener code
+ return on.parse(target, type, listener, addListener, dontFix, this);
+ };
+ on.pausable = function(target, type, listener, dontFix){
+ // summary:
+ // This function acts the same as on(), but with pausable functionality. The
+ // returned signal object has pause() and resume() functions. Calling the
+ // pause() method will cause the listener to not be called for future events. Calling the
+ // resume() method will cause the listener to again be called for future events.
+ var paused;
+ var signal = on(target, type, function(){
+ if(!paused){
+ return listener.apply(this, arguments);
+ }
+ }, dontFix);
+ signal.pause = function(){
+ paused = true;
+ };
+ signal.resume = function(){
+ paused = false;
+ };
+ return signal;
+ };
+ on.once = function(target, type, listener, dontFix){
+ // summary:
+ // This function acts the same as on(), but will only call the listener once. The
+ // listener will be called for the first
+ // event that takes place and then listener will automatically be removed.
+ var signal = on(target, type, function(){
+ // remove this listener
+ signal.remove();
+ // proceed to call the listener
+ return listener.apply(this, arguments);
+ });
+ return signal;
+ };
+ on.parse = function(target, type, listener, addListener, dontFix, matchesTarget){
+ var events;
+ if(type.call){
+ // event handler function
+ // on(node, touch.press, touchListener);
+ return type.call(matchesTarget, target, listener);
+ }
+
+ if(type instanceof Array){
+ // allow an array of event names (or event handler functions)
+ events = type;
+ }else if(type.indexOf(",") > -1){
+ // we allow comma delimited event names, so you can register for multiple events at once
+ events = type.split(/\s*,\s*/);
+ }
+ if(events){
+ var handles = [];
+ var i = 0;
+ var eventName;
+ while(eventName = events[i++]){ // intentional assignment
+ handles.push(on.parse(target, eventName, listener, addListener, dontFix, matchesTarget));
+ }
+ handles.remove = function(){
+ for(var i = 0; i < handles.length; i++){
+ handles[i].remove();
+ }
+ };
+ return handles;
+ }
+ return addListener(target, type, listener, dontFix, matchesTarget);
+ };
+ var touchEvents = /^touch/;
+ function addListener(target, type, listener, dontFix, matchesTarget){
+ // event delegation:
+ var selector = type.match(/(.*):(.*)/);
+ // if we have a selector:event, the last one is interpreted as an event, and we use event delegation
+ if(selector){
+ type = selector[2];
+ selector = selector[1];
+ // create the extension event for selectors and directly call it
+ return on.selector(selector, type).call(matchesTarget, target, listener);
+ }
+ // test to see if it a touch event right now, so we don't have to do it every time it fires
+ if(has("touch")){
+ if(touchEvents.test(type)){
+ // touch event, fix it
+ listener = fixTouchListener(listener);
+ }
+ if(!has("event-orientationchange") && (type == "orientationchange")){
+ //"orientationchange" not supported <= Android 2.1,
+ //but works through "resize" on window
+ type = "resize";
+ target = window;
+ listener = fixTouchListener(listener);
+ }
+ }
+ if(addStopImmediate){
+ // add stopImmediatePropagation if it doesn't exist
+ listener = addStopImmediate(listener);
+ }
+ // normal path, the target is |this|
+ if(target.addEventListener){
+ // the target has addEventListener, which should be used if available (might or might not be a node, non-nodes can implement this method as well)
+ // check for capture conversions
+ var capture = type in captures,
+ adjustedType = capture ? captures[type] : type;
+ target.addEventListener(adjustedType, listener, capture);
+ // create and return the signal
+ return {
+ remove: function(){
+ target.removeEventListener(adjustedType, listener, capture);
+ }
+ };
+ }
+ type = "on" + type;
+ if(fixAttach && target.attachEvent){
+ return fixAttach(target, type, listener);
+ }
+ throw new Error("Target must be an event emitter");
+ }
+ on.matches = function(node, selector, context, children, matchesTarget) {
+ // summary:
+ // Check if a node match the current selector within the constraint of a context
+ // node: DOMNode
+ // The node that originate the event
+ // selector: String
+ // The selector to check against
+ // context: DOMNode
+ // The context to search in.
+ // children: Boolean
+ // Indicates if children elements of the selector should be allowed. This defaults to
+ // true
+ // matchesTarget: Object|dojo/query?
+ // An object with a property "matches" as a function. Default is dojo/query.
+ // Matching DOMNodes will be done against this function
+ // The function must return a Boolean.
+ // It will have 3 arguments: "node", "selector" and "context"
+ // True is expected if "node" is matching the current "selector" in the passed "context"
+ // returns: DOMNode?
+ // The matching node, if any. Else you get false
+
+ // see if we have a valid matchesTarget or default to dojo/query
+ matchesTarget = matchesTarget && (typeof matchesTarget.matches == "function") ? matchesTarget : dojo.query;
+ children = children !== false;
+ // there is a selector, so make sure it matches
+ if(node.nodeType != 1){
+ // text node will fail in native match selector
+ node = node.parentNode;
+ }
+ while(!matchesTarget.matches(node, selector, context)){
+ if(node == context || children === false || !(node = node.parentNode) || node.nodeType != 1){ // intentional assignment
+ return false;
+ }
+ }
+ return node;
+ };
+ on.selector = function(selector, eventType, children){
+ // summary:
+ // Creates a new extension event with event delegation. This is based on
+ // the provided event type (can be extension event) that
+ // only calls the listener when the CSS selector matches the target of the event.
+ //
+ // The application must require() an appropriate level of dojo/query to handle the selector.
+ // selector:
+ // The CSS selector to use for filter events and determine the |this| of the event listener.
+ // eventType:
+ // The event to listen for
+ // children:
+ // Indicates if children elements of the selector should be allowed. This defaults to
+ // true
+ // example:
+ // | require(["dojo/on", "dojo/mouse", "dojo/query!css2"], function(on, mouse){
+ // | on(node, on.selector(".my-class", mouse.enter), handlerForMyHover);
+ return function(target, listener){
+ // if the selector is function, use it to select the node, otherwise use the matches method
+ var matchesTarget = typeof selector == "function" ? {matches: selector} : this,
+ bubble = eventType.bubble;
+ function select(eventTarget){
+ return on.matches(eventTarget, selector, target, children, matchesTarget);
+ }
+ if(bubble){
+ // the event type doesn't naturally bubble, but has a bubbling form, use that, and give it the selector so it can perform the select itself
+ return on(target, bubble(select), listener);
+ }
+ // standard event delegation
+ return on(target, eventType, function(event){
+ // call select to see if we match
+ var eventTarget = select(event.target);
+ // if it matches we call the listener
+ if (eventTarget) {
+ // We save the matching target into the event, so it can be accessed even when hitching (see #18355)
+ event.selectorTarget = eventTarget;
+ return listener.call(eventTarget, event);
+ }
+ });
+ };
+ };
+
+ function syntheticPreventDefault(){
+ this.cancelable = false;
+ this.defaultPrevented = true;
+ }
+ function syntheticStopPropagation(){
+ this.bubbles = false;
+ }
+ var slice = [].slice,
+ syntheticDispatch = on.emit = function(target, type, event){
+ // summary:
+ // Fires an event on the target object.
+ // target:
+ // The target object to fire the event on. This can be a DOM element or a plain
+ // JS object. If the target is a DOM element, native event emitting mechanisms
+ // are used when possible.
+ // type:
+ // The event type name. You can emulate standard native events like "click" and
+ // "mouseover" or create custom events like "open" or "finish".
+ // event:
+ // An object that provides the properties for the event. See https://developer.mozilla.org/en/DOM/event.initEvent
+ // for some of the properties. These properties are copied to the event object.
+ // Of particular importance are the cancelable and bubbles properties. The
+ // cancelable property indicates whether or not the event has a default action
+ // that can be cancelled. The event is cancelled by calling preventDefault() on
+ // the event object. The bubbles property indicates whether or not the
+ // event will bubble up the DOM tree. If bubbles is true, the event will be called
+ // on the target and then each parent successively until the top of the tree
+ // is reached or stopPropagation() is called. Both bubbles and cancelable
+ // default to false.
+ // returns:
+ // If the event is cancelable and the event is not cancelled,
+ // emit will return true. If the event is cancelable and the event is cancelled,
+ // emit will return false.
+ // details:
+ // Note that this is designed to emit events for listeners registered through
+ // dojo/on. It should actually work with any event listener except those
+ // added through IE's attachEvent (IE8 and below's non-W3C event emitting
+ // doesn't support custom event types). It should work with all events registered
+ // through dojo/on. Also note that the emit method does do any default
+ // action, it only returns a value to indicate if the default action should take
+ // place. For example, emitting a keypress event would not cause a character
+ // to appear in a textbox.
+ // example:
+ // To fire our own click event
+ // | require(["dojo/on", "dojo/dom"
+ // | ], function(on, dom){
+ // | on.emit(dom.byId("button"), "click", {
+ // | cancelable: true,
+ // | bubbles: true,
+ // | screenX: 33,
+ // | screenY: 44
+ // | });
+ // We can also fire our own custom events:
+ // | on.emit(dom.byId("slider"), "slide", {
+ // | cancelable: true,
+ // | bubbles: true,
+ // | direction: "left-to-right"
+ // | });
+ // | });
+ var args = slice.call(arguments, 2);
+ var method = "on" + type;
+ if("parentNode" in target){
+ // node (or node-like), create event controller methods
+ var newEvent = args[0] = {};
+ for(var i in event){
+ newEvent[i] = event[i];
+ }
+ newEvent.preventDefault = syntheticPreventDefault;
+ newEvent.stopPropagation = syntheticStopPropagation;
+ newEvent.target = target;
+ newEvent.type = type;
+ event = newEvent;
+ }
+ do{
+ // call any node which has a handler (note that ideally we would try/catch to simulate normal event propagation but that causes too much pain for debugging)
+ target[method] && target[method].apply(target, args);
+ // and then continue up the parent node chain if it is still bubbling (if started as bubbles and stopPropagation hasn't been called)
+ }while(event && event.bubbles && (target = target.parentNode));
+ return event && event.cancelable && event; // if it is still true (was cancelable and was cancelled), return the event to indicate default action should happen
+ };
+ var captures = has("event-focusin") ? {} : {focusin: "focus", focusout: "blur"};
+ if(!has("event-stopimmediatepropagation")){
+ var stopImmediatePropagation =function(){
+ this.immediatelyStopped = true;
+ this.modified = true; // mark it as modified so the event will be cached in IE
+ };
+ var addStopImmediate = function(listener){
+ return function(event){
+ if(!event.immediatelyStopped){// check to make sure it hasn't been stopped immediately
+ event.stopImmediatePropagation = stopImmediatePropagation;
+ return listener.apply(this, arguments);
+ }
+ };
+ };
+ }
+ if(has("dom-addeventlistener")){
+ // emitter that works with native event handling
+ on.emit = function(target, type, event){
+ if(target.dispatchEvent && document.createEvent){
+ // use the native event emitting mechanism if it is available on the target object
+ // create a generic event
+ // we could create branch into the different types of event constructors, but
+ // that would be a lot of extra code, with little benefit that I can see, seems
+ // best to use the generic constructor and copy properties over, making it
+ // easy to have events look like the ones created with specific initializers
+ var ownerDocument = target.ownerDocument || document;
+ var nativeEvent = ownerDocument.createEvent("HTMLEvents");
+ nativeEvent.initEvent(type, !!event.bubbles, !!event.cancelable);
+ // and copy all our properties over
+ for(var i in event){
+ if(!(i in nativeEvent)){
+ nativeEvent[i] = event[i];
+ }
+ }
+ return target.dispatchEvent(nativeEvent) && nativeEvent;
+ }
+ return syntheticDispatch.apply(on, arguments); // emit for a non-node
+ };
+ }else{
+ // no addEventListener, basically old IE event normalization
+ on._fixEvent = function(evt, sender){
+ // summary:
+ // normalizes properties on the event object including event
+ // bubbling methods, keystroke normalization, and x/y positions
+ // evt:
+ // native event object
+ // sender:
+ // node to treat as "currentTarget"
+ if(!evt){
+ var w = sender && (sender.ownerDocument || sender.document || sender).parentWindow || window;
+ evt = w.event;
+ }
+ if(!evt){return evt;}
+ try{
+ if(lastEvent && evt.type == lastEvent.type && evt.srcElement == lastEvent.target){
+ // should be same event, reuse event object (so it can be augmented);
+ // accessing evt.srcElement rather than evt.target since evt.target not set on IE until fixup below
+ evt = lastEvent;
+ }
+ }catch(e){
+ // will occur on IE on lastEvent.type reference if lastEvent points to a previous event that already
+ // finished bubbling, but the setTimeout() to clear lastEvent hasn't fired yet
+ }
+ if(!evt.target){ // check to see if it has been fixed yet
+ evt.target = evt.srcElement;
+ evt.currentTarget = (sender || evt.srcElement);
+ if(evt.type == "mouseover"){
+ evt.relatedTarget = evt.fromElement;
+ }
+ if(evt.type == "mouseout"){
+ evt.relatedTarget = evt.toElement;
+ }
+ if(!evt.stopPropagation){
+ evt.stopPropagation = stopPropagation;
+ evt.preventDefault = preventDefault;
+ }
+ switch(evt.type){
+ case "keypress":
+ var c = ("charCode" in evt ? evt.charCode : evt.keyCode);
+ if (c==10){
+ // CTRL-ENTER is CTRL-ASCII(10) on IE, but CTRL-ENTER on Mozilla
+ c=0;
+ evt.keyCode = 13;
+ }else if(c==13||c==27){
+ c=0; // Mozilla considers ENTER and ESC non-printable
+ }else if(c==3){
+ c=99; // Mozilla maps CTRL-BREAK to CTRL-c
+ }
+ // Mozilla sets keyCode to 0 when there is a charCode
+ // but that stops the event on IE.
+ evt.charCode = c;
+ _setKeyChar(evt);
+ break;
+ }
+ }
+ return evt;
+ };
+ var lastEvent, IESignal = function(handle){
+ this.handle = handle;
+ };
+ IESignal.prototype.remove = function(){
+ delete _dojoIEListeners_[this.handle];
+ };
+ var fixListener = function(listener){
+ // this is a minimal function for closing on the previous listener with as few as variables as possible
+ return function(evt){
+ evt = on._fixEvent(evt, this);
+ var result = listener.call(this, evt);
+ if(evt.modified){
+ // cache the last event and reuse it if we can
+ if(!lastEvent){
+ setTimeout(function(){
+ lastEvent = null;
+ });
+ }
+ lastEvent = evt;
+ }
+ return result;
+ };
+ };
+ var fixAttach = function(target, type, listener){
+ listener = fixListener(listener);
+ if(((target.ownerDocument ? target.ownerDocument.parentWindow : target.parentWindow || target.window || window) != top ||
+ has("jscript") < 5.8) &&
+ !has("config-_allow_leaks")){
+ // IE will leak memory on certain handlers in frames (IE8 and earlier) and in unattached DOM nodes for JScript 5.7 and below.
+ // Here we use global redirection to solve the memory leaks
+ if(typeof _dojoIEListeners_ == "undefined"){
+ _dojoIEListeners_ = [];
+ }
+ var emitter = target[type];
+ if(!emitter || !emitter.listeners){
+ var oldListener = emitter;
+ emitter = Function('event', 'var callee = arguments.callee; for(var i = 0; i 1){
+ return callback ? callback(valueOrPromise) : valueOrPromise;
+ }else{
+ return new Deferred().resolve(valueOrPromise);
+ }
+ }else if(!nativePromise){
+ var deferred = new Deferred(valueOrPromise.cancel);
+ valueOrPromise.then(deferred.resolve, deferred.reject, deferred.progress);
+ valueOrPromise = deferred.promise;
+ }
+
+ if(callback || errback || progback){
+ return valueOrPromise.then(callback, errback, progback);
+ }
+ return valueOrPromise;
+ };
+});
+
+},
+'dojo/_base/json':function(){
+define(["./kernel", "../json"], function(dojo, json){
+
+// module:
+// dojo/_base/json
+
+/*=====
+return {
+ // summary:
+ // This module defines the dojo JSON API.
+};
+=====*/
+
+dojo.fromJson = function(/*String*/ js){
+ // summary:
+ // Parses a JavaScript expression and returns a JavaScript value.
+ // description:
+ // Throws for invalid JavaScript expressions. It does not use a strict JSON parser. It
+ // always delegates to eval(). The content passed to this method must therefore come
+ // from a trusted source.
+ // It is recommend that you use dojo/json's parse function for an
+ // implementation uses the (faster) native JSON parse when available.
+ // js:
+ // a string literal of a JavaScript expression, for instance:
+ // `'{ "foo": [ "bar", 1, { "baz": "thud" } ] }'`
+
+ return eval("(" + js + ")"); // Object
+};
+
+/*=====
+dojo._escapeString = function(){
+ // summary:
+ // Adds escape sequences for non-visual characters, double quote and
+ // backslash and surrounds with double quotes to form a valid string
+ // literal.
+};
+=====*/
+dojo._escapeString = json.stringify; // just delegate to json.stringify
+
+dojo.toJsonIndentStr = "\t";
+dojo.toJson = function(/*Object*/ it, /*Boolean?*/ prettyPrint){
+ // summary:
+ // Returns a [JSON](http://json.org) serialization of an object.
+ // description:
+ // Returns a [JSON](http://json.org) serialization of an object.
+ // Note that this doesn't check for infinite recursion, so don't do that!
+ // It is recommend that you use dojo/json's stringify function for an lighter
+ // and faster implementation that matches the native JSON API and uses the
+ // native JSON serializer when available.
+ // it:
+ // an object to be serialized. Objects may define their own
+ // serialization via a special "__json__" or "json" function
+ // property. If a specialized serializer has been defined, it will
+ // be used as a fallback.
+ // Note that in 1.6, toJson would serialize undefined, but this no longer supported
+ // since it is not supported by native JSON serializer.
+ // prettyPrint:
+ // if true, we indent objects and arrays to make the output prettier.
+ // The variable `dojo.toJsonIndentStr` is used as the indent string --
+ // to use something other than the default (tab), change that variable
+ // before calling dojo.toJson().
+ // Note that if native JSON support is available, it will be used for serialization,
+ // and native implementations vary on the exact spacing used in pretty printing.
+ // returns:
+ // A JSON string serialization of the passed-in object.
+ // example:
+ // simple serialization of a trivial object
+ // | var jsonStr = dojo.toJson({ howdy: "stranger!", isStrange: true });
+ // | doh.is('{"howdy":"stranger!","isStrange":true}', jsonStr);
+ // example:
+ // a custom serializer for an objects of a particular class:
+ // | dojo.declare("Furby", null, {
+ // | furbies: "are strange",
+ // | furbyCount: 10,
+ // | __json__: function(){
+ // | },
+ // | });
+
+ // use dojo/json
+ return json.stringify(it, function(key, value){
+ if(value){
+ var tf = value.__json__||value.json;
+ if(typeof tf == "function"){
+ return tf.call(value);
+ }
+ }
+ return value;
+ }, prettyPrint && dojo.toJsonIndentStr); // String
+};
+
+return dojo;
+});
+
+},
+'dojo/request/watch':function(){
+define([
+ './util',
+ '../errors/RequestTimeoutError',
+ '../errors/CancelError',
+ '../_base/array',
+ '../_base/window',
+ '../has!host-browser?dom-addeventlistener?:../on:'
+], function(util, RequestTimeoutError, CancelError, array, win, on){
+ // avoid setting a timer per request. It degrades performance on IE
+ // something fierece if we don't use unified loops.
+ var _inFlightIntvl = null,
+ _inFlight = [];
+
+ function watchInFlight(){
+ // summary:
+ // internal method that checks each inflight XMLHttpRequest to see
+ // if it has completed or if the timeout situation applies.
+
+ var now = +(new Date);
+
+ // we need manual loop because we often modify _inFlight (and therefore 'i') while iterating
+ for(var i = 0, dfd; i < _inFlight.length && (dfd = _inFlight[i]); i++){
+ var response = dfd.response,
+ options = response.options;
+ if((dfd.isCanceled && dfd.isCanceled()) || (dfd.isValid && !dfd.isValid(response))){
+ _inFlight.splice(i--, 1);
+ watch._onAction && watch._onAction();
+ }else if(dfd.isReady && dfd.isReady(response)){
+ _inFlight.splice(i--, 1);
+ dfd.handleResponse(response);
+ watch._onAction && watch._onAction();
+ }else if(dfd.startTime){
+ // did we timeout?
+ if(dfd.startTime + (options.timeout || 0) < now){
+ _inFlight.splice(i--, 1);
+ // Cancel the request so the io module can do appropriate cleanup.
+ dfd.cancel(new RequestTimeoutError('Timeout exceeded', response));
+ watch._onAction && watch._onAction();
+ }
+ }
+ }
+
+ watch._onInFlight && watch._onInFlight(dfd);
+
+ if(!_inFlight.length){
+ clearInterval(_inFlightIntvl);
+ _inFlightIntvl = null;
+ }
+ }
+
+ function watch(dfd){
+ // summary:
+ // Watches the io request represented by dfd to see if it completes.
+ // dfd: Deferred
+ // The Deferred object to watch.
+ // response: Object
+ // The object used as the value of the request promise.
+ // validCheck: Function
+ // Function used to check if the IO request is still valid. Gets the dfd
+ // object as its only argument.
+ // ioCheck: Function
+ // Function used to check if basic IO call worked. Gets the dfd
+ // object as its only argument.
+ // resHandle: Function
+ // Function used to process response. Gets the dfd
+ // object as its only argument.
+ if(dfd.response.options.timeout){
+ dfd.startTime = +(new Date);
+ }
+
+ if(dfd.isFulfilled()){
+ // bail out if the deferred is already fulfilled
+ return;
+ }
+
+ _inFlight.push(dfd);
+ if(!_inFlightIntvl){
+ _inFlightIntvl = setInterval(watchInFlight, 50);
+ }
+
+ // handle sync requests separately from async:
+ // http://bugs.dojotoolkit.org/ticket/8467
+ if(dfd.response.options.sync){
+ watchInFlight();
+ }
+ }
+
+ watch.cancelAll = function cancelAll(){
+ // summary:
+ // Cancels all pending IO requests, regardless of IO type
+ try{
+ array.forEach(_inFlight, function(dfd){
+ try{
+ dfd.cancel(new CancelError('All requests canceled.'));
+ }catch(e){}
+ });
+ }catch(e){}
+ };
+
+ if(win && on && win.doc.attachEvent){
+ // Automatically call cancel all io calls on unload in IE
+ // http://bugs.dojotoolkit.org/ticket/2357
+ on(win.global, 'unload', function(){
+ watch.cancelAll();
+ });
+ }
+
+ return watch;
+});
+
+},
+'dojo/request/util':function(){
+define([
+ 'exports',
+ '../errors/RequestError',
+ '../errors/CancelError',
+ '../Deferred',
+ '../io-query',
+ '../_base/array',
+ '../_base/lang',
+ '../promise/Promise',
+ '../has'
+], function(exports, RequestError, CancelError, Deferred, ioQuery, array, lang, Promise, has){
+
+ function isArrayBuffer(value) {
+ return has('native-arraybuffer') && value instanceof ArrayBuffer
+ }
+
+ function isBlob(value) {
+ return has('native-blob') && value instanceof Blob
+ }
+
+ function isElement(value) {
+ if(typeof Element !== 'undefined') { //all other
+ return value instanceof Element;
+ }
+
+ //IE<=7
+ return value.nodeType === 1;
+ }
+
+ function isFormData(value) {
+ return has('native-formdata') && value instanceof FormData;
+ }
+
+ function shouldDeepCopy(value) {
+ return value &&
+ typeof value === 'object' &&
+ !isFormData(value) &&
+ !isElement(value) &&
+ !isBlob(value) &&
+ !isArrayBuffer(value)
+ }
+
+ exports.deepCopy = function(target, source) {
+ for (var name in source) {
+ var tval = target[name],
+ sval = source[name];
+ if (name !== '__proto__' && tval !== sval) {
+ if (shouldDeepCopy(sval)) {
+ if (Object.prototype.toString.call(sval) === '[object Date]') { // use this date test to handle crossing frame boundaries
+ target[name] = new Date(sval);
+ } else if (lang.isArray(sval)) {
+ target[name] = exports.deepCopyArray(sval);
+ } else {
+ if (tval && typeof tval === 'object') {
+ exports.deepCopy(tval, sval);
+ } else {
+ target[name] = exports.deepCopy({}, sval);
+ }
+ }
+ } else {
+ target[name] = sval;
+ }
+ }
+ }
+ return target;
+ };
+
+ exports.deepCopyArray = function(source) {
+ var clonedArray = [];
+ for (var i = 0, l = source.length; i < l; i++) {
+ var svalItem = source[i];
+ if (typeof svalItem === 'object') {
+ clonedArray.push(exports.deepCopy({}, svalItem));
+ } else {
+ clonedArray.push(svalItem);
+ }
+ }
+
+ return clonedArray;
+ };
+
+ exports.deepCreate = function deepCreate(source, properties){
+ properties = properties || {};
+ var target = lang.delegate(source),
+ name, value;
+
+ for(name in source){
+ value = source[name];
+
+ if(value && typeof value === 'object'){
+ target[name] = exports.deepCreate(value, properties[name]);
+ }
+ }
+ return exports.deepCopy(target, properties);
+ };
+
+ var freeze = Object.freeze || function(obj){ return obj; };
+ function okHandler(response){
+ return freeze(response);
+ }
+ function dataHandler (response) {
+ return response.data !== undefined ? response.data : response.text;
+ }
+
+ exports.deferred = function deferred(response, cancel, isValid, isReady, handleResponse, last){
+ var def = new Deferred(function(reason){
+ cancel && cancel(def, response);
+
+ if(!reason || !(reason instanceof RequestError) && !(reason instanceof CancelError)){
+ return new CancelError('Request canceled', response);
+ }
+ return reason;
+ });
+
+ def.response = response;
+ def.isValid = isValid;
+ def.isReady = isReady;
+ def.handleResponse = handleResponse;
+
+ function errHandler(error){
+ error.response = response;
+ throw error;
+ }
+ var responsePromise = def.then(okHandler).otherwise(errHandler);
+
+ if(exports.notify){
+ responsePromise.then(
+ lang.hitch(exports.notify, 'emit', 'load'),
+ lang.hitch(exports.notify, 'emit', 'error')
+ );
+ }
+
+ var dataPromise = responsePromise.then(dataHandler);
+
+ // http://bugs.dojotoolkit.org/ticket/16794
+ // The following works around a leak in IE9 through the
+ // prototype using lang.delegate on dataPromise and
+ // assigning the result a property with a reference to
+ // responsePromise.
+ var promise = new Promise();
+ for (var prop in dataPromise) {
+ if (dataPromise.hasOwnProperty(prop)) {
+ promise[prop] = dataPromise[prop];
+ }
+ }
+ promise.response = responsePromise;
+ freeze(promise);
+ // End leak fix
+
+
+ if(last){
+ def.then(function(response){
+ last.call(def, response);
+ }, function(error){
+ last.call(def, response, error);
+ });
+ }
+
+ def.promise = promise;
+ def.then = promise.then;
+
+ return def;
+ };
+
+ exports.addCommonMethods = function addCommonMethods(provider, methods){
+ array.forEach(methods||['GET', 'POST', 'PUT', 'DELETE'], function(method){
+ provider[(method === 'DELETE' ? 'DEL' : method).toLowerCase()] = function(url, options){
+ options = lang.delegate(options||{});
+ options.method = method;
+ return provider(url, options);
+ };
+ });
+ };
+
+ exports.parseArgs = function parseArgs(url, options, skipData){
+ var data = options.data,
+ query = options.query;
+
+ if(data && !skipData){
+ if(typeof data === 'object' && (!(has('native-xhr2')) || !(isArrayBuffer(data) || isBlob(data) ))){
+ options.data = ioQuery.objectToQuery(data);
+ }
+ }
+
+ if(query){
+ if(typeof query === 'object'){
+ query = ioQuery.objectToQuery(query);
+ }
+ if(options.preventCache){
+ query += (query ? '&' : '') + 'request.preventCache=' + (+(new Date));
+ }
+ }else if(options.preventCache){
+ query = 'request.preventCache=' + (+(new Date));
+ }
+
+ if(url && query){
+ url += (~url.indexOf('?') ? '&' : '?') + query;
+ }
+
+ return {
+ url: url,
+ options: options,
+ getHeader: function(headerName){ return null; }
+ };
+ };
+
+ exports.checkStatus = function(stat){
+ stat = stat || 0;
+ return (stat >= 200 && stat < 300) || // allow any 2XX response code
+ stat === 304 || // or, get it out of the cache
+ stat === 1223 || // or, Internet Explorer mangled the status code
+ !stat; // or, we're Titanium/browser chrome/chrome extension requesting a local file
+ };
+});
+
+},
+'dojo/errors/RequestError':function(){
+define(['./create'], function(create){
+ // module:
+ // dojo/errors/RequestError
+
+ /*=====
+ return function(){
+ // summary:
+ // TODOC
+ };
+ =====*/
+
+ return create("RequestError", function(message, response){
+ this.response = response;
+ });
+});
+
+},
+'dojo/errors/RequestTimeoutError':function(){
+define(['./create', './RequestError'], function(create, RequestError){
+ // module:
+ // dojo/errors/RequestTimeoutError
+
+ /*=====
+ return function(){
+ // summary:
+ // TODOC
+ };
+ =====*/
+
+ return create("RequestTimeoutError", null, RequestError, {
+ dojoType: "timeout"
+ });
+});
+
+},
+'dojo/request/xhr':function(){
+define([
+ '../errors/RequestError',
+ './watch',
+ './handlers',
+ './util',
+ '../has'/*=====,
+ '../request',
+ '../_base/declare' =====*/
+], function(RequestError, watch, handlers, util, has/*=====, request, declare =====*/){
+ has.add('native-xhr', function(){
+ // if true, the environment has a native XHR implementation
+ return typeof XMLHttpRequest !== 'undefined';
+ });
+ has.add('dojo-force-activex-xhr', function(){
+ return has('activex') && window.location.protocol === 'file:';
+ });
+
+ has.add('native-xhr2', function(){
+ if(!has('native-xhr') || has('dojo-force-activex-xhr')){ return; }
+ var x = new XMLHttpRequest();
+ return typeof x['addEventListener'] !== 'undefined' &&
+ (typeof opera === 'undefined' || typeof x['upload'] !== 'undefined');
+ });
+
+ has.add('native-formdata', function(){
+ // if true, the environment has a native FormData implementation
+ return typeof FormData !== 'undefined';
+ });
+
+ has.add('native-blob', function(){
+ // if true, the environment has a native Blob implementation
+ return typeof Blob !== 'undefined';
+ });
+
+ has.add('native-arraybuffer', function(){
+ // if true, the environment has a native ArrayBuffer implementation
+ return typeof ArrayBuffer !== 'undefined';
+ });
+
+ has.add('native-response-type', function(){
+ return has('native-xhr') && typeof new XMLHttpRequest().responseType !== 'undefined';
+ });
+
+ has.add('native-xhr2-blob', function(){
+ if(!has('native-response-type')){ return; }
+ var x = new XMLHttpRequest();
+ // The URL used here does not have to be reachable as the XHR's `send` method is never called.
+ // It does need to be parsable/resolvable in all cases, so it should be an absolute URL.
+ // XMLHttpRequest within a Worker created from a Blob does not support relative URL paths.
+ x.open('GET', 'https://dojotoolkit.org/', true);
+ x.responseType = 'blob';
+ // will not be set if unsupported
+ var responseType = x.responseType;
+ x.abort();
+ return responseType === 'blob';
+ });
+
+ // Google Chrome doesn't support "json" response type
+ // up to version 30, so it's intentionally not included here
+ var nativeResponseTypes = {
+ 'blob': has('native-xhr2-blob') ? 'blob' : 'arraybuffer',
+ 'document': 'document',
+ 'arraybuffer': 'arraybuffer'
+ };
+
+ function handleResponse(response, error){
+ var _xhr = response.xhr;
+ response.status = response.xhr.status;
+
+ try {
+ // Firefox throws an error when trying to access
+ // xhr.responseText if response isn't text
+ response.text = _xhr.responseText;
+ } catch (e) {}
+
+ if(response.options.handleAs === 'xml'){
+ response.data = _xhr.responseXML;
+ }
+
+ var handleError;
+ if(error){
+ this.reject(error);
+ }else{
+ try{
+ handlers(response);
+ }catch(e){
+ handleError = e;
+ }
+ if(util.checkStatus(_xhr.status)){
+ if(!handleError){
+ this.resolve(response);
+ }else{
+ this.reject(handleError);
+ }
+ }else{
+ if(!handleError){
+ error = new RequestError('Unable to load ' + response.url + ' status: ' + _xhr.status, response);
+ this.reject(error);
+ }else{
+ error = new RequestError('Unable to load ' + response.url + ' status: ' + _xhr.status +
+ ' and an error in handleAs: transformation of response', response);
+ this.reject(error);
+ }
+ }
+ }
+ }
+
+ var isValid, isReady, addListeners, cancel;
+ if(has('native-xhr2')){
+ // Any platform with XHR2 will only use the watch mechanism for timeout.
+
+ isValid = function(response){
+ // summary:
+ // Check to see if the request should be taken out of the watch queue
+ return !this.isFulfilled();
+ };
+ cancel = function(dfd, response){
+ // summary:
+ // Canceler for deferred
+ response.xhr.abort();
+ };
+ addListeners = function(_xhr, dfd, response, uploadProgress){
+ // summary:
+ // Adds event listeners to the XMLHttpRequest object
+ function onLoad(evt){
+ dfd.handleResponse(response);
+ }
+ function onError(evt){
+ var _xhr = evt.target;
+ var error = new RequestError('Unable to load ' + response.url + ' status: ' + _xhr.status, response);
+ dfd.handleResponse(response, error);
+ }
+
+ function onProgress(transferType, evt){
+ response.transferType = transferType;
+ if(evt.lengthComputable){
+ response.loaded = evt.loaded;
+ response.total = evt.total;
+ dfd.progress(response);
+ } else if(response.xhr.readyState === 3){
+ response.loaded = ('loaded' in evt) ? evt.loaded : evt.position;
+ dfd.progress(response);
+ }
+ }
+
+ function onDownloadProgress(evt) {
+ return onProgress('download', evt);
+ }
+
+ function onUploadProgress(evt) {
+ return onProgress('upload', evt);
+ }
+
+ _xhr.addEventListener('load', onLoad, false);
+ _xhr.addEventListener('error', onError, false);
+ _xhr.addEventListener('progress', onDownloadProgress, false);
+
+ if (uploadProgress && _xhr.upload) {
+ _xhr.upload.addEventListener('progress', onUploadProgress, false);
+ }
+
+ return function(){
+ _xhr.removeEventListener('load', onLoad, false);
+ _xhr.removeEventListener('error', onError, false);
+ _xhr.removeEventListener('progress', onDownloadProgress, false);
+ _xhr.upload.removeEventListener('progress', onUploadProgress, false);
+ _xhr = null;
+ };
+ };
+ }else{
+ isValid = function(response){
+ return response.xhr.readyState; //boolean
+ };
+ isReady = function(response){
+ return 4 === response.xhr.readyState; //boolean
+ };
+ cancel = function(dfd, response){
+ // summary:
+ // canceller function for util.deferred call.
+ var xhr = response.xhr;
+ var _at = typeof xhr.abort;
+ if(_at === 'function' || _at === 'object' || _at === 'unknown'){
+ xhr.abort();
+ }
+ };
+ }
+
+ function getHeader(headerName){
+ return this.xhr.getResponseHeader(headerName);
+ }
+
+ var undefined,
+ defaultOptions = {
+ data: null,
+ query: null,
+ sync: false,
+ method: 'GET'
+ };
+ function xhr(url, options, returnDeferred){
+ var isFormData = has('native-formdata') && options && options.data && options.data instanceof FormData;
+ var response = util.parseArgs(
+ url,
+ util.deepCreate(defaultOptions, options),
+ isFormData
+ );
+ url = response.url;
+ options = response.options;
+ var hasNoData = !options.data && options.method !== 'POST' && options.method !== 'PUT';
+
+ if(has('ie') <= 10){
+ // older IE breaks point 9 in http://www.w3.org/TR/XMLHttpRequest/#the-open()-method and sends fragment, so strip it
+ url = url.split('#')[0];
+ }
+
+ var remover,
+ last = function(){
+ remover && remover();
+ };
+
+ //Make the Deferred object for this xhr request.
+ var dfd = util.deferred(
+ response,
+ cancel,
+ isValid,
+ isReady,
+ handleResponse,
+ last
+ );
+ var _xhr = response.xhr = xhr._create();
+
+ if(!_xhr){
+ // If XHR factory somehow returns nothings,
+ // cancel the deferred.
+ dfd.cancel(new RequestError('XHR was not created'));
+ return returnDeferred ? dfd : dfd.promise;
+ }
+
+ response.getHeader = getHeader;
+
+ if(addListeners){
+ remover = addListeners(_xhr, dfd, response, options.uploadProgress);
+ }
+
+ // IE11 treats data: undefined different than other browsers
+ var data = typeof(options.data) === 'undefined' ? null : options.data,
+ async = !options.sync,
+ method = options.method;
+
+ try{
+ // IE6 won't let you call apply() on the native function.
+ _xhr.open(method, url, async, options.user || undefined, options.password || undefined);
+
+ if(options.withCredentials){
+ _xhr.withCredentials = options.withCredentials;
+ }
+
+ if(has('native-response-type') && options.handleAs in nativeResponseTypes) {
+ _xhr.responseType = nativeResponseTypes[options.handleAs];
+ }
+
+ var headers = options.headers,
+ contentType = (isFormData || hasNoData) ? false : 'application/x-www-form-urlencoded';
+ if(headers){
+ for(var hdr in headers){
+ if(hdr.toLowerCase() === 'content-type'){
+ contentType = headers[hdr];
+ }else if(headers[hdr]){
+ //Only add header if it has a value. This allows for instance, skipping
+ //insertion of X-Requested-With by specifying empty value.
+ _xhr.setRequestHeader(hdr, headers[hdr]);
+ }
+ }
+ }
+
+ if(contentType && contentType !== false){
+ _xhr.setRequestHeader('Content-Type', contentType);
+ }
+ if(!headers || !('X-Requested-With' in headers)){
+ _xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
+ }
+
+ if(util.notify){
+ util.notify.emit('send', response, dfd.promise.cancel);
+ }
+ _xhr.send(data);
+ }catch(e){
+ dfd.reject(e);
+ }
+
+ watch(dfd);
+ _xhr = null;
+
+ return returnDeferred ? dfd : dfd.promise;
+ }
+
+ /*=====
+ xhr = function(url, options){
+ // summary:
+ // Sends a request using XMLHttpRequest with the given URL and options.
+ // url: String
+ // URL to request
+ // options: dojo/request/xhr.__Options?
+ // Options for the request.
+ // returns: dojo/request.__Promise
+ };
+ xhr.__BaseOptions = declare(request.__BaseOptions, {
+ // sync: Boolean?
+ // Whether to make a synchronous request or not. Default
+ // is `false` (asynchronous).
+ // data: String|Object|FormData?
+ // Data to transfer. This is ignored for GET and DELETE
+ // requests.
+ // headers: Object?
+ // Headers to use for the request.
+ // user: String?
+ // Username to use during the request.
+ // password: String?
+ // Password to use during the request.
+ // withCredentials: Boolean?
+ // For cross-site requests, whether to send credentials
+ // or not.
+ // uploadProgress: Boolean?
+ // Upload progress events cause preflighted requests. This
+ // option enables upload progress event support but also
+ // causes all requests to be preflighted.
+ });
+ xhr.__MethodOptions = declare(null, {
+ // method: String?
+ // The HTTP method to use to make the request. Must be
+ // uppercase. Default is `"GET"`.
+ });
+ xhr.__Options = declare([xhr.__BaseOptions, xhr.__MethodOptions]);
+
+ xhr.get = function(url, options){
+ // summary:
+ // Send an HTTP GET request using XMLHttpRequest with the given URL and options.
+ // url: String
+ // URL to request
+ // options: dojo/request/xhr.__BaseOptions?
+ // Options for the request.
+ // returns: dojo/request.__Promise
+ };
+ xhr.post = function(url, options){
+ // summary:
+ // Send an HTTP POST request using XMLHttpRequest with the given URL and options.
+ // url: String
+ // URL to request
+ // options: dojo/request/xhr.__BaseOptions?
+ // Options for the request.
+ // returns: dojo/request.__Promise
+ };
+ xhr.put = function(url, options){
+ // summary:
+ // Send an HTTP PUT request using XMLHttpRequest with the given URL and options.
+ // url: String
+ // URL to request
+ // options: dojo/request/xhr.__BaseOptions?
+ // Options for the request.
+ // returns: dojo/request.__Promise
+ };
+ xhr.del = function(url, options){
+ // summary:
+ // Send an HTTP DELETE request using XMLHttpRequest with the given URL and options.
+ // url: String
+ // URL to request
+ // options: dojo/request/xhr.__BaseOptions?
+ // Options for the request.
+ // returns: dojo/request.__Promise
+ };
+ =====*/
+ xhr._create = function(){
+ // summary:
+ // does the work of portably generating a new XMLHTTPRequest object.
+ throw new Error('XMLHTTP not available');
+ };
+ if(has('native-xhr') && !has('dojo-force-activex-xhr')){
+ xhr._create = function(){
+ return new XMLHttpRequest();
+ };
+ }else if(has('activex')){
+ try{
+ new ActiveXObject('Msxml2.XMLHTTP');
+ xhr._create = function(){
+ return new ActiveXObject('Msxml2.XMLHTTP');
+ };
+ }catch(e){
+ try{
+ new ActiveXObject('Microsoft.XMLHTTP');
+ xhr._create = function(){
+ return new ActiveXObject('Microsoft.XMLHTTP');
+ };
+ }catch(e){}
+ }
+ }
+
+ util.addCommonMethods(xhr);
+
+ return xhr;
+});
+
+},
+'dojo/request/handlers':function(){
+define([
+ '../json',
+ '../_base/kernel',
+ '../_base/array',
+ '../has',
+ '../selector/_loader' // only included for has() qsa tests
+], function(JSON, kernel, array, has){
+ has.add('activex', typeof ActiveXObject !== 'undefined');
+ has.add('dom-parser', function(global){
+ return 'DOMParser' in global;
+ });
+
+ var handleXML;
+ if(has('activex')){
+ // GUIDs obtained from http://msdn.microsoft.com/en-us/library/ms757837(VS.85).aspx
+ var dp = [
+ 'Msxml2.DOMDocument.6.0',
+ 'Msxml2.DOMDocument.4.0',
+ 'MSXML2.DOMDocument.3.0',
+ 'MSXML.DOMDocument' // 2.0
+ ];
+ var lastParser;
+
+ handleXML = function(response){
+ var result = response.data;
+ var text = response.text;
+
+ if(result && has('dom-qsa2.1') && !result.querySelectorAll && has('dom-parser')){
+ // http://bugs.dojotoolkit.org/ticket/15631
+ // IE9 supports a CSS3 querySelectorAll implementation, but the DOM implementation
+ // returned by IE9 xhr.responseXML does not. Manually create the XML DOM to gain
+ // the fuller-featured implementation and avoid bugs caused by the inconsistency
+ result = new DOMParser().parseFromString(text, 'application/xml');
+ }
+
+ function createDocument(p) {
+ try{
+ var dom = new ActiveXObject(p);
+ dom.async = false;
+ dom.loadXML(text);
+ result = dom;
+ lastParser = p;
+ }catch(e){ return false; }
+ return true;
+ }
+
+ if(!result || !result.documentElement){
+ // The creation of an ActiveX object is expensive, so we cache the
+ // parser type to avoid trying all parser types each time we handle a
+ // document. There is some concern that some parser types might fail
+ // depending on the document being parsed. If parsing using the cached
+ // parser type fails, we do the more expensive operation of finding one
+ // that works for the given document.
+ // https://bugs.dojotoolkit.org/ticket/15246
+ if(!lastParser || !createDocument(lastParser)) {
+ array.some(dp, createDocument);
+ }
+ }
+
+ return result;
+ };
+ }
+
+ var handleNativeResponse = function(response) {
+ if(!has('native-xhr2-blob') && response.options.handleAs === 'blob' && typeof Blob !== 'undefined'){
+ return new Blob([ response.xhr.response ], { type: response.xhr.getResponseHeader('Content-Type') });
+ }
+
+ return response.xhr.response;
+ }
+
+ var handlers = {
+ 'javascript': function(response){
+ return kernel.eval(response.text || '');
+ },
+ 'json': function(response){
+ return JSON.parse(response.text || null);
+ },
+ 'xml': handleXML,
+ 'blob': handleNativeResponse,
+ 'arraybuffer': handleNativeResponse,
+ 'document': handleNativeResponse
+ };
+
+ function handle(response){
+ var handler = handlers[response.options.handleAs];
+
+ response.data = handler ? handler(response) : (response.data || response.text);
+
+ return response;
+ }
+
+ handle.register = function(name, handler){
+ handlers[name] = handler;
+ };
+
+ return handle;
+});
+
+},
+'dojo/selector/_loader':function(){
+define(["../has", "require"],
+ function(has, require){
+
+"use strict";
+if (typeof document !== "undefined") {
+ var testDiv = document.createElement("div");
+ has.add("dom-qsa2.1", !!testDiv.querySelectorAll);
+ has.add("dom-qsa3", function(){
+ // test to see if we have a reasonable native selector engine available
+ try{
+ testDiv.innerHTML = ""; // test kind of from sizzle
+ // Safari can't handle uppercase or unicode characters when
+ // in quirks mode, IE8 can't handle pseudos like :empty
+ return testDiv.querySelectorAll(".TEST:empty").length == 1;
+ }catch(e){}
+ });
+}
+
+var fullEngine;
+var acme = "./acme", lite = "./lite";
+return {
+ // summary:
+ // This module handles loading the appropriate selector engine for the given browser
+
+ load: function(id, parentRequire, loaded, config){
+ if (config && config.isBuild) {
+ //Indicate that the optimizer should not wait
+ //for this resource any more and complete optimization.
+ //This resource will be resolved dynamically during
+ //run time in the web browser.
+ loaded();
+ return;
+ }
+
+ var req = require;
+ // here we implement the default logic for choosing a selector engine
+ id = id == "default" ? has("config-selectorEngine") || "css3" : id;
+ id = id == "css2" || id == "lite" ? lite :
+ id == "css2.1" ? has("dom-qsa2.1") ? lite : acme :
+ id == "css3" ? has("dom-qsa3") ? lite : acme :
+ id == "acme" ? acme : (req = parentRequire) && id;
+ if(id.charAt(id.length-1) == '?'){
+ id = id.substring(0,id.length - 1);
+ var optionalLoad = true;
+ }
+ // the query engine is optional, only load it if a native one is not available or existing one has not been loaded
+ if(optionalLoad && (has("dom-compliant-qsa") || fullEngine)){
+ return loaded(fullEngine);
+ }
+ // load the referenced selector engine
+ req([id], function(engine){
+ if(id != "./lite"){
+ fullEngine = engine;
+ }
+ loaded(engine);
+ });
+ }
+};
+});
+
+},
+'dojo/main':function(){
+define([
+ "./_base/kernel", // kernel.isAsync
+ "./has",
+ "require",
+ "./sniff",
+ "./_base/lang",
+ "./_base/array",
+ "./_base/config",
+ "./ready",
+ "./_base/declare",
+ "./_base/connect",
+ "./_base/Deferred",
+ "./_base/json",
+ "./_base/Color",
+ "./has!dojo-firebug?./_firebug/firebug",
+ "./_base/browser",
+ "./_base/loader"
+], function(kernel, has, require, sniff, lang, array, config, ready){
+ // module:
+ // dojo/main
+ // summary:
+ // This is the package main module for the dojo package; it loads dojo base appropriate for the execution environment.
+
+ // Load code to fix IE's console
+ if(config.isDebug){
+ require(["./_firebug/firebug"]);
+ }
+
+ // dojoConfig.require is deprecated; use the loader configuration property deps
+ 1 || has.add("dojo-config-require", 1);
+ if( 1 ){
+ var deps= config.require;
+ if(deps){
+ // config.require may be dot notation
+ deps= array.map(lang.isArray(deps) ? deps : [deps], function(item){ return item.replace(/\./g, "/"); });
+ if(kernel.isAsync){
+ require(deps);
+ }else{
+ // this is a bit janky; in 1.6- dojo is defined before these requires are applied; but in 1.7+
+ // dojo isn't defined until returning from this module; this is only a problem in sync mode
+ // since we're in sync mode, we know we've got our loader with its priority ready queue
+ ready(1, function(){require(deps);});
+ }
+ }
+ }
+
+ return kernel;
+});
+
+},
+'dojo/ready':function(){
+define(["./_base/kernel", "./has", "require", "./domReady", "./_base/lang"], function(dojo, has, require, domReady, lang){
+ // module:
+ // dojo/ready
+ // note:
+ // This module should be unnecessary in dojo 2.0
+
+ var
+ // truthy if DOMContentLoaded or better (e.g., window.onload fired) has been achieved
+ isDomReady = 0,
+
+ // The queue of functions waiting to execute as soon as dojo.ready conditions satisfied
+ loadQ = [],
+
+ // prevent recursion in onLoad
+ onLoadRecursiveGuard = 0,
+
+ handleDomReady = function(){
+ isDomReady = 1;
+ dojo._postLoad = dojo.config.afterOnLoad = true;
+ onEvent();
+ },
+
+ onEvent = function(){
+ // Called when some state changes:
+ // - dom ready
+ // - dojo/domReady has finished processing everything in its queue
+ // - task added to loadQ
+ // - require() has finished loading all currently requested modules
+ //
+ // Run the functions queued with dojo.ready if appropriate.
+
+
+ //guard against recursions into this function
+ if(onLoadRecursiveGuard){
+ return;
+ }
+ onLoadRecursiveGuard = 1;
+
+ // Run tasks in queue if require() is finished loading modules, the dom is ready, and there are no
+ // pending tasks registered via domReady().
+ // The last step is necessary so that a user defined dojo.ready() callback is delayed until after the
+ // domReady() calls inside of dojo. Failure can be seen on dijit/tests/robot/Dialog_ally.html on IE8
+ // because the dijit/focus.js domReady() callback doesn't execute until after the test starts running.
+ while(isDomReady && (!domReady || domReady._Q.length == 0) && (require.idle ? require.idle() : true) && loadQ.length){
+ var f = loadQ.shift();
+ try{
+ f();
+ }catch(e){
+ // force the dojo.js on("error") handler do display the message
+ e.info = e.message;
+ if(require.signal){
+ require.signal("error", e);
+ }else{
+ throw e;
+ }
+ }
+ }
+
+ onLoadRecursiveGuard = 0;
+ };
+
+ // Check if we should run the next queue operation whenever require() finishes loading modules or domReady
+ // finishes processing it's queue.
+ require.on && require.on("idle", onEvent);
+ if(domReady){
+ domReady._onQEmpty = onEvent;
+ }
+
+ var ready = dojo.ready = dojo.addOnLoad = function(priority, context, callback){
+ // summary:
+ // Add a function to execute on DOM content loaded and all requested modules have arrived and been evaluated.
+ // In most cases, the `domReady` plug-in should suffice and this method should not be needed.
+ //
+ // When called in a non-browser environment, just checks that all requested modules have arrived and been
+ // evaluated.
+ // priority: Integer?
+ // The order in which to exec this callback relative to other callbacks, defaults to 1000
+ // context: Object?|Function
+ // The context in which to run execute callback, or a callback if not using context
+ // callback: Function?
+ // The function to execute.
+ //
+ // example:
+ // Simple DOM and Modules ready syntax
+ // | require(["dojo/ready"], function(ready){
+ // | ready(function(){ alert("Dom ready!"); });
+ // | });
+ //
+ // example:
+ // Using a priority
+ // | require(["dojo/ready"], function(ready){
+ // | ready(2, function(){ alert("low priority ready!"); })
+ // | });
+ //
+ // example:
+ // Using context
+ // | require(["dojo/ready"], function(ready){
+ // | ready(foo, function(){
+ // | // in here, this == foo
+ // | });
+ // | });
+ //
+ // example:
+ // Using dojo/hitch style args:
+ // | require(["dojo/ready"], function(ready){
+ // | var foo = { dojoReady: function(){ console.warn(this, "dojo dom and modules ready."); } };
+ // | ready(foo, "dojoReady");
+ // | });
+
+ var hitchArgs = lang._toArray(arguments);
+ if(typeof priority != "number"){
+ callback = context;
+ context = priority;
+ priority = 1000;
+ }else{
+ hitchArgs.shift();
+ }
+ callback = callback ?
+ lang.hitch.apply(dojo, hitchArgs) :
+ function(){
+ context();
+ };
+ callback.priority = priority;
+ for(var i = 0; i < loadQ.length && priority >= loadQ[i].priority; i++){}
+ loadQ.splice(i, 0, callback);
+ onEvent();
+ };
+
+ 1 || has.add("dojo-config-addOnLoad", 1);
+ if( 1 ){
+ var dca = dojo.config.addOnLoad;
+ if(dca){
+ ready[(lang.isArray(dca) ? "apply" : "call")](dojo, dca);
+ }
+ }
+
+ if( 1 && dojo.config.parseOnLoad && !dojo.isAsync){
+ ready(99, function(){
+ if(!dojo.parser){
+ dojo.deprecated("Add explicit require(['dojo/parser']);", "", "2.0");
+ require(["dojo/parser"]);
+ }
+ });
+ }
+
+ if(domReady){
+ domReady(handleDomReady);
+ }else{
+ handleDomReady();
+ }
+
+ return ready;
+});
+
+},
+'dojo/domReady':function(){
+define(['./global', './has'], function(global, has){
+ var doc = document,
+ readyStates = { 'loaded': 1, 'complete': 1 },
+ fixReadyState = typeof doc.readyState != "string",
+ ready = !!readyStates[doc.readyState],
+ readyQ = [],
+ recursiveGuard;
+
+ function domReady(callback){
+ // summary:
+ // Plugin to delay require()/define() callback from firing until the DOM has finished loading.
+ readyQ.push(callback);
+ if(ready){ processQ(); }
+ }
+ domReady.load = function(id, req, load){
+ domReady(load);
+ };
+
+ // Export queue so that ready() can check if it's empty or not.
+ domReady._Q = readyQ;
+ domReady._onQEmpty = function(){
+ // summary:
+ // Private method overridden by dojo/ready, to notify when everything in the
+ // domReady queue has been processed. Do not use directly.
+ // Will be removed in 2.0, along with domReady._Q.
+ };
+
+ // For FF <= 3.5
+ if(fixReadyState){ doc.readyState = "loading"; }
+
+ function processQ(){
+ // Calls all functions in the queue in order, unless processQ() is already running, in which case just return
+
+ if(recursiveGuard){ return; }
+ recursiveGuard = true;
+
+ while(readyQ.length){
+ try{
+ (readyQ.shift())(doc);
+ }catch(err){
+ console.error(err, "in domReady callback", err.stack);
+ }
+ }
+
+ recursiveGuard = false;
+
+ // Notification for dojo/ready. Remove for 2.0.
+ // Note that this could add more tasks to the ready queue.
+ domReady._onQEmpty();
+ }
+
+ if(!ready){
+ var tests = [],
+ detectReady = function(evt){
+ evt = evt || global.event;
+ if(ready || (evt.type == "readystatechange" && !readyStates[doc.readyState])){ return; }
+
+ // For FF <= 3.5
+ if(fixReadyState){ doc.readyState = "complete"; }
+
+ ready = 1;
+ processQ();
+ },
+ on = function(node, event){
+ node.addEventListener(event, detectReady, false);
+ readyQ.push(function(){ node.removeEventListener(event, detectReady, false); });
+ };
+
+ if(!has("dom-addeventlistener")){
+ on = function(node, event){
+ event = "on" + event;
+ node.attachEvent(event, detectReady);
+ readyQ.push(function(){ node.detachEvent(event, detectReady); });
+ };
+
+ var div = doc.createElement("div");
+ try{
+ if(div.doScroll && global.frameElement === null){
+ // the doScroll test is only useful if we're in the top-most frame
+ tests.push(function(){
+ // Derived with permission from Diego Perini's IEContentLoaded
+ // http://javascript.nwbox.com/IEContentLoaded/
+ try{
+ div.doScroll("left");
+ return 1;
+ }catch(e){}
+ });
+ }
+ }catch(e){}
+ }
+
+ on(doc, "DOMContentLoaded");
+ on(global, "load");
+
+ if("onreadystatechange" in doc){
+ on(doc, "readystatechange");
+ }else if(!fixReadyState){
+ // if the ready state property exists and there's
+ // no readystatechange event, poll for the state
+ // to change
+ tests.push(function(){
+ return readyStates[doc.readyState];
+ });
+ }
+
+ if(tests.length){
+ var poller = function(){
+ if(ready){ return; }
+ var i = tests.length;
+ while(i--){
+ if(tests[i]()){
+ detectReady("poller");
+ return;
+ }
+ }
+ setTimeout(poller, 30);
+ };
+ poller();
+ }
+ }
+
+ return domReady;
+});
+
+},
+'dojo/_base/declare':function(){
+define(["./kernel", "../has", "./lang"], function(dojo, has, lang){
+ // module:
+ // dojo/_base/declare
+
+ var mix = lang.mixin, op = Object.prototype, opts = op.toString,
+ xtor, counter = 0, cname = "constructor";
+
+ if(!has("csp-restrictions")){
+ // 'new Function()' is preferable when available since it does not create a closure
+ xtor = new Function;
+ }else{
+ xtor = function(){};
+ }
+
+ function err(msg, cls){ throw new Error("declare" + (cls ? " " + cls : "") + ": " + msg); }
+
+ // C3 Method Resolution Order (see http://www.python.org/download/releases/2.3/mro/)
+ function c3mro(bases, className){
+ var result = [], roots = [{cls: 0, refs: []}], nameMap = {}, clsCount = 1,
+ l = bases.length, i = 0, j, lin, base, top, proto, rec, name, refs;
+
+ // build a list of bases naming them if needed
+ for(; i < l; ++i){
+ base = bases[i];
+ if(!base){
+ err("mixin #" + i + " is unknown. Did you use dojo.require to pull it in?", className);
+ }else if(opts.call(base) != "[object Function]"){
+ err("mixin #" + i + " is not a callable constructor.", className);
+ }
+ lin = base._meta ? base._meta.bases : [base];
+ top = 0;
+ // add bases to the name map
+ for(j = lin.length - 1; j >= 0; --j){
+ proto = lin[j].prototype;
+ if(!proto.hasOwnProperty("declaredClass")){
+ proto.declaredClass = "uniqName_" + (counter++);
+ }
+ name = proto.declaredClass;
+ if(!nameMap.hasOwnProperty(name)){
+ nameMap[name] = {count: 0, refs: [], cls: lin[j]};
+ ++clsCount;
+ }
+ rec = nameMap[name];
+ if(top && top !== rec){
+ rec.refs.push(top);
+ ++top.count;
+ }
+ top = rec;
+ }
+ ++top.count;
+ roots[0].refs.push(top);
+ }
+
+ // remove classes without external references recursively
+ while(roots.length){
+ top = roots.pop();
+ result.push(top.cls);
+ --clsCount;
+ // optimization: follow a single-linked chain
+ while(refs = top.refs, refs.length == 1){
+ top = refs[0];
+ if(!top || --top.count){
+ // branch or end of chain => do not end to roots
+ top = 0;
+ break;
+ }
+ result.push(top.cls);
+ --clsCount;
+ }
+ if(top){
+ // branch
+ for(i = 0, l = refs.length; i < l; ++i){
+ top = refs[i];
+ if(!--top.count){
+ roots.push(top);
+ }
+ }
+ }
+ }
+ if(clsCount){
+ err("can't build consistent linearization", className);
+ }
+
+ // calculate the superclass offset
+ base = bases[0];
+ result[0] = base ?
+ base._meta && base === result[result.length - base._meta.bases.length] ?
+ base._meta.bases.length : 1 : 0;
+
+ return result;
+ }
+
+ function inherited(args, a, f, g){
+ var name, chains, bases, caller, meta, base, proto, opf, pos,
+ cache = this._inherited = this._inherited || {};
+
+ // crack arguments
+ if(typeof args === "string"){
+ name = args;
+ args = a;
+ a = f;
+ f = g;
+ }
+
+ if(typeof args === "function"){
+ // support strict mode
+ caller = args;
+ args = a;
+ a = f;
+ }else{
+ try{
+ caller = args.callee;
+ }catch (e){
+ if(e instanceof TypeError){
+ // caller was defined in a strict-mode context
+ err("strict mode inherited() requires the caller function to be passed before arguments", this.declaredClass);
+ }else{
+ throw e;
+ }
+ }
+ }
+
+ name = name || caller.nom;
+ if(!name){
+ err("can't deduce a name to call inherited()", this.declaredClass);
+ }
+ f = g = 0;
+
+ meta = this.constructor._meta;
+ bases = meta.bases;
+
+ pos = cache.p;
+ if(name != cname){
+ // method
+ if(cache.c !== caller){
+ // cache bust
+ pos = 0;
+ base = bases[0];
+ meta = base._meta;
+ if(meta.hidden[name] !== caller){
+ // error detection
+ chains = meta.chains;
+ if(chains && typeof chains[name] == "string"){
+ err("calling chained method with inherited: " + name, this.declaredClass);
+ }
+ // find caller
+ do{
+ meta = base._meta;
+ proto = base.prototype;
+ if(meta && (proto[name] === caller && proto.hasOwnProperty(name) || meta.hidden[name] === caller)){
+ break;
+ }
+ }while(base = bases[++pos]); // intentional assignment
+ pos = base ? pos : -1;
+ }
+ }
+ // find next
+ base = bases[++pos];
+ if(base){
+ proto = base.prototype;
+ if(base._meta && proto.hasOwnProperty(name)){
+ f = proto[name];
+ }else{
+ opf = op[name];
+ do{
+ proto = base.prototype;
+ f = proto[name];
+ if(f && (base._meta ? proto.hasOwnProperty(name) : f !== opf)){
+ break;
+ }
+ }while(base = bases[++pos]); // intentional assignment
+ }
+ }
+ f = base && f || op[name];
+ }else{
+ // constructor
+ if(cache.c !== caller){
+ // cache bust
+ pos = 0;
+ meta = bases[0]._meta;
+ if(meta && meta.ctor !== caller){
+ // error detection
+ chains = meta.chains;
+ if(!chains || chains.constructor !== "manual"){
+ err("calling chained constructor with inherited", this.declaredClass);
+ }
+ // find caller
+ while(base = bases[++pos]){ // intentional assignment
+ meta = base._meta;
+ if(meta && meta.ctor === caller){
+ break;
+ }
+ }
+ pos = base ? pos : -1;
+ }
+ }
+ // find next
+ while(base = bases[++pos]){ // intentional assignment
+ meta = base._meta;
+ f = meta ? meta.ctor : base;
+ if(f){
+ break;
+ }
+ }
+ f = base && f;
+ }
+
+ // cache the found super method
+ cache.c = f;
+ cache.p = pos;
+
+ // now we have the result
+ if(f){
+ return a === true ? f : f.apply(this, a || args);
+ }
+ // intentionally no return if a super method was not found
+ }
+
+ function getInherited(name, args, a){
+ if(typeof name === "string"){
+ if (typeof args === "function") {
+ return this.__inherited(name, args, a, true);
+ }
+ return this.__inherited(name, args, true);
+ }
+ else if (typeof name === "function") {
+ return this.__inherited(name, args, true);
+ }
+ return this.__inherited(name, true);
+ }
+
+ function inherited__debug(args, a1, a2, a3){
+ var f = this.getInherited(args, a1, a2);
+ if(f){
+ return f.apply(this, a3 || a2 || a1 || args);
+ }
+ // intentionally no return if a super method was not found
+ }
+
+ var inheritedImpl = dojo.config.isDebug ? inherited__debug : inherited;
+
+ // emulation of "instanceof"
+ function isInstanceOf(cls){
+ var bases = this.constructor._meta.bases;
+ for(var i = 0, l = bases.length; i < l; ++i){
+ if(bases[i] === cls){
+ return true;
+ }
+ }
+ return this instanceof cls;
+ }
+
+ function mixOwn(target, source){
+ // add props adding metadata for incoming functions skipping a constructor
+ for(var name in source){
+ if(name != cname && source.hasOwnProperty(name)){
+ target[name] = source[name];
+ }
+ }
+ if(has("bug-for-in-skips-shadowed")){
+ for(var extraNames= lang._extraNames, i= extraNames.length; i;){
+ name = extraNames[--i];
+ if(name != cname && source.hasOwnProperty(name)){
+ target[name] = source[name];
+ }
+ }
+ }
+ }
+
+ // implementation of safe mixin function
+ function safeMixin(target, source){
+ // summary:
+ // Mix in properties skipping a constructor and decorating functions
+ // like it is done by declare().
+ // target: Object
+ // Target object to accept new properties.
+ // source: Object
+ // Source object for new properties.
+ // description:
+ // This function is used to mix in properties like lang.mixin does,
+ // but it skips a constructor property and decorates functions like
+ // declare() does.
+ //
+ // It is meant to be used with classes and objects produced with
+ // declare. Functions mixed in with dojo.safeMixin can use
+ // this.inherited() like normal methods.
+ //
+ // This function is used to implement extend() method of a constructor
+ // produced with declare().
+ //
+ // example:
+ // | var A = declare(null, {
+ // | m1: function(){
+ // | console.log("A.m1");
+ // | },
+ // | m2: function(){
+ // | console.log("A.m2");
+ // | }
+ // | });
+ // | var B = declare(A, {
+ // | m1: function(){
+ // | this.inherited(arguments);
+ // | console.log("B.m1");
+ // | }
+ // | });
+ // | B.extend({
+ // | m2: function(){
+ // | this.inherited(arguments);
+ // | console.log("B.m2");
+ // | }
+ // | });
+ // | var x = new B();
+ // | dojo.safeMixin(x, {
+ // | m1: function(){
+ // | this.inherited(arguments);
+ // | console.log("X.m1");
+ // | },
+ // | m2: function(){
+ // | this.inherited(arguments);
+ // | console.log("X.m2");
+ // | }
+ // | });
+ // | x.m2();
+ // | // prints:
+ // | // A.m1
+ // | // B.m1
+ // | // X.m1
+
+ var name, t;
+ // add props adding metadata for incoming functions skipping a constructor
+ for(name in source){
+ t = source[name];
+ if((t !== op[name] || !(name in op)) && name != cname){
+ if(opts.call(t) == "[object Function]"){
+ // non-trivial function method => attach its name
+ t.nom = name;
+ }
+ target[name] = t;
+ }
+ }
+ if(has("bug-for-in-skips-shadowed") && source){
+ for(var extraNames= lang._extraNames, i= extraNames.length; i;){
+ name = extraNames[--i];
+ t = source[name];
+ if((t !== op[name] || !(name in op)) && name != cname){
+ if(opts.call(t) == "[object Function]"){
+ // non-trivial function method => attach its name
+ t.nom = name;
+ }
+ target[name] = t;
+ }
+ }
+ }
+ return target;
+ }
+
+ function extend(source){
+ declare.safeMixin(this.prototype, source);
+ return this;
+ }
+
+ function createSubclass(mixins, props){
+ // crack parameters
+ if(!(mixins instanceof Array || typeof mixins === 'function')){
+ props = mixins;
+ mixins = undefined;
+ }
+
+ props = props || {};
+ mixins = mixins || [];
+
+ return declare([this].concat(mixins), props);
+ }
+
+ // chained constructor compatible with the legacy declare()
+ function chainedConstructor(bases, ctorSpecial){
+ return function(){
+ var a = arguments, args = a, a0 = a[0], f, i, m,
+ l = bases.length, preArgs;
+
+ if(!(this instanceof a.callee)){
+ // not called via new, so force it
+ return applyNew(a);
+ }
+
+ //this._inherited = {};
+ // perform the shaman's rituals of the original declare()
+ // 1) call two types of the preamble
+ if(ctorSpecial && (a0 && a0.preamble || this.preamble)){
+ // full blown ritual
+ preArgs = new Array(bases.length);
+ // prepare parameters
+ preArgs[0] = a;
+ for(i = 0;;){
+ // process the preamble of the 1st argument
+ a0 = a[0];
+ if(a0){
+ f = a0.preamble;
+ if(f){
+ a = f.apply(this, a) || a;
+ }
+ }
+ // process the preamble of this class
+ f = bases[i].prototype;
+ f = f.hasOwnProperty("preamble") && f.preamble;
+ if(f){
+ a = f.apply(this, a) || a;
+ }
+ // one peculiarity of the preamble:
+ // it is called if it is not needed,
+ // e.g., there is no constructor to call
+ // let's watch for the last constructor
+ // (see ticket #9795)
+ if(++i == l){
+ break;
+ }
+ preArgs[i] = a;
+ }
+ }
+ // 2) call all non-trivial constructors using prepared arguments
+ for(i = l - 1; i >= 0; --i){
+ f = bases[i];
+ m = f._meta;
+ f = m ? m.ctor : f;
+ if(f){
+ f.apply(this, preArgs ? preArgs[i] : a);
+ }
+ }
+ // 3) continue the original ritual: call the postscript
+ f = this.postscript;
+ if(f){
+ f.apply(this, args);
+ }
+ };
+ }
+
+
+ // chained constructor compatible with the legacy declare()
+ function singleConstructor(ctor, ctorSpecial){
+ return function(){
+ var a = arguments, t = a, a0 = a[0], f;
+
+ if(!(this instanceof a.callee)){
+ // not called via new, so force it
+ return applyNew(a);
+ }
+
+ //this._inherited = {};
+ // perform the shaman's rituals of the original declare()
+ // 1) call two types of the preamble
+ if(ctorSpecial){
+ // full blown ritual
+ if(a0){
+ // process the preamble of the 1st argument
+ f = a0.preamble;
+ if(f){
+ t = f.apply(this, t) || t;
+ }
+ }
+ f = this.preamble;
+ if(f){
+ // process the preamble of this class
+ f.apply(this, t);
+ // one peculiarity of the preamble:
+ // it is called even if it is not needed,
+ // e.g., there is no constructor to call
+ // let's watch for the last constructor
+ // (see ticket #9795)
+ }
+ }
+ // 2) call a constructor
+ if(ctor){
+ ctor.apply(this, a);
+ }
+ // 3) continue the original ritual: call the postscript
+ f = this.postscript;
+ if(f){
+ f.apply(this, a);
+ }
+ };
+ }
+
+ // plain vanilla constructor (can use inherited() to call its base constructor)
+ function simpleConstructor(bases){
+ return function(){
+ var a = arguments, i = 0, f, m;
+
+ if(!(this instanceof a.callee)){
+ // not called via new, so force it
+ return applyNew(a);
+ }
+
+ //this._inherited = {};
+ // perform the shaman's rituals of the original declare()
+ // 1) do not call the preamble
+ // 2) call the top constructor (it can use this.inherited())
+ for(; f = bases[i]; ++i){ // intentional assignment
+ m = f._meta;
+ f = m ? m.ctor : f;
+ if(f){
+ f.apply(this, a);
+ break;
+ }
+ }
+ // 3) call the postscript
+ f = this.postscript;
+ if(f){
+ f.apply(this, a);
+ }
+ };
+ }
+
+ function chain(name, bases, reversed){
+ return function(){
+ var b, m, f, i = 0, step = 1;
+ if(reversed){
+ i = bases.length - 1;
+ step = -1;
+ }
+ for(; b = bases[i]; i += step){ // intentional assignment
+ m = b._meta;
+ f = (m ? m.hidden : b.prototype)[name];
+ if(f){
+ f.apply(this, arguments);
+ }
+ }
+ };
+ }
+
+ // forceNew(ctor)
+ // return a new object that inherits from ctor.prototype but
+ // without actually running ctor on the object.
+ function forceNew(ctor){
+ // create object with correct prototype using a do-nothing
+ // constructor
+ xtor.prototype = ctor.prototype;
+ var t = new xtor;
+ xtor.prototype = null; // clean up
+ return t;
+ }
+
+ // applyNew(args)
+ // just like 'new ctor()' except that the constructor and its arguments come
+ // from args, which must be an array or an arguments object
+ function applyNew(args){
+ // create an object with ctor's prototype but without
+ // calling ctor on it.
+ var ctor = args.callee, t = forceNew(ctor);
+ // execute the real constructor on the new object
+ ctor.apply(t, args);
+ return t;
+ }
+
+ function declare(className, superclass, props){
+ // summary:
+ // Create a feature-rich constructor from compact notation.
+ // className: String?
+ // The optional name of the constructor (loosely, a "class")
+ // stored in the "declaredClass" property in the created prototype.
+ // It will be used as a global name for a created constructor.
+ // superclass: Function|Function[]
+ // May be null, a Function, or an Array of Functions. This argument
+ // specifies a list of bases (the left-most one is the most deepest
+ // base).
+ // props: Object
+ // An object whose properties are copied to the created prototype.
+ // Add an instance-initialization function by making it a property
+ // named "constructor".
+ // returns: dojo/_base/declare.__DeclareCreatedObject
+ // New constructor function.
+ // description:
+ // Create a constructor using a compact notation for inheritance and
+ // prototype extension.
+ //
+ // Mixin ancestors provide a type of multiple inheritance.
+ // Prototypes of mixin ancestors are copied to the new class:
+ // changes to mixin prototypes will not affect classes to which
+ // they have been mixed in.
+ //
+ // Ancestors can be compound classes created by this version of
+ // declare(). In complex cases all base classes are going to be
+ // linearized according to C3 MRO algorithm
+ // (see http://www.python.org/download/releases/2.3/mro/ for more
+ // details).
+ //
+ // "className" is cached in "declaredClass" property of the new class,
+ // if it was supplied. The immediate super class will be cached in
+ // "superclass" property of the new class.
+ //
+ // Methods in "props" will be copied and modified: "nom" property
+ // (the declared name of the method) will be added to all copied
+ // functions to help identify them for the internal machinery. Be
+ // very careful, while reusing methods: if you use the same
+ // function under different names, it can produce errors in some
+ // cases.
+ //
+ // It is possible to use constructors created "manually" (without
+ // declare()) as bases. They will be called as usual during the
+ // creation of an instance, their methods will be chained, and even
+ // called by "this.inherited()".
+ //
+ // Special property "-chains-" governs how to chain methods. It is
+ // a dictionary, which uses method names as keys, and hint strings
+ // as values. If a hint string is "after", this method will be
+ // called after methods of its base classes. If a hint string is
+ // "before", this method will be called before methods of its base
+ // classes.
+ //
+ // If "constructor" is not mentioned in "-chains-" property, it will
+ // be chained using the legacy mode: using "after" chaining,
+ // calling preamble() method before each constructor, if available,
+ // and calling postscript() after all constructors were executed.
+ // If the hint is "after", it is chained as a regular method, but
+ // postscript() will be called after the chain of constructors.
+ // "constructor" cannot be chained "before", but it allows
+ // a special hint string: "manual", which means that constructors
+ // are not going to be chained in any way, and programmer will call
+ // them manually using this.inherited(). In the latter case
+ // postscript() will be called after the construction.
+ //
+ // All chaining hints are "inherited" from base classes and
+ // potentially can be overridden. Be very careful when overriding
+ // hints! Make sure that all chained methods can work in a proposed
+ // manner of chaining.
+ //
+ // Once a method was chained, it is impossible to unchain it. The
+ // only exception is "constructor". You don't need to define a
+ // method in order to supply a chaining hint.
+ //
+ // If a method is chained, it cannot use this.inherited() because
+ // all other methods in the hierarchy will be called automatically.
+ //
+ // Usually constructors and initializers of any kind are chained
+ // using "after" and destructors of any kind are chained as
+ // "before". Note that chaining assumes that chained methods do not
+ // return any value: any returned value will be discarded.
+ //
+ // example:
+ // | declare("my.classes.bar", my.classes.foo, {
+ // | // properties to be added to the class prototype
+ // | someValue: 2,
+ // | // initialization function
+ // | constructor: function(){
+ // | this.myComplicatedObject = new ReallyComplicatedObject();
+ // | },
+ // | // other functions
+ // | someMethod: function(){
+ // | doStuff();
+ // | }
+ // | });
+ //
+ // example:
+ // | var MyBase = declare(null, {
+ // | // constructor, properties, and methods go here
+ // | // ...
+ // | });
+ // | var MyClass1 = declare(MyBase, {
+ // | // constructor, properties, and methods go here
+ // | // ...
+ // | });
+ // | var MyClass2 = declare(MyBase, {
+ // | // constructor, properties, and methods go here
+ // | // ...
+ // | });
+ // | var MyDiamond = declare([MyClass1, MyClass2], {
+ // | // constructor, properties, and methods go here
+ // | // ...
+ // | });
+ //
+ // example:
+ // | var F = function(){ console.log("raw constructor"); };
+ // | F.prototype.method = function(){
+ // | console.log("raw method");
+ // | };
+ // | var A = declare(F, {
+ // | constructor: function(){
+ // | console.log("A.constructor");
+ // | },
+ // | method: function(){
+ // | console.log("before calling F.method...");
+ // | this.inherited(arguments);
+ // | console.log("...back in A");
+ // | }
+ // | });
+ // | new A().method();
+ // | // will print:
+ // | // raw constructor
+ // | // A.constructor
+ // | // before calling F.method...
+ // | // raw method
+ // | // ...back in A
+ //
+ // example:
+ // | var A = declare(null, {
+ // | "-chains-": {
+ // | destroy: "before"
+ // | }
+ // | });
+ // | var B = declare(A, {
+ // | constructor: function(){
+ // | console.log("B.constructor");
+ // | },
+ // | destroy: function(){
+ // | console.log("B.destroy");
+ // | }
+ // | });
+ // | var C = declare(B, {
+ // | constructor: function(){
+ // | console.log("C.constructor");
+ // | },
+ // | destroy: function(){
+ // | console.log("C.destroy");
+ // | }
+ // | });
+ // | new C().destroy();
+ // | // prints:
+ // | // B.constructor
+ // | // C.constructor
+ // | // C.destroy
+ // | // B.destroy
+ //
+ // example:
+ // | var A = declare(null, {
+ // | "-chains-": {
+ // | constructor: "manual"
+ // | }
+ // | });
+ // | var B = declare(A, {
+ // | constructor: function(){
+ // | // ...
+ // | // call the base constructor with new parameters
+ // | this.inherited(arguments, [1, 2, 3]);
+ // | // ...
+ // | }
+ // | });
+ //
+ // example:
+ // | var A = declare(null, {
+ // | "-chains-": {
+ // | m1: "before"
+ // | },
+ // | m1: function(){
+ // | console.log("A.m1");
+ // | },
+ // | m2: function(){
+ // | console.log("A.m2");
+ // | }
+ // | });
+ // | var B = declare(A, {
+ // | "-chains-": {
+ // | m2: "after"
+ // | },
+ // | m1: function(){
+ // | console.log("B.m1");
+ // | },
+ // | m2: function(){
+ // | console.log("B.m2");
+ // | }
+ // | });
+ // | var x = new B();
+ // | x.m1();
+ // | // prints:
+ // | // B.m1
+ // | // A.m1
+ // | x.m2();
+ // | // prints:
+ // | // A.m2
+ // | // B.m2
+
+ // crack parameters
+ if(typeof className != "string"){
+ props = superclass;
+ superclass = className;
+ className = "";
+ }
+ props = props || {};
+
+ var proto, i, t, ctor, name, bases, chains, mixins = 1, parents = superclass;
+
+ // build a prototype
+ if(opts.call(superclass) == "[object Array]"){
+ // C3 MRO
+ bases = c3mro(superclass, className);
+ t = bases[0];
+ mixins = bases.length - t;
+ superclass = bases[mixins];
+ }else{
+ bases = [0];
+ if(superclass){
+ if(opts.call(superclass) == "[object Function]"){
+ t = superclass._meta;
+ bases = bases.concat(t ? t.bases : superclass);
+ }else{
+ err("base class is not a callable constructor.", className);
+ }
+ }else if(superclass !== null){
+ err("unknown base class. Did you use dojo.require to pull it in?", className);
+ }
+ }
+ if(superclass){
+ for(i = mixins - 1;; --i){
+ proto = forceNew(superclass);
+ if(!i){
+ // stop if nothing to add (the last base)
+ break;
+ }
+ // mix in properties
+ t = bases[i];
+ (t._meta ? mixOwn : mix)(proto, t.prototype);
+ // chain in new constructor
+ if (has("csp-restrictions")) {
+ ctor = function () {};
+ }
+ else {
+ ctor = new Function;
+ }
+ ctor.superclass = superclass;
+ ctor.prototype = proto;
+ superclass = proto.constructor = ctor;
+ }
+ }else{
+ proto = {};
+ }
+ // add all properties
+ declare.safeMixin(proto, props);
+ // add constructor
+ t = props.constructor;
+ if(t !== op.constructor){
+ t.nom = cname;
+ proto.constructor = t;
+ }
+
+ // collect chains and flags
+ for(i = mixins - 1; i; --i){ // intentional assignment
+ t = bases[i]._meta;
+ if(t && t.chains){
+ chains = mix(chains || {}, t.chains);
+ }
+ }
+ if(proto["-chains-"]){
+ chains = mix(chains || {}, proto["-chains-"]);
+ }
+
+ if(superclass && superclass.prototype && superclass.prototype["-chains-"]) {
+ chains = mix(chains || {}, superclass.prototype["-chains-"]);
+ }
+
+ // build ctor
+ t = !chains || !chains.hasOwnProperty(cname);
+ bases[0] = ctor = (chains && chains.constructor === "manual") ? simpleConstructor(bases) :
+ (bases.length == 1 ? singleConstructor(props.constructor, t) : chainedConstructor(bases, t));
+
+ // add meta information to the constructor
+ ctor._meta = {bases: bases, hidden: props, chains: chains,
+ parents: parents, ctor: props.constructor};
+ ctor.superclass = superclass && superclass.prototype;
+ ctor.extend = extend;
+ ctor.createSubclass = createSubclass;
+ ctor.prototype = proto;
+ proto.constructor = ctor;
+
+ // add "standard" methods to the prototype
+ proto.getInherited = getInherited;
+ proto.isInstanceOf = isInstanceOf;
+ proto.inherited = inheritedImpl;
+ proto.__inherited = inherited;
+
+ // add name if specified
+ if(className){
+ proto.declaredClass = className;
+ lang.setObject(className, ctor);
+ }
+
+ // build chains and add them to the prototype
+ if(chains){
+ for(name in chains){
+ if(proto[name] && typeof chains[name] == "string" && name != cname){
+ t = proto[name] = chain(name, bases, chains[name] === "after");
+ t.nom = name;
+ }
+ }
+ }
+ // chained methods do not return values
+ // no need to chain "invisible" functions
+
+ return ctor; // Function
+ }
+
+ /*=====
+ declare.__DeclareCreatedObject = {
+ // summary:
+ // dojo/_base/declare() returns a constructor `C`. `new C()` returns an Object with the following
+ // methods, in addition to the methods and properties specified via the arguments passed to declare().
+
+ inherited: function(name, caller, args, newArgs){
+ // summary:
+ // Calls a super method.
+ // name: String?
+ // The optional method name. Should be the same as the caller's
+ // name. Usually "name" is specified in complex dynamic cases, when
+ // the calling method was dynamically added, undecorated by
+ // declare(), and it cannot be determined.
+ // caller: Function?
+ // The reference to the calling function. Required only if the
+ // call to "this.inherited" occurs from within strict-mode code.
+ // If the caller is omitted within strict-mode code, an error will
+ // be thrown.
+ // The best way to obtain a reference to the calling function is to
+ // use a named function expression (i.e. place a function name
+ // after the "function" keyword and before the open paren, as in
+ // "function fn(a, b)"). If the function is parsed as an expression
+ // and not a statement (i.e. it's not by itself on its own line),
+ // the function name will only be accessible as an identifier from
+ // within the body of the function.
+ // args: Arguments
+ // The caller supply this argument, which should be the original
+ // "arguments".
+ // newArgs: Object?
+ // If "true", the found function will be returned without
+ // executing it.
+ // If Array, it will be used to call a super method. Otherwise
+ // "args" will be used.
+ // returns:
+ // Whatever is returned by a super method, or a super method itself,
+ // if "true" was specified as newArgs.
+ // description:
+ // This method is used inside method of classes produced with
+ // declare() to call a super method (next in the chain). It is
+ // used for manually controlled chaining. Consider using the regular
+ // chaining, because it is faster. Use "this.inherited()" only in
+ // complex cases.
+ //
+ // This method cannot me called from automatically chained
+ // constructors including the case of a special (legacy)
+ // constructor chaining. It cannot be called from chained methods.
+ //
+ // If "this.inherited()" cannot find the next-in-chain method, it
+ // does nothing and returns "undefined". The last method in chain
+ // can be a default method implemented in Object, which will be
+ // called last.
+ //
+ // If "name" is specified, it is assumed that the method that
+ // received "args" is the parent method for this call. It is looked
+ // up in the chain list and if it is found the next-in-chain method
+ // is called. If it is not found, the first-in-chain method is
+ // called.
+ //
+ // If "name" is not specified, it will be derived from the calling
+ // method (using a methoid property "nom").
+ //
+ // example:
+ // | var B = declare(A, {
+ // | method1: function(a, b, c){
+ // | this.inherited(arguments);
+ // | },
+ // | method2: function(a, b){
+ // | return this.inherited(arguments, [a + b]);
+ // | }
+ // | });
+ // | // next method is not in the chain list because it is added
+ // | // manually after the class was created.
+ // | B.prototype.method3 = function(){
+ // | console.log("This is a dynamically-added method.");
+ // | this.inherited("method3", arguments);
+ // | };
+ // example:
+ // | var B = declare(A, {
+ // | method: function(a, b){
+ // | var super = this.inherited(arguments, true);
+ // | // ...
+ // | if(!super){
+ // | console.log("there is no super method");
+ // | return 0;
+ // | }
+ // | return super.apply(this, arguments);
+ // | }
+ // | });
+ // example:
+ // | "use strict";
+ // | // class is defined in strict-mode code,
+ // | // so caller must be passed before arguments.
+ // | var B = declare(A, {
+ // | // using a named function expression with "fn" as the name.
+ // | method: function fn(a, b) {
+ // | this.inherited(fn, arguments);
+ // | }
+ // | });
+ return {}; // Object
+ },
+
+ getInherited: function(name, caller, args){
+ // summary:
+ // Returns a super method.
+ // name: String?
+ // The optional method name. Should be the same as the caller's
+ // name. Usually "name" is specified in complex dynamic cases, when
+ // the calling method was dynamically added, undecorated by
+ // declare(), and it cannot be determined.
+ // caller: Function?
+ // The caller function. This is required when running in
+ // strict-mode code. A reference to the caller function
+ // can be obtained by using a named function expression
+ // (e.g. function fn(a,b) {...}).
+ // args: Arguments
+ // The caller supply this argument, which should be the original
+ // "arguments".
+ // returns:
+ // Returns a super method (Function) or "undefined".
+ // description:
+ // This method is a convenience method for "this.inherited()".
+ // It uses the same algorithm but instead of executing a super
+ // method, it returns it, or "undefined" if not found.
+ //
+ // example:
+ // | var B = declare(A, {
+ // | method: function(a, b){
+ // | var super = this.getInherited(arguments);
+ // | // ...
+ // | if(!super){
+ // | console.log("there is no super method");
+ // | return 0;
+ // | }
+ // | return super.apply(this, arguments);
+ // | }
+ // | });
+ // example:
+ // | "use strict;" // first line of function or file
+ // | //...
+ // | var B = declare(A, {
+ // | // Using a named function expression with "fn" as the name,
+ // | // since we're in strict mode.
+ // | method: function fn(a, b){
+ // | var super = this.getInherited(fn, arguments);
+ // | if(super){
+ // | return super.apply(this, arguments);
+ // | }
+ // | }
+ // | });
+ return {}; // Object
+ },
+
+ isInstanceOf: function(cls){
+ // summary:
+ // Checks the inheritance chain to see if it is inherited from this
+ // class.
+ // cls: Function
+ // Class constructor.
+ // returns:
+ // "true", if this object is inherited from this class, "false"
+ // otherwise.
+ // description:
+ // This method is used with instances of classes produced with
+ // declare() to determine of they support a certain interface or
+ // not. It models "instanceof" operator.
+ //
+ // example:
+ // | var A = declare(null, {
+ // | // constructor, properties, and methods go here
+ // | // ...
+ // | });
+ // | var B = declare(null, {
+ // | // constructor, properties, and methods go here
+ // | // ...
+ // | });
+ // | var C = declare([A, B], {
+ // | // constructor, properties, and methods go here
+ // | // ...
+ // | });
+ // | var D = declare(A, {
+ // | // constructor, properties, and methods go here
+ // | // ...
+ // | });
+ // |
+ // | var a = new A(), b = new B(), c = new C(), d = new D();
+ // |
+ // | console.log(a.isInstanceOf(A)); // true
+ // | console.log(b.isInstanceOf(A)); // false
+ // | console.log(c.isInstanceOf(A)); // true
+ // | console.log(d.isInstanceOf(A)); // true
+ // |
+ // | console.log(a.isInstanceOf(B)); // false
+ // | console.log(b.isInstanceOf(B)); // true
+ // | console.log(c.isInstanceOf(B)); // true
+ // | console.log(d.isInstanceOf(B)); // false
+ // |
+ // | console.log(a.isInstanceOf(C)); // false
+ // | console.log(b.isInstanceOf(C)); // false
+ // | console.log(c.isInstanceOf(C)); // true
+ // | console.log(d.isInstanceOf(C)); // false
+ // |
+ // | console.log(a.isInstanceOf(D)); // false
+ // | console.log(b.isInstanceOf(D)); // false
+ // | console.log(c.isInstanceOf(D)); // false
+ // | console.log(d.isInstanceOf(D)); // true
+ return {}; // Object
+ },
+
+ extend: function(source){
+ // summary:
+ // Adds all properties and methods of source to constructor's
+ // prototype, making them available to all instances created with
+ // constructor. This method is specific to constructors created with
+ // declare().
+ // source: Object
+ // Source object which properties are going to be copied to the
+ // constructor's prototype.
+ // description:
+ // Adds source properties to the constructor's prototype. It can
+ // override existing properties.
+ //
+ // This method is similar to dojo.extend function, but it is specific
+ // to constructors produced by declare(). It is implemented
+ // using dojo.safeMixin, and it skips a constructor property,
+ // and properly decorates copied functions.
+ //
+ // example:
+ // | var A = declare(null, {
+ // | m1: function(){},
+ // | s1: "Popokatepetl"
+ // | });
+ // | A.extend({
+ // | m1: function(){},
+ // | m2: function(){},
+ // | f1: true,
+ // | d1: 42
+ // | });
+ },
+
+ createSubclass: function(mixins, props){
+ // summary:
+ // Create a subclass of the declared class from a list of base classes.
+ // mixins: Function[]
+ // Specifies a list of bases (the left-most one is the most deepest
+ // base).
+ // props: Object?
+ // An optional object whose properties are copied to the created prototype.
+ // returns: dojo/_base/declare.__DeclareCreatedObject
+ // New constructor function.
+ // description:
+ // Create a constructor using a compact notation for inheritance and
+ // prototype extension.
+ //
+ // Mixin ancestors provide a type of multiple inheritance.
+ // Prototypes of mixin ancestors are copied to the new class:
+ // changes to mixin prototypes will not affect classes to which
+ // they have been mixed in.
+ //
+ // example:
+ // | var A = declare(null, {
+ // | m1: function(){},
+ // | s1: "bar"
+ // | });
+ // | var B = declare(null, {
+ // | m2: function(){},
+ // | s2: "foo"
+ // | });
+ // | var C = declare(null, {
+ // | });
+ // | var D1 = A.createSubclass([B, C], {
+ // | m1: function(){},
+ // | d1: 42
+ // | });
+ // | var d1 = new D1();
+ // |
+ // | // this is equivalent to:
+ // | var D2 = declare([A, B, C], {
+ // | m1: function(){},
+ // | d1: 42
+ // | });
+ // | var d2 = new D2();
+ }
+ };
+ =====*/
+
+ // For back-compat, remove for 2.0
+ dojo.safeMixin = declare.safeMixin = safeMixin;
+ dojo.declare = declare;
+
+ return declare;
+});
+
+},
+'dojo/_base/connect':function(){
+define(["./kernel", "../on", "../topic", "../aspect", "./event", "../mouse", "./sniff", "./lang", "../keys"], function(dojo, on, hub, aspect, eventModule, mouse, has, lang){
+// module:
+// dojo/_base/connect
+
+has.add("events-keypress-typed", function(){ // keypresses should only occur a printable character is hit
+ var testKeyEvent = {charCode: 0};
+ try{
+ testKeyEvent = document.createEvent("KeyboardEvent");
+ (testKeyEvent.initKeyboardEvent || testKeyEvent.initKeyEvent).call(testKeyEvent, "keypress", true, true, null, false, false, false, false, 9, 3);
+ }catch(e){}
+ return testKeyEvent.charCode == 0 && !has("opera");
+});
+
+function connect_(obj, event, context, method, dontFix){
+ method = lang.hitch(context, method);
+ if(!obj || !(obj.addEventListener || obj.attachEvent)){
+ // it is a not a DOM node and we are using the dojo.connect style of treating a
+ // method like an event, must go right to aspect
+ return aspect.after(obj || dojo.global, event, method, true);
+ }
+ if(typeof event == "string" && event.substring(0, 2) == "on"){
+ event = event.substring(2);
+ }
+ if(!obj){
+ obj = dojo.global;
+ }
+ if(!dontFix){
+ switch(event){
+ // dojo.connect has special handling for these event types
+ case "keypress":
+ event = keypress;
+ break;
+ case "mouseenter":
+ event = mouse.enter;
+ break;
+ case "mouseleave":
+ event = mouse.leave;
+ break;
+ }
+ }
+ return on(obj, event, method, dontFix);
+}
+
+var _punctMap = {
+ 106:42,
+ 111:47,
+ 186:59,
+ 187:43,
+ 188:44,
+ 189:45,
+ 190:46,
+ 191:47,
+ 192:96,
+ 219:91,
+ 220:92,
+ 221:93,
+ 222:39,
+ 229:113
+};
+var evtCopyKey = has("mac") ? "metaKey" : "ctrlKey";
+
+
+var _synthesizeEvent = function(evt, props){
+ var faux = lang.mixin({}, evt, props);
+ setKeyChar(faux);
+ // FIXME: would prefer to use lang.hitch: lang.hitch(evt, evt.preventDefault);
+ // but it throws an error when preventDefault is invoked on Safari
+ // does Event.preventDefault not support "apply" on Safari?
+ faux.preventDefault = function(){ evt.preventDefault(); };
+ faux.stopPropagation = function(){ evt.stopPropagation(); };
+ return faux;
+};
+function setKeyChar(evt){
+ evt.keyChar = evt.charCode ? String.fromCharCode(evt.charCode) : '';
+ evt.charOrCode = evt.keyChar || evt.keyCode;
+}
+var keypress;
+if(has("events-keypress-typed")){
+ // this emulates Firefox's keypress behavior where every keydown can correspond to a keypress
+ var _trySetKeyCode = function(e, code){
+ try{
+ // squelch errors when keyCode is read-only
+ // (e.g. if keyCode is ctrl or shift)
+ return (e.keyCode = code);
+ }catch(e){
+ return 0;
+ }
+ };
+ keypress = function(object, listener){
+ var keydownSignal = on(object, "keydown", function(evt){
+ // munge key/charCode
+ var k=evt.keyCode;
+ // These are Windows Virtual Key Codes
+ // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp
+ var unprintable = (k!=13) && k!=32 && (k!=27||!has("ie")) && (k<48||k>90) && (k<96||k>111) && (k<186||k>192) && (k<219||k>222) && k!=229;
+ // synthesize keypress for most unprintables and CTRL-keys
+ if(unprintable||evt.ctrlKey){
+ var c = unprintable ? 0 : k;
+ if(evt.ctrlKey){
+ if(k==3 || k==13){
+ return listener.call(evt.currentTarget, evt); // IE will post CTRL-BREAK, CTRL-ENTER as keypress natively
+ }else if(c>95 && c<106){
+ c -= 48; // map CTRL-[numpad 0-9] to ASCII
+ }else if((!evt.shiftKey)&&(c>=65&&c<=90)){
+ c += 32; // map CTRL-[A-Z] to lowercase
+ }else{
+ c = _punctMap[c] || c; // map other problematic CTRL combinations to ASCII
+ }
+ }
+ // simulate a keypress event
+ var faux = _synthesizeEvent(evt, {type: 'keypress', faux: true, charCode: c});
+ listener.call(evt.currentTarget, faux);
+ if(has("ie")){
+ _trySetKeyCode(evt, faux.keyCode);
+ }
+ }
+ });
+ var keypressSignal = on(object, "keypress", function(evt){
+ var c = evt.charCode;
+ c = c>=32 ? c : 0;
+ evt = _synthesizeEvent(evt, {charCode: c, faux: true});
+ return listener.call(this, evt);
+ });
+ return {
+ remove: function(){
+ keydownSignal.remove();
+ keypressSignal.remove();
+ }
+ };
+ };
+}else{
+ if(has("opera")){
+ keypress = function(object, listener){
+ return on(object, "keypress", function(evt){
+ var c = evt.which;
+ if(c==3){
+ c=99; // Mozilla maps CTRL-BREAK to CTRL-c
+ }
+ // can't trap some keys at all, like INSERT and DELETE
+ // there is no differentiating info between DELETE and ".", or INSERT and "-"
+ c = c<32 && !evt.shiftKey ? 0 : c;
+ if(evt.ctrlKey && !evt.shiftKey && c>=65 && c<=90){
+ // lowercase CTRL-[A-Z] keys
+ c += 32;
+ }
+ return listener.call(this, _synthesizeEvent(evt, { charCode: c }));
+ });
+ };
+ }else{
+ keypress = function(object, listener){
+ return on(object, "keypress", function(evt){
+ setKeyChar(evt);
+ return listener.call(this, evt);
+ });
+ };
+ }
+}
+
+var connect = {
+ // summary:
+ // This module defines the dojo.connect API.
+ // This modules also provides keyboard event handling helpers.
+ // This module exports an extension event for emulating Firefox's keypress handling.
+ // However, this extension event exists primarily for backwards compatibility and
+ // is not recommended. WebKit and IE uses an alternate keypress handling (only
+ // firing for printable characters, to distinguish from keydown events), and most
+ // consider the WebKit/IE behavior more desirable.
+
+ _keypress:keypress,
+
+ connect:function(obj, event, context, method, dontFix){
+ // summary:
+ // `dojo.connect` is a deprecated event handling and delegation method in
+ // Dojo. It allows one function to "listen in" on the execution of
+ // any other, triggering the second whenever the first is called. Many
+ // listeners may be attached to a function, and source functions may
+ // be either regular function calls or DOM events.
+ //
+ // description:
+ // Connects listeners to actions, so that after event fires, a
+ // listener is called with the same arguments passed to the original
+ // function.
+ //
+ // Since `dojo.connect` allows the source of events to be either a
+ // "regular" JavaScript function or a DOM event, it provides a uniform
+ // interface for listening to all the types of events that an
+ // application is likely to deal with though a single, unified
+ // interface. DOM programmers may want to think of it as
+ // "addEventListener for everything and anything".
+ //
+ // When setting up a connection, the `event` parameter must be a
+ // string that is the name of the method/event to be listened for. If
+ // `obj` is null, `kernel.global` is assumed, meaning that connections
+ // to global methods are supported but also that you may inadvertently
+ // connect to a global by passing an incorrect object name or invalid
+ // reference.
+ //
+ // `dojo.connect` generally is forgiving. If you pass the name of a
+ // function or method that does not yet exist on `obj`, connect will
+ // not fail, but will instead set up a stub method. Similarly, null
+ // arguments may simply be omitted such that fewer than 4 arguments
+ // may be required to set up a connection See the examples for details.
+ //
+ // The return value is a handle that is needed to
+ // remove this connection with `dojo.disconnect`.
+ //
+ // obj: Object?
+ // The source object for the event function.
+ // Defaults to `kernel.global` if null.
+ // If obj is a DOM node, the connection is delegated
+ // to the DOM event manager (unless dontFix is true).
+ //
+ // event: String
+ // String name of the event function in obj.
+ // I.e. identifies a property `obj[event]`.
+ //
+ // context: Object|null
+ // The object that method will receive as "this".
+ //
+ // If context is null and method is a function, then method
+ // inherits the context of event.
+ //
+ // If method is a string then context must be the source
+ // object object for method (context[method]). If context is null,
+ // kernel.global is used.
+ //
+ // method: String|Function
+ // A function reference, or name of a function in context.
+ // The function identified by method fires after event does.
+ // method receives the same arguments as the event.
+ // See context argument comments for information on method's scope.
+ //
+ // dontFix: Boolean?
+ // If obj is a DOM node, set dontFix to true to prevent delegation
+ // of this connection to the DOM event manager.
+ //
+ // example:
+ // When obj.onchange(), do ui.update():
+ // | dojo.connect(obj, "onchange", ui, "update");
+ // | dojo.connect(obj, "onchange", ui, ui.update); // same
+ //
+ // example:
+ // Using return value for disconnect:
+ // | var link = dojo.connect(obj, "onchange", ui, "update");
+ // | ...
+ // | dojo.disconnect(link);
+ //
+ // example:
+ // When onglobalevent executes, watcher.handler is invoked:
+ // | dojo.connect(null, "onglobalevent", watcher, "handler");
+ //
+ // example:
+ // When ob.onCustomEvent executes, customEventHandler is invoked:
+ // | dojo.connect(ob, "onCustomEvent", null, "customEventHandler");
+ // | dojo.connect(ob, "onCustomEvent", "customEventHandler"); // same
+ //
+ // example:
+ // When ob.onCustomEvent executes, customEventHandler is invoked
+ // with the same scope (this):
+ // | dojo.connect(ob, "onCustomEvent", null, customEventHandler);
+ // | dojo.connect(ob, "onCustomEvent", customEventHandler); // same
+ //
+ // example:
+ // When globalEvent executes, globalHandler is invoked
+ // with the same scope (this):
+ // | dojo.connect(null, "globalEvent", null, globalHandler);
+ // | dojo.connect("globalEvent", globalHandler); // same
+
+ // normalize arguments
+ var a=arguments, args=[], i=0;
+ // if a[0] is a String, obj was omitted
+ args.push(typeof a[0] == "string" ? null : a[i++], a[i++]);
+ // if the arg-after-next is a String or Function, context was NOT omitted
+ var a1 = a[i+1];
+ args.push(typeof a1 == "string" || typeof a1 == "function" ? a[i++] : null, a[i++]);
+ // absorb any additional arguments
+ for(var l=a.length; i= 0){
+ s.width = w + u;
+ }
+ if(h >= 0){
+ s.height = h + u;
+ }
+ }
+
+ function isButtonTag(/*DomNode*/ node){
+ // summary:
+ // True if the node is BUTTON or INPUT.type="button".
+ return node.tagName.toLowerCase() == "button" ||
+ node.tagName.toLowerCase() == "input" && (node.getAttribute("type") || "").toLowerCase() == "button"; // boolean
+ }
+
+ function usesBorderBox(/*DomNode*/ node){
+ // summary:
+ // True if the node uses border-box layout.
+
+ // We could test the computed style of node to see if a particular box
+ // has been specified, but there are details and we choose not to bother.
+
+ // TABLE and BUTTON (and INPUT type=button) are always border-box by default.
+ // If you have assigned a different box to either one via CSS then
+ // box functions will break.
+
+ return geom.boxModel == "border-box" || node.tagName.toLowerCase() == "table" || isButtonTag(node); // boolean
+ }
+
+ function getBoundingClientRect(/*DomNode*/ node) {
+ // summary:
+ // Gets the bounding client rectangle for a dom node.
+ // node: DOMNode
+
+ // This will return the result of node.getBoundingClientRect if node is in the dom, and
+ // {x:0, y:0, width:0, height:0, top:0, right:0, bottom:0, left:0} if it throws an error or the node is not on the dom
+ // This will handle when IE throws an error or Edge returns an empty object when node is not on the dom
+
+ var retEmpty = { x: 0, y: 0, width: 0, height: 0, top: 0, right: 0, bottom: 0, left: 0 },
+ ret;
+
+ try {
+ ret = node.getBoundingClientRect();
+ } catch (e) {
+ // IE throws an Unspecified Error if the node is not in the dom. Handle this by returning an object with 0 values
+ return retEmpty;
+ }
+
+ // Edge returns an empty object if the node is not in the dom. Handle this by returning an object with 0 values
+ if (typeof ret.left === "undefined") { return retEmpty; }
+
+ return ret;
+ }
+
+ geom.setContentSize = function setContentSize(/*DomNode*/ node, /*Object*/ box, /*Object*/ computedStyle){
+ // summary:
+ // Sets the size of the node's contents, irrespective of margins,
+ // padding, or borders.
+ // node: DOMNode
+ // box: Object
+ // hash with optional "w", and "h" properties for "width", and "height"
+ // respectively. All specified properties should have numeric values in whole pixels.
+ // computedStyle: Object?
+ // This parameter accepts computed styles object.
+ // If this parameter is omitted, the functions will call
+ // dojo/dom-style.getComputedStyle to get one. It is a better way, calling
+ // dojo/dom-style.getComputedStyle once, and then pass the reference to this
+ // computedStyle parameter. Wherever possible, reuse the returned
+ // object of dojo/dom-style.getComputedStyle().
+
+ node = dom.byId(node);
+ var w = box.w, h = box.h;
+ if(usesBorderBox(node)){
+ var pb = geom.getPadBorderExtents(node, computedStyle);
+ if(w >= 0){
+ w += pb.w;
+ }
+ if(h >= 0){
+ h += pb.h;
+ }
+ }
+ setBox(node, NaN, NaN, w, h);
+ };
+
+ var nilExtents = {l: 0, t: 0, w: 0, h: 0};
+
+ geom.setMarginBox = function setMarginBox(/*DomNode*/ node, /*Object*/ box, /*Object*/ computedStyle){
+ // summary:
+ // sets the size of the node's margin box and placement
+ // (left/top), irrespective of box model. Think of it as a
+ // passthrough to setBox that handles box-model vagaries for
+ // you.
+ // node: DOMNode
+ // box: Object
+ // hash with optional "l", "t", "w", and "h" properties for "left", "right", "width", and "height"
+ // respectively. All specified properties should have numeric values in whole pixels.
+ // computedStyle: Object?
+ // This parameter accepts computed styles object.
+ // If this parameter is omitted, the functions will call
+ // dojo/dom-style.getComputedStyle to get one. It is a better way, calling
+ // dojo/dom-style.getComputedStyle once, and then pass the reference to this
+ // computedStyle parameter. Wherever possible, reuse the returned
+ // object of dojo/dom-style.getComputedStyle().
+
+ node = dom.byId(node);
+ var s = computedStyle || style.getComputedStyle(node), w = box.w, h = box.h,
+ // Some elements have special padding, margin, and box-model settings.
+ // To use box functions you may need to set padding, margin explicitly.
+ // Controlling box-model is harder, in a pinch you might set dojo/dom-geometry.boxModel.
+ pb = usesBorderBox(node) ? nilExtents : geom.getPadBorderExtents(node, s),
+ mb = geom.getMarginExtents(node, s);
+ if(has("webkit")){
+ // on Safari (3.1.2), button nodes with no explicit size have a default margin
+ // setting an explicit size eliminates the margin.
+ // We have to swizzle the width to get correct margin reading.
+ if(isButtonTag(node)){
+ var ns = node.style;
+ if(w >= 0 && !ns.width){
+ ns.width = "4px";
+ }
+ if(h >= 0 && !ns.height){
+ ns.height = "4px";
+ }
+ }
+ }
+ if(w >= 0){
+ w = Math.max(w - pb.w - mb.w, 0);
+ }
+ if(h >= 0){
+ h = Math.max(h - pb.h - mb.h, 0);
+ }
+ setBox(node, box.l, box.t, w, h);
+ };
+
+ // =============================
+ // Positioning
+ // =============================
+
+ geom.isBodyLtr = function isBodyLtr(/*Document?*/ doc){
+ // summary:
+ // Returns true if the current language is left-to-right, and false otherwise.
+ // doc: Document?
+ // Optional document to query. If unspecified, use win.doc.
+ // returns: Boolean
+
+ doc = doc || win.doc;
+ return (win.body(doc).dir || doc.documentElement.dir || "ltr").toLowerCase() == "ltr"; // Boolean
+ };
+
+ geom.docScroll = function docScroll(/*Document?*/ doc){
+ // summary:
+ // Returns an object with {node, x, y} with corresponding offsets.
+ // doc: Document?
+ // Optional document to query. If unspecified, use win.doc.
+ // returns: Object
+
+ doc = doc || win.doc;
+ var node = doc.parentWindow || doc.defaultView; // use UI window, not dojo.global window. TODO: use dojo/window::get() except for circular dependency problem
+ return "pageXOffset" in node ? {x: node.pageXOffset, y: node.pageYOffset } :
+ (node = has("quirks") ? win.body(doc) : doc.documentElement) &&
+ {x: geom.fixIeBiDiScrollLeft(node.scrollLeft || 0, doc), y: node.scrollTop || 0 };
+ };
+
+ geom.getIeDocumentElementOffset = function(/*Document?*/ doc){
+ // summary:
+ // Deprecated method previously used for IE6-IE7. Now, just returns `{x:0, y:0}`.
+ return {
+ x: 0,
+ y: 0
+ };
+ };
+
+ geom.fixIeBiDiScrollLeft = function fixIeBiDiScrollLeft(/*Integer*/ scrollLeft, /*Document?*/ doc){
+ // summary:
+ // In RTL direction, scrollLeft should be a negative value, but IE
+ // returns a positive one. All codes using documentElement.scrollLeft
+ // must call this function to fix this error, otherwise the position
+ // will offset to right when there is a horizontal scrollbar.
+ // scrollLeft: Number
+ // doc: Document?
+ // Optional document to query. If unspecified, use win.doc.
+ // returns: Number
+
+ // In RTL direction, scrollLeft should be a negative value, but IE
+ // returns a positive one. All codes using documentElement.scrollLeft
+ // must call this function to fix this error, otherwise the position
+ // will offset to right when there is a horizontal scrollbar.
+
+ doc = doc || win.doc;
+ var ie = has("ie");
+ if(ie && !geom.isBodyLtr(doc)){
+ var qk = has("quirks"),
+ de = qk ? win.body(doc) : doc.documentElement,
+ pwin = win.global; // TODO: use winUtils.get(doc) after resolving circular dependency b/w dom-geometry.js and dojo/window.js
+ if(ie == 6 && !qk && pwin.frameElement && de.scrollHeight > de.clientHeight){
+ scrollLeft += de.clientLeft; // workaround ie6+strict+rtl+iframe+vertical-scrollbar bug where clientWidth is too small by clientLeft pixels
+ }
+ return (ie < 8 || qk) ? (scrollLeft + de.clientWidth - de.scrollWidth) : -scrollLeft; // Integer
+ }
+ return scrollLeft; // Integer
+ };
+
+ geom.position = function(/*DomNode*/ node, /*Boolean?*/ includeScroll){
+ // summary:
+ // Gets the position and size of the passed element relative to
+ // the viewport (if includeScroll==false), or relative to the
+ // document root (if includeScroll==true).
+ //
+ // description:
+ // Returns an object of the form:
+ // `{ x: 100, y: 300, w: 20, h: 15 }`.
+ // If includeScroll==true, the x and y values will include any
+ // document offsets that may affect the position relative to the
+ // viewport.
+ // Uses the border-box model (inclusive of border and padding but
+ // not margin). Does not act as a setter.
+ // node: DOMNode|String
+ // includeScroll: Boolean?
+ // returns: Object
+
+ node = dom.byId(node);
+ var db = win.body(node.ownerDocument),
+ ret= getBoundingClientRect(node);
+ ret = {x: ret.left, y: ret.top, w: ret.right - ret.left, h: ret.bottom - ret.top};
+
+ if(has("ie") < 9){
+ // fixes the position in IE, quirks mode
+ ret.x -= (has("quirks") ? db.clientLeft + db.offsetLeft : 0);
+ ret.y -= (has("quirks") ? db.clientTop + db.offsetTop : 0);
+ }
+
+ // account for document scrolling
+ // if offsetParent is used, ret value already includes scroll position
+ // so we may have to actually remove that value if !includeScroll
+ if(includeScroll){
+ var scroll = geom.docScroll(node.ownerDocument);
+ ret.x += scroll.x;
+ ret.y += scroll.y;
+ }
+
+ return ret; // Object
+ };
+
+ // random "private" functions wildly used throughout the toolkit
+
+ geom.getMarginSize = function getMarginSize(/*DomNode*/ node, /*Object*/ computedStyle){
+ // summary:
+ // returns an object that encodes the width and height of
+ // the node's margin box
+ // node: DOMNode|String
+ // computedStyle: Object?
+ // This parameter accepts computed styles object.
+ // If this parameter is omitted, the functions will call
+ // dojo/dom-style.getComputedStyle to get one. It is a better way, calling
+ // dojo/dom-style.getComputedStyle once, and then pass the reference to this
+ // computedStyle parameter. Wherever possible, reuse the returned
+ // object of dojo/dom-style.getComputedStyle().
+
+ node = dom.byId(node);
+ var me = geom.getMarginExtents(node, computedStyle || style.getComputedStyle(node));
+ var size = getBoundingClientRect(node);
+ return {
+ w: (size.right - size.left) + me.w,
+ h: (size.bottom - size.top) + me.h
+ };
+ };
+
+ geom.normalizeEvent = function(event){
+ // summary:
+ // Normalizes the geometry of a DOM event, normalizing the pageX, pageY,
+ // offsetX, offsetY, layerX, and layerX properties
+ // event: Object
+ if(!("layerX" in event)){
+ event.layerX = event.offsetX;
+ event.layerY = event.offsetY;
+ }
+
+ if(!("pageX" in event)){
+ // FIXME: scroll position query is duped from dojo/_base/html to
+ // avoid dependency on that entire module. Now that HTML is in
+ // Base, we should convert back to something similar there.
+ var se = event.target;
+ var doc = (se && se.ownerDocument) || document;
+ // DO NOT replace the following to use dojo/_base/window.body(), in IE, document.documentElement should be used
+ // here rather than document.body
+ var docBody = has("quirks") ? doc.body : doc.documentElement;
+ event.pageX = event.clientX + geom.fixIeBiDiScrollLeft(docBody.scrollLeft || 0, doc);
+ event.pageY = event.clientY + (docBody.scrollTop || 0);
+ }
+ };
+
+ // TODO: evaluate separate getters/setters for position and sizes?
+
+ return geom;
+});
+
+},
+'dojo/dom-style':function(){
+define(["./sniff", "./dom", "./_base/window"], function(has, dom, win){
+ // module:
+ // dojo/dom-style
+
+ // =============================
+ // Style Functions
+ // =============================
+
+ // getComputedStyle drives most of the style code.
+ // Wherever possible, reuse the returned object.
+ //
+ // API functions below that need to access computed styles accept an
+ // optional computedStyle parameter.
+ // If this parameter is omitted, the functions will call getComputedStyle themselves.
+ // This way, calling code can access computedStyle once, and then pass the reference to
+ // multiple API functions.
+
+ // Although we normally eschew argument validation at this
+ // level, here we test argument 'node' for (duck)type,
+ // by testing nodeType, ecause 'document' is the 'parentNode' of 'body'
+ // it is frequently sent to this function even
+ // though it is not Element.
+ var getComputedStyle, style = {
+ // summary:
+ // This module defines the core dojo DOM style API.
+ };
+ if(has("webkit")){
+ getComputedStyle = function(/*DomNode*/ node){
+ var s;
+ if(node.nodeType == 1){
+ var dv = node.ownerDocument.defaultView;
+ s = dv.getComputedStyle(node, null);
+ if(!s && node.style){
+ node.style.display = "";
+ s = dv.getComputedStyle(node, null);
+ }
+ }
+ return s || {};
+ };
+ }else if(has("ie") && (has("ie") < 9 || has("quirks"))){
+ getComputedStyle = function(node){
+ // IE (as of 7) doesn't expose Element like sane browsers
+ // currentStyle can be null on IE8!
+ return node.nodeType == 1 /* ELEMENT_NODE*/ && node.currentStyle ? node.currentStyle : {};
+ };
+ }else{
+ getComputedStyle = function(node){
+ if(node.nodeType === 1 /* ELEMENT_NODE*/){
+ var dv = node.ownerDocument.defaultView,
+ w = dv.opener ? dv : win.global.window;
+ return w.getComputedStyle(node, null);
+ }
+ return {};
+ };
+ }
+ style.getComputedStyle = getComputedStyle;
+ /*=====
+ style.getComputedStyle = function(node){
+ // summary:
+ // Returns a "computed style" object.
+ //
+ // description:
+ // Gets a "computed style" object which can be used to gather
+ // information about the current state of the rendered node.
+ //
+ // Note that this may behave differently on different browsers.
+ // Values may have different formats and value encodings across
+ // browsers.
+ //
+ // Note also that this method is expensive. Wherever possible,
+ // reuse the returned object.
+ //
+ // Use the dojo/dom-style.get() method for more consistent (pixelized)
+ // return values.
+ //
+ // node: DOMNode
+ // A reference to a DOM node. Does NOT support taking an
+ // ID string for speed reasons.
+ // example:
+ // | require(["dojo/dom-style", "dojo/dom"], function(domStyle, dom){
+ // | domStyle.getComputedStyle(dom.byId('foo')).borderWidth;
+ // | });
+ //
+ // example:
+ // Reusing the returned object, avoiding multiple lookups:
+ // | require(["dojo/dom-style", "dojo/dom"], function(domStyle, dom){
+ // | var cs = domStyle.getComputedStyle(dom.byId("someNode"));
+ // | var w = cs.width, h = cs.height;
+ // | });
+ return; // CSS2Properties
+ };
+ =====*/
+
+ var toPixel;
+ if(!has("ie")){
+ toPixel = function(element, value){
+ // style values can be floats, client code may want
+ // to round for integer pixels.
+ return parseFloat(value) || 0;
+ };
+ }else{
+ toPixel = function(element, avalue){
+ if(!avalue){ return 0; }
+ // on IE7, medium is usually 4 pixels
+ if(avalue == "medium"){ return 4; }
+ // style values can be floats, client code may
+ // want to round this value for integer pixels.
+ if(avalue.slice && avalue.slice(-2) == 'px'){ return parseFloat(avalue); }
+ var s = element.style, rs = element.runtimeStyle, cs = element.currentStyle,
+ sLeft = s.left, rsLeft = rs.left;
+ rs.left = cs.left;
+ try{
+ // 'avalue' may be incompatible with style.left, which can cause IE to throw
+ // this has been observed for border widths using "thin", "medium", "thick" constants
+ // those particular constants could be trapped by a lookup
+ // but perhaps there are more
+ s.left = avalue;
+ avalue = s.pixelLeft;
+ }catch(e){
+ avalue = 0;
+ }
+ s.left = sLeft;
+ rs.left = rsLeft;
+ return avalue;
+ };
+ }
+ style.toPixelValue = toPixel;
+ /*=====
+ style.toPixelValue = function(node, value){
+ // summary:
+ // converts style value to pixels on IE or return a numeric value.
+ // node: DOMNode
+ // value: String
+ // returns: Number
+ };
+ =====*/
+
+ // FIXME: there opacity quirks on FF that we haven't ported over. Hrm.
+
+ var astr = "DXImageTransform.Microsoft.Alpha";
+ var af = function(n, f){
+ try{
+ return n.filters.item(astr);
+ }catch(e){
+ return f ? {} : null;
+ }
+ };
+
+ var _getOpacity =
+ has("ie") < 9 || (has("ie") < 10 && has("quirks")) ? function(node){
+ try{
+ return af(node).Opacity / 100; // Number
+ }catch(e){
+ return 1; // Number
+ }
+ } :
+ function(node){
+ return getComputedStyle(node).opacity;
+ };
+
+ var _setOpacity =
+ has("ie") < 9 || (has("ie") < 10 && has("quirks")) ? function(/*DomNode*/ node, /*Number*/ opacity){
+ if(opacity === ""){ opacity = 1; }
+ var ov = opacity * 100, fullyOpaque = opacity === 1;
+
+ // on IE7 Alpha(Filter opacity=100) makes text look fuzzy so disable it altogether (bug #2661),
+ // but still update the opacity value so we can get a correct reading if it is read later:
+ // af(node, 1).Enabled = !fullyOpaque;
+
+ if(fullyOpaque){
+ node.style.zoom = "";
+ if(af(node)){
+ node.style.filter = node.style.filter.replace(
+ new RegExp("\\s*progid:" + astr + "\\([^\\)]+?\\)", "i"), "");
+ }
+ }else{
+ node.style.zoom = 1;
+ if(af(node)){
+ af(node, 1).Opacity = ov;
+ }else{
+ node.style.filter += " progid:" + astr + "(Opacity=" + ov + ")";
+ }
+ af(node, 1).Enabled = true;
+ }
+
+ if(node.tagName.toLowerCase() == "tr"){
+ for(var td = node.firstChild; td; td = td.nextSibling){
+ if(td.tagName.toLowerCase() == "td"){
+ _setOpacity(td, opacity);
+ }
+ }
+ }
+ return opacity;
+ } :
+ function(node, opacity){
+ return node.style.opacity = opacity;
+ };
+
+ var _pixelNamesCache = {
+ left: true, top: true
+ };
+ var _pixelRegExp = /margin|padding|width|height|max|min|offset/; // |border
+ function _toStyleValue(node, type, value){
+ //TODO: should we really be doing string case conversion here? Should we cache it? Need to profile!
+ type = type.toLowerCase();
+
+ // Adjustments for IE and Edge
+ if(value == "auto"){
+ if(type == "height"){ return node.offsetHeight; }
+ if(type == "width"){ return node.offsetWidth; }
+ }
+ if(type == "fontweight"){
+ switch(value){
+ case 700: return "bold";
+ case 400:
+ default: return "normal";
+ }
+ }
+
+ if(!(type in _pixelNamesCache)){
+ _pixelNamesCache[type] = _pixelRegExp.test(type);
+ }
+ return _pixelNamesCache[type] ? toPixel(node, value) : value;
+ }
+
+ var _floatAliases = {cssFloat: 1, styleFloat: 1, "float": 1};
+
+ // public API
+
+ style.get = function getStyle(/*DOMNode|String*/ node, /*String?*/ name){
+ // summary:
+ // Accesses styles on a node.
+ // description:
+ // Getting the style value uses the computed style for the node, so the value
+ // will be a calculated value, not just the immediate node.style value.
+ // Also when getting values, use specific style names,
+ // like "borderBottomWidth" instead of "border" since compound values like
+ // "border" are not necessarily reflected as expected.
+ // If you want to get node dimensions, use `dojo/dom-geometry.getMarginBox()`,
+ // `dojo/dom-geometry.getContentBox()` or `dojo/dom-geometry.getPosition()`.
+ // node: DOMNode|String
+ // id or reference to node to get style for
+ // name: String?
+ // the style property to get
+ // example:
+ // Passing only an ID or node returns the computed style object of
+ // the node:
+ // | require(["dojo/dom-style", "dojo/dom"], function(domStyle, dom){
+ // | domStyle.get("thinger");
+ // | });
+ // example:
+ // Passing a node and a style property returns the current
+ // normalized, computed value for that property:
+ // | require(["dojo/dom-style", "dojo/dom"], function(domStyle, dom){
+ // | domStyle.get("thinger", "opacity"); // 1 by default
+ // | });
+
+ var n = dom.byId(node), l = arguments.length, op = (name == "opacity");
+ if(l == 2 && op){
+ return _getOpacity(n);
+ }
+ name = _floatAliases[name] ? "cssFloat" in n.style ? "cssFloat" : "styleFloat" : name;
+ var s = style.getComputedStyle(n);
+ return (l == 1) ? s : _toStyleValue(n, name, s[name] || n.style[name]); /* CSS2Properties||String||Number */
+ };
+
+ style.set = function setStyle(/*DOMNode|String*/ node, /*String|Object*/ name, /*String?*/ value){
+ // summary:
+ // Sets styles on a node.
+ // node: DOMNode|String
+ // id or reference to node to set style for
+ // name: String|Object
+ // the style property to set in DOM-accessor format
+ // ("borderWidth", not "border-width") or an object with key/value
+ // pairs suitable for setting each property.
+ // value: String?
+ // If passed, sets value on the node for style, handling
+ // cross-browser concerns. When setting a pixel value,
+ // be sure to include "px" in the value. For instance, top: "200px".
+ // Otherwise, in some cases, some browsers will not apply the style.
+ //
+ // example:
+ // Passing a node, a style property, and a value changes the
+ // current display of the node and returns the new computed value
+ // | require(["dojo/dom-style"], function(domStyle){
+ // | domStyle.set("thinger", "opacity", 0.5); // == 0.5
+ // | });
+ //
+ // example:
+ // Passing a node, an object-style style property sets each of the values in turn and returns the computed style object of the node:
+ // | require(["dojo/dom-style"], function(domStyle){
+ // | domStyle.set("thinger", {
+ // | "opacity": 0.5,
+ // | "border": "3px solid black",
+ // | "height": "300px"
+ // | });
+ // | });
+ //
+ // example:
+ // When the CSS style property is hyphenated, the JavaScript property is camelCased.
+ // font-size becomes fontSize, and so on.
+ // | require(["dojo/dom-style", "dojo/dom"], function(domStyle, dom){
+ // | domStyle.set("thinger",{
+ // | fontSize:"14pt",
+ // | letterSpacing:"1.2em"
+ // | });
+ // | });
+ //
+ // example:
+ // dojo/NodeList implements .style() using the same syntax, omitting the "node" parameter, calling
+ // dojo/dom-style.get() on every element of the list. See: `dojo/query` and `dojo/NodeList`
+ // | require(["dojo/dom-style", "dojo/query", "dojo/NodeList-dom"],
+ // | function(domStyle, query){
+ // | query(".someClassName").style("visibility","hidden");
+ // | // or
+ // | query("#baz > div").style({
+ // | opacity:0.75,
+ // | fontSize:"13pt"
+ // | });
+ // | });
+
+ var n = dom.byId(node), l = arguments.length, op = (name == "opacity");
+ name = _floatAliases[name] ? "cssFloat" in n.style ? "cssFloat" : "styleFloat" : name;
+ if(l == 3){
+ return op ? _setOpacity(n, value) : n.style[name] = value; // Number
+ }
+ for(var x in name){
+ style.set(node, x, name[x]);
+ }
+ return style.getComputedStyle(n);
+ };
+
+ return style;
+});
+
+},
+'dojo/mouse':function(){
+define(["./_base/kernel", "./on", "./has", "./dom", "./_base/window"], function(dojo, on, has, dom, win){
+
+ // module:
+ // dojo/mouse
+
+ has.add("dom-quirks", win.doc && win.doc.compatMode == "BackCompat");
+ has.add("events-mouseenter", win.doc && "onmouseenter" in win.doc.createElement("div"));
+ has.add("events-mousewheel", win.doc && 'onmousewheel' in win.doc);
+
+ var mouseButtons;
+ if((has("dom-quirks") && has("ie")) || !has("dom-addeventlistener")){
+ mouseButtons = {
+ LEFT: 1,
+ MIDDLE: 4,
+ RIGHT: 2,
+ // helper functions
+ isButton: function(e, button){ return e.button & button; },
+ isLeft: function(e){ return e.button & 1; },
+ isMiddle: function(e){ return e.button & 4; },
+ isRight: function(e){ return e.button & 2; }
+ };
+ }else{
+ mouseButtons = {
+ LEFT: 0,
+ MIDDLE: 1,
+ RIGHT: 2,
+ // helper functions
+ isButton: function(e, button){ return e.button == button; },
+ isLeft: function(e){ return e.button == 0; },
+ isMiddle: function(e){ return e.button == 1; },
+ isRight: function(e){ return e.button == 2; }
+ };
+ }
+ dojo.mouseButtons = mouseButtons;
+
+/*=====
+ dojo.mouseButtons = {
+ // LEFT: Number
+ // Numeric value of the left mouse button for the platform.
+ LEFT: 0,
+ // MIDDLE: Number
+ // Numeric value of the middle mouse button for the platform.
+ MIDDLE: 1,
+ // RIGHT: Number
+ // Numeric value of the right mouse button for the platform.
+ RIGHT: 2,
+
+ isButton: function(e, button){
+ // summary:
+ // Checks an event object for a pressed button
+ // e: Event
+ // Event object to examine
+ // button: Number
+ // The button value (example: dojo.mouseButton.LEFT)
+ return e.button == button; // Boolean
+ },
+ isLeft: function(e){
+ // summary:
+ // Checks an event object for the pressed left button
+ // e: Event
+ // Event object to examine
+ return e.button == 0; // Boolean
+ },
+ isMiddle: function(e){
+ // summary:
+ // Checks an event object for the pressed middle button
+ // e: Event
+ // Event object to examine
+ return e.button == 1; // Boolean
+ },
+ isRight: function(e){
+ // summary:
+ // Checks an event object for the pressed right button
+ // e: Event
+ // Event object to examine
+ return e.button == 2; // Boolean
+ }
+ };
+=====*/
+
+ function eventHandler(type, selectHandler){
+ // emulation of mouseenter/leave with mouseover/out using descendant checking
+ var handler = function(node, listener){
+ return on(node, type, function(evt){
+ if(selectHandler){
+ return selectHandler(evt, listener);
+ }
+ if(!dom.isDescendant(evt.relatedTarget, node)){
+ return listener.call(this, evt);
+ }
+ });
+ };
+ handler.bubble = function(select){
+ return eventHandler(type, function(evt, listener){
+ // using a selector, use the select function to determine if the mouse moved inside the selector and was previously outside the selector
+ var target = select(evt.target);
+ var relatedTarget = evt.relatedTarget;
+ if(target && (target != (relatedTarget && relatedTarget.nodeType == 1 && select(relatedTarget)))){
+ return listener.call(target, evt);
+ }
+ });
+ };
+ return handler;
+ }
+ var wheel;
+ if(has("events-mousewheel")){
+ wheel = 'mousewheel';
+ }else{ //firefox
+ wheel = function(node, listener){
+ return on(node, 'DOMMouseScroll', function(evt){
+ evt.wheelDelta = -evt.detail;
+ listener.call(this, evt);
+ });
+ };
+ }
+ return {
+ // summary:
+ // This module provide mouse event handling utility functions and exports
+ // mouseenter and mouseleave event emulation.
+ // example:
+ // To use these events, you register a mouseenter like this:
+ // | define(["dojo/on", "dojo/mouse"], function(on, mouse){
+ // | on(targetNode, mouse.enter, function(event){
+ // | dojo.addClass(targetNode, "highlighted");
+ // | });
+ // | on(targetNode, mouse.leave, function(event){
+ // | dojo.removeClass(targetNode, "highlighted");
+ // | });
+
+ _eventHandler: eventHandler, // for dojo/touch
+
+ // enter: Synthetic Event
+ // This is an extension event for the mouseenter that IE provides, emulating the
+ // behavior on other browsers.
+ enter: eventHandler("mouseover"),
+
+ // leave: Synthetic Event
+ // This is an extension event for the mouseleave that IE provides, emulating the
+ // behavior on other browsers.
+ leave: eventHandler("mouseout"),
+
+ // wheel: Normalized Mouse Wheel Event
+ // This is an extension event for the mousewheel that non-Mozilla browsers provide,
+ // emulating the behavior on Mozilla based browsers.
+ wheel: wheel,
+
+ isLeft: mouseButtons.isLeft,
+ /*=====
+ isLeft: function(){
+ // summary:
+ // Test an event object (from a mousedown event) to see if the left button was pressed.
+ },
+ =====*/
+
+ isMiddle: mouseButtons.isMiddle,
+ /*=====
+ isMiddle: function(){
+ // summary:
+ // Test an event object (from a mousedown event) to see if the middle button was pressed.
+ },
+ =====*/
+
+ isRight: mouseButtons.isRight
+ /*=====
+ , isRight: function(){
+ // summary:
+ // Test an event object (from a mousedown event) to see if the right button was pressed.
+ }
+ =====*/
+ };
+});
+
+},
+'dojo/keys':function(){
+define(["./_base/kernel", "./sniff"], function(dojo, has){
+
+ // module:
+ // dojo/keys
+
+ return dojo.keys = {
+ // summary:
+ // Definitions for common key values. Client code should test keyCode against these named constants,
+ // as the actual codes can vary by browser.
+
+ BACKSPACE: 8,
+ TAB: 9,
+ CLEAR: 12,
+ ENTER: 13,
+ SHIFT: 16,
+ CTRL: 17,
+ ALT: 18,
+ META: has("webkit") ? 91 : 224, // the apple key on macs
+ PAUSE: 19,
+ CAPS_LOCK: 20,
+ ESCAPE: 27,
+ SPACE: 32,
+ PAGE_UP: 33,
+ PAGE_DOWN: 34,
+ END: 35,
+ HOME: 36,
+ LEFT_ARROW: 37,
+ UP_ARROW: 38,
+ RIGHT_ARROW: 39,
+ DOWN_ARROW: 40,
+ INSERT: 45,
+ DELETE: 46,
+ HELP: 47,
+ LEFT_WINDOW: 91,
+ RIGHT_WINDOW: 92,
+ SELECT: 93,
+ NUMPAD_0: 96,
+ NUMPAD_1: 97,
+ NUMPAD_2: 98,
+ NUMPAD_3: 99,
+ NUMPAD_4: 100,
+ NUMPAD_5: 101,
+ NUMPAD_6: 102,
+ NUMPAD_7: 103,
+ NUMPAD_8: 104,
+ NUMPAD_9: 105,
+ NUMPAD_MULTIPLY: 106,
+ NUMPAD_PLUS: 107,
+ NUMPAD_ENTER: 108,
+ NUMPAD_MINUS: 109,
+ NUMPAD_PERIOD: 110,
+ NUMPAD_DIVIDE: 111,
+ F1: 112,
+ F2: 113,
+ F3: 114,
+ F4: 115,
+ F5: 116,
+ F6: 117,
+ F7: 118,
+ F8: 119,
+ F9: 120,
+ F10: 121,
+ F11: 122,
+ F12: 123,
+ F13: 124,
+ F14: 125,
+ F15: 126,
+ NUM_LOCK: 144,
+ SCROLL_LOCK: 145,
+ UP_DPAD: 175,
+ DOWN_DPAD: 176,
+ LEFT_DPAD: 177,
+ RIGHT_DPAD: 178,
+ // virtual key mapping
+ copyKey: has("mac") && !has("air") ? (has("safari") ? 91 : 224 ) : 17
+ };
+});
+
+},
+'dojo/_base/Color':function(){
+define(["./kernel", "./lang", "./array", "./config"], function(dojo, lang, ArrayUtil, config){
+
+ var Color = dojo.Color = function(/*Array|String|Object*/ color){
+ // summary:
+ // Takes a named string, hex string, array of rgb or rgba values,
+ // an object with r, g, b, and a properties, or another `Color` object
+ // and creates a new Color instance to work from.
+ //
+ // example:
+ // Work with a Color instance:
+ // | require(["dojo/_base/color"], function(Color){
+ // | var c = new Color();
+ // | c.setColor([0,0,0]); // black
+ // | var hex = c.toHex(); // #000000
+ // | });
+ //
+ // example:
+ // Work with a node's color:
+ // |
+ // | require(["dojo/_base/color", "dojo/dom-style"], function(Color, domStyle){
+ // | var color = domStyle("someNode", "backgroundColor");
+ // | var n = new Color(color);
+ // | // adjust the color some
+ // | n.r *= .5;
+ // | console.log(n.toString()); // rgb(128, 255, 255);
+ // | });
+ if(color){ this.setColor(color); }
+ };
+
+ // FIXME:
+ // there's got to be a more space-efficient way to encode or discover
+ // these!! Use hex?
+ Color.named = {
+ // summary:
+ // Dictionary list of all CSS named colors, by name. Values are 3-item arrays with corresponding RG and B values.
+ "black": [0,0,0],
+ "silver": [192,192,192],
+ "gray": [128,128,128],
+ "white": [255,255,255],
+ "maroon": [128,0,0],
+ "red": [255,0,0],
+ "purple": [128,0,128],
+ "fuchsia":[255,0,255],
+ "green": [0,128,0],
+ "lime": [0,255,0],
+ "olive": [128,128,0],
+ "yellow": [255,255,0],
+ "navy": [0,0,128],
+ "blue": [0,0,255],
+ "teal": [0,128,128],
+ "aqua": [0,255,255],
+ "transparent": config.transparentColor || [0,0,0,0]
+ };
+
+ lang.extend(Color, {
+ r: 255, g: 255, b: 255, a: 1,
+ _set: function(r, g, b, a){
+ var t = this; t.r = r; t.g = g; t.b = b; t.a = a;
+ },
+ setColor: function(/*Array|String|Object*/ color){
+ // summary:
+ // Takes a named string, hex string, array of rgb or rgba values,
+ // an object with r, g, b, and a properties, or another `Color` object
+ // and sets this color instance to that value.
+ //
+ // example:
+ // | require(["dojo/_base/color"], function(Color){
+ // | var c = new Color(); // no color
+ // | c.setColor("#ededed"); // greyish
+ // | });
+ if(lang.isString(color)){
+ Color.fromString(color, this);
+ }else if(lang.isArray(color)){
+ Color.fromArray(color, this);
+ }else{
+ this._set(color.r, color.g, color.b, color.a);
+ if(!(color instanceof Color)){ this.sanitize(); }
+ }
+ return this; // Color
+ },
+ sanitize: function(){
+ // summary:
+ // Ensures the object has correct attributes
+ // description:
+ // the default implementation does nothing, include dojo.colors to
+ // augment it with real checks
+ return this; // Color
+ },
+ toRgb: function(){
+ // summary:
+ // Returns 3 component array of rgb values
+ // example:
+ // | require(["dojo/_base/color"], function(Color){
+ // | var c = new Color("#000000");
+ // | console.log(c.toRgb()); // [0,0,0]
+ // | });
+ var t = this;
+ return [t.r, t.g, t.b]; // Array
+ },
+ toRgba: function(){
+ // summary:
+ // Returns a 4 component array of rgba values from the color
+ // represented by this object.
+ var t = this;
+ return [t.r, t.g, t.b, t.a]; // Array
+ },
+ toHex: function(){
+ // summary:
+ // Returns a CSS color string in hexadecimal representation
+ // example:
+ // | require(["dojo/_base/color"], function(Color){
+ // | console.log(new Color([0,0,0]).toHex()); // #000000
+ // | });
+ var arr = ArrayUtil.map(["r", "g", "b"], function(x){
+ var s = this[x].toString(16);
+ return s.length < 2 ? "0" + s : s;
+ }, this);
+ return "#" + arr.join(""); // String
+ },
+ toCss: function(/*Boolean?*/ includeAlpha){
+ // summary:
+ // Returns a css color string in rgb(a) representation
+ // example:
+ // | require(["dojo/_base/color"], function(Color){
+ // | var c = new Color("#FFF").toCss();
+ // | console.log(c); // rgb('255','255','255')
+ // | });
+ var t = this, rgb = t.r + ", " + t.g + ", " + t.b;
+ return (includeAlpha ? "rgba(" + rgb + ", " + t.a : "rgb(" + rgb) + ")"; // String
+ },
+ toString: function(){
+ // summary:
+ // Returns a visual representation of the color
+ return this.toCss(true); // String
+ }
+ });
+
+ Color.blendColors = dojo.blendColors = function(
+ /*Color*/ start,
+ /*Color*/ end,
+ /*Number*/ weight,
+ /*Color?*/ obj
+ ){
+ // summary:
+ // Blend colors end and start with weight from 0 to 1, 0.5 being a 50/50 blend,
+ // can reuse a previously allocated Color object for the result
+ var t = obj || new Color();
+ t.r = Math.round(start.r + (end.r - start.r) * weight);
+ t.g = Math.round(start.g + (end.g - start.g) * weight);
+ t.b = Math.round(start.b + (end.b - start.b) * weight);
+ t.a = start.a + (end.a - start.a) * weight;
+ return t.sanitize(); // Color
+ };
+
+ Color.fromRgb = dojo.colorFromRgb = function(/*String*/ color, /*Color?*/ obj){
+ // summary:
+ // Returns a `Color` instance from a string of the form
+ // "rgb(...)" or "rgba(...)". Optionally accepts a `Color`
+ // object to update with the parsed value and return instead of
+ // creating a new object.
+ // returns:
+ // A Color object. If obj is passed, it will be the return value.
+ var m = color.toLowerCase().match(/^rgba?\(([\s\.,0-9]+)\)/);
+ return m && Color.fromArray(m[1].split(/\s*,\s*/), obj); // Color
+ };
+
+ Color.fromHex = dojo.colorFromHex = function(/*String*/ color, /*Color?*/ obj){
+ // summary:
+ // Converts a hex string with a '#' prefix to a color object.
+ // Supports 12-bit #rgb shorthand. Optionally accepts a
+ // `Color` object to update with the parsed value.
+ //
+ // returns:
+ // A Color object. If obj is passed, it will be the return value.
+ //
+ // example:
+ // | require(["dojo/_base/color"], function(Color){
+ // | var thing = new Color().fromHex("#ededed"); // grey, longhand
+ // | var thing2 = new Color().fromHex("#000"); // black, shorthand
+ // | });
+ var t = obj || new Color(),
+ bits = (color.length == 4) ? 4 : 8,
+ mask = (1 << bits) - 1;
+ color = Number("0x" + color.substr(1));
+ if(isNaN(color)){
+ return null; // Color
+ }
+ ArrayUtil.forEach(["b", "g", "r"], function(x){
+ var c = color & mask;
+ color >>= bits;
+ t[x] = bits == 4 ? 17 * c : c;
+ });
+ t.a = 1;
+ return t; // Color
+ };
+
+ Color.fromArray = dojo.colorFromArray = function(/*Array*/ a, /*Color?*/ obj){
+ // summary:
+ // Builds a `Color` from a 3 or 4 element array, mapping each
+ // element in sequence to the rgb(a) values of the color.
+ // example:
+ // | require(["dojo/_base/color"], function(Color){
+ // | var myColor = new Color().fromArray([237,237,237,0.5]); // grey, 50% alpha
+ // | });
+ // returns:
+ // A Color object. If obj is passed, it will be the return value.
+ var t = obj || new Color();
+ t._set(Number(a[0]), Number(a[1]), Number(a[2]), Number(a[3]));
+ if(isNaN(t.a)){ t.a = 1; }
+ return t.sanitize(); // Color
+ };
+
+ Color.fromString = dojo.colorFromString = function(/*String*/ str, /*Color?*/ obj){
+ // summary:
+ // Parses `str` for a color value. Accepts hex, rgb, and rgba
+ // style color values.
+ // description:
+ // Acceptable input values for str may include arrays of any form
+ // accepted by dojo.colorFromArray, hex strings such as "#aaaaaa", or
+ // rgb or rgba strings such as "rgb(133, 200, 16)" or "rgba(10, 10,
+ // 10, 50)"
+ // returns:
+ // A Color object. If obj is passed, it will be the return value.
+ var a = Color.named[str];
+ return a && Color.fromArray(a, obj) || Color.fromRgb(str, obj) || Color.fromHex(str, obj); // Color
+ };
+
+ return Color;
+});
+
+},
+'dojo/_base/browser':function(){
+if(require.has){
+ require.has.add("config-selectorEngine", "acme");
+}
+define([
+ "../ready",
+ "./kernel",
+ "./connect", // until we decide if connect is going back into non-browser environments
+ "./unload",
+ "./window",
+ "./event",
+ "./html",
+ "./NodeList",
+ "../query",
+ "./xhr",
+ "./fx"], function(dojo){
+
+ // module:
+ // dojo/_base/browser
+
+ /*=====
+ return {
+ // summary:
+ // This module causes the browser-only base modules to be loaded.
+ };
+ =====*/
+
+ return dojo;
+});
+
+},
+'dojo/_base/unload':function(){
+define(["./kernel", "./lang", "../on"], function(dojo, lang, on){
+
+// module:
+// dojo/unload
+
+var win = window;
+
+var unload = {
+ // summary:
+ // This module contains the document and window unload detection API.
+ // This module is deprecated. Use on(window, "unload", func)
+ // and on(window, "beforeunload", func) instead.
+
+ addOnWindowUnload: function(/*Object|Function?*/ obj, /*String|Function?*/ functionName){
+ // summary:
+ // Registers a function to be triggered when window.onunload fires.
+ // Deprecated, use on(window, "unload", lang.hitch(obj, functionName)) instead.
+ // description:
+ // The first time that addOnWindowUnload is called Dojo
+ // will register a page listener to trigger your unload
+ // handler with. Note that registering these handlers may
+ // destroy "fastback" page caching in browsers that support
+ // it. Be careful trying to modify the DOM or access
+ // JavaScript properties during this phase of page unloading:
+ // they may not always be available. Consider
+ // addOnUnload() if you need to modify the DOM or do
+ // heavy JavaScript work since it fires at the equivalent of
+ // the page's "onbeforeunload" event.
+ // example:
+ // | var afunc = function() {console.log("global function");};
+ // | require(["dojo/_base/unload"], function(unload) {
+ // | var foo = {bar: function(){ console.log("bar unloading...");},
+ // | data: "mydata"};
+ // | unload.addOnWindowUnload(afunc);
+ // | unload.addOnWindowUnload(foo, "bar");
+ // | unload.addOnWindowUnload(foo, function(){console.log("", this.data);});
+ // | });
+
+ if (!dojo.windowUnloaded){
+ on(win, "unload", (dojo.windowUnloaded = function(){
+ // summary:
+ // signal fired by impending window destruction. You may use
+ // dojo.addOnWindowUnload() to register a listener for this
+ // event. NOTE: if you wish to dojo.connect() to this method
+ // to perform page/application cleanup, be aware that this
+ // event WILL NOT fire if no handler has been registered with
+ // addOnWindowUnload(). This behavior started in Dojo 1.3.
+ // Previous versions always triggered windowUnloaded(). See
+ // addOnWindowUnload for more info.
+ }));
+ }
+ on(win, "unload", lang.hitch(obj, functionName));
+ },
+
+ addOnUnload: function(/*Object?|Function?*/ obj, /*String|Function?*/ functionName){
+ // summary:
+ // Registers a function to be triggered when the page unloads.
+ // Deprecated, use on(window, "beforeunload", lang.hitch(obj, functionName)) instead.
+ // description:
+ // The first time that addOnUnload is called Dojo will
+ // register a page listener to trigger your unload handler
+ // with.
+ //
+ // In a browser environment, the functions will be triggered
+ // during the window.onbeforeunload event. Be careful of doing
+ // too much work in an unload handler. onbeforeunload can be
+ // triggered if a link to download a file is clicked, or if
+ // the link is a javascript: link. In these cases, the
+ // onbeforeunload event fires, but the document is not
+ // actually destroyed. So be careful about doing destructive
+ // operations in a dojo.addOnUnload callback.
+ //
+ // Further note that calling dojo.addOnUnload will prevent
+ // browsers from using a "fast back" cache to make page
+ // loading via back button instantaneous.
+ // example:
+ // | var afunc = function() {console.log("global function");};
+ // | require(["dojo/_base/unload"], function(unload) {
+ // | var foo = {bar: function(){ console.log("bar unloading...");},
+ // | data: "mydata"};
+ // | unload.addOnUnload(afunc);
+ // | unload.addOnUnload(foo, "bar");
+ // | unload.addOnUnload(foo, function(){console.log("", this.data);});
+ // | });
+
+ on(win, "beforeunload", lang.hitch(obj, functionName));
+ }
+};
+
+dojo.addOnWindowUnload = unload.addOnWindowUnload;
+dojo.addOnUnload = unload.addOnUnload;
+
+return unload;
+
+});
+
+},
+'dojo/_base/html':function(){
+define(["./kernel", "../dom", "../dom-style", "../dom-attr", "../dom-prop", "../dom-class", "../dom-construct", "../dom-geometry"], function(dojo, dom, style, attr, prop, cls, ctr, geom){
+ // module:
+ // dojo/dom
+
+ /*=====
+ return {
+ // summary:
+ // This module is a stub for the core dojo DOM API.
+ };
+ =====*/
+
+ // mix-in dom
+ dojo.byId = dom.byId;
+ dojo.isDescendant = dom.isDescendant;
+ dojo.setSelectable = dom.setSelectable;
+
+ // mix-in dom-attr
+ dojo.getAttr = attr.get;
+ dojo.setAttr = attr.set;
+ dojo.hasAttr = attr.has;
+ dojo.removeAttr = attr.remove;
+ dojo.getNodeProp = attr.getNodeProp;
+
+ dojo.attr = function(node, name, value){
+ // summary:
+ // Gets or sets an attribute on an HTML element.
+ // description:
+ // Handles normalized getting and setting of attributes on DOM
+ // Nodes. If 2 arguments are passed, and a the second argument is a
+ // string, acts as a getter.
+ //
+ // If a third argument is passed, or if the second argument is a
+ // map of attributes, acts as a setter.
+ //
+ // When passing functions as values, note that they will not be
+ // directly assigned to slots on the node, but rather the default
+ // behavior will be removed and the new behavior will be added
+ // using `dojo.connect()`, meaning that event handler properties
+ // will be normalized and that some caveats with regards to
+ // non-standard behaviors for onsubmit apply. Namely that you
+ // should cancel form submission using `dojo.stopEvent()` on the
+ // passed event object instead of returning a boolean value from
+ // the handler itself.
+ // node: DOMNode|String
+ // id or reference to the element to get or set the attribute on
+ // name: String|Object
+ // the name of the attribute to get or set.
+ // value: String?
+ // The value to set for the attribute
+ // returns:
+ // when used as a getter, the value of the requested attribute
+ // or null if that attribute does not have a specified or
+ // default value;
+ //
+ // when used as a setter, the DOM node
+ //
+ // example:
+ // | // get the current value of the "foo" attribute on a node
+ // | dojo.attr(dojo.byId("nodeId"), "foo");
+ // | // or we can just pass the id:
+ // | dojo.attr("nodeId", "foo");
+ //
+ // example:
+ // | // use attr() to set the tab index
+ // | dojo.attr("nodeId", "tabIndex", 3);
+ // |
+ //
+ // example:
+ // Set multiple values at once, including event handlers:
+ // | dojo.attr("formId", {
+ // | "foo": "bar",
+ // | "tabIndex": -1,
+ // | "method": "POST",
+ // | "onsubmit": function(e){
+ // | // stop submitting the form. Note that the IE behavior
+ // | // of returning true or false will have no effect here
+ // | // since our handler is connect()ed to the built-in
+ // | // onsubmit behavior and so we need to use
+ // | // dojo.stopEvent() to ensure that the submission
+ // | // doesn't proceed.
+ // | dojo.stopEvent(e);
+ // |
+ // | // submit the form with Ajax
+ // | dojo.xhrPost({ form: "formId" });
+ // | }
+ // | });
+ //
+ // example:
+ // Style is s special case: Only set with an object hash of styles
+ // | dojo.attr("someNode",{
+ // | id:"bar",
+ // | style:{
+ // | width:"200px", height:"100px", color:"#000"
+ // | }
+ // | });
+ //
+ // example:
+ // Again, only set style as an object hash of styles:
+ // | var obj = { color:"#fff", backgroundColor:"#000" };
+ // | dojo.attr("someNode", "style", obj);
+ // |
+ // | // though shorter to use `dojo.style()` in this case:
+ // | dojo.style("someNode", obj);
+
+ if(arguments.length == 2){
+ return attr[typeof name == "string" ? "get" : "set"](node, name);
+ }
+ return attr.set(node, name, value);
+ };
+
+ // mix-in dom-class
+ dojo.hasClass = cls.contains;
+ dojo.addClass = cls.add;
+ dojo.removeClass = cls.remove;
+ dojo.toggleClass = cls.toggle;
+ dojo.replaceClass = cls.replace;
+
+ // mix-in dom-construct
+ dojo._toDom = dojo.toDom = ctr.toDom;
+ dojo.place = ctr.place;
+ dojo.create = ctr.create;
+ dojo.empty = function(node){ ctr.empty(node); };
+ dojo._destroyElement = dojo.destroy = function(node){ ctr.destroy(node); };
+
+ // mix-in dom-geometry
+ dojo._getPadExtents = dojo.getPadExtents = geom.getPadExtents;
+ dojo._getBorderExtents = dojo.getBorderExtents = geom.getBorderExtents;
+ dojo._getPadBorderExtents = dojo.getPadBorderExtents = geom.getPadBorderExtents;
+ dojo._getMarginExtents = dojo.getMarginExtents = geom.getMarginExtents;
+ dojo._getMarginSize = dojo.getMarginSize = geom.getMarginSize;
+ dojo._getMarginBox = dojo.getMarginBox = geom.getMarginBox;
+ dojo.setMarginBox = geom.setMarginBox;
+ dojo._getContentBox = dojo.getContentBox = geom.getContentBox;
+ dojo.setContentSize = geom.setContentSize;
+ dojo._isBodyLtr = dojo.isBodyLtr = geom.isBodyLtr;
+ dojo._docScroll = dojo.docScroll = geom.docScroll;
+ dojo._getIeDocumentElementOffset = dojo.getIeDocumentElementOffset = geom.getIeDocumentElementOffset;
+ dojo._fixIeBiDiScrollLeft = dojo.fixIeBiDiScrollLeft = geom.fixIeBiDiScrollLeft;
+ dojo.position = geom.position;
+
+ dojo.marginBox = function marginBox(/*DomNode|String*/node, /*Object?*/box){
+ // summary:
+ // Getter/setter for the margin-box of node.
+ // description:
+ // Getter/setter for the margin-box of node.
+ // Returns an object in the expected format of box (regardless
+ // if box is passed). The object might look like:
+ // `{ l: 50, t: 200, w: 300: h: 150 }`
+ // for a node offset from its parent 50px to the left, 200px from
+ // the top with a margin width of 300px and a margin-height of
+ // 150px.
+ // node:
+ // id or reference to DOM Node to get/set box for
+ // box:
+ // If passed, denotes that dojo.marginBox() should
+ // update/set the margin box for node. Box is an object in the
+ // above format. All properties are optional if passed.
+ // example:
+ // Retrieve the margin box of a passed node
+ // | var box = dojo.marginBox("someNodeId");
+ // | console.dir(box);
+ //
+ // example:
+ // Set a node's margin box to the size of another node
+ // | var box = dojo.marginBox("someNodeId");
+ // | dojo.marginBox("someOtherNode", box);
+ return box ? geom.setMarginBox(node, box) : geom.getMarginBox(node); // Object
+ };
+
+ dojo.contentBox = function contentBox(/*DomNode|String*/node, /*Object?*/box){
+ // summary:
+ // Getter/setter for the content-box of node.
+ // description:
+ // Returns an object in the expected format of box (regardless if box is passed).
+ // The object might look like:
+ // `{ l: 50, t: 200, w: 300: h: 150 }`
+ // for a node offset from its parent 50px to the left, 200px from
+ // the top with a content width of 300px and a content-height of
+ // 150px. Note that the content box may have a much larger border
+ // or margin box, depending on the box model currently in use and
+ // CSS values set/inherited for node.
+ // While the getter will return top and left values, the
+ // setter only accepts setting the width and height.
+ // node:
+ // id or reference to DOM Node to get/set box for
+ // box:
+ // If passed, denotes that dojo.contentBox() should
+ // update/set the content box for node. Box is an object in the
+ // above format, but only w (width) and h (height) are supported.
+ // All properties are optional if passed.
+ return box ? geom.setContentSize(node, box) : geom.getContentBox(node); // Object
+ };
+
+ dojo.coords = function(/*DomNode|String*/node, /*Boolean?*/includeScroll){
+ // summary:
+ // Deprecated: Use position() for border-box x/y/w/h
+ // or marginBox() for margin-box w/h/l/t.
+ //
+ // Returns an object that measures margin-box (w)idth/(h)eight
+ // and absolute position x/y of the border-box. Also returned
+ // is computed (l)eft and (t)op values in pixels from the
+ // node's offsetParent as returned from marginBox().
+ // Return value will be in the form:
+ //| { l: 50, t: 200, w: 300: h: 150, x: 100, y: 300 }
+ // Does not act as a setter. If includeScroll is passed, the x and
+ // y params are affected as one would expect in dojo.position().
+ dojo.deprecated("dojo.coords()", "Use dojo.position() or dojo.marginBox().");
+ node = dom.byId(node);
+ var s = style.getComputedStyle(node), mb = geom.getMarginBox(node, s);
+ var abs = geom.position(node, includeScroll);
+ mb.x = abs.x;
+ mb.y = abs.y;
+ return mb; // Object
+ };
+
+ // mix-in dom-prop
+ dojo.getProp = prop.get;
+ dojo.setProp = prop.set;
+
+ dojo.prop = function(/*DomNode|String*/node, /*String|Object*/name, /*String?*/value){
+ // summary:
+ // Gets or sets a property on an HTML element.
+ // description:
+ // Handles normalized getting and setting of properties on DOM
+ // Nodes. If 2 arguments are passed, and a the second argument is a
+ // string, acts as a getter.
+ //
+ // If a third argument is passed, or if the second argument is a
+ // map of attributes, acts as a setter.
+ //
+ // When passing functions as values, note that they will not be
+ // directly assigned to slots on the node, but rather the default
+ // behavior will be removed and the new behavior will be added
+ // using `dojo.connect()`, meaning that event handler properties
+ // will be normalized and that some caveats with regards to
+ // non-standard behaviors for onsubmit apply. Namely that you
+ // should cancel form submission using `dojo.stopEvent()` on the
+ // passed event object instead of returning a boolean value from
+ // the handler itself.
+ // node:
+ // id or reference to the element to get or set the property on
+ // name:
+ // the name of the property to get or set.
+ // value:
+ // The value to set for the property
+ // returns:
+ // when used as a getter, the value of the requested property
+ // or null if that attribute does not have a specified or
+ // default value;
+ //
+ // when used as a setter, the DOM node
+ //
+ // example:
+ // | // get the current value of the "foo" property on a node
+ // | dojo.prop(dojo.byId("nodeId"), "foo");
+ // | // or we can just pass the id:
+ // | dojo.prop("nodeId", "foo");
+ //
+ // example:
+ // | // use prop() to set the tab index
+ // | dojo.prop("nodeId", "tabIndex", 3);
+ // |
+ //
+ // example:
+ // Set multiple values at once, including event handlers:
+ // | dojo.prop("formId", {
+ // | "foo": "bar",
+ // | "tabIndex": -1,
+ // | "method": "POST",
+ // | "onsubmit": function(e){
+ // | // stop submitting the form. Note that the IE behavior
+ // | // of returning true or false will have no effect here
+ // | // since our handler is connect()ed to the built-in
+ // | // onsubmit behavior and so we need to use
+ // | // dojo.stopEvent() to ensure that the submission
+ // | // doesn't proceed.
+ // | dojo.stopEvent(e);
+ // |
+ // | // submit the form with Ajax
+ // | dojo.xhrPost({ form: "formId" });
+ // | }
+ // | });
+ //
+ // example:
+ // Style is s special case: Only set with an object hash of styles
+ // | dojo.prop("someNode",{
+ // | id:"bar",
+ // | style:{
+ // | width:"200px", height:"100px", color:"#000"
+ // | }
+ // | });
+ //
+ // example:
+ // Again, only set style as an object hash of styles:
+ // | var obj = { color:"#fff", backgroundColor:"#000" };
+ // | dojo.prop("someNode", "style", obj);
+ // |
+ // | // though shorter to use `dojo.style()` in this case:
+ // | dojo.style("someNode", obj);
+
+ if(arguments.length == 2){
+ return prop[typeof name == "string" ? "get" : "set"](node, name);
+ }
+ // setter
+ return prop.set(node, name, value);
+ };
+
+ // mix-in dom-style
+ dojo.getStyle = style.get;
+ dojo.setStyle = style.set;
+ dojo.getComputedStyle = style.getComputedStyle;
+ dojo.__toPixelValue = dojo.toPixelValue = style.toPixelValue;
+
+ dojo.style = function(node, name, value){
+ // summary:
+ // Accesses styles on a node. If 2 arguments are
+ // passed, acts as a getter. If 3 arguments are passed, acts
+ // as a setter.
+ // description:
+ // Getting the style value uses the computed style for the node, so the value
+ // will be a calculated value, not just the immediate node.style value.
+ // Also when getting values, use specific style names,
+ // like "borderBottomWidth" instead of "border" since compound values like
+ // "border" are not necessarily reflected as expected.
+ // If you want to get node dimensions, use `dojo.marginBox()`,
+ // `dojo.contentBox()` or `dojo.position()`.
+ // node: DOMNode|String
+ // id or reference to node to get/set style for
+ // name: String|Object?
+ // the style property to set in DOM-accessor format
+ // ("borderWidth", not "border-width") or an object with key/value
+ // pairs suitable for setting each property.
+ // value: String?
+ // If passed, sets value on the node for style, handling
+ // cross-browser concerns. When setting a pixel value,
+ // be sure to include "px" in the value. For instance, top: "200px".
+ // Otherwise, in some cases, some browsers will not apply the style.
+ // returns:
+ // when used as a getter, return the computed style of the node if passing in an ID or node,
+ // or return the normalized, computed value for the property when passing in a node and a style property
+ // example:
+ // Passing only an ID or node returns the computed style object of
+ // the node:
+ // | dojo.style("thinger");
+ // example:
+ // Passing a node and a style property returns the current
+ // normalized, computed value for that property:
+ // | dojo.style("thinger", "opacity"); // 1 by default
+ //
+ // example:
+ // Passing a node, a style property, and a value changes the
+ // current display of the node and returns the new computed value
+ // | dojo.style("thinger", "opacity", 0.5); // == 0.5
+ //
+ // example:
+ // Passing a node, an object-style style property sets each of the values in turn and returns the computed style object of the node:
+ // | dojo.style("thinger", {
+ // | "opacity": 0.5,
+ // | "border": "3px solid black",
+ // | "height": "300px"
+ // | });
+ //
+ // example:
+ // When the CSS style property is hyphenated, the JavaScript property is camelCased.
+ // font-size becomes fontSize, and so on.
+ // | dojo.style("thinger",{
+ // | fontSize:"14pt",
+ // | letterSpacing:"1.2em"
+ // | });
+ //
+ // example:
+ // dojo/NodeList implements .style() using the same syntax, omitting the "node" parameter, calling
+ // dojo.style() on every element of the list. See: `dojo/query` and `dojo/NodeList`
+ // | dojo.query(".someClassName").style("visibility","hidden");
+ // | // or
+ // | dojo.query("#baz > div").style({
+ // | opacity:0.75,
+ // | fontSize:"13pt"
+ // | });
+
+ switch(arguments.length){
+ case 1:
+ return style.get(node);
+ case 2:
+ return style[typeof name == "string" ? "get" : "set"](node, name);
+ }
+ // setter
+ return style.set(node, name, value);
+ };
+
+ return dojo;
+});
+
+},
+'dojo/dom-attr':function(){
+define(["exports", "./sniff", "./_base/lang", "./dom", "./dom-style", "./dom-prop"],
+ function(exports, has, lang, dom, style, prop){
+ // module:
+ // dojo/dom-attr
+ // summary:
+ // This module defines the core dojo DOM attributes API.
+
+ // TODOC: summary not showing up in output see https://github.com/csnover/js-doc-parse/issues/42
+
+ // =============================
+ // Element attribute Functions
+ // =============================
+
+ // This module will be obsolete soon. Use dojo/prop instead.
+
+ // dojo/dom-attr.get() should conform to http://www.w3.org/TR/DOM-Level-2-Core/
+
+ // attribute-related functions (to be obsolete soon)
+ var forcePropNames = {
+ innerHTML: 1,
+ textContent:1,
+ className: 1,
+ htmlFor: has("ie") ? 1 : 0,
+ value: 1
+ },
+ attrNames = {
+ // original attribute names
+ classname: "class",
+ htmlfor: "for",
+ // for IE
+ tabindex: "tabIndex",
+ readonly: "readOnly"
+ };
+
+ function _hasAttr(node, name){
+ var attr = node.getAttributeNode && node.getAttributeNode(name);
+ return !!attr && attr.specified; // Boolean
+ }
+
+ // There is a difference in the presence of certain properties and their default values
+ // between browsers. For example, on IE "disabled" is present on all elements,
+ // but it is value is "false"; "tabIndex" of
returns 0 by default on IE, yet other browsers
+ // can return -1.
+
+ exports.has = function hasAttr(/*DOMNode|String*/ node, /*String*/ name){
+ // summary:
+ // Returns true if the requested attribute is specified on the
+ // given element, and false otherwise.
+ // node: DOMNode|String
+ // id or reference to the element to check
+ // name: String
+ // the name of the attribute
+ // returns: Boolean
+ // true if the requested attribute is specified on the
+ // given element, and false otherwise
+
+ var lc = name.toLowerCase();
+ return !!forcePropNames[prop.names[lc] || name] || _hasAttr(dom.byId(node), attrNames[lc] || name); // Boolean
+ };
+
+ exports.get = function getAttr(/*DOMNode|String*/ node, /*String*/ name){
+ // summary:
+ // Gets an attribute on an HTML element.
+ // description:
+ // Handles normalized getting of attributes on DOM Nodes.
+ // node: DOMNode|String
+ // id or reference to the element to get the attribute on
+ // name: String
+ // the name of the attribute to get.
+ // returns:
+ // the value of the requested attribute or null if that attribute does not have a specified or
+ // default value;
+ //
+ // example:
+ // | // get the current value of the "foo" attribute on a node
+ // | require(["dojo/dom-attr", "dojo/dom"], function(domAttr, dom){
+ // | domAttr.get(dom.byId("nodeId"), "foo");
+ // | // or we can just pass the id:
+ // | domAttr.get("nodeId", "foo");
+ // | });
+ // |
+
+ node = dom.byId(node);
+ var lc = name.toLowerCase(),
+ propName = prop.names[lc] || name,
+ forceProp = forcePropNames[propName],
+ value = node[propName]; // should we access this attribute via a property or via getAttribute()?
+
+ if(forceProp && typeof value != "undefined"){
+ // node's property
+ return value; // Anything
+ }
+
+ if(propName == "textContent"){
+ return prop.get(node, propName);
+ }
+
+ if(propName != "href" && (typeof value == "boolean" || lang.isFunction(value))){
+ // node's property
+ return value; // Anything
+ }
+ // node's attribute
+ // we need _hasAttr() here to guard against IE returning a default value
+ var attrName = attrNames[lc] || name;
+ return _hasAttr(node, attrName) ? node.getAttribute(attrName) : null; // Anything
+ };
+
+ exports.set = function setAttr(/*DOMNode|String*/ node, /*String|Object*/ name, /*String?*/ value){
+ // summary:
+ // Sets an attribute on an HTML element.
+ // description:
+ // Handles normalized setting of attributes on DOM Nodes.
+ //
+ // When passing functions as values, note that they will not be
+ // directly assigned to slots on the node, but rather the default
+ // behavior will be removed and the new behavior will be added
+ // using `dojo.connect()`, meaning that event handler properties
+ // will be normalized and that some caveats with regards to
+ // non-standard behaviors for onsubmit apply. Namely that you
+ // should cancel form submission using `dojo.stopEvent()` on the
+ // passed event object instead of returning a boolean value from
+ // the handler itself.
+ // node: DOMNode|String
+ // id or reference to the element to set the attribute on
+ // name: String|Object
+ // the name of the attribute to set, or a hash of key-value pairs to set.
+ // value: String?
+ // the value to set for the attribute, if the name is a string.
+ // returns:
+ // the DOM node
+ //
+ // example:
+ // | // use attr() to set the tab index
+ // | require(["dojo/dom-attr"], function(domAttr){
+ // | domAttr.set("nodeId", "tabIndex", 3);
+ // | });
+ //
+ // example:
+ // Set multiple values at once, including event handlers:
+ // | require(["dojo/dom-attr"],
+ // | function(domAttr){
+ // | domAttr.set("formId", {
+ // | "foo": "bar",
+ // | "tabIndex": -1,
+ // | "method": "POST"
+ // | }
+ // | });
+
+ node = dom.byId(node);
+ if(arguments.length == 2){ // inline'd type check
+ // the object form of setter: the 2nd argument is a dictionary
+ for(var x in name){
+ exports.set(node, x, name[x]);
+ }
+ return node; // DomNode
+ }
+ var lc = name.toLowerCase(),
+ propName = prop.names[lc] || name,
+ forceProp = forcePropNames[propName];
+ if(propName == "style" && typeof value != "string"){ // inline'd type check
+ // special case: setting a style
+ style.set(node, value);
+ return node; // DomNode
+ }
+ if(forceProp || typeof value == "boolean" || lang.isFunction(value)){
+ return prop.set(node, name, value);
+ }
+ // node's attribute
+ node.setAttribute(attrNames[lc] || name, value);
+ return node; // DomNode
+ };
+
+ exports.remove = function removeAttr(/*DOMNode|String*/ node, /*String*/ name){
+ // summary:
+ // Removes an attribute from an HTML element.
+ // node: DOMNode|String
+ // id or reference to the element to remove the attribute from
+ // name: String
+ // the name of the attribute to remove
+
+ dom.byId(node).removeAttribute(attrNames[name.toLowerCase()] || name);
+ };
+
+ exports.getNodeProp = function getNodeProp(/*DomNode|String*/ node, /*String*/ name){
+ // summary:
+ // Returns an effective value of a property or an attribute.
+ // node: DOMNode|String
+ // id or reference to the element to remove the attribute from
+ // name: String
+ // the name of the attribute
+ // returns:
+ // the value of the attribute
+
+ node = dom.byId(node);
+ var lc = name.toLowerCase(), propName = prop.names[lc] || name;
+ if((propName in node) && propName != "href"){
+ // node's property
+ return node[propName]; // Anything
+ }
+ // node's attribute
+ var attrName = attrNames[lc] || name;
+ return _hasAttr(node, attrName) ? node.getAttribute(attrName) : null; // Anything
+ };
+});
+
+},
+'dojo/dom-prop':function(){
+define(["exports", "./_base/kernel", "./sniff", "./_base/lang", "./dom", "./dom-style", "./dom-construct", "./_base/connect"],
+ function(exports, dojo, has, lang, dom, style, ctr, conn){
+ // module:
+ // dojo/dom-prop
+ // summary:
+ // This module defines the core dojo DOM properties API.
+
+ // TODOC: summary not showing up in output, see https://github.com/csnover/js-doc-parse/issues/42
+
+ // =============================
+ // Element properties Functions
+ // =============================
+
+ // helper to connect events
+ var _evtHdlrMap = {}, _ctr = 1, _attrId = dojo._scopeName + "attrid";
+ has.add('dom-textContent', function (global, doc, element) { return 'textContent' in element; });
+
+ exports.names = {
+ // properties renamed to avoid clashes with reserved words
+ "class": "className",
+ "for": "htmlFor",
+ // properties written as camelCase
+ tabindex: "tabIndex",
+ readonly: "readOnly",
+ colspan: "colSpan",
+ frameborder: "frameBorder",
+ rowspan: "rowSpan",
+ textcontent: "textContent",
+ valuetype: "valueType"
+ };
+
+ function getText(/*DOMNode*/node){
+ // summary:
+ // recursion method for get('textContent') to use. Gets text value for a node.
+ // description:
+ // Juse uses nodedValue so things like tags do not end up in
+ // the text as any sort of line return.
+ var text = "", ch = node.childNodes;
+ for(var i = 0, n; n = ch[i]; i++){
+ //Skip comments.
+ if(n.nodeType != 8){
+ if(n.nodeType == 1){
+ text += getText(n);
+ }else{
+ text += n.nodeValue;
+ }
+ }
+ }
+ return text;
+ }
+
+ exports.get = function getProp(/*DOMNode|String*/ node, /*String*/ name){
+ // summary:
+ // Gets a property on an HTML element.
+ // description:
+ // Handles normalized getting of properties on DOM nodes.
+ //
+ // node: DOMNode|String
+ // id or reference to the element to get the property on
+ // name: String
+ // the name of the property to get.
+ // returns:
+ // the value of the requested property or its default value
+ //
+ // example:
+ // | // get the current value of the "foo" property on a node
+ // | require(["dojo/dom-prop", "dojo/dom"], function(domProp, dom){
+ // | domProp.get(dom.byId("nodeId"), "foo");
+ // | // or we can just pass the id:
+ // | domProp.get("nodeId", "foo");
+ // | });
+
+ node = dom.byId(node);
+ var lc = name.toLowerCase(), propName = exports.names[lc] || name;
+
+ if(propName == "textContent" && !has("dom-textContent")){
+ return getText(node);
+ }
+
+ return node[propName]; // Anything
+ };
+
+ exports.set = function setProp(/*DOMNode|String*/ node, /*String|Object*/ name, /*String?*/ value){
+ // summary:
+ // Sets a property on an HTML element.
+ // description:
+ // Handles normalized setting of properties on DOM nodes.
+ //
+ // When passing functions as values, note that they will not be
+ // directly assigned to slots on the node, but rather the default
+ // behavior will be removed and the new behavior will be added
+ // using `dojo.connect()`, meaning that event handler properties
+ // will be normalized and that some caveats with regards to
+ // non-standard behaviors for onsubmit apply. Namely that you
+ // should cancel form submission using `dojo.stopEvent()` on the
+ // passed event object instead of returning a boolean value from
+ // the handler itself.
+ // node: DOMNode|String
+ // id or reference to the element to set the property on
+ // name: String|Object
+ // the name of the property to set, or a hash object to set
+ // multiple properties at once.
+ // value: String?
+ // The value to set for the property
+ // returns:
+ // the DOM node
+ //
+ // example:
+ // | // use prop() to set the tab index
+ // | require(["dojo/dom-prop"], function(domProp){
+ // | domProp.set("nodeId", "tabIndex", 3);
+ // | });
+ //
+ // example:
+ // Set multiple values at once, including event handlers:
+ // | require(["dojo/dom-prop"], function(domProp){
+ // | domProp.set("formId", {
+ // | "foo": "bar",
+ // | "tabIndex": -1,
+ // | "method": "POST",
+ // | });
+ // | });
+
+ node = dom.byId(node);
+ var l = arguments.length;
+ if(l == 2 && typeof name != "string"){ // inline'd type check
+ // the object form of setter: the 2nd argument is a dictionary
+ for(var x in name){
+ exports.set(node, x, name[x]);
+ }
+ return node; // DomNode
+ }
+ var lc = name.toLowerCase(), propName = exports.names[lc] || name;
+ if(propName == "style" && typeof value != "string"){ // inline'd type check
+ // special case: setting a style
+ style.set(node, value);
+ return node; // DomNode
+ }
+ if(propName == "innerHTML"){
+ // special case: assigning HTML
+ // the hash lists elements with read-only innerHTML on IE
+ if(has("ie") && node.tagName.toLowerCase() in {col: 1, colgroup: 1,
+ table: 1, tbody: 1, tfoot: 1, thead: 1, tr: 1, title: 1}){
+ ctr.empty(node);
+ node.appendChild(ctr.toDom(value, node.ownerDocument));
+ }else{
+ node[propName] = value;
+ }
+ return node; // DomNode
+ }
+ if(propName == "textContent" && !has("dom-textContent")) {
+ ctr.empty(node);
+ node.appendChild(node.ownerDocument.createTextNode(value));
+ return node;
+ }
+ if(lang.isFunction(value)){
+ // special case: assigning an event handler
+ // clobber if we can
+ var attrId = node[_attrId];
+ if(!attrId){
+ attrId = _ctr++;
+ node[_attrId] = attrId;
+ }
+ if(!_evtHdlrMap[attrId]){
+ _evtHdlrMap[attrId] = {};
+ }
+ var h = _evtHdlrMap[attrId][propName];
+ if(h){
+ //h.remove();
+ conn.disconnect(h);
+ }else{
+ try{
+ delete node[propName];
+ }catch(e){}
+ }
+ // ensure that event objects are normalized, etc.
+ if(value){
+ //_evtHdlrMap[attrId][propName] = on(node, propName, value);
+ _evtHdlrMap[attrId][propName] = conn.connect(node, propName, value);
+ }else{
+ node[propName] = null;
+ }
+ return node; // DomNode
+ }
+ node[propName] = value;
+ return node; // DomNode
+ };
+});
+
+},
+'dojo/dom-construct':function(){
+define(["exports", "./_base/kernel", "./sniff", "./_base/window", "./dom", "./dom-attr"],
+ function(exports, dojo, has, win, dom, attr){
+ // module:
+ // dojo/dom-construct
+ // summary:
+ // This module defines the core dojo DOM construction API.
+
+ // TODOC: summary not showing up in output, see https://github.com/csnover/js-doc-parse/issues/42
+
+ // support stuff for toDom()
+ var tagWrap = {
+ option: ["select"],
+ tbody: ["table"],
+ thead: ["table"],
+ tfoot: ["table"],
+ tr: ["table", "tbody"],
+ td: ["table", "tbody", "tr"],
+ th: ["table", "thead", "tr"],
+ legend: ["fieldset"],
+ caption: ["table"],
+ colgroup: ["table"],
+ col: ["table", "colgroup"],
+ li: ["ul"]
+ },
+ reTag = /<\s*([\w\:]+)/,
+ masterNode = {}, masterNum = 0,
+ masterName = "__" + dojo._scopeName + "ToDomId";
+
+ // generate start/end tag strings to use
+ // for the injection for each special tag wrap case.
+ for(var param in tagWrap){
+ if(tagWrap.hasOwnProperty(param)){
+ var tw = tagWrap[param];
+ tw.pre = param == "option" ? '