1/** //** ----= CLASS mwSelectInput =------------------------------------------------------------------------------\**//** \ 2* 3* Selector input JS model. Supports dropdowns, multiselects, custom item input, inline filtering and adding new items. 4* 5* @package morweb 6* @subpackage system 7* @category model 8* 9\**//** ---------------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 10jQuery.fn.mwSelectInput = function ($options) { 11 12 if ( !this.length ) 13 return; 14 15 // Retrieving or creating model 16 var $obj = this.data('mwSelectInput') || mwSelectInput(this); //.set($options); 17 18 // Storing in element 19 this.data('mwSelectInput', $obj); 20 21 // Done 22 return $obj; 23 24} //FUNC mwSelectInput 25 26function mwSelectInput ( $el, $options ) { return vEventObject(['onInit', 'onChange', 'onFilter', 'onAdd'], { 27 28 dom : { // Contains shortcuts to usable elements 29 30 // Main 31 container : false, // mwInput element 32 input : false, // Main input (hidden) 33 34 // Panels 35 face : false, // Face bar, wrapping around value input and dropdown button 36 filter : false, // Filter input, used to filter items in list 37 body : false, // Main dropdown body (filter and items container) 38 list : false, // Items wrapper 39 40 // Controls 41 iValue : false, // Value input, used to to display selected value or as custom input 42 iSearch : false, // Search input, used to filter items in list 43 btnDown : false, // Dropdown button subcontrol 44 btnAdd : false, // Button for adding custom values 45 btnClear : false, // Button for resetting search filter 46 47 // Misc 48 items : false, // Individual rendered option items 49 50 overlay : false, // Overlay, when used 51 52 }, //dom 53 54 multiselect : false, // Set TRUE to allow multiple values (checkList) 55 multiline : false, // Set TRUE to use as multiline input 56 filter : false, // Set TRUE to use inline filtering 57 custom : false, // Set TRUE to allow custom values (additinal input) 58 noMobile : false, // Set TRUE to skip init when used with mobile device (relies on native experience) 59 60 resizeDelay : 5, // Resize update delay 61 resizeTimout : false, // Stores timout during window resizing 62 63/* ==== SETUP =============================================================================================================== */ 64 65 /** //** ----= set =--------------------------------------------------------------------------------------\**//** \ 66 * 67 * Updates self properties with given values. 68 * 69 * @param MIXED $option - Option to set. Can be data object to setup several properties. 70 * @param MIXED [$value] - Value to set. Not used if object passes as first parameter. 71 * 72 * @return SELF 73 * 74 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 75 set : function ($option, $value) { 76 77 var $this = this; 78 79 // Values can come as object, or single value 80 // Applying using object, for code unification below 81 // Any variable are accepted, to allow custom data storage 82 var $o = {}; 83 84 if ( arguments.length === 1 ) 85 $o = $option; 86 else 87 $o[$option] = $value; 88 89 // ==== Events ==== 90 91 // Processing events, as those should be cleared before extending 92 for ( var $i in $o ) { 93 94 // Skipping non events and non funcitons 95 if ( !this.__events[$i] || !isFunction($o[$i]) ) 96 continue; 97 98 // Setting up event, and removing it from opitons 99 this[$i]($o[$i]); 100 delete($o[$i]); 101 102 } //FOR each opiton 103 104 // ==== Self ==== 105 106 jQuery.extend(this, $o); 107 108 return this; 109 110 }, //FUNC set 111 112/* ==== INIT ================================================================================================================ */ 113 114 /** //** ----= init =--------------------------------------------------------------------------------------\**//** \ 115 * 116 * Initiates payment form. 117 * 118 * @return self 119 * 120 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 121 init : function () { 122 123 var $this = this; 124 125 // ---- Main ---- 126
127 // Saving main input and looking for wrapper 128 $this.dom.input = $el; 129 $this.dom.container = $el.closest('.mwInput'); 130 131 // Few shortcuts 132 var $container = $this.dom.container; 133 var $input = $this.dom.input; 134 135 // Adding required classes to wrapper 136 $this.dom.container.addClass('list'); 137 138 // ---- Flags ---- 139 140 // Reading flags from wrapper and input 141 // ToDo: improove flags management: classes should be guaranteed during render, for CSS. 142 // Need to put back applied flags 143 $this.set({ 144 multiselect : $input.is('[multiple]'), 145 multiline : $container.is('.multiline'), 146 filter : $container.is('.filter'), 147 custom : $container.is('.custom'), 148 noMobile : $container.is('.noMobile'), 149 }); //set 150 151 // ---- Mobile ---- 152 153 // If mobile is used - need to skip render optionally 154 if ( $this.noMobile && isTouchScreen() ) { 155 156 // For mobile version - skipping render, but showing regular select instead 157 // Adding marker 158 $this.dom.container.addClass('isMobile'); 159 160 return; 161 162 } //IF mobile 163 164 // ---- DOM ---- 165 166 // Hiding main select element 167 $this.dom.input.hide(); 168 169 // Rendering face first 170 $this.renderFace(); 171 172 // Then goes body, everything else would be inside 173 $this.renderBody(); 174 175 // ---- Styles ---- 176 177 178 // ---- Events ---- 179 180 $this.initEvents(); 181 182 // Initial update 183 $this.update(); 184 185 return $this; 186 187 }, //FUNC init 188 189 /** //** ----= initEvents =------------------------------------------------------------------------------\**//** \ 190 * 191 * Initializes events. All in one place, for easier management. 192 * 193 * @return SELF 194 * 195 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 196 initEvents : function ( ) { 197 198 // Few shortucts 199 var $this = this; 200 var $input = $this.dom.input; 201 var $container = $this.dom.container; 202 203 // When select updates - it should update items and face 204 $this.dom.input.on('change.mwSelect', function () { 205 206 $this.update(); 207 208 }); //FUNC input.onchange 209 210 // Adding item clicks, listening on body, in case reinit/changes happen in list or items 211 $this.dom.body.on( 'click.mwSelect', '.item', function () { 212 213 // Getting elements 214 var $item = jQuery(this); 215 var $option = $item.data('option'); 216 217 // No need to do anything if already selected option is clicked again 218 // Applicable only for non-multiselect 219 if ( !$this.multiselect && $option.prop('selected') ) 220 return; 221 222 // Updating property only. Attribute will be also updated by updateItems() 223 // Doing this way to ensure that correct attributes are updated on all items 224 $option.prop( 'selected', !$option.prop('selected') ); 225 226 // Triggering change on main input 227 $this.dom.input.trigger('change'); 228 229 }); //FUNC item.onclick 230 231 // Filter executs on key presses, if input available 232 if ( $this.filter ) { 233 234 $this.dom.iSearch.on('keyup.mwSelect', function () { 235 236 // Updating items, this will apply filter 237 $this.update(); 238 239 }); //FUNC input.onchange 240 241 $this.dom.btnClear.on('click.mwSelect', function () { 242 243 // Just clearing filter value and updating items 244 $this.dom.iSearch.val(''); 245 246 // Updating items, this will apply filter 247 $this.update(); 248 249 }); //FUNC input.onchange 250 251 } //IF filter enabled 252 253 // In inline mode - need to show/hide body 254 if ( !$this.multiline ) { 255 256 // Dropdown button always works 257 $this.dom.btnDown.on('click.mwSelect', function () { 258 259 // Showing/hiding depending on state 260 $this.toggleBody(); 261 262 }); //FUNC button.onclick 263 264 // For non-custom inputs - value also toggles body 265 if ( !$this.custom ) 266 // Dropdown button always works 267 $this.dom.iValue.on('click.mwSelect', function () { 268 269 // Showing/hiding depending on state 270 $this.toggleBody(); 271 272 }); //FUNC input.onclick 273 274 275 } //IF inline mode 276 277 }, //FUNC initEvents 278 279/* ==== Render ============================================================================================================== */ 280 281 /** //** ----= renderBody =------------------------------------------------------------------------------\**//** \ 282 * 283 * Renders main body element. 284 * 285 * @return SELF 286 * 287 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 288 renderBody : function ( ) { 289 290 // Few shortucts 291 var $this = this; 292 var $input = $this.dom.input; 293 var $container = $this.dom.container; 294 295 // Marking body as inline if necessary for CSS 296 var $mode = $this.multiline ? 'multiline absoluteFill' : 'mwInput oneline'; 297 $this.dom.body = jQuery('<div class="body '+$mode+'"></div>').appendTo($container); 298 299 // Reset of css would be set on display 300 301 // ---- Children ---- 302
303 // Rendering filter, it goes inside body 304 $this.renderFilter(); 305 306 // Now can render items list 307 $this.renderList(); 308 309 return $this; 310 311 }, //FUNC renderBody 312 313 /** //** ----= renderFace =------------------------------------------------------------------------------\**//** \ 314 * 315 * Renders face panel. Used to display current value and entering custom value for inline mode. 316 * 317 * @return SELF 318 * 319 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 320 renderFace : function ( ) { 321 322 // Few shortucts 323 var $this = this; 324 var $input = $this.dom.input; 325 var $container = $this.dom.container; 326 327 // Adding face controls only for inline input 328 if ( $this.multiline ) 329 return $this; 330 331 // Creating elements as one html chunk, then finding referrences afterwards 332 var $html = ''; 333 334 // Subcontrol button goes first, as it's floating 335 $html = '<div class="subcontrol right icon gray dropdown"></div>'; 336 337 // Input is wrapped in div to behave properly with floated element nearby 338 $html = $html+'<div class="subInput value"><input type="text" class="mw" /></div>'; 339 340 // Finally - entire thing is wrapped into another element 341 $html = '<div class="face">'+$html+'</div>'; 342 343 // Appending entire thing to container 344 jQuery($html).appendTo($container); 345 346 // Looking for individual elements now 347 $this.dom.iValue = $container.find('.subInput.value input'); 348 $this.dom.btnDown = $container.find('.subcontrol.dropdown'); 349 $this.dom.face = $container.find('.face'); 350 351 // If custom input is not used - value is only for display, so making it readonly 352 if ( !$this.custom ) 353 $this.dom.iValue.attr('readonly', 'readonly'); 354 355 return $this; 356 357 }, //FUNC renderFace 358 359 /** //** ----= renderFilter =------------------------------------------------------------------------------\**//** \ 360 * 361 * Renders filter panel. Used to filter items list, and adding custom values for multiselects. 362 * 363 * @return SELF 364 * 365 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 366 renderFilter : function ( ) { 367 368 // Few shortucts 369 var $this = this; 370 var $input = $this.dom.input; 371 var $container = $this.dom.container; 372 373 // Adding filter only if it's allowed 374 if ( !$this.filter ) 375 return $this; 376 377 // Filter is positioned inside body wrapper, to display and hide together with list 378 // Preparing html for filter bar 379 380 // Subcontrols buttons go first, as they're floating 381 var $html = ''; 382 $html += '<div class="subcontrol left icon gray search"></div>'; 383 $html += '<div class="subcontrol right button icon hi plus add"></div>'; 384 $html += '<div class="subcontrol right icon delete clear gray"></div>'; 385 386 // Input is wrapped in div to behave properly with floated element nearby 387 $html = $html+'<div class="subInput search"><input type="text" class="mw" /></div>'; 388 389 // Finally - entire thing is wrapped into another element 390 $html = '<div class="filter">'+$html+'</div>'; 391 392 // Appending entire thing to container 393 jQuery($html).appendTo($this.dom.body); 394 395 // Looking for individual elements now 396 $this.dom.filter = $this.dom.body.find('.filter'); 397 398 $this.dom.iSearch = $this.dom.filter.find('.subInput.search input'); 399 $this.dom.btnAdd = $this.dom.filter.find('.subcontrol.add'); 400 $this.dom.btnClear = $this.dom.filter.find('.subcontrol.clear'); 401 402 return $this; 403 404 }, //FUNC renderFilter 405 406 /** //** ----= renderList =------------------------------------------------------------------------------\**//** \ 407 * 408 * Renders items panel, including individual items. 409 * 410 * @return SELF 411 * 412 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 413 renderList : function ( ) { 414 415 // Few shortucts 416 var $this = this; 417 var $input = $this.dom.input; 418 var $container = $this.dom.container; 419 420 // ---- Wrap ---- 421 422 // Clearing old wrapper if any happen 423 if ( $this.dom.list ) 424 $this.dom.list.remove(); 425 426 // Recreating items wrapper 427 $this.dom.list = jQuery('<div class="list"></div>').appendTo( $this.dom.body ); 428 429 // ---- Items ---- 430 431 // Resetting items collection 432 $this.dom.items = jQuery([]); 433 434 // Looping through options and generating items 435 // ToDo: support grouping, custom icons, columns and more 436 $input.find('option').each( function () { 437 438 var $option = jQuery(this); 439 440 // Rendering item into body 441 var $item = $this.renderItem($option).appendTo( $this.dom.list ); 442 443 // And storing it in self for future reuse 444 $this.dom.items = $this.dom.items.add($item); 445 446 }); //FOR each item 447
448 return $this; 449 450 }, //FUNC renderList 451 452 /** //** ----= renderItem =------------------------------------------------------------------------------\**//** \ 453 * 454 * Renders single item. 455 * 456 * @return SELF 457 * 458 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 459 renderItem : function ( $option ) { 460 461 // Few shortucts 462 var $this = this; 463 464 // ---- Text ---- 465 466 var $text = $option.html(); 467 468 // ---- Image ---- 469 470 // Preparing image if any 471 var $image = $option.attr('data-image'); 472 var $imageHtml = ''; 473 474 if ( $image ) { 475 476 $imageHtml = '<div class="image" style="background-image: url(\''+$image+'\')"></div>'; 477 478 } //IF image provided 479 480 // ---- Counter ---- 481 482 // Adding counter 483 var $count = $option.attr('data-count'); 484 var $countHtml = ''; 485 486 if ( $count ) { 487 488 $countHtml = '<div class="count">'+$count+'</div>'; 489 490 } //IF count provided 491 492 // ---- Item ---- 493 494 // Creating item 495 var $item = jQuery('<div class="item icon hi left">'+$imageHtml+$countHtml+$text+'</div>'); 496 497 // Setting up links 498 $option.data('item', $item); 499 $item.data('option', $option); 500 501 return $item; 502 503 }, //FUNC renderItem 504 505 /** //** ----= renderOverlay =------------------------------------------------------------------------------\**//** \ 506 * 507 * Renders overlay. 508 * 509 * @return SELF 510 * 511 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 512 renderOverlay : function ( ) { 513 514 // Few shortucts 515 var $this = this; 516 517 // Adding overlay to page 518 $this.dom.overlay = jQuery('<div class="mwInputOverlay mwInput list"></div>').appendTo('body'); 519 520 // Marking body with class as flag 521 // And Moving body inside overlay 522 $this.dom.body 523 // .addClass('show') 524 .appendTo($this.dom.overlay); 525 526 // Click on overlay hides stuff 527 $this.dom.overlay.on('click', function ($e) { 528 529 $this.hideBody(); 530 531 $e.stopPropagation(); 532 533 }); //FUNC overlay.click 534 535 // Preventing click on body for closing (only for multiselects) 536 537 if ( $this.multiselect ) 538 $this.dom.body.on('click', function ($e) { 539 540 $e.stopPropagation(); 541 542 }); //FUNC body.click 543 544 // Filter never closes anyway 545 if ( $this.filter ) 546 $this.dom.filter.on('click', function ($e) { 547 548 $e.stopPropagation(); 549 550 }); //FUNC body.click 551 552 // ---- Resize ---- 553 554 // If body resizes for some readon - need to update selector position 555 // Doing this only for inline mode 556 557 // Initiating window resize after small delay 558 // to skip initial browser resizie events 559 setTimeout( function () { 560 561 // Updating dimensions on resize 562 jQuery(window).on('resize.mwSelect', function ($e) { 563 564 // Using timeout during resize, to reduce updates count 565 if ( $this.resizeTimout ) 566 clearTimeout($this.resizeTimout); 567 568 $this.resizeTimout = setTimeout( function () { 569 570 $this.updatePosition(); 571 572 }, $this.resizeDelay); 573 574 }); //window.onResize 575 576 }, 50); 577 578 return $this; 579 580 }, //FUNC renderOverlay 581 582/* ==== Display ============================================================================================================= */ 583 584 /** //** ----= showBody =--------------------------------------------------------------------------------------\**//** \ 585 * 586 * Displays body, recalculating positions. 587 * 588 * @return SELF 589 * 590 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 591 showBody : function ( ) { 592 593 // Few shortucts 594 var $this = this; 595 596 // Creating overlay, this will also move body inside 597 $this.renderOverlay(); 598 599 // Displaying overlay 600 $this.dom.overlay.show(); 601 602 setTimeout( function () { 603 604 // While it adjusts - can now reposition body 605 // At this point - everything is rendered and have dimensions 606 $this.updatePosition(); 607 608 // Finally - executing fade/slide animation 609 $this.dom.body.addClass('show') 610 $this.dom.overlay.addClass('show'); 611 612 }, 1); 613 614 }, //FUNC showBody 615 616 /** //** ----= hideBody =--------------------------------------------------------------------------------------\**//** \ 617 * 618 * Hides body. 619 * 620 * @return SELF 621 * 622 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 623 hideBody : function ( ) { 624 625 // Few shortucts 626 var $this = this; 627 628 // Hiding overlay and unflagging body 629 $this.dom.overlay.removeClass('show'); 630 $this.dom.body.removeClass('show'); 631 632 // Allowing it to play animation with timeout 633 setTimeout( function () { 634 635 // Putting body back, where it belongs :) 636 // This will also hide it. Inline body is display:none outside overlay 637 $this.dom.body.appendTo( $this.dom.container ); 638 639 // Removing overlay from DOM now 640 $this.dom.overlay.remove(); 641 642 // Clearing resizing tracking 643 jQuery(window).off('resize.mwSelect'); 644 645 }, 200); 646 647 }, //FUNC hideBody 648
649 /** //** ----= toggleBody =------------------------------------------------------------------------------\**//** \ 650 * 651 * Toggles body visibility, depending on current state. 652 * 653 * @return SELF 654 * 655 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 656 toggleBody : function ( ) { 657 658 // Few shortucts 659 var $this = this; 660 661 // Just looking at body state 662 if ( $this.dom.body.is('.show') ) { 663 $this.hideBody(); 664 } //IF visible 665 else { 666 $this.showBody(); 667 } //IF hidden 668 669 }, //FUNC toggleBody 670 671/* ==== HELPERS ============================================================================================================= */ 672 673 /** //** ----= getPosition =-------------------------------------------------------------------------------\**//** \ 674 * 675 * Returns panel position relative to screen. 676 * 677 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 678 getPosition : function () { 679 680 var $this = this; 681 var $el = $this.dom.container; 682 683 var $offs = $el.offset(); 684 var $sTop = jQuery(window).scrollTop(); 685 var $sLeft = jQuery(window).scrollLeft(); 686 687 // Recalculating coords based on scroll position 688 $offs.top = $offs.top - $sTop; 689 $offs.left = $offs.left - $sLeft; 690 691 return $offs; 692 693 }, //FUNC getPosition 694 695 /** //** ----= updatePosition =-------------------------------------------------------------------------------\**//** \ 696 * 697 * Updates body position against element 698 * 699 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 700 updatePosition : function () { 701 702 var $this = this; 703 704 // Not doing anything for non-inline mode and if not visible 705 if ( $this.multiline ) 706 return; 707 708 // Few shortcuts 709 var $input = $this.dom.container; 710 var $body = $this.dom.body; 711 712 // Getting input coordinates and screen size 713 var $pos = $this.getPosition(); 714 var $screen = screenSize(); 715 716 // Calculating margi as % of screen height 717 // Carrying only about height, since that's what is mostly positioned 718 var $margin = $screen.height * 0.05; 719 720 // Getting real body height and calculating max allowed 721 // For this - clearing height first 722 $this.dom.list.css('max-height', ''); 723 724 var $height = $body.height(); 725 var $limit = $height; 726 var $max = $screen.height - ($margin * 2); 727 728 // Calculating real height limit (should be set on list inside body) 729 // Clearing if not necessary anymore (screen resize) 730 if ( $height > $max ) { 731 732 $limit = $max; 733 734 // Accounting for filter if present 735 $this.dom.list.css('max-height', $limit - ($this.filter ? $this.dom.filter.outerHeight() : 0)); 736 737 } //IF too big 738 739 // Calculating new top based on real height and limits 740 // Starting from middle of input 741 var $top = ($pos.top + ($this.dom.container.height() / 2)) - ($limit / 2); 742 743 // Correcting top: it should be lower than margin 744 if ( $top < $margin ) 745 $top = $margin; 746 747 // But also can't be too low (top+height higher than margin) 748 if ( $top + $limit > $screen.height - $margin ) 749 $top = $screen.height - $margin - $limit; 750 751 // Adjusting body 752 // Slightly adjusting sizes, to do not mess with borders recalculations 753 // ToDo: read borders from skin 754 $this.dom.body.css({ 755 width : $this.dom.container.width() - 2, 756 left : $pos.left + 1, 757 top : $top, //$pos.top + ($this.dom.container.height() / 2), 758 }); //$css 759 760 }, //FUNC updatePosition 761 762 /** //** ----= update =--------------------------------------------------------------------------------------\**//** \ 763 * 764 * Updates item states based on current selector state. Uses filtering if available. 765 * Additionally updats filter states, and face if available. 766 * 767 * @return SELF 768 * 769 \**//** -------------------------------------------------------------------= by Mr.V!T @ Morad Media Inc. =----/** //**/ 770 update : function ( ) { 771 772 // Few shortucts 773 var $this = this; 774 775 // Reading/updating filter 776 var $filter = ''; 777 778 if ( $this.filter ) { 779 780 $filter = $this.dom.iSearch.val(); 781 782 // Showing/hiding clear button 783 if ( $filter ) 784 $this.dom.btnClear.show(); 785 else 786 $this.dom.btnClear.hide(); 787 788 } //IF filter used 789 790 // Updating face when applicable 791 // For this - collecting selected values, and concatenating them into lavel afterwards 792 var $val = []; 793 794 // Just looping through items list and setting selected class 795 $this.dom.items.each( function () { 796 797 var $item = jQuery(this); 798 var $option = $item.data('option'); 799 800 // Checking if matching filter, or just showing them all 801 if ( $filter ) { 802 803 // Using regex seaerch for case insensitivity 804 // ToDo: escape filter value 805 if ( $option.html().search( new RegExp($filter, 'i') ) == -1 ) 806 $item.hide(); 807 else 808 $item.show(); 809 810 } //If filter applied 811 else { 812 813 // Just showing, this makes sure we display all items if filter was just cleared 814 $item.show(); 815 816 } //IF filter not applied or just cleared 817 818 // Marking item as selected 819 if ( $option.prop('selected') ) 820 $item.addClass('selected'); 821 else 822 $item.removeClass('selected'); 823 824 // Collecting selected values for face update 825 if ( $option.prop('selected') ) { 826 827 $val.push( $option.text().trim() ); 828 829 } //IF found selected 830 /*/ 831 // Additionally - setting selected atribute on option, for whoever needs this 832 // But this is supported only on multiselects 833 // This appears to be quite slow for obvious reasons, so skipping it for now as noone really needs it :) 834 if ( !$this.dom.input.is('[multiple]') ) 835 return; 836 837 if ( $option.prop('selected') ) 838 $option.attr('selected', 'selected'); 839 else 840 $option.removeAttr('selected', ''); 841 /**/ 842 }); //FOR each item 843 844 // If nothing found - using first option to display something (that's what would be submitted in the end) 845 // Only for non multiline selectors though 846 if ( !$this.multiselect && isEmpty($val) && $this.dom.items.length ) { 847 $val.push( $this.dom.items.first().data('option').text().trim() ); 848 } //IF no values 849 850 // Now can apply value 851 if ( !$this.multiline ) 852 $this.dom.iValue.val( $val.join(', ') || '- Please select one or multiple -' ); 853 854 }, //FUNC update 855 856}).init()} //CONSTRUCTOR mwCodeInput
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.