'use strict'; /*@ Ox.Select Select Object ([options[, self]) -> Select Object options Options object disabled If true, select is disabled id Element id items Items (array of {id, title} or strings) label Label labelWidth Label width max Maximum number of selected items maxWidth Maximum menu width min Minimum number of selected items overlap Can be 'none', 'left' or 'right' selectable is selectable size Size, can be small, medium, large style Style ('rounded' or 'square') title Select title tooltip Tooltip title, or function that returns one (e) -> Tooltip title e Mouse event type Type ('text' or 'image') value Selected id, or array of selected ids width Width in px, or 'auto' self Shared private variable click Click event change Change event @*/ Ox.Select = function(options, self) { self = self || {}; var that = Ox.Element({ tooltip: options.tooltip || '' }, self) .defaults({ id: '', items: [], label: '', labelWidth: 64, max: 1, maxWidth: 0, min: 1, overlap: 'none', size: 'medium', style: 'rounded', title: '', type: 'text', value: options.max != 1 ? [] : '', width: 'auto' }) // fixme: make default selection restorable .options(options) .update({ labelWidth: function() { self.$label.options({width: self.options.labelWidth}); self.$title.css({width: getTitleWidth() + 'px'}); }, title: function() { if (self.options.type == 'text') { self.$title.html(self.options.title); } else { self.$button.options({title: self.options.title}); } }, width: function() { that.css({width: self.options.width- 2 + 'px'}); self.$title.css({width: getTitleWidth() + 'px'}); }, value: function() { var value = self.options.value; if (self.options.type == 'text' && !self.options.title) { self.$title.html(getItem(value).title); } value !== '' && Ox.makeArray(value).forEach(function(value) { self.$menu.checkItem(value); }); self.options.value = self.optionGroup.value(); } }) .addClass( 'OxSelect Ox' + Ox.toTitleCase(self.options.size) + ' Ox' + Ox.toTitleCase(self.options.style) + ( self.options.overlap == 'none' ? '' : ' OxOverlap' + Ox.toTitleCase(self.options.overlap) ) + (self.options.label ? ' OxLabelSelect' : '') ) .css(self.options.width == 'auto' ? {} : { width: self.options.width - 2 + 'px' }) .bindEvent({ anyclick: showMenu, key_escape: loseFocus, key_down: showMenu }); Ox.Log('Form', 'Ox.Select', self.options); self.options.items = self.options.items.map(function(item) { var isObject = Ox.isObject(item); return Ox.isEmpty(item) ? item : { id: isObject ? item.id : item, title: isObject ? item.title : item, checked: Ox.makeArray(self.options.value).indexOf( isObject ? item.id : item ) > -1, disabled: isObject ? item.disabled : false }; }); self.optionGroup = new Ox.OptionGroup( self.options.items, self.options.min, self.options.max, 'checked' ); self.options.items = self.optionGroup.init(); self.options.value = self.optionGroup.value(); if (self.options.label) { self.$label = Ox.Label({ overlap: 'right', textAlign: 'right', title: self.options.label, width: self.options.labelWidth }) .appendTo(that); } if (self.options.type == 'text') { self.$title = $('
') .addClass('OxTitle') .css({ width: getTitleWidth() + 'px' }) .html( self.options.title || getItem(self.options.value).title ) .appendTo(that); } self.$button = Ox.Button({ id: self.options.id + 'Button', style: 'symbol', title: self.options.type == 'text' || !self.options.title ? 'select' : self.options.title, type: 'image' }) .appendTo(that); self.$menu = Ox.Menu({ element: self.$title || self.$button, id: self.options.id + 'Menu', items: [{ group: self.options.id + 'Group', items: self.options.items, max: self.options.max, min: self.options.min }], maxWidth: self.options.maxWidth, side: 'bottom', // FIXME: should be edge size: self.options.size }) .bindEvent({ change: changeMenu, click: clickMenu, hide: hideMenu }); self.options.type == 'image' && self.$menu.addClass('OxRight'); function clickMenu(data) { that.triggerEvent('click', data); } function changeMenu(data) { self.options.value = self.optionGroup.value(); self.$title && self.$title.html( self.options.title || getItem(self.options.value).title ); that.triggerEvent('change', { title: Ox.isEmpty(self.options.value) ? '' : Ox.isArray(self.options.value) ? self.options.value.map(function(value) { return getItem(value).title; }) : getItem(self.options.value).title, value: self.options.value }); } function getItem(id) { return Ox.getObjectById(self.options.items, id); } function getTitleWidth() { // fixme: used to be 22. obscure return self.options.width - 24 - ( self.options.label ? self.options.labelWidth : 0 ); } function hideMenu() { that.loseFocus(); that.removeClass('OxSelected'); } function loseFocus() { that.loseFocus(); } function selectItem() { } function showMenu() { that.gainFocus(); that.addClass('OxSelected'); self.options.tooltip && that.$tooltip.hide(); self.$menu.showMenu(); } /*@ disableItem disableItem @*/ that.disableItem = function(id) { self.$menu.getItem(id).options({disabled: true}); }; /*@ enableItem enableItem @*/ that.enableItem = function(id) { self.$menu.getItem(id).options({disabled: false}); }; /*@ remove remove @*/ self.superRemove = that.remove; that.remove = function() { self.$menu.remove(); self.superRemove(); }; /*@ selected gets selected item () -> returns array of selected items with id and title @*/ that.selected = function() { return Ox.makeArray(self.optionGroup.value()).map(function(id) { return { id: id, title: getItem(id).title }; }); }; /* that.width = function(val) { // fixme: silly hack, and won't work for css() ... remove! that.$element.width(val + 16); that.$button.width(val); //that.$symbol.width(val); return that; }; */ return that; };