1 if(!dojo._hasResource["dijit.form._FormWidget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2 dojo._hasResource["dijit.form._FormWidget"] = true;
3 dojo.provide("dijit.form._FormWidget");
5 dojo.require("dijit._Widget");
6 dojo.require("dijit._Templated");
8 dojo.declare("dijit.form._FormWidget", [dijit._Widget, dijit._Templated],
12 _FormWidget's correspond to native HTML elements such as <checkbox> or <button>.
13 Each _FormWidget represents a single HTML element.
15 All these widgets should have these attributes just like native HTML input elements.
16 You can set them during widget construction.
18 They also share some common methods.
22 // Root CSS class of the widget (ex: dijitTextBox), used to add CSS classes of widget
23 // (ex: "dijitTextBox dijitTextBoxInvalid dijitTextBoxFocused dijitTextBoxInvalidFocused")
24 // See _setStateClass().
28 // Name used when submitting form; same as "name" attribute or plain HTML elements
32 // Corresponds to the native HTML <input> element's attribute.
36 // Corresponds to the native HTML <input> element's attribute.
40 // Corresponds to the native HTML <input> element's attribute.
44 // Order fields are traversed when user hits the tab key
48 // Should this widget respond to user input?
49 // In markup, this is specified as "disabled='disabled'", or just "disabled".
53 // Should this widget respond to user input?
54 // In markup, this is specified as "readOnly".
55 // Similar to disabled except readOnly form values are submitted
58 // intermediateChanges: Boolean
59 // Fires onChange for each value change or only on demand
60 intermediateChanges: false,
62 // These mixins assume that the focus node is an INPUT, as many but not all _FormWidgets are.
63 // Don't attempt to mixin the 'type', 'name' attributes here programatically -- they must be declared
64 // directly in the template as read by the parser in order to function. IE is known to specifically
65 // require the 'name' attribute at element creation time.
66 attributeMap: dojo.mixin(dojo.clone(dijit._Widget.prototype.attributeMap),
67 {value:"focusNode", disabled:"focusNode", readOnly:"focusNode", id:"focusNode", tabIndex:"focusNode", alt:"focusNode"}),
69 setAttribute: function(/*String*/ attr, /*anything*/ value){
70 this.inherited(arguments);
73 var tabIndexNode = this[this.attributeMap['tabIndex']||'domNode'];
75 //reset those, because after the domNode is disabled, we can no longer receive
76 //mouse related events, see #4200
77 this._hovering = false;
79 // remove the tabIndex, especially for FF
80 tabIndexNode.removeAttribute('tabIndex');
82 tabIndexNode.setAttribute('tabIndex', this.tabIndex);
84 dijit.setWaiState(this[this.attributeMap['disabled']||'domNode'], "disabled", value);
85 this._setStateClass();
89 setDisabled: function(/*Boolean*/ disabled){
91 // Set disabled state of widget (Deprecated).
92 dojo.deprecated("setDisabled("+disabled+") is deprecated. Use setAttribute('disabled',"+disabled+") instead.", "", "2.0");
93 this.setAttribute('disabled', disabled);
97 _onMouse : function(/*Event*/ event){
99 // Sets _hovering, _active, and stateModifier properties depending on mouse state,
100 // then calls setStateClass() to set appropriate CSS classes for this.domNode.
102 // To get a different CSS class for hover, send onmouseover and onmouseout events to this method.
103 // To get a different CSS class while mouse button is depressed, send onmousedown to this method.
105 var mouseNode = event.currentTarget;
106 if(mouseNode && mouseNode.getAttribute){
107 this.stateModifier = mouseNode.getAttribute("stateModifier") || "";
114 this._hovering = true;
115 this._active = this._mouseDown;
120 this._hovering = false;
121 this._active = false;
126 this._mouseDown = true;
127 // set a global event to handle mouseup, so it fires properly
128 // even if the cursor leaves the button
129 var mouseUpConnector = this.connect(dojo.body(), "onmouseup", function(){
130 this._active = false;
131 this._mouseDown = false;
132 this._setStateClass();
133 this.disconnect(mouseUpConnector);
135 if(this.isFocusable()){ this.focus(); }
138 this._setStateClass();
142 isFocusable: function(){
143 return !this.disabled && !this.readOnly && this.focusNode && (dojo.style(this.domNode, "display") != "none");
147 setTimeout(dojo.hitch(this, dijit.focus, this.focusNode), 0); // cannot call focus() from an event handler directly
150 _setStateClass: function(){
152 // Update the visual state of the widget by setting the css classes on this.domNode
153 // (or this.stateNode if defined) by combining this.baseClass with
154 // various suffixes that represent the current widget state(s).
156 // In the case where a widget has multiple
157 // states, it sets the class based on all possible
158 // combinations. For example, an invalid form widget that is being hovered
159 // will be "dijitInput dijitInputInvalid dijitInputHover dijitInputInvalidHover".
161 // For complex widgets with multiple regions, there can be various hover/active states,
162 // such as "Hover" or "CloseButtonHover" (for tab buttons).
163 // This is controlled by a stateModifier="CloseButton" attribute on the close button node.
165 // The widget may have one or more of the following states, determined
166 // by this.state, this.checked, this.valid, and this.selected:
167 // Error - ValidationTextBox sets this.state to "Error" if the current input value is invalid
168 // Checked - ex: a checkmark or a ToggleButton in a checked state, will have this.checked==true
169 // Selected - ex: currently selected tab will have this.selected==true
171 // In addition, it may have one or more of the following states,
172 // based on this.disabled and flags set in _onMouse (this._active, this._hovering, this._focused):
173 // Disabled - if the widget is disabled
174 // Active - if the mouse (or space/enter key?) is being pressed down
175 // Focused - if the widget has focus
176 // Hover - if the mouse is over the widget
178 // Get original (non state related, non baseClass related) class specified in template
179 if(!("staticClass" in this)){
180 this.staticClass = (this.stateNode||this.domNode).className;
183 // Compute new set of classes
184 var classes = [ this.baseClass ];
186 function multiply(modifier){
187 classes=classes.concat(dojo.map(classes, function(c){ return c+modifier; }), "dijit"+modifier);
194 multiply(this.state);
197 multiply("Selected");
201 multiply("Disabled");
202 }else if(this.readOnly){
203 multiply("ReadOnly");
204 }else if(this._active){
205 multiply(this.stateModifier+"Active");
211 multiply(this.stateModifier+"Hover");
215 (this.stateNode || this.domNode).className = this.staticClass + " " + classes.join(" ");
218 onChange: function(newValue){
219 // summary: callback when value is changed
222 _onChangeMonitor: 'value',
223 _onChangeActive: false,
225 _handleOnChange: function(/*anything*/ newValue, /*Boolean, optional*/ priorityChange){
226 // summary: set the value of the widget.
227 this._lastValue = newValue;
228 if(this._lastValueReported == undefined && (priorityChange === null || !this._onChangeActive)){
229 this._resetValue = this._lastValueReported = newValue;
231 if((this.intermediateChanges || priorityChange || priorityChange === undefined) &&
232 ((newValue && newValue.toString)?newValue.toString():newValue) !== ((this._lastValueReported && this._lastValueReported.toString)?this._lastValueReported.toString():this._lastValueReported)){
233 this._lastValueReported = newValue;
234 if(this._onChangeActive){ this.onChange(newValue); }
239 this._hasBeenBlurred = false;
240 if(this.setValue && !this._getValueDeprecated){
241 this.setValue(this._resetValue, true);
242 }else if(this._onChangeMonitor){
243 this.setAttribute(this._onChangeMonitor, (this._resetValue !== undefined && this._resetValue !== null)? this._resetValue : '');
248 this.inherited(arguments);
249 this._onChangeActive = true;
250 this._setStateClass();
254 if(this._layoutHackHandle){
255 clearTimeout(this._layoutHackHandle);
257 this.inherited(arguments);
260 setValue: function(/*String*/ value){
261 dojo.deprecated("dijit.form._FormWidget:setValue("+value+") is deprecated. Use setAttribute('value',"+value+") instead.", "", "2.0");
262 this.setAttribute('value', value);
265 _getValueDeprecated: true, // Form uses this, remove when getValue is removed
266 getValue: function(){
267 dojo.deprecated("dijit.form._FormWidget:getValue() is deprecated. Use widget.value instead.", "", "2.0");
271 _layoutHack: function(){
272 // summary: work around table sizing bugs on FF2 by forcing redraw
274 var node=this.domNode;
275 var old = node.style.opacity;
276 node.style.opacity = "0.999";
277 this._layoutHackHandle = setTimeout(dojo.hitch(this, function(){
278 this._layoutHackHandle = null;
279 node.style.opacity = old;
285 dojo.declare("dijit.form._FormValueWidget", dijit.form._FormWidget,
289 _FormValueWidget's correspond to native HTML elements such as <input> or <select> that have user changeable values.
290 Each _ValueWidget represents a single input value, and has a (possibly hidden) <input> element,
291 to which it serializes its input value, so that form submission (either normal submission or via FormBind?)
295 attributeMap: dojo.mixin(dojo.clone(dijit.form._FormWidget.prototype.attributeMap),
298 postCreate: function(){
299 this.setValue(this.value, null);
302 setValue: function(/*anything*/ newValue, /*Boolean, optional*/ priorityChange){
303 // summary: set the value of the widget.
304 this.value = newValue;
305 this._handleOnChange(newValue, priorityChange);
308 _getValueDeprecated: false, // remove when _FormWidget:getValue is removed
309 getValue: function(){
310 // summary: get the value of the widget.
311 return this._lastValue;
315 // summary: restore the value to the last value passed to onChange
316 this.setValue(this._lastValueReported, false);
319 _valueChanged: function(){
320 var v = this.getValue();
321 var lv = this._lastValueReported;
322 // Equality comparison of objects such as dates are done by reference so
323 // two distinct objects are != even if they have the same data. So use
324 // toStrings in case the values are objects.
325 return ((v !== null && (v !== undefined) && v.toString)?v.toString():'') !== ((lv !== null && (lv !== undefined) && lv.toString)?lv.toString():'');
328 _onKeyPress: function(e){
329 if(e.keyCode == dojo.keys.ESCAPE && !e.shiftKey && !e.ctrlKey && !e.altKey){
330 if(this._valueChanged()){