Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
253 changes: 137 additions & 116 deletions select2.sortable.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,123 +3,144 @@
* - enable select2 to be sortable via normal select element
*
* author : Vafour
* modified : Kevin Provance (kprovance)
* inspired by : jQuery Chosen Sortable (https://github.com/mrhenry/jquery-chosen-sortable)
* License : GPL
*/

(function($){
$.fn.extend({
select2SortableOrder: function(){
var $this = this.filter('[multiple]');

$this.each(function(){
var $select = $(this);

// skip elements not select2-ed
if(typeof($select.data('select2')) !== 'object'){
return false;
}

var $select2 = $select.siblings('.select2-container'),
unselected = [],
sorted;

$select.find('option').each(function(){
!this.selected && unselected.push(this);
});

sorted = $($select2.find('.select2-choices li[class!="select2-search-field"]').map( function() {
if (!this) {
return undefined;
}
var id = $(this).data('select2Data').id;
return $select.find('option[value="' + id + '"]')[0];
}));

sorted.push.apply(sorted, unselected);
$select.children().remove();
$select.append(sorted);
});

return $this;
},
select2Sortable: function(){
var args = Array.prototype.slice.call(arguments, 0);
$this = this.filter('[multiple]'),
validMethods = ['destroy'];

if(args.length === 0 || typeof(args[0]) === 'object')
{
var defaultOptions = {
bindOrder : 'formSubmit', // or sortableStop
sortableOptions : {
placeholder : 'ui-state-highlight',
items : 'li:not(.select2-search-field)',
tolerance : 'pointer'
}
};
var options = $.extend(defaultOptions, args[0]);

// Init select2 only if not already initialized to prevent select2 configuration loss
if(typeof($this.data('select2')) !== 'object'){
$this.select2();
}

$this.each(function(){
var $select = $(this),
$select2choices = $select.siblings('.select2-container').find('.select2-choices');

// Init jQuery UI Sortable
$select2choices.sortable(options.sortableOptions);

switch(options.bindOrder){
case 'sortableStop':
// apply options ordering in sortstop event
$select2choices.on("sortstop.select2sortable", function( event, ui ) {
$select.select2SortableOrder();
});
$select.on('change', function(e){
$(this).select2SortableOrder();
});
break;
default:
// apply options ordering in form submit
$select.closest('form').unbind('submit.select2sortable').on('submit.select2sortable', function(){
$select.select2SortableOrder();
});
}

});
}
else if(typeof(args[0] === 'string'))
{
if($.inArray(args[0], validMethods) == -1)
{
throw "Unknown method: " + args[0];
}
if(args[0] === 'destroy')
{
$this.select2SortableDestroy();
}
}
return $this;
},
select2SortableDestroy: function(){
var $this = this.filter('[multiple]');
$this.each(function(){
var $select = $(this),
$select2choices = $select.parent().find('.select2-choices');

// unbind form submit event
$select.closest('form').unbind('submit.select2sortable');

// unbind sortstop event
$select2choices.unbind("sortstop.select2sortable");

// destroy select2Sortable
$select2choices.sortable('destroy');
});
return $this;
}
});
}(jQuery));
(function ($) {
$.fn.extend({
select2SortableOrder: function () {
var $this = this.filter('[multiple]');

$this.each(function () {
var $select = $(this);

// skip elements not select2-ed
if (typeof ($select.data('select2')) !== 'object') {
return false;
}

var $select2 = $select.siblings('.select2-container')
var sorted;

// Opt group names
var optArr = [];

$select.find('optgroup').each(function(idx, val) {
optArr.push (val);
});

$select.find('option').each(function(idx, val) {
var groupName = $(this).parent('optgroup').prop('label');
var optVal = this;

if (groupName === undefined) {
if (this.value !== '') {
optArr.push (optVal);
}
}
});

sorted = $($select2.find('.select2-choices li[class!="select2-search-field"]').map(function () {
if (!this) {
return undefined;
}

var id = $(this).data('select2Data').id;

return $select.find('option[value="' + id + '"]')[0];
}));

sorted.push.apply(sorted, optArr);

$select.children().remove();
$select.append(sorted);
});

return $this;
},

select2Sortable: function () {
var args = Array.prototype.slice.call(arguments, 0);
$this = this.filter('[multiple]'),
validMethods = ['destroy'];

if (args.length === 0 || typeof (args[0]) === 'object') {
var defaultOptions = {
bindOrder: 'formSubmit', // or sortableStop
sortableOptions: {
placeholder: 'ui-state-highlight',
items: 'li:not(.select2-search-field)',
tolerance: 'pointer'
}
};

var options = $.extend(defaultOptions, args[0]);

// Init select2 only if not already initialized to prevent select2 configuration loss
if (typeof ($this.data('select2')) !== 'object') {
$this.select2();
}

$this.each(function () {
var $select = $(this)
var $select2choices = $select.siblings('.select2-container').find('.select2-choices');

// Init jQuery UI Sortable
$select2choices.sortable(options.sortableOptions);

switch (options.bindOrder) {
case 'sortableStop':
// apply options ordering in sortstop event
$select2choices.on("sortstop.select2sortable", function (event, ui) {
$select.select2SortableOrder();
});

$select.on('change', function (e) {
$(this).select2SortableOrder();
});
break;

default:
// apply options ordering in form submit
$select.closest('form').unbind('submit.select2sortable').on('submit.select2sortable', function () {
$select.select2SortableOrder();
});
break;
}
});
}
else if (typeof (args[0] === 'string')) {
if ($.inArray(args[0], validMethods) == -1) {
throw "Unknown method: " + args[0];
}

if (args[0] === 'destroy') {
$this.select2SortableDestroy();
}
}

return $this;
},

select2SortableDestroy: function () {
var $this = this.filter('[multiple]');
$this.each(function () {
var $select = $(this)
var $select2choices = $select.parent().find('.select2-choices');

// unbind form submit event
$select.closest('form').unbind('submit.select2sortable');

// unbind sortstop event
$select2choices.unbind("sortstop.select2sortable");

// destroy select2Sortable
$select2choices.sortable('destroy');
});

return $this;
}
});
}(jQuery));