diff --git a/js/jquery.multi-select.js b/js/jquery.multi-select.js
index 2d70e38..db2f78c 100644
--- a/js/jquery.multi-select.js
+++ b/js/jquery.multi-select.js
@@ -41,9 +41,22 @@
ms.attr('id', ms.attr('id') ? ms.attr('id') : Math.ceil(Math.random()*1000)+'multiselect');
this.$container.attr('id', 'ms-'+ms.attr('id'));
this.$container.addClass(that.options.cssClass);
- ms.find('option').each(function(){
- that.generateLisFromOption(this);
+ var handler = {
+ selectableUl: [],
+ selectionUl: [],
+ selectableOptgroups: {},
+ selectionOptgroups: {}
+ };
+ ms.find('option').each(function(index){
+ that.generateListFromOption(this, index, null, handler);
});
+ that.$selectableUl.prepend(handler.selectableUl.join(''));
+ that.$selectionUl.prepend(handler.selectionUl.join(''));
+ for(var optgroupId in handler.selectableOptgroups){
+ that.$selectableUl.find('#optgroup-selectable-'+optgroupId+' ul.ms-optgroup').append(handler.selectableOptgroups[optgroupId].join(''));
+ that.$selectionUl.find('#optgroup-selection-'+optgroupId+' ul.ms-optgroup').append(handler.selectionOptgroups[optgroupId].join(''));
+ }
+ handler = null;
this.$selectionUl.find('.ms-optgroup-label').hide();
@@ -95,7 +108,7 @@
}
},
- 'generateLisFromOption' : function(option, index, $container){
+ 'generateListFromOption' : function(option, index, $container, $handler){
var that = this,
ms = that.$element,
attributes = "",
@@ -108,35 +121,25 @@
attributes += attr.name+'="'+attr.value+'" ';
}
}
- var selectableLi = $('
'+that.escapeHTML($option.text())+''),
- selectedLi = selectableLi.clone(),
- value = $option.val(),
- elementId = that.sanitize(value);
-
- selectableLi
- .data('ms-value', value)
- .addClass('ms-elem-selectable')
- .attr('id', elementId+'-selectable');
-
- selectedLi
- .data('ms-value', value)
- .addClass('ms-elem-selection')
- .attr('id', elementId+'-selection')
- .hide();
-
- if ($option.attr('disabled') || ms.attr('disabled')){
- selectedLi.addClass(that.options.disabledClass);
- selectableLi.addClass(that.options.disabledClass);
- }
+
+ var value = $option.val(),
+ elementId = that.sanitize(value),
+ elementText = that.escapeHTML($option.text()),
+ elementDisabled = $option.prop('disabled') || ms.prop('disabled'),
+ elementSelected = $option.prop('selected') ? true : false,
+ selectableLi = ''+elementText+'',
+ selectedLi = ''+elementText+'';
+
var $optgroup = $option.parent('optgroup');
+ var hasHandler = typeof $handler === 'object';
if ($optgroup.length > 0){
var optgroupLabel = $optgroup.attr('label'),
optgroupId = that.sanitize(optgroupLabel),
$selectableOptgroup = that.$selectableUl.find('#optgroup-selectable-'+optgroupId),
$selectionOptgroup = that.$selectionUl.find('#optgroup-selection-'+optgroupId);
-
+
if ($selectableOptgroup.length === 0){
var optgroupContainerTpl = '',
optgroupTpl = '';
@@ -159,15 +162,31 @@
}
that.$selectableUl.append($selectableOptgroup);
that.$selectionUl.append($selectionOptgroup);
+
+ if(hasHandler){
+ $handler.selectableOptgroups[optgroupId] = [];
+ $handler.selectionOptgroups[optgroupId] = [];
+ }
+ }
+ if(hasHandler){
+ index = index == undefined ? $handler.selectableOptgroups[optgroupId].length : index;
+ $handler.selectableOptgroups[optgroupId].splice(index, 0, selectableLi);
+ $handler.selectionOptgroups[optgroupId].splice(index, 0, selectedLi);
+ }else{
+ index = index == undefined ? $selectableOptgroup.find('ul').children().length : index + 1;
+ $(selectableLi).insertAt(index, $selectableOptgroup.children());
+ $(selectedLi).insertAt(index, $selectionOptgroup.children());
}
- index = index === undefined ? $selectableOptgroup.find('ul').children().length : index + 1;
- selectableLi.insertAt(index, $selectableOptgroup.children());
- selectedLi.insertAt(index, $selectionOptgroup.children());
} else {
- index = index === undefined ? that.$selectableUl.children().length : index;
-
- selectableLi.insertAt(index, that.$selectableUl);
- selectedLi.insertAt(index, that.$selectionUl);
+ if(hasHandler){
+ index = index == undefined ? $handler.selectableUl.length : index;
+ $handler.selectableUl.splice(index, 0, selectableLi);
+ $handler.selectionUl.splice(index, 0, selectedLi);
+ }else{
+ index = index == undefined ? that.$selectableUl.children().length : index;
+ $(selectableLi).insertAt(index, that.$selectableUl);
+ $(selectedLi).insertAt(index, that.$selectionUl);
+ }
}
},
@@ -193,7 +212,7 @@
}
$option.insertAt(index, $container);
- that.generateLisFromOption($option.get(0), index, option.nested);
+ that.generateListFromOption($option.get(0), index, option.nested);
}
});
},
@@ -297,7 +316,7 @@
}
if ($nextElem.length > 0){
$nextElem.addClass('ms-hover');
- var scrollTo = $list.scrollTop() + $nextElem.position().top -
+ var scrollTo = $list.scrollTop() + $nextElem.position().top -
containerHeight / 2 + elemHeight / 2;
$list.scrollTop(scrollTo);
@@ -354,18 +373,18 @@
},
'select' : function(value, method){
- if (typeof value === 'string'){ value = [value]; }
+ if (typeof value === 'string' || typeof value === 'number'){ value = [''+value]; }
var that = this,
ms = this.$element,
msIds = $.map(value, function(val){ return(that.sanitize(val)); }),
- selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable').filter(':not(.'+that.options.disabledClass+')'),
- selections = this.$selectionUl.find('#' + msIds.join('-selection, #') + '-selection').filter(':not(.'+that.options.disabledClass+')'),
+ selectables = this.$selectableUl.find('#ms-elem-' + msIds.join('-selectable, #ms-elem-')+'-selectable').filter(':not(.'+that.options.disabledClass+')'),
+ selections = this.$selectionUl.find('#ms-elem-' + msIds.join('-selection, #ms-elem-') + '-selection').filter(':not(.'+that.options.disabledClass+')'),
options = ms.find('option:not(:disabled)').filter(function(){ return($.inArray(this.value, value) > -1); });
if (method === 'init'){
- selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable'),
- selections = this.$selectionUl.find('#' + msIds.join('-selection, #') + '-selection');
+ selectables = this.$selectableUl.find('#ms-elem-' + msIds.join('-selectable, #ms-elem-')+'-selectable'),
+ selections = this.$selectionUl.find('#ms-elem-' + msIds.join('-selection, #ms-elem-') + '-selection');
}
if (selectables.length > 0){
@@ -410,13 +429,13 @@
},
'deselect' : function(value){
- if (typeof value === 'string'){ value = [value]; }
+ if (typeof value === 'string' || typeof value === 'number'){ value = [''+value]; }
var that = this,
ms = this.$element,
msIds = $.map(value, function(val){ return(that.sanitize(val)); }),
- selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable'),
- selections = this.$selectionUl.find('#' + msIds.join('-selection, #')+'-selection').filter('.ms-selected').filter(':not(.'+that.options.disabledClass+')'),
+ selectables = this.$selectableUl.find('#ms-elem-' + msIds.join('-selectable, #ms-elem-')+'-selectable'),
+ selections = this.$selectionUl.find('#ms-elem-' + msIds.join('-selection, #ms-elem-')+'-selection').filter('.ms-selected').filter(':not(.'+that.options.disabledClass+')'),
options = ms.find('option').filter(function(){ return($.inArray(this.value, value) > -1); });
if (selections.length > 0){
diff --git a/test/spec/multiSelectSpec.js b/test/spec/multiSelectSpec.js
index c27226e..e83f388 100644
--- a/test/spec/multiSelectSpec.js
+++ b/test/spec/multiSelectSpec.js
@@ -55,7 +55,7 @@ describe("multiSelect", function() {
it ('should select the pre-selected options', function(){
$.each(selectedValues, function(index, value){
- expect($('.ms-selectable ul.ms-list li#'+sanitize(value)+'-selectable')).toBe('.ms-selected');
+ expect($('.ms-selectable ul.ms-list li#ms-elem-'+sanitize(value)+'-selectable')).toBe('.ms-selected');
});
expect($('.ms-selectable ul.ms-list li.ms-selected').length).toEqual(2);
});
@@ -75,7 +75,7 @@ describe("multiSelect", function() {
it ('should select the disabled pre-selected options', function(){
$.each(selectedValues, function(index, value){
- expect($('.ms-selectable ul.ms-list li#'+sanitize(value)+'-selectable')).toBe('.ms-selected');
+ expect($('.ms-selectable ul.ms-list li#ms-elem-'+sanitize(value)+'-selectable')).toBe('.ms-selected');
});
expect($('.ms-selectable ul.ms-list li.ms-selected').length).toEqual(3);
});
@@ -95,7 +95,7 @@ describe("multiSelect", function() {
it ('should not select the disabled non-selected options', function(){
$.each(selectedValues, function(index, value){
- expect($('.ms-selectable ul.ms-list li#'+sanitize(value)+'-selectable')).toBe('.ms-selected');
+ expect($('.ms-selectable ul.ms-list li#ms-elem-'+sanitize(value)+'-selectable')).toBe('.ms-selected');
});
expect($('.ms-selectable ul.ms-list li.ms-selected').length).toEqual(2);
});
@@ -226,7 +226,7 @@ describe("multiSelect", function() {
});
it('should show the associated selected item', function(){
- expect($('#'+sanitize(value)+'-selection')).toBe(':visible');
+ expect($('#ms-elem-'+sanitize(value)+'-selection')).toBe(':visible');
});
it('should trigger the original select change event', function(){
@@ -264,7 +264,7 @@ describe("multiSelect", function() {
});
it('should not show the associated selected item', function(){
- expect($('#'+sanitize(value)+'-selection')).not.toBe(':visible');
+ expect($('#ms-elem-'+sanitize(value)+'-selection')).not.toBe(':visible');
});
it('should not trigger the original select change event', function(){
@@ -328,7 +328,7 @@ describe("multiSelect", function() {
});
it('should show associated selectable item', function(){
- expect($('#'+sanitize(value)+'-selectable')).toBe(':visible');
+ expect($('#ms-elem-'+sanitize(value)+'-selectable')).toBe(':visible');
});
it('should remove the .ms-selected class to the corresponding selectable item', function(){