Path: blob/master/web-gui/buildyourownbotnet/assets/js/jquery.multi-select.js
1292 views
/*1* MultiSelect v0.9.82* Copyright (c) 2012 Louis Cuny3*4* This program is free software. It comes without any warranty, to5* the extent permitted by applicable law. You can redistribute it6* and/or modify it under the terms of the Do What The Fuck You Want7* To Public License, Version 2, as published by Sam Hocevar. See8* http://sam.zoy.org/wtfpl/COPYING for more details.9*/1011!function ($) {1213"use strict";141516/* MULTISELECT CLASS DEFINITION17* ====================== */1819var MultiSelect = function (element, options) {20this.options = options;21this.$element = $(element);2223this.$container = $('<div/>', { 'class': "ms-container" });24this.$selectableContainer = $('<div/>', { 'class': 'ms-selectable' });25this.$selectionContainer = $('<div/>', { 'class': 'ms-selection' });26this.$selectableUl = $('<ul/>', { 'class': "ms-list", 'tabindex' : '-1' });27this.$selectionUl = $('<ul/>', { 'class': "ms-list", 'tabindex' : '-1' });28this.scrollTo = 0;29this.sanitizeRegexp = new RegExp("\\W+", 'gi');30this.elemsSelector = 'li:visible:not(.ms-optgroup-label,.ms-optgroup-container,.'+options.disabledClass+')';31};3233MultiSelect.prototype = {34constructor: MultiSelect,3536init: function(){37var that = this,38ms = this.$element;3940if (ms.next('.ms-container').length === 0){41ms.css({ position: 'absolute', left: '-9999px' });42ms.attr('id', ms.attr('id') ? ms.attr('id') : Math.ceil(Math.random()*1000)+'multiselect');43this.$container.attr('id', 'ms-'+ms.attr('id'));4445ms.find('option').each(function(){46that.generateLisFromOption(this);47});4849this.$selectionUl.find('.ms-optgroup-label').hide();5051if (that.options.selectableHeader){52that.$selectableContainer.append(that.options.selectableHeader);53}54that.$selectableContainer.append(that.$selectableUl);55if (that.options.selectableFooter){56that.$selectableContainer.append(that.options.selectableFooter);57}5859if (that.options.selectionHeader){60that.$selectionContainer.append(that.options.selectionHeader);61}62that.$selectionContainer.append(that.$selectionUl);63if (that.options.selectionFooter){64that.$selectionContainer.append(that.options.selectionFooter);65}6667that.$container.append(that.$selectableContainer);68that.$container.append(that.$selectionContainer);69ms.after(that.$container);7071that.activeMouse(that.$selectableUl);72that.activeKeyboard(that.$selectableUl);7374var action = that.options.dblClick ? 'dblclick' : 'click';7576that.$selectableUl.on(action, '.ms-elem-selectable', function(){77that.select($(this).data('ms-value'));78});79that.$selectionUl.on(action, '.ms-elem-selection', function(){80that.deselect($(this).data('ms-value'));81});8283that.activeMouse(that.$selectionUl);84that.activeKeyboard(that.$selectionUl);8586ms.on('focus', function(){87that.$selectableUl.focus();88})89}9091var selectedValues = ms.find('option:selected').map(function(){ return $(this).val(); }).get();92that.select(selectedValues, 'init');9394if (typeof that.options.afterInit === 'function') {95that.options.afterInit.call(this, this.$container);96}97},9899'generateLisFromOption' : function(option){100var that = this,101ms = that.$element,102attributes = "",103$option = $(option);104105for (var cpt = 0; cpt < option.attributes.length; cpt++){106var attr = option.attributes[cpt];107108if(attr.name !== 'value' && attr.name !== 'disabled'){109attributes += attr.name+'="'+attr.value+'" ';110}111}112var selectableLi = $('<li '+attributes+'><span>'+$option.text()+'</span></li>'),113selectedLi = selectableLi.clone(),114value = $option.val(),115elementId = that.sanitize(value, that.sanitizeRegexp);116117selectableLi118.data('ms-value', value)119.addClass('ms-elem-selectable')120.attr('id', elementId+'-selectable');121122selectedLi123.data('ms-value', value)124.addClass('ms-elem-selection')125.attr('id', elementId+'-selection')126.hide();127128if ($option.prop('disabled') || ms.prop('disabled')){129selectedLi.addClass(that.options.disabledClass);130selectableLi.addClass(that.options.disabledClass);131}132133var $optgroup = $option.parent('optgroup');134135if ($optgroup.length > 0){136var optgroupLabel = $optgroup.attr('label'),137optgroupId = that.sanitize(optgroupLabel, that.sanitizeRegexp),138$selectableOptgroup = that.$selectableUl.find('#optgroup-selectable-'+optgroupId),139$selectionOptgroup = that.$selectionUl.find('#optgroup-selection-'+optgroupId);140141if ($selectableOptgroup.length === 0){142var optgroupContainerTpl = '<li class="ms-optgroup-container"></li>',143optgroupTpl = '<ul class="ms-optgroup"><li class="ms-optgroup-label"><span>'+optgroupLabel+'</span></li></ul>';144145$selectableOptgroup = $(optgroupContainerTpl);146$selectionOptgroup = $(optgroupContainerTpl);147$selectableOptgroup.attr('id', 'optgroup-selectable-'+optgroupId);148$selectionOptgroup.attr('id', 'optgroup-selection-'+optgroupId);149$selectableOptgroup.append($(optgroupTpl));150$selectionOptgroup.append($(optgroupTpl));151if (that.options.selectableOptgroup){152$selectableOptgroup.find('.ms-optgroup-label').on('click', function(){153var values = $optgroup.children(':not(:selected)').map(function(){ return $(this).val() }).get();154that.select(values);155});156$selectionOptgroup.find('.ms-optgroup-label').on('click', function(){157var values = $optgroup.children(':selected').map(function(){ return $(this).val() }).get();158that.deselect(values);159});160}161that.$selectableUl.append($selectableOptgroup);162that.$selectionUl.append($selectionOptgroup);163}164$selectableOptgroup.children().append(selectableLi);165$selectionOptgroup.children().append(selectedLi);166} else {167that.$selectableUl.append(selectableLi);168that.$selectionUl.append(selectedLi);169}170},171172'activeKeyboard' : function($list){173var that = this;174175$list.on('focus', function(){176$(this).addClass('ms-focus');177})178.on('blur', function(){179$(this).removeClass('ms-focus');180})181.on('keydown', function(e){182switch (e.which) {183case 40:184case 38:185e.preventDefault();186e.stopPropagation();187that.moveHighlight($(this), (e.which === 38) ? -1 : 1);188return;189case 37:190case 39:191e.preventDefault();192e.stopPropagation();193that.switchList($list);194return;195case 9:196if(that.$element.is('[tabindex]')){197e.preventDefault();198var tabindex = parseInt(that.$element.attr('tabindex'), 10);199tabindex = (e.shiftKey) ? tabindex-1 : tabindex+1;200$('[tabindex="'+(tabindex)+'"]').focus();201return;202}else{203if(e.shiftKey){204that.$element.trigger('focus');205}206}207}208if($.inArray(e.which, that.options.keySelect) > -1){209e.preventDefault();210e.stopPropagation();211that.selectHighlighted($list);212return;213}214});215},216217'moveHighlight': function($list, direction){218var $elems = $list.find(this.elemsSelector),219$currElem = $elems.filter('.ms-hover'),220$nextElem = null,221elemHeight = $elems.first().outerHeight(),222containerHeight = $list.height(),223containerSelector = '#'+this.$container.prop('id');224225// Deactive mouseenter event when move is active226// It fixes a bug when mouse is over the list227$elems.off('mouseenter');228229$elems.removeClass('ms-hover');230if (direction === 1){ // DOWN231232$nextElem = $currElem.nextAll(this.elemsSelector).first();233if ($nextElem.length === 0){234var $optgroupUl = $currElem.parent();235236if ($optgroupUl.hasClass('ms-optgroup')){237var $optgroupLi = $optgroupUl.parent(),238$nextOptgroupLi = $optgroupLi.next(':visible');239240if ($nextOptgroupLi.length > 0){241$nextElem = $nextOptgroupLi.find(this.elemsSelector).first();242} else {243$nextElem = $elems.first();244}245} else {246$nextElem = $elems.first();247}248}249} else if (direction === -1){ // UP250251$nextElem = $currElem.prevAll(this.elemsSelector).first();252if ($nextElem.length === 0){253var $optgroupUl = $currElem.parent();254255if ($optgroupUl.hasClass('ms-optgroup')){256var $optgroupLi = $optgroupUl.parent(),257$prevOptgroupLi = $optgroupLi.prev(':visible');258259if ($prevOptgroupLi.length > 0){260$nextElem = $prevOptgroupLi.find(this.elemsSelector).last();261} else {262$nextElem = $elems.last();263}264} else {265$nextElem = $elems.last();266}267}268}269if ($nextElem.length > 0){270$nextElem.addClass('ms-hover');271var scrollTo = $list.scrollTop() + $nextElem.position().top -272containerHeight / 2 + elemHeight / 2;273274$list.scrollTop(scrollTo);275}276},277278'selectHighlighted' : function($list){279var $elems = $list.find(this.elemsSelector),280$highlightedElem = $elems.filter('.ms-hover').first();281282if ($highlightedElem.length > 0){283if ($list.parent().hasClass('ms-selectable')){284this.select($highlightedElem.data('ms-value'));285} else {286this.deselect($highlightedElem.data('ms-value'));287}288$elems.removeClass('ms-hover');289}290},291292'switchList' : function($list){293$list.blur();294if ($list.parent().hasClass('ms-selectable')){295this.$selectionUl.focus();296} else {297this.$selectableUl.focus();298}299},300301'activeMouse' : function($list){302var that = this;303304$list.on('mousemove', function(){305var elems = $list.find(that.elemsSelector);306307elems.on('mouseenter', function(){308elems.removeClass('ms-hover');309$(this).addClass('ms-hover');310});311});312},313314'refresh' : function() {315this.destroy();316this.$element.multiSelect(this.options);317},318319'destroy' : function(){320$("#ms-"+this.$element.attr("id")).remove();321this.$element.removeData('multiselect');322},323324'select' : function(value, method){325if (typeof value === 'string'){ value = [value]; }326327var that = this,328ms = this.$element,329msIds = $.map(value, function(val){ return(that.sanitize(val, that.sanitizeRegexp)); }),330selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable').filter(':not(.'+that.options.disabledClass+')'),331selections = this.$selectionUl.find('#' + msIds.join('-selection, #') + '-selection').filter(':not(.'+that.options.disabledClass+')'),332options = ms.find('option:not(:disabled)').filter(function(){ return($.inArray(this.value, value) > -1); });333334if (selectables.length > 0){335selectables.addClass('ms-selected').hide();336selections.addClass('ms-selected').show();337options.prop('selected', true);338339var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container');340if (selectableOptgroups.length > 0){341selectableOptgroups.each(function(){342var selectablesLi = $(this).find('.ms-elem-selectable');343if (selectablesLi.length === selectablesLi.filter('.ms-selected').length){344$(this).find('.ms-optgroup-label').hide();345}346});347348var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container');349selectionOptgroups.each(function(){350var selectionsLi = $(this).find('.ms-elem-selection');351if (selectionsLi.filter('.ms-selected').length > 0){352$(this).find('.ms-optgroup-label').show();353}354});355} else {356if (that.options.keepOrder){357var selectionLiLast = that.$selectionUl.find('.ms-selected');358if((selectionLiLast.length > 1) && (selectionLiLast.last().get(0) != selections.get(0))) {359selections.insertAfter(selectionLiLast.last());360}361}362}363if (method !== 'init'){364ms.trigger('change');365if (typeof that.options.afterSelect === 'function') {366that.options.afterSelect.call(this, value);367}368}369}370},371372'deselect' : function(value){373if (typeof value === 'string'){ value = [value]; }374375var that = this,376ms = this.$element,377msIds = $.map(value, function(val){ return(that.sanitize(val, that.sanitizeRegexp)); }),378selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable'),379selections = this.$selectionUl.find('#' + msIds.join('-selection, #')+'-selection').filter('.ms-selected'),380options = ms.find('option').filter(function(){ return($.inArray(this.value, value) > -1); });381382if (selections.length > 0){383selectables.removeClass('ms-selected').show();384selections.removeClass('ms-selected').hide();385options.prop('selected', false);386387var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container');388if (selectableOptgroups.length > 0){389selectableOptgroups.each(function(){390var selectablesLi = $(this).find('.ms-elem-selectable');391if (selectablesLi.filter(':not(.ms-selected)').length > 0){392$(this).find('.ms-optgroup-label').show();393}394});395396var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container');397selectionOptgroups.each(function(){398var selectionsLi = $(this).find('.ms-elem-selection');399if (selectionsLi.filter('.ms-selected').length === 0){400$(this).find('.ms-optgroup-label').hide();401}402});403}404ms.trigger('change');405if (typeof that.options.afterDeselect === 'function') {406that.options.afterDeselect.call(this, value);407}408}409},410411'select_all' : function(){412var ms = this.$element,413values = ms.val();414415ms.find('option:not(":disabled")').prop('selected', true);416this.$selectableUl.find('.ms-elem-selectable').filter(':not(.'+this.options.disabledClass+')').addClass('ms-selected').hide();417this.$selectionUl.find('.ms-optgroup-label').show();418this.$selectableUl.find('.ms-optgroup-label').hide();419this.$selectionUl.find('.ms-elem-selection').filter(':not(.'+this.options.disabledClass+')').addClass('ms-selected').show();420this.$selectionUl.focus();421ms.trigger('change');422if (typeof this.options.afterSelect === 'function') {423var selectedValues = $.grep(ms.val(), function(item){424return $.inArray(item, values) < 0;425});426this.options.afterSelect.call(this, selectedValues);427}428},429430'deselect_all' : function(){431var ms = this.$element,432values = ms.val();433434ms.find('option').prop('selected', false);435this.$selectableUl.find('.ms-elem-selectable').removeClass('ms-selected').show();436this.$selectionUl.find('.ms-optgroup-label').hide();437this.$selectableUl.find('.ms-optgroup-label').show();438this.$selectionUl.find('.ms-elem-selection').removeClass('ms-selected').hide();439this.$selectableUl.focus();440ms.trigger('change');441if (typeof this.options.afterDeselect === 'function') {442this.options.afterDeselect.call(this, values);443}444},445446sanitize: function(value, reg){447return(value.replace(reg, '_'));448}449};450451/* MULTISELECT PLUGIN DEFINITION452* ======================= */453454$.fn.multiSelect = function () {455var option = arguments[0],456args = arguments;457458return this.each(function () {459var $this = $(this),460data = $this.data('multiselect'),461options = $.extend({}, $.fn.multiSelect.defaults, $this.data(), typeof option === 'object' && option);462463if (!data){ $this.data('multiselect', (data = new MultiSelect(this, options))); }464465if (typeof option === 'string'){466data[option](args[1]);467} else {468data.init();469}470});471};472473$.fn.multiSelect.defaults = {474keySelect: [32],475selectableOptgroup: false,476disabledClass : 'disabled',477dblClick : false,478keepOrder: false479};480481$.fn.multiSelect.Constructor = MultiSelect;482483}(window.jQuery);484485