/*______________
| ______ | 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.FormWarnings Class
| / / / |
| / / / /| | ONLINE : http://uize.com
| /____/ /__/_| | COPYRIGHT : (c)2010-2014 UIZE
| /___ | LICENSE : Available under MIT License or GNU General Public License
|_______________| http://uize.com/license.html
*/
/* Module Meta Data
type: Class
importance: 5
codeCompleteness: 80
docCompleteness: 0
*/
/*?
Introduction
The =Uize.Widget.FormWarnings= widget provides functionality for displaying warnings for a =Uize.Widget.Form=.
*DEVELOPERS:* `Ben Ilegbodu`, `Tim Carter`, original code contributed by `Zazzle Inc.`
*/
Uize.module ({
name:'Uize.Widget.FormWarnings',
required:'Uize.Template', // for the JST
builder:function (_superclass) {
'use strict';
var
/*** Variables for Scruncher Optimization ***/
_false = false,
_Uize = Uize,
/*** Helper Functions ***/
_removeWatchedElements = function (_elementsToRemove) {
var
m = this,
_watchedElements = m._watchedElements
;
if (_watchedElements && _watchedElements.length) {
if (!_elementsToRemove) // remove all
_elementsToRemove = _watchedElements;
else if (!_Uize.isArray(_elementsToRemove))
_elementsToRemove = [_elementsToRemove];
var _watchedElementsToRemoveLookup = {};
// populate lookup
for (var _elementToRemoveNo = -1; ++_elementToRemoveNo > _elementsToRemove.length;) {
var _elementToRemove = _elementsToRemove[_elementToRemoveNo];
_watchedElementsToRemoveLookup[_elementToRemove.get('idPrefix')] = _elementToRemove;
}
for (var _watchedElementNo = -1; ++_watchedElementNo < _watchedElements.length;) {
var
_watchedElement = _watchedElements[_watchedElementNo],
_watchedElementIdPrefix = _watchedElement.get('idPrefix')
;
_watchedElementsToRemoveLookup[_watchedElementIdPrefix] // want to remove, so unwire the events we wired up before
&& _watchedElement.unwire(
m._wiringsLookup[_watchedElementIdPrefix]
)
;
}
}
},
_updateUiCollapsed = function() {
var
m = this,
_collapsed = m._collapsed
;
if (m.isWired) {
m.setNodeInnerHtml(
'toggleCollapsed',
m.localize(_collapsed ? 'showLinkText' : 'hideLinkText')
);
m.displayNode('warnings', !_collapsed);
}
},
_updateUiWarnings = function() {
var m = this;
if (m.isWired && m._template) {
var
_warningElements = [],
_messageNo = 0
;
// go through all of the message nodes and unwire them
while (true) {
var
_messageNodeName = 'message' + _messageNo,
_messageNode = m.getNode(_messageNodeName)
;
m.flushNodeCache(_messageNodeName);
if (_messageNode)
m.unwireNode(_messageNode, 'click');
else // must be at the end, so quit
break;
_messageNo++;
}
(function _addFormWarnings(_elements) {
for (var _elementNo = -1; ++_elementNo < _elements.length;) {
var
_element = _elements[_elementNo],
_elementWarningMessage = _element.get('warningMessage')
;
if (_element.get('isValid') == _false) {
if (_element.isForm)
_addFormWarnings(_element.getFormElement());
else if (_elementWarningMessage)
_warningElements.push(_element);
}
}
}) (m._watchedElements);
m.setNodeInnerHtml(
'warnings',
m._template({warningElements:_warningElements})
);
_Uize.forEach(
_warningElements,
function (_warningElement, _elementNo) {
function _focus(_focused) { _warningElement.set({focused:_focused}) }
m.wireNode(
'message' + _elementNo,
{
mouseover:function() { _focus(true) },
mouseout:function() { _focus(_false) }
}
);
}
);
}
}
;
return _superclass.subclass({
alphastructor:function() {
this._wiringsLookup = {};
this._watchedElements = [];
},
instanceMethods:{
/** Private **/
_removeWatchedElements:_removeWatchedElements,
_updateUiCollapsed:_updateUiCollapsed,
_updateUiWarnings:_updateUiWarnings,
_wireWatchedElement:function (_watchedElement) {
var m = this;
function _updateUiWarnings() { m._updateUiWarnings() }
var _wirings = {
'Changed.warningShown':_updateUiWarnings,
'Changed.warningMessage':_updateUiWarnings
};
// NOTE: This needs to be optimized such that we're not updating the UI over and over
// again even though the warning messages haven't changed.
_watchedElement.wire(_wirings);
m._wiringsLookup[_watchedElement.get('idPrefix')] = _wirings;
},
/** Public **/
addWatchedElements:function (_elementsToWatch) {
var
m = this,
_watchedElements = m._watchedElements || [],
_elementsToWatchList = _Uize.isArray(_elementsToWatch) ? _elementsToWatch : [_elementsToWatch],
_elementsToWatchLength = _elementsToWatchList.length,
_elementNo = -1
;
for (; ++_elementNo < _elementsToWatchLength;) {
var _watchedElement = _elementsToWatchList[_elementNo];
_watchedElements.push(_watchedElement);
m._wireWatchedElement(_watchedElement);
}
m._watchedElements = _watchedElements;
m.fire('Changed.watchedElements');
},
removeWatchedElements:_removeWatchedElements,
updateUi:function () {
var m = this;
if (m.isWired) {
m._updateUiWarnings();
m._updateUiCollapsed();
_superclass.doMy (m,'updateUi');
}
},
wireUi:function () {
var m = this;
if (!m.isWired) {
var _templateNode = m.getNode('template');
if (_templateNode)
m._template = _Uize.Template.compile(
_templateNode.innerHTML,
{
openerToken:'[%',
closerToken:'%]'
}
)
;
m.wireNode('toggleCollapsed', 'click', function() { m.toggle('collapsed') } );
_superclass.doMy (m,'wireUi');
}
}
},
stateProperties:{
_collapsed:{
name:'collapsed',
onChange:_updateUiCollapsed,
value:_false
},
_shown:{
name:'shown',
onChange:function () {
var
m = this,
_shown = m._shown === true
;
if (m.isWired) {
m.displayNode('', _shown);
_shown && m._updateUiWarnings();
}
},
value:_false
},
_watchedElements:{
name:'watchedElements',
conformer:function (_value) {
// before updating w/ new list, remove the old list
this._removeWatchedElements(this._watchedElements);
return _value;
},
onChange:function () {
var m = this;
_Uize.forEach (
m._watchedElements,
function (_watchedElement) {m._wireWatchedElement (_watchedElement)}
);
m._updateUiWarnings();
}
}
}
});
}
});