javascripts/right-selectable-src.js in right-rails-0.5.1 vs javascripts/right-selectable-src.js in right-rails-0.5.2

- old
+ new

@@ -6,11 +6,11 @@ if (!self.RightJS) throw "Gimme RightJS"; /** * Selectable unit main script * - * Copyright (C) 2009 Nikolay V. Nemshilov + * Copyright (C) 2009-2010 Nikolay V. Nemshilov */ var Selectable = new Class(Observer, { extend: { EVENTS: $w('change select unselect disable enable hover leave show hide'), @@ -25,10 +25,12 @@ fxDuration: 'short', // the drop-down options list fx-duration update: null, // a field to be assigned to parseIds: false, // if it should parse integer ids out of the keys + limit: null, // put some number if you'd like to limit the number of selected items + hCont : '&bull;', // single-selectable handle content refresh: true // a flag if it should automatically refresh the items list }, @@ -53,25 +55,28 @@ * * @param mixed reference to an element or the options hash * @param Object options hash */ initialize: function() { - var args = $A(arguments); + var args = $A(arguments), selectbox; if (args[0] && !isHash(args[0])) this.element = $(args[0]); this.$super(isHash(args.last()) ? args.last() : this.element ? eval('('+this.element.get('data-selectable-options')+')') : null); - + if (!this.element) this.element = this.build(); - else if (this.element.tagName == 'SELECT') { + else if ((selectbox = this.element.tagName == 'SELECT')) { this.selectbox = this.harvestOptions(this.element); this.element = this.build().insertTo(this.selectbox, 'before'); - this.assignTo(this.hideOriginal(this.selectbox)); + } this.element._selectable = this.init(); + + if (selectbox) + this.assignTo(this.hideOriginal(this.selectbox)); }, // standard descructor destroy: function() { this.items.each(function(item) { @@ -96,24 +101,27 @@ if (isString(value)) value = value.split(',').map('trim').filter(function(s) { return !s.blank(); }); // resetting the selections this.items.each('removeClass', this.selectedClass); - // selecting the value - var items = this.mapEnabled(value).each('addClass', this.selectedClass); - if (this.isSingle) this.showItem(items[0]); - - return this.calcValue(); + return this.select(value); }, /** * Returns the list of selected items * * @return Array of selectees */ getValue: function() { - return this.value; + if (this.isSingle) { + var item = this.items.first('hasClass', this.selectedClass); + return item ? this.itemValue(item) : null; + } else { + return this.items.filter('hasClass', this.selectedClass).map(function(item) { + return this.itemValue(item); + }, this); + } }, /** * Inserts the widget into the element at the given position * @@ -149,15 +157,15 @@ }.bind(object)); } }.curry(element); if ($(element)) { - assign(this.value); + assign(this.getValue()); connect(this); } else { document.onReady(function() { - assign(this.value); + assign(this.getValue()); connect(this); }.bind(this)); } return this.onChange(assign); @@ -207,19 +215,30 @@ * * @param mixed key or keys * @return Selectable this */ select: function(keys) { - var items = this.mapEnabled(keys); + var items = this.mapEnabled(keys), selected_class = this.selectedClass; if (this.isSingle && items) { - this.items.each('removeClass', this.selectedClass); + this.items.each('removeClass', selected_class); items = [items[0]]; } + // applying the selection limit if ncessary + if (!this.isSingle && this.options.limit) { + var selected = this.items.filter('hasClass', selected_class), clean = []; + while (items.length && (selected.length + clean.length) < this.options.limit) { + var item = items.shift(); + if (!selected.include(item)) + clean.push(item); + } + items = clean; + } + items.each(function(item) { - this.fire('select', item.addClass(this.selectedClass)); + this.fire('select', item.addClass(selected_class)); }, this); return this; }, @@ -283,12 +302,21 @@ this.onMouseover = this.mouseover.bind(this); this.onMouseout = this.mouseout.bind(this); this.onClick = this.click.bind(this); this.value = null; - this.refresh().onSelect('calcValue').onUnselect('calcValue'); + var on_change = function() { + var value = this.getValue(); + if (value != this.value) { + this.value = value; + this.fire('change', value, this); + } + }.bind(this); + + this.refresh().onSelect(on_change).onUnselect(on_change); + if (this.isSingle) this.onSelect('showItem'); if (this.options.disabled) this.disable(this.options.disabled); if (this.options.selected) this.select(this.options.selected); if (this.options.update) this.assignTo(this.options.update); if (this.isSingle) { @@ -307,29 +335,10 @@ } return this; }, - // calculates the value out of the selected items - calcValue: function() { - if (this.isSingle) { - var item = this.items.first('hasClass', this.selectedClass); - var value = item ? this.itemValue(item) : null; - } else { - var value = this.items.filter('hasClass', this.selectedClass).map(function(item) { - return this.itemValue(item); - }, this); - } - - if (value != this.value) { - this.value = value; - this.fire('change', value, this); - } - - return this; - }, - // finds out the value for the item itemValue: function(item) { return item.id ? this.options.parseIds ? item.id.match(/\d+/) : item.id : this.items.indexOf(item); }, @@ -360,11 +369,11 @@ }, this).compact(); }, // returns matching items or all of them if there's no key mapOrAll: function(keys) { - return keys ? this.map(keys) : this.items; + return defined(keys) ? this.map(keys) : this.items; }, // maps and filters only enabled items mapEnabled: function(keys) { return this.mapOrAll(keys).filter(function(item) { @@ -513,10 +522,10 @@ options.options = {}; options.selected = []; options.disabled = []; $A(box.getElementsByTagName('OPTION')).each(function(option, index) { - options.options[option.get('value') || option.innerHTML] = option.innerHTML; + options.options[$(option).get('value') || option.innerHTML] = option.innerHTML; if (option.selected) options.selected.push(index); if (option.disabled) options.disabled.push(index); }); \ No newline at end of file