/** * @constructor * @param {Object} options The options : {value:null} */ hui.ui.Selection = function(options) { this.options = hui.override({value:null},options); this.element = hui.get(options.element); this.name = options.name; this.items = []; this.subItems = []; this.busy = 0; this.selection = null; if (options.items && options.items.length>0) { for (var i=0; i < options.items.length; i++) { var item = options.items[i]; this.items.push(item); var element = hui.get(item.id); item.element = element; this.addItemBehavior(element,item); } this.selection = this._getSelectionWithValue(this.options.value); this._updateUI(); } else if (this.options.value !== null) { this.selection = {value:this.options.value}; } hui.ui.extend(this); }; /** * Creates a new selection widget * @param {Object} options The options : {width:0} */ hui.ui.Selection.create = function(options) { options = hui.override({width:0},options); var e = options.element = hui.build('div', {'class':'hui_selection'}); if (options.width>0) { e.style.width = options.width+'px'; } return new hui.ui.Selection(options); }; hui.ui.Selection.prototype = { /** Get the selected item * @returns {Object} The selected item, null if no selection */ getValue : function() { return this.selection; }, valueForProperty : function(p) { if (p==='value') { return this.selection ? this.selection.value : null; } else if (p==='kind') { return this.selection ? this.selection.kind : null; } return undefined; }, /** Set the selected item * @param {Object} value The selected item */ setValue : function(value) { var item = this._getSelectionWithValue(value); if (item===null) { this.selection = null; } else { this.selection = item; this.kind=item.kind; } this._updateUI(); this.fireChange(); }, _getSelectionWithValue : function(value) { var i; for (i=0; i < this.items.length; i++) { if (this.items[i].value==value) { return this.items[i]; } } for (i=0; i < this.subItems.length; i++) { var items = this.subItems[i].items; for (var j=0; j < items.length; j++) { if (items[j].value==value) { return items[j]; } } } return null; }, /** Changes selection to the first item */ selectFirst : function() { var i; for (i=0; i < this.items.length; i++) { this.changeSelection(this.items[i]); return; } for (i=0; i < this.subItems.length; i++) { var items = this.subItems[i].items; for (var j=0; j < items.length; j++) { this.changeSelection(items[j]); return; } } }, /** Set the value to null */ reset : function() { this.setValue(null); }, addItems : function(options) { options.element = hui.build('div',{parent:this.element}); var items = new hui.ui.Selection.Items(options); items.parent = this; this.subItems.push(items); }, _updateUI : function() { var i; for (i=0; i < this.items.length; i++) { hui.cls.set(this.items[i].element,'hui_selected',this.isSelection(this.items[i])); } for (i=0; i < this.subItems.length; i++) { this.subItems[i]._updateUI(); } }, /** @private */ changeSelection : function(item) { for (var i=0; i < this.subItems.length; i++) { this.subItems[i].selectionChanged(this.selection,item); } this.selection = item; this._updateUI(); this.fireChange(); }, /** @private */ fireChange : function() { this.fire('select',this.selection); this.fireProperty('value',this.selection ? this.selection.value : null); this.fireProperty('kind',this.selection ? this.selection.kind : null); for (var i=0; i < this.subItems.length; i++) { this.subItems[i].parentValueChanged(); } }, /** @private */ registerItems : function(items) { items.parent = this; this.subItems.push(items); }, /** @private */ addItemBehavior : function(node,item) { hui.listen(node,'click',function() { this.itemWasClicked(item); }.bind(this)); hui.listen(node,'dblclick',function(e) { hui.stop(e); hui.selection.clear(); this._onDoubleClick(item); }.bind(this)); node.dragDropInfo = item; }, /** Untested!! */ setObjects : function(items) { this.items = []; hui.each(items,function(item) { this.items.push(item); var node = hui.build('div',{'class':'hui_selection_item'}); item.element = node; this.element.appendChild(node); var inner = hui.build('span',{'class':'hui_selection_label',text:item.title || item.text || ''}); if (item.icon) { node.appendChild(hui.ui.createIcon(item.icon,16)); } node.appendChild(inner); hui.listen(node,'click',function() { this.itemWasClicked(item); }.bind(this)); hui.listen(node,'dblclick',function(e) { hui.stop(e); this._onDoubleClick(item); }.bind(this)); }.bind(this)); this.fireSizeChange(); }, /** @private */ isSelection : function(item) { if (this.selection===null) { return false; } var selected = item.value==this.selection.value; if (this.selection.kind) { selected = selected && item.kind==this.selection.kind; } return selected; }, /** @private */ itemWasClicked : function(item) { if (this.busy>0) {return;} this.changeSelection(item); }, _onDoubleClick : function(item) { if (this.busy>0) {return;} this.fire('open',item); }, _setBusy : function(busy) { this.busy+= busy ? 1 : -1; window.clearTimeout(this.busytimer); if (this.busy>0) { var e = this.element; this.busytimer = window.setTimeout(function() { hui.cls.add(e,'hui_selection_busy'); },300); } else { hui.cls.remove(this.element,'hui_selection_busy'); this.fire('loaded'); } }, _checkValue : function() { if (!this.selection) {return;} var item = this._getSelectionWithValue(this.selection.value); if (!item) { hui.log('Value not found: '+this.selection.value); if (!this.busy) { this.selectFirst(); } else { hui.log('Will not select first since im still busy'); } } }, show : function() { this.element.style.display=''; }, hide : function() { this.element.style.display='none'; } }; /////////////////////////// Items /////////////////////////// /** * A group of items loaded from a source * @constructor * @param {Object} options The options : {element,name,source} */ hui.ui.Selection.Items = function(options) { this.options = hui.override({source:null},options); this.element = hui.get(options.element); this.title = hui.get(this.element.id+'_title'); this.name = options.name; this.disclosed = {}; this.parent = null; this.items = []; hui.ui.extend(this); if (this.options.source) { this.options.source.listen(this); } }; hui.ui.Selection.Items.prototype = { /** * Refresh the underlying source */ refresh : function() { if (this.options.source) { this.options.source.refresh(); } }, setOptions : function(options) { this.$optionsLoaded(options); }, /** @private */ $objectsLoaded : function(objects) { this.$optionsLoaded(objects); }, /** @private */ $optionsLoaded : function(items) { this.items = []; this.element.innerHTML=''; this.buildLevel(this.element,items,0,true); if (this.title) { this.title.style.display=this.items.length>0 ? 'block' : 'none'; } this.parent._updateUI(); this.parent._checkValue(); this.fireSizeChange(); }, $sourceIsBusy : function() { this.parent._setBusy(true); }, /** @private */ $sourceIsNotBusy : function() { this.parent._setBusy(false); }, /** @private */ $sourceShouldRefresh : function() { return hui.dom.isVisible(this.element); }, /** @private */ $visibilityChanged : function() { if (hui.dom.isVisible(this.element)) { if (this.options.source) { // If there is a source, make sure it is initially this.options.source.refreshFirst(); } } }, /** @private */ buildLevel : function(parent,items,inc,open) { if (!items) return; var hierarchical = this.isHierarchy(items); var level = hui.build('div',{'class':'hui_selection_level',style:(open ? 'display:block' : 'display:none'),parent:parent}); hui.each(items,function(item) { var text = item.text || item.title || ''; if (item.type=='title') { hui.build('div',{'class':'hui_selection_title',html:'<span>'+text+'</span>',parent:level}); return; } var hasChildren = item.children && item.children.length>0; var left = inc*16+6; if (!hierarchical && inc>0 || hierarchical && !hasChildren) { left+=13; } var node = hui.build('div',{'class':'hui_selection_item'}); node.style.paddingLeft = left+'px'; if (item.badge) { node.appendChild(hui.build('strong',{'class':'hui_selection_badge',text:item.badge})); } var subOpen = false; if (hierarchical && hasChildren) { var self = this; subOpen = this.disclosed[item.value]; var cls = this.disclosed[item.value] ? 'hui_disclosure hui_disclosure_open' : 'hui_disclosure'; var disc = hui.build('span', {'class': cls, parent: node}); hui.listen(disc,'click',function(e) { hui.stop(e); self.toggle(disc,item); }); } var rendition = hui.ui.callDelegates(this.parent, 'render', item); if (rendition) { node.appendChild(rendition); } else { var inner = hui.build('span', {'class':'hui_selection_label', text: text}); if (item.icon) { node.appendChild(hui.ui.createIcon(item.icon, 16)); } node.appendChild(inner); } hui.listen(node,'click',function(e) { this.parent.itemWasClicked(item); }.bind(this)); hui.listen(node,'dblclick',function(e) { hui.stop(e); hui.selection.clear(); this.parent._onDoubleClick(item); }.bind(this)); level.appendChild(node); var info = {title:text,icon:item.icon,badge:item.badge,kind:item.kind,element:node,value:item.value}; node.dragDropInfo = info; this.items.push(info); this.buildLevel(level,item.children,inc+1,subOpen); }.bind(this)); }, /** @private */ toggle : function(node,item) { if (hui.cls.has(node,'hui_disclosure_open')) { this.disclosed[item.value] = false; hui.get.next(node.parentNode).style.display='none'; hui.cls.remove(node,'hui_disclosure_open'); } else { this.disclosed[item.value] = true; hui.get.next(node.parentNode).style.display='block'; hui.cls.add(node,'hui_disclosure_open'); } this.parent.fireSizeChange(); }, /** @private */ isHierarchy : function(items) { if (!items) {return false;} for (var i=0; i < items.length; i++) { if (items[i]!==null && items[i].children && items[i].children.length>0) { return true; } } return false; }, /** Get the selection of this items group * @returns {Object} The selected item or null */ getValue : function() { if (this.parent.selection === null) { return null; } for (var i=0; i < this.items.length; i++) { if (this.items[i].value == this.parent.selection.value) { return this.items[i]; } } return null; }, _updateUI : function() { for (var i=0; i < this.items.length; i++) { hui.cls.set(this.items[i].element,'hui_selected',this.parent.isSelection(this.items[i])); } }, /** @private */ selectionChanged : function(oldSelection,newSelection) { for (var i=0; i < this.items.length; i++) { var value = this.items[i].value; if (value == newSelection.value) { this.fireProperty('value',newSelection.value); return; } } this.fireProperty('value',null); }, /** * Called when the parent changes value, must fire its new value * @private */ parentValueChanged : function() { for (var i=0; i < this.items.length; i++) { if (this.parent.isSelection(this.items[i])) { this.fireProperty('value',this.items[i].value); return; } } this.fireProperty('value',null); } };