"&&!x?r.childNodes:[];for(o=k.length-
-1;o>=0;--o)c.nodeName(k[o],"tbody")&&!k[o].childNodes.length&&k[o].parentNode.removeChild(k[o])}!c.support.leadingWhitespace&&$.test(l)&&r.insertBefore(b.createTextNode($.exec(l)[0]),r.firstChild);l=r.childNodes}if(l.nodeType)f.push(l);else f=c.merge(f,l)}}if(d)for(h=0;f[h];h++)if(e&&c.nodeName(f[h],"script")&&(!f[h].type||f[h].type.toLowerCase()==="text/javascript"))e.push(f[h].parentNode?f[h].parentNode.removeChild(f[h]):f[h]);else{f[h].nodeType===1&&f.splice.apply(f,[h+1,0].concat(c.makeArray(f[h].getElementsByTagName("script"))));
-d.appendChild(f[h])}return f},cleanData:function(a){for(var b,d,e=c.cache,f=c.event.special,h=c.support.deleteExpando,l=0,k;(k=a[l])!=null;l++)if(!(k.nodeName&&c.noData[k.nodeName.toLowerCase()]))if(d=k[c.expando]){if((b=e[d])&&b.events)for(var o in b.events)f[o]?c.event.remove(k,o):c.removeEvent(k,o,b.handle);if(h)delete k[c.expando];else k.removeAttribute&&k.removeAttribute(c.expando);delete e[d]}}});var Ea=/alpha\([^)]*\)/i,gb=/opacity=([^)]*)/,hb=/-([a-z])/ig,ib=/([A-Z])/g,Fa=/^-?\d+(?:px)?$/i,
-jb=/^-?\d/,kb={position:"absolute",visibility:"hidden",display:"block"},Pa=["Left","Right"],Qa=["Top","Bottom"],W,Ga,aa,lb=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){if(arguments.length===2&&b===B)return this;return c.access(this,a,b,true,function(d,e,f){return f!==B?c.style(d,e,f):c.css(d,e)})};c.extend({cssHooks:{opacity:{get:function(a,b){if(b){var d=W(a,"opacity","opacity");return d===""?"1":d}else return a.style.opacity}}},cssNumber:{zIndex:true,fontWeight:true,opacity:true,
-zoom:true,lineHeight:true},cssProps:{"float":c.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,d,e){if(!(!a||a.nodeType===3||a.nodeType===8||!a.style)){var f,h=c.camelCase(b),l=a.style,k=c.cssHooks[h];b=c.cssProps[h]||h;if(d!==B){if(!(typeof d==="number"&&isNaN(d)||d==null)){if(typeof d==="number"&&!c.cssNumber[h])d+="px";if(!k||!("set"in k)||(d=k.set(a,d))!==B)try{l[b]=d}catch(o){}}}else{if(k&&"get"in k&&(f=k.get(a,false,e))!==B)return f;return l[b]}}},css:function(a,b,d){var e,f=c.camelCase(b),
-h=c.cssHooks[f];b=c.cssProps[f]||f;if(h&&"get"in h&&(e=h.get(a,true,d))!==B)return e;else if(W)return W(a,b,f)},swap:function(a,b,d){var e={},f;for(f in b){e[f]=a.style[f];a.style[f]=b[f]}d.call(a);for(f in b)a.style[f]=e[f]},camelCase:function(a){return a.replace(hb,lb)}});c.curCSS=c.css;c.each(["height","width"],function(a,b){c.cssHooks[b]={get:function(d,e,f){var h;if(e){if(d.offsetWidth!==0)h=oa(d,b,f);else c.swap(d,kb,function(){h=oa(d,b,f)});if(h<=0){h=W(d,b,b);if(h==="0px"&&aa)h=aa(d,b,b);
-if(h!=null)return h===""||h==="auto"?"0px":h}if(h<0||h==null){h=d.style[b];return h===""||h==="auto"?"0px":h}return typeof h==="string"?h:h+"px"}},set:function(d,e){if(Fa.test(e)){e=parseFloat(e);if(e>=0)return e+"px"}else return e}}});if(!c.support.opacity)c.cssHooks.opacity={get:function(a,b){return gb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var d=a.style;d.zoom=1;var e=c.isNaN(b)?"":"alpha(opacity="+b*100+")",f=
-d.filter||"";d.filter=Ea.test(f)?f.replace(Ea,e):d.filter+" "+e}};if(t.defaultView&&t.defaultView.getComputedStyle)Ga=function(a,b,d){var e;d=d.replace(ib,"-$1").toLowerCase();if(!(b=a.ownerDocument.defaultView))return B;if(b=b.getComputedStyle(a,null)){e=b.getPropertyValue(d);if(e===""&&!c.contains(a.ownerDocument.documentElement,a))e=c.style(a,d)}return e};if(t.documentElement.currentStyle)aa=function(a,b){var d,e,f=a.currentStyle&&a.currentStyle[b],h=a.style;if(!Fa.test(f)&&jb.test(f)){d=h.left;
-e=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;h.left=b==="fontSize"?"1em":f||0;f=h.pixelLeft+"px";h.left=d;a.runtimeStyle.left=e}return f===""?"auto":f};W=Ga||aa;if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetHeight;return a.offsetWidth===0&&b===0||!c.support.reliableHiddenOffsets&&(a.style.display||c.css(a,"display"))==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var mb=c.now(),nb=/
+ // |
+ 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("/");
+ }
+ }
+ }
+
+ uri = [];
+ if(relobj.scheme){
+ uri.push(relobj.scheme, ":");
+ }
+ if(relobj.authority){
+ uri.push("//", relobj.authority);
+ }
+ uri.push(relobj.path);
+ if(relobj.query){
+ uri.push("?", relobj.query);
+ }
+ if(relobj.fragment){
+ uri.push("#", relobj.fragment);
+ }
+ }
+
+ this.uri = uri.join("");
+
+ // break the uri into its main components
+ var r = this.uri.match(ore);
+
+ 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);
+
+ if(this.authority != n){
+ // server based naming authority
+ r = this.authority.match(ire);
+
+ this.user = r[3] || n;
+ this.password = r[4] || n;
+ this.host = r[6] || r[7]; // ipv6 || ipv4
+ this.port = r[9] || n;
+ }
+ }
+
+ 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;
+ }
+
+ return new d._Url(loc, url); // dojo._Url
+ };
+
+
+
+})();
+
+/*=====
+dojo.isBrowser = {
+ // example:
+ // | if(dojo.isBrowser){ ... }
+};
+
+dojo.isFF = {
+ // example:
+ // | if(dojo.isFF > 1){ ... }
+};
+
+dojo.isIE = {
+ // example:
+ // | if(dojo.isIE > 6){
+ // | // we are IE7
+ // | }
+};
+
+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.
+ // | }
+};
+
+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";
+
+
+ // 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];
+ }
+ }
+ break; // "first Dojo wins"
+ }
+ }
+ }
+ d.baseUrl = d.config.baseUrl;
+
+ // fill in the rendering support information in dojo.render.*
+ var n = navigator;
+ var dua = n.userAgent,
+ dav = n.appVersion,
+ tv = parseFloat(dav);
+
+ if(dua.indexOf("Opera") >= 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;
+
+ // 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;
+ }
+ }
+
+ 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;
+ }
+ }
+
+ //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";
+
+ // 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(http){
+ d._XMLHTTP_PROGIDS = [progid]; // so faster next time
+ break;
+ }
+ }
+ }
+
+ if(!http){
+ throw new Error("XMLHTTP not available: "+last_e);
+ }
+
+ 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)
+
+ // 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();
+ }
+
+ 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,"");
+ }
+
+ 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;
+ }
+ }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);
+ };
+
+
+ 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())();
+ }
+ 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);
+ }
+ };
+
+ 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(){ /* ... */});
+
+ d._onto(d._unloaders, obj, functionName);
+ if(!_onUnloadAttached){
+ _onUnloadAttached = 1;
+ _handleNodeEvent("onbeforeunload", dojo.unloaded);
+ }
+ };
+
+ })();
+
+ //START DOMContentLoaded
+ dojo._initFired = false;
+ dojo._loadInit = function(e){
+ if(dojo._scrollIntervalId){
+ clearInterval(dojo._scrollIntervalId);
+ dojo._scrollIntervalId = 0;
+ }
+
+ if(!dojo._initFired){
+ dojo._initFired = true;
+
+ //Help out IE to avoid memory leak.
+ if(!dojo.config.afterOnLoad && window.detachEvent){
+ window.detachEvent("onload", dojo._loadInit);
+ }
+
+ if(dojo._inFlightCount == 0){
+ dojo._modulesLoaded();
+ }
+ }
+ }
+
+ 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);
+
+ //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 (){
+ 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();
+ }
+ }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
+
+
+ /*
+ OpenAjax.subscribe("OpenAjax", "onload", function(){
+ if(dojo._inFlightCount == 0){
+ dojo._modulesLoaded();
+ }
+ });
+
+ OpenAjax.subscribe("OpenAjax", "onunload", function(){
+ dojo.unloaded();
+ });
+ */
+} //if (typeof window != 'undefined')
+
+//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]);
+ }
+ }
+})();
+
+//Load debug code if necessary.
+if(dojo.config.isDebug){
+ dojo.require("dojo._firebug.firebug");
+}
+
+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(!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");
+
+
+(function(){
+ var d = dojo, opts = Object.prototype.toString;
+
+ // Crockford (ish) functions
+
+ dojo.isString = function(/*anything*/ it){
+ // summary:
+ // Return true if it is a String
+ return (typeof it == "string" || it instanceof String); // Boolean
+ };
+
+ dojo.isArray = function(/*anything*/ it){
+ // summary:
+ // Return true if it is an Array.
+ // Does not work on Arrays created in other windows.
+ return it && (it instanceof Array || typeof it == "array"); // Boolean
+ };
+
+ dojo.isFunction = function(/*anything*/ it){
+ // summary:
+ // Return true if it is a Function
+ return opts.call(it) === "[object Function]";
+ };
+
+ dojo.isObject = function(/*anything*/ it){
+ // summary:
+ // Returns true if it is a JavaScript object (or an Array, a Function
+ // or null)
+ return it !== undefined &&
+ (it === null || typeof it == "object" || d.isArray(it) || d.isFunction(it)); // Boolean
+ };
+
+ dojo.isArrayLike = function(/*anything*/ it){
+ // summary:
+ // similar to dojo.isArray() but more permissive
+ // 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().
+ // returns:
+ // If it walks like a duck and quacks like a duck, return `true`
+ return it && it !== undefined && // Boolean
+ // keep out built-in constructors (Number, String, ...) which have length
+ // properties
+ !d.isString(it) && !d.isFunction(it) &&
+ !(it.tagName && it.tagName.toLowerCase() == 'form') &&
+ (d.isArray(it) || isFinite(it.length));
+ };
+
+ dojo.isAlien = function(/*anything*/ it){
+ // summary:
+ // Returns true if it is a built-in function or some other kind of
+ // oddball that *should* report as a function but doesn't
+ return it && !d.isFunction(it) && /\{\s*\[native code\]\s*\}/.test(String(it)); // Boolean
+ };
+
+ dojo.extend = function(/*Object*/ constructor, /*Object...*/ props){
+ // summary:
+ // Adds all properties and methods of props to constructor's
+ // prototype, making them available to all instances created with
+ // constructor.
+ for(var i=1, l=arguments.length; i 2){
+ return d._hitchArgs.apply(d, arguments); // Function
+ }
+ if(!method){
+ method = scope;
+ scope = null;
+ }
+ if(d.isString(method)){
+ scope = scope || d.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
+ };
+
+ /*=====
+ 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:
+ // The object to delegate to for properties not found directly on the
+ // return object or in props.
+ // props:
+ // 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
+ }
+ =====*/
+
+ dojo.delegate = dojo._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){
+ d._mixin(tmp, props);
+ }
+ return tmp; // Object
+ };
+ })();
+
+ /*=====
+ dojo._toArray = function(obj, offset, startWith){
+ // summary:
+ // Converts an array-like object (i.e. arguments, DOMCollection) to an
+ // array. Returns a new Array with the elements of obj.
+ // obj: Object
+ // the object to "arrayify". We expect the object to have, at a
+ // minimum, a length property which corresponds to integer-indexed
+ // properties.
+ // offset: Number?
+ // the location in obj to start iterating from. Defaults to 0.
+ // Optional.
+ // startWith: Array?
+ // An array to pack with the properties of obj. If provided,
+ // properties in obj are appended at the end of startWith and
+ // startWith is the returned array.
+ }
+ =====*/
+
+ var efficient = function(obj, offset, startWith){
+ return (startWith||[]).concat(Array.prototype.slice.call(obj, offset||0));
+ };
+
+ var slow = function(obj, offset, startWith){
+ var arr = startWith||[];
+ for(var x = offset || 0; x < obj.length; x++){
+ arr.push(obj[x]);
+ }
+ return arr;
+ };
+
+ dojo._toArray =
+ d.isIE ? function(obj){
+ return ((obj.item) ? slow : efficient).apply(this, arguments);
+ } :
+ efficient;
+
+ dojo.partial = function(/*Function|String*/method /*, ...*/){
+ // summary:
+ // similar to hitch() except that the scope object is left to be
+ // whatever the execution context eventually becomes.
+ // description:
+ // Calling dojo.partial is the functional equivalent of calling:
+ // | dojo.hitch(null, funcName, ...);
+ var arr = [ null ];
+ return d.hitch.apply(d, arr.concat(d._toArray(arguments))); // Function
+ };
+
+ var extraNames = d._extraNames, extraLen = extraNames.length, empty = {};
+
+ dojo.clone = function(/*anything*/ o){
+ // summary:
+ // Clones objects (including DOM nodes) and all children.
+ // Warning: do not clone cyclic structures.
+ if(!o || typeof o != "object" || d.isFunction(o)){
+ // null, undefined, any non-object, or function
+ return o; // anything
+ }
+ if(o.nodeType && "cloneNode" in o){
+ // DOM Node
+ return o.cloneNode(true); // Node
+ }
+ if(o instanceof Date){
+ // Date
+ return new Date(o.getTime()); // Date
+ }
+ if(o instanceof RegExp){
+ // RegExp
+ return new RegExp(o); // RegExp
+ }
+ var r, i, l, s, name;
+ if(d.isArray(o)){
+ // array
+ r = [];
+ for(i = 0, l = o.length; i < l; ++i){
+ if(i in o){
+ r.push(d.clone(o[i]));
+ }
+ }
+// we don't clone functions for performance reasons
+// }else if(d.isFunction(o)){
+// // function
+// r = function(){ return o.apply(this, arguments); };
+ }else{
+ // generic objects
+ r = o.constructor ? new o.constructor() : {};
+ }
+ for(name in o){
+ // the "tobj" condition avoid copying properties in "source"
+ // inherited from Object.prototype. For example, if target has a custom
+ // toString() method, don't overwrite it with the toString() method
+ // that source inherited from Object.prototype
+ s = o[name];
+ if(!(name in r) || (r[name] !== s && (!(name in empty) || empty[name] !== s))){
+ r[name] = d.clone(s);
+ }
+ }
+ // IE doesn't recognize some custom functions in for..in
+ if(extraLen){
+ for(i = 0; i < extraLen; ++i){
+ name = extraNames[i];
+ s = o[name];
+ if(!(name in r) || (r[name] !== s && (!(name in empty) || empty[name] !== s))){
+ r[name] = s; // functions only, we don't clone them
+ }
+ }
+ }
+ return r; // Object
+ };
+
+ /*=====
+ 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()
+ return ""; // String
+ }
+ =====*/
+
+ dojo.trim = String.prototype.trim ?
+ function(str){ return str.trim(); } :
+ function(str){ return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); };
+
+ /*=====
+ 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:
+ // | // 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:
+ // | // uses an array for substitutions:
+ // | dojo.replace("Hello, {0} {2}!",
+ // | ["Robert", "X", "Cringely"]);
+ // | // returns: Hello, Robert Cringely!
+ // example:
+ // | // 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;
+ // | }
+ // | }
+ // | )
+ // | );
+ // | // 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
+ }
+ =====*/
+
+ var _pattern = /\{([^\}]+)\}/g;
+ dojo.replace = function(tmpl, map, pattern){
+ return tmpl.replace(pattern || _pattern, d.isFunction(map) ?
+ map : function(_, k){ return d.getObject(k, false, map); });
+ };
+})();
+
+}
+
+if(!dojo._hasResource["dojo._base.array"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo._base.array"] = true;
+dojo.provide("dojo._base.array");
+
+
+
+(function(){
+ var _getParts = function(arr, obj, cb){
+ return [
+ (typeof arr == "string") ? arr.split("") : arr,
+ obj || dojo.global,
+ // FIXME: cache the anonymous functions we create here?
+ (typeof cb == "string") ? new Function("item", "index", "array", cb) : cb
+ ];
+ };
+
+ var everyOrSome = function(/*Boolean*/every, /*Array|String*/arr, /*Function|String*/callback, /*Object?*/thisObject){
+ var _p = _getParts(arr, thisObject, callback); arr = _p[0];
+ for(var i=0,l=arr.length; i end) || i < end){
+ for(; i != end; i += step){
+ if(array[i] == value){ return i; }
+ }
+ }
+ return -1; // Number
+ },
+
+ lastIndexOf: function(/*Array*/array, /*Object*/value, /*Integer?*/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
+ return dojo.indexOf(array, value, fromIndex, true); // Number
+ },
+
+ forEach: function(/*Array|String*/arr, /*Function|String*/callback, /*Object?*/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 implemenation 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")
+ // | );
+
+ // match the behavior of the built-in forEach WRT empty arrs
+ if(!arr || !arr.length){ return; }
+
+ // FIXME: there are several ways of handilng thisObject. Is
+ // dojo.global always the default context?
+ var _p = _getParts(arr, thisObject, callback); arr = _p[0];
+ for(var i=0,l=arr.length; i1; });
+ // example:
+ // | // returns true
+ // | dojo.every([1, 2, 3, 4], function(item){ return item>0; });
+ return everyOrSome(true, arr, callback, thisObject); // Boolean
+ },
+
+ some: function(/*Array|String*/arr, /*Function|String*/callback, /*Object?*/thisObject){
+ // summary:
+ // Determines whether or not any item in arr satisfies the
+ // condition implemented by callback.
+ // 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 and returns true if the condition is met.
+ // thisObject:
+ // may be used to scope the call to callback
+ // description:
+ // This function corresponds to the JavaScript 1.6 Array.some() method, with one difference: when
+ // run over sparse arrays, this implemenation 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; });
+ return everyOrSome(false, arr, callback, thisObject); // Boolean
+ },
+
+ map: function(/*Array|String*/arr, /*Function|String*/callback, /*Function?*/thisObject){
+ // summary:
+ // applies callback to each element of arr and returns
+ // an Array with the results
+ // arr:
+ // the array to iterate on. If a string, operates on
+ // individual characters.
+ // callback:
+ // a function is invoked with three arguments, (item, index,
+ // array), and returns a value
+ // thisObject:
+ // may be used to scope the call to callback
+ // description:
+ // This function corresponds to the JavaScript 1.6 Array.map() method, with one difference: when
+ // run over sparse arrays, this implemenation 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 });
+
+ var _p = _getParts(arr, thisObject, callback); arr = _p[0];
+ var outArr = (arguments[3] ? (new arguments[3]()) : []);
+ for(var i=0,l=arr.length; i1; });
+
+ var _p = _getParts(arr, thisObject, callback); arr = _p[0];
+ var outArr = [];
+ for(var i=0,l=arr.length; i= 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 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);
+ }
+
+ // 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){
+ var name, i = 0, l = d._extraNames.length;
+ // add props adding metadata for incoming functions skipping a constructor
+ for(name in source){
+ if(name != cname && source.hasOwnProperty(name)){
+ target[name] = source[name];
+ }
+ }
+ // process unenumerable methods on IE
+ for(; i < l; ++i){
+ name = d._extraNames[i];
+ if(name != cname && source.hasOwnProperty(name)){
+ target[name] = source[name];
+ }
+ }
+ }
+
+ // implementation of safe mixin function
+ function safeMixin(target, source){
+ var name, t, i = 0, l = d._extraNames.length;
+ // 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;
+ }
+ }
+ // process unenumerable methods on IE
+ for(; i < l; ++i){
+ name = d._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){
+ 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;
+ }
+
+ d.declare = function(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
+ 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.inherited = inherited;
+ proto.isInstanceOf = isInstanceOf;
+
+ // add name if specified
+ if(className){
+ proto.declaredClass = className;
+ d.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
+ };
+
+ d.safeMixin = safeMixin;
+
+ /*=====
+ 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
+ };
+ =====*/
+
+ /*=====
+ dojo.safeMixin = function(target, source){
+ // summary:
+ // 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 dojo._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
+ };
+ =====*/
+
+ /*=====
+ Object.inherited = function(name, args, newArgs){
+ // summary:
+ // Calls a super method.
+ // name: String?
+ // The optional method name. Should be the same as the caller's
+ // name. Usually "name" is specified in complex dynamic cases, when
+ // the calling method was dynamically added, undecorated by
+ // 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:
+ // 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.
+ //
+ // This method cannot me called from automatically chained
+ // constructors including the case of a special (legacy)
+ // constructor chaining. It cannot be called from chained methods.
+ //
+ // If "this.inherited()" cannot find the next-in-chain method, it
+ // does nothing and returns "undefined". The last method in chain
+ // can be a default method implemented in Object, which will be
+ // called last.
+ //
+ // If "name" is specified, it is assumed that the method that
+ // received "args" is the parent method for this call. It is looked
+ // up in the chain list and if it is found the next-in-chain method
+ // is called. If it is not found, the first-in-chain method is
+ // called.
+ //
+ // If "name" is not specified, it will be derived from the calling
+ // method (using a methoid property "nom").
+ //
+ // example:
+ // | var B = 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:
+ // | 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.
+ //
+ // 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:
+ // | var A = dojo.declare(null, {
+ // | m1: function(){},
+ // | s1: "Popokatepetl"
+ // | });
+ // | A.extend({
+ // | m1: function(){},
+ // | m2: function(){},
+ // | f1: true,
+ // | d1: 42
+ // | });
+ };
+ =====*/
+})();
+
+}
+
+if(!dojo._hasResource["dojo._base.connect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo._base.connect"] = true;
+dojo.provide("dojo._base.connect");
+
+
+
+// this file courtesy of the TurboAjax Group, licensed under a Dojo CLA
+
+// low-level delegation machinery
+dojo._listener = {
+ // create a dispatcher function
+ getDispatcher: function(){
+ // following comments pulled out-of-line to prevent cloning them
+ // in the returned function.
+ // - indices (i) that are really in the array of listeners (ls) will
+ // not be in Array.prototype. This is the 'sparse array' trick
+ // that keeps us safe from libs that take liberties with built-in
+ // objects
+ // - listener is invoked with current scope (this)
+ return function(){
+ var ap = Array.prototype, c = arguments.callee, ls = c._listeners, t = c.target,
+ // return value comes from original target function
+ r = t && t.apply(this, arguments),
+ // make local copy of listener array so it is immutable during processing
+ i, lls = [].concat(ls)
+ ;
+
+ // invoke listeners after target function
+ for(i in lls){
+ if(!(i in ap)){
+ lls[i].apply(this, arguments);
+ }
+ }
+ // return value comes from original target function
+ return r;
+ };
+ },
+ // add a listener to an object
+ add: function(/*Object*/ source, /*String*/ method, /*Function*/ listener){
+ // Whenever 'method' is invoked, 'listener' will have the same scope.
+ // Trying to supporting a context object for the listener led to
+ // complexity.
+ // Non trivial to provide 'once' functionality here
+ // because listener could be the result of a dojo.hitch call,
+ // in which case two references to the same hitch target would not
+ // be equivalent.
+ source = source || dojo.global;
+ // The source method is either null, a dispatcher, or some other function
+ var f = source[method];
+ // Ensure a dispatcher
+ if(!f || !f._listeners){
+ var d = dojo._listener.getDispatcher();
+ // original target function is special
+ d.target = f;
+ // dispatcher holds a list of listeners
+ d._listeners = [];
+ // redirect source to dispatcher
+ f = source[method] = d;
+ }
+ // The contract is that a handle is returned that can
+ // identify this listener for disconnect.
+ //
+ // The type of the handle is private. Here is it implemented as Integer.
+ // DOM event code has this same contract but handle is Function
+ // in non-IE browsers.
+ //
+ // We could have separate lists of before and after listeners.
+ return f._listeners.push(listener); /*Handle*/
+ },
+ // remove a listener from an object
+ remove: function(/*Object*/ source, /*String*/ method, /*Handle*/ handle){
+ var f = (source || dojo.global)[method];
+ // remember that handle is the index+1 (0 is not a valid handle)
+ if(f && f._listeners && handle--){
+ delete f._listeners[handle];
+ }
+ }
+};
+
+// Multiple delegation for arbitrary methods.
+
+// This unit knows nothing about DOM, but we include DOM aware documentation
+// and dontFix argument here to help the autodocs. Actual DOM aware code is in
+// event.js.
+
+dojo.connect = function(/*Object|null*/ obj,
+ /*String*/ event,
+ /*Object|null*/ context,
+ /*String|Function*/ method,
+ /*Boolean?*/ dontFix){
+ // summary:
+ // `dojo.connect` is the core event handling and delegation method in
+ // Dojo. It allows one function to "listen in" on the execution of
+ // any other, triggering the second whenever the first is called. Many
+ // listeners may be attached to a function, and source functions may
+ // be either regular function calls or DOM events.
+ //
+ // description:
+ // Connects listeners to actions, so that after event fires, a
+ // listener is called with the same arguments passed to the original
+ // function.
+ //
+ // Since `dojo.connect` allows the source of events to be either a
+ // "regular" JavaScript function or a DOM event, it provides a uniform
+ // interface for listening to all the types of events that an
+ // application is likely to deal with though a single, unified
+ // interface. DOM programmers may want to think of it as
+ // "addEventListener for everything and anything".
+ //
+ // When setting up a connection, the `event` parameter must be a
+ // string that is the name of the method/event to be listened for. If
+ // `obj` is null, `dojo.global` is assumed, meaning that connections
+ // to global methods are supported but also that you may inadvertently
+ // connect to a global by passing an incorrect object name or invalid
+ // reference.
+ //
+ // `dojo.connect` generally is forgiving. If you pass the name of a
+ // function or method that does not yet exist on `obj`, connect will
+ // not fail, but will instead set up a stub method. Similarly, null
+ // arguments may simply be omitted such that fewer than 4 arguments
+ // may be required to set up a connection See the examples for details.
+ //
+ // The return value is a handle that is needed to
+ // remove this connection with `dojo.disconnect`.
+ //
+ // obj:
+ // The source object for the event function.
+ // Defaults to `dojo.global` if null.
+ // If obj is a DOM node, the connection is delegated
+ // to the DOM event manager (unless dontFix is true).
+ //
+ // event:
+ // String name of the event function in obj.
+ // I.e. identifies a property `obj[event]`.
+ //
+ // context:
+ // The object that method will receive as "this".
+ //
+ // If context is null and method is a function, then method
+ // inherits the context of event.
+ //
+ // If method is a string then context must be the source
+ // object object for method (context[method]). If context is null,
+ // dojo.global is used.
+ //
+ // method:
+ // A function reference, or name of a function in context.
+ // The function identified by method fires after event does.
+ // method receives the same arguments as the event.
+ // See context argument comments for information on method's scope.
+ //
+ // dontFix:
+ // If obj is a DOM node, set dontFix to true to prevent delegation
+ // of this connection to the DOM event manager.
+ //
+ // example:
+ // When obj.onchange(), do ui.update():
+ // | dojo.connect(obj, "onchange", ui, "update");
+ // | dojo.connect(obj, "onchange", ui, ui.update); // same
+ //
+ // example:
+ // Using return value for disconnect:
+ // | var link = dojo.connect(obj, "onchange", ui, "update");
+ // | ...
+ // | dojo.disconnect(link);
+ //
+ // example:
+ // When onglobalevent executes, watcher.handler is invoked:
+ // | dojo.connect(null, "onglobalevent", watcher, "handler");
+ //
+ // example:
+ // When ob.onCustomEvent executes, customEventHandler is invoked:
+ // | dojo.connect(ob, "onCustomEvent", null, "customEventHandler");
+ // | dojo.connect(ob, "onCustomEvent", "customEventHandler"); // same
+ //
+ // example:
+ // When ob.onCustomEvent executes, customEventHandler is invoked
+ // with the same scope (this):
+ // | dojo.connect(ob, "onCustomEvent", null, customEventHandler);
+ // | dojo.connect(ob, "onCustomEvent", customEventHandler); // same
+ //
+ // example:
+ // When globalEvent executes, globalHandler is invoked
+ // with the same scope (this):
+ // | dojo.connect(null, "globalEvent", null, globalHandler);
+ // | dojo.connect("globalEvent", globalHandler); // same
+
+ // normalize arguments
+ var a=arguments, args=[], i=0;
+ // if a[0] is a String, obj was omitted
+ args.push(dojo.isString(a[0]) ? 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(dojo.isString(a1)||dojo.isFunction(a1) ? a[i++] : null, a[i++]);
+ // absorb any additional arguments
+ for(var l=a.length; i44
+ //
+ var returnDeferred = progressCallback == mutator ? this : new dojo.Deferred(promise.cancel);
+ var listener = {
+ resolved: resolvedCallback,
+ error: errorCallback,
+ progress: progressCallback,
+ deferred: returnDeferred
+ };
+ if(nextListener){
+ head = head.next = listener;
+ }
+ else{
+ nextListener = head = listener;
+ }
+ if(finished){
+ notify();
+ }
+ return returnDeferred.promise;
+ };
+ var deferred = this;
+ this.cancel = promise.cancel = function () {
+ // summary:
+ // Cancels the asynchronous operation
+ if(!finished){
+ var error = canceller && canceller(deferred);
+ if(!finished){
+ if (!(error instanceof Error)) {
+ error = new Error(error);
+ }
+ error.log = false;
+ deferred.reject(error);
+ }
+ }
+ };
+ freeze(promise);
+ };
+ dojo.extend(dojo.Deferred, {
+ addCallback: function (/*Function*/callback) {
+ return this.addCallbacks(dojo.hitch.apply(dojo, arguments));
+ },
+
+ addErrback: function (/*Function*/errback) {
+ return this.addCallbacks(null, dojo.hitch.apply(dojo, arguments));
+ },
+
+ addBoth: function (/*Function*/callback) {
+ var enclosed = dojo.hitch.apply(dojo, arguments);
+ return this.addCallbacks(enclosed, enclosed);
+ },
+ fired: -1
+ });
+})();
+dojo.when = function(promiseOrValue, /*Function?*/callback, /*Function?*/errback, /*Function?*/progressHandler){
+ // summary:
+ // This provides normalization between normal synchronous values and
+ // asynchronous promises, so you can interact with them in a common way
+ // example:
+ // | function printFirstAndList(items){
+ // | dojo.when(findFirst(items), console.log);
+ // | dojo.when(findLast(items), console.log);
+ // | }
+ // | function findFirst(items){
+ // | return dojo.when(items, function(items){
+ // | return items[0];
+ // | });
+ // | }
+ // | function findLast(items){
+ // | return dojo.when(items, function(items){
+ // | return items[items.length];
+ // | });
+ // | }
+ // And now all three of his functions can be used sync or async.
+ // | printFirstAndLast([1,2,3,4]) will work just as well as
+ // | printFirstAndLast(dojo.xhrGet(...));
+
+ if(promiseOrValue && typeof promiseOrValue.then === "function"){
+ return promiseOrValue.then(callback, errback, progressHandler);
+ }
+ return callback(promiseOrValue);
+};
+
+}
+
+if(!dojo._hasResource["dojo._base.json"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo._base.json"] = true;
+dojo.provide("dojo._base.json");
+
+
+dojo.fromJson = function(/*String*/ json){
+ // summary:
+ // Parses a [JSON](http://json.org) string to return a JavaScript object.
+ // description:
+ // Throws for invalid JSON strings, but it does not use a strict JSON parser. It
+ // delegates to eval(). The content passed to this method must therefore come
+ // from a trusted source.
+ // json:
+ // a string literal of a JSON item, for instance:
+ // `'{ "foo": [ "bar", 1, { "baz": "thud" } ] }'`
+
+ return eval("(" + json + ")"); // Object
+};
+
+dojo._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
+};
+
+dojo.toJsonIndentStr = "\t";
+dojo.toJson = function(/*Object*/ it, /*Boolean?*/ prettyPrint, /*String?*/ _indentStr){
+ // 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:
+ // 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.
+ // 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().
+ // _indentStr:
+ // private variable for recursive calls when pretty printing, do not use.
+ // 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(){
+ // | },
+ // | });
+
+ if(it === undefined){
+ return "undefined";
+ }
+ var objtype = typeof it;
+ if(objtype == "number" || objtype == "boolean"){
+ return it + "";
+ }
+ if(it === null){
+ return "null";
+ }
+ if(dojo.isString(it)){
+ return dojo._escapeString(it);
+ }
+ // recurse
+ var recurse = arguments.callee;
+ // short-circuit for objects that support "json" serialization
+ // if they return "self" then just pass-through...
+ var newObj;
+ _indentStr = _indentStr || "";
+ var nextIndent = prettyPrint ? _indentStr + dojo.toJsonIndentStr : "";
+ var tf = it.__json__||it.json;
+ if(dojo.isFunction(tf)){
+ newObj = tf.call(it);
+ if(it !== newObj){
+ return recurse(newObj, prettyPrint, nextIndent);
+ }
+ }
+ if(it.nodeType && it.cloneNode){ // isNode
+ // we can't seriailize DOM nodes as regular objects because they have cycles
+ // DOM nodes could be serialized with something like outerHTML, but
+ // that can be provided by users in the form of .json or .__json__ function.
+ throw new Error("Can't serialize DOM nodes");
+ }
+
+ var sep = prettyPrint ? " " : "";
+ var newLine = prettyPrint ? "\n" : "";
+
+ // array
+ if(dojo.isArray(it)){
+ var res = dojo.map(it, function(obj){
+ var val = recurse(obj, prettyPrint, nextIndent);
+ if(typeof val != "string"){
+ val = "undefined";
+ }
+ return newLine + nextIndent + val;
+ });
+ return "[" + res.join("," + sep) + newLine + _indentStr + "]";
+ }
+ /*
+ // look in the registry
+ try {
+ window.o = it;
+ newObj = dojo.json.jsonRegistry.match(it);
+ return recurse(newObj, prettyPrint, nextIndent);
+ }catch(e){
+ // console.log(e);
+ }
+ // it's a function with no adapter, skip it
+ */
+ if(objtype == "function"){
+ return null; // null
+ }
+ // generic object code path
+ var output = [], key;
+ for(key in it){
+ var keyStr, val;
+ if(typeof key == "number"){
+ keyStr = '"' + key + '"';
+ }else if(typeof key == "string"){
+ keyStr = dojo._escapeString(key);
+ }else{
+ // skip non-string or number keys
+ continue;
+ }
+ val = recurse(it[key], prettyPrint, nextIndent);
+ if(typeof val != "string"){
+ // skip non-serializable values
+ continue;
+ }
+ // FIXME: use += on Moz!!
+ // MOW NOTE: using += is a pain because you have to account for the dangling comma...
+ output.push(newLine + nextIndent + keyStr + ":" + sep + val);
+ }
+ return "{" + output.join("," + sep) + newLine + _indentStr + "}"; // String
+};
+
+}
+
+if(!dojo._hasResource["dojo._base.Color"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo._base.Color"] = true;
+dojo.provide("dojo._base.Color");
+
+
+
+
+(function(){
+
+ var d = dojo;
+
+ 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); }
+ };
+
+ // FIXME:
+ // there's got to be a more space-efficient way to encode or discover
+ // these!! Use hex?
+ dojo.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: d.config.transparentColor || [255,255,255]
+ };
+
+ dojo.extend(dojo.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(d.isString(color)){
+ d.colorFromString(color, this);
+ }else if(d.isArray(color)){
+ d.colorFromArray(color, this);
+ }else{
+ this._set(color.r, color.g, color.b, color.a);
+ if(!(color instanceof d.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 = d.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.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 d.Color();
+ d.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.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 && dojo.colorFromArray(m[1].split(/\s*,\s*/), obj); // dojo.Color
+ };
+
+ 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 d.Color(),
+ bits = (color.length == 4) ? 4 : 8,
+ mask = (1 << bits) - 1;
+ color = Number("0x" + color.substr(1));
+ if(isNaN(color)){
+ return null; // dojo.Color
+ }
+ d.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.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 d.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.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 = d.Color.named[str];
+ return a && d.colorFromArray(a, obj) || d.colorFromRgb(str, obj) || d.colorFromHex(str, obj);
+ };
+})();
+
+}
+
+if(!dojo._hasResource["dojo._base.window"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo._base.window"] = true;
+dojo.provide("dojo._base.window");
+
+
+/*=====
+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 = window["document"] || null;
+
+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'));
+
+ // 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 = globalObject;
+ dojo.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 = globalObject;
+ return dojo.withDoc.call(null, globalObject.document, callback, thisObject, cbArguments);
+ }finally{
+ dojo.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,
+ oldLtr = dojo._bodyLtr,
+ oldQ = dojo.isQuirks;
+
+ try{
+ dojo.doc = documentObject;
+ delete dojo._bodyLtr; // uncache
+ dojo.isQuirks = dojo.doc.compatMode == "BackCompat"; // no need to check for QuirksMode which was Opera 7 only
+
+ if(thisObject && typeof callback == "string"){
+ callback = thisObject[callback];
+ }
+
+ return callback.apply(thisObject, cbArguments || []);
+ }finally{
+ dojo.doc = oldDoc;
+ delete dojo._bodyLtr; // in case it was undefined originally, and set to true/false by the alternate document
+ if(oldLtr !== undefined){ dojo._bodyLtr = oldLtr; }
+ dojo.isQuirks = oldQ;
+ }
+};
+
+}
+
+if(!dojo._hasResource["dojo._base.event"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo._base.event"] = true;
+dojo.provide("dojo._base.event");
+
+
+
+// this file courtesy of the TurboAjax Group, licensed under a Dojo CLA
+
+(function(){
+ // DOM event listener machinery
+ var del = (dojo._event_listener = {
+ add: function(/*DOMNode*/ node, /*String*/ name, /*Function*/ fp){
+ if(!node){return;}
+ name = del._normalizeEventName(name);
+ fp = del._fixCallback(name, fp);
+ if(
+ !dojo.isIE &&
+ (name == "mouseenter" || name == "mouseleave")
+ ){
+ var ofp = fp;
+ name = (name == "mouseenter") ? "mouseover" : "mouseout";
+ fp = function(e){
+ if(!dojo.isDescendant(e.relatedTarget, node)){
+ // e.type = oname; // FIXME: doesn't take? SJM: event.type is generally immutable.
+ return ofp.call(this, e);
+ }
+ }
+ }
+ node.addEventListener(name, fp, false);
+ return fp; /*Handle*/
+ },
+ remove: function(/*DOMNode*/ node, /*String*/ event, /*Handle*/ handle){
+ // summary:
+ // clobbers the listener from the node
+ // node:
+ // DOM node to attach the event to
+ // event:
+ // the name of the handler to remove the function from
+ // handle:
+ // the handle returned from add
+ if(node){
+ event = del._normalizeEventName(event);
+ if(!dojo.isIE && (event == "mouseenter" || event == "mouseleave")){
+ event = (event == "mouseenter") ? "mouseover" : "mouseout";
+ }
+
+ node.removeEventListener(event, handle, false);
+ }
+ },
+ _normalizeEventName: function(/*String*/ name){
+ // Generally, name should be lower case, unless it is special
+ // somehow (e.g. a Mozilla DOM event).
+ // Remove 'on'.
+ return name.slice(0,2) =="on" ? name.slice(2) : name;
+ },
+ _fixCallback: function(/*String*/ name, fp){
+ // By default, we only invoke _fixEvent for 'keypress'
+ // If code is added to _fixEvent for other events, we have
+ // to revisit this optimization.
+ // This also applies to _fixEvent overrides for Safari and Opera
+ // below.
+ return name != "keypress" ? fp : function(e){ return fp.call(this, del._fixEvent(e, this)); };
+ },
+ _fixEvent: function(evt, sender){
+ // _fixCallback only attaches us to keypress.
+ // Switch on evt.type anyway because we might
+ // be called directly from dojo.fixEvent.
+ switch(evt.type){
+ case "keypress":
+ del._setKeyChar(evt);
+ break;
+ }
+ return evt;
+ },
+ _setKeyChar: function(evt){
+ evt.keyChar = evt.charCode >= 32 ? String.fromCharCode(evt.charCode) : '';
+ evt.charOrCode = evt.keyChar || evt.keyCode;
+ },
+ // For IE and Safari: some ctrl-key combinations (mostly w/punctuation) do not emit a char code in IE
+ // we map those virtual key codes to ascii here
+ // not valid for all (non-US) keyboards, so maybe we shouldn't bother
+ _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
+ }
+ });
+
+ // DOM events
+
+ dojo.fixEvent = function(/*Event*/ evt, /*DOMNode*/ sender){
+ // summary:
+ // 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"
+ return del._fixEvent(evt, sender);
+ };
+
+ 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.
+ evt.preventDefault();
+ evt.stopPropagation();
+ // NOTE: below, this method is overridden for IE
+ };
+
+ // the default listener to use on dontFix nodes, overriden for IE
+ var node_listener = dojo._listener;
+
+ // Unify connect and event listeners
+ dojo._connect = function(obj, event, context, method, dontFix){
+ // FIXME: need a more strict test
+ var isNode = obj && (obj.nodeType||obj.attachEvent||obj.addEventListener);
+ // choose one of three listener options: raw (connect.js), DOM event on a Node, custom event on a Node
+ // we need the third option to provide leak prevention on broken browsers (IE)
+ var lid = isNode ? (dontFix ? 2 : 1) : 0, l = [dojo._listener, del, node_listener][lid];
+ // create a listener
+ var h = l.add(obj, event, dojo.hitch(context, method));
+ // formerly, the disconnect package contained "l" directly, but if client code
+ // leaks the disconnect package (by connecting it to a node), referencing "l"
+ // compounds the problem.
+ // instead we return a listener id, which requires custom _disconnect below.
+ // return disconnect package
+ return [ obj, event, h, lid ];
+ };
+
+ dojo._disconnect = function(obj, event, handle, listener){
+ ([dojo._listener, del, node_listener][listener]).remove(obj, event, handle);
+ };
+
+ // Constants
+
+ // Public: client code should test
+ // keyCode against these named constants, as the
+ // actual codes can vary by browser.
+ dojo.keys = {
+ // summary:
+ // Definitions for common key values
+ BACKSPACE: 8,
+ TAB: 9,
+ CLEAR: 12,
+ ENTER: 13,
+ SHIFT: 16,
+ CTRL: 17,
+ ALT: 18,
+ META: dojo.isSafari ? 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,
+ // virtual key mapping
+ copyKey: dojo.isMac && !dojo.isAIR ? (dojo.isSafari ? 91 : 224 ) : 17
+ };
+
+ var evtCopyKey = dojo.isMac ? "metaKey" : "ctrlKey";
+
+ dojo.isCopyKey = function(e){
+ // summary:
+ // Checks an event for the copy key (meta on Mac, and ctrl anywhere else)
+ // e: Event
+ // Event object to examine
+ return e[evtCopyKey]; // Boolean
+ };
+
+ // Public: decoding mouse buttons from events
+
+/*=====
+ dojo.mouseButtons = {
+ // LEFT: Number
+ // Numeric value of the left mouse button for the platform.
+ LEFT: 0,
+ // MIDDLE: Number
+ // Numeric value of the middle mouse button for the platform.
+ MIDDLE: 1,
+ // RIGHT: Number
+ // Numeric value of the right mouse button for the platform.
+ RIGHT: 2,
+
+ isButton: function(e, button){
+ // summary:
+ // Checks an event object for a pressed button
+ // e: Event
+ // Event object to examine
+ // button: Number
+ // The button value (example: dojo.mouseButton.LEFT)
+ return e.button == button; // Boolean
+ },
+ isLeft: function(e){
+ // summary:
+ // Checks an event object for the pressed left button
+ // e: Event
+ // Event object to examine
+ return e.button == 0; // Boolean
+ },
+ isMiddle: function(e){
+ // summary:
+ // Checks an event object for the pressed middle button
+ // e: Event
+ // Event object to examine
+ return e.button == 1; // Boolean
+ },
+ isRight: function(e){
+ // summary:
+ // Checks an event object for the pressed right button
+ // e: Event
+ // Event object to examine
+ return e.button == 2; // Boolean
+ }
+ };
+=====*/
+
+ if(dojo.isIE < 9 || (dojo.isIE && dojo.isQuirks)){
+ dojo.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{
+ dojo.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; }
+ };
+ }
+
+ // IE event normalization
+ if(dojo.isIE){
+ 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;
+ }
+ };
+
+ // by default, use the standard listener
+ var iel = dojo._listener;
+ var listenersName = (dojo._ieListenersName = "_" + dojo._scopeName + "_listeners");
+ // dispatcher tracking property
+ if(!dojo.config._allow_leaks){
+ // custom listener that handles leak protection for DOM events
+ node_listener = iel = dojo._ie_listener = {
+ // support handler indirection: event handler functions are
+ // referenced here. Event dispatchers hold only indices.
+ handlers: [],
+ // add a listener to an object
+ add: function(/*Object*/ source, /*String*/ method, /*Function*/ listener){
+ source = source || dojo.global;
+ var f = source[method];
+ if(!f||!f[listenersName]){
+ var d = dojo._getIeDispatcher();
+ // original target function is special
+ d.target = f && (ieh.push(f) - 1);
+ // dispatcher holds a list of indices into handlers table
+ d[listenersName] = [];
+ // redirect source to dispatcher
+ f = source[method] = d;
+ }
+ return f[listenersName].push(ieh.push(listener) - 1) ; /*Handle*/
+ },
+ // remove a listener from an object
+ remove: function(/*Object*/ source, /*String*/ method, /*Handle*/ handle){
+ var f = (source||dojo.global)[method], l = f && f[listenersName];
+ if(f && l && handle--){
+ delete ieh[l[handle]];
+ delete l[handle];
+ }
+ }
+ };
+ // alias used above
+ var ieh = iel.handlers;
+ }
+
+ dojo.mixin(del, {
+ add: function(/*DOMNode*/ node, /*String*/ event, /*Function*/ fp){
+ if(!node){return;} // undefined
+ event = del._normalizeEventName(event);
+ if(event=="onkeypress"){
+ // we need to listen to onkeydown to synthesize
+ // keypress events that otherwise won't fire
+ // on IE
+ var kd = node.onkeydown;
+ if(!kd || !kd[listenersName] || !kd._stealthKeydownHandle){
+ var h = del.add(node, "onkeydown", del._stealthKeyDown);
+ kd = node.onkeydown;
+ kd._stealthKeydownHandle = h;
+ kd._stealthKeydownRefs = 1;
+ }else{
+ kd._stealthKeydownRefs++;
+ }
+ }
+ return iel.add(node, event, del._fixCallback(fp));
+ },
+ remove: function(/*DOMNode*/ node, /*String*/ event, /*Handle*/ handle){
+ event = del._normalizeEventName(event);
+ iel.remove(node, event, handle);
+ if(event=="onkeypress"){
+ var kd = node.onkeydown;
+ if(--kd._stealthKeydownRefs <= 0){
+ iel.remove(node, "onkeydown", kd._stealthKeydownHandle);
+ delete kd._stealthKeydownHandle;
+ }
+ }
+ },
+ _normalizeEventName: function(/*String*/ eventName){
+ // Generally, eventName should be lower case, unless it is
+ // special somehow (e.g. a Mozilla event)
+ // ensure 'on'
+ return eventName.slice(0,2) != "on" ? "on" + eventName : eventName;
+ },
+ _nop: function(){},
+ _fixEvent: function(/*Event*/ evt, /*DOMNode*/ 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);}
+ evt.target = evt.srcElement;
+ evt.currentTarget = (sender || evt.srcElement);
+ evt.layerX = evt.offsetX;
+ evt.layerY = evt.offsetY;
+ // FIXME: scroll position query is duped from dojo.html to
+ // avoid dependency on that entire module. Now that HTML is in
+ // Base, we should convert back to something similar there.
+ var se = evt.srcElement, doc = (se && se.ownerDocument) || document;
+ // DO NOT replace the following to use dojo.body(), in IE, document.documentElement should be used
+ // here rather than document.body
+ var docBody = ((dojo.isIE < 6) || (doc["compatMode"] == "BackCompat")) ? doc.body : doc.documentElement;
+ var offset = dojo._getIeDocumentElementOffset();
+ evt.pageX = evt.clientX + dojo._fixIeBiDiScrollLeft(docBody.scrollLeft || 0) - offset.x;
+ evt.pageY = evt.clientY + (docBody.scrollTop || 0) - offset.y;
+ if(evt.type == "mouseover"){
+ evt.relatedTarget = evt.fromElement;
+ }
+ if(evt.type == "mouseout"){
+ evt.relatedTarget = evt.toElement;
+ }
+ if (dojo.isIE < 9 || dojo.isQuirks) {
+ evt.stopPropagation = del._stopPropagation;
+ evt.preventDefault = del._preventDefault;
+ }
+ return del._fixKeys(evt);
+ },
+ _fixKeys: function(evt){
+ 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;
+ del._setKeyChar(evt);
+ break;
+ }
+ return evt;
+ },
+ _stealthKeyDown: function(evt){
+ // IE doesn't fire keypress for most non-printable characters.
+ // other browsers do, we simulate it here.
+ var kp = evt.currentTarget.onkeypress;
+ // only works if kp exists and is a dispatcher
+ if(!kp || !kp[listenersName]){ return; }
+ // 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 || (dojo.isIE >= 9 && !dojo.isQuirks)) && k!=32 && k!=27 && (k<48||k>90) && (k<96||k>111) && (k<186||k>192) && (k<219||k>222);
+
+ // 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; // 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 = del._punctMap[c] || c; // map other problematic CTRL combinations to ASCII
+ }
+ }
+ // simulate a keypress event
+ var faux = del._synthesizeEvent(evt, {type: 'keypress', faux: true, charCode: c});
+ kp.call(evt.currentTarget, faux);
+ if(dojo.isIE < 9 || (dojo.isIE && dojo.isQuirks)){
+ evt.cancelBubble = faux.cancelBubble;
+ }
+ evt.returnValue = faux.returnValue;
+ _trySetKeyCode(evt, faux.keyCode);
+ }
+ },
+ // Called in Event scope
+ _stopPropagation: function(){
+ this.cancelBubble = true;
+ },
+ _preventDefault: function(){
+ // Setting keyCode to 0 is the only way to prevent certain keypresses (namely
+ // ctrl-combinations that correspond to menu accelerator keys).
+ // Otoh, it prevents upstream listeners from getting this information
+ // Try to split the difference here by clobbering keyCode only for ctrl
+ // combinations. If you still need to access the key upstream, bubbledKeyCode is
+ // provided as a workaround.
+ this.bubbledKeyCode = this.keyCode;
+ if(this.ctrlKey){_trySetKeyCode(this, 0);}
+ this.returnValue = false;
+ }
+ });
+
+ // override stopEvent for IE
+ dojo.stopEvent = (dojo.isIE < 9 || dojo.isQuirks) ? function(evt){
+ evt = evt || window.event;
+ del._stopPropagation.call(evt);
+ del._preventDefault.call(evt);
+ } : dojo.stopEvent;
+ }
+
+ del._synthesizeEvent = function(evt, props){
+ var faux = dojo.mixin({}, evt, props);
+ del._setKeyChar(faux);
+ // FIXME: would prefer to use dojo.hitch: dojo.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;
+ };
+
+ // Opera event normalization
+ if(dojo.isOpera){
+ dojo.mixin(del, {
+ _fixEvent: function(evt, sender){
+ switch(evt.type){
+ case "keypress":
+ 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<41 && !evt.shiftKey ? 0 : c;
+ if(evt.ctrlKey && !evt.shiftKey && c>=65 && c<=90){
+ // lowercase CTRL-[A-Z] keys
+ c += 32;
+ }
+ return del._synthesizeEvent(evt, { charCode: c });
+ }
+ return evt;
+ }
+ });
+ }
+
+ // Webkit event normalization
+ if(dojo.isWebKit){
+ del._add = del.add;
+ del._remove = del.remove;
+
+ dojo.mixin(del, {
+ add: function(/*DOMNode*/ node, /*String*/ event, /*Function*/ fp){
+ if(!node){return;} // undefined
+ var handle = del._add(node, event, fp);
+ if(del._normalizeEventName(event) == "keypress"){
+ // we need to listen to onkeydown to synthesize
+ // keypress events that otherwise won't fire
+ // in Safari 3.1+: https://lists.webkit.org/pipermail/webkit-dev/2007-December/002992.html
+ handle._stealthKeyDownHandle = del._add(node, "keydown", function(evt){
+ //A variation on the IE _stealthKeydown function
+ //Synthesize an onkeypress event, but only for unprintable characters.
+ var k=evt.keyCode;
+ // These are Windows Virtual Key Codes
+ // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp
+ var unprintable = k!=13 && k!=32 && (k<48 || k>90) && (k<96 || k>111) && (k<186 || k>192) && (k<219 || k>222);
+ // 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; // 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 = del._punctMap[c] || c; // map other problematic CTRL combinations to ASCII
+ }
+ }
+ // simulate a keypress event
+ var faux = del._synthesizeEvent(evt, {type: 'keypress', faux: true, charCode: c});
+ fp.call(evt.currentTarget, faux);
+ }
+ });
+ }
+ return handle; /*Handle*/
+ },
+
+ remove: function(/*DOMNode*/ node, /*String*/ event, /*Handle*/ handle){
+ if(node){
+ if(handle._stealthKeyDownHandle){
+ del._remove(node, "keydown", handle._stealthKeyDownHandle);
+ }
+ del._remove(node, event, handle);
+ }
+ },
+ _fixEvent: function(evt, sender){
+ switch(evt.type){
+ case "keypress":
+ if(evt.faux){ return evt; }
+ var c = evt.charCode;
+ c = c>=32 ? c : 0;
+ return del._synthesizeEvent(evt, {charCode: c, faux: true});
+ }
+ return evt;
+ }
+ });
+ }
+ })();
+
+if(dojo.isIE){
+ // keep this out of the closure
+ // closing over 'iel' or 'ieh' b0rks leak prevention
+ // ls[i] is an index into the master handler array
+ dojo._ieDispatcher = function(args, sender){
+ var ap = Array.prototype,
+ h = dojo._ie_listener.handlers,
+ c = args.callee,
+ ls = c[dojo._ieListenersName],
+ t = h[c.target];
+ // return value comes from original target function
+ var r = t && t.apply(sender, args);
+ // make local copy of listener array so it's immutable during processing
+ var lls = [].concat(ls);
+ // invoke listeners after target function
+ for(var i in lls){
+ var f = h[lls[i]];
+ if(!(i in ap) && f){
+ f.apply(sender, args);
+ }
+ }
+ return r;
+ };
+ dojo._getIeDispatcher = function(){
+ // ensure the returned function closes over nothing ("new Function" apparently doesn't close)
+ return new Function(dojo._scopeName + "._ieDispatcher(arguments, this)"); // function
+ };
+ // keep this out of the closure to reduce RAM allocation
+ dojo._event_listener._fixCallback = function(fp){
+ var f = dojo._event_listener._fixEvent;
+ return function(e){ return fp.call(this, f(e, this)); };
+ };
+}
+
+}
+
+if(!dojo._hasResource["dojo._base.html"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dojo._base.html"] = true;
+dojo.provide("dojo._base.html");
+
+
+
+// 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.
+ //
+ // id: String|DOMNode
+ // A string to match an HTML id attribute or a reference to a DOM Node
+ //
+ // doc: Document?
+ // Document to work in. Defaults to the current value of
+ // dojo.doc. Can be used to retrieve
+ // node references from other documents.
+ //
+ // example:
+ // Look up a node by ID:
+ // | var n = dojo.byId("foo");
+ //
+ // example:
+ // Check if a node exists, and use it.
+ // | var n = dojo.byId("bar");
+ // | if(n){ doStuff() ... }
+ //
+ // example:
+ // Allow string or DomNode references to be passed to a custom function:
+ // | var foo = function(nodeOrId){
+ // | nodeOrId = dojo.byId(nodeOrId);
+ // | // ... more stuff
+ // | }
+=====*/
+
+if(dojo.isIE){
+ dojo.byId = function(id, doc){
+ if(typeof id != "string"){
+ return id;
+ }
+ var _d = doc || dojo.doc, te = _d.getElementById(id);
+ // attributes.id.value is better than just id in case the
+ // user has a name=id inside a form
+ if(te && (te.attributes.id.value == id || te.id == id)){
+ return te;
+ }else{
+ var eles = _d.all[id];
+ if(!eles || eles.nodeName){
+ eles = [eles];
+ }
+ // if more than 1, choose first with the correct id
+ var i=0;
+ while((te=eles[i++])){
+ if((te.attributes && te.attributes.id && te.attributes.id.value == id)
+ || te.id == id){
+ return te;
+ }
+ }
+ }
+ };
+}else{
+ dojo.byId = function(id, doc){
+ // inline'd type check.
+ // be sure to return null per documentation, to match IE branch.
+ return ((typeof id == "string") ? (doc || dojo.doc).getElementById(id) : id) || null; // DomNode
+ };
+}
+/*=====
+};
+=====*/
+
+(function(){
+ var d = dojo;
+ var byId = d.byId;
+
+ var _destroyContainer = null,
+ _destroyDoc;
+ d.addOnWindowUnload(function(){
+ _destroyContainer = null; //prevent IE leak
+ });
+
+/*=====
+ dojo._destroyElement = function(node){
+ // summary:
+ // Existing alias for `dojo.destroy`. Deprecated, will be removed
+ // in 2.0
+ }
+=====*/
+ dojo._destroyElement = dojo.destroy = function(/*String|DomNode*/node){
+ // summary:
+ // Removes a node from its parent, clobbering it and all of its
+ // children.
+ //
+ // description:
+ // Removes a node from its parent, clobbering it and all of its
+ // children. Function only works with DomNodes, and returns nothing.
+ //
+ // node:
+ // A String ID or DomNode reference of the element to be destroyed
+ //
+ // example:
+ // Destroy a node byId:
+ // | dojo.destroy("someId");
+ //
+ // example:
+ // Destroy all nodes in a list by reference:
+ // | dojo.query(".someNode").forEach(dojo.destroy);
+
+ node = 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 */
+ }
+ };
+
+ dojo.isDescendant = function(/*DomNode|String*/node, /*DomNode|String*/ancestor){
+ // summary:
+ // Returns true if node is a descendant of ancestor
+ // node: string id or node reference to test
+ // ancestor: string id or node reference of potential parent to test against
+ //
+ // example:
+ // Test is node id="bar" is a descendant of node id="foo"
+ // | if(dojo.isDescendant("bar", "foo")){ ... }
+ try{
+ node = byId(node);
+ ancestor = byId(ancestor);
+ while(node){
+ if(node == ancestor){
+ return true; // Boolean
+ }
+ node = node.parentNode;
+ }
+ }catch(e){ /* squelch, return false */ }
+ return false; // Boolean
+ };
+
+ dojo.setSelectable = function(/*DomNode|String*/node, /*Boolean*/selectable){
+ // summary:
+ // Enable or disable selection on a node
+ // node:
+ // id or reference to node
+ // selectable:
+ // state to put the node in. false indicates unselectable, true
+ // allows selection.
+ // example:
+ // Make the node id="bar" unselectable
+ // | dojo.setSelectable("bar");
+ // example:
+ // Make the node id="bar" selectable
+ // | dojo.setSelectable("bar", true);
+ node = byId(node);
+ if(d.isMozilla){
+ node.style.MozUserSelect = selectable ? "" : "none";
+ }else if(d.isKhtml || d.isWebKit){
+ node.style.KhtmlUserSelect = selectable ? "auto" : "none";
+ }else if(d.isIE){
+ var v = (node.unselectable = selectable ? "" : "on");
+ d.query("*", node).forEach("item.unselectable = '"+v+"'");
+ }
+ //FIXME: else? Opera?
+ };
+
+ var _insertBefore = function(/*DomNode*/node, /*DomNode*/ref){
+ var parent = ref.parentNode;
+ if(parent){
+ parent.insertBefore(node, ref);
+ }
+ };
+
+ var _insertAfter = function(/*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);
+ }
+ }
+ };
+
+ dojo.place = function(node, refNode, position){
+ // summary:
+ // Attempt to insert node into the DOM, choosing from various positioning options.
+ // Returns the first argument resolved to a DOM node.
+ //
+ // node: String|DomNode
+ // id or node reference, or HTML fragment starting with "<" to place relative to refNode
+ //
+ // refNode: String|DomNode
+ // id or node reference to use as basis for placement
+ //
+ // position: String|Number?
+ // string noting the position of node relative to refNode or a
+ // number indicating the location in the childNodes collection of refNode.
+ // Accepted string values are:
+ // | * before
+ // | * after
+ // | * replace
+ // | * only
+ // | * first
+ // | * last
+ // "first" and "last" indicate positions as children of refNode, "replace" replaces refNode,
+ // "only" replaces all children. position defaults to "last" if not specified
+ //
+ // returns: DomNode
+ // Returned values is the first argument resolved to a DOM node.
+ //
+ // .place() is also a method of `dojo.NodeList`, allowing `dojo.query` node lookups.
+ //
+ // example:
+ // Place a node by string id as the last child of another node by string id:
+ // | dojo.place("someNode", "anotherNode");
+ //
+ // example:
+ // Place a node by string id before another node by string id
+ // | dojo.place("someNode", "anotherNode", "before");
+ //
+ // example:
+ // Create a Node, and place it in the body element (last child):
+ // | dojo.place("", dojo.body());
+ //
+ // example:
+ // Put a new LI as the first child of a list by id:
+ // | dojo.place("", "someUl", "first");
+
+ refNode = byId(refNode);
+ if(typeof node == "string"){ // inline'd type check
+ node = /^\s* td", node).forEach(function(i){
+ d._setOpacity(i, opacity);
+ });
+ }
+ return opacity;
+ } :
+ function(node, opacity){
+ return node.style.opacity = opacity;
+ };
+
+ var _pixelNamesCache = {
+ left: true, top: true
+ };
+ var _pixelRegExp = /margin|padding|width|height|max|min|offset/; // |border
+ var _toStyleValue = function(node, type, value){
+ type = type.toLowerCase(); // FIXME: should we really be doing string case conversion here? Should we cache it? Need to profile!
+ if(d.isIE){
+ if(value == "auto"){
+ if(type == "height"){ return node.offsetHeight; }
+ if(type == "width"){ return node.offsetWidth; }
+ }
+ if(type == "fontweight"){
+ switch(value){
+ case 700: return "bold";
+ case 400:
+ default: return "normal";
+ }
+ }
+ }
+ if(!(type in _pixelNamesCache)){
+ _pixelNamesCache[type] = _pixelRegExp.test(type);
+ }
+ return _pixelNamesCache[type] ? px(node, value) : value;
+ };
+
+ var _floatStyle = d.isIE ? "styleFloat" : "cssFloat",
+ _floatAliases = { "cssFloat": _floatStyle, "styleFloat": _floatStyle, "float": _floatStyle }
+ ;
+
+ // public API
+
+ dojo.style = function( /*DomNode|String*/ node,
+ /*String?|Object?*/ style,
+ /*String?*/ value){
+ // summary:
+ // Accesses styles on a node. If 2 arguments are
+ // passed, acts as a getter. If 3 arguments are passed, acts
+ // as a setter.
+ // description:
+ // Getting the style value uses the computed style for the node, so the value
+ // will be a calculated value, not just the immediate node.style value.
+ // Also when getting values, use specific style names,
+ // like "borderBottomWidth" instead of "border" since compound values like
+ // "border" are not necessarily reflected as expected.
+ // If you want to get node dimensions, use `dojo.marginBox()`,
+ // `dojo.contentBox()` or `dojo.position()`.
+ // node:
+ // 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]);
+ }
+ return s;
+ }
+ return (args == 1) ? s : _toStyleValue(n, style, s[style] || n.style[style]); /* CSS2Properties||String||Number */
+ };
+
+ // =============================
+ // 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.
+ 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)
+ };
+ };
+
+ 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)
+ };
+ };
+
+ 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
+ //
+ // 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),
+ 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
+ };
+ };
+
+ dojo._getMarginExtents = function(n, computedStyle){
+ // summary:
+ // returns object with properties useful for box fitting with
+ // regards to box margins (i.e., the outer-box).
+ //
+ // * l/t = marginLeft, marginTop, respectively
+ // * w = total width, margin inclusive
+ // * h = total height, margin inclusive
+ //
+ // 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;
+ }
+ 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.
+
+ // 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._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));
+
+ var size = node.getBoundingClientRect();
+ return {
+ w: (size.right - size.left) + me.w,
+ h: (size.bottom - size.top) + me.h
+ }
+ }
+
+ 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.
+
+ // 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
+ };
+ };
+
+ 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
+ };
+ };
+
+ // 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.
+
+ 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; }
+ };
+
+ 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
+ };
+
+ dojo._usesBorderBox = function(/*DomNode*/node){
+ // summary:
+ // True if the node uses border-box layout.
+
+ // We could test the computed style of node to see if a particular box
+ // has been specified, but there are details and we choose not to bother.
+
+ // TABLE and BUTTON (and INPUT type=button) are always border-box by default.
+ // If you have assigned a different box to either one via CSS then
+ // box functions will break.
+
+ var n = node.tagName;
+ return d.boxModel=="border-box" || n=="TABLE" || d._isButtonTag(node); // boolean
+ };
+
+ dojo._setContentSize = function(/*DomNode*/node, /*Number*/widthPx, /*Number*/heightPx, /*Object*/computedStyle){
+ // summary:
+ // Sets the size of the node's contents, irrespective of margins,
+ // padding, or borders.
+ if(d._usesBorderBox(node)){
+ var pb = d._getPadBorderExtents(node, computedStyle);
+ if(widthPx >= 0){ widthPx += pb.w; }
+ if(heightPx >= 0){ heightPx += pb.h; }
+ }
+ d._setBox(node, NaN, NaN, widthPx, heightPx);
+ };
+
+ 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.
+
+ 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"; }
+ }
+ }
+ 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 };
+
+ // public API
+
+ 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);
+ //
+ // 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
+ };
+
+ 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
+ };
+
+ // =============================
+ // Positioning
+ // =============================
+
+ 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"){
+ 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; }
+ }
+ 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 });
+ };
+
+ dojo._isBodyLtr = function(){
+ return "_bodyLtr" in d? d._bodyLtr :
+ d._bodyLtr = (d.body().dir || d.doc.documentElement.dir || "ltr").toLowerCase() == "ltr"; // Boolean
+ };
+
+ 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.
+
+ //NOTE: assumes we're being called in an IE browser
+
+ var de = d.doc.documentElement; // only deal with HTML element here, _abs handles body/quirks
+
+ 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
+ };
+ }
+
+ };
+
+ 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.
+
+ 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
+ };
+
+ // 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.
+
+ 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);
+ }
+ // account for document scrolling
+ if(includeScroll){
+ var scroll = d._docScroll();
+ ret.x += scroll.x;
+ ret.y += scroll.y;
+ }
+
+ return ret; // Object
+ };
+
+ dojo.coords = function(/*DomNode|String*/node, /*Boolean?*/includeScroll){
+ // summary:
+ // Deprecated: Use position() for border-box x/y/w/h
+ // or marginBox() for margin-box w/h/l/t.
+ // Returns an object representing a node's size and position.
+ //
+ // 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;
+ };
+
+ // =============================
+ // Element attribute Functions
+ // =============================
+
+ // dojo.attr() should conform to http://www.w3.org/TR/DOM-Level-2-Core/
+
+ 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
+ };
+
+ var _fixAttrName = function(/*String*/ name){
+ return _attrNames[name.toLowerCase()] || name;
+ };
+
+ var _hasAttr = function(node, name){
+ var attr = node.getAttributeNode && node.getAttributeNode(name);
+ return attr && attr.specified; // Boolean
+ };
+
+ // There is a difference in the presence of certain properties and their default values
+ // between browsers. For example, on IE "disabled" is present on all elements,
+ // but it is value is "false"; "tabIndex" of
returns 0 by default on IE, yet other browsers
+ // can return -1.
+
+ dojo.hasAttr = function(/*DomNode|String*/node, /*String*/name){
+ // 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
+ };
+
+ 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){
+ // summary:
+ // Gets or sets an attribute on an HTML element.
+ // description:
+ // Handles normalized getting and setting of attributes on DOM
+ // Nodes. If 2 arguments are passed, and a the second argumnt is a
+ // string, acts as a getter.
+ //
+ // If a third argument is passed, or if the second argument is a
+ // map of attributes, acts as a setter.
+ //
+ // When passing functions as values, note that they will not be
+ // directly assigned to slots on the node, but rather the default
+ // behavior will be removed and the new behavior will be added
+ // using `dojo.connect()`, meaning that event handler properties
+ // will be normalized and that some caveats with regards to
+ // non-standard behaviors for onsubmit apply. Namely that you
+ // should cancel form submission using `dojo.stopEvent()` on the
+ // passed event object instead of returning a boolean value from
+ // the handler itself.
+ // node:
+ // id or reference to the element to get or set the 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;
+ //
+ // when used as a setter, the DOM node
+ //
+ // example:
+ // | // get the current value of the "foo" attribute on a node
+ // | dojo.attr(dojo.byId("nodeId"), "foo");
+ // | // or we can just pass the id:
+ // | dojo.attr("nodeId", "foo");
+ //
+ // example:
+ // | // use attr() to set the tab index
+ // | dojo.attr("nodeId", "tabIndex", 3);
+ // |
+ //
+ // example:
+ // Set multiple values at once, including event handlers:
+ // | dojo.attr("formId", {
+ // | "foo": "bar",
+ // | "tabIndex": -1,
+ // | "method": "POST",
+ // | "onsubmit": function(e){
+ // | // stop submitting the form. Note that the IE behavior
+ // | // of returning true or false will have no effect here
+ // | // since our handler is connect()ed to the built-in
+ // | // onsubmit behavior and so we need to use
+ // | // dojo.stopEvent() to ensure that the submission
+ // | // doesn't proceed.
+ // | dojo.stopEvent(e);
+ // |
+ // | // submit the form with Ajax
+ // | dojo.xhrPost({ form: "formId" });
+ // | }
+ // | });
+ //
+ // example:
+ // Style is s special case: Only set with an object hash of styles
+ // | dojo.attr("someNode",{
+ // | id:"bar",
+ // | style:{
+ // | width:"200px", height:"100px", color:"#000"
+ // | }
+ // | });
+ //
+ // example:
+ // Again, only set style as an object hash of styles:
+ // | var obj = { color:"#fff", backgroundColor:"#000" };
+ // | dojo.attr("someNode", "style", obj);
+ // |
+ // | // though shorter to use `dojo.style()` in this case:
+ // | dojo.style("someNode", obj);
+
+ 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.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
+ };
+
+ 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
+ //
+ // example:
+ // Create a DIV:
+ // | var n = dojo.create("div");
+ //
+ // example:
+ // Create a DIV with content:
+ // | var n = dojo.create("div", { innerHTML:"
hi
" });
+ //
+ // example:
+ // Place a new DIV in the BODY, with no attributes set
+ // | var n = dojo.create("div", null, dojo.body());
+ //
+ // 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);
+ // | });
+ //
+ // example:
+ // Create an anchor, with an href. Place in BODY:
+ // | dojo.create("a", { href:"foo.html", title:"Goto FOO!" }, dojo.body());
+ //
+ // 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
+ };
+
+ /*=====
+ 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 = "";
+ };
+
+ /*=====
+ 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" ? '