require({cache:{ 'dijit/form/TextBox':function(){ require({cache:{ 'url:dijit/form/templates/TextBox.html':"
\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: '', _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 // 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: "
", // 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':"\n\t\n\t\t\n\t\t\n\t\t\n\t\n
\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\"${saturationPickerTitle}\"\n\t\t\t\t\"\"\n\t\t\t
\n\t\t
\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\"${huePickerTitle}\"\n\t\t\t\t
\n\t\t\t\t \"\"\n\t\t\t\t
\n\t\t\t
\n\t\t
\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t
${degLabel}
${percentSign}
${percentSign}
\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t\t
\t\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t
\n\t\t\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t
\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: // | // |
// // 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':"
\n\t
\n\t\t
\n\t\t\t\"\"\n\t\t
\n\t
\n\t
\n\t\t
\n\t\t\t
\n\t\t\t\t\n\t\t\t
\n\t\t
\n\t
\n
\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: // | // |
// // example: // | // |
// |

I am content

// |
// 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 `` box, // automatically copy the first entry displayed in the drop down list to // the `` 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 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), '$1' ); // 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, """); //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':"
\n\t\n\t\t\n\t
\n
\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 , not the displayed , // 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 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("", 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':"
\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