/** * @author Ryan Johnson * @copyright 2008 PersonalGrid Corporation * @package LivePipe UI * @license MIT * @url http://livepipe.net/control/rating * @require prototype.js, livepipe.js */ /*global Prototype, Class, Option, $, $A, Control, $break, */ if(typeof(Prototype) == "undefined") { throw "Control.SelectMultiple requires Prototype to be loaded."; } if(typeof(Object.Event) == "undefined") { throw "Control.SelectMultiple requires Object.Event to be loaded."; } Control.SelectMultiple = Class.create({ select: false, container: false, numberOfCheckedBoxes: 0, checkboxes: [], hasExtraOption: false, initialize: function(select,container,options){ this.options = { checkboxSelector: 'input[type=checkbox]', nameSelector: 'span.name', labelSeparator: ', ', valueSeparator: ',', afterChange: Prototype.emptyFunction, overflowString: function(str){ return str.truncate(); }, overflowLength: 30 }; Object.extend(this.options,options || {}); this.select = $(select); this.container = $(container); this.checkboxes = (typeof(this.options.checkboxSelector) == 'function') ? this.options.checkboxSelector.bind(this)() : this.container.getElementsBySelector(this.options.checkboxSelector); var value_was_set = false; if(this.options.value){ value_was_set = true; this.setValue(this.options.value); delete this.options.value; } this.hasExtraOption = false; this.checkboxes.each(function(checkbox){ checkbox.observe('click',this.checkboxOnClick.bind(this,checkbox)); }.bind(this)); this.select.observe('change',this.selectOnChange.bind(this)); this.countAndCheckCheckBoxes(); if(!value_was_set) { this.scanCheckBoxes(); } this.notify('afterChange',this.select.options[this.select.options.selectedIndex].value); }, countAndCheckCheckBoxes: function(){ this.numberOfCheckedBoxes = this.checkboxes.inject(0,function(number,checkbox){ checkbox.checked = (this.select.options[this.select.options.selectedIndex].value == checkbox.value); var value_string = this.select.options[this.select.options.selectedIndex].value; var value_collection = $A(value_string.split ? value_string.split(this.options.valueSeparator) : value_string); var should_check = value_collection.any(function(value) { if (!should_check && checkbox.value == value) { return true; } }.bind(this)); checkbox.checked = should_check; if(checkbox.checked) { ++number; } return number; }.bind(this)); }, setValue: function(value_string){ this.numberOfCheckedBoxes = 0; var value_collection = $A(value_string.split ? value_string.split(this.options.valueSeparator) : value_string); this.checkboxes.each(function(checkbox){ checkbox.checked = false; value_collection.each(function(value){ if(checkbox.value == value){ ++this.numberOfCheckedBoxes; checkbox.checked = true; } }.bind(this)); }.bind(this)); this.scanCheckBoxes(); }, selectOnChange: function(){ this.removeExtraOption(); this.countAndCheckCheckBoxes(); this.notify('afterChange',this.select.options[this.select.options.selectedIndex].value); }, checkboxOnClick: function(checkbox){ this.numberOfCheckedBoxes = this.checkboxes.findAll(function (c) { return c.checked; }).length; this.scanCheckBoxes(); this.notify('afterChange', this.numberOfCheckedBoxes === 0 ? "" : this.select.options[this.select.options.selectedIndex].value); }, scanCheckBoxes: function(){ switch(this.numberOfCheckedBoxes){ case 1: this.checkboxes.each(function(checkbox){ if(checkbox.checked){ $A(this.select.options).each(function(option,i){ if(option.value == checkbox.value){ this.select.options.selectedIndex = i; throw $break; } }.bind(this)); throw $break; } }.bind(this)); break; case 0: this.removeExtraOption(); break; default: this.addExtraOption(); break; } }, getLabelForExtraOption: function(){ var label = (typeof(this.options.nameSelector) == 'function' ? this.options.nameSelector.bind(this)() : this.container.getElementsBySelector(this.options.nameSelector).inject([],function(labels,name_element,i){ if(this.checkboxes[i].checked) { labels.push(name_element.innerHTML); } return labels; }.bind(this)) ).join(this.options.labelSeparator); return (label.length >= this.options.overflowLength && this.options.overflowLength > 0) ? (typeof(this.options.overflowString) == 'function' ? this.options.overflowString(label) : this.options.overflowString) : label; }, getValueForExtraOption: function(){ return this.checkboxes.inject([],function(values,checkbox){ if(checkbox.checked) { values.push(checkbox.value); } return values; }).join(this.options.valueSeparator); }, addExtraOption: function(){ this.removeExtraOption(); this.hasExtraOption = true; this.select.options[this.select.options.length] = new Option(this.getLabelForExtraOption(),this.getValueForExtraOption()); this.select.options.selectedIndex = this.select.options.length - 1; }, removeExtraOption: function(){ if(this.hasExtraOption){ this.select.remove(this.select.options.length - 1); this.hasExtraOption = false; } } }); Object.Event.extend(Control.SelectMultiple);