diff options
Diffstat (limited to 'js/dojo/dojox/mobile/app/_FormWidget.js')
| -rw-r--r-- | js/dojo/dojox/mobile/app/_FormWidget.js | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/js/dojo/dojox/mobile/app/_FormWidget.js b/js/dojo/dojox/mobile/app/_FormWidget.js new file mode 100644 index 0000000..1a6c8cd --- /dev/null +++ b/js/dojo/dojox/mobile/app/_FormWidget.js @@ -0,0 +1,293 @@ +//>>built +// wrapped by build app +define("dojox/mobile/app/_FormWidget", ["dijit","dojo","dojox","dojo/require!dojo/window,dijit/_WidgetBase,dijit/focus"], function(dijit,dojo,dojox){ +dojo.provide("dojox.mobile.app._FormWidget"); +dojo.experimental("dojox.mobile.app._FormWidget"); + +dojo.require("dojo.window"); + +dojo.require("dijit._WidgetBase"); +dojo.require("dijit.focus"); // dijit.focus() + +dojo.declare("dojox.mobile.app._FormWidget", dijit._WidgetBase, { + // summary: + // Base class for widgets corresponding to native HTML elements such as <checkbox> or <button>, + // which can be children of a <form> node or a `dojox.mobile.app.Form` widget. + // + // description: + // 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 or afterwards, via `dijit._WidgetBase.attr`. + // + // They also share some common methods. + + // 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", + + // 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, + + // scrollOnFocus: Boolean + // On focus, should this widget scroll into view? + scrollOnFocus: false, + + // These mixins assume that the focus node is an INPUT, as many but not all _FormWidgets are. + attributeMap: dojo.delegate(dijit._WidgetBase.prototype.attributeMap, { + value: "focusNode", + id: "focusNode", + alt: "focusNode", + title: "focusNode" + }), + + postMixInProperties: function(){ + // Setup name=foo string to be referenced from the template (but only if a name has been specified) + // Unfortunately we can't use attributeMap to set the name due to IE limitations, see #8660 + // Regarding escaping, see heading "Attribute values" in + // http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2 + this.nameAttrSetting = this.name ? ('name="' + this.name.replace(/'/g, """) + '"') : ''; + this.inherited(arguments); + }, + + postCreate: function(){ + this.inherited(arguments); + this.connect(this.domNode, "onmousedown", "_onMouseDown"); + }, + + _setDisabledAttr: function(/*Boolean*/ value){ + this.disabled = value; + dojo.attr(this.focusNode, 'disabled', value); + if(this.valueNode){ + dojo.attr(this.valueNode, 'disabled', value); + } + }, + + _onFocus: function(e){ + if(this.scrollOnFocus){ + dojo.window.scrollIntoView(this.domNode); + } + this.inherited(arguments); + }, + + isFocusable: function(){ + // summary: + // Tells if this widget is focusable or not. Used internally by dijit. + // tags: + // protected + return !this.disabled && !this.readOnly + && this.focusNode && (dojo.style(this.domNode, "display") != "none"); + }, + + focus: function(){ + // summary: + // Put focus on this widget + this.focusNode.focus(); + }, + + compare: function(/*anything*/val1, /*anything*/val2){ + // summary: + // Compare 2 values (as returned by attr('value') for this widget). + // tags: + // protected + if(typeof val1 == "number" && typeof val2 == "number"){ + return (isNaN(val1) && isNaN(val2)) ? 0 : val1 - val2; + }else if(val1 > val2){ + return 1; + }else if(val1 < val2){ + return -1; + }else{ + return 0; + } + }, + + onChange: function(newValue){ + // summary: + // Callback when this widget's value is changed. + // tags: + // callback + }, + + // _onChangeActive: [private] Boolean + // Indicates that changes to the value should call onChange() callback. + // This is false during widget initialization, to avoid calling onChange() + // when the initial value is set. + _onChangeActive: false, + + _handleOnChange: function(/*anything*/ newValue, /* Boolean? */ priorityChange){ + // summary: + // Called when the value of the widget is set. Calls onChange() if appropriate + // newValue: + // the new value + // priorityChange: + // For a slider, for example, dragging the slider is priorityChange==false, + // but on mouse up, it's priorityChange==true. If intermediateChanges==true, + // onChange is only called form priorityChange=true events. + // tags: + // private + this._lastValue = newValue; + if(this._lastValueReported == undefined && (priorityChange === null || !this._onChangeActive)){ + // this block executes not for a change, but during initialization, + // and is used to store away the original value (or for ToggleButton, the original checked state) + this._resetValue = this._lastValueReported = newValue; + } + if((this.intermediateChanges || priorityChange || priorityChange === undefined) && + ((typeof newValue != typeof this._lastValueReported) || + this.compare(newValue, this._lastValueReported) != 0)){ + this._lastValueReported = newValue; + if(this._onChangeActive){ + if(this._onChangeHandle){ + clearTimeout(this._onChangeHandle); + } + // setTimout allows hidden value processing to run and + // also the onChange handler can safely adjust focus, etc + this._onChangeHandle = setTimeout(dojo.hitch(this, + function(){ + this._onChangeHandle = null; + this.onChange(newValue); + }), 0); // try to collapse multiple onChange's fired faster than can be processed + } + } + }, + + create: function(){ + // Overrides _Widget.create() + this.inherited(arguments); + this._onChangeActive = true; + }, + + destroy: function(){ + if(this._onChangeHandle){ // destroy called before last onChange has fired + clearTimeout(this._onChangeHandle); + this.onChange(this._lastValueReported); + } + this.inherited(arguments); + }, + + _onMouseDown: function(e){ + // If user clicks on the button, even if the mouse is released outside of it, + // this button should get focus (to mimics native browser buttons). + // This is also needed on chrome because otherwise buttons won't get focus at all, + // which leads to bizarre focus restore on Dialog close etc. + if(this.isFocusable()){ + // Set a global event to handle mouseup, so it fires properly + // even if the cursor leaves this.domNode before the mouse up event. + var mouseUpConnector = this.connect(dojo.body(), "onmouseup", function(){ + if(this.isFocusable()){ + this.focus(); + } + this.disconnect(mouseUpConnector); + }); + } + }, + + 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; } + dijit.focus(element); + + if(_window["getSelection"] && element.setSelectionRange){ + element.setSelectionRange(start, stop); + } + } +}); + +dojo.declare("dojox.mobile.app._FormValueWidget", dojox.mobile.app._FormWidget, +{ + // summary: + // Base class for widgets corresponding to native HTML elements such as <input> or <select> that have user changeable values. + // description: + // Each _FormValueWidget represents a single input value, and has a (possibly hidden) <input> element, + // to which it serializes it's input value, so that form submission (either normal submission or via FormBind?) + // works as expected. + + // 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. See #8484, #8660. + // TODO: unclear what that {value: ""} is for; FormWidget.attributeMap copies value to focusNode, + // so maybe {value: ""} is so the value *doesn't* get copied to focusNode? + // Seems like we really want value removed from attributeMap altogether + // (although there's no easy way to do that now) + + // 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, + + attributeMap: dojo.delegate(dojox.mobile.app._FormWidget.prototype.attributeMap, { + value: "", + readOnly: "focusNode" + }), + + _setReadOnlyAttr: function(/*Boolean*/ value){ + this.readOnly = value; + dojo.attr(this.focusNode, 'readOnly', value); + }, + + postCreate: function(){ + this.inherited(arguments); + + // Update our reset value if it hasn't yet been set (because this.set() + // is only called when there *is* a value) + if(this._resetValue === undefined){ + this._resetValue = this.value; + } + }, + + _setValueAttr: function(/*anything*/ newValue, /*Boolean, optional*/ priorityChange){ + // summary: + // Hook so attr('value', value) works. + // description: + // Sets the value of the widget. + // If the value has changed, then fire onChange event, unless priorityChange + // is specified as null (or false?) + this.value = newValue; + this._handleOnChange(newValue, priorityChange); + }, + + _getValueAttr: function(){ + // summary: + // Hook so attr('value') works. + return this._lastValue; + }, + + undo: function(){ + // summary: + // Restore the value to the last value passed to onChange + this._setValueAttr(this._lastValueReported, false); + }, + + reset: function(){ + // summary: + // Reset the widget's value to what it was at initialization time + this._hasBeenBlurred = false; + this._setValueAttr(this._resetValue, true); + } +}); + +}); |
