require({cache:{ 'dijit/form/TextBox':function(){ require({cache:{ 'url:dijit/form/templates/TextBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\" id=\"widget_${id}\" role=\"presentation\"\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class=\"dijitReset dijitInputInner\" data-dojo-attach-point='textbox,focusNode' autocomplete=\"off\"\n\t\t\t${!nameAttrSetting} type='${type}'\n\t/></div\n></div>\n"}}); define("dijit/form/TextBox", [ "dojo/_base/declare", // declare "dojo/dom-construct", // domConstruct.create "dojo/dom-style", // domStyle.getComputedStyle "dojo/_base/kernel", // kernel.deprecated "dojo/_base/lang", // lang.hitch "dojo/_base/sniff", // has("ie") has("mozilla") "dojo/_base/window", // win.doc.selection.createRange "./_FormValueWidget", "./_TextBoxMixin", "dojo/text!./templates/TextBox.html", ".." // to export dijit._setSelectionRange, remove in 2.0 ], function(declare, domConstruct, domStyle, kernel, lang, has, win, _FormValueWidget, _TextBoxMixin, template, dijit){ /*===== var _FormValueWidget = dijit.form._FormValueWidget; var _TextBoxMixin = dijit.form._TextBoxMixin; =====*/ // module: // dijit/form/TextBox // summary: // A base class for textbox form inputs var TextBox = declare(/*====="dijit.form.TextBox", =====*/ [_FormValueWidget, _TextBoxMixin], { // summary: // A base class for textbox form inputs templateString: template, _singleNodeTemplate: '<input class="dijit dijitReset dijitLeft dijitInputField" data-dojo-attach-point="textbox,focusNode" autocomplete="off" type="${type}" ${!nameAttrSetting} />', _buttonInputDisabled: has("ie") ? "disabled" : "", // allows IE to disallow focus, but Firefox cannot be disabled for mousedown events baseClass: "dijitTextBox", postMixInProperties: function(){ var type = this.type.toLowerCase(); if(this.templateString && this.templateString.toLowerCase() == "input" || ((type == "hidden" || type == "file") && this.templateString == this.constructor.prototype.templateString)){ this.templateString = this._singleNodeTemplate; } this.inherited(arguments); }, _onInput: function(e){ this.inherited(arguments); if(this.intermediateChanges){ // _TextBoxMixin uses onInput var _this = this; // the setTimeout allows the key to post to the widget input box setTimeout(function(){ _this._handleOnChange(_this.get('value'), false); }, 0); } }, _setPlaceHolderAttr: function(v){ this._set("placeHolder", v); if(!this._phspan){ this._attachPoints.push('_phspan'); // dijitInputField class gives placeHolder same padding as the input field // parent node already has dijitInputField class but it doesn't affect this <span> // since it's position: absolute. this._phspan = domConstruct.create('span',{ onmousedown:function(e){ e.preventDefault(); }, className:'dijitPlaceHolder dijitInputField'},this.textbox,'after'); } this._phspan.innerHTML=""; this._phspan.appendChild(document.createTextNode(v)); this._updatePlaceHolder(); }, _updatePlaceHolder: function(){ if(this._phspan){ this._phspan.style.display=(this.placeHolder&&!this.focused&&!this.textbox.value)?"":"none"; } }, _setValueAttr: function(value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){ this.inherited(arguments); this._updatePlaceHolder(); }, getDisplayedValue: function(){ // summary: // Deprecated. Use get('displayedValue') instead. // tags: // deprecated kernel.deprecated(this.declaredClass+"::getDisplayedValue() is deprecated. Use set('displayedValue') instead.", "", "2.0"); return this.get('displayedValue'); }, setDisplayedValue: function(/*String*/ value){ // summary: // Deprecated. Use set('displayedValue', ...) instead. // tags: // deprecated kernel.deprecated(this.declaredClass+"::setDisplayedValue() is deprecated. Use set('displayedValue', ...) instead.", "", "2.0"); this.set('displayedValue', value); }, _onBlur: function(e){ if(this.disabled){ return; } this.inherited(arguments); this._updatePlaceHolder(); }, _onFocus: function(/*String*/ by){ if(this.disabled || this.readOnly){ return; } this.inherited(arguments); this._updatePlaceHolder(); } }); if(has("ie") < 9){ TextBox = declare(/*===== "dijit.form.TextBox.IEMixin", =====*/ TextBox, { declaredClass: "dijit.form.TextBox", // for user code referencing declaredClass _isTextSelected: function(){ var range = win.doc.selection.createRange(); var parent = range.parentElement(); return parent == this.textbox && range.text.length == 0; }, postCreate: function(){ this.inherited(arguments); // IE INPUT tag fontFamily has to be set directly using STYLE // the setTimeout gives IE a chance to render the TextBox and to deal with font inheritance setTimeout(lang.hitch(this, function(){ try{ var s = domStyle.getComputedStyle(this.domNode); // can throw an exception if widget is immediately destroyed if(s){ var ff = s.fontFamily; if(ff){ var inputs = this.domNode.getElementsByTagName("INPUT"); if(inputs){ for(var i=0; i < inputs.length; i++){ inputs[i].style.fontFamily = ff; } } } } }catch(e){/*when used in a Dialog, and this is called before the dialog is shown, s.fontFamily would trigger "Invalid Argument" error.*/} }), 0); } }); // Overrides definition of _setSelectionRange from _TextBoxMixin (TODO: move to _TextBoxMixin.js?) dijit._setSelectionRange = _TextBoxMixin._setSelectionRange = function(/*DomNode*/ element, /*Number?*/ start, /*Number?*/ stop){ if(element.createTextRange){ var r = element.createTextRange(); r.collapse(true); r.moveStart("character", -99999); // move to 0 r.moveStart("character", start); // delta from 0 is the correct position r.moveEnd("character", stop-start); r.select(); } } }else if(has("mozilla")){ TextBox = declare(/*===== "dijit.form.TextBox.MozMixin", =====*/TextBox, { declaredClass: "dijit.form.TextBox", // for user code referencing declaredClass _onBlur: function(e){ this.inherited(arguments); if(this.selectOnClick){ // clear selection so that the next mouse click doesn't reselect this.textbox.selectionStart = this.textbox.selectionEnd = undefined; } } }); }else{ TextBox.prototype.declaredClass = "dijit.form.TextBox"; } lang.setObject("dijit.form.TextBox", TextBox); // don't do direct assignment, it confuses API doc parser return TextBox; }); }, 'dojox/color':function(){ define("dojox/color", ["./color/_base"], function(dxcolor){ return dxcolor; }); }, 'dijit/DialogUnderlay':function(){ define("dijit/DialogUnderlay", [ "dojo/_base/declare", // declare "dojo/dom-attr", // domAttr.set "dojo/_base/window", // win.body "dojo/window", // winUtils.getBox "./_Widget", "./_TemplatedMixin", "./BackgroundIframe" ], function(declare, domAttr, win, winUtils, _Widget, _TemplatedMixin, BackgroundIframe){ /*===== var _Widget = dijit._Widget; var _TemplatedMixin = dijit._TemplatedMixin; =====*/ // module: // dijit/DialogUnderlay // summary: // The component that blocks the screen behind a `dijit.Dialog` return declare("dijit.DialogUnderlay", [_Widget, _TemplatedMixin], { // summary: // The component that blocks the screen behind a `dijit.Dialog` // // description: // A component used to block input behind a `dijit.Dialog`. Only a single // instance of this widget is created by `dijit.Dialog`, and saved as // a reference to be shared between all Dialogs as `dijit._underlay` // // The underlay itself can be styled based on and id: // | #myDialog_underlay { background-color:red; } // // In the case of `dijit.Dialog`, this id is based on the id of the Dialog, // suffixed with _underlay. // 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'><div class='dijitDialogUnderlay' data-dojo-attach-point='node'></div></div>", // Parameters on creation or updatable later // dialogId: String // Id of the dialog.... DialogUnderlay's id is based on this id dialogId: "", // class: String // This class name is used on the DialogUnderlay node, in addition to dijitDialogUnderlay "class": "", _setDialogIdAttr: function(id){ domAttr.set(this.node, "id", id + "_underlay"); this._set("dialogId", id); }, _setClassAttr: function(clazz){ this.node.className = "dijitDialogUnderlay " + clazz; this._set("class", clazz); }, postCreate: function(){ // summary: // Append the underlay to the body win.body().appendChild(this.domNode); }, layout: function(){ // summary: // Sets the background to the size of the viewport // // description: // 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. // tags: // private var is = this.node.style, os = this.domNode.style; // hide the background temporarily, so that the background itself isn't // causing scrollbars to appear (might happen when user shrinks browser // window and then we are called to resize) os.display = "none"; // then resize and show var viewport = winUtils.getBox(); os.top = viewport.t + "px"; os.left = viewport.l + "px"; is.width = viewport.w + "px"; is.height = viewport.h + "px"; os.display = "block"; }, show: function(){ // summary: // Show the dialog underlay this.domNode.style.display = "block"; this.layout(); this.bgIframe = new BackgroundIframe(this.domNode); }, hide: function(){ // summary: // Hides the dialog underlay this.bgIframe.destroy(); delete this.bgIframe; this.domNode.style.display = "none"; } }); }); }, 'dojox/widget/ColorPicker':function(){ require({cache:{ 'url:dojox/widget/ColorPicker/ColorPicker.html':"<table class=\"dojoxColorPicker\" dojoAttachEvent=\"onkeypress: _handleKey\" cellpadding=\"0\" cellspacing=\"0\">\n\t<tr>\n\t\t<td valign=\"top\" class=\"dojoxColorPickerRightPad\">\n\t\t\t<div class=\"dojoxColorPickerBox\">\n\t\t\t\t<!-- Forcing ABS in style attr due to dojo DND issue with not picking it up form the class. -->\n\t\t\t\t<img role=\"status\" title=\"${saturationPickerTitle}\" alt=\"${saturationPickerTitle}\" class=\"dojoxColorPickerPoint\" src=\"${_pickerPointer}\" tabIndex=\"0\" dojoAttachPoint=\"cursorNode\" style=\"position: absolute; top: 0px; left: 0px;\">\n\t\t\t\t<img role=\"presentation\" alt=\"\" dojoAttachPoint=\"colorUnderlay\" dojoAttachEvent=\"onclick: _setPoint, onmousedown: _stopDrag\" class=\"dojoxColorPickerUnderlay\" src=\"${_underlay}\" ondragstart=\"return false\">\n\t\t\t</div>\n\t\t</td>\n\t\t<td valign=\"top\" class=\"dojoxColorPickerRightPad\">\n\t\t\t<div class=\"dojoxHuePicker\">\n\t\t\t\t<!-- Forcing ABS in style attr due to dojo DND issue with not picking it up form the class. -->\n\t\t\t\t<img role=\"status\" dojoAttachPoint=\"hueCursorNode\" tabIndex=\"0\" class=\"dojoxHuePickerPoint\" title=\"${huePickerTitle}\" alt=\"${huePickerTitle}\" src=\"${_huePickerPointer}\" style=\"position: absolute; top: 0px; left: 0px;\">\n\t\t\t\t<div class=\"dojoxHuePickerUnderlay\" dojoAttachPoint=\"hueNode\">\n\t\t\t\t <img role=\"presentation\" alt=\"\" dojoAttachEvent=\"onclick: _setHuePoint, onmousedown: _stopDrag\" src=\"${_hueUnderlay}\">\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</td>\n\t\t<td valign=\"top\">\n\t\t\t<table cellpadding=\"0\" cellspacing=\"0\">\n\t\t\t\t<tr>\n\t\t\t\t\t<td valign=\"top\" class=\"dojoxColorPickerPreviewContainer\">\n\t\t\t\t\t\t<table cellpadding=\"0\" cellspacing=\"0\">\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td valign=\"top\" class=\"dojoxColorPickerRightPad\">\n\t\t\t\t\t\t\t\t\t<div dojoAttachPoint=\"previewNode\" class=\"dojoxColorPickerPreview\"></div>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td valign=\"top\">\n\t\t\t\t\t\t\t\t\t<div dojoAttachPoint=\"safePreviewNode\" class=\"dojoxColorPickerWebSafePreview\"></div>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<td valign=\"bottom\">\n\t\t\t\t\t\t<table class=\"dojoxColorPickerOptional\" cellpadding=\"0\" cellspacing=\"0\">\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t<div class=\"dijitInline dojoxColorPickerRgb\" dojoAttachPoint=\"rgbNode\">\n\t\t\t\t\t\t\t\t\t\t<table cellpadding=\"1\" cellspacing=\"1\">\n\t\t\t\t\t\t\t\t\t\t<tr><td><label for=\"${_uId}_r\">${redLabel}</label></td><td><input id=\"${_uId}_r\" dojoAttachPoint=\"Rval\" size=\"1\" dojoAttachEvent=\"onchange: _colorInputChange\"></td></tr>\n\t\t\t\t\t\t\t\t\t\t<tr><td><label for=\"${_uId}_g\">${greenLabel}</label></td><td><input id=\"${_uId}_g\" dojoAttachPoint=\"Gval\" size=\"1\" dojoAttachEvent=\"onchange: _colorInputChange\"></td></tr>\n\t\t\t\t\t\t\t\t\t\t<tr><td><label for=\"${_uId}_b\">${blueLabel}</label></td><td><input id=\"${_uId}_b\" dojoAttachPoint=\"Bval\" size=\"1\" dojoAttachEvent=\"onchange: _colorInputChange\"></td></tr>\n\t\t\t\t\t\t\t\t\t\t</table>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t<div class=\"dijitInline dojoxColorPickerHsv\" dojoAttachPoint=\"hsvNode\">\n\t\t\t\t\t\t\t\t\t\t<table cellpadding=\"1\" cellspacing=\"1\">\n\t\t\t\t\t\t\t\t\t\t<tr><td><label for=\"${_uId}_h\">${hueLabel}</label></td><td><input id=\"${_uId}_h\" dojoAttachPoint=\"Hval\"size=\"1\" dojoAttachEvent=\"onchange: _colorInputChange\"> ${degLabel}</td></tr>\n\t\t\t\t\t\t\t\t\t\t<tr><td><label for=\"${_uId}_s\">${saturationLabel}</label></td><td><input id=\"${_uId}_s\" dojoAttachPoint=\"Sval\" size=\"1\" dojoAttachEvent=\"onchange: _colorInputChange\"> ${percentSign}</td></tr>\n\t\t\t\t\t\t\t\t\t\t<tr><td><label for=\"${_uId}_v\">${valueLabel}</label></td><td><input id=\"${_uId}_v\" dojoAttachPoint=\"Vval\" size=\"1\" dojoAttachEvent=\"onchange: _colorInputChange\"> ${percentSign}</td></tr>\n\t\t\t\t\t\t\t\t\t\t</table>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td colspan=\"2\">\n\t\t\t\t\t\t\t\t\t<div class=\"dojoxColorPickerHex\" dojoAttachPoint=\"hexNode\" aria-live=\"polite\">\t\n\t\t\t\t\t\t\t\t\t\t<label for=\"${_uId}_hex\"> ${hexLabel} </label><input id=\"${_uId}_hex\" dojoAttachPoint=\"hexCode, focusNode, valueNode\" size=\"6\" class=\"dojoxColorPickerHexCode\" dojoAttachEvent=\"onchange: _colorInputChange\">\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t</table>\n\t\t</td>\n\t</tr>\n</table>\n\n"}}); define("dojox/widget/ColorPicker", [ "dojo/_base/kernel","dojo/_base/declare","dojo/_base/lang","dojo/_base/array", "dojo/_base/html","dojo/_base/connect","dojo/_base/sniff","dojo/_base/window", "dojo/_base/event","dojo/dom","dojo/dom-class","dojo/keys","dojo/fx","dojo/dnd/move", "dijit/registry","dijit/_base/focus","dijit/form/_FormWidget","dijit/typematic", "dojox/color","dojo/i18n","dojo/i18n!./nls/ColorPicker","dojo/i18n!dojo/cldr/nls/number", "dojo/text!./ColorPicker/ColorPicker.html" ], function(kernel,declare,lang,ArrayUtil,html,Hub,has,win,Event,DOM,DOMClass,Keys,fx,move, registry,FocusManager,FormWidget,Typematic,color,i18n,bundle1,bundle2,template){ kernel.experimental("dojox.widget.ColorPicker"); var webSafeFromHex = function(hex){ // stub, this is planned later: return hex; }; /*===== var FormWidget = dijit.form._FormWidget; =====*/ // TODO: shouldn't this extend _FormValueWidget? return declare("dojox.widget.ColorPicker", FormWidget, { // summary: // a HSV color picker - similar to Photoshop picker // // description: // Provides an interactive HSV ColorPicker similar to // PhotoShop's color selction tool. This is an enhanced // version of the default dijit.ColorPalette, though provides // no accessibility. // // example: // | var picker = new dojox.widget.ColorPicker({ // | // a couple of example toggles: // | animatePoint:false, // | showHsv: false, // | webSafe: false, // | showRgb: false // | }); // // example: // | <!-- markup: --> // | <div dojoType="dojox.widget.ColorPicker"></div> // // showRgb: Boolean // show/update RGB input nodes showRgb: true, // showHsv: Boolean // show/update HSV input nodes showHsv: true, // showHex: Boolean // show/update Hex value field showHex: true, // webSafe: Boolean // deprecated? or just use a toggle to show/hide that node, too? webSafe: true, // animatePoint: Boolean // toggle to use slideTo (true) or just place the cursor (false) on click animatePoint: true, // slideDuration: Integer // time in ms picker node will slide to next location (non-dragging) when animatePoint=true slideDuration: 250, // liveUpdate: Boolean // Set to true to fire onChange in an indeterminate way liveUpdate: false, // PICKER_HUE_H: int // Height of the hue picker, used to calculate positions PICKER_HUE_H: 150, // PICKER_SAT_VAL_H: int // Height of the 2d picker, used to calculate positions PICKER_SAT_VAL_H: 150, // PICKER_SAT_VAL_W: int // Width of the 2d picker, used to calculate positions PICKER_SAT_VAL_W: 150, // PICKER_HUE_SELECTOR_H: int // Height of the hue selector DOM node, used to calc offsets so that selection // is center of the image node. PICKER_HUE_SELECTOR_H: 8, // PICKER_SAT_SELECTOR_H: int // Height of the saturation selector DOM node, used to calc offsets so that selection // is center of the image node. PICKER_SAT_SELECTOR_H: 10, // PICKER_SAT_SELECTOR_W: int // Width of the saturation selector DOM node, used to calc offsets so that selection // is center of the image node. PICKER_SAT_SELECTOR_W: 10, // value: String // Default color for this component. Only hex values are accepted as incoming/returned // values. Adjust this value with `.attr`, eg: dijit.byId("myPicker").attr("value", "#ededed"); // to cause the points to adjust and the values to reflect the current color. value: "#ffffff", _underlay: kernel.moduleUrl("dojox.widget","ColorPicker/images/underlay.png"), _hueUnderlay: kernel.moduleUrl("dojox.widget","ColorPicker/images/hue.png"), _pickerPointer: kernel.moduleUrl("dojox.widget","ColorPicker/images/pickerPointer.png"), _huePickerPointer: kernel.moduleUrl("dojox.widget","ColorPicker/images/hueHandle.png"), _huePickerPointerAlly: kernel.moduleUrl("dojox.widget","ColorPicker/images/hueHandleA11y.png"), templateString: template, postMixInProperties: function(){ if(DOMClass.contains(win.body(), "dijit_a11y")){ // Use the pointer that will show up in high contrast. this._huePickerPointer = this._huePickerPointerAlly; } this._uId = registry.getUniqueId(this.id); lang.mixin(this, i18n.getLocalization("dojox.widget", "ColorPicker")); lang.mixin(this, i18n.getLocalization("dojo.cldr", "number")); this.inherited(arguments); }, postCreate: function(){ // summary: // As quickly as we can, set up ie6 alpha-filter support for our // underlay. we don't do image handles (done in css), just the 'core' // of this widget: the underlay. this.inherited(arguments); if(has("ie") < 7){ this.colorUnderlay.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+this._underlay+"', sizingMethod='scale')"; this.colorUnderlay.src = this._blankGif.toString(); } // hide toggle-able nodes: if(!this.showRgb){ this.rgbNode.style.visibility = "hidden"; } if(!this.showHsv){ this.hsvNode.style.visibility = "hidden"; } if(!this.showHex){ this.hexNode.style.visibility = "hidden"; } if(!this.webSafe){ this.safePreviewNode.style.visibility = "hidden"; } }, startup: function(){ if(this._started){ return; } this._started = true; this.set("value", this.value); this._mover = new move.boxConstrainedMoveable(this.cursorNode, { box: { t: -(this.PICKER_SAT_SELECTOR_H/2), l: -(this.PICKER_SAT_SELECTOR_W/2), w:this.PICKER_SAT_VAL_W, h:this.PICKER_SAT_VAL_H } }); this._hueMover = new move.boxConstrainedMoveable(this.hueCursorNode, { box: { t: -(this.PICKER_HUE_SELECTOR_H/2), l:0, w:0, h:this.PICKER_HUE_H } }); this._subs = []; // no dnd/move/move published ... use a timer: this._subs.push(Hub.subscribe("/dnd/move/stop", lang.hitch(this, "_clearTimer"))); this._subs.push(Hub.subscribe("/dnd/move/start", lang.hitch(this, "_setTimer"))); // Bind to up, down, left and right arrows on the hue and saturation nodes. this._keyListeners = []; this._connects.push(Typematic.addKeyListener(this.hueCursorNode,{ charOrCode: Keys.UP_ARROW, shiftKey: false, metaKey: false, ctrlKey: false, altKey: false }, this, lang.hitch(this, this._updateHueCursorNode), 25, 25)); this._connects.push(Typematic.addKeyListener(this.hueCursorNode,{ charOrCode: Keys.DOWN_ARROW, shiftKey: false, metaKey: false, ctrlKey: false, altKey: false }, this, lang.hitch(this, this._updateHueCursorNode), 25, 25)); this._connects.push(Typematic.addKeyListener(this.cursorNode,{ charOrCode: Keys.UP_ARROW, shiftKey: false, metaKey: false, ctrlKey: false, altKey: false }, this, lang.hitch(this, this._updateCursorNode), 25, 25)); this._connects.push(Typematic.addKeyListener(this.cursorNode,{ charOrCode: Keys.DOWN_ARROW, shiftKey: false, metaKey: false, ctrlKey: false, altKey: false }, this, lang.hitch(this, this._updateCursorNode), 25, 25)); this._connects.push(Typematic.addKeyListener(this.cursorNode,{ charOrCode: Keys.LEFT_ARROW, shiftKey: false, metaKey: false, ctrlKey: false, altKey: false }, this, lang.hitch(this, this._updateCursorNode), 25, 25)); this._connects.push(Typematic.addKeyListener(this.cursorNode,{ charOrCode: Keys.RIGHT_ARROW, shiftKey: false, metaKey: false, ctrlKey: false, altKey: false }, this, lang.hitch(this, this._updateCursorNode), 25, 25)); }, _setValueAttr: function(value){ if(!this._started){ return; } this.setColor(value, true); }, setColor: function(/* String */col, force){ // summary: Set a color on a picker. Usually used to set // initial color as an alternative to passing defaultColor option // to the constructor. col = color.fromString(col); this._updatePickerLocations(col); this._updateColorInputs(col); this._updateValue(col, force); }, _setTimer: function(/* d.dnd.Mover */mover){ if(mover.node != this.cursorNode && mover.node != this.hueCursorNode){ return; } // FIXME: should I assume this? focus on mouse down so on mouse up FocusManager.focus(mover.node); DOM.setSelectable(this.domNode,false); this._timer = setInterval(lang.hitch(this, "_updateColor"), 45); }, _clearTimer: function(/* d.dnd.Mover */mover){ if(!this._timer){ return; } clearInterval(this._timer); this._timer = null; this.onChange(this.value); DOM.setSelectable(this.domNode,true); }, _setHue: function(/* Decimal */h){ // summary: // Sets a natural color background for the // underlay image against closest hue value (full saturation) // h: 0..360 html.style(this.colorUnderlay, "backgroundColor", color.fromHsv(h,100,100).toHex()); }, _updateHueCursorNode: function(count, node, e){ // summary: // Function used by the typematic code to handle cursor position and update // via keyboard. // count: // -1 means stop, anything else is just how many times it was called. // node: // The node generating the event. // e: // The event. if(count !== -1){ var y = html.style(this.hueCursorNode, "top"); var selCenter = this.PICKER_HUE_SELECTOR_H/2; // Account for our offset y += selCenter; var update = false; if(e.charOrCode == Keys.UP_ARROW){ if(y > 0){ y -= 1; update = true; } }else if(e.charOrCode == Keys.DOWN_ARROW){ if(y < this.PICKER_HUE_H){ y += 1; update = true; } } y -= selCenter; if(update){ html.style(this.hueCursorNode, "top", y + "px"); } }else{ this._updateColor(true); } }, _updateCursorNode: function(count, node, e){ // summary: // Function used by the typematic code to handle cursor position and update // via keyboard. // count: // -1 means stop, anything else is just how many times it was called. // node: // The node generating the event. // e: // The event. var selCenterH = this.PICKER_SAT_SELECTOR_H/2; var selCenterW = this.PICKER_SAT_SELECTOR_W/2; if(count !== -1){ var y = html.style(this.cursorNode, "top"); var x = html.style(this.cursorNode, "left"); // Account for our offsets to center y += selCenterH; x += selCenterW; var update = false; if(e.charOrCode == Keys.UP_ARROW){ if(y > 0){ y -= 1; update = true; } }else if(e.charOrCode == Keys.DOWN_ARROW){ if(y < this.PICKER_SAT_VAL_H){ y += 1; update = true; } }else if(e.charOrCode == Keys.LEFT_ARROW){ if(x > 0){ x -= 1; update = true; } }else if(e.charOrCode == Keys.RIGHT_ARROW){ if(x < this.PICKER_SAT_VAL_W){ x += 1; update = true; } } if(update){ // Account for our offsets to center y -= selCenterH; x -= selCenterW; html.style(this.cursorNode, "top", y + "px"); html.style(this.cursorNode, "left", x + "px"); } }else{ this._updateColor(true); } }, _updateColor: function(){ // summary: update the previewNode color, and input values [optional] var hueSelCenter = this.PICKER_HUE_SELECTOR_H/2, satSelCenterH = this.PICKER_SAT_SELECTOR_H/2, satSelCenterW = this.PICKER_SAT_SELECTOR_W/2; var _huetop = html.style(this.hueCursorNode,"top") + hueSelCenter, _pickertop = html.style(this.cursorNode,"top") + satSelCenterH, _pickerleft = html.style(this.cursorNode,"left") + satSelCenterW, h = Math.round(360 - (_huetop / this.PICKER_HUE_H * 360)), col = color.fromHsv(h, _pickerleft / this.PICKER_SAT_VAL_W * 100, 100 - (_pickertop / this.PICKER_SAT_VAL_H * 100)) ; this._updateColorInputs(col); this._updateValue(col, true); // update hue, not all the pickers if(h!=this._hue){ this._setHue(h); } }, _colorInputChange: function(e){ //summary: updates picker position and inputs // according to rgb, hex or hsv input changes var col, hasit = false; switch(e.target){ //transform to hsv to pixels case this.hexCode: col = color.fromString(e.target.value); hasit = true; break; case this.Rval: case this.Gval: case this.Bval: col = color.fromArray([this.Rval.value, this.Gval.value, this.Bval.value]); hasit = true; break; case this.Hval: case this.Sval: case this.Vval: col = color.fromHsv(this.Hval.value, this.Sval.value, this.Vval.value); hasit = true; break; } if(hasit){ this._updatePickerLocations(col); this._updateColorInputs(col); this._updateValue(col, true); } }, _updateValue: function(/* dojox.color.Color */col, /* Boolean */fireChange){ // summary: updates the value of the widget // can cancel reverse onChange by specifying second param var hex = col.toHex(); this.value = this.valueNode.value = hex; // anytime we muck with the color, fire onChange? if(fireChange && (!this._timer || this.liveUpdate)){ this.onChange(hex); } }, _updatePickerLocations: function(/* dojox.color.Color */col){ //summary: update handles on the pickers acording to color values // var hueSelCenter = this.PICKER_HUE_SELECTOR_H/2, satSelCenterH = this.PICKER_SAT_SELECTOR_H/2, satSelCenterW = this.PICKER_SAT_SELECTOR_W/2; var hsv = col.toHsv(), ypos = Math.round(this.PICKER_HUE_H - hsv.h / 360 * this.PICKER_HUE_H) - hueSelCenter, newLeft = Math.round(hsv.s / 100 * this.PICKER_SAT_VAL_W) - satSelCenterW, newTop = Math.round(this.PICKER_SAT_VAL_H - hsv.v / 100 * this.PICKER_SAT_VAL_H) - satSelCenterH ; if(this.animatePoint){ fx.slideTo({ node: this.hueCursorNode, duration: this.slideDuration, top: ypos, left: 0 }).play(); fx.slideTo({ node: this.cursorNode, duration: this.slideDuration, top: newTop, left: newLeft }).play(); } else { html.style(this.hueCursorNode, "top", ypos + "px"); html.style(this.cursorNode, { left: newLeft + "px", top: newTop + "px" }); } // limit hue calculations to only when it changes if(hsv.h != this._hue){ this._setHue(hsv.h); } }, _updateColorInputs: function(/* dojox.color.Color */col){ //summary: updates color inputs that were changed through other inputs //or by clicking on the picker var hex = col.toHex(); if(this.showRgb){ this.Rval.value = col.r; this.Gval.value = col.g; this.Bval.value = col.b; } if(this.showHsv){ var hsv = col.toHsv(); this.Hval.value = Math.round((hsv.h)); // convert to 0..360 this.Sval.value = Math.round(hsv.s); this.Vval.value = Math.round(hsv.v); } if(this.showHex){ this.hexCode.value = hex; } this.previewNode.style.backgroundColor = hex; if(this.webSafe){ this.safePreviewNode.style.backgroundColor = webSafeFromHex(hex); } }, _setHuePoint: function(/* Event */evt){ // summary: set the hue picker handle on relative y coordinates var selCenter = this.PICKER_HUE_SELECTOR_H/2; var ypos = evt.layerY - selCenter; if(this.animatePoint){ fx.slideTo({ node: this.hueCursorNode, duration:this.slideDuration, top: ypos, left: 0, onEnd: lang.hitch(this, function(){ this._updateColor(true); FocusManager.focus(this.hueCursorNode); }) }).play(); }else{ html.style(this.hueCursorNode, "top", ypos + "px"); this._updateColor(false); } }, _setPoint: function(/* Event */evt){ // summary: set our picker point based on relative x/y coordinates // evt.preventDefault(); var satSelCenterH = this.PICKER_SAT_SELECTOR_H/2; var satSelCenterW = this.PICKER_SAT_SELECTOR_W/2; var newTop = evt.layerY - satSelCenterH; var newLeft = evt.layerX - satSelCenterW; if(evt){ FocusManager.focus(evt.target); } if(this.animatePoint){ fx.slideTo({ node: this.cursorNode, duration: this.slideDuration, top: newTop, left: newLeft, onEnd: lang.hitch(this, function(){ this._updateColor(true); FocusManager.focus(this.cursorNode); }) }).play(); }else{ html.style(this.cursorNode, { left: newLeft + "px", top: newTop + "px" }); this._updateColor(false); } }, _handleKey: function(/* Event */e){ // FIXME: not implemented YET // var keys = d.keys; }, focus: function(){ // summary: // Put focus on this widget, only if focus isn't set on it already. if(!this.focused){ FocusManager.focus(this.focusNode); } }, _stopDrag: function(e){ // summary: // Function to hald the mouse down default // to disable draggong of images out of the color // picker. Event.stop(e); }, destroy: function(){ // summary: // Over-ride to clean up subscriptions, etc. this.inherited(arguments); ArrayUtil.forEach(this._subs, function(sub){ Hub.unsubscribe(sub); }); delete this._subs; } }); }); }, 'dijit/TitlePane':function(){ require({cache:{ 'url:dijit/templates/TitlePane.html':"<div>\n\t<div data-dojo-attach-event=\"onclick:_onTitleClick, onkeydown:_onTitleKey\"\n\t\t\tclass=\"dijitTitlePaneTitle\" data-dojo-attach-point=\"titleBarNode\">\n\t\t<div class=\"dijitTitlePaneTitleFocus\" data-dojo-attach-point=\"focusNode\">\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" data-dojo-attach-point=\"arrowNode\" class=\"dijitArrowNode\" role=\"presentation\"\n\t\t\t/><span data-dojo-attach-point=\"arrowNodeInner\" class=\"dijitArrowNodeInner\"></span\n\t\t\t><span data-dojo-attach-point=\"titleNode\" class=\"dijitTitlePaneTextNode\"></span>\n\t\t</div>\n\t</div>\n\t<div class=\"dijitTitlePaneContentOuter\" data-dojo-attach-point=\"hideNode\" role=\"presentation\">\n\t\t<div class=\"dijitReset\" data-dojo-attach-point=\"wipeNode\" role=\"presentation\">\n\t\t\t<div class=\"dijitTitlePaneContentInner\" data-dojo-attach-point=\"containerNode\" role=\"region\" id=\"${id}_pane\">\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"}}); define("dijit/TitlePane", [ "dojo/_base/array", // array.forEach "dojo/_base/declare", // declare "dojo/dom", // dom.setSelectable "dojo/dom-attr", // domAttr.set or get domAttr.remove "dojo/dom-class", // domClass.replace "dojo/dom-geometry", // domGeometry.setMarginBox domGeometry.getMarginBox "dojo/_base/event", // event.stop "dojo/fx", // fxUtils.wipeIn fxUtils.wipeOut "dojo/_base/kernel", // kernel.deprecated "dojo/keys", // keys.DOWN_ARROW keys.ENTER "./_CssStateMixin", "./_TemplatedMixin", "./layout/ContentPane", "dojo/text!./templates/TitlePane.html", "./_base/manager" // defaultDuration ], function(array, declare, dom, domAttr, domClass, domGeometry, event, fxUtils, kernel, keys, _CssStateMixin, _TemplatedMixin, ContentPane, template, manager){ /*===== var _Widget = dijit._Widget; var _TemplatedMixin = dijit._TemplatedMixin; var _CssStateMixin = dijit._CssStateMixin; var ContentPane = dijit.layout.ContentPane; =====*/ // module: // dijit/TitlePane // summary: // A pane with a title on top, that can be expanded or collapsed. return declare("dijit.TitlePane", [ContentPane, _TemplatedMixin, _CssStateMixin], { // summary: // A pane with a title on top, that can be expanded or collapsed. // // description: // An accessible container with a title Heading, and a content // section that slides open and closed. TitlePane is an extension to // `dijit.layout.ContentPane`, providing all the useful content-control aspects from it. // // example: // | // load a TitlePane from remote file: // | var foo = new dijit.TitlePane({ href: "foobar.html", title:"Title" }); // | foo.startup(); // // example: // | <!-- markup href example: --> // | <div data-dojo-type="dijit.TitlePane" data-dojo-props="href: 'foobar.html', title: 'Title'"></div> // // example: // | <!-- markup with inline data --> // | <div data-dojo-type="dijit.TitlePane" title="Title"> // | <p>I am content</p> // | </div> // title: String // Title of the pane title: "", _setTitleAttr: { node: "titleNode", type: "innerHTML" }, // override default where title becomes a hover tooltip // open: Boolean // Whether pane is opened or closed. open: true, // toggleable: Boolean // Whether pane can be opened or closed by clicking the title bar. toggleable: true, // tabIndex: String // Tabindex setting for the title (so users can tab to the title then // use space/enter to open/close the title pane) tabIndex: "0", // duration: Integer // Time in milliseconds to fade in/fade out duration: manager.defaultDuration, // baseClass: [protected] String // The root className to be placed on this widget's domNode. baseClass: "dijitTitlePane", templateString: template, // doLayout: [protected] Boolean // Don't change this parameter from the default value. // This ContentPane parameter doesn't make sense for TitlePane, since TitlePane // is never a child of a layout container, nor should TitlePane try to control // the size of an inner widget. doLayout: false, // Tooltip is defined in _WidgetBase but we need to handle the mapping to DOM here _setTooltipAttr: {node: "focusNode", type: "attribute", attribute: "title"}, // focusNode spans the entire width, titleNode doesn't buildRendering: function(){ this.inherited(arguments); dom.setSelectable(this.titleNode, false); }, postCreate: function(){ this.inherited(arguments); // Hover and focus effect on title bar, except for non-toggleable TitlePanes // This should really be controlled from _setToggleableAttr() but _CssStateMixin // doesn't provide a way to disconnect a previous _trackMouseState() call if(this.toggleable){ this._trackMouseState(this.titleBarNode, "dijitTitlePaneTitle"); } // setup open/close animations var hideNode = this.hideNode, wipeNode = this.wipeNode; this._wipeIn = fxUtils.wipeIn({ node: wipeNode, duration: this.duration, beforeBegin: function(){ hideNode.style.display=""; } }); this._wipeOut = fxUtils.wipeOut({ node: wipeNode, duration: this.duration, onEnd: function(){ hideNode.style.display="none"; } }); }, _setOpenAttr: function(/*Boolean*/ open, /*Boolean*/ animate){ // summary: // Hook to make set("open", boolean) control the open/closed state of the pane. // open: Boolean // True if you want to open the pane, false if you want to close it. array.forEach([this._wipeIn, this._wipeOut], function(animation){ if(animation && animation.status() == "playing"){ animation.stop(); } }); if(animate){ var anim = this[open ? "_wipeIn" : "_wipeOut"]; anim.play(); }else{ this.hideNode.style.display = this.wipeNode.style.display = open ? "" : "none"; } // load content (if this is the first time we are opening the TitlePane // and content is specified as an href, or href was set when hidden) if(this._started){ if(open){ this._onShow(); }else{ this.onHide(); } } this.arrowNodeInner.innerHTML = open ? "-" : "+"; this.containerNode.setAttribute("aria-hidden", open ? "false" : "true"); this.focusNode.setAttribute("aria-pressed", open ? "true" : "false"); this._set("open", open); this._setCss(); }, _setToggleableAttr: function(/*Boolean*/ canToggle){ // summary: // Hook to make set("toggleable", boolean) work. // canToggle: Boolean // True to allow user to open/close pane by clicking title bar. this.focusNode.setAttribute("role", canToggle ? "button" : "heading"); if(canToggle){ // TODO: if canToggle is switched from true to false shouldn't we remove this setting? this.focusNode.setAttribute("aria-controls", this.id+"_pane"); domAttr.set(this.focusNode, "tabIndex", this.tabIndex); }else{ domAttr.remove(this.focusNode, "tabIndex"); } this._set("toggleable", canToggle); this._setCss(); }, _setContentAttr: function(/*String|DomNode|Nodelist*/ content){ // summary: // Hook to make set("content", ...) work. // Typically called when an href is loaded. Our job is to make the animation smooth. if(!this.open || !this._wipeOut || this._wipeOut.status() == "playing"){ // we are currently *closing* the pane (or the pane is closed), so just let that continue this.inherited(arguments); }else{ if(this._wipeIn && this._wipeIn.status() == "playing"){ this._wipeIn.stop(); } // freeze container at current height so that adding new content doesn't make it jump domGeometry.setMarginBox(this.wipeNode, { h: domGeometry.getMarginBox(this.wipeNode).h }); // add the new content (erasing the old content, if any) this.inherited(arguments); // call _wipeIn.play() to animate from current height to new height if(this._wipeIn){ this._wipeIn.play(); }else{ this.hideNode.style.display = ""; } } }, toggle: function(){ // summary: // Switches between opened and closed state // tags: // private this._setOpenAttr(!this.open, true); }, _setCss: function(){ // summary: // Set the open/close css state for the TitlePane // tags: // private var node = this.titleBarNode || this.focusNode; var oldCls = this._titleBarClass; this._titleBarClass = "dijit" + (this.toggleable ? "" : "Fixed") + (this.open ? "Open" : "Closed"); domClass.replace(node, this._titleBarClass, oldCls || ""); this.arrowNodeInner.innerHTML = this.open ? "-" : "+"; }, _onTitleKey: function(/*Event*/ e){ // summary: // Handler for when user hits a key // tags: // private if(e.keyCode == keys.ENTER || e.keyCode == keys.SPACE){ if(this.toggleable){ this.toggle(); event.stop(e); } }else if(e.keyCode == keys.DOWN_ARROW && this.open){ this.containerNode.focus(); e.preventDefault(); } }, _onTitleClick: function(){ // summary: // Handler when user clicks the title bar // tags: // private if(this.toggleable){ this.toggle(); } }, setTitle: function(/*String*/ title){ // summary: // Deprecated. Use set('title', ...) instead. // tags: // deprecated kernel.deprecated("dijit.TitlePane.setTitle() is deprecated. Use set('title', ...) instead.", "", "2.0"); this.set("title", title); } }); }); }, 'dijit/form/_ComboBoxMenuMixin':function(){ define("dijit/form/_ComboBoxMenuMixin", [ "dojo/_base/array", // array.forEach "dojo/_base/declare", // declare "dojo/dom-attr", // domAttr.set "dojo/i18n", // i18n.getLocalization "dojo/_base/window", // win.doc.createTextNode "dojo/i18n!./nls/ComboBox" ], function(array, declare, domAttr, i18n, win){ // module: // dijit/form/_ComboBoxMenuMixin // summary: // Focus-less menu for internal use in `dijit.form.ComboBox` return declare( "dijit.form._ComboBoxMenuMixin", null, { // summary: // Focus-less menu for internal use in `dijit.form.ComboBox` // tags: // private // _messages: Object // Holds "next" and "previous" text for paging buttons on drop down _messages: null, postMixInProperties: function(){ this.inherited(arguments); this._messages = i18n.getLocalization("dijit.form", "ComboBox", this.lang); }, buildRendering: function(){ this.inherited(arguments); // fill in template with i18n messages this.previousButton.innerHTML = this._messages["previousMessage"]; this.nextButton.innerHTML = this._messages["nextMessage"]; }, _setValueAttr: function(/*Object*/ value){ this.value = value; this.onChange(value); }, onClick: function(/*DomNode*/ node){ if(node == this.previousButton){ this._setSelectedAttr(null); this.onPage(-1); }else if(node == this.nextButton){ this._setSelectedAttr(null); this.onPage(1); }else{ this.onChange(node); } }, // stubs onChange: function(/*Number*/ /*===== direction =====*/){ // summary: // Notifies ComboBox/FilteringSelect that user selected an option. // tags: // callback }, onPage: function(/*Number*/ /*===== direction =====*/){ // summary: // Notifies ComboBox/FilteringSelect that user clicked to advance to next/previous page. // tags: // callback }, onClose: function(){ // summary: // Callback from dijit.popup code to this widget, notifying it that it closed // tags: // private this._setSelectedAttr(null); }, _createOption: function(/*Object*/ item, labelFunc){ // summary: // Creates an option to appear on the popup menu subclassed by // `dijit.form.FilteringSelect`. var menuitem = this._createMenuItem(); var labelObject = labelFunc(item); if(labelObject.html){ menuitem.innerHTML = labelObject.label; }else{ menuitem.appendChild( win.doc.createTextNode(labelObject.label) ); } // #3250: in blank options, assign a normal height if(menuitem.innerHTML == ""){ menuitem.innerHTML = " "; // } // update menuitem.dir if BidiSupport was required this.applyTextDir(menuitem, (menuitem.innerText || menuitem.textContent || "")); menuitem.item=item; return menuitem; }, createOptions: function(results, options, labelFunc){ // summary: // Fills in the items in the drop down list // results: // Array of items // options: // The options to the query function of the store // // labelFunc: // Function to produce a label in the drop down list from a dojo.data item this.items = results; // display "Previous . . ." button this.previousButton.style.display = (options.start == 0) ? "none" : ""; domAttr.set(this.previousButton, "id", this.id + "_prev"); // create options using _createOption function defined by parent // ComboBox (or FilteringSelect) class // #2309: // iterate over cache nondestructively array.forEach(results, function(item, i){ var menuitem = this._createOption(item, labelFunc); menuitem.setAttribute("item", i); // index to this.items; use indirection to avoid mem leak domAttr.set(menuitem, "id", this.id + i); this.nextButton.parentNode.insertBefore(menuitem, this.nextButton); }, this); // display "Next . . ." button var displayMore = false; // Try to determine if we should show 'more'... if(results.total && !results.total.then && results.total != -1){ if((options.start + options.count) < results.total){ displayMore = true; }else if((options.start + options.count) > results.total && options.count == results.length){ // Weird return from a data store, where a start + count > maxOptions // implies maxOptions isn't really valid and we have to go into faking it. // And more or less assume more if count == results.length displayMore = true; } }else if(options.count == results.length){ //Don't know the size, so we do the best we can based off count alone. //So, if we have an exact match to count, assume more. displayMore = true; } this.nextButton.style.display = displayMore ? "" : "none"; domAttr.set(this.nextButton,"id", this.id + "_next"); }, clearResultList: function(){ // summary: // Clears the entries in the drop down list, but of course keeps the previous and next buttons. var container = this.containerNode; while(container.childNodes.length > 2){ container.removeChild(container.childNodes[container.childNodes.length-2]); } this._setSelectedAttr(null); }, highlightFirstOption: function(){ // summary: // Highlight the first real item in the list (not Previous Choices). this.selectFirstNode(); }, highlightLastOption: function(){ // summary: // Highlight the last real item in the list (not More Choices). this.selectLastNode(); }, selectFirstNode: function(){ this.inherited(arguments); if(this.getHighlightedOption() == this.previousButton){ this.selectNextNode(); } }, selectLastNode: function(){ this.inherited(arguments); if(this.getHighlightedOption() == this.nextButton){ this.selectPreviousNode(); } }, getHighlightedOption: function(){ return this._getSelectedAttr(); } }); }); }, 'dijit/form/_AutoCompleterMixin':function(){ define("dijit/form/_AutoCompleterMixin", [ "dojo/_base/connect", // keys keys.SHIFT "dojo/data/util/filter", // patternToRegExp "dojo/_base/declare", // declare "dojo/_base/Deferred", // Deferred.when "dojo/dom-attr", // domAttr.get "dojo/_base/event", // event.stop "dojo/keys", "dojo/_base/lang", // lang.clone lang.hitch "dojo/on", "dojo/query", // query "dojo/regexp", // regexp.escapeString "dojo/_base/sniff", // has("ie") "dojo/string", // string.substitute "dojo/_base/window", // win.doc.selection.createRange "./DataList", "../registry", // registry.byId "./_TextBoxMixin" // defines _TextBoxMixin.selectInputText ], function(connect, filter, declare, Deferred, domAttr, event, keys, lang, on, query, regexp, has, string, win, DataList, registry, _TextBoxMixin){ // module: // dijit/form/_AutoCompleterMixin // summary: // A mixin that implements the base functionality for `dijit.form.ComboBox`/`dijit.form.FilteringSelect` return declare("dijit.form._AutoCompleterMixin", null, { // summary: // A mixin that implements the base functionality for `dijit.form.ComboBox`/`dijit.form.FilteringSelect` // description: // All widgets that mix in dijit.form._AutoCompleterMixin must extend `dijit.form._FormValueWidget`. // tags: // protected // item: Object // This is the item returned by the dojo.data.store implementation that // provides the data for this ComboBox, 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: [const] dojo.store.api.Store // Reference to data provider object used by this ComboBox store: null, // fetchProperties: Object // Mixin to the store's fetch. // For example, to set the sort order of the ComboBox menu, pass: // | { sort: [{attribute:"name",descending: true}] } // To override the default queryOptions so that deep=false, do: // | { queryOptions: {ignoreCase: true, deep: false} } fetchProperties:{}, // 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. // Any reference to the `searchAttr` is ignored. query: {}, // list: [const] String // Alternate to specifying a store. Id of a dijit/form/DataList widget. list: "", _setListAttr: function(list){ // Avoid having list applied to the DOM node, since it has native meaning in modern browsers this._set("list", list); }, // autoComplete: Boolean // If user types 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>` field autoComplete: true, // highlightMatch: String // One of: "first", "all" or "none". // // If the ComboBox/FilteringSelect opens with the search results and the searched // string can be found, it will be highlighted. If set to "all" // then will probably want to change `queryExpr` parameter to '*${0}*' // // Highlighting is only performed when `labelType` is "text", so as to not // interfere with any HTML markup an HTML label might contain. highlightMatch: "first", // searchDelay: Integer // Delay in milliseconds between when user types something and we start // searching based on that value searchDelay: 100, // searchAttr: String // Search for items in the data store where this attribute (in the item) // matches what the user typed searchAttr: "name", // labelAttr: String? // The entries in the drop down list come from this attribute in the // dojo.data items. // If not specified, the searchAttr attribute is used instead. labelAttr: "", // labelType: String // Specifies how to interpret the labelAttr in the data store items. // Can be "html" or "text". labelType: "text", // queryExpr: String // This specifies what query ComboBox/FilteringSelect sends to the data store, // based on what the user has typed. Changing this expression will modify // whether the drop down shows only exact matches, a "starting with" match, // etc. Use it in conjunction with highlightMatch. // dojo.data query expression pattern. // `${0}` will be substituted for the user text. // `*` is used for wildcards. // `${0}*` means "starts with", `*${0}*` means "contains", `${0}` means "is" queryExpr: "${0}*", // ignoreCase: Boolean // Set true if the ComboBox/FilteringSelect should ignore case when matching possible items ignoreCase: true, // Flags to _HasDropDown to limit height of drop down to make it fit in viewport maxHeight: -1, // For backwards compatibility let onClick events propagate, even clicks on the down arrow button _stopClickEvents: false, _getCaretPos: function(/*DomNode*/ element){ // khtml 3.5.2 has selection* methods as does webkit nightlies from 2005-06-22 var pos = 0; if(typeof(element.selectionStart) == "number"){ // FIXME: this is totally borked on Moz < 1.3. Any recourse? pos = element.selectionStart; }else if(has("ie")){ // in the case of a mouse click in a popup being handled, // then the win.doc.selection is not the textarea, but the popup // var r = win.doc.selection.createRange(); // hack to get IE 6 to play nice. What a POS browser. var tr = win.doc.selection.createRange().duplicate(); var ntr = element.createTextRange(); tr.move("character",0); ntr.move("character",0); try{ // If control doesn't 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); pos = String(ntr.text).replace(/\r/g,"").length; }catch(e){ // If focus has shifted, 0 is fine for caret pos. } } return pos; }, _setCaretPos: function(/*DomNode*/ element, /*Number*/ location){ location = parseInt(location); _TextBoxMixin.selectInputText(element, location, location); }, _setDisabledAttr: function(/*Boolean*/ value){ // Additional code to set disabled state of ComboBox node. // Overrides _FormValueWidget._setDisabledAttr() or ValidationTextBox._setDisabledAttr(). this.inherited(arguments); this.domNode.setAttribute("aria-disabled", value); }, _abortQuery: function(){ // stop in-progress query if(this.searchTimer){ clearTimeout(this.searchTimer); this.searchTimer = null; } if(this._fetchHandle){ if(this._fetchHandle.cancel){ this._cancelingQuery = true; this._fetchHandle.cancel(); this._cancelingQuery = false; } this._fetchHandle = null; } }, _onInput: function(/*Event*/ evt){ // summary: // Handles paste events. this.inherited(arguments); if(evt.charOrCode == 229){ // IME or cut/paste event this._onKeyPress(evt); } }, _onKey: function(/*Event*/ evt){ // summary: // Handles keyboard events from synthetic dojo/_base/connect._keypress event if(this.disabled || this.readOnly){ return; } var key = evt.keyCode; // except for cutting/pasting case - ctrl + x/v if(evt.altKey || ((evt.ctrlKey || evt.metaKey) && (key != 86 && key != 88)) || key == keys.SHIFT){ return; // throw out weird key combinations and spurious events } var doSearch = false; var pw = this.dropDown; var highlighted = null; this._prev_key_backspace = false; this._abortQuery(); // _HasDropDown will do some of the work: // 1. when drop down is not yet shown: // - if user presses the down arrow key, call loadDropDown() // 2. when drop down is already displayed: // - on ESC key, call closeDropDown() // - otherwise, call dropDown.handleKey() to process the keystroke this.inherited(arguments); if(this._opened){ highlighted = pw.getHighlightedOption(); } switch(key){ case keys.PAGE_DOWN: case keys.DOWN_ARROW: case keys.PAGE_UP: case keys.UP_ARROW: // Keystroke caused ComboBox_menu to move to a different item. // Copy new item to <input> box. if(this._opened){ this._announceOption(highlighted); } event.stop(evt); break; case keys.ENTER: // prevent submitting form if user presses enter. Also // prevent accepting the value if either Next or Previous // are selected if(highlighted){ // only stop event on prev/next if(highlighted == pw.nextButton){ this._nextSearch(1); event.stop(evt); break; }else if(highlighted == pw.previousButton){ this._nextSearch(-1); event.stop(evt); break; } }else{ // Update 'value' (ex: KY) according to currently displayed text this._setBlurValue(); // set value if needed this._setCaretPos(this.focusNode, this.focusNode.value.length); // move cursor to end and cancel highlighting } // default case: // if enter pressed while drop down is open, or for FilteringSelect, // if we are in the middle of a query to convert a directly typed in value to an item, // prevent submit if(this._opened || this._fetchHandle){ event.stop(evt); } // fall through case keys.TAB: var newvalue = this.get('displayedValue'); // if the user had More Choices selected fall into the // _onBlur handler if(pw && ( newvalue == pw._messages["previousMessage"] || newvalue == pw._messages["nextMessage"]) ){ break; } if(highlighted){ this._selectOption(highlighted); } // fall through case keys.ESCAPE: if(this._opened){ this._lastQuery = null; // in case results come back later this.closeDropDown(); } break; case ' ': if(highlighted){ // user is effectively clicking a choice in the drop down menu event.stop(evt); this._selectOption(highlighted); this.closeDropDown(); }else{ // user typed a space into the input box, treat as normal character doSearch = true; } break; case keys.DELETE: case keys.BACKSPACE: this._prev_key_backspace = true; doSearch = true; break; } if(doSearch){ // need to wait a tad before start search so that the event // bubbles through DOM and we have value visible this.item = undefined; // undefined means item needs to be set this.searchTimer = setTimeout(lang.hitch(this, "_startSearchFromInput"),1); } }, _onKeyPress: function(evt){ // Non char keys (F1-F12 etc..) shouldn't open list. // Ascii characters and IME input (Chinese, Japanese etc.) should. if(typeof evt.charOrCode == "string" || evt.charOrCode == 229){ // need to wait a tad before start search so that the event // bubbles through DOM and we have value visible this.item = undefined; // undefined means item needs to be set this.searchTimer = setTimeout(lang.hitch(this, "_startSearchFromInput"),1); } }, _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. var fn = this.focusNode; // IE7: clear selection so next highlight works all the time _TextBoxMixin.selectInputText(fn, fn.value.length); // does text autoComplete the value in the textbox? var caseFilter = this.ignoreCase? 'toLowerCase' : 'substr'; if(text[caseFilter](0).indexOf(this.focusNode.value[caseFilter](0)) == 0){ var cpos = this.autoComplete ? this._getCaretPos(fn) : fn.value.length; // only try to extend if we added the last character at the end of the input if((cpos+1) > fn.value.length){ // only add to input node as we would overwrite Capitalisation of chars // actually, that is ok fn.value = text;//.substr(cpos); // visually highlight the autocompleted characters _TextBoxMixin.selectInputText(fn, cpos); } }else{ // text does not autoComplete; replace the whole value and highlight fn.value = text; _TextBoxMixin.selectInputText(fn); } }, _openResultList: function(/*Object*/ results, /*Object*/ query, /*Object*/ options){ // summary: // Callback when a search completes. // description: // 1. generates drop-down list and calls _showResultList() to display it // 2. if this result list is from user pressing "more choices"/"previous choices" // then tell screen reader to announce new option this._fetchHandle = null; if( this.disabled || this.readOnly || (query[this.searchAttr] !== this._lastQuery) // TODO: better way to avoid getting unwanted notify ){ return; } var wasSelected = this.dropDown.getHighlightedOption(); this.dropDown.clearResultList(); if(!results.length && options.start == 0){ // if no results and not just the previous choices button this.closeDropDown(); 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. this.dropDown.createOptions( results, options, lang.hitch(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 choice if(options.direction){ if(1 == options.direction){ this.dropDown.highlightFirstOption(); }else if(-1 == options.direction){ this.dropDown.highlightLastOption(); } if(wasSelected){ this._announceOption(this.dropDown.getHighlightedOption()); } }else if(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. && !/^[*]+$/.test(query[this.searchAttr].toString())){ this._announceOption(this.dropDown.containerNode.firstChild.nextSibling); // 1st real item } }, _showResultList: function(){ // summary: // Display the drop down if not already displayed, or if it is displayed, then // reposition it if necessary (reposition may be necessary if drop down's height changed). this.closeDropDown(true); this.openDropDown(); this.domNode.setAttribute("aria-expanded", "true"); }, loadDropDown: function(/*Function*/ /*===== callback =====*/){ // Overrides _HasDropDown.loadDropDown(). // This is called when user has pressed button icon or pressed the down arrow key // to open the drop down. this._startSearchAll(); }, isLoaded: function(){ // signal to _HasDropDown that it needs to call loadDropDown() to load the // drop down asynchronously before displaying it return false; }, closeDropDown: function(){ // Overrides _HasDropDown.closeDropDown(). Closes the drop down (assuming that it's open). // This method is the callback when the user types ESC or clicking // the button icon while the drop down is open. It's also called by other code. this._abortQuery(); if(this._opened){ this.inherited(arguments); this.domNode.setAttribute("aria-expanded", "false"); this.focusNode.removeAttribute("aria-activedescendant"); } }, _setBlurValue: function(){ // 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 value var newvalue = this.get('displayedValue'); var pw = this.dropDown; if(pw && ( newvalue == pw._messages["previousMessage"] || newvalue == pw._messages["nextMessage"] ) ){ this._setValueAttr(this._lastValueReported, true); }else if(typeof this.item == "undefined"){ // Update 'value' (ex: KY) according to currently displayed text this.item = null; this.set('displayedValue', newvalue); }else{ if(this.value != this._lastValueReported){ this._handleOnChange(this.value, true); } this._refreshState(); } }, _setItemAttr: function(/*item*/ item, /*Boolean?*/ priorityChange, /*String?*/ displayedValue){ // summary: // Set the displayed valued in the input box, and the hidden value // that gets submitted, based on a dojo.data store item. // description: // Users shouldn't call this function; they should be calling // set('item', value) // tags: // private var value = ''; if(item){ if(!displayedValue){ displayedValue = this.store._oldAPI ? // remove getValue() for 2.0 (old dojo.data API) this.store.getValue(item, this.searchAttr) : item[this.searchAttr]; } value = this._getValueField() != this.searchAttr ? this.store.getIdentity(item) : displayedValue; } this.set('value', value, priorityChange, displayedValue, item); }, _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 // menu. if(!node){ return; } // pull the text value from the item attached to the DOM node var newValue; if(node == this.dropDown.nextButton || node == this.dropDown.previousButton){ newValue = node.innerHTML; this.item = undefined; this.value = ''; }else{ var item = this.dropDown.items[node.getAttribute("item")]; newValue = (this.store._oldAPI ? // remove getValue() for 2.0 (old dojo.data API) this.store.getValue(item, this.searchAttr) : item[this.searchAttr]).toString(); this.set('item', item, false, newValue); } // get the text that the user manually entered (cut off autocompleted text) this.focusNode.value = this.focusNode.value.substring(0, this._lastInput.length); // set up ARIA activedescendant this.focusNode.setAttribute("aria-activedescendant", domAttr.get(node, "id")); // autocomplete the rest of the option to announce change this._autoCompleteText(newValue); }, _selectOption: function(/*DomNode*/ target){ // summary: // Menu callback function, called when an item in the menu is selected. this.closeDropDown(); if(target){ this._announceOption(target); } this._setCaretPos(this.focusNode, this.focusNode.value.length); this._handleOnChange(this.value, true); }, _startSearchAll: function(){ this._startSearch(''); }, _startSearchFromInput: function(){ this._startSearch(this.focusNode.value.replace(/([\\\*\?])/g, "\\$1")); }, _getQueryString: function(/*String*/ text){ return string.substitute(this.queryExpr, [text]); }, _startSearch: function(/*String*/ key){ // summary: // Starts a search for elements matching key (key=="" means to return all items), // and calls _openResultList() when the search completes, to display the results. if(!this.dropDown){ var popupId = this.id + "_popup", dropDownConstructor = lang.isString(this.dropDownClass) ? lang.getObject(this.dropDownClass, false) : this.dropDownClass; this.dropDown = new dropDownConstructor({ onChange: lang.hitch(this, this._selectOption), id: popupId, dir: this.dir, textDir: this.textDir }); this.focusNode.removeAttribute("aria-activedescendant"); this.textbox.setAttribute("aria-owns",popupId); // associate popup with textbox } this._lastInput = key; // Store exactly what was entered by the user. // Setup parameters to be passed to store.query(). // Create a new query to prevent accidentally querying for a hidden // value from FilteringSelect's keyField var query = lang.clone(this.query); // #5970 var options = { start: 0, count: this.pageSize, queryOptions: { // remove for 2.0 ignoreCase: this.ignoreCase, deep: true } }; lang.mixin(options, this.fetchProperties); // Generate query var qs = this._getQueryString(key), q; if(this.store._oldAPI){ // remove this branch for 2.0 q = qs; }else{ // Query on searchAttr is a regex for benefit of dojo.store.Memory, // but with a toString() method to help dojo.store.JsonRest. // Search string like "Co*" converted to regex like /^Co.*$/i. q = filter.patternToRegExp(qs, this.ignoreCase); q.toString = function(){ return qs; }; } this._lastQuery = query[this.searchAttr] = q; // Function to run the query, wait for the results, and then call _openResultList() var _this = this, startQuery = function(){ var resPromise = _this._fetchHandle = _this.store.query(query, options); Deferred.when(resPromise, function(res){ _this._fetchHandle = null; res.total = resPromise.total; _this._openResultList(res, query, options); }, function(err){ _this._fetchHandle = null; if(!_this._cancelingQuery){ // don't treat canceled query as an error console.error(_this.declaredClass + ' ' + err.toString()); _this.closeDropDown(); } }); }; // #5970: set _lastQuery, *then* start the timeout // otherwise, if the user types and the last query returns before the timeout, // _lastQuery won't be set and their input gets rewritten this.searchTimer = setTimeout(lang.hitch(this, function(query, _this){ this.searchTimer = null; startQuery(); // Setup method to handle clicking next/previous buttons to page through results this._nextSearch = this.dropDown.onPage = function(direction){ options.start += options.count * direction; // tell callback the direction of the paging so the screen // reader knows which menu option to shout options.direction = direction; startQuery(); _this.focus(); }; }, query, this), this.searchDelay); }, _getValueField: function(){ // summary: // Helper for postMixInProperties() to set this.value based on data inlined into the markup. // Returns the attribute name in the item (in dijit.form._ComboBoxDataStore) to use as the value. return this.searchAttr; }, //////////// INITIALIZATION METHODS /////////////////////////////////////// constructor: function(){ this.query={}; this.fetchProperties={}; }, postMixInProperties: function(){ if(!this.store){ var srcNodeRef = this.srcNodeRef; var list = this.list; if(list){ this.store = registry.byId(list); }else{ // if user didn't specify store, then assume there are option tags this.store = new DataList({}, srcNodeRef); } // if there is no value set and there is an option list, set // the value to the first value to be consistent with native Select // Firefox and Safari set value // IE6 and Opera set selectedIndex, which is automatically set // by the selected attribute of an option tag // IE6 does not set value, Opera sets value = selectedIndex if(!("value" in this.params)){ var item = (this.item = this.store.fetchSelectedItem()); if(item){ var valueField = this._getValueField(); // remove getValue() for 2.0 (old dojo.data API) this.value = this.store._oldAPI ? this.store.getValue(item, valueField) : item[valueField]; } } } this.inherited(arguments); }, postCreate: function(){ // summary: // Subclasses must call this method from their postCreate() methods // tags: // protected // find any associated label element and add to ComboBox node. var label=query('label[for="'+this.id+'"]'); if(label.length){ label[0].id = (this.id+"_label"); this.domNode.setAttribute("aria-labelledby", label[0].id); } this.inherited(arguments); // HasDropDown calls _onKey() on keydown but we want to be notified of the synthetic // dojo/_base/connect._keypress event too. this.connect(this.focusNode, "onkeypress", "_onKeyPress"); }, _getMenuLabelFromItem: function(/*Item*/ item){ var label = this.labelFunc(item, this.store), labelType = this.labelType; // If labelType is not "text" we don't want to screw any markup ot whatever. if(this.highlightMatch != "none" && this.labelType == "text" && this._lastInput){ label = this.doHighlight(label, this._escapeHtml(this._lastInput)); labelType = "html"; } return {html: labelType == "html", label: label}; }, doHighlight: function(/*String*/ label, /*String*/ find){ // summary: // Highlights the string entered by the user in the menu. By default this // highlights the first occurrence found. Override this method // to implement your custom highlighting. // tags: // protected var // Add (g)lobal modifier when this.highlightMatch == "all" and (i)gnorecase when this.ignoreCase == true modifiers = (this.ignoreCase ? "i" : "") + (this.highlightMatch == "all" ? "g" : ""), i = this.queryExpr.indexOf("${0}"); find = regexp.escapeString(find); // escape regexp special chars return this._escapeHtml(label).replace( // prepend ^ when this.queryExpr == "${0}*" and append $ when this.queryExpr == "*${0}" new RegExp((i == 0 ? "^" : "") + "("+ find +")" + (i == (this.queryExpr.length - 4) ? "$" : ""), modifiers), '<span class="dijitComboBoxHighlightMatch">$1</span>' ); // returns String, (almost) valid HTML (entities encoded) }, _escapeHtml: function(/*String*/ str){ // TODO Should become dojo.html.entities(), when exists use instead // summary: // Adds escape sequences for special characters in XML: &<>"' str = String(str).replace(/&/gm, "&").replace(/</gm, "<") .replace(/>/gm, ">").replace(/"/gm, """); //balance" return str; // string }, reset: function(){ // Overrides the _FormWidget.reset(). // Additionally reset the .item (to clean up). this.item = null; this.inherited(arguments); }, labelFunc: function(/*item*/ item, /*dojo.store.api.Store*/ store){ // summary: // Computes the label to display based on the dojo.data store item. // returns: // The label that the ComboBox should display // tags: // private // Use toString() because XMLStore returns an XMLItem whereas this // method is expected to return a String (#9354). // Remove getValue() for 2.0 (old dojo.data API) return (store._oldAPI ? store.getValue(item, this.labelAttr || this.searchAttr) : item[this.labelAttr || this.searchAttr]).toString(); // String }, _setValueAttr: function(/*String*/ value, /*Boolean?*/ priorityChange, /*String?*/ displayedValue, /*item?*/ item){ // summary: // Hook so set('value', value) works. // description: // Sets the value of the select. this._set("item", item||null); // value not looked up in store if(!value){ value = ''; } // null translates to blank this.inherited(arguments); }, _setTextDirAttr: function(/*String*/ textDir){ // summary: // Setter for textDir, needed for the dropDown's textDir update. // description: // Users shouldn't call this function; they should be calling // set('textDir', value) // tags: // private this.inherited(arguments); // update the drop down also (_ComboBoxMenuMixin) if(this.dropDown){ this.dropDown._set("textDir", textDir); } } }); }); }, 'url:dijit/templates/ColorPalette.html':"<div class=\"dijitInline dijitColorPalette\">\n\t<table dojoAttachPoint=\"paletteTableNode\" class=\"dijitPaletteTable\" cellSpacing=\"0\" cellPadding=\"0\" role=\"grid\">\n\t\t<tbody data-dojo-attach-point=\"gridNode\"></tbody>\n\t</table>\n</div>\n", 'dijit/form/MappedTextBox':function(){ define("dijit/form/MappedTextBox", [ "dojo/_base/declare", // declare "dojo/dom-construct", // domConstruct.place "./ValidationTextBox" ], function(declare, domConstruct, ValidationTextBox){ /*===== var ValidationTextBox = dijit.form.ValidationTextBox; =====*/ // module: // dijit/form/MappedTextBox // summary: // A dijit.form.ValidationTextBox subclass which provides a base class for widgets that have // a visible formatted display value, and a serializable // value in a hidden input field which is actually sent to the server. return declare("dijit.form.MappedTextBox", ValidationTextBox, { // summary: // A dijit.form.ValidationTextBox subclass which provides a base class for widgets that have // a visible formatted display value, and a serializable // value in a hidden input field which is actually sent to the server. // description: // The visible display may // be locale-dependent and interactive. The value sent to the server is stored in a hidden // input field which uses the `name` attribute declared by the original widget. That value sent // to the server is defined by the dijit.form.MappedTextBox.serialize method and is typically // locale-neutral. // tags: // protected postMixInProperties: function(){ this.inherited(arguments); // we want the name attribute to go to the hidden <input>, not the displayed <input>, // so override _FormWidget.postMixInProperties() setting of nameAttrSetting this.nameAttrSetting = ""; }, // Override default behavior to assign name to focusNode _setNameAttr: null, serialize: function(val /*=====, options =====*/){ // summary: // Overridable function used to convert the get('value') result to a canonical // (non-localized) string. For example, will print dates in ISO format, and // numbers the same way as they are represented in javascript. // val: anything // options: Object? // tags: // protected extension return val.toString ? val.toString() : ""; // String }, toString: function(){ // summary: // Returns widget as a printable string using the widget's value // tags: // protected var val = this.filter(this.get('value')); // call filter in case value is nonstring and filter has been customized return val != null ? (typeof val == "string" ? val : this.serialize(val, this.constraints)) : ""; // String }, validate: function(){ // Overrides `dijit.form.TextBox.validate` this.valueNode.value = this.toString(); return this.inherited(arguments); }, buildRendering: function(){ // Overrides `dijit._TemplatedMixin.buildRendering` this.inherited(arguments); // Create a hidden <input> node with the serialized value used for submit // (as opposed to the displayed value). // Passing in name as markup rather than calling domConstruct.create() with an attrs argument // to make query(input[name=...]) work on IE. (see #8660) this.valueNode = domConstruct.place("<input type='hidden'" + (this.name ? " name='" + this.name.replace(/'/g, """) + "'" : "") + "/>", this.textbox, "after"); }, reset: function(){ // Overrides `dijit.form.ValidationTextBox.reset` to // reset the hidden textbox value to '' this.valueNode.value = ''; this.inherited(arguments); } }); }); }, 'dijit/form/ComboBoxMixin':function(){ require({cache:{ 'url:dijit/form/templates/DropDownBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\n\tid=\"widget_${id}\"\n\trole=\"combobox\"\n\t><div class='dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer'\n\t\tdata-dojo-attach-point=\"_buttonNode, _popupStateNode\" role=\"presentation\"\n\t\t><input class=\"dijitReset dijitInputField dijitArrowButtonInner\" value=\"▼ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t\t\t${_buttonInputDisabled}\n\t/></div\n\t><div class='dijitReset dijitValidationContainer'\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"Χ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t/></div\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class='dijitReset dijitInputInner' ${!nameAttrSetting} type=\"text\" autocomplete=\"off\"\n\t\t\tdata-dojo-attach-point=\"textbox,focusNode\" role=\"textbox\" aria-haspopup=\"true\"\n\t/></div\n></div>\n"}}); define("dijit/form/ComboBoxMixin", [ "dojo/_base/declare", // declare "dojo/_base/Deferred", "dojo/_base/kernel", // kernel.deprecated "dojo/_base/lang", // lang.mixin "dojo/store/util/QueryResults", // dojo.store.util.QueryResults "./_AutoCompleterMixin", "./_ComboBoxMenu", "../_HasDropDown", "dojo/text!./templates/DropDownBox.html" ], function(declare, Deferred, kernel, lang, QueryResults, _AutoCompleterMixin, _ComboBoxMenu, _HasDropDown, template){ /*===== var _AutoCompleterMixin = dijit.form._AutoCompleterMixin; var _ComboBoxMenu = dijit.form._ComboBoxMenu; var _HasDropDown = dijit._HasDropDown; =====*/ // module: // dijit/form/ComboBoxMixin // summary: // Provides main functionality of ComboBox widget return declare("dijit.form.ComboBoxMixin", [_HasDropDown, _AutoCompleterMixin], { // summary: // Provides main functionality of ComboBox widget // dropDownClass: [protected extension] Function String // Dropdown widget class used to select a date/time. // Subclasses should specify this. dropDownClass: _ComboBoxMenu, // hasDownArrow: Boolean // Set this textbox to have a down arrow button, to display the drop down list. // Defaults to true. hasDownArrow: true, templateString: template, baseClass: "dijitTextBox dijitComboBox", /*===== // store: [const] dojo.store.api.Store || dojo.data.api.Read // Reference to data provider object used by this ComboBox. // // Should be dojo.store.api.Store, but dojo.data.api.Read supported // for backwards compatibility. store: null, =====*/ // Set classes like dijitDownArrowButtonHover depending on // mouse action over button node cssStateNodes: { "_buttonNode": "dijitDownArrowButton" }, _setHasDownArrowAttr: function(/*Boolean*/ val){ this._set("hasDownArrow", val); this._buttonNode.style.display = val ? "" : "none"; }, _showResultList: function(){ // hide the tooltip this.displayMessage(""); this.inherited(arguments); }, _setStoreAttr: function(store){ // For backwards-compatibility, accept dojo.data store in addition to dojo.store.store. Remove in 2.0. if(!store.get){ lang.mixin(store, { _oldAPI: true, get: function(id){ // summary: // Retrieves an object by it's identity. This will trigger a fetchItemByIdentity. // Like dojo.store.DataStore.get() except returns native item. var deferred = new Deferred(); this.fetchItemByIdentity({ identity: id, onItem: function(object){ deferred.resolve(object); }, onError: function(error){ deferred.reject(error); } }); return deferred.promise; }, query: function(query, options){ // summary: // Queries the store for objects. Like dojo.store.DataStore.query() // except returned Deferred contains array of native items. var deferred = new Deferred(function(){ fetchHandle.abort && fetchHandle.abort(); }); var fetchHandle = this.fetch(lang.mixin({ query: query, onBegin: function(count){ deferred.total = count; }, onComplete: function(results){ deferred.resolve(results); }, onError: function(error){ deferred.reject(error); } }, options)); return QueryResults(deferred); } }); } this._set("store", store); }, postMixInProperties: function(){ // Since _setValueAttr() depends on this.store, _setStoreAttr() needs to execute first. // Unfortunately, without special code, it ends up executing second. if(this.params.store){ this._setStoreAttr(this.params.store); } this.inherited(arguments); // User may try to access this.store.getValue() etc. in a custom labelFunc() function. // It's not available with the new data store for handling inline <option> tags, so add it. if(!this.params.store){ var clazz = this.declaredClass; lang.mixin(this.store, { getValue: function(item, attr){ kernel.deprecated(clazz + ".store.getValue(item, attr) is deprecated for builtin store. Use item.attr directly", "", "2.0"); return item[attr]; }, getLabel: function(item){ kernel.deprecated(clazz + ".store.getLabel(item) is deprecated for builtin store. Use item.label directly", "", "2.0"); return item.name; }, fetch: function(args){ kernel.deprecated(clazz + ".store.fetch() is deprecated for builtin store.", "Use store.query()", "2.0"); var shim = ["dojo/data/ObjectStore"]; // indirection so it doesn't get rolled into a build require(shim, lang.hitch(this, function(ObjectStore){ new ObjectStore({objectStore: this}).fetch(args); })); } }); } } }); }); }, 'dijit/form/_TextBoxMixin':function(){ define("dijit/form/_TextBoxMixin", [ "dojo/_base/array", // array.forEach "dojo/_base/declare", // declare "dojo/dom", // dom.byId "dojo/_base/event", // event.stop "dojo/keys", // keys.ALT keys.CAPS_LOCK keys.CTRL keys.META keys.SHIFT "dojo/_base/lang", // lang.mixin ".." // for exporting dijit._setSelectionRange, dijit.selectInputText ], function(array, declare, dom, event, keys, lang, dijit){ // module: // dijit/form/_TextBoxMixin // summary: // A mixin for textbox form input widgets var _TextBoxMixin = declare("dijit.form._TextBoxMixin", null, { // summary: // A mixin for textbox form input widgets // 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: "", // selectOnClick: [const] Boolean // If true, all text will be selected when focused with mouse selectOnClick: false, // placeHolder: String // Defines a hint to help users fill out the input field (as defined in HTML 5). // This should only contain plain text (no html markup). placeHolder: "", _getValueAttr: function(){ // summary: // Hook so get('value') works as we like. // description: // For `dijit.form.TextBox` this basically returns the value of the <input>. // // For `dijit.form.MappedTextBox` subclasses, which have both // a "displayed value" and a separate "submit value", // This treats the "displayed value" as the master value, computing the // submit value from it via this.parse(). return this.parse(this.get('displayedValue'), this.constraints); }, _setValueAttr: function(value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){ // summary: // Hook so set('value', ...) works. // // description: // Sets the value of the widget to "value" which can be of // any type as determined by the widget. // // value: // The visual element value is also set to a corresponding, // but not necessarily the same, value. // // formattedValue: // If specified, used to set the visual element value, // otherwise a computed visual value is used. // // priorityChange: // If true, an onChange event is fired immediately instead of // waiting for the next blur event. var filteredValue; if(value !== undefined){ // TODO: this is calling filter() on both the display value and the actual value. // I added a comment to the filter() definition about this, but it should be changed. filteredValue = this.filter(value); if(typeof formattedValue != "string"){ if(filteredValue !== null && ((typeof filteredValue != "number") || !isNaN(filteredValue))){ formattedValue = this.filter(this.format(filteredValue, this.constraints)); }else{ formattedValue = ''; } } } if(formattedValue != null && formattedValue != undefined && ((typeof formattedValue) != "number" || !isNaN(formattedValue)) && this.textbox.value != formattedValue){ this.textbox.value = formattedValue; this._set("displayedValue", this.get("displayedValue")); } if(this.textDir == "auto"){ this.applyTextDir(this.focusNode, formattedValue); } this.inherited(arguments, [filteredValue, priorityChange]); }, // displayedValue: String // For subclasses like ComboBox where the displayed value // (ex: Kentucky) and the serialized value (ex: KY) are different, // this represents the displayed value. // // Setting 'displayedValue' through set('displayedValue', ...) // updates 'value', and vice-versa. Otherwise 'value' is updated // from 'displayedValue' periodically, like onBlur etc. // // TODO: move declaration to MappedTextBox? // Problem is that ComboBox references displayedValue, // for benefit of FilteringSelect. displayedValue: "", _getDisplayedValueAttr: function(){ // summary: // Hook so get('displayedValue') works. // description: // Returns the displayed value (what the user sees on the screen), // after filtering (ie, trimming spaces etc.). // // For some subclasses of TextBox (like ComboBox), the displayed value // is different from the serialized value that's actually // sent to the server (see dijit.form.ValidationTextBox.serialize) // TODO: maybe we should update this.displayedValue on every keystroke so that we don't need // this method // TODO: this isn't really the displayed value when the user is typing return this.filter(this.textbox.value); }, _setDisplayedValueAttr: function(/*String*/ value){ // summary: // Hook so set('displayedValue', ...) works. // description: // Sets the value of the visual element to the string "value". // The widget value is also set to a corresponding, // but not necessarily the same, value. if(value === null || value === undefined){ value = '' } else if(typeof value != "string"){ value = String(value) } this.textbox.value = value; // sets the serialized value to something corresponding to specified displayedValue // (if possible), and also updates the textbox.value, for example converting "123" // to "123.00" this._setValueAttr(this.get('value'), undefined); this._set("displayedValue", this.get('displayedValue')); // textDir support if(this.textDir == "auto"){ this.applyTextDir(this.focusNode, value); } }, format: function(value /*=====, constraints =====*/){ // summary: // Replaceable function to convert a value to a properly formatted string. // value: String // constraints: Object // tags: // protected extension return ((value == null || value == undefined) ? "" : (value.toString ? value.toString() : value)); }, parse: function(value /*=====, constraints =====*/){ // summary: // Replaceable function to convert a formatted string to a value // value: String // constraints: Object // tags: // protected extension return value; // String }, _refreshState: function(){ // summary: // After the user types some characters, etc., this method is // called to check the field for validity etc. The base method // in `dijit.form.TextBox` does nothing, but subclasses override. // tags: // protected }, /*===== onInput: function(event){ // summary: // Connect to this function to receive notifications of various user data-input events. // Return false to cancel the event and prevent it from being processed. // event: // keydown | keypress | cut | paste | input // tags: // callback }, =====*/ onInput: function(){}, __skipInputEvent: false, _onInput: function(){ // summary: // Called AFTER the input event has happened // set text direction according to textDir that was defined in creation if(this.textDir == "auto"){ this.applyTextDir(this.focusNode, this.focusNode.value); } this._refreshState(); // In case someone is watch()'ing for changes to displayedValue this._set("displayedValue", this.get("displayedValue")); }, 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 actions this.textbox.setAttribute("value", this.textbox.value); // DOM and JS values should be the same this.inherited(arguments); // normalize input events to reduce spurious event processing // onkeydown: do not forward modifier keys // set charOrCode to numeric keycode // onkeypress: do not forward numeric charOrCode keys (already sent through onkeydown) // onpaste & oncut: set charOrCode to 229 (IME) // oninput: if primary event not already processed, set charOrCode to 229 (IME), else do not forward var handleEvent = function(e){ var charCode = e.charOrCode || e.keyCode || 229; if(e.type == "keydown"){ switch(charCode){ // ignore "state" keys case keys.SHIFT: case keys.ALT: case keys.CTRL: case keys.META: case keys.CAPS_LOCK: return; default: if(charCode >= 65 && charCode <= 90){ return; } // keydown for A-Z can be processed with keypress } } if(e.type == "keypress" && typeof charCode != "string"){ return; } if(e.type == "input"){ if(this.__skipInputEvent){ // duplicate event this.__skipInputEvent = false; return; } }else{ this.__skipInputEvent = true; } // create fake event to set charOrCode and to know if preventDefault() was called var faux = lang.mixin({}, e, { charOrCode: charCode, wasConsumed: false, preventDefault: function(){ faux.wasConsumed = true; e.preventDefault(); }, stopPropagation: function(){ e.stopPropagation(); } }); // give web page author a chance to consume the event if(this.onInput(faux) === false){ event.stop(faux); // return false means stop } if(faux.wasConsumed){ return; } // if preventDefault was called setTimeout(lang.hitch(this, "_onInput", faux), 0); // widget notification after key has posted }; array.forEach([ "onkeydown", "onkeypress", "onpaste", "oncut", "oninput", "oncompositionend" ], function(event){ this.connect(this.textbox, event, handleEvent); }, this); }, _blankValue: '', // if the textbox is blank, what value should be reported filter: function(val){ // summary: // Auto-corrections (such as trimming) that are applied to textbox // value on blur or form submit. // description: // For MappedTextBox subclasses, this is called twice // - once with the display value // - once the value as set/returned by set('value', ...) // and get('value'), ex: a Number for NumberTextBox. // // In the latter case it does corrections like converting null to NaN. In // the former case the NumberTextBox.filter() method calls this.inherited() // to execute standard trimming code in TextBox.filter(). // // TODO: break this into two methods in 2.0 // // tags: // protected extension if(val === null){ return this._blankValue; } if(typeof val != "string"){ return val; } if(this.trim){ val = lang.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; }, _setBlurValue: function(){ this._setValueAttr(this.get('value'), true); }, _onBlur: function(e){ if(this.disabled){ return; } this._setBlurValue(); this.inherited(arguments); if(this._selectOnClickHandle){ this.disconnect(this._selectOnClickHandle); } }, _isTextSelected: function(){ return this.textbox.selectionStart == this.textbox.selectionEnd; }, _onFocus: function(/*String*/ by){ if(this.disabled || this.readOnly){ return; } // Select all text on focus via click if nothing already selected. // Since mouse-up will clear the selection need to defer selection until after mouse-up. // Don't do anything on focus by tabbing into the widget since there's no associated mouse-up event. if(this.selectOnClick && by == "mouse"){ this._selectOnClickHandle = this.connect(this.domNode, "onmouseup", function(){ // Only select all text on first click; otherwise users would have no way to clear // the selection. this.disconnect(this._selectOnClickHandle); // Check if the user selected some text manually (mouse-down, mouse-move, mouse-up) // and if not, then select all the text if(this._isTextSelected()){ _TextBoxMixin.selectInputText(this.textbox); } }); } // call this.inherited() before refreshState(), since this.inherited() will possibly scroll the viewport // (to scroll the TextBox into view), which will affect how _refreshState() positions the tooltip this.inherited(arguments); this._refreshState(); }, reset: function(){ // Overrides dijit._FormWidget.reset(). // Additionally resets the displayed textbox value to '' this.textbox.value = ''; this.inherited(arguments); }, _setTextDirAttr: function(/*String*/ textDir){ // summary: // Setter for textDir. // description: // Users shouldn't call this function; they should be calling // set('textDir', value) // tags: // private // only if new textDir is different from the old one // and on widgets creation. if(!this._created || this.textDir != textDir){ this._set("textDir", textDir); // so the change of the textDir will take place immediately. this.applyTextDir(this.focusNode, this.focusNode.value); } } }); _TextBoxMixin._setSelectionRange = dijit._setSelectionRange = function(/*DomNode*/ element, /*Number?*/ start, /*Number?*/ stop){ if(element.setSelectionRange){ element.setSelectionRange(start, stop); } }; _TextBoxMixin.selectInputText = dijit.selectInputText = function(/*DomNode*/ element, /*Number?*/ start, /*Number?*/ stop){ // summary: // Select text in the input element argument, from start (default 0), to stop (default end). // TODO: use functions in _editor/selection.js? element = dom.byId(element); if(isNaN(start)){ start = 0; } if(isNaN(stop)){ stop = element.value ? element.value.length : 0; } try{ element.focus(); _TextBoxMixin._setSelectionRange(element, start, stop); }catch(e){ /* squelch random errors (esp. on IE) from unexpected focus changes or DOM nodes being hidden */ } }; return _TextBoxMixin; }); }, 'dijit/form/RadioButton':function(){ define("dijit/form/RadioButton", [ "dojo/_base/declare", // declare "./CheckBox", "./_RadioButtonMixin" ], function(declare, CheckBox, _RadioButtonMixin){ /*===== var CheckBox = dijit.form.CheckBox; var _RadioButtonMixin = dijit.form._RadioButtonMixin; =====*/ // module: // dijit/form/RadioButton // summary: // Radio button widget return declare("dijit.form.RadioButton", [CheckBox, _RadioButtonMixin], { // summary: // Same as an HTML radio, but with fancy styling. baseClass: "dijitRadio" }); }); }, 'dijit/form/_RadioButtonMixin':function(){ define("dijit/form/_RadioButtonMixin", [ "dojo/_base/array", // array.forEach "dojo/_base/declare", // declare "dojo/dom-attr", // domAttr.set "dojo/_base/event", // event.stop "dojo/_base/lang", // lang.hitch "dojo/query", // query "dojo/_base/window", // win.doc "../registry" // registry.getEnclosingWidget ], function(array, declare, domAttr, event, lang, query, win, registry){ // module: // dijit/form/_RadioButtonMixin // summary: // Mixin to provide widget functionality for an HTML radio button return declare("dijit.form._RadioButtonMixin", null, { // summary: // Mixin to provide widget functionality for an HTML radio button // type: [private] String // type attribute on <input> node. // Users should not change this value. type: "radio", _getRelatedWidgets: function(){ // Private function needed to help iterate over all radio buttons in a group. var ary = []; query("input[type=radio]", this.focusNode.form || win.doc).forEach( // can't use name= since query doesn't support [] in the name lang.hitch(this, function(inputNode){ if(inputNode.name == this.name && inputNode.form == this.focusNode.form){ var widget = registry.getEnclosingWidget(inputNode); if(widget){ ary.push(widget); } } }) ); return ary; }, _setCheckedAttr: function(/*Boolean*/ value){ // If I am being checked then have to deselect currently checked radio button this.inherited(arguments); if(!this._created){ return; } if(value){ array.forEach(this._getRelatedWidgets(), lang.hitch(this, function(widget){ if(widget != this && widget.checked){ widget.set('checked', false); } })); } }, _onClick: function(/*Event*/ e){ if(this.checked || this.disabled){ // nothing to do event.stop(e); return false; } if(this.readOnly){ // ignored by some browsers so we have to resync the DOM elements with widget values event.stop(e); array.forEach(this._getRelatedWidgets(), lang.hitch(this, function(widget){ domAttr.set(this.focusNode || this.domNode, 'checked', widget.checked); })); return false; } return this.inherited(arguments); } }); }); }, 'dojo/dnd/TimedMoveable':function(){ define("dojo/dnd/TimedMoveable", ["../main", "./Moveable"], function(dojo) { // module: // dojo/dnd/TimedMoveable // summary: // TODOC /*===== dojo.declare("dojo.dnd.__TimedMoveableArgs", [dojo.dnd.__MoveableArgs], { // timeout: Number // delay move by this number of ms, // accumulating position changes during the timeout timeout: 0 }); =====*/ // precalculate long expressions var oldOnMove = dojo.dnd.Moveable.prototype.onMove; dojo.declare("dojo.dnd.TimedMoveable", dojo.dnd.Moveable, { // summary: // A specialized version of Moveable to support an FPS throttling. // This class puts an upper restriction on FPS, which may reduce // the CPU load. The additional parameter "timeout" regulates // the delay before actually moving the moveable object. // object attributes (for markup) timeout: 40, // in ms, 40ms corresponds to 25 fps constructor: function(node, params){ // summary: // an object that makes a node moveable with a timer // node: Node||String // a node (or node's id) to be moved // params: dojo.dnd.__TimedMoveableArgs // object with additional parameters. // sanitize parameters if(!params){ params = {}; } if(params.timeout && typeof params.timeout == "number" && params.timeout >= 0){ this.timeout = params.timeout; } }, onMoveStop: function(/* dojo.dnd.Mover */ mover){ if(mover._timer){ // stop timer clearTimeout(mover._timer); // reflect the last received position oldOnMove.call(this, mover, mover._leftTop) } dojo.dnd.Moveable.prototype.onMoveStop.apply(this, arguments); }, onMove: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){ mover._leftTop = leftTop; if(!mover._timer){ var _t = this; // to avoid using dojo.hitch() mover._timer = setTimeout(function(){ // we don't have any pending requests mover._timer = null; // reflect the last received position oldOnMove.call(_t, mover, mover._leftTop); }, this.timeout); } } }); return dojo.dnd.TimedMoveable; }); }, 'dijit/form/_ListMouseMixin':function(){ define("dijit/form/_ListMouseMixin", [ "dojo/_base/declare", // declare "dojo/_base/event", // event.stop "dojo/touch", "./_ListBase" ], function(declare, event, touch, _ListBase){ /*===== var _ListBase = dijit.form._ListBase; =====*/ // module: // dijit/form/_ListMouseMixin // summary: // a mixin to handle mouse or touch events for a focus-less menu return declare( "dijit.form._ListMouseMixin", _ListBase, { // summary: // a Mixin to handle mouse or touch events for a focus-less menu // Abstract methods that must be defined externally: // onClick: item was chosen (mousedown somewhere on the menu and mouseup somewhere on the menu) // tags: // private postCreate: function(){ this.inherited(arguments); this.connect(this.domNode, "onclick", function(evt){ this._onClick(evt, this._getTarget(evt)); }); this.connect(this.domNode, "onmousedown", "_onMouseDown"); this.connect(this.domNode, "onmouseup", "_onMouseUp"); this.connect(this.domNode, "onmouseover", "_onMouseOver"); this.connect(this.domNode, "onmouseout", "_onMouseOut"); }, _onClick: function(/*Event*/ evt, /*DomNode*/ target){ this._setSelectedAttr(target, false); if(this._deferredClick){ this._deferredClick.remove(); } this._deferredClick = this.defer(function(){ this._deferredClick = null; this.onClick(target); }); }, _onMouseDown: function(/*Event*/ evt){ if(this._hoveredNode){ this.onUnhover(this._hoveredNode); this._hoveredNode = null; } this._isDragging = true; this._setSelectedAttr(this._getTarget(evt), false); }, _onMouseUp: function(/*Event*/ evt){ this._isDragging = false; var selectedNode = this._getSelectedAttr(); var target = this._getTarget(evt); var hoveredNode = this._hoveredNode; if(selectedNode && target == selectedNode){ this.defer(function(){ this._onClick(evt, selectedNode); }); }else if(hoveredNode){ // drag to select this.defer(function(){ this._onClick(evt, hoveredNode); }); } }, _onMouseOut: function(/*Event*/ /*===== evt ====*/){ if(this._hoveredNode){ this.onUnhover(this._hoveredNode); if(this._getSelectedAttr() == this._hoveredNode){ this.onSelect(this._hoveredNode); } this._hoveredNode = null; } if(this._isDragging){ this._cancelDrag = (new Date()).getTime() + 1000; // cancel in 1 second if no _onMouseOver fires } }, _onMouseOver: function(/*Event*/ evt){ if(this._cancelDrag){ var time = (new Date()).getTime(); if(time > this._cancelDrag){ this._isDragging = false; } this._cancelDrag = null; } var node = this._getTarget(evt); if(!node){ return; } if(this._hoveredNode != node){ if(this._hoveredNode){ this._onMouseOut({ target: this._hoveredNode }); } if(node && node.parentNode == this.containerNode){ if(this._isDragging){ this._setSelectedAttr(node, false); }else{ this._hoveredNode = node; this.onHover(node); } } } } }); }); }, 'url:dijit/form/templates/DropDownBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\n\tid=\"widget_${id}\"\n\trole=\"combobox\"\n\t><div class='dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer'\n\t\tdata-dojo-attach-point=\"_buttonNode, _popupStateNode\" role=\"presentation\"\n\t\t><input class=\"dijitReset dijitInputField dijitArrowButtonInner\" value=\"▼ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t\t\t${_buttonInputDisabled}\n\t/></div\n\t><div class='dijitReset dijitValidationContainer'\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"Χ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t/></div\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class='dijitReset dijitInputInner' ${!nameAttrSetting} type=\"text\" autocomplete=\"off\"\n\t\t\tdata-dojo-attach-point=\"textbox,focusNode\" role=\"textbox\" aria-haspopup=\"true\"\n\t/></div\n></div>\n", 'dijit/form/NumberTextBox':function(){ define("dijit/form/NumberTextBox", [ "dojo/_base/declare", // declare "dojo/_base/lang", // lang.hitch lang.mixin "dojo/number", // number._realNumberRegexp number.format number.parse number.regexp "./RangeBoundTextBox" ], function(declare, lang, number, RangeBoundTextBox){ /*===== var RangeBoundTextBox = dijit.form.RangeBoundTextBox; =====*/ // module: // dijit/form/NumberTextBox // summary: // A TextBox for entering numbers, with formatting and range checking /*===== declare( "dijit.form.NumberTextBox.__Constraints", [dijit.form.RangeBoundTextBox.__Constraints, number.__FormatOptions, number.__ParseOptions], { // summary: // Specifies both the rules on valid/invalid values (minimum, maximum, // number of required decimal places), and also formatting options for // displaying the value when the field is not focused. // example: // Minimum/maximum: // To specify a field between 0 and 120: // | {min:0,max:120} // To specify a field that must be an integer: // | {fractional:false} // To specify a field where 0 to 3 decimal places are allowed on input: // | {places:'0,3'} }); =====*/ var NumberTextBoxMixin = declare("dijit.form.NumberTextBoxMixin", null, { // summary: // A mixin for all number textboxes // tags: // protected // Override ValidationTextBox.regExpGen().... we use a reg-ex generating function rather // than a straight regexp to deal with locale (plus formatting options too?) regExpGen: number.regexp, /*===== // constraints: dijit.form.NumberTextBox.__Constraints // Despite the name, this parameter specifies both constraints on the input // (including minimum/maximum allowed values) as well as // formatting options like places (the number of digits to display after // the decimal point). See `dijit.form.NumberTextBox.__Constraints` for details. constraints: {}, ======*/ // value: Number // The value of this NumberTextBox as a Javascript Number (i.e., not a String). // If the displayed value is blank, the value is NaN, and if the user types in // an gibberish value (like "hello world"), the value is undefined // (i.e. get('value') returns undefined). // // Symmetrically, set('value', NaN) will clear the displayed value, // whereas set('value', undefined) will have no effect. value: NaN, // editOptions: [protected] Object // Properties to mix into constraints when the value is being edited. // This is here because we edit the number in the format "12345", which is // different than the display value (ex: "12,345") editOptions: { pattern: '#.######' }, /*===== _formatter: function(value, options){ // summary: // _formatter() is called by format(). It's the base routine for formatting a number, // as a string, for example converting 12345 into "12,345". // value: Number // The number to be converted into a string. // options: dojo.number.__FormatOptions? // Formatting options // tags: // protected extension return "12345"; // String }, =====*/ _formatter: number.format, postMixInProperties: function(){ this.inherited(arguments); this._set("type", "text"); // in case type="number" was specified which messes up parse/format }, _setConstraintsAttr: function(/*Object*/ constraints){ var places = typeof constraints.places == "number"? constraints.places : 0; if(places){ places++; } // decimal rounding errors take away another digit of precision if(typeof constraints.max != "number"){ constraints.max = 9 * Math.pow(10, 15-places); } if(typeof constraints.min != "number"){ constraints.min = -9 * Math.pow(10, 15-places); } this.inherited(arguments, [ constraints ]); if(this.focusNode && this.focusNode.value && !isNaN(this.value)){ this.set('value', this.value); } }, _onFocus: function(){ if(this.disabled){ return; } var val = this.get('value'); if(typeof val == "number" && !isNaN(val)){ var formattedValue = this.format(val, this.constraints); if(formattedValue !== undefined){ this.textbox.value = formattedValue; } } this.inherited(arguments); }, format: function(/*Number*/ value, /*dojo.number.__FormatOptions*/ constraints){ // summary: // Formats the value as a Number, according to constraints. // tags: // protected var formattedValue = String(value); if(typeof value != "number"){ return formattedValue; } if(isNaN(value)){ return ""; } // check for exponential notation that dojo.number.format chokes on if(!("rangeCheck" in this && this.rangeCheck(value, constraints)) && constraints.exponent !== false && /\de[-+]?\d/i.test(formattedValue)){ return formattedValue; } if(this.editOptions && this.focused){ constraints = lang.mixin({}, constraints, this.editOptions); } return this._formatter(value, constraints); }, /*===== _parser: function(value, constraints){ // summary: // Parses the string value as a Number, according to constraints. // value: String // String representing a number // constraints: dojo.number.__ParseOptions // Formatting options // tags: // protected return 123.45; // Number }, =====*/ _parser: number.parse, parse: function(/*String*/ value, /*number.__FormatOptions*/ constraints){ // summary: // Replaceable function to convert a formatted string to a number value // tags: // protected extension var v = this._parser(value, lang.mixin({}, constraints, (this.editOptions && this.focused) ? this.editOptions : {})); if(this.editOptions && this.focused && isNaN(v)){ v = this._parser(value, constraints); // parse w/o editOptions: not technically needed but is nice for the user } return v; }, _getDisplayedValueAttr: function(){ var v = this.inherited(arguments); return isNaN(v) ? this.textbox.value : v; }, filter: function(/*Number*/ value){ // summary: // This is called with both the display value (string), and the actual value (a number). // When called with the actual value it does corrections so that '' etc. are represented as NaN. // Otherwise it dispatches to the superclass's filter() method. // // See `dijit.form.TextBox.filter` for more details. return (value === null || value === '' || value === undefined) ? NaN : this.inherited(arguments); // set('value', null||''||undefined) should fire onChange(NaN) }, serialize: function(/*Number*/ value, /*Object?*/ options){ // summary: // Convert value (a Number) into a canonical string (ie, how the number literal is written in javascript/java/C/etc.) // tags: // protected return (typeof value != "number" || isNaN(value)) ? '' : this.inherited(arguments); }, _setBlurValue: function(){ var val = lang.hitch(lang.mixin({}, this, { focused: true }), "get")('value'); // parse with editOptions this._setValueAttr(val, true); }, _setValueAttr: function(/*Number*/ value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){ // summary: // Hook so set('value', ...) works. if(value !== undefined && formattedValue === undefined){ formattedValue = String(value); if(typeof value == "number"){ if(isNaN(value)){ formattedValue = '' } // check for exponential notation that number.format chokes on else if(("rangeCheck" in this && this.rangeCheck(value, this.constraints)) || this.constraints.exponent === false || !/\de[-+]?\d/i.test(formattedValue)){ formattedValue = undefined; // lets format compute a real string value } }else if(!value){ // 0 processed in if branch above, ''|null|undefined flows through here formattedValue = ''; value = NaN; }else{ // non-numeric values value = undefined; } } this.inherited(arguments, [value, priorityChange, formattedValue]); }, _getValueAttr: function(){ // summary: // Hook so get('value') works. // Returns Number, NaN for '', or undefined for unparseable text var v = this.inherited(arguments); // returns Number for all values accepted by parse() or NaN for all other displayed values // If the displayed value of the textbox is gibberish (ex: "hello world"), this.inherited() above // returns NaN; this if() branch converts the return value to undefined. // Returning undefined prevents user text from being overwritten when doing _setValueAttr(_getValueAttr()). // A blank displayed value is still returned as NaN. if(isNaN(v) && this.textbox.value !== ''){ if(this.constraints.exponent !== false && /\de[-+]?\d/i.test(this.textbox.value) && (new RegExp("^"+number._realNumberRegexp(lang.mixin({}, this.constraints))+"$").test(this.textbox.value))){ // check for exponential notation that parse() rejected (erroneously?) var n = Number(this.textbox.value); return isNaN(n) ? undefined : n; // return exponential Number or undefined for random text (may not be possible to do with the above RegExp check) }else{ return undefined; // gibberish } }else{ return v; // Number or NaN for '' } }, isValid: function(/*Boolean*/ isFocused){ // Overrides dijit.form.RangeBoundTextBox.isValid to check that the editing-mode value is valid since // it may not be formatted according to the regExp validation rules if(!this.focused || this._isEmpty(this.textbox.value)){ return this.inherited(arguments); }else{ var v = this.get('value'); if(!isNaN(v) && this.rangeCheck(v, this.constraints)){ if(this.constraints.exponent !== false && /\de[-+]?\d/i.test(this.textbox.value)){ // exponential, parse doesn't like it return true; // valid exponential number in range }else{ return this.inherited(arguments); } }else{ return false; } } } }); /*===== NumberTextBoxMixin = dijit.form.NumberTextBoxMixin; =====*/ var NumberTextBox = declare("dijit.form.NumberTextBox", [RangeBoundTextBox,NumberTextBoxMixin], { // summary: // A TextBox for entering numbers, with formatting and range checking // description: // NumberTextBox is a textbox for entering and displaying numbers, supporting // the following main features: // // 1. Enforce minimum/maximum allowed values (as well as enforcing that the user types // a number rather than a random string) // 2. NLS support (altering roles of comma and dot as "thousands-separator" and "decimal-point" // depending on locale). // 3. Separate modes for editing the value and displaying it, specifically that // the thousands separator character (typically comma) disappears when editing // but reappears after the field is blurred. // 4. Formatting and constraints regarding the number of places (digits after the decimal point) // allowed on input, and number of places displayed when blurred (see `constraints` parameter). baseClass: "dijitTextBox dijitNumberTextBox" }); NumberTextBox.Mixin = NumberTextBoxMixin; // for monkey patching return NumberTextBox; }); }, 'dijit/ColorPalette':function(){ require({cache:{ 'url:dijit/templates/ColorPalette.html':"<div class=\"dijitInline dijitColorPalette\">\n\t<table dojoAttachPoint=\"paletteTableNode\" class=\"dijitPaletteTable\" cellSpacing=\"0\" cellPadding=\"0\" role=\"grid\">\n\t\t<tbody data-dojo-attach-point=\"gridNode\"></tbody>\n\t</table>\n</div>\n"}}); define("dijit/ColorPalette", [ "require", // require.toUrl "dojo/text!./templates/ColorPalette.html", "./_Widget", "./_TemplatedMixin", "./_PaletteMixin", "dojo/i18n", // i18n.getLocalization "dojo/_base/Color", // dojo.Color dojo.Color.named "dojo/_base/declare", // declare "dojo/dom-class", // domClass.contains "dojo/dom-construct", // domConstruct.place "dojo/_base/window", // win.body "dojo/string", // string.substitute "dojo/i18n!dojo/nls/colors", // translations "dojo/colors" // extend dojo.Color w/names of other colors ], function(require, template, _Widget, _TemplatedMixin, _PaletteMixin, i18n, Color, declare, domClass, domConstruct, win, string){ /*===== var _Widget = dijit._Widget; var _TemplatedMixin = dijit._TemplatedMixin; var _PaletteMixin = dijit._PaletteMixin; =====*/ // module: // dijit/ColorPalette // summary: // A keyboard accessible color-picking widget var ColorPalette = declare("dijit.ColorPalette", [_Widget, _TemplatedMixin, _PaletteMixin], { // summary: // A keyboard accessible color-picking widget // description: // Grid showing various colors, so the user can pick a certain color. // Can be used standalone, or as a popup. // // example: // | <div data-dojo-type="dijit.ColorPalette"></div> // // example: // | var picker = new dijit.ColorPalette({ },srcNode); // | picker.startup(); // palette: [const] String // Size of grid, either "7x10" or "3x4". palette: "7x10", // _palettes: [protected] Map // This represents the value of the colors. // The first level is a hashmap of the different palettes 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"]] }, // templateString: String // The template of this widget. templateString: template, baseClass: "dijitColorPalette", _dyeFactory: function(value, row, col){ // Overrides _PaletteMixin._dyeFactory(). return new this._dyeClass(value, row, col); }, buildRendering: function(){ // Instantiate the template, which makes a skeleton into which we'll insert a bunch of // <img> nodes this.inherited(arguments); // Creates customized constructor for dye class (color of a single cell) for // specified palette and high-contrast vs. normal mode. Used in _getDye(). this._dyeClass = declare(ColorPalette._Color, { hc: domClass.contains(win.body(), "dijit_a11y"), palette: this.palette }); // Creates <img> nodes in each cell of the template. this._preparePalette( this._palettes[this.palette], i18n.getLocalization("dojo", "colors", this.lang)); } }); ColorPalette._Color = declare("dijit._Color", Color, { // summary: // Object associated with each cell in a ColorPalette palette. // Implements dijit.Dye. // Template for each cell in normal (non-high-contrast mode). Each cell contains a wrapper // node for showing the border (called dijitPaletteImg for back-compat), and dijitColorPaletteSwatch // for showing the color. template: "<span class='dijitInline dijitPaletteImg'>" + "<img src='${blankGif}' alt='${alt}' class='dijitColorPaletteSwatch' style='background-color: ${color}'/>" + "</span>", // Template for each cell in high contrast mode. Each cell contains an image with the whole palette, // but scrolled and clipped to show the correct color only hcTemplate: "<span class='dijitInline dijitPaletteImg' style='position: relative; overflow: hidden; height: 12px; width: 14px;'>" + "<img src='${image}' alt='${alt}' style='position: absolute; left: ${left}px; top: ${top}px; ${size}'/>" + "</span>", // _imagePaths: [protected] Map // This is stores the path to the palette images used for high-contrast mode display _imagePaths: { "7x10": require.toUrl("./themes/a11y/colors7x10.png"), "3x4": require.toUrl("./themes/a11y/colors3x4.png") }, constructor: function(/*String*/alias, /*Number*/ row, /*Number*/ col){ this._alias = alias; this._row = row; this._col = col; this.setColor(Color.named[alias]); }, getValue: function(){ // summary: // Note that although dijit._Color is initialized with a value like "white" getValue() always // returns a hex value return this.toHex(); }, fillCell: function(/*DOMNode*/ cell, /*String*/ blankGif){ var html = string.substitute(this.hc ? this.hcTemplate : this.template, { // substitution variables for normal mode color: this.toHex(), blankGif: blankGif, alt: this._alias, // variables used for high contrast mode image: this._imagePaths[this.palette].toString(), left: this._col * -20 - 5, top: this._row * -20 - 5, size: this.palette == "7x10" ? "height: 145px; width: 206px" : "height: 64px; width: 86px" }); domConstruct.place(html, cell); } }); return ColorPalette; }); }, 'url:dijit/form/templates/CheckBox.html':"<div class=\"dijit dijitReset dijitInline\" role=\"presentation\"\n\t><input\n\t \t${!nameAttrSetting} type=\"${type}\" ${checkedAttrSetting}\n\t\tclass=\"dijitReset dijitCheckBoxInput\"\n\t\tdata-dojo-attach-point=\"focusNode\"\n\t \tdata-dojo-attach-event=\"onclick:_onClick\"\n/></div>\n", 'dijit/form/RangeBoundTextBox':function(){ define("dijit/form/RangeBoundTextBox", [ "dojo/_base/declare", // declare "dojo/i18n", // i18n.getLocalization "./MappedTextBox" ], function(declare, i18n, MappedTextBox){ /*===== var MappedTextBox = dijit.form.MappedTextBox; =====*/ // module: // dijit/form/RangeBoundTextBox // summary: // Base class for textbox form widgets which defines a range of valid values. /*===== dijit.form.RangeBoundTextBox.__Constraints = function(){ // min: Number // Minimum signed value. Default is -Infinity // max: Number // Maximum signed value. Default is +Infinity this.min = min; this.max = max; } =====*/ return declare("dijit.form.RangeBoundTextBox", MappedTextBox, { // summary: // Base class for textbox form widgets which defines a range of valid values. // rangeMessage: String // The message to display if value is out-of-range rangeMessage: "", /*===== // constraints: dijit.form.RangeBoundTextBox.__Constraints constraints: {}, ======*/ rangeCheck: function(/*Number*/ primitive, /*dijit.form.RangeBoundTextBox.__Constraints*/ constraints){ // summary: // Overridable function used to validate the range of the numeric input value. // tags: // protected return ("min" in constraints? (this.compare(primitive,constraints.min) >= 0) : true) && ("max" in constraints? (this.compare(primitive,constraints.max) <= 0) : true); // Boolean }, isInRange: function(/*Boolean*/ /*===== isFocused =====*/){ // summary: // Tests if the value is in the min/max range specified in constraints // tags: // protected return this.rangeCheck(this.get('value'), this.constraints); }, _isDefinitelyOutOfRange: function(){ // summary: // Returns true if the value is out of range and will remain // out of range even if the user types more characters var val = this.get('value'); var isTooLittle = false; var isTooMuch = false; if("min" in this.constraints){ var min = this.constraints.min; min = this.compare(val, ((typeof min == "number") && min >= 0 && val !=0) ? 0 : min); isTooLittle = (typeof min == "number") && min < 0; } if("max" in this.constraints){ var max = this.constraints.max; max = this.compare(val, ((typeof max != "number") || max > 0) ? max : 0); isTooMuch = (typeof max == "number") && max > 0; } return isTooLittle || isTooMuch; }, _isValidSubset: function(){ // summary: // Overrides `dijit.form.ValidationTextBox._isValidSubset`. // Returns true if the input is syntactically valid, and either within // range or could be made in range by more typing. return this.inherited(arguments) && !this._isDefinitelyOutOfRange(); }, isValid: function(/*Boolean*/ isFocused){ // Overrides dijit.form.ValidationTextBox.isValid to check that the value is also in range. return this.inherited(arguments) && ((this._isEmpty(this.textbox.value) && !this.required) || this.isInRange(isFocused)); // Boolean }, getErrorMessage: function(/*Boolean*/ isFocused){ // Overrides dijit.form.ValidationTextBox.getErrorMessage to print "out of range" message if appropriate var v = this.get('value'); if(v !== null && v !== '' && v !== undefined && (typeof v != "number" || !isNaN(v)) && !this.isInRange(isFocused)){ // don't check isInRange w/o a real value return this.rangeMessage; // String } return this.inherited(arguments); }, postMixInProperties: function(){ this.inherited(arguments); if(!this.rangeMessage){ this.messages = i18n.getLocalization("dijit.form", "validate", this.lang); this.rangeMessage = this.messages.rangeMessage; } }, _setConstraintsAttr: function(/*Object*/ constraints){ this.inherited(arguments); if(this.focusNode){ // not set when called from postMixInProperties if(this.constraints.min !== undefined){ this.focusNode.setAttribute("aria-valuemin", this.constraints.min); }else{ this.focusNode.removeAttribute("aria-valuemin"); } if(this.constraints.max !== undefined){ this.focusNode.setAttribute("aria-valuemax", this.constraints.max); }else{ this.focusNode.removeAttribute("aria-valuemax"); } } }, _setValueAttr: function(/*Number*/ value, /*Boolean?*/ priorityChange){ // summary: // Hook so set('value', ...) works. this.focusNode.setAttribute("aria-valuenow", value); this.inherited(arguments); }, applyTextDir: function(/*===== element, text =====*/){ // summary: // The function overridden in the _BidiSupport module, // originally used for setting element.dir according to this.textDir. // In this case does nothing. // element: Object // text: String // tags: // protected. } }); }); }, 'dojo/store/util/SimpleQueryEngine':function(){ define("dojo/store/util/SimpleQueryEngine", ["../../_base/array"], function(arrayUtil) { // module: // dojo/store/util/SimpleQueryEngine // summary: // The module defines a simple filtering query engine for object stores. return function(query, options){ // summary: // Simple query engine that matches using filter functions, named filter // functions or objects by name-value on a query object hash // // description: // The SimpleQueryEngine provides a way of getting a QueryResults through // the use of a simple object hash as a filter. The hash will be used to // match properties on data objects with the corresponding value given. In // other words, only exact matches will be returned. // // This function can be used as a template for more complex query engines; // for example, an engine can be created that accepts an object hash that // contains filtering functions, or a string that gets evaluated, etc. // // When creating a new dojo.store, simply set the store's queryEngine // field as a reference to this function. // // query: Object // An object hash with fields that may match fields of items in the store. // Values in the hash will be compared by normal == operator, but regular expressions // or any object that provides a test() method are also supported and can be // used to match strings by more complex expressions // (and then the regex's or object's test() method will be used to match values). // // options: dojo.store.util.SimpleQueryEngine.__queryOptions? // An object that contains optional information such as sort, start, and count. // // returns: Function // A function that caches the passed query under the field "matches". See any // of the "query" methods on dojo.stores. // // example: // Define a store with a reference to this engine, and set up a query method. // // | var myStore = function(options){ // | // ...more properties here // | this.queryEngine = dojo.store.util.SimpleQueryEngine; // | // define our query method // | this.query = function(query, options){ // | return dojo.store.util.QueryResults(this.queryEngine(query, options)(this.data)); // | }; // | }; // create our matching query function switch(typeof query){ default: throw new Error("Can not query with a " + typeof query); case "object": case "undefined": var queryObject = query; query = function(object){ for(var key in queryObject){ var required = queryObject[key]; if(required && required.test){ if(!required.test(object[key])){ return false; } }else if(required != object[key]){ return false; } } return true; }; break; case "string": // named query if(!this[query]){ throw new Error("No filter function " + query + " was found in store"); } query = this[query]; // fall through case "function": // fall through } function execute(array){ // execute the whole query, first we filter var results = arrayUtil.filter(array, query); // next we sort if(options && options.sort){ results.sort(function(a, b){ for(var sort, i=0; sort = options.sort[i]; i++){ var aValue = a[sort.attribute]; var bValue = b[sort.attribute]; // valueOf enables proper comparison of dates aValue = aValue != null ? aValue.valueOf() : aValue; bValue = bValue != null ? bValue.valueOf() : bValue; if (aValue != bValue) { return !!sort.descending == aValue > bValue ? -1 : 1; } } return 0; }); } // now we paginate if(options && (options.start || options.count)){ var total = results.length; results = results.slice(options.start || 0, (options.start || 0) + (options.count || Infinity)); results.total = total; } return results; } execute.matches = query; return execute; }; }); }, 'dojox/color/_base':function(){ define("dojox/color/_base", ["dojo/_base/kernel", "../main", "dojo/_base/lang", "dojo/_base/Color", "dojo/colors"], function(dojo, dojox, lang, Color, colors){ var cx = lang.getObject("dojox.color", true); /*===== cx = dojox.color =====*/ // alias all the dojo.Color mechanisms cx.Color=Color; cx.blend=Color.blendColors; cx.fromRgb=Color.fromRgb; cx.fromHex=Color.fromHex; cx.fromArray=Color.fromArray; cx.fromString=Color.fromString; // alias the dojo.colors mechanisms cx.greyscale=colors.makeGrey; lang.mixin(cx,{ fromCmy: function(/* Object|Array|int */cyan, /*int*/magenta, /*int*/yellow){ // summary // Create a dojox.color.Color from a CMY defined color. // All colors should be expressed as 0-100 (percentage) if(lang.isArray(cyan)){ magenta=cyan[1], yellow=cyan[2], cyan=cyan[0]; } else if(lang.isObject(cyan)){ magenta=cyan.m, yellow=cyan.y, cyan=cyan.c; } cyan/=100, magenta/=100, yellow/=100; var r=1-cyan, g=1-magenta, b=1-yellow; return new Color({ r:Math.round(r*255), g:Math.round(g*255), b:Math.round(b*255) }); // dojox.color.Color }, fromCmyk: function(/* Object|Array|int */cyan, /*int*/magenta, /*int*/yellow, /*int*/black){ // summary // Create a dojox.color.Color from a CMYK defined color. // All colors should be expressed as 0-100 (percentage) if(lang.isArray(cyan)){ magenta=cyan[1], yellow=cyan[2], black=cyan[3], cyan=cyan[0]; } else if(lang.isObject(cyan)){ magenta=cyan.m, yellow=cyan.y, black=cyan.b, cyan=cyan.c; } cyan/=100, magenta/=100, yellow/=100, black/=100; var r,g,b; r = 1-Math.min(1, cyan*(1-black)+black); g = 1-Math.min(1, magenta*(1-black)+black); b = 1-Math.min(1, yellow*(1-black)+black); return new Color({ r:Math.round(r*255), g:Math.round(g*255), b:Math.round(b*255) }); // dojox.color.Color }, fromHsl: function(/* Object|Array|int */hue, /* int */saturation, /* int */luminosity){ // summary // Create a dojox.color.Color from an HSL defined color. // hue from 0-359 (degrees), saturation and luminosity 0-100. if(lang.isArray(hue)){ saturation=hue[1], luminosity=hue[2], hue=hue[0]; } else if(lang.isObject(hue)){ saturation=hue.s, luminosity=hue.l, hue=hue.h; } saturation/=100; luminosity/=100; while(hue<0){ hue+=360; } while(hue>=360){ hue-=360; } var r, g, b; if(hue<120){ r=(120-hue)/60, g=hue/60, b=0; } else if (hue<240){ r=0, g=(240-hue)/60, b=(hue-120)/60; } else { r=(hue-240)/60, g=0, b=(360-hue)/60; } r=2*saturation*Math.min(r, 1)+(1-saturation); g=2*saturation*Math.min(g, 1)+(1-saturation); b=2*saturation*Math.min(b, 1)+(1-saturation); if(luminosity<0.5){ r*=luminosity, g*=luminosity, b*=luminosity; }else{ r=(1-luminosity)*r+2*luminosity-1; g=(1-luminosity)*g+2*luminosity-1; b=(1-luminosity)*b+2*luminosity-1; } return new Color({ r:Math.round(r*255), g:Math.round(g*255), b:Math.round(b*255) }); // dojox.color.Color } }); cx.fromHsv = function(/* Object|Array|int */hue, /* int */saturation, /* int */value){ // summary // Create a dojox.color.Color from an HSV defined color. // hue from 0-359 (degrees), saturation and value 0-100. if(lang.isArray(hue)){ saturation=hue[1], value=hue[2], hue=hue[0]; } else if (lang.isObject(hue)){ saturation=hue.s, value=hue.v, hue=hue.h; } if(hue==360){ hue=0; } saturation/=100; value/=100; var r, g, b; if(saturation==0){ r=value, b=value, g=value; }else{ var hTemp=hue/60, i=Math.floor(hTemp), f=hTemp-i; var p=value*(1-saturation); var q=value*(1-(saturation*f)); var t=value*(1-(saturation*(1-f))); switch(i){ case 0:{ r=value, g=t, b=p; break; } case 1:{ r=q, g=value, b=p; break; } case 2:{ r=p, g=value, b=t; break; } case 3:{ r=p, g=q, b=value; break; } case 4:{ r=t, g=p, b=value; break; } case 5:{ r=value, g=p, b=q; break; } } } return new Color({ r:Math.round(r*255), g:Math.round(g*255), b:Math.round(b*255) }); // dojox.color.Color }; lang.extend(Color,{ toCmy: function(){ // summary // Convert this Color to a CMY definition. var cyan=1-(this.r/255), magenta=1-(this.g/255), yellow=1-(this.b/255); return { c:Math.round(cyan*100), m:Math.round(magenta*100), y:Math.round(yellow*100) }; // Object }, toCmyk: function(){ // summary // Convert this Color to a CMYK definition. var cyan, magenta, yellow, black; var r=this.r/255, g=this.g/255, b=this.b/255; black = Math.min(1-r, 1-g, 1-b); cyan = (1-r-black)/(1-black); magenta = (1-g-black)/(1-black); yellow = (1-b-black)/(1-black); return { c:Math.round(cyan*100), m:Math.round(magenta*100), y:Math.round(yellow*100), b:Math.round(black*100) }; // Object }, toHsl: function(){ // summary // Convert this Color to an HSL definition. var r=this.r/255, g=this.g/255, b=this.b/255; var min = Math.min(r, b, g), max = Math.max(r, g, b); var delta = max-min; var h=0, s=0, l=(min+max)/2; if(l>0 && l<1){ s = delta/((l<0.5)?(2*l):(2-2*l)); } if(delta>0){ if(max==r && max!=g){ h+=(g-b)/delta; } if(max==g && max!=b){ h+=(2+(b-r)/delta); } if(max==b && max!=r){ h+=(4+(r-g)/delta); } h*=60; } return { h:h, s:Math.round(s*100), l:Math.round(l*100) }; // Object }, toHsv: function(){ // summary // Convert this Color to an HSV definition. var r=this.r/255, g=this.g/255, b=this.b/255; var min = Math.min(r, b, g), max = Math.max(r, g, b); var delta = max-min; var h = null, s = (max==0)?0:(delta/max); if(s==0){ h = 0; }else{ if(r==max){ h = 60*(g-b)/delta; }else if(g==max){ h = 120 + 60*(b-r)/delta; }else{ h = 240 + 60*(r-g)/delta; } if(h<0){ h+=360; } } return { h:h, s:Math.round(s*100), v:Math.round(max*100) }; // Object } }); return cx; }); }, 'dojo/store/Memory':function(){ define("dojo/store/Memory", ["../_base/declare", "./util/QueryResults", "./util/SimpleQueryEngine"], function(declare, QueryResults, SimpleQueryEngine) { // module: // dojo/store/Memory // summary: // The module defines an in-memory object store. return declare("dojo.store.Memory", null, { // summary: // This is a basic in-memory object store. It implements dojo.store.api.Store. constructor: function(/*dojo.store.Memory*/ options){ // summary: // Creates a memory object store. // options: // This provides any configuration information that will be mixed into the store. // This should generally include the data property to provide the starting set of data. for(var i in options){ this[i] = options[i]; } this.setData(this.data || []); }, // data: Array // The array of all the objects in the memory store data:null, // idProperty: String // Indicates the property to use as the identity property. The values of this // property should be unique. idProperty: "id", // index: Object // An index of data indices into the data array by id index:null, // queryEngine: Function // Defines the query engine to use for querying the data store queryEngine: SimpleQueryEngine, get: function(id){ // summary: // Retrieves an object by its identity // id: Number // The identity to use to lookup the object // returns: Object // The object in the store that matches the given id. return this.data[this.index[id]]; }, getIdentity: function(object){ // summary: // Returns an object's identity // object: Object // The object to get the identity from // returns: Number return object[this.idProperty]; }, put: function(object, options){ // summary: // Stores an object // object: Object // The object to store. // options: dojo.store.api.Store.PutDirectives?? // Additional metadata for storing the data. Includes an "id" // property if a specific id is to be used. // returns: Number var data = this.data, index = this.index, idProperty = this.idProperty; var id = (options && "id" in options) ? options.id : idProperty in object ? object[idProperty] : Math.random(); if(id in index){ // object exists if(options && options.overwrite === false){ throw new Error("Object already exists"); } // replace the entry in data data[index[id]] = object; }else{ // add the new object index[id] = data.push(object) - 1; } return id; }, add: function(object, options){ // summary: // Creates an object, throws an error if the object already exists // object: Object // The object to store. // options: dojo.store.api.Store.PutDirectives?? // Additional metadata for storing the data. Includes an "id" // property if a specific id is to be used. // returns: Number (options = options || {}).overwrite = false; // call put with overwrite being false return this.put(object, options); }, remove: function(id){ // summary: // Deletes an object by its identity // id: Number // The identity to use to delete the object // returns: Boolean // Returns true if an object was removed, falsy (undefined) if no object matched the id var index = this.index; var data = this.data; if(id in index){ data.splice(index[id], 1); // now we have to reindex this.setData(data); return true; } }, query: function(query, options){ // summary: // Queries the store for objects. // query: Object // The query to use for retrieving objects from the store. // options: dojo.store.api.Store.QueryOptions? // The optional arguments to apply to the resultset. // returns: dojo.store.api.Store.QueryResults // The results of the query, extended with iterative methods. // // example: // Given the following store: // // | var store = new dojo.store.Memory({ // | data: [ // | {id: 1, name: "one", prime: false }, // | {id: 2, name: "two", even: true, prime: true}, // | {id: 3, name: "three", prime: true}, // | {id: 4, name: "four", even: true, prime: false}, // | {id: 5, name: "five", prime: true} // | ] // | }); // // ...find all items where "prime" is true: // // | var results = store.query({ prime: true }); // // ...or find all items where "even" is true: // // | var results = store.query({ even: true }); return QueryResults(this.queryEngine(query, options)(this.data)); }, setData: function(data){ // summary: // Sets the given data as the source for this store, and indexes it // data: Object[] // An array of objects to use as the source of data. if(data.items){ // just for convenience with the data format IFRS expects this.idProperty = data.identifier || this.idProperty; data = this.data = data.items; }else{ this.data = data; } this.index = {}; for(var i = 0, l = data.length; i < l; i++){ this.index[data[i][this.idProperty]] = i; } } }); }); }, 'dijit/form/ComboBox':function(){ define("dijit/form/ComboBox", [ "dojo/_base/declare", // declare "./ValidationTextBox", "./ComboBoxMixin" ], function(declare, ValidationTextBox, ComboBoxMixin){ /*===== var ValidationTextBox = dijit.form.ValidationTextBox; var ComboBoxMixin = dijit.form.ComboBoxMixin; =====*/ // module: // dijit/form/ComboBox // summary: // Auto-completing text box return declare("dijit.form.ComboBox", [ValidationTextBox, ComboBoxMixin], { // summary: // Auto-completing text box // // description: // 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. // If OPTION tags are used as the data provider via markup, // then the OPTION tag's child text node is used as the widget value // when selected. The OPTION tag's value attribute is ignored. // To set the default value when using OPTION tags, specify the selected // attribute on 1 of the child OPTION tags. // // Some of the options to the ComboBox are actually arguments to the data // provider. }); }); }, 'dijit/form/_CheckBoxMixin':function(){ define("dijit/form/_CheckBoxMixin", [ "dojo/_base/declare", // declare "dojo/dom-attr", // domAttr.set "dojo/_base/event" // event.stop ], function(declare, domAttr, event){ // module: // dijit/form/_CheckBoxMixin // summary: // Mixin to provide widget functionality corresponding to an HTML checkbox return declare("dijit.form._CheckBoxMixin", null, { // summary: // Mixin to provide widget functionality corresponding to an HTML checkbox // // 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. // // type: [private] String // type attribute on <input> node. // Overrides `dijit.form.Button.type`. Users should not change this value. type: "checkbox", // value: String // As an initialization parameter, equivalent to value field on normal checkbox // (if checked, the value is passed as the value when form is submitted). value: "on", // readOnly: Boolean // Should this widget respond to user input? // In markup, this is specified as "readOnly". // Similar to disabled except readOnly form values are submitted. readOnly: false, // aria-pressed for toggle buttons, and aria-checked for checkboxes _aria_attr: "aria-checked", _setReadOnlyAttr: function(/*Boolean*/ value){ this._set("readOnly", value); domAttr.set(this.focusNode, 'readOnly', value); }, // Override dijit.form.Button._setLabelAttr() since we don't even have a containerNode. // Normally users won't try to set label, except when CheckBox or RadioButton is the child of a dojox.layout.TabContainer _setLabelAttr: undefined, postMixInProperties: function(){ if(this.value == ""){ this.value = "on"; } this.inherited(arguments); }, reset: function(){ this.inherited(arguments); // Handle unlikely event that the <input type=checkbox> value attribute has changed this._set("value", this.params.value || "on"); domAttr.set(this.focusNode, 'value', this.value); }, _onClick: function(/*Event*/ e){ // summary: // Internal function to handle click actions - need to check // readOnly, since button no longer does that check. if(this.readOnly){ event.stop(e); return false; } return this.inherited(arguments); } }); }); }, 'url:dijit/form/templates/ValidationTextBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\n\tid=\"widget_${id}\" role=\"presentation\"\n\t><div class='dijitReset dijitValidationContainer'\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"Χ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t/></div\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class=\"dijitReset dijitInputInner\" data-dojo-attach-point='textbox,focusNode' autocomplete=\"off\"\n\t\t\t${!nameAttrSetting} type='${type}'\n\t/></div\n></div>\n", 'url:dijit/form/templates/TextBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\" id=\"widget_${id}\" role=\"presentation\"\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class=\"dijitReset dijitInputInner\" data-dojo-attach-point='textbox,focusNode' autocomplete=\"off\"\n\t\t\t${!nameAttrSetting} type='${type}'\n\t/></div\n></div>\n", 'dijit/form/DataList':function(){ define("dijit/form/DataList", [ "dojo/_base/declare", // declare "dojo/dom", // dom.byId "dojo/_base/lang", // lang.trim "dojo/query", // query "dojo/store/Memory", // dojo.store.Memory "../registry" // registry.add registry.remove ], function(declare, dom, lang, query, MemoryStore, registry){ // module: // dijit/form/DataList // summary: // Inefficient but small data store specialized for inlined data via OPTION tags function toItem(/*DOMNode*/ option){ // summary: // Convert <option> node to hash return { id: option.value, value: option.value, name: lang.trim(option.innerText || option.textContent || '') }; } return declare("dijit.form.DataList", MemoryStore, { // summary: // Inefficient but small data store specialized for inlined data via OPTION tags // // description: // Provides a store for inlined data like: // // | <datalist> // | <option value="AL">Alabama</option> // | ... constructor: function(/*Object?*/ params, /*DomNode|String*/ srcNodeRef){ // store pointer to original DOM tree this.domNode = dom.byId(srcNodeRef); lang.mixin(this, params); if(this.id){ registry.add(this); // add to registry so it can be easily found by id } this.domNode.style.display = "none"; this.inherited(arguments, [{ data: query("option", this.domNode).map(toItem) }]); }, destroy: function(){ registry.remove(this.id); }, fetchSelectedItem: function(){ // summary: // Get the option marked as selected, like `<option selected>`. // Not part of dojo.data API. var option = query("> option[selected]", this.domNode)[0] || query("> option", this.domNode)[0]; return option && toItem(option); } }); }); }, 'url:dijit/templates/Dialog.html':"<div class=\"dijitDialog\" role=\"dialog\" aria-labelledby=\"${id}_title\">\n\t<div data-dojo-attach-point=\"titleBar\" class=\"dijitDialogTitleBar\">\n\t<span data-dojo-attach-point=\"titleNode\" class=\"dijitDialogTitle\" id=\"${id}_title\"></span>\n\t<span data-dojo-attach-point=\"closeButtonNode\" class=\"dijitDialogCloseIcon\" data-dojo-attach-event=\"ondijitclick: onCancel\" title=\"${buttonCancel}\" role=\"button\" tabIndex=\"0\">\n\t\t<span data-dojo-attach-point=\"closeText\" class=\"closeText\" title=\"${buttonCancel}\">x</span>\n\t</span>\n\t</div>\n\t\t<div data-dojo-attach-point=\"containerNode\" class=\"dijitDialogPaneContent\"></div>\n</div>\n", 'dijit/form/CheckBox':function(){ require({cache:{ 'url:dijit/form/templates/CheckBox.html':"<div class=\"dijit dijitReset dijitInline\" role=\"presentation\"\n\t><input\n\t \t${!nameAttrSetting} type=\"${type}\" ${checkedAttrSetting}\n\t\tclass=\"dijitReset dijitCheckBoxInput\"\n\t\tdata-dojo-attach-point=\"focusNode\"\n\t \tdata-dojo-attach-event=\"onclick:_onClick\"\n/></div>\n"}}); define("dijit/form/CheckBox", [ "require", "dojo/_base/declare", // declare "dojo/dom-attr", // domAttr.set "dojo/_base/kernel", "dojo/query", // query "dojo/ready", "./ToggleButton", "./_CheckBoxMixin", "dojo/text!./templates/CheckBox.html", "dojo/NodeList-dom" // NodeList.addClass/removeClass ], function(require, declare, domAttr, kernel, query, ready, ToggleButton, _CheckBoxMixin, template){ /*===== var ToggleButton = dijit.form.ToggleButton; var _CheckBoxMixin = dijit.form._CheckBoxMixin; =====*/ // module: // dijit/form/CheckBox // summary: // Checkbox widget // Back compat w/1.6, remove for 2.0 if(!kernel.isAsync){ ready(0, function(){ var requires = ["dijit/form/RadioButton"]; require(requires); // use indirection so modules not rolled into a build }); } return declare("dijit.form.CheckBox", [ToggleButton, _CheckBoxMixin], { // 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: template, baseClass: "dijitCheckBox", _setValueAttr: function(/*String|Boolean*/ newValue, /*Boolean*/ priorityChange){ // summary: // Handler for value= attribute to constructor, and also calls to // set('value', val). // description: // During initialization, just saves as attribute to the <input type=checkbox>. // // After initialization, // when passed a boolean, controls whether or not the CheckBox is checked. // If passed a string, changes the value attribute of the CheckBox (the one // specified as "value" when the CheckBox was constructed (ex: <input // data-dojo-type="dijit.CheckBox" value="chicken">) // widget.set('value', string) will check the checkbox and change the value to the // specified string // widget.set('value', boolean) will change the checked state. if(typeof newValue == "string"){ this._set("value", newValue); domAttr.set(this.focusNode, 'value', newValue); newValue = true; } if(this._created){ this.set('checked', newValue, priorityChange); } }, _getValueAttr: function(){ // summary: // Hook so get('value') works. // description: // If the CheckBox is checked, returns the value attribute. // Otherwise returns false. return (this.checked ? this.value : false); }, // Override behavior from Button, since we don't have an iconNode _setIconClassAttr: null, postMixInProperties: function(){ this.inherited(arguments); // Need to set initial checked state as part of template, so that form submit works. // domAttr.set(node, "checked", bool) doesn't work on IE until node has been attached // to <body>, see #8666 this.checkedAttrSetting = this.checked ? "checked" : ""; }, _fillContent: function(){ // Override Button::_fillContent() since it doesn't make sense for CheckBox, // since CheckBox doesn't even have a container }, _onFocus: function(){ if(this.id){ query("label[for='"+this.id+"']").addClass("dijitFocusedLabel"); } this.inherited(arguments); }, _onBlur: function(){ if(this.id){ query("label[for='"+this.id+"']").removeClass("dijitFocusedLabel"); } this.inherited(arguments); } }); }); }, 'dijit/_PaletteMixin':function(){ define("dijit/_PaletteMixin", [ "dojo/_base/declare", // declare "dojo/dom-attr", // domAttr.set "dojo/dom-class", // domClass.add domClass.remove "dojo/dom-construct", // domConstruct.create domConstruct.place "dojo/_base/event", // event.stop "dojo/keys", // keys "dojo/_base/lang", // lang.getObject "./_CssStateMixin", "./focus", "./typematic" ], function(declare, domAttr, domClass, domConstruct, event, keys, lang, _CssStateMixin, focus, typematic){ /*===== var _CssStateMixin = dijit._CssStateMixin; =====*/ // module: // dijit/_PaletteMixin // summary: // A keyboard accessible palette, for picking a color/emoticon/etc. return declare("dijit._PaletteMixin", [_CssStateMixin], { // summary: // A keyboard accessible palette, for picking a color/emoticon/etc. // description: // A mixin for a grid showing various entities, so the user can pick a certain entity. // defaultTimeout: Number // Number of milliseconds before a held key or button becomes typematic defaultTimeout: 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 rate timeoutChangeRate: 0.90, // value: String // Currently selected color/emoticon/etc. value: "", // _selectedCell: [private] Integer // Index of the currently selected cell. Initially, none selected _selectedCell: -1, /*===== // _currentFocus: [private] DomNode // The currently focused cell (if the palette itself has focus), or otherwise // the cell to be focused when the palette itself gets focus. // Different from value, which represents the selected (i.e. clicked) cell. _currentFocus: null, =====*/ /*===== // _xDim: [protected] Integer // This is the number of cells horizontally across. _xDim: null, =====*/ /*===== // _yDim: [protected] Integer // This is the number of cells vertically down. _yDim: null, =====*/ // tabIndex: String // Widget tab index. tabIndex: "0", // cellClass: [protected] String // CSS class applied to each cell in the palette cellClass: "dijitPaletteCell", // dyeClass: [protected] String // Name of javascript class for Object created for each cell of the palette. // dyeClass should implements dijit.Dye interface dyeClass: '', // summary: String // Localized summary for the palette table summary: '', _setSummaryAttr: "paletteTableNode", _dyeFactory: function(value /*===== , row, col =====*/){ // summary: // Return instance of dijit.Dye for specified cell of palette // tags: // extension var dyeClassObj = lang.getObject(this.dyeClass); return new dyeClassObj(value); }, _preparePalette: function(choices, titles) { // summary: // Subclass must call _preparePalette() from postCreate(), passing in the tooltip // for each cell // choices: String[][] // id's for each cell of the palette, used to create Dye JS object for each cell // titles: String[] // Localized tooltip for each cell this._cells = []; var url = this._blankGif; this.connect(this.gridNode, "ondijitclick", "_onCellClick"); for(var row=0; row < choices.length; row++){ var rowNode = domConstruct.create("tr", {tabIndex: "-1"}, this.gridNode); for(var col=0; col < choices[row].length; col++){ var value = choices[row][col]; if(value){ var cellObject = this._dyeFactory(value, row, col); var cellNode = domConstruct.create("td", { "class": this.cellClass, tabIndex: "-1", title: titles[value], role: "gridcell" }); // prepare cell inner structure cellObject.fillCell(cellNode, url); domConstruct.place(cellNode, rowNode); cellNode.index = this._cells.length; // save cell info into _cells this._cells.push({node:cellNode, dye:cellObject}); } } } 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 cell. // 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: this.isLeftToRight() ? 1 : -1, LEFT_ARROW: this.isLeftToRight() ? -1 : 1 }; for(var key in keyIncrementMap){ this._connects.push( typematic.addKeyListener( this.domNode, {charOrCode: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 ) ); } }, postCreate: function(){ this.inherited(arguments); // Set initial navigable node. this._setCurrent(this._cells[0].node); }, focus: function(){ // summary: // Focus this widget. Puts focus on the most recently focused cell. // The cell already has tabIndex set, just need to set CSS and focus it focus.focus(this._currentFocus); }, _onCellClick: function(/*Event*/ evt){ // summary: // Handler for click, enter key & space key. Selects the cell. // evt: // The event. // tags: // private var target = evt.target; // Find TD associated with click event. For ColorPalette user likely clicked IMG inside of TD while(target.tagName != "TD"){ if(!target.parentNode || target == this.gridNode){ // probably can never happen, but just in case return; } target = target.parentNode; } var value = this._getDye(target).getValue(); // First focus the clicked cell, and then send onChange() notification. // onChange() (via _setValueAttr) must be after the focus call, because // it may trigger a refocus to somewhere else (like the Editor content area), and that // second focus should win. this._setCurrent(target); focus.focus(target); this._setValueAttr(value, true); event.stop(evt); }, _setCurrent: function(/*DomNode*/ node){ // summary: // Sets which node is the focused cell. // description: // At any point in time there's exactly one // cell with tabIndex != -1. If focus is inside the palette then // focus is on that cell. // // After calling this method, arrow key handlers and mouse click handlers // should focus the cell in a setTimeout(). // tags: // protected if("_currentFocus" in this){ // Remove tabIndex on old cell domAttr.set(this._currentFocus, "tabIndex", "-1"); } // Set tabIndex of new cell this._currentFocus = node; if(node){ domAttr.set(node, "tabIndex", this.tabIndex); } }, _setValueAttr: function(value, priorityChange){ // summary: // This selects a cell. It triggers the onChange event. // value: String value of the cell to select // tags: // protected // priorityChange: // Optional parameter used to tell the select whether or not to fire // onChange event. // clear old selected cell if(this._selectedCell >= 0){ domClass.remove(this._cells[this._selectedCell].node, this.cellClass + "Selected"); } this._selectedCell = -1; // search for cell matching specified value if(value){ for(var i = 0; i < this._cells.length; i++){ if(value == this._cells[i].dye.getValue()){ this._selectedCell = i; domClass.add(this._cells[i].node, this.cellClass + "Selected"); break; } } } // record new value, or null if no matching cell this._set("value", this._selectedCell >= 0 ? value : null); if(priorityChange || priorityChange === undefined){ this.onChange(value); } }, onChange: function(/*===== value =====*/){ // summary: // Callback when a cell is selected. // value: String // Value corresponding to cell. }, _navigateByKey: function(increment, typeCount){ // summary: // This is the callback for typematic. // It changes the focus and the highlighed cell. // increment: // How much the key is navigated. // typeCount: // How many times typematic has fired. // tags: // private // typecount == -1 means the key is released. if(typeCount == -1){ return; } var newFocusIndex = this._currentFocus.index + increment; if(newFocusIndex < this._cells.length && newFocusIndex > -1){ var focusNode = this._cells[newFocusIndex].node; this._setCurrent(focusNode); // Actually focus the node, for the benefit of screen readers. // Use setTimeout because IE doesn't like changing focus inside of an event handler setTimeout(lang.hitch(dijit, "focus", focusNode), 0); } }, _getDye: function(/*DomNode*/ cell){ // summary: // Get JS object for given cell DOMNode return this._cells[cell.index].dye; } }); /*===== declare("dijit.Dye", null, { // summary: // Interface for the JS Object associated with a palette cell (i.e. DOMNode) constructor: function(alias, row, col){ // summary: // Initialize according to value or alias like "white" // alias: String }, getValue: function(){ // summary: // Return "value" of cell; meaning of "value" varies by subclass. // description: // For example color hex value, emoticon ascii value etc, entity hex value. }, fillCell: function(cell, blankGif){ // summary: // Add cell DOMNode inner structure // cell: DomNode // The surrounding cell // blankGif: String // URL for blank cell image } } ); =====*/ }); }, 'url:dijit/templates/TitlePane.html':"<div>\n\t<div data-dojo-attach-event=\"onclick:_onTitleClick, onkeydown:_onTitleKey\"\n\t\t\tclass=\"dijitTitlePaneTitle\" data-dojo-attach-point=\"titleBarNode\">\n\t\t<div class=\"dijitTitlePaneTitleFocus\" data-dojo-attach-point=\"focusNode\">\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" data-dojo-attach-point=\"arrowNode\" class=\"dijitArrowNode\" role=\"presentation\"\n\t\t\t/><span data-dojo-attach-point=\"arrowNodeInner\" class=\"dijitArrowNodeInner\"></span\n\t\t\t><span data-dojo-attach-point=\"titleNode\" class=\"dijitTitlePaneTextNode\"></span>\n\t\t</div>\n\t</div>\n\t<div class=\"dijitTitlePaneContentOuter\" data-dojo-attach-point=\"hideNode\" role=\"presentation\">\n\t\t<div class=\"dijitReset\" data-dojo-attach-point=\"wipeNode\" role=\"presentation\">\n\t\t\t<div class=\"dijitTitlePaneContentInner\" data-dojo-attach-point=\"containerNode\" role=\"region\" id=\"${id}_pane\">\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", 'dijit/form/ValidationTextBox':function(){ require({cache:{ 'url:dijit/form/templates/ValidationTextBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\n\tid=\"widget_${id}\" role=\"presentation\"\n\t><div class='dijitReset dijitValidationContainer'\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"Χ \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t/></div\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class=\"dijitReset dijitInputInner\" data-dojo-attach-point='textbox,focusNode' autocomplete=\"off\"\n\t\t\t${!nameAttrSetting} type='${type}'\n\t/></div\n></div>\n"}}); define("dijit/form/ValidationTextBox", [ "dojo/_base/declare", // declare "dojo/i18n", // i18n.getLocalization "./TextBox", "../Tooltip", "dojo/text!./templates/ValidationTextBox.html", "dojo/i18n!./nls/validate" ], function(declare, i18n, TextBox, Tooltip, template){ /*===== var Tooltip = dijit.Tooltip; var TextBox = dijit.form.TextBox; =====*/ // module: // dijit/form/ValidationTextBox // summary: // Base class for textbox widgets with the ability to validate content of various types and provide user feedback. /*===== dijit.form.ValidationTextBox.__Constraints = function(){ // locale: String // locale used for validation, picks up value from this widget's lang attribute // _flags_: anything // various flags passed to regExpGen function this.locale = ""; this._flags_ = ""; } =====*/ return declare("dijit.form.ValidationTextBox", TextBox, { // summary: // Base class for textbox widgets with the ability to validate content of various types and provide user feedback. // tags: // protected templateString: template, baseClass: "dijitTextBox dijitValidationTextBox", // required: Boolean // User is required to enter data into this field. required: false, // promptMessage: String // If defined, display this hint string immediately on focus to the textbox, if empty. // Also displays if the textbox value is Incomplete (not yet valid but will be with additional input). // Think of this like a tooltip that tells the user what to do, not an error message // that tells the user what they've done wrong. // // Message disappears when user starts typing. promptMessage: "", // invalidMessage: String // The message to display if value is invalid. // The translated string value is read from the message file by default. // Set to "" to use the promptMessage instead. invalidMessage: "$_unset_$", // missingMessage: String // The message to display if value is empty and the field is required. // The translated string value is read from the message file by default. // Set to "" to use the invalidMessage instead. missingMessage: "$_unset_$", // message: String // Currently error/prompt message. // When using the default tooltip implementation, this will only be // displayed when the field is focused. message: "", // constraints: dijit.form.ValidationTextBox.__Constraints // user-defined object needed to pass parameters to the validator functions constraints: {}, // regExp: [extension protected] String // regular expression string used to validate the input // Do not specify both regExp and regExpGen regExp: ".*", regExpGen: function(/*dijit.form.ValidationTextBox.__Constraints*/ /*===== constraints =====*/){ // summary: // Overridable function used to generate regExp when dependent on constraints. // Do not specify both regExp and regExpGen. // tags: // extension protected return this.regExp; // String }, // state: [readonly] String // Shows current state (ie, validation result) of input (""=Normal, Incomplete, or Error) state: "", // tooltipPosition: String[] // See description of `dijit.Tooltip.defaultPosition` for details on this parameter. tooltipPosition: [], _setValueAttr: function(){ // summary: // Hook so set('value', ...) works. this.inherited(arguments); this.validate(this.focused); }, validator: function(/*anything*/ value, /*dijit.form.ValidationTextBox.__Constraints*/ constraints){ // summary: // Overridable function used to validate the text input against the regular expression. // tags: // protected return (new RegExp("^(?:" + this.regExpGen(constraints) + ")"+(this.required?"":"?")+"$")).test(value) && (!this.required || !this._isEmpty(value)) && (this._isEmpty(value) || this.parse(value, constraints) !== undefined); // Boolean }, _isValidSubset: function(){ // summary: // Returns true if the value is either already valid or could be made valid by appending characters. // This is used for validation while the user [may be] still typing. return this.textbox.value.search(this._partialre) == 0; }, isValid: function(/*Boolean*/ /*===== isFocused =====*/){ // summary: // Tests if value is valid. // Can override with your own routine in a subclass. // tags: // protected return this.validator(this.textbox.value, this.constraints); }, _isEmpty: function(value){ // summary: // Checks for whitespace return (this.trim ? /^\s*$/ : /^$/).test(value); // Boolean }, getErrorMessage: function(/*Boolean*/ /*===== isFocused =====*/){ // summary: // Return an error message to show if appropriate // tags: // protected return (this.required && this._isEmpty(this.textbox.value)) ? this.missingMessage : this.invalidMessage; // String }, getPromptMessage: function(/*Boolean*/ /*===== isFocused =====*/){ // summary: // Return a hint message to show when widget is first focused // tags: // protected return this.promptMessage; // String }, _maskValidSubsetError: true, validate: function(/*Boolean*/ isFocused){ // summary: // Called by oninit, onblur, and onkeypress. // description: // Show missing or invalid messages if appropriate, and highlight textbox field. // tags: // protected var message = ""; var isValid = this.disabled || this.isValid(isFocused); if(isValid){ this._maskValidSubsetError = true; } var isEmpty = this._isEmpty(this.textbox.value); var isValidSubset = !isValid && isFocused && this._isValidSubset(); this._set("state", isValid ? "" : (((((!this._hasBeenBlurred || isFocused) && isEmpty) || isValidSubset) && this._maskValidSubsetError) ? "Incomplete" : "Error")); this.focusNode.setAttribute("aria-invalid", isValid ? "false" : "true"); if(this.state == "Error"){ this._maskValidSubsetError = isFocused && isValidSubset; // we want the error to show up after a blur and refocus message = this.getErrorMessage(isFocused); }else if(this.state == "Incomplete"){ message = this.getPromptMessage(isFocused); // show the prompt whenever the value is not yet complete this._maskValidSubsetError = !this._hasBeenBlurred || isFocused; // no Incomplete warnings while focused }else if(isEmpty){ message = this.getPromptMessage(isFocused); // show the prompt whenever there's no error and no text } this.set("message", message); return isValid; }, displayMessage: function(/*String*/ message){ // summary: // Overridable method to display validation errors/hints. // By default uses a tooltip. // tags: // extension if(message && this.focused){ Tooltip.show(message, this.domNode, this.tooltipPosition, !this.isLeftToRight()); }else{ Tooltip.hide(this.domNode); } }, _refreshState: function(){ // Overrides TextBox._refreshState() this.validate(this.focused); this.inherited(arguments); }, //////////// INITIALIZATION METHODS /////////////////////////////////////// constructor: function(){ this.constraints = {}; }, _setConstraintsAttr: function(/*Object*/ constraints){ if(!constraints.locale && this.lang){ constraints.locale = this.lang; } this._set("constraints", constraints); this._computePartialRE(); }, _computePartialRE: function(){ var p = this.regExpGen(this.constraints); this.regExp = p; var partialre = ""; // parse the regexp and produce a new regexp that matches valid subsets // if the regexp is .* then there's no use in matching subsets since everything is valid if(p != ".*"){ this.regExp.replace(/\\.|\[\]|\[.*?[^\\]{1}\]|\{.*?\}|\(\?[=:!]|./g, function(re){ switch(re.charAt(0)){ case '{': case '+': case '?': case '*': case '^': case '$': case '|': case '(': partialre += re; break; case ")": partialre += "|$)"; break; default: partialre += "(?:"+re+"|$)"; break; } } );} try{ // this is needed for now since the above regexp parsing needs more test verification "".search(partialre); }catch(e){ // should never be here unless the original RE is bad or the parsing is bad partialre = this.regExp; console.warn('RegExp error in ' + this.declaredClass + ': ' + this.regExp); } // should never be here unless the original RE is bad or the parsing is bad this._partialre = "^(?:" + partialre + ")$"; }, postMixInProperties: function(){ this.inherited(arguments); this.messages = i18n.getLocalization("dijit.form", "validate", this.lang); if(this.invalidMessage == "$_unset_$"){ this.invalidMessage = this.messages.invalidMessage; } if(!this.invalidMessage){ this.invalidMessage = this.promptMessage; } if(this.missingMessage == "$_unset_$"){ this.missingMessage = this.messages.missingMessage; } if(!this.missingMessage){ this.missingMessage = this.invalidMessage; } this._setConstraintsAttr(this.constraints); // this needs to happen now (and later) due to codependency on _set*Attr calls attachPoints }, _setDisabledAttr: function(/*Boolean*/ value){ this.inherited(arguments); // call FormValueWidget._setDisabledAttr() this._refreshState(); }, _setRequiredAttr: function(/*Boolean*/ value){ this._set("required", value); this.focusNode.setAttribute("aria-required", value); this._refreshState(); }, _setMessageAttr: function(/*String*/ message){ this._set("message", message); this.displayMessage(message); }, reset:function(){ // Overrides dijit.form.TextBox.reset() by also // hiding errors about partial matches this._maskValidSubsetError = true; this.inherited(arguments); }, _onBlur: function(){ // the message still exists but for back-compat, and to erase the tooltip // (if the message is being displayed as a tooltip), call displayMessage('') this.displayMessage(''); this.inherited(arguments); } }); }); }, 'dojo/data/util/filter':function(){ define("dojo/data/util/filter", ["../../_base/lang"], function(lang) { // module: // dojo/data/util/filter // summary: // TODOC var filter = lang.getObject("dojo.data.util.filter", true); 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 += "\\"; //fallthrough default: rxp += c; } } rxp += "$"; if(ignoreCase){ return new RegExp(rxp,"mi"); //RegExp }else{ return new RegExp(rxp,"m"); //RegExp } }; return filter; }); }, 'dijit/form/FilteringSelect':function(){ define("dijit/form/FilteringSelect", [ "dojo/data/util/filter", // filter.patternToRegExp "dojo/_base/declare", // declare "dojo/_base/Deferred", // Deferred.when "dojo/_base/lang", // lang.mixin "./MappedTextBox", "./ComboBoxMixin" ], function(filter, declare, Deferred, lang, MappedTextBox, ComboBoxMixin){ /*===== var MappedTextBox = dijit.form.MappedTextBox; var ComboBoxMixin = dijit.form.ComboBoxMixin; =====*/ // module: // dijit/form/FilteringSelect // summary: // An enhanced version of the HTML SELECT tag, populated dynamically return declare("dijit.form.FilteringSelect", [MappedTextBox, ComboBoxMixin], { // summary: // An enhanced version of the HTML SELECT tag, populated dynamically // // description: // An enhanced version of the HTML SELECT tag, populated dynamically. It works // very nicely with very large data sets because it can load and page data as needed. // It also resembles ComboBox, but does not allow values outside of the provided ones. // If OPTION tags are used as the data provider via markup, then the // OPTION tag's child text node is used as the displayed value when selected // while the OPTION tag's value attribute is used as the widget value on form submit. // To set the default value when using OPTION tags, specify the selected // attribute on 1 of the child OPTION tags. // // 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) // required: Boolean // True (default) if user is required to enter a value into this field. required: true, _lastDisplayedValue: "", _isValidSubset: function(){ return this._opened; }, isValid: function(){ // Overrides ValidationTextBox.isValid() return !!this.item || (!this.required && this.get('displayedValue') == ""); // #5974 }, _refreshState: function(){ if(!this.searchTimer){ // state will be refreshed after results are returned this.inherited(arguments); } }, _callbackSetLabel: function( /*Array*/ result, /*Object*/ query, /*Object*/ options, /*Boolean?*/ priorityChange){ // summary: // Callback from dojo.store after lookup of user entered value finishes // setValue does a synchronous lookup, // so it calls _callbackSetLabel directly, // and so does not pass dataObject // still need to test against _lastQuery in case it came too late if((query && query[this.searchAttr] !== this._lastQuery) || (!query && result.length && this.store.getIdentity(result[0]) != this._lastQuery)){ return; } if(!result.length){ //#3268: don't modify display value on bad input //#3285: change CSS to indicate error this.set("value", '', priorityChange || (priorityChange === undefined && !this.focused), this.textbox.value, null); }else{ this.set('item', result[0], priorityChange); } }, _openResultList: function(/*Object*/ results, /*Object*/ query, /*Object*/ options){ // Callback when a data store query completes. // Overrides ComboBox._openResultList() // #3285: tap into search callback to see if user's query resembles a match if(query[this.searchAttr] !== this._lastQuery){ return; } this.inherited(arguments); if(this.item === undefined){ // item == undefined for keyboard search // If the search returned no items that means that the user typed // in something invalid (and they can't make it valid by typing more characters), // so flag the FilteringSelect as being in an invalid state this.validate(true); } }, _getValueAttr: function(){ // summary: // Hook for get('value') to work. // don't get the textbox value but rather the previously set hidden value. // Use this.valueNode.value which isn't always set for other MappedTextBox widgets until blur return this.valueNode.value; }, _getValueField: function(){ // Overrides ComboBox._getValueField() return "value"; }, _setValueAttr: function(/*String*/ value, /*Boolean?*/ priorityChange, /*String?*/ displayedValue, /*item?*/ item){ // summary: // Hook so set('value', value) works. // description: // Sets the value of the select. // Also sets the label to the corresponding value by reverse lookup. if(!this._onChangeActive){ priorityChange = null; } if(item === undefined){ if(value === null || value === ''){ value = ''; if(!lang.isString(displayedValue)){ this._setDisplayedValueAttr(displayedValue||'', priorityChange); return; } } var self = this; this._lastQuery = value; Deferred.when(this.store.get(value), function(item){ self._callbackSetLabel(item? [item] : [], undefined, undefined, priorityChange); }); }else{ this.valueNode.value = value; this.inherited(arguments); } }, _setItemAttr: function(/*item*/ item, /*Boolean?*/ priorityChange, /*String?*/ displayedValue){ // summary: // Set the displayed valued in the input box, and the hidden value // that gets submitted, based on a dojo.data store item. // description: // Users shouldn't call this function; they should be calling // set('item', value) // tags: // private this.inherited(arguments); this._lastDisplayedValue = this.textbox.value; }, _getDisplayQueryString: function(/*String*/ text){ return text.replace(/([\\\*\?])/g, "\\$1"); }, _setDisplayedValueAttr: function(/*String*/ label, /*Boolean?*/ priorityChange){ // summary: // Hook so set('displayedValue', label) works. // description: // Sets textbox to display label. Also performs reverse lookup // to set the hidden value. label should corresponding to item.searchAttr. if(label == null){ label = ''; } // This is called at initialization along with every custom setter. // Usually (or always?) the call can be ignored. If it needs to be // processed then at least make sure that the XHR request doesn't trigger an onChange() // event, even if it returns after creation has finished if(!this._created){ if(!("displayedValue" in this.params)){ return; } priorityChange = false; } // Do a reverse lookup to map the specified displayedValue to the hidden value. // Note that if there's a custom labelFunc() this code if(this.store){ this.closeDropDown(); var query = lang.clone(this.query); // #6196: populate query with user-specifics // Generate query var qs = this._getDisplayQueryString(label), q; if(this.store._oldAPI){ // remove this branch for 2.0 q = qs; }else{ // Query on searchAttr is a regex for benefit of dojo.store.Memory, // but with a toString() method to help dojo.store.JsonRest. // Search string like "Co*" converted to regex like /^Co.*$/i. q = filter.patternToRegExp(qs, this.ignoreCase); q.toString = function(){ return qs; }; } this._lastQuery = query[this.searchAttr] = q; // 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 user this.textbox.value = label; this._lastDisplayedValue = label; this._set("displayedValue", label); // for watch("displayedValue") notification var _this = this; var options = { queryOptions: { ignoreCase: this.ignoreCase, deep: true } }; lang.mixin(options, this.fetchProperties); this._fetchHandle = this.store.query(query, options); Deferred.when(this._fetchHandle, function(result){ _this._fetchHandle = null; _this._callbackSetLabel(result || [], query, options, priorityChange); }, function(err){ _this._fetchHandle = null; if(!_this._cancelingQuery){ // don't treat canceled query as an error console.error('dijit.form.FilteringSelect: ' + err.toString()); } }); } }, undo: function(){ this.set('displayedValue', this._lastDisplayedValue); } }); }); }, 'dojo/colors':function(){ define("dojo/colors", ["./_base/kernel", "./_base/lang", "./_base/Color", "./_base/array"], function(dojo, lang, Color, ArrayUtil) { // module: // dojo/colors // summary: // TODOC var ColorExt = lang.getObject("dojo.colors", true); //TODO: this module appears to break naming conventions /*===== lang.mixin(dojo, { colors: { // summary: Color utilities, extending Base dojo.Color } }); =====*/ // this is a standard conversion prescribed by the CSS3 Color Module var 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; }; // Override base Color.fromRgb with the impl in this module dojo.colorFromRgb = Color.fromRgb = 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], a; if((t == "rgb" && l == 3) || (t == "rgba" && l == 4)){ var r = c[0]; if(r.charAt(r.length - 1) == "%"){ // 3 rgb percentage values a = ArrayUtil.map(c, function(x){ return parseFloat(x) * 2.56; }); if(l == 4){ a[3] = c[3]; } return Color.fromArray(a, obj); // dojo.Color } return Color.fromArray(c, obj); // dojo.Color } if((t == "hsl" && l == 3) || (t == "hsla" && l == 4)){ // normalize hsl values var 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 Module m2 = 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 Color.fromArray(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 values c = Number(c); return isNaN(c) ? high : c < low ? low : c > high ? high : c; // Number }; Color.prototype.sanitize = function(){ // summary: makes sure that the object has correct attributes var 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 }; ColorExt.makeGrey = Color.makeGrey = function(/*Number*/ g, /*Number?*/ a){ // summary: creates a greyscale color with an optional alpha return Color.fromArray([g, g, g, a]); // dojo.Color }; // mixin all CSS3 named colors not already in _base, along with SVG 1.0 variant spellings lang.mixin(Color.named, { "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], "turquoise": [64,224,208], "violet": [238,130,238], "wheat": [245,222,179], "whitesmoke": [245,245,245], "yellowgreen": [154,205,50] }); return Color; }); }, 'dijit/form/_FormSelectWidget':function(){ define("dijit/form/_FormSelectWidget", [ "dojo/_base/array", // array.filter array.forEach array.map array.some "dojo/aspect", // aspect.after "dojo/data/util/sorter", // util.sorter.createSortFunction "dojo/_base/declare", // declare "dojo/dom", // dom.setSelectable "dojo/dom-class", // domClass.toggle "dojo/_base/kernel", // _scopeName "dojo/_base/lang", // lang.delegate lang.isArray lang.isObject lang.hitch "dojo/query", // query "./_FormValueWidget" ], function(array, aspect, sorter, declare, dom, domClass, kernel, lang, query, _FormValueWidget){ /*===== var _FormValueWidget = dijit.form._FormValueWidget; =====*/ // module: // dijit/form/_FormSelectWidget // summary: // Extends _FormValueWidget in order to provide "select-specific" // values - i.e., those values that are unique to <select> elements. /*===== dijit.form.__SelectOption = function(){ // value: String // The value of the option. Setting to empty (or missing) will // place a separator at that location // label: String // The label for our option. It can contain html tags. // selected: Boolean // Whether or not we are a selected option // disabled: Boolean // Whether or not this specific option is disabled this.value = value; this.label = label; this.selected = selected; this.disabled = disabled; } =====*/ return declare("dijit.form._FormSelectWidget", _FormValueWidget, { // summary: // Extends _FormValueWidget in order to provide "select-specific" // values - i.e., those values that are unique to <select> elements. // This also provides the mechanism for reading the elements from // a store, if desired. // multiple: [const] Boolean // Whether or not we are multi-valued multiple: false, // options: dijit.form.__SelectOption[] // The set of options for our select item. Roughly corresponds to // the html <option> tag. options: null, // store: dojo.data.api.Identity // A store which, at the very least implements dojo.data.api.Identity // to use for getting our list of options - rather than reading them // from the <option> html tags. store: null, // query: object // A query to use when fetching items from our store query: null, // queryOptions: object // Query options to use when fetching from the store queryOptions: null, // onFetch: Function // A callback to do with an onFetch - but before any items are actually // iterated over (i.e. to filter even further what you want to add) onFetch: null, // sortByLabel: Boolean // Flag to sort the options returned from a store by the label of // the store. sortByLabel: true, // loadChildrenOnOpen: Boolean // By default loadChildren is called when the items are fetched from the // store. This property allows delaying loadChildren (and the creation // of the options/menuitems) until the user clicks the button to open the // dropdown. loadChildrenOnOpen: false, getOptions: function(/*anything*/ valueOrIdx){ // summary: // Returns a given option (or options). // valueOrIdx: // If passed in as a string, that string is used to look up the option // in the array of options - based on the value property. // (See dijit.form.__SelectOption). // // If passed in a number, then the option with the given index (0-based) // within this select will be returned. // // If passed in a dijit.form.__SelectOption, the same option will be // returned if and only if it exists within this select. // // If passed an array, then an array will be returned with each element // in the array being looked up. // // If not passed a value, then all options will be returned // // returns: // The option corresponding with the given value or index. null // is returned if any of the following are true: // - A string value is passed in which doesn't exist // - An index is passed in which is outside the bounds of the array of options // - A dijit.form.__SelectOption is passed in which is not a part of the select // NOTE: the compare for passing in a dijit.form.__SelectOption checks // if the value property matches - NOT if the exact option exists // NOTE: if passing in an array, null elements will be placed in the returned // array when a value is not found. var lookupValue = valueOrIdx, opts = this.options || [], l = opts.length; if(lookupValue === undefined){ return opts; // dijit.form.__SelectOption[] } if(lang.isArray(lookupValue)){ return array.map(lookupValue, "return this.getOptions(item);", this); // dijit.form.__SelectOption[] } if(lang.isObject(valueOrIdx)){ // We were passed an option - so see if it's in our array (directly), // and if it's not, try and find it by value. if(!array.some(this.options, function(o, idx){ if(o === lookupValue || (o.value && o.value === lookupValue.value)){ lookupValue = idx; return true; } return false; })){ lookupValue = -1; } } if(typeof lookupValue == "string"){ for(var i=0; i<l; i++){ if(opts[i].value === lookupValue){ lookupValue = i; break; } } } if(typeof lookupValue == "number" && lookupValue >= 0 && lookupValue < l){ return this.options[lookupValue]; // dijit.form.__SelectOption } return null; // null }, addOption: function(/*dijit.form.__SelectOption|dijit.form.__SelectOption[]*/ option){ // summary: // Adds an option or options to the end of the select. If value // of the option is empty or missing, a separator is created instead. // Passing in an array of options will yield slightly better performance // since the children are only loaded once. if(!lang.isArray(option)){ option = [option]; } array.forEach(option, function(i){ if(i && lang.isObject(i)){ this.options.push(i); } }, this); this._loadChildren(); }, removeOption: function(/*String|dijit.form.__SelectOption|Number|Array*/ valueOrIdx){ // summary: // Removes the given option or options. You can remove by string // (in which case the value is removed), number (in which case the // index in the options array is removed), or select option (in // which case, the select option with a matching value is removed). // You can also pass in an array of those values for a slightly // better performance since the children are only loaded once. if(!lang.isArray(valueOrIdx)){ valueOrIdx = [valueOrIdx]; } var oldOpts = this.getOptions(valueOrIdx); array.forEach(oldOpts, function(i){ // We can get null back in our array - if our option was not found. In // that case, we don't want to blow up... if(i){ this.options = array.filter(this.options, function(node){ return (node.value !== i.value || node.label !== i.label); }); this._removeOptionItem(i); } }, this); this._loadChildren(); }, updateOption: function(/*dijit.form.__SelectOption|dijit.form.__SelectOption[]*/ newOption){ // summary: // Updates the values of the given option. The option to update // is matched based on the value of the entered option. Passing // in an array of new options will yield better performance since // the children will only be loaded once. if(!lang.isArray(newOption)){ newOption = [newOption]; } array.forEach(newOption, function(i){ var oldOpt = this.getOptions(i), k; if(oldOpt){ for(k in i){ oldOpt[k] = i[k]; } } }, this); this._loadChildren(); }, setStore: function(/*dojo.data.api.Identity*/ store, /*anything?*/ selectedValue, /*Object?*/ fetchArgs){ // summary: // Sets the store you would like to use with this select widget. // The selected value is the value of the new store to set. This // function returns the original store, in case you want to reuse // it or something. // store: dojo.data.api.Identity // The store you would like to use - it MUST implement dojo.data.api.Identity, // and MAY implement dojo.data.api.Notification. // selectedValue: anything? // The value that this widget should set itself to *after* the store // has been loaded // fetchArgs: Object? // The arguments that will be passed to the store's fetch() function var oStore = this.store; fetchArgs = fetchArgs || {}; if(oStore !== store){ // Our store has changed, so update our notifications var h; while(h = this._notifyConnections.pop()){ h.remove(); } if(store && store.getFeatures()["dojo.data.api.Notification"]){ this._notifyConnections = [ aspect.after(store, "onNew", lang.hitch(this, "_onNewItem"), true), aspect.after(store, "onDelete", lang.hitch(this, "_onDeleteItem"), true), aspect.after(store, "onSet", lang.hitch(this, "_onSetItem"), true) ]; } this._set("store", store); } // Turn off change notifications while we make all these changes this._onChangeActive = false; // Remove existing options (if there are any) if(this.options && this.options.length){ this.removeOption(this.options); } // Add our new options if(store){ this._loadingStore = true; store.fetch(lang.delegate(fetchArgs, { onComplete: function(items, opts){ if(this.sortByLabel && !fetchArgs.sort && items.length){ items.sort(sorter.createSortFunction([{ attribute: store.getLabelAttributes(items[0])[0] }], store)); } if(fetchArgs.onFetch){ items = fetchArgs.onFetch.call(this, items, opts); } // TODO: Add these guys as a batch, instead of separately array.forEach(items, function(i){ this._addOptionForItem(i); }, this); // Set our value (which might be undefined), and then tweak // it to send a change event with the real value this._loadingStore = false; this.set("value", "_pendingValue" in this ? this._pendingValue : selectedValue); delete this._pendingValue; if(!this.loadChildrenOnOpen){ this._loadChildren(); }else{ this._pseudoLoadChildren(items); } this._fetchedWith = opts; this._lastValueReported = this.multiple ? [] : null; this._onChangeActive = true; this.onSetStore(); this._handleOnChange(this.value); }, scope: this })); }else{ delete this._fetchedWith; } return oStore; // dojo.data.api.Identity }, // TODO: implement set() and watch() for store and query, although not sure how to handle // setting them individually rather than together (as in setStore() above) _setValueAttr: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){ // summary: // set the value of the widget. // If a string is passed, then we set our value from looking it up. if(this._loadingStore){ // Our store is loading - so save our value, and we'll set it when // we're done this._pendingValue = newValue; return; } var opts = this.getOptions() || []; if(!lang.isArray(newValue)){ newValue = [newValue]; } array.forEach(newValue, function(i, idx){ if(!lang.isObject(i)){ i = i + ""; } if(typeof i === "string"){ newValue[idx] = array.filter(opts, function(node){ return node.value === i; })[0] || {value: "", label: ""}; } }, this); // Make sure some sane default is set newValue = array.filter(newValue, function(i){ return i && i.value; }); if(!this.multiple && (!newValue[0] || !newValue[0].value) && opts.length){ newValue[0] = opts[0]; } array.forEach(opts, function(i){ i.selected = array.some(newValue, function(v){ return v.value === i.value; }); }); var val = array.map(newValue, function(i){ return i.value; }), disp = array.map(newValue, function(i){ return i.label; }); this._set("value", this.multiple ? val : val[0]); this._setDisplay(this.multiple ? disp : disp[0]); this._updateSelection(); this._handleOnChange(this.value, priorityChange); }, _getDisplayedValueAttr: function(){ // summary: // returns the displayed value of the widget var val = this.get("value"); if(!lang.isArray(val)){ val = [val]; } var ret = array.map(this.getOptions(val), function(v){ if(v && "label" in v){ return v.label; }else if(v){ return v.value; } return null; }, this); return this.multiple ? ret : ret[0]; }, _loadChildren: function(){ // summary: // Loads the children represented by this widget's options. // reset the menu to make it populatable on the next click if(this._loadingStore){ return; } array.forEach(this._getChildren(), function(child){ child.destroyRecursive(); }); // Add each menu item array.forEach(this.options, this._addOptionItem, this); // Update states this._updateSelection(); }, _updateSelection: function(){ // summary: // Sets the "selected" class on the item for styling purposes this._set("value", this._getValueFromOpts()); var val = this.value; if(!lang.isArray(val)){ val = [val]; } if(val && val[0]){ array.forEach(this._getChildren(), function(child){ var isSelected = array.some(val, function(v){ return child.option && (v === child.option.value); }); domClass.toggle(child.domNode, this.baseClass + "SelectedOption", isSelected); child.domNode.setAttribute("aria-selected", isSelected); }, this); } }, _getValueFromOpts: function(){ // summary: // Returns the value of the widget by reading the options for // the selected flag var opts = this.getOptions() || []; if(!this.multiple && opts.length){ // Mirror what a select does - choose the first one var opt = array.filter(opts, function(i){ return i.selected; })[0]; if(opt && opt.value){ return opt.value }else{ opts[0].selected = true; return opts[0].value; } }else if(this.multiple){ // Set value to be the sum of all selected return array.map(array.filter(opts, function(i){ return i.selected; }), function(i){ return i.value; }) || []; } return ""; }, // Internal functions to call when we have store notifications come in _onNewItem: function(/*item*/ item, /*Object?*/ parentInfo){ if(!parentInfo || !parentInfo.parent){ // Only add it if we are top-level this._addOptionForItem(item); } }, _onDeleteItem: function(/*item*/ item){ var store = this.store; this.removeOption(store.getIdentity(item)); }, _onSetItem: function(/*item*/ item){ this.updateOption(this._getOptionObjForItem(item)); }, _getOptionObjForItem: function(item){ // summary: // Returns an option object based off the given item. The "value" // of the option item will be the identity of the item, the "label" // of the option will be the label of the item. If the item contains // children, the children value of the item will be set var store = this.store, label = store.getLabel(item), value = (label ? store.getIdentity(item) : null); return {value: value, label: label, item:item}; // dijit.form.__SelectOption }, _addOptionForItem: function(/*item*/ item){ // summary: // Creates (and adds) the option for the given item var store = this.store; if(!store.isItemLoaded(item)){ // We are not loaded - so let's load it and add later store.loadItem({item: item, onItem: function(i){ this._addOptionForItem(i); }, scope: this}); return; } var newOpt = this._getOptionObjForItem(item); this.addOption(newOpt); }, constructor: function(/*Object*/ keywordArgs){ // summary: // Saves off our value, if we have an initial one set so we // can use it if we have a store as well (see startup()) this._oValue = (keywordArgs || {}).value || null; this._notifyConnections = []; }, buildRendering: function(){ this.inherited(arguments); dom.setSelectable(this.focusNode, false); }, _fillContent: function(){ // summary: // Loads our options and sets up our dropdown correctly. We // don't want any content, so we don't call any inherit chain // function. var opts = this.options; if(!opts){ opts = this.options = this.srcNodeRef ? query("> *", this.srcNodeRef).map(function(node){ if(node.getAttribute("type") === "separator"){ return { value: "", label: "", selected: false, disabled: false }; } return { value: (node.getAttribute("data-" + kernel._scopeName + "-value") || node.getAttribute("value")), label: String(node.innerHTML), // FIXME: disabled and selected are not valid on complex markup children (which is why we're // looking for data-dojo-value above. perhaps we should data-dojo-props="" this whole thing?) // decide before 1.6 selected: node.getAttribute("selected") || false, disabled: node.getAttribute("disabled") || false }; }, this) : []; } if(!this.value){ this._set("value", this._getValueFromOpts()); }else if(this.multiple && typeof this.value == "string"){ this._set("value", this.value.split(",")); } }, postCreate: function(){ // summary: // sets up our event handling that we need for functioning // as a select this.inherited(arguments); // Make our event connections for updating state this.connect(this, "onChange", "_updateSelection"); this.connect(this, "startup", "_loadChildren"); this._setValueAttr(this.value, null); }, startup: function(){ // summary: // Connects in our store, if we have one defined this.inherited(arguments); var store = this.store, fetchArgs = {}; array.forEach(["query", "queryOptions", "onFetch"], function(i){ if(this[i]){ fetchArgs[i] = this[i]; } delete this[i]; }, this); if(store && store.getFeatures()["dojo.data.api.Identity"]){ // Temporarily set our store to null so that it will get set // and connected appropriately this.store = null; this.setStore(store, this._oValue, fetchArgs); } }, destroy: function(){ // summary: // Clean up our connections var h; while(h = this._notifyConnections.pop()){ h.remove(); } this.inherited(arguments); }, _addOptionItem: function(/*dijit.form.__SelectOption*/ /*===== option =====*/){ // summary: // User-overridable function which, for the given option, adds an // item to the select. If the option doesn't have a value, then a // separator is added in that place. Make sure to store the option // in the created option widget. }, _removeOptionItem: function(/*dijit.form.__SelectOption*/ /*===== option =====*/){ // summary: // User-overridable function which, for the given option, removes // its item from the select. }, _setDisplay: function(/*String or String[]*/ /*===== newDisplay =====*/){ // summary: // Overridable function which will set the display for the // widget. newDisplay is either a string (in the case of // single selects) or array of strings (in the case of multi-selects) }, _getChildren: function(){ // summary: // Overridable function to return the children that this widget contains. return []; }, _getSelectedOptionsAttr: function(){ // summary: // hooks into this.attr to provide a mechanism for getting the // option items for the current value of the widget. return this.getOptions(this.get("value")); }, _pseudoLoadChildren: function(/*item[]*/ /*===== items =====*/){ // summary: // a function that will "fake" loading children, if needed, and // if we have set to not load children until the widget opens. // items: // An array of items that will be loaded, when needed }, onSetStore: function(){ // summary: // a function that can be connected to in order to receive a // notification that the store has finished loading and all options // from that store are available } }); }); }, 'dijit/form/Select':function(){ require({cache:{ 'url:dijit/form/templates/Select.html':"<table class=\"dijit dijitReset dijitInline dijitLeft\"\n\tdata-dojo-attach-point=\"_buttonNode,tableNode,focusNode\" cellspacing='0' cellpadding='0'\n\trole=\"combobox\" aria-haspopup=\"true\"\n\t><tbody role=\"presentation\"><tr role=\"presentation\"\n\t\t><td class=\"dijitReset dijitStretch dijitButtonContents dijitButtonNode\" role=\"presentation\"\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\" data-dojo-attach-point=\"containerNode,_popupStateNode\"></span\n\t\t\t><input type=\"hidden\" ${!nameAttrSetting} data-dojo-attach-point=\"valueNode\" value=\"${value}\" aria-hidden=\"true\"\n\t\t/></td><td class=\"dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton\"\n\t\t\t\tdata-dojo-attach-point=\"titleNode\" role=\"presentation\"\n\t\t\t><div class=\"dijitReset dijitArrowButtonInner\" role=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitArrowButtonChar\" role=\"presentation\">▼</div\n\t\t></td\n\t></tr></tbody\n></table>\n"}}); define("dijit/form/Select", [ "dojo/_base/array", // array.forEach "dojo/_base/declare", // declare "dojo/dom-attr", // domAttr.set "dojo/dom-class", // domClass.add domClass.remove domClass.toggle "dojo/dom-construct", // domConstruct.create "dojo/dom-geometry", // domGeometry.setMarginBox "dojo/_base/event", // event.stop "dojo/i18n", // i18n.getLocalization "dojo/_base/lang", // lang.hitch "./_FormSelectWidget", "../_HasDropDown", "../Menu", "../MenuItem", "../MenuSeparator", "../Tooltip", "dojo/text!./templates/Select.html", "dojo/i18n!./nls/validate" ], function(array, declare, domAttr, domClass, domConstruct, domGeometry, event, i18n, lang, _FormSelectWidget, _HasDropDown, Menu, MenuItem, MenuSeparator, Tooltip, template){ /*===== var _FormSelectWidget = dijit.form._FormSelectWidget; var _HasDropDown = dijit._HasDropDown; var _FormSelectWidget = dijit._FormSelectWidget; var Menu = dijit.Menu; var MenuItem = dijit.MenuItem; var MenuSeparator = dijit.MenuSeparator; var Tooltip = dijit.Tooltip; =====*/ // module: // dijit/form/Select // summary: // This is a "styleable" select box - it is basically a DropDownButton which // can take a <select> as its input. var _SelectMenu = declare("dijit.form._SelectMenu", Menu, { // summary: // An internally-used menu for dropdown that allows us a vertical scrollbar buildRendering: function(){ // summary: // Stub in our own changes, so that our domNode is not a table // otherwise, we won't respond correctly to heights/overflows this.inherited(arguments); var o = (this.menuTableNode = this.domNode); var n = (this.domNode = domConstruct.create("div", {style: {overflowX: "hidden", overflowY: "scroll"}})); if(o.parentNode){ o.parentNode.replaceChild(n, o); } domClass.remove(o, "dijitMenuTable"); n.className = o.className + " dijitSelectMenu"; o.className = "dijitReset dijitMenuTable"; o.setAttribute("role", "listbox"); n.setAttribute("role", "presentation"); n.appendChild(o); }, postCreate: function(){ // summary: // stop mousemove from selecting text on IE to be consistent with other browsers this.inherited(arguments); this.connect(this.domNode, "onmousemove", event.stop); }, resize: function(/*Object*/ mb){ // summary: // Overridden so that we are able to handle resizing our // internal widget. Note that this is not a "full" resize // implementation - it only works correctly if you pass it a // marginBox. // // mb: Object // The margin box to set this dropdown to. if(mb){ domGeometry.setMarginBox(this.domNode, mb); if("w" in mb){ // We've explicitly set the wrapper <div>'s width, so set <table> width to match. // 100% is safer than a pixel value because there may be a scroll bar with // browser/OS specific width. this.menuTableNode.style.width = "100%"; } } } }); var Select = declare("dijit.form.Select", [_FormSelectWidget, _HasDropDown], { // summary: // This is a "styleable" select box - it is basically a DropDownButton which // can take a <select> as its input. baseClass: "dijitSelect", templateString: template, // required: Boolean // Can be true or false, default is false. required: false, // state: [readonly] String // "Incomplete" if this select is required but unset (i.e. blank value), "" otherwise state: "", // message: String // Currently displayed error/prompt message message: "", // tooltipPosition: String[] // See description of dijit.Tooltip.defaultPosition for details on this parameter. tooltipPosition: [], // emptyLabel: string // What to display in an "empty" dropdown emptyLabel: " ", // // _isLoaded: Boolean // Whether or not we have been loaded _isLoaded: false, // _childrenLoaded: Boolean // Whether or not our children have been loaded _childrenLoaded: false, _fillContent: function(){ // summary: // Set the value to be the first, or the selected index this.inherited(arguments); // set value from selected option if(this.options.length && !this.value && this.srcNodeRef){ var si = this.srcNodeRef.selectedIndex || 0; // || 0 needed for when srcNodeRef is not a SELECT this.value = this.options[si >= 0 ? si : 0].value; } // Create the dropDown widget this.dropDown = new _SelectMenu({id: this.id + "_menu"}); domClass.add(this.dropDown.domNode, this.baseClass + "Menu"); }, _getMenuItemForOption: function(/*dijit.form.__SelectOption*/ option){ // summary: // For the given option, return the menu item that should be // used to display it. This can be overridden as needed if(!option.value && !option.label){ // We are a separator (no label set for it) return new MenuSeparator(); }else{ // Just a regular menu option var click = lang.hitch(this, "_setValueAttr", option); var item = new MenuItem({ option: option, label: option.label || this.emptyLabel, onClick: click, disabled: option.disabled || false }); item.focusNode.setAttribute("role", "listitem"); return item; } }, _addOptionItem: function(/*dijit.form.__SelectOption*/ option){ // summary: // For the given option, add an option to our dropdown. // If the option doesn't have a value, then a separator is added // in that place. if(this.dropDown){ this.dropDown.addChild(this._getMenuItemForOption(option)); } }, _getChildren: function(){ if(!this.dropDown){ return []; } return this.dropDown.getChildren(); }, _loadChildren: function(/*Boolean*/ loadMenuItems){ // summary: // Resets the menu and the length attribute of the button - and // ensures that the label is appropriately set. // loadMenuItems: Boolean // actually loads the child menu items - we only do this when we are // populating for showing the dropdown. if(loadMenuItems === true){ // this.inherited destroys this.dropDown's child widgets (MenuItems). // Avoid this.dropDown (Menu widget) having a pointer to a destroyed widget (which will cause // issues later in _setSelected). (see #10296) if(this.dropDown){ delete this.dropDown.focusedChild; } if(this.options.length){ this.inherited(arguments); }else{ // Drop down menu is blank but add one blank entry just so something appears on the screen // to let users know that they are no choices (mimicing native select behavior) array.forEach(this._getChildren(), function(child){ child.destroyRecursive(); }); var item = new MenuItem({label: " "}); this.dropDown.addChild(item); } }else{ this._updateSelection(); } this._isLoaded = false; this._childrenLoaded = true; if(!this._loadingStore){ // Don't call this if we are loading - since we will handle it later this._setValueAttr(this.value); } }, _setValueAttr: function(value){ this.inherited(arguments); domAttr.set(this.valueNode, "value", this.get("value")); this.validate(this.focused); // to update this.state }, _setDisabledAttr: function(/*Boolean*/ value){ this.inherited(arguments); this.validate(this.focused); // to update this.state }, _setRequiredAttr: function(/*Boolean*/ value){ this._set("required", value); this.focusNode.setAttribute("aria-required", value); this.validate(this.focused); // to update this.state }, _setDisplay: function(/*String*/ newDisplay){ // summary: // sets the display for the given value (or values) var lbl = newDisplay || this.emptyLabel; this.containerNode.innerHTML = '<span class="dijitReset dijitInline ' + this.baseClass + 'Label">' + lbl + '</span>'; this.focusNode.setAttribute("aria-valuetext", lbl); }, validate: function(/*Boolean*/ isFocused){ // summary: // Called by oninit, onblur, and onkeypress, and whenever required/disabled state changes // description: // Show missing or invalid messages if appropriate, and highlight textbox field. // Used when a select is initially set to no value and the user is required to // set the value. var isValid = this.disabled || this.isValid(isFocused); this._set("state", isValid ? "" : "Incomplete"); this.focusNode.setAttribute("aria-invalid", isValid ? "false" : "true"); var message = isValid ? "" : this._missingMsg; if(message && this.focused && this._hasBeenBlurred){ Tooltip.show(message, this.domNode, this.tooltipPosition, !this.isLeftToRight()); }else{ Tooltip.hide(this.domNode); } this._set("message", message); return isValid; }, isValid: function(/*Boolean*/ /*===== isFocused =====*/){ // summary: // Whether or not this is a valid value. The only way a Select // can be invalid is when it's required but nothing is selected. return (!this.required || this.value === 0 || !(/^\s*$/.test(this.value || ""))); // handle value is null or undefined }, reset: function(){ // summary: // Overridden so that the state will be cleared. this.inherited(arguments); Tooltip.hide(this.domNode); this.validate(this.focused); // to update this.state }, postMixInProperties: function(){ // summary: // set the missing message this.inherited(arguments); this._missingMsg = i18n.getLocalization("dijit.form", "validate", this.lang).missingMessage; }, postCreate: function(){ // summary: // stop mousemove from selecting text on IE to be consistent with other browsers this.inherited(arguments); this.connect(this.domNode, "onmousemove", event.stop); }, _setStyleAttr: function(/*String||Object*/ value){ this.inherited(arguments); domClass.toggle(this.domNode, this.baseClass + "FixedWidth", !!this.domNode.style.width); }, isLoaded: function(){ return this._isLoaded; }, loadDropDown: function(/*Function*/ loadCallback){ // summary: // populates the menu this._loadChildren(true); this._isLoaded = true; loadCallback(); }, closeDropDown: function(){ // overriding _HasDropDown.closeDropDown() this.inherited(arguments); if(this.dropDown && this.dropDown.menuTableNode){ // Erase possible width: 100% setting from _SelectMenu.resize(). // Leaving it would interfere with the next openDropDown() call, which // queries the natural size of the drop down. this.dropDown.menuTableNode.style.width = ""; } }, uninitialize: function(preserveDom){ if(this.dropDown && !this.dropDown._destroyed){ this.dropDown.destroyRecursive(preserveDom); delete this.dropDown; } this.inherited(arguments); }, _onFocus: function(){ this.validate(true); // show tooltip if second focus of required tooltip, but no selection this.inherited(arguments); }, _onBlur: function(){ Tooltip.hide(this.domNode); this.inherited(arguments); } }); Select._Menu = _SelectMenu; // for monkey patching return Select; }); }, 'dojo/store/util/QueryResults':function(){ define("dojo/store/util/QueryResults", ["../../_base/array", "../../_base/lang", "../../_base/Deferred" ], function(array, lang, Deferred) { // module: // dojo/store/util/QueryResults // summary: // The module defines a query results wrapper var util = lang.getObject("dojo.store.util", true); util.QueryResults = function(results){ // summary: // A function that wraps the results of a store query with additional // methods. // // description: // QueryResults is a basic wrapper that allows for array-like iteration // over any kind of returned data from a query. While the simplest store // will return a plain array of data, other stores may return deferreds or // promises; this wrapper makes sure that *all* results can be treated // the same. // // Additional methods include `forEach`, `filter` and `map`. // // returns: Object // An array-like object that can be used for iterating over. // // example: // Query a store and iterate over the results. // // | store.query({ prime: true }).forEach(function(item){ // | // do something // | }); if(!results){ return results; } // if it is a promise it may be frozen if(results.then){ results = lang.delegate(results); } function addIterativeMethod(method){ if(!results[method]){ results[method] = function(){ var args = arguments; return Deferred.when(results, function(results){ Array.prototype.unshift.call(args, results); return util.QueryResults(array[method].apply(array, args)); }); }; } } addIterativeMethod("forEach"); addIterativeMethod("filter"); addIterativeMethod("map"); if(!results.total){ results.total = Deferred.when(results, function(results){ return results.length; }); } return results; }; return util.QueryResults; }); }, 'dijit/form/_ListBase':function(){ define("dijit/form/_ListBase", [ "dojo/_base/declare", // declare "dojo/window" // winUtils.scrollIntoView ], function(declare, winUtils){ // module: // dijit/form/_ListBase // summary: // Focus-less menu to handle UI events consistently return declare( "dijit.form._ListBase", null, { // summary: // Focus-less menu to handle UI events consistently // Abstract methods that must be defined externally: // onSelect: item is active (mousedown but not yet mouseup, or keyboard arrow selected but no Enter) // onDeselect: cancels onSelect // tags: // private // selected: DOMnode // currently selected node selected: null, _getTarget: function(/*Event*/ evt){ var tgt = evt.target; var container = this.containerNode; if(tgt == container || tgt == this.domNode){ return null; } while(tgt && tgt.parentNode != container){ // recurse to the top tgt = tgt.parentNode; } return tgt; }, selectFirstNode: function(){ // summary: // Select the first displayed item in the list. var first = this.containerNode.firstChild; while(first && first.style.display == "none"){ first = first.nextSibling; } this._setSelectedAttr(first, true); }, selectLastNode: function(){ // summary: // Select the last displayed item in the list var last = this.containerNode.lastChild; while(last && last.style.display == "none"){ last = last.previousSibling; } this._setSelectedAttr(last, true); }, selectNextNode: function(){ // summary: // Select the item just below the current selection. // If nothing selected, select first node. var selectedNode = this._getSelectedAttr(); if(!selectedNode){ this.selectFirstNode(); }else{ var next = selectedNode.nextSibling; while(next && next.style.display == "none"){ next = next.nextSibling; } if(!next){ this.selectFirstNode(); }else{ this._setSelectedAttr(next, true); } } }, selectPreviousNode: function(){ // summary: // Select the item just above the current selection. // If nothing selected, select last node (if // you select Previous and try to keep scrolling up the list). var selectedNode = this._getSelectedAttr(); if(!selectedNode){ this.selectLastNode(); }else{ var prev = selectedNode.previousSibling; while(prev && prev.style.display == "none"){ prev = prev.previousSibling; } if(!prev){ this.selectLastNode(); }else{ this._setSelectedAttr(prev, true); } } }, _setSelectedAttr: function(/*DomNode*/ node, /*Boolean*/ scroll){ // summary: // Does the actual select. // node: // The option to select // scroll: // If necessary, scroll node into view. Set to false for mouse/touch to // avoid jumping problems on mobile/RTL, see https://bugs.dojotoolkit.org/ticket/17739. if(this.selected != node){ var selectedNode = this._getSelectedAttr(); if(selectedNode){ this.onDeselect(selectedNode); this.selected = null; } if(node && node.parentNode == this.containerNode){ this.selected = node; if(scroll){ winUtils.scrollIntoView(node); } this.onSelect(node); } }else if(node){ this.onSelect(node); } }, _getSelectedAttr: function(){ // summary: // Returns the selected node. var v = this.selected; return (v && v.parentNode == this.containerNode) ? v : (this.selected = null); } }); }); }, 'dijit/form/_ComboBoxMenu':function(){ define("dijit/form/_ComboBoxMenu", [ "dojo/_base/declare", // declare "dojo/dom-class", // domClass.add domClass.remove "dojo/dom-construct", // domConstruct.create "dojo/dom-style", // domStyle.get "dojo/keys", // keys.DOWN_ARROW keys.PAGE_DOWN keys.PAGE_UP keys.UP_ARROW "../_WidgetBase", "../_TemplatedMixin", "./_ComboBoxMenuMixin", "./_ListMouseMixin" ], function(declare, domClass, domConstruct, domStyle, keys, _WidgetBase, _TemplatedMixin, _ComboBoxMenuMixin, _ListMouseMixin){ /*===== var _WidgetBase = dijit._WidgetBase; var _TemplatedMixin = dijit._TemplatedMixin; var _ComboBoxMenuMixin = dijit.form._ComboBoxMenuMixin; var _ListMouseMixin = dijit.form._ListMouseMixin; =====*/ // module: // dijit/form/_ComboBoxMenu // summary: // Focus-less menu for internal use in `dijit.form.ComboBox` return declare("dijit.form._ComboBoxMenu",[_WidgetBase, _TemplatedMixin, _ListMouseMixin, _ComboBoxMenuMixin], { // summary: // Focus-less menu for internal use in `dijit.form.ComboBox` // Abstract methods that must be defined externally: // onChange: item was explicitly chosen (mousedown somewhere on the menu and mouseup somewhere on the menu) // onPage: next(1) or previous(-1) button pressed // tags: // private templateString: "<div class='dijitReset dijitMenu' data-dojo-attach-point='containerNode' style='overflow: auto; overflow-x: hidden;'>" +"<div class='dijitMenuItem dijitMenuPreviousButton' data-dojo-attach-point='previousButton' role='option'></div>" +"<div class='dijitMenuItem dijitMenuNextButton' data-dojo-attach-point='nextButton' role='option'></div>" +"</div>", baseClass: "dijitComboBoxMenu", postCreate: function(){ this.inherited(arguments); if(!this.isLeftToRight()){ domClass.add(this.previousButton, "dijitMenuItemRtl"); domClass.add(this.nextButton, "dijitMenuItemRtl"); } }, _createMenuItem: function(){ return domConstruct.create("div", { "class": "dijitReset dijitMenuItem" +(this.isLeftToRight() ? "" : " dijitMenuItemRtl"), role: "option" }); }, onHover: function(/*DomNode*/ node){ // summary: // Add hover CSS domClass.add(node, "dijitMenuItemHover"); }, onUnhover: function(/*DomNode*/ node){ // summary: // Remove hover CSS domClass.remove(node, "dijitMenuItemHover"); }, onSelect: function(/*DomNode*/ node){ // summary: // Add selected CSS domClass.add(node, "dijitMenuItemSelected"); }, onDeselect: function(/*DomNode*/ node){ // summary: // Remove selected CSS domClass.remove(node, "dijitMenuItemSelected"); }, _page: function(/*Boolean*/ up){ // summary: // Handles page-up and page-down keypresses var scrollamount = 0; var oldscroll = this.domNode.scrollTop; var height = domStyle.get(this.domNode, "height"); // if no item is highlighted, highlight the first option if(!this.getHighlightedOption()){ this.selectNextNode(); } while(scrollamount<height){ var highlighted_option = this.getHighlightedOption(); if(up){ // stop at option 1 if(!highlighted_option.previousSibling || highlighted_option.previousSibling.style.display == "none"){ break; } this.selectPreviousNode(); }else{ // stop at last option if(!highlighted_option.nextSibling || highlighted_option.nextSibling.style.display == "none"){ break; } this.selectNextNode(); } // going backwards var newscroll = this.domNode.scrollTop; scrollamount += (newscroll-oldscroll)*(up ? -1:1); oldscroll = newscroll; } }, handleKey: function(evt){ // summary: // Handle keystroke event forwarded from ComboBox, returning false if it's // a keystroke I recognize and process, true otherwise. switch(evt.keyCode){ case keys.DOWN_ARROW: this.selectNextNode(); return false; case keys.PAGE_DOWN: this._page(false); return false; case keys.UP_ARROW: this.selectPreviousNode(); return false; case keys.PAGE_UP: this._page(true); return false; default: return true; } } }); }); }, 'dijit/Dialog':function(){ require({cache:{ 'url:dijit/templates/Dialog.html':"<div class=\"dijitDialog\" role=\"dialog\" aria-labelledby=\"${id}_title\">\n\t<div data-dojo-attach-point=\"titleBar\" class=\"dijitDialogTitleBar\">\n\t<span data-dojo-attach-point=\"titleNode\" class=\"dijitDialogTitle\" id=\"${id}_title\"></span>\n\t<span data-dojo-attach-point=\"closeButtonNode\" class=\"dijitDialogCloseIcon\" data-dojo-attach-event=\"ondijitclick: onCancel\" title=\"${buttonCancel}\" role=\"button\" tabIndex=\"0\">\n\t\t<span data-dojo-attach-point=\"closeText\" class=\"closeText\" title=\"${buttonCancel}\">x</span>\n\t</span>\n\t</div>\n\t\t<div data-dojo-attach-point=\"containerNode\" class=\"dijitDialogPaneContent\"></div>\n</div>\n"}}); define("dijit/Dialog", [ "require", "dojo/_base/array", // array.forEach array.indexOf array.map "dojo/_base/connect", // connect._keypress "dojo/_base/declare", // declare "dojo/_base/Deferred", // Deferred "dojo/dom", // dom.isDescendant "dojo/dom-class", // domClass.add domClass.contains "dojo/dom-geometry", // domGeometry.position "dojo/dom-style", // domStyle.set "dojo/_base/event", // event.stop "dojo/_base/fx", // fx.fadeIn fx.fadeOut "dojo/i18n", // i18n.getLocalization "dojo/_base/kernel", // kernel.isAsync "dojo/keys", "dojo/_base/lang", // lang.mixin lang.hitch "dojo/on", "dojo/ready", "dojo/_base/sniff", // has("ie") has("opera") "dojo/_base/window", // win.body "dojo/window", // winUtils.getBox "dojo/dnd/Moveable", // Moveable "dojo/dnd/TimedMoveable", // TimedMoveable "./focus", "./_base/manager", // manager.defaultDuration "./_Widget", "./_TemplatedMixin", "./_CssStateMixin", "./form/_FormMixin", "./_DialogMixin", "./DialogUnderlay", "./layout/ContentPane", "dojo/text!./templates/Dialog.html", ".", // for back-compat, exporting dijit._underlay (remove in 2.0) "dojo/i18n!./nls/common" ], function(require, array, connect, declare, Deferred, dom, domClass, domGeometry, domStyle, event, fx, i18n, kernel, keys, lang, on, ready, has, win, winUtils, Moveable, TimedMoveable, focus, manager, _Widget, _TemplatedMixin, _CssStateMixin, _FormMixin, _DialogMixin, DialogUnderlay, ContentPane, template, dijit){ /*===== var _Widget = dijit._Widget; var _TemplatedMixin = dijit._TemplatedMixin; var _CssStateMixin = dijit._CssStateMixin; var _FormMixin = dijit.form._FormMixin; var _DialogMixin = dijit._DialogMixin; =====*/ // module: // dijit/Dialog // summary: // A modal dialog Widget /*===== dijit._underlay = function(kwArgs){ // summary: // A shared instance of a `dijit.DialogUnderlay` // // description: // A shared instance of a `dijit.DialogUnderlay` created and // used by `dijit.Dialog`, though never created until some Dialog // or subclass thereof is shown. }; =====*/ var _DialogBase = declare("dijit._DialogBase", [_TemplatedMixin, _FormMixin, _DialogMixin, _CssStateMixin], { // summary: // A modal dialog Widget // // description: // 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.) // // example: // | <div data-dojo-type="dijit.Dialog" data-dojo-props="href: 'test.html'"></div> // // example: // | var foo = new dijit.Dialog({ title: "test dialog", content: "test content" }; // | dojo.body().appendChild(foo.domNode); // | foo.startup(); templateString: template, baseClass: "dijitDialog", cssStateNodes: { closeButtonNode: "dijitDialogCloseIcon" }, // Map widget attributes to DOMNode attributes. _setTitleAttr: [ { node: "titleNode", type: "innerHTML" }, { node: "titleBar", type: "attribute" } ], // open: [readonly] Boolean // True if Dialog is currently displayed on screen. open: false, // duration: Integer // The time in milliseconds it takes the dialog to fade in and out duration: manager.defaultDuration, // refocus: Boolean // A Toggle to modify the default focus behavior of a Dialog, which // is to re-focus the element which had focus before being opened. // False will disable refocusing. Default: true refocus: true, // autofocus: Boolean // A Toggle to modify the default focus behavior of a Dialog, which // is to focus on the first dialog element after opening the dialog. // False will disable autofocusing. Default: true autofocus: true, // _firstFocusItem: [private readonly] DomNode // The pointer to the first focusable node in the dialog. // Set by `dijit._DialogMixin._getFocusItems`. _firstFocusItem: null, // _lastFocusItem: [private readonly] DomNode // The pointer to which node has focus prior to our dialog. // Set by `dijit._DialogMixin._getFocusItems`. _lastFocusItem: null, // doLayout: [protected] Boolean // Don't change this parameter from the default value. // This ContentPane parameter doesn't make sense for Dialog, since Dialog // is never a child of a layout container, nor can you specify the size of // Dialog in order to control the size of an inner widget. doLayout: false, // draggable: Boolean // Toggles the moveable aspect of the Dialog. If true, Dialog // can be dragged by it's title. If false it will remain centered // in the viewport. draggable: true, //aria-describedby: String // Allows the user to add an aria-describedby attribute onto the dialog. The value should // be the id of the container element of text that describes the dialog purpose (usually // the first text in the dialog). // <div data-dojo-type="dijit.Dialog" aria-describedby="intro" .....> // <div id="intro">Introductory text</div> // <div>rest of dialog contents</div> // </div> "aria-describedby":"", postMixInProperties: function(){ var _nlsResources = i18n.getLocalization("dijit", "common"); lang.mixin(this, _nlsResources); this.inherited(arguments); }, postCreate: function(){ domStyle.set(this.domNode, { display: "none", position:"absolute" }); win.body().appendChild(this.domNode); this.inherited(arguments); this.connect(this, "onExecute", "hide"); this.connect(this, "onCancel", "hide"); this._modalconnects = []; }, onLoad: function(){ // summary: // Called when data has been loaded from an href. // Unlike most other callbacks, this function can be connected to (via `dojo.connect`) // but should *not* be overridden. // tags: // callback // when href is specified we need to reposition the dialog after the data is loaded // and find the focusable elements this._position(); if(this.autofocus && DialogLevelManager.isTop(this)){ this._getFocusItems(this.domNode); focus.focus(this._firstFocusItem); } this.inherited(arguments); }, _endDrag: function(){ // summary: // Called after dragging the Dialog. Saves the position of the dialog in the viewport, // and also adjust position to be fully within the viewport, so user doesn't lose access to handle var nodePosition = domGeometry.position(this.domNode), viewport = winUtils.getBox(); nodePosition.y = Math.min(Math.max(nodePosition.y, 0), (viewport.h - nodePosition.h)); nodePosition.x = Math.min(Math.max(nodePosition.x, 0), (viewport.w - nodePosition.w)); this._relativePosition = nodePosition; this._position(); }, _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). // tags: // private var node = this.domNode; if(this.titleBar && this.draggable){ this._moveable = new ((has("ie") == 6) ? TimedMoveable // prevent overload, see #5285 : Moveable)(node, { handle: this.titleBar }); this.connect(this._moveable, "onMoveStop", "_endDrag"); }else{ domClass.add(node,"dijitDialogFixed"); } this.underlayAttrs = { dialogId: this.id, "class": array.map(this["class"].split(/\s/), function(s){ return s+"_underlay"; }).join(" ") }; }, _size: function(){ // summary: // If necessary, shrink dialog contents so dialog fits in viewport // tags: // private this._checkIfSingleChild(); // If we resized the dialog contents earlier, reset them back to original size, so // that if the user later increases the viewport size, the dialog can display w/out a scrollbar. // Need to do this before the domGeometry.position(this.domNode) call below. if(this._singleChild){ if(this._singleChildOriginalStyle){ this._singleChild.domNode.style.cssText = this._singleChildOriginalStyle; } delete this._singleChildOriginalStyle; }else{ domStyle.set(this.containerNode, { width:"auto", height:"auto" }); } var bb = domGeometry.position(this.domNode); var viewport = winUtils.getBox(); if(bb.w >= viewport.w || bb.h >= viewport.h){ // Reduce size of dialog contents so that dialog fits in viewport var w = Math.min(bb.w, Math.floor(viewport.w * 0.75)), h = Math.min(bb.h, Math.floor(viewport.h * 0.75)); if(this._singleChild && this._singleChild.resize){ this._singleChildOriginalStyle = this._singleChild.domNode.style.cssText; this._singleChild.resize({w: w, h: h}); }else{ domStyle.set(this.containerNode, { width: w + "px", height: h + "px", overflow: "auto", position: "relative" // workaround IE bug moving scrollbar or dragging dialog }); } }else{ if(this._singleChild && this._singleChild.resize){ this._singleChild.resize(); } } }, _position: function(){ // summary: // Position modal dialog in the viewport. If no relative offset // in the viewport has been determined (by dragging, for instance), // center the node. Otherwise, use the Dialog's stored relative offset, // and position the node to top: left: values based on the viewport. if(!domClass.contains(win.body(), "dojoMove")){ // don't do anything if called during auto-scroll var node = this.domNode, viewport = winUtils.getBox(), p = this._relativePosition, bb = p ? null : domGeometry.position(node), l = Math.floor(viewport.l + (p ? p.x : (viewport.w - bb.w) / 2)), t = Math.floor(viewport.t + (p ? p.y : (viewport.h - bb.h) / 2)) ; domStyle.set(node,{ left: l + "px", top: t + "px" }); } }, _onKey: function(/*Event*/ evt){ // summary: // Handles the keyboard events for accessibility reasons // tags: // private if(evt.charOrCode){ var node = evt.target; if(evt.charOrCode === keys.TAB){ this._getFocusItems(this.domNode); } var singleFocusItem = (this._firstFocusItem == this._lastFocusItem); // see if we are shift-tabbing from first focusable item on dialog if(node == this._firstFocusItem && evt.shiftKey && evt.charOrCode === keys.TAB){ if(!singleFocusItem){ focus.focus(this._lastFocusItem); // send focus to last item in dialog } event.stop(evt); }else if(node == this._lastFocusItem && evt.charOrCode === keys.TAB && !evt.shiftKey){ if(!singleFocusItem){ focus.focus(this._firstFocusItem); // send focus to first item in dialog } event.stop(evt); }else{ // see if the key is for the dialog while(node){ if(node == this.domNode || domClass.contains(node, "dijitPopup")){ if(evt.charOrCode == keys.ESCAPE){ this.onCancel(); }else{ return; // just let it go } } node = node.parentNode; } // this key is for the disabled document window if(evt.charOrCode !== keys.TAB){ // allow tabbing into the dialog for a11y event.stop(evt); // opera won't tab to a div }else if(!has("opera")){ try{ this._firstFocusItem.focus(); }catch(e){ /*squelch*/ } } } } }, show: function(){ // summary: // Display the dialog // returns: dojo.Deferred // Deferred object that resolves when the display animation is complete if(this.open){ return; } if(!this._started){ this.startup(); } // first time we show the dialog, there's some initialization stuff to do if(!this._alreadyInitialized){ this._setup(); this._alreadyInitialized=true; } if(this._fadeOutDeferred){ // There's a hide() operation in progress, so cancel it, but still call DialogLevelManager.hide() // as though the hide() completed, in preparation for the DialogLevelManager.show() call below. this._fadeOutDeferred.cancel(); DialogLevelManager.hide(this); } if(!has("touch")){ // If the user scrolls the display or resizes the viewport then reposition the Dialog. But don't do it // for touch devices, because it will counteract when a keyboard pops up and then the browser // auto-scrolls the focused node into view. this._modalconnects.push(on(window, "scroll", lang.hitch(this, "layout"))); this._modalconnects.push(on(window, "resize", lang.hitch(this, function(){ // IE gives spurious resize events and can actually get stuck // in an infinite loop if we don't ignore them var viewport = winUtils.getBox(); if(!this._oldViewport || viewport.h != this._oldViewport.h || viewport.w != this._oldViewport.w){ this.layout(); this._oldViewport = viewport; } }))); } this._modalconnects.push(on(this.domNode, connect._keypress, lang.hitch(this, "_onKey"))); domStyle.set(this.domNode, { opacity:0, display:"" }); this._set("open", true); this._onShow(); // lazy load trigger this._size(); this._position(); // fade-in Animation object, setup below var fadeIn; this._fadeInDeferred = new Deferred(lang.hitch(this, function(){ fadeIn.stop(); delete this._fadeInDeferred; })); fadeIn = fx.fadeIn({ node: this.domNode, duration: this.duration, beforeBegin: lang.hitch(this, function(){ DialogLevelManager.show(this, this.underlayAttrs); }), onEnd: lang.hitch(this, function(){ if(this.autofocus && DialogLevelManager.isTop(this)){ // find focusable items each time dialog is shown since if dialog contains a widget the // first focusable items can change this._getFocusItems(this.domNode); focus.focus(this._firstFocusItem); } this._fadeInDeferred.callback(true); delete this._fadeInDeferred; }) }).play(); return this._fadeInDeferred; }, hide: function(){ // summary: // Hide the dialog // returns: dojo.Deferred // Deferred object that resolves when the hide animation is complete // If we haven't been initialized yet then we aren't showing and we can just return. // Likewise if we are already hidden, or are currently fading out. if(!this._alreadyInitialized || !this.open){ return; } if(this._fadeInDeferred){ this._fadeInDeferred.cancel(); } // fade-in Animation object, setup below var fadeOut; this._fadeOutDeferred = new Deferred(lang.hitch(this, function(){ fadeOut.stop(); delete this._fadeOutDeferred; })); // fire onHide when the promise resolves. this._fadeOutDeferred.then(lang.hitch(this, 'onHide')); fadeOut = fx.fadeOut({ node: this.domNode, duration: this.duration, onEnd: lang.hitch(this, function(){ this.domNode.style.display = "none"; DialogLevelManager.hide(this); this._fadeOutDeferred.callback(true); delete this._fadeOutDeferred; }) }).play(); if(this._scrollConnected){ this._scrollConnected = false; } var h; while(h = this._modalconnects.pop()){ h.remove(); } if(this._relativePosition){ delete this._relativePosition; } this._set("open", false); return this._fadeOutDeferred; }, layout: function(){ // summary: // Position the Dialog and the underlay // tags: // private if(this.domNode.style.display != "none"){ if(dijit._underlay){ // avoid race condition during show() dijit._underlay.layout(); } this._position(); } }, destroy: function(){ if(this._fadeInDeferred){ this._fadeInDeferred.cancel(); } if(this._fadeOutDeferred){ this._fadeOutDeferred.cancel(); } if(this._moveable){ this._moveable.destroy(); } var h; while(h = this._modalconnects.pop()){ h.remove(); } DialogLevelManager.hide(this); this.inherited(arguments); } }); var Dialog = declare("dijit.Dialog", [ContentPane, _DialogBase], {}); Dialog._DialogBase = _DialogBase; // for monkey patching var DialogLevelManager = Dialog._DialogLevelManager = { // summary: // Controls the various active "levels" on the page, starting with the // stuff initially visible on the page (at z-index 0), and then having an entry for // each Dialog shown. _beginZIndex: 950, show: function(/*dijit._Widget*/ dialog, /*Object*/ underlayAttrs){ // summary: // Call right before fade-in animation for new dialog. // Saves current focus, displays/adjusts underlay for new dialog, // and sets the z-index of the dialog itself. // // New dialog will be displayed on top of all currently displayed dialogs. // // Caller is responsible for setting focus in new dialog after the fade-in // animation completes. // Save current focus ds[ds.length-1].focus = focus.curNode; // Display the underlay, or if already displayed then adjust for this new dialog var underlay = dijit._underlay; if(!underlay || underlay._destroyed){ underlay = dijit._underlay = new DialogUnderlay(underlayAttrs); }else{ underlay.set(dialog.underlayAttrs); } // Set z-index a bit above previous dialog var zIndex = ds[ds.length-1].dialog ? ds[ds.length-1].zIndex + 2 : Dialog._DialogLevelManager._beginZIndex; if(ds.length == 1){ // first dialog underlay.show(); } domStyle.set(dijit._underlay.domNode, 'zIndex', zIndex - 1); // Dialog domStyle.set(dialog.domNode, 'zIndex', zIndex); ds.push({dialog: dialog, underlayAttrs: underlayAttrs, zIndex: zIndex}); }, hide: function(/*dijit._Widget*/ dialog){ // summary: // Called when the specified dialog is hidden/destroyed, after the fade-out // animation ends, in order to reset page focus, fix the underlay, etc. // If the specified dialog isn't open then does nothing. // // Caller is responsible for either setting display:none on the dialog domNode, // or calling dijit.popup.hide(), or removing it from the page DOM. if(ds[ds.length-1].dialog == dialog){ // Removing the top (or only) dialog in the stack, return focus // to previous dialog ds.pop(); var pd = ds[ds.length-1]; // the new active dialog (or the base page itself) // Adjust underlay if(ds.length == 1){ // Returning to original page. // Hide the underlay, unless the underlay widget has already been destroyed // because we are being called during page unload (when all widgets are destroyed) if(!dijit._underlay._destroyed){ dijit._underlay.hide(); } }else{ // Popping back to previous dialog, adjust underlay domStyle.set(dijit._underlay.domNode, 'zIndex', pd.zIndex - 1); dijit._underlay.set(pd.underlayAttrs); } // Adjust focus if(dialog.refocus){ // If we are returning control to a previous dialog but for some reason // that dialog didn't have a focused field, set focus to first focusable item. // This situation could happen if two dialogs appeared at nearly the same time, // since a dialog doesn't set it's focus until the fade-in is finished. var focus = pd.focus; if(pd.dialog && (!focus || !dom.isDescendant(focus, pd.dialog.domNode))){ pd.dialog._getFocusItems(pd.dialog.domNode); focus = pd.dialog._firstFocusItem; } if(focus){ // Refocus the button that spawned the Dialog. This will fail in corner cases including // page unload on IE, because the dijit/form/Button that launched the Dialog may get destroyed // before this code runs. (#15058) try{ focus.focus(); }catch(e){} } } }else{ // Removing a dialog out of order (#9944, #10705). // Don't need to mess with underlay or z-index or anything. var idx = array.indexOf(array.map(ds, function(elem){return elem.dialog}), dialog); if(idx != -1){ ds.splice(idx, 1); } } }, isTop: function(/*dijit._Widget*/ dialog){ // summary: // Returns true if specified Dialog is the top in the task return ds[ds.length-1].dialog == dialog; } }; // Stack representing the various active "levels" on the page, starting with the // stuff initially visible on the page (at z-index 0), and then having an entry for // each Dialog shown. // Each element in stack has form { // dialog: dialogWidget, // focus: returnFromGetFocus(), // underlayAttrs: attributes to set on underlay (when this widget is active) // } var ds = Dialog._dialogStack = [ {dialog: null, focus: null, underlayAttrs: null} // entry for stuff at z-index: 0 ]; // Back compat w/1.6, remove for 2.0 if(!kernel.isAsync){ ready(0, function(){ var requires = ["dijit/TooltipDialog"]; require(requires); // use indirection so modules not rolled into a build }); } return Dialog; }); }, 'url:dojox/widget/ColorPicker/ColorPicker.html':"<table class=\"dojoxColorPicker\" dojoAttachEvent=\"onkeypress: _handleKey\" cellpadding=\"0\" cellspacing=\"0\">\n\t<tr>\n\t\t<td valign=\"top\" class=\"dojoxColorPickerRightPad\">\n\t\t\t<div class=\"dojoxColorPickerBox\">\n\t\t\t\t<!-- Forcing ABS in style attr due to dojo DND issue with not picking it up form the class. -->\n\t\t\t\t<img role=\"status\" title=\"${saturationPickerTitle}\" alt=\"${saturationPickerTitle}\" class=\"dojoxColorPickerPoint\" src=\"${_pickerPointer}\" tabIndex=\"0\" dojoAttachPoint=\"cursorNode\" style=\"position: absolute; top: 0px; left: 0px;\">\n\t\t\t\t<img role=\"presentation\" alt=\"\" dojoAttachPoint=\"colorUnderlay\" dojoAttachEvent=\"onclick: _setPoint, onmousedown: _stopDrag\" class=\"dojoxColorPickerUnderlay\" src=\"${_underlay}\" ondragstart=\"return false\">\n\t\t\t</div>\n\t\t</td>\n\t\t<td valign=\"top\" class=\"dojoxColorPickerRightPad\">\n\t\t\t<div class=\"dojoxHuePicker\">\n\t\t\t\t<!-- Forcing ABS in style attr due to dojo DND issue with not picking it up form the class. -->\n\t\t\t\t<img role=\"status\" dojoAttachPoint=\"hueCursorNode\" tabIndex=\"0\" class=\"dojoxHuePickerPoint\" title=\"${huePickerTitle}\" alt=\"${huePickerTitle}\" src=\"${_huePickerPointer}\" style=\"position: absolute; top: 0px; left: 0px;\">\n\t\t\t\t<div class=\"dojoxHuePickerUnderlay\" dojoAttachPoint=\"hueNode\">\n\t\t\t\t <img role=\"presentation\" alt=\"\" dojoAttachEvent=\"onclick: _setHuePoint, onmousedown: _stopDrag\" src=\"${_hueUnderlay}\">\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</td>\n\t\t<td valign=\"top\">\n\t\t\t<table cellpadding=\"0\" cellspacing=\"0\">\n\t\t\t\t<tr>\n\t\t\t\t\t<td valign=\"top\" class=\"dojoxColorPickerPreviewContainer\">\n\t\t\t\t\t\t<table cellpadding=\"0\" cellspacing=\"0\">\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td valign=\"top\" class=\"dojoxColorPickerRightPad\">\n\t\t\t\t\t\t\t\t\t<div dojoAttachPoint=\"previewNode\" class=\"dojoxColorPickerPreview\"></div>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td valign=\"top\">\n\t\t\t\t\t\t\t\t\t<div dojoAttachPoint=\"safePreviewNode\" class=\"dojoxColorPickerWebSafePreview\"></div>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t\t<tr>\n\t\t\t\t\t<td valign=\"bottom\">\n\t\t\t\t\t\t<table class=\"dojoxColorPickerOptional\" cellpadding=\"0\" cellspacing=\"0\">\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t<div class=\"dijitInline dojoxColorPickerRgb\" dojoAttachPoint=\"rgbNode\">\n\t\t\t\t\t\t\t\t\t\t<table cellpadding=\"1\" cellspacing=\"1\">\n\t\t\t\t\t\t\t\t\t\t<tr><td><label for=\"${_uId}_r\">${redLabel}</label></td><td><input id=\"${_uId}_r\" dojoAttachPoint=\"Rval\" size=\"1\" dojoAttachEvent=\"onchange: _colorInputChange\"></td></tr>\n\t\t\t\t\t\t\t\t\t\t<tr><td><label for=\"${_uId}_g\">${greenLabel}</label></td><td><input id=\"${_uId}_g\" dojoAttachPoint=\"Gval\" size=\"1\" dojoAttachEvent=\"onchange: _colorInputChange\"></td></tr>\n\t\t\t\t\t\t\t\t\t\t<tr><td><label for=\"${_uId}_b\">${blueLabel}</label></td><td><input id=\"${_uId}_b\" dojoAttachPoint=\"Bval\" size=\"1\" dojoAttachEvent=\"onchange: _colorInputChange\"></td></tr>\n\t\t\t\t\t\t\t\t\t\t</table>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\t<div class=\"dijitInline dojoxColorPickerHsv\" dojoAttachPoint=\"hsvNode\">\n\t\t\t\t\t\t\t\t\t\t<table cellpadding=\"1\" cellspacing=\"1\">\n\t\t\t\t\t\t\t\t\t\t<tr><td><label for=\"${_uId}_h\">${hueLabel}</label></td><td><input id=\"${_uId}_h\" dojoAttachPoint=\"Hval\"size=\"1\" dojoAttachEvent=\"onchange: _colorInputChange\"> ${degLabel}</td></tr>\n\t\t\t\t\t\t\t\t\t\t<tr><td><label for=\"${_uId}_s\">${saturationLabel}</label></td><td><input id=\"${_uId}_s\" dojoAttachPoint=\"Sval\" size=\"1\" dojoAttachEvent=\"onchange: _colorInputChange\"> ${percentSign}</td></tr>\n\t\t\t\t\t\t\t\t\t\t<tr><td><label for=\"${_uId}_v\">${valueLabel}</label></td><td><input id=\"${_uId}_v\" dojoAttachPoint=\"Vval\" size=\"1\" dojoAttachEvent=\"onchange: _colorInputChange\"> ${percentSign}</td></tr>\n\t\t\t\t\t\t\t\t\t\t</table>\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t\t<tr>\n\t\t\t\t\t\t\t\t<td colspan=\"2\">\n\t\t\t\t\t\t\t\t\t<div class=\"dojoxColorPickerHex\" dojoAttachPoint=\"hexNode\" aria-live=\"polite\">\t\n\t\t\t\t\t\t\t\t\t\t<label for=\"${_uId}_hex\"> ${hexLabel} </label><input id=\"${_uId}_hex\" dojoAttachPoint=\"hexCode, focusNode, valueNode\" size=\"6\" class=\"dojoxColorPickerHexCode\" dojoAttachEvent=\"onchange: _colorInputChange\">\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t</td>\n\t\t\t\t\t\t\t</tr>\n\t\t\t\t\t\t</table>\n\t\t\t\t\t</td>\n\t\t\t\t</tr>\n\t\t\t</table>\n\t\t</td>\n\t</tr>\n</table>\n\n", 'url:dijit/form/templates/Select.html':"<table class=\"dijit dijitReset dijitInline dijitLeft\"\n\tdata-dojo-attach-point=\"_buttonNode,tableNode,focusNode\" cellspacing='0' cellpadding='0'\n\trole=\"combobox\" aria-haspopup=\"true\"\n\t><tbody role=\"presentation\"><tr role=\"presentation\"\n\t\t><td class=\"dijitReset dijitStretch dijitButtonContents dijitButtonNode\" role=\"presentation\"\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\" data-dojo-attach-point=\"containerNode,_popupStateNode\"></span\n\t\t\t><input type=\"hidden\" ${!nameAttrSetting} data-dojo-attach-point=\"valueNode\" value=\"${value}\" aria-hidden=\"true\"\n\t\t/></td><td class=\"dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton\"\n\t\t\t\tdata-dojo-attach-point=\"titleNode\" role=\"presentation\"\n\t\t\t><div class=\"dijitReset dijitArrowButtonInner\" role=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitArrowButtonChar\" role=\"presentation\">▼</div\n\t\t></td\n\t></tr></tbody\n></table>\n", '*now':function(r){r(['dojo/i18n!*preload*dojo/nls/buxDialogs*["ar","az","bg","ca","cs","da","de","de-de","el","en","en-ca","en-gb","en-us","es","es-es","fi","fi-fi","fr","fr-ca","fr-fr","he","he-il","hr","hu","it","it-it","ja","ja-jp","kk","ko","ko-kr","nl","nl-nl","nb","no","pl","pt","pt-br","pt-pt","ro","ru","sk","sl","sv","th","tr","zh","zh-tw","zh-cn","ROOT"]']);} }}); define("dojo/buxDialogs", [], 1);