/*______________
| ______ | 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.FormElement.Select Class
| / / / |
| / / / /| | ONLINE : http://uize.com
| /____/ /__/_| | COPYRIGHT : (c)2011-2014 UIZE
| /___ | LICENSE : Available under MIT License or GNU General Public License
|_______________| http://uize.com/license.html
*/
/* Module Meta Data
type: Class
importance: 6
codeCompleteness: 80
docCompleteness: 0
*/
/*?
Introduction
The =Uize.Widget.FormElement.Select= class serves a wrapper class in order to provide a beter programmable interface to a form element.
*DEVELOPERS:* `Ben Ilegbodu`, original code contributed by `Zazzle Inc.`
*/
Uize.module ({
name:'Uize.Widget.FormElement.Select',
builder:function (_superclass) {
'use strict';
/*** Private Instance Methods ***/
function _updateUiValues (m) {
if (m.isWired) {
var
_oldValue = m.get('value'),
_values = m._values,
_selectNode = m.getNode('input')
;
if (_values && _selectNode && m.get('type') == 'select-one') {
var _valueFound = false;
// setting the value to null was commented out to fix bug 9574.
// it wasn't deleted in case its exclusion caused another bug.
//m.set({value:null});
m._valueNo = -1;
// iterate through the values in values object, replacing the Option nodes
// adding new ones if necessary
for (
var
_valueNo = -1,
_valuesLength = _values.length,
_options = _selectNode.options,
_optionsLength = _options.length
;
++_valueNo < _valuesLength;
) {
var
_valueObject = _values[_valueNo],
_valueObjectName = _valueObject.name,
_selected = _oldValue == _valueObjectName,
_optionNode
;
if (_valueNo < _optionsLength)// option node already exists
_optionNode = _options[_valueNo];
else {
_optionNode = document.createElement('option');
try { _selectNode.add(_optionNode, null) } // standards compliant
catch(_ex) { _selectNode.add(_optionNode) }
}
m.setNodeProperties(
_optionNode,
{
value:_valueObjectName,
text:(_valueObject.valueDetails && _valueObject.valueDetails.displayName) || _valueObject.displayName || _valueObjectName,
selected:_selected
}
);
if (_selected)
_valueFound = true;
}
// Now iterate through options removing any extras
// NOTE: _optionsLength may not be the actual length of the options array at this point
// if we added new options past its original length. But if that's the case, there'll
// be nothing to remove, so it's ok
for (var _optionNo = _optionsLength - 1; _optionNo >= _valueNo; _optionNo--)
_selectNode.remove(_optionNo)
;
if (!(_valueFound && _oldValue) && _values.length)
m.set({value:_values[0].name});
}
}
}
return _superclass.subclass ({
alphastructor:function () {this._values = []},
omegastructor:function () {
var m = this;
m.wire(
'Changed.value',
function () {
if (m.isWired) {
var _selectNode = m.getNode('input');
_selectNode
&& m.set({_valueNo:_selectNode.selectedIndex});
}
}
);
},
instanceMethods:{
wireUi:function () {
var m = this;
if (!m.isWired) {
_superclass.doMy (m,'wireUi');
var
_values = m._values || [],
_selectNode = m.getNode('input')
;
if (_values.length) // values data exists so update the s in the tag
_updateUiValues(m);
else if (_selectNode && m.get('type') == 'select-one') { // build values from tag s
// iterate through each option and add to values state property
for (
var
_value = m.get('value'),
_options = _selectNode.options,
_optionNo = -1,
_optionsLength = _options.length
;
++_optionNo < _optionsLength;
) {
var
_optionNode = _options[_optionNo],
_optionValue = _optionNode.value,
_optionText = _optionNode.text,
_valueObjectName = _optionValue != null ? _optionValue : _optionText
;
_values.push({
name:_valueObjectName,
displayName:_optionText
});
if (_valueObjectName == _value)
_optionNode.selected = true;
}
// set valueNo to be selectedIndex && sync up the value in case it has changed
(m._valueNo = _selectNode.selectedIndex) > -1
&& m.set({value:_values[m._valueNo].name})
;
}
}
}
},
stateProperties:{
_valueNo:{ // readonly
name:'valueNo',
value:-1
},
_values:{
name:'values',
onChange:function () {_updateUiValues (this)}
}
}
});
}
});