Blame | Last modification | View Log | RSS feed
/*Copyright (c) 2004-2007, The Dojo FoundationAll Rights Reserved.Licensed under the Academic Free License version 2.1 or above OR themodified BSD license. For more information on Dojo licensing, see:http://dojotoolkit.org/book/dojo-book-0-9/introduction/licensing*//*This is a compiled version of Dojo, built for deployment and not fordevelopment. To get an editable version, please visit:http://dojotoolkit.orgfor documentation and information on getting the source.*/if(!dojo._hasResource["dojo.colors"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.colors"] = true;dojo.provide("dojo.colors");(function(){// this is a standard convertion prescribed by the CSS3 Color Modulevar hue2rgb = function(m1, m2, h){if(h < 0){ ++h; }if(h > 1){ --h; }var h6 = 6 * h;if(h6 < 1){ return m1 + (m2 - m1) * h6; }if(2 * h < 1){ return m2; }if(3 * h < 2){ return m1 + (m2 - m1) * (2 / 3 - h) * 6; }return m1;};dojo.colorFromRgb = function(/*String*/ color, /*dojo.Color?*/ obj){// summary:// get rgb(a) array from css-style color declarations// description:// this function can handle all 4 CSS3 Color Module formats: rgb,// rgba, hsl, hsla, including rgb(a) with percentage values.var m = color.toLowerCase().match(/^(rgba?|hsla?)\(([\s\.\-,%0-9]+)\)/);if(m){var c = m[2].split(/\s*,\s*/), l = c.length, t = m[1];if((t == "rgb" && l == 3) || (t == "rgba" && l == 4)){var r = c[0];if(r.charAt(r.length - 1) == "%"){// 3 rgb percentage valuesvar a = dojo.map(c, function(x){return parseFloat(x) * 2.56;});if(l == 4){ a[3] = c[3]; }return dojo.colorFromArray(a, obj); // dojo.Color}return dojo.colorFromArray(c, obj); // dojo.Color}if((t == "hsl" && l == 3) || (t == "hsla" && l == 4)){// normalize hsl valuesvar H = ((parseFloat(c[0]) % 360) + 360) % 360 / 360,S = parseFloat(c[1]) / 100,L = parseFloat(c[2]) / 100,// calculate rgb according to the algorithm// recommended by the CSS3 Color Modulem2 = L <= 0.5 ? L * (S + 1) : L + S - L * S,m1 = 2 * L - m2,a = [hue2rgb(m1, m2, H + 1 / 3) * 256,hue2rgb(m1, m2, H) * 256, hue2rgb(m1, m2, H - 1 / 3) * 256, 1];if(l == 4){ a[3] = c[3]; }return dojo.colorFromArray(a, obj); // dojo.Color}}return null; // dojo.Color};var confine = function(c, low, high){// summary:// sanitize a color component by making sure it is a number,// and clamping it to valid valuesc = Number(c);return isNaN(c) ? high : c < low ? low : c > high ? high : c; // Number};dojo.Color.prototype.sanitize = function(){// summary: makes sure that the object has correct attributesvar t = this;t.r = Math.round(confine(t.r, 0, 255));t.g = Math.round(confine(t.g, 0, 255));t.b = Math.round(confine(t.b, 0, 255));t.a = confine(t.a, 0, 1);return this; // dojo.Color};})();dojo.colors.makeGrey = function(/*Number*/ g, /*Number?*/ a){// summary: creates a greyscale color with an optional alphareturn dojo.colorFromArray([g, g, g, a]);};// mixin all CSS3 named colors not already in _base, along with SVG 1.0 variant spellingsdojo.Color.named = dojo.mixin({aliceblue: [240,248,255],antiquewhite: [250,235,215],aquamarine: [127,255,212],azure: [240,255,255],beige: [245,245,220],bisque: [255,228,196],blanchedalmond: [255,235,205],blueviolet: [138,43,226],brown: [165,42,42],burlywood: [222,184,135],cadetblue: [95,158,160],chartreuse: [127,255,0],chocolate: [210,105,30],coral: [255,127,80],cornflowerblue: [100,149,237],cornsilk: [255,248,220],crimson: [220,20,60],cyan: [0,255,255],darkblue: [0,0,139],darkcyan: [0,139,139],darkgoldenrod: [184,134,11],darkgray: [169,169,169],darkgreen: [0,100,0],darkgrey: [169,169,169],darkkhaki: [189,183,107],darkmagenta: [139,0,139],darkolivegreen: [85,107,47],darkorange: [255,140,0],darkorchid: [153,50,204],darkred: [139,0,0],darksalmon: [233,150,122],darkseagreen: [143,188,143],darkslateblue: [72,61,139],darkslategray: [47,79,79],darkslategrey: [47,79,79],darkturquoise: [0,206,209],darkviolet: [148,0,211],deeppink: [255,20,147],deepskyblue: [0,191,255],dimgray: [105,105,105],dimgrey: [105,105,105],dodgerblue: [30,144,255],firebrick: [178,34,34],floralwhite: [255,250,240],forestgreen: [34,139,34],gainsboro: [220,220,220],ghostwhite: [248,248,255],gold: [255,215,0],goldenrod: [218,165,32],greenyellow: [173,255,47],grey: [128,128,128],honeydew: [240,255,240],hotpink: [255,105,180],indianred: [205,92,92],indigo: [75,0,130],ivory: [255,255,240],khaki: [240,230,140],lavender: [230,230,250],lavenderblush: [255,240,245],lawngreen: [124,252,0],lemonchiffon: [255,250,205],lightblue: [173,216,230],lightcoral: [240,128,128],lightcyan: [224,255,255],lightgoldenrodyellow: [250,250,210],lightgray: [211,211,211],lightgreen: [144,238,144],lightgrey: [211,211,211],lightpink: [255,182,193],lightsalmon: [255,160,122],lightseagreen: [32,178,170],lightskyblue: [135,206,250],lightslategray: [119,136,153],lightslategrey: [119,136,153],lightsteelblue: [176,196,222],lightyellow: [255,255,224],limegreen: [50,205,50],linen: [250,240,230],magenta: [255,0,255],mediumaquamarine: [102,205,170],mediumblue: [0,0,205],mediumorchid: [186,85,211],mediumpurple: [147,112,219],mediumseagreen: [60,179,113],mediumslateblue: [123,104,238],mediumspringgreen: [0,250,154],mediumturquoise: [72,209,204],mediumvioletred: [199,21,133],midnightblue: [25,25,112],mintcream: [245,255,250],mistyrose: [255,228,225],moccasin: [255,228,181],navajowhite: [255,222,173],oldlace: [253,245,230],olivedrab: [107,142,35],orange: [255,165,0],orangered: [255,69,0],orchid: [218,112,214],palegoldenrod: [238,232,170],palegreen: [152,251,152],paleturquoise: [175,238,238],palevioletred: [219,112,147],papayawhip: [255,239,213],peachpuff: [255,218,185],peru: [205,133,63],pink: [255,192,203],plum: [221,160,221],powderblue: [176,224,230],rosybrown: [188,143,143],royalblue: [65,105,225],saddlebrown: [139,69,19],salmon: [250,128,114],sandybrown: [244,164,96],seagreen: [46,139,87],seashell: [255,245,238],sienna: [160,82,45],skyblue: [135,206,235],slateblue: [106,90,205],slategray: [112,128,144],slategrey: [112,128,144],snow: [255,250,250],springgreen: [0,255,127],steelblue: [70,130,180],tan: [210,180,140],thistle: [216,191,216],tomato: [255,99,71],transparent: [0, 0, 0, 0],turquoise: [64,224,208],violet: [238,130,238],wheat: [245,222,179],whitesmoke: [245,245,245],yellowgreen: [154,205,50]}, dojo.Color.named);}if(!dojo._hasResource["dojo.i18n"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.i18n"] = true;dojo.provide("dojo.i18n");dojo.i18n.getLocalization = function(/*String*/packageName, /*String*/bundleName, /*String?*/locale){// summary:// Returns an Object containing the localization for a given resource// bundle in a package, matching the specified locale.// description:// Returns a hash containing name/value pairs in its prototypesuch// that values can be easily overridden. Throws an exception if the// bundle is not found. Bundle must have already been loaded by// dojo.requireLocalization() or by a build optimization step. NOTE:// try not to call this method as part of an object property// definition (var foo = { bar: dojo.i18n.getLocalization() }). In// some loading situations, the bundle may not be available in time// for the object definition. Instead, call this method inside a// function that is run after all modules load or the page loads (like// in dojo.adOnLoad()), or in a widget lifecycle method.// packageName:// package which is associated with this resource// bundleName:// the base filename of the resource bundle (without the ".js" suffix)// locale:// the variant to load (optional). By default, the locale defined by// the host environment: dojo.localelocale = dojo.i18n.normalizeLocale(locale);// look for nearest locale matchvar elements = locale.split('-');var module = [packageName,"nls",bundleName].join('.');var bundle = dojo._loadedModules[module];if(bundle){var localization;for(var i = elements.length; i > 0; i--){var loc = elements.slice(0, i).join('_');if(bundle[loc]){localization = bundle[loc];break;}}if(!localization){localization = bundle.ROOT;}// make a singleton prototype so that the caller won't accidentally change the values globallyif(localization){var clazz = function(){};clazz.prototype = localization;return new clazz(); // Object}}throw new Error("Bundle not found: " + bundleName + " in " + packageName+" , locale=" + locale);};dojo.i18n.normalizeLocale = function(/*String?*/locale){// summary:// Returns canonical form of locale, as used by Dojo.//// description:// All variants are case-insensitive and are separated by '-' as specified in RFC 3066.// If no locale is specified, the dojo.locale is returned. dojo.locale is defined by// the user agent's locale unless overridden by djConfig.var result = locale ? locale.toLowerCase() : dojo.locale;if(result == "root"){result = "ROOT";}return result; // String};dojo.i18n._requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String?*/availableFlatLocales){// summary:// See dojo.requireLocalization()// description:// Called by the bootstrap, but factored out so that it is only// included in the build when needed.var targetLocale = dojo.i18n.normalizeLocale(locale);var bundlePackage = [moduleName, "nls", bundleName].join(".");// NOTE:// When loading these resources, the packaging does not match what is// on disk. This is an implementation detail, as this is just a// private data structure to hold the loaded resources. e.g.// tests/hello/nls/en-us/salutations.js is loaded as the object// tests.hello.nls.salutations.en_us={...} The structure on disk is// intended to be most convenient for developers and translators, but// in memory it is more logical and efficient to store in a different// order. Locales cannot use dashes, since the resulting path will// not evaluate as valid JS, so we translate them to underscores.//Find the best-match locale to load if we have available flat locales.var bestLocale = "";if(availableFlatLocales){var flatLocales = availableFlatLocales.split(",");for(var i = 0; i < flatLocales.length; i++){//Locale must match from start of string.if(targetLocale.indexOf(flatLocales[i]) == 0){if(flatLocales[i].length > bestLocale.length){bestLocale = flatLocales[i];}}}if(!bestLocale){bestLocale = "ROOT";}}//See if the desired locale is already loaded.var tempLocale = availableFlatLocales ? bestLocale : targetLocale;var bundle = dojo._loadedModules[bundlePackage];var localizedBundle = null;if(bundle){if(djConfig.localizationComplete && bundle._built){return;}var jsLoc = tempLocale.replace(/-/g, '_');var translationPackage = bundlePackage+"."+jsLoc;localizedBundle = dojo._loadedModules[translationPackage];}if(!localizedBundle){bundle = dojo["provide"](bundlePackage);var syms = dojo._getModuleSymbols(moduleName);var modpath = syms.concat("nls").join("/");var parent;dojo.i18n._searchLocalePath(tempLocale, availableFlatLocales, function(loc){var jsLoc = loc.replace(/-/g, '_');var translationPackage = bundlePackage + "." + jsLoc;var loaded = false;if(!dojo._loadedModules[translationPackage]){// Mark loaded whether it's found or not, so that further load attempts will not be madedojo["provide"](translationPackage);var module = [modpath];if(loc != "ROOT"){module.push(loc);}module.push(bundleName);var filespec = module.join("/") + '.js';loaded = dojo._loadPath(filespec, null, function(hash){// Use singleton with prototype to point to parent bundle, then mix-in result from loadPathvar clazz = function(){};clazz.prototype = parent;bundle[jsLoc] = new clazz();for(var j in hash){ bundle[jsLoc][j] = hash[j]; }});}else{loaded = true;}if(loaded && bundle[jsLoc]){parent = bundle[jsLoc];}else{bundle[jsLoc] = parent;}if(availableFlatLocales){//Stop the locale path searching if we know the availableFlatLocales, since//the first call to this function will load the only bundle that is needed.return true;}});}//Save the best locale bundle as the target locale bundle when we know the//the available bundles.if(availableFlatLocales && targetLocale != bestLocale){bundle[targetLocale.replace(/-/g, '_')] = bundle[bestLocale.replace(/-/g, '_')];}};(function(){// If other locales are used, dojo.requireLocalization should load them as// well, by default.//// Override dojo.requireLocalization to do load the default bundle, then// iterate through the extraLocale list and load those translations as// well, unless a particular locale was requested.var extra = djConfig.extraLocale;if(extra){if(!extra instanceof Array){extra = [extra];}var req = dojo.i18n._requireLocalization;dojo.i18n._requireLocalization = function(m, b, locale, availableFlatLocales){req(m,b,locale, availableFlatLocales);if(locale){return;}for(var i=0; i<extra.length; i++){req(m,b,extra[i], availableFlatLocales);}};}})();dojo.i18n._searchLocalePath = function(/*String*/locale, /*Boolean*/down, /*Function*/searchFunc){// summary:// A helper method to assist in searching for locale-based resources.// Will iterate through the variants of a particular locale, either up// or down, executing a callback function. For example, "en-us" and// true will try "en-us" followed by "en" and finally "ROOT".locale = dojo.i18n.normalizeLocale(locale);var elements = locale.split('-');var searchlist = [];for(var i = elements.length; i > 0; i--){searchlist.push(elements.slice(0, i).join('-'));}searchlist.push(false);if(down){searchlist.reverse();}for(var j = searchlist.length - 1; j >= 0; j--){var loc = searchlist[j] || "ROOT";var stop = searchFunc(loc);if(stop){ break; }}};dojo.i18n._preloadLocalizations = function(/*String*/bundlePrefix, /*Array*/localesGenerated){// summary:// Load built, flattened resource bundles, if available for all// locales used in the page. Only called by built layer files.function preload(locale){locale = dojo.i18n.normalizeLocale(locale);dojo.i18n._searchLocalePath(locale, true, function(loc){for(var i=0; i<localesGenerated.length;i++){if(localesGenerated[i] == loc){dojo["require"](bundlePrefix+"_"+loc);return true; // Boolean}}return false; // Boolean});}preload();var extra = djConfig.extraLocale||[];for(var i=0; i<extra.length; i++){preload(extra[i]);}};}if(!dojo._hasResource["dijit.ColorPalette"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.ColorPalette"] = true;dojo.provide("dijit.ColorPalette");dojo.declare("dijit.ColorPalette",[dijit._Widget, dijit._Templated],{// summary// Grid showing various colors, so the user can pick a certain color// defaultTimeout: Number// number of milliseconds before a held key or button becomes typematicdefaultTimeout: 500,// timeoutChangeRate: Number// fraction of time used to change the typematic timer between events// 1.0 means that each typematic event fires at defaultTimeout intervals// < 1.0 means that each typematic event fires at an increasing faster ratetimeoutChangeRate: 0.90,// palette: String// Size of grid, either "7x10" or "3x4".palette: "7x10",//_value: String// The value of the selected color.value: null,//_currentFocus: Integer// Index of the currently focused color._currentFocus: 0,// _xDim: Integer// This is the number of colors horizontally across._xDim: null,// _yDim: Integer/// This is the number of colors vertically down._yDim: null,// _palettes: Map// This represents the value of the colors.// The first level is a hashmap of the different arrays available// The next two dimensions represent the columns and rows of colors._palettes: {"7x10": [["white", "seashell", "cornsilk", "lemonchiffon","lightyellow", "palegreen", "paleturquoise", "lightcyan", "lavender", "plum"],["lightgray", "pink", "bisque", "moccasin", "khaki", "lightgreen", "lightseagreen", "lightskyblue", "cornflowerblue", "violet"],["silver", "lightcoral", "sandybrown", "orange", "palegoldenrod", "chartreuse", "mediumturquoise", "skyblue", "mediumslateblue","orchid"],["gray", "red", "orangered", "darkorange", "yellow", "limegreen", "darkseagreen", "royalblue", "slateblue", "mediumorchid"],["dimgray", "crimson", "chocolate", "coral", "gold", "forestgreen", "seagreen", "blue", "blueviolet", "darkorchid"],["darkslategray","firebrick","saddlebrown", "sienna", "olive", "green", "darkcyan", "mediumblue","darkslateblue", "darkmagenta" ],["black", "darkred", "maroon", "brown", "darkolivegreen", "darkgreen", "midnightblue", "navy", "indigo", "purple"]],"3x4": [["white", "lime", "green", "blue"],["silver", "yellow", "fuchsia", "navy"],["gray", "red", "purple", "black"]]},// _imagePaths: Map// This is stores the path to the palette images_imagePaths: {"7x10": dojo.moduleUrl("dijit", "templates/colors7x10.png"),"3x4": dojo.moduleUrl("dijit", "templates/colors3x4.png")},// _paletteCoords: Map// This is a map that is used to calculate the coordinates of the// images that make up the palette._paletteCoords: {"leftOffset": 4, "topOffset": 4,"cWidth": 20, "cHeight": 20},// templatePath: String// Path to the template of this widget.templateString:"<div class=\"dijitInline dijitColorPalette\">\n\t<div class=\"dijitColorPaletteInner\" dojoAttachPoint=\"divNode\" waiRole=\"grid\" tabIndex=\"-1\">\n\t\t<img class=\"dijitColorPaletteUnder\" dojoAttachPoint=\"imageNode\" waiRole=\"presentation\">\n\t</div>\t\n</div>\n",// _paletteDims: Object// Size of the supported palettes for alignment purposes._paletteDims: {"7x10": {"width": "206px", "height": "145px"},"3x4": {"width": "86px", "height": "64px"}},postCreate: function(){// A name has to be given to the colorMap, this needs to be unique per Palette.dojo.mixin(this.divNode.style, this._paletteDims[this.palette]);this.imageNode.setAttribute("src", this._imagePaths[this.palette]);var choices = this._palettes[this.palette];this.domNode.style.position = "relative";this._highlightNodes = [];this.colorNames = dojo.i18n.getLocalization("dojo", "colors", this.lang);var url= dojo.moduleUrl("dijit", "templates/blank.gif");var colorObject = new dojo.Color(),coords = this._paletteCoords;for(var row=0; row < choices.length; row++){for(var col=0; col < choices[row].length; col++) {var highlightNode = document.createElement("img");highlightNode.src = url;dojo.addClass(highlightNode, "dijitPaletteImg");var color = choices[row][col],colorValue = colorObject.setColor(dojo.Color.named[color]);highlightNode.alt = this.colorNames[color];highlightNode.color = colorValue.toHex();var highlightStyle = highlightNode.style;highlightStyle.color = highlightStyle.backgroundColor = highlightNode.color;dojo.forEach(["Dijitclick", "MouseOut", "MouseOver", "Blur", "Focus"], function(handler) {this.connect(highlightNode, "on" + handler.toLowerCase(), "_onColor" + handler);}, this);this.divNode.appendChild(highlightNode);highlightStyle.top = coords.topOffset + (row * coords.cHeight) + "px";highlightStyle.left = coords.leftOffset + (col * coords.cWidth) + "px";highlightNode.setAttribute("tabIndex", "-1");highlightNode.title = this.colorNames[color];dijit.setWaiRole(highlightNode, "gridcell");highlightNode.index = this._highlightNodes.length;this._highlightNodes.push(highlightNode);}}this._highlightNodes[this._currentFocus].tabIndex = 0;this._xDim = choices[0].length;this._yDim = choices.length;// Now set all events// The palette itself is navigated to with the tab key on the keyboard// Keyboard navigation within the Palette is with the arrow keys// Spacebar selects the color.// For the up key the index is changed by negative the x dimension.var keyIncrementMap = {UP_ARROW: -this._xDim,// The down key the index is increase by the x dimension.DOWN_ARROW: this._xDim,// Right and left move the index by 1.RIGHT_ARROW: 1,LEFT_ARROW: -1};for(var key in keyIncrementMap){this._connects.push(dijit.typematic.addKeyListener(this.domNode,{keyCode:dojo.keys[key], ctrlKey:false, altKey:false, shiftKey:false},this,function(){var increment = keyIncrementMap[key];return function(count){ this._navigateByKey(increment, count); };}(),this.timeoutChangeRate, this.defaultTimeout));}},focus: function(){// summary:// Focus this ColorPalette.dijit.focus(this._highlightNodes[this._currentFocus]);},onChange: function(color){// summary:// Callback when a color is selected.// color: String// Hex value corresponding to color.// console.debug("Color selected is: "+color);},_onColorDijitclick: function(/*Event*/ evt){// summary:// Handler for click, enter key & space key. Selects the color.// evt:// The event.var target = evt.currentTarget;if (this._currentFocus != target.index){this._currentFocus = target.index;dijit.focus(target);}this._selectColor(target);dojo.stopEvent(evt);},_onColorMouseOut: function(/*Event*/ evt){// summary:// Handler for onMouseOut. Removes highlight.// evt:// The mouse event.dojo.removeClass(evt.currentTarget, "dijitPaletteImgHighlight");},_onColorMouseOver: function(/*Event*/ evt){// summary:// Handler for onMouseOver. Highlights the color.// evt:// The mouse event.var target = evt.currentTarget;target.tabIndex = 0;target.focus();},_onColorBlur: function(/*Event*/ evt){// summary:// Handler for onBlur. Removes highlight and sets// the first color as the palette's tab point.// evt:// The blur event.dojo.removeClass(evt.currentTarget, "dijitPaletteImgHighlight");evt.currentTarget.tabIndex = -1;this._currentFocus = 0;this._highlightNodes[0].tabIndex = 0;},_onColorFocus: function(/*Event*/ evt){// summary:// Handler for onFocus. Highlights the color.// evt:// The focus event.if(this._currentFocus != evt.currentTarget.index){this._highlightNodes[this._currentFocus].tabIndex = -1;}this._currentFocus = evt.currentTarget.index;dojo.addClass(evt.currentTarget, "dijitPaletteImgHighlight");},_selectColor: function(selectNode){// summary:// This selects a color. It triggers the onChange event// area:// The area node that covers the color being selected.this.onChange(this.value = selectNode.color);},_navigateByKey: function(increment, typeCount){// summary:we// This is the callback for typematic.// It changes the focus and the highlighed color.// increment:// How much the key is navigated.// typeCount:// How many times typematic has fired.// typecount == -1 means the key is released.if(typeCount == -1){ return; }var newFocusIndex = this._currentFocus + increment;if(newFocusIndex < this._highlightNodes.length && newFocusIndex > -1){var focusNode = this._highlightNodes[newFocusIndex];focusNode.tabIndex = 0;focusNode.focus();}}});}if(!dojo._hasResource["dijit.Declaration"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.Declaration"] = true;dojo.provide("dijit.Declaration");dojo.declare("dijit.Declaration",dijit._Widget,{// summary:// The Declaration widget allows a user to declare new widget// classes directly from a snippet of markup._noScript: true,widgetClass: "",replaceVars: true,defaults: null,mixins: [],buildRendering: function(){var src = this.srcNodeRef.parentNode.removeChild(this.srcNodeRef);var preambles = dojo.query("> script[type='dojo/method'][event='preamble']", src).orphan();var scripts = dojo.query("> script[type^='dojo/']", src).orphan();var srcType = src.nodeName;var propList = this.defaults||{};// map array of strings like [ "dijit.form.Button" ] to array of mixin objects// (note that dojo.map(this.mixins, dojo.getObject) doesn't work because it passes// a bogus third argument to getObject(), confusing it)this.mixins = this.mixins.length ?dojo.map(this.mixins, function(name){ return dojo.getObject(name); } ) :[ dijit._Widget, dijit._Templated ];if(preambles.length){// we only support one preamble. So be it.propList.preamble = dojo.parser._functionFromScript(preambles[0]);}var parsedScripts = dojo.map(scripts, function(s){var evt = s.getAttribute("event")||"postscript";return {event: evt,func: dojo.parser._functionFromScript(s)};});// do the connects for each <script type="dojo/connect" event="foo"> block and make// all <script type="dojo/method"> tags execute right after constructionthis.mixins.push(function(){dojo.forEach(parsedScripts, function(s){dojo.connect(this, s.event, this, s.func);}, this);});propList.widgetsInTemplate = true;propList._skipNodeCache = true;propList.templateString = "<"+srcType+" class='"+src.className+"' dojoAttachPoint='"+(src.getAttribute("dojoAttachPoint")||'')+"' dojoAttachEvent='"+(src.getAttribute("dojoAttachEvent")||'')+"' >"+src.innerHTML.replace(/\%7B/g,"{").replace(/\%7D/g,"}")+"</"+srcType+">";// console.debug(propList.templateString);// strip things so we don't create stuff under us in the initial setup phasedojo.query("[dojoType]", src).forEach(function(node){node.removeAttribute("dojoType");});// create the new widget classdojo.declare(this.widgetClass,this.mixins,propList);}});}if(!dojo._hasResource["dojo.dnd.common"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.dnd.common"] = true;dojo.provide("dojo.dnd.common");dojo.dnd._copyKey = navigator.appVersion.indexOf("Macintosh") < 0 ? "ctrlKey" : "metaKey";dojo.dnd.getCopyKeyState = function(e) {// summary: abstracts away the difference between selection on Mac and PC,// and returns the state of the "copy" key to be pressed.// e: Event: mouse eventreturn e[dojo.dnd._copyKey]; // Boolean};dojo.dnd._uniqueId = 0;dojo.dnd.getUniqueId = function(){// summary: returns a unique string for use with any DOM elementvar id;do{id = "dojoUnique" + (++dojo.dnd._uniqueId);}while(dojo.byId(id));return id;};dojo.dnd._empty = {};dojo.dnd.isFormElement = function(/*Event*/ e){// summary: returns true, if user clicked on a form elementvar t = e.target;if(t.nodeType == 3 /*TEXT_NODE*/){t = t.parentNode;}return " button textarea input select option ".indexOf(" " + t.tagName.toLowerCase() + " ") >= 0; // Boolean};}if(!dojo._hasResource["dojo.dnd.autoscroll"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.dnd.autoscroll"] = true;dojo.provide("dojo.dnd.autoscroll");dojo.dnd.getViewport = function(){// summary: returns a viewport size (visible part of the window)// FIXME: need more docs!!var d = dojo.doc, dd = d.documentElement, w = window, b = dojo.body();if(dojo.isMozilla){return {w: dd.clientWidth, h: w.innerHeight}; // Object}else if(!dojo.isOpera && w.innerWidth){return {w: w.innerWidth, h: w.innerHeight}; // Object}else if (!dojo.isOpera && dd && dd.clientWidth){return {w: dd.clientWidth, h: dd.clientHeight}; // Object}else if (b.clientWidth){return {w: b.clientWidth, h: b.clientHeight}; // Object}return null; // Object};dojo.dnd.V_TRIGGER_AUTOSCROLL = 32;dojo.dnd.H_TRIGGER_AUTOSCROLL = 32;dojo.dnd.V_AUTOSCROLL_VALUE = 16;dojo.dnd.H_AUTOSCROLL_VALUE = 16;dojo.dnd.autoScroll = function(e){// summary:// a handler for onmousemove event, which scrolls the window, if// necesary// e: Event:// onmousemove event// FIXME: needs more docs!var v = dojo.dnd.getViewport(), dx = 0, dy = 0;if(e.clientX < dojo.dnd.H_TRIGGER_AUTOSCROLL){dx = -dojo.dnd.H_AUTOSCROLL_VALUE;}else if(e.clientX > v.w - dojo.dnd.H_TRIGGER_AUTOSCROLL){dx = dojo.dnd.H_AUTOSCROLL_VALUE;}if(e.clientY < dojo.dnd.V_TRIGGER_AUTOSCROLL){dy = -dojo.dnd.V_AUTOSCROLL_VALUE;}else if(e.clientY > v.h - dojo.dnd.V_TRIGGER_AUTOSCROLL){dy = dojo.dnd.V_AUTOSCROLL_VALUE;}window.scrollBy(dx, dy);};dojo.dnd._validNodes = {"div": 1, "p": 1, "td": 1};dojo.dnd._validOverflow = {"auto": 1, "scroll": 1};dojo.dnd.autoScrollNodes = function(e){// summary:// a handler for onmousemove event, which scrolls the first avaialble// Dom element, it falls back to dojo.dnd.autoScroll()// e: Event:// onmousemove event// FIXME: needs more docs!for(var n = e.target; n;){if(n.nodeType == 1 && (n.tagName.toLowerCase() in dojo.dnd._validNodes)){var s = dojo.getComputedStyle(n);if(s.overflow.toLowerCase() in dojo.dnd._validOverflow){var b = dojo._getContentBox(n, s), t = dojo._abs(n, true);// console.debug(b.l, b.t, t.x, t.y, n.scrollLeft, n.scrollTop);b.l += t.x + n.scrollLeft;b.t += t.y + n.scrollTop;var w = Math.min(dojo.dnd.H_TRIGGER_AUTOSCROLL, b.w / 2),h = Math.min(dojo.dnd.V_TRIGGER_AUTOSCROLL, b.h / 2),rx = e.pageX - b.l, ry = e.pageY - b.t, dx = 0, dy = 0;if(rx > 0 && rx < b.w){if(rx < w){dx = -dojo.dnd.H_AUTOSCROLL_VALUE;}else if(rx > b.w - w){dx = dojo.dnd.H_AUTOSCROLL_VALUE;}}//console.debug("ry =", ry, "b.h =", b.h, "h =", h);if(ry > 0 && ry < b.h){if(ry < h){dy = -dojo.dnd.V_AUTOSCROLL_VALUE;}else if(ry > b.h - h){dy = dojo.dnd.V_AUTOSCROLL_VALUE;}}var oldLeft = n.scrollLeft, oldTop = n.scrollTop;n.scrollLeft = n.scrollLeft + dx;n.scrollTop = n.scrollTop + dy;// if(dx || dy){ console.debug(oldLeft + ", " + oldTop + "\n" + dx + ", " + dy + "\n" + n.scrollLeft + ", " + n.scrollTop); }if(oldLeft != n.scrollLeft || oldTop != n.scrollTop){ return; }}}try{n = n.parentNode;}catch(x){n = null;}}dojo.dnd.autoScroll(e);};}if(!dojo._hasResource["dojo.dnd.Mover"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.dnd.Mover"] = true;dojo.provide("dojo.dnd.Mover");dojo.declare("dojo.dnd.Mover", null, {constructor: function(node, e, host){// summary: an object, which makes a node follow the mouse,// used as a default mover, and as a base class for custom movers// node: Node: a node (or node's id) to be moved// e: Event: a mouse event, which started the move;// only pageX and pageY properties are used// host: Object?: object which implements the functionality of the move,// and defines proper events (onMoveStart and onMoveStop)this.node = dojo.byId(node);this.marginBox = {l: e.pageX, t: e.pageY};this.mouseButton = e.button;var h = this.host = host, d = node.ownerDocument,firstEvent = dojo.connect(d, "onmousemove", this, "onFirstMove");this.events = [dojo.connect(d, "onmousemove", this, "onMouseMove"),dojo.connect(d, "onmouseup", this, "onMouseUp"),// cancel text selection and text draggingdojo.connect(d, "ondragstart", dojo, "stopEvent"),dojo.connect(d, "onselectstart", dojo, "stopEvent"),firstEvent];// notify that the move has startedif(h && h.onMoveStart){h.onMoveStart(this);}},// mouse event processorsonMouseMove: function(e){// summary: event processor for onmousemove// e: Event: mouse eventdojo.dnd.autoScroll(e);var m = this.marginBox;this.host.onMove(this, {l: m.l + e.pageX, t: m.t + e.pageY});},onMouseUp: function(e){if(this.mouseButton == e.button){this.destroy();}},// utilitiesonFirstMove: function(){// summary: makes the node absolute; it is meant to be called only oncethis.node.style.position = "absolute"; // enforcing the absolute modevar m = dojo.marginBox(this.node);m.l -= this.marginBox.l;m.t -= this.marginBox.t;this.marginBox = m;this.host.onFirstMove(this);dojo.disconnect(this.events.pop());},destroy: function(){// summary: stops the move, deletes all references, so the object can be garbage-collecteddojo.forEach(this.events, dojo.disconnect);// undo global settingsvar h = this.host;if(h && h.onMoveStop){h.onMoveStop(this);}// destroy objectsthis.events = this.node = null;}});}if(!dojo._hasResource["dojo.dnd.Moveable"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.dnd.Moveable"] = true;dojo.provide("dojo.dnd.Moveable");dojo.declare("dojo.dnd.Moveable", null, {// object attributes (for markup)handle: "",delay: 0,skip: false,constructor: function(node, params){// summary: an object, which makes a node moveable// node: Node: a node (or node's id) to be moved// params: Object: an optional object with additional parameters;// following parameters are recognized:// handle: Node: a node (or node's id), which is used as a mouse handle// if omitted, the node itself is used as a handle// delay: Number: delay move by this number of pixels// skip: Boolean: skip move of form elements// mover: Object: a constructor of custom Moverthis.node = dojo.byId(node);if(!params){ params = {}; }this.handle = params.handle ? dojo.byId(params.handle) : null;if(!this.handle){ this.handle = this.node; }this.delay = params.delay > 0 ? params.delay : 0;this.skip = params.skip;this.mover = params.mover ? params.mover : dojo.dnd.Mover;this.events = [dojo.connect(this.handle, "onmousedown", this, "onMouseDown"),// cancel text selection and text draggingdojo.connect(this.handle, "ondragstart", this, "onSelectStart"),dojo.connect(this.handle, "onselectstart", this, "onSelectStart")];},// markup methodsmarkupFactory: function(params, node){return new dojo.dnd.Moveable(node, params);},// methodsdestroy: function(){// summary: stops watching for possible move, deletes all references, so the object can be garbage-collecteddojo.forEach(this.events, dojo.disconnect);this.events = this.node = this.handle = null;},// mouse event processorsonMouseDown: function(e){// summary: event processor for onmousedown, creates a Mover for the node// e: Event: mouse eventif(this.skip && dojo.dnd.isFormElement(e)){ return; }if(this.delay){this.events.push(dojo.connect(this.handle, "onmousemove", this, "onMouseMove"));this.events.push(dojo.connect(this.handle, "onmouseup", this, "onMouseUp"));this._lastX = e.pageX;this._lastY = e.pageY;}else{new this.mover(this.node, e, this);}dojo.stopEvent(e);},onMouseMove: function(e){// summary: event processor for onmousemove, used only for delayed drags// e: Event: mouse eventif(Math.abs(e.pageX - this._lastX) > this.delay || Math.abs(e.pageY - this._lastY) > this.delay){this.onMouseUp(e);new this.mover(this.node, e, this);}dojo.stopEvent(e);},onMouseUp: function(e){// summary: event processor for onmouseup, used only for delayed delayed drags// e: Event: mouse eventdojo.disconnect(this.events.pop());dojo.disconnect(this.events.pop());},onSelectStart: function(e){// summary: event processor for onselectevent and ondragevent// e: Event: mouse eventif(!this.skip || !dojo.dnd.isFormElement(e)){dojo.stopEvent(e);}},// local eventsonMoveStart: function(/* dojo.dnd.Mover */ mover){// summary: called before every move operationdojo.publish("/dnd/move/start", [mover]);dojo.addClass(dojo.body(), "dojoMove");dojo.addClass(this.node, "dojoMoveItem");},onMoveStop: function(/* dojo.dnd.Mover */ mover){// summary: called after every move operationdojo.publish("/dnd/move/stop", [mover]);dojo.removeClass(dojo.body(), "dojoMove");dojo.removeClass(this.node, "dojoMoveItem");},onFirstMove: function(/* dojo.dnd.Mover */ mover){// summary: called during the very first move notification,// can be used to initialize coordinates, can be overwritten.// default implementation does nothing},onMove: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){// summary: called during every move notification,// should actually move the node, can be overwritten.this.onMoving(mover, leftTop);dojo.marginBox(mover.node, leftTop);this.onMoved(mover, leftTop);},onMoving: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){// summary: called before every incremental move,// can be overwritten.// default implementation does nothing},onMoved: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){// summary: called after every incremental move,// can be overwritten.// default implementation does nothing}});}if(!dojo._hasResource["dojo.dnd.move"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.dnd.move"] = true;dojo.provide("dojo.dnd.move");dojo.declare("dojo.dnd.move.constrainedMoveable", dojo.dnd.Moveable, {// object attributes (for markup)constraints: function(){},within: false,// markup methodsmarkupFactory: function(params, node){return new dojo.dnd.move.constrainedMoveable(node, params);},constructor: function(node, params){// summary: an object, which makes a node moveable// node: Node: a node (or node's id) to be moved// params: Object: an optional object with additional parameters;// following parameters are recognized:// constraints: Function: a function, which calculates a constraint box,// it is called in a context of the moveable object.// within: Boolean: restrict move within boundaries.// the rest is passed to the base classif(!params){ params = {}; }this.constraints = params.constraints;this.within = params.within;},onFirstMove: function(/* dojo.dnd.Mover */ mover){// summary: called during the very first move notification,// can be used to initialize coordinates, can be overwritten.var c = this.constraintBox = this.constraints.call(this, mover), m = mover.marginBox;c.r = c.l + c.w - (this.within ? m.w : 0);c.b = c.t + c.h - (this.within ? m.h : 0);},onMove: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){// summary: called during every move notification,// should actually move the node, can be overwritten.var c = this.constraintBox;leftTop.l = leftTop.l < c.l ? c.l : c.r < leftTop.l ? c.r : leftTop.l;leftTop.t = leftTop.t < c.t ? c.t : c.b < leftTop.t ? c.b : leftTop.t;dojo.marginBox(mover.node, leftTop);}});dojo.declare("dojo.dnd.move.boxConstrainedMoveable", dojo.dnd.move.constrainedMoveable, {// object attributes (for markup)box: {},// markup methodsmarkupFactory: function(params, node){return new dojo.dnd.move.boxConstrainedMoveable(node, params);},constructor: function(node, params){// summary: an object, which makes a node moveable// node: Node: a node (or node's id) to be moved// params: Object: an optional object with additional parameters;// following parameters are recognized:// box: Object: a constraint box// the rest is passed to the base classvar box = params && params.box;this.constraints = function(){ return box; };}});dojo.declare("dojo.dnd.move.parentConstrainedMoveable", dojo.dnd.move.constrainedMoveable, {// object attributes (for markup)area: "content",// markup methodsmarkupFactory: function(params, node){return new dojo.dnd.move.parentConstrainedMoveable(node, params);},constructor: function(node, params){// summary: an object, which makes a node moveable// node: Node: a node (or node's id) to be moved// params: Object: an optional object with additional parameters;// following parameters are recognized:// area: String: a parent's area to restrict the move,// can be "margin", "border", "padding", or "content".// the rest is passed to the base classvar area = params && params.area;this.constraints = function(){var n = this.node.parentNode,s = dojo.getComputedStyle(n),mb = dojo._getMarginBox(n, s);if(area == "margin"){return mb; // Object}var t = dojo._getMarginExtents(n, s);mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;if(area == "border"){return mb; // Object}t = dojo._getBorderExtents(n, s);mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;if(area == "padding"){return mb; // Object}t = dojo._getPadExtents(n, s);mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;return mb; // Object};}});// WARNING: below are obsolete objects, instead of custom movers use custom moveables (above)dojo.dnd.move.constrainedMover = function(fun, within){// summary: returns a constrained version of dojo.dnd.Mover// description: this function produces n object, which will put a constraint on// the margin box of dragged object in absolute coordinates// fun: Function: called on drag, and returns a constraint box// within: Boolean: if true, constraints the whole dragged object withtin the rectangle,// otherwise the constraint is applied to the left-top cornervar mover = function(node, e, notifier){dojo.dnd.Mover.call(this, node, e, notifier);};dojo.extend(mover, dojo.dnd.Mover.prototype);dojo.extend(mover, {onMouseMove: function(e){// summary: event processor for onmousemove// e: Event: mouse eventdojo.dnd.autoScroll(e);var m = this.marginBox, c = this.constraintBox,l = m.l + e.pageX, t = m.t + e.pageY;l = l < c.l ? c.l : c.r < l ? c.r : l;t = t < c.t ? c.t : c.b < t ? c.b : t;this.host.onMove(this, {l: l, t: t});},onFirstMove: function(){// summary: called once to initialize things; it is meant to be called only oncedojo.dnd.Mover.prototype.onFirstMove.call(this);var c = this.constraintBox = fun.call(this), m = this.marginBox;c.r = c.l + c.w - (within ? m.w : 0);c.b = c.t + c.h - (within ? m.h : 0);}});return mover; // Object};dojo.dnd.move.boxConstrainedMover = function(box, within){// summary: a specialization of dojo.dnd.constrainedMover, which constrains to the specified box// box: Object: a constraint box (l, t, w, h)// within: Boolean: if true, constraints the whole dragged object withtin the rectangle,// otherwise the constraint is applied to the left-top cornerreturn dojo.dnd.move.constrainedMover(function(){ return box; }, within); // Object};dojo.dnd.move.parentConstrainedMover = function(area, within){// summary: a specialization of dojo.dnd.constrainedMover, which constrains to the parent node// area: String: "margin" to constrain within the parent's margin box, "border" for the border box,// "padding" for the padding box, and "content" for the content box; "content" is the default value.// within: Boolean: if true, constraints the whole dragged object withtin the rectangle,// otherwise the constraint is applied to the left-top cornervar fun = function(){var n = this.node.parentNode,s = dojo.getComputedStyle(n),mb = dojo._getMarginBox(n, s);if(area == "margin"){return mb; // Object}var t = dojo._getMarginExtents(n, s);mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;if(area == "border"){return mb; // Object}t = dojo._getBorderExtents(n, s);mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;if(area == "padding"){return mb; // Object}t = dojo._getPadExtents(n, s);mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;return mb; // Object};return dojo.dnd.move.constrainedMover(fun, within); // Object};// patching functions one level up for compatibilitydojo.dnd.constrainedMover = dojo.dnd.move.constrainedMover;dojo.dnd.boxConstrainedMover = dojo.dnd.move.boxConstrainedMover;dojo.dnd.parentConstrainedMover = dojo.dnd.move.parentConstrainedMover;}if(!dojo._hasResource["dojo.fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.fx"] = true;dojo.provide("dojo.fx");dojo.provide("dojo.fx.Toggler");dojo.fx.chain = function(/*dojo._Animation[]*/ animations){// summary: Chain a list of dojo._Animation s to run in sequence// example:// | dojo.fx.chain([// | dojo.fadeIn({ node:node }),// | dojo.fadeOut({ node:otherNode })// | ]).play();//var first = animations.shift();var previous = first;dojo.forEach(animations, function(current){dojo.connect(previous, "onEnd", current, "play");previous = current;});return first; // dojo._Animation};dojo.fx.combine = function(/*dojo._Animation[]*/ animations){// summary: Combine a list of dojo._Animation s to run in parallel// example:// | dojo.fx.combine([// | dojo.fadeIn({ node:node }),// | dojo.fadeOut({ node:otherNode })// | ]).play();var ctr = new dojo._Animation({ curve: [0, 1] });if(!animations.length){ return ctr; }// animations.sort(function(a, b){ return a.duration-b.duration; });ctr.duration = animations[0].duration;dojo.forEach(animations, function(current){dojo.forEach([ "play", "pause", "stop" ],function(e){if(current[e]){dojo.connect(ctr, e, current, e);}});});return ctr; // dojo._Animation};dojo.declare("dojo.fx.Toggler", null, {// summary:// class constructor for an animation toggler. It accepts a packed// set of arguments about what type of animation to use in each// direction, duration, etc.//// example:// | var t = new dojo.fx.Toggler({// | node: "nodeId",// | showDuration: 500,// | // hideDuration will default to "200"// | showFunc: dojo.wipeIn,// | // hideFunc will default to "fadeOut"// | });// | t.show(100); // delay showing for 100ms// | // ...time passes...// | t.hide();// FIXME: need a policy for where the toggler should "be" the next// time show/hide are called if we're stopped somewhere in the// middle.constructor: function(args){var _t = this;dojo.mixin(_t, args);_t.node = args.node;_t._showArgs = dojo.mixin({}, args);_t._showArgs.node = _t.node;_t._showArgs.duration = _t.showDuration;_t.showAnim = _t.showFunc(_t._showArgs);_t._hideArgs = dojo.mixin({}, args);_t._hideArgs.node = _t.node;_t._hideArgs.duration = _t.hideDuration;_t.hideAnim = _t.hideFunc(_t._hideArgs);dojo.connect(_t.showAnim, "beforeBegin", dojo.hitch(_t.hideAnim, "stop", true));dojo.connect(_t.hideAnim, "beforeBegin", dojo.hitch(_t.showAnim, "stop", true));},// node: DomNode// the node to togglenode: null,// showFunc: Function// The function that returns the dojo._Animation to show the nodeshowFunc: dojo.fadeIn,// hideFunc: Function// The function that returns the dojo._Animation to hide the nodehideFunc: dojo.fadeOut,// showDuration:// Time in milliseconds to run the show AnimationshowDuration: 200,// hideDuration:// Time in milliseconds to run the hide AnimationhideDuration: 200,/*=====_showArgs: null,_showAnim: null,_hideArgs: null,_hideAnim: null,_isShowing: false,_isHiding: false,=====*/show: function(delay){// summary: Toggle the node to showingreturn this.showAnim.play(delay || 0);},hide: function(delay){// summary: Toggle the node to hiddenreturn this.hideAnim.play(delay || 0);}});dojo.fx.wipeIn = function(/*Object*/ args){// summary// Returns an animation that will expand the// node defined in 'args' object from it's current height to// it's natural height (with no scrollbar).// Node must have no margin/border/padding.args.node = dojo.byId(args.node);var node = args.node, s = node.style;var anim = dojo.animateProperty(dojo.mixin({properties: {height: {// wrapped in functions so we wait till the last second to query (in case value has changed)start: function(){// start at current [computed] height, but use 1px rather than 0// because 0 causes IE to display the whole panels.overflow="hidden";if(s.visibility=="hidden"||s.display=="none"){s.height="1px";s.display="";s.visibility="";return 1;}else{var height = dojo.style(node, "height");return Math.max(height, 1);}},end: function(){return node.scrollHeight;}}}}, args));dojo.connect(anim, "onEnd", function(){s.height = "auto";});return anim; // dojo._Animation}dojo.fx.wipeOut = function(/*Object*/ args){// summary// Returns an animation that will shrink node defined in "args"// from it's current height to 1px, and then hide it.var node = args.node = dojo.byId(args.node);var s = node.style;var anim = dojo.animateProperty(dojo.mixin({properties: {height: {end: 1 // 0 causes IE to display the whole panel}}}, args));dojo.connect(anim, "beforeBegin", function(){s.overflow = "hidden";s.display = "";});dojo.connect(anim, "onEnd", function(){s.height = "auto";s.display = "none";});return anim; // dojo._Animation}dojo.fx.slideTo = function(/*Object?*/ args){// summary// Returns an animation that will slide "node"// defined in args Object from its current position to// the position defined by (args.left, args.top).// example:// | dojo.fx.slideTo({ node: node, left:"40", top:"50", unit:"px" }).play()var node = (args.node = dojo.byId(args.node));var top = null;var left = null;var init = (function(n){return function(){var cs = dojo.getComputedStyle(n);var pos = cs.position;top = (pos == 'absolute' ? n.offsetTop : parseInt(cs.top) || 0);left = (pos == 'absolute' ? n.offsetLeft : parseInt(cs.left) || 0);if(pos != 'absolute' && pos != 'relative'){var ret = dojo.coords(n, true);top = ret.y;left = ret.x;n.style.position="absolute";n.style.top=top+"px";n.style.left=left+"px";}};})(node);init();var anim = dojo.animateProperty(dojo.mixin({properties: {top: { end: args.top||0 },left: { end: args.left||0 }}}, args));dojo.connect(anim, "beforeBegin", anim, init);return anim; // dojo._Animation}}if(!dojo._hasResource["dijit.layout.ContentPane"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.layout.ContentPane"] = true;dojo.provide("dijit.layout.ContentPane");dojo.declare("dijit.layout.ContentPane",dijit._Widget,{// summary:// A widget that acts as a Container for other widgets, and includes a ajax interface// description:// A widget that can be used as a standalone widget// or as a baseclass for other widgets// Handles replacement of document fragment using either external uri or javascript// generated markup or DOM content, instantiating widgets within that content.// Don't confuse it with an iframe, it only needs/wants document fragments.// It's useful as a child of LayoutContainer, SplitContainer, or TabContainer.// But note that those classes can contain any widget as a child.// example:// Some quick samples:// To change the innerHTML use .setContent('<b>new content</b>')//// Or you can send it a NodeList, .setContent(dojo.query('div [class=selected]', userSelection))// please note that the nodes in NodeList will copied, not moved//// To do a ajax update use .setHref('url')//// href: String// The href of the content that displays now.// Set this at construction if you want to load data externally when the// pane is shown. (Set preload=true to load it immediately.)// Changing href after creation doesn't have any effect; see setHref();href: "",// extractContent: Boolean// Extract visible content from inside of <body> .... </body>extractContent: false,// parseOnLoad: Boolean// parse content and create the widgets, if anyparseOnLoad: true,// preventCache: Boolean// Cache content retreived externallypreventCache: false,// preload: Boolean// Force load of data even if pane is hidden.preload: false,// refreshOnShow: Boolean// Refresh (re-download) content when pane goes from hidden to shownrefreshOnShow: false,// loadingMessage: String// Message that shows while downloadingloadingMessage: "<span class='dijitContentPaneLoading'>${loadingState}</span>",// errorMessage: String// Message that shows if an error occurserrorMessage: "<span class='dijitContentPaneError'>${errorState}</span>",// isLoaded: Boolean// Tells loading status see onLoad|onUnload for event hooksisLoaded: false,// class: String// Class name to apply to ContentPane dom nodes"class": "dijitContentPane",postCreate: function(){// remove the title attribute so it doesn't show up when i hover// over a nodethis.domNode.title = "";if(this.preload){this._loadCheck();}var messages = dojo.i18n.getLocalization("dijit", "loading", this.lang);this.loadingMessage = dojo.string.substitute(this.loadingMessage, messages);this.errorMessage = dojo.string.substitute(this.errorMessage, messages);// for programatically created ContentPane (with <span> tag), need to muck w/CSS// or it's as though overflow:visible is setdojo.addClass(this.domNode, this["class"]);},startup: function(){if(this._started){ return; }this._checkIfSingleChild();if(this._singleChild){this._singleChild.startup();}this._loadCheck();this._started = true;},_checkIfSingleChild: function(){// summary:// Test if we have exactly one widget as a child, and if so assume that we are a container for that widget,// and should propogate startup() and resize() calls to it.var childNodes = dojo.query(">", this.containerNode || this.domNode),childWidgets = childNodes.filter("[widgetId]");if(childNodes.length == 1 && childWidgets.length == 1){this.isContainer = true;this._singleChild = dijit.byNode(childWidgets[0]);}else{delete this.isContainer;delete this._singleChild;}},refresh: function(){// summary:// Force a refresh (re-download) of content, be sure to turn off cache// we return result of _prepareLoad here to avoid code dup. in dojox.layout.ContentPanereturn this._prepareLoad(true);},setHref: function(/*String|Uri*/ href){// summary:// Reset the (external defined) content of this pane and replace with new url// Note: It delays the download until widget is shown if preload is false// href:// url to the page you want to get, must be within the same domain as your mainpagethis.href = href;// we return result of _prepareLoad here to avoid code dup. in dojox.layout.ContentPanereturn this._prepareLoad();},setContent: function(/*String|DomNode|Nodelist*/data){// summary:// Replaces old content with data content, include style classes from old content// data:// the new Content may be String, DomNode or NodeList//// if data is a NodeList (or an array of nodes) nodes are copied// so you can import nodes from another document implicitly// clear href so we cant run refresh and clear content// refresh should only work if we downloaded the contentif(!this._isDownloaded){this.href = "";this._onUnloadHandler();}this._setContent(data || "");this._isDownloaded = false; // must be set after _setContent(..), pathadjust in dojox.layout.ContentPaneif(this.parseOnLoad){this._createSubWidgets();}this._checkIfSingleChild();if(this._singleChild && this._singleChild.resize){this._singleChild.resize(this._contentBox);}this._onLoadHandler();},cancel: function(){// summary:// Cancels a inflight download of contentif(this._xhrDfd && (this._xhrDfd.fired == -1)){this._xhrDfd.cancel();}delete this._xhrDfd; // garbage collect},destroy: function(){// if we have multiple controllers destroying us, bail after the firstif(this._beingDestroyed){return;}// make sure we call onUnloadthis._onUnloadHandler();this._beingDestroyed = true;this.inherited("destroy",arguments);},resize: function(size){dojo.marginBox(this.domNode, size);// Compute content box size in case we [later] need to size child// If either height or width wasn't specified by the user, then query node for it.// But note that setting the margin box and then immediately querying dimensions may return// inaccurate results, so try not to depend on it.var node = this.containerNode || this.domNode,mb = dojo.mixin(dojo.marginBox(node), size||{});this._contentBox = dijit.layout.marginBox2contentBox(node, mb);// If we have a single widget child then size it to fit snugly within my bordersif(this._singleChild && this._singleChild.resize){this._singleChild.resize(this._contentBox);}},_prepareLoad: function(forceLoad){// sets up for a xhrLoad, load is deferred until widget onShow// cancels a inflight downloadthis.cancel();this.isLoaded = false;this._loadCheck(forceLoad);},_loadCheck: function(forceLoad){// call this when you change onShow (onSelected) status when selected in parent container// it's used as a trigger for href download when this.domNode.display != 'none'// sequence:// if no href -> bail// forceLoad -> always load// this.preload -> load when download not in progress, domNode display doesn't matter// this.refreshOnShow -> load when download in progress bails, domNode display !='none' AND// this.open !== false (undefined is ok), isLoaded doesn't matter// else -> load when download not in progress, if this.open !== false (undefined is ok) AND// domNode display != 'none', isLoaded must be falsevar displayState = ((this.open !== false) && (this.domNode.style.display != 'none'));if(this.href &&(forceLoad ||(this.preload && !this._xhrDfd) ||(this.refreshOnShow && displayState && !this._xhrDfd) ||(!this.isLoaded && displayState && !this._xhrDfd))){this._downloadExternalContent();}},_downloadExternalContent: function(){this._onUnloadHandler();// display loading messagethis._setContent(this.onDownloadStart.call(this));var self = this;var getArgs = {preventCache: (this.preventCache || this.refreshOnShow),url: this.href,handleAs: "text"};if(dojo.isObject(this.ioArgs)){dojo.mixin(getArgs, this.ioArgs);}var hand = this._xhrDfd = (this.ioMethod || dojo.xhrGet)(getArgs);hand.addCallback(function(html){try{self.onDownloadEnd.call(self);self._isDownloaded = true;self.setContent.call(self, html); // onload event is called from here}catch(err){self._onError.call(self, 'Content', err); // onContentError}delete self._xhrDfd;return html;});hand.addErrback(function(err){if(!hand.cancelled){// show error message in the paneself._onError.call(self, 'Download', err); // onDownloadError}delete self._xhrDfd;return err;});},_onLoadHandler: function(){this.isLoaded = true;try{this.onLoad.call(this);}catch(e){console.error('Error '+this.widgetId+' running custom onLoad code');}},_onUnloadHandler: function(){this.isLoaded = false;this.cancel();try{this.onUnload.call(this);}catch(e){console.error('Error '+this.widgetId+' running custom onUnload code');}},_setContent: function(cont){this.destroyDescendants();try{var node = this.containerNode || this.domNode;while(node.firstChild){dojo._destroyElement(node.firstChild);}if(typeof cont == "string"){// dijit.ContentPane does only minimal fixes,// No pathAdjustments, script retrieval, style clean etc// some of these should be available in the dojox.layout.ContentPaneif(this.extractContent){match = cont.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);if(match){ cont = match[1]; }}node.innerHTML = cont;}else{// domNode or NodeListif(cont.nodeType){ // domNode (htmlNode 1 or textNode 3)node.appendChild(cont);}else{// nodelist or array such as dojo.Nodelistdojo.forEach(cont, function(n){node.appendChild(n.cloneNode(true));});}}}catch(e){// check if a domfault occurs when we are appending this.errorMessage// like for instance if domNode is a UL and we try append a DIVvar errMess = this.onContentError(e);try{node.innerHTML = errMess;}catch(e){console.error('Fatal '+this.id+' could not change content due to '+e.message, e);}}},_onError: function(type, err, consoleText){// shows user the string that is returned by on[type]Error// overide on[type]Error and return your own string to customizevar errText = this['on' + type + 'Error'].call(this, err);if(consoleText){console.error(consoleText, err);}else if(errText){// a empty string won't change current contentthis._setContent.call(this, errText);}},_createSubWidgets: function(){// summary: scan my contents and create subwidgetsvar rootNode = this.containerNode || this.domNode;try{dojo.parser.parse(rootNode, true);}catch(e){this._onError('Content', e, "Couldn't create widgets in "+this.id+(this.href ? " from "+this.href : ""));}},// EVENT's, should be overide-ableonLoad: function(e){// summary:// Event hook, is called after everything is loaded and widgetified},onUnload: function(e){// summary:// Event hook, is called before old content is cleared},onDownloadStart: function(){// summary:// called before download starts// the string returned by this function will be the html// that tells the user we are loading something// override with your own function if you want to change textreturn this.loadingMessage;},onContentError: function(/*Error*/ error){// summary:// called on DOM faults, require fault etc in content// default is to display errormessage inside pane},onDownloadError: function(/*Error*/ error){// summary:// Called when download error occurs, default is to display// errormessage inside pane. Overide function to change that.// The string returned by this function will be the html// that tells the user a error happendreturn this.errorMessage;},onDownloadEnd: function(){// summary:// called when download is finished}});}if(!dojo._hasResource["dijit.form.Form"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.form.Form"] = true;dojo.provide("dijit.form.Form");dojo.declare("dijit.form._FormMixin", null,{/*summary:Widget corresponding to <form> tag, for validation and serializationusage:<form dojoType="dijit.form.Form" id="myForm">Name: <input type="text" name="name" /></form>myObj={name: "John Doe"};dijit.byId('myForm').setValues(myObj);myObj=dijit.byId('myForm').getValues();TODO:* Repeater* better handling for arrays. Often form elements have names with [] like* people[3].sex (for a list of people [{name: Bill, sex: M}, ...])*/// HTML <FORM> attributesaction: "",method: "",enctype: "",name: "","accept-charset": "",accept: "",target: "",attributeMap: dojo.mixin(dojo.clone(dijit._Widget.prototype.attributeMap),{action: "", method: "", enctype: "", "accept-charset": "", accept: "", target: ""}),// execute: Function// User defined function to do stuff when the user hits the submit buttonexecute: function(/*Object*/ formContents){},// onCancel: Function// Callback when user has canceled dialog, to notify container// (user shouldn't override)onCancel: function(){},// onExecute: Function// Callback when user is about to execute dialog, to notify container// (user shouldn't override)onExecute: function(){},templateString: "<form dojoAttachPoint='containerNode' dojoAttachEvent='onsubmit:_onSubmit' name='${name}' enctype='multipart/form-data'></form>",_onSubmit: function(/*event*/e) {// summary: callback when user hits submit buttondojo.stopEvent(e);this.onExecute(); // notify container that we are about to executethis.execute(this.getValues());},submit: function() {// summary: programatically submit formthis.containerNode.submit();},setValues: function(/*object*/obj) {// summary: fill in form values from a JSON structure// generate map from name --> [list of widgets with that name]var map = {};dojo.forEach(this.getDescendants(), function(widget){if(!widget.name){ return; }var entry = map[widget.name] || (map[widget.name] = [] );entry.push(widget);});// call setValue() or setChecked() for each widget, according to objfor(var name in map){var widgets = map[name], // array of widgets w/this namevalues = dojo.getObject(name, false, obj); // list of values for those widgetsif(!dojo.isArray(values)){values = [ values ];}if(widgets[0].setChecked){// for checkbox/radio, values is a list of which widgets should be checkeddojo.forEach(widgets, function(w, i){w.setChecked(dojo.indexOf(values, w.value) != -1);});}else{// otherwise, values is a list of values to be assigned sequentially to each widgetdojo.forEach(widgets, function(w, i){w.setValue(values[i]);});}}/**** TODO: code for plain input boxes (this shouldn't run for inputs that are part of widgetsdojo.forEach(this.containerNode.elements, function(element){if (element.name == ''){return}; // like "continue"var namePath = element.name.split(".");var myObj=obj;var name=namePath[namePath.length-1];for(var j=1,len2=namePath.length;j<len2;++j) {var p=namePath[j - 1];// repeater support blockvar nameA=p.split("[");if (nameA.length > 1) {if(typeof(myObj[nameA[0]]) == "undefined") {myObj[nameA[0]]=[ ];} // ifnameIndex=parseInt(nameA[1]);if(typeof(myObj[nameA[0]][nameIndex]) == "undefined") {myObj[nameA[0]][nameIndex]={};}myObj=myObj[nameA[0]][nameIndex];continue;} // repeater support endsif(typeof(myObj[p]) == "undefined") {myObj=undefined;break;};myObj=myObj[p];}if (typeof(myObj) == "undefined") {return; // like "continue"}if (typeof(myObj[name]) == "undefined" && this.ignoreNullValues) {return; // like "continue"}// TODO: widget values (just call setValue() on the widget)switch(element.type) {case "checkbox":element.checked = (name in myObj) &&dojo.some(myObj[name], function(val){ return val==element.value; });break;case "radio":element.checked = (name in myObj) && myObj[name]==element.value;break;case "select-multiple":element.selectedIndex=-1;dojo.forEach(element.options, function(option){option.selected = dojo.some(myObj[name], function(val){ return option.value == val; });});break;case "select-one":element.selectedIndex="0";dojo.forEach(element.options, function(option){option.selected = option.value == myObj[name];});break;case "hidden":case "text":case "textarea":case "password":element.value = myObj[name] || "";break;}});*/},getValues: function() {// summary: generate JSON structure from form values// get widget valuesvar obj = {};dojo.forEach(this.getDescendants(), function(widget){var value = widget.getValue ? widget.getValue() : widget.value;var name = widget.name;if(!name){ return; }// Store widget's value(s) as a scalar, except for checkboxes which are automatically arraysif(widget.setChecked){if(/Radio/.test(widget.declaredClass)){// radio buttonif(widget.checked){dojo.setObject(name, value, obj);}}else{// checkbox/toggle buttonvar ary=dojo.getObject(name, false, obj);if(!ary){ary=[];dojo.setObject(name, ary, obj);}if(widget.checked){ary.push(value);}}}else{// plain inputdojo.setObject(name, value, obj);}});/**** code for plain input boxes (see also dojo.formToObject, can we use that instead of this code?* but it doesn't understand [] notation, presumably)var obj = { };dojo.forEach(this.containerNode.elements, function(elm){if (!elm.name) {return; // like "continue"}var namePath = elm.name.split(".");var myObj=obj;var name=namePath[namePath.length-1];for(var j=1,len2=namePath.length;j<len2;++j) {var nameIndex = null;var p=namePath[j - 1];var nameA=p.split("[");if (nameA.length > 1) {if(typeof(myObj[nameA[0]]) == "undefined") {myObj[nameA[0]]=[ ];} // ifnameIndex=parseInt(nameA[1]);if(typeof(myObj[nameA[0]][nameIndex]) == "undefined") {myObj[nameA[0]][nameIndex]={};}} else if(typeof(myObj[nameA[0]]) == "undefined") {myObj[nameA[0]]={}} // ifif (nameA.length == 1) {myObj=myObj[nameA[0]];} else {myObj=myObj[nameA[0]][nameIndex];} // if} // forif ((elm.type != "select-multiple" && elm.type != "checkbox" && elm.type != "radio") || (elm.type=="radio" && elm.checked)) {if(name == name.split("[")[0]) {myObj[name]=elm.value;} else {// can not set value when there is no name}} else if (elm.type == "checkbox" && elm.checked) {if(typeof(myObj[name]) == 'undefined') {myObj[name]=[ ];}myObj[name].push(elm.value);} else if (elm.type == "select-multiple") {if(typeof(myObj[name]) == 'undefined') {myObj[name]=[ ];}for (var jdx=0,len3=elm.options.length; jdx<len3; ++jdx) {if (elm.options[jdx].selected) {myObj[name].push(elm.options[jdx].value);}}} // ifname=undefined;}); // forEach***/return obj;},isValid: function() {// TODO: ComboBox might need time to process a recently input value. This should be async?// make sure that every widget that has a validator function returns truereturn dojo.every(this.getDescendants(), function(widget){return !widget.isValid || widget.isValid();});}});dojo.declare("dijit.form.Form",[dijit._Widget, dijit._Templated, dijit.form._FormMixin],null);}if(!dojo._hasResource["dijit.Dialog"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.Dialog"] = true;dojo.provide("dijit.Dialog");dojo.declare("dijit.DialogUnderlay",[dijit._Widget, dijit._Templated],{// summary: the thing that grays out the screen behind the dialog// Template has two divs; outer div is used for fade-in/fade-out, and also to hold background iframe.// Inner div has opacity specified in CSS file.templateString: "<div class=dijitDialogUnderlayWrapper id='${id}_underlay'><div class=dijitDialogUnderlay dojoAttachPoint='node'></div></div>",postCreate: function(){dojo.body().appendChild(this.domNode);this.bgIframe = new dijit.BackgroundIframe(this.domNode);},layout: function(){// summary// Sets the background to the size of the viewport (rather than the size// of the document) since we need to cover the whole browser window, even// if the document is only a few lines long.var viewport = dijit.getViewport();var is = this.node.style,os = this.domNode.style;os.top = viewport.t + "px";os.left = viewport.l + "px";is.width = viewport.w + "px";is.height = viewport.h + "px";// process twice since the scroll bar may have been removed// by the previous resizingvar viewport2 = dijit.getViewport();if(viewport.w != viewport2.w){ is.width = viewport2.w + "px"; }if(viewport.h != viewport2.h){ is.height = viewport2.h + "px"; }},show: function(){this.domNode.style.display = "block";this.layout();if(this.bgIframe.iframe){this.bgIframe.iframe.style.display = "block";}this._resizeHandler = this.connect(window, "onresize", "layout");},hide: function(){this.domNode.style.display = "none";if(this.bgIframe.iframe){this.bgIframe.iframe.style.display = "none";}this.disconnect(this._resizeHandler);},uninitialize: function(){if(this.bgIframe){this.bgIframe.destroy();}}});dojo.declare("dijit.Dialog",[dijit.layout.ContentPane, dijit._Templated, dijit.form._FormMixin],{// summary:// Pops up a modal dialog window, blocking access to the screen// and also graying out the screen Dialog is extended from// ContentPane so it supports all the same parameters (href, etc.)templateString: null,templateString:"<div class=\"dijitDialog\">\n\t<div dojoAttachPoint=\"titleBar\" class=\"dijitDialogTitleBar\" tabindex=\"0\" waiRole=\"dialog\">\n\t<span dojoAttachPoint=\"titleNode\" class=\"dijitDialogTitle\">${title}</span>\n\t<span dojoAttachPoint=\"closeButtonNode\" class=\"dijitDialogCloseIcon\" dojoAttachEvent=\"onclick: hide\">\n\t\t<span dojoAttachPoint=\"closeText\" class=\"closeText\">x</span>\n\t</span>\n\t</div>\n\t\t<div dojoAttachPoint=\"containerNode\" class=\"dijitDialogPaneContent\"></div>\n\t<span dojoAttachPoint=\"tabEnd\" dojoAttachEvent=\"onfocus:_cycleFocus\" tabindex=\"0\"></span>\n</div>\n",// open: Boolean// is True or False depending on state of dialogopen: false,// duration: Integer// The time in milliseconds it takes the dialog to fade in and outduration: 400,_lastFocusItem:null,attributeMap: dojo.mixin(dojo.clone(dijit._Widget.prototype.attributeMap),{title: "titleBar"}),postCreate: function(){dojo.body().appendChild(this.domNode);this.inherited("postCreate",arguments);this.domNode.style.display="none";this.connect(this, "onExecute", "hide");this.connect(this, "onCancel", "hide");},onLoad: function(){// summary:// when href is specified we need to reposition the dialog after the data is loadedthis._position();this.inherited("onLoad",arguments);},_setup: function(){// summary:// stuff we need to do before showing the Dialog for the first// time (but we defer it until right beforehand, for// performance reasons)this._modalconnects = [];if(this.titleBar){this._moveable = new dojo.dnd.Moveable(this.domNode, { handle: this.titleBar });}this._underlay = new dijit.DialogUnderlay();var node = this.domNode;this._fadeIn = dojo.fx.combine([dojo.fadeIn({node: node,duration: this.duration}),dojo.fadeIn({node: this._underlay.domNode,duration: this.duration,onBegin: dojo.hitch(this._underlay, "show")})]);this._fadeOut = dojo.fx.combine([dojo.fadeOut({node: node,duration: this.duration,onEnd: function(){node.style.display="none";}}),dojo.fadeOut({node: this._underlay.domNode,duration: this.duration,onEnd: dojo.hitch(this._underlay, "hide")})]);},uninitialize: function(){if(this._underlay){this._underlay.destroy();}},_position: function(){// summary: position modal dialog in center of screenif(dojo.hasClass(dojo.body(),"dojoMove")){ return; }var viewport = dijit.getViewport();var mb = dojo.marginBox(this.domNode);var style = this.domNode.style;style.left = Math.floor((viewport.l + (viewport.w - mb.w)/2)) + "px";style.top = Math.floor((viewport.t + (viewport.h - mb.h)/2)) + "px";},_findLastFocus: function(/*Event*/ evt){// summary: called from onblur of dialog container to determine the last focusable itemthis._lastFocused = evt.target;},_cycleFocus: function(/*Event*/ evt){// summary: when tabEnd receives focus, advance focus around to titleBar// on first focus to tabEnd, store the last focused item in dialogif(!this._lastFocusItem){this._lastFocusItem = this._lastFocused;}this.titleBar.focus();},_onKey: function(/*Event*/ evt){if(evt.keyCode){var node = evt.target;// see if we are shift-tabbing from titleBarif(node == this.titleBar && evt.shiftKey && evt.keyCode == dojo.keys.TAB){if(this._lastFocusItem){this._lastFocusItem.focus(); // send focus to last item in dialog if known}dojo.stopEvent(evt);}else{// see if the key is for the dialogwhile(node){if(node == this.domNode){if(evt.keyCode == dojo.keys.ESCAPE){this.hide();}else{return; // just let it go}}node = node.parentNode;}// this key is for the disabled document windowif(evt.keyCode != dojo.keys.TAB){ // allow tabbing into the dialog for a11ydojo.stopEvent(evt);// opera won't tab to a div}else if (!dojo.isOpera){try{this.titleBar.focus();}catch(e){/*squelch*/}}}}},show: function(){// summary: display the dialog// first time we show the dialog, there's some initialization stuff to doif(!this._alreadyInitialized){this._setup();this._alreadyInitialized=true;}if(this._fadeOut.status() == "playing"){this._fadeOut.stop();}this._modalconnects.push(dojo.connect(window, "onscroll", this, "layout"));this._modalconnects.push(dojo.connect(document.documentElement, "onkeypress", this, "_onKey"));// IE doesn't bubble onblur events - use ondeactivate insteadvar ev = typeof(document.ondeactivate) == "object" ? "ondeactivate" : "onblur";this._modalconnects.push(dojo.connect(this.containerNode, ev, this, "_findLastFocus"));dojo.style(this.domNode, "opacity", 0);this.domNode.style.display="block";this.open = true;this._loadCheck(); // lazy load triggerthis._position();this._fadeIn.play();this._savedFocus = dijit.getFocus(this);// set timeout to allow the browser to render dialogsetTimeout(dojo.hitch(this, function(){dijit.focus(this.titleBar);}), 50);},hide: function(){// summary// Hide the dialog// if we haven't been initialized yet then we aren't showing and we can just returnif(!this._alreadyInitialized){return;}if(this._fadeIn.status() == "playing"){this._fadeIn.stop();}this._fadeOut.play();if (this._scrollConnected){this._scrollConnected = false;}dojo.forEach(this._modalconnects, dojo.disconnect);this._modalconnects = [];this.connect(this._fadeOut,"onEnd",dojo.hitch(this,function(){dijit.focus(this._savedFocus);}));this.open = false;},layout: function() {// summary: position the Dialog and the underlayif(this.domNode.style.display == "block"){this._underlay.layout();this._position();}}});dojo.declare("dijit.TooltipDialog",[dijit.layout.ContentPane, dijit._Templated, dijit.form._FormMixin],{// summary:// Pops up a dialog that appears like a Tooltip// title: String// Description of tooltip dialog (required for a11Y)title: "",_lastFocusItem: null,templateString: null,templateString:"<div class=\"dijitTooltipDialog\" >\n\t<div class=\"dijitTooltipContainer\">\n\t\t<div class =\"dijitTooltipContents dijitTooltipFocusNode\" dojoAttachPoint=\"containerNode\" tabindex=\"0\" waiRole=\"dialog\"></div>\n\t</div>\n\t<span dojoAttachPoint=\"tabEnd\" tabindex=\"0\" dojoAttachEvent=\"focus:_cycleFocus\"></span>\n\t<div class=\"dijitTooltipConnector\" ></div>\n</div>\n",postCreate: function(){this.inherited("postCreate",arguments);this.connect(this.containerNode, "onkeypress", "_onKey");// IE doesn't bubble onblur events - use ondeactivate insteadvar ev = typeof(document.ondeactivate) == "object" ? "ondeactivate" : "onblur";this.connect(this.containerNode, ev, "_findLastFocus");this.containerNode.title=this.title;},orient: function(/*Object*/ corner){// summary: configure widget to be displayed in given position relative to the buttonthis.domNode.className="dijitTooltipDialog " +" dijitTooltipAB"+(corner.charAt(1)=='L'?"Left":"Right")+" dijitTooltip"+(corner.charAt(0)=='T' ? "Below" : "Above");},onOpen: function(/*Object*/ pos){// summary: called when dialog is displayedthis.orient(pos.corner);this._loadCheck(); // lazy load triggerthis.containerNode.focus();},_onKey: function(/*Event*/ evt){// summary: keep keyboard focus in dialog; close dialog on escape keyif(evt.keyCode == dojo.keys.ESCAPE){this.onCancel();}else if(evt.target == this.containerNode && evt.shiftKey && evt.keyCode == dojo.keys.TAB){if (this._lastFocusItem){this._lastFocusItem.focus();}dojo.stopEvent(evt);}else if(evt.keyCode == dojo.keys.TAB){// we want the browser's default tab handling to move focus// but we don't want the tab to propagate upwardsevt.stopPropagation();}},_findLastFocus: function(/*Event*/ evt){// summary: called from onblur of dialog container to determine the last focusable itemthis._lastFocused = evt.target;},_cycleFocus: function(/*Event*/ evt){// summary: when tabEnd receives focus, advance focus around to containerNode// on first focus to tabEnd, store the last focused item in dialogif(!this._lastFocusItem){this._lastFocusItem = this._lastFocused;}this.containerNode.focus();}});}if(!dojo._hasResource["dijit._editor.selection"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit._editor.selection"] = true;dojo.provide("dijit._editor.selection");// FIXME:// all of these methods branch internally for IE. This is probably// sub-optimal in terms of runtime performance. We should investigate the// size difference for differentiating at definition time.dojo.mixin(dijit._editor.selection, {getType: function(){// summary: Get the selection type (like document.select.type in IE).if(dojo.doc["selection"]){ //IEreturn dojo.doc.selection.type.toLowerCase();}else{var stype = "text";// Check if the actual selection is a CONTROL (IMG, TABLE, HR, etc...).var oSel;try{oSel = dojo.global.getSelection();}catch(e){ /*squelch*/ }if(oSel && oSel.rangeCount==1){var oRange = oSel.getRangeAt(0);if( (oRange.startContainer == oRange.endContainer) &&((oRange.endOffset - oRange.startOffset) == 1) &&(oRange.startContainer.nodeType != 3 /* text node*/)){stype = "control";}}return stype;}},getSelectedText: function(){// summary:// Return the text (no html tags) included in the current selection or null if no text is selectedif(dojo.doc["selection"]){ //IEif(dijit._editor.selection.getType() == 'control'){return null;}return dojo.doc.selection.createRange().text;}else{var selection = dojo.global.getSelection();if(selection){return selection.toString();}}},getSelectedHtml: function(){// summary:// Return the html of the current selection or null if unavailableif(dojo.doc["selection"]){ //IEif(dijit._editor.selection.getType() == 'control'){return null;}return dojo.doc.selection.createRange().htmlText;}else{var selection = dojo.global.getSelection();if(selection && selection.rangeCount){var frag = selection.getRangeAt(0).cloneContents();var div = document.createElement("div");div.appendChild(frag);return div.innerHTML;}return null;}},getSelectedElement: function(){// summary:// Retrieves the selected element (if any), just in the case that// a single element (object like and image or a table) is// selected.if(this.getType() == "control"){if(dojo.doc["selection"]){ //IEvar range = dojo.doc.selection.createRange();if(range && range.item){return dojo.doc.selection.createRange().item(0);}}else{var selection = dojo.global.getSelection();return selection.anchorNode.childNodes[ selection.anchorOffset ];}}},getParentElement: function(){// summary:// Get the parent element of the current selectionif(this.getType() == "control"){var p = this.getSelectedElement();if(p){ return p.parentNode; }}else{if(dojo.doc["selection"]){ //IEreturn dojo.doc.selection.createRange().parentElement();}else{var selection = dojo.global.getSelection();if(selection){var node = selection.anchorNode;while(node && (node.nodeType != 1)){ // not an elementnode = node.parentNode;}return node;}}}},hasAncestorElement: function(/*String*/tagName /* ... */){// summary:// Check whether current selection has a parent element which is// of type tagName (or one of the other specified tagName)return (this.getAncestorElement.apply(this, arguments) != null);},getAncestorElement: function(/*String*/tagName /* ... */){// summary:// Return the parent element of the current selection which is of// type tagName (or one of the other specified tagName)var node = this.getSelectedElement() || this.getParentElement();return this.getParentOfType(node, arguments);},isTag: function(/*DomNode*/node, /*Array*/tags){if(node && node.tagName){var _nlc = node.tagName.toLowerCase();for(var i=0; i<tags.length; i++){var _tlc = String(tags[i]).toLowerCase();if(_nlc == _tlc){return _tlc;}}}return "";},getParentOfType: function(/*DomNode*/node, /*Array*/tags){while(node){if(this.isTag(node, tags).length){return node;}node = node.parentNode;}return null;},remove: function(){// summary: delete current selectionvar _s = dojo.doc.selection;if(_s){ //IEif(_s.type.toLowerCase() != "none"){_s.clear();}return _s;}else{_s = dojo.global.getSelection();_s.deleteFromDocument();return _s;}},selectElementChildren: function(/*DomNode*/element,/*Boolean?*/nochangefocus){// summary:// clear previous selection and select the content of the node// (excluding the node itself)var _window = dojo.global;var _document = dojo.doc;element = dojo.byId(element);if(_document.selection && dojo.body().createTextRange){ // IEvar range = element.ownerDocument.body.createTextRange();range.moveToElementText(element);if(!nochangefocus){range.select();}}else if(_window["getSelection"]){var selection = _window.getSelection();if(selection["setBaseAndExtent"]){ // Safariselection.setBaseAndExtent(element, 0, element, element.innerText.length - 1);}else if(selection["selectAllChildren"]){ // Mozillaselection.selectAllChildren(element);}}},selectElement: function(/*DomNode*/element,/*Boolean?*/nochangefocus){// summary:// clear previous selection and select element (including all its children)var _document = dojo.doc;element = dojo.byId(element);if(_document.selection && dojo.body().createTextRange){ // IEtry{var range = dojo.body().createControlRange();range.addElement(element);if(!nochangefocus){range.select();}}catch(e){this.selectElementChildren(element,nochangefocus);}}else if(dojo.global["getSelection"]){var selection = dojo.global.getSelection();// FIXME: does this work on Safari?if(selection["removeAllRanges"]){ // Mozillavar range = _document.createRange() ;range.selectNode(element) ;selection.removeAllRanges() ;selection.addRange(range) ;}}}});}if(!dojo._hasResource["dijit._editor.RichText"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit._editor.RichText"] = true;dojo.provide("dijit._editor.RichText");// used to restore content when user leaves this page then comes back// but do not try doing document.write if we are using xd loading.// document.write will only work if RichText.js is included in the dojo.js// file. If it is included in dojo.js and you want to allow rich text saving// for back/forward actions, then set djConfig.allowXdRichTextSave = true.if(!djConfig["useXDomain"] || djConfig["allowXdRichTextSave"]){if(dojo._postLoad){(function(){var savetextarea = dojo.doc.createElement('textarea');savetextarea.id = "dijit._editor.RichText.savedContent";var s = savetextarea.style;s.display='none';s.position='absolute';s.top="-100px";s.left="-100px"s.height="3px";s.width="3px";dojo.body().appendChild(savetextarea);})();}else{//dojo.body() is not available before onLoad is firedtry {dojo.doc.write('<textarea id="dijit._editor.RichText.savedContent" ' +'style="display:none;position:absolute;top:-100px;left:-100px;height:3px;width:3px;overflow:hidden;"></textarea>');}catch(e){ }}}dojo.declare("dijit._editor.RichText", [ dijit._Widget ], {constructor: function(){// summary:// dijit._editor.RichText is the core of the WYSIWYG editor in dojo, which// provides the basic editing features. It also encapsulates the differences// of different js engines for various browsers//// contentPreFilters: Array// pre content filter function register array.// these filters will be executed before the actual// editing area get the html contentthis.contentPreFilters = [];// contentPostFilters: Array// post content filter function register array.// these will be used on the resulting html// from contentDomPostFilters. The resuling// content is the final html (returned by getValue())this.contentPostFilters = [];// contentDomPreFilters: Array// pre content dom filter function register array.// these filters are applied after the result from// contentPreFilters are set to the editing areathis.contentDomPreFilters = [];// contentDomPostFilters: Array// post content dom filter function register array.// these filters are executed on the editing area dom// the result from these will be passed to contentPostFiltersthis.contentDomPostFilters = [];// editingAreaStyleSheets: Array// array to store all the stylesheets applied to the editing areathis.editingAreaStyleSheets=[];this._keyHandlers = {};this.contentPreFilters.push(dojo.hitch(this, "_preFixUrlAttributes"));if(dojo.isMoz){this.contentPreFilters.push(this._fixContentForMoz);}//this.contentDomPostFilters.push(this._postDomFixUrlAttributes);this.onLoadDeferred = new dojo.Deferred();},// inheritWidth: Boolean// whether to inherit the parent's width or simply use 100%inheritWidth: false,// focusOnLoad: Boolean// whether focusing into this instance of richtext when page onloadfocusOnLoad: false,// name: String// If a save name is specified the content is saved and restored when the user// leave this page can come back, or if the editor is not properly closed after// editing has started.name: "",// styleSheets: String// semicolon (";") separated list of css files for the editing areastyleSheets: "",// _content: String// temporary content storage_content: "",// height: String// set height to fix the editor at a specific height, with scrolling.// By default, this is 300px. If you want to have the editor always// resizes to accommodate the content, use AlwaysShowToolbar plugin// and set height=""height: "300px",// minHeight: String// The minimum height that the editor should haveminHeight: "1em",// isClosed: BooleanisClosed: true,// isLoaded: BooleanisLoaded: false,// _SEPARATOR: String// used to concat contents from multiple textareas into a single string_SEPARATOR: "@@**%%__RICHTEXTBOUNDRY__%%**@@",// onLoadDeferred: dojo.Deferred// deferred which is fired when the editor finishes loadingonLoadDeferred: null,postCreate: function(){// summary: initdojo.publish("dijit._editor.RichText::init", [this]);this.open();this.setupDefaultShortcuts();},setupDefaultShortcuts: function(){// summary: add some default key handlers// description:// Overwrite this to setup your own handlers. The default// implementation does not use Editor commands, but directly// executes the builtin commands within the underlying browser// support.var ctrl = this.KEY_CTRL;var exec = function(cmd, arg){return arguments.length == 1 ? function(){ this.execCommand(cmd); } :function(){ this.execCommand(cmd, arg); }}this.addKeyHandler("b", ctrl, exec("bold"));this.addKeyHandler("i", ctrl, exec("italic"));this.addKeyHandler("u", ctrl, exec("underline"));this.addKeyHandler("a", ctrl, exec("selectall"));this.addKeyHandler("s", ctrl, function () { this.save(true); });this.addKeyHandler("1", ctrl, exec("formatblock", "h1"));this.addKeyHandler("2", ctrl, exec("formatblock", "h2"));this.addKeyHandler("3", ctrl, exec("formatblock", "h3"));this.addKeyHandler("4", ctrl, exec("formatblock", "h4"));this.addKeyHandler("\\", ctrl, exec("insertunorderedlist"));if(!dojo.isIE){this.addKeyHandler("Z", ctrl, exec("redo"));}},// events: Array// events which should be connected to the underlying editing areaevents: ["onKeyPress", "onKeyDown", "onKeyUp", "onClick"],// events: Array// events which should be connected to the underlying editing// area, events in this array will be addListener with// capture=truecaptureEvents: [],_editorCommandsLocalized: false,_localizeEditorCommands: function(){if(this._editorCommandsLocalized){return;}this._editorCommandsLocalized = true;//in IE, names for blockformat is locale dependent, so we cache the values here//if the normal way fails, we try the hard way to get the list//do not use _cacheLocalBlockFormatNames here, as it will//trigger security warning in IE7//in the array below, ul can not come directly after ol,//otherwise the queryCommandValue returns Normal for itvar formats = ['p', 'pre', 'address', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'div', 'ul'];var localhtml = "", format, i=0;while((format=formats[i++])){if(format.charAt(1) != 'l'){localhtml += "<"+format+"><span>content</span></"+format+">";}else{localhtml += "<"+format+"><li>content</li></"+format+">";}}//queryCommandValue returns empty if we hide editNode, so move it out of screen temporaryvar div=document.createElement('div');div.style.position = "absolute";div.style.left = "-2000px";div.style.top = "-2000px";document.body.appendChild(div);div.innerHTML = localhtml;var node = div.firstChild;while(node){dijit._editor.selection.selectElement(node.firstChild);dojo.withGlobal(this.window, "selectElement", dijit._editor.selection, [node.firstChild]);var nativename = node.tagName.toLowerCase();this._local2NativeFormatNames[nativename] = document.queryCommandValue("formatblock");//this.queryCommandValue("formatblock");this._native2LocalFormatNames[this._local2NativeFormatNames[nativename]] = nativename;node = node.nextSibling;}document.body.removeChild(div);},open: function(/*DomNode?*/element){// summary:// Transforms the node referenced in this.domNode into a rich text editing// node. This will result in the creation and replacement with an <iframe>// if designMode(FF)/contentEditable(IE) is used.if((!this.onLoadDeferred)||(this.onLoadDeferred.fired >= 0)){this.onLoadDeferred = new dojo.Deferred();}if(!this.isClosed){ this.close(); }dojo.publish("dijit._editor.RichText::open", [ this ]);this._content = "";if((arguments.length == 1)&&(element["nodeName"])){ this.domNode = element; } // else unchangedif( (this.domNode["nodeName"])&&(this.domNode.nodeName.toLowerCase() == "textarea")){// if we were created from a textarea, then we need to create a// new editing harness node.this.textarea = this.domNode;this.name=this.textarea.name;var html = this._preFilterContent(this.textarea.value);this.domNode = dojo.doc.createElement("div");this.domNode.setAttribute('widgetId',this.id);this.textarea.removeAttribute('widgetId');this.domNode.cssText = this.textarea.cssText;this.domNode.className += " "+this.textarea.className;dojo.place(this.domNode, this.textarea, "before");var tmpFunc = dojo.hitch(this, function(){//some browsers refuse to submit display=none textarea, so//move the textarea out of screen insteadwith(this.textarea.style){display = "block";position = "absolute";left = top = "-1000px";if(dojo.isIE){ //nasty IE bug: abnormal formatting if overflow is not hiddenthis.__overflow = overflow;overflow = "hidden";}}});if(dojo.isIE){setTimeout(tmpFunc, 10);}else{tmpFunc();}// this.domNode.innerHTML = html;// if(this.textarea.form){// // FIXME: port: this used to be before advice!!!// dojo.connect(this.textarea.form, "onsubmit", this, function(){// // FIXME: should we be calling close() here instead?// this.textarea.value = this.getValue();// });// }}else{var html = this._preFilterContent(this.getNodeChildrenHtml(this.domNode));this.domNode.innerHTML = '';}if(html == ""){ html = " "; }var content = dojo.contentBox(this.domNode);// var content = dojo.contentBox(this.srcNodeRef);this._oldHeight = content.h;this._oldWidth = content.w;this.savedContent = html;// If we're a list item we have to put in a blank line to force the// bullet to nicely align at the top of textif( (this.domNode["nodeName"]) &&(this.domNode.nodeName == "LI") ){this.domNode.innerHTML = " <br>";}this.editingArea = dojo.doc.createElement("div");this.domNode.appendChild(this.editingArea);if(this.name != "" && (!djConfig["useXDomain"] || djConfig["allowXdRichTextSave"])){var saveTextarea = dojo.byId("dijit._editor.RichText.savedContent");if(saveTextarea.value != ""){var datas = saveTextarea.value.split(this._SEPARATOR), i=0, dat;while((dat=datas[i++])){var data = dat.split(":");if(data[0] == this.name){html = data[1];datas.splice(i, 1);break;}}}// FIXME: need to do something different for Opera/Safaridojo.connect(window, "onbeforeunload", this, "_saveContent");// dojo.connect(window, "onunload", this, "_saveContent");}this.isClosed = false;// Safari's selections go all out of whack if we do it inline,// so for now IE is our only hero//if (typeof document.body.contentEditable != "undefined") {if(dojo.isIE || dojo.isSafari || dojo.isOpera){ // contentEditable, easyvar ifr = this.iframe = dojo.doc.createElement('iframe');ifr.src = 'javascript:void(0)';this.editorObject = ifr;ifr.style.border = "none";ifr.style.width = "100%";ifr.frameBorder = 0;// ifr.style.scrolling = this.height ? "auto" : "vertical";this.editingArea.appendChild(ifr);this.window = ifr.contentWindow;this.document = this.window.document;this.document.open();this.document.write(this._getIframeDocTxt(html));this.document.close();if(dojo.isIE >= 7){if(this.height){ifr.style.height = this.height;}if(this.minHeight){ifr.style.minHeight = this.minHeight;}}else{ifr.style.height = this.height ? this.height : this.minHeight;}if(dojo.isIE){this._localizeEditorCommands();}this.onLoad();}else{ // designMode in iframethis._drawIframe(html);}// TODO: this is a guess at the default line-height, kinda worksif(this.domNode.nodeName == "LI"){ this.domNode.lastChild.style.marginTop = "-1.2em"; }this.domNode.className += " RichTextEditable";},//static cache variables shared among all instance of this class_local2NativeFormatNames: {},_native2LocalFormatNames: {},_localizedIframeTitles: null,_getIframeDocTxt: function(/* String */ html){var _cs = dojo.getComputedStyle(this.domNode);if(!this.height && !dojo.isMoz){html="<div>"+html+"</div>";}var font = [ _cs.fontWeight, _cs.fontSize, _cs.fontFamily ].join(" ");// line height is tricky - applying a units value will mess things up.// if we can't get a non-units value, bail out.var lineHeight = _cs.lineHeight;if(lineHeight.indexOf("px") >= 0){lineHeight = parseFloat(lineHeight)/parseFloat(_cs.fontSize);// console.debug(lineHeight);}else if(lineHeight.indexOf("em")>=0){lineHeight = parseFloat(lineHeight);}else{lineHeight = "1.0";}return [this.isLeftToRight() ? "<html><head>" : "<html dir='rtl'><head>",(dojo.isMoz ? "<title>" + this._localizedIframeTitles.iframeEditTitle + "</title>" : ""),"<style>","body,html {"," background:transparent;"," padding: 0;"," margin: 0;","}",// TODO: left positioning will cause contents to disappear out of view// if it gets too wide for the visible area"body{"," top:0px; left:0px; right:0px;",((this.height||dojo.isOpera) ? "" : "position: fixed;")," font:", font, ";",// FIXME: IE 6 won't understand min-height?" min-height:", this.minHeight, ";"," line-height:", lineHeight,"}","p{ margin: 1em 0 !important; }",(this.height ?"" : "body,html{overflow-y:hidden;/*for IE*/} body > div {overflow-x:auto;/*for FF to show vertical scrollbar*/}"),"li > ul:-moz-first-node, li > ol:-moz-first-node{ padding-top: 1.2em; } ","li{ min-height:1.2em; }","</style>",this._applyEditingAreaStyleSheets(),"</head><body>"+html+"</body></html>"].join(""); // String},_drawIframe: function(/*String*/html){// summary:// Draws an iFrame using the existing one if one exists.// Used by Mozilla, Safari, and Operaif(!this.iframe){var ifr = this.iframe = dojo.doc.createElement("iframe");// this.iframe.src = "about:blank";// document.body.appendChild(this.iframe);// console.debug(this.iframe.contentDocument.open());// dojo.body().appendChild(this.iframe);var ifrs = ifr.style;// ifrs.border = "1px solid black";ifrs.border = "none";ifrs.lineHeight = "0"; // squash line heightifrs.verticalAlign = "bottom";// ifrs.scrolling = this.height ? "auto" : "vertical";this.editorObject = this.iframe;// get screen reader text for mozilla here, toothis._localizedIframeTitles = dojo.i18n.getLocalization("dijit", "Textarea");// need to find any associated label element and update iframe document titlevar label=dojo.query('label[for="'+this.id+'"]');if(label.length){this._localizedIframeTitles.iframeEditTitle = label[0].innerHTML + " " + this._localizedIframeTitles.iframeEditTitle;}}// opera likes this to be outside the with block// this.iframe.src = "javascript:void(0)";//dojo.uri.dojoUri("src/widget/templates/richtextframe.html") + ((dojo.doc.domain != currentDomain) ? ("#"+dojo.doc.domain) : "");this.iframe.style.width = this.inheritWidth ? this._oldWidth : "100%";if(this.height){this.iframe.style.height = this.height;}else{this.iframe.height = this._oldHeight;}if(this.textarea){var tmpContent = this.srcNodeRef;}else{var tmpContent = dojo.doc.createElement('div');tmpContent.style.display="none";tmpContent.innerHTML = html;//append tmpContent to under the current domNode so that the margin//calculation below is correctthis.editingArea.appendChild(tmpContent);}this.editingArea.appendChild(this.iframe);//do we want to show the content before the editing area finish loading here?//if external style sheets are used for the editing area, the appearance now//and after loading of the editing area won't be the same (and padding/margin//calculation above may not be accurate)// tmpContent.style.display = "none";// this.editingArea.appendChild(this.iframe);var _iframeInitialized = false;// console.debug(this.iframe);// var contentDoc = this.iframe.contentWindow.document;// note that on Safari lower than 420+, we have to get the iframe// by ID in order to get something w/ a contentDocument propertyvar contentDoc = this.iframe.contentDocument;contentDoc.open();contentDoc.write(this._getIframeDocTxt(html));contentDoc.close();// now we wait for onload. Janky hack!var ifrFunc = dojo.hitch(this, function(){if(!_iframeInitialized){_iframeInitialized = true;}else{ return; }if(!this.editNode){try{if(this.iframe.contentWindow){this.window = this.iframe.contentWindow;this.document = this.iframe.contentWindow.document}else if(this.iframe.contentDocument){// for operathis.window = this.iframe.contentDocument.window;this.document = this.iframe.contentDocument;}if(!this.document.body){throw 'Error';}}catch(e){setTimeout(ifrFunc,500);_iframeInitialized = false;return;}dojo._destroyElement(tmpContent);this.document.designMode = "on";// try{// this.document.designMode = "on";// }catch(e){// this._tryDesignModeOnClick=true;// }this.onLoad();}else{dojo._destroyElement(tmpContent);this.editNode.innerHTML = html;this.onDisplayChanged();}this._preDomFilterContent(this.editNode);});ifrFunc();},_applyEditingAreaStyleSheets: function(){// summary:// apply the specified css files in styleSheetsvar files = [];if(this.styleSheets){files = this.styleSheets.split(';');this.styleSheets = '';}//empty this.editingAreaStyleSheets here, as it will be filled in addStyleSheetfiles = files.concat(this.editingAreaStyleSheets);this.editingAreaStyleSheets = [];var text='', i=0, url;while((url=files[i++])){var abstring = (new dojo._Url(dojo.global.location, url)).toString();this.editingAreaStyleSheets.push(abstring);text += '<link rel="stylesheet" type="text/css" href="'+abstring+'"/>'}return text;},addStyleSheet: function(/*dojo._Url*/uri){// summary:// add an external stylesheet for the editing area// uri: a dojo.uri.Uri pointing to the url of the external css filevar url=uri.toString();//if uri is relative, then convert it to absolute so that it can be resolved correctly in iframeif(url.charAt(0) == '.' || (url.charAt(0) != '/' && !uri.host)){url = (new dojo._Url(dojo.global.location, url)).toString();}if(dojo.indexOf(this.editingAreaStyleSheets, url) > -1){console.debug("dijit._editor.RichText.addStyleSheet: Style sheet "+url+" is already applied to the editing area!");return;}this.editingAreaStyleSheets.push(url);if(this.document.createStyleSheet){ //IEthis.document.createStyleSheet(url);}else{ //other browservar head = this.document.getElementsByTagName("head")[0];var stylesheet = this.document.createElement("link");with(stylesheet){rel="stylesheet";type="text/css";href=url;}head.appendChild(stylesheet);}},removeStyleSheet: function(/*dojo._Url*/uri){// summary:// remove an external stylesheet for the editing areavar url=uri.toString();//if uri is relative, then convert it to absolute so that it can be resolved correctly in iframeif(url.charAt(0) == '.' || (url.charAt(0) != '/' && !uri.host)){url = (new dojo._Url(dojo.global.location, url)).toString();}var index = dojo.indexOf(this.editingAreaStyleSheets, url);if(index == -1){console.debug("dijit._editor.RichText.removeStyleSheet: Style sheet "+url+" is not applied to the editing area so it can not be removed!");return;}delete this.editingAreaStyleSheets[index];dojo.withGlobal(this.window,'query', dojo, ['link:[href="'+url+'"]']).orphan()},disabled: false,_mozSettingProps: ['styleWithCSS','insertBrOnReturn'],setDisabled: function(/*Boolean*/ disabled){if(dojo.isIE || dojo.isSafari || dojo.isOpera){this.editNode.contentEditable=!disabled;}else{ //mozif(disabled){this._mozSettings=[false,this.blockNodeForEnter==='BR'];}this.document.designMode=(disabled?'off':'on');if(!disabled){dojo.forEach(this._mozSettingProps, function(s,i){this.document.execCommand(s,false,this._mozSettings[i]);},this);}// this.document.execCommand('contentReadOnly', false, disabled);// if(disabled){// this.blur(); //to remove the blinking caret// }//}this.disabled=disabled;},/* Event handlers*****************/_isResized: function(){ return false; },onLoad: function(/* Event */ e){// summary: handler after the content of the document finishes loadingthis.isLoaded = true;if(this.height || dojo.isMoz){this.editNode=this.document.body;}else{this.editNode=this.document.body.firstChild;}this.editNode.contentEditable = true; //should do no harm in FFthis._preDomFilterContent(this.editNode);var events=this.events.concat(this.captureEvents),i=0,et;while((et=events[i++])){this.connect(this.document, et.toLowerCase(), et);}if(!dojo.isIE){try{ // sanity check for Mozilla// this.document.execCommand("useCSS", false, true); // old moz callthis.document.execCommand("styleWithCSS", false, false); // new moz call//this.document.execCommand("insertBrOnReturn", false, false); // new moz call}catch(e2){ }// FIXME: when scrollbars appear/disappear this needs to be fired}else{ // IE contentEditable// give the node Layout on IEthis.editNode.style.zoom = 1.0;}if(this.focusOnLoad){this.focus();}this.onDisplayChanged(e);if(this.onLoadDeferred){this.onLoadDeferred.callback(true);}},onKeyDown: function(/* Event */ e){// summary: Fired on keydown// console.info("onkeydown:", e.keyCode);// we need this event at the moment to get the events from control keys// such as the backspace. It might be possible to add this to Dojo, so that// keyPress events can be emulated by the keyDown and keyUp detection.if(dojo.isIE){if(e.keyCode === dojo.keys.BACKSPACE && this.document.selection.type === "Control"){// IE has a bug where if a non-text object is selected in the editor,// hitting backspace would act as if the browser's back button was// clicked instead of deleting the object. see #1069dojo.stopEvent(e);this.execCommand("delete");}else if( (65 <= e.keyCode&&e.keyCode <= 90) ||(e.keyCode>=37&&e.keyCode<=40) // FIXME: get this from connect() instead!){ //arrow keyse.charCode = e.keyCode;this.onKeyPress(e);}}else if (dojo.isMoz){if(e.keyCode == dojo.keys.TAB && !e.shiftKey && !e.ctrlKey && !e.altKey && this.iframe){// update iframe document title for screen readerthis.iframe.contentDocument.title = this._localizedIframeTitles.iframeFocusTitle;// Place focus on the iframe. A subsequent tab or shift tab will put focus// on the correct control.this.iframe.focus(); // this.focus(); won't workdojo.stopEvent(e);}else if (e.keyCode == dojo.keys.TAB && e.shiftKey){// if there is a toolbar, set focus to it, otherwise ignoreif (this.toolbar){this.toolbar.focus();}dojo.stopEvent(e);}}},onKeyUp: function(e){// summary: Fired on keyupreturn;},KEY_CTRL: 1,KEY_SHIFT: 2,onKeyPress: function(e){// summary: Fired on keypress// console.info("onkeypress:", e.keyCode);// handle the various key eventsvar modifiers = e.ctrlKey ? this.KEY_CTRL : 0 | e.shiftKey?this.KEY_SHIFT : 0;var key = e.keyChar||e.keyCode;if(this._keyHandlers[key]){// console.debug("char:", e.key);var handlers = this._keyHandlers[key], i = 0, h;while((h = handlers[i++])){if(modifiers == h.modifiers){if(!h.handler.apply(this,arguments)){e.preventDefault();}break;}}}// function call after the character has been insertedsetTimeout(dojo.hitch(this, function(){this.onKeyPressed(e);}), 1);},addKeyHandler: function(/*String*/key, /*Int*/modifiers, /*Function*/handler){// summary: add a handler for a keyboard shortcutif(!dojo.isArray(this._keyHandlers[key])){ this._keyHandlers[key] = []; }this._keyHandlers[key].push({modifiers: modifiers || 0,handler: handler});},onKeyPressed: function(/*Event*/e){this.onDisplayChanged(/*e*/); // can't pass in e},onClick: function(/*Event*/e){// console.debug('onClick',this._tryDesignModeOnClick);// if(this._tryDesignModeOnClick){// try{// this.document.designMode='on';// this._tryDesignModeOnClick=false;// }catch(e){}// }this.onDisplayChanged(e); },_onBlur: function(e){var _c=this.getValue(true);if(_c!=this.savedContent){this.onChange(_c);this.savedContent=_c;}if (dojo.isMoz && this.iframe){this.iframe.contentDocument.title = this._localizedIframeTitles.iframeEditTitle;}// console.info('_onBlur')},_initialFocus: true,_onFocus: function(/*Event*/e){// console.info('_onFocus')// summary: Fired on focusif( (dojo.isMoz)&&(this._initialFocus) ){this._initialFocus = false;if(this.editNode.innerHTML.replace(/^\s+|\s+$/g, "") == " "){this.placeCursorAtStart();// this.execCommand("selectall");// this.window.getSelection().collapseToStart();}}},blur: function(){// summary: remove focus from this instanceif(this.iframe){this.window.blur();}else if(this.editNode){this.editNode.blur();}},focus: function(){// summary: move focus to this instanceif(this.iframe && !dojo.isIE){dijit.focus(this.iframe);}else if(this.editNode && this.editNode.focus){// editNode may be hidden in display:none div, lets just punt in this casedijit.focus(this.editNode);}else{console.debug("Have no idea how to focus into the editor!");}},// _lastUpdate: 0,updateInterval: 200,_updateTimer: null,onDisplayChanged: function(/*Event*/e){// summary:// This event will be fired everytime the display context// changes and the result needs to be reflected in the UI.// description:// If you don't want to have update too often,// onNormalizedDisplayChanged should be used instead// var _t=new Date();if(!this._updateTimer){// this._lastUpdate=_t;if(this._updateTimer){clearTimeout(this._updateTimer);}this._updateTimer=setTimeout(dojo.hitch(this,this.onNormalizedDisplayChanged),this.updateInterval);}},onNormalizedDisplayChanged: function(){// summary:// This event is fired every updateInterval ms or more// description:// If something needs to happen immidiately after a// user change, please use onDisplayChanged insteadthis._updateTimer=null;},onChange: function(newContent){// summary:// this is fired if and only if the editor loses focus and// the content is changed// console.log('onChange',newContent);},_normalizeCommand: function(/*String*/cmd){// summary:// Used as the advice function by dojo.connect to map our// normalized set of commands to those supported by the target// browservar command = cmd.toLowerCase();if(command == "formatblock"){if(dojo.isSafari){ command = "heading"; }}else if(command == "hilitecolor" && !dojo.isMoz){command = "backcolor";}return command;},queryCommandAvailable: function(/*String*/command){// summary:// Tests whether a command is supported by the host. Clients SHOULD check// whether a command is supported before attempting to use it, behaviour// for unsupported commands is undefined.// command: The command to test forvar ie = 1;var mozilla = 1 << 1;var safari = 1 << 2;var opera = 1 << 3;var safari420 = 1 << 4;var gt420 = dojo.isSafari;function isSupportedBy(browsers){return {ie: Boolean(browsers & ie),mozilla: Boolean(browsers & mozilla),safari: Boolean(browsers & safari),safari420: Boolean(browsers & safari420),opera: Boolean(browsers & opera)}}var supportedBy = null;switch(command.toLowerCase()){case "bold": case "italic": case "underline":case "subscript": case "superscript":case "fontname": case "fontsize":case "forecolor": case "hilitecolor":case "justifycenter": case "justifyfull": case "justifyleft":case "justifyright": case "delete": case "selectall":supportedBy = isSupportedBy(mozilla | ie | safari | opera);break;case "createlink": case "unlink": case "removeformat":case "inserthorizontalrule": case "insertimage":case "insertorderedlist": case "insertunorderedlist":case "indent": case "outdent": case "formatblock":case "inserthtml": case "undo": case "redo": case "strikethrough":supportedBy = isSupportedBy(mozilla | ie | opera | safari420);break;case "blockdirltr": case "blockdirrtl":case "dirltr": case "dirrtl":case "inlinedirltr": case "inlinedirrtl":supportedBy = isSupportedBy(ie);break;case "cut": case "copy": case "paste":supportedBy = isSupportedBy( ie | mozilla | safari420);break;case "inserttable":supportedBy = isSupportedBy(mozilla | ie);break;case "insertcell": case "insertcol": case "insertrow":case "deletecells": case "deletecols": case "deleterows":case "mergecells": case "splitcell":supportedBy = isSupportedBy(ie | mozilla);break;default: return false;}return (dojo.isIE && supportedBy.ie) ||(dojo.isMoz && supportedBy.mozilla) ||(dojo.isSafari && supportedBy.safari) ||(gt420 && supportedBy.safari420) ||(dojo.isOpera && supportedBy.opera); // Boolean return true if the command is supported, false otherwise},execCommand: function(/*String*/command, argument){// summary: Executes a command in the Rich Text area// command: The command to execute// argument: An optional argument to the commandvar returnValue;//focus() is required for IE to work//In addition, focus() makes sure after the execution of//the command, the editor receives the focus as expectedthis.focus();command = this._normalizeCommand(command);if(argument != undefined){if(command == "heading"){throw new Error("unimplemented");}else if((command == "formatblock") && dojo.isIE){argument = '<'+argument+'>';}}if(command == "inserthtml"){//TODO: we shall probably call _preDomFilterContent here as wellargument=this._preFilterContent(argument);if(dojo.isIE){var insertRange = this.document.selection.createRange();insertRange.pasteHTML(argument);insertRange.select();//insertRange.collapse(true);returnValue=true;}else if(dojo.isMoz && !argument.length){//mozilla can not inserthtml an empty html to delete current selection//so we delete the selection instead in this casedojo.withGlobal(this.window,'remove',dijit._editor.selection); // FIXMEreturnValue=true;}else{returnValue=this.document.execCommand(command, false, argument);}}else if((command == "unlink")&&(this.queryCommandEnabled("unlink"))&&(dojo.isMoz || dojo.isSafari)){// fix up unlink in Mozilla to unlink the link and not just the selection// grab selection// Mozilla gets upset if we just store the range so we have to// get the basic properties and recreate to save the selectionvar selection = this.window.getSelection();// var selectionRange = selection.getRangeAt(0);// var selectionStartContainer = selectionRange.startContainer;// var selectionStartOffset = selectionRange.startOffset;// var selectionEndContainer = selectionRange.endContainer;// var selectionEndOffset = selectionRange.endOffset;// select our link and unlinkvar a = dojo.withGlobal(this.window, "getAncestorElement",dijit._editor.selection, ['a']);dojo.withGlobal(this.window, "selectElement", dijit._editor.selection, [a]);returnValue=this.document.execCommand("unlink", false, null);}else if((command == "hilitecolor")&&(dojo.isMoz)){// // mozilla doesn't support hilitecolor properly when useCSS is// // set to false (bugzilla #279330)this.document.execCommand("styleWithCSS", false, true);returnValue = this.document.execCommand(command, false, argument);this.document.execCommand("styleWithCSS", false, false);}else if((dojo.isIE)&&( (command == "backcolor")||(command == "forecolor") )){// Tested under IE 6 XP2, no problem here, comment out// IE weirdly collapses ranges when we exec these commands, so prevent it// var tr = this.document.selection.createRange();argument = arguments.length > 1 ? argument : null;returnValue = this.document.execCommand(command, false, argument);// timeout is workaround for weird IE behavior were the text// selection gets correctly re-created, but subsequent input// apparently isn't bound to it// setTimeout(function(){tr.select();}, 1);}else{argument = arguments.length > 1 ? argument : null;// if(dojo.isMoz){// this.document = this.iframe.contentWindow.document// }if(argument || command!="createlink"){returnValue = this.document.execCommand(command, false, argument);}}this.onDisplayChanged();return returnValue;},queryCommandEnabled: function(/*String*/command){// summary: check whether a command is enabled or notcommand = this._normalizeCommand(command);if(dojo.isMoz || dojo.isSafari){if(command == "unlink"){ // mozilla returns true always// console.debug(dojo.withGlobal(this.window, "hasAncestorElement",dijit._editor.selection, ['a']));return dojo.withGlobal(this.window, "hasAncestorElement",dijit._editor.selection, ['a']);}else if (command == "inserttable"){return true;}}//see #4109if(dojo.isSafari)if(command == "copy"){command="cut";}else if(command == "paste"){return true;}// return this.document.queryCommandEnabled(command);var elem = (dojo.isIE) ? this.document.selection.createRange() : this.document;return elem.queryCommandEnabled(command);},queryCommandState: function(command){// summary: check the state of a given commandcommand = this._normalizeCommand(command);return this.document.queryCommandState(command);},queryCommandValue: function(command){// summary: check the value of a given commandcommand = this._normalizeCommand(command);if(dojo.isIE && command == "formatblock"){return this._local2NativeFormatNames[this.document.queryCommandValue(command)];}return this.document.queryCommandValue(command);},// Misc.placeCursorAtStart: function(){// summary:// place the cursor at the start of the editing areathis.focus();//see comments in placeCursorAtEndvar isvalid=false;if(dojo.isMoz){var first=this.editNode.firstChild;while(first){if(first.nodeType == 3){if(first.nodeValue.replace(/^\s+|\s+$/g, "").length>0){isvalid=true;dojo.withGlobal(this.window, "selectElement", dijit._editor.selection, [first]);break;}}else if(first.nodeType == 1){isvalid=true;dojo.withGlobal(this.window, "selectElementChildren",dijit._editor.selection, [first]);break;}first = first.nextSibling;}}else{isvalid=true;dojo.withGlobal(this.window, "selectElementChildren",dijit._editor.selection, [this.editNode]);}if(isvalid){dojo.withGlobal(this.window, "collapse", dijit._editor.selection, [true]);}},placeCursorAtEnd: function(){// summary:// place the cursor at the end of the editing areathis.focus();//In mozilla, if last child is not a text node, we have to use selectElementChildren on this.editNode.lastChild//otherwise the cursor would be placed at the end of the closing tag of this.editNode.lastChildvar isvalid=false;if(dojo.isMoz){var last=this.editNode.lastChild;while(last){if(last.nodeType == 3){if(last.nodeValue.replace(/^\s+|\s+$/g, "").length>0){isvalid=true;dojo.withGlobal(this.window, "selectElement",dijit._editor.selection, [last]);break;}}else if(last.nodeType == 1){isvalid=true;if(last.lastChild){dojo.withGlobal(this.window, "selectElement",dijit._editor.selection, [last.lastChild]);}else{dojo.withGlobal(this.window, "selectElement",dijit._editor.selection, [last]);}break;}last = last.previousSibling;}}else{isvalid=true;dojo.withGlobal(this.window, "selectElementChildren",dijit._editor.selection, [this.editNode]);}if(isvalid){dojo.withGlobal(this.window, "collapse", dijit._editor.selection, [false]);}},getValue: function(/*Boolean?*/nonDestructive){// summary:// return the current content of the editing area (post filters are applied)if(this.textarea){if(this.isClosed || !this.isLoaded){return this.textarea.value;}}return this._postFilterContent(null, nonDestructive);},setValue: function(/*String*/html){// summary:// this function set the content. No undo history is preservedif(this.textarea && (this.isClosed || !this.isLoaded)){this.textarea.value=html;}else{html = this._preFilterContent(html);if(this.isClosed){this.domNode.innerHTML = html;this._preDomFilterContent(this.domNode);}else{this.editNode.innerHTML = html;this._preDomFilterContent(this.editNode);}}},replaceValue: function(/*String*/html){// summary:// this function set the content while trying to maintain the undo stack// (now only works fine with Moz, this is identical to setValue in all// other browsers)if(this.isClosed){this.setValue(html);}else if(this.window && this.window.getSelection && !dojo.isMoz){ // Safari// look ma! it's a totally f'd browser!this.setValue(html);}else if(this.window && this.window.getSelection){ // Mozhtml = this._preFilterContent(html);this.execCommand("selectall");if(dojo.isMoz && !html){ html = " " }this.execCommand("inserthtml", html);this._preDomFilterContent(this.editNode);}else if(this.document && this.document.selection){//IE//In IE, when the first element is not a text node, say//an <a> tag, when replacing the content of the editing//area, the <a> tag will be around all the content//so for now, use setValue for IE toothis.setValue(html);}},_preFilterContent: function(/*String*/html){// summary:// filter the input before setting the content of the editing areavar ec = html;dojo.forEach(this.contentPreFilters, function(ef){ if(ef){ ec = ef(ec); } });return ec;},_preDomFilterContent: function(/*DomNode*/dom){// summary:// filter the inputdom = dom || this.editNode;dojo.forEach(this.contentDomPreFilters, function(ef){if(ef && dojo.isFunction(ef)){ef(dom);}}, this);},_postFilterContent: function(/*DomNode|DomNode[]?*/dom,/*Boolean?*/nonDestructive){// summary:// filter the output after getting the content of the editing areadom = dom || this.editNode;if(this.contentDomPostFilters.length){if(nonDestructive && dom['cloneNode']){dom = dom.cloneNode(true);}dojo.forEach(this.contentDomPostFilters, function(ef){dom = ef(dom);});}var ec = this.getNodeChildrenHtml(dom);if(!ec.replace(/^(?:\s|\xA0)+/g, "").replace(/(?:\s|\xA0)+$/g,"").length){ ec = ""; }// if(dojo.isIE){// //removing appended <P> </P> for IE// ec = ec.replace(/(?:<p> </p>[\n\r]*)+$/i,"");// }dojo.forEach(this.contentPostFilters, function(ef){ec = ef(ec);});return ec;},_saveContent: function(/*Event*/e){// summary:// Saves the content in an onunload event if the editor has not been closedvar saveTextarea = dojo.byId("dijit._editor.RichText.savedContent");saveTextarea.value += this._SEPARATOR + this.name + ":" + this.getValue();},escapeXml: function(/*String*/str, /*Boolean*/noSingleQuotes){//summary:// Adds escape sequences for special characters in XML: &<>"'// Optionally skips escapes for single quotesstr = str.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """);if(!noSingleQuotes){str = str.replace(/'/gm, "'");}return str; // string},getNodeHtml: function(/* DomNode */node){switch(node.nodeType){case 1: //element nodevar output = '<'+node.tagName.toLowerCase();if(dojo.isMoz){if(node.getAttribute('type')=='_moz'){node.removeAttribute('type');}if(node.getAttribute('_moz_dirty') != undefined){node.removeAttribute('_moz_dirty');}}//store the list of attributes and sort it to have the//attributes appear in the dictionary ordervar attrarray = [];if(dojo.isIE){var s = node.outerHTML;s = s.substr(0,s.indexOf('>'));s = s.replace(/(?:['"])[^"']*\1/g, '');//to make the following regexp safevar reg = /([^\s=]+)=/g;var m, key;while((m = reg.exec(s)) != undefined){key=m[1];if(key.substr(0,3) != '_dj'){if(key == 'src' || key == 'href'){if(node.getAttribute('_djrealurl')){attrarray.push([key,node.getAttribute('_djrealurl')]);continue;}}if(key == 'class'){attrarray.push([key,node.className]);}else{attrarray.push([key,node.getAttribute(key)]);}}}}else{var attr, i=0, attrs = node.attributes;while((attr=attrs[i++])){//ignore all attributes starting with _dj which are//internal temporary attributes used by the editorif(attr.name.substr(0,3) != '_dj' /*&&(attr.specified == undefined || attr.specified)*/){var v = attr.value;if(attr.name == 'src' || attr.name == 'href'){if(node.getAttribute('_djrealurl')){v = node.getAttribute('_djrealurl');}}attrarray.push([attr.name,v]);}}}attrarray.sort(function(a,b){return a[0]<b[0]?-1:(a[0]==b[0]?0:1);});i=0;while((attr=attrarray[i++])){output += ' '+attr[0]+'="'+attr[1]+'"';}if(node.childNodes.length){output += '>' + this.getNodeChildrenHtml(node)+'</'+node.tagName.toLowerCase()+'>';}else{output += ' />';}break;case 3: //text// FIXME:var output = this.escapeXml(node.nodeValue,true);break;case 8: //comment// FIXME:var output = '<!--'+this.escapeXml(node.nodeValue,true)+'-->';break;default:var output = "Element not recognized - Type: " + node.nodeType + " Name: " + node.nodeName;}return output;},getNodeChildrenHtml: function(/* DomNode */dom){// summary: Returns the html content of a DomNode and childrenvar out = "";if(!dom){ return out; }var nodes = dom["childNodes"]||dom;var i=0;var node;while((node=nodes[i++])){out += this.getNodeHtml(node);}return out; // String},close: function(/*Boolean*/save, /*Boolean*/force){// summary:// Kills the editor and optionally writes back the modified contents to the// element from which it originated.// save:// Whether or not to save the changes. If false, the changes are discarded.// force:if(this.isClosed){return false; }if(!arguments.length){ save = true; }this._content = this.getValue();var changed = (this.savedContent != this._content);// line height is squashed for iframes// FIXME: why was this here? if (this.iframe){ this.domNode.style.lineHeight = null; }if(this.interval){ clearInterval(this.interval); }if(this.textarea){with(this.textarea.style){position = "";left = top = "";if(dojo.isIE){overflow = this.__overflow;this.__overflow = null;}}if(save){this.textarea.value = this._content;}else{this.textarea.value = this.savedContent;}dojo._destroyElement(this.domNode);this.domNode = this.textarea;}else{if(save){//why we treat moz differently? comment out to fix #1061// if(dojo.isMoz){// var nc = dojo.doc.createElement("span");// this.domNode.appendChild(nc);// nc.innerHTML = this.editNode.innerHTML;// }else{// this.domNode.innerHTML = this._content;// }this.domNode.innerHTML = this._content;}else{this.domNode.innerHTML = this.savedContent;}}dojo.removeClass(this.domNode, "RichTextEditable");this.isClosed = true;this.isLoaded = false;// FIXME: is this always the right thing to do?delete this.editNode;if(this.window && this.window._frameElement){this.window._frameElement = null;}this.window = null;this.document = null;this.editingArea = null;this.editorObject = null;return changed; // Boolean: whether the content has been modified},destroyRendering: function(){// summary: stub},destroy: function(){this.destroyRendering();if(!this.isClosed){ this.close(false); }this.inherited("destroy",arguments);//dijit._editor.RichText.superclass.destroy.call(this);},_fixContentForMoz: function(/* String */ html){// summary:// Moz can not handle strong/em tags correctly, convert them to b/ihtml = html.replace(/<(\/)?strong([ \>])/gi, '<$1b$2' );html = html.replace(/<(\/)?em([ \>])/gi, '<$1i$2' );return html; // String},_srcInImgRegex : /(?:(<img(?=\s).*?\ssrc=)("|')(.*?)\2)|(?:(<img\s.*?src=)([^"'][^ >]+))/gi ,_hrefInARegex : /(?:(<a(?=\s).*?\shref=)("|')(.*?)\2)|(?:(<a\s.*?href=)([^"'][^ >]+))/gi ,_preFixUrlAttributes: function(/* String */ html){html = html.replace(this._hrefInARegex, '$1$4$2$3$5$2 _djrealurl=$2$3$5$2') ;html = html.replace(this._srcInImgRegex, '$1$4$2$3$5$2 _djrealurl=$2$3$5$2') ;return html; // String}});}if(!dojo._hasResource["dijit.Toolbar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.Toolbar"] = true;dojo.provide("dijit.Toolbar");dojo.declare("dijit.Toolbar",[dijit._Widget, dijit._Templated, dijit._KeyNavContainer],{templateString:'<div class="dijit dijitToolbar" waiRole="toolbar" tabIndex="${tabIndex}" dojoAttachPoint="containerNode">' +// '<table style="table-layout: fixed" class="dijitReset dijitToolbarTable">' + // factor out style// '<tr class="dijitReset" dojoAttachPoint="containerNode"></tr>'+// '</table>' +'</div>',tabIndex: "0",postCreate: function(){this.connectKeyNavHandlers(this.isLeftToRight() ? [dojo.keys.LEFT_ARROW] : [dojo.keys.RIGHT_ARROW],this.isLeftToRight() ? [dojo.keys.RIGHT_ARROW] : [dojo.keys.LEFT_ARROW]);},startup: function(){this.startupKeyNavChildren();}});// Combine with dijit.MenuSeparator??dojo.declare("dijit.ToolbarSeparator",[ dijit._Widget, dijit._Templated ],{// summary// A line between two menu itemstemplateString: '<div class="dijitToolbarSeparator dijitInline"></div>',postCreate: function(){ dojo.setSelectable(this.domNode, false); },isFocusable: function(){ return false; }});}if(!dojo._hasResource["dijit.form.Button"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.form.Button"] = true;dojo.provide("dijit.form.Button");dojo.declare("dijit.form.Button", dijit.form._FormWidget, {/** usage* <button dojoType="button" onClick="...">Hello world</button>** var button1 = new dijit.form.Button({label: "hello world", onClick: foo});* dojo.body().appendChild(button1.domNode);*/// summary// Basically the same thing as a normal HTML button, but with special styling.// label: String// text to display in buttonlabel: "",// showLabel: Boolean// whether or not to display the text label in buttonshowLabel: true,// iconClass: String// class to apply to div in button to make it display an iconiconClass: "",type: "button",baseClass: "dijitButton",templateString:"<div class=\"dijit dijitLeft dijitInline dijitButton\"\n\tdojoAttachEvent=\"onclick:_onButtonClick,onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\"\n\t><div class='dijitRight'\n\t\t><button class=\"dijitStretch dijitButtonNode dijitButtonContents\" dojoAttachPoint=\"focusNode,titleNode\"\n\t\t\ttype=\"${type}\" waiRole=\"button\" waiState=\"labelledby-${id}_label\"\n\t\t\t><span class=\"dijitInline ${iconClass}\" dojoAttachPoint=\"iconNode\" \n \t\t\t\t><span class=\"dijitToggleButtonIconChar\">✓</span \n\t\t\t></span\n\t\t\t><span class=\"dijitButtonText\" id=\"${id}_label\" dojoAttachPoint=\"containerNode\">${label}</span\n\t\t></button\n\t></div\n></div>\n",// TODO: set button's title to this.containerNode.innerText_onClick: function(/*Event*/ e){// summary: internal function to handle click actionsif(this.disabled){ return false; }this._clicked(); // widget click actionsreturn this.onClick(e); // user click actions},_onButtonClick: function(/*Event*/ e){// summary: callback when the user mouse clicks the button portiondojo.stopEvent(e);var okToSubmit = this._onClick(e) !== false; // returning nothing is same as true// for some reason type=submit buttons don't automatically submit the form; do it manuallyif(this.type=="submit" && okToSubmit){for(var node=this.domNode; node; node=node.parentNode){var widget=dijit.byNode(node);if(widget && widget._onSubmit){widget._onSubmit(e);break;}if(node.tagName.toLowerCase() == "form"){if(!node.onsubmit || node.onsubmit()){ node.submit(); }break;}}}},postCreate: function(){// summary:// get label and set as title on button icon if necessaryif (this.showLabel == false){var labelText = "";this.label = this.containerNode.innerHTML;labelText = dojo.trim(this.containerNode.innerText || this.containerNode.textContent);// set title attrib on iconNodethis.titleNode.title=labelText;dojo.addClass(this.containerNode,"dijitDisplayNone");}this.inherited(arguments);},onClick: function(/*Event*/ e){// summary: user callback for when button is clicked// if type="submit", return value != false to perform submitreturn true;},_clicked: function(/*Event*/ e){// summary: internal replaceable function for when the button is clicked},setLabel: function(/*String*/ content){// summary: reset the label (text) of the button; takes an HTML stringthis.containerNode.innerHTML = this.label = content;if(dojo.isMozilla){ // Firefox has re-render issues with tablesvar oldDisplay = dojo.getComputedStyle(this.domNode).display;this.domNode.style.display="none";var _this = this;setTimeout(function(){_this.domNode.style.display=oldDisplay;},1);}if (this.showLabel == false){this.titleNode.title=dojo.trim(this.containerNode.innerText || this.containerNode.textContent);}}});/** usage* <button dojoType="DropDownButton" label="Hello world"><div dojotype=dijit.Menu>...</div></button>** var button1 = new dijit.form.DropDownButton({ label: "hi", dropDown: new dijit.Menu(...) });* dojo.body().appendChild(button1);*/dojo.declare("dijit.form.DropDownButton", [dijit.form.Button, dijit._Container], {// summary// push the button and a menu shows upbaseClass : "dijitDropDownButton",templateString:"<div class=\"dijit dijitLeft dijitInline\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse,onclick:_onDropDownClick,onkeydown:_onDropDownKeydown,onblur:_onDropDownBlur,onkeypress:_onKey\"\n\t><div class='dijitRight'>\n\t<button class=\"dijitStretch dijitButtonNode dijitButtonContents\" type=\"${type}\"\n\t\tdojoAttachPoint=\"focusNode,titleNode\" waiRole=\"button\" waiState=\"haspopup-true,labelledby-${id}_label\"\n\t\t><div class=\"dijitInline ${iconClass}\" dojoAttachPoint=\"iconNode\"></div\n\t\t><span class=\"dijitButtonText\" \tdojoAttachPoint=\"containerNode,popupStateNode\"\n\t\tid=\"${id}_label\">${label}</span\n\t\t><span class='dijitA11yDownArrow'>▼</span>\n\t</button>\n</div></div>\n",_fillContent: function(){// my inner HTML contains both the button contents and a drop down widget, like// <DropDownButton> <span>push me</span> <Menu> ... </Menu> </DropDownButton>// The first node is assumed to be the button content. The widget is the popup.if(this.srcNodeRef){ // programatically created buttons might not define srcNodeRef//FIXME: figure out how to filter out the widget and use all remaining nodes as button// content, not just nodes[0]var nodes = dojo.query("*", this.srcNodeRef);dijit.form.DropDownButton.superclass._fillContent.call(this, nodes[0]);// save pointer to srcNode so we can grab the drop down widget after it's instantiatedthis.dropDownContainer = this.srcNodeRef;}},startup: function(){// the child widget from srcNodeRef is the dropdown widget. Insert it in the page DOM,// make it invisible, and store a reference to pass to the popup code.if(!this.dropDown){var dropDownNode = dojo.query("[widgetId]", this.dropDownContainer)[0];this.dropDown = dijit.byNode(dropDownNode);delete this.dropDownContainer;}dojo.body().appendChild(this.dropDown.domNode);this.dropDown.domNode.style.display="none";},_onArrowClick: function(/*Event*/ e){// summary: callback when the user mouse clicks on menu popup nodeif(this.disabled){ return; }this._toggleDropDown();},_onDropDownClick: function(/*Event*/ e){// on Firefox 2 on the Mac it is possible to fire onclick// by pressing enter down on a second element and transferring// focus to the DropDownButton;// we want to prevent opening our menu in this situation// and only do so if we have seen a keydown on this button;// e.detail != 0 means that we were fired by mousevar isMacFFlessThan3 = dojo.isFF && dojo.isFF < 3&& navigator.appVersion.indexOf("Macintosh") != -1;if(!isMacFFlessThan3 || e.detail != 0 || this._seenKeydown){this._onArrowClick(e);}this._seenKeydown = false;},_onDropDownKeydown: function(/*Event*/ e){this._seenKeydown = true;},_onDropDownBlur: function(/*Event*/ e){this._seenKeydown = false;},_onKey: function(/*Event*/ e){// summary: callback when the user presses a key on menu popup nodeif(this.disabled){ return; }if(e.keyCode == dojo.keys.DOWN_ARROW){if(!this.dropDown || this.dropDown.domNode.style.display=="none"){dojo.stopEvent(e);return this._toggleDropDown();}}},_onBlur: function(){// summary: called magically when focus has shifted away from this widget and it's dropdownthis._closeDropDown();// don't focus on button. the user has explicitly focused on something else.},_toggleDropDown: function(){// summary: toggle the drop-down widget; if it is up, close it, if not, open itif(this.disabled){ return; }dijit.focus(this.popupStateNode);var dropDown = this.dropDown;if(!dropDown){ return false; }if(!dropDown.isShowingNow){// If there's an href, then load that first, so we don't get a flickerif(dropDown.href && !dropDown.isLoaded){var self = this;var handler = dojo.connect(dropDown, "onLoad", function(){dojo.disconnect(handler);self._openDropDown();});dropDown._loadCheck(true);return;}else{this._openDropDown();}}else{this._closeDropDown();}},_openDropDown: function(){var dropDown = this.dropDown;var oldWidth=dropDown.domNode.style.width;var self = this;dijit.popup.open({parent: this,popup: dropDown,around: this.domNode,orient: this.isLeftToRight() ? {'BL':'TL', 'BR':'TR', 'TL':'BL', 'TR':'BR'}: {'BR':'TR', 'BL':'TL', 'TR':'BR', 'TL':'BL'},onExecute: function(){self._closeDropDown(true);},onCancel: function(){self._closeDropDown(true);},onClose: function(){dropDown.domNode.style.width = oldWidth;self.popupStateNode.removeAttribute("popupActive");this._opened = false;}});if(this.domNode.offsetWidth > dropDown.domNode.offsetWidth){var adjustNode = null;if(!this.isLeftToRight()){adjustNode = dropDown.domNode.parentNode;var oldRight = adjustNode.offsetLeft + adjustNode.offsetWidth;}// make menu at least as wide as the buttondojo.marginBox(dropDown.domNode, {w: this.domNode.offsetWidth});if(adjustNode){adjustNode.style.left = oldRight - this.domNode.offsetWidth + "px";}}this.popupStateNode.setAttribute("popupActive", "true");this._opened=true;if(dropDown.focus){dropDown.focus();}// TODO: set this.checked and call setStateClass(), to affect button look while drop down is shown},_closeDropDown: function(/*Boolean*/ focus){if(this._opened){dijit.popup.close(this.dropDown);if(focus){ this.focus(); }this._opened = false;}}});/** usage* <button dojoType="ComboButton" onClick="..."><span>Hello world</span><div dojoType=dijit.Menu>...</div></button>** var button1 = new dijit.form.ComboButton({label: "hello world", onClick: foo, dropDown: "myMenu"});* dojo.body().appendChild(button1.domNode);*/dojo.declare("dijit.form.ComboButton", dijit.form.DropDownButton, {// summary// left side is normal button, right side displays menutemplateString:"<table class='dijit dijitReset dijitInline dijitLeft'\n\tcellspacing='0' cellpadding='0'\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\">\n\t<tr>\n\t\t<td\tclass=\"dijitStretch dijitButtonContents dijitButtonNode\"\n\t\t\ttabIndex=\"${tabIndex}\"\n\t\t\tdojoAttachEvent=\"ondijitclick:_onButtonClick\" dojoAttachPoint=\"titleNode\"\n\t\t\twaiRole=\"button\" waiState=\"labelledby-${id}_label\">\n\t\t\t<div class=\"dijitInline ${iconClass}\" dojoAttachPoint=\"iconNode\"></div>\n\t\t\t<span class=\"dijitButtonText\" id=\"${id}_label\" dojoAttachPoint=\"containerNode\">${label}</span>\n\t\t</td>\n\t\t<td class='dijitReset dijitRight dijitButtonNode dijitDownArrowButton'\n\t\t\tdojoAttachPoint=\"popupStateNode,focusNode\"\n\t\t\tdojoAttachEvent=\"ondijitclick:_onArrowClick, onkeypress:_onKey\"\n\t\t\tstateModifier=\"DownArrow\"\n\t\t\ttitle=\"${optionsTitle}\" name=\"${name}\"\n\t\t\twaiRole=\"button\" waiState=\"haspopup-true\"\n\t\t><div waiRole=\"presentation\">▼</div>\n\t</td></tr>\n</table>\n",attributeMap: dojo.mixin(dojo.clone(dijit.form._FormWidget.prototype.attributeMap),{id:"", name:""}),// optionsTitle: String// text that describes the options menu (accessibility)optionsTitle: "",baseClass: "dijitComboButton",_focusedNode: null,postCreate: function(){this.inherited(arguments);this._focalNodes = [this.titleNode, this.popupStateNode];dojo.forEach(this._focalNodes, dojo.hitch(this, function(node){if(dojo.isIE){this.connect(node, "onactivate", this._onNodeFocus);}else{this.connect(node, "onfocus", this._onNodeFocus);}}));},focusFocalNode: function(node){// summary: Focus the focal node node.this._focusedNode = node;dijit.focus(node);},hasNextFocalNode: function(){// summary: Returns true if this widget has no node currently// focused or if there is a node following the focused one.// False is returned if the last node has focus.return this._focusedNode !== this.getFocalNodes()[1];},focusNext: function(){// summary: Focus the focal node following the current node with focus// or the first one if no node currently has focus.this._focusedNode = this.getFocalNodes()[this._focusedNode ? 1 : 0];dijit.focus(this._focusedNode);},hasPrevFocalNode: function(){// summary: Returns true if this widget has no node currently// focused or if there is a node before the focused one.// False is returned if the first node has focus.return this._focusedNode !== this.getFocalNodes()[0];},focusPrev: function(){// summary: Focus the focal node before the current node with focus// or the last one if no node currently has focus.this._focusedNode = this.getFocalNodes()[this._focusedNode ? 0 : 1];dijit.focus(this._focusedNode);},getFocalNodes: function(){// summary: Returns an array of focal nodes for this widget.return this._focalNodes;},_onNodeFocus: function(evt){this._focusedNode = evt.currentTarget;},_onBlur: function(evt){this.inherited(arguments);this._focusedNode = null;}});dojo.declare("dijit.form.ToggleButton", dijit.form.Button, {// summary// A button that can be in two states (checked or not).// Can be base class for things like tabs or checkbox or radio buttonsbaseClass: "dijitToggleButton",// checked: Boolean// Corresponds to the native HTML <input> element's attribute.// In markup, specified as "checked='checked'" or just "checked".// True if the button is depressed, or the checkbox is checked,// or the radio button is selected, etc.checked: false,_clicked: function(/*Event*/ evt){this.setChecked(!this.checked);},setChecked: function(/*Boolean*/ checked){// summary// Programatically deselect the buttonthis.checked = checked;dijit.setWaiState(this.focusNode || this.domNode, "pressed", this.checked);this._setStateClass();this.onChange(checked);}});}if(!dojo._hasResource["dijit._editor._Plugin"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit._editor._Plugin"] = true;dojo.provide("dijit._editor._Plugin");dojo.declare("dijit._editor._Plugin", null, {// summary// This represents a "plugin" to the editor, which is basically// a single button on the Toolbar and some associated codeconstructor: function(/*Object?*/args, /*DomNode?*/node){if(args){dojo.mixin(this, args);}},editor: null,iconClassPrefix: "dijitEditorIcon",button: null,queryCommand: null,command: "",commandArg: null,useDefaultCommand: true,buttonClass: dijit.form.Button,updateInterval: 200, // only allow updates every two tenths of a second_initButton: function(){if(this.command.length){var label = this.editor.commands[this.command];var className = "dijitEditorIcon "+this.iconClassPrefix + this.command.charAt(0).toUpperCase() + this.command.substr(1);if(!this.button){var props = {label: label,showLabel: false,iconClass: className,dropDown: this.dropDown};this.button = new this.buttonClass(props);}}},updateState: function(){var _e = this.editor;var _c = this.command;if(!_e){ return; }if(!_e.isLoaded){ return; }if(!_c.length){ return; }if(this.button){try{var enabled = _e.queryCommandEnabled(_c);this.button.setDisabled(!enabled);if(this.button.setChecked){this.button.setChecked(_e.queryCommandState(_c));}}catch(e){console.debug(e);}}},setEditor: function(/*Widget*/editor){// FIXME: detatch from previous editor!!this.editor = editor;// FIXME: prevent creating this if we don't need to (i.e., editor can't handle our command)this._initButton();// FIXME: wire up editor to button here!if( (this.command.length) &&(!this.editor.queryCommandAvailable(this.command))){// console.debug("hiding:", this.command);if(this.button){this.button.domNode.style.display = "none";}}if(this.button && this.useDefaultCommand){dojo.connect(this.button, "onClick",dojo.hitch(this.editor, "execCommand", this.command, this.commandArg));}dojo.connect(this.editor, "onNormalizedDisplayChanged", this, "updateState");},setToolbar: function(/*Widget*/toolbar){if(this.button){toolbar.addChild(this.button);}// console.debug("adding", this.button, "to:", toolbar);}});}if(!dojo._hasResource["dijit.Editor"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.Editor"] = true;dojo.provide("dijit.Editor");dojo.declare("dijit.Editor",dijit._editor.RichText,{// summary: A rich-text Editing widget// plugins: Array// a list of plugin names (as strings) or instances (as objects)// for this widget.plugins: null,// extraPlugins: Array// a list of extra plugin names which will be appended to plugins arrayextraPlugins: null,constructor: function(){this.plugins=["undo","redo","|","cut","copy","paste","|","bold","italic","underline","strikethrough","|","insertOrderedList","insertUnorderedList","indent","outdent","|","justifyLeft","justifyRight","justifyCenter","justifyFull"/*"createLink"*/];this._plugins=[];this._editInterval = this.editActionInterval * 1000;},postCreate: function(){//for custom undo/redoif(this.customUndo){dojo['require']("dijit._editor.range");this._steps=this._steps.slice(0);this._undoedSteps=this._undoedSteps.slice(0);// this.addKeyHandler('z',this.KEY_CTRL,this.undo);// this.addKeyHandler('y',this.KEY_CTRL,this.redo);}if(dojo.isArray(this.extraPlugins)){this.plugins=this.plugins.concat(this.extraPlugins);}// try{dijit.Editor.superclass.postCreate.apply(this, arguments);this.commands = dojo.i18n.getLocalization("dijit._editor", "commands", this.lang);if(!this.toolbar){// if we haven't been assigned a toolbar, create onevar toolbarNode = dojo.doc.createElement("div");dojo.place(toolbarNode, this.editingArea, "before");this.toolbar = new dijit.Toolbar({}, toolbarNode);}dojo.forEach(this.plugins, this.addPlugin, this);this.onNormalizedDisplayChanged(); //update toolbar button status// }catch(e){ console.debug(e); }},destroy: function(){dojo.forEach(this._plugins, function(p){if(p.destroy){p.destroy();}});this._plugins=[];this.toolbar.destroy(); delete this.toolbar;this.inherited('destroy',arguments);},addPlugin: function(/*String||Object*/plugin, /*Integer?*/index){// summary:// takes a plugin name as a string or a plugin instance and// adds it to the toolbar and associates it with this editor// instance. The resulting plugin is added to the Editor's// plugins array. If index is passed, it's placed in the plugins// array at that index. No big magic, but a nice helper for// passing in plugin names via markup.// plugin: String, args object or plugin instance. Required.// args: This object will be passed to the plugin constructor.// index:// Integer, optional. Used when creating an instance from// something already in this.plugins. Ensures that the new// instance is assigned to this.plugins at that index.var args=dojo.isString(plugin)?{name:plugin}:plugin;if(!args.setEditor){var o={"args":args,"plugin":null,"editor":this};dojo.publish("dijit.Editor.getPlugin",[o]);if(!o.plugin){var pc = dojo.getObject(args.name);if(pc){o.plugin=new pc(args);}}if(!o.plugin){console.debug('Cannot find plugin',plugin);return;}plugin=o.plugin;}if(arguments.length > 1){this._plugins[index] = plugin;}else{this._plugins.push(plugin);}plugin.setEditor(this);if(dojo.isFunction(plugin.setToolbar)){plugin.setToolbar(this.toolbar);}},/* beginning of custom undo/redo support */// customUndo: Boolean// Whether we shall use custom undo/redo support instead of the native// browser support. By default, we only enable customUndo for IE, as it// has broken native undo/redo support. Note: the implementation does// support other browsers which have W3C DOM2 Range API.customUndo: dojo.isIE,// editActionInterval: Integer// When using customUndo, not every keystroke will be saved as a step.// Instead typing (including delete) will be grouped together: after// a user stop typing for editActionInterval seconds, a step will be// saved; if a user resume typing within editActionInterval seconds,// the timeout will be restarted. By default, editActionInterval is 3// seconds.editActionInterval: 3,beginEditing: function(cmd){if(!this._inEditing){this._inEditing=true;this._beginEditing(cmd);}if(this.editActionInterval>0){if(this._editTimer){clearTimeout(this._editTimer);}this._editTimer = setTimeout(dojo.hitch(this, this.endEditing), this._editInterval);}},_steps:[],_undoedSteps:[],execCommand: function(cmd){if(this.customUndo && (cmd=='undo' || cmd=='redo')){return this[cmd]();}else{try{if(this.customUndo){this.endEditing();this._beginEditing();}var r = this.inherited('execCommand',arguments);if(this.customUndo){this._endEditing();}return r;}catch(e){if(dojo.isMoz && /copy|cut|paste/.test(cmd)){// Warn user of platform limitation. Cannot programmatically access keyboard. See ticket #4136var sub = dojo.string.substitute,accel = {cut:'X', copy:'C', paste:'V'},isMac = navigator.userAgent.indexOf("Macintosh") != -1;alert(sub(this.commands.systemShortcutFF,[this.commands[cmd], sub(this.commands[isMac ? 'appleKey' : 'ctrlKey'], [accel[cmd]])]));}return false;}}},queryCommandEnabled: function(cmd){if(this.customUndo && (cmd=='undo' || cmd=='redo')){return cmd=='undo'?(this._steps.length>1):(this._undoedSteps.length>0);}else{return this.inherited('queryCommandEnabled',arguments);}},_changeToStep: function(from,to){this.setValue(to.text);var b=to.bookmark;if(!b){ return; }if(dojo.isIE){if(dojo.isArray(b)){//IE CONTROLvar tmp=[];dojo.forEach(b,function(n){tmp.push(dijit.range.getNode(n,this.editNode));},this);b=tmp;}}else{//w3c rangevar r=dijit.range.create();r.setStart(dijit.range.getNode(b.startContainer,this.editNode),b.startOffset);r.setEnd(dijit.range.getNode(b.endContainer,this.editNode),b.endOffset);b=r;}dojo.withGlobal(this.window,'moveToBookmark',dijit,[b]);},undo: function(){// console.log('undo');this.endEditing(true);var s=this._steps.pop();if(this._steps.length>0){this.focus();this._changeToStep(s,this._steps[this._steps.length-1]);this._undoedSteps.push(s);this.onDisplayChanged();return true;}return false;},redo: function(){// console.log('redo');this.endEditing(true);var s=this._undoedSteps.pop();if(s && this._steps.length>0){this.focus();this._changeToStep(this._steps[this._steps.length-1],s);this._steps.push(s);this.onDisplayChanged();return true;}return false;},endEditing: function(ignore_caret){if(this._editTimer){clearTimeout(this._editTimer);}if(this._inEditing){this._endEditing(ignore_caret);this._inEditing=false;}},_getBookmark: function(){var b=dojo.withGlobal(this.window,dijit.getBookmark);if(dojo.isIE){if(dojo.isArray(b)){//CONTROLvar tmp=[];dojo.forEach(b,function(n){tmp.push(dijit.range.getIndex(n,this.editNode).o);},this);b=tmp;}}else{//w3c rangevar tmp=dijit.range.getIndex(b.startContainer,this.editNode).ob={startContainer:tmp,startOffset:b.startOffset,endContainer:b.endContainer===b.startContainer?tmp:dijit.range.getIndex(b.endContainer,this.editNode).o,endOffset:b.endOffset};}return b;},_beginEditing: function(cmd){if(this._steps.length===0){this._steps.push({'text':this.savedContent,'bookmark':this._getBookmark()});}},_endEditing: function(ignore_caret){var v=this.getValue(true);this._undoedSteps=[];//clear undoed stepsthis._steps.push({'text':v,'bookmark':this._getBookmark()});},onKeyDown: function(e){if(!this.customUndo){this.inherited('onKeyDown',arguments);return;}var k=e.keyCode,ks=dojo.keys;if(e.ctrlKey){if(k===90||k===122){ //zdojo.stopEvent(e);this.undo();return;}else if(k===89||k===121){ //ydojo.stopEvent(e);this.redo();return;}}this.inherited('onKeyDown',arguments);switch(k){case ks.ENTER:this.beginEditing();break;case ks.BACKSPACE:case ks.DELETE:this.beginEditing();break;case 88: //xcase 86: //vif(e.ctrlKey && !e.altKey && !e.metaKey){this.endEditing();//end current typing step if anyif(e.keyCode == 88){this.beginEditing('cut');//use timeout to trigger after the cut is completesetTimeout(dojo.hitch(this, this.endEditing), 1);}else{this.beginEditing('paste');//use timeout to trigger after the paste is completesetTimeout(dojo.hitch(this, this.endEditing), 1);}break;}//pass throughdefault:if(!e.ctrlKey && !e.altKey && !e.metaKey && (e.keyCode<dojo.keys.F1 || e.keyCode>dojo.keys.F15)){this.beginEditing();break;}//pass throughcase ks.ALT:this.endEditing();break;case ks.UP_ARROW:case ks.DOWN_ARROW:case ks.LEFT_ARROW:case ks.RIGHT_ARROW:case ks.HOME:case ks.END:case ks.PAGE_UP:case ks.PAGE_DOWN:this.endEditing(true);break;//maybe ctrl+backspace/delete, so don't endEditing when ctrl is pressedcase ks.CTRL:case ks.SHIFT:case ks.TAB:break;}},_onBlur: function(){this.inherited('_onBlur',arguments);this.endEditing(true);},onClick: function(){this.endEditing(true);this.inherited('onClick',arguments);}/* end of custom undo/redo support */});/* the following code is to registered a handler to get default plugins */dojo.subscribe("dijit.Editor.getPlugin",null,function(o){if(o.plugin){ return; }var args=o.args, p;var _p = dijit._editor._Plugin;var name=args.name;switch(name){case "undo": case "redo": case "cut": case "copy": case "paste": case "insertOrderedList":case "insertUnorderedList": case "indent": case "outdent": case "justifyCenter":case "justifyFull": case "justifyLeft": case "justifyRight": case "delete":case "selectAll": case "removeFormat":p = new _p({ command: name });break;case "bold": case "italic": case "underline": case "strikethrough":case "subscript": case "superscript":p = new _p({ buttonClass: dijit.form.ToggleButton, command: name });break;case "|":p = new _p({ button: new dijit.ToolbarSeparator() });break;case "createLink":// dojo['require']('dijit._editor.plugins.LinkDialog');p = new dijit._editor.plugins.LinkDialog({ command: name });break;case "foreColor": case "hiliteColor":p = new dijit._editor.plugins.TextColor({ command: name });break;case "fontName": case "fontSize": case "formatBlock":p = new dijit._editor.plugins.FontChoice({ command: name });}// console.log('name',name,p);o.plugin=p;});}if(!dojo._hasResource["dijit.Menu"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.Menu"] = true;dojo.provide("dijit.Menu");dojo.declare("dijit.Menu",[dijit._Widget, dijit._Templated, dijit._KeyNavContainer],{constructor: function() {this._bindings = [];},templateString:'<table class="dijit dijitMenu dijitReset dijitMenuTable" waiRole="menu" dojoAttachEvent="onkeypress:_onKeyPress">' +'<tbody class="dijitReset" dojoAttachPoint="containerNode"></tbody>'+'</table>',// targetNodeIds: String[]// Array of dom node ids of nodes to attach to.// Fill this with nodeIds upon widget creation and it becomes context menu for those nodes.targetNodeIds: [],// contextMenuForWindow: Boolean// if true, right clicking anywhere on the window will cause this context menu to open;// if false, must specify targetNodeIdscontextMenuForWindow: false,// parentMenu: Widget// pointer to menu that displayed meparentMenu: null,// popupDelay: Integer// number of milliseconds before hovering (without clicking) causes the popup to automatically openpopupDelay: 500,// _contextMenuWithMouse: Boolean// used to record mouse and keyboard events to determine if a context// menu is being opened with the keyboard or the mouse_contextMenuWithMouse: false,postCreate: function(){if(this.contextMenuForWindow){this.bindDomNode(dojo.body());}else{dojo.forEach(this.targetNodeIds, this.bindDomNode, this);}this.connectKeyNavHandlers([dojo.keys.UP_ARROW], [dojo.keys.DOWN_ARROW]);},startup: function(){dojo.forEach(this.getChildren(), function(child){ child.startup(); });this.startupKeyNavChildren();},onExecute: function(){// summary: attach point for notification about when a menu item has been executed},onCancel: function(/*Boolean*/ closeAll){// summary: attach point for notification about when the user cancels the current menu},_moveToPopup: function(/*Event*/ evt){if(this.focusedChild && this.focusedChild.popup && !this.focusedChild.disabled){this.focusedChild._onClick(evt);}},_onKeyPress: function(/*Event*/ evt){// summary// Handle keyboard based menu navigation.if(evt.ctrlKey || evt.altKey){ return; }switch(evt.keyCode){case dojo.keys.RIGHT_ARROW:this._moveToPopup(evt);dojo.stopEvent(evt);break;case dojo.keys.LEFT_ARROW:if(this.parentMenu){this.onCancel(false);}else{dojo.stopEvent(evt);}break;}},onItemHover: function(/*MenuItem*/ item){this.focusChild(item);if(this.focusedChild.popup && !this.focusedChild.disabled && !this.hover_timer){this.hover_timer = setTimeout(dojo.hitch(this, "_openPopup"), this.popupDelay);}},_onChildBlur: function(item){// Close all popups that are open and descendants of this menudijit.popup.close(item.popup);item._blur();this._stopPopupTimer();},onItemUnhover: function(/*MenuItem*/ item){},_stopPopupTimer: function(){if(this.hover_timer){clearTimeout(this.hover_timer);this.hover_timer = null;}},_getTopMenu: function(){for(var top=this; top.parentMenu; top=top.parentMenu);return top;},onItemClick: function(/*Widget*/ item){// summary: user defined function to handle clicks on an item// summary: internal function for clicksif(item.disabled){ return false; }if(item.popup){if(!this.is_open){this._openPopup();}}else{// before calling user defined handler, close hierarchy of menus// and restore focus to place it was when menu was openedthis.onExecute();// user defined handler for clickitem.onClick();}},// thanks burstlib!_iframeContentWindow: function(/* HTMLIFrameElement */iframe_el) {// summary// returns the window reference of the passed iframevar win = dijit.getDocumentWindow(dijit.Menu._iframeContentDocument(iframe_el)) ||// Moz. TODO: is this available when defaultView isn't?dijit.Menu._iframeContentDocument(iframe_el)['__parent__'] ||(iframe_el.name && document.frames[iframe_el.name]) || null;return win; // Window},_iframeContentDocument: function(/* HTMLIFrameElement */iframe_el){// summary// returns a reference to the document object inside iframe_elvar doc = iframe_el.contentDocument // W3|| (iframe_el.contentWindow && iframe_el.contentWindow.document) // IE|| (iframe_el.name && document.frames[iframe_el.name] && document.frames[iframe_el.name].document)|| null;return doc; // HTMLDocument},bindDomNode: function(/*String|DomNode*/ node){// summary: attach menu to given nodenode = dojo.byId(node);//TODO: this is to support context popups in Editor. Maybe this shouldn't be in dijit.Menuvar win = dijit.getDocumentWindow(node.ownerDocument);if(node.tagName.toLowerCase()=="iframe"){win = this._iframeContentWindow(node);node = dojo.withGlobal(win, dojo.body);}// to capture these events at the top level,// attach to document, not bodyvar cn = (node == dojo.body() ? dojo.doc : node);node[this.id] = this._bindings.push([dojo.connect(cn, "oncontextmenu", this, "_openMyself"),dojo.connect(cn, "onkeydown", this, "_contextKey"),dojo.connect(cn, "onmousedown", this, "_contextMouse")]);},unBindDomNode: function(/*String|DomNode*/ nodeName){// summary: detach menu from given nodevar node = dojo.byId(nodeName);var bid = node[this.id]-1, b = this._bindings[bid];dojo.forEach(b, dojo.disconnect);delete this._bindings[bid];},_contextKey: function(e){this._contextMenuWithMouse = false;if (e.keyCode == dojo.keys.F10) {dojo.stopEvent(e);if (e.shiftKey && e.type=="keydown") {// FF: copying the wrong property from e will cause the system// context menu to appear in spite of stopEvent. Don't know// exactly which properties cause this effect.var _e = { target: e.target, pageX: e.pageX, pageY: e.pageY };_e.preventDefault = _e.stopPropagation = function(){};// IE: without the delay, focus work in "open" causes the system// context menu to appear in spite of stopEvent.window.setTimeout(dojo.hitch(this, function(){ this._openMyself(_e); }), 1);}}},_contextMouse: function(e){this._contextMenuWithMouse = true;},_openMyself: function(/*Event*/ e){// summary:// Internal function for opening myself when the user// does a right-click or something similardojo.stopEvent(e);// Get coordinates.// if we are opening the menu with the mouse or on safari open// the menu at the mouse cursor// (Safari does not have a keyboard command to open the context menu// and we don't currently have a reliable way to determine// _contextMenuWithMouse on Safari)var x,y;if(dojo.isSafari || this._contextMenuWithMouse){x=e.pageX;y=e.pageY;}else{// otherwise open near e.targetvar coords = dojo.coords(e.target, true);x = coords.x + 10;y = coords.y + 10;}var self=this;var savedFocus = dijit.getFocus(this);function closeAndRestoreFocus(){// user has clicked on a menu or popupdijit.focus(savedFocus);dijit.popup.close(self);}dijit.popup.open({popup: this,x: x,y: y,onExecute: closeAndRestoreFocus,onCancel: closeAndRestoreFocus,orient: this.isLeftToRight() ? 'L' : 'R'});this.focus();this._onBlur = function(){// Usually the parent closes the child widget but if this is a context// menu then there is no parentdijit.popup.close(this);// don't try to restore focus; user has clicked another part of the screen// and set focus there}},onOpen: function(/*Event*/ e){// summary// Open menu relative to the mousethis.isShowingNow = true;},onClose: function(){// summary: callback when this menu is closedthis._stopPopupTimer();this.parentMenu = null;this.isShowingNow = false;this.currentPopup = null;if(this.focusedChild){this._onChildBlur(this.focusedChild);this.focusedChild = null;}},_openPopup: function(){// summary: open the popup to the side of the current menu itemthis._stopPopupTimer();var from_item = this.focusedChild;var popup = from_item.popup;if(popup.isShowingNow){ return; }popup.parentMenu = this;var self = this;dijit.popup.open({parent: this,popup: popup,around: from_item.arrowCell,orient: this.isLeftToRight() ? {'TR': 'TL', 'TL': 'TR'} : {'TL': 'TR', 'TR': 'TL'},onCancel: function(){// called when the child menu is canceleddijit.popup.close(popup);from_item.focus(); // put focus back on my nodeself.currentPopup = null;}});this.currentPopup = popup;if(popup.focus){popup.focus();}}});dojo.declare("dijit.MenuItem",[dijit._Widget, dijit._Templated, dijit._Contained],{// summary// A line item in a Menu2// Make 3 columns// icon, label, and expand arrow (BiDi-dependent) indicating sub-menutemplateString:'<tr class="dijitReset dijitMenuItem"'+'dojoAttachEvent="onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick">'+'<td class="dijitReset"><div class="dijitMenuItemIcon ${iconClass}" dojoAttachPoint="iconNode" ></div></td>'+'<td tabIndex="-1" class="dijitReset dijitMenuItemLabel" dojoAttachPoint="containerNode" waiRole="menuitem"></td>'+'<td class="dijitReset" dojoAttachPoint="arrowCell">'+'<div class="dijitMenuExpand" dojoAttachPoint="expand" style="display:none">'+'<span class="dijitInline dijitArrowNode dijitMenuExpandInner">+</span>'+'</div>'+'</td>'+'</tr>',// label: String// menu textlabel: '',// iconClass: String// class to apply to div in button to make it display an iconiconClass: "",// disabled: Boolean// if true, the menu item is disabled// if false, the menu item is enableddisabled: false,postCreate: function(){dojo.setSelectable(this.domNode, false);this.setDisabled(this.disabled);if(this.label){this.containerNode.innerHTML=this.label;}},_onHover: function(){// summary: callback when mouse is moved onto menu itemthis.getParent().onItemHover(this);},_onUnhover: function(){// summary: callback when mouse is moved off of menu item// if we are unhovering the currently selected item// then unselect itthis.getParent().onItemUnhover(this);},_onClick: function(evt){this.getParent().onItemClick(this);dojo.stopEvent(evt);},onClick: function() {// summary// User defined function to handle clicks},focus: function(){dojo.addClass(this.domNode, 'dijitMenuItemHover');try{dijit.focus(this.containerNode);}catch(e){// this throws on IE (at least) in some scenarios}},_blur: function(){dojo.removeClass(this.domNode, 'dijitMenuItemHover');},setDisabled: function(/*Boolean*/ value){// summary: enable or disable this menu itemthis.disabled = value;dojo[value ? "addClass" : "removeClass"](this.domNode, 'dijitMenuItemDisabled');dijit.setWaiState(this.containerNode, 'disabled', value ? 'true' : 'false');}});dojo.declare("dijit.PopupMenuItem",dijit.MenuItem,{_fillContent: function(){// my inner HTML contains both the menu item text and a popup widget, like// <div dojoType="dijit.PopupMenuItem">// <span>pick me</span>// <popup> ... </popup>// </div>// the first part holds the menu item text and the second part is the popupif(this.srcNodeRef){var nodes = dojo.query("*", this.srcNodeRef);dijit.PopupMenuItem.superclass._fillContent.call(this, nodes[0]);// save pointer to srcNode so we can grab the drop down widget after it's instantiatedthis.dropDownContainer = this.srcNodeRef;}},startup: function(){// we didn't copy the dropdown widget from the this.srcNodeRef, so it's in no-man's// land now. move it to document.body.if(!this.popup){var node = dojo.query("[widgetId]", this.dropDownContainer)[0];this.popup = dijit.byNode(node);}dojo.body().appendChild(this.popup.domNode);this.popup.domNode.style.display="none";dojo.addClass(this.expand, "dijitMenuExpandEnabled");dojo.style(this.expand, "display", "");dijit.setWaiState(this.containerNode, "haspopup", "true");}});dojo.declare("dijit.MenuSeparator",[dijit._Widget, dijit._Templated, dijit._Contained],{// summary// A line between two menu itemstemplateString: '<tr class="dijitMenuSeparator"><td colspan=3>'+'<div class="dijitMenuSeparatorTop"></div>'+'<div class="dijitMenuSeparatorBottom"></div>'+'</td></tr>',postCreate: function(){dojo.setSelectable(this.domNode, false);},isFocusable: function(){// summary:// over ride to always return falsereturn false;}});}if(!dojo._hasResource["dojo.regexp"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.regexp"] = true;dojo.provide("dojo.regexp");dojo.regexp.escapeString = function(/*String*/str, /*String?*/except){// summary:// Adds escape sequences for special characters in regular expressions// except:// a String with special characters to be left unescaped// return str.replace(/([\f\b\n\t\r[\^$|?*+(){}])/gm, "\\$1"); // stringreturn str.replace(/([\.$?*!=:|{}\(\)\[\]\\\/^])/g, function(ch){if(except && except.indexOf(ch) != -1){return ch;}return "\\" + ch;}); // String}dojo.regexp.buildGroupRE = function(/*Object|Array*/arr, /*Function*/re, /*Boolean?*/nonCapture){// summary:// Builds a regular expression that groups subexpressions// description:// A utility function used by some of the RE generators. The// subexpressions are constructed by the function, re, in the second// parameter. re builds one subexpression for each elem in the array// a, in the first parameter. Returns a string for a regular// expression that groups all the subexpressions.// arr:// A single value or an array of values.// re:// A function. Takes one parameter and converts it to a regular// expression.// nonCapture:// If true, uses non-capturing match, otherwise matches are retained// by regular expression. Defaults to false// case 1: a is a single value.if(!(arr instanceof Array)){return re(arr); // String}// case 2: a is an arrayvar b = [];for(var i = 0; i < arr.length; i++){// convert each elem to a REb.push(re(arr[i]));}// join the REs as alternatives in a RE group.return dojo.regexp.group(b.join("|"), nonCapture); // String}dojo.regexp.group = function(/*String*/expression, /*Boolean?*/nonCapture){// summary:// adds group match to expression// nonCapture:// If true, uses non-capturing match, otherwise matches are retained// by regular expression.return "(" + (nonCapture ? "?:":"") + expression + ")"; // String}}if(!dojo._hasResource["dojo.number"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.number"] = true;dojo.provide("dojo.number");/*=====dojo.number.__formatOptions = function(kwArgs){// pattern: String?// override formatting pattern with this string (see// dojo.number._applyPattern)// type: String?// choose a format type based on the locale from the following:// decimal, scientific, percent, currency. decimal by default.// places: Number?// fixed number of decimal places to show. This overrides any// information in the provided pattern.// round: NUmber?// 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1// means don't round.// currency: String?// iso4217 currency code// symbol: String?// localized currency symbol// locale: String?// override the locale used to determine formatting rules}=====*/dojo.number.format = function(/*Number*/value, /*dojo.number.__formatOptions?*/options){// summary:// Format a Number as a String, using locale-specific settings// description:// Create a string from a Number using a known localized pattern.// Formatting patterns appropriate to the locale are chosen from the// CLDR http://unicode.org/cldr as well as the appropriate symbols and// delimiters. See http://www.unicode.org/reports/tr35/#Number_Elements// value:// the number to be formatted. If not a valid JavaScript number,// return null.options = dojo.mixin({}, options || {});var locale = dojo.i18n.normalizeLocale(options.locale);var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale);options.customs = bundle;var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"];if(isNaN(value)){ return null; } // nullreturn dojo.number._applyPattern(value, pattern, options); // String};//dojo.number._numberPatternRE = /(?:[#0]*,?)*[#0](?:\.0*#*)?/; // not precise, but good enoughdojo.number._numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/; // not precise, but good enoughdojo.number._applyPattern = function(/*Number*/value, /*String*/pattern, /*dojo.number.__formatOptions?*/options){// summary:// Apply pattern to format value as a string using options. Gives no// consideration to local customs.// value:// the number to be formatted.// pattern:// a pattern string as described in// http://www.unicode.org/reports/tr35/#Number_Format_Patterns// options: dojo.number.__formatOptions?// _applyPattern is usually called via dojo.number.format() which// populates an extra property in the options parameter, "customs".// The customs object specifies group and decimal parameters if set.//TODO: support escapesoptions = options || {};var group = options.customs.group;var decimal = options.customs.decimal;var patternList = pattern.split(';');var positivePattern = patternList[0];pattern = patternList[(value < 0) ? 1 : 0] || ("-" + positivePattern);//TODO: only test against unescapedif(pattern.indexOf('%') != -1){value *= 100;}else if(pattern.indexOf('\u2030') != -1){value *= 1000; // per mille}else if(pattern.indexOf('\u00a4') != -1){group = options.customs.currencyGroup || group;//mixins instead?decimal = options.customs.currencyDecimal || decimal;// Should these be mixins instead?pattern = pattern.replace(/\u00a4{1,3}/, function(match){var prop = ["symbol", "currency", "displayName"][match.length-1];return options[prop] || options.currency || "";});}else if(pattern.indexOf('E') != -1){throw new Error("exponential notation not supported");}//TODO: support @ sig figs?var numberPatternRE = dojo.number._numberPatternRE;var numberPattern = positivePattern.match(numberPatternRE);if(!numberPattern){throw new Error("unable to find a number expression in pattern: "+pattern);}return pattern.replace(numberPatternRE,dojo.number._formatAbsolute(value, numberPattern[0], {decimal: decimal, group: group, places: options.places}));}dojo.number.round = function(/*Number*/value, /*Number*/places, /*Number?*/multiple){// summary:// Rounds the number at the given number of places// value:// the number to round// places:// the number of decimal places where rounding takes place// multiple:// rounds next place to nearest multiplevar pieces = String(value).split(".");var length = (pieces[1] && pieces[1].length) || 0;if(length > places){var factor = Math.pow(10, places);if(multiple > 0){factor *= 10/multiple;places++;} //FIXMEvalue = Math.round(value * factor)/factor;// truncate to remove any residual floating point valuespieces = String(value).split(".");length = (pieces[1] && pieces[1].length) || 0;if(length > places){pieces[1] = pieces[1].substr(0, places);value = Number(pieces.join("."));}}return value; //Number}/*=====dojo.number.__formatAbsoluteOptions = function(kwArgs){// decimal: String?// the decimal separator// group: String?// the group separator// places: Integer?// number of decimal places// round: Number?// 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1// means don't round.}=====*/dojo.number._formatAbsolute = function(/*Number*/value, /*String*/pattern, /*dojo.number.__formatAbsoluteOptions?*/options){// summary:// Apply numeric pattern to absolute value using options. Gives no// consideration to local customs.// value:// the number to be formatted, ignores sign// pattern:// the number portion of a pattern (e.g. #,##0.00)options = options || {};if(options.places === true){options.places=0;}if(options.places === Infinity){options.places=6;} // avoid a loop; pick a limitvar patternParts = pattern.split(".");var maxPlaces = (options.places >= 0) ? options.places : (patternParts[1] && patternParts[1].length) || 0;if(!(options.round < 0)){value = dojo.number.round(value, maxPlaces, options.round);}var valueParts = String(Math.abs(value)).split(".");var fractional = valueParts[1] || "";if(options.places){valueParts[1] = dojo.string.pad(fractional.substr(0, options.places), options.places, '0', true);}else if(patternParts[1] && options.places !== 0){// Pad fractional with trailing zerosvar pad = patternParts[1].lastIndexOf("0") + 1;if(pad > fractional.length){valueParts[1] = dojo.string.pad(fractional, pad, '0', true);}// Truncate fractionalvar places = patternParts[1].length;if(places < fractional.length){valueParts[1] = fractional.substr(0, places);}}else{if(valueParts[1]){ valueParts.pop(); }}// Pad whole with leading zerosvar patternDigits = patternParts[0].replace(',', '');pad = patternDigits.indexOf("0");if(pad != -1){pad = patternDigits.length - pad;if(pad > valueParts[0].length){valueParts[0] = dojo.string.pad(valueParts[0], pad);}// Truncate wholeif(patternDigits.indexOf("#") == -1){valueParts[0] = valueParts[0].substr(valueParts[0].length - pad);}}// Add group separatorsvar index = patternParts[0].lastIndexOf(',');var groupSize, groupSize2;if(index != -1){groupSize = patternParts[0].length - index - 1;var remainder = patternParts[0].substr(0, index);index = remainder.lastIndexOf(',');if(index != -1){groupSize2 = remainder.length - index - 1;}}var pieces = [];for(var whole = valueParts[0]; whole;){var off = whole.length - groupSize;pieces.push((off > 0) ? whole.substr(off) : whole);whole = (off > 0) ? whole.slice(0, off) : "";if(groupSize2){groupSize = groupSize2;delete groupSize2;}}valueParts[0] = pieces.reverse().join(options.group || ",");return valueParts.join(options.decimal || ".");};/*=====dojo.number.__regexpOptions = function(kwArgs){// pattern: String?// override pattern with this string. Default is provided based on// locale.// type: String?// choose a format type based on the locale from the following:// decimal, scientific, percent, currency. decimal by default.// locale: String?// override the locale used to determine formatting rules// strict: Boolean?// strict parsing, false by default// places: Number|String?// number of decimal places to accept: Infinity, a positive number, or// a range "n,m". By default, defined by pattern.}=====*/dojo.number.regexp = function(/*dojo.number.__regexpOptions?*/options){// summary:// Builds the regular needed to parse a number// description:// Returns regular expression with positive and negative match, group// and decimal separatorsreturn dojo.number._parseInfo(options).regexp; // String}dojo.number._parseInfo = function(/*Object?*/options){options = options || {};var locale = dojo.i18n.normalizeLocale(options.locale);var bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale);var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"];//TODO: memoize?var group = bundle.group;var decimal = bundle.decimal;var factor = 1;if(pattern.indexOf('%') != -1){factor /= 100;}else if(pattern.indexOf('\u2030') != -1){factor /= 1000; // per mille}else{var isCurrency = pattern.indexOf('\u00a4') != -1;if(isCurrency){group = bundle.currencyGroup || group;decimal = bundle.currencyDecimal || decimal;}}//TODO: handle quoted escapesvar patternList = pattern.split(';');if(patternList.length == 1){patternList.push("-" + patternList[0]);}var re = dojo.regexp.buildGroupRE(patternList, function(pattern){pattern = "(?:"+dojo.regexp.escapeString(pattern, '.')+")";return pattern.replace(dojo.number._numberPatternRE, function(format){var flags = {signed: false,separator: options.strict ? group : [group,""],fractional: options.fractional,decimal: decimal,exponent: false};var parts = format.split('.');var places = options.places;if(parts.length == 1 || places === 0){flags.fractional = false;}else{if(typeof places == "undefined"){ places = parts[1].lastIndexOf('0')+1; }if(places && options.fractional == undefined){flags.fractional = true;} // required fractional, unless otherwise specifiedif(!options.places && (places < parts[1].length)){ places += "," + parts[1].length; }flags.places = places;}var groups = parts[0].split(',');if(groups.length>1){flags.groupSize = groups.pop().length;if(groups.length>1){flags.groupSize2 = groups.pop().length;}}return "("+dojo.number._realNumberRegexp(flags)+")";});}, true);if(isCurrency){// substitute the currency symbol for the placeholder in the patternre = re.replace(/(\s*)(\u00a4{1,3})(\s*)/g, function(match, before, target, after){var prop = ["symbol", "currency", "displayName"][target.length-1];var symbol = dojo.regexp.escapeString(options[prop] || options.currency || "");before = before ? "\\s" : "";after = after ? "\\s" : "";if(!options.strict){if(before){before += "*";}if(after){after += "*";}return "(?:"+before+symbol+after+")?";}return before+symbol+after;});}//TODO: substitute localized sign/percent/permille/etc.?// normalize whitespace and returnreturn {regexp: re.replace(/[\xa0 ]/g, "[\\s\\xa0]"), group: group, decimal: decimal, factor: factor}; // Object}/*=====dojo.number.__parseOptions = function(kwArgs){// pattern: String// override pattern with this string. Default is provided based on// locale.// type: String?// choose a format type based on the locale from the following:// decimal, scientific, percent, currency. decimal by default.// locale: String// override the locale used to determine formatting rules// strict: Boolean?// strict parsing, false by default// currency: Object// object with currency information}=====*/dojo.number.parse = function(/*String*/expression, /*dojo.number.__parseOptions?*/options){// summary:// Convert a properly formatted string to a primitive Number, using// locale-specific settings.// description:// Create a Number from a string using a known localized pattern.// Formatting patterns are chosen appropriate to the locale.// Formatting patterns are implemented using the syntax described at// *URL*// expression:// A string representation of a Numbervar info = dojo.number._parseInfo(options);var results = (new RegExp("^"+info.regexp+"$")).exec(expression);if(!results){return NaN; //NaN}var absoluteMatch = results[1]; // match for the positive expressionif(!results[1]){if(!results[2]){return NaN; //NaN}// matched the negative patternabsoluteMatch =results[2];info.factor *= -1;}// Transform it to something Javascript can parse as a number. Normalize// decimal point and strip out group separators or alternate forms of whitespaceabsoluteMatch = absoluteMatch.replace(new RegExp("["+info.group + "\\s\\xa0"+"]", "g"), "").replace(info.decimal, ".");// Adjust for negative sign, percent, etc. as necessaryreturn Number(absoluteMatch) * info.factor; //Number};/*=====dojo.number.__realNumberRegexpFlags = function(kwArgs){// places: Number?// The integer number of decimal places or a range given as "n,m". If// not given, the decimal part is optional and the number of places is// unlimited.// decimal: String?// A string for the character used as the decimal point. Default// is ".".// fractional: Boolean|Array?// Whether decimal places are allowed. Can be true, false, or [true,// false]. Default is [true, false]// exponent: Boolean|Array?// Express in exponential notation. Can be true, false, or [true,// false]. Default is [true, false], (i.e. will match if the// exponential part is present are not).// eSigned: Boolean|Array?// The leading plus-or-minus sign on the exponent. Can be true,// false, or [true, false]. Default is [true, false], (i.e. will// match if it is signed or unsigned). flags in regexp.integer can be// applied.}=====*/dojo.number._realNumberRegexp = function(/*dojo.number.__realNumberRegexpFlags?*/flags){// summary:// Builds a regular expression to match a real number in exponential// notation// flags:// An object// assign default values to missing paramtersflags = flags || {};if(typeof flags.places == "undefined"){ flags.places = Infinity; }if(typeof flags.decimal != "string"){ flags.decimal = "."; }if(typeof flags.fractional == "undefined" || /^0/.test(flags.places)){ flags.fractional = [true, false]; }if(typeof flags.exponent == "undefined"){ flags.exponent = [true, false]; }if(typeof flags.eSigned == "undefined"){ flags.eSigned = [true, false]; }// integer REvar integerRE = dojo.number._integerRegexp(flags);// decimal REvar decimalRE = dojo.regexp.buildGroupRE(flags.fractional,function(q){var re = "";if(q && (flags.places!==0)){re = "\\" + flags.decimal;if(flags.places == Infinity){re = "(?:" + re + "\\d+)?";}else{re += "\\d{" + flags.places + "}";}}return re;},true);// exponent REvar exponentRE = dojo.regexp.buildGroupRE(flags.exponent,function(q){if(q){ return "([eE]" + dojo.number._integerRegexp({ signed: flags.eSigned}) + ")"; }return "";});// real number REvar realRE = integerRE + decimalRE;// allow for decimals without integers, e.g. .25if(decimalRE){realRE = "(?:(?:"+ realRE + ")|(?:" + decimalRE + "))";}return realRE + exponentRE; // String};/*=====dojo.number.__integerRegexpFlags = function(kwArgs){// signed: Boolean?// The leading plus-or-minus sign. Can be true, false, or [true,// false]. Default is [true, false], (i.e. will match if it is signed// or unsigned).// separator: String?// The character used as the thousands separator. Default is no// separator. For more than one symbol use an array, e.g. [",", ""],// makes ',' optional.// groupSize: Number?// group size between separators// flags.groupSize2: Number?// second grouping (for India)}=====*/dojo.number._integerRegexp = function(/*dojo.number.__integerRegexpFlags?*/flags){// summary:// Builds a regular expression that matches an integer// flags:// An object// assign default values to missing paramtersflags = flags || {};if(typeof flags.signed == "undefined"){ flags.signed = [true, false]; }if(typeof flags.separator == "undefined"){flags.separator = "";}else if(typeof flags.groupSize == "undefined"){flags.groupSize = 3;}// build sign REvar signRE = dojo.regexp.buildGroupRE(flags.signed,function(q) { return q ? "[-+]" : ""; },true);// number REvar numberRE = dojo.regexp.buildGroupRE(flags.separator,function(sep){if(!sep){return "(?:0|[1-9]\\d*)";}sep = dojo.regexp.escapeString(sep);if(sep == " "){ sep = "\\s"; }else if(sep == "\xa0"){ sep = "\\s\\xa0"; }var grp = flags.groupSize, grp2 = flags.groupSize2;if(grp2){var grp2RE = "(?:0|[1-9]\\d{0," + (grp2-1) + "}(?:[" + sep + "]\\d{" + grp2 + "})*[" + sep + "]\\d{" + grp + "})";return ((grp-grp2) > 0) ? "(?:" + grp2RE + "|(?:0|[1-9]\\d{0," + (grp-1) + "}))" : grp2RE;}return "(?:0|[1-9]\\d{0," + (grp-1) + "}(?:[" + sep + "]\\d{" + grp + "})*)";},true);// integer REreturn signRE + numberRE; // String}}if(!dojo._hasResource["dijit.ProgressBar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.ProgressBar"] = true;dojo.provide("dijit.ProgressBar");dojo.declare("dijit.ProgressBar", [dijit._Widget, dijit._Templated], {// summary:// a progress widget//// usage:// <div dojoType="ProgressBar"// places="0"// progress="..." maximum="..."></div>// progress: String (Percentage or Number)// initial progress value.// with "%": percentage value, 0% <= progress <= 100%// or without "%": absolute value, 0 <= progress <= maximumprogress: "0",// maximum: Float// max sample numbermaximum: 100,// places: Number// number of places to show in values; 0 by defaultplaces: 0,// indeterminate: Boolean// false: show progress// true: show that a process is underway but that the progress is unknownindeterminate: false,templateString:"<div class=\"dijitProgressBar dijitProgressBarEmpty\"\n\t><div waiRole=\"progressbar\" tabindex=\"0\" dojoAttachPoint=\"internalProgress\" class=\"dijitProgressBarFull\"\n\t\t><div class=\"dijitProgressBarTile\"></div\n\t\t><span style=\"visibility:hidden\"> </span\n\t></div\n\t><div dojoAttachPoint=\"label\" class=\"dijitProgressBarLabel\" id=\"${id}_label\"> </div\n\t><img dojoAttachPoint=\"inteterminateHighContrastImage\" class=\"dijitProgressBarIndeterminateHighContrastImage\"\n\t></img\n></div>\n",_indeterminateHighContrastImagePath:dojo.moduleUrl("dijit", "themes/a11y/indeterminate_progress.gif"),// public functionspostCreate: function(){this.inherited("postCreate",arguments);this.inteterminateHighContrastImage.setAttribute("src",this._indeterminateHighContrastImagePath);this.update();},update: function(/*Object?*/attributes){// summary: update progress information//// attributes: may provide progress and/or maximum properties on this parameter,// see attribute specs for details.dojo.mixin(this, attributes||{});var percent = 1, classFunc;if(this.indeterminate){classFunc = "addClass";dijit.removeWaiState(this.internalProgress, "valuenow");dijit.removeWaiState(this.internalProgress, "valuemin");dijit.removeWaiState(this.internalProgress, "valuemax");}else{classFunc = "removeClass";if(String(this.progress).indexOf("%") != -1){percent = Math.min(parseFloat(this.progress)/100, 1);this.progress = percent * this.maximum;}else{this.progress = Math.min(this.progress, this.maximum);percent = this.progress / this.maximum;}var text = this.report(percent);this.label.firstChild.nodeValue = text;dijit.setWaiState(this.internalProgress, "describedby", this.label.id);dijit.setWaiState(this.internalProgress, "valuenow", this.progress);dijit.setWaiState(this.internalProgress, "valuemin", 0);dijit.setWaiState(this.internalProgress, "valuemax", this.maximum);}dojo[classFunc](this.domNode, "dijitProgressBarIndeterminate");this.internalProgress.style.width = (percent * 100) + "%";this.onChange();},report: function(/*float*/percent){// Generates message to show; may be overridden by userreturn dojo.number.format(percent, {type: "percent", places: this.places, locale: this.lang});},onChange: function(){}});}if(!dojo._hasResource["dijit.TitlePane"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.TitlePane"] = true;dojo.provide("dijit.TitlePane");dojo.declare("dijit.TitlePane",[dijit.layout.ContentPane, dijit._Templated],{// summary// A pane with a title on top, that can be opened or collapsed.//// title: String// Title of the panetitle: "",// open: Boolean// Whether pane is opened or closed.open: true,// duration: Integer// Time in milliseconds to fade in/fade outduration: 250,// baseClass: String// the root className to use for the various states of this widgetbaseClass: "dijitTitlePane",templateString:"<div class=\"dijitTitlePane\">\n\t<div dojoAttachEvent=\"onclick:toggle,onkeypress: _onTitleKey,onfocus:_handleFocus,onblur:_handleFocus\" tabindex=\"0\"\n\t\t\twaiRole=\"button\" class=\"dijitTitlePaneTitle\" dojoAttachPoint=\"focusNode\">\n\t\t<div dojoAttachPoint=\"arrowNode\" class=\"dijitInline dijitArrowNode\"><span dojoAttachPoint=\"arrowNodeInner\" class=\"dijitArrowNodeInner\"></span></div>\n\t\t<div dojoAttachPoint=\"titleNode\" class=\"dijitTitlePaneTextNode\"></div>\n\t</div>\n\t<div class=\"dijitTitlePaneContentOuter\" dojoAttachPoint=\"hideNode\">\n\t\t<div class=\"dijitReset\" dojoAttachPoint=\"wipeNode\">\n\t\t\t<div class=\"dijitTitlePaneContentInner\" dojoAttachPoint=\"containerNode\" waiRole=\"region\" tabindex=\"-1\">\n\t\t\t\t<!-- nested divs because wipeIn()/wipeOut() doesn't work right on node w/padding etc. Put padding on inner div. -->\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n",postCreate: function(){this.setTitle(this.title);if(!this.open){this.hideNode.style.display = this.wipeNode.style.display = "none";}this._setCss();dojo.setSelectable(this.titleNode, false);this.inherited("postCreate",arguments);dijit.setWaiState(this.containerNode, "labelledby", this.titleNode.id);dijit.setWaiState(this.focusNode, "haspopup", "true");// setup open/close animationsvar hideNode = this.hideNode, wipeNode = this.wipeNode;this._wipeIn = dojo.fx.wipeIn({node: this.wipeNode,duration: this.duration,beforeBegin: function(){hideNode.style.display="";}});this._wipeOut = dojo.fx.wipeOut({node: this.wipeNode,duration: this.duration,onEnd: function(){hideNode.style.display="none";}});},setContent: function(content){// summary// Typically called when an href is loaded. Our job is to make the animation smoothif(this._wipeOut.status() == "playing"){// we are currently *closing* the pane, so just let that continuethis.inherited("setContent",arguments);}else{if(this._wipeIn.status() == "playing"){this._wipeIn.stop();}// freeze container at current height so that adding new content doesn't make it jumpdojo.marginBox(this.wipeNode, {h: dojo.marginBox(this.wipeNode).h});// add the new content (erasing the old content, if any)this.inherited("setContent",arguments);// call _wipeIn.play() to animate from current height to new heightthis._wipeIn.play();}},toggle: function(){// summary: switches between opened and closed statedojo.forEach([this._wipeIn, this._wipeOut], function(animation){if(animation.status() == "playing"){animation.stop();}});this[this.open ? "_wipeOut" : "_wipeIn"].play();this.open =! this.open;// load content (if this is the first time we are opening the TitlePane// and content is specified as an href, or we have setHref when hidden)this._loadCheck();this._setCss();},_setCss: function(){// summary: set the open/close css state for the TitlePanevar classes = ["dijitClosed", "dijitOpen"];var boolIndex = this.open;dojo.removeClass(this.focusNode, classes[!boolIndex+0]);this.focusNode.className += " " + classes[boolIndex+0];// provide a character based indicator for images-off modethis.arrowNodeInner.innerHTML = this.open ? "-" : "+";},_onTitleKey: function(/*Event*/ e){// summary: callback when user hits a keyif(e.keyCode == dojo.keys.ENTER || e.charCode == dojo.keys.SPACE){this.toggle();}else if(e.keyCode == dojo.keys.DOWN_ARROW){if(this.open){this.containerNode.focus();e.preventDefault();}}},_handleFocus: function(/*Event*/ e){// summary: handle blur and focus for this widget// add/removeClass is safe to call without hasClass in this casedojo[(e.type=="focus" ? "addClass" : "removeClass")](this.focusNode,this.baseClass+"Focused");},setTitle: function(/*String*/ title){// summary: sets the text of the titlethis.titleNode.innerHTML=title;}});}if(!dojo._hasResource["dijit.Tooltip"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.Tooltip"] = true;dojo.provide("dijit.Tooltip");dojo.declare("dijit._MasterTooltip",[dijit._Widget, dijit._Templated],{// summary// Internal widget that holds the actual tooltip markup,// which occurs once per page.// Called by Tooltip widgets which are just containers to hold// the markup// duration: Integer// Milliseconds to fade in/fade outduration: 200,templateString:"<div class=\"dijitTooltip dijitTooltipLeft\" id=\"dojoTooltip\">\n\t<div class=\"dijitTooltipContainer dijitTooltipContents\" dojoAttachPoint=\"containerNode\" waiRole='alert'></div>\n\t<div class=\"dijitTooltipConnector\"></div>\n</div>\n",postCreate: function(){dojo.body().appendChild(this.domNode);this.bgIframe = new dijit.BackgroundIframe(this.domNode);// Setup fade-in and fade-out functions.this.fadeIn = dojo.fadeIn({ node: this.domNode, duration: this.duration, onEnd: dojo.hitch(this, "_onShow") });this.fadeOut = dojo.fadeOut({ node: this.domNode, duration: this.duration, onEnd: dojo.hitch(this, "_onHide") });},show: function(/*String*/ innerHTML, /*DomNode*/ aroundNode){// summary:// Display tooltip w/specified contents to right specified node// (To left if there's no space on the right, or if LTR==right)if(this.aroundNode && this.aroundNode === aroundNode){return;}if(this.fadeOut.status() == "playing"){// previous tooltip is being hidden; wait until the hide completes then show new onethis._onDeck=arguments;return;}this.containerNode.innerHTML=innerHTML;// Firefox bug. when innerHTML changes to be shorter than previous// one, the node size will not be updated until it moves.this.domNode.style.top = (this.domNode.offsetTop + 1) + "px";// position the element and change CSS according to positionvar align = this.isLeftToRight() ? {'BR': 'BL', 'BL': 'BR'} : {'BL': 'BR', 'BR': 'BL'};var pos = dijit.placeOnScreenAroundElement(this.domNode, aroundNode, align);this.domNode.className="dijitTooltip dijitTooltip" + (pos.corner=='BL' ? "Right" : "Left");//FIXME: might overwrite class// show itdojo.style(this.domNode, "opacity", 0);this.fadeIn.play();this.isShowingNow = true;this.aroundNode = aroundNode;},_onShow: function(){if(dojo.isIE){// the arrow won't show up on a node w/an opacity filterthis.domNode.style.filter="";}},hide: function(aroundNode){// summary: hide the tooltipif(!this.aroundNode || this.aroundNode !== aroundNode){return;}if(this._onDeck){// this hide request is for a show() that hasn't even started yet;// just cancel the pending show()this._onDeck=null;return;}this.fadeIn.stop();this.isShowingNow = false;this.aroundNode = null;this.fadeOut.play();},_onHide: function(){this.domNode.style.cssText=""; // to position offscreen againif(this._onDeck){// a show request has been queued up; do it nowthis.show.apply(this, this._onDeck);this._onDeck=null;}}});dijit.showTooltip = function(/*String*/ innerHTML, /*DomNode*/ aroundNode){// summary:// Display tooltip w/specified contents to right specified node// (To left if there's no space on the right, or if LTR==right)if(!dijit._masterTT){ dijit._masterTT = new dijit._MasterTooltip(); }return dijit._masterTT.show(innerHTML, aroundNode);};dijit.hideTooltip = function(aroundNode){// summary: hide the tooltipif(!dijit._masterTT){ dijit._masterTT = new dijit._MasterTooltip(); }return dijit._masterTT.hide(aroundNode);};dojo.declare("dijit.Tooltip",dijit._Widget,{// summary// Pops up a tooltip (a help message) when you hover over a node.// label: String// Text to display in the tooltip.// Specified as innerHTML when creating the widget from markup.label: "",// showDelay: Integer// Number of milliseconds to wait after hovering over/focusing on the object, before// the tooltip is displayed.showDelay: 400,// connectId: String[]// Id(s) of domNodes to attach the tooltip to.// When user hovers over any of the specified dom nodes, the tooltip will appear.connectId: [],postCreate: function(){if(this.srcNodeRef){this.srcNodeRef.style.display = "none";}this._connectNodes = [];dojo.forEach(this.connectId, function(id) {var node = dojo.byId(id);if (node) {this._connectNodes.push(node);dojo.forEach(["onMouseOver", "onMouseOut", "onFocus", "onBlur", "onHover", "onUnHover"], function(event){this.connect(node, event.toLowerCase(), "_"+event);}, this);if(dojo.isIE){// BiDi workaroundnode.style.zoom = 1;}}}, this);},_onMouseOver: function(/*Event*/ e){this._onHover(e);},_onMouseOut: function(/*Event*/ e){if(dojo.isDescendant(e.relatedTarget, e.target)){// false event; just moved from target to target child; ignore.return;}this._onUnHover(e);},_onFocus: function(/*Event*/ e){this._focus = true;this._onHover(e);},_onBlur: function(/*Event*/ e){this._focus = false;this._onUnHover(e);},_onHover: function(/*Event*/ e){if(!this._showTimer){var target = e.target;this._showTimer = setTimeout(dojo.hitch(this, function(){this.open(target)}), this.showDelay);}},_onUnHover: function(/*Event*/ e){// keep a tooltip open if the associated element has focusif(this._focus){ return; }if(this._showTimer){clearTimeout(this._showTimer);delete this._showTimer;}this.close();},open: function(/*DomNode*/ target){// summary: display the tooltip; usually not called directly.target = target || this._connectNodes[0];if(!target){ return; }if(this._showTimer){clearTimeout(this._showTimer);delete this._showTimer;}dijit.showTooltip(this.label || this.domNode.innerHTML, target);this._connectNode = target;},close: function(){// summary: hide the tooltip; usually not called directly.dijit.hideTooltip(this._connectNode);delete this._connectNode;if(this._showTimer){clearTimeout(this._showTimer);delete this._showTimer;}},uninitialize: function(){this.close();}});}if(!dojo._hasResource["dojo.cookie"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.cookie"] = true;dojo.provide("dojo.cookie");/*=====dojo.__cookieProps = function(kwArgs){// expires: Date|Number?// If a number, seen as the number of days from today. If a date, the// date past which the cookie is invalid. If expires is in the past,// the cookie will be deleted If expires is left out or is 0, the// cookie will expire when the browser closes.// path: String?// The path to use for the cookie.// domain: String?// The domain to use for the cookie.// secure: Boolean?// Whether to only send the cookie on secure connections}=====*/dojo.cookie = function(/*String*/name, /*String?*/value, /*dojo.__cookieProps?*/props){// summary:// Get or set a cookie.// description:// If you pass in one argument, the the value of the cookie is returned//// If you pass in two arguments, the cookie value is set to the second// argument.//// If you pass in three arguments, the cookie value is set to the// second argument, and the options on the third argument are used for// extended properties on the cookie// name:// The name of the cookie// value:// Optional. The value for the cookie.// props:// Optional additional properties for the cookie// example:// set a cookie with the JSON-serialized contents of an object which// will expire 5 days from now:// | dojo.cookie("configObj", dojo.toJson(config), { expires: 5 });//// example:// de-serialize a cookie back into a JavaScript object:// | var config = dojo.fromJson(dojo.cookie("configObj"));//// example:// delete a cookie:// | dojo.cookie("configObj", null);var c = document.cookie;if(arguments.length == 1){var idx = c.lastIndexOf(name+'=');if(idx == -1){ return null; }var start = idx+name.length+1;var end = c.indexOf(';', idx+name.length+1);if(end == -1){ end = c.length; }return decodeURIComponent(c.substring(start, end));}else{props = props || {};value = encodeURIComponent(value);if(typeof(props.expires) == "number"){var d = new Date();d.setTime(d.getTime()+(props.expires*24*60*60*1000));props.expires = d;}document.cookie = name + "=" + value+ (props.expires ? "; expires=" + props.expires.toUTCString() : "")+ (props.path ? "; path=" + props.path : "")+ (props.domain ? "; domain=" + props.domain : "")+ (props.secure ? "; secure" : "");return null;}};}if(!dojo._hasResource["dijit.Tree"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.Tree"] = true;dojo.provide("dijit.Tree");dojo.declare("dijit._TreeNode",[dijit._Widget, dijit._Templated, dijit._Container, dijit._Contained],{// summary// Single node within a tree// item: dojo.data.Item// the dojo.data entry this tree representsitem: null,isTreeNode: true,// label: String// Text of this tree nodelabel: "",isExpandable: null, // show expando nodeisExpanded: false,// state: String// dynamic loading-related stuff.// When an empty folder node appears, it is "UNCHECKED" first,// then after dojo.data query it becomes "LOADING" and, finally "LOADED"state: "UNCHECKED",templateString:"<div class=\"dijitTreeNode dijitTreeExpandLeaf dijitTreeChildrenNo\" waiRole=\"presentation\"\n\t><span dojoAttachPoint=\"expandoNode\" class=\"dijitTreeExpando\" waiRole=\"presentation\"\n\t></span\n\t><span dojoAttachPoint=\"expandoNodeText\" class=\"dijitExpandoText\" waiRole=\"presentation\"\n\t></span\n\t>\n\t<div dojoAttachPoint=\"contentNode\" class=\"dijitTreeContent\" waiRole=\"presentation\">\n\t\t<div dojoAttachPoint=\"iconNode\" class=\"dijitInline dijitTreeIcon\" waiRole=\"presentation\"></div>\n\t\t<span dojoAttachPoint=\"labelNode\" class=\"dijitTreeLabel\" wairole=\"treeitem\" tabindex=\"-1\"></span>\n\t</div>\n</div>\n",postCreate: function(){// set label, escaping special charactersthis.setLabelNode(this.label);// set expand icon for leafthis._setExpando();// set icon and label class based on itemthis._updateItemClasses(this.item);if(this.isExpandable){dijit.setWaiState(this.labelNode, "expanded", this.isExpanded);}},markProcessing: function(){// summary: visually denote that tree is loading data, etc.this.state = "LOADING";this._setExpando(true);},unmarkProcessing: function(){// summary: clear markup from markProcessing() callthis._setExpando(false);},_updateItemClasses: function(item){// summary: set appropriate CSS classes for item (used to allow for item updates to change respective CSS)this.iconNode.className = "dijitInline dijitTreeIcon " + this.tree.getIconClass(item);this.labelNode.className = "dijitTreeLabel " + this.tree.getLabelClass(item);},_updateLayout: function(){// summary: set appropriate CSS classes for this.domNodevar parent = this.getParent();if(parent && parent.isTree && parent._hideRoot){/* if we are hiding the root node then make every first level child look like a root node */dojo.addClass(this.domNode, "dijitTreeIsRoot");}else{dojo.toggleClass(this.domNode, "dijitTreeIsLast", !this.getNextSibling());}},_setExpando: function(/*Boolean*/ processing){// summary: set the right image for the expando node// apply the appropriate class to the expando nodevar styles = ["dijitTreeExpandoLoading", "dijitTreeExpandoOpened","dijitTreeExpandoClosed", "dijitTreeExpandoLeaf"];var idx = processing ? 0 : (this.isExpandable ? (this.isExpanded ? 1 : 2) : 3);dojo.forEach(styles,function(s){dojo.removeClass(this.expandoNode, s);}, this);dojo.addClass(this.expandoNode, styles[idx]);// provide a non-image based indicator for images-off modethis.expandoNodeText.innerHTML =processing ? "*" :(this.isExpandable ?(this.isExpanded ? "-" : "+") : "*");},expand: function(){// summary: show my childrenif(this.isExpanded){ return; }// cancel in progress collapse operationif(this._wipeOut.status() == "playing"){this._wipeOut.stop();}this.isExpanded = true;dijit.setWaiState(this.labelNode, "expanded", "true");dijit.setWaiRole(this.containerNode, "group");this._setExpando();this._wipeIn.play();},collapse: function(){if(!this.isExpanded){ return; }// cancel in progress expand operationif(this._wipeIn.status() == "playing"){this._wipeIn.stop();}this.isExpanded = false;dijit.setWaiState(this.labelNode, "expanded", "false");this._setExpando();this._wipeOut.play();},setLabelNode: function(label){this.labelNode.innerHTML="";this.labelNode.appendChild(document.createTextNode(label));},_setChildren: function(/* Object[] */ childrenArray){// summary:// Sets the children of this node.// Sets this.isExpandable based on whether or not there are children// Takes array of objects like: {label: ...} (_TreeNode options basically)// See parameters of _TreeNode for details.this.destroyDescendants();this.state = "LOADED";var nodeMap= {};if(childrenArray && childrenArray.length > 0){this.isExpandable = true;if(!this.containerNode){ // maybe this node was unfolderized and still has containerthis.containerNode = this.tree.containerNodeTemplate.cloneNode(true);this.domNode.appendChild(this.containerNode);}// Create _TreeNode widget for each specified tree nodedojo.forEach(childrenArray, function(childParams){var child = new dijit._TreeNode(dojo.mixin({tree: this.tree,label: this.tree.getLabel(childParams.item)}, childParams));this.addChild(child);var identity = this.tree.store.getIdentity(childParams.item);nodeMap[identity] = child;if(this.tree.persist){if(this.tree._openedItemIds[identity]){this.tree._expandNode(child);}}}, this);// note that updateLayout() needs to be called on each child after// _all_ the children existdojo.forEach(this.getChildren(), function(child, idx){child._updateLayout();});}else{this.isExpandable=false;}if(this._setExpando){// change expando to/form dot or + icon, as appropriatethis._setExpando(false);}if(this.isTree && this._hideRoot){// put first child in tab index if one exists.var fc = this.getChildren()[0];var tabnode = fc ? fc.labelNode : this.domNode;tabnode.setAttribute("tabIndex", "0");}// create animations for showing/hiding the children (if children exist)if(this.containerNode && !this._wipeIn){this._wipeIn = dojo.fx.wipeIn({node: this.containerNode, duration: 150});this._wipeOut = dojo.fx.wipeOut({node: this.containerNode, duration: 150});}return nodeMap;},_addChildren: function(/* object[] */ childrenArray){// summary:// adds the children to this node.// Takes array of objects like: {label: ...} (_TreeNode options basically)// See parameters of _TreeNode for details.var nodeMap = {};if(childrenArray && childrenArray.length > 0){dojo.forEach(childrenArray, function(childParams){var child = new dijit._TreeNode(dojo.mixin({tree: this.tree,label: this.tree.getLabel(childParams.item)}, childParams));this.addChild(child);nodeMap[this.tree.store.getIdentity(childParams.item)] = child;}, this);dojo.forEach(this.getChildren(), function(child, idx){child._updateLayout();});}return nodeMap;},deleteNode: function(/* treeNode */ node){node.destroy();var children = this.getChildren();if(children.length == 0){this.isExpandable = false;this.collapse();}dojo.forEach(children, function(child){child._updateLayout();});},makeExpandable: function(){//summary// if this node wasn't already showing the expando node,// turn it into one and call _setExpando()this.isExpandable = true;this._setExpando(false);}});dojo.declare("dijit.Tree",dijit._TreeNode,{// summary// This widget displays hierarchical data from a store. A query is specified// to get the "top level children" from a data store, and then those items are// queried for their children and so on (but lazily, as the user clicks the expand node).//// Thus in the default mode of operation this widget is technically a forest, not a tree,// in that there can be multiple "top level children". However, if you specify label,// then a special top level node (not corresponding to any item in the datastore) is// created, to father all the top level children.// store: String||dojo.data.Store// The store to get data to display in the treestore: null,// query: String// query to get top level node(s) of tree (ex: {type:'continent'})query: null,// childrenAttr: String// one ore more attributes that holds children of a tree nodechildrenAttr: ["children"],templateString:"<div class=\"dijitTreeContainer\" style=\"\" waiRole=\"tree\"\n\tdojoAttachEvent=\"onclick:_onClick,onkeypress:_onKeyPress\">\n\t<div class=\"dijitTreeNode dijitTreeIsRoot dijitTreeExpandLeaf dijitTreeChildrenNo\" waiRole=\"presentation\"\n\t\tdojoAttachPoint=\"rowNode\"\n\t\t><span dojoAttachPoint=\"expandoNode\" class=\"dijitTreeExpando\" waiRole=\"presentation\"\n\t\t></span\n\t\t><span dojoAttachPoint=\"expandoNodeText\" class=\"dijitExpandoText\" waiRole=\"presentation\"\n\t\t></span\n\t\t>\n\t\t<div dojoAttachPoint=\"contentNode\" class=\"dijitTreeContent\" waiRole=\"presentation\">\n\t\t\t<div dojoAttachPoint=\"iconNode\" class=\"dijitInline dijitTreeIcon\" waiRole=\"presentation\"></div>\n\t\t\t<span dojoAttachPoint=\"labelNode\" class=\"dijitTreeLabel\" wairole=\"treeitem\" tabindex=\"0\"></span>\n\t\t</div>\n\t</div>\n</div>\n",isExpandable: true,isTree: true,// persist: Boolean// enables/disables use of cookies for state saving.persist: true,// dndController: String// class name to use as as the dnd controllerdndController: null,//parameters to pull off of the tree and pass on to the dndController as its paramsdndParams: ["onDndDrop","itemCreator","onDndCancel","checkAcceptance", "checkItemAcceptance"],//declare the above items so they can be pulled from the tree's markuponDndDrop:null,itemCreator:null,onDndCancel:null,checkAcceptance:null,checkItemAcceptance:null,_publish: function(/*String*/ topicName, /*Object*/ message){// summary:// Publish a message for this widget/topicdojo.publish(this.id, [dojo.mixin({tree: this, event: topicName}, message||{})]);},postMixInProperties: function(){this.tree = this;this.lastFocused = this.labelNode;this._itemNodeMap={};this._hideRoot = !this.label;if(!this.store.getFeatures()['dojo.data.api.Identity']){throw new Error("dijit.tree requires access to a store supporting the dojo.data Identity api");}if(!this.cookieName){this.cookieName = this.id + "SaveStateCookie";}// if the store supports Notification, subscribe to the notification eventsif(this.store.getFeatures()['dojo.data.api.Notification']){this.connect(this.store, "onNew", "_onNewItem");this.connect(this.store, "onDelete", "_onDeleteItem");this.connect(this.store, "onSet", "_onSetItem");}},postCreate: function(){// load in which nodes should be opened automaticallyif(this.persist){var cookie = dojo.cookie(this.cookieName);this._openedItemIds = {};if(cookie){dojo.forEach(cookie.split(','), function(item){this._openedItemIds[item] = true;}, this);}}// make template for container node (we will clone this and insert it into// any nodes that have children)var div = document.createElement('div');div.style.display = 'none';div.className = "dijitTreeContainer";dijit.setWaiRole(div, "presentation");this.containerNodeTemplate = div;if(this._hideRoot){this.rowNode.style.display="none";}this.inherited("postCreate", arguments);// load top level childrenthis._expandNode(this);if(this.dndController){if(dojo.isString(this.dndController)){this.dndController= dojo.getObject(this.dndController);}var params={};for (var i=0; i<this.dndParams.length;i++){if(this[this.dndParams[i]]){params[this.dndParams[i]]=this[this.dndParams[i]];}}this.dndController= new this.dndController(this, params);}this.connect(this.domNode,dojo.isIE ? "onactivate" : "onfocus","_onTreeFocus");},////////////// Data store related functions //////////////////////mayHaveChildren: function(/*dojo.data.Item*/ item){// summary// User overridable function to tell if an item has or may have children.// Controls whether or not +/- expando icon is shown.// (For efficiency reasons we may not want to check if an element has// children until user clicks the expando node)return dojo.some(this.childrenAttr, function(attr){return this.store.hasAttribute(item, attr);}, this);},getItemChildren: function(/*dojo.data.Item*/ parentItem, /*function(items)*/ onComplete){// summary// User overridable function that return array of child items of given parent item,// or if parentItem==null then return top items in treevar store = this.store;if(parentItem == null){// get top level nodesstore.fetch({ query: this.query, onComplete: onComplete});}else{// get children of specified nodevar childItems = [];for (var i=0; i<this.childrenAttr.length; i++){childItems= childItems.concat(store.getValues(parentItem, this.childrenAttr[i]));}// count how many items need to be loadedvar _waitCount = 0;dojo.forEach(childItems, function(item){ if(!store.isItemLoaded(item)){ _waitCount++; } });if(_waitCount == 0){// all items are already loaded. proceed..onComplete(childItems);}else{// still waiting for some or all of the items to loadfunction onItem(item){if(--_waitCount == 0){// all nodes have been loaded, send them to the treeonComplete(childItems);}}dojo.forEach(childItems, function(item){if(!store.isItemLoaded(item)){store.loadItem({item: item, onItem: onItem});}});}}},getItemParentIdentity: function(/*dojo.data.Item*/ item, /*Object*/ parentInfo){// summary// User overridable function, to return id of parent (or null if top level).// It's called with args from dojo.store.onNewreturn this.store.getIdentity(parentInfo.item); // String},getLabel: function(/*dojo.data.Item*/ item){// summary: user overridable function to get the label for a tree node (given the item)return this.store.getLabel(item); // String},getIconClass: function(/*dojo.data.Item*/ item){// summary: user overridable function to return CSS class name to display icon},getLabelClass: function(/*dojo.data.Item*/ item){// summary: user overridable function to return CSS class name to display label},_onLoadAllItems: function(/*_TreeNode*/ node, /*dojo.data.Item[]*/ items){// sumary: callback when all the children of a given node have been loadedvar childParams=dojo.map(items, function(item){return {item: item,isExpandable: this.mayHaveChildren(item)};}, this);dojo.mixin(this._itemNodeMap,node._setChildren(childParams));this._expandNode(node);},/////////// Keyboard and Mouse handlers ////////////////////_onKeyPress: function(/*Event*/ e){// summary: translates keypress events into commands for the controllerif(e.altKey){ return; }var treeNode = dijit.getEnclosingWidget(e.target);if(!treeNode){ return; }// Note: On IE e.keyCode is not 0 for printables so check e.charCode.// In dojo charCode is universally 0 for non-printables.if(e.charCode){ // handle printables (letter navigation)// Check for key navigation.var navKey = e.charCode;if(!e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey){navKey = (String.fromCharCode(navKey)).toLowerCase();this._onLetterKeyNav( { node: treeNode, key: navKey } );dojo.stopEvent(e);}}else{ // handle non-printables (arrow keys)var map = this._keyHandlerMap;if(!map){// setup table mapping keys to eventsmap = {};map[dojo.keys.ENTER]="_onEnterKey";map[dojo.keys.LEFT_ARROW]="_onLeftArrow";map[dojo.keys.RIGHT_ARROW]="_onRightArrow";map[dojo.keys.UP_ARROW]="_onUpArrow";map[dojo.keys.DOWN_ARROW]="_onDownArrow";map[dojo.keys.HOME]="_onHomeKey";map[dojo.keys.END]="_onEndKey";this._keyHandlerMap = map;}if(this._keyHandlerMap[e.keyCode]){this[this._keyHandlerMap[e.keyCode]]( { node: treeNode, item: treeNode.item } );dojo.stopEvent(e);}}},_onEnterKey: function(/*Object*/ message){this._publish("execute", { item: message.item, node: message.node} );this.onClick(message.item, message.node);},_onDownArrow: function(/*Object*/ message){// summary: down arrow pressed; get next visible node, set focus therevar returnNode = this._navToNextNode(message.node);if(returnNode && returnNode.isTreeNode){returnNode.tree.focusNode(returnNode);return returnNode;}},_onUpArrow: function(/*Object*/ message){// summary: up arrow pressed; move to previous visible nodevar nodeWidget = message.node;var returnWidget = nodeWidget;// if younger siblingsvar previousSibling = nodeWidget.getPreviousSibling();if(previousSibling){nodeWidget = previousSibling;// if the previous nodeWidget is expanded, dive in deepwhile(nodeWidget.isExpandable && nodeWidget.isExpanded && nodeWidget.hasChildren()){returnWidget = nodeWidget;// move to the last childvar children = nodeWidget.getChildren();nodeWidget = children[children.length-1];}}else{// if this is the first child, return the parent// unless the parent is the root of a tree with a hidden rootvar parent = nodeWidget.getParent();if(!(this._hideRoot && parent === this)){nodeWidget = parent;}}if(nodeWidget && nodeWidget.isTreeNode){returnWidget = nodeWidget;}if(returnWidget && returnWidget.isTreeNode){returnWidget.tree.focusNode(returnWidget);return returnWidget;}},_onRightArrow: function(/*Object*/ message){// summary: right arrow pressed; go to child nodevar nodeWidget = message.node;var returnWidget = nodeWidget;// if not expanded, expand, else move to 1st childif(nodeWidget.isExpandable && !nodeWidget.isExpanded){this._expandNode(nodeWidget);}else if(nodeWidget.hasChildren()){nodeWidget = nodeWidget.getChildren()[0];}if(nodeWidget && nodeWidget.isTreeNode){returnWidget = nodeWidget;}if(returnWidget && returnWidget.isTreeNode){returnWidget.tree.focusNode(returnWidget);return returnWidget;}},_onLeftArrow: function(/*Object*/ message){// summary: left arrow pressed; go to parentvar node = message.node;var returnWidget = node;// if not collapsed, collapse, else move to parentif(node.isExpandable && node.isExpanded){this._collapseNode(node);}else{node = node.getParent();}if(node && node.isTreeNode){returnWidget = node;}if(returnWidget && returnWidget.isTreeNode){returnWidget.tree.focusNode(returnWidget);return returnWidget;}},_onHomeKey: function(){// summary: home pressed; get first visible node, set focus therevar returnNode = this._navToRootOrFirstNode();if(returnNode){returnNode.tree.focusNode(returnNode);return returnNode;}},_onEndKey: function(/*Object*/ message){// summary: end pressed; go to last visible nodevar returnWidget = message.node.tree;var lastChild = returnWidget;while(lastChild.isExpanded){var c = lastChild.getChildren();lastChild = c[c.length - 1];if(lastChild.isTreeNode){returnWidget = lastChild;}}if(returnWidget && returnWidget.isTreeNode){returnWidget.tree.focusNode(returnWidget);return returnWidget;}},_onLetterKeyNav: function(message){// summary: letter key pressed; search for node starting with first char = keyvar node = startNode = message.node;var key = message.key;do{node = this._navToNextNode(node);//check for last node, jump to first node if necessaryif(!node){node = this._navToRootOrFirstNode();}}while(node !== startNode && (node.label.charAt(0).toLowerCase() != key));if(node && node.isTreeNode){// no need to set focus if back where we startedif(node !== startNode){node.tree.focusNode(node);}return node;}},_onClick: function(/*Event*/ e){// summary: translates click events into commands for the controller to processvar domElement = e.target;// find nodevar nodeWidget = dijit.getEnclosingWidget(domElement);if(!nodeWidget || !nodeWidget.isTreeNode){return;}if(domElement == nodeWidget.expandoNode ||domElement == nodeWidget.expandoNodeText){// expando node was clickedif(nodeWidget.isExpandable){this._onExpandoClick({node:nodeWidget});}}else{this._publish("execute", { item: nodeWidget.item, node: nodeWidget} );this.onClick(nodeWidget.item, nodeWidget);this.focusNode(nodeWidget);}dojo.stopEvent(e);},_onExpandoClick: function(/*Object*/ message){// summary: user clicked the +/- icon; expand or collapse my children.var node = message.node;if(node.isExpanded){this._collapseNode(node);}else{this._expandNode(node);}},onClick: function(/* dojo.data */ item, /*TreeNode*/ node){// summary: user overridable function for executing a tree item},_navToNextNode: function(node){// summary: get next visible nodevar returnNode;// if this is an expanded node, get the first childif(node.isExpandable && node.isExpanded && node.hasChildren()){returnNode = node.getChildren()[0];}else{// find a parent node with a siblingwhile(node && node.isTreeNode){returnNode = node.getNextSibling();if(returnNode){break;}node = node.getParent();}}return returnNode;},_navToRootOrFirstNode: function(){// summary: get first visible nodeif(!this._hideRoot){return this;}else{var returnNode = this.getChildren()[0];if(returnNode && returnNode.isTreeNode){return returnNode;}}},_collapseNode: function(/*_TreeNode*/ node){// summary: called when the user has requested to collapse the nodeif(node.isExpandable){if(node.state == "LOADING"){// ignore clicks while we are in the process of loading datareturn;}if(this.lastFocused){// are we collapsing a descendant with focus?if(dojo.isDescendant(this.lastFocused.domNode, node.domNode)){this.focusNode(node);}else{// clicking the expando node might have erased focus from// the current item; restore itthis.focusNode(this.lastFocused);}}node.collapse();if(this.persist && node.item){delete this._openedItemIds[this.store.getIdentity(node.item)];this._saveState();}}},_expandNode: function(/*_TreeNode*/ node){// summary: called when the user has requested to expand the node// clicking the expando node might have erased focus from the current item; restore itvar t = node.tree;if(t.lastFocused){ t.focusNode(t.lastFocused); }if(!node.isExpandable){return;}var store = this.store;var getValue = this.store.getValue;switch(node.state){case "LOADING":// ignore clicks while we are in the process of loading datareturn;case "UNCHECKED":// need to load all the children, and then expandnode.markProcessing();var _this = this;var onComplete = function(childItems){node.unmarkProcessing();_this._onLoadAllItems(node, childItems);};this.getItemChildren(node.item, onComplete);break;default:// data is already loaded; just proceedif(node.expand){ // top level Tree doesn't have expand() methodnode.expand();if(this.persist && node.item){this._openedItemIds[this.store.getIdentity(node.item)] = true;this._saveState();}}break;}},////////////////// Miscellaneous functions ////////////////blurNode: function(){// summary// Removes focus from the currently focused node (which must be visible).// Usually not called directly (just call focusNode() on another node instead)var node = this.lastFocused;if(!node){ return; }var labelNode = node.labelNode;dojo.removeClass(labelNode, "dijitTreeLabelFocused");labelNode.setAttribute("tabIndex", "-1");this.lastFocused = null;},focusNode: function(/* _tree.Node */ node){// summary// Focus on the specified node (which must be visible)// set focus so that the label will be voiced using screen readersnode.labelNode.focus();},_onBlur: function(){// summary:// We've moved away from the whole tree. The currently "focused" node// (see focusNode above) should remain as the lastFocused node so we can// tab back into the tree. Just change CSS to get rid of the dotted border// until that timeif(this.lastFocused){var labelNode = this.lastFocused.labelNode;dojo.removeClass(labelNode, "dijitTreeLabelFocused");}},_onTreeFocus: function(evt){var node = dijit.getEnclosingWidget(evt.target);if(node != this.lastFocused){this.blurNode();}var labelNode = node.labelNode;// set tabIndex so that the tab key can find this nodelabelNode.setAttribute("tabIndex", "0");dojo.addClass(labelNode, "dijitTreeLabelFocused");this.lastFocused = node;},//////////////// Events from data store //////////////////////////_onNewItem: function(/*Object*/ item, parentInfo){//summary: callback when new item has been added to the store.var loadNewItem; // should new item be displayed in tree?if(parentInfo){var parent = this._itemNodeMap[this.getItemParentIdentity(item, parentInfo)];// If new item's parent item not in tree view yet, can safely ignore.// Also, if a query of specified parent wouldn't return this item, then ignore.if(!parent ||dojo.indexOf(this.childrenAttr, parentInfo.attribute) == -1){return;}}var childParams = {item: item,isExpandable: this.mayHaveChildren(item)};if(parent){if(!parent.isExpandable){parent.makeExpandable();}if(parent.state=="LOADED" || parent.isExpanded){var childrenMap=parent._addChildren([childParams]);}}else{// top level nodevar childrenMap=this._addChildren([childParams]);}if(childrenMap){dojo.mixin(this._itemNodeMap, childrenMap);//this._itemNodeMap[this.store.getIdentity(item)]=child;}},_onDeleteItem: function(/*Object*/ item){//summary: delete event from the store//since the object has just been deleted, we need to//use the name directlyvar identity = this.store.getIdentity(item);var node = this._itemNodeMap[identity];if(node){var parent = node.getParent();parent.deleteNode(node);this._itemNodeMap[identity]=null;}},_onSetItem: function(/*Object*/ item){//summary: set data event on an item in the storevar identity = this.store.getIdentity(item);node = this._itemNodeMap[identity];if(node){node.setLabelNode(this.getLabel(item));node._updateItemClasses(item);}},_saveState: function(){//summary: create and save a cookie with the currently expanded nodes identifiersif(!this.persist){return;}var ary = [];for(var id in this._openedItemIds){ary.push(id);}dojo.cookie(this.cookieName, ary.join(","));}});}if(!dojo._hasResource["dijit.form.TextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.form.TextBox"] = true;dojo.provide("dijit.form.TextBox");dojo.declare("dijit.form.TextBox",dijit.form._FormWidget,{// summary:// A generic textbox field.// Serves as a base class to derive more specialized functionality in subclasses.// trim: Boolean// Removes leading and trailing whitespace if true. Default is false.trim: false,// uppercase: Boolean// Converts all characters to uppercase if true. Default is false.uppercase: false,// lowercase: Boolean// Converts all characters to lowercase if true. Default is false.lowercase: false,// propercase: Boolean// Converts the first character of each word to uppercase if true.propercase: false,// maxLength: String// HTML INPUT tag maxLength declaration.maxLength: "",templateString:"<input class=\"dojoTextBox\" dojoAttachPoint='textbox,focusNode' name=\"${name}\"\n\tdojoAttachEvent='onmouseenter:_onMouse,onmouseleave:_onMouse,onfocus:_onMouse,onblur:_onMouse,onkeyup,onkeypress:_onKeyPress'\n\tautocomplete=\"off\" type=\"${type}\"\n\t/>\n",baseClass: "dijitTextBox",attributeMap: dojo.mixin(dojo.clone(dijit.form._FormWidget.prototype.attributeMap),{maxLength:"focusNode"}),getDisplayedValue: function(){return this.filter(this.textbox.value);},getValue: function(){return this.parse(this.getDisplayedValue(), this.constraints);},setValue: function(value, /*Boolean, optional*/ priorityChange, /*String, optional*/ formattedValue){var filteredValue = this.filter(value);if((typeof filteredValue == typeof value) && (formattedValue == null || formattedValue == undefined)){formattedValue = this.format(filteredValue, this.constraints);}if(formattedValue != null && formattedValue != undefined){this.textbox.value = formattedValue;}dijit.form.TextBox.superclass.setValue.call(this, filteredValue, priorityChange);},setDisplayedValue: function(/*String*/value){this.textbox.value = value;this.setValue(this.getValue(), true);},forWaiValuenow: function(){return this.getDisplayedValue();},format: function(/* String */ value, /* Object */ constraints){// summary: Replacable function to convert a value to a properly formatted stringreturn ((value == null || value == undefined) ? "" : (value.toString ? value.toString() : value));},parse: function(/* String */ value, /* Object */ constraints){// summary: Replacable function to convert a formatted string to a valuereturn value;},postCreate: function(){// setting the value here is needed since value="" in the template causes "undefined"// and setting in the DOM (instead of the JS object) helps with form reset actionsthis.textbox.setAttribute("value", this.getDisplayedValue());this.inherited('postCreate', arguments);if(this.srcNodeRef){dojo.style(this.textbox, "cssText", this.style);this.textbox.className += " " + this["class"];}this._layoutHack();},_layoutHack: function(){// summary: work around table sizing bugs on FF2 by forcing redrawif(dojo.isFF == 2 && this.domNode.tagName=="TABLE"){var node=this.domNode;var old = node.style.opacity;node.style.opacity = "0.999";setTimeout(function(){node.style.opacity = old;}, 0);}},filter: function(val){// summary: Apply various filters to textbox valueif(val == undefined || val == null){ return ""; }else if(typeof val != "string"){ return val; }if(this.trim){val = dojo.trim(val);}if(this.uppercase){val = val.toUpperCase();}if(this.lowercase){val = val.toLowerCase();}if(this.propercase){val = val.replace(/[^\s]+/g, function(word){return word.substring(0,1).toUpperCase() + word.substring(1);});}return val;},// event handlers, you can over-ride these in your own subclasses_onBlur: function(){this.setValue(this.getValue(), (this.isValid ? this.isValid() : true));},onkeyup: function(){// TODO: it would be nice to massage the value (ie: automatic uppercase, etc) as the user types// but this messes up the cursor position if you are typing into the middle of a word, and// also trimming doesn't work correctly (it prevents spaces between words too!)// this.setValue(this.getValue());}});}if(!dojo._hasResource["dijit.InlineEditBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.InlineEditBox"] = true;dojo.provide("dijit.InlineEditBox");dojo.declare("dijit.InlineEditBox",dijit._Widget,{// summary: An element with in-line edit capabilitites//// description:// Behavior for an existing node (<p>, <div>, <span>, etc.) so that// when you click it, an editor shows up in place of the original// text. Optionally, Save and Cancel button are displayed below the edit widget.// When Save is clicked, the text is pulled from the edit// widget and redisplayed and the edit widget is again hidden.// By default a plain Textarea widget is used as the editor (or for// inline values a TextBox), but you can specify an editor such as// dijit.Editor (for editing HTML) or a Slider (for adjusting a number).// An edit widget must support the following API to be used:// String getDisplayedValue() OR String getValue()// void setDisplayedValue(String) OR void setValue(String)// void focus()//// editing: Boolean// Is the node currently in edit mode?editing: false,// autoSave: Boolean// Changing the value automatically saves it; don't have to push save button// (and save button isn't even displayed)autoSave: true,// buttonSave: String// Save button labelbuttonSave: "",// buttonCancel: String// Cancel button labelbuttonCancel: "",// renderAsHtml: Boolean// Set this to true if the specified Editor's value should be interpreted as HTML// rather than plain text (ie, dijit.Editor)renderAsHtml: false,// editor: String// Class name for Editor widgeteditor: "dijit.form.TextBox",// editorParams: Object// Set of parameters for editor, like {required: true}editorParams: {},onChange: function(value){// summary: User should set this handler to be notified of changes to value},// width: String// Width of editor. By default it's width=100% (ie, block mode)width: "100%",// value: String// The display value of the widget in read-only modevalue: "",// noValueIndicator: String// The text that gets displayed when there is no value (so that the user has a place to click to edit)noValueIndicator: "<span style='font-family: wingdings; text-decoration: underline;'> ✍ </span>",postMixInProperties: function(){this.inherited('postMixInProperties', arguments);// save pointer to original source node, since Widget nulls-out srcNodeRefthis.displayNode = this.srcNodeRef;// connect handlers to the display nodevar events = {ondijitclick: "_onClick",onmouseover: "_onMouseOver",onmouseout: "_onMouseOut",onfocus: "_onMouseOver",onblur: "_onMouseOut"};for(var name in events){this.connect(this.displayNode, name, events[name]);}dijit.setWaiRole(this.displayNode, "button");if(!this.displayNode.getAttribute("tabIndex")){this.displayNode.setAttribute("tabIndex", 0);}if(!this.value){this.value = this.displayNode.innerHTML;}this._setDisplayValue(this.value); // if blank, change to icon for "input needed"},_onMouseOver: function(){dojo.addClass(this.displayNode, this.disabled ? "dijitDisabledClickableRegion" : "dijitClickableRegion");},_onMouseOut: function(){dojo.removeClass(this.displayNode, this.disabled ? "dijitDisabledClickableRegion" : "dijitClickableRegion");},_onClick: function(/*Event*/ e){if(this.disabled){ return; }if(e){ dojo.stopEvent(e); }this._onMouseOut();// Since FF gets upset if you move a node while in an event handler for that node...setTimeout(dojo.hitch(this, "_edit"), 0);},_edit: function(){// summary: display the editor widget in place of the original (read only) markupthis.editing = true;var editValue =(this.renderAsHtml ?this.value :this.value.replace(/\s*\r?\n\s*/g,"").replace(/<br\/?>/gi, "\n").replace(/>/g,">").replace(/</g,"<").replace(/&/g,"&"));// Placeholder for edit widget// Put place holder (and eventually editWidget) before the display node so that it's positioned correctly// when Calendar dropdown appears, which happens automatically on focus.var placeholder = document.createElement("span");dojo.place(placeholder, this.domNode, "before");var ew = this.editWidget = new dijit._InlineEditor({value: dojo.trim(editValue),autoSave: this.autoSave,buttonSave: this.buttonSave,buttonCancel: this.buttonCancel,renderAsHtml: this.renderAsHtml,editor: this.editor,editorParams: this.editorParams,style: dojo.getComputedStyle(this.displayNode),save: dojo.hitch(this, "save"),cancel: dojo.hitch(this, "cancel"),width: this.width}, placeholder);// to avoid screen jitter, we first create the editor with position:absolute, visibility:hidden,// and then when it's finished rendering, we switch from display mode to editorvar ews = ew.domNode.style;this.displayNode.style.display="none";ews.position = "static";ews.visibility = "visible";// Replace the display widget with edit widget, leaving them both displayed for a brief time so that// focus can be shifted without incident. (browser may needs some time to render the editor.)this.domNode = ew.domNode;setTimeout(function(){ew.focus();}, 100);},_showText: function(/*Boolean*/ focus){// summary: revert to display mode, and optionally focus on display node// display the read-only text and then quickly hide the editor (to avoid screen jitter)this.displayNode.style.display="";var ews = this.editWidget.domNode.style;ews.position="absolute";ews.visibility="hidden";this.domNode = this.displayNode;// give the browser some time to render the display node and then shift focus to it// and hide the edit widgetvar _this = this;setTimeout(function(){if(focus){dijit.focus(_this.displayNode);}_this.editWidget.destroy();delete _this.editWidget;}, 100);},save: function(/*Boolean*/ focus){// summary:// Save the contents of the editor and revert to display mode.// focus: Boolean// Focus on the display mode textthis.editing = false;this.value = this.editWidget.getValue() + "";if(this.renderAsHtml){this.value = this.value.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """).replace("\n", "<br>");}this._setDisplayValue(this.value);// tell the world that we have changedthis.onChange(this.value);this._showText(focus);},_setDisplayValue: function(/*String*/ val){// summary: inserts specified HTML value into this node, or an "input needed" character if node is blankthis.displayNode.innerHTML = val || this.noValueIndicator;},cancel: function(/*Boolean*/ focus){// summary:// Revert to display mode, discarding any changes made in the editorthis.editing = false;this._showText(focus);}});dojo.declare("dijit._InlineEditor",[dijit._Widget, dijit._Templated],{// summary:// internal widget used by InlineEditBox, displayed when in editing mode// to display the editor and maybe save/cancel buttons. Calling code should// connect to save/cancel methods to detect when editing is finished//// Has mainly the same parameters as InlineEditBox, plus these values://// style: Object// Set of CSS attributes of display node, to replicate in editor//// value: String// Value as an HTML string or plain text string, depending on renderAsHTML flagtemplateString:"<fieldset dojoAttachPoint=\"editNode\" waiRole=\"presentation\" style=\"position: absolute; visibility:hidden\" class=\"dijitReset dijitInline\"\n\tdojoAttachEvent=\"onkeypress: _onKeyPress\" \n\t><input dojoAttachPoint=\"editorPlaceholder\"\n\t/><span dojoAttachPoint=\"buttonContainer\"\n\t\t><button class='saveButton' dojoAttachPoint=\"saveButton\" dojoType=\"dijit.form.Button\" dojoAttachEvent=\"onClick:save\">${buttonSave}</button\n\t\t><button class='cancelButton' dojoAttachPoint=\"cancelButton\" dojoType=\"dijit.form.Button\" dojoAttachEvent=\"onClick:cancel\">${buttonCancel}</button\n\t></span\n></fieldset>\n",widgetsInTemplate: true,postMixInProperties: function(){this.inherited('postMixInProperties', arguments);this.messages = dojo.i18n.getLocalization("dijit", "common", this.lang);dojo.forEach(["buttonSave", "buttonCancel"], function(prop){if(!this[prop]){ this[prop] = this.messages[prop]; }}, this);},postCreate: function(){// Create edit widget in place in the templatevar cls = dojo.getObject(this.editor);var ew = this.editWidget = new cls(this.editorParams, this.editorPlaceholder);// Copy the style from the source// Don't copy ALL properties though, just the necessary/applicable onesvar srcStyle = this.style;dojo.forEach(["fontWeight","fontFamily","fontSize","fontStyle"], function(prop){ew.focusNode.style[prop]=srcStyle[prop];}, this);dojo.forEach(["marginTop","marginBottom","marginLeft", "marginRight"], function(prop){this.domNode.style[prop]=srcStyle[prop];}, this);if(this.width=="100%"){// block modeew.domNode.style.width = "100%"; // because display: block doesn't work for table widgetsthis.domNode.style.display="block";}else{// inline-block modeew.domNode.style.width = this.width + (Number(this.width)==this.width ? "px" : "");}this.connect(this.editWidget, "onChange", "_onChange");// setting the value of the edit widget will cause a possibly asynchronous onChange() call.// we need to ignore it, since we are only interested in when the user changes the value.this._ignoreNextOnChange = true;(this.editWidget.setDisplayedValue||this.editWidget.setValue).call(this.editWidget, this.value);this._initialText = this.getValue();if(this.autoSave){this.buttonContainer.style.display="none";}},destroy: function(){this.editWidget.destroy();this.inherited(arguments);},getValue: function(){var ew = this.editWidget;return ew.getDisplayedValue ? ew.getDisplayedValue() : ew.getValue();},_onKeyPress: function(e){// summary: Callback when keypress in the edit box (see template).// description:// For autoSave widgets, if Esc/Enter, call cancel/save.// For non-autoSave widgets, enable save button if the text value is// different than the original value.if(this._exitInProgress){return;}if(this.autoSave){// If Enter/Esc pressed, treat as save/cancel.if(e.keyCode == dojo.keys.ESCAPE){dojo.stopEvent(e);this._exitInProgress = true;this.cancel(true);}else if(e.keyCode == dojo.keys.ENTER){dojo.stopEvent(e);this._exitInProgress = true;this.save(true);}}else{var _this = this;// Delay before calling getValue().// The delay gives the browser a chance to update the Textarea.setTimeout(function(){_this.saveButton.setDisabled(_this.getValue() == _this._initialText);}, 100);}},_onBlur: function(){// summary:// Called when focus moves outside the editorif(this._exitInProgress){// when user clicks the "save" button, focus is shifted back to display text, causing this// function to be called, but in that case don't do anythingreturn;}if(this.autoSave){this._exitInProgress = true;if(this.getValue() == this._initialText){this.cancel(false);}else{this.save(false);}}},enableSave: function(){// summary: User replacable function returning a Boolean to indicate// if the Save button should be enabled or not - usually due to invalid conditionsreturn this.editWidget.isValid ? this.editWidget.isValid() : true; // Boolean},_onChange: function(){// summary:// Called when the underlying widget fires an onChange event,// which means that the user has finished entering the valueif(this._ignoreNextOnChange){delete this._ignoreNextOnChange;return;}if(this._exitInProgress){// TODO: the onChange event might happen after the return key for an async widget// like FilteringSelect. Shouldn't be deleting the edit widget on end-of-editreturn;}if(this.autoSave){this._exitInProgress = true;this.save(true);}else{// in case the keypress event didn't get through (old problem with Textarea that has been fixed// in theory) or if the keypress event comes too quickly and the value inside the Textarea hasn't// been updated yet)this.saveButton.setDisabled((this.getValue() == this._initialText) || !this.enableSave());}},enableSave: function(){// summary: User replacable function returning a Boolean to indicate// if the Save button should be enabled or not - usually due to invalid conditionsreturn this.editWidget.isValid ? this.editWidget.isValid() : true;},focus: function(){this.editWidget.focus();dijit.selectInputText(this.editWidget.focusNode);}});dijit.selectInputText = function(/*DomNode*/element){// summary: select all the text in an input element// TODO: use functions in _editor/selection.js?var _window = dojo.global;var _document = dojo.doc;element = dojo.byId(element);if(_document["selection"] && dojo.body()["createTextRange"]){ // IEif(element.createTextRange){var range = element.createTextRange();range.moveStart("character", 0);range.moveEnd("character", element.value.length);range.select();}}else if(_window["getSelection"]){var selection = _window.getSelection();// FIXME: does this work on Safari?if(element.setSelectionRange){element.setSelectionRange(0, element.value.length);}}element.focus();};}if(!dojo._hasResource["dijit.form.CheckBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.form.CheckBox"] = true;dojo.provide("dijit.form.CheckBox");dojo.declare("dijit.form.CheckBox",dijit.form.ToggleButton,{// summary:// Same as an HTML checkbox, but with fancy styling.//// description:// User interacts with real html inputs.// On onclick (which occurs by mouse click, space-bar, or// using the arrow keys to switch the selected radio button),// we update the state of the checkbox/radio.//// There are two modes:// 1. High contrast mode// 2. Normal mode// In case 1, the regular html inputs are shown and used by the user.// In case 2, the regular html inputs are invisible but still used by// the user. They are turned quasi-invisible and overlay the background-image.templateString:"<fieldset class=\"dijitReset dijitInline\" waiRole=\"presentation\"\n\t><input\n\t \ttype=\"${type}\" name=\"${name}\"\n\t\tclass=\"dijitReset dijitCheckBoxInput\"\n\t\tdojoAttachPoint=\"inputNode,focusNode\"\n\t \tdojoAttachEvent=\"onmouseover:_onMouse,onmouseout:_onMouse,onclick:_onClick\"\n/></fieldset>\n",baseClass: "dijitCheckBox",// Value of "type" attribute for <input>type: "checkbox",// value: Value// equivalent to value field on normal checkbox (if checked, the value is passed as// the value when form is submitted)value: "on",postCreate: function(){dojo.setSelectable(this.inputNode, false);this.setChecked(this.checked);this.inherited(arguments);},setChecked: function(/*Boolean*/ checked){if(dojo.isIE){if(checked){ this.inputNode.setAttribute('checked', 'checked'); }else{ this.inputNode.removeAttribute('checked'); }}else{ this.inputNode.checked = checked; }this.inherited(arguments);},setValue: function(/*String*/ value){if(value == null){ value = ""; }this.inputNode.value = value;dijit.form.CheckBox.superclass.setValue.call(this,value);}});dojo.declare("dijit.form.RadioButton",dijit.form.CheckBox,{// summary:// Same as an HTML radio, but with fancy styling.//// description:// Implementation details//// Specialization:// We keep track of dijit radio groups so that we can update the state// of all the siblings (the "context") in a group based on input// events. We don't rely on browser radio grouping.type: "radio",baseClass: "dijitRadio",// This shared object keeps track of all widgets, grouped by name_groups: {},postCreate: function(){// add this widget to _groups(this._groups[this.name] = this._groups[this.name] || []).push(this);this.inherited(arguments);},uninitialize: function(){// remove this widget from _groupsdojo.forEach(this._groups[this.name], function(widget, i, arr){if(widget === this){arr.splice(i, 1);return;}}, this);},setChecked: function(/*Boolean*/ checked){// If I am being checked then have to deselect currently checked radio buttonif(checked){dojo.forEach(this._groups[this.name], function(widget){if(widget != this && widget.checked){widget.setChecked(false);}}, this);}this.inherited(arguments);},_clicked: function(/*Event*/ e){if(!this.checked){this.setChecked(true);}}});}if(!dojo._hasResource["dojo.data.util.filter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.data.util.filter"] = true;dojo.provide("dojo.data.util.filter");dojo.data.util.filter.patternToRegExp = function(/*String*/pattern, /*boolean?*/ ignoreCase){// summary:// Helper function to convert a simple pattern to a regular expression for matching.// description:// Returns a regular expression object that conforms to the defined conversion rules.// For example:// ca* -> /^ca.*$/// *ca* -> /^.*ca.*$/// *c\*a* -> /^.*c\*a.*$/// *c\*a?* -> /^.*c\*a..*$/// and so on.//// pattern: string// A simple matching pattern to convert that follows basic rules:// * Means match anything, so ca* means match anything starting with ca// ? Means match single character. So, b?b will match to bob and bab, and so on.// \ is an escape character. So for example, \* means do not treat * as a match, but literal character *.// To use a \ as a character in the string, it must be escaped. So in the pattern it should be// represented by \\ to be treated as an ordinary \ character instead of an escape.//// ignoreCase:// An optional flag to indicate if the pattern matching should be treated as case-sensitive or not when comparing// By default, it is assumed case sensitive.var rxp = "^";var c = null;for(var i = 0; i < pattern.length; i++){c = pattern.charAt(i);switch (c) {case '\\':rxp += c;i++;rxp += pattern.charAt(i);break;case '*':rxp += ".*"; break;case '?':rxp += "."; break;case '$':case '^':case '/':case '+':case '.':case '|':case '(':case ')':case '{':case '}':case '[':case ']':rxp += "\\"; //fallthroughdefault:rxp += c;}}rxp += "$";if(ignoreCase){return new RegExp(rxp,"i"); //RegExp}else{return new RegExp(rxp); //RegExp}};}if(!dojo._hasResource["dojo.data.util.sorter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.data.util.sorter"] = true;dojo.provide("dojo.data.util.sorter");dojo.data.util.sorter.basicComparator = function( /*anything*/ a,/*anything*/ b){// summary:// Basic comparision function that compares if an item is greater or less than another item// description:// returns 1 if a > b, -1 if a < b, 0 if equal.// undefined values are treated as larger values so that they're pushed to the end of the list.var ret = 0;if(a > b || typeof a === "undefined" || a === null){ret = 1;}else if(a < b || typeof b === "undefined" || b === null){ret = -1;}return ret; //int, {-1,0,1}};dojo.data.util.sorter.createSortFunction = function( /* attributes array */sortSpec,/*dojo.data.core.Read*/ store){// summary:// Helper function to generate the sorting function based off the list of sort attributes.// description:// The sort function creation will look for a property on the store called 'comparatorMap'. If it exists// it will look in the mapping for comparisons function for the attributes. If one is found, it will// use it instead of the basic comparator, which is typically used for strings, ints, booleans, and dates.// Returns the sorting function for this particular list of attributes and sorting directions.//// sortSpec: array// A JS object that array that defines out what attribute names to sort on and whether it should be descenting or asending.// The objects should be formatted as follows:// {// attribute: "attributeName-string" || attribute,// descending: true|false; // Default is false.// }// store: object// The datastore object to look up item values from.//var sortFunctions=[];function createSortFunction(attr, dir){return function(itemA, itemB){var a = store.getValue(itemA, attr);var b = store.getValue(itemB, attr);//See if we have a override for an attribute comparison.var comparator = null;if(store.comparatorMap){if(typeof attr !== "string"){attr = store.getIdentity(attr);}comparator = store.comparatorMap[attr]||dojo.data.util.sorter.basicComparator;}comparator = comparator||dojo.data.util.sorter.basicComparator;return dir * comparator(a,b); //int};}for(var i = 0; i < sortSpec.length; i++){sortAttribute = sortSpec[i];if(sortAttribute.attribute){var direction = (sortAttribute.descending) ? -1 : 1;sortFunctions.push(createSortFunction(sortAttribute.attribute, direction));}}return function(rowA, rowB){var i=0;while(i < sortFunctions.length){var ret = sortFunctions[i++](rowA, rowB);if(ret !== 0){return ret;//int}}return 0; //int}; // Function};}if(!dojo._hasResource["dojo.data.util.simpleFetch"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.data.util.simpleFetch"] = true;dojo.provide("dojo.data.util.simpleFetch");dojo.data.util.simpleFetch.fetch = function(/* Object? */ request){// summary:// The simpleFetch mixin is designed to serve as a set of function(s) that can// be mixed into other datastore implementations to accelerate their development.// The simpleFetch mixin should work well for any datastore that can respond to a _fetchItems()// call by returning an array of all the found items that matched the query. The simpleFetch mixin// is not designed to work for datastores that respond to a fetch() call by incrementally// loading items, or sequentially loading partial batches of the result// set. For datastores that mixin simpleFetch, simpleFetch// implements a fetch method that automatically handles eight of the fetch()// arguments -- onBegin, onItem, onComplete, onError, start, count, sort and scope// The class mixing in simpleFetch should not implement fetch(),// but should instead implement a _fetchItems() method. The _fetchItems()// method takes three arguments, the keywordArgs object that was passed// to fetch(), a callback function to be called when the result array is// available, and an error callback to be called if something goes wrong.// The _fetchItems() method should ignore any keywordArgs parameters for// start, count, onBegin, onItem, onComplete, onError, sort, and scope.// The _fetchItems() method needs to correctly handle any other keywordArgs// parameters, including the query parameter and any optional parameters// (such as includeChildren). The _fetchItems() method should create an array of// result items and pass it to the fetchHandler along with the original request object// -- or, the _fetchItems() method may, if it wants to, create an new request object// with other specifics about the request that are specific to the datastore and pass// that as the request object to the handler.//// For more information on this specific function, see dojo.data.api.Read.fetch()request = request || {};if(!request.store){request.store = this;}var self = this;var _errorHandler = function(errorData, requestObject){if(requestObject.onError){var scope = requestObject.scope || dojo.global;requestObject.onError.call(scope, errorData, requestObject);}};var _fetchHandler = function(items, requestObject){var oldAbortFunction = requestObject.abort || null;var aborted = false;var startIndex = requestObject.start?requestObject.start:0;var endIndex = requestObject.count?(startIndex + requestObject.count):items.length;requestObject.abort = function(){aborted = true;if(oldAbortFunction){oldAbortFunction.call(requestObject);}};var scope = requestObject.scope || dojo.global;if(!requestObject.store){requestObject.store = self;}if(requestObject.onBegin){requestObject.onBegin.call(scope, items.length, requestObject);}if(requestObject.sort){items.sort(dojo.data.util.sorter.createSortFunction(requestObject.sort, self));}if(requestObject.onItem){for(var i = startIndex; (i < items.length) && (i < endIndex); ++i){var item = items[i];if(!aborted){requestObject.onItem.call(scope, item, requestObject);}}}if(requestObject.onComplete && !aborted){var subset = null;if (!requestObject.onItem) {subset = items.slice(startIndex, endIndex);}requestObject.onComplete.call(scope, subset, requestObject);}};this._fetchItems(request, _fetchHandler, _errorHandler);return request; // Object};}if(!dojo._hasResource["dojo.data.ItemFileReadStore"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.data.ItemFileReadStore"] = true;dojo.provide("dojo.data.ItemFileReadStore");dojo.declare("dojo.data.ItemFileReadStore", null,{// summary:// The ItemFileReadStore implements the dojo.data.api.Read API and reads// data from JSON files that have contents in this format --// { items: [// { name:'Kermit', color:'green', age:12, friends:['Gonzo', {_reference:{name:'Fozzie Bear'}}]},// { name:'Fozzie Bear', wears:['hat', 'tie']},// { name:'Miss Piggy', pets:'Foo-Foo'}// ]}// Note that it can also contain an 'identifer' property that specified which attribute on the items// in the array of items that acts as the unique identifier for that item.//constructor: function(/* Object */ keywordParameters){// summary: constructor// keywordParameters: {url: String}// keywordParameters: {data: jsonObject}// keywordParameters: {typeMap: object)// The structure of the typeMap object is as follows:// {// type0: function || object,// type1: function || object,// ...// typeN: function || object// }// Where if it is a function, it is assumed to be an object constructor that takes the// value of _value as the initialization parameters. If it is an object, then it is assumed// to be an object of general form:// {// type: function, //constructor.// deserialize: function(value) //The function that parses the value and constructs the object defined by type appropriately.// }this._arrayOfAllItems = [];this._arrayOfTopLevelItems = [];this._loadFinished = false;this._jsonFileUrl = keywordParameters.url;this._jsonData = keywordParameters.data;this._datatypeMap = keywordParameters.typeMap || {};if(!this._datatypeMap['Date']){//If no default mapping for dates, then set this as default.//We use the dojo.date.stamp here because the ISO format is the 'dojo way'//of generically representing dates.this._datatypeMap['Date'] = {type: Date,deserialize: function(value){return dojo.date.stamp.fromISOString(value);}};}this._features = {'dojo.data.api.Read':true, 'dojo.data.api.Identity':true};this._itemsByIdentity = null;this._storeRefPropName = "_S"; // Default name for the store reference to attach to every item.this._itemNumPropName = "_0"; // Default Item Id for isItem to attach to every item.this._rootItemPropName = "_RI"; // Default Item Id for isItem to attach to every item.this._loadInProgress = false; //Got to track the initial load to prevent duelling loads of the dataset.this._queuedFetches = [];},url: "", // use "" rather than undefined for the benefit of the parser (#3539)_assertIsItem: function(/* item */ item){// summary:// This function tests whether the item passed in is indeed an item in the store.// item:// The item to test for being contained by the store.if(!this.isItem(item)){throw new Error("dojo.data.ItemFileReadStore: Invalid item argument.");}},_assertIsAttribute: function(/* attribute-name-string */ attribute){// summary:// This function tests whether the item passed in is indeed a valid 'attribute' like type for the store.// attribute:// The attribute to test for being contained by the store.if(typeof attribute !== "string"){throw new Error("dojo.data.ItemFileReadStore: Invalid attribute argument.");}},getValue: function( /* item */ item,/* attribute-name-string */ attribute,/* value? */ defaultValue){// summary:// See dojo.data.api.Read.getValue()var values = this.getValues(item, attribute);return (values.length > 0)?values[0]:defaultValue; // mixed},getValues: function(/* item */ item,/* attribute-name-string */ attribute){// summary:// See dojo.data.api.Read.getValues()this._assertIsItem(item);this._assertIsAttribute(attribute);return item[attribute] || []; // Array},getAttributes: function(/* item */ item){// summary:// See dojo.data.api.Read.getAttributes()this._assertIsItem(item);var attributes = [];for(var key in item){// Save off only the real item attributes, not the special id marks for O(1) isItem.if((key !== this._storeRefPropName) && (key !== this._itemNumPropName) && (key !== this._rootItemPropName)){attributes.push(key);}}return attributes; // Array},hasAttribute: function( /* item */ item,/* attribute-name-string */ attribute) {// summary:// See dojo.data.api.Read.hasAttribute()return this.getValues(item, attribute).length > 0;},containsValue: function(/* item */ item,/* attribute-name-string */ attribute,/* anything */ value){// summary:// See dojo.data.api.Read.containsValue()var regexp = undefined;if(typeof value === "string"){regexp = dojo.data.util.filter.patternToRegExp(value, false);}return this._containsValue(item, attribute, value, regexp); //boolean.},_containsValue: function( /* item */ item,/* attribute-name-string */ attribute,/* anything */ value,/* RegExp?*/ regexp){// summary:// Internal function for looking at the values contained by the item.// description:// Internal function for looking at the values contained by the item. This// function allows for denoting if the comparison should be case sensitive for// strings or not (for handling filtering cases where string case should not matter)//// item:// The data item to examine for attribute values.// attribute:// The attribute to inspect.// value:// The value to match.// regexp:// Optional regular expression generated off value if value was of string type to handle wildcarding.// If present and attribute values are string, then it can be used for comparison instead of 'value'return dojo.some(this.getValues(item, attribute), function(possibleValue){if(possibleValue !== null && !dojo.isObject(possibleValue) && regexp){if(possibleValue.toString().match(regexp)){return true; // Boolean}}else if(value === possibleValue){return true; // Boolean}});},isItem: function(/* anything */ something){// summary:// See dojo.data.api.Read.isItem()if(something && something[this._storeRefPropName] === this){if(this._arrayOfAllItems[something[this._itemNumPropName]] === something){return true;}}return false; // Boolean},isItemLoaded: function(/* anything */ something){// summary:// See dojo.data.api.Read.isItemLoaded()return this.isItem(something); //boolean},loadItem: function(/* object */ keywordArgs){// summary:// See dojo.data.api.Read.loadItem()this._assertIsItem(keywordArgs.item);},getFeatures: function(){// summary:// See dojo.data.api.Read.getFeatures()return this._features; //Object},getLabel: function(/* item */ item){// summary:// See dojo.data.api.Read.getLabel()if(this._labelAttr && this.isItem(item)){return this.getValue(item,this._labelAttr); //String}return undefined; //undefined},getLabelAttributes: function(/* item */ item){// summary:// See dojo.data.api.Read.getLabelAttributes()if(this._labelAttr){return [this._labelAttr]; //array}return null; //null},_fetchItems: function( /* Object */ keywordArgs,/* Function */ findCallback,/* Function */ errorCallback){// summary:// See dojo.data.util.simpleFetch.fetch()var self = this;var filter = function(requestArgs, arrayOfItems){var items = [];if(requestArgs.query){var ignoreCase = requestArgs.queryOptions ? requestArgs.queryOptions.ignoreCase : false;//See if there are any string values that can be regexp parsed first to avoid multiple regexp gens on the//same value for each item examined. Much more efficient.var regexpList = {};for(var key in requestArgs.query){var value = requestArgs.query[key];if(typeof value === "string"){regexpList[key] = dojo.data.util.filter.patternToRegExp(value, ignoreCase);}}for(var i = 0; i < arrayOfItems.length; ++i){var match = true;var candidateItem = arrayOfItems[i];if(candidateItem === null){match = false;}else{for(var key in requestArgs.query) {var value = requestArgs.query[key];if (!self._containsValue(candidateItem, key, value, regexpList[key])){match = false;}}}if(match){items.push(candidateItem);}}findCallback(items, requestArgs);}else{// We want a copy to pass back in case the parent wishes to sort the array.// We shouldn't allow resort of the internal list, so that multiple callers// can get lists and sort without affecting each other. We also need to// filter out any null values that have been left as a result of deleteItem()// calls in ItemFileWriteStore.for(var i = 0; i < arrayOfItems.length; ++i){var item = arrayOfItems[i];if(item !== null){items.push(item);}}findCallback(items, requestArgs);}};if(this._loadFinished){filter(keywordArgs, this._getItemsArray(keywordArgs.queryOptions));}else{if(this._jsonFileUrl){//If fetches come in before the loading has finished, but while//a load is in progress, we have to defer the fetching to be//invoked in the callback.if(this._loadInProgress){this._queuedFetches.push({args: keywordArgs, filter: filter});}else{this._loadInProgress = true;var getArgs = {url: self._jsonFileUrl,handleAs: "json-comment-optional"};var getHandler = dojo.xhrGet(getArgs);getHandler.addCallback(function(data){try{self._getItemsFromLoadedData(data);self._loadFinished = true;self._loadInProgress = false;filter(keywordArgs, self._getItemsArray(keywordArgs.queryOptions));self._handleQueuedFetches();}catch(e){self._loadFinished = true;self._loadInProgress = false;errorCallback(e, keywordArgs);}});getHandler.addErrback(function(error){self._loadInProgress = false;errorCallback(error, keywordArgs);});}}else if(this._jsonData){try{this._loadFinished = true;this._getItemsFromLoadedData(this._jsonData);this._jsonData = null;filter(keywordArgs, this._getItemsArray(keywordArgs.queryOptions));}catch(e){errorCallback(e, keywordArgs);}}else{errorCallback(new Error("dojo.data.ItemFileReadStore: No JSON source data was provided as either URL or a nested Javascript object."), keywordArgs);}}},_handleQueuedFetches: function(){// summary:// Internal function to execute delayed request in the store.//Execute any deferred fetches now.if (this._queuedFetches.length > 0) {for(var i = 0; i < this._queuedFetches.length; i++){var fData = this._queuedFetches[i];var delayedQuery = fData.args;var delayedFilter = fData.filter;if(delayedFilter){delayedFilter(delayedQuery, this._getItemsArray(delayedQuery.queryOptions));}else{this.fetchItemByIdentity(delayedQuery);}}this._queuedFetches = [];}},_getItemsArray: function(/*object?*/queryOptions){// summary:// Internal function to determine which list of items to search over.// queryOptions: The query options parameter, if any.if(queryOptions && queryOptions.deep) {return this._arrayOfAllItems;}return this._arrayOfTopLevelItems;},close: function(/*dojo.data.api.Request || keywordArgs || null */ request){// summary:// See dojo.data.api.Read.close()},_getItemsFromLoadedData: function(/* Object */ dataObject){// summary:// Function to parse the loaded data into item format and build the internal items array.// description:// Function to parse the loaded data into item format and build the internal items array.//// dataObject:// The JS data object containing the raw data to convery into item format.//// returns: array// Array of items in store item format.// First, we define a couple little utility functions...function valueIsAnItem(/* anything */ aValue){// summary:// Given any sort of value that could be in the raw json data,// return true if we should interpret the value as being an// item itself, rather than a literal value or a reference.// example:// | false == valueIsAnItem("Kermit");// | false == valueIsAnItem(42);// | false == valueIsAnItem(new Date());// | false == valueIsAnItem({_type:'Date', _value:'May 14, 1802'});// | false == valueIsAnItem({_reference:'Kermit'});// | true == valueIsAnItem({name:'Kermit', color:'green'});// | true == valueIsAnItem({iggy:'pop'});// | true == valueIsAnItem({foo:42});var isItem = ((aValue != null) &&(typeof aValue == "object") &&(!dojo.isArray(aValue)) &&(!dojo.isFunction(aValue)) &&(aValue.constructor == Object) &&(typeof aValue._reference == "undefined") &&(typeof aValue._type == "undefined") &&(typeof aValue._value == "undefined"));return isItem;}var self = this;function addItemAndSubItemsToArrayOfAllItems(/* Item */ anItem){self._arrayOfAllItems.push(anItem);for(var attribute in anItem){var valueForAttribute = anItem[attribute];if(valueForAttribute){if(dojo.isArray(valueForAttribute)){var valueArray = valueForAttribute;for(var k = 0; k < valueArray.length; ++k){var singleValue = valueArray[k];if(valueIsAnItem(singleValue)){addItemAndSubItemsToArrayOfAllItems(singleValue);}}}else{if(valueIsAnItem(valueForAttribute)){addItemAndSubItemsToArrayOfAllItems(valueForAttribute);}}}}}this._labelAttr = dataObject.label;// We need to do some transformations to convert the data structure// that we read from the file into a format that will be convenient// to work with in memory.// Step 1: Walk through the object hierarchy and build a list of all itemsvar i;var item;this._arrayOfAllItems = [];this._arrayOfTopLevelItems = dataObject.items;for(i = 0; i < this._arrayOfTopLevelItems.length; ++i){item = this._arrayOfTopLevelItems[i];addItemAndSubItemsToArrayOfAllItems(item);item[this._rootItemPropName]=true;}// Step 2: Walk through all the attribute values of all the items,// and replace single values with arrays. For example, we change this:// { name:'Miss Piggy', pets:'Foo-Foo'}// into this:// { name:['Miss Piggy'], pets:['Foo-Foo']}//// We also store the attribute names so we can validate our store// reference and item id special properties for the O(1) isItemvar allAttributeNames = {};var key;for(i = 0; i < this._arrayOfAllItems.length; ++i){item = this._arrayOfAllItems[i];for(key in item){if (key !== this._rootItemPropName){var value = item[key];if(value !== null){if(!dojo.isArray(value)){item[key] = [value];}}else{item[key] = [null];}}allAttributeNames[key]=key;}}// Step 3: Build unique property names to use for the _storeRefPropName and _itemNumPropName// This should go really fast, it will generally never even run the loop.while(allAttributeNames[this._storeRefPropName]){this._storeRefPropName += "_";}while(allAttributeNames[this._itemNumPropName]){this._itemNumPropName += "_";}// Step 4: Some data files specify an optional 'identifier', which is// the name of an attribute that holds the identity of each item.// If this data file specified an identifier attribute, then build a// hash table of items keyed by the identity of the items.var arrayOfValues;var identifier = dataObject.identifier;if(identifier){this._itemsByIdentity = {};this._features['dojo.data.api.Identity'] = identifier;for(i = 0; i < this._arrayOfAllItems.length; ++i){item = this._arrayOfAllItems[i];arrayOfValues = item[identifier];var identity = arrayOfValues[0];if(!this._itemsByIdentity[identity]){this._itemsByIdentity[identity] = item;}else{if(this._jsonFileUrl){throw new Error("dojo.data.ItemFileReadStore: The json data as specified by: [" + this._jsonFileUrl + "] is malformed. Items within the list have identifier: [" + identifier + "]. Value collided: [" + identity + "]");}else if(this._jsonData){throw new Error("dojo.data.ItemFileReadStore: The json data provided by the creation arguments is malformed. Items within the list have identifier: [" + identifier + "]. Value collided: [" + identity + "]");}}}}else{this._features['dojo.data.api.Identity'] = Number;}// Step 5: Walk through all the items, and set each item's properties// for _storeRefPropName and _itemNumPropName, so that store.isItem() will return true.for(i = 0; i < this._arrayOfAllItems.length; ++i){item = this._arrayOfAllItems[i];item[this._storeRefPropName] = this;item[this._itemNumPropName] = i;}// Step 6: We walk through all the attribute values of all the items,// looking for type/value literals and item-references.//// We replace item-references with pointers to items. For example, we change:// { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] }// into this:// { name:['Kermit'], friends:[miss_piggy] }// (where miss_piggy is the object representing the 'Miss Piggy' item).//// We replace type/value pairs with typed-literals. For example, we change:// { name:['Nelson Mandela'], born:[{_type:'Date', _value:'July 18, 1918'}] }// into this:// { name:['Kermit'], born:(new Date('July 18, 1918')) }//// We also generate the associate map for all items for the O(1) isItem function.for(i = 0; i < this._arrayOfAllItems.length; ++i){item = this._arrayOfAllItems[i]; // example: { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] }for(key in item){arrayOfValues = item[key]; // example: [{_reference:{name:'Miss Piggy'}}]for(var j = 0; j < arrayOfValues.length; ++j) {value = arrayOfValues[j]; // example: {_reference:{name:'Miss Piggy'}}if(value !== null && typeof value == "object"){if(value._type && value._value){var type = value._type; // examples: 'Date', 'Color', or 'ComplexNumber'var mappingObj = this._datatypeMap[type]; // examples: Date, dojo.Color, foo.math.ComplexNumber, {type: dojo.Color, deserialize(value){ return new dojo.Color(value)}}if(!mappingObj){throw new Error("dojo.data.ItemFileReadStore: in the typeMap constructor arg, no object class was specified for the datatype '" + type + "'");}else if(dojo.isFunction(mappingObj)){arrayOfValues[j] = new mappingObj(value._value);}else if(dojo.isFunction(mappingObj.deserialize)){arrayOfValues[j] = mappingObj.deserialize(value._value);}else{throw new Error("dojo.data.ItemFileReadStore: Value provided in typeMap was neither a constructor, nor a an object with a deserialize function");}}if(value._reference){var referenceDescription = value._reference; // example: {name:'Miss Piggy'}if(dojo.isString(referenceDescription)){// example: 'Miss Piggy'// from an item like: { name:['Kermit'], friends:[{_reference:'Miss Piggy'}]}arrayOfValues[j] = this._itemsByIdentity[referenceDescription];}else{// example: {name:'Miss Piggy'}// from an item like: { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] }for(var k = 0; k < this._arrayOfAllItems.length; ++k){var candidateItem = this._arrayOfAllItems[k];var found = true;for(var refKey in referenceDescription){if(candidateItem[refKey] != referenceDescription[refKey]){found = false;}}if(found){arrayOfValues[j] = candidateItem;}}}}}}}}},getIdentity: function(/* item */ item){// summary:// See dojo.data.api.Identity.getIdentity()var identifier = this._features['dojo.data.api.Identity'];if(identifier === Number){return item[this._itemNumPropName]; // Number}else{var arrayOfValues = item[identifier];if(arrayOfValues){return arrayOfValues[0]; // Object || String}}return null; // null},fetchItemByIdentity: function(/* Object */ keywordArgs){// summary:// See dojo.data.api.Identity.fetchItemByIdentity()// Hasn't loaded yet, we have to trigger the load.if(!this._loadFinished){var self = this;if(this._jsonFileUrl){if(this._loadInProgress){this._queuedFetches.push({args: keywordArgs});}else{this._loadInProgress = true;var getArgs = {url: self._jsonFileUrl,handleAs: "json-comment-optional"};var getHandler = dojo.xhrGet(getArgs);getHandler.addCallback(function(data){var scope = keywordArgs.scope?keywordArgs.scope:dojo.global;try{self._getItemsFromLoadedData(data);self._loadFinished = true;self._loadInProgress = false;var item = self._getItemByIdentity(keywordArgs.identity);if(keywordArgs.onItem){keywordArgs.onItem.call(scope, item);}self._handleQueuedFetches();}catch(error){self._loadInProgress = false;if(keywordArgs.onError){keywordArgs.onError.call(scope, error);}}});getHandler.addErrback(function(error){self._loadInProgress = false;if(keywordArgs.onError){var scope = keywordArgs.scope?keywordArgs.scope:dojo.global;keywordArgs.onError.call(scope, error);}});}}else if(this._jsonData){// Passed in data, no need to xhr.self._getItemsFromLoadedData(self._jsonData);self._jsonData = null;self._loadFinished = true;var item = self._getItemByIdentity(keywordArgs.identity);if(keywordArgs.onItem){var scope = keywordArgs.scope?keywordArgs.scope:dojo.global;keywordArgs.onItem.call(scope, item);}}}else{// Already loaded. We can just look it up and call back.var item = this._getItemByIdentity(keywordArgs.identity);if(keywordArgs.onItem){var scope = keywordArgs.scope?keywordArgs.scope:dojo.global;keywordArgs.onItem.call(scope, item);}}},_getItemByIdentity: function(/* Object */ identity){// summary:// Internal function to look an item up by its identity map.var item = null;if(this._itemsByIdentity){item = this._itemsByIdentity[identity];}else{item = this._arrayOfAllItems[identity];}if(item === undefined){item = null;}return item; // Object},getIdentityAttributes: function(/* item */ item){// summary:// See dojo.data.api.Identity.getIdentifierAttributes()var identifier = this._features['dojo.data.api.Identity'];if(identifier === Number){// If (identifier === Number) it means getIdentity() just returns// an integer item-number for each item. The dojo.data.api.Identity// spec says we need to return null if the identity is not composed// of attributesreturn null; // null}else{return [identifier]; // Array}},_forceLoad: function(){// summary:// Internal function to force a load of the store if it hasn't occurred yet. This is required// for specific functions to work properly.var self = this;if(this._jsonFileUrl){var getArgs = {url: self._jsonFileUrl,handleAs: "json-comment-optional",sync: true};var getHandler = dojo.xhrGet(getArgs);getHandler.addCallback(function(data){try{//Check to be sure there wasn't another load going on concurrently//So we don't clobber data that comes in on it. If there is a load going on//then do not save this data. It will potentially clobber current data.//We mainly wanted to sync/wait here.//TODO: Revisit the loading scheme of this store to improve multi-initial//request handling.if (self._loadInProgress !== true && !self._loadFinished) {self._getItemsFromLoadedData(data);self._loadFinished = true;}}catch(e){console.log(e);throw e;}});getHandler.addErrback(function(error){throw error;});}else if(this._jsonData){self._getItemsFromLoadedData(self._jsonData);self._jsonData = null;self._loadFinished = true;}}});//Mix in the simple fetch implementation to this class.dojo.extend(dojo.data.ItemFileReadStore,dojo.data.util.simpleFetch);}if(!dojo._hasResource["dijit.form.ValidationTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.form.ValidationTextBox"] = true;dojo.provide("dijit.form.ValidationTextBox");dojo.declare("dijit.form.ValidationTextBox",dijit.form.TextBox,{// summary:// A subclass of TextBox.// Over-ride isValid in subclasses to perform specific kinds of validation.templateString:"<table style=\"display: -moz-inline-stack;\" class=\"dijit dijitReset dijitInlineTable\" cellspacing=\"0\" cellpadding=\"0\"\n\tid=\"widget_${id}\" name=\"${name}\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse\" waiRole=\"presentation\"\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset dijitInputField\" width=\"100%\"\n\t\t\t><input dojoAttachPoint='textbox,focusNode' dojoAttachEvent='onfocus,onblur:_onMouse,onkeyup,onkeypress:_onKeyPress' autocomplete=\"off\"\n\t\t\ttype='${type}' name='${name}'\n\t\t/></td\n\t\t><td class=\"dijitReset dijitValidationIconField\" width=\"0%\"\n\t\t\t><div dojoAttachPoint='iconNode' class='dijitValidationIcon'></div><div class='dijitValidationIconText'>Χ</div\n\t\t></td\n\t></tr\n></table>\n",baseClass: "dijitTextBox",// default values for new subclass properties// required: Boolean// Can be true or false, default is false.required: false,// promptMessage: String// Hint stringpromptMessage: "",// invalidMessage: String// The message to display if value is invalid.invalidMessage: "$_unset_$", // read from the message file if not overridden// constraints: Object// user-defined object needed to pass parameters to the validator functionsconstraints: {},// regExp: String// regular expression string used to validate the input// Do not specify both regExp and regExpGenregExp: ".*",// regExpGen: Function// user replaceable function used to generate regExp when dependent on constraints// Do not specify both regExp and regExpGenregExpGen: function(constraints){ return this.regExp; },// state: String// Shows current state (ie, validation result) of input (Normal, Warning, or Error)state: "",setValue: function(){this.inherited('setValue', arguments);this.validate(false);},validator: function(value,constraints){// summary: user replaceable function used to validate the text input against the regular expression.return (new RegExp("^(" + this.regExpGen(constraints) + ")"+(this.required?"":"?")+"$")).test(value) &&(!this.required || !this._isEmpty(value)) &&(this._isEmpty(value) || this.parse(value, constraints) !== null);},isValid: function(/* Boolean*/ isFocused){// summary: Need to over-ride with your own validation code in subclassesreturn this.validator(this.textbox.value, this.constraints);},_isEmpty: function(value){// summary: Checks for whitespacereturn /^\s*$/.test(value); // Boolean},getErrorMessage: function(/* Boolean*/ isFocused){// summary: return an error message to show if appropriatereturn this.invalidMessage;},getPromptMessage: function(/* Boolean*/ isFocused){// summary: return a hint to show if appropriatereturn this.promptMessage;},validate: function(/* Boolean*/ isFocused){// summary:// Called by oninit, onblur, and onkeypress.// description:// Show missing or invalid messages if appropriate, and highlight textbox field.var message = "";var isValid = this.isValid(isFocused);var isEmpty = this._isEmpty(this.textbox.value);this.state = (isValid || (!this._hasBeenBlurred && isEmpty)) ? "" : "Error";this._setStateClass();dijit.setWaiState(this.focusNode, "invalid", (isValid? "false" : "true"));if(isFocused){if(isEmpty){message = this.getPromptMessage(true);}if(!message && !isValid){message = this.getErrorMessage(true);}}this._displayMessage(message);},// currently displayed message_message: "",_displayMessage: function(/*String*/ message){if(this._message == message){ return; }this._message = message;this.displayMessage(message);},displayMessage: function(/*String*/ message){// summary:// User overridable method to display validation errors/hints.// By default uses a tooltip.if(message){dijit.showTooltip(message, this.domNode);}else{dijit.hideTooltip(this.domNode);}},_hasBeenBlurred: false,_onBlur: function(evt){this._hasBeenBlurred = true;this.validate(false);this.inherited('_onBlur', arguments);},onfocus: function(evt){// TODO: change to _onFocus?this.validate(true);this._onMouse(evt); // update CSS classes},onkeyup: function(evt){this.onfocus(evt);},//////////// INITIALIZATION METHODS ///////////////////////////////////////constructor: function(){this.constraints = {};},postMixInProperties: function(){this.inherited('postMixInProperties', arguments);this.constraints.locale=this.lang;this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);if(this.invalidMessage == "$_unset_$"){ this.invalidMessage = this.messages.invalidMessage; }var p = this.regExpGen(this.constraints);this.regExp = p;// make value a string for all types so that form reset works well}});dojo.declare("dijit.form.MappedTextBox",dijit.form.ValidationTextBox,{// summary:// A subclass of ValidationTextBox.// Provides a hidden input field and a serialize method to overrideserialize: function(val, /*Object?*/options){// summary: user replaceable function used to convert the getValue() result to a Stringreturn (val.toString ? val.toString() : "");},toString: function(){// summary: display the widget as a printable string using the widget's valuevar val = this.filter(this.getValue());return (val!=null) ? ((typeof val == "string") ? val : this.serialize(val, this.constraints)) : "";},validate: function(){this.valueNode.value = this.toString();this.inherited('validate', arguments);},postCreate: function(){var textbox = this.textbox;var valueNode = (this.valueNode = document.createElement("input"));valueNode.setAttribute("type", textbox.type);valueNode.setAttribute("value", this.toString());dojo.style(valueNode, "display", "none");valueNode.name = this.textbox.name;this.textbox.name = "_" + this.textbox.name + "_displayed_";this.textbox.removeAttribute("name");dojo.place(valueNode, textbox, "after");this.inherited('postCreate', arguments);}});dojo.declare("dijit.form.RangeBoundTextBox",dijit.form.MappedTextBox,{// summary:// A subclass of MappedTextBox.// Tests for a value out-of-range/*===== contraints object:// min: Number// Minimum signed value. Default is -Infinitymin: undefined,// max: Number// Maximum signed value. Default is +Infinitymax: undefined,=====*/// rangeMessage: String// The message to display if value is out-of-rangerangeMessage: "",compare: function(val1, val2){// summary: compare 2 valuesreturn val1 - val2;},rangeCheck: function(/* Number */ primitive, /* Object */ constraints){// summary: user replaceable function used to validate the range of the numeric input valuevar isMin = (typeof constraints.min != "undefined");var isMax = (typeof constraints.max != "undefined");if(isMin || isMax){return (!isMin || this.compare(primitive,constraints.min) >= 0) &&(!isMax || this.compare(primitive,constraints.max) <= 0);}else{ return true; }},isInRange: function(/* Boolean*/ isFocused){// summary: Need to over-ride with your own validation code in subclassesreturn this.rangeCheck(this.getValue(), this.constraints);},isValid: function(/* Boolean*/ isFocused){return this.inherited('isValid', arguments) &&((this._isEmpty(this.textbox.value) && !this.required) || this.isInRange(isFocused));},getErrorMessage: function(/* Boolean*/ isFocused){if(dijit.form.RangeBoundTextBox.superclass.isValid.call(this, false) && !this.isInRange(isFocused)){ return this.rangeMessage; }else{ return this.inherited('getErrorMessage', arguments); }},postMixInProperties: function(){this.inherited('postMixInProperties', arguments);if(!this.rangeMessage){this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);this.rangeMessage = this.messages.rangeMessage;}},postCreate: function(){this.inherited('postCreate', arguments);if(typeof this.constraints.min != "undefined"){dijit.setWaiState(this.focusNode, "valuemin", this.constraints.min);}if(typeof this.constraints.max != "undefined"){dijit.setWaiState(this.focusNode, "valuemax", this.constraints.max);}}});}if(!dojo._hasResource["dijit.form.ComboBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.form.ComboBox"] = true;dojo.provide("dijit.form.ComboBox");dojo.declare("dijit.form.ComboBoxMixin",null,{// summary:// Auto-completing text box, and base class for FilteringSelect widget.//// The drop down box's values are populated from an class called// a data provider, which returns a list of values based on the characters// that the user has typed into the input box.//// Some of the options to the ComboBox are actually arguments to the data// provider.//// You can assume that all the form widgets (and thus anything that mixes// in ComboBoxMixin) will inherit from _FormWidget and thus the "this"// reference will also "be a" _FormWidget.// item: Object// This is the item returned by the dojo.data.store implementation that// provides the data for this cobobox, it's the currently selected item.item: null,// pageSize: Integer// Argument to data provider.// Specifies number of search results per page (before hitting "next" button)pageSize: Infinity,// store: Object// Reference to data provider object used by this ComboBoxstore: null,// query: Object// A query that can be passed to 'store' to initially filter the items,// before doing further filtering based on searchAttr and the key.query: {},// autoComplete: Boolean// If you type in a partial string, and then tab out of the <input> box,// automatically copy the first entry displayed in the drop down list to// the <input> fieldautoComplete: true,// searchDelay: Integer// Delay in milliseconds between when user types something and we start// searching based on that valuesearchDelay: 100,// searchAttr: String// Searches pattern match against this fieldsearchAttr: "name",// ignoreCase: Boolean// Set true if the ComboBox should ignore case when matching possible itemsignoreCase: true,// hasDownArrow: Boolean// Set this textbox to have a down arrow button.// Defaults to true.hasDownArrow:true,// _hasFocus: Boolean// Represents focus state of the textbox// TODO: get rid of this; it's unnecessary (but currently referenced in FilteringSelect)_hasFocus:false,templateString:"<table class=\"dijit dijitReset dijitInlineTable dijitLeft\" cellspacing=\"0\" cellpadding=\"0\"\n\tid=\"widget_${id}\" name=\"${name}\" dojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse\" waiRole=\"presentation\"\n\t><tr class=\"dijitReset\"\n\t\t><td class='dijitReset dijitStretch dijitInputField' width=\"100%\"\n\t\t\t><input type=\"text\" autocomplete=\"off\" name=\"${name}\"\n\t\t\tdojoAttachEvent=\"onkeypress, onkeyup, onfocus, compositionend\"\n\t\t\tdojoAttachPoint=\"textbox,focusNode\" waiRole=\"combobox\"\n\t\t/></td\n\t\t><td class=\"dijitReset dijitValidationIconField\" width=\"0%\"\n\t\t\t><div dojoAttachPoint='iconNode' class='dijitValidationIcon'></div\n\t\t\t><div class='dijitValidationIconText'>Χ</div\n\t\t></td\n\t\t><td class='dijitReset dijitRight dijitButtonNode dijitDownArrowButton' width=\"0%\"\n\t\t\tdojoAttachPoint=\"downArrowNode\"\n\t\t\tdojoAttachEvent=\"onmousedown:_onArrowMouseDown,onmouseup:_onMouse,onmouseenter:_onMouse,onmouseleave:_onMouse\"\n\t\t\t><div class=\"dijitDownArrowButtonInner\" waiRole=\"presentation\"\n\t\t\t\t><div class=\"dijitDownArrowButtonChar\">▼</div\n\t\t\t></div\n\t\t></td\t\n\t></tr\n></table>\n",baseClass:"dijitComboBox",_lastDisplayedValue: "",getValue:function(){// don't get the textbox value but rather the previously set hidden valuereturn dijit.form.TextBox.superclass.getValue.apply(this, arguments);},setDisplayedValue:function(/*String*/ value){this._lastDisplayedValue = value;this.setValue(value, true);},_getCaretPos: function(/*DomNode*/ element){// khtml 3.5.2 has selection* methods as does webkit nightlies from 2005-06-22if(typeof(element.selectionStart)=="number"){// FIXME: this is totally borked on Moz < 1.3. Any recourse?return element.selectionStart;}else if(dojo.isIE){// in the case of a mouse click in a popup being handled,// then the document.selection is not the textarea, but the popup// var r = document.selection.createRange();// hack to get IE 6 to play nice. What a POS browser.var tr = document.selection.createRange().duplicate();var ntr = element.createTextRange();tr.move("character",0);ntr.move("character",0);try{// If control doesnt have focus, you get an exception.// Seems to happen on reverse-tab, but can also happen on tab (seems to be a race condition - only happens sometimes).// There appears to be no workaround for this - googled for quite a while.ntr.setEndPoint("EndToEnd", tr);return String(ntr.text).replace(/\r/g,"").length;}catch(e){return 0; // If focus has shifted, 0 is fine for caret pos.}}},_setCaretPos: function(/*DomNode*/ element, /*Number*/ location){location = parseInt(location);this._setSelectedRange(element, location, location);},_setSelectedRange: function(/*DomNode*/ element, /*Number*/ start, /*Number*/ end){if(!end){end = element.value.length;} // NOTE: Strange - should be able to put caret at start of text?// Mozilla// parts borrowed from http://www.faqts.com/knowledge_base/view.phtml/aid/13562/fid/130if(element.setSelectionRange){dijit.focus(element);element.setSelectionRange(start, end);}else if(element.createTextRange){ // IEvar range = element.createTextRange();with(range){collapse(true);moveEnd('character', end);moveStart('character', start);select();}}else{ //otherwise try the event-creation hack (our own invention)// do we need these?element.value = element.value;element.blur();dijit.focus(element);// figure out how far back to govar dist = parseInt(element.value.length)-end;var tchar = String.fromCharCode(37);var tcc = tchar.charCodeAt(0);for(var x = 0; x < dist; x++){var te = document.createEvent("KeyEvents");te.initKeyEvent("keypress", true, true, null, false, false, false, false, tcc, tcc);element.dispatchEvent(te);}}},onkeypress: function(/*Event*/ evt){// summary: handles keyboard events//except for pasting case - ctrl + v(118)if(evt.altKey || (evt.ctrlKey && evt.charCode != 118)){return;}var doSearch = false;this.item = null; // #4872if(this._isShowingNow){this._popupWidget.handleKey(evt);}switch(evt.keyCode){case dojo.keys.PAGE_DOWN:case dojo.keys.DOWN_ARROW:if(!this._isShowingNow||this._prev_key_esc){this._arrowPressed();doSearch=true;}else{this._announceOption(this._popupWidget.getHighlightedOption());}dojo.stopEvent(evt);this._prev_key_backspace = false;this._prev_key_esc = false;break;case dojo.keys.PAGE_UP:case dojo.keys.UP_ARROW:if(this._isShowingNow){this._announceOption(this._popupWidget.getHighlightedOption());}dojo.stopEvent(evt);this._prev_key_backspace = false;this._prev_key_esc = false;break;case dojo.keys.ENTER:// prevent submitting form if user presses enter// also prevent accepting the value if either Next or Previous are selectedvar highlighted;if(this._isShowingNow&&(highlighted=this._popupWidget.getHighlightedOption())){// only stop event on prev/nextif(highlighted==this._popupWidget.nextButton){this._nextSearch(1);dojo.stopEvent(evt);break;}else if(highlighted==this._popupWidget.previousButton){this._nextSearch(-1);dojo.stopEvent(evt);break;}}else{this.setDisplayedValue(this.getDisplayedValue());}// default case:// prevent submit, but allow event to bubbleevt.preventDefault();// fall throughcase dojo.keys.TAB:var newvalue=this.getDisplayedValue();// #4617: if the user had More Choices selected fall into the _onBlur handlerif(this._popupWidget &&(newvalue == this._popupWidget._messages["previousMessage"] ||newvalue == this._popupWidget._messages["nextMessage"])){break;}if(this._isShowingNow){this._prev_key_backspace = false;this._prev_key_esc = false;if(this._popupWidget.getHighlightedOption()){this._popupWidget.setValue({target:this._popupWidget.getHighlightedOption()}, true);}this._hideResultList();}break;case dojo.keys.SPACE:this._prev_key_backspace = false;this._prev_key_esc = false;if(this._isShowingNow && this._popupWidget.getHighlightedOption()){dojo.stopEvent(evt);this._selectOption();this._hideResultList();}else{doSearch = true;}break;case dojo.keys.ESCAPE:this._prev_key_backspace = false;this._prev_key_esc = true;this._hideResultList();if(this._lastDisplayedValue != this.getDisplayedValue()){this.setDisplayedValue(this._lastDisplayedValue);dojo.stopEvent(evt);}else{this.setValue(this.getValue(), false);}break;case dojo.keys.DELETE:case dojo.keys.BACKSPACE:this._prev_key_esc = false;this._prev_key_backspace = true;doSearch = true;break;case dojo.keys.RIGHT_ARROW: // fall throughcase dojo.keys.LEFT_ARROW: // fall throughthis._prev_key_backspace = false;this._prev_key_esc = false;break;default:// non char keys (F1-F12 etc..) shouldn't open listthis._prev_key_backspace = false;this._prev_key_esc = false;if(dojo.isIE || evt.charCode != 0){doSearch=true;}}if(this.searchTimer){clearTimeout(this.searchTimer);}if(doSearch){// need to wait a tad before start search so that the event bubbles through DOM and we have value visiblethis.searchTimer = setTimeout(dojo.hitch(this, this._startSearchFromInput), this.searchDelay);}},_autoCompleteText: function(/*String*/ text){// summary:// Fill in the textbox with the first item from the drop down list, and// highlight the characters that were auto-completed. For example, if user// typed "CA" and the drop down list appeared, the textbox would be changed to// "California" and "ifornia" would be highlighted.// IE7: clear selection so next highlight works all the timethis._setSelectedRange(this.focusNode, this.focusNode.value.length, this.focusNode.value.length);// does text autoComplete the value in the textbox?// #3744: escape regexp so the user's input isn't treated as a regular expression.// Example: If the user typed "(" then the regexp would throw "unterminated parenthetical."// Also see #2558 for the autocompletion bug this regular expression fixes.if(new RegExp("^"+escape(this.focusNode.value), this.ignoreCase ? "i" : "").test(escape(text))){var cpos = this._getCaretPos(this.focusNode);// only try to extend if we added the last character at the end of the inputif((cpos+1) > this.focusNode.value.length){// only add to input node as we would overwrite Capitalisation of chars// actually, that is okthis.focusNode.value = text;//.substr(cpos);// visually highlight the autocompleted charactersthis._setSelectedRange(this.focusNode, cpos, this.focusNode.value.length);dijit.setWaiState(this.focusNode, "valuenow", text);}}else{// text does not autoComplete; replace the whole value and highlightthis.focusNode.value = text;this._setSelectedRange(this.focusNode, 0, this.focusNode.value.length);dijit.setWaiState(this.focusNode, "valuenow", text);}},_openResultList: function(/*Object*/ results, /*Object*/ dataObject){if(this.disabled || dataObject.query[this.searchAttr] != this._lastQuery){return;}this._popupWidget.clearResultList();if(!results.length){this._hideResultList();return;}// Fill in the textbox with the first item from the drop down list, and// highlight the characters that were auto-completed. For example, if user// typed "CA" and the drop down list appeared, the textbox would be changed to// "California" and "ifornia" would be highlighted.var zerothvalue=new String(this.store.getValue(results[0], this.searchAttr));if(zerothvalue && this.autoComplete && !this._prev_key_backspace &&// when the user clicks the arrow button to show the full list,// startSearch looks for "*".// it does not make sense to autocomplete// if they are just previewing the options available.(dataObject.query[this.searchAttr] != "*")){this._autoCompleteText(zerothvalue);// announce the autocompleted valuedijit.setWaiState(this.focusNode || this.domNode, "valuenow", zerothvalue);}this._popupWidget.createOptions(results, dataObject, dojo.hitch(this, this._getMenuLabelFromItem));// show our list (only if we have content, else nothing)this._showResultList();// #4091: tell the screen reader that the paging callback finished by shouting the next choiceif(dataObject.direction){if(dataObject.direction==1){this._popupWidget.highlightFirstOption();}else if(dataObject.direction==-1){this._popupWidget.highlightLastOption();}this._announceOption(this._popupWidget.getHighlightedOption());}},_showResultList: function(){this._hideResultList();var items = this._popupWidget.getItems(),visibleCount = Math.min(items.length,this.maxListLength);this._arrowPressed();// hide the tooltipthis._displayMessage("");// Position the list and if it's too big to fit on the screen then// size it to the maximum possible height// Our dear friend IE doesnt take max-height so we need to calculate that on our own every time// TODO: want to redo this, see http://trac.dojotoolkit.org/ticket/3272, http://trac.dojotoolkit.org/ticket/4108with(this._popupWidget.domNode.style){// natural size of the list has changed, so erase old width/height settings,// which were hardcoded in a previous call to this function (via dojo.marginBox() call)width="";height="";}var best=this.open();// #3212: only set auto scroll bars if necessary// prevents issues with scroll bars appearing when they shouldn't when node is made wider (fractional pixels cause this)var popupbox=dojo.marginBox(this._popupWidget.domNode);this._popupWidget.domNode.style.overflow=((best.h==popupbox.h)&&(best.w==popupbox.w))?"hidden":"auto";// #4134: borrow TextArea scrollbar test so content isn't covered by scrollbar and horizontal scrollbar doesn't appearvar newwidth=best.w;if(best.h<this._popupWidget.domNode.scrollHeight){newwidth+=16;}dojo.marginBox(this._popupWidget.domNode, {h:best.h,w:Math.max(newwidth,this.domNode.offsetWidth)});},_hideResultList: function(){if(this._isShowingNow){dijit.popup.close(this._popupWidget);this._arrowIdle();this._isShowingNow=false;}},_onBlur: function(){// summary: called magically when focus has shifted away from this widget and it's dropdownthis._hasFocus=false;this._hasBeenBlurred = true;this._hideResultList();this._arrowIdle();// if the user clicks away from the textbox OR tabs away, set the value to the textbox value// #4617: if value is now more choices or previous choices, revert the valuevar newvalue=this.getDisplayedValue();if(this._popupWidget&&(newvalue==this._popupWidget._messages["previousMessage"]||newvalue==this._popupWidget._messages["nextMessage"])){this.setValue(this._lastValueReported, true);}else{this.setDisplayedValue(newvalue);}},onfocus:function(/*Event*/ evt){this._hasFocus=true;// update styling to reflect that we are focusedthis._onMouse(evt);},_announceOption: function(/*Node*/ node){// summary:// a11y code that puts the highlighted option in the textbox// This way screen readers will know what is happening in the menuif(node==null){return;}// pull the text value from the item attached to the DOM nodevar newValue;if(node==this._popupWidget.nextButton||node==this._popupWidget.previousButton){newValue=node.innerHTML;}else{newValue=this.store.getValue(node.item, this.searchAttr);}// get the text that the user manually entered (cut off autocompleted text)this.focusNode.value=this.focusNode.value.substring(0, this._getCaretPos(this.focusNode));// autocomplete the rest of the option to announce changethis._autoCompleteText(newValue);},_selectOption: function(/*Event*/ evt){var tgt = null;if(!evt){evt ={ target: this._popupWidget.getHighlightedOption()};}// what if nothing is highlighted yet?if(!evt.target){// handle autocompletion where the the user has hit ENTER or TABthis.setDisplayedValue(this.getDisplayedValue());return;// otherwise the user has accepted the autocompleted value}else{tgt = evt.target;}if(!evt.noHide){this._hideResultList();this._setCaretPos(this.focusNode, this.store.getValue(tgt.item, this.searchAttr).length);}this._doSelect(tgt);},_doSelect: function(tgt){this.item = tgt.item;this.setValue(this.store.getValue(tgt.item, this.searchAttr), true);},_onArrowMouseDown: function(evt){// summary: callback when arrow is clickedif(this.disabled){return;}dojo.stopEvent(evt);this.focus();if(this._isShowingNow){this._hideResultList();}else{// forces full population of results, if they click// on the arrow it means they want to see more optionsthis._startSearch("");}},_startSearchFromInput: function(){this._startSearch(this.focusNode.value);},_startSearch: function(/*String*/ key){if(!this._popupWidget){this._popupWidget = new dijit.form._ComboBoxMenu({onChange: dojo.hitch(this, this._selectOption)});}// create a new query to prevent accidentally querying for a hidden value from FilteringSelect's keyFieldvar query=this.query;this._lastQuery=query[this.searchAttr]=key+"*";var dataObject=this.store.fetch({queryOptions:{ignoreCase:this.ignoreCase, deep:true}, query: query, onComplete:dojo.hitch(this, "_openResultList"), start:0, count:this.pageSize});function nextSearch(dataObject, direction){dataObject.start+=dataObject.count*direction;// #4091: tell callback the direction of the paging so the screen reader knows which menu option to shoutdataObject.direction=direction;dataObject.store.fetch(dataObject);}this._nextSearch=this._popupWidget.onPage=dojo.hitch(this, nextSearch, dataObject);},_getValueField:function(){return this.searchAttr;},/////////////// Event handlers /////////////////////_arrowPressed: function(){if(!this.disabled&&this.hasDownArrow){dojo.addClass(this.downArrowNode, "dijitArrowButtonActive");}},_arrowIdle: function(){if(!this.disabled&&this.hasDownArrow){dojo.removeClass(this.downArrowNode, "dojoArrowButtonPushed");}},compositionend: function(/*Event*/ evt){// summary: When inputting characters using an input method, such as Asian// languages, it will generate this event instead of onKeyDown event// Note: this event is only triggered in FF (not in IE)this.onkeypress({charCode:-1});},//////////// INITIALIZATION METHODS ///////////////////////////////////////constructor: function(){this.query={};},postMixInProperties: function(){if(!this.hasDownArrow){this.baseClass = "dijitTextBox";}if(!this.store){// if user didn't specify store, then assume there are option tagsvar items = this.srcNodeRef ? dojo.query("> option", this.srcNodeRef).map(function(node){node.style.display="none";return { value: node.getAttribute("value"), name: String(node.innerHTML) };}) : {};this.store = new dojo.data.ItemFileReadStore({data: {identifier:this._getValueField(), items:items}});// if there is no value set and there is an option list,// set the value to the first value to be consistent with native Selectif(items && items.length && !this.value){// For <select>, IE does not let you set the value attribute of the srcNodeRef (and thus dojo.mixin does not copy it).// IE does understand selectedIndex though, which is automatically set by the selected attribute of an option tagthis.value = items[this.srcNodeRef.selectedIndex != -1 ? this.srcNodeRef.selectedIndex : 0][this._getValueField()];}}},uninitialize:function(){if(this._popupWidget){this._hideResultList();this._popupWidget.destroy()};},_getMenuLabelFromItem:function(/*Item*/ item){return {html:false, label:this.store.getValue(item, this.searchAttr)};},open:function(){this._isShowingNow=true;return dijit.popup.open({popup: this._popupWidget,around: this.domNode,parent: this});}});dojo.declare("dijit.form._ComboBoxMenu",[dijit._Widget, dijit._Templated],{// summary:// Focus-less div based menu for internal use in ComboBoxtemplateString:"<div class='dijitMenu' dojoAttachEvent='onmousedown,onmouseup,onmouseover,onmouseout' tabIndex='-1' style='overflow:\"auto\";'>"+"<div class='dijitMenuItem dijitMenuPreviousButton' dojoAttachPoint='previousButton'></div>"+"<div class='dijitMenuItem dijitMenuNextButton' dojoAttachPoint='nextButton'></div>"+"</div>",_messages:null,postMixInProperties:function(){this._messages = dojo.i18n.getLocalization("dijit.form", "ComboBox", this.lang);this.inherited("postMixInProperties", arguments);},setValue:function(/*Object*/ value){this.value=value;this.onChange(value);},onChange:function(/*Object*/ value){},onPage:function(/*Number*/ direction){},postCreate:function(){// fill in template with i18n messagesthis.previousButton.innerHTML=this._messages["previousMessage"];this.nextButton.innerHTML=this._messages["nextMessage"];this.inherited("postCreate", arguments);},onClose:function(){this._blurOptionNode();},_createOption:function(/*Object*/ item, labelFunc){// summary: creates an option to appear on the popup menu// subclassed by FilteringSelectvar labelObject=labelFunc(item);var menuitem = document.createElement("div");if(labelObject.html){menuitem.innerHTML=labelObject.label;}else{menuitem.appendChild(document.createTextNode(labelObject.label));}// #3250: in blank options, assign a normal heightif(menuitem.innerHTML==""){menuitem.innerHTML=" "}menuitem.item=item;return menuitem;},createOptions:function(results, dataObject, labelFunc){//this._dataObject=dataObject;//this._dataObject.onComplete=dojo.hitch(comboBox, comboBox._openResultList);// display "Previous . . ." buttonthis.previousButton.style.display=dataObject.start==0?"none":"";// create options using _createOption function defined by parent ComboBox (or FilteringSelect) class// #2309: iterate over cache nondestructivelyvar _this=this;dojo.forEach(results, function(item){var menuitem=_this._createOption(item, labelFunc);menuitem.className = "dijitMenuItem";_this.domNode.insertBefore(menuitem, _this.nextButton);});// display "Next . . ." buttonthis.nextButton.style.display=dataObject.count==results.length?"":"none";},clearResultList:function(){// keep the previous and next buttons of coursewhile(this.domNode.childNodes.length>2){this.domNode.removeChild(this.domNode.childNodes[this.domNode.childNodes.length-2]);}},// these functions are called in showResultListgetItems:function(){return this.domNode.childNodes;},getListLength:function(){return this.domNode.childNodes.length-2;},onmousedown:function(/*Event*/ evt){dojo.stopEvent(evt);},onmouseup:function(/*Event*/ evt){if(evt.target === this.domNode){return;}else if(evt.target==this.previousButton){this.onPage(-1);}else if(evt.target==this.nextButton){this.onPage(1);}else{var tgt=evt.target;// while the clicked node is inside the divwhile(!tgt.item){// recurse to the toptgt=tgt.parentNode;}this.setValue({target:tgt}, true);}},onmouseover:function(/*Event*/ evt){if(evt.target === this.domNode){ return; }var tgt=evt.target;if(!(tgt==this.previousButton||tgt==this.nextButton)){// while the clicked node is inside the divwhile(!tgt.item){// recurse to the toptgt=tgt.parentNode;}}this._focusOptionNode(tgt);},onmouseout:function(/*Event*/ evt){if(evt.target === this.domNode){ return; }this._blurOptionNode();},_focusOptionNode:function(/*DomNode*/ node){// summary:// does the actual highlightif(this._highlighted_option != node){this._blurOptionNode();this._highlighted_option = node;dojo.addClass(this._highlighted_option, "dijitMenuItemHover");}},_blurOptionNode:function(){// summary:// removes highlight on highlighted optionif(this._highlighted_option){dojo.removeClass(this._highlighted_option, "dijitMenuItemHover");this._highlighted_option = null;}},_highlightNextOption:function(){// because each press of a button clears the menu,// the highlighted option sometimes becomes detached from the menu!// test to see if the option has a parent to see if this is the case.if(!this.getHighlightedOption()){this._focusOptionNode(this.domNode.firstChild.style.display=="none"?this.domNode.firstChild.nextSibling:this.domNode.firstChild);}else if(this._highlighted_option.nextSibling&&this._highlighted_option.nextSibling.style.display!="none"){this._focusOptionNode(this._highlighted_option.nextSibling);}// scrollIntoView is called outside of _focusOptionNode because in IE putting it inside causes the menu to scroll up on mouseoverdijit.scrollIntoView(this._highlighted_option);},highlightFirstOption:function(){// highlight the non-Previous choices optionthis._focusOptionNode(this.domNode.firstChild.nextSibling);dijit.scrollIntoView(this._highlighted_option);},highlightLastOption:function(){// highlight the noon-More choices optionthis._focusOptionNode(this.domNode.lastChild.previousSibling);dijit.scrollIntoView(this._highlighted_option);},_highlightPrevOption:function(){// if nothing selected, highlight last option// makes sense if you select Previous and try to keep scrolling up the listif(!this.getHighlightedOption()){this._focusOptionNode(this.domNode.lastChild.style.display=="none"?this.domNode.lastChild.previousSibling:this.domNode.lastChild);}else if(this._highlighted_option.previousSibling&&this._highlighted_option.previousSibling.style.display!="none"){this._focusOptionNode(this._highlighted_option.previousSibling);}dijit.scrollIntoView(this._highlighted_option);},_page:function(/*Boolean*/ up){var scrollamount=0;var oldscroll=this.domNode.scrollTop;var height=parseInt(dojo.getComputedStyle(this.domNode).height);// if no item is highlighted, highlight the first optionif(!this.getHighlightedOption()){this._highlightNextOption();}while(scrollamount<height){if(up){// stop at option 1if(!this.getHighlightedOption().previousSibling||this._highlighted_option.previousSibling.style.display=="none"){break;}this._highlightPrevOption();}else{// stop at last optionif(!this.getHighlightedOption().nextSibling||this._highlighted_option.nextSibling.style.display=="none"){break;}this._highlightNextOption();}// going backwardsvar newscroll=this.domNode.scrollTop;scrollamount+=(newscroll-oldscroll)*(up ? -1:1);oldscroll=newscroll;}},pageUp:function(){this._page(true);},pageDown:function(){this._page(false);},getHighlightedOption:function(){// summary:// Returns the highlighted option.return this._highlighted_option&&this._highlighted_option.parentNode ? this._highlighted_option : null;},handleKey:function(evt){switch(evt.keyCode){case dojo.keys.DOWN_ARROW:this._highlightNextOption();break;case dojo.keys.PAGE_DOWN:this.pageDown();break;case dojo.keys.UP_ARROW:this._highlightPrevOption();break;case dojo.keys.PAGE_UP:this.pageUp();break;}}});dojo.declare("dijit.form.ComboBox",[dijit.form.ValidationTextBox, dijit.form.ComboBoxMixin],{postMixInProperties: function(){dijit.form.ComboBoxMixin.prototype.postMixInProperties.apply(this, arguments);dijit.form.ValidationTextBox.prototype.postMixInProperties.apply(this, arguments);}});}if(!dojo._hasResource["dojo.cldr.monetary"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.cldr.monetary"] = true;dojo.provide("dojo.cldr.monetary");dojo.cldr.monetary.getData = function(code){// summary: A mapping of currency code to currency-specific formatting information. Returns a unique object with properties: places, round.// code: an iso4217 currency code// from http://www.unicode.org/cldr/data/common/supplemental/supplementalData.xml:supplementalData/currencyData/fractionsvar placesData = {ADP:0,BHD:3,BIF:0,BYR:0,CLF:0,CLP:0,DJF:0,ESP:0,GNF:0,IQD:3,ITL:0,JOD:3,JPY:0,KMF:0,KRW:0,KWD:3,LUF:0,LYD:3,MGA:0,MGF:0,OMR:3,PYG:0,RWF:0,TND:3,TRL:0,VUV:0,XAF:0,XOF:0,XPF:0};var roundingData = {CHF:5};var places = placesData[code], round = roundingData[code];if(typeof places == "undefined"){ places = 2; }if(typeof round == "undefined"){ round = 0; }return {places: places, round: round}; // Object};}if(!dojo._hasResource["dojo.currency"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.currency"] = true;dojo.provide("dojo.currency");dojo.currency._mixInDefaults = function(options){options = options || {};options.type = "currency";// Get locale-depenent currency data, like the symbolvar bundle = dojo.i18n.getLocalization("dojo.cldr", "currency", options.locale) || {};// Mixin locale-independent currency data, like # of placesvar iso = options.currency;var data = dojo.cldr.monetary.getData(iso);dojo.forEach(["displayName","symbol","group","decimal"], function(prop){data[prop] = bundle[iso+"_"+prop];});data.fractional = [true, false];// Mixin with provided optionsreturn dojo.mixin(data, options);}dojo.currency.format = function(/*Number*/value, /*Object?*/options){// summary:// Format a Number as a String, using locale-specific settings//// description:// Create a string from a Number using a known localized pattern.// Formatting patterns appropriate to the locale are chosen from the CLDR http://unicode.org/cldr// as well as the appropriate symbols and delimiters. See http://www.unicode.org/reports/tr35/#Number_Elements//// value:// the number to be formatted.//// options: object {currency: String, pattern: String?, places: Number?, round: Number?, symbol: String?, locale: String?}// currency- the ISO4217 currency code, a three letter sequence like "USD"// See http://en.wikipedia.org/wiki/ISO_4217// symbol- override currency symbol. Normally, will be looked up in table of supported currencies, and ISO currency code will// be used if not found. See dojo.i18n.cldr.nls->currency.js// pattern- override formatting pattern with this string (see dojo.number.applyPattern)// places- fixed number of decimal places to show. Default is defined by the currency.// round- 5 rounds to nearest .5; 0 rounds to nearest whole (default). -1 means don't round.// locale- override the locale used to determine formatting rulesreturn dojo.number.format(value, dojo.currency._mixInDefaults(options));}dojo.currency.regexp = function(/*Object?*/options){//// summary:// Builds the regular needed to parse a number//// description:// Returns regular expression with positive and negative match, group and decimal separators//// options: object {pattern: String, locale: String, strict: Boolean, places: mixed}// currency- the ISO4217 currency code, a three letter sequence like "USD"// See http://en.wikipedia.org/wiki/ISO_4217// symbol- override currency symbol. Normally, will be looked up in table of supported currencies, and ISO currency code will// be used if not found. See dojo.i18n.cldr.nls->currency.js// pattern- override pattern with this string// locale- override the locale used to determine formatting rules// strict- strict parsing, false by default// places- number of decimal places to accept. Default is defined by currency.return dojo.number.regexp(dojo.currency._mixInDefaults(options)); // String}dojo.currency.parse = function(/*String*/expression, /*Object?*/options){//// summary:// Convert a properly formatted string to a primitive Number,// using locale-specific settings.//// description:// Create a Number from a string using a known localized pattern.// Formatting patterns are chosen appropriate to the locale.// Formatting patterns are implemented using the syntax described at *URL*//// expression: A string representation of a Number//// options: object {pattern: string, locale: string, strict: boolean}// currency- the ISO4217 currency code, a three letter sequence like "USD"// See http://en.wikipedia.org/wiki/ISO_4217// symbol- override currency symbol. Normally, will be looked up in table of supported currencies, and ISO currency code will// be used if not found. See dojo.i18n.cldr.nls->currency.js// pattern- override pattern with this string// locale- override the locale used to determine formatting rules// strict- strict parsing, false by default// places- number of decimal places to accept. Default is defined by currency.// fractional- where places are implied by pattern or explicit 'places' parameter, whether to include the fractional portion.// By default for currencies, it the fractional portion is optional.return dojo.number.parse(expression, dojo.currency._mixInDefaults(options));}}if(!dojo._hasResource["dijit.form.NumberTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.form.NumberTextBox"] = true;dojo.provide("dijit.form.NumberTextBox");dojo.declare("dijit.form.NumberTextBoxMixin",null,{// summary:// A mixin for all number textboxesregExpGen: dojo.number.regexp,format: function(/*Number*/ value, /*Object*/ constraints){if(isNaN(value)){ return ""; }return dojo.number.format(value, constraints);},parse: dojo.number.parse,filter: function(/*Number*/ value){if(typeof value == "string"){ return this.inherited('filter', arguments); }return (isNaN(value) ? '' : value);},value: NaN});dojo.declare("dijit.form.NumberTextBox",[dijit.form.RangeBoundTextBox,dijit.form.NumberTextBoxMixin],{// summary:// A validating, serializable, range-bound text box.// constraints object: min, max, places});}if(!dojo._hasResource["dijit.form.CurrencyTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.form.CurrencyTextBox"] = true;dojo.provide("dijit.form.CurrencyTextBox");//FIXME: dojo.experimental throws an unreadable exception?//dojo.experimental("dijit.form.CurrencyTextBox");dojo.declare("dijit.form.CurrencyTextBox",dijit.form.NumberTextBox,{// code: String// the ISO4217 currency code, a three letter sequence like "USD"// See http://en.wikipedia.org/wiki/ISO_4217currency: "",regExpGen: dojo.currency.regexp,format: dojo.currency.format,parse: dojo.currency.parse,postMixInProperties: function(){if(this.constraints === dijit.form.ValidationTextBox.prototype.constraints){// declare a constraints property on 'this' so we don't overwrite the shared default object in 'prototype'this.constraints = {};}this.constraints.currency = this.currency;dijit.form.CurrencyTextBox.superclass.postMixInProperties.apply(this, arguments);}});}if(!dojo._hasResource["dojo.cldr.supplemental"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.cldr.supplemental"] = true;dojo.provide("dojo.cldr.supplemental");dojo.cldr.supplemental.getFirstDayOfWeek = function(/*String?*/locale){// summary: Returns a zero-based index for first day of the week// description:// Returns a zero-based index for first day of the week, as used by the local (Gregorian) calendar.// e.g. Sunday (returns 0), or Monday (returns 1)// from http://www.unicode.org/cldr/data/common/supplemental/supplementalData.xml:supplementalData/weekData/firstDayvar firstDay = {/*default is 1=Monday*/mv:5,ae:6,af:6,bh:6,dj:6,dz:6,eg:6,er:6,et:6,iq:6,ir:6,jo:6,ke:6,kw:6,lb:6,ly:6,ma:6,om:6,qa:6,sa:6,sd:6,so:6,tn:6,ye:6,as:0,au:0,az:0,bw:0,ca:0,cn:0,fo:0,ge:0,gl:0,gu:0,hk:0,ie:0,il:0,is:0,jm:0,jp:0,kg:0,kr:0,la:0,mh:0,mo:0,mp:0,mt:0,nz:0,ph:0,pk:0,sg:0,th:0,tt:0,tw:0,um:0,us:0,uz:0,vi:0,za:0,zw:0,et:0,mw:0,ng:0,tj:0,gb:0,sy:4};var country = dojo.cldr.supplemental._region(locale);var dow = firstDay[country];return (typeof dow == 'undefined') ? 1 : dow; /*Number*/};dojo.cldr.supplemental._region = function(/*String?*/locale){locale = dojo.i18n.normalizeLocale(locale);var tags = locale.split('-');var region = tags[1];if(!region){// IE often gives language only (#2269)// Arbitrary mappings of language-only locales to a country:region = {de:"de", en:"us", es:"es", fi:"fi", fr:"fr", hu:"hu", it:"it",ja:"jp", ko:"kr", nl:"nl", pt:"br", sv:"se", zh:"cn"}[tags[0]];}else if(region.length == 4){// The ISO 3166 country code is usually in the second position, unless a// 4-letter script is given. See http://www.ietf.org/rfc/rfc4646.txtregion = tags[2];}return region;}dojo.cldr.supplemental.getWeekend = function(/*String?*/locale){// summary: Returns a hash containing the start and end days of the weekend// description:// Returns a hash containing the start and end days of the weekend according to local custom using locale,// or by default in the user's locale.// e.g. {start:6, end:0}// from http://www.unicode.org/cldr/data/common/supplemental/supplementalData.xml:supplementalData/weekData/weekend{Start,End}var weekendStart = {/*default is 6=Saturday*/eg:5,il:5,sy:5,'in':0,ae:4,bh:4,dz:4,iq:4,jo:4,kw:4,lb:4,ly:4,ma:4,om:4,qa:4,sa:4,sd:4,tn:4,ye:4};var weekendEnd = {/*default is 0=Sunday*/ae:5,bh:5,dz:5,iq:5,jo:5,kw:5,lb:5,ly:5,ma:5,om:5,qa:5,sa:5,sd:5,tn:5,ye:5,af:5,ir:5,eg:6,il:6,sy:6};var country = dojo.cldr.supplemental._region(locale);var start = weekendStart[country];var end = weekendEnd[country];if(typeof start == 'undefined'){start=6;}if(typeof end == 'undefined'){end=0;}return {start:start, end:end}; /*Object {start,end}*/};}if(!dojo._hasResource["dojo.date"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.date"] = true;dojo.provide("dojo.date");dojo.date.getDaysInMonth = function(/*Date*/dateObject){// summary:// Returns the number of days in the month used by dateObjectvar month = dateObject.getMonth();var days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];if(month == 1 && dojo.date.isLeapYear(dateObject)){ return 29; } // Numberreturn days[month]; // Number}dojo.date.isLeapYear = function(/*Date*/dateObject){// summary:// Determines if the year of the dateObject is a leap year// description:// Leap years are years with an additional day YYYY-02-29, where the// year number is a multiple of four with the following exception: If// a year is a multiple of 100, then it is only a leap year if it is// also a multiple of 400. For example, 1900 was not a leap year, but// 2000 is one.var year = dateObject.getFullYear();return !(year%400) || (!(year%4) && !!(year%100)); // Boolean}// FIXME: This is not localizeddojo.date.getTimezoneName = function(/*Date*/dateObject){// summary:// Get the user's time zone as provided by the browser// dateObject:// Needed because the timezone may vary with time (daylight savings)// description:// Try to get time zone info from toString or toLocaleString method of// the Date object -- UTC offset is not a time zone. See// http://www.twinsun.com/tz/tz-link.htm Note: results may be// inconsistent across browsers.var str = dateObject.toString(); // Start looking in toStringvar tz = ''; // The result -- return empty string if nothing foundvar match;// First look for something in parentheses -- fast lookup, no regexvar pos = str.indexOf('(');if(pos > -1){tz = str.substring(++pos, str.indexOf(')'));}else{// If at first you don't succeed ...// If IE knows about the TZ, it appears before the year// Capital letters or slash before a 4-digit year// at the end of stringvar pat = /([A-Z\/]+) \d{4}$/;if((match = str.match(pat))){tz = match[1];}else{// Some browsers (e.g. Safari) glue the TZ on the end// of toLocaleString instead of putting it in toStringstr = dateObject.toLocaleString();// Capital letters or slash -- end of string,// after spacepat = / ([A-Z\/]+)$/;if((match = str.match(pat))){tz = match[1];}}}// Make sure it doesn't somehow end up return AM or PMreturn (tz == 'AM' || tz == 'PM') ? '' : tz; // String}// Utility methods to do arithmetic calculations with Datesdojo.date.compare = function(/*Date*/date1, /*Date?*/date2, /*String?*/portion){// summary:// Compare two date objects by date, time, or both.// description:// Returns 0 if equal, positive if a > b, else negative.// date1:// Date object// date2:// Date object. If not specified, the current Date is used.// portion:// A string indicating the "date" or "time" portion of a Date object.// Compares both "date" and "time" by default. One of the following:// "date", "time", "datetime"// Extra step required in copy for IE - see #3112date1 = new Date(Number(date1));date2 = new Date(Number(date2 || new Date()));if(typeof portion !== "undefined"){if(portion == "date"){// Ignore times and compare dates.date1.setHours(0, 0, 0, 0);date2.setHours(0, 0, 0, 0);}else if(portion == "time"){// Ignore dates and compare times.date1.setFullYear(0, 0, 0);date2.setFullYear(0, 0, 0);}}if(date1 > date2){ return 1; } // intif(date1 < date2){ return -1; } // intreturn 0; // int};dojo.date.add = function(/*Date*/date, /*String*/interval, /*int*/amount){// summary:// Add to a Date in intervals of different size, from milliseconds to years// date: Date// Date object to start with// interval:// A string representing the interval. One of the following:// "year", "month", "day", "hour", "minute", "second",// "millisecond", "quarter", "week", "weekday"// amount:// How much to add to the date.var sum = new Date(Number(date)); // convert to Number before copying to accomodate IE (#3112)var fixOvershoot = false;var property = "Date";switch(interval){case "day":break;case "weekday"://i18n FIXME: assumes Saturday/Sunday weekend, but even this is not standard. There are CLDR entries to localize this.var days, weeks;var adj = 0;// Divide the increment time span into weekspans plus leftover days// e.g., 8 days is one 5-day weekspan / and two leftover days// Can't have zero leftover days, so numbers divisible by 5 get// a days value of 5, and the remaining days make up the number of weeksvar mod = amount % 5;if(!mod){days = (amount > 0) ? 5 : -5;weeks = (amount > 0) ? ((amount-5)/5) : ((amount+5)/5);}else{days = mod;weeks = parseInt(amount/5);}// Get weekday value for orig date paramvar strt = date.getDay();// Orig date is Sat / positive incrementer// Jump over Sunif(strt == 6 && amount > 0){adj = 1;}else if(strt == 0 && amount < 0){// Orig date is Sun / negative incrementer// Jump back over Satadj = -1;}// Get weekday val for the new datevar trgt = strt + days;// New date is on Sat or Sunif(trgt == 0 || trgt == 6){adj = (amount > 0) ? 2 : -2;}// Increment by number of weeks plus leftover days plus// weekend adjustmentsamount = 7 * weeks + days + adj;break;case "year":property = "FullYear";// Keep increment/decrement from 2/29 out of MarchfixOvershoot = true;break;case "week":amount *= 7;break;case "quarter":// Naive quarter is just three monthsamount *= 3;// fallthrough...case "month":// Reset to last day of month if you overshootfixOvershoot = true;property = "Month";break;case "hour":case "minute":case "second":case "millisecond":property = "UTC" + interval.charAt(0).toUpperCase() + interval.substring(1) + "s";}if(property){sum["set"+property](sum["get"+property]()+amount);}if(fixOvershoot && (sum.getDate() < date.getDate())){sum.setDate(0);}return sum; // Date};dojo.date.difference = function(/*Date*/date1, /*Date?*/date2, /*String?*/interval){// summary:// Get the difference in a specific unit of time (e.g., number of// months, weeks, days, etc.) between two dates, rounded to the// nearest integer.// date1:// Date object// date2:// Date object. If not specified, the current Date is used.// interval:// A string representing the interval. One of the following:// "year", "month", "day", "hour", "minute", "second",// "millisecond", "quarter", "week", "weekday"// Defaults to "day".date2 = date2 || new Date();interval = interval || "day";var yearDiff = date2.getFullYear() - date1.getFullYear();var delta = 1; // Integer return valueswitch(interval){case "quarter":var m1 = date1.getMonth();var m2 = date2.getMonth();// Figure out which quarter the months are invar q1 = Math.floor(m1/3) + 1;var q2 = Math.floor(m2/3) + 1;// Add quarters for any year difference between the datesq2 += (yearDiff * 4);delta = q2 - q1;break;case "weekday":var days = Math.round(dojo.date.difference(date1, date2, "day"));var weeks = parseInt(dojo.date.difference(date1, date2, "week"));var mod = days % 7;// Even number of weeksif(mod == 0){days = weeks*5;}else{// Weeks plus spare change (< 7 days)var adj = 0;var aDay = date1.getDay();var bDay = date2.getDay();weeks = parseInt(days/7);mod = days % 7;// Mark the date advanced by the number of// round weeks (may be zero)var dtMark = new Date(date1);dtMark.setDate(dtMark.getDate()+(weeks*7));var dayMark = dtMark.getDay();// Spare change days -- 6 or lessif(days > 0){switch(true){// Range starts on Satcase aDay == 6:adj = -1;break;// Range starts on Suncase aDay == 0:adj = 0;break;// Range ends on Satcase bDay == 6:adj = -1;break;// Range ends on Suncase bDay == 0:adj = -2;break;// Range contains weekendcase (dayMark + mod) > 5:adj = -2;}}else if(days < 0){switch(true){// Range starts on Satcase aDay == 6:adj = 0;break;// Range starts on Suncase aDay == 0:adj = 1;break;// Range ends on Satcase bDay == 6:adj = 2;break;// Range ends on Suncase bDay == 0:adj = 1;break;// Range contains weekendcase (dayMark + mod) < 0:adj = 2;}}days += adj;days -= (weeks*2);}delta = days;break;case "year":delta = yearDiff;break;case "month":delta = (date2.getMonth() - date1.getMonth()) + (yearDiff * 12);break;case "week":// Truncate instead of rounding// Don't use Math.floor -- value may be negativedelta = parseInt(dojo.date.difference(date1, date2, "day")/7);break;case "day":delta /= 24;// fallthroughcase "hour":delta /= 60;// fallthroughcase "minute":delta /= 60;// fallthroughcase "second":delta /= 1000;// fallthroughcase "millisecond":delta *= date2.getTime() - date1.getTime();}// Round for fractional values and DST leapsreturn Math.round(delta); // Number (integer)};}if(!dojo._hasResource["dojo.date.locale"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dojo.date.locale"] = true;dojo.provide("dojo.date.locale");// Localization methods for Date. Honor local customs using locale-dependent dojo.cldr data.// Load the bundles containing localization information for// names and formats//NOTE: Everything in this module assumes Gregorian calendars.// Other calendars will be implemented in separate modules.(function(){// Format a pattern without literalsfunction formatPattern(dateObject, bundle, pattern){return pattern.replace(/([a-z])\1*/ig, function(match){var s;var c = match.charAt(0);var l = match.length;var pad;var widthList = ["abbr", "wide", "narrow"];switch(c){case 'G':s = bundle[(l < 4) ? "eraAbbr" : "eraNames"][dateObject.getFullYear() < 0 ? 0 : 1];break;case 'y':s = dateObject.getFullYear();switch(l){case 1:break;case 2:s = String(s); s = s.substr(s.length - 2);break;default:pad = true;}break;case 'Q':case 'q':s = Math.ceil((dateObject.getMonth()+1)/3);// switch(l){// case 1: case 2:pad = true;// break;// case 3: case 4: // unimplemented// }break;case 'M':case 'L':var m = dateObject.getMonth();var width;switch(l){case 1: case 2:s = m+1; pad = true;break;case 3: case 4: case 5:width = widthList[l-3];break;}if(width){var type = (c == "L") ? "standalone" : "format";var prop = ["months",type,width].join("-");s = bundle[prop][m];}break;case 'w':var firstDay = 0;s = dojo.date.locale._getWeekOfYear(dateObject, firstDay); pad = true;break;case 'd':s = dateObject.getDate(); pad = true;break;case 'D':s = dojo.date.locale._getDayOfYear(dateObject); pad = true;break;case 'E':case 'e':case 'c': // REVIEW: don't see this in the spec?var d = dateObject.getDay();var width;switch(l){case 1: case 2:if(c == 'e'){var first = dojo.cldr.supplemental.getFirstDayOfWeek(options.locale);d = (d-first+7)%7;}if(c != 'c'){s = d+1; pad = true;break;}// else fallthrough...case 3: case 4: case 5:width = widthList[l-3];break;}if(width){var type = (c == "c") ? "standalone" : "format";var prop = ["days",type,width].join("-");s = bundle[prop][d];}break;case 'a':var timePeriod = (dateObject.getHours() < 12) ? 'am' : 'pm';s = bundle[timePeriod];break;case 'h':case 'H':case 'K':case 'k':var h = dateObject.getHours();// strange choices in the date format make it impossible to write this succinctlyswitch (c) {case 'h': // 1-12s = (h % 12) || 12;break;case 'H': // 0-23s = h;break;case 'K': // 0-11s = (h % 12);break;case 'k': // 1-24s = h || 24;break;}pad = true;break;case 'm':s = dateObject.getMinutes(); pad = true;break;case 's':s = dateObject.getSeconds(); pad = true;break;case 'S':s = Math.round(dateObject.getMilliseconds() * Math.pow(10, l-3));break;case 'v': // FIXME: don't know what this is. seems to be same as z?case 'z':// We only have one timezone to offer; the one from the browsers = dojo.date.getTimezoneName(dateObject);if(s){break;}l=4;// fallthrough... use GMT if tz not availablecase 'Z':var offset = dateObject.getTimezoneOffset();var tz = [(offset<=0 ? "+" : "-"),dojo.string.pad(Math.floor(Math.abs(offset)/60), 2),dojo.string.pad(Math.abs(offset)% 60, 2)];if(l==4){tz.splice(0, 0, "GMT");tz.splice(3, 0, ":");}s = tz.join("");break;// case 'Y': case 'u': case 'W': case 'F': case 'g': case 'A':// console.debug(match+" modifier unimplemented");default:throw new Error("dojo.date.locale.format: invalid pattern char: "+pattern);}if(pad){ s = dojo.string.pad(s, l); }return s;});}dojo.date.locale.format = function(/*Date*/dateObject, /*Object?*/options){// summary:// Format a Date object as a String, using locale-specific settings.//// description:// Create a string from a Date object using a known localized pattern.// By default, this method formats both date and time from dateObject.// Formatting patterns are chosen appropriate to the locale. Different// formatting lengths may be chosen, with "full" used by default.// Custom patterns may be used or registered with translations using// the addCustomFormats method.// Formatting patterns are implemented using the syntax described at// http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns//// dateObject:// the date and/or time to be formatted. If a time only is formatted,// the values in the year, month, and day fields are irrelevant. The// opposite is true when formatting only dates.//// options: object {selector: string, formatLength: string, datePattern: string, timePattern: string, locale: string}// selector- choice of 'time','date' (default: date and time)// formatLength- choice of long, short, medium or full (plus any custom additions). Defaults to 'short'// datePattern,timePattern- override pattern with this string// am,pm- override strings for am/pm in times// locale- override the locale used to determine formatting rulesoptions = options || {};var locale = dojo.i18n.normalizeLocale(options.locale);var formatLength = options.formatLength || 'short';var bundle = dojo.date.locale._getGregorianBundle(locale);var str = [];var sauce = dojo.hitch(this, formatPattern, dateObject, bundle);if(options.selector == "year"){// Special case as this is not yet driven by CLDR datavar year = dateObject.getFullYear();if(locale.match(/^zh|^ja/)){year += "\u5E74";}return year;}if(options.selector != "time"){var datePattern = options.datePattern || bundle["dateFormat-"+formatLength];if(datePattern){str.push(_processPattern(datePattern, sauce));}}if(options.selector != "date"){var timePattern = options.timePattern || bundle["timeFormat-"+formatLength];if(timePattern){str.push(_processPattern(timePattern, sauce));}}var result = str.join(" "); //TODO: use locale-specific pattern to assemble date + timereturn result; // String};dojo.date.locale.regexp = function(/*Object?*/options){// summary:// Builds the regular needed to parse a localized date//// options: object {selector: string, formatLength: string, datePattern: string, timePattern: string, locale: string, strict: boolean}// selector- choice of 'time', 'date' (default: date and time)// formatLength- choice of long, short, medium or full (plus any custom additions). Defaults to 'short'// datePattern,timePattern- override pattern with this string// locale- override the locale used to determine formatting rulesreturn dojo.date.locale._parseInfo(options).regexp; // String};dojo.date.locale._parseInfo = function(/*Object?*/options){options = options || {};var locale = dojo.i18n.normalizeLocale(options.locale);var bundle = dojo.date.locale._getGregorianBundle(locale);var formatLength = options.formatLength || 'short';var datePattern = options.datePattern || bundle["dateFormat-" + formatLength];var timePattern = options.timePattern || bundle["timeFormat-" + formatLength];var pattern;if(options.selector == 'date'){pattern = datePattern;}else if(options.selector == 'time'){pattern = timePattern;}else{pattern = datePattern + ' ' + timePattern; //TODO: use locale-specific pattern to assemble date + time}var tokens = [];var re = _processPattern(pattern, dojo.hitch(this, _buildDateTimeRE, tokens, bundle, options));return {regexp: re, tokens: tokens, bundle: bundle};};dojo.date.locale.parse = function(/*String*/value, /*Object?*/options){// summary:// Convert a properly formatted string to a primitive Date object,// using locale-specific settings.//// description:// Create a Date object from a string using a known localized pattern.// By default, this method parses looking for both date and time in the string.// Formatting patterns are chosen appropriate to the locale. Different// formatting lengths may be chosen, with "full" used by default.// Custom patterns may be used or registered with translations using// the addCustomFormats method.// Formatting patterns are implemented using the syntax described at// http://www.unicode.org/reports/tr35/#Date_Format_Patterns//// value:// A string representation of a date//// options: object {selector: string, formatLength: string, datePattern: string, timePattern: string, locale: string, strict: boolean}// selector- choice of 'time', 'date' (default: date and time)// formatLength- choice of long, short, medium or full (plus any custom additions). Defaults to 'short'// datePattern,timePattern- override pattern with this string// am,pm- override strings for am/pm in times// locale- override the locale used to determine formatting rules// strict- strict parsing, off by defaultvar info = dojo.date.locale._parseInfo(options);var tokens = info.tokens, bundle = info.bundle;var re = new RegExp("^" + info.regexp + "$");var match = re.exec(value);if(!match){ return null; } // nullvar widthList = ['abbr', 'wide', 'narrow'];//1972 is a leap year. We want to avoid Feb 29 rolling over into Mar 1,//in the cases where the year is parsed after the month and day.var result = new Date(1972, 0);var expected = {};var amPm = "";dojo.forEach(match, function(v, i){if(!i){return;}var token=tokens[i-1];var l=token.length;switch(token.charAt(0)){case 'y':if(l != 2){//interpret year literally, so '5' would be 5 A.D.result.setFullYear(v);expected.year = v;}else{if(v<100){v = Number(v);//choose century to apply, according to a sliding window//of 80 years before and 20 years after present yearvar year = '' + new Date().getFullYear();var century = year.substring(0, 2) * 100;var yearPart = Number(year.substring(2, 4));var cutoff = Math.min(yearPart + 20, 99);var num = (v < cutoff) ? century + v : century - 100 + v;result.setFullYear(num);expected.year = num;}else{//we expected 2 digits and got more...if(options.strict){return null;}//interpret literally, so '150' would be 150 A.D.//also tolerate '1950', if 'yyyy' input passed to 'yy' formatresult.setFullYear(v);expected.year = v;}}break;case 'M':if(l>2){var months = bundle['months-format-' + widthList[l-3]].concat();if(!options.strict){//Tolerate abbreviating period in month part//Case-insensitive comparisonv = v.replace(".","").toLowerCase();months = dojo.map(months, function(s){ return s.replace(".","").toLowerCase(); } );}v = dojo.indexOf(months, v);if(v == -1){// console.debug("dojo.date.locale.parse: Could not parse month name: '" + v + "'.");return null;}}else{v--;}result.setMonth(v);expected.month = v;break;case 'E':case 'e':var days = bundle['days-format-' + widthList[l-3]].concat();if(!options.strict){//Case-insensitive comparisonv = v.toLowerCase();days = dojo.map(days, "".toLowerCase);}v = dojo.indexOf(days, v);if(v == -1){// console.debug("dojo.date.locale.parse: Could not parse weekday name: '" + v + "'.");return null;}//TODO: not sure what to actually do with this input,//in terms of setting something on the Date obj...?//without more context, can't affect the actual date//TODO: just validate?break;case 'd':result.setDate(v);expected.date = v;break;case 'D'://FIXME: need to defer this until after the year is set for leap-year?result.setMonth(0);result.setDate(v);break;case 'a': //am/pmvar am = options.am || bundle.am;var pm = options.pm || bundle.pm;if(!options.strict){var period = /\./g;v = v.replace(period,'').toLowerCase();am = am.replace(period,'').toLowerCase();pm = pm.replace(period,'').toLowerCase();}if(options.strict && v != am && v != pm){// console.debug("dojo.date.locale.parse: Could not parse am/pm part.");return null;}// we might not have seen the hours field yet, so store the state and apply hour change lateramPm = (v == pm) ? 'p' : (v == am) ? 'a' : '';break;case 'K': //hour (1-24)if(v==24){v=0;}// fallthrough...case 'h': //hour (1-12)case 'H': //hour (0-23)case 'k': //hour (0-11)//TODO: strict bounds checking, paddingif(v > 23){// console.debug("dojo.date.locale.parse: Illegal hours value");return null;}//in the 12-hour case, adjusting for am/pm requires the 'a' part//which could come before or after the hour, so we will adjust laterresult.setHours(v);break;case 'm': //minutesresult.setMinutes(v);break;case 's': //secondsresult.setSeconds(v);break;case 'S': //millisecondsresult.setMilliseconds(v);// break;// case 'w'://TODO var firstDay = 0;// default://TODO: throw?// console.debug("dojo.date.locale.parse: unsupported pattern char=" + token.charAt(0));}});var hours = result.getHours();if(amPm === 'p' && hours < 12){result.setHours(hours + 12); //e.g., 3pm -> 15}else if(amPm === 'a' && hours == 12){result.setHours(0); //12am -> 0}//validate parse date fields versus input date fieldsif(expected.year && result.getFullYear() != expected.year){// console.debug("dojo.date.locale.parse: Parsed year: '" + result.getFullYear() + "' did not match input year: '" + expected.year + "'.");return null;}if(expected.month && result.getMonth() != expected.month){// console.debug("dojo.date.locale.parse: Parsed month: '" + result.getMonth() + "' did not match input month: '" + expected.month + "'.");return null;}if(expected.date && result.getDate() != expected.date){// console.debug("dojo.date.locale.parse: Parsed day of month: '" + result.getDate() + "' did not match input day of month: '" + expected.date + "'.");return null;}//TODO: implement a getWeekday() method in order to test//validity of input strings containing 'EEE' or 'EEEE'...return result; // Date};function _processPattern(pattern, applyPattern, applyLiteral, applyAll){//summary: Process a pattern with literals in it// Break up on single quotes, treat every other one as a literal, except '' which becomes 'var identity = function(x){return x;};applyPattern = applyPattern || identity;applyLiteral = applyLiteral || identity;applyAll = applyAll || identity;//split on single quotes (which escape literals in date format strings)//but preserve escaped single quotes (e.g., o''clock)var chunks = pattern.match(/(''|[^'])+/g);var literal = false;dojo.forEach(chunks, function(chunk, i){if(!chunk){chunks[i]='';}else{chunks[i]=(literal ? applyLiteral : applyPattern)(chunk);literal = !literal;}});return applyAll(chunks.join(''));}function _buildDateTimeRE(tokens, bundle, options, pattern){pattern = dojo.regexp.escapeString(pattern);if(!options.strict){ pattern = pattern.replace(" a", " ?a"); } // kludge to tolerate no space before am/pmreturn pattern.replace(/([a-z])\1*/ig, function(match){// Build a simple regexp. Avoid captures, which would ruin the tokens listvar s;var c = match.charAt(0);var l = match.length;var p2 = '', p3 = '';if(options.strict){if(l > 1){ p2 = '0' + '{'+(l-1)+'}'; }if(l > 2){ p3 = '0' + '{'+(l-2)+'}'; }}else{p2 = '0?'; p3 = '0{0,2}';}switch(c){case 'y':s = '\\d{2,4}';break;case 'M':s = (l>2) ? '\\S+' : p2+'[1-9]|1[0-2]';break;case 'D':s = p2+'[1-9]|'+p3+'[1-9][0-9]|[12][0-9][0-9]|3[0-5][0-9]|36[0-6]';break;case 'd':s = p2+'[1-9]|[12]\\d|3[01]';break;case 'w':s = p2+'[1-9]|[1-4][0-9]|5[0-3]';break;case 'E':s = '\\S+';break;case 'h': //hour (1-12)s = p2+'[1-9]|1[0-2]';break;case 'k': //hour (0-11)s = p2+'\\d|1[01]';break;case 'H': //hour (0-23)s = p2+'\\d|1\\d|2[0-3]';break;case 'K': //hour (1-24)s = p2+'[1-9]|1\\d|2[0-4]';break;case 'm':case 's':s = '[0-5]\\d';break;case 'S':s = '\\d{'+l+'}';break;case 'a':var am = options.am || bundle.am || 'AM';var pm = options.pm || bundle.pm || 'PM';if(options.strict){s = am + '|' + pm;}else{s = am + '|' + pm;if(am != am.toLowerCase()){ s += '|' + am.toLowerCase(); }if(pm != pm.toLowerCase()){ s += '|' + pm.toLowerCase(); }}break;default:// case 'v':// case 'z':// case 'Z':s = ".*";// console.debug("parse of date format, pattern=" + pattern);}if(tokens){ tokens.push(match); }return "(" + s + ")"; // add capture}).replace(/[\xa0 ]/g, "[\\s\\xa0]"); // normalize whitespace. Need explicit handling of \xa0 for IE.}})();(function(){var _customFormats = [];dojo.date.locale.addCustomFormats = function(/*String*/packageName, /*String*/bundleName){// summary:// Add a reference to a bundle containing localized custom formats to be// used by date/time formatting and parsing routines.//// description:// The user may add custom localized formats where the bundle has properties following the// same naming convention used by dojo for the CLDR data: dateFormat-xxxx / timeFormat-xxxx// The pattern string should match the format used by the CLDR.// See dojo.date.format for details.// The resources must be loaded by dojo.requireLocalization() prior to use_customFormats.push({pkg:packageName,name:bundleName});};dojo.date.locale._getGregorianBundle = function(/*String*/locale){var gregorian = {};dojo.forEach(_customFormats, function(desc){var bundle = dojo.i18n.getLocalization(desc.pkg, desc.name, locale);gregorian = dojo.mixin(gregorian, bundle);}, this);return gregorian; /*Object*/};})();dojo.date.locale.addCustomFormats("dojo.cldr","gregorian");dojo.date.locale.getNames = function(/*String*/item, /*String*/type, /*String?*/use, /*String?*/locale){// summary:// Used to get localized strings from dojo.cldr for day or month names.//// item: 'months' || 'days'// type: 'wide' || 'narrow' || 'abbr' (e.g. "Monday", "Mon", or "M" respectively, in English)// use: 'standAlone' || 'format' (default)// locale: override locale used to find the namesvar label;var lookup = dojo.date.locale._getGregorianBundle(locale);var props = [item, use, type];if(use == 'standAlone'){label = lookup[props.join('-')];}props[1] = 'format';// return by copy so changes won't be made accidentally to the in-memory modelreturn (label || lookup[props.join('-')]).concat(); /*Array*/};dojo.date.locale.isWeekend = function(/*Date?*/dateObject, /*String?*/locale){// summary:// Determines if the date falls on a weekend, according to local custom.var weekend = dojo.cldr.supplemental.getWeekend(locale);var day = (dateObject || new Date()).getDay();if(weekend.end < weekend.start){weekend.end += 7;if(day < weekend.start){ day += 7; }}return day >= weekend.start && day <= weekend.end; // Boolean};// These are used only by format and strftime. Do they need to be public? Which module should they go in?dojo.date.locale._getDayOfYear = function(/*Date*/dateObject){// summary: gets the day of the year as represented by dateObjectreturn dojo.date.difference(new Date(dateObject.getFullYear(), 0, 1), dateObject) + 1; // Number};dojo.date.locale._getWeekOfYear = function(/*Date*/dateObject, /*Number*/firstDayOfWeek){if(arguments.length == 1){ firstDayOfWeek = 0; } // Sundayvar firstDayOfYear = new Date(dateObject.getFullYear(), 0, 1).getDay();var adj = (firstDayOfYear - firstDayOfWeek + 7) % 7;var week = Math.floor((dojo.date.locale._getDayOfYear(dateObject) + adj - 1) / 7);// if year starts on the specified day, start counting weeks at 1if(firstDayOfYear == firstDayOfWeek){ week++; }return week; // Number};}if(!dojo._hasResource["dijit._Calendar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit._Calendar"] = true;dojo.provide("dijit._Calendar");dojo.declare("dijit._Calendar",[dijit._Widget, dijit._Templated],{/*summary:A simple GUI for choosing a date in the context of a monthly calendar.description:This widget is used internally by other widgets and is not accessibleas a standalone widget.This widget can't be used in a form because it doesn't serialize the date to an<input> field. For a form element, use DateTextBox instead.Note that the parser takes all dates attributes passed in the `RFC 3339` format:http://www.faqs.org/rfcs/rfc3339.html (2005-06-30T08:05:00-07:00)so that they are serializable and locale-independent.usage:var calendar = new dijit._Calendar({}, dojo.byId("calendarNode"));-or-<div dojoType="dijit._Calendar"></div>*/templateString:"<table cellspacing=\"0\" cellpadding=\"0\" class=\"dijitCalendarContainer\">\n\t<thead>\n\t\t<tr class=\"dijitReset dijitCalendarMonthContainer\" valign=\"top\">\n\t\t\t<th class='dijitReset' dojoAttachPoint=\"decrementMonth\">\n\t\t\t\t<span class=\"dijitInline dijitCalendarIncrementControl dijitCalendarDecrease\"><span dojoAttachPoint=\"decreaseArrowNode\" class=\"dijitA11ySideArrow dijitCalendarIncrementControl dijitCalendarDecreaseInner\">-</span></span>\n\t\t\t</th>\n\t\t\t<th class='dijitReset' colspan=\"5\">\n\t\t\t\t<div dojoAttachPoint=\"monthLabelSpacer\" class=\"dijitCalendarMonthLabelSpacer\"></div>\n\t\t\t\t<div dojoAttachPoint=\"monthLabelNode\" class=\"dijitCalendarMonth\"></div>\n\t\t\t</th>\n\t\t\t<th class='dijitReset' dojoAttachPoint=\"incrementMonth\">\n\t\t\t\t<div class=\"dijitInline dijitCalendarIncrementControl dijitCalendarIncrease\"><span dojoAttachPoint=\"increaseArrowNode\" class=\"dijitA11ySideArrow dijitCalendarIncrementControl dijitCalendarIncreaseInner\">+</span></div>\n\t\t\t</th>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<th class=\"dijitReset dijitCalendarDayLabelTemplate\"><span class=\"dijitCalendarDayLabel\"></span></th>\n\t\t</tr>\n\t</thead>\n\t<tbody dojoAttachEvent=\"onclick: _onDayClick\" class=\"dijitReset dijitCalendarBodyContainer\">\n\t\t<tr class=\"dijitReset dijitCalendarWeekTemplate\">\n\t\t\t<td class=\"dijitReset dijitCalendarDateTemplate\"><span class=\"dijitCalendarDateLabel\"></span></td>\n\t\t</tr>\n\t</tbody>\n\t<tfoot class=\"dijitReset dijitCalendarYearContainer\">\n\t\t<tr>\n\t\t\t<td class='dijitReset' valign=\"top\" colspan=\"7\">\n\t\t\t\t<h3 class=\"dijitCalendarYearLabel\">\n\t\t\t\t\t<span dojoAttachPoint=\"previousYearLabelNode\" class=\"dijitInline dijitCalendarPreviousYear\"></span>\n\t\t\t\t\t<span dojoAttachPoint=\"currentYearLabelNode\" class=\"dijitInline dijitCalendarSelectedYear\"></span>\n\t\t\t\t\t<span dojoAttachPoint=\"nextYearLabelNode\" class=\"dijitInline dijitCalendarNextYear\"></span>\n\t\t\t\t</h3>\n\t\t\t</td>\n\t\t</tr>\n\t</tfoot>\n</table>\t\n",// value: Date// the currently selected Datevalue: new Date(),// dayWidth: String// How to represent the days of the week in the calendar header. See dojo.date.localedayWidth: "narrow",setValue: function(/*Date*/ value){// summary: set the current date and update the UI. If the date is disabled, the selection will// not change, but the display will change to the corresponding month.if(!this.value || dojo.date.compare(value, this.value)){value = new Date(value);this.displayMonth = new Date(value);if(!this.isDisabledDate(value, this.lang)){this.value = value;this.value.setHours(0,0,0,0);this.onChange(this.value);}this._populateGrid();}},_setText: function(node, text){while(node.firstChild){node.removeChild(node.firstChild);}node.appendChild(document.createTextNode(text));},_populateGrid: function(){var month = this.displayMonth;month.setDate(1);var firstDay = month.getDay();var daysInMonth = dojo.date.getDaysInMonth(month);var daysInPreviousMonth = dojo.date.getDaysInMonth(dojo.date.add(month, "month", -1));var today = new Date();var selected = this.value;var dayOffset = dojo.cldr.supplemental.getFirstDayOfWeek(this.lang);if(dayOffset > firstDay){ dayOffset -= 7; }// Iterate through dates in the calendar and fill in date numbers and style infodojo.query(".dijitCalendarDateTemplate", this.domNode).forEach(function(template, i){i += dayOffset;var date = new Date(month);var number, clazz = "dijitCalendar", adj = 0;if(i < firstDay){number = daysInPreviousMonth - firstDay + i + 1;adj = -1;clazz += "Previous";}else if(i >= (firstDay + daysInMonth)){number = i - firstDay - daysInMonth + 1;adj = 1;clazz += "Next";}else{number = i - firstDay + 1;clazz += "Current";}if(adj){date = dojo.date.add(date, "month", adj);}date.setDate(number);if(!dojo.date.compare(date, today, "date")){clazz = "dijitCalendarCurrentDate " + clazz;}if(!dojo.date.compare(date, selected, "date")){clazz = "dijitCalendarSelectedDate " + clazz;}if(this.isDisabledDate(date, this.lang)){clazz = "dijitCalendarDisabledDate " + clazz;}template.className = clazz + "Month dijitCalendarDateTemplate";template.dijitDateValue = date.valueOf();var label = dojo.query(".dijitCalendarDateLabel", template)[0];this._setText(label, date.getDate());}, this);// Fill in localized month namevar monthNames = dojo.date.locale.getNames('months', 'wide', 'standAlone', this.lang);this._setText(this.monthLabelNode, monthNames[month.getMonth()]);// Fill in localized prev/current/next yearsvar y = month.getFullYear() - 1;dojo.forEach(["previous", "current", "next"], function(name){this._setText(this[name+"YearLabelNode"],dojo.date.locale.format(new Date(y++, 0), {selector:'year', locale:this.lang}));}, this);// Set up repeating mouse behaviorvar _this = this;var typematic = function(nodeProp, dateProp, adj){dijit.typematic.addMouseListener(_this[nodeProp], _this, function(count){if(count >= 0){ _this._adjustDisplay(dateProp, adj); }}, 0.8, 500);};typematic("incrementMonth", "month", 1);typematic("decrementMonth", "month", -1);typematic("nextYearLabelNode", "year", 1);typematic("previousYearLabelNode", "year", -1);},postCreate: function(){dijit._Calendar.superclass.postCreate.apply(this);var cloneClass = dojo.hitch(this, function(clazz, n){var template = dojo.query(clazz, this.domNode)[0];for(var i=0; i<n; i++){template.parentNode.appendChild(template.cloneNode(true));}});// clone the day label and calendar day templates 6 times to make 7 columnscloneClass(".dijitCalendarDayLabelTemplate", 6);cloneClass(".dijitCalendarDateTemplate", 6);// now make 6 week rowscloneClass(".dijitCalendarWeekTemplate", 5);// insert localized day names in the headervar dayNames = dojo.date.locale.getNames('days', this.dayWidth, 'standAlone', this.lang);var dayOffset = dojo.cldr.supplemental.getFirstDayOfWeek(this.lang);dojo.query(".dijitCalendarDayLabel", this.domNode).forEach(function(label, i){this._setText(label, dayNames[(i + dayOffset) % 7]);}, this);// Fill in spacer element with all the month names (invisible) so that the maximum width will affect layoutvar monthNames = dojo.date.locale.getNames('months', 'wide', 'standAlone', this.lang);dojo.forEach(monthNames, function(name){var monthSpacer = dojo.doc.createElement("div");this._setText(monthSpacer, name);this.monthLabelSpacer.appendChild(monthSpacer);}, this);this.value = null;this.setValue(new Date());},_adjustDisplay: function(/*String*/part, /*int*/amount){this.displayMonth = dojo.date.add(this.displayMonth, part, amount);this._populateGrid();},_onDayClick: function(/*Event*/evt){var node = evt.target;dojo.stopEvent(evt);while(!node.dijitDateValue){node = node.parentNode;}if(!dojo.hasClass(node, "dijitCalendarDisabledDate")){this.setValue(node.dijitDateValue);this.onValueSelected(this.value);}},onValueSelected: function(/*Date*/date){//summary: a date cell was selected. It may be the same as the previous value.},onChange: function(/*Date*/date){//summary: called only when the selected date has changed},isDisabledDate: function(/*Date*/dateObject, /*String?*/locale){// summary:// May be overridden to disable certain dates in the calendar e.g. isDisabledDate=dojo.date.locale.isWeekendreturn false; // Boolean}});}if(!dojo._hasResource["dijit._TimePicker"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit._TimePicker"] = true;dojo.provide("dijit._TimePicker");dojo.declare("dijit._TimePicker",[dijit._Widget, dijit._Templated],{// summary:// A graphical time picker that TimeTextBox pops up// It is functionally modeled after the Java applet at http://java.arcadevillage.com/applets/timepica.htm// See ticket #599templateString:"<div id=\"widget_${id}\" class=\"dijitMenu\"\n ><div dojoAttachPoint=\"upArrow\" class=\"dijitButtonNode\"><span class=\"dijitTimePickerA11yText\">▲</span></div\n ><div dojoAttachPoint=\"timeMenu,focusNode\" dojoAttachEvent=\"onclick:_onOptionSelected,onmouseover,onmouseout\"></div\n ><div dojoAttachPoint=\"downArrow\" class=\"dijitButtonNode\"><span class=\"dijitTimePickerA11yText\">▼</span></div\n></div>\n",baseClass: "dijitTimePicker",// clickableIncrement: String// ISO-8601 string representing the amount by which// every clickable element in the time picker increases// Set in non-Zulu time, without a time zone// Example: "T00:15:00" creates 15 minute increments// Must divide visibleIncrement evenlyclickableIncrement: "T00:15:00",// visibleIncrement: String// ISO-8601 string representing the amount by which// every element with a visible time in the time picker increases// Set in non Zulu time, without a time zone// Example: "T01:00:00" creates text in every 1 hour incrementvisibleIncrement: "T01:00:00",// visibleRange: String// ISO-8601 string representing the range of this TimePicker// The TimePicker will only display times in this range// Example: "T05:00:00" displays 5 hours of optionsvisibleRange: "T05:00:00",// value: String// Date to display.// Defaults to current time and date.// Can be a Date object or an ISO-8601 string// If you specify the GMT time zone ("-01:00"),// the time will be converted to the local time in the local time zone.// Otherwise, the time is considered to be in the local time zone.// If you specify the date and isDate is true, the date is used.// Example: if your local time zone is GMT -05:00,// "T10:00:00" becomes "T10:00:00-05:00" (considered to be local time),// "T10:00:00-01:00" becomes "T06:00:00-05:00" (4 hour difference),// "T10:00:00Z" becomes "T05:00:00-05:00" (5 hour difference between Zulu and local time)// "yyyy-mm-ddThh:mm:ss" is the format to set the date and time// Example: "2007-06-01T09:00:00"value: new Date(),_visibleIncrement:2,_clickableIncrement:1,_totalIncrements:10,constraints:{},serialize: dojo.date.stamp.toISOString,setValue:function(/*Date*/ date, /*Boolean*/ priority){// summary:// Set the value of the TimePicker// Redraws the TimePicker around the new date//dijit._TimePicker.superclass.setValue.apply(this, arguments);this.value=date;this._showText();},isDisabledDate: function(/*Date*/dateObject, /*String?*/locale){// summary:// May be overridden to disable certain dates in the TimePicker e.g. isDisabledDate=dojo.date.locale.isWeekendreturn false; // Boolean},_showText:function(){this.timeMenu.innerHTML="";var fromIso = dojo.date.stamp.fromISOString;this._clickableIncrementDate=fromIso(this.clickableIncrement);this._visibleIncrementDate=fromIso(this.visibleIncrement);this._visibleRangeDate=fromIso(this.visibleRange);// get the value of the increments and the range in seconds (since 00:00:00) to find out how many divs to createvar sinceMidnight = function(/*Date*/ date){return date.getHours()*60*60+date.getMinutes()*60+date.getSeconds();};var clickableIncrementSeconds = sinceMidnight(this._clickableIncrementDate);var visibleIncrementSeconds = sinceMidnight(this._visibleIncrementDate);var visibleRangeSeconds = sinceMidnight(this._visibleRangeDate);// round reference date to previous visible incrementvar time = this.value.getTime();this._refDate = new Date(time - time % (visibleIncrementSeconds*1000));// assume clickable increment is the smallest unitthis._clickableIncrement=1;// divide the visible range by the clickable increment to get the number of divs to create// example: 10:00:00/00:15:00 -> display 40 divsthis._totalIncrements=visibleRangeSeconds/clickableIncrementSeconds;// divide the visible increments by the clickable increments to get how often to display the time inline// example: 01:00:00/00:15:00 -> display the time every 4 divsthis._visibleIncrement=visibleIncrementSeconds/clickableIncrementSeconds;for(var i=-this._totalIncrements/2; i<=this._totalIncrements/2; i+=this._clickableIncrement){var div=this._createOption(i);this.timeMenu.appendChild(div);}// TODO:// I commented this out because it// causes problems for a TimeTextBox in a Dialog, or as the editor of an InlineEditBox,// because the timeMenu node isn't visible yet. -- Bill (Bug #????)// dijit.focus(this.timeMenu);},postCreate:function(){// instantiate constraintsif(this.constraints===dijit._TimePicker.prototype.constraints){this.constraints={};}// dojo.date.locale needs the lang in the constraints as localeif(!this.constraints.locale){this.constraints.locale=this.lang;}// assign typematic mouse listeners to the arrow buttonsthis.connect(this.timeMenu, dojo.isIE ? "onmousewheel" : 'DOMMouseScroll', "_mouseWheeled");dijit.typematic.addMouseListener(this.upArrow,this,this._onArrowUp, 0.8, 500);dijit.typematic.addMouseListener(this.downArrow,this,this._onArrowDown, 0.8, 500);//dijit.typematic.addListener(this.upArrow,this.timeMenu, {keyCode:dojo.keys.UP_ARROW,ctrlKey:false,altKey:false,shiftKey:false}, this, "_onArrowUp", 0.8, 500);//dijit.typematic.addListener(this.downArrow, this.timeMenu, {keyCode:dojo.keys.DOWN_ARROW,ctrlKey:false,altKey:false,shiftKey:false}, this, "_onArrowDown", 0.8,500);this.inherited("postCreate", arguments);this.setValue(this.value);},_createOption:function(/*Number*/ index){// summary: creates a clickable time optionvar div=document.createElement("div");var date = (div.date = new Date(this._refDate));div.index=index;var incrementDate = this._clickableIncrementDate;date.setHours(date.getHours()+incrementDate.getHours()*index,date.getMinutes()+incrementDate.getMinutes()*index,date.getSeconds()+incrementDate.getSeconds()*index);var innerDiv = document.createElement('div');dojo.addClass(div,this.baseClass+"Item");dojo.addClass(innerDiv,this.baseClass+"ItemInner");innerDiv.innerHTML=dojo.date.locale.format(date, this.constraints);div.appendChild(innerDiv);if(index%this._visibleIncrement<1 && index%this._visibleIncrement>-1){dojo.addClass(div, this.baseClass+"Marker");}else if(index%this._clickableIncrement==0){dojo.addClass(div, this.baseClass+"Tick");}if(this.isDisabledDate(date)){// set disableddojo.addClass(div, this.baseClass+"ItemDisabled");}if(dojo.date.compare(this.value, date, this.constraints.selector)==0){div.selected=true;dojo.addClass(div, this.baseClass+"ItemSelected");}return div;},_onOptionSelected:function(/*Object*/ tgt){var tdate = tgt.target.date || tgt.target.parentNode.date;if(!tdate||this.isDisabledDate(tdate)){return;}this.setValue(tdate);this.onValueSelected(tdate);},onValueSelected:function(value){},onmouseover:function(/*Event*/ e){var tgr = (e.target.parentNode === this.timeMenu) ? e.target : e.target.parentNode;this._highlighted_option=tgr;dojo.addClass(tgr, this.baseClass+"ItemHover");},onmouseout:function(/*Event*/ e){var tgr = (e.target.parentNode === this.timeMenu) ? e.target : e.target.parentNode;if(this._highlighted_option===tgr){dojo.removeClass(tgr, this.baseClass+"ItemHover");}},_mouseWheeled:function(/*Event*/e){// summary: handle the mouse wheel listenerdojo.stopEvent(e);// we're not _measuring_ the scroll amount, just directionvar scrollAmount = (dojo.isIE ? e.wheelDelta : -e.detail);this[(scrollAmount>0 ? "_onArrowUp" : "_onArrowDown")](); // yes, we're making a new dom node every time you mousewheel, or click},_onArrowUp:function(){// summary: remove the bottom time and add one to the topvar index=this.timeMenu.childNodes[0].index-1;var div=this._createOption(index);this.timeMenu.removeChild(this.timeMenu.childNodes[this.timeMenu.childNodes.length-1]);this.timeMenu.insertBefore(div, this.timeMenu.childNodes[0]);},_onArrowDown:function(){// summary: remove the top time and add one to the bottomvar index=this.timeMenu.childNodes[this.timeMenu.childNodes.length-1].index+1;var div=this._createOption(index);this.timeMenu.removeChild(this.timeMenu.childNodes[0]);this.timeMenu.appendChild(div);}});}if(!dojo._hasResource["dijit.form.TimeTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.form.TimeTextBox"] = true;dojo.provide("dijit.form.TimeTextBox");dojo.declare("dijit.form.TimeTextBox",dijit.form.RangeBoundTextBox,{// summary:// A validating, serializable, range-bound date text box.// constraints object: min, maxregExpGen: dojo.date.locale.regexp,compare: dojo.date.compare,format: function(/*Date*/ value, /*Object*/ constraints){if(!value || value.toString() == this._invalid){ return null; }return dojo.date.locale.format(value, constraints);},parse: dojo.date.locale.parse,serialize: dojo.date.stamp.toISOString,value: new Date(""), // NaN_invalid: (new Date("")).toString(), // NaN_popupClass: "dijit._TimePicker",postMixInProperties: function(){//dijit.form.RangeBoundTextBox.prototype.postMixInProperties.apply(this, arguments);this.inherited("postMixInProperties",arguments);var constraints = this.constraints;constraints.selector = 'time';if(typeof constraints.min == "string"){ constraints.min = dojo.date.stamp.fromISOString(constraints.min); }if(typeof constraints.max == "string"){ constraints.max = dojo.date.stamp.fromISOString(constraints.max); }},_onFocus: function(/*Event*/ evt){// summary: open the TimePicker popupthis._open();},setValue: function(/*Date*/ value, /*Boolean, optional*/ priorityChange){// summary:// Sets the date on this textboxthis.inherited('setValue', arguments);if(this._picker){// #3948: fix blank date on popup onlyif(!value || value.toString() == this._invalid){value=new Date();}this._picker.setValue(value);}},_open: function(){// summary:// opens the TimePicker, and sets the onValueSelected valueif(this.disabled){return;}var self = this;if(!this._picker){var popupProto=dojo.getObject(this._popupClass, false);this._picker = new popupProto({onValueSelected: function(value){self.focus(); // focus the textbox before the popup closes to avoid reopening the popupsetTimeout(dojo.hitch(self, "_close"), 1); // allow focus time to take// this will cause InlineEditBox and other handlers to do stuff so make sure it's lastdijit.form.TimeTextBox.superclass.setValue.call(self, value, true);},lang: this.lang,constraints:this.constraints,isDisabledDate: function(/*Date*/ date){// summary:// disables dates outside of the min/max of the TimeTextBoxreturn self.constraints && (dojo.date.compare(self.constraints.min,date) > 0 || dojo.date.compare(self.constraints.max,date) < 0);}});this._picker.setValue(this.getValue() || new Date());}if(!this._opened){dijit.popup.open({parent: this,popup: this._picker,around: this.domNode,onCancel: dojo.hitch(this, this._close),onClose: function(){ self._opened=false; }});this._opened=true;}dojo.marginBox(this._picker.domNode,{ w:this.domNode.offsetWidth });},_close: function(){if(this._opened){dijit.popup.close(this._picker);this._opened=false;}},_onBlur: function(){// summary: called magically when focus has shifted away from this widget and it's dropdownthis._close();this.inherited('_onBlur', arguments);// don't focus on <input>. the user has explicitly focused on something else.},getDisplayedValue:function(){return this.textbox.value;},setDisplayedValue:function(/*String*/ value){this.textbox.value=value;}});}if(!dojo._hasResource["dijit.form.DateTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.form.DateTextBox"] = true;dojo.provide("dijit.form.DateTextBox");dojo.declare("dijit.form.DateTextBox",dijit.form.TimeTextBox,{// summary:// A validating, serializable, range-bound date text box._popupClass: "dijit._Calendar",postMixInProperties: function(){this.inherited('postMixInProperties', arguments);this.constraints.selector = 'date';}});}if(!dojo._hasResource["dijit.form.FilteringSelect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.form.FilteringSelect"] = true;dojo.provide("dijit.form.FilteringSelect");dojo.declare("dijit.form.FilteringSelect",[dijit.form.MappedTextBox, dijit.form.ComboBoxMixin],{/** summary* Enhanced version of HTML's <select> tag.** Similar features:* - There is a drop down list of possible values.* - You can only enter a value from the drop down list. (You can't enter an arbitrary value.)* - The value submitted with the form is the hidden value (ex: CA),* not the displayed value a.k.a. label (ex: California)** Enhancements over plain HTML version:* - If you type in some text then it will filter down the list of possible values in the drop down list.* - List can be specified either as a static list or via a javascript function (that can get the list from a server)*/// searchAttr: String// Searches pattern match against this field// labelAttr: String// Optional. The text that actually appears in the drop down.// If not specified, the searchAttr text is used instead.labelAttr: "",// labelType: String// "html" or "text"labelType: "text",_isvalid:true,isValid:function(){return this._isvalid;},_callbackSetLabel: function(/*Array*/ result, /*Object*/ dataObject, /*Boolean, optional*/ priorityChange){// summary// Callback function that dynamically sets the label of the ComboBox// setValue does a synchronous lookup,// so it calls _callbackSetLabel directly,// and so does not pass dataObject// dataObject==null means do not test the lastQuery, just continueif(dataObject&&dataObject.query[this.searchAttr]!=this._lastQuery){return;}if(!result.length){//#3268: do nothing on bad input//this._setValue("", "");//#3285: change CSS to indicate errorif(!this._hasFocus){ this.valueNode.value=""; }dijit.form.TextBox.superclass.setValue.call(this, undefined, !this._hasFocus);this._isvalid=false;this.validate(this._hasFocus);}else{this._setValueFromItem(result[0], priorityChange);}},_openResultList: function(/*Object*/ results, /*Object*/ dataObject){// #3285: tap into search callback to see if user's query resembles a matchif(dataObject.query[this.searchAttr]!=this._lastQuery){return;}this._isvalid=results.length!=0;this.validate(true);dijit.form.ComboBoxMixin.prototype._openResultList.apply(this, arguments);},getValue:function(){// don't get the textbox value but rather the previously set hidden valuereturn this.valueNode.value;},_getValueField:function(){// used for option tag selectsreturn "value";},_setValue:function(/*String*/ value, /*String*/ displayedValue, /*Boolean, optional*/ priorityChange){this.valueNode.value = value;dijit.form.FilteringSelect.superclass.setValue.call(this, value, priorityChange, displayedValue);this._lastDisplayedValue = displayedValue;},setValue: function(/*String*/ value, /*Boolean, optional*/ priorityChange){// summary// Sets the value of the select.// Also sets the label to the corresponding value by reverse lookup.//#3347: fetchItemByIdentity if no keyAttr specifiedvar self=this;var handleFetchByIdentity = function(item, priorityChange){if(item){if(self.store.isItemLoaded(item)){self._callbackSetLabel([item], undefined, priorityChange);}else{self.store.loadItem({item:item, onItem: function(result, dataObject){self._callbackSetLabel(result, dataObject, priorityChange)}});}}else{self._isvalid=false;// prevent errors from Tooltip not being created yetself.validate(false);}}this.store.fetchItemByIdentity({identity: value, onItem: function(item){handleFetchByIdentity(item, priorityChange)}});},_setValueFromItem: function(/*item*/ item, /*Boolean, optional*/ priorityChange){// summary// Set the displayed valued in the input box, based on a selected item.// Users shouldn't call this function; they should be calling setDisplayedValue() insteadthis._isvalid=true;this._setValue(this.store.getIdentity(item), this.labelFunc(item, this.store), priorityChange);},labelFunc: function(/*item*/ item, /*dojo.data.store*/ store){// summary: Event handler called when the label changes// returns the label that the ComboBox should displayreturn store.getValue(item, this.searchAttr);},onkeyup: function(/*Event*/ evt){// summary: internal function// FilteringSelect needs to wait for the complete label before committing to a reverse lookup//this.setDisplayedValue(this.textbox.value);},_doSelect: function(/*Event*/ tgt){// summary:// ComboBox's menu callback function// FilteringSelect overrides this to set both the visible and hidden value from the information stored in the menuthis.item = tgt.item;this._setValueFromItem(tgt.item, true);},setDisplayedValue:function(/*String*/ label){// summary:// Set textbox to display label// Also performs reverse lookup to set the hidden value// Used in InlineEditBoxif(this.store){var query={};this._lastQuery=query[this.searchAttr]=label;// if the label is not valid, the callback will never set it,// so the last valid value will get the warning textbox// set the textbox value now so that the impending warning will make sense to the userthis.textbox.value=label;this._lastDisplayedValue=label;this.store.fetch({query:query, queryOptions:{ignoreCase:this.ignoreCase, deep:true}, onComplete: dojo.hitch(this, this._callbackSetLabel)});}},_getMenuLabelFromItem:function(/*Item*/ item){// internal function to help ComboBoxMenu figure out what to displayif(this.labelAttr){return {html:this.labelType=="html", label:this.store.getValue(item, this.labelAttr)};}else{// because this function is called by ComboBoxMenu, this.inherited tries to find the superclass of ComboBoxMenureturn dijit.form.ComboBoxMixin.prototype._getMenuLabelFromItem.apply(this, arguments);}},postMixInProperties: function(){dijit.form.ComboBoxMixin.prototype.postMixInProperties.apply(this, arguments);dijit.form.MappedTextBox.prototype.postMixInProperties.apply(this, arguments);}});}if(!dojo._hasResource["dijit.form._Spinner"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.form._Spinner"] = true;dojo.provide("dijit.form._Spinner");dojo.declare("dijit.form._Spinner",dijit.form.RangeBoundTextBox,{// summary: Mixin for validation widgets with a spinner// description: This class basically (conceptually) extends dijit.form.ValidationTextBox.// It modifies the template to have up/down arrows, and provides related handling code.// defaultTimeout: Number// number of milliseconds before a held key or button becomes typematicdefaultTimeout: 500,// timeoutChangeRate: Number// fraction of time used to change the typematic timer between events// 1.0 means that each typematic event fires at defaultTimeout intervals// < 1.0 means that each typematic event fires at an increasing faster ratetimeoutChangeRate: 0.90,// smallDelta: Number// adjust the value by this much when spinning using the arrow keys/buttonssmallDelta: 1,// largeDelta: Number// adjust the value by this much when spinning using the PgUp/Dn keyslargeDelta: 10,templateString:"<table class=\"dijit dijitReset dijitInlineTable dijitLeft\" cellspacing=\"0\" cellpadding=\"0\"\n\tid=\"widget_${id}\" name=\"${name}\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse,onkeypress:_onKeyPress\"\n\twaiRole=\"presentation\"\n\t><tr class=\"dijitReset\"\n\t\t><td rowspan=\"2\" class=\"dijitReset dijitStretch dijitInputField\" width=\"100%\"\n\t\t\t><input dojoAttachPoint=\"textbox,focusNode\" type=\"${type}\" dojoAttachEvent=\"onfocus,onkeyup\"\n\t\t\t\twaiRole=\"spinbutton\" autocomplete=\"off\" name=\"${name}\"\n\t\t></td\n\t\t><td rowspan=\"2\" class=\"dijitReset dijitValidationIconField\" width=\"0%\" \n\t\t\t><div dojoAttachPoint='iconNode' class='dijitValidationIcon'></div\n\t\t></td\n\t\t><td class=\"dijitReset dijitRight dijitButtonNode dijitUpArrowButton\" width=\"0%\"\n\t\t\t\tdojoAttachPoint=\"upArrowNode\"\n\t\t\t\tdojoAttachEvent=\"onmousedown:_handleUpArrowEvent,onmouseup:_handleUpArrowEvent,onmouseover:_handleUpArrowEvent,onmouseout:_handleUpArrowEvent\"\n\t\t\t\tstateModifier=\"UpArrow\"\n\t\t\t><div class=\"dijitA11yUpArrow\">▲</div\n\t\t></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset dijitRight dijitButtonNode dijitDownArrowButton\" width=\"0%\"\n\t\t\t\tdojoAttachPoint=\"downArrowNode\"\n\t\t\t\tdojoAttachEvent=\"onmousedown:_handleDownArrowEvent,onmouseup:_handleDownArrowEvent,onmouseover:_handleDownArrowEvent,onmouseout:_handleDownArrowEvent\"\n\t\t\t\tstateModifier=\"DownArrow\"\n\t\t\t><div class=\"dijitA11yDownArrow\">▼</div\n\t\t></td\n\t></tr\n></table>\n\n",baseClass: "dijitSpinner",adjust: function(/* Object */ val, /*Number*/ delta){// summary: user replaceable function used to adjust a primitive value(Number/Date/...) by the delta amount specified// the val is adjusted in a way that makes sense to the object typereturn val;},_handleUpArrowEvent : function(/*Event*/ e){this._onMouse(e, this.upArrowNode);},_handleDownArrowEvent : function(/*Event*/ e){this._onMouse(e, this.downArrowNode);},_arrowPressed: function(/*Node*/ nodePressed, /*Number*/ direction){if(this.disabled){ return; }dojo.addClass(nodePressed, "dijitSpinnerButtonActive");this.setValue(this.adjust(this.getValue(), direction*this.smallDelta), false);},_arrowReleased: function(/*Node*/ node){if(this.disabled){ return; }this._wheelTimer = null;dijit.focus(this.textbox);dojo.removeClass(node, "dijitSpinnerButtonActive");},_typematicCallback: function(/*Number*/ count, /*DOMNode*/ node, /*Event*/ evt){if(node == this.textbox){ node = (evt.keyCode == dojo.keys.UP_ARROW) ? this.upArrowNode : this.downArrowNode; }if(count == -1){ this._arrowReleased(node); }else{ this._arrowPressed(node, (node == this.upArrowNode) ? 1 : -1); }},_wheelTimer: null,_mouseWheeled: function(/*Event*/ evt){dojo.stopEvent(evt);var scrollAmount = 0;if(typeof evt.wheelDelta == 'number'){ // IEscrollAmount = evt.wheelDelta;}else if(typeof evt.detail == 'number'){ // Mozilla+FirefoxscrollAmount = -evt.detail;}if(scrollAmount > 0){var node = this.upArrowNode;var dir = +1;}else if(scrollAmount < 0){var node = this.downArrowNode;var dir = -1;}else{ return; }this._arrowPressed(node, dir);if(this._wheelTimer != null){clearTimeout(this._wheelTimer);}var _this = this;this._wheelTimer = setTimeout(function(){_this._arrowReleased(node);}, 50);},postCreate: function(){this.inherited('postCreate', arguments);// extra listenersthis.connect(this.textbox, dojo.isIE ? "onmousewheel" : 'DOMMouseScroll', "_mouseWheeled");dijit.typematic.addListener(this.upArrowNode, this.textbox, {keyCode:dojo.keys.UP_ARROW,ctrlKey:false,altKey:false,shiftKey:false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout);dijit.typematic.addListener(this.downArrowNode, this.textbox, {keyCode:dojo.keys.DOWN_ARROW,ctrlKey:false,altKey:false,shiftKey:false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout);}});}if(!dojo._hasResource["dijit.form.NumberSpinner"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.form.NumberSpinner"] = true;dojo.provide("dijit.form.NumberSpinner");dojo.declare("dijit.form.NumberSpinner",[dijit.form._Spinner, dijit.form.NumberTextBoxMixin],{// summary: Number Spinner// description: This widget is the same as NumberTextBox but with up/down arrows addedrequired: true,adjust: function(/* Object */ val, /*Number*/ delta){// summary: change Number val by the given amountvar newval = val+delta;if(isNaN(val) || isNaN(newval)){ return val; }if((typeof this.constraints.max == "number") && (newval > this.constraints.max)){newval = this.constraints.max;}if((typeof this.constraints.min == "number") && (newval < this.constraints.min)){newval = this.constraints.min;}return newval;}});}if(!dojo._hasResource["dijit.form.Slider"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.form.Slider"] = true;dojo.provide("dijit.form.Slider");dojo.declare("dijit.form.HorizontalSlider",[dijit.form._FormWidget, dijit._Container],{// summary// A form widget that allows one to select a value with a horizontally draggable imagetemplateString:"<table class=\"dijit dijitReset dijitSlider\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" rules=\"none\"\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t\t><td dojoAttachPoint=\"containerNode,topDecoration\" class=\"dijitReset\" style=\"text-align:center;width:100%;\"></td\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitHorizontalSliderButtonContainer\"\n\t\t\t><div class=\"dijitHorizontalSliderDecrementIcon\" tabIndex=\"-1\" style=\"display:none\" dojoAttachPoint=\"decrementButton\" dojoAttachEvent=\"onclick: decrement\"><span class=\"dijitSliderButtonInner\">-</span></div\n\t\t></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><div class=\"dijitSliderBar dijitSliderBumper dijitHorizontalSliderBumper dijitSliderLeftBumper dijitHorizontalSliderLeftBumper\"></div\n\t\t></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><input dojoAttachPoint=\"valueNode\" type=\"hidden\" name=\"${name}\"\n\t\t\t/><div style=\"position:relative;\" dojoAttachPoint=\"sliderBarContainer\"\n\t\t\t\t><div dojoAttachPoint=\"progressBar\" class=\"dijitSliderBar dijitHorizontalSliderBar dijitSliderProgressBar dijitHorizontalSliderProgressBar\" dojoAttachEvent=\"onclick:_onBarClick\"\n\t\t\t\t\t><div dojoAttachPoint=\"sliderHandle,focusNode\" class=\"dijitSliderMoveable dijitHorizontalSliderMoveable\" dojoAttachEvent=\"onkeypress:_onKeyPress,onclick:_onHandleClick\" waiRole=\"slider\" valuemin=\"${minimum}\" valuemax=\"${maximum}\"\n\t\t\t\t\t\t><div class=\"dijitSliderImageHandle dijitHorizontalSliderImageHandle\"></div\n\t\t\t\t\t></div\n\t\t\t\t></div\n\t\t\t\t><div dojoAttachPoint=\"remainingBar\" class=\"dijitSliderBar dijitHorizontalSliderBar dijitSliderRemainingBar dijitHorizontalSliderRemainingBar\" dojoAttachEvent=\"onclick:_onBarClick\"></div\n\t\t\t></div\n\t\t></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><div class=\"dijitSliderBar dijitSliderBumper dijitHorizontalSliderBumper dijitSliderRightBumper dijitHorizontalSliderRightBumper\"></div\n\t\t></td\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitHorizontalSliderButtonContainer\" style=\"right:0px;\"\n\t\t\t><div class=\"dijitHorizontalSliderIncrementIcon\" tabIndex=\"-1\" style=\"display:none\" dojoAttachPoint=\"incrementButton\" dojoAttachEvent=\"onclick: increment\"><span class=\"dijitSliderButtonInner\">+</span></div\n\t\t></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t\t><td dojoAttachPoint=\"containerNode,bottomDecoration\" class=\"dijitReset\" style=\"text-align:center;\"></td\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t></tr\n></table>\n",value: 0,// showButtons: boolean// Show increment/decrement buttons at the ends of the slider?showButtons: true,// minimum:: integer// The minimum value allowed.minimum: 0,// maximum: integer// The maximum allowed value.maximum: 100,// discreteValues: integer// The maximum allowed values dispersed evenly between minimum and maximum (inclusive).discreteValues: Infinity,// pageIncrement: integer// The amount of change with shift+arrowpageIncrement: 2,// clickSelect: boolean// If clicking the progress bar changes the value or notclickSelect: true,widgetsInTemplate: true,attributeMap: dojo.mixin(dojo.clone(dijit.form._FormWidget.prototype.attributeMap),{id:"", name:"valueNode"}),baseClass: "dijitSlider",_mousePixelCoord: "pageX",_pixelCount: "w",_startingPixelCoord: "x",_startingPixelCount: "l",_handleOffsetCoord: "left",_progressPixelSize: "width",_upsideDown: false,_onKeyPress: function(/*Event*/ e){if(this.disabled || e.altKey || e.ctrlKey){ return; }switch(e.keyCode){case dojo.keys.HOME:this.setValue(this.minimum, false);break;case dojo.keys.END:this.setValue(this.maximum, false);break;case dojo.keys.UP_ARROW:case (this._isReversed() ? dojo.keys.LEFT_ARROW : dojo.keys.RIGHT_ARROW):case dojo.keys.PAGE_UP:this.increment(e);break;case dojo.keys.DOWN_ARROW:case (this._isReversed() ? dojo.keys.RIGHT_ARROW : dojo.keys.LEFT_ARROW):case dojo.keys.PAGE_DOWN:this.decrement(e);break;default:this.inherited("_onKeyPress", arguments);return;}dojo.stopEvent(e);},_onHandleClick: function(e){if(this.disabled){ return; }if(!dojo.isIE){// make sure you get focus when dragging the handle// (but don't do on IE because it causes a flicker on mouse up (due to blur then focus)dijit.focus(this.sliderHandle);}dojo.stopEvent(e);},_isReversed: function() {return !(this._upsideDown || this.isLeftToRight());},_onBarClick: function(e){if(this.disabled || !this.clickSelect){ return; }dijit.focus(this.sliderHandle);dojo.stopEvent(e);var abspos = dojo.coords(this.sliderBarContainer, true);var pixelValue = e[this._mousePixelCoord] - abspos[this._startingPixelCoord];this._setPixelValue(this._isReversed() || this._upsideDown ? (abspos[this._pixelCount] - pixelValue) : pixelValue, abspos[this._pixelCount], true);},_setPixelValue: function(/*Number*/ pixelValue, /*Number*/ maxPixels, /*Boolean, optional*/ priorityChange){if(this.disabled){ return; }pixelValue = pixelValue < 0 ? 0 : maxPixels < pixelValue ? maxPixels : pixelValue;var count = this.discreteValues;if(count <= 1 || count == Infinity){ count = maxPixels; }count--;var pixelsPerValue = maxPixels / count;var wholeIncrements = Math.round(pixelValue / pixelsPerValue);this.setValue((this.maximum-this.minimum)*wholeIncrements/count + this.minimum, priorityChange);},setValue: function(/*Number*/ value, /*Boolean, optional*/ priorityChange){this.valueNode.value = this.value = value;this.inherited('setValue', arguments);var percent = (value - this.minimum) / (this.maximum - this.minimum);this.progressBar.style[this._progressPixelSize] = (percent*100) + "%";this.remainingBar.style[this._progressPixelSize] = ((1-percent)*100) + "%";},_bumpValue: function(signedChange){if(this.disabled){ return; }var s = dojo.getComputedStyle(this.sliderBarContainer);var c = dojo._getContentBox(this.sliderBarContainer, s);var count = this.discreteValues;if(count <= 1 || count == Infinity){ count = c[this._pixelCount]; }count--;var value = (this.value - this.minimum) * count / (this.maximum - this.minimum) + signedChange;if(value < 0){ value = 0; }if(value > count){ value = count; }value = value * (this.maximum - this.minimum) / count + this.minimum;this.setValue(value, true);},decrement: function(e){// summary// decrement slider by 1 unitthis._bumpValue(e.keyCode == dojo.keys.PAGE_DOWN?-this.pageIncrement:-1);},increment: function(e){// summary// increment slider by 1 unitthis._bumpValue(e.keyCode == dojo.keys.PAGE_UP?this.pageIncrement:1);},_mouseWheeled: function(/*Event*/ evt){dojo.stopEvent(evt);var scrollAmount = 0;if(typeof evt.wheelDelta == 'number'){ // IEscrollAmount = evt.wheelDelta;}else if(typeof evt.detail == 'number'){ // Mozilla+FirefoxscrollAmount = -evt.detail;}if(scrollAmount > 0){this.increment(evt);}else if(scrollAmount < 0){this.decrement(evt);}},startup: function(){dojo.forEach(this.getChildren(), function(child){if(this[child.container] != this.containerNode){this[child.container].appendChild(child.domNode);}}, this);},_onBlur: function(){dijit.form.HorizontalSlider.superclass.setValue.call(this, this.value, true);},postCreate: function(){if(this.showButtons){this.incrementButton.style.display="";this.decrementButton.style.display="";}this.connect(this.domNode, dojo.isIE ? "onmousewheel" : 'DOMMouseScroll', "_mouseWheeled");// define a custom constructor for a SliderMover that points back to mevar _self = this;var mover = function(){dijit.form._SliderMover.apply(this, arguments);this.widget = _self;};dojo.extend(mover, dijit.form._SliderMover.prototype);this._movable = new dojo.dnd.Moveable(this.sliderHandle, {mover: mover});this.inherited('postCreate', arguments);},destroy: function(){this._movable.destroy();this.inherited('destroy', arguments);}});dojo.declare("dijit.form.VerticalSlider",dijit.form.HorizontalSlider,{// summary// A form widget that allows one to select a value with a vertically draggable imagetemplateString:"<table class=\"dijitReset dijitSlider\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" rules=\"none\"\n><tbody class=\"dijitReset\"\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\"></td\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitVerticalSliderButtonContainer\"\n\t\t\t><div class=\"dijitVerticalSliderIncrementIcon\" tabIndex=\"-1\" style=\"display:none\" dojoAttachPoint=\"incrementButton\" dojoAttachEvent=\"onclick: increment\"><span class=\"dijitSliderButtonInner\">+</span></div\n\t\t></td\n\t\t><td class=\"dijitReset\"></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\"></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><center><div class=\"dijitSliderBar dijitSliderBumper dijitVerticalSliderBumper dijitSliderTopBumper dijitVerticalSliderTopBumper\"></div></center\n\t\t></td\n\t\t><td class=\"dijitReset\"></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td dojoAttachPoint=\"leftDecoration\" class=\"dijitReset\" style=\"text-align:center;height:100%;\"></td\n\t\t><td class=\"dijitReset\" style=\"height:100%;\"\n\t\t\t><input dojoAttachPoint=\"valueNode\" type=\"hidden\" name=\"${name}\"\n\t\t\t/><center style=\"position:relative;height:100%;\" dojoAttachPoint=\"sliderBarContainer\"\n\t\t\t\t><div dojoAttachPoint=\"remainingBar\" class=\"dijitSliderBar dijitVerticalSliderBar dijitSliderRemainingBar dijitVerticalSliderRemainingBar\" dojoAttachEvent=\"onclick:_onBarClick\"></div\n\t\t\t\t><div dojoAttachPoint=\"progressBar\" class=\"dijitSliderBar dijitVerticalSliderBar dijitSliderProgressBar dijitVerticalSliderProgressBar\" dojoAttachEvent=\"onclick:_onBarClick\"\n\t\t\t\t\t><div dojoAttachPoint=\"sliderHandle,focusNode\" class=\"dijitSliderMoveable\" dojoAttachEvent=\"onkeypress:_onKeyPress,onclick:_onHandleClick\" style=\"vertical-align:top;\" waiRole=\"slider\" valuemin=\"${minimum}\" valuemax=\"${maximum}\"\n\t\t\t\t\t\t><div class=\"dijitSliderImageHandle dijitVerticalSliderImageHandle\"></div\n\t\t\t\t\t></div\n\t\t\t\t></div\n\t\t\t></center\n\t\t></td\n\t\t><td dojoAttachPoint=\"containerNode,rightDecoration\" class=\"dijitReset\" style=\"text-align:center;height:100%;\"></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\"></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><center><div class=\"dijitSliderBar dijitSliderBumper dijitVerticalSliderBumper dijitSliderBottomBumper dijitVerticalSliderBottomBumper\"></div></center\n\t\t></td\n\t\t><td class=\"dijitReset\"></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\"></td\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitVerticalSliderButtonContainer\"\n\t\t\t><div class=\"dijitVerticalSliderDecrementIcon\" tabIndex=\"-1\" style=\"display:none\" dojoAttachPoint=\"decrementButton\" dojoAttachEvent=\"onclick: decrement\"><span class=\"dijitSliderButtonInner\">-</span></div\n\t\t></td\n\t\t><td class=\"dijitReset\"></td\n\t></tr\n></tbody></table>\n",_mousePixelCoord: "pageY",_pixelCount: "h",_startingPixelCoord: "y",_startingPixelCount: "t",_handleOffsetCoord: "top",_progressPixelSize: "height",_upsideDown: true});dojo.declare("dijit.form._SliderMover",dojo.dnd.Mover,{onMouseMove: function(e){var widget = this.widget;var c = this.constraintBox;if(!c){var container = widget.sliderBarContainer;var s = dojo.getComputedStyle(container);var c = dojo._getContentBox(container, s);c[widget._startingPixelCount] = 0;this.constraintBox = c;}var m = this.marginBox;var pixelValue = widget._isReversed() ?e[widget._mousePixelCoord] - dojo._abs(widget.sliderBarContainer).x :m[widget._startingPixelCount] + e[widget._mousePixelCoord];dojo.hitch(widget, "_setPixelValue")(widget._isReversed() || widget._upsideDown? (c[widget._pixelCount]-pixelValue) : pixelValue, c[widget._pixelCount]);},destroy: function(e){var widget = this.widget;widget.setValue(widget.value, true);dojo.dnd.Mover.prototype.destroy.call(this);}});dojo.declare("dijit.form.HorizontalRule", [dijit._Widget, dijit._Templated],{// Summary:// Create hash marks for the Horizontal slidertemplateString: '<div class="RuleContainer HorizontalRuleContainer"></div>',// count: Integer// Number of hash marks to generatecount: 3,// container: Node// If this is a child widget, connect it to this parent nodecontainer: "containerNode",// ruleStyle: String// CSS style to apply to individual hash marksruleStyle: "",_positionPrefix: '<div class="RuleMark HorizontalRuleMark" style="left:',_positionSuffix: '%;',_suffix: '"></div>',_genHTML: function(pos, ndx){return this._positionPrefix + pos + this._positionSuffix + this.ruleStyle + this._suffix;},_isHorizontal: true,postCreate: function(){if(this.count==1){var innerHTML = this._genHTML(50, 0);}else{var interval = 100 / (this.count-1);if(!this._isHorizontal || this.isLeftToRight()){var innerHTML = this._genHTML(0, 0);for(var i=1; i < this.count-1; i++){innerHTML += this._genHTML(interval*i, i);}innerHTML += this._genHTML(100, this.count-1);}else{var innerHTML = this._genHTML(100, 0);for(var i=1; i < this.count-1; i++){innerHTML += this._genHTML(100-interval*i, i);}innerHTML += this._genHTML(0, this.count-1);}}this.domNode.innerHTML = innerHTML;}});dojo.declare("dijit.form.VerticalRule", dijit.form.HorizontalRule,{// Summary:// Create hash marks for the Vertical slidertemplateString: '<div class="RuleContainer VerticalRuleContainer"></div>',_positionPrefix: '<div class="RuleMark VerticalRuleMark" style="top:',_isHorizontal: false});dojo.declare("dijit.form.HorizontalRuleLabels", dijit.form.HorizontalRule,{// Summary:// Create labels for the Horizontal slidertemplateString: '<div class="RuleContainer HorizontalRuleContainer"></div>',// labelStyle: String// CSS style to apply to individual text labelslabelStyle: "",// labels: Array// Array of text labels to render - evenly spaced from left-to-right or bottom-to-toplabels: [],// numericMargin: Integer// Number of generated numeric labels that should be rendered as '' on the ends when labels[] are not specifiednumericMargin: 0,// numericMinimum: Integer// Leftmost label value for generated numeric labels when labels[] are not specifiedminimum: 0,// numericMaximum: Integer// Rightmost label value for generated numeric labels when labels[] are not specifiedmaximum: 1,// constraints: object// pattern, places, lang, et al (see dojo.number) for generated numeric labels when labels[] are not specifiedconstraints: {pattern:"#%"},_positionPrefix: '<div class="RuleLabelContainer HorizontalRuleLabelContainer" style="left:',_labelPrefix: '"><span class="RuleLabel HorizontalRuleLabel">',_suffix: '</span></div>',_calcPosition: function(pos){return pos;},_genHTML: function(pos, ndx){return this._positionPrefix + this._calcPosition(pos) + this._positionSuffix + this.labelStyle + this._labelPrefix + this.labels[ndx] + this._suffix;},getLabels: function(){// summary: user replaceable function to return the labels array// if the labels array was not specified directly, then see if <li> children werevar labels = this.labels;if(!labels.length){// for markup creation, labels are specified as child elementslabels = dojo.query("> li", this.srcNodeRef).map(function(node){return String(node.innerHTML);});}this.srcNodeRef.innerHTML = '';// if the labels were not specified directly and not as <li> children, then calculate numeric labelsif(!labels.length && this.count > 1){var start = this.minimum;var inc = (this.maximum - start) / (this.count-1);for (var i=0; i < this.count; i++){labels.push((i<this.numericMargin||i>=(this.count-this.numericMargin))? '' : dojo.number.format(start, this.constraints));start += inc;}}return labels;},postMixInProperties: function(){this.inherited('postMixInProperties', arguments);this.labels = this.getLabels();this.count = this.labels.length;}});dojo.declare("dijit.form.VerticalRuleLabels", dijit.form.HorizontalRuleLabels,{// Summary:// Create labels for the Vertical slidertemplateString: '<div class="RuleContainer VerticalRuleContainer"></div>',_positionPrefix: '<div class="RuleLabelContainer VerticalRuleLabelContainer" style="top:',_labelPrefix: '"><span class="RuleLabel VerticalRuleLabel">',_calcPosition: function(pos){return 100-pos;},_isHorizontal: false});}if(!dojo._hasResource["dijit.form.Textarea"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.form.Textarea"] = true;dojo.provide("dijit.form.Textarea");dojo.declare("dijit.form.Textarea",dijit.form._FormWidget,{// summary// A textarea that resizes vertically to contain the data.// Takes nearly all the parameters (name, value, etc.) that a vanilla textarea takes.// Cols is not supported and the width should be specified with style width.// Rows is not supported since this widget adjusts the height.// usage:// <textarea dojoType="dijit.form.TextArea">...</textarea>attributeMap: dojo.mixin(dojo.clone(dijit.form._FormWidget.prototype.attributeMap),{style:"styleNode", 'class':"styleNode"}),templateString: (dojo.isIE || dojo.isSafari || dojo.isMozilla) ?((dojo.isIE || dojo.isSafari) ? '<fieldset id="${id}" class="dijitInline dijitInputField dijitTextArea" dojoAttachPoint="styleNode" waiRole="presentation"><div dojoAttachPoint="editNode,focusNode,eventNode" dojoAttachEvent="onpaste:_changing,oncut:_changing" waiRole="textarea" style="text-decoration:none;_padding-bottom:16px;display:block;overflow:auto;" contentEditable="true"></div>': '<span id="${id}" class="dijitReset">'+'<iframe src="javascript:<html><head><title>${_iframeEditTitle}</title></head><body><script>var _postCreate=window.frameElement?window.frameElement.postCreate:null;if(_postCreate)_postCreate();</script></body></html>"'+' dojoAttachPoint="iframe,styleNode" dojoAttachEvent="onblur:_onIframeBlur" class="dijitInline dijitInputField dijitTextArea"></iframe>')+ '<textarea name="${name}" value="${value}" dojoAttachPoint="formValueNode" style="display:none;"></textarea>'+ ((dojo.isIE || dojo.isSafari) ? '</fieldset>':'</span>'): '<textarea id="${id}" name="${name}" value="${value}" dojoAttachPoint="formValueNode,editNode,focusNode,styleNode" class="dijitInputField dijitTextArea"></textarea>',focus: function(){// summary: Received focus, needed for the InlineEditBox widgetif(!this.disabled){this._changing(); // set initial height}if(dojo.isMozilla){dijit.focus(this.iframe);}else{dijit.focus(this.focusNode);}},setValue: function(/*String*/ value, /*Boolean, optional*/ priorityChange){var editNode = this.editNode;if(typeof value == "string"){editNode.innerHTML = ""; // wipe out old nodesif(value.split){var _this=this;var isFirst = true;dojo.forEach(value.split("\n"), function(line){if(isFirst){ isFirst = false; }else {editNode.appendChild(document.createElement("BR")); // preserve line breaks}editNode.appendChild(document.createTextNode(line)); // use text nodes so that imbedded tags can be edited});}else{editNode.appendChild(document.createTextNode(value));}}else{// blah<BR>blah --> blah\nblah// <P>blah</P><P>blah</P> --> blah\nblah// <DIV>blah</DIV><DIV>blah</DIV> --> blah\nblah// &<> -->&< >value = editNode.innerHTML;if(this.iframe){ // strip sizeNodevalue = value.replace(/<div><\/div>\r?\n?$/i,"");}value = value.replace(/\s*\r?\n|^\s+|\s+$| /g,"").replace(/>\s+</g,"><").replace(/<\/(p|div)>$|^<(p|div)[^>]*>/gi,"").replace(/([^>])<div>/g,"$1\n").replace(/<\/p>\s*<p[^>]*>|<br[^>]*>/gi,"\n").replace(/<[^>]*>/g,"").replace(/&/gi,"\&").replace(/</gi,"<").replace(/>/gi,">");}this.value = this.formValueNode.value = value;if(this.iframe){var sizeNode = document.createElement('div');editNode.appendChild(sizeNode);var newHeight = sizeNode.offsetTop;if(editNode.scrollWidth > editNode.clientWidth){ newHeight+=16; } // scrollbar space needed?if(this.lastHeight != newHeight){ // cache size so that we don't get a resize event because of a resize eventif(newHeight == 0){ newHeight = 16; } // height = 0 causes the browser to not set scrollHeightdojo.contentBox(this.iframe, {h: newHeight});this.lastHeight = newHeight;}editNode.removeChild(sizeNode);}dijit.form.Textarea.superclass.setValue.call(this, this.getValue(), priorityChange);},getValue: function(){return this.formValueNode.value.replace(/\r/g,"");},postMixInProperties: function(){dijit.form.Textarea.superclass.postMixInProperties.apply(this,arguments);// don't let the source text be converted to a DOM structure since we just want raw textif(this.srcNodeRef && this.srcNodeRef.innerHTML != ""){this.value = this.srcNodeRef.innerHTML;this.srcNodeRef.innerHTML = "";}if((!this.value || this.value == "") && this.srcNodeRef && this.srcNodeRef.value){this.value = this.srcNodeRef.value;}if(!this.value){ this.value = ""; }this.value = this.value.replace(/\r\n/g,"\n").replace(/>/g,">").replace(/</g,"<").replace(/&/g,"&");if(dojo.isMozilla){// In the case of Firefox an iframe is used and when the text gets focus,// focus is fired from the document object. There isn't a way to put a// waiRole on the document object and as a result screen readers don't// announce the role. As a result screen reader users are lost.//// An additional problem is that the browser gives the document object a// very cryptic accessible name, e.g.// wysiwyg://13/http://archive.dojotoolkit.org/nightly/dojotoolkit/dijit/tests/form/test_InlineEditBox.html// When focus is fired from the document object, the screen reader speaks// the accessible name. The cyptic accessile name is confusing.//// A workaround for both of these problems is to give the iframe's// document a title, the name of which is similar to a role name, i.e.// "edit area". This will be used as the accessible name which will replace// the cryptic name and will also convey the role information to the user.// Because it is read directly to the user, the string must be localized.// In addition, since a <label> element can not be associated with an iframe, if// this control has a label, insert the text into the title as well.var _nlsResources = dojo.i18n.getLocalization("dijit", "Textarea");this._iframeEditTitle = _nlsResources.iframeEditTitle;this._iframeFocusTitle = _nlsResources.iframeFocusTitle;var label=dojo.query('label[for="'+this.id+'"]');if(label.length){this._iframeEditTitle = label[0].innerHTML + " " + this._iframeEditTitle;}var body = this.focusNode = this.editNode = document.createElement('BODY');body.style.margin="0px";body.style.padding="0px";body.style.border="0px";}},postCreate: function(){if(dojo.isIE || dojo.isSafari){this.domNode.style.overflowY = 'hidden';}else if(dojo.isMozilla){var w = this.iframe.contentWindow;try { // #4715: peeking at the title can throw a security exception during iframe setupvar title = this.iframe.contentDocument.title;} catch(e) { var title = ''; }if(!w || !title){this.iframe.postCreate = dojo.hitch(this, this.postCreate);return;}var d = w.document;d.getElementsByTagName('HTML')[0].replaceChild(this.editNode, d.getElementsByTagName('BODY')[0]);if(!this.isLeftToRight()){d.getElementsByTagName('HTML')[0].dir = "rtl";}this.iframe.style.overflowY = 'hidden';this.eventNode = d;// this.connect won't destroy this handler cleanly since its on the iframe's window object// resize is a method of window, not documentw.addEventListener("resize", dojo.hitch(this, this._changed), false); // resize is only on the window object}else{this.focusNode = this.domNode;}if(this.eventNode){this.connect(this.eventNode, "keypress", this._onKeyPress);this.connect(this.eventNode, "mousemove", this._changed);this.connect(this.eventNode, "focus", this._focused);this.connect(this.eventNode, "blur", this._blurred);}if(this.editNode){this.connect(this.editNode, "change", this._changed); // needed for mouse paste events per #3479}this.inherited('postCreate', arguments);},// event handlers, you can over-ride these in your own subclasses_focused: function(e){dojo.addClass(this.iframe||this.domNode, "dijitInputFieldFocused");this._changed(e);},_blurred: function(e){dojo.removeClass(this.iframe||this.domNode, "dijitInputFieldFocused");this._changed(e, true);},_onIframeBlur: function(){// Reset the title back to "edit area".this.iframe.contentDocument.title = this._iframeEditTitle;},_onKeyPress: function(e){if(e.keyCode == dojo.keys.TAB && !e.shiftKey && !e.ctrlKey && !e.altKey && this.iframe){// Pressing the tab key in the iframe (with designMode on) will cause the// entry of a tab character so we have to trap that here. Since we don't// know the next focusable object we put focus on the iframe and then the// user has to press tab again (which then does the expected thing).// A problem with that is that the screen reader user hears "edit area"// announced twice which causes confusion. By setting the// contentDocument's title to "edit area frame" the confusion should be// eliminated.this.iframe.contentDocument.title = this._iframeFocusTitle;// Place focus on the iframe. A subsequent tab or shift tab will put focus// on the correct control.// Note: Can't use this.focus() because that results in a call to// dijit.focus and if that receives an iframe target it will set focus// on the iframe's contentWindow.this.iframe.focus(); // this.focus(); won't workdojo.stopEvent(e);}else if(e.keyCode == dojo.keys.ENTER){e.stopPropagation();}else if(this.inherited("_onKeyPress", arguments) && this.iframe){// #3752:// The key press will not make it past the iframe.// If a widget is listening outside of the iframe, (like InlineEditBox)// it will not hear anything.// Create an equivalent event so everyone else knows what is going on.var te = document.createEvent("KeyEvents");te.initKeyEvent("keypress", true, true, null, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.keyCode, e.charCode);this.iframe.dispatchEvent(te);}this._changing();},_changing: function(e){// summary: event handler for when a change is imminentsetTimeout(dojo.hitch(this, "_changed", e, false), 1);},_changed: function(e, priorityChange){// summary: event handler for when a change has already happenedif(this.iframe && this.iframe.contentDocument.designMode != "on"){this.iframe.contentDocument.designMode="on"; // in case this failed on init due to being hidden}this.setValue(null, priorityChange);}});}if(!dojo._hasResource["dijit.layout.StackContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.layout.StackContainer"] = true;dojo.provide("dijit.layout.StackContainer");dojo.declare("dijit.layout.StackContainer",dijit.layout._LayoutWidget,// summary// A container that has multiple children, but shows only// one child at a time (like looking at the pages in a book one by one).//// Publishes topics <widgetId>-addChild, <widgetId>-removeChild, and <widgetId>-selectChild//// Can be base class for container, Wizard, Show, etc.{// doLayout: Boolean// if true, change the size of my currently displayed child to match my sizedoLayout: true,_started: false,// selectedChildWidget: Widget// References the currently selected child widget, if anypostCreate: function(){dijit.setWaiRole((this.containerNode || this.domNode), "tabpanel");this.connect(this.domNode, "onkeypress", this._onKeyPress);},startup: function(){if(this._started){ return; }var children = this.getChildren();// Setup each page paneldojo.forEach(children, this._setupChild, this);// Figure out which child to initially displaydojo.some(children, function(child){if(child.selected){this.selectedChildWidget = child;}return child.selected;}, this);var selected = this.selectedChildWidget;// Default to the first childif(!selected && children[0]){selected = this.selectedChildWidget = children[0];selected.selected = true;}if(selected){this._showChild(selected);}// Now publish information about myself so any StackControllers can initialize..dojo.publish(this.id+"-startup", [{children: children, selected: selected}]);this.inherited("startup",arguments);this._started = true;},_setupChild: function(/*Widget*/ page){// Summary: prepare the given childpage.domNode.style.display = "none";// since we are setting the width/height of the child elements, they need// to be position:relative, or IE has problems (See bug #2033)page.domNode.style.position = "relative";return page; // dijit._Widget},addChild: function(/*Widget*/ child, /*Integer?*/ insertIndex){// summary: Adds a widget to the stackdijit._Container.prototype.addChild.apply(this, arguments);child = this._setupChild(child);if(this._started){// in case the tab titles have overflowed from one line to two linesthis.layout();dojo.publish(this.id+"-addChild", [child, insertIndex]);// if this is the first child, then select itif(!this.selectedChildWidget){this.selectChild(child);}}},removeChild: function(/*Widget*/ page){// summary: Removes the pane from the stackdijit._Container.prototype.removeChild.apply(this, arguments);// If we are being destroyed than don't run the code below (to select another page), because we are deleting// every page one by oneif(this._beingDestroyed){ return; }if(this._started){// this will notify any tablists to remove a button; do this first because it may affect sizingdojo.publish(this.id+"-removeChild", [page]);// in case the tab titles now take up one line instead of two linesthis.layout();}if(this.selectedChildWidget === page){this.selectedChildWidget = undefined;if(this._started){var children = this.getChildren();if(children.length){this.selectChild(children[0]);}}}},selectChild: function(/*Widget*/ page){// summary:// Show the given widget (which must be one of my children)page = dijit.byId(page);if(this.selectedChildWidget != page){// Deselect old page and select new onethis._transition(page, this.selectedChildWidget);this.selectedChildWidget = page;dojo.publish(this.id+"-selectChild", [page]);}},_transition: function(/*Widget*/newWidget, /*Widget*/oldWidget){if(oldWidget){this._hideChild(oldWidget);}this._showChild(newWidget);// Size the new widget, in case this is the first time it's being shown,// or I have been resized since the last time it was shown.// page must be visible for resizing to workif(this.doLayout && newWidget.resize){newWidget.resize(this._containerContentBox || this._contentBox);}},_adjacent: function(/*Boolean*/ forward){// summary: Gets the next/previous child widget in this container from the current selectionvar children = this.getChildren();var index = dojo.indexOf(children, this.selectedChildWidget);index += forward ? 1 : children.length - 1;return children[ index % children.length ]; // dijit._Widget},forward: function(){// Summary: advance to next pagethis.selectChild(this._adjacent(true));},back: function(){// Summary: go back to previous pagethis.selectChild(this._adjacent(false));},_onKeyPress: function(e){dojo.publish(this.id+"-containerKeyPress", [{ e: e, page: this}]);},layout: function(){if(this.doLayout && this.selectedChildWidget && this.selectedChildWidget.resize){this.selectedChildWidget.resize(this._contentBox);}},_showChild: function(/*Widget*/ page){var children = this.getChildren();page.isFirstChild = (page == children[0]);page.isLastChild = (page == children[children.length-1]);page.selected = true;page.domNode.style.display="";if(page._loadCheck){page._loadCheck(); // trigger load in ContentPane}if(page.onShow){page.onShow();}},_hideChild: function(/*Widget*/ page){page.selected=false;page.domNode.style.display="none";if(page.onHide){page.onHide();}},closeChild: function(/*Widget*/ page){// summary// callback when user clicks the [X] to remove a page// if onClose() returns true then remove and destroy the childdvar remove = page.onClose(this, page);if(remove){this.removeChild(page);// makes sure we can clean up executeScripts in ContentPane onUnLoadpage.destroy();}},destroy: function(){this._beingDestroyed = true;this.inherited("destroy",arguments);}});dojo.declare("dijit.layout.StackController",[dijit._Widget, dijit._Templated, dijit._Container],{// summary:// Set of buttons to select a page in a page list.// Monitors the specified StackContainer, and whenever a page is// added, deleted, or selected, updates itself accordingly.templateString: "<span wairole='tablist' dojoAttachEvent='onkeypress' class='dijitStackController'></span>",// containerId: String// the id of the page container that I point tocontainerId: "",// buttonWidget: String// the name of the button widget to create to correspond to each pagebuttonWidget: "dijit.layout._StackButton",postCreate: function(){dijit.setWaiRole(this.domNode, "tablist");this.pane2button = {}; // mapping from panes to buttonsthis._subscriptions=[dojo.subscribe(this.containerId+"-startup", this, "onStartup"),dojo.subscribe(this.containerId+"-addChild", this, "onAddChild"),dojo.subscribe(this.containerId+"-removeChild", this, "onRemoveChild"),dojo.subscribe(this.containerId+"-selectChild", this, "onSelectChild"),dojo.subscribe(this.containerId+"-containerKeyPress", this, "onContainerKeyPress")];},onStartup: function(/*Object*/ info){// summary: called after StackContainer has finished initializingdojo.forEach(info.children, this.onAddChild, this);this.onSelectChild(info.selected);},destroy: function(){dojo.forEach(this._subscriptions, dojo.unsubscribe);this.inherited("destroy",arguments);},onAddChild: function(/*Widget*/ page, /*Integer?*/ insertIndex){// summary:// Called whenever a page is added to the container.// Create button corresponding to the page.// add a node that will be promoted to the button widgetvar refNode = document.createElement("span");this.domNode.appendChild(refNode);// create an instance of the button widgetvar cls = dojo.getObject(this.buttonWidget);var button = new cls({label: page.title, closeButton: page.closable}, refNode);this.addChild(button, insertIndex);this.pane2button[page] = button;page.controlButton = button; // this value might be overwritten if two tabs point to same containerdojo.connect(button, "onClick", dojo.hitch(this,"onButtonClick",page));dojo.connect(button, "onClickCloseButton", dojo.hitch(this,"onCloseButtonClick",page));if(!this._currentChild){ // put the first child into the tab orderbutton.focusNode.setAttribute("tabIndex","0");this._currentChild = page;}},onRemoveChild: function(/*Widget*/ page){// summary:// Called whenever a page is removed from the container.// Remove the button corresponding to the page.if(this._currentChild === page){ this._currentChild = null; }var button = this.pane2button[page];if(button){// TODO? if current child { reassign }button.destroy();}this.pane2button[page] = null;},onSelectChild: function(/*Widget*/ page){// summary:// Called when a page has been selected in the StackContainer, either by me or by another StackControllerif(!page){ return; }if(this._currentChild){var oldButton=this.pane2button[this._currentChild];oldButton.setChecked(false);oldButton.focusNode.setAttribute("tabIndex", "-1");}var newButton=this.pane2button[page];newButton.setChecked(true);this._currentChild = page;newButton.focusNode.setAttribute("tabIndex", "0");},onButtonClick: function(/*Widget*/ page){// summary:// Called whenever one of my child buttons is pressed in an attempt to select a pagevar container = dijit.byId(this.containerId); // TODO: do this via topics?container.selectChild(page);},onCloseButtonClick: function(/*Widget*/ page){// summary:// Called whenever one of my child buttons [X] is pressed in an attempt to close a pagevar container = dijit.byId(this.containerId);container.closeChild(page);var b = this.pane2button[this._currentChild];if(b){dijit.focus(b.focusNode || b.domNode);}},// TODO: this is a bit redundant with forward, back api in StackContaineradjacent: function(/*Boolean*/ forward){// find currently focused button in children arrayvar children = this.getChildren();var current = dojo.indexOf(children, this.pane2button[this._currentChild]);// pick next button to focus onvar offset = forward ? 1 : children.length - 1;return children[ (current + offset) % children.length ]; // dijit._Widget},onkeypress: function(/*Event*/ e){// summary:// Handle keystrokes on the page list, for advancing to next/previous button// and closing the current page if the page is closable.if(this.disabled || e.altKey ){ return; }var forward = true;if(e.ctrlKey || !e._djpage){var k = dojo.keys;switch(e.keyCode){case k.LEFT_ARROW:case k.UP_ARROW:case k.PAGE_UP:forward = false;// fall throughcase k.RIGHT_ARROW:case k.DOWN_ARROW:case k.PAGE_DOWN:this.adjacent(forward).onClick();dojo.stopEvent(e);break;case k.DELETE:if(this._currentChild.closable){this.onCloseButtonClick(this._currentChild);}dojo.stopEvent(e);break;default:if(e.ctrlKey){if(e.keyCode == k.TAB){this.adjacent(!e.shiftKey).onClick();dojo.stopEvent(e);}else if(e.keyChar == "w"){if(this._currentChild.closable){this.onCloseButtonClick(this._currentChild);}dojo.stopEvent(e); // avoid browser tab closing.}}}}},onContainerKeyPress: function(/*Object*/ info){info.e._djpage = info.page;this.onkeypress(info.e);}});dojo.declare("dijit.layout._StackButton",dijit.form.ToggleButton,{// summary// Internal widget used by StackContainer.// The button-like or tab-like object you click to select or delete a pagetabIndex: "-1", // StackContainer buttons are not in the tab order by defaultpostCreate: function(/*Event*/ evt){dijit.setWaiRole((this.focusNode || this.domNode), "tab");this.inherited("postCreate", arguments);},onClick: function(/*Event*/ evt){// summary: This is for TabContainer where the tabs are <span> rather than button,// so need to set focus explicitly (on some browsers)dijit.focus(this.focusNode);// ... now let StackController catch the event and tell me what to do},onClickCloseButton: function(/*Event*/ evt){// summary// StackContainer connects to this function; if your widget contains a close button// then clicking it should call this function.evt.stopPropagation();}});// These arguments can be specified for the children of a StackContainer.// Since any widget can be specified as a StackContainer child, mix them// into the base widget class. (This is a hack, but it's effective.)dojo.extend(dijit._Widget, {// title: String// Title of this widget. Used by TabContainer to the name the tab, etc.title: "",// selected: Boolean// Is this child currently selected?selected: false,// closable: Boolean// True if user can close (destroy) this child, such as (for example) clicking the X on the tab.closable: false, // true if user can close this tab paneonClose: function(){// summary: Callback if someone tries to close the child, child will be closed if func returns truereturn true;}});}if(!dojo._hasResource["dijit.layout.AccordionContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.layout.AccordionContainer"] = true;dojo.provide("dijit.layout.AccordionContainer");dojo.declare("dijit.layout.AccordionContainer",dijit.layout.StackContainer,{// summary:// Holds a set of panes where every pane's title is visible, but only one pane's content is visible at a time,// and switching between panes is visualized by sliding the other panes up/down.// usage:// <div dojoType="dijit.layout.AccordionContainer">// <div dojoType="dijit.layout.AccordionPane" title="pane 1">// <div dojoType="dijit.layout.ContentPane">...</div>// </div>// <div dojoType="dijit.layout.AccordionPane" title="pane 2">// <p>This is some text</p>// ...// </div>// duration: Integer// Amount of time (in ms) it takes to slide panesduration: 250,_verticalSpace: 0,postCreate: function(){this.domNode.style.overflow="hidden";this.inherited("postCreate",arguments);dijit.setWaiRole(this.domNode, "tablist");dojo.addClass(this.domNode,"dijitAccordionContainer");},startup: function(){if(this._started){ return; }this.inherited("startup",arguments);if(this.selectedChildWidget){var style = this.selectedChildWidget.containerNode.style;style.display = "";style.overflow = "auto";this.selectedChildWidget._setSelectedState(true);}},layout: function(){// summary// Set the height of the open pane based on what room remains// get cumulative height of all the title bars, and figure out which pane is openvar totalCollapsedHeight = 0;var openPane = this.selectedChildWidget;dojo.forEach(this.getChildren(), function(child){totalCollapsedHeight += child.getTitleHeight();});var mySize = this._contentBox;this._verticalSpace = (mySize.h - totalCollapsedHeight);if(openPane){openPane.containerNode.style.height = this._verticalSpace + "px";/***TODO: this is wrong. probably you wanted to call resize on the SplitContainerinside the AccordionPane??if(openPane.resize){openPane.resize({h: this._verticalSpace});}***/}},_setupChild: function(/*Widget*/ page){// Summary: prepare the given childreturn page;},_transition: function(/*Widget?*/newWidget, /*Widget?*/oldWidget){//TODO: should be able to replace this with calls to slideIn/slideOutif(this._inTransition){ return; }this._inTransition = true;var animations = [];var paneHeight = this._verticalSpace;if(newWidget){newWidget.setSelected(true);var newContents = newWidget.containerNode;newContents.style.display = "";animations.push(dojo.animateProperty({node: newContents,duration: this.duration,properties: {height: { start: "1", end: paneHeight }},onEnd: function(){newContents.style.overflow = "auto";}}));}if(oldWidget){oldWidget.setSelected(false);var oldContents = oldWidget.containerNode;oldContents.style.overflow = "hidden";animations.push(dojo.animateProperty({node: oldContents,duration: this.duration,properties: {height: { start: paneHeight, end: "1" }},onEnd: function(){oldContents.style.display = "none";}}));}this._inTransition = false;dojo.fx.combine(animations).play();},// note: we are treating the container as controller here_onKeyPress: function(/*Event*/ e){if(this.disabled || e.altKey ){ return; }var k = dojo.keys;switch(e.keyCode){case k.LEFT_ARROW:case k.UP_ARROW:case k.PAGE_UP:this._adjacent(false)._onTitleClick();dojo.stopEvent(e);break;case k.RIGHT_ARROW:case k.DOWN_ARROW:case k.PAGE_DOWN:this._adjacent(true)._onTitleClick();dojo.stopEvent(e);break;default:if(e.ctrlKey && e.keyCode == k.TAB){this._adjacent(e._dijitWidget, !e.shiftKey)._onTitleClick();dojo.stopEvent(e);}}}});dojo.declare("dijit.layout.AccordionPane",[dijit.layout.ContentPane, dijit._Templated, dijit._Contained],{// summary// AccordionPane is a ContentPane with a title that may contain another widget.// Nested layout widgets, such as SplitContainer, are not supported at this time.templateString:"<div class='dijitAccordionPane'\n\t><div dojoAttachPoint='titleNode,focusNode' dojoAttachEvent='ondijitclick:_onTitleClick,onkeypress:_onTitleKeyPress,onfocus:_handleFocus,onblur:_handleFocus'\n\t\tclass='dijitAccordionTitle' wairole=\"tab\"\n\t\t><div class='dijitAccordionArrow'></div\n\t\t><div class='arrowTextUp' waiRole=\"presentation\">▲</div\n\t\t><div class='arrowTextDown' waiRole=\"presentation\">▼</div\n\t\t><div dojoAttachPoint='titleTextNode' class='dijitAccordionText'>${title}</div></div\n\t><div><div dojoAttachPoint='containerNode' style='overflow: hidden; height: 1px; display: none'\n\t\tclass='dijitAccordionBody' wairole=\"tabpanel\"\n\t></div></div>\n</div>\n",postCreate: function(){this.inherited("postCreate",arguments)dojo.setSelectable(this.titleNode, false);this.setSelected(this.selected);},getTitleHeight: function(){// summary: returns the height of the title dom nodereturn dojo.marginBox(this.titleNode).h; // Integer},_onTitleClick: function(){// summary: callback when someone clicks my titlevar parent = this.getParent();if(!parent._inTransition){parent.selectChild(this);dijit.focus(this.focusNode);}},_onTitleKeyPress: function(/*Event*/ evt){evt._dijitWidget = this;return this.getParent()._onKeyPress(evt);},_setSelectedState: function(/*Boolean*/ isSelected){this.selected = isSelected;dojo[(isSelected ? "addClass" : "removeClass")](this.domNode,"dijitAccordionPane-selected");this.focusNode.setAttribute("tabIndex", isSelected ? "0" : "-1");},_handleFocus: function(/*Event*/e){// summary: handle the blur and focus state of this widgetdojo[(e.type=="focus" ? "addClass" : "removeClass")](this.focusNode,"dijitAccordionPaneFocused");},setSelected: function(/*Boolean*/ isSelected){// summary: change the selected state on this panethis._setSelectedState(isSelected);if(isSelected){ this.onSelected(); }},onSelected: function(){// summary: called when this pane is selected}});}if(!dojo._hasResource["dijit.layout.LayoutContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.layout.LayoutContainer"] = true;dojo.provide("dijit.layout.LayoutContainer");dojo.declare("dijit.layout.LayoutContainer",dijit.layout._LayoutWidget,{// summary// Provides Delphi-style panel layout semantics.//// details// A LayoutContainer is a box with a specified size (like style="width: 500px; height: 500px;"),// that contains children widgets marked with "layoutAlign" of "left", "right", "bottom", "top", and "client".// It takes it's children marked as left/top/bottom/right, and lays them out along the edges of the box,// and then it takes the child marked "client" and puts it into the remaining space in the middle.//// Left/right positioning is similar to CSS's "float: left" and "float: right",// and top/bottom positioning would be similar to "float: top" and "float: bottom", if there were such// CSS.//// Note that there can only be one client element, but there can be multiple left, right, top,// or bottom elements.//// usage// <style>// html, body{ height: 100%; width: 100%; }// </style>// <div dojoType="dijit.layout.LayoutContainer" style="width: 100%; height: 100%">// <div dojoType="dijit.layout.ContentPane" layoutAlign="top">header text</div>// <div dojoType="dijit.layout.ContentPane" layoutAlign="left" style="width: 200px;">table of contents</div>// <div dojoType="dijit.layout.ContentPane" layoutAlign="client">client area</div>// </div>//// Lays out each child in the natural order the children occur in.// Basically each child is laid out into the "remaining space", where "remaining space" is initially// the content area of this widget, but is reduced to a smaller rectangle each time a child is added.//layout: function(){dijit.layout.layoutChildren(this.domNode, this._contentBox, this.getChildren());},addChild: function(/*Widget*/ child, /*Integer?*/ insertIndex){dijit._Container.prototype.addChild.apply(this, arguments);if(this._started){dijit.layout.layoutChildren(this.domNode, this._contentBox, this.getChildren());}},removeChild: function(/*Widget*/ widget){dijit._Container.prototype.removeChild.apply(this, arguments);if(this._started){dijit.layout.layoutChildren(this.domNode, this._contentBox, this.getChildren());}}});// This argument can be specified for the children of a LayoutContainer.// Since any widget can be specified as a LayoutContainer child, mix it// into the base widget class. (This is a hack, but it's effective.)dojo.extend(dijit._Widget, {// layoutAlign: String// "none", "left", "right", "bottom", "top", and "client".// See the LayoutContainer description for details on this parameter.layoutAlign: 'none'});}if(!dojo._hasResource["dijit.layout.LinkPane"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.layout.LinkPane"] = true;dojo.provide("dijit.layout.LinkPane");dojo.declare("dijit.layout.LinkPane",[dijit.layout.ContentPane, dijit._Templated],{// summary:// A ContentPane that loads data remotely// description:// LinkPane is just a ContentPane that loads data remotely (via the href attribute),// and has markup similar to an anchor. The anchor's body (the words between <a> and </a>)// become the title of the widget (used for TabContainer, AccordionContainer, etc.)// example:// <a href="foo.html">my title</a>// I'm using a template because the user may specify the input as// <a href="foo.html">title</a>, in which case we need to get rid of the// <a> because we don't want a link.templateString: '<div class="dijitLinkPane"></div>',postCreate: function(){// If user has specified node contents, they become the title// (the link must be plain text)if(this.srcNodeRef){this.title += this.srcNodeRef.innerHTML;}this.inherited("postCreate",arguments);}});}if(!dojo._hasResource["dijit.layout.SplitContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.layout.SplitContainer"] = true;dojo.provide("dijit.layout.SplitContainer");//// FIXME: make it prettier// FIXME: active dragging upwards doesn't always shift other bars (direction calculation is wrong in this case)//dojo.declare("dijit.layout.SplitContainer",dijit.layout._LayoutWidget,{// summary:// A Container widget with sizing handles in-between each child// description:// Contains multiple children widgets, all of which are displayed side by side// (either horizontally or vertically); there's a bar between each of the children,// and you can adjust the relative size of each child by dragging the bars.//// You must specify a size (width and height) for the SplitContainer.//// activeSizing: Boolean// If true, the children's size changes as you drag the bar;// otherwise, the sizes don't change until you drop the bar (by mouse-up)activeSizing: false,// sizerWidth: Integer// Size in pixels of the bar between each childsizerWidth: 7, // FIXME: this should be a CSS attribute (at 7 because css wants it to be 7 until we fix to css)// orientation: String// either 'horizontal' or vertical; indicates whether the children are// arranged side-by-side or up/down.orientation: 'horizontal',// persist: Boolean// Save splitter positions in a cookiepersist: true,postMixInProperties: function(){this.inherited("postMixInProperties",arguments);this.isHorizontal = (this.orientation == 'horizontal');},postCreate: function(){this.inherited("postCreate",arguments);this.sizers = [];dojo.addClass(this.domNode, "dijitSplitContainer");// overflow has to be explicitly hidden for splitContainers using gekko (trac #1435)// to keep other combined css classes from inadvertantly making the overflow visibleif(dojo.isMozilla){this.domNode.style.overflow = '-moz-scrollbars-none'; // hidden doesn't work}// create the fake draggerif(typeof this.sizerWidth == "object"){try{ //FIXME: do this without a try/catchthis.sizerWidth = parseInt(this.sizerWidth.toString());}catch(e){ this.sizerWidth = 7; }}var sizer = this.virtualSizer = document.createElement('div');sizer.style.position = 'relative';// #1681: work around the dreaded 'quirky percentages in IE' layout bug// If the splitcontainer's dimensions are specified in percentages, it// will be resized when the virtualsizer is displayed in _showSizingLine// (typically expanding its bounds unnecessarily). This happens because// we use position: relative for .dijitSplitContainer.// The workaround: instead of changing the display style attribute,// switch to changing the zIndex (bring to front/move to back)sizer.style.zIndex = 10;sizer.className = this.isHorizontal ? 'dijitSplitContainerVirtualSizerH' : 'dijitSplitContainerVirtualSizerV';this.domNode.appendChild(sizer);dojo.setSelectable(sizer, false);},startup: function(){if(this._started){ return; }dojo.forEach(this.getChildren(), function(child, i, children){// attach the children and create the draggersthis._injectChild(child);if(i < children.length-1){this._addSizer();}}, this);if(this.persist){this._restoreState();}this.inherited("startup",arguments);this._started = true;},_injectChild: function(child){child.domNode.style.position = "absolute";dojo.addClass(child.domNode, "dijitSplitPane");},_addSizer: function(){var i = this.sizers.length;// TODO: use a template for this!!!var sizer = this.sizers[i] = document.createElement('div');sizer.className = this.isHorizontal ? 'dijitSplitContainerSizerH' : 'dijitSplitContainerSizerV';// add the thumb divvar thumb = document.createElement('div');thumb.className = 'thumb';sizer.appendChild(thumb);// FIXME: are you serious? why aren't we using mover start/stop combo?var self = this;var handler = (function(){ var sizer_i = i; return function(e){ self.beginSizing(e, sizer_i); } })();dojo.connect(sizer, "onmousedown", handler);this.domNode.appendChild(sizer);dojo.setSelectable(sizer, false);},removeChild: function(widget){// summary: Remove sizer, but only if widget is really our child and// we have at least one sizer to throw awayif(this.sizers.length && dojo.indexOf(this.getChildren(), widget) != -1){var i = this.sizers.length - 1;dojo._destroyElement(this.sizers[i]);this.sizers.length--;}// Remove widget and repaintthis.inherited("removeChild",arguments);if(this._started){this.layout();}},addChild: function(/*Widget*/ child, /*Integer?*/ insertIndex){// summary: Add a child widget to the container// child: a widget to add// insertIndex: postion in the "stack" to add the child widgetthis.inherited("addChild",arguments);if(this._started){// Do the stuff that startup() does for each widgetthis._injectChild(child);var children = this.getChildren();if(children.length > 1){this._addSizer();}// and then reposition (ie, shrink) every pane to make room for the new guythis.layout();}},layout: function(){// summary:// Do layout of panels// base class defines this._contentBox on initial creation and also// on resizethis.paneWidth = this._contentBox.w;this.paneHeight = this._contentBox.h;var children = this.getChildren();if(!children.length){ return; }//// calculate space//var space = this.isHorizontal ? this.paneWidth : this.paneHeight;if(children.length > 1){space -= this.sizerWidth * (children.length - 1);}//// calculate total of SizeShare values//var outOf = 0;dojo.forEach(children, function(child){outOf += child.sizeShare;});//// work out actual pixels per sizeshare unit//var pixPerUnit = space / outOf;//// set the SizeActual member of each pane//var totalSize = 0;dojo.forEach(children.slice(0, children.length - 1), function(child){var size = Math.round(pixPerUnit * child.sizeShare);child.sizeActual = size;totalSize += size;});children[children.length-1].sizeActual = space - totalSize;//// make sure the sizes are ok//this._checkSizes();//// now loop, positioning each pane and letting children resize themselves//var pos = 0;var size = children[0].sizeActual;this._movePanel(children[0], pos, size);children[0].position = pos;pos += size;// if we don't have any sizers, our layout method hasn't been called yet// so bail until we are called..TODO: REVISIT: need to change the startup// algorithm to guaranteed the ordering of calls to layout methodif(!this.sizers){return;}dojo.some(children.slice(1), function(child, i){// error-checkingif(!this.sizers[i]){return true;}// first we position the sizing handle before this panethis._moveSlider(this.sizers[i], pos, this.sizerWidth);this.sizers[i].position = pos;pos += this.sizerWidth;size = child.sizeActual;this._movePanel(child, pos, size);child.position = pos;pos += size;}, this);},_movePanel: function(panel, pos, size){if(this.isHorizontal){panel.domNode.style.left = pos + 'px'; // TODO: resize() takes l and t parameters too, don't need to set manuallypanel.domNode.style.top = 0;var box = {w: size, h: this.paneHeight};if(panel.resize){panel.resize(box);}else{dojo.marginBox(panel.domNode, box);}}else{panel.domNode.style.left = 0; // TODO: resize() takes l and t parameters too, don't need to set manuallypanel.domNode.style.top = pos + 'px';var box = {w: this.paneWidth, h: size};if(panel.resize){panel.resize(box);}else{dojo.marginBox(panel.domNode, box);}}},_moveSlider: function(slider, pos, size){if(this.isHorizontal){slider.style.left = pos + 'px';slider.style.top = 0;dojo.marginBox(slider, { w: size, h: this.paneHeight });}else{slider.style.left = 0;slider.style.top = pos + 'px';dojo.marginBox(slider, { w: this.paneWidth, h: size });}},_growPane: function(growth, pane){if(growth > 0){if(pane.sizeActual > pane.sizeMin){if((pane.sizeActual - pane.sizeMin) > growth){// stick all the growth in this panepane.sizeActual = pane.sizeActual - growth;growth = 0;}else{// put as much growth in here as we cangrowth -= pane.sizeActual - pane.sizeMin;pane.sizeActual = pane.sizeMin;}}}return growth;},_checkSizes: function(){var totalMinSize = 0;var totalSize = 0;var children = this.getChildren();dojo.forEach(children, function(child){totalSize += child.sizeActual;totalMinSize += child.sizeMin;});// only make adjustments if we have enough space for all the minimumsif(totalMinSize <= totalSize){var growth = 0;dojo.forEach(children, function(child){if(child.sizeActual < child.sizeMin){growth += child.sizeMin - child.sizeActual;child.sizeActual = child.sizeMin;}});if(growth > 0){var list = this.isDraggingLeft ? children.reverse() : children;dojo.forEach(list, function(child){growth = this._growPane(growth, child);}, this);}}else{dojo.forEach(children, function(child){child.sizeActual = Math.round(totalSize * (child.sizeMin / totalMinSize));});}},beginSizing: function(e, i){var children = this.getChildren();this.paneBefore = children[i];this.paneAfter = children[i+1];this.isSizing = true;this.sizingSplitter = this.sizers[i];if(!this.cover){this.cover = dojo.doc.createElement('div');this.domNode.appendChild(this.cover);var s = this.cover.style;s.position = 'absolute';s.zIndex = 1;s.top = 0;s.left = 0;s.width = "100%";s.height = "100%";}else{this.cover.style.zIndex = 1;}this.sizingSplitter.style.zIndex = 2;// TODO: REVISIT - we want MARGIN_BOX and core hasn't exposed that yet (but can't we use it anyway if we pay attention? we do elsewhere.)this.originPos = dojo.coords(children[0].domNode, true);if(this.isHorizontal){var client = (e.layerX ? e.layerX : e.offsetX);var screen = e.pageX;this.originPos = this.originPos.x;}else{var client = (e.layerY ? e.layerY : e.offsetY);var screen = e.pageY;this.originPos = this.originPos.y;}this.startPoint = this.lastPoint = screen;this.screenToClientOffset = screen - client;this.dragOffset = this.lastPoint - this.paneBefore.sizeActual - this.originPos - this.paneBefore.position;if(!this.activeSizing){this._showSizingLine();}//// attach mouse events//this._connects = [];this._connects.push(dojo.connect(document.documentElement, "onmousemove", this, "changeSizing"));this._connects.push(dojo.connect(document.documentElement, "onmouseup", this, "endSizing"));dojo.stopEvent(e);},changeSizing: function(e){if(!this.isSizing){ return; }this.lastPoint = this.isHorizontal ? e.pageX : e.pageY;this.movePoint();if(this.activeSizing){this._updateSize();}else{this._moveSizingLine();}dojo.stopEvent(e);},endSizing: function(e){if(!this.isSizing){ return; }if(this.cover){this.cover.style.zIndex = -1;}if(!this.activeSizing){this._hideSizingLine();}this._updateSize();this.isSizing = false;if(this.persist){this._saveState(this);}dojo.forEach(this._connects,dojo.disconnect);},movePoint: function(){// make sure lastPoint is a legal point to drag tovar p = this.lastPoint - this.screenToClientOffset;var a = p - this.dragOffset;a = this.legaliseSplitPoint(a);p = a + this.dragOffset;this.lastPoint = p + this.screenToClientOffset;},legaliseSplitPoint: function(a){a += this.sizingSplitter.position;this.isDraggingLeft = !!(a > 0);if(!this.activeSizing){var min = this.paneBefore.position + this.paneBefore.sizeMin;if(a < min){a = min;}var max = this.paneAfter.position + (this.paneAfter.sizeActual - (this.sizerWidth + this.paneAfter.sizeMin));if(a > max){a = max;}}a -= this.sizingSplitter.position;this._checkSizes();return a;},_updateSize: function(){//FIXME: sometimes this.lastPoint is NaNvar pos = this.lastPoint - this.dragOffset - this.originPos;var start_region = this.paneBefore.position;var end_region = this.paneAfter.position + this.paneAfter.sizeActual;this.paneBefore.sizeActual = pos - start_region;this.paneAfter.position = pos + this.sizerWidth;this.paneAfter.sizeActual = end_region - this.paneAfter.position;dojo.forEach(this.getChildren(), function(child){child.sizeShare = child.sizeActual;});if(this._started){this.layout();}},_showSizingLine: function(){this._moveSizingLine();dojo.marginBox(this.virtualSizer,this.isHorizontal ? { w: this.sizerWidth, h: this.paneHeight } : { w: this.paneWidth, h: this.sizerWidth });this.virtualSizer.style.display = 'block';},_hideSizingLine: function(){this.virtualSizer.style.display = 'none';},_moveSizingLine: function(){var pos = (this.lastPoint - this.startPoint) + this.sizingSplitter.position;dojo.style(this.virtualSizer,(this.isHorizontal ? "left" : "top"),pos+"px");// this.virtualSizer.style[ this.isHorizontal ? "left" : "top" ] = pos + 'px'; // FIXME: remove this line if the previous is better},_getCookieName: function(i){return this.id + "_" + i;},_restoreState: function(){dojo.forEach(this.getChildren(), function(child, i){var cookieName = this._getCookieName(i);var cookieValue = dojo.cookie(cookieName);if(cookieValue){var pos = parseInt(cookieValue);if(typeof pos == "number"){child.sizeShare = pos;}}}, this);},_saveState: function(){dojo.forEach(this.getChildren(), function(child, i){dojo.cookie(this._getCookieName(i), child.sizeShare);}, this);}});// These arguments can be specified for the children of a SplitContainer.// Since any widget can be specified as a SplitContainer child, mix them// into the base widget class. (This is a hack, but it's effective.)dojo.extend(dijit._Widget, {// sizeMin: Integer// Minimum size (width or height) of a child of a SplitContainer.// The value is relative to other children's sizeShare properties.sizeMin: 10,// sizeShare: Integer// Size (width or height) of a child of a SplitContainer.// The value is relative to other children's sizeShare properties.// For example, if there are two children and each has sizeShare=10, then// each takes up 50% of the available space.sizeShare: 10});}if(!dojo._hasResource["dijit.layout.TabContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.layout.TabContainer"] = true;dojo.provide("dijit.layout.TabContainer");dojo.declare("dijit.layout.TabContainer",[dijit.layout.StackContainer, dijit._Templated],{// summary:// A Container with Title Tabs, each one pointing at a pane in the container.// description:// A TabContainer is a container that has multiple panes, but shows only// one pane at a time. There are a set of tabs corresponding to each pane,// where each tab has the title (aka title) of the pane, and optionally a close button.//// Publishes topics <widgetId>-addChild, <widgetId>-removeChild, and <widgetId>-selectChild// (where <widgetId> is the id of the TabContainer itself.//// tabPosition: String// Defines where tabs go relative to tab content.// "top", "bottom", "left-h", "right-h"tabPosition: "top",templateString: null, // override setting in StackContainertemplateString:"<div class=\"dijitTabContainer\">\n\t<div dojoAttachPoint=\"tablistNode\"></div>\n\t<div class=\"dijitTabPaneWrapper\" dojoAttachPoint=\"containerNode\"></div>\n</div>\n",postCreate: function(){dijit.layout.TabContainer.superclass.postCreate.apply(this, arguments);// create the tab list that will have a tab (a.k.a. tab button) for each tab panelthis.tablist = new dijit.layout.TabController({id: this.id + "_tablist",tabPosition: this.tabPosition,doLayout: this.doLayout,containerId: this.id}, this.tablistNode);},_setupChild: function(/* Widget */tab){dojo.addClass(tab.domNode, "dijitTabPane");this.inherited("_setupChild",arguments);return tab; // Widget},startup: function(){if(this._started){ return; }// wire up the tablist and its tabsthis.tablist.startup();this.inherited("startup",arguments);if(dojo.isSafari){// sometimes safari 3.0.3 miscalculates the height of the tab labels, see #4058setTimeout(dojo.hitch(this, "layout"), 0);}},layout: function(){// Summary: Configure the content pane to take up all the space except for where the tabs areif(!this.doLayout){ return; }// position and size the titles and the container nodevar titleAlign=this.tabPosition.replace(/-h/,"");var children = [{domNode: this.tablist.domNode, layoutAlign: titleAlign},{domNode: this.containerNode, layoutAlign: "client"}];dijit.layout.layoutChildren(this.domNode, this._contentBox, children);// Compute size to make each of my children.// children[1] is the margin-box size of this.containerNode, set by layoutChildren() call abovethis._containerContentBox = dijit.layout.marginBox2contentBox(this.containerNode, children[1]);if(this.selectedChildWidget){this._showChild(this.selectedChildWidget);if(this.doLayout && this.selectedChildWidget.resize){this.selectedChildWidget.resize(this._containerContentBox);}}},destroy: function(){this.tablist.destroy();this.inherited("destroy",arguments);}});//TODO: make private?dojo.declare("dijit.layout.TabController",dijit.layout.StackController,{// summary:// Set of tabs (the things with titles and a close button, that you click to show a tab panel).// description:// Lets the user select the currently shown pane in a TabContainer or StackContainer.// TabController also monitors the TabContainer, and whenever a pane is// added or deleted updates itself accordingly.templateString: "<div wairole='tablist' dojoAttachEvent='onkeypress:onkeypress'></div>",// tabPosition: String// Defines where tabs go relative to the content.// "top", "bottom", "left-h", "right-h"tabPosition: "top",// doLayout: Boolean// TODOC: deprecate doLayout? not sure.doLayout: true,// buttonWidget: String// the name of the tab widget to create to correspond to each pagebuttonWidget: "dijit.layout._TabButton",postMixInProperties: function(){this["class"] = "dijitTabLabels-" + this.tabPosition + (this.doLayout ? "" : " dijitTabNoLayout");this.inherited("postMixInProperties",arguments);}});dojo.declare("dijit.layout._TabButton",dijit.layout._StackButton,{// summary:// A tab (the thing you click to select a pane).// description:// Contains the title of the pane, and optionally a close-button to destroy the pane.// This is an internal widget and should not be instantiated directly.baseClass: "dijitTab",templateString:"<div dojoAttachEvent='onclick:onClick,onmouseenter:_onMouse,onmouseleave:_onMouse'>\n <div class='dijitTabInnerDiv' dojoAttachPoint='innerDiv'>\n <span dojoAttachPoint='containerNode,focusNode'>${!label}</span>\n <span dojoAttachPoint='closeButtonNode' class='closeImage' dojoAttachEvent='onmouseenter:_onMouse, onmouseleave:_onMouse, onclick:onClickCloseButton' stateModifier='CloseButton'>\n <span dojoAttachPoint='closeText' class='closeText'>x</span>\n </span>\n </div>\n</div>\n",postCreate: function(){if(this.closeButton){dojo.addClass(this.innerDiv, "dijitClosable");} else {this.closeButtonNode.style.display="none";}this.inherited("postCreate",arguments);dojo.setSelectable(this.containerNode, false);}});}if(!dojo._hasResource["dijit.dijit-all"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.dojo._hasResource["dijit.dijit-all"] = true;console.warn("dijit-all may include much more code than your application actually requires. We strongly recommend that you investigate a custom build or the web build tool");dojo.provide("dijit.dijit-all");}dojo.i18n._preloadLocalizations("dijit.nls.dijit-all", ["es-es", "es", "hu", "it-it", "de", "pt-br", "pl", "fr-fr", "zh-cn", "pt", "en-us", "zh", "ru", "xx", "fr", "zh-tw", "it", "cs", "en-gb", "de-de", "ja-jp", "ko-kr", "ko", "en", "ROOT", "ja"]);