// vim: et:ts=4:sw=4:sts=4:ft=javascript 'use strict'; /*@ Ox.Select Select Object () -> Select Object (options) -> Select Object (options, self) -> Select Object options Options object disabled If true, select is disabled id Element id items Items 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' 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') width Width in px, or 'auto' self Shared private variable click Click event change Change event @*/ Ox.Select = function(options, self) { // fixme: make selected a separate option // fixme: selected item needs attribute "checked", not "selected" ... that's strange self = self || {}; var that = Ox.Element({ tooltip: options.tooltip || '' }, self) .defaults({ id: '', items: [], label: '', labelWidth: 64, max: 1, maxWidth: 0, min: 1, overlap: 'none', // can be none, left or right size: 'medium', style: 'rounded', title: '', type: 'text', // can be 'text' or 'image' value: '', width: 'auto' }) // fixme: make default selection restorable // or allow for extra action items below options // fixme: passing value has no effect .options(options) .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({ click: showMenu, key_escape: loseFocus, key_down: showMenu }); Ox.Log('Form', 'Ox.Select', self.options); self.optionGroup = new Ox.OptionGroup( self.options.items, self.options.min, self.options.max ); self.options.items = self.optionGroup.init(); self.checked = self.optionGroup.checked(); if (self.options.label) { self.$label = Ox.Label({ overlap: 'right', textAlign: 'right', title: self.options.label, width: self.options.labelWidth }) .click(function() { // fixme: ??? // that.focus(); }) .appendTo(that); } if (self.options.type == 'text') { self.$title = $('
') .addClass('OxTitle') .css({ width: getTitleWidth() + 'px' }) .html( self.options.title || self.options.items[self.checked[0]].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) { //Ox.Log('Form', 'clickMenu: ', self.options.id, data) self.checked = self.optionGroup.checked(); self.options.value = data.checked.length ? data.checked[0].id : ''; self.$title && self.$title.html( self.options.title ? self.options.title : data.checked[0].title ); that.triggerEvent('change', { selected: data.checked, value: self.options.value }); } function getTitleWidth() { // fixme: used to be 22. obscure return self.options.width - 24 - ( self.options.label ? self.options.labelWidth : 0 ); } function hideMenu() { //Ox.Log('Form', '%% hideMenu that', that, 'self', self) that.removeClass('OxSelected'); // self.$button.removeClass('OxSelected'); //Ox.Log('Form', '%% hideMenu end') } function loseFocus() { that.loseFocus(); } function showMenu() { that.gainFocus(); that.addClass('OxSelected'); self.options.tooltip && that.$tooltip.hide(); self.$menu.showMenu(); } self.setOption = function(key, value) { if (key == 'labelWidth') { self.$label.options({width: value}); self.$title.css({width: getTitleWidth() + 'px'}); } else if (key == 'title') { if (self.options.type == 'text') { self.$title.html(value); } else { self.$button.options({title: value}); } } else if (key == 'width') { Ox.Log('Form', 'SETTING WIDTH OPTION', value) that.css({width: value - 2 + 'px'}); self.$title.css({width: getTitleWidth() + 'px'}); } else if (key == 'value') { Ox.Log('Form', 'SETTING VALUE OPTION', value) that.selectItem(value); } }; that.disableItem = function(id) { self.$menu.getItem(id).options({disabled: true}); }; that.enableItem = function(id) { self.$menu.getItem(id).options({disabled: false}); }; self.superRemove = that.remove; that.remove = function() { self.$menu.remove(); self.superRemove(); }; // FIXME: selected() _and_ selectItem() _and_ value() ??? /*@ selected gets selected item () -> returns object of selected items with id, title @*/ that.selected = function() { return self.optionGroup.checked().map(function(v) { return { id: self.options.items[v].id, title: self.options.items[v].title }; }); }; /*@ selectItem select item in group (id) -> select item by id id item id @*/ that.selectItem = function(id) { Ox.Log('Form', 'selectItem', id, self.options.items, self.options.items.length, Ox.getObjectById(self.options.items, id)) self.options.type == 'text' && self.$title.html( Ox.getObjectById(self.options.items, id).title ); self.$menu.checkItem(id); self.checked = self.optionGroup.checked(); }; /* 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; }; */ that.value = function() { var selected; if (arguments.length == 0) { selected = that.selected(); return selected.length ? that.selected()[0].id : ''; } else { that.selectItem(arguments[0]); return that; /* Ox.Log('Form', 'ELSE'); that.selectItem(arguments[0]); return that; */ } }; return that; };