/*______________ | ______ | 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.Tree Class | / / / | | / / / /| | ONLINE : http://uize.com | /____/ /__/_| | COPYRIGHT : (c)2003-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: 100 docCompleteness: 2 */ /*? Introduction The =Uize.Widget.Tree= class is a base class for hierarchical collapsible/expandable tree widgets of many kinds, including lists, drop-down menus, etc. *DEVELOPERS:* `Chris van Rensburg` */ Uize.module ({ name:'Uize.Widget.Tree', builder:function (_superclass) { 'use strict'; var /*** Variables for Scruncher Optimization ***/ _undefined, _false = false ; /*** Private Instance Methods ***/ function _canonicalizeItemSpecifier (m,_itemSpecifier) { return ( typeof _itemSpecifier == 'string' ? _itemSpecifier : m.getItemInfoFromSpecifier (_itemSpecifier).itemSpecifier ); } return _superclass.subclass ({ instanceMethods:{ getItemFromSpecifier:function (_itemSpecifier) { return this.getItemInfoFromSpecifier (_itemSpecifier).item; }, getItemInfoFromSpecifier:function (_itemSpecifier) { var m = this, _item, _items = m._items, _canonicalItemSpecifier = [], _titleParts = [], _itemSpecifierWasArray = Uize.isArray (_itemSpecifier), _itemDelimiter = m._itemDelimiter, _itemSpecifierLevels = _itemSpecifierWasArray ? _itemSpecifier : _itemSpecifier.split (_itemDelimiter), _itemSpecifierLevelsLength = _itemSpecifierLevels.length ; for (var _levelNo = -1; ++_levelNo < _itemSpecifierLevelsLength;) { var _itemSpecifierForLevel = _itemSpecifierLevels [_levelNo]; if (_itemSpecifierWasArray && typeof _itemSpecifierForLevel == 'string') _itemSpecifierForLevel = Uize.findRecordNo (_items,{title:_itemSpecifierForLevel}) ; _item = _items [_itemSpecifierForLevel]; if (_item) { _items = _item.items; _canonicalItemSpecifier.push (_itemSpecifierForLevel); _titleParts.push (_item.title); } else { break; } } return { item:_item, titleParts:_titleParts, itemSpecifier:_item ? _canonicalItemSpecifier.join (_itemDelimiter) : '' }; }, setExpandedDepth:function (_expandedDepth,_itemSpecifier) { var m = this; m.traverseTree ({ itemHandler: function (_item,_itemSpecifier,_depth) { m.setItemExpanded (_itemSpecifier,_depth < _expandedDepth); }, itemSpecifier:_itemSpecifier }); }, setItemExpanded:function (_itemSpecifier,_expanded) { /* NOTE: - override the implementation of this method in a subclass - fall back to using this implementation in subclass implementation if widget is not yet wired */ var _item = this.getItemFromSpecifier (_itemSpecifier); _item.expanded = typeof _expanded == 'boolean' ? _expanded : _item.expanded === _false; }, collapseAllBut:function (_expandedItemSpecifier) { var m = this, _itemDelimiter = m._itemDelimiter ; _expandedItemSpecifier = _canonicalizeItemSpecifier (m,_expandedItemSpecifier); m.traverseTree ({ itemHandler: function (_item,_itemSpecifier) { m.setItemExpanded ( _itemSpecifier, !(_expandedItemSpecifier + _itemDelimiter).indexOf (_itemSpecifier + _itemDelimiter) ); } }); }, traverseTree:function (_params) { var m = this, _itemSpecifier = _params.itemSpecifier, _itemDelimiter = m._itemDelimiter, _nop = Uize.nop, _itemHandler = _params.itemHandler || _nop, _beforeSubItemsHandler = _params.beforeSubItemsHandler || _nop, _afterSubItemsHandler = _params.afterSubItemsHandler || _nop ; function _traverseItem (_item,_itemSpecifier,_depth) { _itemHandler (_item,_itemSpecifier,_depth); var _itemItems = _item.items; if (_itemItems && _itemItems.length) { _beforeSubItemsHandler (_item,_itemSpecifier,_depth); _traverseItems (_itemItems,_itemSpecifier + _itemDelimiter,_depth + 1); _afterSubItemsHandler (_item,_itemSpecifier,_depth); } } function _traverseItems (_items,_itemSpecifierPrefix,_depth) { for (var _itemNo = -1, _itemsLength = _items.length; ++_itemNo < _itemsLength;) _traverseItem (_items [_itemNo],_itemSpecifierPrefix + _itemNo,_depth) ; } if (_itemSpecifier) { _itemSpecifier = _canonicalizeItemSpecifier (m,_itemSpecifier); _traverseItem (m.getItemFromSpecifier (_itemSpecifier),_itemSpecifier,0); } else { _traverseItems (m._items,'',0); } } }, staticMethods:{ itemHasChildren:function (_item) { return !!(_item && _item.items && _item.items.length); }, itemIsDivider:function (_item) { return !!_item && _item.title == '-' && !this.itemHasChildren (_item); } }, stateProperties:{ _itemDelimiter:{ name:'itemDelimiter', value:'x' }, _items:{ name:'items', value:[], onChange:function () { var m = this; if (m.isWired) { m.removeUi (); m.insertUi (); } } }, _value:{ name:'value', value:[] } }, set:{ built:_false } }); } });