SOURCE CODE: Uize.Widget.Picker
/*______________
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
| / / | ---------------------------------------------------
| / O / | MODULE : Uize.Widget.Picker Class
| / / / |
| / / / /| | ONLINE : http://www.uize.com
| /____/ /__/_| | COPYRIGHT : (c)2009-2012 UIZE
| /___ | LICENSE : Available under MIT License or GNU General Public License
|_______________| http://www.uize.com/license.html
*/
/* Module Meta Data
type: Class
importance: 6
codeCompleteness: 100
testCompleteness: 0
docCompleteness: 7
*/
/*?
Introduction
The =Uize.Widget.Picker= class acts as a base class for value picker widget classes, such as the =Uize.Widget.Picker.Date= class.
*DEVELOPERS:* `Chris van Rensburg`, `Ben Ilegbodu`
### In a Nutshell
- deferred loading of picker dialog, including loading of JavaScript modules, building and insertion of HTML markup for widget, and wiring up of picker dialog widget, so that many picker instances can be created on a page without adding siginificant load to the page.
- dialog is moored to =selector= button's root node, with =offsetX= and =offsetY= values that are half the width and height of the selector button's root node, respectively, so that the top left corner of the diaog should be positioned by the center of the selector button.
- picker dialog is shared among multiple picker instances
- when the picker dialog is launched, the values of the piped properties are relayed to the picker dialog widget, which are in turn piped through to the counterpart properties of the picker widget, allowing multiple =Uize.Widget.Picker= instances to share the same dialog widget. Whenever the dialog is launched for a specific picker instance, the dialog's state is synchronized to the state of the picker instance.
- widget class for dialog is configurable. This allows a subclass specific to your own Web application to be used, which is likely to be a subclass of =Uize.Widget.Dialog.Picker=
*/
Uize.module ({
name:'Uize.Widget.Picker',
superclass:'Uize.Widget.FormElement',
required:[
'Uize.Widget.Button.ValueDisplay',
'Uize.Node.Event'
],
builder:function (_superclass) {
/*** Variables for Scruncher Optimization ***/
var _null = null;
/*** Class Constructor ***/
var
_class = _superclass.subclass (
_null,
function () {
var _this = this;
function _pickValue () {
_this.set({focused:false});
var
_mooringNode = _this.getMooringNode(),
_mooringNodeDims = Uize.Node.getDimensions (_mooringNode)
;
function _possiblyFocus () {
_this._allowManualEntry && _this.set({focused:true})
}
_this.callInherited ('useDialog') ({
component:_this._dialogComponent
? Uize.copyInto(_this._dialogComponent, {value:_this.get('value')})
: _null,
widgetClassName:_this._dialogWidgetClass,
widgetProperties:
Uize.copyInto (
{
name:_this._dialogName || 'dialog' + _this._dialogWidgetClass.replace (/\./g,''),
picker:_this,
mooringNode:_mooringNode,
offsetX:_mooringNodeDims.width >> 1,
offsetY:_mooringNodeDims.height >> 1
},
_this.getDialogWidgetProperties(),
_this.get ((_this._pipedProperties || []).concat ('value'))
),
submitHandler:function (_valueInfo,_event) {
_this.handleDialogSubmit(_valueInfo);
_event && _event.keepOpen || _possiblyFocus ();
},
dismissHandler:_possiblyFocus
});
}
/*** watch focus by user ***/
_this.wire (
'Changed.focused',
function () { _this.get('focused') && !_this._allowManualEntry && _pickValue () }
);
/*** watch click on input node ***/
_this.wireNode (
'input',
'mousedown',
function (_event) {
if (!_this._allowManualEntry) {
Uize.Node.Event.abort (_event);
_pickValue ();
}
}
);
/*** add selector button */
_this.addChild (
'selector',
_this._selectorButtonWidgetClass || Uize.Widget.Button.ValueDisplay,
_this._selectorButtonWidgetProperties
).wire ('Click',_pickValue);
/*?
Child Widgets
selector
document...
*/
}
),
_classPrototype = _class.prototype
;
/*** Public Methods ***/
_classPrototype.getDialogWidgetProperties = function() { return _null };
_classPrototype.getMooringNode = function() {
return this.children.selector.getNode () || this.getNode ('input')
};
_classPrototype.handleDialogSubmit = function(_valueInfo) {
var
_this = this,
_value = _valueInfo.value,
_valueDetails = _valueInfo.valueDetails,
_undefined
;
_this.set(
Uize.copyInto(
{},
_valueDetails !== _undefined ? {valueDetails:_valueDetails} : _undefined,
_value !== _undefined
? ({
value:_value != _null
? (_this._valueFormatter ? _this._valueFormatter.call (_this,_value) : _value)
: ''
}) : _undefined
)
);
};
/*** Register Properties ***/
_class.registerProperties ({
_allowManualEntry:{
name:'allowManualEntry',
value:true
/*?
State Properties
allowManualEntry
document...
NOTES
- the initial value is =true=
*/
},
_dialogComponent:'dialogComponent',
_dialogName:'dialogName',
_dialogWidgetClass:'dialogWidgetClass',
/*?
State Properties
dialogWidgetClass
document...
NOTES
- the initial value is =undefined=
*/
_pipedProperties:'pipedProperties',
/*?
State Properties
pipedProperties
document...
NOTES
- the initial value is =undefined=
*/
_selectorButtonWidgetClass:'selectorButtonWidgetClass',
_selectorButtonWidgetProperties:'selectorButtonWidgetProperties',
_valueDetails:{
name:'valueDetails',
onChange:function() {
var _selector = this.children.selector;
_selector
&& _selector.set({valueDetails:this._valueDetails});
}
},
_valueFormatter:'valueFormatter'
/*?
State Properties
valueFormatter
document...
NOTES
- the initial value is =undefined=
*/
});
/*** Override Initial Values for Inherited State Properties ***/
_class.set ({
value:_null
});
return _class;
}
});