webui-aria2/js/libs/dojox/mobile/app/_FormWidget.js.uncompressed.js
2012-05-01 19:52:07 +08:00

294 lines
9.6 KiB
JavaScript

//>>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, "&quot;") + '"') : '';
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);
}
});
});