aboutsummaryrefslogtreecommitdiff
path: root/includes/js/dijit/form
diff options
context:
space:
mode:
Diffstat (limited to 'includes/js/dijit/form')
-rw-r--r--includes/js/dijit/form/Button.js425
-rw-r--r--includes/js/dijit/form/CheckBox.js133
-rw-r--r--includes/js/dijit/form/ComboBox.js1060
-rw-r--r--includes/js/dijit/form/CurrencyTextBox.js51
-rw-r--r--includes/js/dijit/form/DateTextBox.js20
-rw-r--r--includes/js/dijit/form/FilteringSelect.js241
-rw-r--r--includes/js/dijit/form/Form.js384
-rw-r--r--includes/js/dijit/form/MultiSelect.js84
-rw-r--r--includes/js/dijit/form/NumberSpinner.js31
-rw-r--r--includes/js/dijit/form/NumberTextBox.js79
-rw-r--r--includes/js/dijit/form/SimpleTextarea.js50
-rw-r--r--includes/js/dijit/form/Slider.js481
-rw-r--r--includes/js/dijit/form/TextBox.js185
-rw-r--r--includes/js/dijit/form/Textarea.js261
-rw-r--r--includes/js/dijit/form/TimeTextBox.js33
-rw-r--r--includes/js/dijit/form/ValidationTextBox.js308
-rw-r--r--includes/js/dijit/form/_DateTimeTextBox.js175
-rw-r--r--includes/js/dijit/form/_FormWidget.js340
-rw-r--r--includes/js/dijit/form/_Spinner.js117
-rw-r--r--includes/js/dijit/form/nls/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/ar/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/ar/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/ar/validate.js1
-rw-r--r--includes/js/dijit/form/nls/cs/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/cs/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/cs/validate.js1
-rw-r--r--includes/js/dijit/form/nls/da/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/da/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/da/validate.js1
-rw-r--r--includes/js/dijit/form/nls/de/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/de/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/de/validate.js1
-rw-r--r--includes/js/dijit/form/nls/el/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/el/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/el/validate.js1
-rw-r--r--includes/js/dijit/form/nls/es/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/es/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/es/validate.js1
-rw-r--r--includes/js/dijit/form/nls/fi/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/fi/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/fi/validate.js1
-rw-r--r--includes/js/dijit/form/nls/fr/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/fr/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/fr/validate.js1
-rw-r--r--includes/js/dijit/form/nls/he/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/he/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/he/validate.js1
-rw-r--r--includes/js/dijit/form/nls/hu/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/hu/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/hu/validate.js1
-rw-r--r--includes/js/dijit/form/nls/it/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/it/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/it/validate.js1
-rw-r--r--includes/js/dijit/form/nls/ja/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/ja/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/ja/validate.js1
-rw-r--r--includes/js/dijit/form/nls/ko/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/ko/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/ko/validate.js1
-rw-r--r--includes/js/dijit/form/nls/nb/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/nb/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/nb/validate.js1
-rw-r--r--includes/js/dijit/form/nls/nl/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/nl/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/nl/validate.js1
-rw-r--r--includes/js/dijit/form/nls/pl/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/pl/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/pl/validate.js1
-rw-r--r--includes/js/dijit/form/nls/pt-pt/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/pt-pt/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/pt-pt/validate.js1
-rw-r--r--includes/js/dijit/form/nls/pt/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/pt/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/pt/validate.js1
-rw-r--r--includes/js/dijit/form/nls/ru/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/ru/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/ru/validate.js1
-rw-r--r--includes/js/dijit/form/nls/sv/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/sv/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/sv/validate.js1
-rw-r--r--includes/js/dijit/form/nls/tr/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/tr/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/tr/validate.js1
-rw-r--r--includes/js/dijit/form/nls/validate.js1
-rw-r--r--includes/js/dijit/form/nls/zh-tw/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/zh-tw/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/zh-tw/validate.js1
-rw-r--r--includes/js/dijit/form/nls/zh/ComboBox.js1
-rw-r--r--includes/js/dijit/form/nls/zh/Textarea.js1
-rw-r--r--includes/js/dijit/form/nls/zh/validate.js1
-rw-r--r--includes/js/dijit/form/templates/Button.html11
-rw-r--r--includes/js/dijit/form/templates/CheckBox.html7
-rw-r--r--includes/js/dijit/form/templates/ComboBox.html19
-rw-r--r--includes/js/dijit/form/templates/ComboButton.html21
-rw-r--r--includes/js/dijit/form/templates/DropDownButton.html13
-rw-r--r--includes/js/dijit/form/templates/HorizontalSlider.html37
-rw-r--r--includes/js/dijit/form/templates/InlineEditBox.html12
-rw-r--r--includes/js/dijit/form/templates/Spinner.html28
-rw-r--r--includes/js/dijit/form/templates/TextBox.html4
-rw-r--r--includes/js/dijit/form/templates/TimePicker.html5
-rw-r--r--includes/js/dijit/form/templates/ValidationTextBox.html12
-rw-r--r--includes/js/dijit/form/templates/VerticalSlider.html46
103 files changed, 4745 insertions, 0 deletions
diff --git a/includes/js/dijit/form/Button.js b/includes/js/dijit/form/Button.js
new file mode 100644
index 0000000..f81078f
--- /dev/null
+++ b/includes/js/dijit/form/Button.js
@@ -0,0 +1,425 @@
+if(!dojo._hasResource["dijit.form.Button"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.Button"] = true;
+dojo.provide("dijit.form.Button");
+
+dojo.require("dijit.form._FormWidget");
+dojo.require("dijit._Container");
+
+dojo.declare("dijit.form.Button",
+ dijit.form._FormWidget,
+ {
+ // summary:
+ // Basically the same thing as a normal HTML button, but with special styling.
+ //
+ // example:
+ // | <button dojoType="dijit.form.Button" onClick="...">Hello world</button>
+ //
+ // example:
+ // | var button1 = new dijit.form.Button({label: "hello world", onClick: foo});
+ // | dojo.body().appendChild(button1.domNode);
+ //
+ // label: String
+ // text to display in button
+ label: "",
+
+ // showLabel: Boolean
+ // whether or not to display the text label in button
+ showLabel: true,
+
+ // iconClass: String
+ // class to apply to div in button to make it display an icon
+ iconClass: "",
+
+ type: "button",
+ baseClass: "dijitButton",
+ templateString:"<div class=\"dijit dijitReset dijitLeft dijitInline\"\n\tdojoAttachEvent=\"onclick:_onButtonClick,onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\"\n\twaiRole=\"presentation\"\n\t><button class=\"dijitReset dijitStretch dijitButtonNode dijitButtonContents\" dojoAttachPoint=\"focusNode,titleNode\"\n\t\ttype=\"${type}\" waiRole=\"button\" waiState=\"labelledby-${id}_label\"\n\t\t><span class=\"dijitReset dijitInline ${iconClass}\" dojoAttachPoint=\"iconNode\" \n \t\t\t><span class=\"dijitReset dijitToggleButtonIconChar\">&#10003;</span \n\t\t></span\n\t\t><div class=\"dijitReset dijitInline\"><center class=\"dijitReset dijitButtonText\" id=\"${id}_label\" dojoAttachPoint=\"containerNode\">${label}</center></div\n\t></button\n></div>\n",
+
+ _onChangeMonitor: '',
+ // TODO: set button's title to this.containerNode.innerText
+
+ _onClick: function(/*Event*/ e){
+ // summary: internal function to handle click actions
+ if(this.disabled || this.readOnly){
+ dojo.stopEvent(e); // needed for checkbox
+ return false;
+ }
+ this._clicked(); // widget click actions
+ return this.onClick(e); // user click actions
+ },
+
+ _onButtonClick: function(/*Event*/ e){
+ // summary: callback when the user mouse clicks the button portion
+ if(this._onClick(e) === false){ // returning nothing is same as true
+ dojo.stopEvent(e);
+ }else if(this.type=="submit" && !this.focusNode.form){ // see if a nonform widget needs to be signalled
+ for(var node=this.domNode; node.parentNode/*#5935*/; node=node.parentNode){
+ var widget=dijit.byNode(node);
+ if(widget && typeof widget._onSubmit == "function"){
+ widget._onSubmit(e);
+ break;
+ }
+ }
+ }
+ },
+
+ postCreate: function(){
+ // summary:
+ // get label and set as title on button icon if necessary
+ if (this.showLabel == false){
+ var labelText = "";
+ this.label = this.containerNode.innerHTML;
+ labelText = dojo.trim(this.containerNode.innerText || this.containerNode.textContent || '');
+ // set title attrib on iconNode
+ this.titleNode.title=labelText;
+ dojo.addClass(this.containerNode,"dijitDisplayNone");
+ }
+ dojo.setSelectable(this.focusNode, false);
+ this.inherited(arguments);
+ },
+
+ onClick: function(/*Event*/ e){
+ // summary: user callback for when button is clicked
+ // if type="submit", return true to perform submit
+ return true;
+ },
+
+ _clicked: function(/*Event*/ e){
+ // summary: internal replaceable function for when the button is clicked
+ },
+
+ setLabel: function(/*String*/ content){
+ // summary: reset the label (text) of the button; takes an HTML string
+ this.containerNode.innerHTML = this.label = content;
+ this._layoutHack();
+ if (this.showLabel == false){
+ this.titleNode.title=dojo.trim(this.containerNode.innerText || this.containerNode.textContent || '');
+ }
+ }
+});
+
+
+dojo.declare("dijit.form.DropDownButton", [dijit.form.Button, dijit._Container], {
+ // summary: A button with a popup
+ //
+ // example:
+ // | <button dojoType="dijit.form.DropDownButton" label="Hello world">
+ // | <div dojotype="dijit.Menu">...</div>
+ // | </button>
+ //
+ // example:
+ // | var button1 = new dijit.form.DropDownButton({ label: "hi", dropDown: new dijit.Menu(...) });
+ // | dojo.body().appendChild(button1);
+ //
+
+ baseClass : "dijitDropDownButton",
+
+ templateString:"<div class=\"dijit dijitReset dijitLeft dijitInline\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse,onclick:_onDropDownClick,onkeydown:_onDropDownKeydown,onblur:_onDropDownBlur,onkeypress:_onKey\"\n\twaiRole=\"presentation\"\n\t><div class='dijitReset dijitRight' waiRole=\"presentation\"\n\t><button class=\"dijitReset dijitStretch dijitButtonNode dijitButtonContents\" type=\"${type}\"\n\t\tdojoAttachPoint=\"focusNode,titleNode\" waiRole=\"button\" waiState=\"haspopup-true,labelledby-${id}_label\"\n\t\t><div class=\"dijitReset dijitInline ${iconClass}\" dojoAttachPoint=\"iconNode\" waiRole=\"presentation\"></div\n\t\t><div class=\"dijitReset dijitInline dijitButtonText\" dojoAttachPoint=\"containerNode,popupStateNode\" waiRole=\"presentation\"\n\t\t\tid=\"${id}_label\">${label}</div\n\t\t><div class=\"dijitReset dijitInline dijitArrowButtonInner\" waiRole=\"presentation\">&thinsp;</div\n\t\t><div class=\"dijitReset dijitInline dijitArrowButtonChar\" waiRole=\"presentation\">&#9660;</div\n\t></button\n></div></div>\n",
+
+ _fillContent: function(){
+ // my inner HTML contains both the button contents and a drop down widget, like
+ // <DropDownButton> <span>push me</span> <Menu> ... </Menu> </DropDownButton>
+ // The first node is assumed to be the button content. The widget is the popup.
+ if(this.srcNodeRef){ // programatically created buttons might not define srcNodeRef
+ //FIXME: figure out how to filter out the widget and use all remaining nodes as button
+ // content, not just nodes[0]
+ var nodes = dojo.query("*", this.srcNodeRef);
+ dijit.form.DropDownButton.superclass._fillContent.call(this, nodes[0]);
+
+ // save pointer to srcNode so we can grab the drop down widget after it's instantiated
+ this.dropDownContainer = this.srcNodeRef;
+ }
+ },
+
+ startup: function(){
+ if(this._started){ return; }
+
+ // the child widget from srcNodeRef is the dropdown widget. Insert it in the page DOM,
+ // make it invisible, and store a reference to pass to the popup code.
+ if(!this.dropDown){
+ var dropDownNode = dojo.query("[widgetId]", this.dropDownContainer)[0];
+ this.dropDown = dijit.byNode(dropDownNode);
+ delete this.dropDownContainer;
+ }
+ dijit.popup.prepare(this.dropDown.domNode);
+
+ this.inherited(arguments);
+ },
+
+ destroyDescendants: function(){
+ if(this.dropDown){
+ this.dropDown.destroyRecursive();
+ delete this.dropDown;
+ }
+ this.inherited(arguments);
+ },
+
+ _onArrowClick: function(/*Event*/ e){
+ // summary: callback when the user mouse clicks on menu popup node
+ if(this.disabled || this.readOnly){ return; }
+ this._toggleDropDown();
+ },
+
+ _onDropDownClick: function(/*Event*/ e){
+ // on Firefox 2 on the Mac it is possible to fire onclick
+ // by pressing enter down on a second element and transferring
+ // focus to the DropDownButton;
+ // we want to prevent opening our menu in this situation
+ // and only do so if we have seen a keydown on this button;
+ // e.detail != 0 means that we were fired by mouse
+ var isMacFFlessThan3 = dojo.isFF && dojo.isFF < 3
+ && navigator.appVersion.indexOf("Macintosh") != -1;
+ if(!isMacFFlessThan3 || e.detail != 0 || this._seenKeydown){
+ this._onArrowClick(e);
+ }
+ this._seenKeydown = false;
+ },
+
+ _onDropDownKeydown: function(/*Event*/ e){
+ this._seenKeydown = true;
+ },
+
+ _onDropDownBlur: function(/*Event*/ e){
+ this._seenKeydown = false;
+ },
+
+ _onKey: function(/*Event*/ e){
+ // summary: callback when the user presses a key on menu popup node
+ if(this.disabled || this.readOnly){ return; }
+ if(e.keyCode == dojo.keys.DOWN_ARROW){
+ if(!this.dropDown || this.dropDown.domNode.style.visibility=="hidden"){
+ dojo.stopEvent(e);
+ this._toggleDropDown();
+ }
+ }
+ },
+
+ _onBlur: function(){
+ // summary: called magically when focus has shifted away from this widget and it's dropdown
+ this._closeDropDown();
+ // don't focus on button. the user has explicitly focused on something else.
+ this.inherited(arguments);
+ },
+
+ _toggleDropDown: function(){
+ // summary: toggle the drop-down widget; if it is up, close it, if not, open it
+ if(this.disabled || this.readOnly){ return; }
+ dijit.focus(this.popupStateNode);
+ var dropDown = this.dropDown;
+ if(!dropDown){ return; }
+ if(!this._opened){
+ // If there's an href, then load that first, so we don't get a flicker
+ if(dropDown.href && !dropDown.isLoaded){
+ var self = this;
+ var handler = dojo.connect(dropDown, "onLoad", function(){
+ dojo.disconnect(handler);
+ self._openDropDown();
+ });
+ dropDown._loadCheck(true);
+ return;
+ }else{
+ this._openDropDown();
+ }
+ }else{
+ this._closeDropDown();
+ }
+ },
+
+ _openDropDown: function(){
+ var dropDown = this.dropDown;
+ var oldWidth=dropDown.domNode.style.width;
+ var self = this;
+
+ dijit.popup.open({
+ parent: this,
+ popup: dropDown,
+ around: this.domNode,
+ orient:
+ // TODO: add user-defined positioning option, like in Tooltip.js
+ this.isLeftToRight() ? {'BL':'TL', 'BR':'TR', 'TL':'BL', 'TR':'BR'}
+ : {'BR':'TR', 'BL':'TL', 'TR':'BR', 'TL':'BL'},
+ onExecute: function(){
+ self._closeDropDown(true);
+ },
+ onCancel: function(){
+ self._closeDropDown(true);
+ },
+ onClose: function(){
+ dropDown.domNode.style.width = oldWidth;
+ self.popupStateNode.removeAttribute("popupActive");
+ this._opened = false;
+ }
+ });
+ if(this.domNode.offsetWidth > dropDown.domNode.offsetWidth){
+ var adjustNode = null;
+ if(!this.isLeftToRight()){
+ adjustNode = dropDown.domNode.parentNode;
+ var oldRight = adjustNode.offsetLeft + adjustNode.offsetWidth;
+ }
+ // make menu at least as wide as the button
+ dojo.marginBox(dropDown.domNode, {w: this.domNode.offsetWidth});
+ if(adjustNode){
+ adjustNode.style.left = oldRight - this.domNode.offsetWidth + "px";
+ }
+ }
+ this.popupStateNode.setAttribute("popupActive", "true");
+ this._opened=true;
+ if(dropDown.focus){
+ dropDown.focus();
+ }
+ // TODO: set this.checked and call setStateClass(), to affect button look while drop down is shown
+ },
+
+ _closeDropDown: function(/*Boolean*/ focus){
+ if(this._opened){
+ dijit.popup.close(this.dropDown);
+ if(focus){ this.focus(); }
+ this._opened = false;
+ }
+ }
+});
+
+dojo.declare("dijit.form.ComboButton", dijit.form.DropDownButton, {
+ // summary: A Normal Button with a DropDown
+ //
+ // example:
+ // | <button dojoType="dijit.form.ComboButton" onClick="...">
+ // | <span>Hello world</span>
+ // | <div dojoType="dijit.Menu">...</div>
+ // | </button>
+ //
+ // example:
+ // | var button1 = new dijit.form.ComboButton({label: "hello world", onClick: foo, dropDown: "myMenu"});
+ // | dojo.body().appendChild(button1.domNode);
+ //
+
+ templateString:"<table class='dijit dijitReset dijitInline dijitLeft'\n\tcellspacing='0' cellpadding='0' waiRole=\"presentation\"\n\t><tbody waiRole=\"presentation\"><tr waiRole=\"presentation\"\n\t\t><td\tclass=\"dijitReset dijitStretch dijitButtonContents dijitButtonNode\"\n\t\t\ttabIndex=\"${tabIndex}\"\n\t\t\tdojoAttachEvent=\"ondijitclick:_onButtonClick,onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\" dojoAttachPoint=\"titleNode\"\n\t\t\twaiRole=\"button\" waiState=\"labelledby-${id}_label\"\n\t\t\t><div class=\"dijitReset dijitInline ${iconClass}\" dojoAttachPoint=\"iconNode\" waiRole=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitInline dijitButtonText\" id=\"${id}_label\" dojoAttachPoint=\"containerNode\" waiRole=\"presentation\">${label}</div\n\t\t></td\n\t\t><td class='dijitReset dijitStretch dijitButtonNode dijitArrowButton dijitDownArrowButton'\n\t\t\tdojoAttachPoint=\"popupStateNode,focusNode\"\n\t\t\tdojoAttachEvent=\"ondijitclick:_onArrowClick, onkeypress:_onKey,onmouseenter:_onMouse,onmouseleave:_onMouse\"\n\t\t\tstateModifier=\"DownArrow\"\n\t\t\ttitle=\"${optionsTitle}\" name=\"${name}\"\n\t\t\twaiRole=\"button\" waiState=\"haspopup-true\"\n\t\t\t><div class=\"dijitReset dijitArrowButtonInner\" waiRole=\"presentation\">&thinsp;</div\n\t\t\t><div class=\"dijitReset dijitArrowButtonChar\" waiRole=\"presentation\">&#9660;</div\n\t\t></td\n\t></tr></tbody\n></table>\n",
+
+ attributeMap: dojo.mixin(dojo.clone(dijit.form._FormWidget.prototype.attributeMap),
+ {id:"", name:""}),
+
+ // optionsTitle: String
+ // text that describes the options menu (accessibility)
+ optionsTitle: "",
+
+ baseClass: "dijitComboButton",
+
+ _focusedNode: null,
+
+ postCreate: function(){
+ this.inherited(arguments);
+ this._focalNodes = [this.titleNode, this.popupStateNode];
+ dojo.forEach(this._focalNodes, dojo.hitch(this, function(node){
+ if(dojo.isIE){
+ this.connect(node, "onactivate", this._onNodeFocus);
+ this.connect(node, "ondeactivate", this._onNodeBlur);
+ }else{
+ this.connect(node, "onfocus", this._onNodeFocus);
+ this.connect(node, "onblur", this._onNodeBlur);
+ }
+ }));
+ },
+
+ focusFocalNode: function(node){
+ // summary: Focus the focal node node.
+ this._focusedNode = node;
+ dijit.focus(node);
+ },
+
+ hasNextFocalNode: function(){
+ // summary: Returns true if this widget has no node currently
+ // focused or if there is a node following the focused one.
+ // False is returned if the last node has focus.
+ return this._focusedNode !== this.getFocalNodes()[1];
+ },
+
+ focusNext: function(){
+ // summary: Focus the focal node following the current node with focus
+ // or the first one if no node currently has focus.
+ this._focusedNode = this.getFocalNodes()[this._focusedNode ? 1 : 0];
+ dijit.focus(this._focusedNode);
+ },
+
+ hasPrevFocalNode: function(){
+ // summary: Returns true if this widget has no node currently
+ // focused or if there is a node before the focused one.
+ // False is returned if the first node has focus.
+ return this._focusedNode !== this.getFocalNodes()[0];
+ },
+
+ focusPrev: function(){
+ // summary: Focus the focal node before the current node with focus
+ // or the last one if no node currently has focus.
+ this._focusedNode = this.getFocalNodes()[this._focusedNode ? 0 : 1];
+ dijit.focus(this._focusedNode);
+ },
+
+ getFocalNodes: function(){
+ // summary: Returns an array of focal nodes for this widget.
+ return this._focalNodes;
+ },
+
+ _onNodeFocus: function(evt){
+ this._focusedNode = evt.currentTarget;
+ var fnc = this._focusedNode == this.focusNode ? "dijitDownArrowButtonFocused" : "dijitButtonContentsFocused";
+ dojo.addClass(this._focusedNode, fnc);
+ },
+
+ _onNodeBlur: function(evt){
+ var fnc = evt.currentTarget == this.focusNode ? "dijitDownArrowButtonFocused" : "dijitButtonContentsFocused";
+ dojo.removeClass(evt.currentTarget, fnc);
+ },
+
+ _onBlur: function(){
+ this.inherited(arguments);
+ this._focusedNode = null;
+ }
+});
+
+dojo.declare("dijit.form.ToggleButton", dijit.form.Button, {
+ // summary:
+ // A button that can be in two states (checked or not).
+ // Can be base class for things like tabs or checkbox or radio buttons
+
+ baseClass: "dijitToggleButton",
+
+ // checked: Boolean
+ // Corresponds to the native HTML <input> element's attribute.
+ // In markup, specified as "checked='checked'" or just "checked".
+ // True if the button is depressed, or the checkbox is checked,
+ // or the radio button is selected, etc.
+ checked: false,
+
+ _onChangeMonitor: 'checked',
+
+ attributeMap: dojo.mixin(dojo.clone(dijit.form.Button.prototype.attributeMap),
+ {checked:"focusNode"}),
+
+ _clicked: function(/*Event*/ evt){
+ this.setAttribute('checked', !this.checked);
+ },
+
+ setAttribute: function(/*String*/ attr, /*anything*/ value){
+ this.inherited(arguments);
+ switch(attr){
+ case "checked":
+ dijit.setWaiState(this.focusNode || this.domNode, "pressed", this.checked);
+ this._setStateClass();
+ this._handleOnChange(this.checked, true);
+ }
+ },
+
+
+ setChecked: function(/*Boolean*/ checked){
+ // summary:
+ // Programatically deselect the button
+ dojo.deprecated("setChecked("+checked+") is deprecated. Use setAttribute('checked',"+checked+") instead.", "", "2.0");
+ this.setAttribute('checked', checked);
+ },
+
+ postCreate: function(){
+ this.inherited(arguments);
+ this.setAttribute('checked', this.checked); //to initially set wai pressed state
+ }
+});
+
+}
diff --git a/includes/js/dijit/form/CheckBox.js b/includes/js/dijit/form/CheckBox.js
new file mode 100644
index 0000000..295a711
--- /dev/null
+++ b/includes/js/dijit/form/CheckBox.js
@@ -0,0 +1,133 @@
+if(!dojo._hasResource["dijit.form.CheckBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.CheckBox"] = true;
+dojo.provide("dijit.form.CheckBox");
+
+dojo.require("dijit.form.Button");
+
+dojo.declare(
+ "dijit.form.CheckBox",
+ dijit.form.ToggleButton,
+ {
+ // summary:
+ // Same as an HTML checkbox, but with fancy styling.
+ //
+ // description:
+ // User interacts with real html inputs.
+ // On onclick (which occurs by mouse click, space-bar, or
+ // using the arrow keys to switch the selected radio button),
+ // we update the state of the checkbox/radio.
+ //
+ // There are two modes:
+ // 1. High contrast mode
+ // 2. Normal mode
+ // In case 1, the regular html inputs are shown and used by the user.
+ // In case 2, the regular html inputs are invisible but still used by
+ // the user. They are turned quasi-invisible and overlay the background-image.
+
+ templateString:"<div class=\"dijitReset dijitInline\" waiRole=\"presentation\"\n\t><input\n\t \ttype=\"${type}\" name=\"${name}\"\n\t\tclass=\"dijitReset dijitCheckBoxInput\"\n\t\tdojoAttachPoint=\"focusNode\"\n\t \tdojoAttachEvent=\"onmouseover:_onMouse,onmouseout:_onMouse,onclick:_onClick\"\n/></div>\n",
+
+ baseClass: "dijitCheckBox",
+
+ // Value of "type" attribute for <input>
+ type: "checkbox",
+
+ // value: Value
+ // equivalent to value field on normal checkbox (if checked, the value is passed as
+ // the value when form is submitted)
+ value: "on",
+
+ setValue: function(/*String or Boolean*/ newValue){
+ // summary:
+ // 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
+ // dojoType="dijit.CheckBox" value="chicken">)
+ if(typeof newValue == "string"){
+ this.setAttribute('value', newValue);
+ newValue = true;
+ }
+ this.setAttribute('checked', newValue);
+ },
+
+ _getValueDeprecated: false, // remove when _FormWidget:_getValueDeprecated is removed
+ getValue: function(){
+ // summary:
+ // If the CheckBox is checked, returns the value attribute.
+ // Otherwise returns false.
+ return (this.checked ? this.value : false);
+ },
+
+ reset: function(){
+ this.inherited(arguments);
+ this.setAttribute('value', this._resetValueAttr);
+ },
+
+ postCreate: function(){
+ this.inherited(arguments);
+ this._resetValueAttr = this.value;
+ }
+ }
+);
+
+dojo.declare(
+ "dijit.form.RadioButton",
+ dijit.form.CheckBox,
+ {
+ // summary:
+ // Same as an HTML radio, but with fancy styling.
+ //
+ // description:
+ // Implementation details
+ //
+ // Specialization:
+ // We keep track of dijit radio groups so that we can update the state
+ // of all the siblings (the "context") in a group based on input
+ // events. We don't rely on browser radio grouping.
+
+ type: "radio",
+ baseClass: "dijitRadio",
+
+ // This shared object keeps track of all widgets, grouped by name
+ _groups: {},
+
+ postCreate: function(){
+ // add this widget to _groups
+ (this._groups[this.name] = this._groups[this.name] || []).push(this);
+
+ this.inherited(arguments);
+ },
+
+ uninitialize: function(){
+ // remove this widget from _groups
+ dojo.forEach(this._groups[this.name], function(widget, i, arr){
+ if(widget === this){
+ arr.splice(i, 1);
+ return;
+ }
+ }, this);
+ },
+
+ setAttribute: function(/*String*/ attr, /*anything*/ value){
+ // If I am being checked then have to deselect currently checked radio button
+ this.inherited(arguments);
+ switch(attr){
+ case "checked":
+ if(this.checked){
+ dojo.forEach(this._groups[this.name], function(widget){
+ if(widget != this && widget.checked){
+ widget.setAttribute('checked', false);
+ }
+ }, this);
+ }
+ }
+ },
+
+ _clicked: function(/*Event*/ e){
+ if(!this.checked){
+ this.setAttribute('checked', true);
+ }
+ }
+ }
+);
+
+}
diff --git a/includes/js/dijit/form/ComboBox.js b/includes/js/dijit/form/ComboBox.js
new file mode 100644
index 0000000..77a75f0
--- /dev/null
+++ b/includes/js/dijit/form/ComboBox.js
@@ -0,0 +1,1060 @@
+if(!dojo._hasResource["dijit.form.ComboBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.ComboBox"] = true;
+dojo.provide("dijit.form.ComboBox");
+
+dojo.require("dijit.form.ValidationTextBox");
+dojo.requireLocalization("dijit.form", "ComboBox", null, "zh,ROOT,pt,da,tr,ru,de,sv,ja,he,fi,nb,el,ar,pt-pt,cs,fr,es,ko,nl,zh-tw,pl,it,hu");
+
+dojo.declare(
+ "dijit.form.ComboBoxMixin",
+ null,
+ {
+ // item: Object
+ // This is the item returned by the dojo.data.store implementation that
+ // provides the data for this cobobox, it's the currently selected item.
+ item: null,
+
+ // pageSize: Integer
+ // Argument to data provider.
+ // Specifies number of search results per page (before hitting "next" button)
+ pageSize: Infinity,
+
+ // store: Object
+ // Reference to data provider object used by this ComboBox
+ store: null,
+
+ // query: Object
+ // A query that can be passed to 'store' to initially filter the items,
+ // before doing further filtering based on `searchAttr` and the key.
+ // Any reference to the `searchAttr` is ignored.
+ query: {},
+
+ // autoComplete: Boolean
+ // If you type in a partial string, and then tab out of the `<input>` box,
+ // automatically copy the first entry displayed in the drop down list to
+ // the `<input>` field
+ autoComplete: true,
+
+ // searchDelay: Integer
+ // Delay in milliseconds between when user types something and we start
+ // searching based on that value
+ searchDelay: 100,
+
+ // searchAttr: String
+ // Searches pattern match against this field
+ searchAttr: "name",
+
+ // queryExpr: String
+ // 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 should ignore case when matching possible items
+ ignoreCase: true,
+
+ // hasDownArrow: Boolean
+ // Set this textbox to have a down arrow button.
+ // Defaults to true.
+ hasDownArrow:true,
+
+ templateString:"<div class=\"dijit dijitReset dijitInlineTable dijitLeft\"\n\tid=\"widget_${id}\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\" dojoAttachPoint=\"comboNode\" waiRole=\"combobox\" tabIndex=\"-1\"\n\t><div style=\"overflow:hidden;\"\n\t\t><div class='dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton'\n\t\t\tdojoAttachPoint=\"downArrowNode\" waiRole=\"presentation\"\n\t\t\tdojoAttachEvent=\"onmousedown:_onArrowMouseDown,onmouseup:_onMouse,onmouseenter:_onMouse,onmouseleave:_onMouse\"\n\t\t\t><div class=\"dijitArrowButtonInner\">&thinsp;</div\n\t\t\t><div class=\"dijitArrowButtonChar\">&#9660;</div\n\t\t></div\n\t\t><div class=\"dijitReset dijitValidationIcon\"><br></div\n\t\t><div class=\"dijitReset dijitValidationIconText\">&Chi;</div\n\t\t><div class=\"dijitReset dijitInputField\"\n\t\t\t><input type=\"text\" autocomplete=\"off\" name=\"${name}\" class='dijitReset'\n\t\t\tdojoAttachEvent=\"onkeypress:_onKeyPress, onfocus:_update, compositionend,onkeyup\"\n\t\t\tdojoAttachPoint=\"textbox,focusNode\" waiRole=\"textbox\" waiState=\"haspopup-true,autocomplete-list\"\n\t\t/></div\n\t></div\n></div>\n",
+
+ baseClass:"dijitComboBox",
+
+ _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(dojo.isIE){
+ // in the case of a mouse click in a popup being handled,
+ // then the dojo.doc.selection is not the textarea, but the popup
+ // var r = dojo.doc.selection.createRange();
+ // hack to get IE 6 to play nice. What a POS browser.
+ var tr = dojo.doc.selection.createRange().duplicate();
+ var ntr = element.createTextRange();
+ tr.move("character",0);
+ ntr.move("character",0);
+ try{
+ // If control doesnt have focus, you get an exception.
+ // Seems to happen on reverse-tab, but can also happen on tab (seems to be a race condition - only happens sometimes).
+ // There appears to be no workaround for this - googled for quite a while.
+ ntr.setEndPoint("EndToEnd", tr);
+ 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);
+ dijit.selectInputText(element, location, location);
+ },
+
+ _setAttribute: function(/*String*/ attr, /*anything*/ value){
+ // summary: additional code to set disablbed state of combobox node
+ if (attr == "disabled"){
+ dijit.setWaiState(this.comboNode, "disabled", value);
+ }
+ },
+
+ _onKeyPress: function(/*Event*/ evt){
+ // summary: handles keyboard events
+
+ //except for pasting case - ctrl + v(118)
+ if(evt.altKey || (evt.ctrlKey && evt.charCode != 118)){
+ return;
+ }
+ var doSearch = false;
+ var pw = this._popupWidget;
+ var dk = dojo.keys;
+ if(this._isShowingNow){
+ pw.handleKey(evt);
+ }
+ switch(evt.keyCode){
+ case dk.PAGE_DOWN:
+ case dk.DOWN_ARROW:
+ if(!this._isShowingNow||this._prev_key_esc){
+ this._arrowPressed();
+ doSearch=true;
+ }else{
+ this._announceOption(pw.getHighlightedOption());
+ }
+ dojo.stopEvent(evt);
+ this._prev_key_backspace = false;
+ this._prev_key_esc = false;
+ break;
+
+ case dk.PAGE_UP:
+ case dk.UP_ARROW:
+ if(this._isShowingNow){
+ this._announceOption(pw.getHighlightedOption());
+ }
+ dojo.stopEvent(evt);
+ this._prev_key_backspace = false;
+ this._prev_key_esc = false;
+ break;
+
+ case dk.ENTER:
+ // prevent submitting form if user presses enter. Also
+ // prevent accepting the value if either Next or Previous
+ // are selected
+ var highlighted;
+ if( this._isShowingNow &&
+ (highlighted = pw.getHighlightedOption())
+ ){
+ // only stop event on prev/next
+ if(highlighted == pw.nextButton){
+ this._nextSearch(1);
+ dojo.stopEvent(evt);
+ break;
+ }else if(highlighted == pw.previousButton){
+ this._nextSearch(-1);
+ dojo.stopEvent(evt);
+ break;
+ }
+ }else{
+ this.setDisplayedValue(this.getDisplayedValue());
+ }
+ // default case:
+ // prevent submit, but allow event to bubble
+ evt.preventDefault();
+ // fall through
+
+ case dk.TAB:
+ var newvalue = this.getDisplayedValue();
+ // #4617:
+ // if the user had More Choices selected fall into the
+ // _onBlur handler
+ if(pw && (
+ newvalue == pw._messages["previousMessage"] ||
+ newvalue == pw._messages["nextMessage"])
+ ){
+ break;
+ }
+ if(this._isShowingNow){
+ this._prev_key_backspace = false;
+ this._prev_key_esc = false;
+ if(pw.getHighlightedOption()){
+ pw.setValue({ target: pw.getHighlightedOption() }, true);
+ }
+ this._hideResultList();
+ }
+ break;
+
+ case dk.SPACE:
+ this._prev_key_backspace = false;
+ this._prev_key_esc = false;
+ if(this._isShowingNow && pw.getHighlightedOption()){
+ dojo.stopEvent(evt);
+ this._selectOption();
+ this._hideResultList();
+ }else{
+ doSearch = true;
+ }
+ break;
+
+ case dk.ESCAPE:
+ this._prev_key_backspace = false;
+ this._prev_key_esc = true;
+ if(this._isShowingNow){
+ dojo.stopEvent(evt);
+ this._hideResultList();
+ }
+ this.inherited(arguments);
+ break;
+
+ case dk.DELETE:
+ case dk.BACKSPACE:
+ this._prev_key_esc = false;
+ this._prev_key_backspace = true;
+ doSearch = true;
+ break;
+
+ case dk.RIGHT_ARROW: // fall through
+ case dk.LEFT_ARROW:
+ this._prev_key_backspace = false;
+ this._prev_key_esc = false;
+ break;
+
+ default: // non char keys (F1-F12 etc..) shouldn't open list
+ this._prev_key_backspace = false;
+ this._prev_key_esc = false;
+ if(dojo.isIE || evt.charCode != 0){
+ doSearch = true;
+ }
+ }
+ if(this.searchTimer){
+ clearTimeout(this.searchTimer);
+ }
+ if(doSearch){
+ // need to wait a tad before start search so that the event
+ // bubbles through DOM and we have value visible
+ setTimeout(dojo.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
+ dijit.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._getCaretPos(fn);
+ // 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
+ dijit.selectInputText(fn, cpos);
+ }
+ }else{
+ // text does not autoComplete; replace the whole value and highlight
+ fn.value = text;
+ dijit.selectInputText(fn);
+ }
+ },
+
+ _openResultList: function(/*Object*/ results, /*Object*/ dataObject){
+ if( this.disabled ||
+ this.readOnly ||
+ (dataObject.query[this.searchAttr] != this._lastQuery)
+ ){
+ return;
+ }
+ this._popupWidget.clearResultList();
+ if(!results.length){
+ this._hideResultList();
+ return;
+ }
+
+ // Fill in the textbox with the first item from the drop down list,
+ // and highlight the characters that were auto-completed. For
+ // example, if user typed "CA" and the drop down list appeared, the
+ // textbox would be changed to "California" and "ifornia" would be
+ // highlighted.
+
+ var zerothvalue = new String(this.store.getValue(results[0], this.searchAttr));
+ if(zerothvalue && this.autoComplete && !this._prev_key_backspace &&
+ (dataObject.query[this.searchAttr] != "*")){
+ // 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.
+ this._autoCompleteText(zerothvalue);
+ }
+ this._popupWidget.createOptions(
+ results,
+ dataObject,
+ dojo.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(dataObject.direction){
+ if(1 == dataObject.direction){
+ this._popupWidget.highlightFirstOption();
+ }else if(-1 == dataObject.direction){
+ this._popupWidget.highlightLastOption();
+ }
+ this._announceOption(this._popupWidget.getHighlightedOption());
+ }
+ },
+
+ _showResultList: function(){
+ this._hideResultList();
+ var items = this._popupWidget.getItems(),
+ visibleCount = Math.min(items.length,this.maxListLength);
+ this._arrowPressed();
+ // hide the tooltip
+ this.displayMessage("");
+
+ // Position the list and if it's too big to fit on the screen then
+ // size it to the maximum possible height
+ // Our dear friend IE doesnt take max-height so we need to
+ // calculate that on our own every time
+
+ // TODO: want to redo this, see
+ // http://trac.dojotoolkit.org/ticket/3272
+ // and
+ // http://trac.dojotoolkit.org/ticket/4108
+
+ with(this._popupWidget.domNode.style){
+ // natural size of the list has changed, so erase old
+ // width/height settings, which were hardcoded in a previous
+ // call to this function (via dojo.marginBox() call)
+ width = "";
+ height = "";
+ }
+ var best = this.open();
+ // #3212:
+ // only set auto scroll bars if necessary prevents issues with
+ // scroll bars appearing when they shouldn't when node is made
+ // wider (fractional pixels cause this)
+ var popupbox = dojo.marginBox(this._popupWidget.domNode);
+ this._popupWidget.domNode.style.overflow =
+ ((best.h==popupbox.h)&&(best.w==popupbox.w)) ? "hidden" : "auto";
+ // #4134:
+ // borrow TextArea scrollbar test so content isn't covered by
+ // scrollbar and horizontal scrollbar doesn't appear
+ var newwidth = best.w;
+ if(best.h < this._popupWidget.domNode.scrollHeight){
+ newwidth += 16;
+ }
+ dojo.marginBox(this._popupWidget.domNode, {
+ h: best.h,
+ w: Math.max(newwidth, this.domNode.offsetWidth)
+ });
+ dijit.setWaiState(this.comboNode, "expanded", "true");
+ },
+
+ _hideResultList: function(){
+ if(this._isShowingNow){
+ dijit.popup.close(this._popupWidget);
+ this._arrowIdle();
+ this._isShowingNow=false;
+ dijit.setWaiState(this.comboNode, "expanded", "false");
+ dijit.removeWaiState(this.focusNode,"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.getDisplayedValue();
+ var pw = this._popupWidget;
+ if(pw && (
+ newvalue == pw._messages["previousMessage"] ||
+ newvalue == pw._messages["nextMessage"]
+ )
+ ){
+ this.setValue(this._lastValueReported, true);
+ }else{
+ this.setDisplayedValue(newvalue);
+ }
+ },
+
+ _onBlur: function(){
+ // summary: called magically when focus has shifted away from this widget and it's dropdown
+ this._hideResultList();
+ this._arrowIdle();
+ this.inherited(arguments);
+ },
+
+ _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 == null){
+ return;
+ }
+ // pull the text value from the item attached to the DOM node
+ var newValue;
+ if( node == this._popupWidget.nextButton ||
+ node == this._popupWidget.previousButton){
+ newValue = node.innerHTML;
+ }else{
+ newValue = this.store.getValue(node.item, this.searchAttr);
+ }
+ // get the text that the user manually entered (cut off autocompleted text)
+ this.focusNode.value = this.focusNode.value.substring(0, this._getCaretPos(this.focusNode));
+ //set up ARIA activedescendant
+ dijit.setWaiState(this.focusNode, "activedescendant", dojo.attr(node, "id"));
+ // autocomplete the rest of the option to announce change
+ this._autoCompleteText(newValue);
+ },
+
+ _selectOption: function(/*Event*/ evt){
+ var tgt = null;
+ if(!evt){
+ evt ={ target: this._popupWidget.getHighlightedOption()};
+ }
+ // what if nothing is highlighted yet?
+ if(!evt.target){
+ // handle autocompletion where the the user has hit ENTER or TAB
+ this.setDisplayedValue(this.getDisplayedValue());
+ return;
+ // otherwise the user has accepted the autocompleted value
+ }else{
+ tgt = evt.target;
+ }
+ if(!evt.noHide){
+ this._hideResultList();
+ this._setCaretPos(this.focusNode, this.store.getValue(tgt.item, this.searchAttr).length);
+ }
+ this._doSelect(tgt);
+ },
+
+ _doSelect: function(tgt){
+ this.item = tgt.item;
+ this.setValue(this.store.getValue(tgt.item, this.searchAttr), true);
+ },
+
+ _onArrowMouseDown: function(evt){
+ // summary: callback when arrow is clicked
+ if(this.disabled || this.readOnly){
+ return;
+ }
+ dojo.stopEvent(evt);
+ this.focus();
+ if(this._isShowingNow){
+ this._hideResultList();
+ }else{
+ // forces full population of results, if they click
+ // on the arrow it means they want to see more options
+ this._startSearch("");
+ }
+ },
+
+ _startSearchFromInput: function(){
+ this._startSearch(this.focusNode.value);
+ },
+
+ _getQueryString: function(/*String*/ text){
+ return dojo.string.substitute(this.queryExpr, [text]);
+ },
+
+ _startSearch: function(/*String*/ key){
+ if(!this._popupWidget){
+ var popupId = this.id + "_popup";
+ this._popupWidget = new dijit.form._ComboBoxMenu({
+ onChange: dojo.hitch(this, this._selectOption),
+ id:popupId
+ });
+ dijit.removeWaiState(this.focusNode,"activedescendant");
+ dijit.setWaiState(this.textbox,"owns",popupId); // associate popup with textbox
+ }
+ // create a new query to prevent accidentally querying for a hidden
+ // value from FilteringSelect's keyField
+ this.item = null; // #4872
+ var query = dojo.clone(this.query); // #5970
+ this._lastQuery = query[this.searchAttr] = this._getQueryString(key);
+ // #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(dojo.hitch(this, function(query, _this){
+ var dataObject = this.store.fetch({
+ queryOptions: {
+ ignoreCase: this.ignoreCase,
+ deep: true
+ },
+ query: query,
+ onComplete: dojo.hitch(this, "_openResultList"),
+ onError: function(errText){
+ console.error('dijit.form.ComboBox: ' + errText);
+ dojo.hitch(_this, "_hideResultList")();
+ },
+ start:0,
+ count:this.pageSize
+ });
+
+ var nextSearch = function(dataObject, direction){
+ dataObject.start += dataObject.count*direction;
+ // #4091:
+ // tell callback the direction of the paging so the screen
+ // reader knows which menu option to shout
+ dataObject.direction = direction;
+ this.store.fetch(dataObject);
+ }
+ this._nextSearch = this._popupWidget.onPage = dojo.hitch(this, nextSearch, dataObject);
+ }, query, this), this.searchDelay);
+ },
+
+ _getValueField:function(){
+ return this.searchAttr;
+ },
+
+ /////////////// Event handlers /////////////////////
+
+ _arrowPressed: function(){
+ if(!this.disabled && !this.readOnly && this.hasDownArrow){
+ dojo.addClass(this.downArrowNode, "dijitArrowButtonActive");
+ }
+ },
+
+ _arrowIdle: function(){
+ if(!this.disabled && !this.readOnly && this.hasDownArrow){
+ dojo.removeClass(this.downArrowNode, "dojoArrowButtonPushed");
+ }
+ },
+
+ // FIXME:
+ // this is public so we can't remove until 2.0, but the name
+ // SHOULD be "compositionEnd"
+
+ compositionend: function(/*Event*/ evt){
+ // summary:
+ // When inputting characters using an input method, such as
+ // Asian languages, it will generate this event instead of
+ // onKeyDown event Note: this event is only triggered in FF
+ // (not in IE)
+ this.onkeypress({charCode:-1});
+ },
+
+ //////////// INITIALIZATION METHODS ///////////////////////////////////////
+
+ constructor: function(){
+ this.query={};
+ },
+
+ postMixInProperties: function(){
+ if(!this.hasDownArrow){
+ this.baseClass = "dijitTextBox";
+ }
+ if(!this.store){
+ var srcNodeRef = this.srcNodeRef;
+
+ // if user didn't specify store, then assume there are option tags
+ this.store = new dijit.form._ComboBoxDataStore(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( !this.value || (
+ (typeof srcNodeRef.selectedIndex == "number") &&
+ srcNodeRef.selectedIndex.toString() === this.value)
+ ){
+ var item = this.store.fetchSelectedItem();
+ if(item){
+ this.value = this.store.getValue(item, this._getValueField());
+ }
+ }
+ }
+ },
+
+ _postCreate:function(){
+ //find any associated label element and add to combobox node.
+ var label=dojo.query('label[for="'+this.id+'"]');
+ if(label.length){
+ label[0].id = (this.id+"_label");
+ var cn=this.comboNode;
+ dijit.setWaiState(cn, "labelledby", label[0].id);
+ dijit.setWaiState(cn, "disabled", this.disabled);
+
+ }
+ },
+
+ uninitialize:function(){
+ if(this._popupWidget){
+ this._hideResultList();
+ this._popupWidget.destroy()
+ }
+ },
+
+ _getMenuLabelFromItem:function(/*Item*/ item){
+ return {
+ html: false,
+ label: this.store.getValue(item, this.searchAttr)
+ };
+ },
+
+ open:function(){
+ this._isShowingNow=true;
+ return dijit.popup.open({
+ popup: this._popupWidget,
+ around: this.domNode,
+ parent: this
+ });
+ },
+
+ reset:function(){
+ // summary:
+ // Additionally reset the .item (to clean up).
+ this.item = null;
+ this.inherited(arguments);
+ }
+
+ }
+);
+
+dojo.declare(
+ "dijit.form._ComboBoxMenu",
+ [dijit._Widget, dijit._Templated],
+
+ {
+ // summary:
+ // Focus-less div based menu for internal use in ComboBox
+
+ templateString: "<ul class='dijitMenu' dojoAttachEvent='onmousedown:_onMouseDown,onmouseup:_onMouseUp,onmouseover:_onMouseOver,onmouseout:_onMouseOut' tabIndex='-1' style='overflow:\"auto\";'>"
+ +"<li class='dijitMenuItem dijitMenuPreviousButton' dojoAttachPoint='previousButton'></li>"
+ +"<li class='dijitMenuItem dijitMenuNextButton' dojoAttachPoint='nextButton'></li>"
+ +"</ul>",
+ _messages: null,
+
+ postMixInProperties: function(){
+ this._messages = dojo.i18n.getLocalization("dijit.form", "ComboBox", this.lang);
+ this.inherited("postMixInProperties", arguments);
+ },
+
+ setValue: function(/*Object*/ value){
+ this.value = value;
+ this.onChange(value);
+ },
+
+ // stubs
+ onChange: function(/*Object*/ value){},
+ onPage: function(/*Number*/ direction){},
+
+ postCreate:function(){
+ // fill in template with i18n messages
+ this.previousButton.innerHTML = this._messages["previousMessage"];
+ this.nextButton.innerHTML = this._messages["nextMessage"];
+ this.inherited("postCreate", arguments);
+ },
+
+ onClose:function(){
+ this._blurOptionNode();
+ },
+
+ _createOption:function(/*Object*/ item, labelFunc){
+ // summary:
+ // creates an option to appear on the popup menu subclassed by
+ // FilteringSelect
+
+ var labelObject = labelFunc(item);
+ var menuitem = dojo.doc.createElement("li");
+ dijit.setWaiRole(menuitem, "option");
+ if(labelObject.html){
+ menuitem.innerHTML = labelObject.label;
+ }else{
+ menuitem.appendChild(
+ dojo.doc.createTextNode(labelObject.label)
+ );
+ }
+ // #3250: in blank options, assign a normal height
+ if(menuitem.innerHTML == ""){
+ menuitem.innerHTML = "&nbsp;";
+ }
+ menuitem.item=item;
+ return menuitem;
+ },
+
+ createOptions: function(results, dataObject, labelFunc){
+ //this._dataObject=dataObject;
+ //this._dataObject.onComplete=dojo.hitch(comboBox, comboBox._openResultList);
+ // display "Previous . . ." button
+ this.previousButton.style.display = (dataObject.start == 0) ? "none" : "";
+ dojo.attr(this.previousButton, "id", this.id + "_prev");
+ // create options using _createOption function defined by parent
+ // ComboBox (or FilteringSelect) class
+ // #2309:
+ // iterate over cache nondestructively
+ dojo.forEach(results, function(item, i){
+ var menuitem = this._createOption(item, labelFunc);
+ menuitem.className = "dijitMenuItem";
+ dojo.attr(menuitem, "id", this.id + i);
+ this.domNode.insertBefore(menuitem, this.nextButton);
+ }, this);
+ // display "Next . . ." button
+ this.nextButton.style.display = (dataObject.count == results.length) ? "" : "none";
+ dojo.attr(this.nextButton,"id", this.id + "_next")
+ },
+
+ clearResultList: function(){
+ // keep the previous and next buttons of course
+ while(this.domNode.childNodes.length>2){
+ this.domNode.removeChild(this.domNode.childNodes[this.domNode.childNodes.length-2]);
+ }
+ },
+
+ // these functions are called in showResultList
+ getItems: function(){
+ return this.domNode.childNodes;
+ },
+
+ getListLength: function(){
+ return this.domNode.childNodes.length-2;
+ },
+
+ _onMouseDown: function(/*Event*/ evt){
+ dojo.stopEvent(evt);
+ },
+
+ _onMouseUp: function(/*Event*/ evt){
+ if(evt.target === this.domNode){
+ return;
+ }else if(evt.target==this.previousButton){
+ this.onPage(-1);
+ }else if(evt.target==this.nextButton){
+ this.onPage(1);
+ }else{
+ var tgt = evt.target;
+ // while the clicked node is inside the div
+ while(!tgt.item){
+ // recurse to the top
+ tgt = tgt.parentNode;
+ }
+ this.setValue({ target: tgt }, true);
+ }
+ },
+
+ _onMouseOver: function(/*Event*/ evt){
+ if(evt.target === this.domNode){ return; }
+ var tgt = evt.target;
+ if(!(tgt == this.previousButton || tgt == this.nextButton)){
+ // while the clicked node is inside the div
+ while(!tgt.item){
+ // recurse to the top
+ tgt = tgt.parentNode;
+ }
+ }
+ this._focusOptionNode(tgt);
+ },
+
+ _onMouseOut:function(/*Event*/ evt){
+ if(evt.target === this.domNode){ return; }
+ this._blurOptionNode();
+ },
+
+ _focusOptionNode:function(/*DomNode*/ node){
+ // summary:
+ // does the actual highlight
+ if(this._highlighted_option != node){
+ this._blurOptionNode();
+ this._highlighted_option = node;
+ dojo.addClass(this._highlighted_option, "dijitMenuItemHover");
+ }
+ },
+
+ _blurOptionNode:function(){
+ // summary:
+ // removes highlight on highlighted option
+ if(this._highlighted_option){
+ dojo.removeClass(this._highlighted_option, "dijitMenuItemHover");
+ this._highlighted_option = null;
+ }
+ },
+
+ _highlightNextOption:function(){
+ // summary:
+ // Highlight the item just below the current selection.
+ // If nothing selected, highlight first option
+
+ // because each press of a button clears the menu,
+ // the highlighted option sometimes becomes detached from the menu!
+ // test to see if the option has a parent to see if this is the case.
+ var fc = this.domNode.firstChild;
+ if(!this.getHighlightedOption()){
+ this._focusOptionNode(fc.style.display=="none" ? fc.nextSibling : fc);
+ }else{
+ var ns = this._highlighted_option.nextSibling;
+ if(ns && ns.style.display!="none"){
+ this._focusOptionNode(ns);
+ }
+ }
+ // scrollIntoView is called outside of _focusOptionNode because in IE putting it inside causes the menu to scroll up on mouseover
+ dijit.scrollIntoView(this._highlighted_option);
+ },
+
+ highlightFirstOption:function(){
+ // summary:
+ // Highlight the first real item in the list (not Previous Choices).
+ this._focusOptionNode(this.domNode.firstChild.nextSibling);
+ dijit.scrollIntoView(this._highlighted_option);
+ },
+
+ highlightLastOption:function(){
+ // summary:
+ // Highlight the last real item in the list (not More Choices).
+ this._focusOptionNode(this.domNode.lastChild.previousSibling);
+ dijit.scrollIntoView(this._highlighted_option);
+ },
+
+ _highlightPrevOption:function(){
+ // summary:
+ // Highlight the item just above the current selection.
+ // If nothing selected, highlight last option (if
+ // you select Previous and try to keep scrolling up the list)
+ var lc = this.domNode.lastChild;
+ if(!this.getHighlightedOption()){
+ this._focusOptionNode(lc.style.display == "none" ? lc.previousSibling : lc);
+ }else{
+ var ps = this._highlighted_option.previousSibling;
+ if(ps && ps.style.display != "none"){
+ this._focusOptionNode(ps);
+ }
+ }
+ dijit.scrollIntoView(this._highlighted_option);
+ },
+
+ _page:function(/*Boolean*/ up){
+ var scrollamount = 0;
+ var oldscroll = this.domNode.scrollTop;
+ var height = dojo.style(this.domNode, "height");
+ // if no item is highlighted, highlight the first option
+ if(!this.getHighlightedOption()){
+ this._highlightNextOption();
+ }
+ while(scrollamount<height){
+ if(up){
+ // stop at option 1
+ if(!this.getHighlightedOption().previousSibling ||
+ this._highlighted_option.previousSibling.style.display == "none"){
+ break;
+ }
+ this._highlightPrevOption();
+ }else{
+ // stop at last option
+ if(!this.getHighlightedOption().nextSibling ||
+ this._highlighted_option.nextSibling.style.display == "none"){
+ break;
+ }
+ this._highlightNextOption();
+ }
+ // going backwards
+ var newscroll=this.domNode.scrollTop;
+ scrollamount+=(newscroll-oldscroll)*(up ? -1:1);
+ oldscroll=newscroll;
+ }
+ },
+
+ pageUp: function(){ this._page(true); },
+
+ pageDown: function(){ this._page(false); },
+
+ getHighlightedOption: function(){
+ // summary:
+ // Returns the highlighted option.
+ var ho = this._highlighted_option;
+ return (ho && ho.parentNode) ? ho : null;
+ },
+
+ handleKey: function(evt){
+ switch(evt.keyCode){
+ case dojo.keys.DOWN_ARROW:
+ this._highlightNextOption();
+ break;
+ case dojo.keys.PAGE_DOWN:
+ this.pageDown();
+ break;
+ case dojo.keys.UP_ARROW:
+ this._highlightPrevOption();
+ break;
+ case dojo.keys.PAGE_UP:
+ this.pageUp();
+ break;
+ }
+ }
+ }
+);
+
+dojo.declare(
+ "dijit.form.ComboBox",
+ [dijit.form.ValidationTextBox, dijit.form.ComboBoxMixin],
+ {
+ // summary:
+ // Auto-completing text box, and base class for dijit.form.FilteringSelect.
+ //
+ // 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.
+ //
+ // Some of the options to the ComboBox are actually arguments to the data
+ // provider.
+ //
+ // You can assume that all the form widgets (and thus anything that mixes
+ // in dijit.formComboBoxMixin) will inherit from dijit.form._FormWidget and thus the `this`
+ // reference will also "be a" _FormWidget.
+
+ postMixInProperties: function(){
+ // this.inherited(arguments); // ??
+ dijit.form.ComboBoxMixin.prototype.postMixInProperties.apply(this, arguments);
+ dijit.form.ValidationTextBox.prototype.postMixInProperties.apply(this, arguments);
+ },
+
+ postCreate: function(){
+ dijit.form.ComboBoxMixin.prototype._postCreate.apply(this, arguments);
+ dijit.form.ValidationTextBox.prototype.postCreate.apply(this, arguments);
+ },
+ setAttribute: function(/*String*/ attr, /*anything*/ value){
+ dijit.form.ValidationTextBox.prototype.setAttribute.apply(this, arguments);
+ dijit.form.ComboBoxMixin.prototype._setAttribute.apply(this, arguments);
+ }
+
+ }
+);
+
+dojo.declare("dijit.form._ComboBoxDataStore", null, {
+ // summary:
+ // Inefficient but small data store specialized for inlined ComboBox data
+ //
+ // description:
+ // Provides a store for inlined data like:
+ //
+ // | <select>
+ // | <option value="AL">Alabama</option>
+ // | ...
+ //
+ // Actually. just implements the subset of dojo.data.Read/Notification
+ // needed for ComboBox and FilteringSelect to work.
+ //
+ // Note that an item is just a pointer to the <option> DomNode.
+
+ constructor: function( /*DomNode*/ root){
+ this.root = root;
+/*
+ // TODO: this was added in #3858 but unclear why/if it's needed; doesn't seem to be.
+ // If it is needed then can we just hide the select itself instead?
+ dojo.query("> option", root).forEach(function(node){
+ node.style.display="none";
+ });
+*/
+ },
+
+ getValue: function( /* item */ item,
+ /* attribute-name-string */ attribute,
+ /* value? */ defaultValue){
+ return (attribute == "value") ? item.value : (item.innerText || item.textContent || '');
+ },
+
+ isItemLoaded: function(/* anything */ something) {
+ return true;
+ },
+
+ fetch: function(/* Object */ args){
+ // summary:
+ // Given a query and set of defined options, such as a start and count of items to return,
+ // this method executes the query and makes the results available as data items.
+ // Refer to dojo.data.api.Read.fetch() more details.
+ //
+ // description:
+ // Given a query like
+ //
+ // | {
+ // | query: {name: "Cal*"},
+ // | start: 30,
+ // | count: 20,
+ // | ignoreCase: true,
+ // | onComplete: function(/* item[] */ items, /* Object */ args){...}
+ // | }
+ //
+ // will call `onComplete()` with the results of the query (and the argument to this method)
+
+ // convert query to regex (ex: convert "first\last*" to /^first\\last.*$/i) and get matching vals
+ var query = "^" + args.query.name
+ .replace(/([\\\|\(\)\[\{\^\$\+\?\.\<\>])/g, "\\$1")
+ .replace("*", ".*") + "$",
+ matcher = new RegExp(query, args.queryOptions.ignoreCase ? "i" : ""),
+ items = dojo.query("> option", this.root).filter(function(option){
+ return (option.innerText || option.textContent || '').match(matcher);
+ } );
+
+ var start = args.start || 0,
+ end = ("count" in args && args.count != Infinity) ? (start + args.count) : items.length ;
+ args.onComplete(items.slice(start, end), args);
+ return args; // Object
+ // TODO: I don't need to return the length?
+ },
+
+ close: function(/*dojo.data.api.Request || args || null */ request){
+ return;
+ },
+
+ getLabel: function(/* item */ item){
+ return item.innerHTML;
+ },
+
+ getIdentity: function(/* item */ item){
+ return dojo.attr(item, "value");
+ },
+
+ fetchItemByIdentity: function(/* Object */ args){
+ // summary:
+ // Given the identity of an item, this method returns the item that has
+ // that identity through the onItem callback.
+ // Refer to dojo.data.api.Identity.fetchItemByIdentity() for more details.
+ //
+ // description:
+ // Given arguments like:
+ //
+ // | {identity: "CA", onItem: function(item){...}
+ //
+ // Call `onItem()` with the DOM node `<option value="CA">California</option>`
+ var item = dojo.query("option[value='" + args.identity + "']", this.root)[0];
+ args.onItem(item);
+ },
+
+ fetchSelectedItem: function(){
+ // summary:
+ // Get the option marked as selected, like `<option selected>`.
+ // Not part of dojo.data API.
+ var root = this.root,
+ si = root.selectedIndex;
+ return dojo.query("> option:nth-child(" +
+ (si != -1 ? si+1 : 1) + ")",
+ root)[0]; // dojo.data.Item
+ }
+});
+
+}
diff --git a/includes/js/dijit/form/CurrencyTextBox.js b/includes/js/dijit/form/CurrencyTextBox.js
new file mode 100644
index 0000000..c04d07e
--- /dev/null
+++ b/includes/js/dijit/form/CurrencyTextBox.js
@@ -0,0 +1,51 @@
+if(!dojo._hasResource["dijit.form.CurrencyTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.CurrencyTextBox"] = true;
+dojo.provide("dijit.form.CurrencyTextBox");
+
+//FIXME: dojo.experimental throws an unreadable exception?
+//dojo.experimental("dijit.form.CurrencyTextBox");
+
+dojo.require("dojo.currency");
+dojo.require("dijit.form.NumberTextBox");
+
+dojo.declare(
+ "dijit.form.CurrencyTextBox",
+ dijit.form.NumberTextBox,
+ {
+ // summary:
+ // A validating currency textbox
+ //
+ // constraints: dijit.form._DateTimeTextBox.__Constraints
+ //
+ // currency: String
+ // the [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD"
+ currency: "",
+
+ /*=====
+ constraints: {},
+ ======*/
+
+ regExpGen: dojo.currency.regexp,
+ _formatter: dojo.currency.format,
+/*=====
+ parse: function(value, constraints){
+ // summary: parses the value as a Currency, according to constraints
+ // value: String
+ //
+ // constraints: dojo.currency.__ParseOptions
+ },
+=====*/
+ parse: dojo.currency.parse,
+
+ postMixInProperties: function(){
+ if(this.constraints === dijit.form.ValidationTextBox.prototype.constraints){
+ // declare a constraints property on 'this' so we don't overwrite the shared default object in 'prototype'
+ this.constraints = {};
+ }
+ this.constraints.currency = this.currency;
+ dijit.form.CurrencyTextBox.superclass.postMixInProperties.apply(this, arguments);
+ }
+ }
+);
+
+}
diff --git a/includes/js/dijit/form/DateTextBox.js b/includes/js/dijit/form/DateTextBox.js
new file mode 100644
index 0000000..c3ce9d8
--- /dev/null
+++ b/includes/js/dijit/form/DateTextBox.js
@@ -0,0 +1,20 @@
+if(!dojo._hasResource["dijit.form.DateTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.DateTextBox"] = true;
+dojo.provide("dijit.form.DateTextBox");
+
+dojo.require("dijit._Calendar");
+dojo.require("dijit.form._DateTimeTextBox");
+
+dojo.declare(
+ "dijit.form.DateTextBox",
+ dijit.form._DateTimeTextBox,
+ {
+ // summary:
+ // A validating, serializable, range-bound date text box with a popup calendar
+
+ popupClass: "dijit._Calendar",
+ _selector: "date"
+ }
+);
+
+}
diff --git a/includes/js/dijit/form/FilteringSelect.js b/includes/js/dijit/form/FilteringSelect.js
new file mode 100644
index 0000000..d1e25c0
--- /dev/null
+++ b/includes/js/dijit/form/FilteringSelect.js
@@ -0,0 +1,241 @@
+if(!dojo._hasResource["dijit.form.FilteringSelect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.FilteringSelect"] = true;
+dojo.provide("dijit.form.FilteringSelect");
+
+dojo.require("dijit.form.ComboBox");
+
+dojo.declare(
+ "dijit.form.FilteringSelect",
+ [dijit.form.MappedTextBox, dijit.form.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.
+ //
+ // Similar features:
+ // - There is a drop down list of possible values.
+ // - You can only enter a value from the drop down list. (You can't
+ // enter an arbitrary value.)
+ // - The value submitted with the form is the hidden value (ex: CA),
+ // not the displayed value a.k.a. label (ex: California)
+ //
+ // Enhancements over plain HTML version:
+ // - If you type in some text then it will filter down the list of
+ // possible values in the drop down list.
+ // - List can be specified either as a static list or via a javascript
+ // function (that can get the list from a server)
+ //
+ // searchAttr: String
+ // Searches pattern match against this field
+ //
+ // labelAttr: String
+ // Optional. The text that actually appears in the drop down.
+ // If not specified, the searchAttr text is used instead.
+ labelAttr: "",
+
+ // labelType: String
+ // "html" or "text"
+ labelType: "text",
+
+ _isvalid:true,
+
+ _lastDisplayedValue: "",
+
+ isValid:function(){
+ return this._isvalid;
+ },
+
+ _callbackSetLabel: function( /*Array*/ result,
+ /*Object*/ dataObject,
+ /*Boolean?*/ priorityChange){
+ // summary:
+ // Callback function that dynamically sets the label of the
+ // ComboBox
+
+ // setValue does a synchronous lookup,
+ // so it calls _callbackSetLabel directly,
+ // and so does not pass dataObject
+ // dataObject==null means do not test the lastQuery, just continue
+ if(dataObject && dataObject.query[this.searchAttr] != this._lastQuery){
+ return;
+ }
+ if(!result.length){
+ //#3268: do nothing on bad input
+ //this._setValue("", "");
+ //#3285: change CSS to indicate error
+ if(!this._focused){ this.valueNode.value=""; }
+ dijit.form.TextBox.superclass.setValue.call(this, undefined, !this._focused);
+ this._isvalid=false;
+ this.validate(this._focused);
+ }else{
+ this._setValueFromItem(result[0], priorityChange);
+ }
+ },
+
+ _openResultList: function(/*Object*/ results, /*Object*/ dataObject){
+ // #3285: tap into search callback to see if user's query resembles a match
+ if(dataObject.query[this.searchAttr] != this._lastQuery){
+ return;
+ }
+ this._isvalid = results.length != 0; // FIXME: should this be greater-than?
+ this.validate(true);
+ dijit.form.ComboBoxMixin.prototype._openResultList.apply(this, arguments);
+ },
+
+ getValue:function(){
+ // don't get the textbox value but rather the previously set hidden value
+ return this.valueNode.value;
+ },
+
+ _getValueField:function(){
+ // used for option tag selects
+ return "value";
+ },
+
+ _setValue:function( /*String*/ value,
+ /*String*/ displayedValue,
+ /*Boolean?*/ priorityChange){
+ this.valueNode.value = value;
+ dijit.form.FilteringSelect.superclass.setValue.call(this, value, priorityChange, displayedValue);
+ this._lastDisplayedValue = displayedValue;
+ },
+
+ setValue: function(/*String*/ value, /*Boolean?*/ priorityChange){
+ // summary
+ // Sets the value of the select.
+ // Also sets the label to the corresponding value by reverse lookup.
+
+ //#3347: fetchItemByIdentity if no keyAttr specified
+ var self=this;
+ var handleFetchByIdentity = function(item, priorityChange){
+ if(item){
+ if(self.store.isItemLoaded(item)){
+ self._callbackSetLabel([item], undefined, priorityChange);
+ }else{
+ self.store.loadItem({
+ item: item,
+ onItem: function(result, dataObject){
+ self._callbackSetLabel(result, dataObject, priorityChange);
+ }
+ });
+ }
+ }else{
+ self._isvalid=false;
+ // prevent errors from Tooltip not being created yet
+ self.validate(false);
+ }
+ }
+ this.store.fetchItemByIdentity({
+ identity: value,
+ onItem: function(item){
+ handleFetchByIdentity(item, priorityChange);
+ }
+ });
+ },
+
+ _setValueFromItem: function(/*item*/ item, /*Boolean?*/ priorityChange){
+ // summary:
+ // Set the displayed valued in the input box, based on a
+ // selected item.
+ // description:
+ // Users shouldn't call this function; they should be calling
+ // setDisplayedValue() instead
+ this._isvalid=true;
+ this._setValue( this.store.getIdentity(item),
+ this.labelFunc(item, this.store),
+ priorityChange);
+ },
+
+ labelFunc: function(/*item*/ item, /*dojo.data.store*/ store){
+ // summary: Event handler called when the label changes
+ // return: the label that the ComboBox should display
+ return store.getValue(item, this.searchAttr);
+ },
+
+ _doSelect: function(/*Event*/ tgt){
+ // summary:
+ // ComboBox's menu callback function
+ // description:
+ // FilteringSelect overrides this to set both the visible and
+ // hidden value from the information stored in the menu
+ this.item = tgt.item;
+ this._setValueFromItem(tgt.item, true);
+ },
+
+ setDisplayedValue:function(/*String*/ label, /*Boolean?*/ priorityChange){
+ // summary:
+ // Set textbox to display label. Also performs reverse lookup
+ // to set the hidden value. Used in InlineEditBox
+
+ if(this.store){
+ var query = dojo.clone(this.query); // #6196: populate query with user-specifics
+ this._lastQuery = query[this.searchAttr] = label;
+ // if the label is not valid, the callback will never set it,
+ // so the last valid value will get the warning textbox set the
+ // textbox value now so that the impending warning will make
+ // sense to the user
+ this.textbox.value = label;
+ this._lastDisplayedValue = label;
+ var _this = this;
+ this.store.fetch({
+ query: query,
+ queryOptions: {
+ ignoreCase: this.ignoreCase,
+ deep: true
+ },
+ onComplete: function(result, dataObject){
+ dojo.hitch(_this, "_callbackSetLabel")(result, dataObject, priorityChange);
+ },
+ onError: function(errText){
+ console.error('dijit.form.FilteringSelect: ' + errText);
+ dojo.hitch(_this, "_setValue")(undefined, label, false);
+ }
+ });
+ }
+ },
+
+ _getMenuLabelFromItem:function(/*Item*/ item){
+ // internal function to help ComboBoxMenu figure out what to display
+ if(this.labelAttr){
+ return {
+ html: this.labelType=="html",
+ label: this.store.getValue(item, this.labelAttr)
+ };
+ }else{
+ // because this function is called by ComboBoxMenu,
+ // this.inherited tries to find the superclass of ComboBoxMenu
+ return dijit.form.ComboBoxMixin.prototype._getMenuLabelFromItem.apply(this, arguments);
+ }
+ },
+
+ postMixInProperties: function(){
+ // FIXME: shouldn't this just be a call to inherited?
+ dijit.form.ComboBoxMixin.prototype.postMixInProperties.apply(this, arguments);
+ dijit.form.MappedTextBox.prototype.postMixInProperties.apply(this, arguments);
+ },
+
+ postCreate: function(){
+ dijit.form.ComboBoxMixin.prototype._postCreate.apply(this, arguments);
+ dijit.form.MappedTextBox.prototype.postCreate.apply(this, arguments);
+ },
+
+ setAttribute: function(/*String*/ attr, /*anything*/ value){
+ dijit.form.MappedTextBox.prototype.setAttribute.apply(this, arguments);
+ dijit.form.ComboBoxMixin.prototype._setAttribute.apply(this, arguments);
+ },
+
+ undo: function(){
+ this.setDisplayedValue(this._lastDisplayedValue);
+ },
+
+ _valueChanged: function(){
+ return this.getDisplayedValue()!=this._lastDisplayedValue;
+ }
+ }
+);
+
+}
diff --git a/includes/js/dijit/form/Form.js b/includes/js/dijit/form/Form.js
new file mode 100644
index 0000000..4ad29f9
--- /dev/null
+++ b/includes/js/dijit/form/Form.js
@@ -0,0 +1,384 @@
+if(!dojo._hasResource["dijit.form.Form"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.Form"] = true;
+dojo.provide("dijit.form.Form");
+
+dojo.require("dijit._Widget");
+dojo.require("dijit._Templated");
+
+dojo.declare("dijit.form._FormMixin", null,
+ {
+ //
+ // summary:
+ // Widget corresponding to HTML form tag, for validation and serialization
+ //
+ // example:
+ // | <form dojoType="dijit.form.Form" id="myForm">
+ // | Name: <input type="text" name="name" />
+ // | </form>
+ // | myObj = {name: "John Doe"};
+ // | dijit.byId('myForm').setValues(myObj);
+ // |
+ // | myObj=dijit.byId('myForm').getValues();
+
+ // TODO:
+ // * Repeater
+ // * better handling for arrays. Often form elements have names with [] like
+ // * people[3].sex (for a list of people [{name: Bill, sex: M}, ...])
+ //
+ //
+
+ reset: function(){
+ dojo.forEach(this.getDescendants(), function(widget){
+ if(widget.reset){
+ widget.reset();
+ }
+ });
+ },
+
+ validate: function(){
+ // summary: returns if the form is valid - same as isValid - but
+ // provides a few additional (ui-specific) features.
+ // 1 - it will highlight any sub-widgets that are not
+ // valid
+ // 2 - it will call focus() on the first invalid
+ // sub-widget
+ var didFocus = false;
+ return dojo.every(dojo.map(this.getDescendants(), function(widget){
+ // Need to set this so that "required" widgets get their
+ // state set.
+ widget._hasBeenBlurred = true;
+ var valid = !widget.validate || widget.validate();
+ if (!valid && !didFocus) {
+ // Set focus of the first non-valid widget
+ dijit.scrollIntoView(widget.containerNode||widget.domNode);
+ widget.focus();
+ didFocus = true;
+ }
+ return valid;
+ }), "return item;");
+ },
+
+ setValues: function(/*object*/obj){
+ // summary: fill in form values from a JSON structure
+
+ // generate map from name --> [list of widgets with that name]
+ var map = { };
+ dojo.forEach(this.getDescendants(), function(widget){
+ if(!widget.name){ return; }
+ var entry = map[widget.name] || (map[widget.name] = [] );
+ entry.push(widget);
+ });
+
+ // call setValue() or setAttribute('checked') for each widget, according to obj
+ for(var name in map){
+ var widgets = map[name], // array of widgets w/this name
+ values = dojo.getObject(name, false, obj); // list of values for those widgets
+ if(!dojo.isArray(values)){
+ values = [ values ];
+ }
+ if(typeof widgets[0].checked == 'boolean'){
+ // for checkbox/radio, values is a list of which widgets should be checked
+ dojo.forEach(widgets, function(w, i){
+ w.setValue(dojo.indexOf(values, w.value) != -1);
+ });
+ }else if(widgets[0]._multiValue){
+ // it takes an array (e.g. multi-select)
+ widgets[0].setValue(values);
+ }else{
+ // otherwise, values is a list of values to be assigned sequentially to each widget
+ dojo.forEach(widgets, function(w, i){
+ w.setValue(values[i]);
+ });
+ }
+ }
+
+ /***
+ * TODO: code for plain input boxes (this shouldn't run for inputs that are part of widgets)
+
+ dojo.forEach(this.containerNode.elements, function(element){
+ if (element.name == ''){return}; // like "continue"
+ var namePath = element.name.split(".");
+ var myObj=obj;
+ var name=namePath[namePath.length-1];
+ for(var j=1,len2=namePath.length;j<len2;++j){
+ var p=namePath[j - 1];
+ // repeater support block
+ var nameA=p.split("[");
+ if (nameA.length > 1){
+ if(typeof(myObj[nameA[0]]) == "undefined"){
+ myObj[nameA[0]]=[ ];
+ } // if
+
+ nameIndex=parseInt(nameA[1]);
+ if(typeof(myObj[nameA[0]][nameIndex]) == "undefined"){
+ myObj[nameA[0]][nameIndex] = { };
+ }
+ myObj=myObj[nameA[0]][nameIndex];
+ continue;
+ } // repeater support ends
+
+ if(typeof(myObj[p]) == "undefined"){
+ myObj=undefined;
+ break;
+ };
+ myObj=myObj[p];
+ }
+
+ if (typeof(myObj) == "undefined"){
+ return; // like "continue"
+ }
+ if (typeof(myObj[name]) == "undefined" && this.ignoreNullValues){
+ return; // like "continue"
+ }
+
+ // TODO: widget values (just call setValue() on the widget)
+
+ switch(element.type){
+ case "checkbox":
+ element.checked = (name in myObj) &&
+ dojo.some(myObj[name], function(val){ return val==element.value; });
+ break;
+ case "radio":
+ element.checked = (name in myObj) && myObj[name]==element.value;
+ break;
+ case "select-multiple":
+ element.selectedIndex=-1;
+ dojo.forEach(element.options, function(option){
+ option.selected = dojo.some(myObj[name], function(val){ return option.value == val; });
+ });
+ break;
+ case "select-one":
+ element.selectedIndex="0";
+ dojo.forEach(element.options, function(option){
+ option.selected = option.value == myObj[name];
+ });
+ break;
+ case "hidden":
+ case "text":
+ case "textarea":
+ case "password":
+ element.value = myObj[name] || "";
+ break;
+ }
+ });
+ */
+ },
+
+ getValues: function(){
+ // summary: generate JSON structure from form values
+
+ // get widget values
+ var obj = { };
+ dojo.forEach(this.getDescendants(), function(widget){
+ var name = widget.name;
+ if(!name){ return; }
+
+ // Single value widget (checkbox, radio, or plain <input> type widget
+ var value = (widget.getValue && !widget._getValueDeprecated) ? widget.getValue() : widget.value;
+
+ // Store widget's value(s) as a scalar, except for checkboxes which are automatically arrays
+ if(typeof widget.checked == 'boolean'){
+ if(/Radio/.test(widget.declaredClass)){
+ // radio button
+ if(value !== false){
+ dojo.setObject(name, value, obj);
+ }
+ }else{
+ // checkbox/toggle button
+ var ary=dojo.getObject(name, false, obj);
+ if(!ary){
+ ary=[];
+ dojo.setObject(name, ary, obj);
+ }
+ if(value !== false){
+ ary.push(value);
+ }
+ }
+ }else{
+ // plain input
+ dojo.setObject(name, value, obj);
+ }
+ });
+
+ /***
+ * code for plain input boxes (see also dojo.formToObject, can we use that instead of this code?
+ * but it doesn't understand [] notation, presumably)
+ var obj = { };
+ dojo.forEach(this.containerNode.elements, function(elm){
+ if (!elm.name) {
+ return; // like "continue"
+ }
+ var namePath = elm.name.split(".");
+ var myObj=obj;
+ var name=namePath[namePath.length-1];
+ for(var j=1,len2=namePath.length;j<len2;++j){
+ var nameIndex = null;
+ var p=namePath[j - 1];
+ var nameA=p.split("[");
+ if (nameA.length > 1){
+ if(typeof(myObj[nameA[0]]) == "undefined"){
+ myObj[nameA[0]]=[ ];
+ } // if
+ nameIndex=parseInt(nameA[1]);
+ if(typeof(myObj[nameA[0]][nameIndex]) == "undefined"){
+ myObj[nameA[0]][nameIndex] = { };
+ }
+ } else if(typeof(myObj[nameA[0]]) == "undefined"){
+ myObj[nameA[0]] = { }
+ } // if
+
+ if (nameA.length == 1){
+ myObj=myObj[nameA[0]];
+ } else{
+ myObj=myObj[nameA[0]][nameIndex];
+ } // if
+ } // for
+
+ if ((elm.type != "select-multiple" && elm.type != "checkbox" && elm.type != "radio") || (elm.type=="radio" && elm.checked)){
+ if(name == name.split("[")[0]){
+ myObj[name]=elm.value;
+ } else{
+ // can not set value when there is no name
+ }
+ } else if (elm.type == "checkbox" && elm.checked){
+ if(typeof(myObj[name]) == 'undefined'){
+ myObj[name]=[ ];
+ }
+ myObj[name].push(elm.value);
+ } else if (elm.type == "select-multiple"){
+ if(typeof(myObj[name]) == 'undefined'){
+ myObj[name]=[ ];
+ }
+ for (var jdx=0,len3=elm.options.length; jdx<len3; ++jdx){
+ if (elm.options[jdx].selected){
+ myObj[name].push(elm.options[jdx].value);
+ }
+ }
+ } // if
+ name=undefined;
+ }); // forEach
+ ***/
+ return obj;
+ },
+
+ // TODO: ComboBox might need time to process a recently input value. This should be async?
+ isValid: function(){
+ // summary: make sure that every widget that has a validator function returns true
+ return dojo.every(this.getDescendants(), function(widget){
+ return !widget.isValid || widget.isValid();
+ });
+ }
+ });
+
+dojo.declare(
+ "dijit.form.Form",
+ [dijit._Widget, dijit._Templated, dijit.form._FormMixin],
+ {
+ // summary:
+ // Adds conveniences to regular HTML form
+
+ // HTML <FORM> attributes
+ name: "",
+ action: "",
+ method: "",
+ encType: "",
+ "accept-charset": "",
+ accept: "",
+ target: "",
+
+ templateString: "<form dojoAttachPoint='containerNode' dojoAttachEvent='onreset:_onReset,onsubmit:_onSubmit' name='${name}'></form>",
+
+ attributeMap: dojo.mixin(dojo.clone(dijit._Widget.prototype.attributeMap),
+ {action: "", method: "", encType: "", "accept-charset": "", accept: "", target: ""}),
+
+ execute: function(/*Object*/ formContents){
+ // summary:
+ // Deprecated: use submit()
+ },
+
+ onExecute: function(){
+ // summary:
+ // Deprecated: use onSubmit()
+ },
+
+ setAttribute: function(/*String*/ attr, /*anything*/ value){
+ this.inherited(arguments);
+ switch(attr){
+ case "encType":
+ if(dojo.isIE){ this.domNode.encoding = value; }
+ }
+ },
+
+ postCreate: function(){
+ // IE tries to hide encType
+ if(dojo.isIE && this.srcNodeRef && this.srcNodeRef.attributes){
+ var item = this.srcNodeRef.attributes.getNamedItem('encType');
+ if(item && !item.specified && (typeof item.value == "string")){
+ this.setAttribute('encType', item.value);
+ }
+ }
+ this.inherited(arguments);
+ },
+
+ onReset: function(/*Event?*/e){
+ // summary:
+ // Callback when user resets the form. This method is intended
+ // to be over-ridden. When the `reset` method is called
+ // programmatically, the return value from `onReset` is used
+ // to compute whether or not resetting should proceed
+ return true; // Boolean
+ },
+
+ _onReset: function(e){
+ // create fake event so we can know if preventDefault() is called
+ var faux = {
+ returnValue: true, // the IE way
+ preventDefault: function(){ // not IE
+ this.returnValue = false;
+ },
+ stopPropagation: function(){}, currentTarget: e.currentTarget, target: e.target
+ };
+ // if return value is not exactly false, and haven't called preventDefault(), then reset
+ if(!(this.onReset(faux) === false) && faux.returnValue){
+ this.reset();
+ }
+ dojo.stopEvent(e);
+ return false;
+ },
+
+ _onSubmit: function(e){
+ var fp = dijit.form.Form.prototype;
+ // TODO: remove ths if statement beginning with 2.0
+ if(this.execute != fp.execute || this.onExecute != fp.onExecute){
+ dojo.deprecated("dijit.form.Form:execute()/onExecute() are deprecated. Use onSubmit() instead.", "", "2.0");
+ this.onExecute();
+ this.execute(this.getValues());
+ }
+ if(this.onSubmit(e) === false){ // only exactly false stops submit
+ dojo.stopEvent(e);
+ }
+ },
+
+ onSubmit: function(/*Event?*/e){
+ // summary:
+ // Callback when user submits the form. This method is
+ // intended to be over-ridden, but by default it checks and
+ // returns the validity of form elements. When the `submit`
+ // method is called programmatically, the return value from
+ // `onSubmit` is used to compute whether or not submission
+ // should proceed
+
+ return this.isValid(); // Boolean
+ },
+
+ submit: function(){
+ // summary:
+ // programmatically submit form if and only if the `onSubmit` returns true
+ if(!(this.onSubmit() === false)){
+ this.containerNode.submit();
+ }
+ }
+ }
+);
+
+}
diff --git a/includes/js/dijit/form/MultiSelect.js b/includes/js/dijit/form/MultiSelect.js
new file mode 100644
index 0000000..e1f468c
--- /dev/null
+++ b/includes/js/dijit/form/MultiSelect.js
@@ -0,0 +1,84 @@
+if(!dojo._hasResource["dijit.form.MultiSelect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.MultiSelect"] = true;
+dojo.provide("dijit.form.MultiSelect");
+
+dojo.require("dijit.form._FormWidget");
+
+dojo.declare("dijit.form.MultiSelect",dijit.form._FormWidget,{
+ // summary: Wrapper for a native select multiple="true" element to
+ // interact with dijit.form.Form
+
+ // size: Number
+ // Number of elements to display on a page
+ // NOTE: may be removed in version 2.0, since elements may have variable height;
+ // set the size via style="..." or CSS class names instead.
+ size: 7,
+
+ templateString: "<select multiple='true' dojoAttachPoint='containerNode,focusNode' dojoAttachEvent='onchange: _onChange'></select>",
+
+ attributeMap: dojo.mixin(dojo.clone(dijit.form._FormWidget.prototype.attributeMap),
+ {size:"focusNode"}),
+
+ addSelected: function(/* dijit.form.MultiSelect */select){
+ // summary: Move the selected nodes af an passed Select widget
+ // instance to this Select widget.
+ //
+ // example:
+ // | // move all the selected values from "bar" to "foo"
+ // | dijit.byId("foo").addSelected(dijit.byId("bar"));
+
+ select.getSelected().forEach(function(n){
+ this.containerNode.appendChild(n);
+ },this);
+ },
+
+ getSelected: function(){
+ // summary: Access the NodeList of the selected options directly
+ return dojo.query("option",this.containerNode).filter(function(n){
+ return n.selected; // Boolean
+ });
+ },
+
+ _getValueDeprecated: false, // remove when _FormWidget:_getValueDeprecated is removed in 2.0
+ getValue: function(){
+ // summary: Returns an array of the selected options' values
+ return this.getSelected().map(function(n){
+ return n.value;
+ });
+ },
+
+ _multiValue: true, // for Form
+ setValue: function(/* Array */values){
+ // summary: Set the value(s) of this Select based on passed values
+ dojo.query("option",this.containerNode).forEach(function(n){
+ n.selected = (dojo.indexOf(values,n.value) != -1);
+ });
+ },
+
+ invertSelection: function(onChange){
+ // summary: Invert the selection
+ // onChange: Boolean
+ // If null, onChange is not fired.
+ dojo.query("option",this.containerNode).forEach(function(n){
+ n.selected = !n.selected;
+ });
+ this._handleOnChange(this.getValue(), onChange==true);
+ },
+
+ _onChange: function(/*Event*/ e){
+ this._handleOnChange(this.getValue(), true);
+ },
+
+ // for layout widgets:
+ resize: function(/* Object */size){
+ if(size){
+ dojo.marginBox(this.domNode, size);
+ }
+ },
+
+ postCreate: function(){
+ this._onChange();
+ }
+});
+
+}
diff --git a/includes/js/dijit/form/NumberSpinner.js b/includes/js/dijit/form/NumberSpinner.js
new file mode 100644
index 0000000..a9054b0
--- /dev/null
+++ b/includes/js/dijit/form/NumberSpinner.js
@@ -0,0 +1,31 @@
+if(!dojo._hasResource["dijit.form.NumberSpinner"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.NumberSpinner"] = true;
+dojo.provide("dijit.form.NumberSpinner");
+
+dojo.require("dijit.form._Spinner");
+dojo.require("dijit.form.NumberTextBox");
+
+dojo.declare(
+"dijit.form.NumberSpinner",
+[dijit.form._Spinner, dijit.form.NumberTextBoxMixin],
+{
+ // summary:
+ // extends NumberTextBox to add up/down arrows for incremental change to the value
+
+ required: true,
+
+ adjust: function(/* Object */ val, /*Number*/ delta){
+ // summary: change Number val by the given amount
+ var newval = val+delta;
+ if(isNaN(val) || isNaN(newval)){ return val; }
+ if((typeof this.constraints.max == "number") && (newval > this.constraints.max)){
+ newval = this.constraints.max;
+ }
+ if((typeof this.constraints.min == "number") && (newval < this.constraints.min)){
+ newval = this.constraints.min;
+ }
+ return newval;
+ }
+});
+
+}
diff --git a/includes/js/dijit/form/NumberTextBox.js b/includes/js/dijit/form/NumberTextBox.js
new file mode 100644
index 0000000..f8344a9
--- /dev/null
+++ b/includes/js/dijit/form/NumberTextBox.js
@@ -0,0 +1,79 @@
+if(!dojo._hasResource["dijit.form.NumberTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.NumberTextBox"] = true;
+dojo.provide("dijit.form.NumberTextBox");
+
+dojo.require("dijit.form.ValidationTextBox");
+dojo.require("dojo.number");
+
+/*=====
+dojo.declare(
+ "dijit.form.NumberTextBox.__Constraints",
+ [dijit.form.RangeBoundTextBox.__Constraints, dojo.number.__FormatOptions, dojo.number.__ParseOptions]
+);
+=====*/
+
+dojo.declare(
+ "dijit.form.NumberTextBoxMixin",
+ null,
+ {
+ // summary:
+ // A mixin for all number textboxes
+
+ regExpGen: dojo.number.regexp,
+
+ /*=====
+ // constraints: dijit.form.NumberTextBox.__Constraints
+ constraints: {},
+ ======*/
+
+ // editOptions: Object
+ // properties to mix into constraints when the value is being edited
+ editOptions: { pattern: '#.######' },
+
+ _onFocus: function(){
+ this.setValue(this.getValue(), false);
+ this.inherited(arguments);
+ },
+
+ _formatter: dojo.number.format,
+
+ format: function(/*Number*/ value, /*dojo.number.__FormatOptions*/ constraints){
+ // summary: formats the value as a Number, according to constraints
+
+ if(typeof value == "string") { return value; }
+ if(isNaN(value)){ return ""; }
+ if(this.editOptions && this._focused){
+ constraints = dojo.mixin(dojo.mixin({}, this.editOptions), this.constraints);
+ }
+ return this._formatter(value, constraints);
+ },
+
+ parse: dojo.number.parse,
+ /*=====
+ parse: function(value, constraints){
+ // summary: parses the value as a Number, according to constraints
+ // value: String
+ //
+ // constraints: dojo.number.__ParseOptions
+ },
+ =====*/
+
+ filter: function(/*Number*/ value){
+ if(typeof value == "string"){ return this.inherited('filter', arguments); }
+ return isNaN(value) ? '' : value;
+ },
+
+ value: NaN
+ }
+);
+
+dojo.declare(
+ "dijit.form.NumberTextBox",
+ [dijit.form.RangeBoundTextBox,dijit.form.NumberTextBoxMixin],
+ {
+ // summary:
+ // A validating, serializable, range-bound text box.
+ }
+);
+
+}
diff --git a/includes/js/dijit/form/SimpleTextarea.js b/includes/js/dijit/form/SimpleTextarea.js
new file mode 100644
index 0000000..54db151
--- /dev/null
+++ b/includes/js/dijit/form/SimpleTextarea.js
@@ -0,0 +1,50 @@
+if(!dojo._hasResource["dijit.form.SimpleTextarea"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.SimpleTextarea"] = true;
+dojo.provide("dijit.form.SimpleTextarea");
+
+dojo.require("dijit.form._FormWidget");
+
+dojo.declare("dijit.form.SimpleTextarea",
+ dijit.form._FormValueWidget,
+{
+ // summary:
+ // A simple textarea that degrades, and responds to
+ // minimal LayoutContainer usage, and works with dijit.form.Form.
+ // Doesn't automatically size according to input, like Textarea.
+ //
+ // example:
+ // | <textarea dojoType="dijit.form.SimpleTextarea" name="foo" value="bar" rows=30 cols=40/>
+ //
+
+ baseClass: "dijitTextArea",
+
+ attributeMap: dojo.mixin(dojo.clone(dijit.form._FormValueWidget.prototype.attributeMap),
+ {rows:"focusNode", cols: "focusNode"}),
+
+ // rows: Number
+ // The number of rows of text.
+ rows: "",
+
+ // rows: Number
+ // The number of characters per line.
+ cols: "",
+
+ templateString: "<textarea name='${name}' dojoAttachPoint='focusNode,containerNode'>",
+
+ postMixInProperties: function(){
+ if(this.srcNodeRef){
+ this.value = this.srcNodeRef.value;
+ }
+ },
+
+ setValue: function(/*String*/ val){
+ this.domNode.value = val;
+ this.inherited(arguments);
+ },
+
+ getValue: function(){
+ return this.domNode.value.replace(/\r/g,"");
+ }
+});
+
+}
diff --git a/includes/js/dijit/form/Slider.js b/includes/js/dijit/form/Slider.js
new file mode 100644
index 0000000..2290376
--- /dev/null
+++ b/includes/js/dijit/form/Slider.js
@@ -0,0 +1,481 @@
+if(!dojo._hasResource["dijit.form.Slider"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.Slider"] = true;
+dojo.provide("dijit.form.Slider");
+
+dojo.require("dijit.form._FormWidget");
+dojo.require("dijit._Container");
+dojo.require("dojo.dnd.move");
+dojo.require("dijit.form.Button");
+dojo.require("dojo.number");
+dojo.require("dojo._base.fx");
+
+dojo.declare(
+ "dijit.form.HorizontalSlider",
+ [dijit.form._FormValueWidget, dijit._Container],
+{
+ // summary
+ // A form widget that allows one to select a value with a horizontally draggable image
+
+ templateString:"<table class=\"dijit dijitReset dijitSlider\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" rules=\"none\"\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t\t><td dojoAttachPoint=\"containerNode,topDecoration\" class=\"dijitReset\" style=\"text-align:center;width:100%;\"></td\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitSliderButtonContainerH\"\n\t\t\t><div class=\"dijitSliderDecrementIconH\" tabIndex=\"-1\" style=\"display:none\" dojoAttachPoint=\"decrementButton\" dojoAttachEvent=\"onclick: decrement\"><span class=\"dijitSliderButtonInner\">-</span></div\n\t\t></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><div class=\"dijitSliderBar dijitSliderBumper dijitSliderBumperH dijitSliderLeftBumper dijitSliderLeftBumper\" dojoAttachEvent=\"onclick:_onClkDecBumper\"></div\n\t\t></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><input dojoAttachPoint=\"valueNode\" type=\"hidden\" name=\"${name}\"\n\t\t\t/><div waiRole=\"presentation\" style=\"position:relative;\" dojoAttachPoint=\"sliderBarContainer\"\n\t\t\t\t><div waiRole=\"presentation\" dojoAttachPoint=\"progressBar\" class=\"dijitSliderBar dijitSliderBarH dijitSliderProgressBar dijitSliderProgressBarH\" dojoAttachEvent=\"onclick:_onBarClick\"\n\t\t\t\t\t><div dojoAttachPoint=\"sliderHandle,focusNode\" class=\"dijitSliderMoveable dijitSliderMoveableH\" dojoAttachEvent=\"onkeypress:_onKeyPress,onmousedown:_onHandleClick\" waiRole=\"slider\" valuemin=\"${minimum}\" valuemax=\"${maximum}\"\n\t\t\t\t\t\t><div class=\"dijitSliderImageHandle dijitSliderImageHandleH\"></div\n\t\t\t\t\t></div\n\t\t\t\t></div\n\t\t\t\t><div waiRole=\"presentation\" dojoAttachPoint=\"remainingBar\" class=\"dijitSliderBar dijitSliderBarH dijitSliderRemainingBar dijitSliderRemainingBarH\" dojoAttachEvent=\"onclick:_onBarClick\"></div\n\t\t\t></div\n\t\t></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><div class=\"dijitSliderBar dijitSliderBumper dijitSliderBumperH dijitSliderRightBumper dijitSliderRightBumper\" dojoAttachEvent=\"onclick:_onClkIncBumper\"></div\n\t\t></td\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitSliderButtonContainerH\" style=\"right:0px;\"\n\t\t\t><div class=\"dijitSliderIncrementIconH\" tabIndex=\"-1\" style=\"display:none\" dojoAttachPoint=\"incrementButton\" dojoAttachEvent=\"onclick: increment\"><span class=\"dijitSliderButtonInner\">+</span></div\n\t\t></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t\t><td dojoAttachPoint=\"containerNode,bottomDecoration\" class=\"dijitReset\" style=\"text-align:center;\"></td\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t></tr\n></table>\n",
+ value: 0,
+
+ // showButtons: boolean
+ // Show increment/decrement buttons at the ends of the slider?
+ showButtons: true,
+
+ // minimum:: integer
+ // The minimum value allowed.
+ minimum: 0,
+
+ // maximum: integer
+ // The maximum allowed value.
+ maximum: 100,
+
+ // discreteValues: integer
+ // The maximum allowed values dispersed evenly between minimum and maximum (inclusive).
+ discreteValues: Infinity,
+
+ // pageIncrement: integer
+ // The amount of change with shift+arrow
+ pageIncrement: 2,
+
+ // clickSelect: boolean
+ // If clicking the progress bar changes the value or not
+ clickSelect: true,
+
+ // slideDuration: Number
+ // The time in ms to take to animate the slider handle from 0% to 100%
+ slideDuration: 1000,
+
+ widgetsInTemplate: true,
+
+ attributeMap: dojo.mixin(dojo.clone(dijit.form._FormWidget.prototype.attributeMap),
+ {id:"", name:"valueNode"}),
+
+ baseClass: "dijitSlider",
+
+ _mousePixelCoord: "pageX",
+ _pixelCount: "w",
+ _startingPixelCoord: "x",
+ _startingPixelCount: "l",
+ _handleOffsetCoord: "left",
+ _progressPixelSize: "width",
+
+ _onKeyPress: function(/*Event*/ e){
+ if(this.disabled || this.readOnly || e.altKey || e.ctrlKey){ return; }
+ switch(e.keyCode){
+ case dojo.keys.HOME:
+ this.setValue(this.minimum, true);
+ break;
+ case dojo.keys.END:
+ this.setValue(this.maximum, true);
+ break;
+ // this._descending === false: if ascending vertical (min on top)
+ // (this._descending || this.isLeftToRight()): if left-to-right horizontal or descending vertical
+ case ((this._descending || this.isLeftToRight()) ? dojo.keys.RIGHT_ARROW : dojo.keys.LEFT_ARROW):
+ case (this._descending === false ? dojo.keys.DOWN_ARROW : dojo.keys.UP_ARROW):
+ case (this._descending === false ? dojo.keys.PAGE_DOWN : dojo.keys.PAGE_UP):
+ this.increment(e);
+ break;
+ case ((this._descending || this.isLeftToRight()) ? dojo.keys.LEFT_ARROW : dojo.keys.RIGHT_ARROW):
+ case (this._descending === false ? dojo.keys.UP_ARROW : dojo.keys.DOWN_ARROW):
+ case (this._descending === false ? dojo.keys.PAGE_UP : dojo.keys.PAGE_DOWN):
+ this.decrement(e);
+ break;
+ default:
+ this.inherited(arguments);
+ return;
+ }
+ dojo.stopEvent(e);
+ },
+
+ _onHandleClick: function(e){
+ if(this.disabled || this.readOnly){ return; }
+ if(!dojo.isIE){
+ // make sure you get focus when dragging the handle
+ // (but don't do on IE because it causes a flicker on mouse up (due to blur then focus)
+ dijit.focus(this.sliderHandle);
+ }
+ dojo.stopEvent(e);
+ },
+
+ _isReversed: function(){
+ return !this.isLeftToRight();
+ },
+
+ _onBarClick: function(e){
+ if(this.disabled || this.readOnly || !this.clickSelect){ return; }
+ dijit.focus(this.sliderHandle);
+ dojo.stopEvent(e);
+ var abspos = dojo.coords(this.sliderBarContainer, true);
+ var pixelValue = e[this._mousePixelCoord] - abspos[this._startingPixelCoord];
+ this._setPixelValue(this._isReversed() ? (abspos[this._pixelCount] - pixelValue) : pixelValue, abspos[this._pixelCount], true);
+ },
+
+ _setPixelValue: function(/*Number*/ pixelValue, /*Number*/ maxPixels, /*Boolean, optional*/ priorityChange){
+ if(this.disabled || this.readOnly){ return; }
+ pixelValue = pixelValue < 0 ? 0 : maxPixels < pixelValue ? maxPixels : pixelValue;
+ var count = this.discreteValues;
+ if(count <= 1 || count == Infinity){ count = maxPixels; }
+ count--;
+ var pixelsPerValue = maxPixels / count;
+ var wholeIncrements = Math.round(pixelValue / pixelsPerValue);
+ this.setValue((this.maximum-this.minimum)*wholeIncrements/count + this.minimum, priorityChange);
+ },
+
+ setValue: function(/*Number*/ value, /*Boolean, optional*/ priorityChange){
+ this.valueNode.value = this.value = value;
+ dijit.setWaiState(this.focusNode, "valuenow", value);
+ this.inherited(arguments);
+ var percent = (value - this.minimum) / (this.maximum - this.minimum);
+ var progressBar = (this._descending === false) ? this.remainingBar : this.progressBar;
+ var remainingBar = (this._descending === false) ? this.progressBar : this.remainingBar;
+ if(priorityChange && this.slideDuration > 0 && progressBar.style[this._progressPixelSize]){
+ // animate the slider
+ var _this = this;
+ var props = {};
+ var start = parseFloat(progressBar.style[this._progressPixelSize]);
+ var duration = this.slideDuration * (percent-start/100);
+ if(duration == 0){ return; }
+ if(duration < 0){ duration = 0 - duration; }
+ props[this._progressPixelSize] = { start: start, end: percent*100, units:"%" };
+ dojo.animateProperty({ node: progressBar, duration: duration,
+ onAnimate: function(v){ remainingBar.style[_this._progressPixelSize] = (100-parseFloat(v[_this._progressPixelSize])) + "%"; },
+ properties: props
+ }).play();
+ }
+ else{
+ progressBar.style[this._progressPixelSize] = (percent*100) + "%";
+ remainingBar.style[this._progressPixelSize] = ((1-percent)*100) + "%";
+ }
+ },
+
+ _bumpValue: function(signedChange){
+ if(this.disabled || this.readOnly){ return; }
+ var s = dojo.getComputedStyle(this.sliderBarContainer);
+ var c = dojo._getContentBox(this.sliderBarContainer, s);
+ var count = this.discreteValues;
+ if(count <= 1 || count == Infinity){ count = c[this._pixelCount]; }
+ count--;
+ var value = (this.value - this.minimum) * count / (this.maximum - this.minimum) + signedChange;
+ if(value < 0){ value = 0; }
+ if(value > count){ value = count; }
+ value = value * (this.maximum - this.minimum) / count + this.minimum;
+ this.setValue(value, true);
+ },
+
+ _onClkIncBumper: function(){
+ this.setValue(this._descending === false ? this.minimum : this.maximum, true);
+ },
+
+ _onClkDecBumper: function(){
+ this.setValue(this._descending === false ? this.maximum : this.minimum, true);
+ },
+
+ decrement: function(e){
+ // summary
+ // decrement slider by 1 unit
+ this._bumpValue(e.keyCode == dojo.keys.PAGE_DOWN?-this.pageIncrement:-1);
+ },
+
+ increment: function(e){
+ // summary
+ // increment slider by 1 unit
+ this._bumpValue(e.keyCode == dojo.keys.PAGE_UP?this.pageIncrement:1);
+ },
+
+ _mouseWheeled: function(/*Event*/ evt){
+ dojo.stopEvent(evt);
+ var scrollAmount = 0;
+ if(typeof evt.wheelDelta == 'number'){ // IE
+ scrollAmount = evt.wheelDelta;
+ }else if(typeof evt.detail == 'number'){ // Mozilla+Firefox
+ scrollAmount = -evt.detail;
+ }
+ if(scrollAmount > 0){
+ this.increment(evt);
+ }else if(scrollAmount < 0){
+ this.decrement(evt);
+ }
+ },
+
+ startup: function(){
+ dojo.forEach(this.getChildren(), function(child){
+ if(this[child.container] != this.containerNode){
+ this[child.container].appendChild(child.domNode);
+ }
+ }, this);
+ },
+
+ postCreate: function(){
+ if(this.showButtons){
+ this.incrementButton.style.display="";
+ this.decrementButton.style.display="";
+ }
+ this.connect(this.domNode, dojo.isIE ? "onmousewheel" : 'DOMMouseScroll', "_mouseWheeled");
+
+ // define a custom constructor for a SliderMover that points back to me
+ var _self = this;
+ var mover = function(){
+ dijit.form._SliderMover.apply(this, arguments);
+ this.widget = _self;
+ };
+ dojo.extend(mover, dijit.form._SliderMover.prototype);
+
+ this._movable = new dojo.dnd.Moveable(this.sliderHandle, {mover: mover});
+ dijit.setWaiState(this.focusNode, "valuemin", this.minimum);
+ dijit.setWaiState(this.focusNode, "valuemax", this.maximum);
+
+ this.inherited(arguments);
+ },
+
+ destroy: function(){
+ this._movable.destroy();
+ this.inherited(arguments);
+ }
+});
+
+dojo.declare(
+ "dijit.form.VerticalSlider",
+ dijit.form.HorizontalSlider,
+{
+ // summary
+ // A form widget that allows one to select a value with a vertically draggable image
+
+ templateString:"<table class=\"dijitReset dijitSlider\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" rules=\"none\"\n><tbody class=\"dijitReset\"\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\"></td\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitSliderButtonContainerV\"\n\t\t\t><div class=\"dijitSliderIncrementIconV\" tabIndex=\"-1\" style=\"display:none\" dojoAttachPoint=\"incrementButton\" dojoAttachEvent=\"onclick:_topButtonClicked\"><span class=\"dijitSliderButtonInner\">+</span></div\n\t\t></td\n\t\t><td class=\"dijitReset\"></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\"></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><center><div class=\"dijitSliderBar dijitSliderBumper dijitSliderBumperV dijitSliderTopBumper dijitSliderTopBumper\" dojoAttachEvent=\"onclick:_onClkIncBumper\"></div></center\n\t\t></td\n\t\t><td class=\"dijitReset\"></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td dojoAttachPoint=\"leftDecoration\" class=\"dijitReset\" style=\"text-align:center;height:100%;\"></td\n\t\t><td class=\"dijitReset\" style=\"height:100%;\"\n\t\t\t><input dojoAttachPoint=\"valueNode\" type=\"hidden\" name=\"${name}\"\n\t\t\t/><center waiRole=\"presentation\" style=\"position:relative;height:100%;\" dojoAttachPoint=\"sliderBarContainer\"\n\t\t\t\t><div waiRole=\"presentation\" dojoAttachPoint=\"remainingBar\" class=\"dijitSliderBar dijitSliderBarV dijitSliderRemainingBar dijitSliderRemainingBarV\" dojoAttachEvent=\"onclick:_onBarClick\"><!--#5629--></div\n\t\t\t\t><div waiRole=\"presentation\" dojoAttachPoint=\"progressBar\" class=\"dijitSliderBar dijitSliderBarV dijitSliderProgressBar dijitSliderProgressBarV\" dojoAttachEvent=\"onclick:_onBarClick\"\n\t\t\t\t\t><div dojoAttachPoint=\"sliderHandle,focusNode\" class=\"dijitSliderMoveable\" dojoAttachEvent=\"onkeypress:_onKeyPress,onmousedown:_onHandleClick\" style=\"vertical-align:top;\" waiRole=\"slider\" valuemin=\"${minimum}\" valuemax=\"${maximum}\"\n\t\t\t\t\t\t><div class=\"dijitSliderImageHandle dijitSliderImageHandleV\"></div\n\t\t\t\t\t></div\n\t\t\t\t></div\n\t\t\t></center\n\t\t></td\n\t\t><td dojoAttachPoint=\"containerNode,rightDecoration\" class=\"dijitReset\" style=\"text-align:center;height:100%;\"></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\"></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><center><div class=\"dijitSliderBar dijitSliderBumper dijitSliderBumperV dijitSliderBottomBumper dijitSliderBottomBumper\" dojoAttachEvent=\"onclick:_onClkDecBumper\"></div></center\n\t\t></td\n\t\t><td class=\"dijitReset\"></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\"></td\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitSliderButtonContainerV\"\n\t\t\t><div class=\"dijitSliderDecrementIconV\" tabIndex=\"-1\" style=\"display:none\" dojoAttachPoint=\"decrementButton\" dojoAttachEvent=\"onclick:_bottomButtonClicked\"><span class=\"dijitSliderButtonInner\">-</span></div\n\t\t></td\n\t\t><td class=\"dijitReset\"></td\n\t></tr\n></tbody></table>\n",
+ _mousePixelCoord: "pageY",
+ _pixelCount: "h",
+ _startingPixelCoord: "y",
+ _startingPixelCount: "t",
+ _handleOffsetCoord: "top",
+ _progressPixelSize: "height",
+
+ // _descending: boolean
+ // Specifies if the slider values go from high-on-top (true), or low-on-top (false)
+ // TODO: expose this in 1.2 - the css progress/remaining bar classes need to be reversed
+ _descending: true,
+
+ startup: function(){
+ if(this._started){ return; }
+
+ if(!this.isLeftToRight() && dojo.isMoz){
+ if(this.leftDecoration){this._rtlRectify(this.leftDecoration);}
+ if(this.rightDecoration){this._rtlRectify(this.rightDecoration);}
+ }
+
+ this.inherited(arguments);
+ },
+
+ _isReversed: function(){
+ return this._descending;
+ },
+
+ _topButtonClicked: function(e){
+ if(this._descending){
+ this.increment(e);
+ }else{
+ this.decrement(e);
+ }
+ },
+
+ _bottomButtonClicked: function(e){
+ if(this._descending){
+ this.decrement(e);
+ }else{
+ this.increment(e);
+ }
+ },
+
+ _rtlRectify: function(decorationNode/*NodeList*/){
+ // summary:
+ // Rectify children nodes for left/right decoration in rtl case.
+ // Simply switch the rule and label child for each decoration node.
+ var childNodes = [];
+ while(decorationNode.firstChild){
+ childNodes.push(decorationNode.firstChild);
+ decorationNode.removeChild(decorationNode.firstChild);
+ }
+ for(var i = childNodes.length-1; i >=0; i--){
+ if(childNodes[i]){
+ decorationNode.appendChild(childNodes[i]);
+ }
+ }
+ }
+});
+
+dojo.declare("dijit.form._SliderMover",
+ dojo.dnd.Mover,
+{
+ onMouseMove: function(e){
+ var widget = this.widget;
+ var abspos = widget._abspos;
+ if(!abspos){
+ abspos = widget._abspos = dojo.coords(widget.sliderBarContainer, true);
+ widget._setPixelValue_ = dojo.hitch(widget, "_setPixelValue");
+ widget._isReversed_ = widget._isReversed();
+ }
+ var pixelValue = e[widget._mousePixelCoord] - abspos[widget._startingPixelCoord];
+ widget._setPixelValue_(widget._isReversed_ ? (abspos[widget._pixelCount]-pixelValue) : pixelValue, abspos[widget._pixelCount], false);
+ },
+
+ destroy: function(e){
+ dojo.dnd.Mover.prototype.destroy.apply(this, arguments);
+ var widget = this.widget;
+ widget.setValue(widget.value, true);
+ }
+});
+
+
+dojo.declare("dijit.form.HorizontalRule", [dijit._Widget, dijit._Templated],
+{
+ // Summary:
+ // Create hash marks for the Horizontal slider
+ templateString: '<div class="dijitRuleContainer dijitRuleContainerH"></div>',
+
+ // count: Integer
+ // Number of hash marks to generate
+ count: 3,
+
+ // container: Node
+ // If this is a child widget, connect it to this parent node
+ container: "containerNode",
+
+ // ruleStyle: String
+ // CSS style to apply to individual hash marks
+ ruleStyle: "",
+
+ _positionPrefix: '<div class="dijitRuleMark dijitRuleMarkH" style="left:',
+ _positionSuffix: '%;',
+ _suffix: '"></div>',
+
+ _genHTML: function(pos, ndx){
+ return this._positionPrefix + pos + this._positionSuffix + this.ruleStyle + this._suffix;
+ },
+
+ _isHorizontal: true,
+
+ postCreate: function(){
+ var innerHTML;
+ if(this.count==1){
+ innerHTML = this._genHTML(50, 0);
+ }else{
+ var i;
+ var interval = 100 / (this.count-1);
+ if(!this._isHorizontal || this.isLeftToRight()){
+ innerHTML = this._genHTML(0, 0);
+ for(i=1; i < this.count-1; i++){
+ innerHTML += this._genHTML(interval*i, i);
+ }
+ innerHTML += this._genHTML(100, this.count-1);
+ }else{
+ innerHTML = this._genHTML(100, 0);
+ for(i=1; i < this.count-1; i++){
+ innerHTML += this._genHTML(100-interval*i, i);
+ }
+ innerHTML += this._genHTML(0, this.count-1);
+ }
+ }
+ this.domNode.innerHTML = innerHTML;
+ }
+});
+
+dojo.declare("dijit.form.VerticalRule", dijit.form.HorizontalRule,
+{
+ // Summary:
+ // Create hash marks for the Vertical slider
+ templateString: '<div class="dijitRuleContainer dijitRuleContainerV"></div>',
+ _positionPrefix: '<div class="dijitRuleMark dijitRuleMarkV" style="top:',
+
+ _isHorizontal: false
+});
+
+dojo.declare("dijit.form.HorizontalRuleLabels", dijit.form.HorizontalRule,
+{
+ // Summary:
+ // Create labels for the Horizontal slider
+ templateString: '<div class="dijitRuleContainer dijitRuleContainerH"></div>',
+
+ // labelStyle: String
+ // CSS style to apply to individual text labels
+ labelStyle: "",
+
+ // labels: Array
+ // Array of text labels to render - evenly spaced from left-to-right or bottom-to-top
+ labels: [],
+
+ // numericMargin: Integer
+ // Number of generated numeric labels that should be rendered as '' on the ends when labels[] are not specified
+ numericMargin: 0,
+
+ // numericMinimum: Integer
+ // Leftmost label value for generated numeric labels when labels[] are not specified
+ minimum: 0,
+
+ // numericMaximum: Integer
+ // Rightmost label value for generated numeric labels when labels[] are not specified
+ maximum: 1,
+
+ // constraints: object
+ // pattern, places, lang, et al (see dojo.number) for generated numeric labels when labels[] are not specified
+ constraints: {pattern:"#%"},
+
+ _positionPrefix: '<div class="dijitRuleLabelContainer dijitRuleLabelContainerH" style="left:',
+ _labelPrefix: '"><span class="dijitRuleLabel dijitRuleLabelH">',
+ _suffix: '</span></div>',
+
+ _calcPosition: function(pos){
+ return pos;
+ },
+
+ _genHTML: function(pos, ndx){
+ return this._positionPrefix + this._calcPosition(pos) + this._positionSuffix + this.labelStyle + this._labelPrefix + this.labels[ndx] + this._suffix;
+ },
+
+ getLabels: function(){
+ // summary: user replaceable function to return the labels array
+
+ // if the labels array was not specified directly, then see if <li> children were
+ var labels = this.labels;
+ if(!labels.length){
+ // for markup creation, labels are specified as child elements
+ labels = dojo.query("> li", this.srcNodeRef).map(function(node){
+ return String(node.innerHTML);
+ });
+ }
+ this.srcNodeRef.innerHTML = '';
+ // if the labels were not specified directly and not as <li> children, then calculate numeric labels
+ if(!labels.length && this.count > 1){
+ var start = this.minimum;
+ var inc = (this.maximum - start) / (this.count-1);
+ for (var i=0; i < this.count; i++){
+ labels.push((i<this.numericMargin||i>=(this.count-this.numericMargin))? '' : dojo.number.format(start, this.constraints));
+ start += inc;
+ }
+ }
+ return labels;
+ },
+
+ postMixInProperties: function(){
+ this.inherited(arguments);
+ this.labels = this.getLabels();
+ this.count = this.labels.length;
+ }
+});
+
+dojo.declare("dijit.form.VerticalRuleLabels", dijit.form.HorizontalRuleLabels,
+{
+ // Summary:
+ // Create labels for the Vertical slider
+ templateString: '<div class="dijitRuleContainer dijitRuleContainerV"></div>',
+
+ _positionPrefix: '<div class="dijitRuleLabelContainer dijitRuleLabelContainerV" style="top:',
+ _labelPrefix: '"><span class="dijitRuleLabel dijitRuleLabelV">',
+
+ _calcPosition: function(pos){
+ return 100-pos;
+ },
+
+ _isHorizontal: false
+});
+
+}
diff --git a/includes/js/dijit/form/TextBox.js b/includes/js/dijit/form/TextBox.js
new file mode 100644
index 0000000..f36aff4
--- /dev/null
+++ b/includes/js/dijit/form/TextBox.js
@@ -0,0 +1,185 @@
+if(!dojo._hasResource["dijit.form.TextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.TextBox"] = true;
+dojo.provide("dijit.form.TextBox");
+
+dojo.require("dijit.form._FormWidget");
+
+dojo.declare(
+ "dijit.form.TextBox",
+ dijit.form._FormValueWidget,
+ {
+ // summary:
+ // A base class for textbox form inputs
+ //
+ // trim: Boolean
+ // Removes leading and trailing whitespace if true. Default is false.
+ trim: false,
+
+ // uppercase: Boolean
+ // Converts all characters to uppercase if true. Default is false.
+ uppercase: false,
+
+ // lowercase: Boolean
+ // Converts all characters to lowercase if true. Default is false.
+ lowercase: false,
+
+ // propercase: Boolean
+ // Converts the first character of each word to uppercase if true.
+ propercase: false,
+
+ // maxLength: String
+ // HTML INPUT tag maxLength declaration.
+ maxLength: "",
+
+ templateString:"<input class=\"dijit dijitReset dijitLeft\" dojoAttachPoint='textbox,focusNode' name=\"${name}\"\n\tdojoAttachEvent='onmouseenter:_onMouse,onmouseleave:_onMouse,onfocus:_onMouse,onblur:_onMouse,onkeypress:_onKeyPress,onkeyup'\n\tautocomplete=\"off\" type=\"${type}\"\n\t/>\n",
+ baseClass: "dijitTextBox",
+
+ attributeMap: dojo.mixin(dojo.clone(dijit.form._FormValueWidget.prototype.attributeMap),
+ {maxLength:"focusNode"}),
+
+ getDisplayedValue: function(){
+ // summary:
+ // Returns the formatted value that the user sees in the textbox, which may be different
+ // from the serialized value that's actually sent to the server (see dijit.form.ValidationTextBox.serialize)
+ return this.filter(this.textbox.value);
+ },
+
+ getValue: function(){
+ return this.parse(this.getDisplayedValue(), this.constraints);
+ },
+
+ setValue: function(value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){
+ // summary:
+ // 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 = this.filter(value);
+ if((((typeof filteredValue == typeof value) && (value !== undefined/*#5317*/)) || (value === null/*#5329*/)) && (formattedValue == null || formattedValue == undefined)){
+ formattedValue = this.format(filteredValue, this.constraints);
+ }
+ if(formattedValue != null && formattedValue != undefined){
+ this.textbox.value = formattedValue;
+ }
+ dijit.form.TextBox.superclass.setValue.call(this, filteredValue, priorityChange);
+ },
+
+ setDisplayedValue: function(/*String*/value, /*Boolean?*/ priorityChange){
+ // summary:
+ // 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.
+ //
+ // priorityChange:
+ // If true, an onChange event is fired immediately instead of
+ // waiting for the next blur event.
+
+ this.textbox.value = value;
+ this.setValue(this.getValue(), priorityChange);
+ },
+
+ format: function(/* String */ value, /* Object */ constraints){
+ // summary:
+ // Replacable function to convert a value to a properly formatted string
+ return ((value == null || value == undefined) ? "" : (value.toString ? value.toString() : value));
+ },
+
+ parse: function(/* String */ value, /* Object */ constraints){
+ // summary:
+ // Replacable function to convert a formatted string to a value
+ return value;
+ },
+
+ postCreate: function(){
+ // setting the value here is needed since value="" in the template causes "undefined"
+ // and setting in the DOM (instead of the JS object) helps with form reset actions
+ this.textbox.setAttribute("value", this.getDisplayedValue());
+ this.inherited(arguments);
+
+ /*#5297:if(this.srcNodeRef){
+ dojo.style(this.textbox, "cssText", this.style);
+ this.textbox.className += " " + this["class"];
+ }*/
+ this._layoutHack();
+ },
+
+ filter: function(val){
+ // summary:
+ // Apply specified filters to textbox value
+ if(val === null || val === undefined){ return ""; }
+ else if(typeof val != "string"){ return val; }
+ if(this.trim){
+ val = dojo.trim(val);
+ }
+ if(this.uppercase){
+ val = val.toUpperCase();
+ }
+ if(this.lowercase){
+ val = val.toLowerCase();
+ }
+ if(this.propercase){
+ val = val.replace(/[^\s]+/g, function(word){
+ return word.substring(0,1).toUpperCase() + word.substring(1);
+ });
+ }
+ return val;
+ },
+
+ _setBlurValue: function(){
+ this.setValue(this.getValue(), (this.isValid ? this.isValid() : true));
+ },
+
+ _onBlur: function(){
+ this._setBlurValue();
+ this.inherited(arguments);
+ },
+
+ onkeyup: function(){
+ // summary:
+ // User replaceable keyup event handler
+ }
+ }
+);
+
+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?
+ var _window = dojo.global;
+ var _document = dojo.doc;
+ element = dojo.byId(element);
+ if(isNaN(start)){ start = 0; }
+ if(isNaN(stop)){ stop = element.value ? element.value.length : 0; }
+ element.focus();
+ if(_document["selection"] && dojo.body()["createTextRange"]){ // IE
+ if(element.createTextRange){
+ var range = element.createTextRange();
+ with(range){
+ collapse(true);
+ moveStart("character", start);
+ moveEnd("character", stop);
+ select();
+ }
+ }
+ }else if(_window["getSelection"]){
+ var selection = _window.getSelection();
+ // FIXME: does this work on Safari?
+ if(element.setSelectionRange){
+ element.setSelectionRange(start, stop);
+ }
+ }
+}
+
+}
diff --git a/includes/js/dijit/form/Textarea.js b/includes/js/dijit/form/Textarea.js
new file mode 100644
index 0000000..b879aae
--- /dev/null
+++ b/includes/js/dijit/form/Textarea.js
@@ -0,0 +1,261 @@
+if(!dojo._hasResource["dijit.form.Textarea"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.Textarea"] = true;
+dojo.provide("dijit.form.Textarea");
+
+dojo.require("dijit.form._FormWidget");
+dojo.require("dojo.i18n");
+dojo.requireLocalization("dijit.form", "Textarea", null, "zh,pt,da,tr,ru,de,ROOT,sv,ja,he,fi,nb,el,ar,pt-pt,cs,fr,es,ko,nl,zh-tw,pl,it,hu");
+
+dojo.declare(
+ "dijit.form.Textarea",
+ dijit.form._FormValueWidget,
+ {
+ // summary: A resizing textarea widget
+ //
+ // description:
+ // A textarea that resizes vertically to contain the data.
+ // Takes nearly all the parameters (name, value, etc.) that a vanilla textarea takes.
+ // Cols is not supported and the width should be specified with style width.
+ // Rows is not supported since this widget adjusts the height.
+ //
+ // example:
+ // | <textarea dojoType="dijit.form.TextArea">...</textarea>
+ //
+
+ attributeMap: dojo.mixin(dojo.clone(dijit.form._FormValueWidget.prototype.attributeMap),
+ {style:"styleNode", 'class':"styleNode"}),
+
+ templateString: (dojo.isIE || dojo.isSafari || dojo.isFF) ?
+ ((dojo.isIE || dojo.isSafari || dojo.isFF >= 3) ? '<fieldset id="${id}" class="dijitInline dijitInputField dijitTextArea" dojoAttachPoint="styleNode" waiRole="presentation"><div dojoAttachPoint="editNode,focusNode,eventNode" dojoAttachEvent="onpaste:_changing,oncut:_changing" waiRole="textarea" style="text-decoration:none;display:block;overflow:auto;" contentEditable="true"></div>'
+ : '<span id="${id}" class="dijitReset">'+
+ '<iframe src="javascript:<html><head><title>${_iframeEditTitle}</title></head><body><script>var _postCreate=window.frameElement?window.frameElement.postCreate:null;if(_postCreate)_postCreate();</script></body></html>"'+
+ ' dojoAttachPoint="iframe,styleNode" dojoAttachEvent="onblur:_onIframeBlur" class="dijitInline dijitInputField dijitTextArea"></iframe>')
+ + '<textarea name="${name}" value="${value}" dojoAttachPoint="formValueNode" style="display:none;"></textarea>'
+ + ((dojo.isIE || dojo.isSafari || dojo.isFF >= 3) ? '</fieldset>':'</span>')
+ : '<textarea id="${id}" name="${name}" value="${value}" dojoAttachPoint="formValueNode,editNode,focusNode,styleNode" class="dijitInputField dijitTextArea">'+dojo.isFF+'</textarea>',
+
+ setAttribute: function(/*String*/ attr, /*anything*/ value){
+ this.inherited(arguments);
+ switch(attr){
+ case "disabled":
+ this.formValueNode.disabled = this.disabled;
+ case "readOnly":
+ if(dojo.isIE || dojo.isSafari || dojo.isFF >= 3){
+ this.editNode.contentEditable = (!this.disabled && !this.readOnly);
+ }else if(dojo.isFF){
+ this.iframe.contentDocument.designMode = (this.disabled || this.readOnly)? "off" : "on";
+ }
+ }
+ },
+
+ focus: function(){
+ // summary: Received focus, needed for the InlineEditBox widget
+ if(!this.disabled && !this.readOnly){
+ this._changing(); // set initial height
+ }
+ dijit.focus(this.iframe || this.focusNode);
+ },
+
+ setValue: function(/*String*/ value, /*Boolean, optional*/ priorityChange){
+ var editNode = this.editNode;
+ if(typeof value == "string"){
+ editNode.innerHTML = ""; // wipe out old nodes
+ if(value.split){
+ var _this=this;
+ var isFirst = true;
+ dojo.forEach(value.split("\n"), function(line){
+ if(isFirst){ isFirst = false; }
+ else{
+ editNode.appendChild(dojo.doc.createElement("BR")); // preserve line breaks
+ }
+ if(line){
+ editNode.appendChild(dojo.doc.createTextNode(line)); // use text nodes so that imbedded tags can be edited
+ }
+ });
+ }else if(value){
+ editNode.appendChild(dojo.doc.createTextNode(value));
+ }
+ if(!dojo.isIE){
+ editNode.appendChild(dojo.doc.createElement("BR")); // so that you see a cursor
+ }
+ }else{
+ // blah<BR>blah --> blah\nblah
+ // <P>blah</P><P>blah</P> --> blah\nblah
+ // <DIV>blah</DIV><DIV>blah</DIV> --> blah\nblah
+ // &amp;&lt;&gt; -->&< >
+ value = editNode.innerHTML;
+ if(this.iframe){ // strip sizeNode
+ value = value.replace(/<div><\/div>\r?\n?$/i,"");
+ }
+ value = value.replace(/\s*\r?\n|^\s+|\s+$|&nbsp;/g,"").replace(/>\s+</g,"><").replace(/<\/(p|div)>$|^<(p|div)[^>]*>/gi,"").replace(/([^>])<div>/g,"$1\n").replace(/<\/p>\s*<p[^>]*>|<br[^>]*>|<\/div>\s*<div[^>]*>/gi,"\n").replace(/<[^>]*>/g,"").replace(/&amp;/gi,"\&").replace(/&lt;/gi,"<").replace(/&gt;/gi,">");
+ if(!dojo.isIE){
+ value = value.replace(/\n$/,""); // remove added <br>
+ }
+ }
+ this.value = this.formValueNode.value = value;
+ if(this.iframe){
+ var sizeNode = dojo.doc.createElement('div');
+ editNode.appendChild(sizeNode);
+ var newHeight = sizeNode.offsetTop;
+ if(editNode.scrollWidth > editNode.clientWidth){ newHeight+=16; } // scrollbar space needed?
+ if(this.lastHeight != newHeight){ // cache size so that we don't get a resize event because of a resize event
+ if(newHeight == 0){ newHeight = 16; } // height = 0 causes the browser to not set scrollHeight
+ dojo.contentBox(this.iframe, {h: newHeight});
+ this.lastHeight = newHeight;
+ }
+ editNode.removeChild(sizeNode);
+ }
+ dijit.form.Textarea.superclass.setValue.call(this, this.getValue(), priorityChange);
+ },
+
+ getValue: function(){
+ return this.value.replace(/\r/g,"");
+ },
+
+ postMixInProperties: function(){
+ this.inherited(arguments);
+ // don't let the source text be converted to a DOM structure since we just want raw text
+ if(this.srcNodeRef && this.srcNodeRef.innerHTML != ""){
+ this.value = this.srcNodeRef.innerHTML;
+ this.srcNodeRef.innerHTML = "";
+ }
+ if((!this.value || this.value == "") && this.srcNodeRef && this.srcNodeRef.value){
+ this.value = this.srcNodeRef.value;
+ }
+ if(!this.value){ this.value = ""; }
+ this.value = this.value.replace(/\r\n/g,"\n").replace(/&gt;/g,">").replace(/&lt;/g,"<").replace(/&amp;/g,"&");
+ if(dojo.isFF == 2){
+ // In the case of Firefox an iframe is used and when the text gets focus,
+ // focus is fired from the document object. There isn't a way to put a
+ // waiRole on the document object and as a result screen readers don't
+ // announce the role. As a result screen reader users are lost.
+ //
+ // An additional problem is that the browser gives the document object a
+ // very cryptic accessible name, e.g.
+ // wysiwyg://13/http://archive.dojotoolkit.org/nightly/dojotoolkit/dijit/tests/form/test_InlineEditBox.html
+ // When focus is fired from the document object, the screen reader speaks
+ // the accessible name. The cyptic accessile name is confusing.
+ //
+ // A workaround for both of these problems is to give the iframe's
+ // document a title, the name of which is similar to a role name, i.e.
+ // "edit area". This will be used as the accessible name which will replace
+ // the cryptic name and will also convey the role information to the user.
+ // Because it is read directly to the user, the string must be localized.
+ // In addition, since a <label> element can not be associated with an iframe, if
+ // this control has a label, insert the label text into the title as well.
+ var _nlsResources = dojo.i18n.getLocalization("dijit.form", "Textarea");
+ this._iframeEditTitle = _nlsResources.iframeEditTitle;
+ this._iframeFocusTitle = _nlsResources.iframeFocusTitle;
+ var label=dojo.query('label[for="'+this.id+'"]');
+ if(label.length){
+ this._iframeEditTitle = label[0].innerHTML + " " + this._iframeEditTitle;
+ }
+ var body = this.focusNode = this.editNode = dojo.doc.createElement('BODY');
+ body.style.margin="0px";
+ body.style.padding="0px";
+ body.style.border="0px";
+ }
+ },
+
+ postCreate: function(){
+ if(dojo.isIE || dojo.isSafari || dojo.isFF >= 3){
+ this.domNode.style.overflowY = 'hidden';
+ }else if(dojo.isFF){
+ var w = this.iframe.contentWindow;
+ var title = '';
+ try { // #4715: peeking at the title can throw a security exception during iframe setup
+ title = this.iframe.contentDocument.title;
+ } catch(e) {}
+ if(!w || !title){
+ this.iframe.postCreate = dojo.hitch(this, this.postCreate);
+ return;
+ }
+ var d = w.document;
+ d.getElementsByTagName('HTML')[0].replaceChild(this.editNode, d.getElementsByTagName('BODY')[0]);
+ if(!this.isLeftToRight()){
+ d.getElementsByTagName('HTML')[0].dir = "rtl";
+ }
+ this.iframe.style.overflowY = 'hidden';
+ this.eventNode = d;
+ // this.connect won't destroy this handler cleanly since its on the iframe's window object
+ // resize is a method of window, not document
+ w.addEventListener("resize", dojo.hitch(this, this._changed), false); // resize is only on the window object
+ }else{
+ this.focusNode = this.domNode;
+ }
+ if(this.eventNode){
+ this.connect(this.eventNode, "keypress", this._onKeyPress);
+ this.connect(this.eventNode, "mousemove", this._changed);
+ this.connect(this.eventNode, "focus", this._focused);
+ this.connect(this.eventNode, "blur", this._blurred);
+ }
+ if(this.editNode){
+ this.connect(this.editNode, "change", this._changed); // needed for mouse paste events per #3479
+ }
+ this.inherited('postCreate', arguments);
+ },
+
+ // event handlers, you can over-ride these in your own subclasses
+ _focused: function(e){
+ dojo.addClass(this.iframe||this.domNode, "dijitInputFieldFocused");
+ this._changed(e);
+ },
+
+ _blurred: function(e){
+ dojo.removeClass(this.iframe||this.domNode, "dijitInputFieldFocused");
+ this._changed(e, true);
+ },
+
+ _onIframeBlur: function(){
+ // Reset the title back to "edit area".
+ this.iframe.contentDocument.title = this._iframeEditTitle;
+ },
+
+ _onKeyPress: function(e){
+ if(e.keyCode == dojo.keys.TAB && !e.shiftKey && !e.ctrlKey && !e.altKey && this.iframe){
+ // Pressing the tab key in the iframe (with designMode on) will cause the
+ // entry of a tab character so we have to trap that here. Since we don't
+ // know the next focusable object we put focus on the iframe and then the
+ // user has to press tab again (which then does the expected thing).
+ // A problem with that is that the screen reader user hears "edit area"
+ // announced twice which causes confusion. By setting the
+ // contentDocument's title to "edit area frame" the confusion should be
+ // eliminated.
+ this.iframe.contentDocument.title = this._iframeFocusTitle;
+ // Place focus on the iframe. A subsequent tab or shift tab will put focus
+ // on the correct control.
+ // Note: Can't use this.focus() because that results in a call to
+ // dijit.focus and if that receives an iframe target it will set focus
+ // on the iframe's contentWindow.
+ this.iframe.focus(); // this.focus(); won't work
+ dojo.stopEvent(e);
+ }else if(e.keyCode == dojo.keys.ENTER){
+ e.stopPropagation();
+ }else if(this.inherited("_onKeyPress", arguments) && this.iframe){
+ // #3752:
+ // The key press will not make it past the iframe.
+ // If a widget is listening outside of the iframe, (like InlineEditBox)
+ // it will not hear anything.
+ // Create an equivalent event so everyone else knows what is going on.
+ var te = dojo.doc.createEvent("KeyEvents");
+ te.initKeyEvent("keypress", true, true, null, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.keyCode, e.charCode);
+ this.iframe.dispatchEvent(te);
+ }
+ this._changing();
+ },
+
+ _changing: function(e){
+ // summary: event handler for when a change is imminent
+ setTimeout(dojo.hitch(this, "_changed", e, false), 1);
+ },
+
+ _changed: function(e, priorityChange){
+ // summary: event handler for when a change has already happened
+ if(this.iframe && this.iframe.contentDocument.designMode != "on" && !this.disabled && !this.readOnly){
+ this.iframe.contentDocument.designMode="on"; // in case this failed on init due to being hidden
+ }
+ this.setValue(null, priorityChange || false);
+ }
+});
+
+}
diff --git a/includes/js/dijit/form/TimeTextBox.js b/includes/js/dijit/form/TimeTextBox.js
new file mode 100644
index 0000000..1774e61
--- /dev/null
+++ b/includes/js/dijit/form/TimeTextBox.js
@@ -0,0 +1,33 @@
+if(!dojo._hasResource["dijit.form.TimeTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.TimeTextBox"] = true;
+dojo.provide("dijit.form.TimeTextBox");
+
+dojo.require("dijit._TimePicker");
+dojo.require("dijit.form._DateTimeTextBox");
+
+/*=====
+dojo.declare(
+ "dijit.form.TimeTextBox.__Constraints",
+ [dijit.form._DateTimeTextBox.__Constraints, dijit._TimePicker.__Constraints]
+);
+=====*/
+
+dojo.declare(
+ "dijit.form.TimeTextBox",
+ dijit.form._DateTimeTextBox,
+ {
+ // summary:
+ // A validating, serializable, range-bound time text box with a popup time picker
+
+ popupClass: "dijit._TimePicker",
+ _selector: "time"
+
+/*=====
+ ,
+ // constraints: dijit.form.TimeTextBox.__Constraints
+ constraints:{}
+=====*/
+ }
+);
+
+}
diff --git a/includes/js/dijit/form/ValidationTextBox.js b/includes/js/dijit/form/ValidationTextBox.js
new file mode 100644
index 0000000..4f354d0
--- /dev/null
+++ b/includes/js/dijit/form/ValidationTextBox.js
@@ -0,0 +1,308 @@
+if(!dojo._hasResource["dijit.form.ValidationTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form.ValidationTextBox"] = true;
+dojo.provide("dijit.form.ValidationTextBox");
+
+dojo.require("dojo.i18n");
+
+dojo.require("dijit.form.TextBox");
+dojo.require("dijit.Tooltip");
+
+dojo.requireLocalization("dijit.form", "validate", null, "zh,pt,da,tr,ru,de,sv,ja,he,fi,nb,el,ar,pt-pt,ROOT,cs,fr,es,ko,nl,zh-tw,pl,it,hu");
+
+/*=====
+ 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_ = "";
+ }
+=====*/
+
+dojo.declare(
+ "dijit.form.ValidationTextBox",
+ dijit.form.TextBox,
+ {
+ // summary:
+ // A TextBox subclass with the ability to validate content of various types and provide user feedback.
+
+ templateString:"<div class=\"dijit dijitReset dijitInlineTable dijitLeft\"\n\tid=\"widget_${id}\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\" waiRole=\"presentation\"\n\t><div style=\"overflow:hidden;\"\n\t\t><div class=\"dijitReset dijitValidationIcon\"><br></div\n\t\t><div class=\"dijitReset dijitValidationIconText\">&Chi;</div\n\t\t><div class=\"dijitReset dijitInputField\"\n\t\t\t><input class=\"dijitReset\" dojoAttachPoint='textbox,focusNode' dojoAttachEvent='onfocus:_update,onkeyup:_onkeyup,onblur:_onMouse,onkeypress:_onKeyPress' autocomplete=\"off\"\n\t\t\ttype='${type}' name='${name}'\n\t\t/></div\n\t></div\n></div>\n",
+ baseClass: "dijitTextBox",
+
+ // default values for new subclass properties
+ // required: Boolean
+ // Can be true or false, default is false.
+ required: false,
+
+ // promptMessage: String
+ // Hint string
+ promptMessage: "",
+
+ // invalidMessage: String
+ // The message to display if value is invalid.
+ invalidMessage: "$_unset_$", // read from the message file if not overridden
+
+ // constraints: dijit.form.ValidationTextBox.__Constraints
+ // user-defined object needed to pass parameters to the validator functions
+ constraints: {},
+
+ // regExp: String
+ // regular expression string used to validate the input
+ // Do not specify both regExp and regExpGen
+ regExp: ".*",
+
+ // regExpGen: Function
+ // user replaceable function used to generate regExp when dependent on constraints
+ // Do not specify both regExp and regExpGen
+ regExpGen: function(/*dijit.form.ValidationTextBox.__Constraints*/constraints){ return this.regExp; },
+
+ // state: String
+ // Shows current state (ie, validation result) of input (Normal, Warning, or Error)
+ state: "",
+
+ // tooltipPosition: String[]
+ // See description of dijit.Tooltip.defaultPosition for details on this parameter.
+ tooltipPosition: [],
+
+ setValue: function(){
+ this.inherited(arguments);
+ this.validate(this._focused);
+ },
+
+ validator: function(/*anything*/value, /*dijit.form.ValidationTextBox.__Constraints*/constraints){
+ // summary: user replaceable function used to validate the text input against the regular expression.
+ return (new RegExp("^(" + this.regExpGen(constraints) + ")"+(this.required?"":"?")+"$")).test(value) &&
+ (!this.required || !this._isEmpty(value)) &&
+ (this._isEmpty(value) || this.parse(value, constraints) !== undefined); // Boolean
+ },
+
+ isValid: function(/*Boolean*/ isFocused){
+ // summary: Need to over-ride with your own validation code in subclasses
+ return this.validator(this.textbox.value, this.constraints);
+ },
+
+ _isEmpty: function(value){
+ // summary: Checks for whitespace
+ return /^\s*$/.test(value); // Boolean
+ },
+
+ getErrorMessage: function(/*Boolean*/ isFocused){
+ // summary: return an error message to show if appropriate
+ return this.invalidMessage; // String
+ },
+
+ getPromptMessage: function(/*Boolean*/ isFocused){
+ // summary: return a hint to show if appropriate
+ return this.promptMessage; // String
+ },
+
+ validate: function(/*Boolean*/ isFocused){
+ // summary:
+ // Called by oninit, onblur, and onkeypress.
+ // description:
+ // Show missing or invalid messages if appropriate, and highlight textbox field.
+ var message = "";
+ var isValid = this.isValid(isFocused);
+ var isEmpty = this._isEmpty(this.textbox.value);
+ this.state = (isValid || (!this._hasBeenBlurred && isEmpty)) ? "" : "Error";
+ this._setStateClass();
+ dijit.setWaiState(this.focusNode, "invalid", isValid ? "false" : "true");
+ if(isFocused){
+ if(isEmpty){
+ message = this.getPromptMessage(true);
+ }
+ if(!message && this.state == "Error"){
+ message = this.getErrorMessage(true);
+ }
+ }
+ this.displayMessage(message);
+ return isValid;
+ },
+
+ // currently displayed message
+ _message: "",
+
+ displayMessage: function(/*String*/ message){
+ // summary:
+ // User overridable method to display validation errors/hints.
+ // By default uses a tooltip.
+ if(this._message == message){ return; }
+ this._message = message;
+ dijit.hideTooltip(this.domNode);
+ if(message){
+ dijit.showTooltip(message, this.domNode, this.tooltipPosition);
+ }
+ },
+
+ _refreshState: function(){
+ this.validate(this._focused);
+ },
+
+ _update: function(/*Event*/e){
+ this._refreshState();
+ this._onMouse(e); // update CSS classes
+ },
+
+ _onkeyup: function(/*Event*/e){
+ this._update(e);
+ this.onkeyup(e);
+ },
+
+ //////////// INITIALIZATION METHODS ///////////////////////////////////////
+
+ constructor: function(){
+ this.constraints = {};
+ },
+
+ postMixInProperties: function(){
+ this.inherited(arguments);
+ this.constraints.locale = this.lang;
+ this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);
+ if(this.invalidMessage == "$_unset_$"){ this.invalidMessage = this.messages.invalidMessage; }
+ var p = this.regExpGen(this.constraints);
+ this.regExp = p;
+ }
+ }
+);
+
+dojo.declare(
+ "dijit.form.MappedTextBox",
+ dijit.form.ValidationTextBox,
+ {
+ // summary:
+ // A dijit.form.ValidationTextBox subclass which provides a visible formatted display and a serializable
+ // value in a hidden input field which is actually sent to the server. 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 serveris defined by the dijit.form.MappedTextBox.serialize method and is typically
+ // locale-neutral.
+
+ serialize: function(/*anything*/val, /*Object?*/options){
+ // summary: user replaceable function used to convert the getValue() result to a String
+ return val.toString ? val.toString() : ""; // String
+ },
+
+ toString: function(){
+ // summary: display the widget as a printable string using the widget's value
+ var val = this.filter(this.getValue());
+ return val != null ? (typeof val == "string" ? val : this.serialize(val, this.constraints)) : ""; // String
+ },
+
+ validate: function(){
+ this.valueNode.value = this.toString();
+ return this.inherited(arguments);
+ },
+
+ setAttribute: function(/*String*/ attr, /*anything*/ value){
+ this.inherited(arguments);
+ switch(attr){
+ case "disabled":
+ if(this.valueNode){
+ this.valueNode.disabled = this.disabled;
+ }
+ }
+ },
+
+ postCreate: function(){
+ var textbox = this.textbox;
+ var valueNode = (this.valueNode = dojo.doc.createElement("input"));
+ valueNode.setAttribute("type", textbox.type);
+ valueNode.setAttribute("value", this.toString());
+ dojo.style(valueNode, "display", "none");
+ valueNode.name = this.textbox.name;
+ valueNode.disabled = this.textbox.disabled;
+ this.textbox.name = this.textbox.name + "_displayed_";
+ this.textbox.removeAttribute("name");
+ dojo.place(valueNode, textbox, "after");
+
+ this.inherited(arguments);
+ }
+ }
+);
+
+/*=====
+ 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;
+ }
+=====*/
+
+dojo.declare(
+ "dijit.form.RangeBoundTextBox",
+ dijit.form.MappedTextBox,
+ {
+ // summary:
+ // A dijit.form.MappedTextBox subclass which defines a range of valid values
+ //
+ // constraints: dijit.form.RangeBoundTextBox.__Constraints
+ //
+ // rangeMessage: String
+ // The message to display if value is out-of-range
+
+ /*=====
+ constraints: {},
+ ======*/
+ rangeMessage: "",
+
+ compare: function(/*anything*/val1, /*anything*/val2){
+ // summary: compare 2 values
+ return val1 - val2; // anything
+ },
+
+ rangeCheck: function(/*Number*/ primitive, /*dijit.form.RangeBoundTextBox.__Constraints*/ constraints){
+ // summary: user replaceable function used to validate the range of the numeric input value
+ var isMin = "min" in constraints;
+ var isMax = "max" in constraints;
+ if(isMin || isMax){
+ return (!isMin || this.compare(primitive,constraints.min) >= 0) &&
+ (!isMax || this.compare(primitive,constraints.max) <= 0);
+ }
+ return true; // Boolean
+ },
+
+ isInRange: function(/*Boolean*/ isFocused){
+ // summary: Need to over-ride with your own validation code in subclasses
+ return this.rangeCheck(this.getValue(), this.constraints);
+ },
+
+ isValid: function(/*Boolean*/ isFocused){
+ return this.inherited(arguments) &&
+ ((this._isEmpty(this.textbox.value) && !this.required) || this.isInRange(isFocused)); // Boolean
+ },
+
+ getErrorMessage: function(/*Boolean*/ isFocused){
+ if(dijit.form.RangeBoundTextBox.superclass.isValid.call(this, false) && !this.isInRange(isFocused)){ return this.rangeMessage; } // String
+ return this.inherited(arguments);
+ },
+
+ postMixInProperties: function(){
+ this.inherited(arguments);
+ if(!this.rangeMessage){
+ this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);
+ this.rangeMessage = this.messages.rangeMessage;
+ }
+ },
+
+ postCreate: function(){
+ this.inherited(arguments);
+ if(this.constraints.min !== undefined){
+ dijit.setWaiState(this.focusNode, "valuemin", this.constraints.min);
+ }
+ if(this.constraints.max !== undefined){
+ dijit.setWaiState(this.focusNode, "valuemax", this.constraints.max);
+ }
+ },
+
+ setValue: function(/*Number*/ value, /*Boolean?*/ priorityChange){
+ dijit.setWaiState(this.focusNode, "valuenow", value);
+ this.inherited('setValue', arguments);
+ }
+ }
+);
+
+}
diff --git a/includes/js/dijit/form/_DateTimeTextBox.js b/includes/js/dijit/form/_DateTimeTextBox.js
new file mode 100644
index 0000000..2f3b933
--- /dev/null
+++ b/includes/js/dijit/form/_DateTimeTextBox.js
@@ -0,0 +1,175 @@
+if(!dojo._hasResource["dijit.form._DateTimeTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form._DateTimeTextBox"] = true;
+dojo.provide("dijit.form._DateTimeTextBox");
+
+dojo.require("dojo.date");
+dojo.require("dojo.date.locale");
+dojo.require("dojo.date.stamp");
+dojo.require("dijit.form.ValidationTextBox");
+
+/*=====
+dojo.declare(
+ "dijit.form._DateTimeTextBox.__Constraints",
+ [dijit.form.RangeBoundTextBox.__Constraints, dojo.date.locale.__FormatOptions]
+);
+=====*/
+
+dojo.declare(
+ "dijit.form._DateTimeTextBox",
+ dijit.form.RangeBoundTextBox,
+ {
+ // summary:
+ // A validating, serializable, range-bound date or time text box.
+ //
+ // constraints: dijit.form._DateTimeTextBox.__Constraints
+
+ /*=====
+ constraints: {},
+ ======*/
+ regExpGen: dojo.date.locale.regexp,
+ compare: dojo.date.compare,
+ format: function(/*Date*/ value, /*dojo.date.locale.__FormatOptions*/ constraints){
+ // summary: formats the value as a Date, according to constraints
+ if(!value){ return ''; }
+ return dojo.date.locale.format(value, constraints);
+ },
+ parse: function(/*String*/ value, /*dojo.date.locale.__FormatOptions*/ constraints){
+ // summary: parses the value as a Date, according to constraints
+ return dojo.date.locale.parse(value, constraints) || undefined; /* can't return null to getValue since that's special */
+ },
+
+ serialize: dojo.date.stamp.toISOString,
+
+ // value: Date
+ // The value of this widget as a JavaScript Date object. Use `getValue`/`setValue` to manipulate.
+ // When passed to the parser in markup, must be specified according to `dojo.date.stamp.fromISOString`
+ value: new Date(""), // value.toString()="NaN"
+
+ // popupClass: String
+ // Name of the popup widget class used to select a date/time
+ popupClass: "", // default is no popup = text only
+ _selector: "",
+
+ postMixInProperties: function(){
+ //dijit.form.RangeBoundTextBox.prototype.postMixInProperties.apply(this, arguments);
+ this.inherited(arguments);
+ if(!this.value || this.value.toString() == dijit.form._DateTimeTextBox.prototype.value.toString()){
+ this.value = undefined;
+ }
+ var constraints = this.constraints;
+ constraints.selector = this._selector;
+ constraints.fullYear = true; // see #5465 - always format with 4-digit years
+ var fromISO = dojo.date.stamp.fromISOString;
+ if(typeof constraints.min == "string"){ constraints.min = fromISO(constraints.min); }
+ if(typeof constraints.max == "string"){ constraints.max = fromISO(constraints.max); }
+ },
+
+ _onFocus: function(/*Event*/ evt){
+ // summary: open the TimePicker popup
+ this._open();
+ },
+
+ setValue: function(/*Date*/ value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){
+ // summary:
+ // Sets the date on this textbox. Note that `value` must be a Javascript Date object.
+ this.inherited(arguments);
+ if(this._picker){
+ // #3948: fix blank date on popup only
+ if(!value){value=new Date();}
+ this._picker.setValue(value);
+ }
+ },
+
+ _open: function(){
+ // summary:
+ // opens the TimePicker, and sets the onValueSelected value
+
+ if(this.disabled || this.readOnly || !this.popupClass){return;}
+
+ var textBox = this;
+
+ if(!this._picker){
+ var PopupProto=dojo.getObject(this.popupClass, false);
+ this._picker = new PopupProto({
+ onValueSelected: function(value){
+
+ textBox.focus(); // focus the textbox before the popup closes to avoid reopening the popup
+ setTimeout(dojo.hitch(textBox, "_close"), 1); // allow focus time to take
+
+ // this will cause InlineEditBox and other handlers to do stuff so make sure it's last
+ dijit.form._DateTimeTextBox.superclass.setValue.call(textBox, value, true);
+ },
+ lang: textBox.lang,
+ constraints: textBox.constraints,
+ isDisabledDate: function(/*Date*/ date){
+ // summary:
+ // disables dates outside of the min/max of the _DateTimeTextBox
+ var compare = dojo.date.compare;
+ var constraints = textBox.constraints;
+ return constraints && (constraints.min && (compare(constraints.min, date, "date") > 0) ||
+ (constraints.max && compare(constraints.max, date, "date") < 0));
+ }
+ });
+ this._picker.setValue(this.getValue() || new Date());
+ }
+ if(!this._opened){
+ dijit.popup.open({
+ parent: this,
+ popup: this._picker,
+ around: this.domNode,
+ onCancel: dojo.hitch(this, this._close),
+ onClose: function(){ textBox._opened=false; }
+ });
+ this._opened=true;
+ }
+
+ dojo.marginBox(this._picker.domNode,{ w:this.domNode.offsetWidth });
+ },
+
+ _close: function(){
+ if(this._opened){
+ dijit.popup.close(this._picker);
+ this._opened=false;
+ }
+ },
+
+ _onBlur: function(){
+ // summary: called magically when focus has shifted away from this widget and it's dropdown
+ this._close();
+ if(this._picker){
+ // teardown so that constraints will be rebuilt next time (redundant reference: #6002)
+ this._picker.destroy();
+ delete this._picker;
+ }
+ this.inherited(arguments);
+ // don't focus on <input>. the user has explicitly focused on something else.
+ },
+
+ getDisplayedValue:function(){
+ return this.textbox.value;
+ },
+
+ setDisplayedValue:function(/*String*/ value, /*Boolean?*/ priorityChange){
+ this.setValue(this.parse(value, this.constraints), priorityChange, value);
+ },
+
+ destroy: function(){
+ if(this._picker){
+ this._picker.destroy();
+ delete this._picker;
+ }
+ this.inherited(arguments);
+ },
+
+ _onKeyPress: function(/*Event*/e){
+ if(dijit.form._DateTimeTextBox.superclass._onKeyPress.apply(this, arguments)){
+ if(this._opened && e.keyCode == dojo.keys.ESCAPE && !e.shiftKey && !e.ctrlKey && !e.altKey){
+ this._close();
+ dojo.stopEvent(e);
+ }
+ }
+ }
+ }
+);
+
+}
diff --git a/includes/js/dijit/form/_FormWidget.js b/includes/js/dijit/form/_FormWidget.js
new file mode 100644
index 0000000..5f29df2
--- /dev/null
+++ b/includes/js/dijit/form/_FormWidget.js
@@ -0,0 +1,340 @@
+if(!dojo._hasResource["dijit.form._FormWidget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form._FormWidget"] = true;
+dojo.provide("dijit.form._FormWidget");
+
+dojo.require("dijit._Widget");
+dojo.require("dijit._Templated");
+
+dojo.declare("dijit.form._FormWidget", [dijit._Widget, dijit._Templated],
+{
+ /*
+ Summary:
+ _FormWidget's correspond to native HTML elements such as <checkbox> or <button>.
+ Each _FormWidget represents a single HTML element.
+
+ All these widgets should have these attributes just like native HTML input elements.
+ You can set them during widget construction.
+
+ They also share some common methods.
+ */
+
+ // baseClass: String
+ // Root CSS class of the widget (ex: dijitTextBox), used to add CSS classes of widget
+ // (ex: "dijitTextBox dijitTextBoxInvalid dijitTextBoxFocused dijitTextBoxInvalidFocused")
+ // See _setStateClass().
+ baseClass: "",
+
+ // name: String
+ // Name used when submitting form; same as "name" attribute or plain HTML elements
+ name: "",
+
+ // alt: String
+ // Corresponds to the native HTML <input> element's attribute.
+ alt: "",
+
+ // value: String
+ // Corresponds to the native HTML <input> element's attribute.
+ value: "",
+
+ // type: String
+ // Corresponds to the native HTML <input> element's attribute.
+ type: "text",
+
+ // tabIndex: Integer
+ // Order fields are traversed when user hits the tab key
+ tabIndex: "0",
+
+ // disabled: Boolean
+ // Should this widget respond to user input?
+ // In markup, this is specified as "disabled='disabled'", or just "disabled".
+ disabled: false,
+
+ // 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,
+
+ // intermediateChanges: Boolean
+ // Fires onChange for each value change or only on demand
+ intermediateChanges: false,
+
+ // These mixins assume that the focus node is an INPUT, as many but not all _FormWidgets are.
+ // Don't attempt to mixin the 'type', 'name' attributes here programatically -- they must be declared
+ // directly in the template as read by the parser in order to function. IE is known to specifically
+ // require the 'name' attribute at element creation time.
+ attributeMap: dojo.mixin(dojo.clone(dijit._Widget.prototype.attributeMap),
+ {value:"focusNode", disabled:"focusNode", readOnly:"focusNode", id:"focusNode", tabIndex:"focusNode", alt:"focusNode"}),
+
+ setAttribute: function(/*String*/ attr, /*anything*/ value){
+ this.inherited(arguments);
+ switch(attr){
+ case "disabled":
+ var tabIndexNode = this[this.attributeMap['tabIndex']||'domNode'];
+ if(value){
+ //reset those, because after the domNode is disabled, we can no longer receive
+ //mouse related events, see #4200
+ this._hovering = false;
+ this._active = false;
+ // remove the tabIndex, especially for FF
+ tabIndexNode.removeAttribute('tabIndex');
+ }else{
+ tabIndexNode.setAttribute('tabIndex', this.tabIndex);
+ }
+ dijit.setWaiState(this[this.attributeMap['disabled']||'domNode'], "disabled", value);
+ this._setStateClass();
+ }
+ },
+
+ setDisabled: function(/*Boolean*/ disabled){
+ // summary:
+ // Set disabled state of widget (Deprecated).
+ dojo.deprecated("setDisabled("+disabled+") is deprecated. Use setAttribute('disabled',"+disabled+") instead.", "", "2.0");
+ this.setAttribute('disabled', disabled);
+ },
+
+
+ _onMouse : function(/*Event*/ event){
+ // summary:
+ // Sets _hovering, _active, and stateModifier properties depending on mouse state,
+ // then calls setStateClass() to set appropriate CSS classes for this.domNode.
+ //
+ // To get a different CSS class for hover, send onmouseover and onmouseout events to this method.
+ // To get a different CSS class while mouse button is depressed, send onmousedown to this method.
+
+ var mouseNode = event.currentTarget;
+ if(mouseNode && mouseNode.getAttribute){
+ this.stateModifier = mouseNode.getAttribute("stateModifier") || "";
+ }
+
+ if(!this.disabled){
+ switch(event.type){
+ case "mouseenter":
+ case "mouseover":
+ this._hovering = true;
+ this._active = this._mouseDown;
+ break;
+
+ case "mouseout":
+ case "mouseleave":
+ this._hovering = false;
+ this._active = false;
+ break;
+
+ case "mousedown" :
+ this._active = true;
+ this._mouseDown = true;
+ // set a global event to handle mouseup, so it fires properly
+ // even if the cursor leaves the button
+ var mouseUpConnector = this.connect(dojo.body(), "onmouseup", function(){
+ this._active = false;
+ this._mouseDown = false;
+ this._setStateClass();
+ this.disconnect(mouseUpConnector);
+ });
+ if(this.isFocusable()){ this.focus(); }
+ break;
+ }
+ this._setStateClass();
+ }
+ },
+
+ isFocusable: function(){
+ return !this.disabled && !this.readOnly && this.focusNode && (dojo.style(this.domNode, "display") != "none");
+ },
+
+ focus: function(){
+ setTimeout(dojo.hitch(this, dijit.focus, this.focusNode), 0); // cannot call focus() from an event handler directly
+ },
+
+ _setStateClass: function(){
+ // summary
+ // Update the visual state of the widget by setting the css classes on this.domNode
+ // (or this.stateNode if defined) by combining this.baseClass with
+ // various suffixes that represent the current widget state(s).
+ //
+ // In the case where a widget has multiple
+ // states, it sets the class based on all possible
+ // combinations. For example, an invalid form widget that is being hovered
+ // will be "dijitInput dijitInputInvalid dijitInputHover dijitInputInvalidHover".
+ //
+ // For complex widgets with multiple regions, there can be various hover/active states,
+ // such as "Hover" or "CloseButtonHover" (for tab buttons).
+ // This is controlled by a stateModifier="CloseButton" attribute on the close button node.
+ //
+ // The widget may have one or more of the following states, determined
+ // by this.state, this.checked, this.valid, and this.selected:
+ // Error - ValidationTextBox sets this.state to "Error" if the current input value is invalid
+ // Checked - ex: a checkmark or a ToggleButton in a checked state, will have this.checked==true
+ // Selected - ex: currently selected tab will have this.selected==true
+ //
+ // In addition, it may have one or more of the following states,
+ // based on this.disabled and flags set in _onMouse (this._active, this._hovering, this._focused):
+ // Disabled - if the widget is disabled
+ // Active - if the mouse (or space/enter key?) is being pressed down
+ // Focused - if the widget has focus
+ // Hover - if the mouse is over the widget
+
+ // Get original (non state related, non baseClass related) class specified in template
+ if(!("staticClass" in this)){
+ this.staticClass = (this.stateNode||this.domNode).className;
+ }
+
+ // Compute new set of classes
+ var classes = [ this.baseClass ];
+
+ function multiply(modifier){
+ classes=classes.concat(dojo.map(classes, function(c){ return c+modifier; }), "dijit"+modifier);
+ }
+
+ if(this.checked){
+ multiply("Checked");
+ }
+ if(this.state){
+ multiply(this.state);
+ }
+ if(this.selected){
+ multiply("Selected");
+ }
+
+ if(this.disabled){
+ multiply("Disabled");
+ }else if(this.readOnly){
+ multiply("ReadOnly");
+ }else if(this._active){
+ multiply(this.stateModifier+"Active");
+ }else{
+ if(this._focused){
+ multiply("Focused");
+ }
+ if(this._hovering){
+ multiply(this.stateModifier+"Hover");
+ }
+ }
+
+ (this.stateNode || this.domNode).className = this.staticClass + " " + classes.join(" ");
+ },
+
+ onChange: function(newValue){
+ // summary: callback when value is changed
+ },
+
+ _onChangeMonitor: 'value',
+ _onChangeActive: false,
+
+ _handleOnChange: function(/*anything*/ newValue, /*Boolean, optional*/ priorityChange){
+ // summary: set the value of the widget.
+ this._lastValue = newValue;
+ if(this._lastValueReported == undefined && (priorityChange === null || !this._onChangeActive)){
+ this._resetValue = this._lastValueReported = newValue;
+ }
+ if((this.intermediateChanges || priorityChange || priorityChange === undefined) &&
+ ((newValue && newValue.toString)?newValue.toString():newValue) !== ((this._lastValueReported && this._lastValueReported.toString)?this._lastValueReported.toString():this._lastValueReported)){
+ this._lastValueReported = newValue;
+ if(this._onChangeActive){ this.onChange(newValue); }
+ }
+ },
+
+ reset: function(){
+ this._hasBeenBlurred = false;
+ if(this.setValue && !this._getValueDeprecated){
+ this.setValue(this._resetValue, true);
+ }else if(this._onChangeMonitor){
+ this.setAttribute(this._onChangeMonitor, (this._resetValue !== undefined && this._resetValue !== null)? this._resetValue : '');
+ }
+ },
+
+ create: function(){
+ this.inherited(arguments);
+ this._onChangeActive = true;
+ this._setStateClass();
+ },
+
+ destroy: function(){
+ if(this._layoutHackHandle){
+ clearTimeout(this._layoutHackHandle);
+ }
+ this.inherited(arguments);
+ },
+
+ setValue: function(/*String*/ value){
+ dojo.deprecated("dijit.form._FormWidget:setValue("+value+") is deprecated. Use setAttribute('value',"+value+") instead.", "", "2.0");
+ this.setAttribute('value', value);
+ },
+
+ _getValueDeprecated: true, // Form uses this, remove when getValue is removed
+ getValue: function(){
+ dojo.deprecated("dijit.form._FormWidget:getValue() is deprecated. Use widget.value instead.", "", "2.0");
+ return this.value;
+ },
+
+ _layoutHack: function(){
+ // summary: work around table sizing bugs on FF2 by forcing redraw
+ if(dojo.isFF == 2){
+ var node=this.domNode;
+ var old = node.style.opacity;
+ node.style.opacity = "0.999";
+ this._layoutHackHandle = setTimeout(dojo.hitch(this, function(){
+ this._layoutHackHandle = null;
+ node.style.opacity = old;
+ }), 0);
+ }
+ }
+});
+
+dojo.declare("dijit.form._FormValueWidget", dijit.form._FormWidget,
+{
+ /*
+ Summary:
+ _FormValueWidget's correspond to native HTML elements such as <input> or <select> that have user changeable values.
+ Each _ValueWidget represents a single input value, and has a (possibly hidden) <input> element,
+ to which it serializes its input value, so that form submission (either normal submission or via FormBind?)
+ works as expected.
+ */
+
+ attributeMap: dojo.mixin(dojo.clone(dijit.form._FormWidget.prototype.attributeMap),
+ {value:""}),
+
+ postCreate: function(){
+ this.setValue(this.value, null);
+ },
+
+ setValue: function(/*anything*/ newValue, /*Boolean, optional*/ priorityChange){
+ // summary: set the value of the widget.
+ this.value = newValue;
+ this._handleOnChange(newValue, priorityChange);
+ },
+
+ _getValueDeprecated: false, // remove when _FormWidget:getValue is removed
+ getValue: function(){
+ // summary: get the value of the widget.
+ return this._lastValue;
+ },
+
+ undo: function(){
+ // summary: restore the value to the last value passed to onChange
+ this.setValue(this._lastValueReported, false);
+ },
+
+ _valueChanged: function(){
+ var v = this.getValue();
+ var lv = this._lastValueReported;
+ // Equality comparison of objects such as dates are done by reference so
+ // two distinct objects are != even if they have the same data. So use
+ // toStrings in case the values are objects.
+ return ((v !== null && (v !== undefined) && v.toString)?v.toString():'') !== ((lv !== null && (lv !== undefined) && lv.toString)?lv.toString():'');
+ },
+
+ _onKeyPress: function(e){
+ if(e.keyCode == dojo.keys.ESCAPE && !e.shiftKey && !e.ctrlKey && !e.altKey){
+ if(this._valueChanged()){
+ this.undo();
+ dojo.stopEvent(e);
+ return false;
+ }
+ }
+ return true;
+ }
+});
+
+}
diff --git a/includes/js/dijit/form/_Spinner.js b/includes/js/dijit/form/_Spinner.js
new file mode 100644
index 0000000..6837552
--- /dev/null
+++ b/includes/js/dijit/form/_Spinner.js
@@ -0,0 +1,117 @@
+if(!dojo._hasResource["dijit.form._Spinner"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.form._Spinner"] = true;
+dojo.provide("dijit.form._Spinner");
+
+dojo.require("dijit.form.ValidationTextBox");
+
+dojo.declare(
+ "dijit.form._Spinner",
+ dijit.form.RangeBoundTextBox,
+ {
+
+ // summary: Mixin for validation widgets with a spinner
+ // description: This class basically (conceptually) extends dijit.form.ValidationTextBox.
+ // It modifies the template to have up/down arrows, and provides related handling code.
+
+ // defaultTimeout: Number
+ // number of milliseconds before a held key or button becomes 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,
+
+ // smallDelta: Number
+ // adjust the value by this much when spinning using the arrow keys/buttons
+ smallDelta: 1,
+ // largeDelta: Number
+ // adjust the value by this much when spinning using the PgUp/Dn keys
+ largeDelta: 10,
+
+ templateString:"<div class=\"dijit dijitReset dijitInlineTable dijitLeft\"\n\tid=\"widget_${id}\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\" waiRole=\"presentation\"\n\t><div class=\"dijitInputLayoutContainer\"\n\t\t><div class=\"dijitReset dijitSpinnerButtonContainer\"\n\t\t\t>&nbsp;<div class=\"dijitReset dijitLeft dijitButtonNode dijitArrowButton dijitUpArrowButton\"\n\t\t\t\tdojoAttachPoint=\"upArrowNode\"\n\t\t\t\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse\"\n\t\t\t\tstateModifier=\"UpArrow\"\n\t\t\t\t><div class=\"dijitArrowButtonInner\">&thinsp;</div\n\t\t\t\t><div class=\"dijitArrowButtonChar\">&#9650;</div\n\t\t\t></div\n\t\t\t><div class=\"dijitReset dijitLeft dijitButtonNode dijitArrowButton dijitDownArrowButton\"\n\t\t\t\tdojoAttachPoint=\"downArrowNode\"\n\t\t\t\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse\"\n\t\t\t\tstateModifier=\"DownArrow\"\n\t\t\t\t><div class=\"dijitArrowButtonInner\">&thinsp;</div\n\t\t\t\t><div class=\"dijitArrowButtonChar\">&#9660;</div\n\t\t\t></div\n\t\t></div\n\t\t><div class=\"dijitReset dijitValidationIcon\"><br></div\n\t\t><div class=\"dijitReset dijitValidationIconText\">&Chi;</div\n\t\t><div class=\"dijitReset dijitInputField\"\n\t\t\t><input class='dijitReset' dojoAttachPoint=\"textbox,focusNode\" type=\"${type}\" dojoAttachEvent=\"onfocus:_update,onkeyup:_onkeyup,onkeypress:_onKeyPress\"\n\t\t\t\twaiRole=\"spinbutton\" autocomplete=\"off\" name=\"${name}\"\n\t\t/></div\n\t></div\n></div>\n",
+ baseClass: "dijitSpinner",
+
+ adjust: function(/* Object */ val, /*Number*/ delta){
+ // summary: user replaceable function used to adjust a primitive value(Number/Date/...) by the delta amount specified
+ // the val is adjusted in a way that makes sense to the object type
+ return val;
+ },
+
+ _arrowState: function(/*Node*/ node, /*Boolean*/ pressed){
+ this._active = pressed;
+ this.stateModifier = node.getAttribute("stateModifier") || "";
+ this._setStateClass();
+ },
+
+ _arrowPressed: function(/*Node*/ nodePressed, /*Number*/ direction){
+ if(this.disabled || this.readOnly){ return; }
+ this._arrowState(nodePressed, true);
+ this.setValue(this.adjust(this.getValue(), direction*this.smallDelta), false);
+ dijit.selectInputText(this.textbox, this.textbox.value.length);
+ },
+
+ _arrowReleased: function(/*Node*/ node){
+ this._wheelTimer = null;
+ if(this.disabled || this.readOnly){ return; }
+ this._arrowState(node, false);
+ },
+
+ _typematicCallback: function(/*Number*/ count, /*DOMNode*/ node, /*Event*/ evt){
+ if(node == this.textbox){ node = (evt.keyCode == dojo.keys.UP_ARROW) ? this.upArrowNode : this.downArrowNode; }
+ if(count == -1){ this._arrowReleased(node); }
+ else{ this._arrowPressed(node, (node == this.upArrowNode) ? 1 : -1); }
+ },
+
+ _wheelTimer: null,
+ _mouseWheeled: function(/*Event*/ evt){
+ dojo.stopEvent(evt);
+ var scrollAmount = 0;
+ if(typeof evt.wheelDelta == 'number'){ // IE
+ scrollAmount = evt.wheelDelta;
+ }else if(typeof evt.detail == 'number'){ // Mozilla+Firefox
+ scrollAmount = -evt.detail;
+ }
+ var node, dir;
+ if(scrollAmount > 0){
+ node = this.upArrowNode;
+ dir = +1;
+ }else if(scrollAmount < 0){
+ node = this.downArrowNode;
+ dir = -1;
+ }else{ return; }
+ this._arrowPressed(node, dir);
+ if(this._wheelTimer != null){
+ clearTimeout(this._wheelTimer);
+ }
+ var _this = this;
+ this._wheelTimer = setTimeout(function(){_this._arrowReleased(node);}, 50);
+ },
+
+ postCreate: function(){
+ this.inherited('postCreate', arguments);
+
+ // extra listeners
+ this.connect(this.textbox, dojo.isIE ? "onmousewheel" : 'DOMMouseScroll', "_mouseWheeled");
+ this._connects.push(dijit.typematic.addListener(this.upArrowNode, this.textbox, {keyCode:dojo.keys.UP_ARROW,ctrlKey:false,altKey:false,shiftKey:false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout));
+ this._connects.push(dijit.typematic.addListener(this.downArrowNode, this.textbox, {keyCode:dojo.keys.DOWN_ARROW,ctrlKey:false,altKey:false,shiftKey:false}, this, "_typematicCallback", this.timeoutChangeRate, this.defaultTimeout));
+ if(dojo.isIE){
+ // When spinner is moved from hidden to visible, call _setStateClass to remind IE to render it. (#6123)
+ var _this = this;
+ this.connect(this.domNode, "onresize",
+ function(){ setTimeout(dojo.hitch(_this,
+ function(){
+ // cause the IE expressions to rerun
+ this.upArrowNode.style.behavior = '';
+ this.downArrowNode.style.behavior = '';
+ // cause IE to rerender
+ this._setStateClass();
+ }), 0);
+ }
+ );
+ }
+ }
+});
+
+}
diff --git a/includes/js/dijit/form/nls/ComboBox.js b/includes/js/dijit/form/nls/ComboBox.js
new file mode 100644
index 0000000..49bba39
--- /dev/null
+++ b/includes/js/dijit/form/nls/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"Previous choices","nextMessage":"More choices"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/Textarea.js b/includes/js/dijit/form/nls/Textarea.js
new file mode 100644
index 0000000..4b0e996
--- /dev/null
+++ b/includes/js/dijit/form/nls/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"edit area","iframeFocusTitle":"edit area frame"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/ar/ComboBox.js b/includes/js/dijit/form/nls/ar/ComboBox.js
new file mode 100644
index 0000000..d165d7e
--- /dev/null
+++ b/includes/js/dijit/form/nls/ar/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"الاختيارات السابقة ","nextMessage":"مزيد من الاختيارات "}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/ar/Textarea.js b/includes/js/dijit/form/nls/ar/Textarea.js
new file mode 100644
index 0000000..fe623c6
--- /dev/null
+++ b/includes/js/dijit/form/nls/ar/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"مساحة التحرير","iframeFocusTitle":"اطار مساحة التحرير"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/ar/validate.js b/includes/js/dijit/form/nls/ar/validate.js
new file mode 100644
index 0000000..81106f5
--- /dev/null
+++ b/includes/js/dijit/form/nls/ar/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"هذه القيمة ليس بالمدى الصحيح. ","invalidMessage":"القيمة التي تم ادخالها غير صحيحة. ","missingMessage":"يجب ادخال هذه القيمة. "}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/cs/ComboBox.js b/includes/js/dijit/form/nls/cs/ComboBox.js
new file mode 100644
index 0000000..84e0841
--- /dev/null
+++ b/includes/js/dijit/form/nls/cs/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"Předchozí volby","nextMessage":"Další volby"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/cs/Textarea.js b/includes/js/dijit/form/nls/cs/Textarea.js
new file mode 100644
index 0000000..8a75ddc
--- /dev/null
+++ b/includes/js/dijit/form/nls/cs/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"oblast úprav","iframeFocusTitle":"rámec oblasti úprav"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/cs/validate.js b/includes/js/dijit/form/nls/cs/validate.js
new file mode 100644
index 0000000..7bb7b9e
--- /dev/null
+++ b/includes/js/dijit/form/nls/cs/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"Tato hodnota je mimo rozsah.","invalidMessage":"Zadaná hodnota není platná.","missingMessage":"Tato hodnota je vyžadována."}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/da/ComboBox.js b/includes/js/dijit/form/nls/da/ComboBox.js
new file mode 100644
index 0000000..4ddc10d
--- /dev/null
+++ b/includes/js/dijit/form/nls/da/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"Forrige valg","nextMessage":"Flere valg"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/da/Textarea.js b/includes/js/dijit/form/nls/da/Textarea.js
new file mode 100644
index 0000000..244c210
--- /dev/null
+++ b/includes/js/dijit/form/nls/da/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"redigeringsområde","iframeFocusTitle":"ramme om redigeringsområde"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/da/validate.js b/includes/js/dijit/form/nls/da/validate.js
new file mode 100644
index 0000000..2874dd8
--- /dev/null
+++ b/includes/js/dijit/form/nls/da/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"Værdien er uden for intervallet.","invalidMessage":"Den angivne værdi er ugyldig.","missingMessage":"Værdien er påkrævet."}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/de/ComboBox.js b/includes/js/dijit/form/nls/de/ComboBox.js
new file mode 100644
index 0000000..6cce34b
--- /dev/null
+++ b/includes/js/dijit/form/nls/de/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"Vorherige Auswahl","nextMessage":"Weitere Auswahlmöglichkeiten"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/de/Textarea.js b/includes/js/dijit/form/nls/de/Textarea.js
new file mode 100644
index 0000000..2cf75db
--- /dev/null
+++ b/includes/js/dijit/form/nls/de/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"Editierbereich","iframeFocusTitle":"Rahmen für Editierbereich"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/de/validate.js b/includes/js/dijit/form/nls/de/validate.js
new file mode 100644
index 0000000..597796d
--- /dev/null
+++ b/includes/js/dijit/form/nls/de/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"Dieser Wert liegt außerhalb des gültigen Bereichs. ","invalidMessage":"Der eingegebene Wert ist ungültig. ","missingMessage":"Dieser Wert ist erforderlich."}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/el/ComboBox.js b/includes/js/dijit/form/nls/el/ComboBox.js
new file mode 100644
index 0000000..ec294d1
--- /dev/null
+++ b/includes/js/dijit/form/nls/el/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"Προηγούμενες επιλογές","nextMessage":"Περισσότερες επιλογές"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/el/Textarea.js b/includes/js/dijit/form/nls/el/Textarea.js
new file mode 100644
index 0000000..9ce37a9
--- /dev/null
+++ b/includes/js/dijit/form/nls/el/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"περιοχή επεξεργασίας","iframeFocusTitle":"πλαίσιο περιοχής επεξεργασίας"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/el/validate.js b/includes/js/dijit/form/nls/el/validate.js
new file mode 100644
index 0000000..cc57d55
--- /dev/null
+++ b/includes/js/dijit/form/nls/el/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"Η τιμή αυτή δεν ανήκει στο εύρος έγκυρων τιμών.","invalidMessage":"Η τιμή που καταχωρήσατε δεν είναι έγκυρη.","missingMessage":"Η τιμή αυτή πρέπει απαραίτητα να καθοριστεί."}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/es/ComboBox.js b/includes/js/dijit/form/nls/es/ComboBox.js
new file mode 100644
index 0000000..5bf69f9
--- /dev/null
+++ b/includes/js/dijit/form/nls/es/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"Opciones anteriores","nextMessage":"Más opciones"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/es/Textarea.js b/includes/js/dijit/form/nls/es/Textarea.js
new file mode 100644
index 0000000..f92a50f
--- /dev/null
+++ b/includes/js/dijit/form/nls/es/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"área de edición","iframeFocusTitle":"marco del área de edición"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/es/validate.js b/includes/js/dijit/form/nls/es/validate.js
new file mode 100644
index 0000000..65e190e
--- /dev/null
+++ b/includes/js/dijit/form/nls/es/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"Este valor está fuera del intervalo.","invalidMessage":"El valor especificado no es válido.","missingMessage":"Este valor es necesario."}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/fi/ComboBox.js b/includes/js/dijit/form/nls/fi/ComboBox.js
new file mode 100644
index 0000000..6d9b830
--- /dev/null
+++ b/includes/js/dijit/form/nls/fi/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"Edelliset valinnat","nextMessage":"Lisää valintoja"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/fi/Textarea.js b/includes/js/dijit/form/nls/fi/Textarea.js
new file mode 100644
index 0000000..5efaee9
--- /dev/null
+++ b/includes/js/dijit/form/nls/fi/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"muokkausalue","iframeFocusTitle":"muokkausalueen kehys"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/fi/validate.js b/includes/js/dijit/form/nls/fi/validate.js
new file mode 100644
index 0000000..276efcd
--- /dev/null
+++ b/includes/js/dijit/form/nls/fi/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"Tämä arvo on sallitun alueen ulkopuolella.","invalidMessage":"Annettu arvo ei kelpaa.","missingMessage":"Tämä arvo on pakollinen."}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/fr/ComboBox.js b/includes/js/dijit/form/nls/fr/ComboBox.js
new file mode 100644
index 0000000..14b3976
--- /dev/null
+++ b/includes/js/dijit/form/nls/fr/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"Choix précédents","nextMessage":"Plus de choix"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/fr/Textarea.js b/includes/js/dijit/form/nls/fr/Textarea.js
new file mode 100644
index 0000000..4abb6c3
--- /dev/null
+++ b/includes/js/dijit/form/nls/fr/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"zone d'édition","iframeFocusTitle":"cadre de la zone d'édition"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/fr/validate.js b/includes/js/dijit/form/nls/fr/validate.js
new file mode 100644
index 0000000..95a0169
--- /dev/null
+++ b/includes/js/dijit/form/nls/fr/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"Cette valeur n'est pas comprise dans la plage autorisée.","invalidMessage":"La valeur indiquée n'est pas correcte.","missingMessage":"Cette valeur est requise."}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/he/ComboBox.js b/includes/js/dijit/form/nls/he/ComboBox.js
new file mode 100644
index 0000000..169d0f5
--- /dev/null
+++ b/includes/js/dijit/form/nls/he/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"האפשרויות הקודמות","nextMessage":"אפשרויות נוספות"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/he/Textarea.js b/includes/js/dijit/form/nls/he/Textarea.js
new file mode 100644
index 0000000..809eadf
--- /dev/null
+++ b/includes/js/dijit/form/nls/he/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"אזור עריכה","iframeFocusTitle":"מסגרת אזור עריכה"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/he/validate.js b/includes/js/dijit/form/nls/he/validate.js
new file mode 100644
index 0000000..5b58183
--- /dev/null
+++ b/includes/js/dijit/form/nls/he/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"הערך מחוץ לטווח. ","invalidMessage":"הערך שצוין אינו חוקי.","missingMessage":"זהו ערך דרוש. "}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/hu/ComboBox.js b/includes/js/dijit/form/nls/hu/ComboBox.js
new file mode 100644
index 0000000..4b6a620
--- /dev/null
+++ b/includes/js/dijit/form/nls/hu/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"Előző menüpontok","nextMessage":"További menüpontok"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/hu/Textarea.js b/includes/js/dijit/form/nls/hu/Textarea.js
new file mode 100644
index 0000000..9b4ca01
--- /dev/null
+++ b/includes/js/dijit/form/nls/hu/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"szerkesztési terület","iframeFocusTitle":"szerkesztési terület keret"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/hu/validate.js b/includes/js/dijit/form/nls/hu/validate.js
new file mode 100644
index 0000000..35edb8b
--- /dev/null
+++ b/includes/js/dijit/form/nls/hu/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"Az érték kívül van a megengedett tartományon. ","invalidMessage":"A megadott érték érvénytelen. ","missingMessage":"Meg kell adni egy értéket. "}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/it/ComboBox.js b/includes/js/dijit/form/nls/it/ComboBox.js
new file mode 100644
index 0000000..9f67072
--- /dev/null
+++ b/includes/js/dijit/form/nls/it/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"Scelte precedenti","nextMessage":"Altre scelte"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/it/Textarea.js b/includes/js/dijit/form/nls/it/Textarea.js
new file mode 100644
index 0000000..1b14ecc
--- /dev/null
+++ b/includes/js/dijit/form/nls/it/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"modifica area","iframeFocusTitle":"modifica frame area"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/it/validate.js b/includes/js/dijit/form/nls/it/validate.js
new file mode 100644
index 0000000..af7227f
--- /dev/null
+++ b/includes/js/dijit/form/nls/it/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"Questo valore non è compreso nell'intervallo.","invalidMessage":"Il valore immesso non è valido.","missingMessage":"Questo valore è obbligatorio."}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/ja/ComboBox.js b/includes/js/dijit/form/nls/ja/ComboBox.js
new file mode 100644
index 0000000..6b34170
--- /dev/null
+++ b/includes/js/dijit/form/nls/ja/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"以前の選択項目","nextMessage":"追加の選択項目"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/ja/Textarea.js b/includes/js/dijit/form/nls/ja/Textarea.js
new file mode 100644
index 0000000..8a52f4a
--- /dev/null
+++ b/includes/js/dijit/form/nls/ja/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"編集域","iframeFocusTitle":"編集域フレーム"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/ja/validate.js b/includes/js/dijit/form/nls/ja/validate.js
new file mode 100644
index 0000000..450cd7e
--- /dev/null
+++ b/includes/js/dijit/form/nls/ja/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"この値は範囲外です。","invalidMessage":"入力した値は無効です。","missingMessage":"この値は必須です。"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/ko/ComboBox.js b/includes/js/dijit/form/nls/ko/ComboBox.js
new file mode 100644
index 0000000..87d0f06
--- /dev/null
+++ b/includes/js/dijit/form/nls/ko/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"이전 선택사항","nextMessage":"기타 선택사항"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/ko/Textarea.js b/includes/js/dijit/form/nls/ko/Textarea.js
new file mode 100644
index 0000000..5c4e916
--- /dev/null
+++ b/includes/js/dijit/form/nls/ko/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"편집 영역","iframeFocusTitle":"편집 영역 프레임"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/ko/validate.js b/includes/js/dijit/form/nls/ko/validate.js
new file mode 100644
index 0000000..c76c676
--- /dev/null
+++ b/includes/js/dijit/form/nls/ko/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"이 값은 범위를 벗어납니다.","invalidMessage":"입력된 값이 올바르지 않습니다.","missingMessage":"이 값은 필수입니다."}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/nb/ComboBox.js b/includes/js/dijit/form/nls/nb/ComboBox.js
new file mode 100644
index 0000000..de14554
--- /dev/null
+++ b/includes/js/dijit/form/nls/nb/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"Tidligere valg","nextMessage":"Flere valg"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/nb/Textarea.js b/includes/js/dijit/form/nls/nb/Textarea.js
new file mode 100644
index 0000000..16fadf5
--- /dev/null
+++ b/includes/js/dijit/form/nls/nb/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"redigeringsområde","iframeFocusTitle":"ramme for redigeringsområde"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/nb/validate.js b/includes/js/dijit/form/nls/nb/validate.js
new file mode 100644
index 0000000..2fe96f2
--- /dev/null
+++ b/includes/js/dijit/form/nls/nb/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"Denne verdien er utenfor gyldig område.","invalidMessage":"Den angitte verdien er ikke gyldig.","missingMessage":"Denne verdien er obligatorisk."}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/nl/ComboBox.js b/includes/js/dijit/form/nls/nl/ComboBox.js
new file mode 100644
index 0000000..b5885d7
--- /dev/null
+++ b/includes/js/dijit/form/nls/nl/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"Eerdere opties","nextMessage":"Meer opties"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/nl/Textarea.js b/includes/js/dijit/form/nls/nl/Textarea.js
new file mode 100644
index 0000000..d13c3a6
--- /dev/null
+++ b/includes/js/dijit/form/nls/nl/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"veld bewerken","iframeFocusTitle":"veldkader bewerken"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/nl/validate.js b/includes/js/dijit/form/nls/nl/validate.js
new file mode 100644
index 0000000..b3062c1
--- /dev/null
+++ b/includes/js/dijit/form/nls/nl/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"Deze waarde is niet toegestaan.","invalidMessage":"De opgegeven waarde is ongeldig.","missingMessage":"Deze waarde is verplicht."}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/pl/ComboBox.js b/includes/js/dijit/form/nls/pl/ComboBox.js
new file mode 100644
index 0000000..f2b4b08
--- /dev/null
+++ b/includes/js/dijit/form/nls/pl/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"Poprzednie wybory","nextMessage":"Więcej wyborów"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/pl/Textarea.js b/includes/js/dijit/form/nls/pl/Textarea.js
new file mode 100644
index 0000000..8948800
--- /dev/null
+++ b/includes/js/dijit/form/nls/pl/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"obszar edycji","iframeFocusTitle":"ramka obszaru edycji"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/pl/validate.js b/includes/js/dijit/form/nls/pl/validate.js
new file mode 100644
index 0000000..cf05d2f
--- /dev/null
+++ b/includes/js/dijit/form/nls/pl/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"Ta wartość jest spoza zakresu.","invalidMessage":"Wprowadzona wartość jest niepoprawna.","missingMessage":"Ta wartość jest wymagana."}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/pt-pt/ComboBox.js b/includes/js/dijit/form/nls/pt-pt/ComboBox.js
new file mode 100644
index 0000000..2540542
--- /dev/null
+++ b/includes/js/dijit/form/nls/pt-pt/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"Opções anteriores","nextMessage":"Mais opções"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/pt-pt/Textarea.js b/includes/js/dijit/form/nls/pt-pt/Textarea.js
new file mode 100644
index 0000000..bcd75e7
--- /dev/null
+++ b/includes/js/dijit/form/nls/pt-pt/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"área de edição","iframeFocusTitle":"painel da área de edição"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/pt-pt/validate.js b/includes/js/dijit/form/nls/pt-pt/validate.js
new file mode 100644
index 0000000..c9312e2
--- /dev/null
+++ b/includes/js/dijit/form/nls/pt-pt/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"Este valor encontra-se fora do intervalo.","invalidMessage":"O valor introduzido não é válido.","missingMessage":"O valor é requerido."}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/pt/ComboBox.js b/includes/js/dijit/form/nls/pt/ComboBox.js
new file mode 100644
index 0000000..2540542
--- /dev/null
+++ b/includes/js/dijit/form/nls/pt/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"Opções anteriores","nextMessage":"Mais opções"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/pt/Textarea.js b/includes/js/dijit/form/nls/pt/Textarea.js
new file mode 100644
index 0000000..7fc20ab
--- /dev/null
+++ b/includes/js/dijit/form/nls/pt/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"área de edição","iframeFocusTitle":"quadro da área de edição"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/pt/validate.js b/includes/js/dijit/form/nls/pt/validate.js
new file mode 100644
index 0000000..fab945e
--- /dev/null
+++ b/includes/js/dijit/form/nls/pt/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"Este valor está fora dos limites.","invalidMessage":"O valor inserido não é válido.","missingMessage":"Este valor é necessário."}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/ru/ComboBox.js b/includes/js/dijit/form/nls/ru/ComboBox.js
new file mode 100644
index 0000000..193f4ee
--- /dev/null
+++ b/includes/js/dijit/form/nls/ru/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"Предыдущие варианты","nextMessage":"Следующие варианты"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/ru/Textarea.js b/includes/js/dijit/form/nls/ru/Textarea.js
new file mode 100644
index 0000000..ad7ad22
--- /dev/null
+++ b/includes/js/dijit/form/nls/ru/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"область редактирования","iframeFocusTitle":"фрейм области редактирования"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/ru/validate.js b/includes/js/dijit/form/nls/ru/validate.js
new file mode 100644
index 0000000..35fb5ca
--- /dev/null
+++ b/includes/js/dijit/form/nls/ru/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"Это значение вне диапазона.","invalidMessage":"Указано недопустимое значение.","missingMessage":"Это обязательное значение."}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/sv/ComboBox.js b/includes/js/dijit/form/nls/sv/ComboBox.js
new file mode 100644
index 0000000..860bf75
--- /dev/null
+++ b/includes/js/dijit/form/nls/sv/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"Föregående alternativ","nextMessage":"Fler alternativ"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/sv/Textarea.js b/includes/js/dijit/form/nls/sv/Textarea.js
new file mode 100644
index 0000000..9e508ac
--- /dev/null
+++ b/includes/js/dijit/form/nls/sv/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"redigeringsområde","iframeFocusTitle":"redigeringsområdesram"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/sv/validate.js b/includes/js/dijit/form/nls/sv/validate.js
new file mode 100644
index 0000000..8c1b537
--- /dev/null
+++ b/includes/js/dijit/form/nls/sv/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"Värdet är utanför intervallet.","invalidMessage":"Det angivna värdet är ogiltigt.","missingMessage":"Värdet är obligatoriskt."}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/tr/ComboBox.js b/includes/js/dijit/form/nls/tr/ComboBox.js
new file mode 100644
index 0000000..46f71dc
--- /dev/null
+++ b/includes/js/dijit/form/nls/tr/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"Önceki seçenekler","nextMessage":"Diğer seçenekler"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/tr/Textarea.js b/includes/js/dijit/form/nls/tr/Textarea.js
new file mode 100644
index 0000000..3f2b5e7
--- /dev/null
+++ b/includes/js/dijit/form/nls/tr/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"düzenleme alanı","iframeFocusTitle":"düzenleme alanı çerçevesi"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/tr/validate.js b/includes/js/dijit/form/nls/tr/validate.js
new file mode 100644
index 0000000..838dbda
--- /dev/null
+++ b/includes/js/dijit/form/nls/tr/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"Bu değer aralık dışında.","invalidMessage":"Girilen değer geçersiz.","missingMessage":"Bu değer gerekli."}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/validate.js b/includes/js/dijit/form/nls/validate.js
new file mode 100644
index 0000000..29a1a47
--- /dev/null
+++ b/includes/js/dijit/form/nls/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"This value is out of range.","invalidMessage":"The value entered is not valid.","missingMessage":"This value is required."}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/zh-tw/ComboBox.js b/includes/js/dijit/form/nls/zh-tw/ComboBox.js
new file mode 100644
index 0000000..ead5fa6
--- /dev/null
+++ b/includes/js/dijit/form/nls/zh-tw/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"前一個選擇項","nextMessage":"其他選擇項"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/zh-tw/Textarea.js b/includes/js/dijit/form/nls/zh-tw/Textarea.js
new file mode 100644
index 0000000..cb7abda
--- /dev/null
+++ b/includes/js/dijit/form/nls/zh-tw/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"編輯區","iframeFocusTitle":"編輯區框"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/zh-tw/validate.js b/includes/js/dijit/form/nls/zh-tw/validate.js
new file mode 100644
index 0000000..b398a31
--- /dev/null
+++ b/includes/js/dijit/form/nls/zh-tw/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"此值超出範圍。","invalidMessage":"輸入的值無效。","missingMessage":"必須提供此值。"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/zh/ComboBox.js b/includes/js/dijit/form/nls/zh/ComboBox.js
new file mode 100644
index 0000000..7cc92cf
--- /dev/null
+++ b/includes/js/dijit/form/nls/zh/ComboBox.js
@@ -0,0 +1 @@
+({"previousMessage":"先前选项","nextMessage":"更多选项"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/zh/Textarea.js b/includes/js/dijit/form/nls/zh/Textarea.js
new file mode 100644
index 0000000..e1cf172
--- /dev/null
+++ b/includes/js/dijit/form/nls/zh/Textarea.js
@@ -0,0 +1 @@
+({"iframeEditTitle":"编辑区","iframeFocusTitle":"编辑区框架"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/nls/zh/validate.js b/includes/js/dijit/form/nls/zh/validate.js
new file mode 100644
index 0000000..e2c01f5
--- /dev/null
+++ b/includes/js/dijit/form/nls/zh/validate.js
@@ -0,0 +1 @@
+({"rangeMessage":"此值超出范围。","invalidMessage":"输入的值无效。","missingMessage":"此值是必需值。"}) \ No newline at end of file
diff --git a/includes/js/dijit/form/templates/Button.html b/includes/js/dijit/form/templates/Button.html
new file mode 100644
index 0000000..09dbad8
--- /dev/null
+++ b/includes/js/dijit/form/templates/Button.html
@@ -0,0 +1,11 @@
+<div class="dijit dijitReset dijitLeft dijitInline"
+ dojoAttachEvent="onclick:_onButtonClick,onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse"
+ waiRole="presentation"
+ ><button class="dijitReset dijitStretch dijitButtonNode dijitButtonContents" dojoAttachPoint="focusNode,titleNode"
+ type="${type}" waiRole="button" waiState="labelledby-${id}_label"
+ ><span class="dijitReset dijitInline ${iconClass}" dojoAttachPoint="iconNode"
+ ><span class="dijitReset dijitToggleButtonIconChar">&#10003;</span
+ ></span
+ ><div class="dijitReset dijitInline"><center class="dijitReset dijitButtonText" id="${id}_label" dojoAttachPoint="containerNode">${label}</center></div
+ ></button
+></div>
diff --git a/includes/js/dijit/form/templates/CheckBox.html b/includes/js/dijit/form/templates/CheckBox.html
new file mode 100644
index 0000000..580b820
--- /dev/null
+++ b/includes/js/dijit/form/templates/CheckBox.html
@@ -0,0 +1,7 @@
+<div class="dijitReset dijitInline" waiRole="presentation"
+ ><input
+ type="${type}" name="${name}"
+ class="dijitReset dijitCheckBoxInput"
+ dojoAttachPoint="focusNode"
+ dojoAttachEvent="onmouseover:_onMouse,onmouseout:_onMouse,onclick:_onClick"
+/></div>
diff --git a/includes/js/dijit/form/templates/ComboBox.html b/includes/js/dijit/form/templates/ComboBox.html
new file mode 100644
index 0000000..b957b54
--- /dev/null
+++ b/includes/js/dijit/form/templates/ComboBox.html
@@ -0,0 +1,19 @@
+<div class="dijit dijitReset dijitInlineTable dijitLeft"
+ id="widget_${id}"
+ dojoAttachEvent="onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse" dojoAttachPoint="comboNode" waiRole="combobox" tabIndex="-1"
+ ><div style="overflow:hidden;"
+ ><div class='dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton'
+ dojoAttachPoint="downArrowNode" waiRole="presentation"
+ dojoAttachEvent="onmousedown:_onArrowMouseDown,onmouseup:_onMouse,onmouseenter:_onMouse,onmouseleave:_onMouse"
+ ><div class="dijitArrowButtonInner">&thinsp;</div
+ ><div class="dijitArrowButtonChar">&#9660;</div
+ ></div
+ ><div class="dijitReset dijitValidationIcon"><br></div
+ ><div class="dijitReset dijitValidationIconText">&Chi;</div
+ ><div class="dijitReset dijitInputField"
+ ><input type="text" autocomplete="off" name="${name}" class='dijitReset'
+ dojoAttachEvent="onkeypress:_onKeyPress, onfocus:_update, compositionend,onkeyup"
+ dojoAttachPoint="textbox,focusNode" waiRole="textbox" waiState="haspopup-true,autocomplete-list"
+ /></div
+ ></div
+></div>
diff --git a/includes/js/dijit/form/templates/ComboButton.html b/includes/js/dijit/form/templates/ComboButton.html
new file mode 100644
index 0000000..6b46ea0
--- /dev/null
+++ b/includes/js/dijit/form/templates/ComboButton.html
@@ -0,0 +1,21 @@
+<table class='dijit dijitReset dijitInline dijitLeft'
+ cellspacing='0' cellpadding='0' waiRole="presentation"
+ ><tbody waiRole="presentation"><tr waiRole="presentation"
+ ><td class="dijitReset dijitStretch dijitButtonContents dijitButtonNode"
+ tabIndex="${tabIndex}"
+ dojoAttachEvent="ondijitclick:_onButtonClick,onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse" dojoAttachPoint="titleNode"
+ waiRole="button" waiState="labelledby-${id}_label"
+ ><div class="dijitReset dijitInline ${iconClass}" dojoAttachPoint="iconNode" waiRole="presentation"></div
+ ><div class="dijitReset dijitInline dijitButtonText" id="${id}_label" dojoAttachPoint="containerNode" waiRole="presentation">${label}</div
+ ></td
+ ><td class='dijitReset dijitStretch dijitButtonNode dijitArrowButton dijitDownArrowButton'
+ dojoAttachPoint="popupStateNode,focusNode"
+ dojoAttachEvent="ondijitclick:_onArrowClick, onkeypress:_onKey,onmouseenter:_onMouse,onmouseleave:_onMouse"
+ stateModifier="DownArrow"
+ title="${optionsTitle}" name="${name}"
+ waiRole="button" waiState="haspopup-true"
+ ><div class="dijitReset dijitArrowButtonInner" waiRole="presentation">&thinsp;</div
+ ><div class="dijitReset dijitArrowButtonChar" waiRole="presentation">&#9660;</div
+ ></td
+ ></tr></tbody
+></table>
diff --git a/includes/js/dijit/form/templates/DropDownButton.html b/includes/js/dijit/form/templates/DropDownButton.html
new file mode 100644
index 0000000..2e62f55
--- /dev/null
+++ b/includes/js/dijit/form/templates/DropDownButton.html
@@ -0,0 +1,13 @@
+<div class="dijit dijitReset dijitLeft dijitInline"
+ dojoAttachEvent="onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse,onclick:_onDropDownClick,onkeydown:_onDropDownKeydown,onblur:_onDropDownBlur,onkeypress:_onKey"
+ waiRole="presentation"
+ ><div class='dijitReset dijitRight' waiRole="presentation"
+ ><button class="dijitReset dijitStretch dijitButtonNode dijitButtonContents" type="${type}"
+ dojoAttachPoint="focusNode,titleNode" waiRole="button" waiState="haspopup-true,labelledby-${id}_label"
+ ><div class="dijitReset dijitInline ${iconClass}" dojoAttachPoint="iconNode" waiRole="presentation"></div
+ ><div class="dijitReset dijitInline dijitButtonText" dojoAttachPoint="containerNode,popupStateNode" waiRole="presentation"
+ id="${id}_label">${label}</div
+ ><div class="dijitReset dijitInline dijitArrowButtonInner" waiRole="presentation">&thinsp;</div
+ ><div class="dijitReset dijitInline dijitArrowButtonChar" waiRole="presentation">&#9660;</div
+ ></button
+></div></div>
diff --git a/includes/js/dijit/form/templates/HorizontalSlider.html b/includes/js/dijit/form/templates/HorizontalSlider.html
new file mode 100644
index 0000000..4dac451
--- /dev/null
+++ b/includes/js/dijit/form/templates/HorizontalSlider.html
@@ -0,0 +1,37 @@
+<table class="dijit dijitReset dijitSlider" cellspacing="0" cellpadding="0" border="0" rules="none"
+ ><tr class="dijitReset"
+ ><td class="dijitReset" colspan="2"></td
+ ><td dojoAttachPoint="containerNode,topDecoration" class="dijitReset" style="text-align:center;width:100%;"></td
+ ><td class="dijitReset" colspan="2"></td
+ ></tr
+ ><tr class="dijitReset"
+ ><td class="dijitReset dijitSliderButtonContainer dijitSliderButtonContainerH"
+ ><div class="dijitSliderDecrementIconH" tabIndex="-1" style="display:none" dojoAttachPoint="decrementButton" dojoAttachEvent="onclick: decrement"><span class="dijitSliderButtonInner">-</span></div
+ ></td
+ ><td class="dijitReset"
+ ><div class="dijitSliderBar dijitSliderBumper dijitSliderBumperH dijitSliderLeftBumper dijitSliderLeftBumper" dojoAttachEvent="onclick:_onClkDecBumper"></div
+ ></td
+ ><td class="dijitReset"
+ ><input dojoAttachPoint="valueNode" type="hidden" name="${name}"
+ /><div waiRole="presentation" style="position:relative;" dojoAttachPoint="sliderBarContainer"
+ ><div waiRole="presentation" dojoAttachPoint="progressBar" class="dijitSliderBar dijitSliderBarH dijitSliderProgressBar dijitSliderProgressBarH" dojoAttachEvent="onclick:_onBarClick"
+ ><div dojoAttachPoint="sliderHandle,focusNode" class="dijitSliderMoveable dijitSliderMoveableH" dojoAttachEvent="onkeypress:_onKeyPress,onmousedown:_onHandleClick" waiRole="slider" valuemin="${minimum}" valuemax="${maximum}"
+ ><div class="dijitSliderImageHandle dijitSliderImageHandleH"></div
+ ></div
+ ></div
+ ><div waiRole="presentation" dojoAttachPoint="remainingBar" class="dijitSliderBar dijitSliderBarH dijitSliderRemainingBar dijitSliderRemainingBarH" dojoAttachEvent="onclick:_onBarClick"></div
+ ></div
+ ></td
+ ><td class="dijitReset"
+ ><div class="dijitSliderBar dijitSliderBumper dijitSliderBumperH dijitSliderRightBumper dijitSliderRightBumper" dojoAttachEvent="onclick:_onClkIncBumper"></div
+ ></td
+ ><td class="dijitReset dijitSliderButtonContainer dijitSliderButtonContainerH" style="right:0px;"
+ ><div class="dijitSliderIncrementIconH" tabIndex="-1" style="display:none" dojoAttachPoint="incrementButton" dojoAttachEvent="onclick: increment"><span class="dijitSliderButtonInner">+</span></div
+ ></td
+ ></tr
+ ><tr class="dijitReset"
+ ><td class="dijitReset" colspan="2"></td
+ ><td dojoAttachPoint="containerNode,bottomDecoration" class="dijitReset" style="text-align:center;"></td
+ ><td class="dijitReset" colspan="2"></td
+ ></tr
+></table>
diff --git a/includes/js/dijit/form/templates/InlineEditBox.html b/includes/js/dijit/form/templates/InlineEditBox.html
new file mode 100644
index 0000000..6db3496
--- /dev/null
+++ b/includes/js/dijit/form/templates/InlineEditBox.html
@@ -0,0 +1,12 @@
+<span
+ ><fieldset dojoAttachPoint="editNode" style="display:none;" waiRole="presentation"
+ ><div dojoAttachPoint="containerNode" dojoAttachEvent="onkeypress:_onEditWidgetKeyPress"></div
+ ><div dojoAttachPoint="buttonContainer"
+ ><button class='saveButton' dojoAttachPoint="saveButton" dojoType="dijit.form.Button" dojoAttachEvent="onClick:save">${buttonSave}</button
+ ><button class='cancelButton' dojoAttachPoint="cancelButton" dojoType="dijit.form.Button" dojoAttachEvent="onClick:cancel">${buttonCancel}</button
+ ></div
+ ></fieldset
+ ><span tabIndex="0" dojoAttachPoint="textNode,focusNode" waiRole="button" style="display:none;"
+ dojoAttachEvent="onkeypress:_onKeyPress,onclick:_onClick,onmouseout:_onMouseOut,onmouseover:_onMouseOver,onfocus:_onMouseOver,onblur:_onMouseOut"
+ ></span
+></span>
diff --git a/includes/js/dijit/form/templates/Spinner.html b/includes/js/dijit/form/templates/Spinner.html
new file mode 100644
index 0000000..981c698
--- /dev/null
+++ b/includes/js/dijit/form/templates/Spinner.html
@@ -0,0 +1,28 @@
+<div class="dijit dijitReset dijitInlineTable dijitLeft"
+ id="widget_${id}"
+ dojoAttachEvent="onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse" waiRole="presentation"
+ ><div class="dijitInputLayoutContainer"
+ ><div class="dijitReset dijitSpinnerButtonContainer"
+ >&nbsp;<div class="dijitReset dijitLeft dijitButtonNode dijitArrowButton dijitUpArrowButton"
+ dojoAttachPoint="upArrowNode"
+ dojoAttachEvent="onmouseenter:_onMouse,onmouseleave:_onMouse"
+ stateModifier="UpArrow"
+ ><div class="dijitArrowButtonInner">&thinsp;</div
+ ><div class="dijitArrowButtonChar">&#9650;</div
+ ></div
+ ><div class="dijitReset dijitLeft dijitButtonNode dijitArrowButton dijitDownArrowButton"
+ dojoAttachPoint="downArrowNode"
+ dojoAttachEvent="onmouseenter:_onMouse,onmouseleave:_onMouse"
+ stateModifier="DownArrow"
+ ><div class="dijitArrowButtonInner">&thinsp;</div
+ ><div class="dijitArrowButtonChar">&#9660;</div
+ ></div
+ ></div
+ ><div class="dijitReset dijitValidationIcon"><br></div
+ ><div class="dijitReset dijitValidationIconText">&Chi;</div
+ ><div class="dijitReset dijitInputField"
+ ><input class='dijitReset' dojoAttachPoint="textbox,focusNode" type="${type}" dojoAttachEvent="onfocus:_update,onkeyup:_onkeyup,onkeypress:_onKeyPress"
+ waiRole="spinbutton" autocomplete="off" name="${name}"
+ /></div
+ ></div
+></div>
diff --git a/includes/js/dijit/form/templates/TextBox.html b/includes/js/dijit/form/templates/TextBox.html
new file mode 100644
index 0000000..804fe1e
--- /dev/null
+++ b/includes/js/dijit/form/templates/TextBox.html
@@ -0,0 +1,4 @@
+<input class="dijit dijitReset dijitLeft" dojoAttachPoint='textbox,focusNode' name="${name}"
+ dojoAttachEvent='onmouseenter:_onMouse,onmouseleave:_onMouse,onfocus:_onMouse,onblur:_onMouse,onkeypress:_onKeyPress,onkeyup'
+ autocomplete="off" type="${type}"
+ /> \ No newline at end of file
diff --git a/includes/js/dijit/form/templates/TimePicker.html b/includes/js/dijit/form/templates/TimePicker.html
new file mode 100644
index 0000000..0bf3c40
--- /dev/null
+++ b/includes/js/dijit/form/templates/TimePicker.html
@@ -0,0 +1,5 @@
+<div id="widget_${id}" class="dijitMenu"
+ ><div dojoAttachPoint="upArrow" class="dijitButtonNode"><span class="dijitTimePickerA11yText">&#9650;</span></div
+ ><div dojoAttachPoint="timeMenu,focusNode" dojoAttachEvent="onclick:_onOptionSelected,onmouseover,onmouseout"></div
+ ><div dojoAttachPoint="downArrow" class="dijitButtonNode"><span class="dijitTimePickerA11yText">&#9660;</span></div
+></div>
diff --git a/includes/js/dijit/form/templates/ValidationTextBox.html b/includes/js/dijit/form/templates/ValidationTextBox.html
new file mode 100644
index 0000000..2bdb674
--- /dev/null
+++ b/includes/js/dijit/form/templates/ValidationTextBox.html
@@ -0,0 +1,12 @@
+<div class="dijit dijitReset dijitInlineTable dijitLeft"
+ id="widget_${id}"
+ dojoAttachEvent="onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse" waiRole="presentation"
+ ><div style="overflow:hidden;"
+ ><div class="dijitReset dijitValidationIcon"><br></div
+ ><div class="dijitReset dijitValidationIconText">&Chi;</div
+ ><div class="dijitReset dijitInputField"
+ ><input class="dijitReset" dojoAttachPoint='textbox,focusNode' dojoAttachEvent='onfocus:_update,onkeyup:_onkeyup,onblur:_onMouse,onkeypress:_onKeyPress' autocomplete="off"
+ type='${type}' name='${name}'
+ /></div
+ ></div
+></div>
diff --git a/includes/js/dijit/form/templates/VerticalSlider.html b/includes/js/dijit/form/templates/VerticalSlider.html
new file mode 100644
index 0000000..88b2951
--- /dev/null
+++ b/includes/js/dijit/form/templates/VerticalSlider.html
@@ -0,0 +1,46 @@
+<table class="dijitReset dijitSlider" cellspacing="0" cellpadding="0" border="0" rules="none"
+><tbody class="dijitReset"
+ ><tr class="dijitReset"
+ ><td class="dijitReset"></td
+ ><td class="dijitReset dijitSliderButtonContainer dijitSliderButtonContainerV"
+ ><div class="dijitSliderIncrementIconV" tabIndex="-1" style="display:none" dojoAttachPoint="incrementButton" dojoAttachEvent="onclick:_topButtonClicked"><span class="dijitSliderButtonInner">+</span></div
+ ></td
+ ><td class="dijitReset"></td
+ ></tr
+ ><tr class="dijitReset"
+ ><td class="dijitReset"></td
+ ><td class="dijitReset"
+ ><center><div class="dijitSliderBar dijitSliderBumper dijitSliderBumperV dijitSliderTopBumper dijitSliderTopBumper" dojoAttachEvent="onclick:_onClkIncBumper"></div></center
+ ></td
+ ><td class="dijitReset"></td
+ ></tr
+ ><tr class="dijitReset"
+ ><td dojoAttachPoint="leftDecoration" class="dijitReset" style="text-align:center;height:100%;"></td
+ ><td class="dijitReset" style="height:100%;"
+ ><input dojoAttachPoint="valueNode" type="hidden" name="${name}"
+ /><center waiRole="presentation" style="position:relative;height:100%;" dojoAttachPoint="sliderBarContainer"
+ ><div waiRole="presentation" dojoAttachPoint="remainingBar" class="dijitSliderBar dijitSliderBarV dijitSliderRemainingBar dijitSliderRemainingBarV" dojoAttachEvent="onclick:_onBarClick"><!--#5629--></div
+ ><div waiRole="presentation" dojoAttachPoint="progressBar" class="dijitSliderBar dijitSliderBarV dijitSliderProgressBar dijitSliderProgressBarV" dojoAttachEvent="onclick:_onBarClick"
+ ><div dojoAttachPoint="sliderHandle,focusNode" class="dijitSliderMoveable" dojoAttachEvent="onkeypress:_onKeyPress,onmousedown:_onHandleClick" style="vertical-align:top;" waiRole="slider" valuemin="${minimum}" valuemax="${maximum}"
+ ><div class="dijitSliderImageHandle dijitSliderImageHandleV"></div
+ ></div
+ ></div
+ ></center
+ ></td
+ ><td dojoAttachPoint="containerNode,rightDecoration" class="dijitReset" style="text-align:center;height:100%;"></td
+ ></tr
+ ><tr class="dijitReset"
+ ><td class="dijitReset"></td
+ ><td class="dijitReset"
+ ><center><div class="dijitSliderBar dijitSliderBumper dijitSliderBumperV dijitSliderBottomBumper dijitSliderBottomBumper" dojoAttachEvent="onclick:_onClkDecBumper"></div></center
+ ></td
+ ><td class="dijitReset"></td
+ ></tr
+ ><tr class="dijitReset"
+ ><td class="dijitReset"></td
+ ><td class="dijitReset dijitSliderButtonContainer dijitSliderButtonContainerV"
+ ><div class="dijitSliderDecrementIconV" tabIndex="-1" style="display:none" dojoAttachPoint="decrementButton" dojoAttachEvent="onclick:_bottomButtonClicked"><span class="dijitSliderButtonInner">-</span></div
+ ></td
+ ><td class="dijitReset"></td
+ ></tr
+></tbody></table>