https://seoup.su/bitrix/templates/seoup/assets/plugins/jquery-multi-select/js/jquery.multi-select.js
1/* 2* MultiSelect v0.9.8 3* Copyright (c) 2012 Louis Cuny 4* 5* This program is free software. It comes without any warranty, to 6* the extent permitted by applicable law. You can redistribute it 7* and/or modify it under the terms of the Do What The Fuck You Want 8* To Public License, Version 2, as published by Sam Hocevar. See 9* http://sam.zoy.org/wtfpl/COPYING for more details. 10*/ 11 12!function ($) { 13 14 "use strict"; 15 16 17 /* MULTISELECT CLASS DEFINITION 18 * ====================== */ 19 20 var MultiSelect = function (element, options) { 21 this.options = options; 22 this.$element = $(element); 23 24 this.$container = $('<div/>', { 'class': "ms-container" }); 25 this.$selectableContainer = $('<div/>', { 'class': 'ms-selectable' }); 26 this.$selectionContainer = $('<div/>', { 'class': 'ms-selection' }); 27 this.$selectableUl = $('<ul/>', { 'class': "ms-list", 'tabindex' : '-1' }); 28 this.$selectionUl = $('<ul/>', { 'class': "ms-list", 'tabindex' : '-1' }); 29 this.scrollTo = 0; 30 this.sanitizeRegexp = new RegExp("\\W+", 'gi'); 31 this.elemsSelector = 'li:visible:not(.ms-optgroup-label,.ms-optgroup-container,.'+options.disabledClass+')'; 32 }; 33 34 MultiSelect.prototype = { 35 constructor: MultiSelect, 36 37 init: function(){ 38 var that = this, 39 ms = this.$element; 40 41 if (ms.next('.ms-container').length === 0){ 42 ms.css({ position: 'absolute', left: '-9999px' }); 43 ms.attr('id', ms.attr('id') ? ms.attr('id') : Math.ceil(Math.random()*1000)+'multiselect'); 44 this.$container.attr('id', 'ms-'+ms.attr('id')); 45 46 ms.find('option').each(function(){ 47 that.generateLisFromOption(this); 48 }); 49 50 this.$selectionUl.find('.ms-optgroup-label').hide(); 51 52 if (that.options.selectableHeader){ 53 that.$selectableContainer.append(that.options.selectableHeader); 54 } 55 that.$selectableContainer.append(that.$selectableUl); 56 if (that.options.selectableFooter){ 57 that.$selectableContainer.append(that.options.selectableFooter); 58 } 59 60 if (that.options.selectionHeader){ 61 that.$selectionContainer.append(that.options.selectionHeader); 62 } 63 that.$selectionContainer.append(that.$selectionUl); 64 if (that.options.selectionFooter){ 65 that.$selectionContainer.append(that.options.selectionFooter); 66 } 67 68 that.$container.append(that.$selectableContainer); 69 that.$container.append(that.$selectionContainer); 70 ms.after(that.$container); 71 72 that.activeMouse(that.$selectableUl); 73 that.activeKeyboard(that.$selectableUl); 74 75 var action = that.options.dblClick ? 'dblclick' : 'click'; 76 77 that.$selectableUl.on(action, '.ms-elem-selectable', function(){ 78 that.select($(this).data('ms-value')); 79 }); 80 that.$selectionUl.on(action, '.ms-elem-selection', function(){ 81 that.deselect($(this).data('ms-value')); 82 }); 83 84 that.activeMouse(that.$selectionUl); 85 that.activeKeyboard(that.$selectionUl); 86 87 ms.on('focus', function(){ 88 that.$selectableUl.focus(); 89 }) 90 } 91 92 var selectedValues = ms.find('option:selected').map(function(){ return $(this).val(); }).get(); 93 that.select(selectedValues, 'init'); 94 95 if (typeof that.options.afterInit === 'function') { 96 that.options.afterInit.call(this, this.$container); 97 } 98 }, 99 100 'generateLisFromOption' : function(option){ 101 var that = this, 102 ms = that.$element, 103 attributes = "", 104 $option = $(option); 105 106 for (var cpt = 0; cpt < option.attributes.length; cpt++){ 107 var attr = option.attributes[cpt]; 108 109 if(attr.name !== 'value' && attr.name !== 'disabled'){ 110 attributes += attr.name+'="'+attr.value+'" '; 111 } 112 } 113 var selectableLi = $('<li '+attributes+'><span>'+$option.text()+'</span></li>'), 114 selectedLi = selectableLi.clone(), 115 value = $option.val(), 116 elementId = that.sanitize(value, that.sanitizeRegexp); 117 118 selectableLi 119 .data('ms-value', value) 120 .addClass('ms-elem-selectable') 121 .attr('id', elementId+'-selectable'); 122 123 selectedLi 124 .data('ms-value', value) 125 .addClass('ms-elem-selection') 126 .attr('id', elementId+'-selection') 127 .hide(); 128 129 if ($option.prop('disabled') || ms.prop('disabled')){ 130 selectedLi.addClass(that.options.disabledClass); 131 selectableLi.addClass(that.options.disabledClass); 132 } 133 134 var $optgroup = $option.parent('optgroup'); 135 136 if ($optgroup.length > 0){ 137 var optgroupLabel = $optgroup.attr('label'), 138 optgroupId = that.sanitize(optgroupLabel, that.sanitizeRegexp), 139 $selectableOptgroup = that.$selectableUl.find('#optgroup-selectable-'+optgroupId), 140 $selectionOptgroup = that.$selectionUl.find('#optgroup-selection-'+optgroupId); 141 142 if ($selectableOptgroup.length === 0){ 143 var optgroupContainerTpl = '<li class="ms-optgroup-container"></li>', 144 optgroupTpl = '<ul class="ms-optgroup"><li class="ms-optgroup-label"><span>'+optgroupLabel+'</span></li></ul>'; 145 146 $selectableOptgroup = $(optgroupContainerTpl); 147 $selectionOptgroup = $(optgroupContainerTpl); 148 $selectableOptgroup.attr('id', 'optgroup-selectable-'+optgroupId); 149 $selectionOptgroup.attr('id', 'optgroup-selection-'+optgroupId); 150 $selectableOptgroup.append($(optgroupTpl)); 151 $selectionOptgroup.append($(optgroupTpl)); 152 if (that.options.selectableOptgroup){ 153 $selectableOptgroup.find('.ms-optgroup-label').on('click', function(){ 154 var values = $optgroup.children(':not(:selected)').map(function(){ return $(this).val() }).get(); 155 that.select(values); 156 }); 157 $selectionOptgroup.find('.ms-optgroup-label').on('click', function(){ 158 var values = $optgroup.children(':selected').map(function(){ return $(this).val() }).get(); 159 that.deselect(values); 160 }); 161 } 162 that.$selectableUl.append($selectableOptgroup); 163 that.$selectionUl.append($selectionOptgroup); 164 } 165 $selectableOptgroup.children().append(selectableLi); 166 $selectionOptgroup.children().append(selectedLi); 167 } else { 168 that.$selectableUl.append(selectableLi); 169 that.$selectionUl.append(selectedLi); 170 } 171 }, 172 173 'activeKeyboard' : function($list){ 174 var that = this; 175 176 $list.on('focus', function(){ 177 $(this).addClass('ms-focus'); 178 }) 179 .on('blur', function(){ 180 $(this).removeClass('ms-focus'); 181 }) 182 .on('keydown', function(e){ 183 switch (e.which) { 184 case 40: 185 case 38: 186 e.preventDefault(); 187 e.stopPropagation(); 188 that.moveHighlight($(this), (e.which === 38) ? -1 : 1); 189 return; 190 case 32: 191 e.preventDefault(); 192 e.stopPropagation(); 193 that.selectHighlighted($list); 194 return; 195 case 37: 196 case 39: 197 e.preventDefault(); 198 e.stopPropagation(); 199 that.switchList($list); 200 return; 201 } 202 }); 203 }, 204 205 'moveHighlight': function($list, direction){ 206 var $elems = $list.find(this.elemsSelector), 207 $currElem = $elems.filter('.ms-hover'), 208 $nextElem = null, 209 elemHeight = $elems.first().outerHeight(), 210 containerHeight = $list.height(), 211 containerSelector = '#'+this.$container.prop('id'); 212 213 // Deactive mouseenter event when move is active 214 // It fixes a bug when mouse is over the list 215 $elems.off('mouseenter'); 216 217 $elems.removeClass('ms-hover'); 218 if (direction === 1){ // DOWN 219 220 $nextElem = $currElem.nextAll(this.elemsSelector).first(); 221 if ($nextElem.length === 0){ 222 var $optgroupUl = $currElem.parent(); 223 224 if ($optgroupUl.hasClass('ms-optgroup')){ 225 var $optgroupLi = $optgroupUl.parent(), 226 $nextOptgroupLi = $optgroupLi.next(':visible'); 227 228 if ($nextOptgroupLi.length > 0){ 229 $nextElem = $nextOptgroupLi.find(this.elemsSelector).first(); 230 } else { 231 $nextElem = $elems.first(); 232 } 233 } else { 234 $nextElem = $elems.first(); 235 } 236 } 237 } else if (direction === -1){ // UP 238 239 $nextElem = $currElem.prevAll(this.elemsSelector).first(); 240 if ($nextElem.length === 0){ 241 var $optgroupUl = $currElem.parent(); 242 243 if ($optgroupUl.hasClass('ms-optgroup')){ 244 var $optgroupLi = $optgroupUl.parent(), 245 $prevOptgroupLi = $optgroupLi.prev(':visible'); 246 247 if ($prevOptgroupLi.length > 0){ 248 $nextElem = $prevOptgroupLi.find(this.elemsSelector).last(); 249 } else {
250 $nextElem = $elems.last(); 251 } 252 } else { 253 $nextElem = $elems.last(); 254 } 255 } 256 } 257 if ($nextElem.length > 0){ 258 $nextElem.addClass('ms-hover'); 259 var scrollTo = $list.scrollTop() + $nextElem.position().top - 260 containerHeight / 2 + elemHeight / 2; 261 262 $list.scrollTop(scrollTo); 263 } 264 }, 265 266 'selectHighlighted' : function($list){ 267 var $elems = $list.find(this.elemsSelector), 268 $highlightedElem = $elems.filter('.ms-hover').first(); 269 270 if ($highlightedElem.length > 0){ 271 if ($list.parent().hasClass('ms-selectable')){ 272 this.select($highlightedElem.data('ms-value')); 273 } else { 274 this.deselect($highlightedElem.data('ms-value')); 275 } 276 $elems.removeClass('ms-hover'); 277 } 278 }, 279 280 'switchList' : function($list){ 281 $list.blur(); 282 if ($list.parent().hasClass('ms-selectable')){ 283 this.$selectionUl.focus(); 284 } else { 285 this.$selectableUl.focus(); 286 } 287 }, 288 289 'activeMouse' : function($list){ 290 var that = this; 291 292 $list.on('mousemove', function(){ 293 var elems = $list.find(that.elemsSelector); 294 295 elems.on('mouseenter', function(){ 296 elems.removeClass('ms-hover'); 297 $(this).addClass('ms-hover'); 298 }); 299 }); 300 }, 301 302 'refresh' : function() { 303 this.destroy(); 304 this.$element.multiSelect(this.options); 305 }, 306 307 'destroy' : function(){ 308 $("#ms-"+this.$element.attr("id")).remove(); 309 this.$element.removeData('multiselect'); 310 }, 311 312 'select' : function(value, method){ 313 if (typeof value === 'string'){ value = [value]; } 314 315 var that = this, 316 ms = this.$element, 317 msIds = $.map(value, function(val){ return(that.sanitize(val, that.sanitizeRegexp)); }), 318 selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable').filter(':not(.'+that.options.disabledClass+')'), 319 selections = this.$selectionUl.find('#' + msIds.join('-selection, #') + '-selection').filter(':not(.'+that.options.disabledClass+')'), 320 options = ms.find('option:not(:disabled)').filter(function(){ return($.inArray(this.value, value) > -1); }); 321 322 if (selectables.length > 0){ 323 selectables.addClass('ms-selected').hide(); 324 selections.addClass('ms-selected').show(); 325 options.prop('selected', true); 326 327 var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container'); 328 if (selectableOptgroups.length > 0){ 329 selectableOptgroups.each(function(){ 330 var selectablesLi = $(this).find('.ms-elem-selectable'); 331 if (selectablesLi.length === selectablesLi.filter('.ms-selected').length){ 332 $(this).find('.ms-optgroup-label').hide(); 333 } 334 }); 335 336 var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container'); 337 selectionOptgroups.each(function(){ 338 var selectionsLi = $(this).find('.ms-elem-selection'); 339 if (selectionsLi.filter('.ms-selected').length > 0){ 340 $(this).find('.ms-optgroup-label').show(); 341 } 342 }); 343 } else { 344 if (that.options.keepOrder){ 345 var selectionLiLast = that.$selectionUl.find('.ms-selected'); 346 if((selectionLiLast.length > 1) && (selectionLiLast.last().get(0) != selections.get(0))) { 347 selections.insertAfter(selectionLiLast.last()); 348 } 349 } 350 } 351 if (method !== 'init'){ 352 ms.trigger('change'); 353 if (typeof that.options.afterSelect === 'function') { 354 that.options.afterSelect.call(this, value); 355 } 356 } 357 } 358 }, 359 360 'deselect' : function(value){ 361 if (typeof value === 'string'){ value = [value]; } 362 363 var that = this, 364 ms = this.$element, 365 msIds = $.map(value, function(val){ return(that.sanitize(val, that.sanitizeRegexp)); }), 366 selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable'), 367 selections = this.$selectionUl.find('#' + msIds.join('-selection, #')+'-selection').filter('.ms-selected'), 368 options = ms.find('option').filter(function(){ return($.inArray(this.value, value) > -1); }); 369 370 if (selections.length > 0){ 371 selectables.removeClass('ms-selected').show(); 372 selections.removeClass('ms-selected').hide(); 373 options.prop('selected', false); 374 375 var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container'); 376 if (selectableOptgroups.length > 0){ 377 selectableOptgroups.each(function(){ 378 var selectablesLi = $(this).find('.ms-elem-selectable'); 379 if (selectablesLi.filter(':not(.ms-selected)').length > 0){ 380 $(this).find('.ms-optgroup-label').show(); 381 } 382 }); 383 384 var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container'); 385 selectionOptgroups.each(function(){
386 var selectionsLi = $(this).find('.ms-elem-selection'); 387 if (selectionsLi.filter('.ms-selected').length === 0){ 388 $(this).find('.ms-optgroup-label').hide(); 389 } 390 }); 391 } 392 ms.trigger('change'); 393 if (typeof that.options.afterDeselect === 'function') { 394 that.options.afterDeselect.call(this, value); 395 } 396 } 397 }, 398 399 'select_all' : function(){ 400 var ms = this.$element, 401 values = ms.val(); 402 403 ms.find('option:not(":disabled")').prop('selected', true); 404 this.$selectableUl.find('.ms-elem-selectable').filter(':not(.'+this.options.disabledClass+')').addClass('ms-selected').hide(); 405 this.$selectionUl.find('.ms-optgroup-label').show(); 406 this.$selectableUl.find('.ms-optgroup-label').hide(); 407 this.$selectionUl.find('.ms-elem-selection').filter(':not(.'+this.options.disabledClass+')').addClass('ms-selected').show(); 408 this.$selectionUl.focus(); 409 ms.trigger('change'); 410 if (typeof this.options.afterSelect === 'function') { 411 var selectedValues = $.grep(ms.val(), function(item){ 412 return $.inArray(item, values) < 0; 413 }); 414 this.options.afterSelect.call(this, selectedValues); 415 } 416 }, 417 418 'deselect_all' : function(){ 419 var ms = this.$element, 420 values = ms.val(); 421 422 ms.find('option').prop('selected', false); 423 this.$selectableUl.find('.ms-elem-selectable').removeClass('ms-selected').show(); 424 this.$selectionUl.find('.ms-optgroup-label').hide(); 425 this.$selectableUl.find('.ms-optgroup-label').show(); 426 this.$selectionUl.find('.ms-elem-selection').removeClass('ms-selected').hide(); 427 this.$selectableUl.focus(); 428 ms.trigger('change'); 429 if (typeof this.options.afterDeselect === 'function') { 430 this.options.afterDeselect.call(this, values); 431 } 432 }, 433 434 sanitize: function(value, reg){ 435 return(value.replace(reg, '_')); 436 } 437 }; 438 439 /* MULTISELECT PLUGIN DEFINITION 440 * ======================= */ 441 442 $.fn.multiSelect = function () { 443 var option = arguments[0], 444 args = arguments; 445 446 return this.each(function () { 447 var $this = $(this), 448 data = $this.data('multiselect'), 449 options = $.extend({}, $.fn.multiSelect.defaults, $this.data(), typeof option === 'object' && option); 450 451 if (!data){ $this.data('multiselect', (data = new MultiSelect(this, options))); } 452 453 if (typeof option === 'string'){ 454 data[option](args[1]); 455 } else { 456 data.init(); 457 } 458 }); 459 }; 460 461 $.fn.multiSelect.defaults = { 462 selectableOptgroup: false, 463 disabledClass : 'disabled', 464 dblClick : false, 465 keepOrder: false 466 }; 467 468 $.fn.multiSelect.Constructor = MultiSelect; 469 470}(window.jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.