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 : '•', // 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