From 1354d17270961fff662d40f90521223f8fd0d73b Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Tue, 14 Aug 2012 18:59:10 +0400 Subject: update dojo to 1.7.3 --- lib/dojo/dojo.js.uncompressed.js | 22216 +++++++++++++++++++++---------------- 1 file changed, 12516 insertions(+), 9700 deletions(-) (limited to 'lib/dojo/dojo.js.uncompressed.js') diff --git a/lib/dojo/dojo.js.uncompressed.js b/lib/dojo/dojo.js.uncompressed.js index af7051aaf..69b3d2e5e 100644 --- a/lib/dojo/dojo.js.uncompressed.js +++ b/lib/dojo/dojo.js.uncompressed.js @@ -11,3972 +11,3623 @@ http://dojotoolkit.org */ -;(function(){ +(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 discadred by + // building a customized verion with the build system. - /* - dojo, dijit, and dojox must always be the first three, and in that order. - djConfig.scopeMap = [ - ["dojo", "fojo"], - ["dijit", "fijit"], - ["dojox", "fojox"] - - ] - */ + // 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. + + // define a minimal library to help build the loader + var noop = function(){ + }, - /**Build will replace this comment with a scoped djConfig **/ + isEmpty = function(it){ + for(var p in it){ + return 0; + } + return 1; + }, - //The null below can be relaced by a build-time value used instead of djConfig.scopeMap. - var sMap = null; + toString = {}.toString, - //See if new scopes need to be defined. - if((sMap || (typeof djConfig != "undefined" && djConfig.scopeMap)) && (typeof window != "undefined")){ - var scopeDef = "", scopePrefix = "", scopeSuffix = "", scopeMap = {}, scopeMapRev = {}; - sMap = sMap || djConfig.scopeMap; - for(var i = 0; i < sMap.length; i++){ - //Make local variables, then global variables that use the locals. - var newScope = sMap[i]; - scopeDef += "var " + newScope[0] + " = {}; " + newScope[1] + " = " + newScope[0] + ";" + newScope[1] + "._scopeName = '" + newScope[1] + "';"; - scopePrefix += (i == 0 ? "" : ",") + newScope[0]; - scopeSuffix += (i == 0 ? "" : ",") + newScope[1]; - scopeMap[newScope[0]] = newScope[1]; - scopeMapRev[newScope[1]] = newScope[0]; - } + isFunction = function(it){ + return toString.call(it) == "[object Function]"; + }, - eval(scopeDef + "dojo._scopeArgs = [" + scopeSuffix + "];"); + isString = function(it){ + return toString.call(it) == "[object String]"; + }, - dojo._scopePrefixArgs = scopePrefix; - dojo._scopePrefix = "(function(" + scopePrefix + "){"; - dojo._scopeSuffix = "})(" + scopeSuffix + ")"; - dojo._scopeMap = scopeMap; - dojo._scopeMapRev = scopeMapRev; - } + isArray = function(it){ + return toString.call(it) == "[object Array]"; + }, -/*===== -// note: -// 'djConfig' does not exist under 'dojo.*' so that it can be set before the -// 'dojo' variable exists. -// note: -// Setting any of these variables *after* the library has loaded does -// nothing at all. + forEach = function(vector, callback){ + if(vector){ + for(var i = 0; i < vector.length;){ + callback(vector[i++]); + } + } + }, -djConfig = { - // summary: - // Application code can set the global 'djConfig' prior to loading - // the library to override certain global settings for how dojo works. - // - // isDebug: Boolean - // Defaults to `false`. If set to `true`, ensures that Dojo provides - // extended debugging feedback via Firebug. If Firebug is not available - // on your platform, setting `isDebug` to `true` will force Dojo to - // pull in (and display) the version of Firebug Lite which is - // integrated into the Dojo distribution, thereby always providing a - // debugging/logging console when `isDebug` is enabled. Note that - // Firebug's `console.*` methods are ALWAYS defined by Dojo. If - // `isDebug` is false and you are on a platform without Firebug, these - // methods will be defined as no-ops. - isDebug: false, - // debugAtAllCosts: Boolean - // Defaults to `false`. If set to `true`, this triggers an alternate - // mode of the package system in which dependencies are detected and - // only then are resources evaluated in dependency order via - // ` - // | - d._modulePrefixes[module] = { name: module, value: prefix }; - }; - - dojo.requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String?*/availableFlatLocales){ - // summary: - // Declares translated resources and loads them if necessary, in the - // same style as dojo.require. Contents of the resource bundle are - // typically strings, but may be any name/value pair, represented in - // JSON format. See also `dojo.i18n.getLocalization`. - // - // description: - // Load translated resource bundles provided underneath the "nls" - // directory within a package. Translated resources may be located in - // different packages throughout the source tree. - // - // Each directory is named for a locale as specified by RFC 3066, - // (http://www.ietf.org/rfc/rfc3066.txt), normalized in lowercase. - // Note that the two bundles in the example do not define all the - // same variants. For a given locale, bundles will be loaded for - // that locale and all more general locales above it, including a - // fallback at the root directory. For example, a declaration for - // the "de-at" locale will first load `nls/de-at/bundleone.js`, - // then `nls/de/bundleone.js` and finally `nls/bundleone.js`. The - // data will be flattened into a single Object so that lookups - // will follow this cascading pattern. An optional build step can - // preload the bundles to avoid data redundancy and the multiple - // network hits normally required to load these resources. - // - // moduleName: - // name of the package containing the "nls" directory in which the - // bundle is found - // - // bundleName: - // bundle name, i.e. the filename without the '.js' suffix. Using "nls" as a - // a bundle name is not supported, since "nls" is the name of the folder - // that holds bundles. Using "nls" as the bundle name will cause problems - // with the custom build. - // - // locale: - // the locale to load (optional) By default, the browser's user - // locale as defined by dojo.locale - // - // availableFlatLocales: - // A comma-separated list of the available, flattened locales for this - // bundle. This argument should only be set by the build process. - // - // example: - // A particular widget may define one or more resource bundles, - // structured in a program as follows, where moduleName is - // mycode.mywidget and bundleNames available include bundleone and - // bundletwo: - // | ... - // | mycode/ - // | mywidget/ - // | nls/ - // | bundleone.js (the fallback translation, English in this example) - // | bundletwo.js (also a fallback translation) - // | de/ - // | bundleone.js - // | bundletwo.js - // | de-at/ - // | bundleone.js - // | en/ - // | (empty; use the fallback translation) - // | en-us/ - // | bundleone.js - // | en-gb/ - // | bundleone.js - // | es/ - // | bundleone.js - // | bundletwo.js - // | ...etc - // | ... - // - - d.require("dojo.i18n"); - d.i18n._requireLocalization.apply(d.hostenv, arguments); - }; - - - var ore = new RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"), - ire = new RegExp("^((([^\\[:]+):)?([^@]+)@)?(\\[([^\\]]+)\\]|([^\\[:]*))(:([0-9]+))?$"); - - dojo._Url = function(/*dojo._Url|String...*/){ - // summary: - // Constructor to create an object representing a URL. - // It is marked as private, since we might consider removing - // or simplifying it. - // description: - // Each argument is evaluated in order relative to the next until - // a canonical uri is produced. To get an absolute Uri relative to - // the current document use: - // new dojo._Url(document.baseURI, url) - - var n = null, - _a = arguments, - uri = [_a[0]]; - // resolve uri components relative to each other - for(var i = 1; i<_a.length; i++){ - if(!_a[i]){ continue; } - - // Safari doesn't support this.constructor so we have to be explicit - // FIXME: Tracked (and fixed) in Webkit bug 3537. - // http://bugs.webkit.org/show_bug.cgi?id=3537 - var relobj = new d._Url(_a[i]+""), - uriobj = new d._Url(uri[0]+""); - - if( - relobj.path == "" && - !relobj.scheme && - !relobj.authority && - !relobj.query - ){ - if(relobj.fragment != n){ - uriobj.fragment = relobj.fragment; - } - relobj = uriobj; - }else if(!relobj.scheme){ - relobj.scheme = uriobj.scheme; - - if(!relobj.authority){ - relobj.authority = uriobj.authority; - - if(relobj.path.charAt(0) != "/"){ - var path = uriobj.path.substring(0, - uriobj.path.lastIndexOf("/") + 1) + relobj.path; - - var segs = path.split("/"); - for(var j = 0; j < segs.length; j++){ - if(segs[j] == "."){ - // flatten "./" references - if(j == segs.length - 1){ - segs[j] = ""; - }else{ - segs.splice(j, 1); - j--; - } - }else if(j > 0 && !(j == 1 && segs[0] == "") && - segs[j] == ".." && segs[j-1] != ".."){ - // flatten "../" references - if(j == (segs.length - 1)){ - segs.splice(j, 1); - segs[j - 1] = ""; - }else{ - segs.splice(j - 1, 2); - j -= 2; - } - } - } - relobj.path = segs.join("/"); + // 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, packageMapProg, pathsMapProg, alwaysCreate); } - } - uri = []; - if(relobj.scheme){ - uri.push(relobj.scheme, ":"); - } - if(relobj.authority){ - uri.push("//", relobj.authority); + result = modules[mid]; + if(result){ + return alwaysCreate ? makeModuleInfo(result.pid, result.mid, result.pack, result.url, cacheId) : modules[mid]; + } } - uri.push(relobj.path); - if(relobj.query){ - uri.push("?", relobj.query); + // 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 + + mapItem = runMapProg(mid, pathsMapProg); + if(mapItem){ + url = mapItem[1] + mid.substring(mapItem[3] - 1); + }else if(pid){ + url = pack.location + "/" + midInPackage; + }else if(has("config-tlmSiblingOfDojo")){ + url = "../" + mid; + }else{ + url = mid; } - if(relobj.fragment){ - uri.push("#", relobj.fragment); + // if result is not absolute, add baseUrl + if(!(/(^\/)|(\:)/.test(url))){ + url = baseUrl + url; } - } - - this.uri = uri.join(""); - - // break the uri into its main components - var r = this.uri.match(ore); + url += ".js"; + return makeModuleInfo(pid, mid, pack, compactPath(url), cacheId); + }, - this.scheme = r[2] || (r[1] ? "" : n); - this.authority = r[4] || (r[3] ? "" : n); - this.path = r[5]; // can never be undefined - this.query = r[7] || (r[6] ? "" : n); - this.fragment = r[9] || (r[8] ? "" : n); + getModuleInfo = function(mid, referenceModule){ + return getModuleInfo_(mid, referenceModule, packs, modules, req.baseUrl, packageMapProg, pathsMapProg); + }, - if(this.authority != n){ - // server based naming authority - r = this.authority.match(ire); + resolvePluginResourceId = function(plugin, prid, referenceModule){ + return plugin.normalize ? plugin.normalize(prid, function(mid){return toAbsMid(mid, referenceModule);}) : toAbsMid(prid, referenceModule); + }, - this.user = r[3] || n; - this.password = r[4] || n; - this.host = r[6] || r[7]; // ipv6 || ipv4 - this.port = r[9] || n; - } - } + 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){ + checkCompleteGuard++; + execModule(plugin); + checkIdle(); + } + if(plugin.executed){ + promoteModuleToPlugin(plugin); + }else{ + // we are in xdomain mode for some reason + execQ.unshift(plugin); + } + } - dojo._Url.prototype.toString = function(){ return this.uri; }; - dojo.moduleUrl = function(/*String*/module, /*dojo._Url||String*/url){ - // summary: - // Returns a `dojo._Url` object 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"); - // | // NOTE: we assign the string representation of the url object - // | img.src = pngPath.toString(); - // | // 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 lenghty 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"); - var loc = d._getModuleSymbols(module).join('/'); - if(!loc){ return null; } - if(loc.lastIndexOf("/") != loc.length-1){ - loc += "/"; - } - - //If the path is an absolute path (starts with a / or is on another - //domain/xdomain) then don't add the baseUrl. - var colonIndex = loc.indexOf(":"); - if(loc.charAt(0) != "/" && (colonIndex == -1 || colonIndex > loc.indexOf("/"))){ - loc = d.baseUrl + loc; - } + if(plugin.executed === executed && !plugin.load){ + // executed the module not knowing it was a plugin + promoteModuleToPlugin(plugin); + } - return new d._Url(loc, url); // dojo._Url - }; + // 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)); + }, + 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 likde a module id + url.substring(0, url.length-5) + ); + }, -})(); + nonModuleProps = { + injected: arrived, + executed: executed, + def: nonmodule, + result: nonmodule + }, -/*===== -dojo.isBrowser = { - // example: - // | if(dojo.isBrowser){ ... } -}; + makeCjs = function(mid){ + return modules[mid] = mix({mid:mid}, nonModuleProps); + }, -dojo.isFF = { - // example: - // | if(dojo.isFF > 1){ ... } -}; + cjsRequireModule = makeCjs("require"), + cjsExportsModule = makeCjs("exports"), + cjsModuleModule = makeCjs("module"), -dojo.isIE = { - // example: - // | if(dojo.isIE > 6){ - // | // we are IE7 - // | } -}; + 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); + }, -dojo.isSafari = { - // example: - // | if(dojo.isSafari){ ... } - // example: - // Detect iPhone: - // | if(dojo.isSafari && navigator.userAgent.indexOf("iPhone") != -1){ - // | // we are iPhone. Note, iPod touch reports "iPod" above and fails this test. - // | } -}; + abortExec = {}, -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: 2, - // 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: 6, - // isKhtml: Number | undefined - // Version as a Number if client is a KHTML browser. undefined otherwise. Corresponds to major - // detected version. - isKhtml: 0, - // isWebKit: Number | undefined - // Version as a Number if client is a WebKit-derived browser (Konqueror, - // Safari, Chrome, etc.). undefined otherwise. - isWebKit: 0, - // isMozilla: Number | undefined - // Version as a Number if client is a Mozilla-based browser (Firefox, - // SeaMonkey). undefined otherwise. Corresponds to major detected version. - isMozilla: 0, - // isOpera: Number | undefined - // Version as a Number if client is Opera. undefined otherwise. Corresponds to - // major detected version. - isOpera: 0, - // isSafari: Number | undefined - // Version as a Number if client is Safari or iPhone. undefined otherwise. - isSafari: 0, - // isChrome: Number | undefined - // Version as a Number if client is Chrome browser. undefined otherwise. - isChrome: 0 - // isMac: Boolean - // True if the client runs on Mac -} -=====*/ -if(typeof window != 'undefined'){ - dojo.isBrowser = true; - dojo._name = "browser"; + defOrder = 0, + promoteModuleToPlugin = function(pluginModule){ + var plugin = pluginModule.result; + pluginModule.dynamic = plugin.dynamic; + pluginModule.normalize = plugin.normalize; + pluginModule.load = plugin.load; + return pluginModule; + }, - // attempt to figure out the path to dojo if it isn't set in the config - (function(){ - var d = dojo; - - // this is a scope protection closure. We set browser versions and grab - // the URL we were loaded from here. - - // grab the node we were loaded from - if(document && document.getElementsByTagName){ - var scripts = document.getElementsByTagName("script"); - var rePkg = /dojo(\.xd)?\.js(\W|$)/i; - for(var i = 0; i < scripts.length; i++){ - var src = scripts[i].getAttribute("src"); - if(!src){ continue; } - var m = src.match(rePkg); - if(m){ - // find out where we came from - if(!d.config.baseUrl){ - d.config.baseUrl = src.substring(0, m.index); - } - // and find out if we need to modify our behavior - var cfg = (scripts[i].getAttribute("djConfig") || scripts[i].getAttribute("data-dojo-config")); - if(cfg){ - var cfgo = eval("({ "+cfg+" })"); - for(var x in cfgo){ - dojo.config[x] = cfgo[x]; - } + 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 pseudoMid = pseudoPluginResource.mid, + 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]){ + // 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= 0){ d.isOpera = tv; } - if(dua.indexOf("AdobeAIR") >= 0){ d.isAIR = 1; } - d.isKhtml = (dav.indexOf("Konqueror") >= 0) ? tv : 0; - d.isWebKit = parseFloat(dua.split("WebKit/")[1]) || undefined; - d.isChrome = parseFloat(dua.split("Chrome/")[1]) || undefined; - d.isMac = dav.indexOf("Macintosh") >= 0; + forEach(execQ, substituteModules); + }, - // safari detection derived from: - // http://developer.apple.com/internet/safari/faq.html#anchor2 - // http://developer.apple.com/internet/safari/uamatrix.html - var index = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0); - if(index && !dojo.isChrome){ - // try to grab the explicit Safari version first. If we don't get - // one, look for less than 419.3 as the indication that we're on something - // "Safari 2-ish". - d.isSafari = parseFloat(dav.split("Version/")[1]); - if(!d.isSafari || parseFloat(dav.substr(index + 7)) <= 419.3){ - d.isSafari = 2; + finishExec = function(module){ + req.trace("loader-finish-exec", [module.mid]); + module.executed = executed; + module.defOrder = defOrder++; + 1 && forEach(module.provides, function(cb){ cb(); }); + if(module.loadQ){ + // the module was a plugin + promoteModuleToPlugin(module); + resolvePluginLoadQ(module); + } + // remove all occurences of this module from the execQ + for(i = 0; i < execQ.length;){ + if(execQ[i] === module){ + execQ.splice(i, 1); + }else{ + i++; + } } - } + }, - if(dua.indexOf("Gecko") >= 0 && !d.isKhtml && !d.isWebKit){ d.isMozilla = d.isMoz = tv; } - if(d.isMoz){ - //We really need to get away from this. Consider a sane isGecko approach for the future. - d.isFF = parseFloat(dua.split("Firefox/")[1] || dua.split("Minefield/")[1]) || undefined; - } - if(document.all && !d.isOpera){ - d.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(d.isIE) != mode){ - d.isIE = mode; - } - } + circleTrace = [], - //Workaround to get local file loads of dojo to work on IE 7 - //by forcing to not use native xhr. - if(dojo.isIE && window.location.protocol === "file:"){ - dojo.config.ieForceActiveXXhr=true; - } - - d.isQuirks = document.compatMode == "BackCompat"; + execModule = function(module, strict){ + // run the dependency vector, then run the factory for module + if(module.executed === executing){ + req.trace("loader-circular-dependency", [circleTrace.concat(mid).join("->")]); + return (!module.def || strict) ? abortExec : (module.cjs && module.cjs.exports); + } + // at this point the module is either not executed or fully executed - // TODO: is the HTML LANG attribute relevant? - d.locale = dojo.config.locale || (d.isIE ? n.userLanguage : n.language).toLowerCase(); - // These are in order of decreasing likelihood; this will change in time. - d._XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0']; - - d._xhrObj = function(){ - // summary: - // does the work of portably generating a new XMLHTTPRequest object. - var http, last_e; - if(!dojo.isIE || !dojo.config.ieForceActiveXXhr){ - try{ http = new XMLHttpRequest(); }catch(e){} - } - if(!http){ - for(var i=0; i<3; ++i){ - var progid = d._XMLHTTP_PROGIDS[i]; - try{ - http = new ActiveXObject(progid); - }catch(e){ - last_e = e; - } + 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]); + } - if(http){ - d._XMLHTTP_PROGIDS = [progid]; // so faster next time - break; + // 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 premade 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(i < deps.length){ + 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); } - - if(!http){ - throw new Error("XMLHTTP not available: "+last_e); - } + // at this point the module is guaranteed fully executed - return http; // XMLHTTPRequest instance - } - - d._isDocumentOk = function(http){ - var stat = http.status || 0, - lp = location.protocol; - return (stat >= 200 && stat < 300) || // Boolean - stat == 304 || // allow any 2XX response code - stat == 1223 || // get it out of the cache - // Internet Explorer mangled the status code - // Internet Explorer mangled the status code OR we're Titanium/browser chrome/chrome extension requesting a local file - (!stat && (lp == "file:" || lp == "chrome:" || lp == "chrome-extension:" || lp == "app:")); - } - - //See if base tag is in use. - //This is to fix http://trac.dojotoolkit.org/ticket/3973, - //but really, we need to find out how to get rid of the dojo._Url reference - //below and still have DOH work with the dojo.i18n test following some other - //test that uses the test frame to load a document (trac #2757). - //Opera still has problems, but perhaps a larger issue of base tag support - //with XHR requests (hasBase is true, but the request is still made to document - //path, not base path). - var owloc = window.location+""; - var base = document.getElementsByTagName("base"); - var hasBase = (base && base.length > 0); - - d._getText = function(/*URI*/ uri, /*Boolean*/ fail_ok){ - // summary: Read the contents of the specified uri and return those contents. - // uri: - // A relative or absolute uri. If absolute, it still must be in - // the same "domain" as we are. - // fail_ok: - // Default false. If fail_ok and loading fails, return null - // instead of throwing. - // returns: The response text. null is returned when there is a - // failure and failure is okay (an exception otherwise) + 0 && circleTrace.pop(); + return module.result; + }, - // NOTE: must be declared before scope switches ie. this._xhrObj() - var http = d._xhrObj(); - if(!hasBase && dojo._Url){ - uri = (new dojo._Url(owloc, uri)).toString(); - } + checkCompleteGuard = 0, - if(d.config.cacheBust){ - //Make sure we have a string before string methods are used on uri - uri += ""; - uri += (uri.indexOf("?") == -1 ? "?" : "&") + String(d.config.cacheBust).replace(/\W+/g,""); + 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; } - - http.open('GET', uri, false); - try{ - http.send(null); - if(!d._isDocumentOk(http)){ - var err = Error("Unable to load "+uri+" status:"+ http.status); - err.status = http.status; - err.responseText = http.responseText; - throw err; + checkCompleteGuard++; + 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++; } - }catch(e){ - if(fail_ok){ return null; } // null - // rethrow the exception - throw e; } - return http.responseText; // String - } - - - var _w = window; - var _handleNodeEvent = function(/*String*/evtName, /*Function*/fp){ - // summary: - // non-destructively adds the specified function to the node's - // evtName handler. - // evtName: should be in the form "onclick" for "onclick" handlers. - // Make sure you pass in the "on" part. - var _a = _w.attachEvent || _w.addEventListener; - evtName = _w.attachEvent ? evtName : evtName.substring(2); - _a(evtName, function(){ - fp.apply(_w, arguments); - }, false); - }; - + checkIdle(); + }, - d._windowUnloaders = []; - - d.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 - // dojo.addOnWindowUnload. This behavior started in Dojo 1.3. - // Previous versions always triggered dojo.windowUnloaded. See - // dojo.addOnWindowUnload for more info. - var mll = d._windowUnloaders; - while(mll.length){ - (mll.pop())(); + checkIdle = function(){ + checkCompleteGuard--; + if(execComplete()){ + signal("idle", []); } - d = null; }; - var _onWindowUnloadAttached = 0; - d.addOnWindowUnload = function(/*Object?|Function?*/obj, /*String|Function?*/functionName){ - // summary: - // registers a function to be triggered when window.onunload - // fires. - // 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 - // destory "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 - // dojo.addOnUnload() if you need to modify the DOM or do - // heavy JavaScript work since it fires at the eqivalent of - // the page's "onbeforeunload" event. - // example: - // | dojo.addOnWindowUnload(functionPointer) - // | dojo.addOnWindowUnload(object, "functionName"); - // | dojo.addOnWindowUnload(object, function(){ /* ... */}); - d._onto(d._windowUnloaders, obj, functionName); - if(!_onWindowUnloadAttached){ - _onWindowUnloadAttached = 1; - _handleNodeEvent("onunload", d.windowUnloaded); - } + 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); + delete modules[module.mid]; }; + } - var _onUnloadAttached = 0; - d.addOnUnload = function(/*Object?|Function?*/obj, /*String|Function?*/functionName){ - // summary: - // registers a function to be triggered when the page unloads. - // description: - // The first time that addOnUnload is called Dojo will - // register a page listener to trigger your unload handler - // with. - // - // In a browser enviroment, 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: - // | dojo.addOnUnload(functionPointer) - // | dojo.addOnUnload(object, "functionName") - // | dojo.addOnUnload(object, function(){ /* ... */}); + if(1){ + if(has("dojo-loader-eval-hint-url")===undefined){ + has.add("dojo-loader-eval-hint-url", 1); + } - d._onto(d._unloaders, obj, functionName); - if(!_onUnloadAttached){ - _onUnloadAttached = 1; - _handleNodeEvent("onbeforeunload", dojo.unloaded); - } - }; + var fixupUrl= function(url){ + url += ""; // make sure url is a Javascript string (some paths may be a Java string) + return url + (cacheBust ? ((/\?/.test(url) ? "&" : "?") + cacheBust) : ""); + }, + + 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); + } - //START DOMContentLoaded - dojo._initFired = false; - dojo._loadInit = function(e){ - if(dojo._scrollIntervalId){ - clearInterval(dojo._scrollIntervalId); - dojo._scrollIntervalId = 0; - } + 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); + } + }, - if(!dojo._initFired){ - dojo._initFired = true; + // for IE, injecting a module may result in a recursive execution if the module is in the cache - //Help out IE to avoid memory leak. - if(!dojo.config.afterOnLoad && window.detachEvent){ - window.detachEvent("onload", dojo._loadInit); - } + cached = 0, - if(dojo._inFlightCount == 0){ - dojo._modulesLoaded(); - } - } - } + injectingModule = 0, - if(!dojo.config.afterOnLoad){ - if(document.addEventListener){ - //Standards. Hooray! Assumption here that if standards based, - //it knows about DOMContentLoaded. It is OK if it does not, the fall through - //to window onload should be good enough. - document.addEventListener("DOMContentLoaded", dojo._loadInit, false); - window.addEventListener("load", dojo._loadInit, false); - }else if(window.attachEvent){ - window.attachEvent("onload", dojo._loadInit); + injectingCachedModule = 0, - //DOMContentLoaded approximation. Diego Perini found this MSDN article - //that indicates doScroll is available after DOM ready, so do a setTimeout - //to check when it is available. - //http://msdn.microsoft.com/en-us/library/ms531426.aspx - if(!dojo.config.skipIeDomLoaded && self === self.top){ - dojo._scrollIntervalId = setInterval(function (){ + evalModuleText = function(text, module){ + // see def() for the injectingCachedModule bracket; it simply causes a short, safe curcuit + injectingCachedModule = 1; + if(has("config-dojo-loader-catches")){ try{ - //When dojo is loaded into an iframe in an IE HTML Application - //(HTA), such as in a selenium test, javascript in the iframe - //can't see anything outside of it, so self===self.top is true, - //but the iframe is not the top window and doScroll will be - //available before document.body is set. Test document.body - //before trying the doScroll trick - if(document.body){ - document.documentElement.doScroll("left"); - dojo._loadInit(); + if(text===cached){ + cached.call(null); + }else{ + req.eval(text, has("dojo-loader-eval-hint-url") ? module.url : module.mid); } - }catch (e){} - }, 30); - } - } - } - - if(dojo.isIE){ - try{ - (function(){ - document.namespaces.add("v", "urn:schemas-microsoft-com:vml"); - var vmlElems = ["*", "group", "roundrect", "oval", "shape", "rect", "imagedata", "path", "textpath", "text"], - i = 0, l = 1, s = document.createStyleSheet(); - if(dojo.isIE >= 8){ - i = 1; - l = vmlElems.length; - } - for(; i < l; ++i){ - s.addRule("v\\:" + vmlElems[i], "behavior:url(#default#VML); display:inline-block"); - } - })(); - }catch(e){} - } - //END DOMContentLoaded - + }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; + }, - /* - OpenAjax.subscribe("OpenAjax", "onload", function(){ - if(dojo._inFlightCount == 0){ - dojo._modulesLoaded(); - } - }); + 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. - OpenAjax.subscribe("OpenAjax", "onunload", function(){ - dojo.unloaded(); - }); - */ -} //if (typeof window != 'undefined') + 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 normalze 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; + } + } -//Register any module paths set up in djConfig. Need to do this -//in the hostenvs since hostenv_browser can read djConfig from a -//script tag's attribute. -(function(){ - var mp = dojo.config["modulePaths"]; - if(mp){ - for(var param in mp){ - dojo.registerModulePath(param, mp[param]); - } - } -})(); + 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 + setArrived(module); + mix(module, nonModuleProps); + } -//Load debug code if necessary. -if(dojo.config.isDebug){ - dojo.require("dojo._firebug.firebug"); -} + 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[module.cacheId]; + 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(dojo.config.debugAtAllCosts){ - // this breaks the new AMD based module loader. The XDomain won't be necessary - // anyway if you switch to the asynchronous loader - //dojo.config.useXDomain = true; - //dojo.require("dojo._base._loader.loader_xd"); - dojo.require("dojo._base._loader.loader_debug"); - dojo.require("dojo.i18n"); -} + 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 guarnateed-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; + }; -if(!dojo._hasResource["dojo._base.lang"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojo._base.lang"] = true; -dojo.provide("dojo._base.lang"); + 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; + } + } + }); + // resolve deps with respect to this module + for(var i = 0; i < deps.length; i++){ + deps[i] = getModule(deps[i], module); + } -(function(){ - var d = dojo, opts = Object.prototype.toString; + if(1 && legacyMode && !waiting[mid]){ + // the module showed up without being asked for; it was probably in a + // + return new dojo.NodeList(); // dojo.NodeList +}; +=====*/ - dojo.style = function( /*DomNode|String*/ node, - /*String?|Object?*/ style, - /*String?*/ value){ +function queryForEngine(engine, NodeList){ + var query = function(/*String*/ query, /*String|DOMNode?*/ root){ // 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: - // id or reference to node to get/set style for - // style: - // 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: - // 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 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" - // | }); - - var n = byId(node), args = arguments.length, op = (style == "opacity"); - style = _floatAliases[style] || style; - if(args == 3){ - return op ? d._setOpacity(n, value) : n.style[style] = value; /*Number*/ - } - if(args == 2 && op){ - return d._getOpacity(n); - } - var s = gcs(n); - if(args == 2 && typeof style != "string"){ // inline'd type check - for(var x in style){ - d.style(node, x, style[x]); + // Returns nodes which match the given CSS selector, searching the + // entire document by default but optionally taking a node to scope + // the search by. Returns an instance of dojo.NodeList. + if(typeof root == "string"){ + root = dom.byId(root); + if(!root){ + return new NodeList([]); } - return s; } - return (args == 1) ? s : _toStyleValue(n, style, s[style] || n.style[style]); /* CSS2Properties||String||Number */ + var results = typeof query == "string" ? engine(query, root) : query.orphan ? query : [query]; + if(results.orphan){ + // already wrapped + return results; + } + return new NodeList(results); }; + query.matches = engine.match || function(node, selector, root){ + // summary: + // Test to see if a node matches a selector + return query.filter([node], selector, root).length > 0; + }; + // the engine provides a filtering function, use it to for matching + query.filter = engine.filter || function(nodes, selector, root){ + // summary: + // Filters an array of nodes. Note that this does not guarantee to return a dojo.NodeList, just an array. + return query(selector, root).filter(function(node){ + return array.indexOf(nodes, node) > -1; + }); + }; + if(typeof engine != "function"){ + var search = engine.search; + engine = function(selector, root){ + // Slick does it backwards (or everyone else does it backwards, probably the latter) + return search(root || document, selector); + }; + } + return query; +} +var query = queryForEngine(defaultEngine, NodeList); +// the query that is returned from this module is slightly different than dojo.query, +// because dojo.query has to maintain backwards compatibility with returning a +// true array which has performance problems. The query returned from the module +// does not use true arrays, but rather inherits from Array, making it much faster to +// instantiate. +dojo.query = queryForEngine(defaultEngine, function(array){ + // call it without the new operator to invoke the back-compat behavior that returns a true array + return NodeList(array); +}); + +query.load = /*===== dojo.query.load= ======*/ function(id, parentRequire, loaded, config){ + // summary: can be used as AMD plugin to conditionally load new query engine + // example: + // | define(["dojo/query!custom"], function(qsa){ + // | // loaded selector/custom.js as engine + // | qsa("#foobar").forEach(...); + // | }); + loader.load(id, parentRequire, function(engine){ + loaded(queryForEngine(engine, NodeList)); + }); +}; - // ============================= - // Box Functions - // ============================= - - dojo._getPadExtents = function(/*DomNode*/n, /*Object*/computedStyle){ - // summary: - // Returns object with special values specifically useful for node - // fitting. - // description: - // Returns an object with `w`, `h`, `l`, `t` properties: - // | l/t = left/top padding (respectively) - // | w = the total of the left and right padding - // | h = the total of the top and bottom padding - // If 'node' has position, l/t forms the origin for child nodes. - // The w/h are used for calculating boxes. - // Normally application code will not need to invoke this - // directly, and will use the ...box... functions instead. +dojo._filterQueryResult = query._filterResult = function(nodes, selector, root){ + return new NodeList(query.filter(nodes, selector, root)); +}; +dojo.NodeList = query.NodeList = NodeList; +return query; +}); + +}, +'dojo/has':function(){ +define(["require"], function(require) { + // 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 + // 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){ + // notice the condition is written so that if 1 is transformed to 1 during a build + // the conditional will be (!1 && typeof has=="function") which is statically false and the closure + // compiler will discard the block. var - s = computedStyle||gcs(n), - l = px(n, s.paddingLeft), - t = px(n, s.paddingTop); - return { - l: l, - t: t, - w: l+px(n, s.paddingRight), - h: t+px(n, s.paddingBottom) + 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 + global = this, + doc = isBrowser && document, + element = doc && doc.createElement("DiV"), + cache = {}; + + has = /*===== dojo.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 }; - }; - dojo._getBorderExtents = function(/*DomNode*/n, /*Object*/computedStyle){ - // summary: - // returns an object with properties useful for noting the border - // dimensions. - // description: - // * l/t = the sum of left/top border (respectively) - // * w = the sum of the left and right border - // * h = the sum of the top and bottom border - // - // The w/h are used for calculating boxes. - // Normally application code will not need to invoke this - // directly, and will use the ...box... functions instead. - var - ne = "none", - s = computedStyle||gcs(n), - bl = (s.borderLeftStyle != ne ? px(n, s.borderLeftWidth) : 0), - bt = (s.borderTopStyle != ne ? px(n, s.borderTopWidth) : 0); - return { - l: bl, - t: bt, - w: bl + (s.borderRightStyle!=ne ? px(n, s.borderRightWidth) : 0), - h: bt + (s.borderBottomStyle!=ne ? px(n, s.borderBottomWidth) : 0) + has.cache = cache; + + has.add = /*====== dojo.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 + true || has.add("host-browser", isBrowser); + true || has.add("dom", isBrowser); + true || has.add("dojo-dom-ready-api", 1); + true || has.add("dojo-sniff", 1); + } + + if(1){ + var agent = navigator.userAgent; + // Common application level tests + has.add("dom-addeventlistener", !!document.addEventListener); + has.add("touch", "ontouchstart" in document); + // I don't know if any of these tests are really correct, just a rough guess + has.add("device-width", screen.availWidth || innerWidth); + has.add("agent-ios", !!agent.match(/iPhone|iP[ao]d/)); + has.add("agent-android", agent.indexOf("android") > 1); + } + + has.clearElement = /*===== dojo.has.clearElement= ======*/ function(element) { + // summary: + // Deletes the contents of the element passed to test functions. + element.innerHTML= ""; + return element; }; - dojo._getPadBorderExtents = function(/*DomNode*/n, /*Object*/computedStyle){ - // summary: - // Returns object with properties useful for box fitting with - // regards to padding. - // description: - // * l/t = the sum of left/top padding and left/top border (respectively) - // * w = the sum of the left and right padding and border - // * h = the sum of the top and bottom padding and border + has.normalize = /*===== dojo.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). // - // The w/h are used for calculating boxes. - // Normally application code will not need to invoke this - // directly, and will use the ...box... functions instead. + // toAbsMid: Function + // Resolves a relative module id into an absolute module id var - s = computedStyle||gcs(n), - p = d._getPadExtents(n, s), - b = d._getBorderExtents(n, s); - return { - l: p.l + b.l, - t: p.t + b.t, - w: p.w + b.w, - h: p.h + b.h - }; + 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); }; - dojo._getMarginExtents = function(n, computedStyle){ - // summary: - // returns object with properties useful for box fitting with - // regards to box margins (i.e., the outer-box). + has.load = /*===== dojo.has.load= ======*/ function(id, parentRequire, loaded){ + // summary: + // Conditional loading of AMD modules based on a has feature test value. // - // * l/t = marginLeft, marginTop, respectively - // * w = total width, margin inclusive - // * h = total height, margin inclusive + // id: String + // Gives the resolved module id to load. // - // The w/h are used for calculating boxes. - // Normally application code will not need to invoke this - // directly, and will use the ...box... functions instead. - var - s = computedStyle||gcs(n), - l = px(n, s.marginLeft), - t = px(n, s.marginTop), - r = px(n, s.marginRight), - b = px(n, s.marginBottom); - if(d.isWebKit && (s.position != "absolute")){ - // FIXME: Safari's version of the computed right margin - // is the space between our right edge and the right edge - // of our offsetParent. - // What we are looking for is the actual margin value as - // determined by CSS. - // Hack solution is to assume left/right margins are the same. - r = l; + // 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 { - l: l, - t: t, - w: l+r, - h: t+b - }; }; - // Box getters work in any box context because offsetWidth/clientWidth - // are invariant wrt box context - // - // They do *not* work for display: inline objects that have padding styles - // because the user agent ignores padding (it's bogus styling in any case) - // - // Be careful with IMGs because they are inline or block depending on - // browser and browser mode. + return has; +}); - // Although it would be easier to read, there are not separate versions of - // _getMarginBox for each browser because: - // 1. the branching is not expensive - // 2. factoring the shared code wastes cycles (function call overhead) - // 3. duplicating the shared code wastes bytes +}, +'dojo/_base/loader':function(){ +define(["./kernel", "../has", "require", "module", "./json", "./lang", "./array"], function(dojo, has, require, thisModule, json, lang, array) { + // module: + // dojo/_base/lader + // summary: + // This module defines the v1.x synchronous loader API. - dojo._getMarginBox = function(/*DomNode*/node, /*Object*/computedStyle){ - // summary: - // returns an object that encodes the width, height, left and top - // positions of the node's margin box. - var s = computedStyle || gcs(node), me = d._getMarginExtents(node, s); - var l = node.offsetLeft - me.l, t = node.offsetTop - me.t, p = node.parentNode; - if(d.isMoz){ - // Mozilla: - // If offsetParent has a computed overflow != visible, the offsetLeft is decreased - // by the parent's border. - // We don't want to compute the parent's style, so instead we examine node's - // computed left/top which is more stable. - var sl = parseFloat(s.left), st = parseFloat(s.top); - if(!isNaN(sl) && !isNaN(st)){ - l = sl, t = st; - }else{ - // If child's computed left/top are not parseable as a number (e.g. "auto"), we - // have no choice but to examine the parent's computed style. - if(p && p.style){ - var pcs = gcs(p); - if(pcs.overflow != "visible"){ - var be = d._getBorderExtents(p, pcs); - l += be.l, t += be.t; - } - } - } - }else if(d.isOpera || (d.isIE > 7 && !d.isQuirks)){ - // On Opera and IE 8, offsetLeft/Top includes the parent's border - if(p){ - be = d._getBorderExtents(p); - l -= be.l; - t -= be.t; - } - } - return { - l: l, - t: t, - w: node.offsetWidth + me.w, - h: node.offsetHeight + me.h - }; - } - - dojo._getMarginSize = function(/*DomNode*/node, /*Object*/computedStyle){ - // summary: - // returns an object that encodes the width and height of - // the node's margin box - node = byId(node); - var me = d._getMarginExtents(node, computedStyle || gcs(node)); + // signal the loader in sync mode... + //>>pure-amd - var size = node.getBoundingClientRect(); - return { - w: (size.right - size.left) + me.w, - h: (size.bottom - size.top) + me.h - } + if (!1){ + console.error("cannot load the Dojo v1.x loader with a foreign loader"); + return 0; } - dojo._getContentBox = function(node, computedStyle){ - // summary: - // Returns an object that encodes the width, height, left and top - // positions of the node's content box, irrespective of the - // current box model. + var makeErrorToken = function(id){ + return {src:thisModule.id, id:id}; + }, - // clientWidth/Height are important since the automatically account for scrollbars - // fallback to offsetWidth/Height for special cases (see #3378) - var s = computedStyle || gcs(node), - pe = d._getPadExtents(node, s), - be = d._getBorderExtents(node, s), - w = node.clientWidth, - h - ; - if(!w){ - w = node.offsetWidth, h = node.offsetHeight; - }else{ - h = node.clientHeight, be.w = be.h = 0; - } - // On Opera, offsetLeft includes the parent's border - if(d.isOpera){ pe.l += be.l; pe.t += be.t; }; - return { - l: pe.l, - t: pe.t, - w: w - pe.w - be.w, - h: h - pe.h - be.h - }; - }; + slashName = function(name){ + return name.replace(/\./g, "/"); + }, - dojo._getBorderBox = function(node, computedStyle){ - var s = computedStyle || gcs(node), - pe = d._getPadExtents(node, s), - cb = d._getContentBox(node, s) - ; - return { - l: cb.l - pe.l, - t: cb.t - pe.t, - w: cb.w + pe.w, - h: cb.h + pe.h - }; - }; + buildDetectRe = /\/\/>>built/, - // Box setters depend on box context because interpretation of width/height styles - // vary wrt box context. - // - // The value of dojo.boxModel is used to determine box context. - // dojo.boxModel can be set directly to change behavior. - // - // Beware of display: inline objects that have padding styles - // because the user agent ignores padding (it's a bogus setup anyway) - // - // Be careful with IMGs because they are inline or block depending on - // browser and browser mode. - // - // Elements other than DIV may have special quirks, like built-in - // margins or padding, or values not detectable via computedStyle. - // In particular, margins on TABLE do not seems to appear - // at all in computedStyle on Mozilla. + dojoRequireCallbacks = [], + dojoRequireModuleStack = [], - dojo._setBox = function(/*DomNode*/node, /*Number?*/l, /*Number?*/t, /*Number?*/w, /*Number?*/h, /*String?*/u){ - // summary: - // sets width/height/left/top in the current (native) box-model - // dimentions. Uses the unit passed in u. - // node: - // DOM Node reference. Id string not supported for performance - // reasons. - // l: - // left offset from parent. - // t: - // top offset from parent. - // w: - // width in current box model. - // h: - // width in current box model. - // u: - // unit measure to use for other measures. Defaults to "px". - u = u || "px"; - var s = node.style; - if(!isNaN(l)){ s.left = l + u; } - if(!isNaN(t)){ s.top = t + u; } - if(w >= 0){ s.width = w + u; } - if(h >= 0){ s.height = h + u; } - }; + dojoRequirePlugin = function(mid, require, loaded){ + dojoRequireCallbacks.push(loaded); + array.forEach(mid.split(","), function(mid){ + var module = getModule(mid, require.module); + dojoRequireModuleStack.push(module); + injectModule(module); + }); + checkDojoRequirePlugin(); + }, - dojo._isButtonTag = function(/*DomNode*/node) { - // summary: - // True if the node is BUTTON or INPUT.type="button". - return node.tagName == "BUTTON" - || node.tagName=="INPUT" && (node.getAttribute("type")||'').toUpperCase() == "BUTTON"; // boolean - }; + // checkDojoRequirePlugin inspects all of the modules demanded by a dojo/require! dependency + // to see if they have arrived. The loader does not release *any* of these modules to be instantiated + // until *all* of these modules are on board, thereby preventing the evaluation of a module with dojo.require's + // that reference modules that are not available. + // + // The algorithm works by traversing the dependency graphs (remember, there can be cycles so they are not trees) + // of each module in the dojoRequireModuleStack array (which contains the list of modules demanded by dojo/require!). + // The moment a single module is discovered that is missing, the algorithm gives up and indicates that not all + // modules are on board. dojo/loadInit! and dojo/require! are ignored because there dependencies are inserted + // directly in dojoRequireModuleStack. For example, if "your/module" module depends on "dojo/require!my/module", then + // *both* "dojo/require!my/module" and "my/module" will be in dojoRequireModuleStack. Obviously, if "my/module" + // is on board, then "dojo/require!my/module" is also satisfied, so the algorithm doesn't check for "dojo/require!my/module". + // + // Note: inserting a dojo/require! dependency in the dojoRequireModuleStack achieves nothing + // with the current algorithm; however, having such modules present makes it possible to optimize the algorithm + // + // Note: prior versions of this algorithm had an optimization that signaled loaded on dojo/require! dependencies + // individually (rather than waiting for them all to be resolved). The implementation proved problematic with cycles + // and plugins. However, it is possible to reattach that strategy in the future. + + // a set from module-id to {undefined | 1 | 0}, where... + // undefined => the module has not been inspected + // 0 => the module or at least one of its dependencies has not arrived + // 1 => the module is a loadInit! or require! plugin resource, or is currently being traversed (therefore, assume + // OK until proven otherwise), or has been completely traversed and all dependencies have arrived + touched, + + traverse = function(m){ + touched[m.mid] = 1; + for(var t, module, deps = m.deps || [], i= 0; i= 0){ widthPx += pb.w; } - if(heightPx >= 0){ heightPx += pb.h; } - } - d._setBox(node, NaN, NaN, widthPx, heightPx); - }; + // requireList is the list of modules that need to be downloaded but not executed before the callingModule can be executed + requireList.length && deps.push("dojo/require!" + requireList.join(",")); - dojo._setMarginBox = function(/*DomNode*/node, /*Number?*/leftPx, /*Number?*/topPx, - /*Number?*/widthPx, /*Number?*/heightPx, - /*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 dojo._setBox that handles box-model vagaries for - // you. + dojoRequireCallbacks.push(loaded); + array.forEach(requireList, function(mid){ + var module = getModule(mid, require.module); + dojoRequireModuleStack.push(module); + injectModule(module); + }); + checkDojoRequirePlugin(); + }); + }); + }, - var s = computedStyle || gcs(node), - // 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.boxModel. - bb = d._usesBorderBox(node), - pb = bb ? _nilExtents : d._getPadBorderExtents(node, s) - ; - if(d.isWebKit){ - // 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(d._isButtonTag(node)){ - var ns = node.style; - if(widthPx >= 0 && !ns.width) { ns.width = "4px"; } - if(heightPx >= 0 && !ns.height) { ns.height = "4px"; } + extractApplication = function( + text, // the text to search + startSearch, // the position in text to start looking for the closing paren + startApplication // the position in text where the function application expression starts + ){ + // find end of the call by finding the matching end paren + // Warning: as usual, this will fail in the presense of unmatched right parans contained in strings, regexs, or unremoved comments + var parenRe = /\(|\)/g, + matchCount = 1, + match; + parenRe.lastIndex = startSearch; + while((match = parenRe.exec(text))){ + if(match[0] == ")"){ + matchCount -= 1; + }else{ + matchCount += 1; + } + if(matchCount == 0){ + break; + } } - } - var mb = d._getMarginExtents(node, s); - if(widthPx >= 0){ widthPx = Math.max(widthPx - pb.w - mb.w, 0); } - if(heightPx >= 0){ heightPx = Math.max(heightPx - pb.h - mb.h, 0); } - d._setBox(node, leftPx, topPx, widthPx, heightPx); - }; - var _nilExtents = { l:0, t:0, w:0, h:0 }; + if(matchCount != 0){ + throw "unmatched paren around character " + parenRe.lastIndex + " in: " + text; + } - // public API + //Put the master matching string in the results. + return [dojo.trim(text.substring(startApplication, parenRe.lastIndex))+";\n", parenRe.lastIndex]; + }, - dojo.marginBox = function(/*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 marginbox of a passed node - // | var box = dojo.marginBox("someNodeId"); - // | console.dir(box); + // the following regex is taken from 1.6. It is a very poor technique to remove comments and + // will fail in some cases; for example, consider the code... // - // example: - // Set a node's marginbox to the size of another node - // | var box = dojo.marginBox("someNodeId"); - // | dojo.marginBox("someOtherNode", box); - - var n = byId(node), s = gcs(n), b = box; - return !b ? d._getMarginBox(n, s) : d._setMarginBox(n, b.l, b.t, b.w, b.h, s); // Object - }; + // var message = "Category-1 */* Category-2"; + // + // The regex that follows will see a /* comment and trash the code accordingly. In fact, there are all + // kinds of cases like this with strings and regexs that will cause this design to fail miserably. + // + // Alternative regex designs exist that will result in less-likely failures, but will still fail in many cases. + // The only solution guaranteed 100% correct is to parse the code and that seems overkill for this + // backcompat/unbuilt-xdomain layer. In the end, since it's been this way for a while, we won't change it. + // See the opening paragraphs of Chapter 7 or ECME-262 which describes the lexical abiguity further. + removeCommentRe = /(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg, - dojo.contentBox = function(/*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. - var n = byId(node), s = gcs(n), b = box; - return !b ? d._getContentBox(n, s) : d._setContentSize(n, b.w, b.h, s); // Object - }; + syncLoaderApiRe = /(^|\s)dojo\.(loadInit|require|provide|requireLocalization|requireIf|requireAfterIf|platformRequire)\s*\(/mg, - // ============================= - // Positioning - // ============================= + amdLoaderApiRe = /(^|\s)(require|define)\s*\(/m, + + extractLegacyApiApplications = function(text, noCommentText){ + // scan the noCommentText for any legacy loader API applications. Copy such applications into result (this is + // used by the builder). Move dojo.loadInit applications to loadInitApplications string. Copy all other applications + // to otherApplications string. If no applications were found, return 0, signalling an AMD module. Otherwise, return + // loadInitApplications + otherApplications. Fixup text by replacing + // + // dojo.loadInit(// etc... + // + // with + // + // \n 0 && dojo.loadInit(// etc... + // + // Which results in the dojo.loadInit from *not* being applied. This design goes a long way towards protecting the + // code from an over-agressive removeCommentRe. However... + // + // WARNING: the removeCommentRe will cause an error if a detected comment removes all or part of a legacy-loader application + // that is not in a comment. + + var match, startSearch, startApplication, application, + loadInitApplications = [], + otherApplications = [], + allApplications = []; + + // noCommentText may be provided by a build app with comments extracted by a better method than regex (hopefully) + noCommentText = noCommentText || text.replace(removeCommentRe, function(match){ + // remove iff the detected comment has text that looks like a sync loader API application; this helps by + // removing as little as possible, minimizing the changes the janky regex will kill the module + syncLoaderApiRe.lastIndex = amdLoaderApiRe.lastIndex = 0; + return (syncLoaderApiRe.test(match) || amdLoaderApiRe.test(match)) ? "" : match; + }); - var _sumAncestorProperties = function(node, prop){ - if(!(node = (node||0).parentNode)){return 0;} - var val, retVal = 0, _b = d.body(); - while(node && node.style){ - if(gcs(node).position == "fixed"){ + // find and extract all dojo.loadInit applications + while((match = syncLoaderApiRe.exec(noCommentText))){ + startSearch = syncLoaderApiRe.lastIndex; + startApplication = startSearch - match[0].length; + application = extractApplication(noCommentText, startSearch, startApplication); + if(match[2]=="loadInit"){ + loadInitApplications.push(application[0]); + }else{ + otherApplications.push(application[0]); + } + syncLoaderApiRe.lastIndex = application[1]; + } + allApplications = loadInitApplications.concat(otherApplications); + if(allApplications.length || !amdLoaderApiRe.test(noCommentText)){ + // either there were some legacy loader API applications or there were no AMD API applications + return [text.replace(/(^|\s)dojo\.loadInit\s*\(/g, "\n0 && dojo.loadInit("), allApplications.join(""), allApplications]; + }else{ + // legacy loader API *was not* detected and AMD API *was* detected; therefore, assume it's an AMD module return 0; } - val = node[prop]; - if(val){ - retVal += val - 0; - // opera and khtml #body & #html has the same values, we only - // need one value - if(node == _b){ break; } + }, + + transformToAmd = function(module, text){ + // This is roughly the equivalent of dojo._xdCreateResource in 1.6-; however, it expresses a v1.6- dojo + // module in terms of AMD define instead of creating the dojo proprietary xdomain module expression. + // The module could have originated from several sources: + // + // * amd require() a module, e.g., require(["my/module"]) + // * amd require() a nonmodule, e.g., require(["my/resource.js"') + // * amd define() deps vector (always a module) + // * dojo.require() a module, e.g. dojo.require("my.module") + // * dojo.require() a nonmodule, e.g., dojo.require("my.module", true) + // * dojo.requireIf/requireAfterIf/platformRequire a module + // + // The module is scanned for legacy loader API applications; if none are found, then assume the module is an + // AMD module and return 0. Otherwise, a synthetic dojo/loadInit plugin resource is created and the module text + // is rewritten as an AMD module with the single dependency of this synthetic resource. When the dojo/loadInit + // plugin loaded the synthetic resource, it will cause all dojo.loadInit's to be executed, find all dojo.require's + // (either directly consequent to dojo.require or indirectly consequent to dojo.require[After]If or + // dojo.platformRequire, and finally cause loading of all dojo.required modules with the dojo/require plugin. Thus, + // when the dojo/loadInit plugin reports it has been loaded, all modules required by the given module are guaranteed + // loaded (but not executed). This then allows the module to execute it's code path without interupts, thereby + // following the synchronous code path. + + var extractResult, id, names = [], namesAsStrings = []; + if(buildDetectRe.test(text) || !(extractResult = extractLegacyApiApplications(text))){ + // buildDetectRe.test(text) => a built module, always AMD + // extractResult==0 => no sync API + return 0; } - node = node.parentNode; - } - return retVal; // integer - }; - dojo._docScroll = function(){ - var n = d.global; - return "pageXOffset" in n - ? { x:n.pageXOffset, y:n.pageYOffset } - : (n = d.isQuirks? d.doc.body : d.doc.documentElement, { x:d._fixIeBiDiScrollLeft(n.scrollLeft || 0), y:n.scrollTop || 0 }); - }; + // manufacture a synthetic module id that can never be a real mdule id (just like require does) + id = module.mid + "-*loadInit"; - dojo._isBodyLtr = function(){ - return "_bodyLtr" in d? d._bodyLtr : - d._bodyLtr = (d.body().dir || d.doc.documentElement.dir || "ltr").toLowerCase() == "ltr"; // Boolean - }; + // construct the dojo/loadInit names vector which causes any relocated names to be defined as lexical variables under their not-relocated name + // the dojo/loadInit plugin assumes the first name in names is "dojo" - dojo._getIeDocumentElementOffset = function(){ - // summary: - // returns the offset in x and y from the document body to the - // visual edge of the page - // description: - // The following values in IE contain an offset: - // | event.clientX - // | event.clientY - // | node.getBoundingClientRect().left - // | node.getBoundingClientRect().top - // But other position related values do not contain this offset, - // such as node.offsetLeft, node.offsetTop, node.style.left and - // node.style.top. The offset is always (2, 2) in LTR direction. - // When the body is in RTL direction, the offset counts the width - // of left scroll bar's width. This function computes the actual - // offset. + for(var p in getModule("dojo", module).result.scopeMap){ + names.push(p); + namesAsStrings.push('"' + p + '"'); + } - //NOTE: assumes we're being called in an IE browser + // rewrite the module as a synthetic dojo/loadInit plugin resource + the module expressed as an AMD module that depends on this synthetic resource + return "// xdomain rewrite of " + module.path + "\n" + + "define('" + id + "',{\n" + + "\tnames:" + dojo.toJson(names) + ",\n" + + "\tdef:function(" + names.join(",") + "){" + extractResult[1] + "}" + + "});\n\n" + + "define(" + dojo.toJson(names.concat(["dojo/loadInit!"+id])) + ", function(" + names.join(",") + "){\n" + extractResult[0] + "});"; + }, - var de = d.doc.documentElement; // only deal with HTML element here, _abs handles body/quirks + loaderVars = require.initSyncLoader(dojoRequirePlugin, checkDojoRequirePlugin, transformToAmd), - if(d.isIE < 8){ - var r = de.getBoundingClientRect(); // works well for IE6+ - //console.debug('rect left,top = ' + r.left+','+r.top + ', html client left/top = ' + de.clientLeft+','+de.clientTop + ', rtl = ' + (!d._isBodyLtr()) + ', quirks = ' + d.isQuirks); - var l = r.left, - t = r.top; - if(d.isIE < 7){ - l += de.clientLeft; // scrollbar size in strict/RTL, or, - t += de.clientTop; // HTML border size in strict - } - return { - x: l < 0? 0 : l, // FRAME element border size can lead to inaccurate negative values - y: t < 0? 0 : t - }; - }else{ - return { - x: 0, - y: 0 - }; - } + sync = + loaderVars.sync, - }; - - dojo._fixIeBiDiScrollLeft = function(/*Integer*/ scrollLeft){ - // 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. + xd = + loaderVars.xd, - var ie = d.isIE; - if(ie && !d._isBodyLtr()){ - var qk = d.isQuirks, - de = qk ? d.doc.body : d.doc.documentElement; - if(ie == 6 && !qk && d.global.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 - }; + arrived = + loaderVars.arrived, - // FIXME: need a setter for coords or a moveTo!! - dojo._abs = dojo.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. + nonmodule = + loaderVars.nonmodule, - node = byId(node); - var db = d.body(), - dh = db.parentNode, - ret = node.getBoundingClientRect(); - ret = { x: ret.left, y: ret.top, w: ret.right - ret.left, h: ret.bottom - ret.top }; - if(d.isIE){ - // On IE there's a 2px offset that we need to adjust for, see _getIeDocumentElementOffset() - var offset = d._getIeDocumentElementOffset(); - - // fixes the position in IE, quirks mode - ret.x -= offset.x + (d.isQuirks ? db.clientLeft+db.offsetLeft : 0); - ret.y -= offset.y + (d.isQuirks ? db.clientTop+db.offsetTop : 0); - }else if(d.isFF == 3){ - // In FF3 you have to subtract the document element margins. - // Fixed in FF3.5 though. - var cs = gcs(dh); - ret.x -= px(dh, cs.marginLeft) + px(dh, cs.borderLeftWidth); - ret.y -= px(dh, cs.marginTop) + px(dh, cs.borderTopWidth); + executing = + loaderVars.executing, + + executed = + loaderVars.executed, + + syncExecStack = + loaderVars.syncExecStack, + + modules = + loaderVars.modules, + + execQ = + loaderVars.execQ, + + getModule = + loaderVars.getModule, + + injectModule = + loaderVars.injectModule, + + setArrived = + loaderVars.setArrived, + + signal = + loaderVars.signal, + + finishExec = + loaderVars.finishExec, + + execModule = + loaderVars.execModule, + + getLegacyMode = + loaderVars.getLegacyMode; + + dojo.provide = function(mid){ + var executingModule = syncExecStack[0], + module = lang.mixin(getModule(slashName(mid), require.module), { + executed:executing, + result:lang.getObject(mid, true) + }); + setArrived(module); + if(executingModule){ + (executingModule.provides || (executingModule.provides = [])).push(function(){ + module.result = lang.getObject(mid); + delete module.provides; + module.executed!==executed && finishExec(module); + }); + }// else dojo.provide called not consequent to loading; therefore, give up trying to publish module value to loader namespace + return module.result; + }; + + has.add("config-publishRequireResult", 1, 0, 0); + + dojo.require = function(moduleName, omitModuleCheck) { + // summary: + // loads a Javascript module from the appropriate URI + // + // moduleName: String + // module name to load, using periods for separators, + // e.g. "dojo.date.locale". Module paths are de-referenced by dojo's + // internal mapping of locations to names and are disambiguated by + // longest prefix. See `dojo.registerModulePath()` for details on + // registering new modules. + // + // omitModuleCheck: Boolean? + // if `true`, omitModuleCheck skips the step of ensuring that the + // loaded file actually defines the symbol it is referenced by. + // For example if it called as `dojo.require("a.b.c")` and the + // file located at `a/b/c.js` does not define an object `a.b.c`, + // and exception will be throws whereas no exception is raised + // when called as `dojo.require("a.b.c", true)` + // + // description: + // Modules are loaded via dojo.require by using one of two loaders: the normal loader + // and the xdomain loader. The xdomain loader is used when dojo was built with a + // custom build that specified loader=xdomain and the module lives on a modulePath + // that is a whole URL, with protocol and a domain. The versions of Dojo that are on + // the Google and AOL CDNs use the xdomain loader. + // + // If the module is loaded via the xdomain loader, it is an asynchronous load, since + // the module is added via a dynamically created script tag. This + // means that dojo.require() can return before the module has loaded. However, this + // should only happen in the case where you do dojo.require calls in the top-level + // HTML page, or if you purposely avoid the loader checking for dojo.require + // dependencies in your module by using a syntax like dojo["require"] to load the module. + // + // Sometimes it is useful to not have the loader detect the dojo.require calls in the + // module so that you can dynamically load the modules as a result of an action on the + // page, instead of right at module load time. + // + // Also, for script blocks in an HTML page, the loader does not pre-process them, so + // it does not know to download the modules before the dojo.require calls occur. + // + // So, in those two cases, when you want on-the-fly module loading or for script blocks + // in the HTML page, special care must be taken if the dojo.required code is loaded + // asynchronously. To make sure you can execute code that depends on the dojo.required + // modules, be sure to add the code that depends on the modules in a dojo.addOnLoad() + // callback. dojo.addOnLoad waits for all outstanding modules to finish loading before + // executing. + // + // This type of syntax works with both xdomain and normal loaders, so it is good + // practice to always use this idiom for on-the-fly code loading and in HTML script + // blocks. If at some point you change loaders and where the code is loaded from, + // it will all still work. + // + // More on how dojo.require + // `dojo.require("A.B")` first checks to see if symbol A.B is + // defined. If it is, it is simply returned (nothing to do). + // + // If it is not defined, it will look for `A/B.js` in the script root + // directory. + // + // `dojo.require` throws an exception if it cannot find a file + // to load, or if the symbol `A.B` is not defined after loading. + // + // It returns the object `A.B`, but note the caveats above about on-the-fly loading and + // HTML script blocks when the xdomain loader is loading a module. + // + // `dojo.require()` does nothing about importing symbols into + // the current namespace. It is presumed that the caller will + // take care of that. + // + // example: + // To use dojo.require in conjunction with dojo.ready: + // + // | dojo.require("foo"); + // | dojo.require("bar"); + // | dojo.addOnLoad(function(){ + // | //you can now safely do something with foo and bar + // | }); + // + // example: + // For example, to import all symbols into a local block, you might write: + // + // | with (dojo.require("A.B")) { + // | ... + // | } + // + // And to import just the leaf symbol to a local variable: + // + // | var B = dojo.require("A.B"); + // | ... + // + // returns: + // the required namespace object + function doRequire(mid, omitModuleCheck){ + var module = getModule(slashName(mid), require.module); + if(syncExecStack.length && syncExecStack[0].finish){ + // switched to async loading in the middle of evaluating a legacy module; stop + // applying dojo.require so the remaining dojo.requires are applied in order + syncExecStack[0].finish.push(mid); + return undefined; + } + + // recall module.executed has values {0, executing, executed}; therefore, truthy indicates executing or executed + if(module.executed){ + return module.result; + } + omitModuleCheck && (module.result = nonmodule); + + var currentMode = getLegacyMode(); + + // recall, in sync mode to inject is to *eval* the module text + // if the module is a legacy module, this is the same as executing + // but if the module is an AMD module, this means defining, not executing + injectModule(module); + // the inject may have changed the mode + currentMode = getLegacyMode(); + + // in sync mode to dojo.require is to execute + if(module.executed!==executed && module.injected===arrived){ + // the module was already here before injectModule was called probably finishing up a xdomain + // load, but maybe a module given to the loader directly rather than having the loader retrieve it + loaderVars.holdIdle(); + execModule(module); + loaderVars.releaseIdle(); + } + if(module.executed){ + return module.result; + } + + if(currentMode==sync){ + // the only way to get here is in sync mode and dojo.required a module that + // * was loaded async in the injectModule application a few lines up + // * was an AMD module that had deps that are being loaded async and therefore couldn't execute + if(module.cjs){ + // the module was an AMD module; unshift, not push, which causes the current traversal to be reattempted from the top + execQ.unshift(module); + }else{ + // the module was a legacy module + syncExecStack.length && (syncExecStack[0].finish= [mid]); + } + }else{ + // the loader wasn't in sync mode on entry; probably async mode; therefore, no expectation of getting + // the module value synchronously; make sure it gets executed though + execQ.push(module); } - // account for document scrolling - if(includeScroll){ - var scroll = d._docScroll(); - ret.x += scroll.x; - ret.y += scroll.y; + return undefined; } - return ret; // Object + var result = doRequire(moduleName, omitModuleCheck); + if(has("config-publishRequireResult") && !lang.exists(moduleName) && result!==undefined){ + lang.setObject(moduleName, result); + } + return result; }; - dojo.coords = function(/*DomNode|String*/node, /*Boolean?*/includeScroll){ + dojo.loadInit = function(f) { + f(); + }; + + dojo.registerModulePath = function(/*String*/moduleName, /*String*/prefix){ // summary: - // Deprecated: Use position() for border-box x/y/w/h - // or marginBox() for margin-box w/h/l/t. - // Returns an object representing a node's size and position. - // + // Maps a module name to a path // description: - // 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(). - var n = byId(node), s = gcs(n), mb = d._getMarginBox(n, s); - var abs = d.position(n, includeScroll); - mb.x = abs.x; - mb.y = abs.y; - return mb; + // An unregistered module is given the default path of ../[module], + // relative to Dojo root. For example, module acme is mapped to + // ../acme. If you want to use a different module name, use + // dojo.registerModulePath. + // example: + // If your dojo.js is located at this location in the web root: + // | /myapp/js/dojo/dojo/dojo.js + // and your modules are located at: + // | /myapp/js/foo/bar.js + // | /myapp/js/foo/baz.js + // | /myapp/js/foo/thud/xyzzy.js + // Your application can tell Dojo to locate the "foo" namespace by calling: + // | dojo.registerModulePath("foo", "../../foo"); + // At which point you can then use dojo.require() to load the + // modules (assuming they provide() the same things which are + // required). The full code might be: + // | + // | + + var paths = {}; + paths[moduleName.replace(/\./g, "/")] = prefix; + require({paths:paths}); }; - // ============================= - // Element attribute Functions - // ============================= + 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 choosen 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" ] + // | }); - // dojo.attr() should conform to http://www.w3.org/TR/DOM-Level-2-Core/ + 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); + } + } + }; - var _propNames = { - // 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", - valuetype: "valueType" - }, - _attrNames = { - // original attribute names - classname: "class", - htmlfor: "for", - // for IE - tabindex: "tabIndex", - readonly: "readOnly" - }, - _forcePropNames = { - innerHTML: 1, - className: 1, - htmlFor: d.isIE, - value: 1 - }; + 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"); - var _fixAttrName = function(/*String*/ name){ - return _attrNames[name.toLowerCase()] || name; + if(condition){ + dojo.require(moduleName, omitModuleCheck); + } }; - var _hasAttr = function(node, name){ - var attr = node.getAttributeNode && node.getAttributeNode(name); - return attr && attr.specified; // Boolean + dojo.requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale){ + require(["../i18n"], function(i18n){ + i18n.getLocalization(moduleName, bundleName, locale); + }); + }; + + return { + extractLegacyApiApplications:extractLegacyApiApplications, + require:loaderVars.dojoRequirePlugin, + loadInit:dojoLoadInitPlugin + }; +}); + +}, +'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}'); + 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){ + // 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. + 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){ + // 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); + 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(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/declare':function(){ +define(["./kernel", "../has", "./lang"], function(dojo, has, lang){ + // module: + // dojo/_base/declare + // summary: + // This module defines dojo.declare. + + var mix = lang.mixin, op = Object.prototype, opts = op.toString, + xtor = new Function, counter = 0, cname = "constructor"; + + 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){ + 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 = 0; + + caller = args.callee; + name = name || caller.nom; + if(!name){ + err("can't deduce a name to call inherited()", this.declaredClass); + } + + 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){ + if(typeof name == "string"){ + return this.__inherited(name, args, true); + } + return this.__inherited(name, true); + } + + function inherited__debug(args, a1, a2){ + var f = this.getInherited(args, a1); + if(f){ return f.apply(this, 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){ + 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")){ + 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; + } + + // chained constructor compatible with the legacy dojo.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 dojo.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 dojo.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 dojo.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 dojo.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){ + // 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 + 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-"]); + } + + // 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.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 + } + + /*===== + dojo.declare = function(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: + // 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 + // dojo.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 + // dojo.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: + // | dojo.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 = dojo.declare(null, { + // | // constructor, properties, and methods go here + // | // ... + // | }); + // | var MyClass1 = dojo.declare(MyBase, { + // | // constructor, properties, and methods go here + // | // ... + // | }); + // | var MyClass2 = dojo.declare(MyBase, { + // | // constructor, properties, and methods go here + // | // ... + // | }); + // | var MyDiamond = dojo.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 = dojo.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 = dojo.declare(null, { + // | "-chains-": { + // | destroy: "before" + // | } + // | }); + // | var B = dojo.declare(A, { + // | constructor: function(){ + // | console.log("B.constructor"); + // | }, + // | destroy: function(){ + // | console.log("B.destroy"); + // | } + // | }); + // | var C = dojo.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 = dojo.declare(null, { + // | "-chains-": { + // | constructor: "manual" + // | } + // | }); + // | var B = dojo.declare(A, { + // | constructor: function(){ + // | // ... + // | // call the base constructor with new parameters + // | this.inherited(arguments, [1, 2, 3]); + // | // ... + // | } + // | }); + // + // example: + // | var A = dojo.declare(null, { + // | "-chains-": { + // | m1: "before" + // | }, + // | m1: function(){ + // | console.log("A.m1"); + // | }, + // | m2: function(){ + // | console.log("A.m2"); + // | } + // | }); + // | var B = dojo.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 + return new Function(); // Function }; + =====*/ - // 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. - - dojo.hasAttr = function(/*DomNode|String*/node, /*String*/name){ + /*===== + dojo.safeMixin = function(target, source){ // summary: - // Returns true if the requested attribute is specified on the - // given element, and false otherwise. - // node: - // id or reference to the element to check - // name: - // the name of the attribute - // returns: - // true if the requested attribute is specified on the - // given element, and false otherwise - var lc = name.toLowerCase(); - return _forcePropNames[_propNames[lc] || name] || _hasAttr(byId(node), _attrNames[lc] || name); // Boolean + // Mix in properties skipping a constructor and decorating functions + // like it is done by dojo.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 + // dojo.declare does. + // + // It is meant to be used with classes and objects produced with + // dojo.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 dojo.declare(). + // + // example: + // | var A = dojo.declare(null, { + // | m1: function(){ + // | console.log("A.m1"); + // | }, + // | m2: function(){ + // | console.log("A.m2"); + // | } + // | }); + // | var B = dojo.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 _evtHdlrMap = {}, _ctr = 0, - _attrId = dojo._scopeName + "attrid", - // the next dictionary lists elements with read-only innerHTML on IE - _roInnerHtml = {col: 1, colgroup: 1, - // frameset: 1, head: 1, html: 1, style: 1, - table: 1, tbody: 1, tfoot: 1, thead: 1, tr: 1, title: 1}; - - dojo.attr = function(/*DomNode|String*/node, /*String|Object*/name, /*String?*/value){ + /*===== + Object.inherited = function(name, args, newArgs){ // summary: - // Gets or sets an attribute on an HTML element. + // 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 + // dojo.declare, and it cannot be determined. + // 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: - // Handles normalized getting and setting of attributes on DOM - // Nodes. If 2 arguments are passed, and a the second argumnt is a - // string, acts as a getter. + // This method is used inside method of classes produced with + // dojo.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. // - // If a third argument is passed, or if the second argument is a - // map of attributes, acts as a setter. + // 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. // - // 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 attribute on - // name: - // the name of the attribute to get or set. - // value: - // 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; + // 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. // - // when used as a setter, the DOM node + // 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: - // | // 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"); + // | var B = dojo.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 = dojo.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); + // | } + // | }); + return {}; // Object + } + =====*/ + + /*===== + Object.getInherited = function(name, 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 + // dojo.declare, and it cannot be determined. + // 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: - // | // use attr() to set the tab index - // | dojo.attr("nodeId", "tabIndex", 3); + // | var B = dojo.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); + // | } + // | }); + return {}; // Object + } + =====*/ + + /*===== + 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 + // dojo.declare to determine of they support a certain interface or + // not. It models "instanceof" operator. + // + // example: + // | var A = dojo.declare(null, { + // | // constructor, properties, and methods go here + // | // ... + // | }); + // | var B = dojo.declare(null, { + // | // constructor, properties, and methods go here + // | // ... + // | }); + // | var C = dojo.declare([A, B], { + // | // constructor, properties, and methods go here + // | // ... + // | }); + // | var D = dojo.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 + } + =====*/ + + /*===== + 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 + // dojo.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. // - // 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" }); - // | } - // | }); + // This method is similar to dojo.extend function, but it is specific + // to constructors produced by dojo.declare. It is implemented + // using dojo.safeMixin, and it skips a constructor property, + // and properly decorates copied functions. // // 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" - // | } + // | var A = dojo.declare(null, { + // | m1: function(){}, + // | s1: "Popokatepetl" + // | }); + // | A.extend({ + // | m1: function(){}, + // | m2: function(){}, + // | f1: true, + // | d1: 42 // | }); - // - // 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); - - node = byId(node); - var args = arguments.length, prop; - if(args == 2 && typeof name != "string"){ // inline'd type check - // the object form of setter: the 2nd argument is a dictionary - for(var x in name){ - d.attr(node, x, name[x]); - } - return node; // DomNode - } - var lc = name.toLowerCase(), - propName = _propNames[lc] || name, - forceProp = _forcePropNames[propName], - attrName = _attrNames[lc] || name; - if(args == 3){ - // setter - do{ - if(propName == "style" && typeof value != "string"){ // inline'd type check - // special case: setting a style - d.style(node, value); - break; - } - if(propName == "innerHTML"){ - // special case: assigning HTML - if(d.isIE && node.tagName.toLowerCase() in _roInnerHtml){ - d.empty(node); - node.appendChild(d._toDom(value, node.ownerDocument)); - }else{ - node[propName] = value; - } - break; - } - if(d.isFunction(value)){ - // special case: assigning an event handler - // clobber if we can - var attrId = d.attr(node, _attrId); - if(!attrId){ - attrId = _ctr++; - d.attr(node, _attrId, attrId); - } - if(!_evtHdlrMap[attrId]){ - _evtHdlrMap[attrId] = {}; - } - var h = _evtHdlrMap[attrId][propName]; - if(h){ - d.disconnect(h); - }else{ - try{ - delete node[propName]; - }catch(e){} - } - // ensure that event objects are normalized, etc. - _evtHdlrMap[attrId][propName] = d.connect(node, propName, value); - break; - } - if(forceProp || typeof value == "boolean"){ - // special case: forcing assignment to the property - // special case: setting boolean to a property instead of attribute - node[propName] = value; - break; - } - // node's attribute - node.setAttribute(attrName, value); - }while(false); - return node; // DomNode - } - // getter - // should we access this attribute via a property or - // via getAttribute()? - value = node[propName]; - if(forceProp && typeof value != "undefined"){ - // node's property - return value; // Anything - } - if(propName != "href" && (typeof value == "boolean" || d.isFunction(value))){ - // node's property - return value; // Anything - } - // node's attribute - // we need _hasAttr() here to guard against IE returning a default value - return _hasAttr(node, attrName) ? node.getAttribute(attrName) : null; // Anything }; + =====*/ - dojo.removeAttr = function(/*DomNode|String*/ node, /*String*/ name){ - // summary: - // Removes an attribute from an HTML element. - // node: - // id or reference to the element to remove the attribute from - // name: - // the name of the attribute to remove - byId(node).removeAttribute(_fixAttrName(name)); - }; + dojo.safeMixin = declare.safeMixin = safeMixin; + dojo.declare = declare; - dojo.getNodeProp = function(/*DomNode|String*/ node, /*String*/ name){ - // summary: - // Returns an effective value of a property or an attribute. - // node: - // id or reference to the element to remove the attribute from - // name: - // the name of the attribute - node = byId(node); - var lc = name.toLowerCase(), - propName = _propNames[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 - }; + return declare; +}); - dojo.create = function(tag, attrs, refNode, pos){ - // summary: - // Create an element, allowing for optional attribute decoration - // and placement. - // - // description: - // A DOM Element creation function. A shorthand method for creating a node or - // a fragment, and allowing for a convenient optional attribute setting step, - // as well as an optional DOM placement reference. - //| - // Attributes are set by passing the optional object through `dojo.attr`. - // See `dojo.attr` for noted caveats and nuances, and API if applicable. - //| - // Placement is done via `dojo.place`, assuming the new node to be the action - // node, passing along the optional reference node and position. - // - // tag: String|DomNode - // A string of the element to create (eg: "div", "a", "p", "li", "script", "br"), - // or an existing DOM node to process. - // - // attrs: Object - // An object-hash of attributes to set on the newly created node. - // Can be null, if you don't want to set any attributes/styles. - // See: `dojo.attr` for a description of available attributes. - // - // refNode: String?|DomNode? - // Optional reference node. Used by `dojo.place` to place the newly created - // node somewhere in the dom relative to refNode. Can be a DomNode reference - // or String ID of a node. - // - // pos: String? - // Optional positional reference. Defaults to "last" by way of `dojo.place`, - // though can be set to "first","after","before","last", "replace" or "only" - // to further control the placement of the new node relative to the refNode. - // 'refNode' is required if a 'pos' is specified. - // - // returns: DomNode +}, +'dojo/dom':function(){ +define(["./_base/sniff", "./_base/lang", "./_base/window"], + function(has, lang, win){ + // module: + // dojo/dom + // summary: + // This module defines the core dojo DOM API. + + // FIXME: need to add unit tests for all the semi-public methods + + try{ + document.execCommand("BackgroundImageCache", false, true); + }catch(e){ + // sane browsers don't have cache "issues" + } + + // ============================= + // DOM Functions + // ============================= + + /*===== + dojo.byId = function(id, doc){ + // summary: + // Returns DOM node with matching `id` attribute or `null` + // if not found. If `id` is a DomNode, this function is a no-op. // - // example: - // Create a DIV: - // | var n = dojo.create("div"); + // id: String|DOMNode + // A string to match an HTML id attribute or a reference to a DOM Node // - // example: - // Create a DIV with content: - // | var n = dojo.create("div", { innerHTML:"

hi

" }); + // doc: Document? + // Document to work in. Defaults to the current value of + // dojo.doc. Can be used to retrieve + // node references from other documents. // // example: - // Place a new DIV in the BODY, with no attributes set - // | var n = dojo.create("div", null, dojo.body()); + // Look up a node by ID: + // | var n = dojo.byId("foo"); // // example: - // Create an UL, and populate it with LI's. Place the list as the first-child of a - // node with id="someId": - // | var ul = dojo.create("ul", null, "someId", "first"); - // | var items = ["one", "two", "three", "four"]; - // | dojo.forEach(items, function(data){ - // | dojo.create("li", { innerHTML: data }, ul); - // | }); + // Check if a node exists, and use it. + // | var n = dojo.byId("bar"); + // | if(n){ doStuff() ... } // // example: - // Create an anchor, with an href. Place in BODY: - // | dojo.create("a", { href:"foo.html", title:"Goto FOO!" }, dojo.body()); + // Allow string or DomNode references to be passed to a custom function: + // | var foo = function(nodeOrId){ + // | nodeOrId = dojo.byId(nodeOrId); + // | // ... more stuff + // | } + =====*/ + + /*===== + dojo.isDescendant = function(node, 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: - // Create a `dojo.NodeList()` from a new element (for syntatic sugar): - // | dojo.query(dojo.create('div')) - // | .addClass("newDiv") - // | .onclick(function(e){ console.log('clicked', e.target) }) - // | .place("#someNode"); // redundant, but cleaner. - - var doc = d.doc; - if(refNode){ - refNode = byId(refNode); - doc = refNode.ownerDocument; - } - if(typeof tag == "string"){ // inline'd type check - tag = doc.createElement(tag); - } - if(attrs){ d.attr(tag, attrs); } - if(refNode){ d.place(tag, refNode, pos); } - return tag; // DomNode + // Test is node id="bar" is a descendant of node id="foo" + // | if(dojo.isDescendant("bar", "foo")){ ... } }; - - /*===== - dojo.empty = function(node){ - // summary: - // safely removes all children of the node. - // node: DOMNode|String - // a reference to a DOM node or an id. - // example: - // Destroy node's children byId: - // | dojo.empty("someId"); - // - // example: - // Destroy all nodes' children in a list by reference: - // | dojo.query(".someNode").forEach(dojo.empty); - } =====*/ - d.empty = - d.isIE ? function(node){ - node = byId(node); - for(var c; c = node.lastChild;){ // intentional assignment - d.destroy(c); - } - } : - function(node){ - byId(node).innerHTML = ""; - }; + // TODO: do we need this function in the base? /*===== - dojo._toDom = function(frag, doc){ - // summary: - // instantiates an HTML fragment returning the corresponding DOM. - // frag: String - // the HTML fragment - // doc: DocumentNode? - // optional document to use when creating DOM nodes, defaults to - // dojo.doc if not specified. - // returns: DocumentFragment - // - // example: - // Create a table row: - // | var tr = dojo._toDom("First!"); - } - =====*/ - - // support stuff for dojo._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 = "__" + d._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" ? '' : "<" + tw.join("><") + ">"; + tw.post = ""; + // the last line is destructive: it reverses the array, + // but we don't care at this point + } + } - var specials = ">~+"; + function _insertBefore(/*DomNode*/node, /*DomNode*/ref){ + var parent = ref.parentNode; + if(parent){ + parent.insertBefore(node, ref); + } + } - // global thunk to determine whether we should treat the current query as - // case sensitive or not. This switch is flipped by the query evaluator - // based on the document passed as the context to search. - var caseSensitive = false; + function _insertAfter(/*DomNode*/node, /*DomNode*/ref){ + // summary: + // Try to insert node after ref + var parent = ref.parentNode; + if(parent){ + if(parent.lastChild == ref){ + parent.appendChild(node); + }else{ + parent.insertBefore(node, ref.nextSibling); + } + } + } - // how high? - var yesman = function(){ return true; }; + var _destroyContainer = null, + _destroyDoc; + on(window, "unload", function(){ + _destroyContainer = null; //prevent IE leak + }); + + exports.toDom = function toDom(frag, doc){ + doc = doc || win.doc; + var masterId = doc[masterName]; + if(!masterId){ + doc[masterName] = masterId = ++masterNum + ""; + masterNode[masterId] = doc.createElement("div"); + } - //////////////////////////////////////////////////////////////////////// - // Tokenizer - //////////////////////////////////////////////////////////////////////// + // make sure the frag is a string. + frag += ""; - var getQueryParts = function(query){ - // summary: - // state machine for query tokenization - // description: - // instead of using a brittle and slow regex-based CSS parser, - // dojo.query implements an AST-style query representation. This - // representation is only generated once per query. For example, - // the same query run multiple times or under different root nodes - // does not re-parse the selector expression but instead uses the - // cached data structure. The state machine implemented here - // terminates on the last " " (space) character and returns an - // ordered array of query component structures (or "parts"). Each - // part represents an operator or a simple CSS filtering - // expression. The structure for parts is documented in the code - // below. - - - // NOTE: - // this code is designed to run fast and compress well. Sacrifices - // to readability and maintainability have been made. Your best - // bet when hacking the tokenizer is to put The Donnas on *really* - // loud (may we recommend their "Spend The Night" release?) and - // just assume you're gonna make mistakes. Keep the unit tests - // open and run them frequently. Knowing is half the battle ;-) - if(specials.indexOf(query.slice(-1)) >= 0){ - // if we end with a ">", "+", or "~", that means we're implicitly - // searching all children, so make it explicit - query += " * " + // find the starting tag, and get node wrapper + var match = frag.match(reTag), + tag = match ? match[1].toLowerCase() : "", + master = masterNode[masterId], + wrap, i, fc, df; + if(match && tagWrap[tag]){ + wrap = tagWrap[tag]; + master.innerHTML = wrap.pre + frag + wrap.post; + for(i = wrap.length; i; --i){ + master = master.firstChild; + } }else{ - // if you have not provided a terminator, one will be provided for - // you... - query += " "; + master.innerHTML = frag; } - var ts = function(/*Integer*/ s, /*Integer*/ e){ - // trim and slice. - - // take an index to start a string slice from and an end position - // and return a trimmed copy of that sub-string - return trim(query.slice(s, e)); + // one node shortcut => return the node itself + if(master.childNodes.length == 1){ + return master.removeChild(master.firstChild); // DOMNode } - // the overall data graph of the full query, as represented by queryPart objects - var queryParts = []; - - - // state keeping vars - var inBrackets = -1, inParens = -1, inMatchFor = -1, - inPseudo = -1, inClass = -1, inId = -1, inTag = -1, - lc = "", cc = "", pStart; - - // iteration vars - var x = 0, // index in the query - ql = query.length, - currentPart = null, // data structure representing the entire clause - _cp = null; // the current pseudo or attr matcher - - // several temporary variables are assigned to this structure during a - // potential sub-expression match: - // attr: - // a string representing the current full attribute match in a - // bracket expression - // type: - // if there's an operator in a bracket expression, this is - // used to keep track of it - // value: - // the internals of parenthetical expression for a pseudo. for - // :nth-child(2n+1), value might be "2n+1" + // return multiple nodes as a document fragment + df = doc.createDocumentFragment(); + while(fc = master.firstChild){ // intentional assignment + df.appendChild(fc); + } + return df; // DOMNode + }; - var endTag = function(){ - // called when the tokenizer hits the end of a particular tag name. - // Re-sets state variables for tag matching and sets up the matcher - // to handle the next type of token (tag or operator). - if(inTag >= 0){ - var tv = (inTag == x) ? null : ts(inTag, x); // .toLowerCase(); - currentPart[ (specials.indexOf(tv) < 0) ? "tag" : "oper" ] = tv; - inTag = -1; + exports.place = function place(/*DOMNode|String*/node, /*DOMNode|String*/refNode, /*String|Number?*/position){ + refNode = dom.byId(refNode); + if(typeof node == "string"){ // inline'd type check + node = /^\s*= 0){ - currentPart.id = ts(inId, x).replace(/\\/g, ""); - inId = -1; - } + exports.create = function create(/*DOMNode|String*/tag, /*Object*/attrs, /*DOMNode?|String?*/refNode, /*String?*/pos){ + var doc = win.doc; + if(refNode){ + refNode = dom.byId(refNode); + doc = refNode.ownerDocument; + } + if(typeof tag == "string"){ // inline'd type check + tag = doc.createElement(tag); } + if(attrs){ attr.set(tag, attrs); } + if(refNode){ exports.place(tag, refNode, pos); } + return tag; // DomNode + }; - var endClass = function(){ - // called when the tokenizer might be at the end of a class name - // match. CSS allows for multiple classes, so we augment the - // current item with another class in its list - if(inClass >= 0){ - currentPart.classes.push(ts(inClass+1, x).replace(/\\/g, "")); - inClass = -1; + exports.empty = + has("ie") ? function(node){ + node = dom.byId(node); + for(var c; c = node.lastChild;){ // intentional assignment + exports.destroy(c); } - } + } : + function(node){ + dom.byId(node).innerHTML = ""; + }; - var endAll = function(){ - // at the end of a simple fragment, so wall off the matches - endId(); endTag(); endClass(); + exports.destroy = function destroy(/*DOMNode|String*/node){ + node = dom.byId(node); + try{ + var doc = node.ownerDocument; + // cannot use _destroyContainer.ownerDocument since this can throw an exception on IE + if(!_destroyContainer || _destroyDoc != doc){ + _destroyContainer = doc.createElement("div"); + _destroyDoc = doc; + } + _destroyContainer.appendChild(node.parentNode ? node.parentNode.removeChild(node) : node); + // NOTE: see http://trac.dojotoolkit.org/ticket/2931. This may be a bug and not a feature + _destroyContainer.innerHTML = ""; + }catch(e){ + /* squelch */ } + }; +}); - var endPart = function(){ - endAll(); - if(inPseudo >= 0){ - currentPart.pseudos.push({ name: ts(inPseudo+1, x) }); - } - // hint to the selector engine to tell it whether or not it - // needs to do any iteration. Many simple selectors don't, and - // we can avoid significant construction-time work by advising - // the system to skip them - currentPart.loops = ( - currentPart.pseudos.length || - currentPart.attrs.length || - currentPart.classes.length ); +}, +'dojo/keys':function(){ +define("dojo/keys", ["./_base/kernel", "./_base/sniff"], function(dojo, has) { + // module: + // dojo/keys + // summary: + // key constants +// Constants + +// Public: client code should test +// keyCode against these named constants, as the +// actual codes can vary by browser. +return dojo.keys = { + // summary: + // Definitions for common key values + BACKSPACE: 8, + TAB: 9, + CLEAR: 12, + ENTER: 13, + SHIFT: 16, + CTRL: 17, + ALT: 18, + META: has("safari") ? 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/domReady':function(){ +define(['./has'], function(has){ + var global = this, + doc = document, + readyStates = { 'loaded': 1, 'complete': 1 }, + fixReadyState = typeof doc.readyState != "string", + ready = !!readyStates[doc.readyState]; + + // For FF <= 3.5 + if(fixReadyState){ doc.readyState = "loading"; } + + if(!ready){ + var readyQ = [], tests = [], + detectReady = function(evt){ + evt = evt || global.event; + if(ready || (evt.type == "readystatechange" && !readyStates[doc.readyState])){ return; } + ready = 1; + + // For FF <= 3.5 + if(fixReadyState){ doc.readyState = "complete"; } + + while(readyQ.length){ + (readyQ.shift())(); + } + }, + 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); }); + }; - currentPart.oquery = currentPart.query = ts(pStart, x); // save the full expression as a string + 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"); - // otag/tag are hints to suggest to the system whether or not - // it's an operator or a tag. We save a copy of otag since the - // tag name is cast to upper-case in regular HTML matches. The - // system has a global switch to figure out if the current - // expression needs to be case sensitive or not and it will use - // otag or tag accordingly - currentPart.otag = currentPart.tag = (currentPart["oper"]) ? null : (currentPart.tag || "*"); + 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(currentPart.tag){ - // if we're in a case-insensitive HTML doc, we likely want - // the toUpperCase when matching on element.tagName. If we - // do it here, we can skip the string op per node - // comparison - currentPart.tag = currentPart.tag.toUpperCase(); - } - - // add the part to the list - if(queryParts.length && (queryParts[queryParts.length-1].oper)){ - // operators are always infix, so we remove them from the - // list and attach them to the next match. The evaluator is - // responsible for sorting out how to handle them. - currentPart.infixOper = queryParts.pop(); - currentPart.query = currentPart.infixOper.query + " " + currentPart.query; - /* - console.debug( "swapping out the infix", - currentPart.infixOper, - "and attaching it to", - currentPart); - */ - } - queryParts.push(currentPart); - - currentPart = null; - } - - // iterate over the query, character by character, building up a - // list of query part objects - for(; lc=cc, cc=query.charAt(x), x < ql; x++){ - // cc: the current character in the match - // lc: the last character (if any) - - // someone is trying to escape something, so don't try to match any - // fragments. We assume we're inside a literal. - if(lc == "\\"){ continue; } - if(!currentPart){ // a part was just ended or none has yet been created - // NOTE: I hate all this alloc, but it's shorter than writing tons of if's - pStart = x; - // rules describe full CSS sub-expressions, like: - // #someId - // .className:first-child - // but not: - // thinger > div.howdy[type=thinger] - // the indidual components of the previous query would be - // split into 3 parts that would be represented a structure - // like: - // [ - // { - // query: "thinger", - // tag: "thinger", - // }, - // { - // query: "div.howdy[type=thinger]", - // classes: ["howdy"], - // infixOper: { - // query: ">", - // oper: ">", - // } - // }, - // ] - currentPart = { - query: null, // the full text of the part's rule - pseudos: [], // CSS supports multiple pseud-class matches in a single rule - attrs: [], // CSS supports multi-attribute match, so we need an array - classes: [], // class matches may be additive, e.g.: .thinger.blah.howdy - tag: null, // only one tag... - oper: null, // ...or operator per component. Note that these wind up being exclusive. - id: null, // the id component of a rule - getTag: function(){ - return (caseSensitive) ? this.otag : this.tag; + 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(); + } + } - // if we don't have a part, we assume we're going to start at - // the beginning of a match, which should be a tag name. This - // might fault a little later on, but we detect that and this - // iteration will still be fine. - inTag = x; - } - - if(inBrackets >= 0){ - // look for a the close first - if(cc == "]"){ // if we're in a [...] clause and we end, do assignment - if(!_cp.attr){ - // no attribute match was previously begun, so we - // assume this is an attribute existence match in the - // form of [someAttributeName] - _cp.attr = ts(inBrackets+1, x); - }else{ - // we had an attribute already, so we know that we're - // matching some sort of value, as in [attrName=howdy] - _cp.matchFor = ts((inMatchFor||inBrackets+1), x); - } - var cmf = _cp.matchFor; - if(cmf){ - // try to strip quotes from the matchFor value. We want - // [attrName=howdy] to match the same - // as [attrName = 'howdy' ] - if( (cmf.charAt(0) == '"') || (cmf.charAt(0) == "'") ){ - _cp.matchFor = cmf.slice(1, -1); - } - } - // end the attribute by adding it to the list of attributes. - currentPart.attrs.push(_cp); - _cp = null; // necessary? - inBrackets = inMatchFor = -1; - }else if(cc == "="){ - // if the last char was an operator prefix, make sure we - // record it along with the "=" operator. - var addToCc = ("|~^$*".indexOf(lc) >=0 ) ? lc : ""; - _cp.type = addToCc+cc; - _cp.attr = ts(inBrackets+1, x-addToCc.length); - inMatchFor = x+1; - } - // now look for other clause parts - }else if(inParens >= 0){ - // if we're in a parenthetical expression, we need to figure - // out if it's attached to a pseudo-selector rule like - // :nth-child(1) - if(cc == ")"){ - if(inPseudo >= 0){ - _cp.value = ts(inParens+1, x); - } - inPseudo = inParens = -1; - } - }else if(cc == "#"){ - // start of an ID match - endAll(); - inId = x+1; - }else if(cc == "."){ - // start of a class match - endAll(); - inClass = x; - }else if(cc == ":"){ - // start of a pseudo-selector match - endAll(); - inPseudo = x; - }else if(cc == "["){ - // start of an attribute match. - endAll(); - inBrackets = x; - // provide a new structure for the attribute match to fill-in - _cp = { - /*===== - attr: null, type: null, matchFor: null - =====*/ - }; - }else if(cc == "("){ - // we really only care if we've entered a parenthetical - // expression if we're already inside a pseudo-selector match - if(inPseudo >= 0){ - // provide a new structure for the pseudo match to fill-in - _cp = { - name: ts(inPseudo+1, x), - value: null - } - currentPart.pseudos.push(_cp); - } - inParens = x; - }else if( - (cc == " ") && - // if it's a space char and the last char is too, consume the - // current one without doing more work - (lc != cc) - ){ - endPart(); - } + function domReady(callback){ + if(ready){ + callback(1); + }else{ + readyQ.push(callback); } - return queryParts; + } + domReady.load = function(id, req, load){ + domReady(load); }; - - //////////////////////////////////////////////////////////////////////// - // DOM query infrastructure - //////////////////////////////////////////////////////////////////////// + return domReady; +}); - var agree = function(first, second){ - // the basic building block of the yes/no chaining system. agree(f1, - // f2) generates a new function which returns the boolean results of - // both of the passed functions to a single logical-anded result. If - // either are not passed, the other is used exclusively. - if(!first){ return second; } - if(!second){ return first; } +}, +'dojo/_base/lang':function(){ +define(["./kernel", "../has", "./sniff"], function(dojo, has){ + // module: + // dojo/_base/lang + // summary: + // This module defines Javascript language extensions. - return function(){ - return first.apply(window, arguments) && second.apply(window, arguments); + has.add("bug-for-in-skips-shadowed", function(){ + // if true, the for-in interator skips object properties that exist in Object's prototype (IE 6 - ?) + for(var i in {toString: 1}){ + return 0; } - }; + return 1; + }); - var getArr = function(i, arr){ - // helps us avoid array alloc when we don't need it - var r = arr||[]; // FIXME: should this be 'new d._NodeListCtor()' ? - if(i){ r.push(i); } - return r; - }; + var _extraNames = + has("bug-for-in-skips-shadowed") ? + "hasOwnProperty.valueOf.isPrototypeOf.propertyIsEnumerable.toLocaleString.toString.constructor".split(".") : [], - var _isElement = function(n){ return (1 == n.nodeType); }; + _extraLen = _extraNames.length, - // FIXME: need to coalesce _getAttr with defaultGetter - var blank = ""; - var _getAttr = function(elem, attr){ - if(!elem){ return blank; } - if(attr == "class"){ - return elem.className || blank; - } - if(attr == "for"){ - return elem.htmlFor || blank; - } - if(attr == "style"){ - return elem.style.cssText || blank; - } - return (caseSensitive ? elem.getAttribute(attr) : elem.getAttribute(attr, 2)) || blank; - }; + _mixin = function(dest, source, copyFunc){ + 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; + } + } - var attrs = { - "*=": function(attr, value){ - return function(elem){ - // E[foo*="bar"] - // an E element whose "foo" attribute value contains - // the substring "bar" - return (_getAttr(elem, attr).indexOf(value)>=0); + 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 }, - "^=": function(attr, value){ - // E[foo^="bar"] - // an E element whose "foo" attribute value begins exactly - // with the string "bar" - return function(elem){ - return (_getAttr(elem, attr).indexOf(value)==0); + + mixin = function(dest, sources){ + if(!dest){ dest = {}; } + for(var i = 1, l = arguments.length; i < l; i++){ + lang._mixin(dest, arguments[i]); } + return dest; // Object }, - "$=": function(attr, value){ - // E[foo$="bar"] - // an E element whose "foo" attribute value ends exactly - // with the string "bar" - var tval = " "+value; - return function(elem){ - var ea = " "+_getAttr(elem, attr); - return (ea.lastIndexOf(value)==(ea.length-value.length)); + + getProp = function(/*Array*/parts, /*Boolean*/create, /*Object*/context){ + var p, i = 0, dojoGlobal = dojo.global; + if(!context){ + if(!parts.length){ + return dojoGlobal; + }else{ + p = parts[i++]; + try{ + context = dojo.scopeMap[p] && dojo.scopeMap[p][1]; + }catch(e){} + context = context || (p in dojoGlobal ? dojoGlobal[p] : (create ? dojoGlobal[p] = {} : undefined)); + } + } + while(context && (p = parts[i++])){ + context = (p in context ? context[p] : (create ? context[p] = {} : undefined)); } + return context; // mixed }, - "~=": function(attr, value){ - // E[foo~="bar"] - // an E element whose "foo" attribute value is a list of - // space-separated values, one of which is exactly equal - // to "bar" - // return "[contains(concat(' ',@"+attr+",' '), ' "+ value +" ')]"; - var tval = " "+value+" "; - return function(elem){ - var ea = " "+_getAttr(elem, attr)+" "; - return (ea.indexOf(tval)>=0); - } + setObject = function(name, value, context){ + var parts = name.split("."), p = parts.pop(), obj = getProp(parts, true, context); + return obj && p ? (obj[p] = value) : undefined; // Object }, - "|=": function(attr, value){ - // E[hreflang|="en"] - // an E element whose "hreflang" attribute has a - // hyphen-separated list of values beginning (from the - // left) with "en" - var valueDash = " "+value+"-"; - return function(elem){ - var ea = " "+_getAttr(elem, attr); - return ( - (ea == value) || - (ea.indexOf(valueDash)==0) - ); - } + + getObject = function(name, create, context){ + return getProp(name.split("."), create, context); // Object }, - "=": function(attr, value){ - return function(elem){ - return (_getAttr(elem, attr) == value); - } - } - }; - // avoid testing for node type if we can. Defining this in the negative - // here to avoid negation in the fast path. - var _noNES = (typeof getDoc().firstChild.nextElementSibling == "undefined"); - var _ns = !_noNES ? "nextElementSibling" : "nextSibling"; - var _ps = !_noNES ? "previousElementSibling" : "previousSibling"; - var _simpleNodeTest = (_noNES ? _isElement : yesman); + exists = function(name, obj){ + return lang.getObject(name, false, obj) !== undefined; // Boolean + }, - var _lookLeft = function(node){ - // look left - while(node = node[_ps]){ - if(_simpleNodeTest(node)){ return false; } - } - return true; - }; + opts = Object.prototype.toString, - var _lookRight = function(node){ - // look right - while(node = node[_ns]){ - if(_simpleNodeTest(node)){ return false; } - } - return true; - }; + // Crockford (ish) functions + + isString = function(it){ + return (typeof it == "string" || it instanceof String); // Boolean + }, + + isArray = function(it){ + return it && (it instanceof Array || typeof it == "array"); // Boolean + }, + + isFunction = function(it){ + return opts.call(it) === "[object Function]"; + }, - var getNodeIndex = function(node){ - var root = node.parentNode; - var i = 0, - tret = root[childNodesName], - ci = (node["_i"]||-1), - cl = (root["_l"]||-1); + isObject = function(it){ + return it !== undefined && + (it === null || typeof it == "object" || lang.isArray(it) || lang.isFunction(it)); // Boolean + }, - if(!tret){ return -1; } - var l = tret.length; + isArrayLike = function(it){ + return it && it !== undefined && // 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)); + }, - // we calculate the parent length as a cheap way to invalidate the - // cache. It's not 100% accurate, but it's much more honest than what - // other libraries do - if( cl == l && ci >= 0 && cl >= 0 ){ - // if it's legit, tag and release - return ci; - } + isAlien = function(it){ + return it && !lang.isFunction(it) && /\{\s*\[native code\]\s*\}/.test(String(it)); // Boolean + }, - // else re-key things - root["_l"] = l; - ci = -1; - for(var te = root["firstElementChild"]||root["firstChild"]; te; te = te[_ns]){ - if(_simpleNodeTest(te)){ - te["_i"] = ++i; - if(node === te){ - // NOTE: - // shortcutting the return at this step in indexing works - // very well for benchmarking but we avoid it here since - // it leads to potential O(n^2) behavior in sequential - // getNodexIndex operations on a previously un-indexed - // parent. We may revisit this at a later time, but for - // now we just want to get the right answer more often - // than not. - ci = i; - } + extend = function(constructor, props){ + 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(['dojo.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 }, - "first-child": function(){ return _lookLeft; }, - "last-child": function(){ return _lookRight; }, - "only-child": function(name, condition){ - return function(node){ - if(!_lookLeft(node)){ return false; } - if(!_lookRight(node)){ return false; } - return true; - }; - }, - "empty": function(name, condition){ - return function(elem){ - // DomQuery and jQuery get this wrong, oddly enough. - // The CSS 3 selectors spec is pretty explicit about it, too. - var cn = elem.childNodes; - var cnl = elem.childNodes.length; - // if(!cnl){ return true; } - for(var x=cnl-1; x >= 0; x--){ - var nt = cn[x].nodeType; - if((nt === 1)||(nt == 3)){ return false; } + + 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 true; - } + return tmp; // Object + }; + })(), + + efficient = function(obj, offset, startWith){ + return (startWith||[]).concat(Array.prototype.slice.call(obj, offset||0)); }, - "contains": function(name, condition){ - var cz = condition.charAt(0); - if( cz == '"' || cz == "'" ){ //remove quote - condition = condition.slice(1, -1); - } - return function(elem){ - return (elem.innerHTML.indexOf(condition) >= 0); - } - }, - "not": function(name, condition){ - var p = getQueryParts(condition)[0]; - var ignores = { el: 1 }; - if(p.tag != "*"){ - ignores.tag = 1; - } - if(!p.classes.length){ - ignores.classes = 1; - } - var ntf = getSimpleFilterFunc(p, ignores); - return function(elem){ - return (!ntf(elem)); - } - }, - "nth-child": function(name, condition){ - var pi = parseInt; - // avoid re-defining function objects if we can - if(condition == "odd"){ - return isOdd; - }else if(condition == "even"){ - return isEven; - } - // FIXME: can we shorten this? - if(condition.indexOf("n") != -1){ - var tparts = condition.split("n", 2); - var pred = tparts[0] ? ((tparts[0] == '-') ? -1 : pi(tparts[0])) : 1; - var idx = tparts[1] ? pi(tparts[1]) : 0; - var lb = 0, ub = -1; - if(pred > 0){ - if(idx < 0){ - idx = (idx % pred) && (pred + (idx % pred)); - }else if(idx>0){ - if(idx >= pred){ - lb = idx - idx % pred; + + _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]); } - idx = idx % pred; + return arr; } - }else if(pred<0){ - pred *= -1; - // idx has to be greater than 0 when pred is negative; - // shall we throw an error here? - if(idx > 0){ - ub = idx; - idx = idx % pred; - } - } - if(pred > 0){ - return function(elem){ - var i = getNodeIndex(elem); - return (i>=lb) && (ub<0 || i<=ub) && ((i % pred) == idx); + return function(obj){ + return ((obj.item) ? slow : efficient).apply(this, arguments); + }; + })() : efficient, + + partial = function(/*Function|String*/method /*, ...*/){ + var arr = [ null ]; + return lang.hitch.apply(dojo, arr.concat(lang._toArray(arguments))); // Function + }, + + clone = function(/*anything*/ src){ + 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.push(clone(src[i])); } - }else{ - condition = idx; } + // 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() : {}; } - var ncount = pi(condition); - return function(elem){ - return (getNodeIndex(elem) == ncount); - } - } - }; + return lang._mixin(r, src, clone); + }, - var defaultGetter = (d.isIE < 9 || (dojo.isIE && dojo.isQuirks)) ? function(cond){ - var clc = cond.toLowerCase(); - if(clc == "class"){ cond = "className"; } - return function(elem){ - return (caseSensitive ? elem.getAttribute(cond) : elem[cond]||elem[clc]); - } - } : function(cond){ - return function(elem){ - return (elem && elem.getAttribute && elem.hasAttribute(cond)); - } - }; - var getSimpleFilterFunc = function(query, ignores){ - // generates a node tester function based on the passed query part. The - // query part is one of the structures generated by the query parser - // when it creates the query AST. The "ignores" object specifies which - // (if any) tests to skip, allowing the system to avoid duplicating - // work where it may have already been taken into account by other - // factors such as how the nodes to test were fetched in the first - // place - if(!query){ return yesman; } - ignores = ignores||{}; + trim = String.prototype.trim ? + function(str){ return str.trim(); } : + function(str){ return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); }, - var ff = null; - if(!("el" in ignores)){ - ff = agree(ff, _isElement); - } + _pattern = /\{([^\}]+)\}/g, - if(!("tag" in ignores)){ - if(query.tag != "*"){ - ff = agree(ff, function(elem){ - return (elem && (elem.tagName == query.getTag())); - }); - } - } + replace = function(tmpl, map, pattern){ + return tmpl.replace(pattern || _pattern, lang.isFunction(map) ? + map : function(_, k){ return getObject(k, false, map); }); + }, - if(!("classes" in ignores)){ - each(query.classes, function(cname, idx, arr){ - // get the class name - /* - var isWildcard = cname.charAt(cname.length-1) == "*"; - if(isWildcard){ - cname = cname.substr(0, cname.length-1); - } - // I dislike the regex thing, even if memoized in a cache, but it's VERY short - var re = new RegExp("(?:^|\\s)" + cname + (isWildcard ? ".*" : "") + "(?:\\s|$)"); - */ - var re = new RegExp("(?:^|\\s)" + cname + "(?:\\s|$)"); - ff = agree(ff, function(elem){ - return re.test(elem.className); - }); - ff.count = idx; - }); - } + lang = { + _extraNames:_extraNames, + _mixin:_mixin, + mixin:mixin, + setObject:setObject, + getObject:getObject, + exists:exists, + isString:isString, + isArray:isArray, + isFunction:isFunction, + isObject:isObject, + isArrayLike:isArrayLike, + isAlien:isAlien, + extend:extend, + _hitchArgs:_hitchArgs, + hitch:hitch, + delegate:delegate, + _toArray:_toArray, + partial:partial, + clone:clone, + trim:trim, + replace:replace + }; - if(!("pseudos" in ignores)){ - each(query.pseudos, function(pseudo){ - var pn = pseudo.name; - if(pseudos[pn]){ - ff = agree(ff, pseudos[pn](pn, pseudo.value)); - } - }); - } + 1 && mixin(dojo, lang); + return lang; - if(!("attrs" in ignores)){ - each(query.attrs, function(attr){ - var matcher; - var a = attr.attr; - // type, attr, matchFor - if(attr.type && attrs[attr.type]){ - matcher = attrs[attr.type](a, attr.matchFor); - }else if(a.length){ - matcher = defaultGetter(a); - } - if(matcher){ - ff = agree(ff, matcher); - } - }); - } + /*===== + dojo._extraNames + // summary: + // Array of strings. Lists property names that must be explicitly processed during for-in interation + // in environments that have has("bug-for-in-skips-shadowed") true. + =====*/ - if(!("id" in ignores)){ - if(query.id){ - ff = agree(ff, function(elem){ - return (!!elem && (elem.id == query.id)); - }); - } - } + /*===== + dojo._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. + } + =====*/ - if(!ff){ - if(!("default" in ignores)){ - ff = yesman; - } - } - return ff; - }; + /*===== + dojo.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: + // | dojo.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); + } + =====*/ - var _nextSibling = function(filterFunc){ - return function(node, ret, bag){ - while(node = node[_ns]){ - if(_noNES && (!_isElement(node))){ continue; } - if( - (!bag || _isUnique(node, bag)) && - filterFunc(node) - ){ - ret.push(node); - } - break; - } - return ret; - } - }; + /*===== + dojo.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 _nextSiblings = function(filterFunc){ - return function(root, ret, bag){ - var te = root[_ns]; - while(te){ - if(_simpleNodeTest(te)){ - if(bag && !_isUnique(te, bag)){ - break; - } - if(filterFunc(te)){ - ret.push(te); - } - } - te = te[_ns]; - } - return ret; - } - }; + /*===== + dojo.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. + } + =====*/ - // get an array of child *elements*, skipping text and comment nodes - var _childElements = function(filterFunc){ - filterFunc = filterFunc||yesman; - return function(root, ret, bag){ - // get an array of child elements, skipping text and comment nodes - var te, x = 0, tret = root[childNodesName]; - while(te = tret[x++]){ - if( - _simpleNodeTest(te) && - (!bag || _isUnique(te, bag)) && - (filterFunc(te, x)) - ){ - ret.push(te); - } - } - return ret; - }; - }; - - /* - // thanks, Dean! - var itemIsAfterRoot = d.isIE ? function(item, root){ - return (item.sourceIndex > root.sourceIndex); - } : function(item, root){ - return (item.compareDocumentPosition(root) == 2); - }; - */ + /*===== + dojo.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 + } + =====*/ - // test to see if node is below root - var _isDescendant = function(node, root){ - var pn = node.parentNode; - while(pn){ - if(pn == root){ - break; - } - pn = pn.parentNode; - } - return !!pn; - }; - - var _getElementsFuncCache = {}; - - var getElementsFunc = function(query){ - var retFunc = _getElementsFuncCache[query.query]; - // if we've got a cached dispatcher, just use that - if(retFunc){ return retFunc; } - // else, generate a new on - - // NOTE: - // this function returns a function that searches for nodes and - // filters them. The search may be specialized by infix operators - // (">", "~", or "+") else it will default to searching all - // descendants (the " " selector). Once a group of children is - // found, a test function is applied to weed out the ones we - // don't want. Many common cases can be fast-pathed. We spend a - // lot of cycles to create a dispatcher that doesn't do more work - // than necessary at any point since, unlike this function, the - // dispatchers will be called every time. The logic of generating - // efficient dispatchers looks like this in pseudo code: - // - // # if it's a purely descendant query (no ">", "+", or "~" modifiers) - // if infixOperator == " ": - // if only(id): - // return def(root): - // return d.byId(id, root); - // - // elif id: - // return def(root): - // return filter(d.byId(id, root)); - // - // elif cssClass && getElementsByClassName: - // return def(root): - // return filter(root.getElementsByClassName(cssClass)); - // - // elif only(tag): - // return def(root): - // return root.getElementsByTagName(tagName); - // - // else: - // # search by tag name, then filter - // return def(root): - // return filter(root.getElementsByTagName(tagName||"*")); - // - // elif infixOperator == ">": - // # search direct children - // return def(root): - // return filter(root.children); - // - // elif infixOperator == "+": - // # search next sibling - // return def(root): - // return filter(root.nextElementSibling); - // - // elif infixOperator == "~": - // # search rightward siblings - // return def(root): - // return filter(nextSiblings(root)); - - var io = query.infixOper; - var oper = (io ? io.oper : ""); - // the default filter func which tests for all conditions in the query - // part. This is potentially inefficient, so some optimized paths may - // re-define it to test fewer things. - var filterFunc = getSimpleFilterFunc(query, { el: 1 }); - var qt = query.tag; - var wildcardTag = ("*" == qt); - var ecs = getDoc()["getElementsByClassName"]; - - if(!oper){ - // if there's no infix operator, then it's a descendant query. ID - // and "elements by class name" variants can be accelerated so we - // call them out explicitly: - if(query.id){ - // testing shows that the overhead of yesman() is acceptable - // and can save us some bytes vs. re-defining the function - // everywhere. - filterFunc = (!query.loops && wildcardTag) ? - yesman : - getSimpleFilterFunc(query, { el: 1, id: 1 }); - - retFunc = function(root, arr){ - var te = d.byId(query.id, (root.ownerDocument||root)); - if(!te || !filterFunc(te)){ return; } - if(9 == root.nodeType){ // if root's a doc, we just return directly - return getArr(te, arr); - }else{ // otherwise check ancestry - if(_isDescendant(te, root)){ - return getArr(te, arr); - } - } - } - }else if( - ecs && - // isAlien check. Workaround for Prototype.js being totally evil/dumb. - /\{\s*\[native code\]\s*\}/.test(String(ecs)) && - query.classes.length && - !cssCaseBug - ){ - // it's a class-based query and we've got a fast way to run it. - - // ignore class and ID filters since we will have handled both - filterFunc = getSimpleFilterFunc(query, { el: 1, classes: 1, id: 1 }); - var classesString = query.classes.join(" "); - retFunc = function(root, arr, bag){ - var ret = getArr(0, arr), te, x=0; - var tret = root.getElementsByClassName(classesString); - while((te = tret[x++])){ - if(filterFunc(te, root) && _isUnique(te, bag)){ - ret.push(te); - } - } - return ret; - }; + /*===== + dojo.isString = function(it){ + // summary: + // Return true if it is a String + // it: anything + // Item to test. + } + =====*/ - }else if(!wildcardTag && !query.loops){ - // it's tag only. Fast-path it. - retFunc = function(root, arr, bag){ - var ret = getArr(0, arr), te, x=0; - var tret = root.getElementsByTagName(query.getTag()); - while((te = tret[x++])){ - if(_isUnique(te, bag)){ - ret.push(te); - } - } - return ret; - }; - }else{ - // the common case: - // a descendant selector without a fast path. By now it's got - // to have a tag selector, even if it's just "*" so we query - // by that and filter - filterFunc = getSimpleFilterFunc(query, { el: 1, tag: 1, id: 1 }); - retFunc = function(root, arr, bag){ - var ret = getArr(0, arr), te, x=0; - // we use getTag() to avoid case sensitivity issues - var tret = root.getElementsByTagName(query.getTag()); - while((te = tret[x++])){ - if(filterFunc(te, root) && _isUnique(te, bag)){ - ret.push(te); - } - } - return ret; - }; - } - }else{ - // the query is scoped in some way. Instead of querying by tag we - // use some other collection to find candidate nodes - var skipFilters = { el: 1 }; - if(wildcardTag){ - skipFilters.tag = 1; - } - filterFunc = getSimpleFilterFunc(query, skipFilters); - if("+" == oper){ - retFunc = _nextSibling(filterFunc); - }else if("~" == oper){ - retFunc = _nextSiblings(filterFunc); - }else if(">" == oper){ - retFunc = _childElements(filterFunc); - } - } - // cache it and return - return _getElementsFuncCache[query.query] = retFunc; - }; - - var filterDown = function(root, queryParts){ - // NOTE: - // this is the guts of the DOM query system. It takes a list of - // parsed query parts and a root and finds children which match - // the selector represented by the parts - var candidates = getArr(root), qp, x, te, qpl = queryParts.length, bag, ret; - - for(var i = 0; i < qpl; i++){ - ret = []; - qp = queryParts[i]; - x = candidates.length - 1; - if(x > 0){ - // if we have more than one root at this level, provide a new - // hash to use for checking group membership but tell the - // system not to post-filter us since we will already have been - // gauranteed to be unique - bag = {}; - ret.nozip = true; - } - var gef = getElementsFunc(qp); - for(var j = 0; (te = candidates[j]); j++){ - // for every root, get the elements that match the descendant - // selector, adding them to the "ret" array and filtering them - // via membership in this level's bag. If there are more query - // parts, then this level's return will be used as the next - // level's candidates - gef(te, ret, bag); - } - if(!ret.length){ break; } - candidates = ret; - } - return ret; - }; + /*===== + dojo.isArray = function(it){ + // summary: + // Return true if it is an Array. + // Does not work on Arrays created in other windows. + // it: anything + // Item to test. + } + =====*/ - //////////////////////////////////////////////////////////////////////// - // the query runner - //////////////////////////////////////////////////////////////////////// - - // these are the primary caches for full-query results. The query - // dispatcher functions are generated then stored here for hash lookup in - // the future - var _queryFuncCacheDOM = {}, - _queryFuncCacheQSA = {}; - - // this is the second level of spliting, from full-length queries (e.g., - // "div.foo .bar") into simple query expressions (e.g., ["div.foo", - // ".bar"]) - var getStepQueryFunc = function(query){ - var qparts = getQueryParts(trim(query)); - - // if it's trivial, avoid iteration and zipping costs - if(qparts.length == 1){ - // we optimize this case here to prevent dispatch further down the - // chain, potentially slowing things down. We could more elegantly - // handle this in filterDown(), but it's slower for simple things - // that need to be fast (e.g., "#someId"). - var tef = getElementsFunc(qparts[0]); - return function(root){ - var r = tef(root, new qlc()); - if(r){ r.nozip = true; } - return r; - } - } - - // otherwise, break it up and return a runner that iterates over the parts recursively - return function(root){ - return filterDown(root, qparts); - } - }; - - // NOTES: - // * we can't trust QSA for anything but document-rooted queries, so - // caching is split into DOM query evaluators and QSA query evaluators - // * caching query results is dirty and leak-prone (or, at a minimum, - // prone to unbounded growth). Other toolkits may go this route, but - // they totally destroy their own ability to manage their memory - // footprint. If we implement it, it should only ever be with a fixed - // total element reference # limit and an LRU-style algorithm since JS - // has no weakref support. Caching compiled query evaluators is also - // potentially problematic, but even on large documents the size of the - // query evaluators is often < 100 function objects per evaluator (and - // LRU can be applied if it's ever shown to be an issue). - // * since IE's QSA support is currently only for HTML documents and even - // then only in IE 8's "standards mode", we have to detect our dispatch - // route at query time and keep 2 separate caches. Ugg. - - // we need to determine if we think we can run a given query via - // querySelectorAll or if we'll need to fall back on DOM queries to get - // there. We need a lot of information about the environment and the query - // to make the determiniation (e.g. does it support QSA, does the query in - // question work in the native QSA impl, etc.). - var nua = navigator.userAgent; - // some versions of Safari provided QSA, but it was buggy and crash-prone. - // We need te detect the right "internal" webkit version to make this work. - var wk = "WebKit/"; - var is525 = ( - d.isWebKit && - (nua.indexOf(wk) > 0) && - (parseFloat(nua.split(wk)[1]) > 528) - ); + /*===== + dojo.isFunction = function(it){ + // summary: + // Return true if it is a Function + // it: anything + // Item to test. + } + =====*/ - // IE QSA queries may incorrectly include comment nodes, so we throw the - // zipping function into "remove" comments mode instead of the normal "skip - // it" which every other QSA-clued browser enjoys - var noZip = d.isIE ? "commentStrip" : "nozip"; + /*===== + dojo.isObject = function(it){ + // summary: + // Returns true if it is a JavaScript object (or an Array, a Function + // or null) + // it: anything + // Item to test. + } + =====*/ - var qsa = "querySelectorAll"; - var qsaAvail = ( - !!getDoc()[qsa] && - // see #5832 - (!d.isSafari || (d.isSafari > 3.1) || is525 ) - ); + /*===== + dojo.isArrayLike = function(it){ + // summary: + // similar to dojo.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 + // dojo.isArrayLike(), but will return false when passed to + // dojo.isArray(). + } + =====*/ - //Don't bother with n+3 type of matches, IE complains if we modify those. - var infixSpaceRe = /n\+\d|([^ ])?([>~+])([^ =])?/g; - var infixSpaceFunc = function(match, pre, ch, post) { - return ch ? (pre ? pre + " " : "") + ch + (post ? " " + post : "") : /*n+3*/ match; - }; - - var getQueryFunc = function(query, forceDOM){ - //Normalize query. The CSS3 selectors spec allows for omitting spaces around - //infix operators, >, ~ and + - //Do the work here since detection for spaces is used as a simple "not use QSA" - //test below. - query = query.replace(infixSpaceRe, infixSpaceFunc); - - if(qsaAvail){ - // if we've got a cached variant and we think we can do it, run it! - var qsaCached = _queryFuncCacheQSA[query]; - if(qsaCached && !forceDOM){ return qsaCached; } - } - - // else if we've got a DOM cached variant, assume that we already know - // all we need to and use it - var domCached = _queryFuncCacheDOM[query]; - if(domCached){ return domCached; } - - // TODO: - // today we're caching DOM and QSA branches separately so we - // recalc useQSA every time. If we had a way to tag root+query - // efficiently, we'd be in good shape to do a global cache. - - var qcz = query.charAt(0); - var nospace = (-1 == query.indexOf(" ")); - - // byId searches are wicked fast compared to QSA, even when filtering - // is required - if( (query.indexOf("#") >= 0) && (nospace) ){ - forceDOM = true; - } - - var useQSA = ( - qsaAvail && (!forceDOM) && - // as per CSS 3, we can't currently start w/ combinator: - // http://www.w3.org/TR/css3-selectors/#w3cselgrammar - (specials.indexOf(qcz) == -1) && - // IE's QSA impl sucks on pseudos - (!d.isIE || (query.indexOf(":") == -1)) && - - (!(cssCaseBug && (query.indexOf(".") >= 0))) && - - // FIXME: - // need to tighten up browser rules on ":contains" and "|=" to - // figure out which aren't good - // Latest webkit (around 531.21.8) does not seem to do well with :checked on option - // elements, even though according to spec, selected options should - // match :checked. So go nonQSA for it: - // http://bugs.dojotoolkit.org/ticket/5179 - (query.indexOf(":contains") == -1) && (query.indexOf(":checked") == -1) && - (query.indexOf("|=") == -1) // some browsers don't grok it - ); - - // TODO: - // if we've got a descendant query (e.g., "> .thinger" instead of - // just ".thinger") in a QSA-able doc, but are passed a child as a - // root, it should be possible to give the item a synthetic ID and - // trivially rewrite the query to the form "#synid > .thinger" to - // use the QSA branch - - - if(useQSA){ - var tq = (specials.indexOf(query.charAt(query.length-1)) >= 0) ? - (query + " *") : query; - return _queryFuncCacheQSA[query] = function(root){ - try{ - // the QSA system contains an egregious spec bug which - // limits us, effectively, to only running QSA queries over - // entire documents. See: - // http://ejohn.org/blog/thoughts-on-queryselectorall/ - // despite this, we can also handle QSA runs on simple - // selectors, but we don't want detection to be expensive - // so we're just checking for the presence of a space char - // right now. Not elegant, but it's cheaper than running - // the query parser when we might not need to - if(!((9 == root.nodeType) || nospace)){ throw ""; } - var r = root[qsa](tq); - // skip expensive duplication checks and just wrap in a NodeList - r[noZip] = true; - return r; - }catch(e){ - // else run the DOM branch on this query, ensuring that we - // default that way in the future - return getQueryFunc(query, true)(root); - } - } - }else{ - // DOM branch - var parts = query.split(/\s*,\s*/); - return _queryFuncCacheDOM[query] = ((parts.length < 2) ? - // if not a compound query (e.g., ".foo, .bar"), cache and return a dispatcher - getStepQueryFunc(query) : - // if it *is* a complex query, break it up into its - // constituent parts and return a dispatcher that will - // merge the parts when run - function(root){ - var pindex = 0, // avoid array alloc for every invocation - ret = [], - tp; - while((tp = parts[pindex++])){ - ret = ret.concat(getStepQueryFunc(tp)(root)); - } - return ret; - } - ); - } - }; + /*===== + dojo.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 + } + =====*/ - var _zipIdx = 0; + /*===== + dojo.extend = function(constructor, props){ + // summary: + // Adds all properties and methods of props to constructor's + // prototype, making them available to all instances created with + // constructor. + // constructor: Object + // Target constructor to extend. + // props: Object... + // One or more objects to mix into constructor.prototype + } + =====*/ - // NOTE: - // this function is Moo inspired, but our own impl to deal correctly - // with XML in IE - var _nodeUID = d.isIE ? function(node){ - if(caseSensitive){ - // XML docs don't have uniqueID on their nodes - return (node.getAttribute("_uid") || node.setAttribute("_uid", ++_zipIdx) || _zipIdx); + /*===== + dojo.hitch = function(scope, method){ + // summary: + // Returns a function that will only ever execute in the a given scope. + // This allows for easy use of object member functions + // in callbacks and other places in which the "this" keyword may + // otherwise not reference the expected scope. + // Any number of default positional arguments may be passed as parameters + // beyond "method". + // Each of these values will be used to "placehold" (similar to curry) + // for the hitched function. + // scope: Object + // The scope to use when method executes. If method is a string, + // scope is also the object containing method. + // method: Function|String... + // A function to be hitched to scope, or the name of the method in + // scope to be hitched. + // example: + // | dojo.hitch(foo, "bar")(); + // runs foo.bar() in the scope of foo + // example: + // | dojo.hitch(foo, myFunction); + // returns a function that runs myFunction in the scope of foo + // example: + // Expansion on the default positional arguments passed along from + // hitch. Passed args are mixed first, additional args after. + // | var foo = { bar: function(a, b, c){ console.log(a, b, c); } }; + // | var fn = dojo.hitch(foo, "bar", 1, 2); + // | fn(3); // logs "1, 2, 3" + // example: + // | var foo = { bar: 2 }; + // | dojo.hitch(foo, function(){ this.bar = 10; })(); + // execute an anonymous function in scope of foo + } + =====*/ - }else{ - return node.uniqueID; - } - } : - function(node){ - return (node._uid || (node._uid = ++_zipIdx)); - }; - - // determine if a node in is unique in a "bag". In this case we don't want - // to flatten a list of unique items, but rather just tell if the item in - // question is already in the bag. Normally we'd just use hash lookup to do - // this for us but IE's DOM is busted so we can't really count on that. On - // the upside, it gives us a built in unique ID function. - var _isUnique = function(node, bag){ - if(!bag){ return 1; } - var id = _nodeUID(node); - if(!bag[id]){ return bag[id] = 1; } - return 0; - }; + /*===== + dojo.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 implementaton 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 = dojo.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 + } + =====*/ - // attempt to efficiently determine if an item in a list is a dupe, - // returning a list of "uniques", hopefully in doucment order - var _zipIdxName = "_zipIdx"; - var _zip = function(arr){ - if(arr && arr.nozip){ - return (qlc._wrap) ? qlc._wrap(arr) : arr; - } - // var ret = new d._NodeListCtor(); - var ret = new qlc(); - if(!arr || !arr.length){ return ret; } - if(arr[0]){ - ret.push(arr[0]); - } - if(arr.length < 2){ return ret; } + /*===== + dojo.partial = function(method){ + // summary: + // similar to hitch() except that the scope object is left to be + // whatever the execution context eventually becomes. + // method: Function|String + // description: + // Calling dojo.partial is the functional equivalent of calling: + // | dojo.hitch(null, funcName, ...); + } + =====*/ - _zipIdx++; - - // we have to fork here for IE and XML docs because we can't set - // expandos on their nodes (apparently). *sigh* - if(d.isIE && caseSensitive){ - var szidx = _zipIdx+""; - arr[0].setAttribute(_zipIdxName, szidx); - for(var x = 1, te; te = arr[x]; x++){ - if(arr[x].getAttribute(_zipIdxName) != szidx){ - ret.push(te); - } - te.setAttribute(_zipIdxName, szidx); - } - }else if(d.isIE && arr.commentStrip){ - try{ - for(var x = 1, te; te = arr[x]; x++){ - if(_isElement(te)){ - ret.push(te); - } - } - }catch(e){ /* squelch */ } - }else{ - if(arr[0]){ arr[0][_zipIdxName] = _zipIdx; } - for(var x = 1, te; te = arr[x]; x++){ - if(arr[x][_zipIdxName] != _zipIdx){ - ret.push(te); - } - te[_zipIdxName] = _zipIdx; - } - } - return ret; - }; + /*===== + dojo.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 + // dojo.string.trim() + } + =====*/ + + /*===== + dojo.clone = function(src){ + // summary: + // Clones objects (including DOM nodes) and all children. + // Warning: do not clone cyclic structures. + // src: + // The object to clone + } + =====*/ - // the main executor - d.query = function(/*String*/ query, /*String|DOMNode?*/ root){ + /*===== + dojo._toArray = function(obj, offset, startWith){ // summary: - // Returns nodes which match the given CSS3 selector, searching the - // entire document by default but optionally taking a node to scope - // the search by. Returns an instance of dojo.NodeList. - // description: - // dojo.query() is the swiss army knife of DOM node manipulation in - // Dojo. Much like Prototype's "$$" (bling-bling) function or JQuery's - // "$" function, dojo.query provides robust, high-performance - // CSS-based node selector support with the option of scoping searches - // to a particular sub-tree of a document. - // - // Supported Selectors: - // -------------------- - // - // dojo.query() supports a rich set of CSS3 selectors, including: - // - // * class selectors (e.g., `.foo`) - // * node type selectors like `span` - // * ` ` descendant selectors - // * `>` child element selectors - // * `#foo` style ID selectors - // * `*` universal selector - // * `~`, the preceded-by sibling selector - // * `+`, the immediately preceded-by sibling selector - // * attribute queries: - // | * `[foo]` attribute presence selector - // | * `[foo='bar']` attribute value exact match - // | * `[foo~='bar']` attribute value list item match - // | * `[foo^='bar']` attribute start match - // | * `[foo$='bar']` attribute end match - // | * `[foo*='bar']` attribute substring match - // * `:first-child`, `:last-child`, and `:only-child` positional selectors - // * `:empty` content emtpy selector - // * `:checked` pseudo selector - // * `:nth-child(n)`, `:nth-child(2n+1)` style positional calculations - // * `:nth-child(even)`, `:nth-child(odd)` positional selectors - // * `:not(...)` negation pseudo selectors - // - // Any legal combination of these selectors will work with - // `dojo.query()`, including compound selectors ("," delimited). - // Very complex and useful searches can be constructed with this - // palette of selectors and when combined with functions for - // manipulation presented by dojo.NodeList, many types of DOM - // manipulation operations become very straightforward. - // - // Unsupported Selectors: - // ---------------------- - // - // While dojo.query handles many CSS3 selectors, some fall outside of - // what's reasonable for a programmatic node querying engine to - // handle. Currently unsupported selectors include: - // - // * namespace-differentiated selectors of any form - // * all `::` pseduo-element selectors - // * certain pseduo-selectors which don't get a lot of day-to-day use: - // | * `:root`, `:lang()`, `:target`, `:focus` - // * all visual and state selectors: - // | * `:root`, `:active`, `:hover`, `:visisted`, `:link`, - // `:enabled`, `:disabled` - // * `:*-of-type` pseudo selectors - // - // dojo.query and XML Documents: - // ----------------------------- - // - // `dojo.query` (as of dojo 1.2) supports searching XML documents - // in a case-sensitive manner. If an HTML document is served with - // a doctype that forces case-sensitivity (e.g., XHTML 1.1 - // Strict), dojo.query() will detect this and "do the right - // thing". Case sensitivity is dependent upon the document being - // searched and not the query used. It is therefore possible to - // use case-sensitive queries on strict sub-documents (iframes, - // etc.) or XML documents while still assuming case-insensitivity - // for a host/root document. - // - // Non-selector Queries: - // --------------------- - // - // If something other than a String is passed for the query, - // `dojo.query` will return a new `dojo.NodeList` instance - // constructed from that parameter alone and all further - // processing will stop. This means that if you have a reference - // to a node or NodeList, you can quickly construct a new NodeList - // from the original by calling `dojo.query(node)` or - // `dojo.query(list)`. - // - // query: - // The CSS3 expression to match against. For details on the syntax of - // CSS3 selectors, see - // root: - // A DOMNode (or node id) to scope the search from. Optional. - // returns: dojo.NodeList - // An instance of `dojo.NodeList`. Many methods are available on - // NodeLists for searching, iterating, manipulating, and handling - // events on the matched nodes in the returned list. - // example: - // search the entire document for elements with the class "foo": - // | dojo.query(".foo"); - // these elements will match: - // | - // | - // |

- // example: - // search the entire document for elements with the classes "foo" *and* "bar": - // | dojo.query(".foo.bar"); - // these elements will match: - // | - // while these will not: - // | - // |

- // example: - // find `` elements which are descendants of paragraphs and - // which have a "highlighted" class: - // | dojo.query("p span.highlighted"); - // the innermost span in this fragment matches: - // |

- // | ... - // | ... - // | - // |

+ // 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. + } + =====*/ + + /*===== + dojo.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: - // set an "odd" class on all odd table rows inside of the table - // `#tabular_data`, using the `>` (direct child) selector to avoid - // affecting any nested tables: - // | dojo.query("#tabular_data > tbody > tr:nth-child(odd)").addClass("odd"); + // | // uses a dictionary for substitutions: + // | dojo.replace("Hello, {name.first} {name.last} AKA {nick}!", + // | { + // | nick: "Bob", + // | name: { + // | first: "Robert", + // | middle: "X", + // | last: "Cringely" + // | } + // | }); + // | // returns: Hello, Robert Cringely AKA Bob! // example: - // remove all elements with the class "error" from the document - // and store them in a list: - // | var errors = dojo.query(".error").orphan(); + // | // uses an array for substitutions: + // | dojo.replace("Hello, {0} {2}!", + // | ["Robert", "X", "Cringely"]); + // | // returns: Hello, Robert Cringely! // example: - // add an onclick handler to every submit button in the document - // which causes the form to be sent via Ajax instead: - // | dojo.query("input[type='submit']").onclick(function(e){ - // | dojo.stopEvent(e); // prevent sending the form - // | var btn = e.target; - // | dojo.xhrPost({ - // | form: btn.form, - // | load: function(data){ - // | // replace the form with the response - // | var div = dojo.doc.createElement("div"); - // | dojo.place(div, btn.form, "after"); - // | div.innerHTML = data; - // | dojo.style(btn.form, "display", "none"); + // | // uses a function for substitutions: + // | function sum(a){ + // | var t = 0; + // | dojo.forEach(a, function(x){ t += x; }); + // | return t; + // | } + // | dojo.replace( + // | "{count} payments averaging {avg} USD per payment.", + // | dojo.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; + // | } // | } - // | }); - // | }); - - //Set list constructor to desired value. This can change - //between calls, so always re-assign here. - qlc = d._NodeListCtor; + // | ) + // | ); + // | // prints: 3 payments averaging 13 USD per payment. + // example: + // | // uses an alternative PHP-like pattern for substitutions: + // | dojo.replace("Hello, ${0} ${2}!", + // | ["Robert", "X", "Cringely"], /\$\{([^\}]+)\}/g); + // | // returns: Hello, Robert Cringely! + return ""; // String + } + =====*/ +}); - if(!query){ - return new qlc(); - } - if(query.constructor == qlc){ - return query; - } - if(typeof query != "string"){ // inline'd type check - return new qlc(query); // dojo.NodeList - } - if(typeof root == "string"){ // inline'd type check - root = d.byId(root); - if(!root){ return new qlc(); } +}, +'dojo/Evented':function(){ +define(["./aspect", "./on"], function(aspect, on){ + // summary: + // The export of this module is 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 emiting events: + // |define(["dojo/Evented"], function(Evented){ + // | var EventedWidget = dojo.declare([Evented, dijit._Widget], {...}); + // | widget = new EventedWidget(); + // | widget.on("open", function(event){ + // | ... do something with event + // | }); + // | + // | widget.emit("open", {name:"some event", ...}); + + "use strict"; + var after = aspect.after; + function Evented(){ + } + 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; +}); - root = root||getDoc(); - var od = root.ownerDocument||root.documentElement; - - // throw the big case sensitivity switch +}, +'dojo/mouse':function(){ +define(["./_base/kernel", "./on", "./has", "./dom", "./_base/window"], function(dojo, on, has, dom, win){ - // NOTE: - // Opera in XHTML mode doesn't detect case-sensitivity correctly - // and it's not clear that there's any way to test for it - caseSensitive = (root.contentType && root.contentType=="application/xml") || - (d.isOpera && (root.doctype || od.toString() == "[object XMLDocument]")) || - (!!od) && - (d.isIE ? od.xml : (root.xmlVersion||od.xmlVersion)); + /*===== + dojo.mouse = { + // summary: + // This module provide mouse event handling utility functions and exports + // mouseenter and mouseleave event emulation. + // enter: Synthetic Event + // This is an extension event for the mouseenter that IE provides, emulating the + // behavior on other browsers. + // leave: Synthetic Event + // This is an extension event for the mouseleave that IE provides, emulating the + // behavior on other browsers. + // isLeft: Function + // Test an event object (from a mousedown event) to see if the left button was pressed. + // isMiddle: Function + // Test an event object (from a mousedown event) to see if the middle button was pressed. + // isRight: Function + // Test an event object (from a mousedown event) to see if the right button was pressed. + // 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"); + // | }); + }; + ======*/ - // NOTE: - // adding "true" as the 2nd argument to getQueryFunc is useful for - // testing the DOM branch without worrying about the - // behavior/performance of the QSA branch. - var r = getQueryFunc(query)(root); + has.add("dom-quirks", win.doc && win.doc.compatMode == "BackCompat"); + has.add("events-mouseenter", win.doc && "onmouseenter" in win.doc.createElement("div")); - // FIXME: - // need to investigate this branch WRT #8074 and #8075 - if(r && r.nozip && !qlc._wrap){ - return r; - } - return _zip(r); // dojo.NodeList + var mouseButtons; + if(has("dom-quirks") || !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; - // FIXME: need to add infrastructure for post-filtering pseudos, ala :last - d.query.pseudos = pseudos; - - // function for filtering a NodeList based on a selector, optimized for simple selectors - d._filterQueryResult = function(/*NodeList*/ nodeList, /*String*/ filter, /*String|DOMNode?*/ root){ - var tmpNodeList = new d._NodeListCtor(), - parts = getQueryParts(filter), - filterFunc = - (parts.length == 1 && !/[^\w#\.]/.test(filter)) ? - getSimpleFilterFunc(parts[0]) : - function(node) { - return dojo.query(filter, root).indexOf(node) != -1; - }; - for(var x = 0, te; te = nodeList[x]; x++){ - if(filterFunc(te)){ tmpNodeList.push(te); } - } - return tmpNodeList; - } -};//end defineQuery +/*===== + 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, -var defineAcme= function(){ - // a self-sufficient query impl - acme = { - trim: function(/*String*/ str){ + isButton: function(e, button){ // summary: - // trims whitespaces from both sides of the string - str = str.replace(/^\s+/, ''); - for(var i = str.length - 1; i >= 0; i--){ - if(/\S/.test(str.charAt(i))){ - str = str.substring(0, i + 1); - break; - } - } - return str; // String + // 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 }, - forEach: function(/*String*/ arr, /*Function*/ callback, /*Object?*/ thisObject){ - // summary: - // an iterator function that passes items, indexes, - // and the array to a callback - if(!arr || !arr.length){ return; } - for(var i=0,l=arr.length; i= 0) ? tv: undefined; - acme.isKhtml = (dav.indexOf("Konqueror") >= 0) ? tv : undefined; - acme.isWebKit = parseFloat(dua.split("WebKit/")[1]) || undefined; - acme.isChrome = parseFloat(dua.split("Chrome/")[1]) || undefined; - var index = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0); - if(index && !acme.isChrome){ - acme.isSafari = parseFloat(dav.split("Version/")[1]); - if(!acme.isSafari || parseFloat(dav.substr(index + 7)) <= 419.3){ - acme.isSafari = 2; + function eventHandler(type, mustBubble){ + // emulation of mouseenter/leave with mouseover/out using descendant checking + var handler = function(node, listener){ + return on(node, type, function(evt){ + if(!dom.isDescendant(evt.relatedTarget, mustBubble ? evt.target : node)){ + return listener.call(this, evt); + } + }); + }; + if(!mustBubble){ + handler.bubble = eventHandler(type, true); } + return handler; } - if(document.all && !acme.isOpera){ - acme.isIE = parseFloat(dav.split("MSIE ")[1]) || undefined; - } - - Array._wrap = function(arr){ return arr; }; - return acme; -}; - - //prefers queryPortability, then acme, then dojo - if(this["dojo"]){ - dojo.provide("dojo._base.query"); - - - defineQuery(this["queryPortability"]||this["acme"]||dojo); - }else{ - defineQuery(this["queryPortability"]||this["acme"]||defineAcme()); - } - -})(); - -/* -*/ - -} - -if(!dojo._hasResource["dojo._base.xhr"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojo._base.xhr"] = true; -dojo.provide("dojo._base.xhr"); - - - - - - -(function(){ - var _d = dojo, cfg = _d.config; - - 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; - } + return { + enter: eventHandler("mouseover"), + leave: eventHandler("mouseout"), + isLeft: mouseButtons.isLeft, + isMiddle: mouseButtons.isMiddle, + isRight: mouseButtons.isRight + }; +}); + +}, +'dojo/topic':function(){ +define(["./Evented"], function(Evented){ + // summary: + // The export of this module is a pubsub hub + // You can also use listen function itself as a pub/sub hub: + // | topic.subscribe("some/topic", function(event){ + // | ... do something with event + // | }); + // | topic.publish("some/topic", {name:"some event", ...}); - var val = obj[name]; - if(typeof val == "string"){ // inline'd type check - obj[name] = [val, value]; - }else if(_d.isArray(val)){ - val.push(value); - }else{ - obj[name] = value; + var hub = new Evented; + return { + publish: function(topic, event){ + // summary: + // Publishes a message to a topic on the pub/sub hub. All arguments after + // the first will be passed to the subscribers, so any number of arguments + // can be provided (not just event). + // topic: String + // The name of the topic to publish to + // event: Object + // An event to distribute to the topic listeners + return hub.emit.apply(hub, arguments); + }, + subscribe: function(topic, listener){ + // summary: + // Subcribes to a topic on the pub/sub hub + // topic: String + // The topic to subscribe to + // listener: Function + // A function to call when a message is published to the given topic + return hub.on.apply(hub, arguments); } } - - dojo.fieldToObject = function(/*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. - var ret = null; - var item = _d.byId(inputNode); - if(item){ - var _in = item.name; - var type = (item.type||"").toLowerCase(); - if(_in && type && !item.disabled){ - if(type == "radio" || type == "checkbox"){ - if(item.checked){ ret = item.value; } - }else if(item.multiple){ - ret = []; - _d.query("option", item).forEach(function(opt){ - if(opt.selected){ - ret.push(opt.value); - } - }); - }else{ - ret = item.value; - } - } - } - return ret; // Object - }; - - dojo.formToObject = function(/*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. - // - // example: - // This form: - // |
- // | - // | - // | - // | - // |
- // - // yields this object structure as the result of a call to - // formToObject(): - // - // | { - // | blah: "blah", - // | multi: [ - // | "thud", - // | "thonk" - // | ] - // | }; +}); + +}, +'dojo/_base/xhr':function(){ +define([ + "./kernel", "./sniff", "require", "../io-query", "../dom", "../dom-form", "./Deferred", "./json", "./lang", "./array", "../on" +], function(dojo, has, require, ioq, dom, domForm, deferred, json, lang, array, on){ + // module: + // dojo/_base.xhr + // summary: + // This modules defines the dojo.xhr* API. - var ret = {}; - var exclude = "file|submit|image|reset|button|"; - _d.forEach(dojo.byId(formNode).elements, function(item){ - var _in = item.name; - var type = (item.type||"").toLowerCase(); - if(_in && type && exclude.indexOf(type) == -1 && !item.disabled){ - setValue(ret, _in, _d.fieldToObject(item)); - if(type == "image"){ - ret[_in+".x"] = ret[_in+".y"] = ret[_in].x = ret[_in].y = 0; - } - } - }); - return ret; // Object - }; + has.add("native-xhr", function() { + // if true, the environment has a native XHR implementation + return typeof XMLHttpRequest !== 'undefined'; + }); - dojo.objectToQuery = function(/*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; - var pairs = []; - var backstop = {}; - for(var name in map){ - var value = map[name]; - if(value != backstop[name]){ - var assign = enc(name) + "="; - if(_d.isArray(value)){ - for(var i=0; i < value.length; i++){ - pairs.push(assign + enc(value[i])); - } - }else{ - pairs.push(assign + enc(value)); - } + if(1 && require.getXhr){ + dojo._xhrObj = require.getXhr; + }else if (has("native-xhr")){ + dojo._xhrObj = function(){ + // summary: + // does the work of portably generating a new XMLHTTPRequest object. + try{ + return new XMLHttpRequest(); + }catch(e){ + throw new Error("XMLHTTP not available: "+e); } - } - return pairs.join("&"); // String - }; - - dojo.formToQuery = function(/*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 - return _d.objectToQuery(_d.formToObject(formNode)); // String - }; - - dojo.formToJson = function(/*DOMNode||String*/ formNode, /*Boolean?*/prettyPrint){ - // summary: - // Create a serialized JSON string from a form node or string - // ID identifying the form to serialize - return _d.toJson(_d.formToObject(formNode), prettyPrint); // String - }; - - dojo.queryToObject = function(/*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. - - // FIXME: should we grab the URL string if we're not passed one? - var ret = {}; - var qp = str.split("&"); - var dec = decodeURIComponent; - _d.forEach(qp, function(item){ - if(item.length){ - var parts = item.split("="); - var name = dec(parts.shift()); - var val = dec(parts.join("=")); - if(typeof ret[name] == "string"){ // inline'd type check - ret[name] = [ret[name]]; - } - - if(_d.isArray(ret[name])){ - ret[name].push(val); - }else{ - ret[name] = val; + }; + }else{ + // PROGIDs are in order of decreasing likelihood; this will change in time. + 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 } - }); - return ret; // Object - }; + } + dojo._xhrObj= function() { + return new ActiveXObject(progid); + }; + } + + var cfg = dojo.config; + + // mix in io-query and dom-form + dojo.objectToQuery = ioq.objectToQuery; + dojo.queryToObject = ioq.queryToObject; + dojo.fieldToObject = domForm.fieldToObject; + dojo.formToObject = domForm.toObject; + dojo.formToQuery = domForm.toQuery; + dojo.formToJson = domForm.toJson; // need to block async callbacks from snatching this thread as the result // of an async callback might call another sync XHR, this hangs khtml forever @@ -9927,7 +10350,7 @@ dojo.provide("dojo._base.xhr"); dojo._blockAsync = false; // MOW: remove dojo._contentHandlers alias in 2.0 - var handlers = _d._contentHandlers = dojo.contentHandlers = { + var handlers = dojo._contentHandlers = dojo.contentHandlers = { // summary: // A map of availble XHR transport handle types. Name matches the // `handleAs` attribute passed to XHR calls. @@ -9951,13 +10374,13 @@ dojo.provide("dojo._base.xhr"); // | load: function(data){ /* data is a toUpper version of foo.txt */ } // | }); - text: function(xhr){ + "text": function(xhr){ // summary: A contentHandler which simply returns the plaintext response data return xhr.responseText; }, - json: function(xhr){ + "json": function(xhr){ // summary: A contentHandler which returns a JavaScript object created from the response data - return _d.fromJson(xhr.responseText || null); + return json.fromJson(xhr.responseText || null); }, "json-comment-filtered": function(xhr){ // summary: A contentHandler which expects comment-filtered JSON. @@ -9986,33 +10409,36 @@ dojo.provide("dojo._base.xhr"); if(cStartIdx == -1 || cEndIdx == -1){ throw new Error("JSON was not comment filtered"); } - return _d.fromJson(value.substring(cStartIdx+2, cEndIdx)); + return json.fromJson(value.substring(cStartIdx+2, cEndIdx)); }, - javascript: function(xhr){ + "javascript": function(xhr){ // summary: A contentHandler which evaluates the response data, expecting it to be valid JavaScript // FIXME: try Moz and IE specific eval variants? - return _d.eval(xhr.responseText); + return dojo.eval(xhr.responseText); }, - xml: function(xhr){ + "xml": function(xhr){ // summary: A contentHandler returning an XML Document parsed from the response data var result = xhr.responseXML; - if(_d.isIE && (!result || !result.documentElement)){ - //WARNING: this branch used by the xml handling in dojo.io.iframe, - //so be sure to test dojo.io.iframe if making changes below. - var ms = function(n){ return "MSXML" + n + ".DOMDocument"; }; - var dp = ["Microsoft.XMLDOM", ms(6), ms(4), ms(3), ms(2)]; - _d.some(dp, function(p){ - try{ - var dom = new ActiveXObject(p); - dom.async = false; - dom.loadXML(xhr.responseText); - result = dom; - }catch(e){ return false; } - return true; - }); - } - return result; // DOMDocument + + if(has("ie")){ + if((!result || !result.documentElement)){ + //WARNING: this branch used by the xml handling in dojo.io.iframe, + //so be sure to test dojo.io.iframe if making changes below. + var ms = function(n){ return "MSXML" + n + ".DOMDocument"; }; + var dp = ["Microsoft.XMLDOM", ms(6), ms(4), ms(3), ms(2)]; + array.some(dp, function(p){ + try{ + var dom = new ActiveXObject(p); + dom.async = false; + dom.loadXML(xhr.responseText); + result = dom; + }catch(e){ return false; } + return true; + }); + } + } + return result; // DOMDocument }, "json-comment-optional": function(xhr){ // summary: A contentHandler which checks the presence of comment-filtered JSON and @@ -10048,15 +10474,15 @@ dojo.provide("dojo._base.xhr"); // Acceptable values depend on the type of IO // transport (see specific IO calls for more information). // rawBody: String? - // Sets the raw body for an HTTP request. If this is used, then the content - // property is ignored. This is mostly useful for HTTP methods that have - // a body to their requests, like PUT or POST. This property can be used instead - // of postData and putData for dojo.rawXhrPost and dojo.rawXhrPut respectively. + // Sets the raw body for an HTTP request. If this is used, then the content + // property is ignored. This is mostly useful for HTTP methods that have + // a body to their requests, like PUT or POST. This property can be used instead + // of postData and putData for dojo.rawXhrPost and dojo.rawXhrPut respectively. // ioPublish: Boolean? // Set this explicitly to false to prevent publishing of topics related to - // IO operations. Otherwise, if djConfig.ioPublish is set to true, topics - // will be published via dojo.publish for different phases of an IO operation. - // See dojo.__IoPublish for a list of topics that are published. + // IO operations. Otherwise, if djConfig.ioPublish is set to true, topics + // will be published via dojo.publish for different phases of an IO operation. + // See dojo.__IoPublish for a list of topics that are published. // load: Function? // This function will be // called on a successful HTTP response code. @@ -10064,7 +10490,7 @@ dojo.provide("dojo._base.xhr"); // This function will // be called when the request fails due to a network or server error, the url // is invalid, etc. It will also be called if the load or handle callback throws an - // exception, unless djConfig.debugAtAllCosts is true. This allows deployed applications + // exception, unless djConfig.debugAtAllCosts is true. This allows deployed applications // to continue to run even when a logic error happens in the callback, while making // it easier to troubleshoot while in debug mode. // handle: Function? @@ -10150,34 +10576,34 @@ dojo.provide("dojo._base.xhr"); /*===== dojo.__IoPublish = function(){ - // summary: - // This is a list of IO topics that can be published - // if djConfig.ioPublish is set to true. IO topics can be - // published for any Input/Output, network operation. So, - // dojo.xhr, dojo.io.script and dojo.io.iframe can all - // trigger these topics to be published. + // summary: + // This is a list of IO topics that can be published + // if djConfig.ioPublish is set to true. IO topics can be + // published for any Input/Output, network operation. So, + // dojo.xhr, dojo.io.script and dojo.io.iframe can all + // trigger these topics to be published. // start: String // "/dojo/io/start" is sent when there are no outstanding IO - // requests, and a new IO request is started. No arguments - // are passed with this topic. + // requests, and a new IO request is started. No arguments + // are passed with this topic. // send: String // "/dojo/io/send" is sent whenever a new IO request is started. - // It passes the dojo.Deferred for the request with the topic. + // It passes the dojo.Deferred for the request with the topic. // load: String // "/dojo/io/load" is sent whenever an IO request has loaded - // successfully. It passes the response and the dojo.Deferred - // for the request with the topic. + // successfully. It passes the response and the dojo.Deferred + // for the request with the topic. // error: String // "/dojo/io/error" is sent whenever an IO request has errored. - // It passes the error and the dojo.Deferred - // for the request with the topic. + // It passes the error and the dojo.Deferred + // for the request with the topic. // done: String // "/dojo/io/done" is sent whenever an IO request has completed, - // either by loading or by erroring. It passes the error and - // the dojo.Deferred for the request with the topic. + // either by loading or by erroring. It passes the error and + // the dojo.Deferred for the request with the topic. // stop: String // "/dojo/io/stop" is sent when all outstanding IO requests have - // finished. No arguments are passed with this topic. + // finished. No arguments are passed with this topic. this.start = "/dojo/io/start"; this.send = "/dojo/io/send"; this.load = "/dojo/io/load"; @@ -10216,17 +10642,17 @@ dojo.provide("dojo._base.xhr"); //Get values from form if requestd. var formObject = null; if(args.form){ - var form = _d.byId(args.form); + var form = dom.byId(args.form); //IE requires going through getAttributeNode instead of just getAttribute in some form cases, - //so use it for all. See #2844 + //so use it for all. See #2844 var actnNode = form.getAttributeNode("action"); ioArgs.url = ioArgs.url || (actnNode ? actnNode.value : null); - formObject = _d.formToObject(form); + formObject = domForm.toObject(form); } // set up the query params var miArgs = [{}]; - + if(formObject){ // potentially over-ride url-provided params w/ form values miArgs.push(formObject); @@ -10238,11 +10664,11 @@ dojo.provide("dojo._base.xhr"); if(args.preventCache){ miArgs.push({"dojo.preventCache": new Date().valueOf()}); } - ioArgs.query = _d.objectToQuery(_d.mixin.apply(null, miArgs)); - + ioArgs.query = ioq.objectToQuery(lang.mixin.apply(null, miArgs)); + // .. and the real work of getting the deferred in order, etc. ioArgs.handleAs = args.handleAs || "text"; - var d = new _d.Deferred(canceller); + var d = new deferred(canceller); d.addCallbacks(okHandler, function(error){ return errHandler(error, d); }); @@ -10252,44 +10678,44 @@ dojo.provide("dojo._base.xhr"); //The callbacks will get the deferred result value as the //first argument and the ioArgs object as the second argument. var ld = args.load; - if(ld && _d.isFunction(ld)){ + if(ld && lang.isFunction(ld)){ d.addCallback(function(value){ return ld.call(args, value, ioArgs); }); } var err = args.error; - if(err && _d.isFunction(err)){ + if(err && lang.isFunction(err)){ d.addErrback(function(value){ return err.call(args, value, ioArgs); }); } var handle = args.handle; - if(handle && _d.isFunction(handle)){ + if(handle && lang.isFunction(handle)){ d.addBoth(function(value){ return handle.call(args, value, ioArgs); }); } //Plug in topic publishing, if dojo.publish is loaded. - if(cfg.ioPublish && _d.publish && ioArgs.args.ioPublish !== false){ + if(cfg.ioPublish && dojo.publish && ioArgs.args.ioPublish !== false){ d.addCallbacks( function(res){ - _d.publish("/dojo/io/load", [d, res]); + dojo.publish("/dojo/io/load", [d, res]); return res; }, function(res){ - _d.publish("/dojo/io/error", [d, res]); + dojo.publish("/dojo/io/error", [d, res]); return res; } ); d.addBoth(function(res){ - _d.publish("/dojo/io/done", [d, res]); + dojo.publish("/dojo/io/done", [d, res]); return res; }); } d.ioArgs = ioArgs; - + // FIXME: need to wire up the xhr object's abort method to something // analagous in the Deferred return d; @@ -10297,7 +10723,7 @@ dojo.provide("dojo._base.xhr"); var _deferredCancel = function(/*Deferred*/dfd){ // summary: canceller function for dojo._ioSetArgs call. - + dfd.canceled = true; var xhr = dfd.ioArgs.xhr; var _at = typeof xhr.abort; @@ -10330,8 +10756,8 @@ dojo.provide("dojo._base.xhr"); // something fierece if we don't use unified loops. var _inFlightIntvl = null; var _inFlight = []; - - + + //Use a separate count for knowing if we are starting/stopping io calls. //Cannot use _inFlight.length since it can change at a different time than //when we want to do this kind of test. We only want to decrement the count @@ -10341,8 +10767,8 @@ dojo.provide("dojo._base.xhr"); var _checkPubCount = function(dfd){ if(_pubCount <= 0){ _pubCount = 0; - if(cfg.ioPublish && _d.publish && (!dfd || dfd && dfd.ioArgs.args.ioPublish !== false)){ - _d.publish("/dojo/io/stop"); + if(cfg.ioPublish && dojo.publish && (!dfd || dfd && dfd.ioArgs.args.ioPublish !== false)){ + dojo.publish("/dojo/io/stop"); } } }; @@ -10351,12 +10777,12 @@ dojo.provide("dojo._base.xhr"); //summary: // internal method that checks each inflight XMLHttpRequest to see // if it has completed or if the timeout situation applies. - + var now = (new Date()).getTime(); // make sure sync calls stay thread safe, if this callback is called // during a sync call and this results in another sync call before the // first sync call ends the browser hangs - if(!_d._blockAsync){ + if(!dojo._blockAsync){ // we need manual loop because we often modify _inFlight (and therefore 'i') while iterating // note: the second clause is an assigment on purpose, lint may complain for(var i = 0, tif; i < _inFlight.length && (tif = _inFlight[i]); i++){ @@ -10399,7 +10825,6 @@ dojo.provide("dojo._base.xhr"); if(!_inFlight.length){ clearInterval(_inFlightIntvl); _inFlightIntvl = null; - return; } }; @@ -10407,7 +10832,7 @@ dojo.provide("dojo._base.xhr"); //summary: Cancels all pending IO requests, regardless of IO type //(xhr, script, iframe). try{ - _d.forEach(_inFlight, function(i){ + array.forEach(_inFlight, function(i){ try{ i.dfd.cancel(); }catch(e){/*squelch*/} @@ -10417,28 +10842,28 @@ dojo.provide("dojo._base.xhr"); //Automatically call cancel all io calls on unload //in IE for trac issue #2357. - if(_d.isIE){ - _d.addOnWindowUnload(_d._ioCancelAll); + if(has("ie")){ + on(window, "unload", dojo._ioCancelAll); } - - _d._ioNotifyStart = function(/*Deferred*/dfd){ + + dojo._ioNotifyStart = function(/*Deferred*/dfd){ // summary: - // If dojo.publish is available, publish topics - // about the start of a request queue and/or the - // the beginning of request. + // If dojo.publish is available, publish topics + // about the start of a request queue and/or the + // the beginning of request. // description: - // Used by IO transports. An IO transport should - // call this method before making the network connection. - if(cfg.ioPublish && _d.publish && dfd.ioArgs.args.ioPublish !== false){ + // Used by IO transports. An IO transport should + // call this method before making the network connection. + if(cfg.ioPublish && dojo.publish && dfd.ioArgs.args.ioPublish !== false){ if(!_pubCount){ - _d.publish("/dojo/io/start"); + dojo.publish("/dojo/io/start"); } _pubCount += 1; - _d.publish("/dojo/io/send", [dfd]); + dojo.publish("/dojo/io/send", [dfd]); } }; - _d._ioWatch = function(dfd, validCheck, ioCheck, resHandle){ + dojo._ioWatch = function(dfd, validCheck, ioCheck, resHandle){ // summary: // Watches the io request represented by dfd to see if it completes. // dfd: Deferred @@ -10456,7 +10881,7 @@ dojo.provide("dojo._base.xhr"); if(args.timeout){ dfd.startTime = (new Date()).getTime(); } - + _inFlight.push({dfd: dfd, validCheck: validCheck, ioCheck: ioCheck, resHandle: resHandle}); if(!_inFlightIntvl){ _inFlightIntvl = setInterval(_watchInFlight, 50); @@ -10481,12 +10906,13 @@ dojo.provide("dojo._base.xhr"); }; var _resHandle = function(/*Deferred*/dfd){ var xhr = dfd.ioArgs.xhr; - if(_d._isDocumentOk(xhr)){ + if(dojo._isDocumentOk(xhr)){ dfd.callback(dfd); }else{ var err = new Error("Unable to load " + dfd.ioArgs.url + " status:" + xhr.status); err.status = xhr.status; err.responseText = xhr.responseText; + err.xhr = xhr; dfd.errback(err); } }; @@ -10518,6 +10944,10 @@ dojo.provide("dojo._base.xhr"); // false is default. Indicates whether a request should be // allowed to fail (and therefore no console error message in // the event of a failure) + // contentType: String|Boolean + // "application/x-www-form-urlencoded" is default. Set to false to + // prevent a Content-Type header from being sent, or to a string + // to send a different Content-Type. this.handleAs = handleAs; this.sync = sync; this.headers = headers; @@ -10535,17 +10965,17 @@ dojo.provide("dojo._base.xhr"); // for those HTTP methods. There are also methods for "raw" PUT and POST methods // via dojo.rawXhrPut() and dojo.rawXhrPost() respectively. // method: - // HTTP method to be used, such as GET, POST, PUT, DELETE. Should be uppercase. + // HTTP method to be used, such as GET, POST, PUT, DELETE. Should be uppercase. // hasBody: // If the request has an HTTP body, then pass true for hasBody. //Make the Deferred object for this xhr request. - var dfd = _d._ioSetArgs(args, _deferredCancel, _deferredOk, _deferError); + var dfd = dojo._ioSetArgs(args, _deferredCancel, _deferredOk, _deferError); var ioArgs = dfd.ioArgs; //Pass the args to _xhrObj, to allow alternate XHR calls based specific calls, like //the one used for iframe proxies. - var xhr = ioArgs.xhr = _d._xhrObj(ioArgs.args); + var xhr = ioArgs.xhr = dojo._xhrObj(ioArgs.args); //If XHR factory fails, cancel the deferred. if(!xhr){ dfd.cancel(); @@ -10562,7 +10992,7 @@ dojo.provide("dojo._base.xhr"); }else if((arguments.length > 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. - _d._ioAddQueryToUrl(ioArgs); + dojo._ioAddQueryToUrl(ioArgs); } // IE 6 is a steaming pile. It won't let you call apply() on the native function (xhr.open). @@ -10580,12 +11010,14 @@ dojo.provide("dojo._base.xhr"); } } // FIXME: is this appropriate for all content types? - xhr.setRequestHeader("Content-Type", args.contentType || _defaultContentType); + if(args.contentType !== false){ + xhr.setRequestHeader("Content-Type", args.contentType || _defaultContentType); + } if(!args.headers || !("X-Requested-With" in args.headers)){ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); } // FIXME: set other headers here! - _d._ioNotifyStart(dfd); + dojo._ioNotifyStart(dfd); if(dojo.config.debugAtAllCosts){ xhr.send(ioArgs.query); }else{ @@ -10596,768 +11028,3152 @@ dojo.provide("dojo._base.xhr"); dfd.cancel(); } } - _d._ioWatch(dfd, _validCheck, _ioCheck, _resHandle); - xhr = null; - return dfd; // dojo.Deferred - }; + dojo._ioWatch(dfd, _validCheck, _ioCheck, _resHandle); + xhr = null; + return dfd; // dojo.Deferred + }; + + dojo.xhrGet = function(/*dojo.__XhrArgs*/ args){ + // summary: + // Sends an HTTP GET request to the server. + return dojo.xhr("GET", args); // dojo.Deferred + }; + + dojo.rawXhrPost = dojo.xhrPost = function(/*dojo.__XhrArgs*/ args){ + // summary: + // Sends an HTTP POST request to the server. In addtion 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.Deferred + }; + + dojo.rawXhrPut = dojo.xhrPut = function(/*dojo.__XhrArgs*/ args){ + // summary: + // Sends an HTTP PUT request to the server. In addtion 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.Deferred + }; + + dojo.xhrDelete = function(/*dojo.__XhrArgs*/ args){ + // summary: + // Sends an HTTP DELETE request to the server. + return dojo.xhr("DELETE", args); //dojo.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(http){ + var stat = http.status || 0; + stat = + (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 + return stat; // Boolean + }; + + 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/unload':function(){ +define(["./kernel", "./connect"], function(dojo, connect) { + // module: + // dojo/unload + // summary: + // This module contains the document and window unload detection API. + + var win = window; + + /*===== + 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 + // dojo.addOnWindowUnload. This behavior started in Dojo 1.3. + // Previous versions always triggered dojo.windowUnloaded. See + // dojo.addOnWindowUnload for more info. + }; + =====*/ + + dojo.addOnWindowUnload = function(/*Object?|Function?*/obj, /*String|Function?*/functionName){ + // summary: + // registers a function to be triggered when window.onunload + // fires. + // 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 + // destory "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 + // dojo.addOnUnload() if you need to modify the DOM or do + // heavy JavaScript work since it fires at the eqivalent of + // the page's "onbeforeunload" event. + // example: + // | dojo.addOnWindowUnload(functionPointer) + // | dojo.addOnWindowUnload(object, "functionName"); + // | dojo.addOnWindowUnload(object, function(){ /* ... */}); + + if (!dojo.windowUnloaded) { + connect.connect(win, "unload", (dojo.windowUnloaded= function(){})); + } + connect.connect(win, "unload", obj, functionName); + }; + + dojo.addOnUnload = function(/*Object?|Function?*/obj, /*String|Function?*/functionName){ + // summary: + // registers a function to be triggered when the page unloads. + // description: + // The first time that addOnUnload is called Dojo will + // register a page listener to trigger your unload handler + // with. + // + // In a browser enviroment, 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: + // | dojo.addOnUnload(functionPointer) + // | dojo.addOnUnload(object, "functionName") + // | dojo.addOnUnload(object, function(){ /* ... */}); + + connect.connect(win, "beforeunload", obj, functionName); + }; + + return { + addOnWindowUnload: dojo.addOnWindowUnload, + addOnUnload: dojo.addOnUnload + }; +}); + +}, +'dojo/_base/NodeList':function(){ +define(["./kernel", "../query", "./array", "./html", "../NodeList-dom"], function(dojo, query, array){ + // module: + // dojo/_base/NodeList + // summary: + // This module defines dojo.NodeList. + +var NodeList = query.NodeList; + + /*===== + dojo.extend(dojo.NodeList, { + connect: function(methodName, objOrFunc, funcName){ + // summary: + // attach event handlers to every item of the NodeList. Uses dojo.connect() + // so event properties are normalized + // methodName: String + // the name of the method to attach to. For DOM events, this should be + // the lower-case name of the event + // objOrFunc: Object|Function|String + // if 2 arguments are passed (methodName, objOrFunc), objOrFunc should + // reference a function or be the name of the function in the global + // namespace to attach. If 3 arguments are provided + // (methodName, objOrFunc, funcName), objOrFunc must be the scope to + // locate the bound function in + // funcName: String? + // optional. A string naming the function in objOrFunc to bind to the + // event. May also be a function reference. + // example: + // add an onclick handler to every button on the page + // | dojo.query("div:nth-child(odd)").connect("onclick", function(e){ + // | console.log("clicked!"); + // | }); + // example: + // attach foo.bar() to every odd div's onmouseover + // | dojo.query("div:nth-child(odd)").connect("onmouseover", foo, "bar"); + }, + coords: function(){ + // summary: + // Deprecated: Use position() for border-box x/y/w/h + // or marginBox() for margin-box w/h/l/t. + // Returns the box objects of all elements in a node list as + // an Array (*not* a NodeList). Acts like `dojo.coords`, though assumes + // the node passed is each node in this list. + + return dojo.map(this, dojo.coords); // Array + } + }); + + var NodeList = dojo.NodeList; + =====*/ + var nlp = NodeList.prototype; + + // don't bind early to dojo.connect since we no longer explicitly depend on it + nlp.connect = NodeList._adaptAsForEach(function(){ + return dojo.connect.apply(this, arguments); + }); + nlp.coords = NodeList._adaptAsMap(dojo.coords); + + NodeList.events = [ + // summary: + // list of all DOM events used in NodeList + "blur", "focus", "change", "click", "error", "keydown", "keypress", + "keyup", "load", "mousedown", "mouseenter", "mouseleave", "mousemove", + "mouseout", "mouseover", "mouseup", "submit" + ]; + + // FIXME: pseudo-doc the above automatically generated on-event functions + + // syntactic sugar for DOM events + array.forEach(NodeList.events, function(evt){ + var _oe = "on" + evt; + nlp[_oe] = function(a, b){ + return this.connect(_oe, a, b); + }; + // FIXME: should these events trigger publishes? + /* + return (a ? this.connect(_oe, a, b) : + this.forEach(function(n){ + // FIXME: + // listeners get buried by + // addEventListener and can't be dug back + // out to be triggered externally. + // see: + // http://developer.mozilla.org/en/docs/DOM:element + + console.log(n, evt, _oe); + + // FIXME: need synthetic event support! + var _e = { target: n, faux: true, type: evt }; + // dojo._event_listener._synthesizeEvent({}, { target: n, faux: true, type: evt }); + try{ n[evt](_e); }catch(e){ console.log(e); } + try{ n[_oe](_e); }catch(e){ console.log(e); } + }) + ); + */ + } + ); + + dojo.NodeList = NodeList; + return dojo.NodeList; +}); + +}, +'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 `dojo.Color` object + // and creates a new Color instance to work from. + // + // example: + // Work with a Color instance: + // | var c = new dojo.Color(); + // | c.setColor([0,0,0]); // black + // | var hex = c.toHex(); // #000000 + // + // example: + // Work with a node's color: + // | var color = dojo.style("someNode", "backgroundColor"); + // | var n = new dojo.Color(color); + // | // adjust the color some + // | n.r *= .5; + // | console.log(n.toString()); // rgb(128, 255, 255); + if(color){ this.setColor(color); } + }; + + /*===== + lang.mixin(dojo.Color,{ + named:{ + // summary: Dictionary list of all CSS named colors, by name. Values are 3-item arrays with corresponding RG and B values. + } + }); + =====*/ + + // FIXME: + // there's got to be a more space-efficient way to encode or discover + // these!! Use hex? + Color.named = { + "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 `dojo.Color` object + // and sets this color instance to that value. + // + // example: + // | var c = new dojo.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; // dojo.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; // dojo.Color + }, + toRgb: function(){ + // summary: + // Returns 3 component array of rgb values + // example: + // | var c = new dojo.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: + // | console.log(new dojo.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: + // | var c = new dojo.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 + } + }); - dojo.xhrGet = function(/*dojo.__XhrArgs*/ args){ - // summary: - // Sends an HTTP GET request to the server. - return _d.xhr("GET", args); // dojo.Deferred + Color.blendColors = dojo.blendColors = function( + /*dojo.Color*/ start, + /*dojo.Color*/ end, + /*Number*/ weight, + /*dojo.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 dojo.Color object for the result + var t = obj || new Color(); + ArrayUtil.forEach(["r", "g", "b", "a"], function(x){ + t[x] = start[x] + (end[x] - start[x]) * weight; + if(x != "a"){ t[x] = Math.round(t[x]); } + }); + return t.sanitize(); // dojo.Color }; - dojo.rawXhrPost = dojo.xhrPost = function(/*dojo.__XhrArgs*/ args){ - // summary: - // Sends an HTTP POST request to the server. In addtion 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 _d.xhr("POST", args, true); // dojo.Deferred + Color.fromRgb = dojo.colorFromRgb = function(/*String*/ color, /*dojo.Color?*/ obj){ + // summary: + // Returns a `dojo.Color` instance from a string of the form + // "rgb(...)" or "rgba(...)". Optionally accepts a `dojo.Color` + // object to update with the parsed value and return instead of + // creating a new object. + // returns: + // A dojo.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); // dojo.Color }; - dojo.rawXhrPut = dojo.xhrPut = function(/*dojo.__XhrArgs*/ args){ - // summary: - // Sends an HTTP PUT request to the server. In addtion 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 _d.xhr("PUT", args, true); // dojo.Deferred + Color.fromHex = dojo.colorFromHex = function(/*String*/ color, /*dojo.Color?*/ obj){ + // summary: + // Converts a hex string with a '#' prefix to a color object. + // Supports 12-bit #rgb shorthand. Optionally accepts a + // `dojo.Color` object to update with the parsed value. + // + // returns: + // A dojo.Color object. If obj is passed, it will be the return value. + // + // example: + // | var thing = dojo.colorFromHex("#ededed"); // grey, longhand + // + // example: + // | var thing = dojo.colorFromHex("#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; // dojo.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; // dojo.Color }; - dojo.xhrDelete = function(/*dojo.__XhrArgs*/ args){ - // summary: - // Sends an HTTP DELETE request to the server. - return _d.xhr("DELETE", args); //dojo.Deferred + Color.fromArray = dojo.colorFromArray = function(/*Array*/ a, /*dojo.Color?*/ obj){ + // summary: + // Builds a `dojo.Color` from a 3 or 4 element array, mapping each + // element in sequence to the rgb(a) values of the color. + // example: + // | var myColor = dojo.colorFromArray([237,237,237,0.5]); // grey, 50% alpha + // returns: + // A dojo.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(); // dojo.Color }; - /* - 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"); + Color.fromString = dojo.colorFromString = function(/*String*/ str, /*dojo.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 dojo.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); // dojo.Color + }; + + return Color; +}); + +}, +'dojo/selector/_loader':function(){ +define(["../has", "require"], + function(has, require){ +// summary: +// This module handles loading the appropriate selector engine for the given browser +"use strict"; +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 { + load: function(id, parentRequire, loaded, config){ + 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); + }); } - */ -})(); - -} - -if(!dojo._hasResource["dojo._base.fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojo._base.fx"] = true; -dojo.provide("dojo._base.fx"); - - - - - - -/* - Animation loosely package based on Dan Pupius' work, contributed under CLA: - http://pupius.co.uk/js/Toolkit.Drawing.js -*/ -(function(){ - var d = dojo; - var _mixin = d._mixin; +}; +}); - dojo._Line = function(/*int*/ start, /*int*/ end){ - // summary: - // dojo._Line is the object used to generate values from a start value - // to an end value - // start: int - // Beginning value for range - // end: int - // Ending value for range - this.start = start; - this.end = end; +}, +'dojo/on':function(){ +define(["./has!dom-addeventlistener?:./aspect", "./_base/kernel", "./has"], function(aspect, dojo, has){ + // summary: + // The export of this module is 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(listen){ + // | 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(listen, 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. + + "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? + } + var on = function(target, type, listener, dontFix){ + if(target.on){ + // delegate to the target's on() method, so it can handle it's own listening if it wants + 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){ + if(type.call){ + // event handler function + // on(node, dojo.touch.press, touchListener); + return type.call(matchesTarget, target, listener); + } + + if(type.indexOf(",") > -1){ + // we allow comma delimited event names, so you can register for multiple events at once + var events = type.split(/\s*,\s*/); + var handles = []; + var i = 0; + var eventName; + while(eventName = events[i++]){ + handles.push(addListener(target, eventName, listener, 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); + } + } + // 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; + target.addEventListener(capture ? captures[type] : type, listener, capture); + // create and return the signal + return { + remove: function(){ + target.removeEventListener(type, listener, capture); + } + }; + } + type = "on" + type; + if(fixAttach && target.attachEvent){ + return fixAttach(target, type, listener); + } + throw new Error("Target must be an event emitter"); + } - dojo._Line.prototype.getValue = function(/*float*/ n){ - // summary: Returns the point on the line - // n: a floating point number greater than 0 and less than 1 - return ((this.end - this.start) * n) + this.start; // Decimal + 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. + // 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 (except in the case of normally non-bubbling events like mouse.enter, in which case it defaults to false). + // example: + // define(["dojo/on", "dojo/mouse"], function(listen, mouse){ + // on(node, on.selector(".my-class", mouse.enter), handlerForMyHover); + return function(target, listener){ + var matchesTarget = this; + var bubble = eventType.bubble; + if(bubble){ + // the event type doesn't naturally bubble, but has a bubbling form, use that + eventType = bubble; + }else if(children !== false){ + // for normal bubbling events we default to allowing children of the selector + children = true; + } + return on(target, eventType, function(event){ + var eventTarget = event.target; + // see if we have a valid matchesTarget or default to dojo.query + matchesTarget = matchesTarget && matchesTarget.matches ? matchesTarget : dojo.query; + // there is a selector, so make sure it matches + while(!matchesTarget.matches(eventTarget, selector, target)){ + if(eventTarget == target || !children || !(eventTarget = eventTarget.parentNode)){ // intentional assignment + return; + } + } + return listener.call(eventTarget, event); + }); + }; }; - dojo.Animation = function(args){ - // summary: - // A generic animation class that fires callbacks into its handlers - // object at various states. - // description: - // A generic animation class that fires callbacks into its handlers - // object at various states. Nearly all dojo animation functions - // return an instance of this method, usually without calling the - // .play() method beforehand. Therefore, you will likely need to - // call .play() on instances of `dojo.Animation` when one is - // returned. - // args: Object - // The 'magic argument', mixing all the properties into this - // animation instance. + function syntheticPreventDefault(){ + this.cancelable = false; + } + 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 emiting 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 emiting + // 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, emiting a keypress event would not cause a character + // to appear in a textbox. + // example: + // To fire our own click event + // | on.emit(dojo.byId("button"), "click", { + // | cancelable: true, + // | bubbles: true, + // | screenX: 33, + // | screenY: 44 + // | }); + // We can also fire our own custom events: + // | on.emit(dojo.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 = {}; + if(has("dom-addeventlistener")){ + // normalize focusin and focusout + captures = { + focusin: "focus", + focusout: "blur" + }; + if(has("opera")){ + captures.keydown = "keypress"; // this one needs to be transformed because Opera doesn't support repeating keys on keydown (and keypress works because it incorrectly fires on all keydown events) + } + + // emiter that works with native event handling + on.emit = function(target, type, event){ + if(target.dispatchEvent && document.createEvent){ + // use the native event emiting 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 nativeEvent = document.createEvent("HTMLEvents"); + nativeEvent.initEvent(type, !!event.bubbles, !!event.cancelable); + // and copy all our properties over + for(var i in event){ + var value = event[i]; + 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);} + 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 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); + return listener.call(this, evt); + } + } + 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 emiter = target[type]; + if(!emiter || !emiter.listeners){ + var oldListener = emiter; + target[type] = emiter = Function('event', 'var callee = arguments.callee; for(var i = 0; i 1){ ... } + }; - d.extend(dojo.Animation, { - // duration: Integer - // The time in milliseonds the animation will take to run - duration: 350, + dojo.isIE = { + // example: + // | if(dojo.isIE > 6){ + // | // we are IE7 + // | } + }; - /*===== - // curve: dojo._Line|Array - // A two element array of start and end values, or a `dojo._Line` instance to be - // used in the Animation. - curve: null, + dojo.isSafari = { + // example: + // | if(dojo.isSafari){ ... } + // example: + // Detect iPhone: + // | if(dojo.isSafari && navigator.userAgent.indexOf("iPhone") != -1){ + // | // we are iPhone. Note, iPod touch reports "iPod" above and fails this test. + // | } + }; - // easing: Function? - // A Function to adjust the acceleration (or deceleration) of the progress - // across a dojo._Line - easing: null, + dojo.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: 2, + // 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: 6, + // isKhtml: Number | undefined + // Version as a Number if client is a KHTML browser. undefined otherwise. Corresponds to major + // detected version. + isKhtml: 0, + // isWebKit: Number | undefined + // Version as a Number if client is a WebKit-derived browser (Konqueror, + // Safari, Chrome, etc.). undefined otherwise. + isWebKit: 0, + // isMozilla: Number | undefined + // Version as a Number if client is a Mozilla-based browser (Firefox, + // SeaMonkey). undefined otherwise. Corresponds to major detected version. + isMozilla: 0, + // isOpera: Number | undefined + // Version as a Number if client is Opera. undefined otherwise. Corresponds to + // major detected version. + isOpera: 0, + // isSafari: Number | undefined + // Version as a Number if client is Safari or iPhone. undefined otherwise. + isSafari: 0, + // isChrome: Number | undefined + // Version as a Number if client is Chrome browser. undefined otherwise. + isChrome: 0, + // isMac: Boolean + // True if the client runs on Mac + isMac: 0, + // isIos: Boolean + // True if client is iPhone, iPod, or iPad + isIos: 0, + // isAndroid: Number | undefined + // Version as a Number if client is android browser. undefined otherwise. + isAndroid: 0, + // isWii: Boolean + // True if client is Wii + isWii: 0 + }); =====*/ - // repeat: Integer? - // The number of times to loop the animation - repeat: 0, + // fill in the rendering support information in dojo.render.* + if(dua.indexOf("AdobeAIR") >= 0){ isAIR = 1; } + isKhtml = (dav.indexOf("Konqueror") >= 0) ? tv : 0; + isWebKit = parseFloat(dua.split("WebKit/")[1]) || undefined; + isChrome = parseFloat(dua.split("Chrome/")[1]) || undefined; + isMac = dav.indexOf("Macintosh") >= 0; + isIos = /iPhone|iPod|iPad/.test(dua); + isAndroid = parseFloat(dua.split("Android ")[1]) || undefined; + isWii = typeof opera != "undefined" && opera.wiiremote; + + // safari detection derived from: + // http://developer.apple.com/internet/safari/faq.html#anchor2 + // http://developer.apple.com/internet/safari/uamatrix.html + var index = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0); + if(index && !isChrome){ + // try to grab the explicit Safari version first. If we don't get + // one, look for less than 419.3 as the indication that we're on something + // "Safari 2-ish". + isSafari = parseFloat(dav.split("Version/")[1]); + if(!isSafari || parseFloat(dav.substr(index + 7)) <= 419.3){ + isSafari = 2; + } + } - // rate: Integer? - // the time in milliseconds to wait before advancing to next frame - // (used as a fps timer: 1000/rate = fps) - rate: 20 /* 50 fps */, + if (!has("dojo-webkit")) { + if(dua.indexOf("Opera") >= 0){ + isOpera = tv; + // 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 + if(isOpera >= 9.8){ + isOpera = parseFloat(dua.split("Version/")[1]) || tv; + } + } + + if(dua.indexOf("Gecko") >= 0 && !isKhtml && !isWebKit){ + isMozilla = isMoz = tv; + } + if(isMoz){ + //We really need to get away from this. Consider a sane isGecko approach for the future. + isFF = parseFloat(dua.split("Firefox/")[1] || dua.split("Minefield/")[1]) || undefined; + } + if(document.all && !isOpera){ + 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; + } + } + } + + isQuirks = document.compatMode == "BackCompat"; + + hasAdd("opera", dojo.isOpera = isOpera); + hasAdd("air", dojo.isAIR = isAIR); + hasAdd("khtml", dojo.isKhtml = isKhtml); + hasAdd("webkit", dojo.isWebKit = isWebKit); + hasAdd("chrome", dojo.isChrome = isChrome); + hasAdd("mac", dojo.isMac = isMac ); + hasAdd("safari", dojo.isSafari = isSafari); + hasAdd("mozilla", dojo.isMozilla = dojo.isMoz = isMozilla ); + hasAdd("ie", dojo.isIE = isIE ); + hasAdd("ff", dojo.isFF = isFF); + hasAdd("quirks", dojo.isQuirks = isQuirks); + hasAdd("ios", dojo.isIos = isIos); + hasAdd("android", dojo.isAndroid = isAndroid); + + dojo.locale = dojo.locale || (isIE ? n.userLanguage : n.language).toLowerCase(); + + return has; +}); + +}, +'dojo/_base/array':function(){ +define("dojo/_base/array", ["./kernel", "../has", "./lang"], function(dojo, has, lang){ + // module: + // dojo/_base/array + // summary: + // This module defines the Javascript v1.6 array extensions. /*===== - // delay: Integer? - // The time in milliseconds to wait before starting animation after it - // has been .play()'ed - delay: null, + dojo.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 one difference: 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. + // 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? + // returns: Number + }; + dojo.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 one difference: when + // run over sparse arrays, the Dojo function invokes the callback for every index whereas JavaScript + // 1.6's lastIndexOf skips the holes in the sparse array. + // 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 + }; + dojo.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 dojo.every() or dojo.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: + // | dojo.forEach( + // | [ "thinger", "blah", "howdy", 10 ], + // | function(item){ + // | console.log(item); + // | } + // | ); + // example: + // | // log out the members and their indexes + // | dojo.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 + // | dojo.forEach( + // | [ "thinger", "blah", "howdy", 10 ], + // | obj.callback, + // | obj + // | ); + // | + // | // alternately, we can accomplish the same thing with dojo.hitch() + // | dojo.forEach( + // | [ "thinger", "blah", "howdy", 10 ], + // | dojo.hitch(obj, "callback") + // | ); + // arr: Array|String + // callback: Function|String + // thisObject: Object? + }; + dojo.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 + // | dojo.every([1, 2, 3, 4], function(item){ return item>1; }); + // example: + // | // returns true + // | dojo.every([1, 2, 3, 4], function(item){ return item>0; }); + }; + dojo.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 + // | dojo.some([1, 2, 3, 4], function(item){ return item>1; }); + // example: + // | // is false + // | dojo.some([1, 2, 3, 4], function(item){ return item<1; }); + }; + dojo.map = function(arr, callback, thisObject){ + // 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] + // | dojo.map([1, 2, 3, 4], function(item){ return item+1 }); + }; + dojo.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] + // | dojo.filter([1, 2, 3, 4], function(item){ return item>1; }); + }; + =====*/ - // beforeBegin: Event? - // Synthetic event fired before a dojo.Animation begins playing (synchronous) - beforeBegin: null, + // our old simple function builder stuff + var cache = {}, u, array; // the export object - // onBegin: Event? - // Synthetic event fired as a dojo.Animation begins playing (useful?) - onBegin: null, + function clearCache(){ + cache = {}; + } - // onAnimate: Event? - // Synthetic event fired at each interval of a `dojo.Animation` - onAnimate: null, + function buildFn(fn){ + return cache[fn] = new Function("item", "index", "array", fn); // Function + } + // magic snippet: if(typeof fn == "string") fn = cache[fn] || buildFn(fn); - // onEnd: Event? - // Synthetic event fired after the final frame of a `dojo.Animation` - onEnd: null, + // every & some - // onPlay: Event? - // Synthetic event fired any time a `dojo.Animation` is play()'ed - onPlay: null, + 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") 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 + } + } + // var every = everyOrSome(false), some = everyOrSome(true); - // onPause: Event? - // Synthetic event fired when a `dojo.Animation` is paused - onPause: null, + // indexOf, lastIndexOf - // onStop: Event - // Synthetic event fires when a `dojo.Animation` is stopped - onStop: null, + 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 indexOf = index(true), lastIndexOf = index(false); - =====*/ + function forEach(a, fn, o){ + var i = 0, l = a && a.length || 0; + if(l && typeof a == "string") a = a.split(""); + if(typeof fn == "string") fn = cache[fn] || buildFn(fn); + if(o){ + for(; i < l; ++i){ + fn.call(o, a[i], i, a); + } + }else{ + for(; i < l; ++i){ + fn(a[i], i, a); + } + } + } - _percent: 0, - _startRepeatCount: 0, + function map(a, fn, o, Ctr){ + // TODO: why do we have a non-standard signature here? do we need "Ctr"? + var i = 0, l = a && a.length || 0, out = new (Ctr || Array)(l); + if(l && typeof a == "string") a = a.split(""); + if(typeof fn == "string") fn = cache[fn] || buildFn(fn); + if(o){ + for(; i < l; ++i){ + out[i] = fn.call(o, a[i], i, a); + } + }else{ + for(; i < l; ++i){ + out[i] = fn(a[i], i, a); + } + } + return out; // Array + } - _getStep: function(){ - var _p = this._percent, - _e = this.easing - ; - return _e ? _e(_p) : _p; - }, - _fire: function(/*Event*/ evt, /*Array?*/ args){ - // summary: - // Convenience function. Fire event "evt" and pass it the - // arguments specified in "args". - // description: - // Convenience function. Fire event "evt" and pass it the - // arguments specified in "args". - // Fires the callback in the scope of the `dojo.Animation` - // instance. - // evt: - // The event to fire. - // args: - // The arguments to pass to the event. - var a = args||[]; - if(this[evt]){ - if(d.config.debugAtAllCosts){ - this[evt].apply(this, a); - }else{ - try{ - this[evt].apply(this, a); - }catch(e){ - // squelch and log because we shouldn't allow exceptions in - // synthetic event handlers to cause the internal timer to run - // amuck, potentially pegging the CPU. I'm not a fan of this - // squelch, but hopefully logging will make it clear what's - // going on - console.error("exception in animation handler for:", evt); - console.error(e); - } + function filter(a, fn, o){ + // TODO: do we need "Ctr" here like in map()? + var i = 0, l = a && a.length || 0, out = [], value; + if(l && typeof a == "string") a = a.split(""); + if(typeof fn == "string") fn = cache[fn] || buildFn(fn); + if(o){ + for(; i < l; ++i){ + value = a[i]; + if(fn.call(o, value, i, a)){ + out.push(value); } } - return this; // dojo.Animation - }, + }else{ + for(; i < l; ++i){ + value = a[i]; + if(fn(value, i, a)){ + out.push(value); + } + } + } + return out; // Array + } - play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){ - // summary: - // Start the animation. - // delay: - // How many milliseconds to delay before starting. - // gotoStart: - // If true, starts the animation from the beginning; otherwise, - // starts it from its current position. - // returns: dojo.Animation - // The instance to allow chaining. + array = { + every: everyOrSome(false), + some: everyOrSome(true), + indexOf: index(true), + lastIndexOf: index(false), + forEach: forEach, + map: map, + filter: filter, + clearCache: clearCache + }; - var _t = this; - if(_t._delayTimer){ _t._clearTimer(); } - if(gotoStart){ - _t._stopTimer(); - _t._active = _t._paused = false; - _t._percent = 0; - }else if(_t._active && !_t._paused){ - return _t; + 1 && lang.mixin(dojo, array); + + /*===== return dojo.array; =====*/ + return array; +}); + +}, +'dojo/_base/json':function(){ +define(["./kernel", "../json"], function(dojo, json){ + // module: + // dojo/_base/json + // 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 +}; - _t._fire("beforeBegin", [_t.node]); +return dojo; +}); - var de = delay || _t.delay, - _p = dojo.hitch(_t, "_play", gotoStart); +}, +'dojo/dom-class':function(){ +define(["./_base/lang", "./_base/array", "./dom"], function(lang, array, dom){ + // module: + // dojo/dom-class + // summary: + // This module defines the core dojo DOM class API. - if(de > 0){ - _t._delayTimer = setTimeout(_p, de); - return _t; - } - _p(); - return _t; - }, + var className = "className"; - _play: function(gotoStart){ - var _t = this; - if(_t._delayTimer){ _t._clearTimer(); } - _t._startTime = new Date().valueOf(); - if(_t._paused){ - _t._startTime -= _t.duration * _t._percent; - } + /* Part I of classList-based implementation is preserved here for posterity + var classList = "classList"; + has.add("dom-classList", function(){ + return classList in document.createElement("p"); + }); + */ - _t._active = true; - _t._paused = false; - var value = _t.curve.getValue(_t._getStep()); - if(!_t._percent){ - if(!_t._startRepeatCount){ - _t._startRepeatCount = _t.repeat; - } - _t._fire("onBegin", [value]); - } + // ============================= + // (CSS) Class Functions + // ============================= - _t._fire("onPlay", [value]); + /*===== + dojo.hasClass = function(node, classStr){ + // summary: + // Returns whether or not the specified classes are a portion of the + // class list currently applied to the node. + // + // node: String|DOMNode + // String ID or DomNode reference to check the class for. + // + // classStr: String + // A string class name to look for. + // + // returns: Boolean + // + // example: + // Do something if a node with id="someNode" has class="aSillyClassName" present + // | if(dojo.hasClass("someNode","aSillyClassName")){ ... } + }; + =====*/ - _t._cycle(); - return _t; // dojo.Animation - }, + /*===== + dojo.addClass = function(node, classStr){ + // summary: + // Adds the specified classes to the end of the class list on the + // passed node. Will not re-apply duplicate classes. + // + // node: String|DOMNode + // String ID or DomNode reference to add a class string too + // + // classStr: String|Array + // A String class name to add, or several space-separated class names, + // or an array of class names. + // + // example: + // Add a class to some node: + // | dojo.addClass("someNode", "anewClass"); + // + // example: + // Add two classes at once: + // | dojo.addClass("someNode", "firstClass secondClass"); + // + // example: + // Add two classes at once (using array): + // | dojo.addClass("someNode", ["firstClass", "secondClass"]); + // + // example: + // Available in `dojo.NodeList` for multiple additions + // | dojo.query("ul > li").addClass("firstLevel"); + }; + =====*/ - pause: function(){ - // summary: Pauses a running animation. - var _t = this; - if(_t._delayTimer){ _t._clearTimer(); } - _t._stopTimer(); - if(!_t._active){ return _t; /*dojo.Animation*/ } - _t._paused = true; - _t._fire("onPause", [_t.curve.getValue(_t._getStep())]); - return _t; // dojo.Animation - }, + /*===== + dojo.removeClass = function(node, classStr){ + // summary: + // Removes the specified classes from node. No `dojo.hasClass` + // check is required. + // + // node: String|DOMNode + // String ID or DomNode reference to remove the class from. + // + // classStr: String|Array + // An optional String class name to remove, or several space-separated + // class names, or an array of class names. If omitted, all class names + // will be deleted. + // + // example: + // Remove a class from some node: + // | dojo.removeClass("someNode", "firstClass"); + // + // example: + // Remove two classes from some node: + // | dojo.removeClass("someNode", "firstClass secondClass"); + // + // example: + // Remove two classes from some node (using array): + // | dojo.removeClass("someNode", ["firstClass", "secondClass"]); + // + // example: + // Remove all classes from some node: + // | dojo.removeClass("someNode"); + // + // example: + // Available in `dojo.NodeList()` for multiple removal + // | dojo.query(".foo").removeClass("foo"); + }; + =====*/ - gotoPercent: function(/*Decimal*/ percent, /*Boolean?*/ andPlay){ - // summary: - // Sets the progress of the animation. - // percent: - // A percentage in decimal notation (between and including 0.0 and 1.0). - // andPlay: - // If true, play the animation after setting the progress. - var _t = this; - _t._stopTimer(); - _t._active = _t._paused = true; - _t._percent = percent; - if(andPlay){ _t.play(); } - return _t; // dojo.Animation - }, + /*===== + dojo.replaceClass = function(node, addClassStr, removeClassStr){ + // summary: + // Replaces one or more classes on a node if not present. + // Operates more quickly than calling dojo.removeClass and dojo.addClass + // + // node: String|DOMNode + // String ID or DomNode reference to remove the class from. + // + // addClassStr: String|Array + // A String class name to add, or several space-separated class names, + // or an array of class names. + // + // removeClassStr: String|Array? + // A String class name to remove, or several space-separated class names, + // or an array of class names. + // + // example: + // | dojo.replaceClass("someNode", "add1 add2", "remove1 remove2"); + // + // example: + // Replace all classes with addMe + // | dojo.replaceClass("someNode", "addMe"); + // + // example: + // Available in `dojo.NodeList()` for multiple toggles + // | dojo.query(".findMe").replaceClass("addMe", "removeMe"); + }; + =====*/ - stop: function(/*boolean?*/ gotoEnd){ - // summary: Stops a running animation. - // gotoEnd: If true, the animation will end. - var _t = this; - if(_t._delayTimer){ _t._clearTimer(); } - if(!_t._timer){ return _t; /* dojo.Animation */ } - _t._stopTimer(); - if(gotoEnd){ - _t._percent = 1; - } - _t._fire("onStop", [_t.curve.getValue(_t._getStep())]); - _t._active = _t._paused = false; - return _t; // dojo.Animation - }, + /*===== + dojo.toggleClass = function(node, classStr, condition){ + // summary: + // Adds a class to node if not present, or removes if present. + // Pass a boolean condition if you want to explicitly add or remove. + // Returns the condition that was specified directly or indirectly. + // + // node: String|DOMNode + // String ID or DomNode reference to toggle a class string + // + // classStr: String|Array + // A String class name to toggle, or several space-separated class names, + // or an array of class names. + // + // condition: + // If passed, true means to add the class, false means to remove. + // Otherwise dojo.hasClass(node, classStr) is used to detect the class presence. + // + // example: + // | dojo.toggleClass("someNode", "hovered"); + // + // example: + // Forcefully add a class + // | dojo.toggleClass("someNode", "hovered", true); + // + // example: + // Available in `dojo.NodeList()` for multiple toggles + // | dojo.query(".toggleMe").toggleClass("toggleMe"); + }; + =====*/ - status: function(){ - // summary: - // Returns a string token representation of the status of - // the animation, one of: "paused", "playing", "stopped" - if(this._active){ - return this._paused ? "paused" : "playing"; // String + var cls, // exports object + spaces = /\s+/, a1 = [""]; + + function str2array(s){ + if(typeof s == "string" || s instanceof String){ + if(s && !spaces.test(s)){ + a1[0] = s; + return a1; } - return "stopped"; // String - }, + var a = s.split(spaces); + if(a.length && !a[0]){ + a.shift(); + } + if(a.length && !a[a.length - 1]){ + a.pop(); + } + return a; + } + // assumed to be an array + if(!s){ + return []; + } + return array.filter(s, function(x){ return x; }); + } - _cycle: function(){ - var _t = this; - if(_t._active){ - var curr = new Date().valueOf(); - var step = (curr - _t._startTime) / (_t.duration); + /* Part II of classList-based implementation is preserved here for posterity + if(has("dom-classList")){ + // new classList version + cls = { + contains: function containsClass(node, classStr){ + var clslst = classStr && dom.byId(node)[classList]; + return clslst && clslst.contains(classStr); // Boolean + }, - if(step >= 1){ - step = 1; + add: function addClass(node, classStr){ + node = dom.byId(node); + classStr = str2array(classStr); + for(var i = 0, len = classStr.length; i < len; ++i){ + node[classList].add(classStr[i]); } - _t._percent = step; + }, - // Perform easing - if(_t.easing){ - step = _t.easing(step); + remove: function removeClass(node, classStr){ + node = dom.byId(node); + if(classStr === undefined){ + node[className] = ""; + }else{ + classStr = str2array(classStr); + for(var i = 0, len = classStr.length; i < len; ++i){ + node[classList].remove(classStr[i]); + } } + }, - _t._fire("onAnimate", [_t.curve.getValue(step)]); - - if(_t._percent < 1){ - _t._startTimer(); + replace: function replaceClass(node, addClassStr, removeClassStr){ + node = dom.byId(node); + if(removeClassStr === undefined){ + node[className] = ""; }else{ - _t._active = false; + removeClassStr = str2array(removeClassStr); + for(var i = 0, len = removeClassStr.length; i < len; ++i){ + node[classList].remove(removeClassStr[i]); + } + } + addClassStr = str2array(addClassStr); + for(i = 0, len = addClassStr.length; i < len; ++i){ + node[classList].add(addClassStr[i]); + } + }, - if(_t.repeat > 0){ - _t.repeat--; - _t.play(null, true); - }else if(_t.repeat == -1){ - _t.play(null, true); - }else{ - if(_t._startRepeatCount){ - _t.repeat = _t._startRepeatCount; - _t._startRepeatCount = 0; - } + toggle: function toggleClass(node, classStr, condition){ + node = dom.byId(node); + if(condition === undefined){ + classStr = str2array(classStr); + for(var i = 0, len = classStr.length; i < len; ++i){ + node[classList].toggle(classStr[i]); } - _t._percent = 0; - _t._fire("onEnd", [_t.node]); - !_t.repeat && _t._stopTimer(); + }else{ + cls[condition ? "add" : "remove"](node, classStr); + } + return condition; // Boolean + } + } + } + */ + + // regular DOM version + var fakeNode = {}; // for effective replacement + cls = { + contains: function containsClass(/*DomNode|String*/node, /*String*/classStr){ + return ((" " + dom.byId(node)[className] + " ").indexOf(" " + classStr + " ") >= 0); // Boolean + }, + + add: function addClass(/*DomNode|String*/node, /*String|Array*/classStr){ + node = dom.byId(node); + classStr = str2array(classStr); + var cls = node[className], oldLen; + cls = cls ? " " + cls + " " : " "; + oldLen = cls.length; + for(var i = 0, len = classStr.length, c; i < len; ++i){ + c = classStr[i]; + if(c && cls.indexOf(" " + c + " ") < 0){ + cls += c + " "; + } + } + if(oldLen < cls.length){ + node[className] = cls.substr(1, cls.length - 2); + } + }, + + remove: function removeClass(/*DomNode|String*/node, /*String|Array?*/classStr){ + node = dom.byId(node); + var cls; + if(classStr !== undefined){ + classStr = str2array(classStr); + cls = " " + node[className] + " "; + for(var i = 0, len = classStr.length; i < len; ++i){ + cls = cls.replace(" " + classStr[i] + " ", " "); } + cls = lang.trim(cls); + }else{ + cls = ""; } - return _t; // dojo.Animation + if(node[className] != cls){ node[className] = cls; } }, - _clearTimer: function(){ - // summary: Clear the play delay timer - clearTimeout(this._delayTimer); - delete this._delayTimer; + replace: function replaceClass(/*DomNode|String*/node, /*String|Array*/addClassStr, /*String|Array?*/removeClassStr){ + node = dom.byId(node); + fakeNode[className] = node[className]; + cls.remove(fakeNode, removeClassStr); + cls.add(fakeNode, addClassStr); + if(node[className] !== fakeNode[className]){ + node[className] = fakeNode[className]; + } + }, + + toggle: function toggleClass(/*DomNode|String*/node, /*String|Array*/classStr, /*Boolean?*/condition){ + node = dom.byId(node); + if(condition === undefined){ + classStr = str2array(classStr); + for(var i = 0, len = classStr.length, c; i < len; ++i){ + c = classStr[i]; + cls[cls.contains(node, c) ? "remove" : "add"](node, c); + } + }else{ + cls[condition ? "add" : "remove"](node, classStr); + } + return condition; // Boolean } + }; - }); + return cls; +}); - // the local timer, stubbed into all Animation instances - var ctr = 0, - timer = null, - runner = { - run: function(){} - }; +}, +'dojo/_base/window':function(){ +define(["./kernel", "../has", "./sniff"], function(dojo, has){ + // module: + // dojo/window + // summary: + // This module provides an API to save/set/restore the global/document scope. - d.extend(d.Animation, { +/*===== +dojo.doc = { + // summary: + // Alias for the current document. 'dojo.doc' can be modified + // for temporary context shifting. Also see dojo.withDoc(). + // description: + // Refer to dojo.doc rather + // than referring to 'window.document' to ensure your code runs + // correctly in managed contexts. + // example: + // | n.appendChild(dojo.doc.createElement('div')); +} +=====*/ +dojo.doc = this["document"] || null; - _startTimer: function(){ - if(!this._timer){ - this._timer = d.connect(runner, "run", this, "_cycle"); - ctr++; - } - if(!timer){ - timer = setInterval(d.hitch(runner, "run"), this.rate); - } - }, +dojo.body = function(){ + // summary: + // Return the body element of the document + // return the body object associated with dojo.doc + // example: + // | dojo.body().appendChild(dojo.doc.createElement('div')); - _stopTimer: function(){ - if(this._timer){ - d.disconnect(this._timer); - this._timer = null; - ctr--; - } - if(ctr <= 0){ - clearInterval(timer); - timer = null; - ctr = 0; + // Note: document.body is not defined for a strict xhtml document + // Would like to memoize this, but dojo.doc can change vi dojo.withDoc(). + return dojo.doc.body || dojo.doc.getElementsByTagName("body")[0]; // Node +}; + +dojo.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; +}; + +dojo.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 dojo.withDoc.call(null, globalObject.document, callback, thisObject, cbArguments); + }finally{ + dojo.global = ret.global = oldGlob; + } +}; + +dojo.withDoc = function( /*DocumentElement*/documentObject, + /*Function*/callback, + /*Object?*/thisObject, + /*Array?*/cbArguments){ + // summary: + // Invoke callback with documentObject as dojo.doc. + // description: + // Invoke callback with documentObject as dojo.doc. If provided, + // callback will be executed in the context of object thisObject + // When callback() returns or throws an error, the dojo.doc will + // be restored to its previous state. + + var oldDoc = dojo.doc, + oldQ = dojo.isQuirks, + oldIE = dojo.isIE, isIE, mode, pwin; + + try{ + dojo.doc = ret.doc = documentObject; + // update dojo.isQuirks and the value of the has feature "quirks" + 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]; + } - var _makeFadeable = - d.isIE ? function(node){ - // only set the zoom if the "tickle" value would be the same as the - // default - var ns = node.style; - // don't set the width to auto if it didn't already cascade that way. - // We don't want to f anyones designs - if(!ns.width.length && d.style(node, "width") == "auto"){ - ns.width = "auto"; - } - } : - function(){}; + 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); + } +}; - dojo._fade = function(/*Object*/ args){ - // summary: - // Returns an animation that will fade the node defined by - // args.node from the start to end values passed (args.start - // args.end) (end is mandatory, start is optional) +var ret = { + global: dojo.global, + doc: dojo.doc, + body: dojo.body, + setContext: dojo.setContext, + withGlobal: dojo.withGlobal, + withDoc: dojo.withDoc +}; - args.node = d.byId(args.node); - var fArgs = _mixin({ properties: {} }, args), - props = (fArgs.properties.opacity = {}); +return ret; - props.start = !("start" in fArgs) ? - function(){ - return +d.style(fArgs.node, "opacity")||0; - } : fArgs.start; - props.end = fArgs.end; +}); - var anim = d.animateProperty(fArgs); - d.connect(anim, "beforeBegin", d.partial(_makeFadeable, fArgs.node)); +}, +'dojo/_base/config':function(){ +define(["../has", "require"], function(has, require){ + // module: + // dojo/_base/config + // 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-uniqe 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 + // | }); - return anim; // dojo.Animation - }; + 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 + this.dojoConfig || this.djConfig || {}; + adviseHas(result, "config", 1); + adviseHas(result.has, "", 1); + } + return result; - /*===== - dojo.__FadeArgs = function(node, duration, easing){ - // node: DOMNode|String - // The node referenced in the animation - // duration: Integer? - // Duration of the animation in milliseconds. - // easing: Function? - // An easing function. - this.node = node; - this.duration = duration; - this.easing = easing; +/*===== +// note: +// 'dojoConfig' does not exist under 'dojo.*' so that it can be set before the +// 'dojo' variable exists. +// note: +// Setting any of these variables *after* the library has loaded does +// nothing at all. + +// FIXME: can we document these on dojo.config object and explain they must be set via djConfig/dojoConfig global prior to loading dojo.js + +dojoConfig = { + // summary: + // Application code can set the global 'dojoConfig' prior to loading + // the library to control certain global settings for how dojo works. + // + // isDebug: Boolean + // Defaults to `false`. If set to `true`, ensures that Dojo provides + // extended debugging feedback via Firebug. If Firebug is not available + // on your platform, setting `isDebug` to `true` will force Dojo to + // pull in (and display) the version of Firebug Lite which is + // integrated into the Dojo distribution, thereby always providing a + // debugging/logging console when `isDebug` is enabled. Note that + // Firebug's `console.*` methods are ALWAYS defined by Dojo. If + // `isDebug` is false and you are on a platform without Firebug, these + // methods will be defined as no-ops. + 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: 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. Specifiying + // `djConfig.modulePaths = { "foo": "../../bar" }` is the equivalent + // of calling `dojo.registerModulePath("foo", "../../bar");`. Multiple + // modules may be configured via `djConfig.modulePaths`. + modulePaths: {}, + // afterOnLoad: Boolean + // Indicates Dojo was added to the page after the page load. In this case + // Dojo will not wait for the page DOMContentLoad/load events and fire + // its dojo.addOnLoad callbacks after making sure all outstanding + // dojo.required modules have loaded. Only works with a built dojo.js, + // it does not work the dojo.js directly from source control. + afterOnLoad: false, + // addOnLoad: Function or Array + // Adds a callback via dojo.addOnLoad. Useful when Dojo is added after + // the page loads and djConfig.afterOnLoad is true. Supports the same + // arguments as dojo.addOnLoad. 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, + // require: Array + // An array of module names to be loaded immediately after dojo.js has been included + // in a page. + require: [], + // defaultDuration: Array + // 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.publish. See dojo.__IoPublish for a list + // of topics that are published. + ioPublish: false, + // useCustomLogger: Anything? + // If set to a value that evaluates to true such as a string or array and + // isDebug is true and Firebug is not available or running, then it bypasses + // the creation of Firebug Lite allowing you to define your own console object. + useCustomLogger: undefined, + // 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, + // skipIeDomLoaded: Boolean + // For IE only, skip the DOMContentLoaded hack used. Sometimes it can cause an Operation + // Aborted error if the rest of the page triggers script defers before the DOM is ready. + // If this is config value is set to true, then dojo.addOnLoad callbacks will not be + // triggered until the page load event, which is after images and iframes load. If you + // want to trigger the callbacks sooner, you can put a script block in the bottom of + // your HTML that calls dojo._loadInit();. If you are using multiversion support, change + // "dojo." to the appropriate scope name for dojo. + skipIeDomLoaded: false +} +=====*/ +}); + + +}, +'dojo/_base/event':function(){ +define(["./kernel", "../on", "../has", "../dom-geometry"], function(dojo, on, has, dom){ + // module: + // dojo/_base/event + // summary: + // This module defines dojo DOM event API. + if(on._fixEvent){ + var fixEvent = on._fixEvent; + on._fixEvent = function(evt, se){ + // add some additional normalization for back-compat, this isn't in on.js because it is somewhat more expensive + evt = fixEvent(evt, se); + if(evt){ + dom.normalizeEvent(evt); + } + return evt; + }; } - =====*/ - - dojo.fadeIn = function(/*dojo.__FadeArgs*/ args){ - // summary: - // Returns an animation that will fade node defined in 'args' from - // its current opacity to fully opaque. - return d._fade(_mixin({ end: 1 }, args)); // dojo.Animation - }; - - dojo.fadeOut = function(/*dojo.__FadeArgs*/ args){ + dojo.fixEvent = function(/*Event*/ evt, /*DOMNode*/ sender){ // summary: - // Returns an animation that will fade node defined in 'args' - // from its current opacity to fully transparent. - return d._fade(_mixin({ end: 0 }, args)); // dojo.Animation - }; - - dojo._defaultEasing = function(/*Decimal?*/ n){ - // summary: The default easing function for dojo.Animation(s) - return 0.5 + ((Math.sin((n + 1.5) * Math.PI)) / 2); - }; - - var PropLine = function(properties){ - // PropLine is an internal class which is used to model the values of - // an a group of CSS properties across an animation lifecycle. In - // particular, the "getValue" function handles getting interpolated - // values between start and end for a particular CSS value. - this._properties = properties; - for(var p in properties){ - var prop = properties[p]; - if(prop.start instanceof d.Color){ - // create a reusable temp color object to keep intermediate results - prop.tempColor = new d.Color(); - } + // normalizes properties on the event object including event + // bubbling methods, keystroke normalization, and x/y positions + // evt: Event + // native event object + // sender: DOMNode + // node to treat as "currentTarget" + if(on._fixEvent){ + return on._fixEvent(evt, sender); } + return evt; // Event }; + + dojo.stopEvent = function(/*Event*/ evt){ + // summary: + // prevents propagation and clobbers the default action of the + // passed event + // evt: Event + // The event object. If omitted, window.event is used on IE. + if(has("dom-addeventlistener") || (evt && evt.preventDefault)){ + evt.preventDefault(); + evt.stopPropagation(); + }else{ + evt = evt || window.event; + evt.cancelBubble = true; + on._preventDefault.call(evt); + } + }; + + return { + fix: dojo.fixEvent, + stop: dojo.stopEvent + }; +}); + +}, +'dojo/main':function(){ +define([ + "./_base/kernel", + "./has", + "require", + "./_base/sniff", + "./_base/lang", + "./_base/array", + "./ready", + "./_base/declare", + "./_base/connect", + "./_base/Deferred", + "./_base/json", + "./_base/Color", + "./has!dojo-firebug?./_firebug/firebug", + "./_base/browser", + "./_base/loader"], function(dojo, has, require, sniff, lang, array, ready){ + // module: + // dojo/main + // summary: + // This is the package main module for the dojo package; it loads dojo base appropriate for the execution environment. + + // the preferred way to load the dojo firebug console is by setting has("dojo-firebug") true in dojoConfig + // the isDebug config switch is for backcompat and will work fine in sync loading mode; it works in + // async mode too, but there's no guarantee when the module is loaded; therefore, if you need a firebug + // console guarnanteed at a particular spot in an app, either set config.has["dojo-firebug"] true before + // loading dojo.js or explicitly include dojo/_firebug/firebug in a dependency list. + if(dojo.config.isDebug){ + require(["./_firebug/firebug"]); + } - PropLine.prototype.getValue = function(r){ - var ret = {}; - for(var p in this._properties){ - var prop = this._properties[p], - start = prop.start; - if(start instanceof d.Color){ - ret[p] = d.blendColors(start, prop.end, r, prop.tempColor).toCss(); - }else if(!d.isArray(start)){ - ret[p] = ((prop.end - start) * r) + start + (p != "opacity" ? prop.units || "px" : 0); + // dojoConfig.require is deprecated; use the loader configuration property deps + true || has.add("dojo-config-require", 1); + if(1){ + var deps= dojo.config.require; + if(deps){ + // dojo.config.require may be dot notation + deps= array.map(lang.isArray(deps) ? deps : [deps], function(item){ return item.replace(/\./g, "/"); }); + if(dojo.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 ret; - }; + } - /*===== - dojo.declare("dojo.__AnimArgs", [dojo.__FadeArgs], { - // Properties: Object? - // A hash map of style properties to Objects describing the transition, - // such as the properties of dojo._Line with an additional 'units' property - properties: {} + return dojo; +}); - //TODOC: add event callbacks - }); - =====*/ +}, +'dojo/ready':function(){ +define(["./_base/kernel", "./has", "require", "./domReady", "./_base/lang"], function(dojo, has, require, domReady, lang) { + // module: + // dojo/ready + // summary: + // This module defines the dojo.ready API. + // + // 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, - dojo.animateProperty = function(/*dojo.__AnimArgs*/ args){ - // summary: - // Returns an animation that will transition the properties of - // node defined in `args` depending how they are defined in - // `args.properties` - // - // description: - // `dojo.animateProperty` is the foundation of most `dojo.fx` - // animations. It takes an object of "properties" corresponding to - // style properties, and animates them in parallel over a set - // duration. - // - // example: - // A simple animation that changes the width of the specified node. - // | dojo.animateProperty({ - // | node: "nodeId", - // | properties: { width: 400 }, - // | }).play(); - // Dojo figures out the start value for the width and converts the - // integer specified for the width to the more expressive but - // verbose form `{ width: { end: '400', units: 'px' } }` which you - // can also specify directly. Defaults to 'px' if ommitted. - // - // example: - // Animate width, height, and padding over 2 seconds... the - // pedantic way: - // | dojo.animateProperty({ node: node, duration:2000, - // | properties: { - // | width: { start: '200', end: '400', units:"px" }, - // | height: { start:'200', end: '400', units:"px" }, - // | paddingTop: { start:'5', end:'50', units:"px" } - // | } - // | }).play(); - // Note 'paddingTop' is used over 'padding-top'. Multi-name CSS properties - // are written using "mixed case", as the hyphen is illegal as an object key. - // - // example: - // Plug in a different easing function and register a callback for - // when the animation ends. Easing functions accept values between - // zero and one and return a value on that basis. In this case, an - // exponential-in curve. - // | dojo.animateProperty({ - // | node: "nodeId", - // | // dojo figures out the start value - // | properties: { width: { end: 400 } }, - // | easing: function(n){ - // | return (n==0) ? 0 : Math.pow(2, 10 * (n - 1)); - // | }, - // | onEnd: function(node){ - // | // called when the animation finishes. The animation - // | // target is passed to this function - // | } - // | }).play(500); // delay playing half a second - // - // example: - // Like all `dojo.Animation`s, animateProperty returns a handle to the - // Animation instance, which fires the events common to Dojo FX. Use `dojo.connect` - // to access these events outside of the Animation definiton: - // | var anim = dojo.animateProperty({ - // | node:"someId", - // | properties:{ - // | width:400, height:500 - // | } - // | }); - // | dojo.connect(anim,"onEnd", function(){ - // | console.log("animation ended"); - // | }); - // | // play the animation now: - // | anim.play(); - // - // example: - // Each property can be a function whose return value is substituted along. - // Additionally, each measurement (eg: start, end) can be a function. The node - // reference is passed direcly to callbacks. - // | dojo.animateProperty({ - // | node:"mine", - // | properties:{ - // | height:function(node){ - // | // shrink this node by 50% - // | return dojo.position(node).h / 2 - // | }, - // | width:{ - // | start:function(node){ return 100; }, - // | end:function(node){ return 200; } - // | } - // | } - // | }).play(); - // + // a function to call to cause onLoad to be called when all requested modules have been loaded + requestCompleteSignal, - var n = args.node = d.byId(args.node); - if(!args.easing){ args.easing = d._defaultEasing; } + // The queue of functions waiting to execute as soon as dojo.ready conditions satisfied + loadQ = [], - var anim = new d.Animation(args); - d.connect(anim, "beforeBegin", anim, function(){ - var pm = {}; - for(var p in this.properties){ - // Make shallow copy of properties into pm because we overwrite - // some values below. In particular if start/end are functions - // we don't want to overwrite them or the functions won't be - // called if the animation is reused. - if(p == "width" || p == "height"){ - this.node.display = "block"; - } - var prop = this.properties[p]; - if(d.isFunction(prop)){ - prop = prop(n); - } - prop = pm[p] = _mixin({}, (d.isObject(prop) ? prop: { end: prop })); + // prevent recursion in onLoad + onLoadRecursiveGuard = 0, - if(d.isFunction(prop.start)){ - prop.start = prop.start(n); - } - if(d.isFunction(prop.end)){ - prop.end = prop.end(n); - } - var isColor = (p.toLowerCase().indexOf("color") >= 0); - function getStyle(node, p){ - // dojo.style(node, "height") can return "auto" or "" on IE; this is more reliable: - var v = { height: node.offsetHeight, width: node.offsetWidth }[p]; - if(v !== undefined){ return v; } - v = d.style(node, p); - return (p == "opacity") ? +v : (isColor ? v : parseFloat(v)); - } - if(!("end" in prop)){ - prop.end = getStyle(n, p); - }else if(!("start" in prop)){ - prop.start = getStyle(n, p); - } + handleDomReady = function(){ + isDomReady = 1; + dojo._postLoad = dojo.config.afterOnLoad = true; + if(loadQ.length){ + requestCompleteSignal(onLoad); + } + }, - if(isColor){ - prop.start = new d.Color(prop.start); - prop.end = new d.Color(prop.end); - }else{ - prop.start = (p == "opacity") ? +prop.start : parseFloat(prop.start); + // run the next function queued with dojo.ready + onLoad = function(){ + if(isDomReady && !onLoadRecursiveGuard && loadQ.length){ + //guard against recursions into this function + onLoadRecursiveGuard = 1; + var f = loadQ.shift(); + try{ + f(); + } + // FIXME: signal the error via require.on + finally{ + onLoadRecursiveGuard = 0; + } + onLoadRecursiveGuard = 0; + if(loadQ.length){ + requestCompleteSignal(onLoad); } } - this.curve = new PropLine(pm); - }); - d.connect(anim, "onAnimate", d.hitch(d, "style", anim.node)); - return anim; // dojo.Animation - }; + }; - dojo.anim = function( /*DOMNode|String*/ node, - /*Object*/ properties, - /*Integer?*/ duration, - /*Function?*/ easing, - /*Function?*/ onEnd, - /*Integer?*/ delay){ - // summary: - // A simpler interface to `dojo.animateProperty()`, also returns - // an instance of `dojo.Animation` but begins the animation - // immediately, unlike nearly every other Dojo animation API. - // description: - // `dojo.anim` is a simpler (but somewhat less powerful) version - // of `dojo.animateProperty`. It uses defaults for many basic properties - // and allows for positional parameters to be used in place of the - // packed "property bag" which is used for other Dojo animation - // methods. - // - // The `dojo.Animation` object returned from `dojo.anim` will be - // already playing when it is returned from this function, so - // calling play() on it again is (usually) a no-op. - // node: - // a DOM node or the id of a node to animate CSS properties on - // duration: - // The number of milliseconds over which the animation - // should run. Defaults to the global animation default duration - // (350ms). - // easing: - // An easing function over which to calculate acceleration - // and deceleration of the animation through its duration. - // A default easing algorithm is provided, but you may - // plug in any you wish. A large selection of easing algorithms - // are available in `dojo.fx.easing`. - // onEnd: - // A function to be called when the animation finishes - // running. - // delay: - // The number of milliseconds to delay beginning the - // animation by. The default is 0. - // example: - // Fade out a node - // | dojo.anim("id", { opacity: 0 }); - // example: - // Fade out a node over a full second - // | dojo.anim("id", { opacity: 0 }, 1000); - return d.animateProperty({ // dojo.Animation - node: node, - duration: duration || d.Animation.prototype.duration, - properties: properties, - easing: easing, - onEnd: onEnd - }).play(delay || 0); - }; -})(); + // define requireCompleteSignal; impl depends on loader + if(1){ + require.on("idle", onLoad); + requestCompleteSignal = function(){ + if(require.idle()){ + onLoad(); + } // else do nothing, onLoad will be called with the next idle signal + }; + }else{ + // RequireJS or similar + requestCompleteSignal = function(){ + // the next function call will fail if you don't have a loader with require.ready + // in that case, either fix your loader, use dojo's loader, or don't call dojo.ready; + require.ready(onLoad); + }; + } -} + 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. + // 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 + // | dojo.ready(function(){ alert("Dom ready!"); }); + // + // example: + // Using a priority + // | dojo.ready(2, function(){ alert("low priority ready!"); }) + // + // example: + // Using context + // | dojo.ready(foo, function(){ + // | // in here, this == foo + // | }) + // + // example: + // Using dojo.hitch style args: + // | var foo = { dojoReady: function(){ console.warn(this, "dojo dom and modules ready."); } }; + // | dojo.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); + requestCompleteSignal(); + }; -if(!dojo._hasResource["dojo._base.browser"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojo._base.browser"] = true; -dojo.provide("dojo._base.browser"); + true || 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(1){ + domReady(handleDomReady); + }else{ + handleDomReady(); + } + return ready; +}); +}, +'dojo/aspect':function(){ +define([], function(){ +// TODOC: after/before/around return object +// TODOC: after/before/around param types. +/*===== + dojo.aspect = { + // 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 + // | }); + + 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. + }, + + 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 + }, + 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 + } + }; +=====*/ - //Need this to be the last code segment in base, so do not place any - //dojo/requireIf calls in this file/ Otherwise, due to how the build system - //puts all requireIf dependencies after the current file, the require calls - //could be called before all of base is defined/ - dojo.forEach(dojo.config.require, function(i){ - dojo["require"](i); - }); + "use strict"; + var nextId = 0; + 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(){ + signal.cancelled = true; + }, + advice: function(target, args){ + return signal.cancelled ? + previous.advice(target, args) : // cancelled, skip to next one + advised.apply(target, args); // called the advised function + } + }; + }else{ + // create the remove handler + signal = { + remove: function(){ + 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; + } + } + }, + id: nextId++, + advice: advice, + receiveArguments: receiveArguments + }; + } + if(previous && !around){ + if(type == "after"){ + // add the listener to the end of the list + var next = previous; + while(next){ + previous = next; + next = next.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 = nextId; + // before advice + var args = arguments; + var before = dispatcher.before; + while(before){ + 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){ + results = after.receiveArguments ? after.advice.apply(this, args) || results : + after.advice.call(this, results); + after = after.next; + } + return results; + }; + if(existing){ + dispatcher.around = {advice: function(target, args){ + return existing.apply(target, args); + }}; + } + dispatcher.target = target; + } + var results = advise((dispatcher || existing), type, advice, receiveArguments); + advice = null; + return results; + }; + } + return { + before: aspect("before"), + around: aspect("around"), + after: aspect("after") + }; +}); + +}, +'dojo/_base/connect':function(){ +define(["./kernel", "../on", "../topic", "../aspect", "./event", "../mouse", "./sniff", "./lang", "../keys"], function(kernel, on, hub, aspect, eventModule, mouse, has, lang){ +// module: +// dojo/_base/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. +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 || kernel.global, event, method, true); + } + if(typeof event == "string" && event.substring(0, 2) == "on"){ + event = event.substring(2); + } + if(!obj){ + obj = kernel.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 || (has("ie") >= 9 && !has("quirks"))) && 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); + }); + }; + } } -if(!dojo._hasResource["dojo._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. -dojo._hasResource["dojo._base"] = true; -dojo.provide("dojo._base"); +var connect = { + _keypress:keypress, + + connect:function(obj, event, context, method, dontFix){ + // 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