/**
* @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);
}
};