vendor: 14,746 bytes, lines 1-324
1/** 2 * Display a nice easy to use multiselect list 3 * @Version: 2.4.23 4 * @Author: Patrick Springstubbe 5 * @Contact: @JediNobleclem 6 * @Website: springstubbe.us 7 * @Source: https://github.com/nobleclem/jQuery-MultiSelect 8 * 9 * Usage: 10 * $('select[multiple]').multiselect(); 11 * $('select[multiple]').multiselect({ texts: { placeholder: 'Select options' } }); 12 * $('select[multiple]').multiselect('reload'); 13 * $('select[multiple]').multiselect( 'loadOptions', [{ 14 * name : 'Option Name 1', 15 * value : 'option-value-1', 16 * checked: false, 17 * attributes : { 18 * custom1: 'value1', 19 * custom2: 'value2' 20 * } 21 * },{ 22 * name : 'Option Name 2', 23 * value : 'option-value-2', 24 * checked: false, 25 * attributes : { 26 * custom1: 'value1', 27 * custom2: 'value2' 28 * } 29 * }]); 30 * 31 **/ 32(function($){ 33 var defaults = { 34 columns: 1, // how many columns should be use to show options 35 search : false, // include option search box 36 37 // search filter options 38 searchOptions : { 39 delay : 250, // time (in ms) between keystrokes until search happens 40 showOptGroups: false, // show option group titles if no options remaining 41 searchText : true, // search within the text 42 searchValue : false, // search within the value 43 onSearch : function( element ){} // fires on keyup before search on options happens 44 }, 45 46 // plugin texts 47 texts: { 48 placeholder : 'Select options', // text to use in dummy input 49 search : 'Search', // search input placeholder text 50 searchNoResult : 'No results', // search results not found text 51 selectedOptions: ' selected', // selected suffix text 52 selectAll : 'Select all', // select all text 53 unselectAll : 'Unselect all', // unselect all text 54 noneSelected : 'None Selected' // None selected text 55 }, 56 57 // general options 58 selectAll : false, // add select all option 59 selectGroup : false, // select entire optgroup 60 minHeight : 200, // minimum height of option overlay 61 maxHeight : null, // maximum height of option overlay 62 maxWidth : null, // maximum width of option overlay (or selector) 63 maxPlaceholderWidth : null, // maximum width of placeholder button 64 maxPlaceholderOpts : 10, // maximum number of placeholder options to show until "# selected" shown instead 65 showCheckbox : true, // display the checkbox to the user 66 checkboxAutoFit : false, // auto calc checkbox padding 67 optionAttributes : [], // attributes to copy to the checkbox from the option element 68 replacePlaceholderText : true, // replace text of placeholder if button is too small 69 70 // Callbacks 71 onLoad : function( element ){}, // fires at end of list initialization 72 onOptionClick : function( element, option ){}, // fires when an option is clicked 73 onControlOpen : function( element ){}, // fires when the options list is opened 74 onControlClose: function( element ){}, // fires when the options list is closed 75 onSelectAll : function( element, selected ){}, // fires when (un)select all is clicked 76 onPlaceholder : function( element, placeholder, selectedOpts ){}, // fires when the placeholder txt is updated 77 }; 78 79 var msCounter = 1; // counter for each select list 80 var msOptCounter = 1; // counter for each option on page 81 82 // FOR LEGACY BROWSERS (talking to you IE8) 83 if( typeof Array.prototype.map !== 'function' ) { 84 Array.prototype.map = function( callback, thisArg ) { 85 if( typeof thisArg === 'undefined' ) { 86 thisArg = this; 87 } 88 89 return $.isArray( thisArg ) ? $.map( thisArg, callback ) : []; 90 }; 91 } 92 if( typeof String.prototype.trim !== 'function' ) { 93 String.prototype.trim = function() { 94 return this.replace(/^\s+|\s+$/g, ''); 95 }; 96 } 97 98 function MultiSelect( element, options ) 99 { 100 this.element = element; 101 this.options = $.extend( true, {}, defaults, options ); 102 this.updateSelectAll = true; 103 this.updatePlaceholder = true; 104 this.listNumber = msCounter; 105 106 msCounter = msCounter + 1; // increment counter 107 108 /* Make sure its a multiselect list */ 109 if( !$(this.element).attr('multiple') ) { 110 throw new Error( '[jQuery-MultiSelect] Select list must be a multiselect list in order to use this plugin' ); 111 } 112 113 /* Options validation checks */ 114 if( this.options.search ){ 115 if( !this.options.searchOptions.searchText && !this.options.searchOptions.searchValue ){ 116 throw new Error( '[jQuery-MultiSelect] Either searchText or searchValue should be true.' ); 117 } 118 } 119 120 /** BACKWARDS COMPATIBILITY **/ 121 if( 'placeholder' in this.options ) { 122 this.options.texts.placeholder = this.options.placeholder; 123 delete this.options.placeholder; 124 } 125 if( 'default' in this.options.searchOptions ) { 126 this.options.texts.search = this.options.searchOptions['default']; 127 delete this.options.searchOptions['default']; 128 } 129 /** END BACKWARDS COMPATIBILITY **/ 130 131 // load this instance 132 this.load(); 133 } 134 135 MultiSelect.prototype = { 136 /* LOAD CUSTOM MULTISELECT DOM/ACTIONS */ 137 load: function() { 138 var instance = this; 139 140 // make sure this is a select list and not loaded 141 if( (instance.element.nodeName.toUpperCase() != 'SELECT') || $(instance.element).hasClass('jqmsLoaded') ) { 142 return true; 143 } 144 145 // sanity check so we don't double load on a select element 146 $(instance.element).addClass('jqmsLoaded ms-list-'+ instance.listNumber ).data( 'plugin_multiselect-instance', instance ); 147 148 // add option container 149 $(instance.element).after('<div id="ms-list-'+ instance.listNumber +'" class="ms-options-wrap"><button type="button"><span>None Selected</span></button><div class="ms-options"><ul></ul></div></div>'); 150 151 var placeholder = $(instance.element).siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> button:first-child'); 152 var optionsWrap = $(instance.element).siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> .ms-options'); 153 var optionsList = optionsWrap.find('> ul'); 154 155 // don't show checkbox (add class for css to hide checkboxes) 156 if( !instance.options.showCheckbox ) { 157 optionsWrap.addClass('hide-checkbox'); 158 } 159 else if( instance.options.checkboxAutoFit ) { 160 optionsWrap.addClass('checkbox-autofit'); 161 } 162 163 // check if list is disabled 164 if( $(instance.element).prop( 'disabled' ) ) { 165 placeholder.prop( 'disabled', true ); 166 } 167 168 // set placeholder maxWidth 169 if( instance.options.maxPlaceholderWidth ) { 170 placeholder.css( 'maxWidth', instance.options.maxPlaceholderWidth ); 171 } 172 173 // override with user defined maxHeight 174 if( instance.options.maxHeight ) { 175 var maxHeight = instance.options.maxHeight; 176 } 177 else { 178 // cacl default maxHeight 179 var maxHeight = ($(window).height() - optionsWrap.offset().top + $(window).scrollTop() - 20); 180 } 181 182 // maxHeight cannot be less than options.minHeight 183 maxHeight = maxHeight < instance.options.minHeight ? instance.options.minHeight : maxHeight; 184 185 optionsWrap.css({ 186 maxWidth : instance.options.maxWidth, 187 minHeight: instance.options.minHeight, 188 maxHeight: maxHeight, 189 }); 190 191 // isolate options scroll 192 // @source: https://github.com/nobleclem/jQuery-IsolatedScroll 193 optionsWrap.on( 'touchmove mousewheel DOMMouseScroll', function ( e ) { 194 if( ($(this).outerHeight() < $(this)[0].scrollHeight) ) { 195 var e0 = e.originalEvent, 196 delta = e0.wheelDelta || -e0.detail; 197 198 if( ($(this).outerHeight() + $(this)[0].scrollTop) > $(this)[0].scrollHeight ) { 199 e.preventDefault(); 200 this.scrollTop += ( delta < 0 ? 1 : -1 ); 201 } 202 } 203 }); 204 205 // hide options menus if click happens off of the list placeholder button 206 $(document).off('click.ms-hideopts').on('click.ms-hideopts', function( event ){ 207 if( !$(event.target).closest('.ms-options-wrap').length ) { 208 $('.ms-options-wrap.ms-active > .ms-options').each(function(){ 209 $(this).closest('.ms-options-wrap').removeClass('ms-active'); 210 211 var listID = $(this).closest('.ms-options-wrap').attr('id'); 212 213 var thisInst = $(this).parent().siblings('.'+ listID +'.jqmsLoaded').data('plugin_multiselect-instance'); 214 215 // USER CALLBACK 216 if( typeof thisInst.options.onControlClose == 'function' ) { 217 thisInst.options.onControlClose( thisInst.element ); 218 } 219 }); 220 } 221 // hide open option lists if escape key pressed 222 }).on('keydown', function( event ){ 223 if( (event.keyCode || event.which) == 27 ) { // esc key 224 $(this).trigger('click.ms-hideopts'); 225 } 226 }); 227 228 // handle pressing enter|space while tabbing through 229 placeholder.on('keydown', function( event ){ 230 var code = (event.keyCode || event.which); 231 if( (code == 13) || (code == 32) ) { // enter OR space 232 placeholder.trigger( 'mousedown' ); 233 } 234 }); 235 236 // disable button action 237 placeholder.on( 'mousedown', function( event ){ 238 // ignore if its not a left click 239 if( event.which && (event.which != 1) ) { 240 return true; 241 } 242 243 // hide other menus before showing this one 244 $('.ms-options-wrap.ms-active').each(function(){ 245 if( $(this).siblings( '.'+ $(this).attr('id') +'.jqmsLoaded')[0] != optionsWrap.parent().siblings('.ms-list-'+ instance.listNumber +'.jqmsLoaded')[0] ) { 246 $(this).removeClass('ms-active'); 247 248 var thisInst = $(this).siblings( '.'+ $(this).attr('id') +'.jqmsLoaded').data('plugin_multiselect-instance'); 249 250 // USER CALLBACK 251 if( typeof thisInst.options.onControlClose == 'function' ) { 252 thisInst.options.onControlClose( thisInst.element ); 253 } 254 } 255 }); 256 257 // show/hide options 258 optionsWrap.closest('.ms-options-wrap').toggleClass('ms-active'); 259 260 // recalculate height 261 if( optionsWrap.closest('.ms-options-wrap').hasClass('ms-active') ) { 262 // USER CALLBACK 263 if( typeof instance.options.onControlOpen == 'function' ) { 264 instance.options.onControlOpen( instance.element ); 265 } 266 267 optionsWrap.css( 'maxHeight', '' ); 268 269 // override with user defined maxHeight 270 if( instance.options.maxHeight ) { 271 var maxHeight = instance.options.maxHeight; 272 } 273 else { 274 // cacl default maxHeight 275 var maxHeight = ($(window).height() - optionsWrap.offset().top + $(window).scrollTop() - 20); 276 } 277 278 if( maxHeight ) { 279 // maxHeight cannot be less than options.minHeight 280 maxHeight = maxHeight < instance.options.minHeight ? instance.options.minHeight : maxHeight; 281 282 optionsWrap.css( 'maxHeight', maxHeight ); 283 } 284 } 285 else if( typeof instance.options.onControlClose == 'function' ) { 286 instance.options.onControlClose( instance.element ); 287 } 288 }).click(function( event ){ event.preventDefault(); }); 289 290 // add placeholder copy 291 if( instance.options.texts.placeholder ) { 292 placeholder.find('span').text( instance.options.texts.placeholder ); 293 } 294 295 // add search box 296 if( instance.options.search ) { 297 optionsList.before('<div class="ms-search"><input type="text" value="" placeholder="'+ instance.options.texts.search +'" /></div>'); 298 optionsList.after('<div class="no-result-message">' + instance.options.texts.searchNoResult + '</div>'); 299 300 var search = optionsWrap.find('.ms-search input'); 301 302 search.on('keyup', function(){ 303 // ignore keystrokes that don't make a difference 304 if( $(this).data('lastsearch') == $(this).val() ) { 305 return true; 306 } 307 308 // pause timeout 309 if( $(this).data('searchTimeout') ) { 310 clearTimeout( $(this).data('searchTimeout') ); 311 } 312 313 var thisSearchElem = $(this); 314 315 $(this).data('searchTimeout', setTimeout(function(){ 316 thisSearchElem.data('lastsearch', thisSearchElem.val() ); 317 318 // USER CALLBACK 319 if( typeof instance.options.searchOptions.onSearch == 'function' ) { 320 instance.options.searchOptions.onSearch( instance.element ); 321 } 322 323 // search non optgroup li's 324 var searchString = $.trim( search.val().toLowerCase().replace(' ', '-')
vendor: 22,239 bytes, lines 324-840
324); 325 if( searchString ) { 326 optionsList.find('li[data-search-term*="'+ searchString +'"]:not(.optgroup)').removeClass('ms-hidden'); 327 optionsList.find('li:not([data-search-term*="'+ searchString +'"], .optgroup)').addClass('ms-hidden'); 328 } 329 else { 330 optionsList.find('.ms-hidden').removeClass('ms-hidden'); 331 } 332 333 // show/hide optgroups based on if there are items visible within 334 if( !instance.options.searchOptions.showOptGroups ) { 335 optionsList.find('.optgroup').each(function(){ 336 if( $(this).find('li:not(.ms-hidden)').length ) { 337 $(this).show(); 338 } 339 else { 340 $(this).hide(); 341 } 342 }); 343 } 344 345 instance._updateSelectAllText(); 346 }, instance.options.searchOptions.delay )); 347 }); 348 } 349 350 // add global select all options 351 if( instance.options.selectAll ) { 352 optionsList.before('<a href="#" class="ms-selectall global">' + instance.options.texts.selectAll + '</a>'); 353 } 354 355 // handle select all option 356 optionsWrap.on('click', '.ms-selectall', function( event ){ 357 event.preventDefault(); 358 359 instance.updateSelectAll = false; 360 instance.updatePlaceholder = false; 361 362 var select = optionsWrap.parent().siblings('.ms-list-'+ instance.listNumber +'.jqmsLoaded'); 363 364 if( $(this).hasClass('global') ) { 365 // check if any options are not selected if so then select them 366 if( optionsList.find('li:not(.optgroup, .selected, .ms-hidden) input[type="checkbox"]:not(:disabled)').length ) { 367 // get unselected vals, mark as selected, return val list 368 optionsList.find('li:not(.optgroup, .selected, .ms-hidden) input[type="checkbox"]:not(:disabled)').closest('li').addClass('selected'); 369 optionsList.find('li.selected input[type="checkbox"]:not(:disabled)').prop( 'checked', true ); 370 } 371 // deselect everything 372 else { 373 optionsList.find('li:not(.optgroup, .ms-hidden).selected input[type="checkbox"]:not(:disabled)').closest('li').removeClass('selected'); 374 optionsList.find('li:not(.optgroup, .ms-hidden, .selected) input[type="checkbox"]:not(:disabled)').prop( 'checked', false ); 375 } 376 } 377 else if( $(this).closest('li').hasClass('optgroup') ) { 378 var optgroup = $(this).closest('li.optgroup'); 379 380 // check if any selected if so then select them 381 if( optgroup.find('li:not(.selected, .ms-hidden) input[type="checkbox"]:not(:disabled)').length ) { 382 optgroup.find('li:not(.selected, .ms-hidden) input[type="checkbox"]:not(:disabled)').closest('li').addClass('selected'); 383 optgroup.find('li.selected input[type="checkbox"]:not(:disabled)').prop( 'checked', true ); 384 } 385 // deselect everything 386 else { 387 optgroup.find('li:not(.ms-hidden).selected input[type="checkbox"]:not(:disabled)').closest('li').removeClass('selected'); 388 optgroup.find('li:not(.ms-hidden, .selected) input[type="checkbox"]:not(:disabled)').prop( 'checked', false ); 389 } 390 } 391 392 var vals = []; 393 optionsList.find('li.selected input[type="checkbox"]').each(function(){ 394 vals.push( $(this).val() ); 395 }); 396 select.val( vals ).trigger('change'); 397 398 instance.updateSelectAll = true; 399 instance.updatePlaceholder = true; 400 401 // USER CALLBACK 402 if( typeof instance.options.onSelectAll == 'function' ) { 403 instance.options.onSelectAll( instance.element, vals.length ); 404 } 405 406 instance._updateSelectAllText(); 407 instance._updatePlaceholderText(); 408 }); 409 410 // add options to wrapper 411 var options = []; 412 $(instance.element).children().each(function(){ 413 if( this.nodeName.toUpperCase() == 'OPTGROUP' ) { 414 var groupOptions = []; 415 416 $(this).children('option').each(function(){ 417 var thisOptionAtts = {}; 418 for( var i = 0; i < instance.options.optionAttributes.length; i++ ) { 419 var thisOptAttr = instance.options.optionAttributes[ i ]; 420 421 if( $(this).attr( thisOptAttr ) !== undefined ) { 422 thisOptionAtts[ thisOptAttr ] = $(this).attr( thisOptAttr ); 423 } 424 } 425 426 groupOptions.push({ 427 name : $(this).text(), 428 value : $(this).val(), 429 checked: $(this).prop( 'selected' ), 430 attributes: thisOptionAtts 431 }); 432 }); 433 434 options.push({ 435 label : $(this).attr('label'), 436 options: groupOptions 437 }); 438 } 439 else if( this.nodeName.toUpperCase() == 'OPTION' ) { 440 var thisOptionAtts = {}; 441 for( var i = 0; i < instance.options.optionAttributes.length; i++ ) { 442 var thisOptAttr = instance.options.optionAttributes[ i ]; 443 444 if( $(this).attr( thisOptAttr ) !== undefined ) { 445 thisOptionAtts[ thisOptAttr ] = $(this).attr( thisOptAttr ); 446 } 447 } 448 449 options.push({ 450 name : $(this).text(), 451 value : $(this).val(), 452 checked : $(this).prop( 'selected' ), 453 attributes: thisOptionAtts 454 }); 455 } 456 else { 457 // bad option 458 return true; 459 } 460 }); 461 instance.loadOptions( options, true, false ); 462 463 // BIND SELECT ACTION 464 optionsWrap.on( 'click', 'input[type="checkbox"]', function(){ 465 $(this).closest( 'li' ).toggleClass( 'selected' ); 466 467 var select = optionsWrap.parent().siblings('.ms-list-'+ instance.listNumber +'.jqmsLoaded'); 468 469 // toggle clicked option 470 select.find('option[value="'+ instance._escapeSelector( $(this).val() ) +'"]').prop( 471 'selected', $(this).is(':checked') 472 ).closest('select').trigger('change'); 473 474 // USER CALLBACK 475 if( typeof instance.options.onOptionClick == 'function' ) { 476 instance.options.onOptionClick(instance.element, this); 477 } 478 479 instance._updateSelectAllText(); 480 instance._updatePlaceholderText(); 481 }); 482 483 // BIND FOCUS EVENT 484 optionsWrap.on('focusin', 'input[type="checkbox"]', function(){ 485 $(this).closest('label').addClass('focused'); 486 }).on('focusout', 'input[type="checkbox"]', function(){ 487 $(this).closest('label').removeClass('focused'); 488 }); 489 490 // USER CALLBACK 491 if( typeof instance.options.onLoad === 'function' ) { 492 instance.options.onLoad( instance.element ); 493 } 494 495 // hide native select list 496 $(instance.element).hide(); 497 }, 498 499 /* LOAD SELECT OPTIONS */ 500 loadOptions: function( options, overwrite, updateSelect ) { 501 // console.log( options ); 502 overwrite = (typeof overwrite == 'boolean') ? overwrite : true; 503 updateSelect = (typeof updateSelect == 'boolean') ? updateSelect : true; 504 505 var instance = this; 506 var select = $(instance.element); 507 var optionsList = select.siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> .ms-options > ul'); 508 var optionsWrap = select.siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> .ms-options'); 509 510 if( overwrite ) { 511 optionsList.find('> li').remove(); 512 513 if( updateSelect ) { 514 select.find('> *').remove(); 515 } 516 } 517 518 var containers = []; 519 for( var key in options ) { 520 // Prevent prototype methods injected into options from being iterated over. 521 if( !options.hasOwnProperty( key ) ) { 522 continue; 523 } 524 525 var thisOption = options[ key ]; 526 var container = $('<li/>'); 527 var appendContainer = true; 528 529 // OPTION 530 if( thisOption.hasOwnProperty('value') ) { 531 if( instance.options.showCheckbox && instance.options.checkboxAutoFit ) { 532 container.addClass('ms-reflow'); 533 } 534 535 // add option to ms dropdown 536 instance._addOption( container, thisOption ); 537 538 if( updateSelect ) { 539 var selOption = $('<option/>', { 540 value: thisOption.value, 541 text : thisOption.name 542 }); 543 544 // add custom user attributes 545 if( thisOption.hasOwnProperty('attributes') && Object.keys( thisOption.attributes ).length ) { 546 selOption.attr( thisOption.attributes ); 547 } 548 549 // mark option as selected 550 if( thisOption.checked ) { 551 selOption.prop( 'selected', true ); 552 } 553 554 select.append( selOption ); 555 } 556 } 557 // OPTGROUP 558 else if( thisOption.hasOwnProperty('options') ) { 559 var optGroup = $('<optgroup/>', { 560 label: thisOption.label 561 }); 562 563 optionsList.find('> li.optgroup > span.label').each(function(){ 564 if( $(this).text() == thisOption.label ) { 565 container = $(this).closest('.optgroup'); 566 appendContainer = false; 567 } 568 }); 569 570 // prepare to append optgroup to select element 571 if( updateSelect ) { 572 if( select.find('optgroup[label="'+ thisOption.label +'"]').length ) { 573 optGroup = select.find('optgroup[label="'+ thisOption.label +'"]'); 574 } 575 else { 576 select.append( optGroup ); 577 } 578 } 579 580 // setup container 581 if( appendContainer ) { 582 container.addClass('optgroup'); 583 container.append('<span class="label">'+ thisOption.label +'</span>'); 584 container.find('> .label').css({ 585 clear: 'both' 586 }); 587 588 // add select all link 589 if( instance.options.selectGroup ) { 590 container.append('<a href="#" class="ms-selectall">' + instance.options.texts.selectAll + '</a>'); 591 } 592 593 container.append('<ul/>'); 594 } 595 596 for( var gKey in thisOption.options ) { 597 // Prevent prototype methods injected into options from 598 // being iterated over. 599 if( !thisOption.options.hasOwnProperty( gKey ) ) { 600 continue; 601 } 602 603 var thisGOption = thisOption.options[ gKey ]; 604 var gContainer = $('<li/>'); 605 if( instance.options.showCheckbox && instance.options.checkboxAutoFit ) { 606 gContainer.addClass('ms-reflow'); 607 } 608 609 // no clue what this is we hit (skip) 610 if( !thisGOption.hasOwnProperty('value') ) { 611 continue; 612 } 613 614 instance._addOption( gContainer, thisGOption ); 615 616 container.find('> ul').append( gContainer ); 617 618 // add option to optgroup in select element 619 if( updateSelect ) { 620 var selOption = $('<option/>', { 621 value: thisGOption.value, 622 text : thisGOption.name 623 }); 624 625 // add custom user attributes 626 if( thisGOption.hasOwnProperty('attributes') && Object.keys( thisGOption.attributes ).length ) { 627 selOption.attr( thisGOption.attributes ); 628 } 629 630 // mark option as selected 631 if( thisGOption.checked ) { 632 selOption.prop( 'selected', true ); 633 } 634 635 optGroup.append( selOption ); 636 } 637 } 638 } 639 else { 640 // no clue what this is we hit (skip) 641 continue; 642 } 643 644 if( appendContainer ) { 645 containers.push( container ); 646 } 647 } 648 optionsList.append( containers ); 649 650 // pad out label for room for the checkbox 651 if( instance.options.checkboxAutoFit && instance.options.showCheckbox && !optionsWrap.hasClass('hide-checkbox') ) { 652 var chkbx = optionsList.find('.ms-reflow:eq(0) input[type="checkbox"]'); 653 if( chkbx.length ) { 654 var checkboxWidth = chkbx.outerWidth(); 655 checkboxWidth = checkboxWidth ? checkboxWidth : 15; 656 657 optionsList.find('.ms-reflow label').css( 658 'padding-left', 659 (parseInt( chkbx.closest('label').css('padding-left') ) * 2) + checkboxWidth 660 ); 661 662 optionsList.find('.ms-reflow').removeClass('ms-reflow'); 663 } 664 } 665 666 // update placeholder text 667 instance._updatePlaceholderText(); 668 669 // RESET COLUMN STYLES 670 optionsWrap.find('ul').css({ 671 'column-count' : '', 672 'column-gap' : '', 673 '-webkit-column-count': '', 674 '-webkit-column-gap' : '', 675 '-moz-column-count' : '', 676 '-moz-column-gap' : '' 677 }); 678 679 // COLUMNIZE 680 if( select.find('optgroup').length ) { 681 // float non grouped options 682 optionsList.find('> li:not(.optgroup)').css({ 683 'float': 'left', 684 width: (100 / instance.options.columns) +'%' 685 }); 686 687 // add CSS3 column styles 688 optionsList.find('li.optgroup').css({ 689 clear: 'both' 690 }).find('> ul').css({ 691 'column-count' : instance.options.columns, 692 'column-gap' : 0, 693 '-webkit-column-count': instance.options.columns, 694 '-webkit-column-gap' : 0, 695 '-moz-column-count' : instance.options.columns, 696 '-moz-column-gap' : 0 697 }); 698 699 // for crappy IE versions float grouped options 700 if( this._ieVersion() && (this._ieVersion() < 10) ) { 701 optionsList.find('li.optgroup > ul > li').css({ 702 'float': 'left', 703 width: (100 / instance.options.columns) +'%' 704 }); 705 } 706 } 707 else { 708 // add CSS3 column styles 709 optionsList.css({ 710 'column-count' : instance.options.columns, 711 'column-gap' : 0, 712 '-webkit-column-count': instance.options.columns, 713 '-webkit-column-gap' : 0, 714 '-moz-column-count' : instance.options.columns, 715 '-moz-column-gap' : 0 716 }); 717 718 // for crappy IE versions float grouped options 719 if( this._ieVersion() && (this._ieVersion() < 10) ) { 720 optionsList.find('> li').css({ 721 'float': 'left', 722 width: (100 / instance.options.columns) +'%' 723 }); 724 } 725 } 726 727 // update un/select all logic 728 instance._updateSelectAllText(); 729 }, 730 731 /* UPDATE MULTISELECT CONFIG OPTIONS */ 732 settings: function( options ) { 733 this.options = $.extend( true, {}, this.options, options ); 734 this.reload(); 735 }, 736 737 /* RESET THE DOM */ 738 unload: function() { 739 $(this.element).siblings('#ms-list-'+ this.listNumber +'.ms-options-wrap').remove(); 740 $(this.element).show(function(){ 741 $(this).css('display','').removeClass('jqmsLoaded'); 742 }); 743 }, 744 745 /* RELOAD JQ MULTISELECT LIST */ 746 reload: function() { 747 // remove existing options 748 $(this.element).siblings('#ms-list-'+ this.listNumber +'.ms-options-wrap').remove(); 749 $(this.element).removeClass('jqmsLoaded'); 750 751 // load element 752 this.load(); 753 }, 754 755 // RESET BACK TO DEFAULT VALUES & RELOAD 756 reset: function() { 757 var defaultVals = []; 758 $(this.element).find('option').each(function(){ 759 if( $(this).prop('defaultSelected') ) { 760 defaultVals.push( $(this).val() ); 761 } 762 }); 763 764 $(this.element).val( defaultVals ); 765 766 this.reload(); 767 }, 768 769 disable: function( status ) { 770 status = (typeof status === 'boolean') ? status : true; 771 $(this.element).prop( 'disabled', status ); 772 $(this.element).siblings('#ms-list-'+ this.listNumber +'.ms-options-wrap').find('button:first-child') 773 .prop( 'disabled', status ); 774 }, 775 776 /** PRIVATE FUNCTIONS **/ 777 // update the un/select all texts based on selected options and visibility 778 _updateSelectAllText: function(){ 779 if( !this.updateSelectAll ) { 780 return; 781 } 782 783 var instance = this; 784 785 // select all not used at all so just do nothing 786 if( !instance.options.selectAll && !instance.options.selectGroup ) { 787 return; 788 } 789 790 var optionsWrap = $(instance.element).siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> .ms-options'); 791 792 // update un/select all text 793 optionsWrap.find('.ms-selectall').each(function(){ 794 var unselected = $(this).parent().find('li:not(.optgroup,.selected,.ms-hidden)'); 795 796 $(this).text( 797 unselected.length ? instance.options.texts.selectAll : instance.options.texts.unselectAll 798 ); 799 }); 800 801 var shownOptionsCount = optionsWrap.find('> ul li:not(.optgroup,.ms-hidden)').length; 802 803 // show/hide no-results message 804 optionsWrap.find('.no-result-message').toggle( shownOptionsCount ? false : true ); 805 806 // show/hide (un)select all element as necessary 807 optionsWrap.find('.ms-selectall.global').toggle( shownOptionsCount ? true : false ); 808 }, 809 810 // update selected placeholder text 811 _updatePlaceholderText: function(){ 812 if( !this.updatePlaceholder ) { 813 return; 814 } 815 816 var instance = this; 817 var select = $(instance.element); 818 var selectVals = select.val() ? select.val() : []; 819 var placeholder = select.siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> button:first-child'); 820 var placeholderTxt = placeholder.find('span'); 821 var optionsWrap = select.siblings('#ms-list-'+ instance.listNumber +'.ms-options-wrap').find('> .ms-options'); 822 823 // if there are disabled options get those values as well 824 if( select.find('option:selected:disabled').length ) { 825 selectVals = []; 826 select.find('option:selected').each(function(){ 827 selectVals.push( $(this).val() ); 828 }); 829 } 830 831 // get selected options 832 var selOpts = []; 833 for( var key in selectVals ) { 834 // Prevent prototype methods injected into options from being iterated over. 835 if( !selectVals.hasOwnProperty( key ) ) { 836 continue; 837 } 838 839 selOpts.push( 840
vendor: 2,807 bytes, lines 840-911
840$.trim( select.find('option[value="'+ instance._escapeSelector( selectVals[ key ] ) +'"]').text() ) 841 ); 842 843 if( selOpts.length >= instance.options.maxPlaceholderOpts ) { 844 break; 845 } 846 } 847 848 // UPDATE PLACEHOLDER TEXT WITH OPTIONS SELECTED 849 placeholderTxt.text( selOpts.join( ', ' ) ); 850 851 if( selOpts.length ) { 852 optionsWrap.closest('.ms-options-wrap').addClass('ms-has-selections'); 853 854 // USER CALLBACK 855 if( typeof instance.options.onPlaceholder == 'function' ) { 856 instance.options.onPlaceholder( instance.element, placeholderTxt, selOpts ); 857 } 858 } 859 else { 860 optionsWrap.closest('.ms-options-wrap').removeClass('ms-has-selections'); 861 } 862 863 // replace placeholder text 864 if( !selOpts.length ) { 865 placeholderTxt.text( instance.options.texts.placeholder ); 866 } 867 // if copy is larger than button width use "# selected" 868 else if( instance.options.replacePlaceholderText && ((placeholderTxt.width() > placeholder.width()) || (selOpts.length != selectVals.length)) ) { 869 placeholderTxt.text( selectVals.length + instance.options.texts.selectedOptions ); 870 } 871 }, 872 873 // Add option to the custom dom list 874 _addOption: function( container, option ) { 875 var instance = this; 876 var optionNameText = $('<div/>').html( option.name ).text(); 877 878 var thisOption = $('<label/>', { 879 for : 'ms-opt-'+ msOptCounter 880 }).text( optionNameText ); 881 882 var thisCheckbox = $('<input>', { 883 type : 'checkbox', 884 title: optionNameText, 885 id : 'ms-opt-'+ msOptCounter, 886 value: option.value 887 }); 888 889 // add user defined attributes 890 if( option.hasOwnProperty('attributes') && Object.keys( option.attributes ).length ) { 891 thisCheckbox.attr( option.attributes ); 892 } 893 894 if( option.checked ) { 895 container.addClass('default selected'); 896 thisCheckbox.prop( 'checked', true ); 897 } 898 899 thisOption.prepend( thisCheckbox ); 900 901 var searchTerm = ''; 902/* if( instance.options.searchOptions.searchText ) { 903 searchTerm += ' ' + optionNameText.toLowerCase(); 904 } 905 if( instance.options.searchOptions.searchValue ) { 906 searchTerm += ' ' + option.value.toLowerCase(); 907 } */ 908 909 searchTerm += ' ' + option.value.toLowerCase(); 910 911 container.attr( 'data-search-term', $.trim( searchTerm
vendor: 1,834 bytes, lines 911-966
911) ).prepend( thisOption ); 912 913 msOptCounter = msOptCounter + 1; 914 }, 915 916 // check ie version 917 _ieVersion: function() { 918 var myNav = navigator.userAgent.toLowerCase(); 919 return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false; 920 }, 921 922 // escape selector 923 _escapeSelector: function( string ) { 924 if( typeof $.escapeSelector == 'function' ) { 925 return $.escapeSelector( string ); 926 } 927 else { 928 return string.replace(/[!"#$%&'()*+,.\/:;<=>?@[\\\]^`{|}~]/g, "\\$&"); 929 } 930 } 931 }; 932 933 // ENABLE JQUERY PLUGIN FUNCTION 934 $.fn.multiselect = function( options ){ 935 if( !this.length ) { 936 return; 937 } 938 939 var args = arguments; 940 var ret; 941 942 // menuize each list 943 if( (options === undefined) || (typeof options === 'object') ) { 944 return this.each(function(){ 945 if( !$.data( this, 'plugin_multiselect' ) ) { 946 $.data( this, 'plugin_multiselect', new MultiSelect( this, options ) ); 947 } 948 }); 949 } else if( (typeof options === 'string') && (options[0] !== '_') && (options !== 'init') ) { 950 this.each(function(){ 951 var instance = $.data( this, 'plugin_multiselect' ); 952 953 if( instance instanceof MultiSelect && typeof instance[ options ] === 'function' ) { 954 ret = instance[ options ].apply( instance, Array.prototype.slice.call( args, 1 ) ); 955 } 956 957 // special destruct handler 958 if( options === 'unload' ) { 959 $.data( this, 'plugin_multiselect', null ); 960 } 961 }); 962 963 return ret; 964 } 965 }; 966}(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.