From e44a7e37b6c7b5961adaffc62b9042b8d442938e Mon Sep 17 00:00:00 2001 From: mensonge Date: Thu, 13 Nov 2008 09:49:11 +0000 Subject: 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 --- includes/js/dijit/form/Button.js | 425 ++++++++ includes/js/dijit/form/CheckBox.js | 133 +++ includes/js/dijit/form/ComboBox.js | 1060 ++++++++++++++++++++ includes/js/dijit/form/CurrencyTextBox.js | 51 + includes/js/dijit/form/DateTextBox.js | 20 + includes/js/dijit/form/FilteringSelect.js | 241 +++++ includes/js/dijit/form/Form.js | 384 +++++++ includes/js/dijit/form/MultiSelect.js | 84 ++ includes/js/dijit/form/NumberSpinner.js | 31 + includes/js/dijit/form/NumberTextBox.js | 79 ++ includes/js/dijit/form/SimpleTextarea.js | 50 + includes/js/dijit/form/Slider.js | 481 +++++++++ includes/js/dijit/form/TextBox.js | 185 ++++ includes/js/dijit/form/Textarea.js | 261 +++++ includes/js/dijit/form/TimeTextBox.js | 33 + includes/js/dijit/form/ValidationTextBox.js | 308 ++++++ includes/js/dijit/form/_DateTimeTextBox.js | 175 ++++ includes/js/dijit/form/_FormWidget.js | 340 +++++++ includes/js/dijit/form/_Spinner.js | 117 +++ includes/js/dijit/form/nls/ComboBox.js | 1 + includes/js/dijit/form/nls/Textarea.js | 1 + includes/js/dijit/form/nls/ar/ComboBox.js | 1 + includes/js/dijit/form/nls/ar/Textarea.js | 1 + includes/js/dijit/form/nls/ar/validate.js | 1 + includes/js/dijit/form/nls/cs/ComboBox.js | 1 + includes/js/dijit/form/nls/cs/Textarea.js | 1 + includes/js/dijit/form/nls/cs/validate.js | 1 + includes/js/dijit/form/nls/da/ComboBox.js | 1 + includes/js/dijit/form/nls/da/Textarea.js | 1 + includes/js/dijit/form/nls/da/validate.js | 1 + includes/js/dijit/form/nls/de/ComboBox.js | 1 + includes/js/dijit/form/nls/de/Textarea.js | 1 + includes/js/dijit/form/nls/de/validate.js | 1 + includes/js/dijit/form/nls/el/ComboBox.js | 1 + includes/js/dijit/form/nls/el/Textarea.js | 1 + includes/js/dijit/form/nls/el/validate.js | 1 + includes/js/dijit/form/nls/es/ComboBox.js | 1 + includes/js/dijit/form/nls/es/Textarea.js | 1 + includes/js/dijit/form/nls/es/validate.js | 1 + includes/js/dijit/form/nls/fi/ComboBox.js | 1 + includes/js/dijit/form/nls/fi/Textarea.js | 1 + includes/js/dijit/form/nls/fi/validate.js | 1 + includes/js/dijit/form/nls/fr/ComboBox.js | 1 + includes/js/dijit/form/nls/fr/Textarea.js | 1 + includes/js/dijit/form/nls/fr/validate.js | 1 + includes/js/dijit/form/nls/he/ComboBox.js | 1 + includes/js/dijit/form/nls/he/Textarea.js | 1 + includes/js/dijit/form/nls/he/validate.js | 1 + includes/js/dijit/form/nls/hu/ComboBox.js | 1 + includes/js/dijit/form/nls/hu/Textarea.js | 1 + includes/js/dijit/form/nls/hu/validate.js | 1 + includes/js/dijit/form/nls/it/ComboBox.js | 1 + includes/js/dijit/form/nls/it/Textarea.js | 1 + includes/js/dijit/form/nls/it/validate.js | 1 + includes/js/dijit/form/nls/ja/ComboBox.js | 1 + includes/js/dijit/form/nls/ja/Textarea.js | 1 + includes/js/dijit/form/nls/ja/validate.js | 1 + includes/js/dijit/form/nls/ko/ComboBox.js | 1 + includes/js/dijit/form/nls/ko/Textarea.js | 1 + includes/js/dijit/form/nls/ko/validate.js | 1 + includes/js/dijit/form/nls/nb/ComboBox.js | 1 + includes/js/dijit/form/nls/nb/Textarea.js | 1 + includes/js/dijit/form/nls/nb/validate.js | 1 + includes/js/dijit/form/nls/nl/ComboBox.js | 1 + includes/js/dijit/form/nls/nl/Textarea.js | 1 + includes/js/dijit/form/nls/nl/validate.js | 1 + includes/js/dijit/form/nls/pl/ComboBox.js | 1 + includes/js/dijit/form/nls/pl/Textarea.js | 1 + includes/js/dijit/form/nls/pl/validate.js | 1 + includes/js/dijit/form/nls/pt-pt/ComboBox.js | 1 + includes/js/dijit/form/nls/pt-pt/Textarea.js | 1 + includes/js/dijit/form/nls/pt-pt/validate.js | 1 + includes/js/dijit/form/nls/pt/ComboBox.js | 1 + includes/js/dijit/form/nls/pt/Textarea.js | 1 + includes/js/dijit/form/nls/pt/validate.js | 1 + includes/js/dijit/form/nls/ru/ComboBox.js | 1 + includes/js/dijit/form/nls/ru/Textarea.js | 1 + includes/js/dijit/form/nls/ru/validate.js | 1 + includes/js/dijit/form/nls/sv/ComboBox.js | 1 + includes/js/dijit/form/nls/sv/Textarea.js | 1 + includes/js/dijit/form/nls/sv/validate.js | 1 + includes/js/dijit/form/nls/tr/ComboBox.js | 1 + includes/js/dijit/form/nls/tr/Textarea.js | 1 + includes/js/dijit/form/nls/tr/validate.js | 1 + includes/js/dijit/form/nls/validate.js | 1 + includes/js/dijit/form/nls/zh-tw/ComboBox.js | 1 + includes/js/dijit/form/nls/zh-tw/Textarea.js | 1 + includes/js/dijit/form/nls/zh-tw/validate.js | 1 + includes/js/dijit/form/nls/zh/ComboBox.js | 1 + includes/js/dijit/form/nls/zh/Textarea.js | 1 + includes/js/dijit/form/nls/zh/validate.js | 1 + includes/js/dijit/form/templates/Button.html | 11 + includes/js/dijit/form/templates/CheckBox.html | 7 + includes/js/dijit/form/templates/ComboBox.html | 19 + includes/js/dijit/form/templates/ComboButton.html | 21 + .../js/dijit/form/templates/DropDownButton.html | 13 + .../js/dijit/form/templates/HorizontalSlider.html | 37 + .../js/dijit/form/templates/InlineEditBox.html | 12 + includes/js/dijit/form/templates/Spinner.html | 28 + includes/js/dijit/form/templates/TextBox.html | 4 + includes/js/dijit/form/templates/TimePicker.html | 5 + .../js/dijit/form/templates/ValidationTextBox.html | 12 + .../js/dijit/form/templates/VerticalSlider.html | 46 + 103 files changed, 4745 insertions(+) create mode 100644 includes/js/dijit/form/Button.js create mode 100644 includes/js/dijit/form/CheckBox.js create mode 100644 includes/js/dijit/form/ComboBox.js create mode 100644 includes/js/dijit/form/CurrencyTextBox.js create mode 100644 includes/js/dijit/form/DateTextBox.js create mode 100644 includes/js/dijit/form/FilteringSelect.js create mode 100644 includes/js/dijit/form/Form.js create mode 100644 includes/js/dijit/form/MultiSelect.js create mode 100644 includes/js/dijit/form/NumberSpinner.js create mode 100644 includes/js/dijit/form/NumberTextBox.js create mode 100644 includes/js/dijit/form/SimpleTextarea.js create mode 100644 includes/js/dijit/form/Slider.js create mode 100644 includes/js/dijit/form/TextBox.js create mode 100644 includes/js/dijit/form/Textarea.js create mode 100644 includes/js/dijit/form/TimeTextBox.js create mode 100644 includes/js/dijit/form/ValidationTextBox.js create mode 100644 includes/js/dijit/form/_DateTimeTextBox.js create mode 100644 includes/js/dijit/form/_FormWidget.js create mode 100644 includes/js/dijit/form/_Spinner.js create mode 100644 includes/js/dijit/form/nls/ComboBox.js create mode 100644 includes/js/dijit/form/nls/Textarea.js create mode 100644 includes/js/dijit/form/nls/ar/ComboBox.js create mode 100644 includes/js/dijit/form/nls/ar/Textarea.js create mode 100644 includes/js/dijit/form/nls/ar/validate.js create mode 100644 includes/js/dijit/form/nls/cs/ComboBox.js create mode 100644 includes/js/dijit/form/nls/cs/Textarea.js create mode 100644 includes/js/dijit/form/nls/cs/validate.js create mode 100644 includes/js/dijit/form/nls/da/ComboBox.js create mode 100644 includes/js/dijit/form/nls/da/Textarea.js create mode 100644 includes/js/dijit/form/nls/da/validate.js create mode 100644 includes/js/dijit/form/nls/de/ComboBox.js create mode 100644 includes/js/dijit/form/nls/de/Textarea.js create mode 100644 includes/js/dijit/form/nls/de/validate.js create mode 100644 includes/js/dijit/form/nls/el/ComboBox.js create mode 100644 includes/js/dijit/form/nls/el/Textarea.js create mode 100644 includes/js/dijit/form/nls/el/validate.js create mode 100644 includes/js/dijit/form/nls/es/ComboBox.js create mode 100644 includes/js/dijit/form/nls/es/Textarea.js create mode 100644 includes/js/dijit/form/nls/es/validate.js create mode 100644 includes/js/dijit/form/nls/fi/ComboBox.js create mode 100644 includes/js/dijit/form/nls/fi/Textarea.js create mode 100644 includes/js/dijit/form/nls/fi/validate.js create mode 100644 includes/js/dijit/form/nls/fr/ComboBox.js create mode 100644 includes/js/dijit/form/nls/fr/Textarea.js create mode 100644 includes/js/dijit/form/nls/fr/validate.js create mode 100644 includes/js/dijit/form/nls/he/ComboBox.js create mode 100644 includes/js/dijit/form/nls/he/Textarea.js create mode 100644 includes/js/dijit/form/nls/he/validate.js create mode 100644 includes/js/dijit/form/nls/hu/ComboBox.js create mode 100644 includes/js/dijit/form/nls/hu/Textarea.js create mode 100644 includes/js/dijit/form/nls/hu/validate.js create mode 100644 includes/js/dijit/form/nls/it/ComboBox.js create mode 100644 includes/js/dijit/form/nls/it/Textarea.js create mode 100644 includes/js/dijit/form/nls/it/validate.js create mode 100644 includes/js/dijit/form/nls/ja/ComboBox.js create mode 100644 includes/js/dijit/form/nls/ja/Textarea.js create mode 100644 includes/js/dijit/form/nls/ja/validate.js create mode 100644 includes/js/dijit/form/nls/ko/ComboBox.js create mode 100644 includes/js/dijit/form/nls/ko/Textarea.js create mode 100644 includes/js/dijit/form/nls/ko/validate.js create mode 100644 includes/js/dijit/form/nls/nb/ComboBox.js create mode 100644 includes/js/dijit/form/nls/nb/Textarea.js create mode 100644 includes/js/dijit/form/nls/nb/validate.js create mode 100644 includes/js/dijit/form/nls/nl/ComboBox.js create mode 100644 includes/js/dijit/form/nls/nl/Textarea.js create mode 100644 includes/js/dijit/form/nls/nl/validate.js create mode 100644 includes/js/dijit/form/nls/pl/ComboBox.js create mode 100644 includes/js/dijit/form/nls/pl/Textarea.js create mode 100644 includes/js/dijit/form/nls/pl/validate.js create mode 100644 includes/js/dijit/form/nls/pt-pt/ComboBox.js create mode 100644 includes/js/dijit/form/nls/pt-pt/Textarea.js create mode 100644 includes/js/dijit/form/nls/pt-pt/validate.js create mode 100644 includes/js/dijit/form/nls/pt/ComboBox.js create mode 100644 includes/js/dijit/form/nls/pt/Textarea.js create mode 100644 includes/js/dijit/form/nls/pt/validate.js create mode 100644 includes/js/dijit/form/nls/ru/ComboBox.js create mode 100644 includes/js/dijit/form/nls/ru/Textarea.js create mode 100644 includes/js/dijit/form/nls/ru/validate.js create mode 100644 includes/js/dijit/form/nls/sv/ComboBox.js create mode 100644 includes/js/dijit/form/nls/sv/Textarea.js create mode 100644 includes/js/dijit/form/nls/sv/validate.js create mode 100644 includes/js/dijit/form/nls/tr/ComboBox.js create mode 100644 includes/js/dijit/form/nls/tr/Textarea.js create mode 100644 includes/js/dijit/form/nls/tr/validate.js create mode 100644 includes/js/dijit/form/nls/validate.js create mode 100644 includes/js/dijit/form/nls/zh-tw/ComboBox.js create mode 100644 includes/js/dijit/form/nls/zh-tw/Textarea.js create mode 100644 includes/js/dijit/form/nls/zh-tw/validate.js create mode 100644 includes/js/dijit/form/nls/zh/ComboBox.js create mode 100644 includes/js/dijit/form/nls/zh/Textarea.js create mode 100644 includes/js/dijit/form/nls/zh/validate.js create mode 100644 includes/js/dijit/form/templates/Button.html create mode 100644 includes/js/dijit/form/templates/CheckBox.html create mode 100644 includes/js/dijit/form/templates/ComboBox.html create mode 100644 includes/js/dijit/form/templates/ComboButton.html create mode 100644 includes/js/dijit/form/templates/DropDownButton.html create mode 100644 includes/js/dijit/form/templates/HorizontalSlider.html create mode 100644 includes/js/dijit/form/templates/InlineEditBox.html create mode 100644 includes/js/dijit/form/templates/Spinner.html create mode 100644 includes/js/dijit/form/templates/TextBox.html create mode 100644 includes/js/dijit/form/templates/TimePicker.html create mode 100644 includes/js/dijit/form/templates/ValidationTextBox.html create mode 100644 includes/js/dijit/form/templates/VerticalSlider.html (limited to 'includes/js/dijit/form') 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: + // | + // + // 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:"
+ // + // example: + // | var button1 = new dijit.form.DropDownButton({ label: "hi", dropDown: new dijit.Menu(...) }); + // | dojo.body().appendChild(button1); + // + + baseClass : "dijitDropDownButton", + + templateString:"
+ // + // example: + // | var button1 = new dijit.form.ComboButton({label: "hello world", onClick: foo, dropDown: "myMenu"}); + // | dojo.body().appendChild(button1.domNode); + // + + templateString:"
${label}
\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 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:"
\n", + + baseClass: "dijitCheckBox", + + // Value of "type" attribute for + 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: ) + 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 `` box, + // automatically copy the first entry displayed in the drop down list to + // the `` 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:"

Χ
\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: "
    " + +"
  • " + +"
  • " + +"
", + _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 + // | + // | ... + // + // 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 ` + var item = dojo.query("option[value='" + args.identity + "']", this.root)[0]; + args.onItem(item); + }, + + fetchSelectedItem: function(){ + // summary: + // Get the option marked as selected, like `