1/*! 2 * pickadate.js v3.6.2, 2019/03/19 3 * By Amsul, http://amsul.ca 4 * Hosted on http://amsul.github.io/pickadate.js 5 * Licensed under MIT 6 */ 7 8(function ( factory ) { 9 10 // AMD. 11 if ( typeof define == 'function' && define.amd ) 12 define( 'picker', ['jquery'], factory ) 13 14 // Node.js/browserify. 15 else if ( typeof exports == 'object' ) 16 module.exports = factory( require('jquery') ) 17 18 // Browser globals. 19 else this.Picker = factory( jQuery ) 20 21}(function( $ ) { 22 23var $window = $( window ) 24var $document = $( document ) 25var $html = $( document.documentElement ) 26var supportsTransitions = document.documentElement.style.transition != null 27 28 29/** 30 * The picker constructor that creates a blank picker. 31 */ 32function PickerConstructor( ELEMENT, NAME, COMPONENT, OPTIONS ) { 33 34 // If thereâs no element, return the picker constructor. 35 if ( !ELEMENT ) return PickerConstructor 36 37 38 var 39 IS_DEFAULT_THEME = false, 40 41 42 // The state of the picker. 43 STATE = { 44 id: ELEMENT.id || 'P' + Math.abs( ~~(Math.random() * new Date()) ) 45 }, 46 47 48 // Merge the defaults and options passed. 49 SETTINGS = COMPONENT ? $.extend( true, {}, COMPONENT.defaults, OPTIONS ) : OPTIONS || {}, 50 51 52 // Merge the default classes with the settings classes. 53 CLASSES = $.extend( {}, PickerConstructor.klasses(), SETTINGS.klass ), 54 55 56 // The element node wrapper into a jQuery object. 57 $ELEMENT = $( ELEMENT ), 58 59 60 // Pseudo picker constructor. 61 PickerInstance = function() { 62 return this.start() 63 }, 64 65 66 // The picker prototype. 67 P = PickerInstance.prototype = { 68 69 constructor: PickerInstance, 70 71 $node: $ELEMENT, 72 73 74 /** 75 * Initialize everything 76 */ 77 start: function() { 78 79 // If itâs already started, do nothing. 80 if ( STATE && STATE.start ) return P 81 82 83 // Update the picker states. 84 STATE.methods = {} 85 STATE.start = true 86 STATE.open = false 87 STATE.type = ELEMENT.type 88 89 90 // Confirm focus state, convert into text input to remove UA stylings, 91 // and set as readonly to prevent keyboard popup. 92 ELEMENT.autofocus = ELEMENT == getActiveElement() 93 ELEMENT.readOnly = !SETTINGS.editable 94 ELEMENT.id = ELEMENT.id || STATE.id 95 if ( ELEMENT.type != 'text' ) { 96 ELEMENT.type = 'text' 97 } 98 99 100 // Create a new picker component with the settings. 101 P.component = new COMPONENT(P, SETTINGS) 102 103 104 // Create the picker root and then prepare it. 105 P.$root = $( '<div class="' + CLASSES.picker + '" id="' + ELEMENT.id + '_root" />' ) 106 prepareElementRoot() 107 108 109 // Create the picker holder and then prepare it. 110 P.$holder = $( createWrappedComponent() ).appendTo( P.$root ) 111 prepareElementHolder() 112 113 114 // If thereâs a format for the hidden input element, create the element. 115 if ( SETTINGS.formatSubmit ) { 116 prepareElementHidden() 117 } 118 119 120 // Prepare the input element. 121 prepareElement() 122 123 124 // Insert the hidden input as specified in the settings. 125 if ( SETTINGS.containerHidden ) $( SETTINGS.containerHidden ).append( P._hidden ) 126 else $ELEMENT.after( P._hidden ) 127 128 129 // Insert the root as specified in the settings. 130 if ( SETTINGS.container ) $( SETTINGS.container ).append( P.$root ) 131 else $ELEMENT.after( P.$root ) 132 133 134 // Bind the default component and settings events. 135 P.on({ 136 start: P.component.onStart, 137 render: P.component.onRender, 138 stop: P.component.onStop, 139 open: P.component.onOpen, 140 close: P.component.onClose, 141 set: P.component.onSet 142 }).on({ 143 start: SETTINGS.onStart, 144 render: SETTINGS.onRender, 145 stop: SETTINGS.onStop, 146 open: SETTINGS.onOpen, 147 close: SETTINGS.onClose, 148 set: SETTINGS.onSet 149 }) 150 151 152 // Once weâre all set, check the theme in use. 153 IS_DEFAULT_THEME = isUsingDefaultTheme( P.$holder[0] ) 154 155 156 // If the element has autofocus, open the picker. 157 if ( ELEMENT.autofocus ) { 158 P.open() 159 } 160 161 162 // Trigger queued the âstartâ and ârenderâ events. 163 return P.trigger( 'start' ).trigger( 'render' ) 164 }, //start 165 166 167 /**
168 * Render a new picker 169 */ 170 render: function( entireComponent ) { 171 172 // Insert a new component holder in the root or box. 173 if ( entireComponent ) { 174 P.$holder = $( createWrappedComponent() ) 175 prepareElementHolder() 176 P.$root.html( P.$holder ) 177 } 178 else P.$root.find( '.' + CLASSES.box ).html( P.component.nodes( STATE.open ) ) 179 180 // Trigger the queued ârenderâ events. 181 return P.trigger( 'render' ) 182 }, //render 183 184 185 /** 186 * Destroy everything 187 */ 188 stop: function() { 189 190 // If itâs already stopped, do nothing. 191 if ( !STATE.start ) return P 192 193 // Then close the picker. 194 P.close() 195 196 // Remove the hidden field. 197 if ( P._hidden ) { 198 P._hidden.parentNode.removeChild( P._hidden ) 199 } 200 201 // Remove the root. 202 P.$root.remove() 203 204 // Remove the input class, remove the stored data, and unbind 205 // the events (after a tick for IE - see `P.close`). 206 $ELEMENT.removeClass( CLASSES.input ).removeData( NAME ) 207 setTimeout( function() { 208 $ELEMENT.off( '.' + STATE.id ) 209 }, 0) 210 211 // Restore the element state 212 ELEMENT.type = STATE.type 213 ELEMENT.readOnly = false 214 215 // Trigger the queued âstopâ events. 216 P.trigger( 'stop' ) 217 218 // Reset the picker states. 219 STATE.methods = {} 220 STATE.start = false 221 222 return P 223 }, //stop 224 225 226 /** 227 * Open up the picker 228 */ 229 open: function( dontGiveFocus ) { 230 231 // If itâs already open, do nothing. 232 if ( STATE.open ) return P 233 234 // Add the âactiveâ class. 235 $ELEMENT.addClass( CLASSES.active ) 236 aria( ELEMENT, 'expanded', true ) 237 238 // * A Firefox bug, when `html` has `overflow:hidden`, results in 239 // killing transitions :(. So add the âopenedâ state on the next tick. 240 // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=625289 241 setTimeout( function() { 242 243 // Add the âopenedâ class to the picker root. 244 P.$root.addClass( CLASSES.opened ) 245 aria( P.$root[0], 'hidden', false ) 246 247 }, 0 ) 248 249 // If we have to give focus, bind the element and doc events. 250 if ( dontGiveFocus !== false ) { 251 252 // Set it as open. 253 STATE.open = true 254 255 // Prevent the page from scrolling. 256 if ( IS_DEFAULT_THEME ) { 257 $('body'). 258 css( 'overflow', 'hidden' ). 259 css( 'padding-right', '+=' + getScrollbarWidth() ) 260 } 261 262 // Pass focus to the root elementâs jQuery object. 263 focusPickerOnceOpened() 264 265 // Bind the document events. 266 $document.on( 'click.' + STATE.id + ' focusin.' + STATE.id, function( event ) { 267 268 var target = getRealEventTarget( event, ELEMENT ) 269 270 // If the target of the event is not the element, close the picker picker. 271 // * Donât worry about clicks or focusins on the root because those donât bubble up. 272 // Also, for Firefox, a click on an `option` element bubbles up directly 273 // to the doc. So make sure the target wasn't the doc. 274 // * In Firefox stopPropagation() doesnât prevent right-click events from bubbling, 275 // which causes the picker to unexpectedly close when right-clicking it. So make 276 // sure the event wasnât a right-click. 277 // * In Chrome 62 and up, password autofill causes a simulated focusin event which 278 // closes the picker. 279 if ( ! event.isSimulated && target != ELEMENT && target != document && event.which != 3 ) { 280 281 // If the target was the holder that c
281overs the screen, 282 // keep the element focused to maintain tabindex. 283 P.close( target === P.$holder[0] ) 284 } 285 286 }).on( 'keydown.' + STATE.id, function( event ) { 287 288 var 289 // Get the keycode. 290 keycode = event.keyCode, 291 292 // Translate that to a selection change. 293 keycodeToMove = P.component.key[ keycode ], 294 295 // Grab the target. 296 target = getRealEventTarget( event, ELEMENT ) 297 298 299 // On escape, close the picker and give focus. 300 if ( keycode == 27 ) { 301 P.close( true ) 302 } 303 304 305 // Check if there is a key movement or âenterâ keypress on the element. 306 else if ( target == P.$holder[0] && ( keycodeToMove || keycode == 13 ) ) { 307 308 // Prevent the default action to stop page movement. 309 event.preventDefault() 310 311 // Trigger the key movement action. 312 if ( keycodeToMove ) { 313 PickerConstructor._.trigger( P.component.key.go, P, [ PickerConstructor._.trigger( keycodeToMove ) ] ) 314 } 315 316 // On âenterâ, if the highlighted item isnât disabled, set the value and close. 317 else if ( !P.$root.find( '.' + CLASSES.highlighted ).hasClass( CLASSES.disabled ) ) { 318 P.set( 'select', P.component.item.highlight ) 319 if ( SETTINGS.closeOnSelect ) { 320 P.close( true ) 321 } 322 } 323 } 324 325 326 // If the target is within the root and âenterâ is pressed, 327 // prevent the default action and trigger a click on the target instead. 328 else if ( $.contains( P.$root[0], target ) && keycode == 13 ) { 329 event.preventDefault() 330 target.click() 331 } 332 }) 333 } 334 335 // Trigger the queued âopenâ events. 336 return P.trigger( 'open' ) 337 }, //open 338 339 340 /** 341 * Close the picker 342 */ 343 close: function( giveFocus ) { 344 345 // If we need to give focus, do it before changing states. 346 if ( giveFocus ) { 347 if ( SETTINGS.editable ) { 348 ELEMENT.focus() 349 } 350 else { 351 // ....ah yes! It wouldâve been incomplete without a crazy workaround for IE :| 352 // The focus is triggered *after* the close has completed - causing it 353 // to open again. So unbind and rebind the event at the next tick. 354 P.$holder.off( 'focus.toOpen' ).focus() 355 setTimeout( function() { 356 P.$holder.on( 'focus.toOpen', handleFocusToOpenEvent ) 357 }, 0 ) 358 } 359 } 360 361 // Remove the âactiveâ class. 362 $ELEMENT.removeClass( CLASSES.active ) 363 aria( ELEMENT, 'expanded', false ) 364 365 // * A Firefox bug, when `html` has `overflow:hidden`, results in 366 // killing transitions :(. So remove the âopenedâ state on the next tick. 367 // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=625289 368 setTimeout( function() { 369 370 // Remove the âopenedâ and âfocusedâ class from the picker root. 371 P.$root.removeClass( CLASSES.opened + ' ' + CLASSES.focused ) 372 aria( P.$root[0], 'hidden', true ) 373 374 }, 0 ) 375 376 // If itâs already closed, do nothing more. 377 if ( !STATE.open ) return P 378 379 // Set it as closed. 380 STATE.open = false 381 382 // Allow the page to scroll. 383 if ( IS_DEFAULT_THEME ) { 384 $('body'). 385 css( 'overflow', '' ). 386 css( 'padding-right', '-=' + getScrollbarWidth() ) 387 } 388 389 // Unbind the document events. 390 $document.off( '.' + STATE.id ) 391 392 // Trigger the queued âcloseâ events. 393 return P.trigger( 'close' ) 394 }, //close 395 396 397 /** 398 * Clear the values 399 */ 400 clear: function( options ) { 401 return P.set( 'clear', null, options ) 402 }, //clear 403 404 405 /** 406 * Set something 407 */ 408 set: function( thing, value, options ) { 409 410 var thingItem, thingValue, 411 thingIsObject = $.isPlainObject( thing ), 412 thingObject = thingIsObject ? thing : {} 413 414 // Make sure we have usable options. 415 options = thingIsObject && $.isPlainObject( value ) ? value : options || {} 416 417 if ( thing ) { 418 419 // If the thing isnât an object, make it one. 420 if ( !thingIsObject ) { 421 thingObject[ thing ] = value 422 } 423 424 // Go through the things of items to set. 425 for ( thingItem in thingObject ) { 426 427 // Grab the value of the thing. 428 thingValue = thingObject[ thingItem ] 429 430 // First, if the item exists and thereâs a value, set it. 431 if ( thingItem in P.component.item ) { 432 if ( thingValue === undefined ) thingValue = null 433 P.component.set( thingItem, thingValue, options ) 434 } 435 436 // Then, check to update the element value and broadcast a change. 437 if ( ( thingItem == 'select' || thingItem == 'clear' ) && SETTINGS.updateInput ) { 438 $ELEMENT. 439 val( thingItem == 'clear' ? '' : P.get( thingItem, SETTINGS.format ) ). 440 trigger( 'change' ) 441 } 442 } 443 444 // Render a new picker. 445 P.render() 446 } 447 448 // When the method isnât muted, trigger queued âsetâ events and pass the `thingObject`. 449 return options.muted ? P : P.trigger( 'set', thingObject ) 450 }, //set 451 452 453 /** 454 * Get something 455 */ 456 get: function( thing, format ) { 457 458 // Make sure thereâs something to get. 459 thing = thing || 'value' 460 461 // If a picker state exists, return that. 462 if ( STATE[ thing ] != null ) { 463 return STATE[ thing ] 464 } 465 466 // Return the submission value, if that. 467 if ( thing == 'valueSubmit' ) { 468 if ( P._hidden ) { 469 return P._hidden.value 470 } 471 thing = 'value' 472 } 473 474 // Return the value, if that. 475 if ( thing == 'value' ) { 476 return ELEMENT.value 477 } 478 479 // Check if a component item exists, return that. 480 if ( thing in P.component.item ) { 481 if ( typeof format == 'string' ) { 482 var thingValue = P.component.get( thing ) 483 return thingValue ? 484 PickerConstructor._.trigger( 485 P.component.formats.toString, 486 P.component, 487 [ format, thingValue ] 488 ) : '' 489 } 490 return P.component.get( thing ) 491 } 492 }, //get 493 494 495 496 /** 497 * Bind events on the things. 498 */ 499 on: function( thing, method, internal ) { 500 501 var thingName, thingMethod, 502 thingIsObject = $.isPlainObject( thing ), 503 thingObject = thingIsObject ? thing : {} 504 505 if ( thing ) { 506 507 // If the thing isnât an object, make it one. 508 if ( !thingIsObject ) { 509 thingObject[ thing ] = method 510 } 511 512 // Go through the things to bind to. 513 for ( thingName in thingObject ) { 514 515 // Grab the method of the thing. 516 thingMethod = thingObject[ thingName ] 517 518 // If it was an internal binding, prefix it. 519 if ( internal ) { 520 thingName = '_' + thingName 521 } 522 523 // Make sure the thing methods collection exists. 524 STATE.methods[ thingName ] = STATE.methods[ thingName ] || [] 525 526 // Add the method to the relative method collection. 527 STATE.methods[ thingName ].push( thingMethod ) 528 } 529 } 530 531 return P 532 }, //on 533 534 535 536 /** 537 * Unbind events on the things. 538 */ 539 off: function() { 540 var i, thingName, 541 names = arguments; 542 for ( i = 0, namesCount = names.length; i < namesCount; i += 1 ) { 543 thingName = names[i] 544 if ( thingName in STATE.methods ) { 545 delete STATE.methods[thingName] 546 } 547 } 548 return P 549 }, 550 551 552 /** 553 * Fire off method events. 554 */ 555 trigger: function( name, data ) { 556 var _trigger = function( name ) { 557 var methodList = STATE.methods[ name ] 558 if ( methodList ) { 559 methodList.map( function( method ) { 560 PickerConstructor._.trigger( method, P, [ data ] ) 561 }) 562 } 563 } 564 _trigger( '_' + name ) 565 _trigger( name ) 566 return P 567 }
567 //trigger 568 } //PickerInstance.prototype 569 570 571 /** 572 * Wrap the picker holder components together. 573 */ 574 function createWrappedComponent() { 575 576 // Create a picker wrapper holder 577 return PickerConstructor._.node( 'div', 578 579 // Create a picker wrapper node 580 PickerConstructor._.node( 'div', 581 582 // Create a picker frame 583 PickerConstructor._.node( 'div', 584 585 // Create a picker box node 586 PickerConstructor._.node( 'div', 587 588 // Create the components nodes. 589 P.component.nodes( STATE.open ), 590 591 // The picker box class 592 CLASSES.box 593 ), 594 595 // Picker wrap class 596 CLASSES.wrap 597 ), 598 599 // Picker frame class 600 CLASSES.frame 601 ), 602 603 // Picker holder class 604 CLASSES.holder, 605 606 'tabindex="-1"' 607 ) //endreturn 608 } //createWrappedComponent 609 610 /** 611 * Prepare the input element with all bindings. 612 */ 613 function prepareElement() { 614 615 $ELEMENT. 616 617 // Store the picker data by component name. 618 data(NAME, P). 619 620 // Add the âinputâ class name. 621 addClass(CLASSES.input). 622 623 // If thereâs a `data-value`, update the value of the element. 624 val( $ELEMENT.data('value') ? 625 P.get('select', SETTINGS.format) : 626 ELEMENT.value 627 ). 628 629 // On focus/click, open the picker. 630 on( 'focus.' + STATE.id + ' click.' + STATE.id, 631 debounce(function(event) { 632 event.preventDefault() 633 P.open() 634 }, 100)) 635 636 // Only bind keydown events if the element isnât editable. 637 if ( !SETTINGS.editable ) { 638 639 $ELEMENT. 640 641 // Handle keyboard event based on the picker being opened or not. 642 on( 'keydown.' + STATE.id, handleKeydownEvent ) 643 } 644 645 646 // Update the aria attributes. 647 aria(ELEMENT, { 648 haspopup: true, 649 expanded: false, 650 readonly: false, 651 owns: ELEMENT.id + '_root' 652 }) 653 } 654 655 656 /** 657 * Prepare the root picker element with all bindings. 658 */ 659 function prepareElementRoot() { 660 aria( P.$root[0], 'hidden', true ) 661 } 662 663 664 /** 665 * Prepare the holder picker element with all bindings. 666 */ 667 function prepareElementHolder() { 668 669 P.$holder. 670 671 on({ 672 673 // For iOS8. 674 keydown: handleKeydownEvent, 675 676 'focus.toOpen': handleFocusToOpenEvent, 677 678 blur: function() { 679 // Remove the âtargetâ class. 680 $ELEMENT.removeClass( CLASSES.target ) 681 }, 682 683 // When something within the holder is focused, stop from bubbling 684 // to the doc and remove the âfocusedâ state from the root. 685 focusin: function( event ) { 686 P.$root.removeClass( CLASSES.focused ) 687 event.stopPropagation() 688 }, 689 690 // When something within the holder is clicked, stop it 691 // from bubbling to the doc. 692 'mousedown click': function( event ) { 693 694 var target = getRealEventTarget( event, ELEMENT ) 695 696 // Make sure the target isnât the root holder so it can bubble up. 697 if ( target != P.$holder[0] ) { 698 699 event.stopPropagation() 700 701 // * For mousedown events, cancel the default action in order to 702 // prevent cases where focus is shifted onto external elements 703 // when using things like jQuery mobile or MagnificPopup (ref: #249 & #120). 704 // Also, for Firefox, donât prevent action on the `option` element. 705 if ( event.type == 'mousedown' && !$( target ).is( 'input, select, textarea, button, option' )) { 706 707 event.preventDefault() 708 709 // Re-focus onto the holder so that users can click away 710 // from elements focused within the picker. 711 P.$holder.eq(0).focus() 712 } 713 } 714 } 715 716 }). 717 718 // If thereâs a click on an actionable element, carry out the actions.
719 on( 'click', '[data-pick], [data-nav], [data-clear], [data-close]', function() { 720 721 var $target = $( this ), 722 targetData = $target.data(), 723 targetDisabled = $target.hasClass( CLASSES.navDisabled ) || $target.hasClass( CLASSES.disabled ), 724 725 // * For IE, non-focusable elements can be active elements as well 726 // (http://stackoverflow.com/a/2684561). 727 activeElement = getActiveElement() 728 activeElement = activeElement && ( (activeElement.type || activeElement.href ) ? activeElement : null); 729 730 // If itâs disabled or nothing inside is actively focused, re-focus the element. 731 if ( targetDisabled || activeElement && !$.contains( P.$root[0], activeElement ) ) { 732 P.$holder.eq(0).focus() 733 } 734 735 // If something is superficially changed, update the `highlight` based on the `nav`. 736 if ( !targetDisabled && targetData.nav ) { 737 P.set( 'highlight', P.component.item.highlight, { nav: targetData.nav } ) 738 } 739 740 // If something is picked, set `select` then close with focus. 741 else if ( !targetDisabled && 'pick' in targetData ) { 742 P.set( 'select', targetData.pick ) 743 if ( SETTINGS.closeOnSelect ) { 744 P.close( true ) 745 } 746 } 747 748 // If a âclearâ button is pressed, empty the values and close with focus. 749 else if ( targetData.clear ) { 750 P.clear() 751 if ( SETTINGS.closeOnClear ) { 752 P.close( true ) 753 } 754 } 755 756 else if ( targetData.close ) { 757 P.close( true ) 758 } 759 760 }) //P.$holder 761 762 } 763 764 765 /** 766 * Prepare the hidden input element along with all bindings. 767 */ 768 function prepareElementHidden() { 769 770 var name 771 772 if ( SETTINGS.hiddenName === true ) { 773 name = ELEMENT.name 774 ELEMENT.name = '' 775 } 776 else { 777 name = [ 778 typeof SETTINGS.hiddenPrefix == 'string' ? SETTINGS.hiddenPrefix : '', 779 typeof SETTINGS.hiddenSuffix == 'string' ? SETTINGS.hiddenSuffix : '_submit' 780 ] 781 name = name[0] + ELEMENT.name + name[1] 782 } 783 784 P._hidden = $( 785 '<input ' + 786 'type=hidden ' + 787 788 // Create the name using the original inputâs with a prefix and suffix. 789 'name="' + name + '"' + 790 791 // If the element has a value, set the hidden value as well. 792 ( 793 $ELEMENT.data('value') || ELEMENT.value ? 794 ' value="' + P.get('select', SETTINGS.formatSubmit) + '"' : 795 '' 796 ) + 797 '>' 798 )[0] 799 800 $ELEMENT. 801 802 // If the value changes, update the hidden input with the correct format. 803 on('change.' + STATE.id, function() { 804 P._hidden.value = ELEMENT.value ? 805 P.get('select', SETTINGS.formatSubmit) : 806 '' 807 }) 808 } 809 810 811 // Wait for transitions to end before focusing the holder. Otherwise, while 812 // using the `container` option, the view jumps to the container. 813 function focusPickerOnceOpened() { 814 815 if (IS_DEFAULT_THEME && supportsTransitions) { 816 P.$holder.find('.' + CLASSES.frame).one('transitionend', function() { 817 P.$holder.eq(0).focus() 818 }) 819 } 820 else { 821 setTimeout(function() { 822 P.$holder.eq(0).focus() 823 }, 0) 824 } 825 } 826 827 828 function handleFocusToOpenEvent(event) { 829 830 // Stop the event from propagating to the doc. 831 event.stopPropagation() 832 833 // Add the âtargetâ class. 834 $ELEMENT.addClass( CLASSES.target ) 835 836 // Add the âfocusedâ class to the root. 837 P.$root.addClass( CLASSES.focused ) 838 839 // And then finally open the picker. 840 P.open() 841 } 842 843 844 // For iOS8. 845 function handleKeydownEvent( event ) { 846 847 var keycode = event.keyCode, 848 849 // Check if one of the delete keys was pressed. 850 isKeycodeDelete = /^(8|46)$/.test(keycode) 851 852 // For some reason IE clears the input value on âescapeâ. 853 if ( keycode == 27 ) { 854 P.close( true ) 855 return false 856 } 857 858 // Check if `space` or `delete` was pressed or the picker is closed with a key movement. 859 if ( keycode == 32 || isKeycodeDelete || !STATE.open && P.component.key[keycode] ) { 860
861 // Prevent it from moving the page and bubbling to doc. 862 event.preventDefault() 863 event.stopPropagation() 864 865 // If `delete` was pressed, clear the values and close the picker. 866 // Otherwise open the picker. 867 if ( isKeycodeDelete ) { P.clear().close() } 868 else { P.open() } 869 } 870 } 871 872 873 // Return a new picker instance. 874 return new PickerInstance() 875} //PickerConstructor 876 877 878 879/** 880 * The default classes and prefix to use for the HTML classes. 881 */ 882PickerConstructor.klasses = function( prefix ) { 883 prefix = prefix || 'picker' 884 return { 885 886 picker: prefix, 887 opened: prefix + '--opened', 888 focused: prefix + '--focused', 889 890 input: prefix + '__input', 891 active: prefix + '__input--active', 892 target: prefix + '__input--target', 893 894 holder: prefix + '__holder', 895 896 frame: prefix + '__frame', 897 wrap: prefix + '__wrap', 898 899 box: prefix + '__box' 900 } 901} //PickerConstructor.klasses 902 903 904 905/** 906 * Check if the default theme is being used. 907 */ 908function isUsingDefaultTheme( element ) { 909 910 var theme, 911 prop = 'position' 912 913 // For IE. 914 if ( element.currentStyle ) { 915 theme = element.currentStyle[prop] 916 } 917 918 // For normal browsers. 919 else if ( window.getComputedStyle ) { 920 theme = getComputedStyle( element )[prop] 921 } 922 923 return theme == 'fixed' 924} 925 926 927 928/** 929 * Get the width of the browserâs scrollbar. 930 * Taken from: https://github.com/VodkaBears/Remodal/blob/master/src/jquery.remodal.js 931 */ 932function getScrollbarWidth() { 933 934 if ( $html.height() <= $window.height() ) { 935 return 0 936 } 937 938 var $outer = $( '<div style="visibility:hidden;width:100px" />' ). 939 appendTo( 'body' ) 940 941 // Get the width without scrollbars. 942 var widthWithoutScroll = $outer[0].offsetWidth 943 944 // Force adding scrollbars. 945 $outer.css( 'overflow', 'scroll' ) 946 947 // Add the inner div. 948 var $inner = $( '<div style="width:100%" />' ).appendTo( $outer ) 949 950 // Get the width with scrollbars. 951 var widthWithScroll = $inner[0].offsetWidth 952 953 // Remove the divs. 954 $outer.remove() 955 956 // Return the difference between the widths. 957 return widthWithoutScroll - widthWithScroll 958} 959 960 961 962/** 963 * Get the target element from the event. 964 * If ELEMENT is supplied and present in the event path (ELEMENT is ancestor of the target), 965 * returns ELEMENT instead 966 */ 967function getRealEventTarget( event, ELEMENT ) { 968 969 var path = [] 970 971 if ( event.path ) { 972 path = event.path 973 } 974 975 if ( event.originalEvent && event.originalEvent.path ) { 976 path = event.originalEvent.path 977 } 978 979 if ( path && path.length > 0 ) { 980 if ( ELEMENT && path.indexOf( ELEMENT ) >= 0 ) { 981 return ELEMENT 982 } else { 983 return path[0] 984 } 985 } 986 987 return event.target 988} 989 990// taken from https://davidwalsh.name/javascript-debounce-function 991function debounce(func, wait, immediate) { 992 var timeout; 993 return function() { 994 var context = this, args = arguments; 995 var later = function() { 996 timeout = null; 997 if (!immediate) func.apply(context, args); 998 }; 999 var callNow = immediate && !timeout; 1000 clearTimeout(timeout); 1001 timeout = setTimeout(later, wait); 1002 if (callNow) func.apply(context, args); 1003 }; 1004} 1005 1006/** 1007 * PickerConstructor helper methods. 1008 */ 1009PickerConstructor._ = { 1010 1011 /** 1012 * Create a group of nodes. Expects: 1013 * ` 1014 { 1015 min: {Integer}, 1016 max: {Integer}, 1017 i: {Integer}, 1018 node: {String}, 1019 item: {Function} 1020 } 1021 * ` 1022 */ 1023 group: function( groupObject ) { 1024 1025 var 1026 // Scope for the looped object 1027 loopObjectScope, 1028 1029 // Create the nodes list 1030 nodesList = '', 1031 1032 // The counter starts from the `min` 1033 counter = PickerConstructor._.trigger( groupObject.min, groupObject ) 1034 1035 1036 // Loop from the `min` to `max`, incrementing by `i` 1037 for ( ; counter <= PickerConstructor._.trigger( groupObject.max, groupObject, [ counter ] ); counter += groupObject.i ) { 1038 1039 // Trigger the `item` function within scope of the object 1040 loopObjectScope = PickerConstructor._.trigger( groupObject.item, groupObject, [ counter ] ) 1041 1042 // Splice the subgroup and create nodes out of the sub nodes 1043 nodesList += PickerConstructor._.node( 1044 groupObject.node, 1045 loopObjectScope[ 0 ], // the node 1046 loopObjectScope[ 1 ], // the classes 1047 loopObjectScope[ 2 ] // the attributes 1048 ) 1049 } 1050 1051 // Return the list of nodes 1052 return nodesList 1053 }, //group 1054 1055 1056 /** 1057 * Create a dom node string 1058 */ 1059 node: function( wrapper, item, klass, attribute ) { 1060 1061 // If the item is false-y, just return an empty string 1062 if ( !item ) return '' 1063 1064 // If the item is an array, do a join 1065 item = $.isArray( item ) ? item.join( '' ) : item 1066 1067 // Check for the class 1068 klass = klass ? ' class="' + klass + '"' : '' 1069 1070 // Check for any attributes 1071 attribute = attribute ? ' ' + attribute : '' 1072 1073 // Return the wrapped item 1074 return '<' + wrapper + klass + attribute + '>' + item + '</' + wrapper + '>' 1075 }, //node 1076 1077 1078 /** 1079 * Lead numbers below 10 with a zero. 1080 */ 1081 lead: function( number ) { 1082 return ( number < 10 ? '0': '' ) + number 1083 }, 1084 1085 1086 /** 1087 * Trigger a function otherwise return the value. 1088 */ 1089 trigger: function( callback, scope, args ) { 1090 return typeof callback == 'function' ? callback.apply( scope, args || [] ) : callback 1091 }, 1092 1093 1094 /** 1095 * If the second character is a digit, length is 2 otherwise 1. 1096 */ 1097 digits: function( string ) { 1098 return ( /\d/ ).test( string[ 1 ] ) ? 2 : 1 1099 }, 1100 1101 1102 /** 1103 * Tell if something is a date object. 1104 */ 1105 isDate: function( value ) { 1106 return {}.toString.call( value ).indexOf( 'Date' ) > -1 && this.isInteger( value.getDate() ) 1107 }, 1108 1109 1110 /** 1111 * Tell if something is an integer. 1112 */ 1113 isInteger: function( value ) { 1114 return {}.toString.call( value ).indexOf( 'Number' ) > -1 && value % 1 === 0 1115 }, 1116 1117 1118 /** 1119 * Create ARIA attribute strings. 1120 */ 1121 ariaAttr: ariaAttr 1122} //PickerConstructor._ 1123 1124 1125 1126/** 1127 * Extend the picker with a component and defaults. 1128 */ 1129PickerConstructor.extend = function( name, Component ) { 1130 1131 // Extend jQuery. 1132 $.fn[ name ] = function( options, action ) { 1133 1134 // Grab the component data. 1135 var componentData = this.data( name ) 1136 1137 // If the picker is requested, return the data object. 1138 if ( options == 'picker' ) { 1139 return componentData 1140 } 1141 1142 // If the component data exists and `options` is a string, carry out the action. 1143 if ( componentData && typeof options == 'string' ) { 1144 return PickerConstructor._.trigger( componentData[ options ], componentData, [ action ] ) 1145 } 1146 1147 // Otherwise go through each matched element and if the component 1148 // doesnât exist, create a new picker using `this` element 1149 // and merging the defaults and options with a deep copy. 1150 return this.each( function() { 1151 var $this = $( this ) 1152 if ( !$this.data( name ) ) { 1153 new PickerConstructor( this, name, Component, options ) 1154 } 1155 }) 1156 } 1157 1158 // Set the defaults. 1159 $.fn[ name ].defaults = Component.defaults 1160} //PickerConstructor.extend 1161 1162 1163 1164function aria(element, attribute, value) { 1165 if ( $.isPlainObject(attribute) ) { 1166 for ( var key in attribute ) { 1167 ariaSet(element, key, attribute[key]) 1168 } 1169 } 1170 else { 1171 ariaSet(element, attribute, value) 1172 } 1173} 1174function ariaSet(element, attribute, value) { 1175 element.setAttribute( 1176 (attribute == 'role' ? '' : 'aria-') + attribute, 1177 value 1178 ) 1179} 1180function ariaAttr(attribute, data) { 1181 if ( !$.isPlainObject(attribute) ) { 1182 attribute = { attribute: data } 1183 } 1184 data = '' 1185 for ( var key in attribute ) { 1186 var attr = (key == 'role' ? '' : 'aria-') + key, 1187 attrVal = attribute[key] 1188 data += attrVal == null ? '' : attr + '="' + attribute[key] + '"' 1189 } 1190 return data 1191} 1192 1193// IE8 bug throws an error for activeElements within iframes. 1194function getActiveElement() { 1195 try { 1196 return document.activeElement 1197 } catch ( err ) { } 1198} 1199 1200 1201 1202// Expose the picker constructor. 1203return PickerConstructor 1204 1205 1206}));
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.