diff options
author | mensonge <mensonge@b3834d28-1941-0410-a4f8-b48e95affb8f> | 2008-11-13 09:49:11 +0000 |
---|---|---|
committer | mensonge <mensonge@b3834d28-1941-0410-a4f8-b48e95affb8f> | 2008-11-13 09:49:11 +0000 |
commit | e44a7e37b6c7b5961adaffc62b9042b8d442938e (patch) | |
tree | 95b67c356e93163467db2451f2b8cce84ed5d582 /includes/js/dijit/form | |
parent | a62b9742ee5e28bcec6872d88f50f25b820914f6 (diff) | |
download | semanticscuttle-e44a7e37b6c7b5961adaffc62b9042b8d442938e.tar.gz semanticscuttle-e44a7e37b6c7b5961adaffc62b9042b8d442938e.tar.bz2 |
New feature: basic Ajax suggestion for tags and implementation of Dojo toolkit
git-svn-id: https://semanticscuttle.svn.sourceforge.net/svnroot/semanticscuttle/trunk@151 b3834d28-1941-0410-a4f8-b48e95affb8f
Diffstat (limited to 'includes/js/dijit/form')
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\">✓</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\"> </div\n\t\t><div class=\"dijitReset dijitInline dijitArrowButtonChar\" waiRole=\"presentation\">▼</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\"> </div\n\t\t\t><div class=\"dijitReset dijitArrowButtonChar\" waiRole=\"presentation\">▼</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\"> </div\n\t\t\t><div class=\"dijitArrowButtonChar\">▼</div\n\t\t></div\n\t\t><div class=\"dijitReset dijitValidationIcon\"><br></div\n\t\t><div class=\"dijitReset dijitValidationIconText\">Χ</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 = " "; + } + 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 + // &<> -->&< > + value = editNode.innerHTML; + if(this.iframe){ // strip sizeNode + value = value.replace(/<div><\/div>\r?\n?$/i,""); + } + value = value.replace(/\s*\r?\n|^\s+|\s+$| /g,"").replace(/>\s+</g,"><").replace(/<\/(p|div)>$|^<(p|div)[^>]*>/gi,"").replace(/([^>])<div>/g,"$1\n").replace(/<\/p>\s*<p[^>]*>|<br[^>]*>|<\/div>\s*<div[^>]*>/gi,"\n").replace(/<[^>]*>/g,"").replace(/&/gi,"\&").replace(/</gi,"<").replace(/>/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(/>/g,">").replace(/</g,"<").replace(/&/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\">Χ</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> <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\"> </div\n\t\t\t\t><div class=\"dijitArrowButtonChar\">▲</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\"> </div\n\t\t\t\t><div class=\"dijitArrowButtonChar\">▼</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\">Χ</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">✓</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"> </div + ><div class="dijitArrowButtonChar">▼</div + ></div + ><div class="dijitReset dijitValidationIcon"><br></div + ><div class="dijitReset dijitValidationIconText">Χ</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"> </div + ><div class="dijitReset dijitArrowButtonChar" waiRole="presentation">▼</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"> </div + ><div class="dijitReset dijitInline dijitArrowButtonChar" waiRole="presentation">▼</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" + > <div class="dijitReset dijitLeft dijitButtonNode dijitArrowButton dijitUpArrowButton" + dojoAttachPoint="upArrowNode" + dojoAttachEvent="onmouseenter:_onMouse,onmouseleave:_onMouse" + stateModifier="UpArrow" + ><div class="dijitArrowButtonInner"> </div + ><div class="dijitArrowButtonChar">▲</div + ></div + ><div class="dijitReset dijitLeft dijitButtonNode dijitArrowButton dijitDownArrowButton" + dojoAttachPoint="downArrowNode" + dojoAttachEvent="onmouseenter:_onMouse,onmouseleave:_onMouse" + stateModifier="DownArrow" + ><div class="dijitArrowButtonInner"> </div + ><div class="dijitArrowButtonChar">▼</div + ></div + ></div + ><div class="dijitReset dijitValidationIcon"><br></div + ><div class="dijitReset dijitValidationIconText">Χ</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">▲</span></div + ><div dojoAttachPoint="timeMenu,focusNode" dojoAttachEvent="onclick:_onOptionSelected,onmouseover,onmouseout"></div + ><div dojoAttachPoint="downArrow" class="dijitButtonNode"><span class="dijitTimePickerA11yText">▼</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">Χ</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> |