New file |
0,0 → 1,269 |
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: |
FormElement widgets correspond to native HTML elements such as <input> or <button> or <select>. |
Each FormElement 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. |
|
All these widgets should have these attributes just like native HTML input elements. |
You can set them during widget construction, but after that they are read only. |
|
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: "", |
|
// value: String |
// Corresponds to the native HTML <input> element's attribute. |
value: "", |
|
// name: String |
// Name used when submitting form; same as "name" attribute or plain HTML elements |
name: "", |
|
// id: String |
// Corresponds to the native HTML <input> element's attribute. |
// Also becomes the id for the widget. |
id: "", |
|
// alt: String |
// Corresponds to the native HTML <input> element's attribute. |
alt: "", |
|
// 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, |
|
// 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), |
{id:"focusNode", tabIndex:"focusNode", alt:"focusNode"}), |
|
setDisabled: function(/*Boolean*/ disabled){ |
// summary: |
// Set disabled state of widget. |
|
this.domNode.disabled = this.disabled = disabled; |
if(this.focusNode){ |
this.focusNode.disabled = disabled; |
} |
if(disabled){ |
//reset those, because after the domNode is disabled, we can no longer receive |
//mouse related events, see #4200 |
this._hovering = false; |
this._active = false; |
} |
dijit.setWaiState(this.focusNode || this.domNode, "disabled", disabled); |
this._setStateClass(); |
}, |
|
|
_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.target; |
if(mouseNode && mouseNode.getAttribute){ |
this.stateModifier = mouseNode.getAttribute("stateModifier") || ""; |
} |
|
if(!this.disabled){ |
switch(event.type){ |
case "mouseenter" : |
case "mouseover" : |
this._hovering = true; |
break; |
|
case "mouseout" : |
case "mouseleave" : |
this._hovering = false; |
break; |
|
case "mousedown" : |
this._active = true; |
// set a global event to handle mouseup, so it fires properly |
// even if the cursor leaves the button |
var self = this; |
// #2685: use this.connect and disconnect so destroy works properly |
var mouseUpConnector = this.connect(dojo.body(), "onmouseup", function(){ |
self._active = false; |
self._setStateClass(); |
self.disconnect(mouseUpConnector); |
}); |
break; |
} |
this._setStateClass(); |
} |
}, |
|
isFocusable: function(){ |
return !this.disabled && (dojo.style(this.domNode, "display") != "none"); |
}, |
|
focus: function(){ |
dijit.focus(this.focusNode); |
}, |
|
_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 at most one 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 |
// |
// (even if multiple af the above conditions are true we only pick the first matching one) |
|
|
// 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; })); |
} |
|
if(this.checked){ |
multiply("Checked"); |
} |
if(this.state){ |
multiply(this.state); |
} |
if(this.selected){ |
multiply("Selected"); |
} |
|
// Only one of these four can be applied. |
// Active trumps Focused, Focused trumps Hover, and Disabled trumps all. |
if(this.disabled){ |
multiply("Disabled"); |
}else if(this._active){ |
multiply(this.stateModifier+"Active"); |
}else{ |
if(this._focused){ |
multiply("Focused"); |
} |
if((this.stateModifier || !this._focused) && this._hovering){ |
multiply(this.stateModifier+"Hover"); |
} |
} |
(this.stateNode || this.domNode).className = this.staticClass + " " + classes.join(" "); |
}, |
|
onChange: function(newValue){ |
// summary: callback when value is changed |
}, |
|
postCreate: function(){ |
this.setValue(this.value, null); // null reserved for initial value |
this.setDisabled(this.disabled); |
this._setStateClass(); |
}, |
|
setValue: function(/*anything*/ newValue, /*Boolean, optional*/ priorityChange){ |
// summary: set the value of the widget. |
this._lastValue = newValue; |
dijit.setWaiState(this.focusNode || this.domNode, "valuenow", this.forWaiValuenow()); |
if(priorityChange === undefined){ priorityChange = true; } // setValue with value only should fire onChange |
if(this._lastValueReported == undefined && priorityChange === null){ // don't report the initial value |
this._lastValueReported = newValue; |
} |
if((this.intermediateChanges || priorityChange) && |
((newValue && newValue.toString)?newValue.toString():newValue) !== ((this._lastValueReported && this._lastValueReported.toString)?this._lastValueReported.toString():this._lastValueReported)){ |
this._lastValueReported = newValue; |
this.onChange(newValue); |
} |
}, |
|
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); |
}, |
|
_onKeyPress: function(e){ |
if(e.keyCode == dojo.keys.ESCAPE && !e.shiftKey && !e.ctrlKey && !e.altKey){ |
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. |
if((typeof lv != "undefined") && ((v!==null && v.toString)?v.toString():null) !== lv.toString()){ |
this.undo(); |
dojo.stopEvent(e); |
return false; |
} |
} |
return true; |
}, |
|
forWaiValuenow: function(){ |
// summary: returns a value, reflecting the current state of the widget, |
// to be used for the ARIA valuenow. |
// This method may be overridden by subclasses that want |
// to use something other than this.getValue() for valuenow |
return this.getValue(); |
} |
}); |
|
} |