https://buffalosocietyofartists.org/wp-content/plugins/cm-expert-d…/jquery.sumoselect.js?ver=2.6.0.1
vendor: 33,215 bytes, lines 1-908
1/*global jQuery, define, module, require*/ 2/*! 3 * jquery.sumoselect 4 * http://hemantnegi.github.io/jquery.sumoselect 5 * 2016-12-12 6 * 7 * Copyright 2015 Hemant Negi 8 * Email : [email protected] 9 * Compressor http://refresh-sf.com/ 10 */ 11 12(function (factory) { 13 'use strict'; 14 if (typeof define === 'function' && define.amd) { 15 define(['jquery'], factory); 16 } else if (typeof exports !== 'undefined') { 17 module.exports = factory(require('jquery')); 18 } else { 19 factory(jQuery); 20 } 21 22})(($) => { 23 24 'namespace sumo'; 25 $.fn.SumoSelect = function (options) { 26 // Extra check for IE compatibility 27 const dispatchEvent = (target, eventName) => { 28 let event = null; 29 if(typeof(Event) === 'function') { 30 event = new Event(eventName, { 31 bubbles: true 32 }); 33 }else{ 34 event = document.createEvent('Event'); 35 event.initEvent(eventName, true, true); 36 } 37 38 target.dispatchEvent(event); 39 }; 40 41 // missing forEach on NodeList for IE11 42 if (window.NodeList && !NodeList.prototype.forEach) { 43 NodeList.prototype.forEach = Array.prototype.forEach; 44 } 45 46 // This is the easiest way to have default options. 47 const defaultOptions = { 48 placeholder: 'Select Here', // Dont change it here. 49 csvDispCount: 3, // display no. of items in multiselect. 0 to display all. 50 captionFormat: '{0} Selected', // format of caption text. you can set your locale. 51 captionFormatAllSelected: '{0} all selected!', // format of caption text when all elements are selected. set null to use captionFormat. It will not work if there are disabled elements in select. 52 floatWidth: 400, // Screen width of device at which the list is rendered in floating popup fashion. 53 forceCustomRendering: true, // force the custom modal on all devices below floatWidth resolution. 54 nativeOnDevice: ['Android', 'BlackBerry', 'iPhone', 'iPad', 'iPod', 'Opera Mini', 'IEMobile', 'Silk'], // 55 outputAsCSV: false, // true to POST data as csv ( false for Html control array ie. default select ) 56 csvSepChar: ',', // separation char in csv mode 57 okCancelInMulti: false, // display ok cancel buttons in desktop mode multiselect also. 58 isClickAwayOk: false, // for okCancelInMulti=true. sets whether click outside will trigger Ok or Cancel (default is cancel). 59 triggerChangeCombined: true, // im multi select mode whether to trigger change event on individual selection or combined selection. 60 selectAll: false, // to display select all button in multiselect mode.|| also select all will not be available on mobile devices. 61 62 search: false, // to display input for filtering content. selectAlltext will be input text placeholder 63 searchText: 'Search...', // placeholder for search input 64 searchFn (haystack, needle) { // search function 65 return haystack.toLowerCase().indexOf(needle.toLowerCase()) < 0; 66 }, 67 noMatch: 'No matches for "{0}"', 68 prefix: '', // some prefix usually the field name. eg. '<b>Hello</b>' 69 locale: ['OK', 'Cancel', 'Select All'], // all text that is used. don't change the index. 70 up: false, // set true to open upside. 71 showTitle: true, // set to false to prevent title (tooltip) from appearing 72 max: null, // Maximum number of options selected (when multiple) 73 // eslint-disable-next-line no-unused-vars 74 renderLi: (li, _originalOption) => li // Custom <li> item renderer 75 }; 76 77 const ret = this.each(function () { 78 const selObj = this; // the original select object. 79 if (this.sumo || !$(this).is('select')) return; //already initialized 80 81 const settings = $.extend({}, defaultOptions, options, $(this).data()); 82 83 this.sumo = { 84 E: $(selObj), //the jquery object of original select element. 85 is_multi: $(selObj).attr('multiple'), //if its a multiple select 86 select: '', 87 caption: '', 88 placeholder: '', 89 optDiv: '', 90 CaptionCont: '', 91 ul: '', 92 is_floating: false, 93 is_opened: false, 94 //backdrop: '', 95 mob: false, // if to open device default select 96 Pstate: [], 97 lastUnselected: null, 98 selectedCount: 0, 99 100 createElems () { 101 const O = this; 102 const selectedOptions = O.E.find('option:checked'); 103 O.E.wrap('<div class="SumoSelect" tabindex="0" role="button" aria-expanded="false">'); 104 selectedOptions.each((_, selectedOption) => { // Fix for IE resetting index to 0 when -1 105 selectedOption.selected = true; 106 }); 107 O.select = O.E.parent(); 108 O.caption = $('<span>'); 109 O.CaptionCont = $(`<p class="CaptionCont SelectBox ${O.E.attr('class')}" ><label><i></i></label></p>`) 110 .attr('style', O.E.attr('style')) 111 .prepend(O.caption); 112 O.select.append(O.CaptionCont); 113 114 // default turn off if no multiselect 115 if (!O.is_multi) settings.okCancelInMulti = false; 116 117 if (O.E.attr('disabled')) 118 O.select.addClass('disabled').removeAttr('tabindex'); 119 120 //if output as csv and is a multiselect. 121 if (settings.outputAsCSV && O.is_multi && O.E.attr('name')) { 122 //create a hidden field to store csv value. 123 O.select.append($('<input class="HEMANT123" type="hidden" />').attr('name', O.E.attr('name')).val(O.getSelStr())); 124 125 // so it can not post the original select. 126 O.E.removeAttr('name'); 127 } 128 129 //break for mobile rendring.. if forceCustomRendering is false 130 //if (O.isMobile() && !settings.forceCustomRendering) { 131 // O.setNativeMobile(); 132 // return; 133 //} 134 135 // if there is a name attr in select add a class to container div 136 if (O.E.attr('name')) O.select.addClass(`sumo_${O.E.attr('name').replace(/\[\]/, '')}`); 137 138 //hide original select 139 O.E.addClass('SumoUnder').attr('tabindex', '-1'); 140 141 //## Creating the list... 142 O.optDiv = $(`<div class="optWrapper ${settings.up ? 'up' : ''}">`); 143 144 //branch for floating list in low res devices. 145 O.floatingList(); 146 147 //Creating the markup for the available options 148 O.ul = $('<ul class="options">'); 149 O.optDiv.append(O.ul); 150 151 // Select all functionality 152 if (settings.selectAll && O.is_multi && !settings.max) O.SelAll(); 153 154 // search functionality 155 if (settings.search) O.Search(); 156 157 O.ul.append(O.prepItems(O.E.children())); 158 159 //if multiple then add the class multiple and add OK / CANCEL button 160 if (O.is_multi) O.multiSelelect(); 161 162 O.select.append(O.optDiv); 163 O._handleMax(); 164 O.basicEvents(); 165 O.selAllState(); 166 }, 167 168 prepItems (opts, d) { 169 const lis = [], O = this; 170 $(opts).each((i, opt) => { // parsing options to li 171 const $opt = $(opt); 172 lis.push($opt.is('optgroup') ? 173 $(`<li class="group ${opt.disabled ? 'disabled' : ''}"><label></label><ul></ul></li>`) 174 .find('label') 175 .text($opt.attr('label')) 176 .end() 177 .find('ul') 178 .append(O.prepItems($opt.children(), opt.disabled)) 179 .end() 180 : 181 O.createLi($opt, d) 182 ); 183 }); 184 return lis; 185 }, 186 187 //## Creates a LI element from a given option and binds events to it 188 //## returns the jquery instance of li (not inserted in dom) 189 createLi (opt, d) { 190 const O = this; 191 192 if (!opt.attr('value')) opt.attr('value', opt.val()); 193 const li = $(`<li class="opt"><label>${opt.html()}</label></li>`); 194 195 li.data('opt', opt); // store a direct reference to option. 196 opt.data('li', li); // store a direct reference to list item. 197 if (O.is_multi) li.prepend('<span><i></i></span>'); 198 199 if (opt[0].disabled || d) 200 li.addClass('disabled'); 201 202 O.onOptClick(li); 203 204 if (opt[0].selected) { 205 li.addClass('selected'); 206 O.selectedCount++; 207 } 208 209 if (opt.attr('class')) 210 li.addClass(opt.attr('class')); 211 212 if (opt.attr('title')) 213 li.attr('title', opt.attr('title')); 214 215 return settings.renderLi(li, opt); 216 }, 217 218 //## Returns the selected items as string in a Multiselect. 219 getSelStr () { 220 // get the pre selected items. 221 const sopt = []; 222 this.E.find('option:checked').each(function () { sopt.push($(this).val()); }); 223 return sopt.join(settings.csvSepChar); 224 }, 225 226 //## THOSE OK/CANCEL BUTTONS ON MULTIPLE SELECT. 227 multiSelelect () { 228 const O = this; 229 O.optDiv.addClass('multiple'); 230 O.okbtn = $('<p tabindex="0" class="btnOk"></p>').click(() => { 231 //if combined change event is set. 232 O._okbtn(); 233 O.hideOpts(); 234 }); 235 [O.okbtn[0].innerText] = settings.locale; 236 237 O.cancelBtn = $('<p tabindex="0" class="btnCancel"></p>').click(() => { 238 O._cnbtn(); 239 O.hideOpts(); 240 }); 241 [, O.cancelBtn[0].innerText] = settings.locale; 242 243 const btns = O.okbtn.add(O.cancelBtn); 244 O.optDiv.append($('<div class="MultiControls">').append(btns)); 245 246 // handling keyboard navigation on ok cancel buttons. 247 btns.on('keydown.sumo', function (e) { 248 const el = $(this); 249 switch (e.which) { 250 case 32: // space 251 case 13: // enter 252 el.trigger('click'); 253 break; 254 255 case 9: //tab 256 if (el.hasClass('btnOk')) return; 257 break; 258 case 27: // esc 259 O._cnbtn(); 260 O.hideOpts(); 261 return; 262 default: 263 break; 264 } 265 e.stopPropagation(); 266 e.preventDefault(); 267 }); 268 }, 269 270 _okbtn () { 271 const O = this; 272 let cg = 0; 273 //if combined change event is set. 274 if (settings.triggerChangeCombined) { 275 //check for a change in the selection. 276 if (O.E.find('option:checked').length !== O.Pstate.length) { 277 cg = 1; 278 } 279 else { 280 O.E.find('option').each((i, e) => { 281 if (e.selected && O.Pstate.indexOf(i) < 0) cg = 1; 282 }); 283 } 284 285 if (cg) { 286 O.callChange(); 287 O.setText(); 288 } 289 } 290 }, 291 _cnbtn () { 292 const O = this; 293 //remove all selections 294 O.E.find('option:checked').each(function () { this.selected = false; }); 295 O.optDiv.find('li.selected').removeClass('selected'); 296 297 //restore selections from saved state. 298 for (let i = 0; i < O.Pstate.length; i++) { 299 O.E.find('option')[O.Pstate[i]].selected = true; 300 O.ul.find('li.opt').eq(O.Pstate[i]).addClass('selected'); 301 } 302 O.selAllState(); 303 }, 304 305 _handleMax () { 306 // Disable options if max reached 307 if (settings.max) { 308 if (this.selectedCount >= +settings.max) { 309 this.optDiv.find('li.opt').not('.hidden').each((ix, e) => { 310 if (!$(e).hasClass('selected')) { 311 $(e).addClass('temporary-disabled disabled'); 312 } 313 }); 314 } else { 315 // Enable options back 316 this.optDiv.find('li.opt').not('.hidden').each((ix, e) => { 317 if ($(e).hasClass('temporary-disabled')) { 318 $(e).removeClass('temporary-disabled disabled'); 319 } 320 }); 321 } 322 } 323 }, 324 325 SelAll () { 326 const O = this; 327 if (!O.is_multi) return; 328 O.selAll = $('<p class="select-all"><span><i></i></span><label></label></p>'); 329 [, , O.selAll.find('label')[0].innerText] = settings.locale; 330 O.optDiv.addClass('selall'); 331 O.selAll.on('click', () => { 332 O.selAll.toggleClass('selected'); 333 O.toggSelAll(O.selAll.hasClass('selected'), 1); 334 //O.selAllState(); 335 }); 336 337 O.optDiv.prepend(O.selAll); 338 }, 339 340 // search module (can be removed if not required.) 341 Search () { 342 const O = this, 343 cc = O.CaptionCont.addClass('search'), 344 P = $('<p class="no-match">'), 345 fn = (options.searchFn && typeof options.searchFn === 'function') ? options.searchFn : settings.searchFn; 346 347 O.ftxt = $('<input type="text" class="search-txt" value="" autocomplete="off">') 348 .on('click', (e) => { 349 e.stopPropagation(); 350 }); 351 O.ftxt[0].placeholder = settings.searchText; 352 cc.append(O.ftxt); 353 O.optDiv.children('ul').after(P); 354 355 O.ftxt.on('keyup.sumo', () => { 356 const hid = O.optDiv.find('ul.options li.opt').each((ix, e) => { 357 const el = $(e), 358 {0: opt} = el.data('opt'); 359 opt.hidden = fn(el.text(), O.ftxt.val(), el); 360 el.toggleClass('hidden', opt.hidden); 361 }).not('.hidden'); 362 363 // Hide opt-groups with no options matched 364 O.optDiv[0].querySelectorAll('li.group').forEach(optGroup => { 365 if (optGroup.querySelector('li:not(.hidden)')) { 366 optGroup.classList.remove('hidden'); 367 } else { 368 optGroup.classList.add('hidden'); 369 } 370 }); 371 372 P.html(settings.noMatch.replace(/\{0\}/g, '<em></em>')).toggle(!hid.length); 373 P.find('em').text(O.ftxt.val()); 374 O.selAllState(); 375 }); 376 }, 377 378 selAllState () { 379 const O = this; 380 if (settings.selectAll && O.is_multi) { 381 let sc = 0, vc = 0; 382 O.optDiv.find('li.opt').not('.hidden .disabled').each((ix, e) => { 383 if ($(e).hasClass('selected')) sc++; 384 vc++; 385 }); 386 //select all checkbox state change. 387 if (sc === vc) O.selAll.removeClass('partial').addClass('selected'); 388 else if (sc === 0) O.selAll.removeClass('selected partial'); 389 else O.selAll.addClass('partial');//.removeClass('selected'); 390 } 391 }, 392 393 showOpts () { 394 const O = this; 395 if (O.E.attr('disabled')) return; // if select is disabled then retrun 396 O.E.trigger('sumo:opening', O); 397 O.is_opened = true; 398 O.select.addClass('open').attr('aria-expanded', 'true'); 399 O.E.trigger('sumo:opened', O); 400 401 if (O.ftxt) O.ftxt.focus(); 402 else O.select.focus(); 403 404 // hide options on click outside. 405 $(document).on('click.sumo', (e) => { 406 if (!O.select.is(e.target) // if the target of the click isn't the container... 407 && O.select.has(e.target).length === 0) { // ... nor a descendant of the container 408 if (!O.is_opened) return; 409 O.hideOpts(); 410 if (settings.okCancelInMulti) { 411 if (settings.isClickAwayOk) 412 O._okbtn(); 413 else 414 O._cnbtn(); 415 } 416 } 417 }); 418 419 if (O.is_floating) { 420 let H = O.optDiv.children('ul').outerHeight() + 2; // +2 is clear fix 421 if (O.is_multi) H = H + +O.optDiv.css('padding-bottom'); 422 O.optDiv.css('height', H); 423 $('body').addClass('sumoStopScroll'); 424 } 425 426 O.setPstate(); 427 }, 428 429 //maintain state when ok/cancel buttons are available storing the indexes. 430 setPstate () { 431 const O = this; 432 if (O.is_multi && (O.is_floating || settings.okCancelInMulti)) { 433 O.Pstate = []; 434 // assuming that find returns elements in tree order 435 O.E.find('option').each((i, e) => { if (e.selected) O.Pstate.push(i); }); 436 } 437 }, 438 439 callChange () { 440 this.E.get().forEach(e => { 441 dispatchEvent(e, 'change'); 442 dispatchEvent(e, 'click'); 443 }); 444 }, 445 446 hideOpts () { 447 const O = this; 448 if (O.is_opened) { 449 O.E.trigger('sumo:closing', O); 450 O.is_opened = false; 451 O.select.removeClass('open').attr('aria-expanded', 'false').find('ul li.sel').removeClass('sel'); 452 O.E.trigger('sumo:closed', O); 453 $(document).off('click.sumo'); 454 $('body').removeClass('sumoStopScroll'); 455 456 // clear the search 457 if (settings.search) { 458 O.ftxt.val(''); 459 O.ftxt.trigger('keyup.sumo'); 460 } 461 } 462 }, 463 setOnOpen () { 464 const O = this; 465 let li = O.optDiv.find('li.opt:not(.hidden)').eq(settings.search ? 0 : O.E[0].selectedIndex); 466 if (li.hasClass('disabled')) { 467 li = li.next(':not(disabled)'); 468 if (!li.length) return; 469 } 470 O.optDiv.find('li.sel').removeClass('sel'); 471 li.addClass('sel'); 472 O.showOpts(); 473 }, 474 nav (up) { 475 const O = this; 476 let c = null, sel = O.ul.find('li.opt.sel:not(.hidden)'); 477 const 478 s = O.ul.find('li.opt:not(.disabled):not(.hidden)'), 479 idx = s.index(sel); 480 if (O.is_opened && sel.length) { 481 if (up && idx > 0) 482 c = s.eq(idx - 1); 483 else if (!up && idx < s.length - 1 && idx > -1) 484 c = s.eq(idx + 1); 485 else return; // if no items before or after 486 487 sel.removeClass('sel'); 488 sel = c.addClass('sel'); 489 490 // setting sel item to visible view. 491 const { ul } = O, 492 st = ul.scrollTop(), 493 t = sel.position().top + st; 494 if (t >= st + ul.height() - sel.outerHeight()) 495 ul.scrollTop(t - ul.height() + sel.outerHeight()); 496 if (t < st) 497 ul.scrollTop(t); 498 499 } 500 else 501 O.setOnOpen(); 502 }, 503 504 basicEvents () { 505 const O = this; 506 O.CaptionCont.click((evt) => { 507 O.E.trigger('click'); 508 if (O.is_opened) O.hideOpts(); else O.showOpts(); 509 evt.stopPropagation(); 510 }); 511 512 O.select.on('keydown.sumo', (e) => { 513 switch (e.which) { 514 case 38: // up 515 O.nav(true); 516 break; 517 518 case 40: // down 519 O.nav(false); 520 break; 521 522 case 65: // shortcut ctrl + a to select all and ctrl + shift + a to unselect all. 523 if (O.is_multi && !settings.max && e.ctrlKey) { 524 O.toggSelAll(!e.shiftKey, 1); 525 break; 526 } 527 else 528 return; 529 530 case 32: // space 531 if (settings.search && O.ftxt.is(e.target)) return; 532 break; 533 case 13: // enter 534 if (O.is_opened) 535 O.optDiv.find('ul li.sel').trigger('click'); 536 else 537 O.setOnOpen(); 538 break; 539 case 9: //tab 540 if (!settings.okCancelInMulti) 541 O.hideOpts(); 542 return; 543 case 27: // esc 544 if (settings.okCancelInMulti) O._cnbtn(); 545 O.hideOpts(); 546 return; 547 548 default: 549 return; // exit this handler for other keys 550 } 551 e.preventDefault(); // prevent the default action (scroll / move caret) 552 }); 553 554 $(window).on('resize.sumo', () => { 555 O.floatingList(); 556 }); 557 }, 558 559 onOptClick (li) { 560 const O = this; 561 li.click(function () { 562 const $li = $(this); 563 if ($li.hasClass('disabled')) return; 564 if (O.is_multi) { 565 $li.toggleClass('selected'); 566 $li.data('opt')[0].selected = $li.hasClass('selected'); 567 if ($li.data('opt')[0].selected === false) { 568 O.lastUnselected = $li.data('opt')[0].textContent; 569 O.selectedCount--; 570 } else { 571 O.selectedCount++; 572 } 573 574 if (settings.max) { 575 O._handleMax(); 576 } 577 578 O.selAllState(); 579 } 580 else { 581 $li.parent().find('li.selected').removeClass('selected'); //if not multiselect then remove all selections from this list 582 $li.toggleClass('selected'); 583 $li.data('opt')[0].selected = true; 584 O.selectedCount = 1; 585 } 586 587 //branch for combined change event. 588 if (!(O.is_multi && settings.triggerChangeCombined && (O.is_floating || settings.okCancelInMulti))) { 589 O.setText(); 590 O.callChange(); 591 } 592 593 if (!O.is_multi) O.hideOpts(); //if its not a multiselect then hide on single select. 594 }); 595 }, 596 597 // fixed some variables that were not explicitly typed (michc) 598 setText () { 599 const O = this; 600 O.placeholder = ""; 601 if (O.is_multi) { 602 const sels = O.E.find(':checked').not(':disabled'); //selected options. 603 604 if (settings.csvDispCount && sels.length > settings.csvDispCount) { 605 if (sels.length === O.E.find('option').length && settings.captionFormatAllSelected) { 606 O.placeholder = settings.captionFormatAllSelected.replace(/\{0\}/g, sels.length); 607 } 608 else { 609 O.placeholder = settings.captionFormat.replace(/\{0\}/g, sels.length); 610 } 611 } 612 else { 613 O.placeholder = sels.toArray().map(selected => selected.innerText).join(', '); 614 } 615 } 616 else { 617 O.placeholder = O.E.find(':checked').not(':disabled').text(); 618 } 619 620 let is_placeholder = false; 621 622 if (!O.placeholder) { 623 624 is_placeholder = true; 625 626 O.placeholder = O.E.attr('placeholder'); 627 if (!O.placeholder) //if placeholder is there then set it 628 O.placeholder = O.E.find('option:disabled:checked').text(); 629 } 630 631 O.placeholder = O.placeholder ? (`${settings.prefix} ${O.placeholder}`) : settings.placeholder; 632 633 //set display text 634 O.caption.text(O.placeholder); 635 if (settings.showTitle) O.CaptionCont.attr('title', O.placeholder); 636 637 //set the hidden field if post as csv is true. 638 const csvField = O.select.find('input.HEMANT123'); 639 if (csvField.length) csvField.val(O.getSelStr()); 640 641 //add class placeholder if its a placeholder text. 642 if (is_placeholder) O.caption.addClass('placeholder'); else O.caption.removeClass('placeholder'); 643 return O.placeholder; 644 }, 645 646 isMobile () { 647 648 // Adapted from http://www.detectmobilebrowsers.com 649 const ua = navigator.userAgent || navigator.vendor || window.opera; 650 651 // Checks for iOs, Android, Blackberry, Opera Mini, and Windows mobile devices 652 for (let i = 0; i < settings.nativeOnDevice.length; i++) if (ua.toString().toLowerCase().indexOf(settings.nativeOnDevice[i].toLowerCase()) > 0) return settings.nativeOnDevice[i]; 653 return false; 654 }, 655 656 setNativeMobile () { 657 const O = this; 658 O.E.addClass('SelectClass');//.css('height', O.select.outerHeight()); 659 O.mob = true; 660 O.E.change(() => { 661 O.setText(); 662 }); 663 }, 664 665 floatingList () { 666 const O = this; 667 //called on init and also on resize. 668 //O.is_floating = true if window width is < specified float width 669 O.is_floating = $(window).width() <= settings.floatWidth; 670 671 //set class isFloating 672 O.optDiv.toggleClass('isFloating', O.is_floating); 673 674 //remove height if not floating 675 if (!O.is_floating) O.optDiv.css('height', ''); 676 677 //toggle class according to okCancelInMulti flag only when it is not floating 678 O.optDiv.toggleClass('okCancelInMulti', settings.okCancelInMulti && !O.is_floating); 679 }, 680 681 //HELPERS FOR OUTSIDERS 682 // validates range of given item operations 683 vRange (i) { 684 const O = this; 685 const opts = O.E.find('option'); 686 if (opts.length <= i || i < 0) throw new Error("index out of bounds"); 687 return O; 688 }, 689 690 //toggles selection on c as boolean. 691 toggSel (c, i) { 692 const O = this; 693 let opt = null; 694 if (typeof (i) === "number") { 695 O.vRange(i); 696 opt = O.E.find('option')[i]; 697 } 698 else { 699 opt = O.E.find(`option[value="${i}"]`)[0] || 0; 700 } 701 if (!opt || opt.disabled) 702 return; 703 704 if (opt.selected !== c) { 705 if ((settings.max && !opt.selected && O.selectedCount < settings.max) || opt.selected || (!settings.max && !opt.selected)) { 706 opt.selected = c; 707 if (!O.mob) $(opt).data('li').toggleClass('selected', c); 708 709 O.callChange(); 710 O.setPstate(); 711 O.setText(); 712 O.selAllState(); 713 } 714 } 715 }, 716 717 //toggles disabled on c as boolean. 718 toggDis (c, i) { 719 const O = this.vRange(i); 720 O.E.find('option')[i].disabled = c; 721 if (c) O.E.find('option')[i].selected = false; 722 if (!O.mob) O.optDiv.find('ul.options li.opt').eq(i).toggleClass('disabled', c).removeClass('selected'); 723 O.setText(); 724 }, 725 726 // toggle disable/enable on complete select control 727 toggSumo (val) { 728 const O = this; 729 O.enabled = val; 730 O.select.toggleClass('disabled', val); 731 732 if (val) { 733 O.E.attr('disabled', 'disabled'); 734 O.select.removeAttr('tabindex'); 735 } 736 else { 737 O.E.removeAttr('disabled'); 738 O.select.attr('tabindex', '0'); 739 } 740 741 return O; 742 }, 743 744 // toggles all option on c as boolean. 745 // set direct=false/0 bypasses okCancelInMulti behaviour. 746 toggSelAll (c, direct) { 747 const O = this; 748 const cloneOriginalEvents = $.extend(true, {}, $._data(O.E.get(0), "events")); // clone original select elements events 749 O.E.off(); // unbind original select elements events because we do not want the following clicks to trigger change on it 750 751 if (O.is_multi) { 752 // Select all 753 if (c) { 754 O.E.find('option:not(:checked):not(:disabled):not(:hidden)').toArray().forEach(option => { 755 if (!$(option).data('li').hasClass('hidden')) { 756 option.selected = true; 757 $(option).data('li').toggleClass('selected', true); 758 } 759 }); 760 } else { 761 // Unselect all 762 O.E.find('option:checked:not(:disabled):not(:hidden)').toArray().forEach(option => { 763 if (!$(option).data('li').hasClass('hidden')) { 764 option.selected = false; 765 $(option).data('li').toggleClass('selected', false); 766 } 767 }); 768 } 769 } else { 770 if (!c) O.E[0].selectedIndex = -1; 771 else console.warn('You called `SelectAll` on a non-multiple select'); 772 } 773 774 // rebind original select elements events 775 $.each(cloneOriginalEvents, (_, e) => { 776 $.each(e, (__, ev) => { 777 O.E.on(ev.type, ev.handler); 778 }); 779 }); 780 781 if((O.is_multi && !settings.okCancelInMulti) || !O.is_multi){ 782 O.callChange(); // call change on original select element 783 O.setText(); 784 } 785 786 if (!direct) { 787 if (!O.mob && O.selAll) O.selAll.removeClass('partial').toggleClass('selected', !!c); 788 O.setText(); 789 O.setPstate(); 790 } 791 }, 792 793 /* outside accessibility options 794 which can be accessed from the element instance. 795 */ 796 reload () { 797 const elm = this.unload(); 798 return $(elm).SumoSelect(settings); 799 }, 800 801 unload () { 802 const O = this; 803 O.select.before(O.E); 804 O.E.show(); 805 O.E[0].classList.remove('SumoUnder'); 806 807 if (settings.outputAsCSV && O.is_multi && O.select.find('input.HEMANT123').length) { 808 O.E.attr('name', O.select.find('input.HEMANT123').attr('name')); // restore the name; 809 } 810 O.select.remove(); 811 delete selObj.sumo; 812 O.E.trigger('sumo:unloaded', O); 813 return selObj; 814 }, 815 816 //## add a new option to select at a given index. 817 add (val, txt, i, attr) { 818 if (typeof val === "undefined") throw new Error("No value to add"); 819 820 const O = this; 821 const opts = O.E.find('option'); 822 const value = val; 823 let 824 text = txt, 825 index = i; 826 if (typeof txt === "number") { // .add('xxx', 2) shorthand 827 index = txt; 828 text = val; 829 } else if (typeof txt === "undefined") { // .add('xxx') shorthand 830 text = val; 831 } 832 833 const opt = $("<option></option>").val(value).html(text); 834 835 if (attr && typeof attr === "object") { 836 $.each(attr, (j, v) => { 837 opt.attr(j, v); 838 }); 839 } 840 841 if (opts.length < index) throw new Error("index out of bounds"); 842 843 if (typeof index === "undefined" || opts.length === index) { // add it to the last if given index is last no or no index provides. 844 O.E.append(opt); 845 if (!O.mob) O.ul.append(O.createLi(opt)); 846 } 847 else { 848 opts.eq(index).before(opt); 849 if (!O.mob) O.ul.find('li.opt').eq(index).before(O.createLi(opt)); 850 } 851 852 return selObj; 853 }, 854 855 //## removes an item at a given index. 856 remove (i) { 857 const O = this.vRange(i); 858 O.E.find('option').eq(i).remove(); 859 if (!O.mob) O.optDiv.find('ul.options li.opt').eq(i).remove(); 860 O.setText(); 861 }, 862 863 // removes all but the selected one 864 removeAll () { 865 const O = this; 866 const optionList = O.E.find('option'); 867 868 for (let x = (optionList.length - 1); x >= 0; x--) { 869 if (optionList[x].selected !== true) { 870 O.remove(x); 871 } 872 } 873 874 }, 875 876 877 find (val) { 878 const O = this; 879 const optionList = O.E.find('option'); 880 for (const x in optionList) { 881 if (optionList[x].value === val) { 882 return +x; 883 } 884 } 885 886 return -1; 887 888 }, 889 890 //## Select an item at a given index. 891 selectItem (i) { this.toggSel(true, i); }, 892 893 //## UnSelect an iten at a given index. 894 unSelectItem (i) { this.toggSel(false, i); }, 895 896 //## Select all items of the select. 897 selectAll () { this.toggSelAll(true); }, 898 899 //## UnSelect all items of the select. 900 unSelectAll () { this.toggSelAll(false); }, 901 902 //## Disable an iten at a given index. 903 disableItem (i) { this.toggDis(true, i); }, 904 905 //## Removes disabled an iten at a given index. 906 enableItem (i) { this.toggDis(false, i); }, 907 908 //## New simple methods as getter and setter are not working fine in ie8-
909 //## variable to check state of control if enabled or disabled. 910 enabled: true, 911 //## Enables the control 912 enable () { return this.toggSumo(false); }, 913 914 //## Disables the control 915 disable () { return this.toggSumo(true); }, 916 917 918 init () { 919 const O = this; 920 O.createElems(); 921 O.setText(); 922 O.E.trigger('sumo:initialized', O); 923 return O; 924 } 925 926 }; 927 928 selObj.sumo.init(); 929 }); 930 931 return ret.length === 1 ? ret[0] : ret; 932 }; 933 934 935});
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.