vendor: 529,681 bytes, lines 1-19070
1/*! jQuery UI - v1.13.3 - 2024-04-26 2* https://jqueryui.com 3* Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-patch.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js 4* Copyright OpenJS Foundation and other contributors; Licensed MIT */ 5 6( function( factory ) { 7 "use strict"; 8 9 if ( typeof define === "function" && define.amd ) { 10 11 // AMD. Register as an anonymous module. 12 define( [ "jquery" ], factory ); 13 } else { 14 15 // Browser globals 16 factory( jQuery ); 17 } 18} )( function( $ ) { 19"use strict"; 20 21$.ui = $.ui || {}; 22 23var version = $.ui.version = "1.13.3"; 24 25 26/*! 27 * jQuery UI Widget 1.13.3 28 * https://jqueryui.com 29 * 30 * Copyright OpenJS Foundation and other contributors 31 * Released under the MIT license. 32 * https://jquery.org/license 33 */ 34 35//>>label: Widget 36//>>group: Core 37//>>description: Provides a factory for creating stateful widgets with a common API. 38//>>docs: https://api.jqueryui.com/jQuery.widget/ 39//>>demos: https://jqueryui.com/widget/ 40 41 42var widgetUuid = 0; 43var widgetHasOwnProperty = Array.prototype.hasOwnProperty; 44var widgetSlice = Array.prototype.slice; 45 46$.cleanData = ( function( orig ) { 47 return function( elems ) { 48 var events, elem, i; 49 for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) { 50 51 // Only trigger remove when necessary to save time 52 events = $._data( elem, "events" ); 53 if ( events && events.remove ) { 54 $( elem ).triggerHandler( "remove" ); 55 } 56 } 57 orig( elems ); 58 }; 59} )( $.cleanData ); 60 61$.widget = function( name, base, prototype ) { 62 var existingConstructor, constructor, basePrototype; 63 64 // ProxiedPrototype allows the provided prototype to remain unmodified 65 // so that it can be used as a mixin for multiple widgets (#8876) 66 var proxiedPrototype = {}; 67 68 var namespace = name.split( "." )[ 0 ]; 69 name = name.split( "." )[ 1 ]; 70 var fullName = namespace + "-" + name; 71 72 if ( !prototype ) { 73 prototype = base; 74 base = $.Widget; 75 } 76 77 if ( Array.isArray( prototype ) ) { 78 prototype = $.extend.apply( null, [ {} ].concat( prototype ) ); 79 } 80 81 // Create selector for plugin 82 $.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) { 83 return !!$.data( elem, fullName ); 84 }; 85 86 $[ namespace ] = $[ namespace ] || {}; 87 existingConstructor = $[ namespace ][ name ]; 88 constructor = $[ namespace ][ name ] = function( options, element ) { 89 90 // Allow instantiation without "new" keyword 91 if ( !this || !this._createWidget ) { 92 return new constructor( options, element ); 93 } 94 95 // Allow instantiation without initializing for simple inheritance 96 // must use "new" keyword (the code above always passes args) 97 if ( arguments.length ) { 98 this._createWidget( options, element ); 99 } 100 }; 101 102 // Extend with the existing constructor to carry over any static properties 103 $.extend( constructor, existingConstructor, { 104 version: prototype.version, 105 106 // Copy the object used to create the prototype in case we need to 107 // redefine the widget later 108 _proto: $.extend( {}, prototype ), 109 110 // Track widgets that inherit from this widget in case this widget is 111 // redefined after a widget inherits from it 112 _childConstructors: [] 113 } ); 114 115 basePrototype = new base(); 116 117 // We need to make the options hash a property directly on the new instance 118 // otherwise we'll modify the options hash on the prototype that we're 119 // inheriting from 120 basePrototype.options = $.widget.extend( {}, basePrototype.options ); 121 $.each( prototype, function( prop, value ) { 122 if ( typeof value !== "function" ) { 123 proxiedPrototype[ prop ] = value; 124 return; 125 } 126 proxiedPrototype[ prop ] = ( function() { 127 function _super() { 128 return base.prototype[ prop ].apply( this, arguments ); 129 } 130 131 function _superApply( args ) { 132 return base.prototype[ prop ].apply( this, args ); 133 } 134 135 return function() { 136 var __super = this._super; 137 var __superApply = this._superApply; 138 var returnValue; 139 140 this._super = _super; 141 this._superApply = _superApply; 142 143 returnValue = value.apply( this, arguments ); 144 145 this._super = __super; 146 this._superApply = __superApply; 147 148 return returnValue; 149 }; 150 } )(); 151 } ); 152 constructor.prototype = $.widget.extend( basePrototype, { 153 154 // TODO: remove support for widgetEventPrefix 155 // always use the name + a colon as the prefix, e.g., draggable:start 156 // don't prefix for widgets that aren't DOM-based 157 widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name 158 }, proxiedPrototype, { 159 constructor: constructor, 160 namespace: namespace, 161 widgetName: name, 162 widgetFullName: fullName 163 } ); 164 165 // If this widget is being redefined then we need to find all widgets that 166 // are inheriting from it and redefine all of them so that they inherit from 167 // the new version of this widget. We're essentially trying to replace one 168 // level in the prototype chain. 169 if ( existingConstructor ) { 170 $.each( existingConstructor._childConstructors, function( i, child ) { 171 var childPrototype = child.prototype; 172 173 // Redefine the child widget using the same prototype that was 174 // originally used, but inherit from the new version of the base 175 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, 176 child._proto ); 177 } ); 178 179 // Remove the list of existing child constructors from the old constructor 180 // so the old child constructors can be garbage collected 181 delete existingConstructor._childConstructors; 182 } else { 183 base._childConstructors.push( constructor ); 184 } 185 186 $.widget.bridge( name, constructor ); 187 188 return constructor; 189}; 190 191$.widget.extend = function( target ) { 192 var input = widgetSlice.call( arguments, 1 ); 193 var inputIndex = 0; 194 var inputLength = input.length; 195 var key; 196 var value; 197 198 for ( ; inputIndex < inputLength; inputIndex++ ) { 199 for ( key in input[ inputIndex ] ) { 200 value = input[ inputIndex ][ key ]; 201 if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) { 202 203 // Clone objects 204 if ( $.isPlainObject( value ) ) { 205 target[ key ] = $.isPlainObject( target[ key ] ) ? 206 $.widget.extend( {}, target[ key ], value ) : 207 208 // Don't extend strings, arrays, etc. with objects 209 $.widget.extend( {}, value ); 210 211 // Copy everything else by reference 212 } else { 213 target[ key ] = value; 214 } 215 } 216 } 217 } 218 return target; 219}; 220 221$.widget.bridge = function( name, object ) { 222 var fullName = object.prototype.widgetFullName || name; 223 $.fn[ name ] = function( options ) { 224 var isMethodCall = typeof options === "string"; 225 var args = widgetSlice.call( arguments, 1 ); 226 var returnValue = this; 227 228 if ( isMethodCall ) { 229 230 // If this is an empty collection, we need to have the instance method 231 // return undefined instead of the jQuery instance 232 if ( !this.length && options === "instance" ) { 233 returnValue = undefined; 234 } else { 235 this.each( function() { 236 var methodValue; 237 var instance = $.data( this, fullName ); 238 239 if ( options === "instance" ) { 240 returnValue = instance; 241 return false; 242 } 243 244 if ( !instance ) { 245 return $.error( "cannot call methods on " + name + 246 " prior to initialization; " + 247 "attempted to call method '" + options + "'" ); 248 } 249 250 if ( typeof instance[ options ] !== "function" || 251 options.charAt( 0 ) === "_" ) { 252 return $.error( "no such method '" + options + "' for " + name + 253 " widget instance" ); 254 } 255 256 methodValue = instance[ options ].apply( instance, args ); 257 258 if ( methodValue !== instance && methodValue !== undefined ) { 259 returnValue = methodValue && methodValue.jquery ? 260 returnValue.pushStack( methodValue.get() ) : 261 methodValue; 262 return false; 263 } 264 } ); 265 } 266 } else { 267 268 // Allow multiple hashes to be passed on init 269 if ( args.length ) { 270 options = $.widget.extend.apply( null, [ options ].concat( args ) ); 271 } 272 273 this.each( function() { 274 var instance = $.data( this, fullName ); 275 if ( instance ) { 276 instance.option( options || {} ); 277 if ( instance._init ) { 278 instance._init(); 279 } 280 } else { 281 $.data( this, fullName, new object( options, this ) ); 282 } 283 } ); 284 } 285 286 return returnValue; 287 }; 288}; 289 290$.Widget = function( /* options, element */ ) {}; 291$.Widget._childConstructors = []; 292 293$.Widget.prototype = { 294 widgetName: "widget", 295 widgetEventPrefix: "", 296 defaultElement: "<div>", 297 298 options: { 299 classes: {}, 300 disabled: false, 301 302 // Callbacks 303 create: null 304 }, 305 306 _createWidget: function( options, element ) { 307 element = $( element || this.defaultElement || this )[ 0 ]; 308 this.element = $( element ); 309 this.uuid = widgetUuid++; 310 this.eventNamespace = "." + this.widgetName + this.uuid; 311 312 this.bindings = $(); 313 this.hoverable = $(); 314 this.focusable = $(); 315 this.classesElementLookup = {}; 316 317 if ( element !== this ) { 318 $.data( element, this.widgetFullName, this ); 319 this._on( true, this.element, { 320 remove: function( event ) { 321 if ( event.target === element ) { 322 this.destroy(); 323 } 324 } 325 } ); 326 this.document = $( element.style ? 327 328 // Element within the document 329 element.ownerDocument : 330 331 // Element is window or document 332 element.document || element ); 333 this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow ); 334 } 335 336 this.options = $.widget.extend( {}, 337 this.options, 338 this._getCreateOptions(), 339 options ); 340 341 this._create(); 342 343 if ( this.options.disabled ) { 344 this._setOptionDisabled( this.options.disabled ); 345 } 346 347 this._trigger( "create", null, this._getCreateEventData() ); 348 this._init(); 349 }, 350 351 _getCreateOptions: function() { 352 return {}; 353 }, 354 355 _getCreateEventData: $.noop, 356 357 _create: $.noop, 358 359 _init: $.noop, 360 361 destroy: function() { 362 var that = this; 363 364 this._destroy(); 365 $.each( this.classesElementLookup, function( key, value ) { 366 that._removeClass( value, key ); 367 } ); 368 369 // We can probably remove the unbind calls in 2.0 370 // all event bindings should go through this._on() 371 this.element 372 .off( this.eventNamespace ) 373 .removeData( this.widgetFullName ); 374 this.widget() 375 .off( this.eventNamespace ) 376 .removeAttr( "aria-disabled" ); 377 378 // Clean up events and states 379 this.bindings.off( this.eventNamespace ); 380 }, 381 382 _destroy: $.noop, 383 384 widget: function() { 385 return this.element; 386 }, 387 388 option: function( key, value ) { 389 var options = key; 390 var parts; 391 var curOption; 392 var i; 393 394 if ( arguments.length === 0 ) { 395 396 // Don't return a reference to the internal hash 397 return $.widget.extend( {}, this.options ); 398 } 399 400 if ( typeof key === "string" ) { 401 402 // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } 403 options = {}; 404 parts = key.split( "." ); 405 key = parts.shift(); 406 if ( parts.length ) { 407 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); 408 for ( i = 0; i < parts.length - 1; i++ ) { 409 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; 410 curOption = curOption[ parts[ i ] ]; 411 } 412 key = parts.pop(); 413 if ( arguments.length === 1 ) { 414 return curOption[ key ] === undefined ? null : curOption[ key ]; 415 } 416 curOption[ key ] = value; 417 } else { 418 if ( arguments.length === 1 ) { 419 return this.options[ key ] === undefined ? null : this.options[ key ]; 420 } 421 options[ key ] = value; 422 } 423 } 424 425 this._setOptions( options ); 426 427 return this; 428 }, 429 430 _setOptions: function( options ) { 431 var key; 432 433 for ( key in options ) { 434 this._setOption( key, options[ key ] ); 435 } 436 437 return this; 438 }, 439 440 _setOption: function( key, value ) { 441 if ( key === "classes" ) { 442 this._setOptionClasses( value ); 443 } 444 445 this.options[ key ] = value; 446 447 if ( key === "disabled" ) { 448 this._setOptionDisabled( value ); 449 } 450 451 return this; 452 }, 453 454 _setOptionClasses: function( value ) { 455 var classKey, elements, currentElements; 456 457 for ( classKey in value ) { 458 currentElements = this.classesElementLookup[ classKey ]; 459 if ( value[ classKey ] === this.options.classes[ classKey ] || 460 !currentElements || 461 !currentElements.length ) { 462 continue; 463 } 464 465 // We are doing this to create a new jQuery object because the _removeClass() call 466 // on the next line is going to destroy the reference to the current elements being 467 // tracked. We need to save a copy of this collection so that we can add the new classes 468 // below. 469 elements = $( currentElements.get() ); 470 this._removeClass( currentElements, classKey ); 471 472 // We don't use _addClass() here, because that uses this.options.classes 473 // for generating the string of classes. We want to use the value passed in from 474 // _setOption(), this is the new value of the classes option which was passed to 475 // _setOption(). We pass this value directly to _classes(). 476 elements.addClass( this._classes( { 477 element: elements, 478 keys: classKey, 479 classes: value, 480 add: true 481 } ) ); 482 } 483 }, 484 485 _setOptionDisabled: function( value ) { 486 this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value ); 487 488 // If the widget is becoming disabled, then nothing is interactive 489 if ( value ) { 490 this._removeClass( this.hoverable, null, "ui-state-hover" ); 491 this._removeClass( this.focusable, null, "ui-state-focus" ); 492 } 493 }, 494 495 enable: function() { 496 return this._setOptions( { disabled: false } ); 497 }, 498 499 disable: function() { 500 return this._setOptions( { disabled: true } ); 501 }, 502 503 _classes: function( options ) { 504 var full = []; 505 var that = this; 506 507 options = $.extend( { 508 element: this.element, 509 classes: this.options.classes || {} 510 }, options ); 511 512 function bindRemoveEvent() { 513 var nodesToBind = []; 514 515 options.element.each( function( _, element ) { 516 var isTracked = $.map( that.classesElementLookup, function( elements ) { 517 return elements; 518 } ) 519 .some( function( elements ) { 520 return elements.is( element ); 521 } ); 522 523 if ( !isTracked ) { 524 nodesToBind.push( element ); 525 } 526 } ); 527 528 that._on( $( nodesToBind ), { 529 remove: "_untrackClassesElement" 530 } ); 531 } 532 533 function processClassString( classes, checkOption ) { 534 var current, i; 535 for ( i = 0; i < classes.length; i++ ) { 536 current = that.classesElementLookup[ classes[ i ] ] || $(); 537 if ( options.add ) { 538 bindRemoveEvent(); 539 current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) ); 540 } else { 541 current = $( current.not( options.element ).get() ); 542 } 543 that.classesElementLookup[ classes[ i ] ] = current; 544 full.push( classes[ i ] ); 545 if ( checkOption && options.classes[ classes[ i ] ] ) { 546 full.push( options.classes[ classes[ i ] ] ); 547 } 548 } 549 } 550 551 if ( options.keys ) { 552 processClassString( options.keys.match( /\S+/g ) || [], true ); 553 } 554 if ( options.extra ) { 555 processClassString( options.extra.match( /\S+/g ) || [] ); 556 } 557 558 return full.join( " " ); 559 }, 560 561 _untrackClassesElement: function( event ) { 562 var that = this; 563 $.each( that.classesElementLookup, function( key, value ) { 564 if ( $.inArray( event.target, value ) !== -1 ) { 565 that.classesElementLookup[ key ] = $( value.not( event.target ).get() ); 566 } 567 } ); 568 569 this._off( $( event.target ) ); 570 }, 571 572 _removeClass: function( element, keys, extra ) { 573 return this._toggleClass( element, keys, extra, false ); 574 }, 575 576 _addClass: function( element, keys, extra ) { 577 return this._toggleClass( element, keys, extra, true ); 578 }, 579 580 _toggleClass: function( element, keys, extra, add ) { 581 add = ( typeof add === "boolean" ) ? add : extra; 582 var shift = ( typeof element === "string" || element === null ), 583 options = { 584 extra: shift ? keys : extra, 585 keys: shift ? element : keys, 586 element: shift ? this.element : element, 587 add: add 588 }; 589 options.element.toggleClass( this._classes( options ), add ); 590 return this; 591 }, 592 593 _on: function( suppressDisabledCheck, element, handlers ) { 594 var delegateElement; 595 var instance = this; 596 597 // No suppressDisabledCheck flag, shuffle arguments 598 if ( typeof suppressDisabledCheck !== "boolean" ) { 599 handlers = element; 600 element = suppressDisabledCheck; 601 suppressDisabledCheck = false; 602 } 603 604 // No element argument, shuffle and use this.element 605 if ( !handlers ) { 606 handlers = element; 607 element = this.element; 608 delegateElement = this.widget(); 609 } else { 610 element = delegateElement = $( element ); 611 this.bindings = this.bindings.add( element ); 612 } 613 614 $.each( handlers, function( event, handler ) { 615 function handlerProxy() { 616 617 // Allow widgets to customize the disabled handling 618 // - disabled as an array instead of boolean 619 // - disabled class as method for disabling individual parts 620 if ( !suppressDisabledCheck && 621 ( instance.options.disabled === true || 622 $( this ).hasClass( "ui-state-disabled" ) ) ) { 623 return; 624 } 625 return ( typeof handler === "string" ? instance[ handler ] : handler ) 626 .apply( instance, arguments ); 627 } 628 629 // Copy the guid so direct unbinding works 630 if ( typeof handler !== "string" ) { 631 handlerProxy.guid = handler.guid = 632 handler.guid || handlerProxy.guid || $.guid++; 633 } 634 635 var match = event.match( /^([\w:-]*)\s*(.*)$/ ); 636 var eventName = match[ 1 ] + instance.eventNamespace; 637 var selector = match[ 2 ]; 638 639 if ( selector ) { 640 delegateElement.on( eventName, selector, handlerProxy ); 641 } else { 642 element.on( eventName, handlerProxy ); 643 } 644 } ); 645 }, 646 647 _off: function( element, eventName ) { 648 eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) + 649 this.eventNamespace; 650 element.off( eventName ); 651 652 // Clear the stack to avoid memory leaks (#10056) 653 this.bindings = $( this.bindings.not( element ).get() ); 654 this.focusable = $( this.focusable.not( element ).get() ); 655 this.hoverable = $( this.hoverable.not( element ).get() ); 656 }, 657 658 _delay: function( handler, delay ) { 659 function handlerProxy() { 660 return ( typeof handler === "string" ? instance[ handler ] : handler ) 661 .apply( instance, arguments ); 662 } 663 var instance = this; 664 return setTimeout( handlerProxy, delay || 0 ); 665 }, 666 667 _hoverable: function( element ) { 668 this.hoverable = this.hoverable.add( element ); 669 this._on( element, { 670 mouseenter: function( event ) { 671 this._addClass( $( event.currentTarget ), null, "ui-state-hover" ); 672 }, 673 mouseleave: function( event ) { 674 this._removeClass( $( event.currentTarget ), null, "ui-state-hover" ); 675 } 676 } ); 677 }, 678 679 _focusable: function( element ) { 680 this.focusable = this.focusable.add( element ); 681 this._on( element, { 682 focusin: function( event ) { 683 this._addClass( $( event.currentTarget ), null, "ui-state-focus" ); 684 }, 685 focusout: function( event ) { 686 this._removeClass( $( event.currentTarget ), null, "ui-state-focus" ); 687 } 688 } ); 689 }, 690 691 _trigger: function( type, event, data ) { 692 var prop, orig; 693 var callback = this.options[ type ]; 694 695 data = data || {}; 696 event = $.Event( event ); 697 event.type = ( type === this.widgetEventPrefix ? 698 type : 699 this.widgetEventPrefix + type ).toLowerCase(); 700 701 // The original event may come from any element 702 // so we need to reset the target on the new event 703 event.target = this.element[ 0 ]; 704 705 // Copy original event properties over to the new event 706 orig = event.originalEvent; 707 if ( orig ) { 708 for ( prop in orig ) { 709 if ( !( prop in event ) ) { 710 event[ prop ] = orig[ prop ]; 711 } 712 } 713 } 714 715 this.element.trigger( event, data ); 716 return !( typeof callback === "function" && 717 callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false || 718 event.isDefaultPrevented() ); 719 } 720}; 721 722$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { 723 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { 724 if ( typeof options === "string" ) { 725 options = { effect: options }; 726 } 727 728 var hasOptions; 729 var effectName = !options ? 730 method : 731 options === true || typeof options === "number" ? 732 defaultEffect : 733 options.effect || defaultEffect; 734 735 options = options || {}; 736 if ( typeof options === "number" ) { 737 options = { duration: options }; 738 } else if ( options === true ) { 739 options = {}; 740 } 741 742 hasOptions = !$.isEmptyObject( options ); 743 options.complete = callback; 744 745 if ( options.delay ) { 746 element.delay( options.delay ); 747 } 748 749 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { 750 element[ method ]( options ); 751 } else if ( effectName !== method && element[ effectName ] ) { 752 element[ effectName ]( options.duration, options.easing, callback ); 753 } else { 754 element.queue( function( next ) { 755 $( this )[ method ](); 756 if ( callback ) { 757 callback.call( element[ 0 ] ); 758 } 759 next(); 760 } ); 761 } 762 }; 763} ); 764 765var widget = $.widget; 766 767 768/*! 769 * jQuery UI Position 1.13.3 770 * https://jqueryui.com 771 * 772 * Copyright OpenJS Foundation and other contributors 773 * Released under the MIT license. 774 * https://jquery.org/license 775 * 776 * https://api.jqueryui.com/position/ 777 */ 778 779//>>label: Position 780//>>group: Core 781//>>description: Positions elements relative to other elements. 782//>>docs: https://api.jqueryui.com/position/ 783//>>demos: https://jqueryui.com/position/ 784 785 786( function() { 787var cachedScrollbarWidth, 788 max = Math.max, 789 abs = Math.abs, 790 rhorizontal = /left|center|right/, 791 rvertical = /top|center|bottom/, 792 roffset = /[\+\-]\d+(\.[\d]+)?%?/, 793 rposition = /^\w+/, 794 rpercent = /%$/, 795 _position = $.fn.position; 796 797function getOffsets( offsets, width, height ) { 798 return [ 799 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), 800 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) 801 ]; 802} 803 804function parseCss( element, property ) { 805 return parseInt( $.css( element, property ), 10 ) || 0; 806} 807 808function isWindow( obj ) { 809 return obj != null && obj === obj.window; 810} 811 812function getDimensions( elem ) { 813 var raw = elem[ 0 ]; 814 if ( raw.nodeType === 9 ) { 815 return { 816 width: elem.width(), 817 height: elem.height(), 818 offset: { top: 0, left: 0 } 819 }; 820 } 821 if ( isWindow( raw ) ) { 822 return { 823 width: elem.width(), 824 height: elem.height(), 825 offset: { top: elem.scrollTop(), left: elem.scrollLeft() } 826 }; 827 } 828 if ( raw.preventDefault ) { 829 return { 830 width: 0, 831 height: 0, 832 offset: { top: raw.pageY, left: raw.pageX } 833 }; 834 } 835 return { 836 width: elem.outerWidth(), 837 height: elem.outerHeight(), 838 offset: elem.offset() 839 }; 840} 841 842$.position = { 843 scrollbarWidth: function() { 844 if ( cachedScrollbarWidth !== undefined ) { 845 return cachedScrollbarWidth; 846 } 847 var w1, w2, 848 div = $( "<div style=" + 849 "'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" + 850 "<div style='height:300px;width:auto;'></div></div>" ), 851 innerDiv = div.children()[ 0 ]; 852 853 $( "body" ).append( div ); 854 w1 = innerDiv.offsetWidth; 855 div.css( "overflow", "scroll" ); 856 857 w2 = innerDiv.offsetWidth; 858 859 if ( w1 === w2 ) { 860 w2 = div[ 0 ].clientWidth; 861 } 862 863 div.remove(); 864 865 return ( cachedScrollbarWidth = w1 - w2 ); 866 }, 867 getScrollInfo: function( within ) { 868 var overflowX = within.isWindow || within.isDocument ? "" : 869 within.element.css( "overflow-x" ), 870 overflowY = within.isWindow || within.isDocument ? "" : 871 within.element.css( "overflow-y" ), 872 hasOverflowX = overflowX === "scroll" || 873 ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ), 874 hasOverflowY = overflowY === "scroll" || 875 ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight ); 876 return { 877 width: hasOverflowY ? $.position.scrollbarWidth() : 0, 878 height: hasOverflowX ? $.position.scrollbarWidth() : 0 879 }; 880 }, 881 getWithinInfo: function( element ) { 882 var withinElement = $( element || window ), 883 isElemWindow = isWindow( withinElement[ 0 ] ), 884 isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9, 885 hasOffset = !isElemWindow && !isDocument; 886 return { 887 element: withinElement, 888 isWindow: isElemWindow, 889 isDocument: isDocument, 890 offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 }, 891 scrollLeft: withinElement.scrollLeft(), 892 scrollTop: withinElement.scrollTop(), 893 width: withinElement.outerWidth(), 894 height: withinElement.outerHeight() 895 }; 896 } 897}; 898 899$.fn.position = function( options ) { 900 if ( !options || !options.of ) { 901 return _position.apply( this, arguments ); 902 } 903 904 // Make a copy, we don't want to modify arguments 905 options = $.extend( {}, options ); 906 907 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, 908 909 // Make sure string options are treated as CSS selectors 910 target = typeof options.of === "string" ? 911 $( document ).find( options.of ) : 912 $( options.of ), 913 914 within = $.position.getWithinInfo( options.within ), 915 scrollInfo = $.position.getScrollInfo( within ), 916 collision = ( options.collision || "flip" ).split( " " ), 917 offsets = {}; 918 919 dimensions = getDimensions( target ); 920 if ( target[ 0 ].preventDefault ) { 921 922 // Force left top to allow flipping 923 options.at = "left top"; 924 } 925 targetWidth = dimensions.width; 926 targetHeight = dimensions.height; 927 targetOffset = dimensions.offset; 928 929 // Clone to reuse original targetOffset later 930 basePosition = $.extend( {}, targetOffset ); 931 932 // Force my and at to have valid horizontal and vertical positions 933 // if a value is missing or invalid, it will be converted to center 934 $.each( [ "my", "at" ], function() { 935 var pos = ( options[ this ] || "" ).split( " " ), 936 horizontalOffset, 937 verticalOffset; 938 939 if ( pos.length === 1 ) { 940 pos = rhorizontal.test( pos[ 0 ] ) ? 941 pos.concat( [ "center" ] ) : 942 rvertical.test( pos[ 0 ] ) ? 943 [ "center" ].concat( pos ) : 944 [ "center", "center" ]; 945 } 946 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; 947 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; 948 949 // Calculate offsets 950 horizontalOffset = roffset.exec( pos[ 0 ] ); 951 verticalOffset = roffset.exec( pos[ 1 ] ); 952 offsets[ this ] = [ 953 horizontalOffset ? horizontalOffset[ 0 ] : 0, 954 verticalOffset ? verticalOffset[ 0 ] : 0 955 ]; 956 957 // Reduce to just the positions without the offsets 958 options[ this ] = [ 959 rposition.exec( pos[ 0 ] )[ 0 ], 960 rposition.exec( pos[ 1 ] )[ 0 ] 961 ]; 962 } ); 963 964 // Normalize collision option 965 if ( collision.length === 1 ) { 966 collision[ 1 ] = collision[ 0 ]; 967 } 968 969 if ( options.at[ 0 ] === "right" ) { 970 basePosition.left += targetWidth; 971 } else if ( options.at[ 0 ] === "center" ) { 972 basePosition.left += targetWidth / 2; 973 } 974 975 if ( options.at[ 1 ] === "bottom" ) { 976 basePosition.top += targetHeight; 977 } else if ( options.at[ 1 ] === "center" ) { 978 basePosition.top += targetHeight / 2; 979 } 980 981 atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); 982 basePosition.left += atOffset[ 0 ]; 983 basePosition.top += atOffset[ 1 ]; 984 985 return this.each( function() { 986 var collisionPosition, using, 987 elem = $( this ), 988 elemWidth = elem.outerWidth(), 989 elemHeight = elem.outerHeight(), 990 marginLeft = parseCss( this, "marginLeft" ), 991 marginTop = parseCss( this, "marginTop" ), 992 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + 993 scrollInfo.width, 994 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + 995 scrollInfo.height, 996 position = $.extend( {}, basePosition ), 997 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); 998 999 if ( options.my[ 0 ] === "right" ) { 1000 position.left -= elemWidth; 1001 } else if ( options.my[ 0 ] === "center" ) { 1002 position.left -= elemWidth / 2; 1003 } 1004 1005 if ( options.my[ 1 ] === "bottom" ) { 1006 position.top -= elemHeight; 1007 } else if ( options.my[ 1 ] === "center" ) { 1008 position.top -= elemHeight / 2; 1009 } 1010 1011 position.left += myOffset[ 0 ]; 1012 position.top += myOffset[ 1 ]; 1013 1014 collisionPosition = { 1015 marginLeft: marginLeft, 1016 marginTop: marginTop 1017 }; 1018 1019 $.each( [ "left", "top" ], function( i, dir ) { 1020 if ( $.ui.position[ collision[ i ] ] ) { 1021 $.ui.position[ collision[ i ] ][ dir ]( position, { 1022 targetWidth: targetWidth, 1023 targetHeight: targetHeight, 1024 elemWidth: elemWidth, 1025 elemHeight: elemHeight, 1026 collisionPosition: collisionPosition, 1027 collisionWidth: collisionWidth, 1028 collisionHeight: collisionHeight, 1029 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], 1030 my: options.my, 1031 at: options.at, 1032 within: within, 1033 elem: elem 1034 } ); 1035 } 1036 } ); 1037 1038 if ( options.using ) { 1039 1040 // Adds feedback as second argument to using callback, if present 1041 using = function( props ) { 1042 var left = targetOffset.left - position.left, 1043 right = left + targetWidth - elemWidth, 1044 top = targetOffset.top - position.top, 1045 bottom = top + targetHeight - elemHeight, 1046 feedback = { 1047 target: { 1048 element: target, 1049 left: targetOffset.left, 1050 top: targetOffset.top, 1051 width: targetWidth, 1052 height: targetHeight 1053 }, 1054 element: { 1055 element: elem, 1056 left: position.left, 1057 top: position.top, 1058 width: elemWidth, 1059 height: elemHeight 1060 }, 1061 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", 1062 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" 1063 }; 1064 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { 1065 feedback.horizontal = "center"; 1066 } 1067 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { 1068 feedback.vertical = "middle"; 1069 } 1070 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { 1071 feedback.important = "horizontal"; 1072 } else { 1073 feedback.important = "vertical"; 1074 } 1075 options.using.call( this, props, feedback ); 1076 }; 1077 } 1078 1079 elem.offset( $.extend( position, { using: using } ) ); 1080 } ); 1081}; 1082 1083$.ui.position = { 1084 fit: { 1085 left: function( position, data ) { 1086 var within = data.within, 1087 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, 1088 outerWidth = within.width, 1089 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 1090 overLeft = withinOffset - collisionPosLeft, 1091 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, 1092 newOverRight; 1093 1094 // Element is wider than within 1095 if ( data.collisionWidth > outerWidth ) { 1096 1097 // Element is initially over the left side of within 1098 if ( overLeft > 0 && overRight <= 0 ) { 1099 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - 1100 withinOffset; 1101 position.left += overLeft - newOverRight; 1102 1103 // Element is initially over right side of within 1104 } else if ( overRight > 0 && overLeft <= 0 ) { 1105 position.left = withinOffset; 1106 1107 // Element is initially over both left and right sides of within 1108 } else { 1109 if ( overLeft > overRight ) { 1110 position.left = withinOffset + outerWidth - data.collisionWidth; 1111 } else { 1112 position.left = withinOffset; 1113 } 1114 } 1115 1116 // Too far left -> align with left edge 1117 } else if ( overLeft > 0 ) { 1118 position.left += overLeft; 1119 1120 // Too far right -> align with right edge 1121 } else if ( overRight > 0 ) { 1122 position.left -= overRight; 1123 1124 // Adjust based on position and margin 1125 } else { 1126 position.left = max( position.left - collisionPosLeft, position.left ); 1127 } 1128 }, 1129 top: function( position, data ) { 1130 var within = data.within, 1131 withinOffset = within.isWindow ? within.scrollTop : within.offset.top, 1132 outerHeight = data.within.height, 1133 collisionPosTop = position.top - data.collisionPosition.marginTop, 1134 overTop = withinOffset - collisionPosTop, 1135 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, 1136 newOverBottom; 1137 1138 // Element is taller than within 1139 if ( data.collisionHeight > outerHeight ) { 1140 1141 // Element is initially over the top of within 1142 if ( overTop > 0 && overBottom <= 0 ) { 1143 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - 1144 withinOffset; 1145 position.top += overTop - newOverBottom; 1146 1147 // Element is initially over bottom of within 1148 } else if ( overBottom > 0 && overTop <= 0 ) { 1149 position.top = withinOffset; 1150 1151 // Element is initially over both top and bottom of within 1152 } else { 1153 if ( overTop > overBottom ) { 1154 position.top = withinOffset + outerHeight - data.collisionHeight; 1155 } else { 1156 position.top = withinOffset; 1157 } 1158 } 1159 1160 // Too far up -> align with top 1161 } else if ( overTop > 0 ) { 1162 position.top += overTop; 1163 1164 // Too far down -> align with bottom edge 1165 } else if ( overBottom > 0 ) { 1166 position.top -= overBottom; 1167 1168 // Adjust based on position and margin 1169 } else { 1170 position.top = max( position.top - collisionPosTop, position.top ); 1171 } 1172 } 1173 }, 1174 flip: { 1175 left: function( position, data ) { 1176 var within = data.within, 1177 withinOffset = within.offset.left + within.scrollLeft, 1178 outerWidth = within.width, 1179 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, 1180 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 1181 overLeft = collisionPosLeft - offsetLeft, 1182 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, 1183 myOffset = data.my[ 0 ] === "left" ? 1184 -data.elemWidth : 1185 data.my[ 0 ] === "right" ? 1186 data.elemWidth : 1187 0, 1188 atOffset = data.at[ 0 ] === "left" ? 1189 data.targetWidth : 1190 data.at[ 0 ] === "right" ? 1191 -data.targetWidth : 1192 0, 1193 offset = -2 * data.offset[ 0 ], 1194 newOverRight, 1195 newOverLeft; 1196 1197 if ( overLeft < 0 ) { 1198 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - 1199 outerWidth - withinOffset; 1200 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { 1201 position.left += myOffset + atOffset + offset; 1202 } 1203 } else if ( overRight > 0 ) { 1204 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + 1205 atOffset + offset - offsetLeft; 1206 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { 1207 position.left += myOffset + atOffset + offset; 1208 } 1209 } 1210 }, 1211 top: function( position, data ) { 1212 var within = data.within, 1213 withinOffset = within.offset.top + within.scrollTop, 1214 outerHeight = within.height, 1215 offsetTop = within.isWindow ? within.scrollTop : within.offset.top, 1216 collisionPosTop = position.top - data.collisionPosition.marginTop, 1217 overTop = collisionPosTop - offsetTop, 1218 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, 1219 top = data.my[ 1 ] === "top", 1220 myOffset = top ? 1221 -data.elemHeight : 1222 data.my[ 1 ] === "bottom" ? 1223 data.elemHeight : 1224 0, 1225 atOffset = data.at[ 1 ] === "top" ? 1226 data.targetHeight : 1227 data.at[ 1 ] === "bottom" ? 1228 -data.targetHeight : 1229 0, 1230 offset = -2 * data.offset[ 1 ], 1231 newOverTop, 1232 newOverBottom; 1233 if ( overTop < 0 ) { 1234 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - 1235 outerHeight - withinOffset; 1236 if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) { 1237 position.top += myOffset + atOffset + offset; 1238 } 1239 } else if ( overBottom > 0 ) { 1240 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + 1241 offset - offsetTop; 1242 if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) { 1243 position.top += myOffset + atOffset + offset; 1244 } 1245 } 1246 } 1247 }, 1248 flipfit: { 1249 left: function() { 1250 $.ui.position.flip.left.apply( this, arguments ); 1251 $.ui.position.fit.left.apply( this, arguments ); 1252 }, 1253 top: function() { 1254 $.ui.position.flip.top.apply( this, arguments ); 1255 $.ui.position.fit.top.apply( this, arguments ); 1256 } 1257 } 1258}; 1259 1260} )(); 1261 1262var position = $.ui.position; 1263 1264 1265/*! 1266 * jQuery UI :data 1.13.3 1267 * https://jqueryui.com 1268 * 1269 * Copyright OpenJS Foundation and other contributors 1270 * Released under the MIT license. 1271 * https://jquery.org/license 1272 */ 1273 1274//>>label: :data Selector 1275//>>group: Core 1276//>>description: Selects elements which have data stored under the specified key. 1277//>>docs: https://api.jqueryui.com/data-selector/ 1278 1279 1280var data = $.extend( $.expr.pseudos, { 1281 data: $.expr.createPseudo ? 1282 $.expr.createPseudo( function( dataName ) { 1283 return function( elem ) { 1284 return !!$.data( elem, dataName ); 1285 }; 1286 } ) : 1287 1288 // Support: jQuery <1.8 1289 function( elem, i, match ) { 1290 return !!$.data( elem, match[ 3 ] ); 1291 } 1292} ); 1293 1294/*! 1295 * jQuery UI Disable Selection 1.13.3 1296 * https://jqueryui.com 1297 * 1298 * Copyright OpenJS Foundation and other contributors 1299 * Released under the MIT license. 1300 * https://jquery.org/license 1301 */ 1302 1303//>>label: disableSelection 1304//>>group: Core 1305//>>description: Disable selection of text content within the set of matched elements. 1306//>>docs: https://api.jqueryui.com/disableSelection/ 1307 1308// This file is deprecated 1309 1310var disableSelection = $.fn.extend( { 1311 disableSelection: ( function() { 1312 var eventType = "onselectstart" in document.createElement( "div" ) ? 1313 "selectstart" : 1314 "mousedown"; 1315 1316 return function() { 1317 return this.on( eventType + ".ui-disableSelection", function( event ) { 1318 event.preventDefault(); 1319 } ); 1320 }; 1321 } )(), 1322 1323 enableSelection: function() { 1324 return this.off( ".ui-disableSelection" ); 1325 } 1326} ); 1327 1328 1329 1330// Create a local jQuery because jQuery Color relies on it and the 1331// global may not exist with AMD and a custom build (#10199). 1332// This module is a noop if used as a regular AMD module. 1333// eslint-disable-next-line no-unused-vars 1334var jQuery = $; 1335 1336 1337/*! 1338 * jQuery Color Animations v2.2.0 1339 * https://github.com/jquery/jquery-color 1340 * 1341 * Copyright OpenJS Foundation and other contributors 1342 * Released under the MIT license. 1343 * https://jquery.org/license 1344 * 1345 * Date: Sun May 10 09:02:36 2020 +0200 1346 */ 1347 1348 1349 1350 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " + 1351 "borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", 1352 1353 class2type = {}, 1354 toString = class2type.toString, 1355 1356 // plusequals test for += 100 -= 100 1357 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, 1358 1359 // a set of RE's that can match strings and generate color tuples. 1360 stringParsers = [ { 1361 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 1362 parse: function( execResult ) { 1363 return [ 1364 execResult[ 1 ], 1365 execResult[ 2 ], 1366 execResult[ 3 ], 1367 execResult[ 4 ] 1368 ]; 1369 } 1370 }, { 1371 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 1372 parse: function( execResult ) { 1373 return [ 1374 execResult[ 1 ] * 2.55, 1375 execResult[ 2 ] * 2.55, 1376 execResult[ 3 ] * 2.55, 1377 execResult[ 4 ] 1378 ]; 1379 } 1380 }, { 1381 1382 // this regex ignores A-F because it's compared against an already lowercased string 1383 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?/, 1384 parse: function( execResult ) { 1385 return [ 1386 parseInt( execResult[ 1 ], 16 ), 1387 parseInt( execResult[ 2 ], 16 ), 1388 parseInt( execResult[ 3 ], 16 ), 1389 execResult[ 4 ] ? 1390 ( parseInt( execResult[ 4 ], 16 ) / 255 ).toFixed( 2 ) : 1391 1 1392 ]; 1393 } 1394 }, { 1395 1396 // this regex ignores A-F because it's compared against an already lowercased string 1397 re: /#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?/, 1398 parse: function( execResult ) { 1399 return [ 1400 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), 1401 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), 1402 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ), 1403 execResult[ 4 ] ? 1404 ( parseInt( execResult[ 4 ] + execResult[ 4 ], 16 ) / 255 ) 1405 .toFixed( 2 ) : 1406 1 1407 ]; 1408 } 1409 }, { 1410 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 1411 space: "hsla", 1412 parse: function( execResult ) { 1413 return [ 1414 execResult[ 1 ], 1415 execResult[ 2 ] / 100, 1416 execResult[ 3 ] / 100, 1417 execResult[ 4 ] 1418 ]; 1419 } 1420 } ], 1421 1422 // jQuery.Color( ) 1423 color = jQuery.Color = function( color, green, blue, alpha ) { 1424 return new jQuery.Color.fn.parse( color, green, blue, alpha ); 1425 }, 1426 spaces = { 1427 rgba: { 1428 props: { 1429 red: { 1430 idx: 0, 1431 type: "byte" 1432 }, 1433 green: { 1434 idx: 1, 1435 type: "byte" 1436 }, 1437 blue: { 1438 idx: 2, 1439 type: "byte" 1440 } 1441 } 1442 }, 1443 1444 hsla: { 1445 props: { 1446 hue: { 1447 idx: 0, 1448 type: "degrees" 1449 }, 1450 saturation: { 1451 idx: 1, 1452 type: "percent" 1453 }, 1454 lightness: { 1455 idx: 2, 1456 type: "percent" 1457 } 1458 } 1459 } 1460 }, 1461 propTypes = { 1462 "byte": { 1463 floor: true, 1464 max: 255 1465 }, 1466 "percent": { 1467 max: 1 1468 }, 1469 "degrees": { 1470 mod: 360, 1471 floor: true 1472 } 1473 }, 1474 support = color.support = {}, 1475 1476 // element for support tests 1477 supportElem = jQuery( "<p>" )[ 0 ], 1478 1479 // colors = jQuery.Color.names 1480 colors, 1481 1482 // local aliases of functions called often 1483 each = jQuery.each; 1484 1485// determine rgba support immediately 1486supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; 1487support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; 1488 1489// define cache name and alpha properties 1490// for rgba and hsla spaces 1491each( spaces, function( spaceName, space ) { 1492 space.cache = "_" + spaceName; 1493 space.props.alpha = { 1494 idx: 3, 1495 type: "percent", 1496 def: 1 1497 }; 1498} ); 1499 1500// Populate the class2type map 1501jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), 1502 function( _i, name ) { 1503 class2type[ "[object " + name + "]" ] = name.toLowerCase(); 1504 } ); 1505 1506function getType( obj ) { 1507 if ( obj == null ) { 1508 return obj + ""; 1509 } 1510 1511 return typeof obj === "object" ? 1512 class2type[ toString.call( obj ) ] || "object" : 1513 typeof obj; 1514} 1515 1516function clamp( value, prop, allowEmpty ) { 1517 var type = propTypes[ prop.type ] || {}; 1518 1519 if ( value == null ) { 1520 return ( allowEmpty || !prop.def ) ? null : prop.def; 1521 } 1522 1523 // ~~ is an short way of doing floor for positive numbers 1524 value = type.floor ? ~~value : parseFloat( value ); 1525 1526 // IE will pass in empty strings as value for alpha, 1527 // which will hit this case 1528 if ( isNaN( value ) ) { 1529 return prop.def; 1530 } 1531 1532 if ( type.mod ) { 1533 1534 // we add mod before modding to make sure that negatives values 1535 // get converted properly: -10 -> 350 1536 return ( value + type.mod ) % type.mod; 1537 } 1538 1539 // for now all property types without mod have min and max 1540 return Math.min( type.max, Math.max( 0, value ) ); 1541} 1542 1543function stringParse( string ) { 1544 var inst = color(), 1545 rgba = inst._rgba = []; 1546 1547 string = string.toLowerCase(); 1548 1549 each( stringParsers, function( _i, parser ) { 1550 var parsed, 1551 match = parser.re.exec( string ), 1552 values = match && parser.parse( match ), 1553 spaceName = parser.space || "rgba"; 1554 1555 if ( values ) { 1556 parsed = inst[ spaceName ]( values ); 1557 1558 // if this was an rgba parse the assignment might happen twice 1559 // oh well.... 1560 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; 1561 rgba = inst._rgba = parsed._rgba; 1562 1563 // exit each( stringParsers ) here because we matched 1564 return false; 1565 } 1566 } ); 1567 1568 // Found a stringParser that handled it 1569 if ( rgba.length ) { 1570 1571 // if this came from a parsed string, force "transparent" when alpha is 0 1572 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) 1573 if ( rgba.join() === "0,0,0,0" ) { 1574 jQuery.extend( rgba, colors.transparent ); 1575 } 1576 return inst; 1577 } 1578 1579 // named colors 1580 return colors[ string ]; 1581} 1582 1583color.fn = jQuery.extend( color.prototype, { 1584 parse: function( red, green, blue, alpha ) { 1585 if ( red === undefined ) { 1586 this._rgba = [ null, null, null, null ]; 1587 return this; 1588 } 1589 if ( red.jquery || red.nodeType ) { 1590 red = jQuery( red ).css( green ); 1591 green = undefined; 1592 } 1593 1594 var inst = this, 1595 type = getType( red ), 1596 rgba = this._rgba = []; 1597 1598 // more than 1 argument specified - assume ( red, green, blue, alpha ) 1599 if ( green !== undefined ) { 1600 red = [ red, green, blue, alpha ]; 1601 type = "array"; 1602 } 1603 1604 if ( type === "string" ) { 1605 return this.parse( stringParse( red ) || colors._default ); 1606 } 1607 1608 if ( type === "array" ) { 1609 each( spaces.rgba.props, function( _key, prop ) { 1610 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); 1611 } ); 1612 return this; 1613 } 1614 1615 if ( type === "object" ) { 1616 if ( red instanceof color ) { 1617 each( spaces, function( _spaceName, space ) { 1618 if ( red[ space.cache ] ) { 1619 inst[ space.cache ] = red[ space.cache ].slice(); 1620 } 1621 } ); 1622 } else { 1623 each( spaces, function( _spaceName, space ) { 1624 var cache = space.cache; 1625 each( space.props, function( key, prop ) { 1626 1627 // if the cache doesn't exist, and we know how to convert 1628 if ( !inst[ cache ] && space.to ) { 1629 1630 // if the value was null, we don't need to copy it 1631 // if the key was alpha, we don't need to copy it either 1632 if ( key === "alpha" || red[ key ] == null ) { 1633 return; 1634 } 1635 inst[ cache ] = space.to( inst._rgba ); 1636 } 1637 1638 // this is the only case where we allow nulls for ALL properties. 1639 // call clamp with alwaysAllowEmpty 1640 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); 1641 } ); 1642 1643 // everything defined but alpha? 1644 if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { 1645 1646 // use the default of 1 1647 if ( inst[ cache ][ 3 ] == null ) { 1648 inst[ cache ][ 3 ] = 1; 1649 } 1650 1651 if ( space.from ) { 1652 inst._rgba = space.from( inst[ cache ] ); 1653 } 1654 } 1655 } ); 1656 } 1657 return this; 1658 } 1659 }, 1660 is: function( compare ) { 1661 var is = color( compare ), 1662 same = true, 1663 inst = this; 1664 1665 each( spaces, function( _, space ) { 1666 var localCache, 1667 isCache = is[ space.cache ]; 1668 if ( isCache ) { 1669 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; 1670 each( space.props, function( _, prop ) { 1671 if ( isCache[ prop.idx ] != null ) { 1672 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); 1673 return same; 1674 } 1675 } ); 1676 } 1677 return same; 1678 } ); 1679 return same; 1680 }, 1681 _space: function() { 1682 var used = [], 1683 inst = this; 1684 each( spaces, function( spaceName, space ) { 1685 if ( inst[ space.cache ] ) { 1686 used.push( spaceName ); 1687 } 1688 } ); 1689 return used.pop(); 1690 }, 1691 transition: function( other, distance ) { 1692 var end = color( other ), 1693 spaceName = end._space(), 1694 space = spaces[ spaceName ], 1695 startColor = this.alpha() === 0 ? color( "transparent" ) : this, 1696 start = startColor[ space.cache ] || space.to( startColor._rgba ), 1697 result = start.slice(); 1698 1699 end = end[ space.cache ]; 1700 each( space.props, function( _key, prop ) { 1701 var index = prop.idx, 1702 startValue = start[ index ], 1703 endValue = end[ index ], 1704 type = propTypes[ prop.type ] || {}; 1705 1706 // if null, don't override start value 1707 if ( endValue === null ) { 1708 return; 1709 } 1710 1711 // if null - use end 1712 if ( startValue === null ) { 1713 result[ index ] = endValue; 1714 } else { 1715 if ( type.mod ) { 1716 if ( endValue - startValue > type.mod / 2 ) { 1717 startValue += type.mod; 1718 } else if ( startValue - endValue > type.mod / 2 ) { 1719 startValue -= type.mod; 1720 } 1721 } 1722 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); 1723 } 1724 } ); 1725 return this[ spaceName ]( result ); 1726 }, 1727 blend: function( opaque ) { 1728 1729 // if we are already opaque - return ourself 1730 if ( this._rgba[ 3 ] === 1 ) { 1731 return this; 1732 } 1733 1734 var rgb = this._rgba.slice(), 1735 a = rgb.pop(), 1736 blend = color( opaque )._rgba; 1737 1738 return color( jQuery.map( rgb, function( v, i ) { 1739 return ( 1 - a ) * blend[ i ] + a * v; 1740 } ) ); 1741 }, 1742 toRgbaString: function() { 1743 var prefix = "rgba(", 1744 rgba = jQuery.map( this._rgba, function( v, i ) { 1745 if ( v != null ) { 1746 return v; 1747 } 1748 return i > 2 ? 1 : 0; 1749 } ); 1750 1751 if ( rgba[ 3 ] === 1 ) { 1752 rgba.pop(); 1753 prefix = "rgb("; 1754 } 1755 1756 return prefix + rgba.join() + ")"; 1757 }, 1758 toHslaString: function() { 1759 var prefix = "hsla(", 1760 hsla = jQuery.map( this.hsla(), function( v, i ) { 1761 if ( v == null ) { 1762 v = i > 2 ? 1 : 0; 1763 } 1764 1765 // catch 1 and 2 1766 if ( i && i < 3 ) { 1767 v = Math.round( v * 100 ) + "%"; 1768 } 1769 return v; 1770 } ); 1771 1772 if ( hsla[ 3 ] === 1 ) { 1773 hsla.pop(); 1774 prefix = "hsl("; 1775 } 1776 return prefix + hsla.join() + ")"; 1777 }, 1778 toHexString: function( includeAlpha ) { 1779 var rgba = this._rgba.slice(), 1780 alpha = rgba.pop(); 1781 1782 if ( includeAlpha ) { 1783 rgba.push( ~~( alpha * 255 ) ); 1784 } 1785 1786 return "#" + jQuery.map( rgba, function( v ) { 1787 1788 // default to 0 when nulls exist 1789 v = ( v || 0 ).toString( 16 ); 1790 return v.length === 1 ? "0" + v : v; 1791 } ).join( "" ); 1792 }, 1793 toString: function() { 1794 return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); 1795 } 1796} ); 1797color.fn.parse.prototype = color.fn; 1798 1799// hsla conversions adapted from: 1800// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 1801 1802function hue2rgb( p, q, h ) { 1803 h = ( h + 1 ) % 1; 1804 if ( h * 6 < 1 ) { 1805 return p + ( q - p ) * h * 6; 1806 } 1807 if ( h * 2 < 1 ) { 1808 return q; 1809 } 1810 if ( h * 3 < 2 ) { 1811 return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6; 1812 } 1813 return p; 1814} 1815 1816spaces.hsla.to = function( rgba ) { 1817 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { 1818 return [ null, null, null, rgba[ 3 ] ]; 1819 } 1820 var r = rgba[ 0 ] / 255, 1821 g = rgba[ 1 ] / 255, 1822 b = rgba[ 2 ] / 255, 1823 a = rgba[ 3 ], 1824 max = Math.max( r, g, b ), 1825 min = Math.min( r, g, b ), 1826 diff = max - min, 1827 add = max + min, 1828 l = add * 0.5, 1829 h, s; 1830 1831 if ( min === max ) { 1832 h = 0; 1833 } else if ( r === max ) { 1834 h = ( 60 * ( g - b ) / diff ) + 360; 1835 } else if ( g === max ) { 1836 h = ( 60 * ( b - r ) / diff ) + 120; 1837 } else { 1838 h = ( 60 * ( r - g ) / diff ) + 240; 1839 } 1840 1841 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0% 1842 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) 1843 if ( diff === 0 ) { 1844 s = 0; 1845 } else if ( l <= 0.5 ) { 1846 s = diff / add; 1847 } else { 1848 s = diff / ( 2 - add ); 1849 } 1850 return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ]; 1851}; 1852 1853spaces.hsla.from = function( hsla ) { 1854 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { 1855 return [ null, null, null, hsla[ 3 ] ]; 1856 } 1857 var h = hsla[ 0 ] / 360, 1858 s = hsla[ 1 ], 1859 l = hsla[ 2 ], 1860 a = hsla[ 3 ], 1861 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, 1862 p = 2 * l - q; 1863 1864 return [ 1865 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), 1866 Math.round( hue2rgb( p, q, h ) * 255 ), 1867 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), 1868 a 1869 ]; 1870}; 1871 1872 1873each( spaces, function( spaceName, space ) { 1874 var props = space.props, 1875 cache = space.cache, 1876 to = space.to, 1877 from = space.from; 1878 1879 // makes rgba() and hsla() 1880 color.fn[ spaceName ] = function( value ) { 1881 1882 // generate a cache for this space if it doesn't exist 1883 if ( to && !this[ cache ] ) { 1884 this[ cache ] = to( this._rgba ); 1885 } 1886 if ( value === undefined ) { 1887 return this[ cache ].slice(); 1888 } 1889 1890 var ret, 1891 type = getType( value ), 1892 arr = ( type === "array" || type === "object" ) ? value : arguments, 1893 local = this[ cache ].slice(); 1894 1895 each( props, function( key, prop ) { 1896 var val = arr[ type === "object" ? key : prop.idx ]; 1897 if ( val == null ) { 1898 val = local[ prop.idx ]; 1899 } 1900 local[ prop.idx ] = clamp( val, prop ); 1901 } ); 1902 1903 if ( from ) { 1904 ret = color( from( local ) ); 1905 ret[ cache ] = local; 1906 return ret; 1907 } else { 1908 return color( local ); 1909 } 1910 }; 1911 1912 // makes red() green() blue() alpha() hue() saturation() lightness() 1913 each( props, function( key, prop ) { 1914 1915 // alpha is included in more than one space 1916 if ( color.fn[ key ] ) { 1917 return; 1918 } 1919 color.fn[ key ] = function( value ) { 1920 var local, cur, match, fn, 1921 vtype = getType( value ); 1922 1923 if ( key === "alpha" ) { 1924 fn = this._hsla ? "hsla" : "rgba"; 1925 } else { 1926 fn = spaceName; 1927 } 1928 local = this[ fn ](); 1929 cur = local[ prop.idx ]; 1930 1931 if ( vtype === "undefined" ) { 1932 return cur; 1933 } 1934 1935 if ( vtype === "function" ) { 1936 value = value.call( this, cur ); 1937 vtype = getType( value ); 1938 } 1939 if ( value == null && prop.empty ) { 1940 return this; 1941 } 1942 if ( vtype === "string" ) { 1943 match = rplusequals.exec( value ); 1944 if ( match ) { 1945 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); 1946 } 1947 } 1948 local[ prop.idx ] = value; 1949 return this[ fn ]( local ); 1950 }; 1951 } ); 1952} ); 1953 1954// add cssHook and .fx.step function for each named hook. 1955// accept a space separated string of properties 1956color.hook = function( hook ) { 1957 var hooks = hook.split( " " ); 1958 each( hooks, function( _i, hook ) { 1959 jQuery.cssHooks[ hook ] = { 1960 set: function( elem, value ) { 1961 var parsed, curElem, 1962 backgroundColor = ""; 1963 1964 if ( value !== "transparent" && ( getType( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) { 1965 value = color( parsed || value ); 1966 if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { 1967 curElem = hook === "backgroundColor" ? elem.parentNode : elem; 1968 while ( 1969 ( backgroundColor === "" || backgroundColor === "transparent" ) && 1970 curElem && curElem.style 1971 ) { 1972 try { 1973 backgroundColor = jQuery.css( curElem, "backgroundColor" ); 1974 curElem = curElem.parentNode; 1975 } catch ( e ) { 1976 } 1977 } 1978 1979 value = value.blend( backgroundColor && backgroundColor !== "transparent" ? 1980 backgroundColor : 1981 "_default" ); 1982 } 1983 1984 value = value.toRgbaString(); 1985 } 1986 try { 1987 elem.style[ hook ] = value; 1988 } catch ( e ) { 1989 1990 // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' 1991 } 1992 } 1993 }; 1994 jQuery.fx.step[ hook ] = function( fx ) { 1995 if ( !fx.colorInit ) { 1996 fx.start = color( fx.elem, hook ); 1997 fx.end = color( fx.end ); 1998 fx.colorInit = true; 1999 } 2000 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); 2001 }; 2002 } ); 2003 2004}; 2005 2006color.hook( stepHooks ); 2007 2008jQuery.cssHooks.borderColor = { 2009 expand: function( value ) { 2010 var expanded = {}; 2011 2012 each( [ "Top", "Right", "Bottom", "Left" ], function( _i, part ) { 2013 expanded[ "border" + part + "Color" ] = value; 2014 } ); 2015 return expanded; 2016 } 2017}; 2018 2019// Basic color names only. 2020// Usage of any of the other color names requires adding yourself or including 2021// jquery.color.svg-names.js. 2022colors = jQuery.Color.names = { 2023 2024 // 4.1. Basic color keywords 2025 aqua: "#00ffff", 2026 black: "#000000", 2027 blue: "#0000ff", 2028 fuchsia: "#ff00ff", 2029 gray: "#808080", 2030 green: "#008000", 2031 lime: "#00ff00", 2032 maroon: "#800000", 2033 navy: "#000080", 2034 olive: "#808000", 2035 purple: "#800080", 2036 red: "#ff0000", 2037 silver: "#c0c0c0", 2038 teal: "#008080", 2039 white: "#ffffff", 2040 yellow: "#ffff00", 2041 2042 // 4.2.3. "transparent" color keyword 2043 transparent: [ null, null, null, 0 ], 2044 2045 _default: "#ffffff" 2046}; 2047 2048 2049/*! 2050 * jQuery UI Effects 1.13.3 2051 * https://jqueryui.com 2052 * 2053 * Copyright OpenJS Foundation and other contributors 2054 * Released under the MIT license. 2055 * https://jquery.org/license 2056 */ 2057 2058//>>label: Effects Core 2059//>>group: Effects 2060/* eslint-disable max-len */ 2061//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects. 2062/* eslint-enable max-len */ 2063//>>docs: https://api.jqueryui.com/category/effects-core/ 2064//>>demos: https://jqueryui.com/effect/ 2065 2066 2067var dataSpace = "ui-effects-", 2068 dataSpaceStyle = "ui-effects-style", 2069 dataSpaceAnimated = "ui-effects-animated"; 2070 2071$.effects = { 2072 effect: {} 2073}; 2074 2075/******************************************************************************/ 2076/****************************** CLASS ANIMATIONS ******************************/ 2077/******************************************************************************/ 2078( function() { 2079 2080var classAnimationActions = [ "add", "remove", "toggle" ], 2081 shorthandStyles = { 2082 border: 1, 2083 borderBottom: 1, 2084 borderColor: 1, 2085 borderLeft: 1, 2086 borderRight: 1, 2087 borderTop: 1, 2088 borderWidth: 1, 2089 margin: 1, 2090 padding: 1 2091 }; 2092 2093$.each( 2094 [ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], 2095 function( _, prop ) { 2096 $.fx.step[ prop ] = function( fx ) { 2097 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { 2098 jQuery.style( fx.elem, prop, fx.end ); 2099 fx.setAttr = true; 2100 } 2101 }; 2102 } 2103); 2104 2105function camelCase( string ) { 2106 return string.replace( /-([\da-z])/gi, function( all, letter ) { 2107 return letter.toUpperCase(); 2108 } ); 2109} 2110 2111function getElementStyles( elem ) { 2112 var key, len, 2113 style = elem.ownerDocument.defaultView ? 2114 elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : 2115 elem.currentStyle, 2116 styles = {}; 2117 2118 if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { 2119 len = style.length; 2120 while ( len-- ) { 2121 key = style[ len ]; 2122 if ( typeof style[ key ] === "string" ) { 2123 styles[ camelCase( key ) ] = style[ key ]; 2124 } 2125 } 2126 2127 // Support: Opera, IE <9 2128 } else { 2129 for ( key in style ) { 2130 if ( typeof style[ key ] === "string" ) { 2131 styles[ key ] = style[ key ]; 2132 } 2133 } 2134 } 2135 2136 return styles; 2137} 2138 2139function styleDifference( oldStyle, newStyle ) { 2140 var diff = {}, 2141 name, value; 2142 2143 for ( name in newStyle ) { 2144 value = newStyle[ name ]; 2145 if ( oldStyle[ name ] !== value ) { 2146 if ( !shorthandStyles[ name ] ) { 2147 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { 2148 diff[ name ] = value; 2149 } 2150 } 2151 } 2152 } 2153 2154 return diff; 2155} 2156 2157// Support: jQuery <1.8 2158if ( !$.fn.addBack ) { 2159 $.fn.addBack = function( selector ) { 2160 return this.add( selector == null ? 2161 this.prevObject : this.prevObject.filter( selector ) 2162 ); 2163 }; 2164} 2165 2166$.effects.animateClass = function( value, duration, easing, callback ) { 2167 var o = $.speed( duration, easing, callback ); 2168 2169 return this.queue( function() { 2170 var animated = $( this ), 2171 baseClass = animated.attr( "class" ) || "", 2172 applyClassChange, 2173 allAnimations = o.children ? animated.find( "*" ).addBack() : animated; 2174 2175 // Map the animated objects to store the original styles. 2176 allAnimations = allAnimations.map( function() { 2177 var el = $( this ); 2178 return { 2179 el: el, 2180 start: getElementStyles( this ) 2181 }; 2182 } ); 2183 2184 // Apply class change 2185 applyClassChange = function() { 2186 $.each( classAnimationActions, function( i, action ) { 2187 if ( value[ action ] ) { 2188 animated[ action + "Class" ]( value[ action ] ); 2189 } 2190 } ); 2191 }; 2192 applyClassChange(); 2193 2194 // Map all animated objects again - calculate new styles and diff 2195 allAnimations = allAnimations.map( function() { 2196 this.end = getElementStyles( this.el[ 0 ] ); 2197 this.diff = styleDifference( this.start, this.end ); 2198 return this; 2199 } ); 2200 2201 // Apply original class 2202 animated.attr( "class", baseClass ); 2203 2204 // Map all animated objects again - this time collecting a promise 2205 allAnimations = allAnimations.map( function() { 2206 var styleInfo = this, 2207 dfd = $.Deferred(), 2208 opts = $.extend( {}, o, { 2209 queue: false, 2210 complete: function() { 2211 dfd.resolve( styleInfo ); 2212 } 2213 } ); 2214 2215 this.el.animate( this.diff, opts ); 2216 return dfd.promise(); 2217 } ); 2218 2219 // Once all animations have completed: 2220 $.when.apply( $, allAnimations.get() ).done( function() { 2221 2222 // Set the final class 2223 applyClassChange(); 2224 2225 // For each animated element, 2226 // clear all css properties that were animated 2227 $.each( arguments, function() { 2228 var el = this.el; 2229 $.each( this.diff, function( key ) { 2230 el.css( key, "" ); 2231 } ); 2232 } ); 2233 2234 // This is guarnteed to be there if you use jQuery.speed() 2235 // it also handles dequeuing the next anim... 2236 o.complete.call( animated[ 0 ] ); 2237 } ); 2238 } ); 2239}; 2240 2241$.fn.extend( { 2242 addClass: ( function( orig ) { 2243 return function( classNames, speed, easing, callback ) { 2244 return speed ? 2245 $.effects.animateClass.call( this, 2246 { add: classNames }, speed, easing, callback ) : 2247 orig.apply( this, arguments ); 2248 }; 2249 } )( $.fn.addClass ), 2250 2251 removeClass: ( function( orig ) { 2252 return function( classNames, speed, easing, callback ) { 2253 return arguments.length > 1 ? 2254 $.effects.animateClass.call( this, 2255 { remove: classNames }, speed, easing, callback ) : 2256 orig.apply( this, arguments ); 2257 }; 2258 } )( $.fn.removeClass ), 2259 2260 toggleClass: ( function( orig ) { 2261 return function( classNames, force, speed, easing, callback ) { 2262 if ( typeof force === "boolean" || force === undefined ) { 2263 if ( !speed ) { 2264 2265 // Without speed parameter 2266 return orig.apply( this, arguments ); 2267 } else { 2268 return $.effects.animateClass.call( this, 2269 ( force ? { add: classNames } : { remove: classNames } ), 2270 speed, easing, callback ); 2271 } 2272 } else { 2273 2274 // Without force parameter 2275 return $.effects.animateClass.call( this, 2276 { toggle: classNames }, force, speed, easing ); 2277 } 2278 }; 2279 } )( $.fn.toggleClass ), 2280 2281 switchClass: function( remove, add, speed, easing, callback ) { 2282 return $.effects.animateClass.call( this, { 2283 add: add, 2284 remove: remove 2285 }, speed, easing, callback ); 2286 } 2287} ); 2288 2289} )(); 2290 2291/******************************************************************************/ 2292/*********************************** EFFECTS **********************************/ 2293/******************************************************************************/ 2294 2295( function() { 2296 2297if ( $.expr && $.expr.pseudos && $.expr.pseudos.animated ) { 2298 $.expr.pseudos.animated = ( function( orig ) { 2299 return function( elem ) { 2300 return !!$( elem ).data( dataSpaceAnimated ) || orig( elem ); 2301 }; 2302 } )( $.expr.pseudos.animated ); 2303} 2304 2305if ( $.uiBackCompat !== false ) { 2306 $.extend( $.effects, { 2307 2308 // Saves a set of properties in a data storage 2309 save: function( element, set ) { 2310 var i = 0, length = set.length; 2311 for ( ; i < length; i++ ) { 2312 if ( set[ i ] !== null ) { 2313 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); 2314 } 2315 } 2316 }, 2317 2318 // Restores a set of previously saved properties from a data storage 2319 restore: function( element, set ) { 2320 var val, i = 0, length = set.length; 2321 for ( ; i < length; i++ ) { 2322 if ( set[ i ] !== null ) { 2323 val = element.data( dataSpace + set[ i ] ); 2324 element.css( set[ i ], val ); 2325 } 2326 } 2327 }, 2328 2329 setMode: function( el, mode ) { 2330 if ( mode === "toggle" ) { 2331 mode = el.is( ":hidden" ) ? "show" : "hide"; 2332 } 2333 return mode; 2334 }, 2335 2336 // Wraps the element around a wrapper that copies position properties 2337 createWrapper: function( element ) { 2338 2339 // If the element is already wrapped, return it 2340 if ( element.parent().is( ".ui-effects-wrapper" ) ) { 2341 return element.parent(); 2342 } 2343 2344 // Wrap the element 2345 var props = { 2346 width: element.outerWidth( true ), 2347 height: element.outerHeight( true ), 2348 "float": element.css( "float" ) 2349 }, 2350 wrapper = $( "<div></div>" ) 2351 .addClass( "ui-effects-wrapper" ) 2352 .css( { 2353 fontSize: "100%", 2354 background: "transparent", 2355 border: "none", 2356 margin: 0, 2357 padding: 0 2358 } ), 2359 2360 // Store the size in case width/height are defined in % - Fixes #5245 2361 size = { 2362 width: element.width(), 2363 height: element.height() 2364 }, 2365 active = document.activeElement; 2366 2367 // Support: Firefox 2368 // Firefox incorrectly exposes anonymous content 2369 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 2370 try { 2371 // eslint-disable-next-line no-unused-expressions 2372 active.id; 2373 } catch ( e ) { 2374 active = document.body; 2375 } 2376 2377 element.wrap( wrapper ); 2378 2379 // Fixes #7595 - Elements lose focus when wrapped. 2380 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 2381 $( active ).trigger( "focus" ); 2382 } 2383 2384 // Hotfix for jQuery 1.4 since some change in wrap() seems to actually 2385 // lose the reference to the wrapped element 2386 wrapper = element.parent(); 2387 2388 // Transfer positioning properties to the wrapper 2389 if ( element.css( "position" ) === "static" ) { 2390 wrapper.css( { position: "relative" } ); 2391 element.css( { position: "relative" } ); 2392 } else { 2393 $.extend( props, { 2394 position: element.css( "position" ), 2395 zIndex: element.css( "z-index" ) 2396 } ); 2397 $.each( [ "top", "left", "bottom", "right" ], function( i, pos ) { 2398 props[ pos ] = element.css( pos ); 2399 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { 2400 props[ pos ] = "auto"; 2401 } 2402 } ); 2403 element.css( { 2404 position: "relative", 2405 top: 0, 2406 left: 0, 2407 right: "auto", 2408 bottom: "auto" 2409 } ); 2410 } 2411 element.css( size ); 2412 2413 return wrapper.css( props ).show(); 2414 }, 2415 2416 removeWrapper: function( element ) { 2417 var active = document.activeElement; 2418 2419 if ( element.parent().is( ".ui-effects-wrapper" ) ) { 2420 element.parent().replaceWith( element ); 2421 2422 // Fixes #7595 - Elements lose focus when wrapped. 2423 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 2424 $( active ).trigger( "focus" ); 2425 } 2426 } 2427 2428 return element; 2429 } 2430 } ); 2431} 2432 2433$.extend( $.effects, { 2434 version: "1.13.3", 2435 2436 define: function( name, mode, effect ) { 2437 if ( !effect ) { 2438 effect = mode; 2439 mode = "effect"; 2440 } 2441 2442 $.effects.effect[ name ] = effect; 2443 $.effects.effect[ name ].mode = mode; 2444 2445 return effect; 2446 }, 2447 2448 scaledDimensions: function( element, percent, direction ) { 2449 if ( percent === 0 ) { 2450 return { 2451 height: 0, 2452 width: 0, 2453 outerHeight: 0, 2454 outerWidth: 0 2455 }; 2456 } 2457 2458 var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1, 2459 y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1; 2460 2461 return { 2462 height: element.height() * y, 2463 width: element.width() * x, 2464 outerHeight: element.outerHeight() * y, 2465 outerWidth: element.outerWidth() * x 2466 }; 2467 2468 }, 2469 2470 clipToBox: function( animation ) { 2471 return { 2472 width: animation.clip.right - animation.clip.left, 2473 height: animation.clip.bottom - animation.clip.top, 2474 left: animation.clip.left, 2475 top: animation.clip.top 2476 }; 2477 }, 2478 2479 // Injects recently queued functions to be first in line (after "inprogress") 2480 unshift: function( element, queueLength, count ) { 2481 var queue = element.queue(); 2482 2483 if ( queueLength > 1 ) { 2484 queue.splice.apply( queue, 2485 [ 1, 0 ].concat( queue.splice( queueLength, count ) ) ); 2486 } 2487 element.dequeue(); 2488 }, 2489 2490 saveStyle: function( element ) { 2491 element.data( dataSpaceStyle, element[ 0 ].style.cssText ); 2492 }, 2493 2494 restoreStyle: function( element ) { 2495 element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || ""; 2496 element.removeData( dataSpaceStyle ); 2497 }, 2498 2499 mode: function( element, mode ) { 2500 var hidden = element.is( ":hidden" ); 2501 2502 if ( mode === "toggle" ) { 2503 mode = hidden ? "show" : "hide"; 2504 } 2505 if ( hidden ? mode === "hide" : mode === "show" ) { 2506 mode = "none"; 2507 } 2508 return mode; 2509 }, 2510 2511 // Translates a [top,left] array into a baseline value 2512 getBaseline: function( origin, original ) { 2513 var y, x; 2514 2515 switch ( origin[ 0 ] ) { 2516 case "top": 2517 y = 0; 2518 break; 2519 case "middle": 2520 y = 0.5; 2521 break; 2522 case "bottom": 2523 y = 1; 2524 break; 2525 default: 2526 y = origin[ 0 ] / original.height; 2527 } 2528 2529 switch ( origin[ 1 ] ) { 2530 case "left": 2531 x = 0; 2532 break; 2533 case "center": 2534 x = 0.5; 2535 break; 2536 case "right": 2537 x = 1; 2538 break; 2539 default: 2540 x = origin[ 1 ] / original.width; 2541 } 2542 2543 return { 2544 x: x, 2545 y: y 2546 }; 2547 }, 2548 2549 // Creates a placeholder element so that the original element can be made absolute 2550 createPlaceholder: function( element ) { 2551 var placeholder, 2552 cssPosition = element.css( "position" ), 2553 position = element.position(); 2554 2555 // Lock in margins first to account for form elements, which 2556 // will change margin if you explicitly set height 2557 // see: https://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380 2558 // Support: Safari 2559 element.css( { 2560 marginTop: element.css( "marginTop" ), 2561 marginBottom: element.css( "marginBottom" ), 2562 marginLeft: element.css( "marginLeft" ), 2563 marginRight: element.css( "marginRight" ) 2564 } ) 2565 .outerWidth( element.outerWidth() ) 2566 .outerHeight( element.outerHeight() ); 2567 2568 if ( /^(static|relative)/.test( cssPosition ) ) { 2569 cssPosition = "absolute"; 2570 2571 placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( { 2572 2573 // Convert inline to inline block to account for inline elements 2574 // that turn to inline block based on content (like img) 2575 display: /^(inline|ruby)/.test( element.css( "display" ) ) ? 2576 "inline-block" : 2577 "block", 2578 visibility: "hidden", 2579 2580 // Margins need to be set to account for margin collapse 2581 marginTop: element.css( "marginTop" ), 2582 marginBottom: element.css( "marginBottom" ), 2583 marginLeft: element.css( "marginLeft" ), 2584 marginRight: element.css( "marginRight" ), 2585 "float": element.css( "float" ) 2586 } ) 2587 .outerWidth( element.outerWidth() ) 2588 .outerHeight( element.outerHeight() ) 2589 .addClass( "ui-effects-placeholder" ); 2590 2591 element.data( dataSpace + "placeholder", placeholder ); 2592 } 2593 2594 element.css( { 2595 position: cssPosition, 2596 left: position.left, 2597 top: position.top 2598 } ); 2599 2600 return placeholder; 2601 }, 2602 2603 removePlaceholder: function( element ) { 2604 var dataKey = dataSpace + "placeholder", 2605 placeholder = element.data( dataKey ); 2606 2607 if ( placeholder ) { 2608 placeholder.remove(); 2609 element.removeData( dataKey ); 2610 } 2611 }, 2612 2613 // Removes a placeholder if it exists and restores 2614 // properties that were modified during placeholder creation 2615 cleanUp: function( element ) { 2616 $.effects.restoreStyle( element ); 2617 $.effects.removePlaceholder( element ); 2618 }, 2619 2620 setTransition: function( element, list, factor, value ) { 2621 value = value || {}; 2622 $.each( list, function( i, x ) { 2623 var unit = element.cssUnit( x ); 2624 if ( unit[ 0 ] > 0 ) { 2625 value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; 2626 } 2627 } ); 2628 return value; 2629 } 2630} ); 2631 2632// Return an effect options object for the given parameters: 2633function _normalizeArguments( effect, options, speed, callback ) { 2634 2635 // Allow passing all options as the first parameter 2636 if ( $.isPlainObject( effect ) ) { 2637 options = effect; 2638 effect = effect.effect; 2639 } 2640 2641 // Convert to an object 2642 effect = { effect: effect }; 2643 2644 // Catch (effect, null, ...) 2645 if ( options == null ) { 2646 options = {}; 2647 } 2648 2649 // Catch (effect, callback) 2650 if ( typeof options === "function" ) { 2651 callback = options; 2652 speed = null; 2653 options = {}; 2654 } 2655 2656 // Catch (effect, speed, ?) 2657 if ( typeof options === "number" || $.fx.speeds[ options ] ) { 2658 callback = speed; 2659 speed = options; 2660 options = {}; 2661 } 2662 2663 // Catch (effect, options, callback) 2664 if ( typeof speed === "function" ) { 2665 callback = speed; 2666 speed = null; 2667 } 2668 2669 // Add options to effect 2670 if ( options ) { 2671 $.extend( effect, options ); 2672 } 2673 2674 speed = speed || options.duration; 2675 effect.duration = $.fx.off ? 0 : 2676 typeof speed === "number" ? speed : 2677 speed in $.fx.speeds ? $.fx.speeds[ speed ] : 2678 $.fx.speeds._default; 2679 2680 effect.complete = callback || options.complete; 2681 2682 return effect; 2683} 2684 2685function standardAnimationOption( option ) { 2686 2687 // Valid standard speeds (nothing, number, named speed) 2688 if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) { 2689 return true; 2690 } 2691 2692 // Invalid strings - treat as "normal" speed 2693 if ( typeof option === "string" && !$.effects.effect[ option ] ) { 2694 return true; 2695 } 2696 2697 // Complete callback 2698 if ( typeof option === "function" ) { 2699 return true; 2700 } 2701 2702 // Options hash (but not naming an effect) 2703 if ( typeof option === "object" && !option.effect ) { 2704 return true; 2705 } 2706 2707 // Didn't match any standard API 2708 return false; 2709} 2710 2711$.fn.extend( { 2712 effect: function( /* effect, options, speed, callback */ ) { 2713 var args = _normalizeArguments.apply( this, arguments ), 2714 effectMethod = $.effects.effect[ args.effect ], 2715 defaultMode = effectMethod.mode, 2716 queue = args.queue, 2717 queueName = queue || "fx", 2718 complete = args.complete, 2719 mode = args.mode, 2720 modes = [], 2721 prefilter = function( next ) { 2722 var el = $( this ), 2723 normalizedMode = $.effects.mode( el, mode ) || defaultMode; 2724 2725 // Sentinel for duck-punching the :animated pseudo-selector 2726 el.data( dataSpaceAnimated, true ); 2727 2728 // Save effect mode for later use, 2729 // we can't just call $.effects.mode again later, 2730 // as the .show() below destroys the initial state 2731 modes.push( normalizedMode ); 2732 2733 // See $.uiBackCompat inside of run() for removal of defaultMode in 1.14 2734 if ( defaultMode && ( normalizedMode === "show" || 2735 ( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) { 2736 el.show(); 2737 } 2738 2739 if ( !defaultMode || normalizedMode !== "none" ) { 2740 $.effects.saveStyle( el ); 2741 } 2742 2743 if ( typeof next === "function" ) { 2744 next(); 2745 } 2746 }; 2747 2748 if ( $.fx.off || !effectMethod ) { 2749 2750 // Delegate to the original method (e.g., .show()) if possible 2751 if ( mode ) { 2752 return this[ mode ]( args.duration, complete ); 2753 } else { 2754 return this.each( function() { 2755 if ( complete ) { 2756 complete.call( this ); 2757 } 2758 } ); 2759 } 2760 } 2761 2762 function run( next ) { 2763 var elem = $( this ); 2764 2765 function cleanup() { 2766 elem.removeData( dataSpaceAnimated ); 2767 2768 $.effects.cleanUp( elem ); 2769 2770 if ( args.mode === "hide" ) { 2771 elem.hide(); 2772 } 2773 2774 done(); 2775 } 2776 2777 function done() { 2778 if ( typeof complete === "function" ) { 2779 complete.call( elem[ 0 ] ); 2780 } 2781 2782 if ( typeof next === "function" ) { 2783 next(); 2784 } 2785 } 2786 2787 // Override mode option on a per element basis, 2788 // as toggle can be either show or hide depending on element state 2789 args.mode = modes.shift(); 2790 2791 if ( $.uiBackCompat !== false && !defaultMode ) { 2792 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { 2793 2794 // Call the core method to track "olddisplay" properly 2795 elem[ mode ](); 2796 done(); 2797 } else { 2798 effectMethod.call( elem[ 0 ], args, done ); 2799 } 2800 } else { 2801 if ( args.mode === "none" ) { 2802 2803 // Call the core method to track "olddisplay" properly 2804 elem[ mode ](); 2805 done(); 2806 } else { 2807 effectMethod.call( elem[ 0 ], args, cleanup ); 2808 } 2809 } 2810 } 2811 2812 // Run prefilter on all elements first to ensure that 2813 // any showing or hiding happens before placeholder creation, 2814 // which ensures that any layout changes are correctly captured. 2815 return queue === false ? 2816 this.each( prefilter ).each( run ) : 2817 this.queue( queueName, prefilter ).queue( queueName, run ); 2818 }, 2819 2820 show: ( function( orig ) { 2821 return function( option ) { 2822 if ( standardAnimationOption( option ) ) { 2823 return orig.apply( this, arguments ); 2824 } else { 2825 var args = _normalizeArguments.apply( this, arguments ); 2826 args.mode = "show"; 2827 return this.effect.call( this, args ); 2828 } 2829 }; 2830 } )( $.fn.show ), 2831 2832 hide: ( function( orig ) { 2833 return function( option ) { 2834 if ( standardAnimationOption( option ) ) { 2835 return orig.apply( this, arguments ); 2836 } else { 2837 var args = _normalizeArguments.apply( this, arguments ); 2838 args.mode = "hide"; 2839 return this.effect.call( this, args ); 2840 } 2841 }; 2842 } )( $.fn.hide ), 2843 2844 toggle: ( function( orig ) { 2845 return function( option ) { 2846 if ( standardAnimationOption( option ) || typeof option === "boolean" ) { 2847 return orig.apply( this, arguments ); 2848 } else { 2849 var args = _normalizeArguments.apply( this, arguments ); 2850 args.mode = "toggle"; 2851 return this.effect.call( this, args ); 2852 } 2853 }; 2854 } )( $.fn.toggle ), 2855 2856 cssUnit: function( key ) { 2857 var style = this.css( key ), 2858 val = []; 2859 2860 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { 2861 if ( style.indexOf( unit ) > 0 ) { 2862 val = [ parseFloat( style ), unit ]; 2863 } 2864 } ); 2865 return val; 2866 }, 2867 2868 cssClip: function( clipObj ) { 2869 if ( clipObj ) { 2870 return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " + 2871 clipObj.bottom + "px " + clipObj.left + "px)" ); 2872 } 2873 return parseClip( this.css( "clip" ), this ); 2874 }, 2875 2876 transfer: function( options, done ) { 2877 var element = $( this ), 2878 target = $( options.to ), 2879 targetFixed = target.css( "position" ) === "fixed", 2880 body = $( "body" ), 2881 fixTop = targetFixed ? body.scrollTop() : 0, 2882 fixLeft = targetFixed ? body.scrollLeft() : 0, 2883 endPosition = target.offset(), 2884 animation = { 2885 top: endPosition.top - fixTop, 2886 left: endPosition.left - fixLeft, 2887 height: target.innerHeight(), 2888 width: target.innerWidth() 2889 }, 2890 startPosition = element.offset(), 2891 transfer = $( "<div class='ui-effects-transfer'></div>" ); 2892 2893 transfer 2894 .appendTo( "body" ) 2895 .addClass( options.className ) 2896 .css( { 2897 top: startPosition.top - fixTop, 2898 left: startPosition.left - fixLeft, 2899 height: element.innerHeight(), 2900 width: element.innerWidth(), 2901 position: targetFixed ? "fixed" : "absolute" 2902 } ) 2903 .animate( animation, options.duration, options.easing, function() { 2904 transfer.remove(); 2905 if ( typeof done === "function" ) { 2906 done(); 2907 } 2908 } ); 2909 } 2910} ); 2911 2912function parseClip( str, element ) { 2913 var outerWidth = element.outerWidth(), 2914 outerHeight = element.outerHeight(), 2915 clipRegex = /^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/, 2916 values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ]; 2917 2918 return { 2919 top: parseFloat( values[ 1 ] ) || 0, 2920 right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ), 2921 bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ), 2922 left: parseFloat( values[ 4 ] ) || 0 2923 }; 2924} 2925 2926$.fx.step.clip = function( fx ) { 2927 if ( !fx.clipInit ) { 2928 fx.start = $( fx.elem ).cssClip(); 2929 if ( typeof fx.end === "string" ) { 2930 fx.end = parseClip( fx.end, fx.elem ); 2931 } 2932 fx.clipInit = true; 2933 } 2934 2935 $( fx.elem ).cssClip( { 2936 top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top, 2937 right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right, 2938 bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom, 2939 left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left 2940 } ); 2941}; 2942 2943} )(); 2944 2945/******************************************************************************/ 2946/*********************************** EASING ***********************************/ 2947/******************************************************************************/ 2948 2949( function() { 2950 2951// Based on easing equations from Robert Penner (http://robertpenner.com/easing) 2952 2953var baseEasings = {}; 2954 2955$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { 2956 baseEasings[ name ] = function( p ) { 2957 return Math.pow( p, i + 2 ); 2958 }; 2959} ); 2960 2961$.extend( baseEasings, { 2962 Sine: function( p ) { 2963 return 1 - Math.cos( p * Math.PI / 2 ); 2964 }, 2965 Circ: function( p ) { 2966 return 1 - Math.sqrt( 1 - p * p ); 2967 }, 2968 Elastic: function( p ) { 2969 return p === 0 || p === 1 ? p : 2970 -Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 ); 2971 }, 2972 Back: function( p ) { 2973 return p * p * ( 3 * p - 2 ); 2974 }, 2975 Bounce: function( p ) { 2976 var pow2, 2977 bounce = 4; 2978 2979 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} 2980 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); 2981 } 2982} ); 2983 2984$.each( baseEasings, function( name, easeIn ) { 2985 $.easing[ "easeIn" + name ] = easeIn; 2986 $.easing[ "easeOut" + name ] = function( p ) { 2987 return 1 - easeIn( 1 - p ); 2988 }; 2989 $.easing[ "easeInOut" + name ] = function( p ) { 2990 return p < 0.5 ? 2991 easeIn( p * 2 ) / 2 : 2992 1 - easeIn( p * -2 + 2 ) / 2; 2993 }; 2994} ); 2995 2996} )(); 2997 2998var effect = $.effects; 2999 3000 3001/*! 3002 * jQuery UI Effects Blind 1.13.3 3003 * https://jqueryui.com 3004 * 3005 * Copyright OpenJS Foundation and other contributors 3006 * Released under the MIT license. 3007 * https://jquery.org/license 3008 */ 3009 3010//>>label: Blind Effect 3011//>>group: Effects 3012//>>description: Blinds the element. 3013//>>docs: https://api.jqueryui.com/blind-effect/ 3014//>>demos: https://jqueryui.com/effect/ 3015 3016 3017var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) { 3018 var map = { 3019 up: [ "bottom", "top" ], 3020 vertical: [ "bottom", "top" ], 3021 down: [ "top", "bottom" ], 3022 left: [ "right", "left" ], 3023 horizontal: [ "right", "left" ], 3024 right: [ "left", "right" ] 3025 }, 3026 element = $( this ), 3027 direction = options.direction || "up", 3028 start = element.cssClip(), 3029 animate = { clip: $.extend( {}, start ) }, 3030 placeholder = $.effects.createPlaceholder( element ); 3031 3032 animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ]; 3033 3034 if ( options.mode === "show" ) { 3035 element.cssClip( animate.clip ); 3036 if ( placeholder ) { 3037 placeholder.css( $.effects.clipToBox( animate ) ); 3038 } 3039 3040 animate.clip = start; 3041 } 3042 3043 if ( placeholder ) { 3044 placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing ); 3045 } 3046 3047 element.animate( animate, { 3048 queue: false, 3049 duration: options.duration, 3050 easing: options.easing, 3051 complete: done 3052 } ); 3053} ); 3054 3055 3056/*! 3057 * jQuery UI Effects Bounce 1.13.3 3058 * https://jqueryui.com 3059 * 3060 * Copyright OpenJS Foundation and other contributors 3061 * Released under the MIT license. 3062 * https://jquery.org/license 3063 */ 3064 3065//>>label: Bounce Effect 3066//>>group: Effects 3067//>>description: Bounces an element horizontally or vertically n times. 3068//>>docs: https://api.jqueryui.com/bounce-effect/ 3069//>>demos: https://jqueryui.com/effect/ 3070 3071 3072var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) { 3073 var upAnim, downAnim, refValue, 3074 element = $( this ), 3075 3076 // Defaults: 3077 mode = options.mode, 3078 hide = mode === "hide", 3079 show = mode === "show", 3080 direction = options.direction || "up", 3081 distance = options.distance, 3082 times = options.times || 5, 3083 3084 // Number of internal animations 3085 anims = times * 2 + ( show || hide ? 1 : 0 ), 3086 speed = options.duration / anims, 3087 easing = options.easing, 3088 3089 // Utility: 3090 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 3091 motion = ( direction === "up" || direction === "left" ), 3092 i = 0, 3093 3094 queuelen = element.queue().length; 3095 3096 $.effects.createPlaceholder( element ); 3097 3098 refValue = element.css( ref ); 3099 3100 // Default distance for the BIGGEST bounce is the outer Distance / 3 3101 if ( !distance ) { 3102 distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; 3103 } 3104 3105 if ( show ) { 3106 downAnim = { opacity: 1 }; 3107 downAnim[ ref ] = refValue; 3108 3109 // If we are showing, force opacity 0 and set the initial position 3110 // then do the "first" animation 3111 element 3112 .css( "opacity", 0 ) 3113 .css( ref, motion ? -distance * 2 : distance * 2 ) 3114 .animate( downAnim, speed, easing ); 3115 } 3116 3117 // Start at the smallest distance if we are hiding 3118 if ( hide ) { 3119 distance = distance / Math.pow( 2, times - 1 ); 3120 } 3121 3122 downAnim = {}; 3123 downAnim[ ref ] = refValue; 3124 3125 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here 3126 for ( ; i < times; i++ ) { 3127 upAnim = {}; 3128 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 3129 3130 element 3131 .animate( upAnim, speed, easing ) 3132 .animate( downAnim, speed, easing ); 3133 3134 distance = hide ? distance * 2 : distance / 2; 3135 } 3136 3137 // Last Bounce when Hiding 3138 if ( hide ) { 3139 upAnim = { opacity: 0 }; 3140 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 3141 3142 element.animate( upAnim, speed, easing ); 3143 } 3144 3145 element.queue( done ); 3146 3147 $.effects.unshift( element, queuelen, anims + 1 ); 3148} ); 3149 3150 3151/*! 3152 * jQuery UI Effects Clip 1.13.3 3153 * https://jqueryui.com 3154 * 3155 * Copyright OpenJS Foundation and other contributors 3156 * Released under the MIT license. 3157 * https://jquery.org/license 3158 */ 3159 3160//>>label: Clip Effect 3161//>>group: Effects 3162//>>description: Clips the element on and off like an old TV. 3163//>>docs: https://api.jqueryui.com/clip-effect/ 3164//>>demos: https://jqueryui.com/effect/ 3165 3166 3167var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) { 3168 var start, 3169 animate = {}, 3170 element = $( this ), 3171 direction = options.direction || "vertical", 3172 both = direction === "both", 3173 horizontal = both || direction === "horizontal", 3174 vertical = both || direction === "vertical"; 3175 3176 start = element.cssClip(); 3177 animate.clip = { 3178 top: vertical ? ( start.bottom - start.top ) / 2 : start.top, 3179 right: horizontal ? ( start.right - start.left ) / 2 : start.right, 3180 bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom, 3181 left: horizontal ? ( start.right - start.left ) / 2 : start.left 3182 }; 3183 3184 $.effects.createPlaceholder( element ); 3185 3186 if ( options.mode === "show" ) { 3187 element.cssClip( animate.clip ); 3188 animate.clip = start; 3189 } 3190 3191 element.animate( animate, { 3192 queue: false, 3193 duration: options.duration, 3194 easing: options.easing, 3195 complete: done 3196 } ); 3197 3198} ); 3199 3200 3201/*! 3202 * jQuery UI Effects Drop 1.13.3 3203 * https://jqueryui.com 3204 * 3205 * Copyright OpenJS Foundation and other contributors 3206 * Released under the MIT license. 3207 * https://jquery.org/license 3208 */ 3209 3210//>>label: Drop Effect 3211//>>group: Effects 3212//>>description: Moves an element in one direction and hides it at the same time. 3213//>>docs: https://api.jqueryui.com/drop-effect/ 3214//>>demos: https://jqueryui.com/effect/ 3215 3216 3217var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) { 3218 3219 var distance, 3220 element = $( this ), 3221 mode = options.mode, 3222 show = mode === "show", 3223 direction = options.direction || "left", 3224 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 3225 motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=", 3226 oppositeMotion = ( motion === "+=" ) ? "-=" : "+=", 3227 animation = { 3228 opacity: 0 3229 }; 3230 3231 $.effects.createPlaceholder( element ); 3232 3233 distance = options.distance || 3234 element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2; 3235 3236 animation[ ref ] = motion + distance; 3237 3238 if ( show ) { 3239 element.css( animation ); 3240 3241 animation[ ref ] = oppositeMotion + distance; 3242 animation.opacity = 1; 3243 } 3244 3245 // Animate 3246 element.animate( animation, { 3247 queue: false, 3248 duration: options.duration, 3249 easing: options.easing, 3250 complete: done 3251 } ); 3252} ); 3253 3254 3255/*! 3256 * jQuery UI Effects Explode 1.13.3 3257 * https://jqueryui.com 3258 * 3259 * Copyright OpenJS Foundation and other contributors 3260 * Released under the MIT license. 3261 * https://jquery.org/license 3262 */ 3263 3264//>>label: Explode Effect 3265//>>group: Effects 3266/* eslint-disable max-len */ 3267//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness. 3268/* eslint-enable max-len */ 3269//>>docs: https://api.jqueryui.com/explode-effect/ 3270//>>demos: https://jqueryui.com/effect/ 3271 3272 3273var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) { 3274 3275 var i, j, left, top, mx, my, 3276 rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3, 3277 cells = rows, 3278 element = $( this ), 3279 mode = options.mode, 3280 show = mode === "show", 3281 3282 // Show and then visibility:hidden the element before calculating offset 3283 offset = element.show().css( "visibility", "hidden" ).offset(), 3284 3285 // Width and height of a piece 3286 width = Math.ceil( element.outerWidth() / cells ), 3287 height = Math.ceil( element.outerHeight() / rows ), 3288 pieces = []; 3289 3290 // Children animate complete: 3291 function childComplete() { 3292 pieces.push( this ); 3293 if ( pieces.length === rows * cells ) { 3294 animComplete(); 3295 } 3296 } 3297 3298 // Clone the element for each row and cell. 3299 for ( i = 0; i < rows; i++ ) { // ===> 3300 top = offset.top + i * height; 3301 my = i - ( rows - 1 ) / 2; 3302 3303 for ( j = 0; j < cells; j++ ) { // ||| 3304 left = offset.left + j * width; 3305 mx = j - ( cells - 1 ) / 2; 3306 3307 // Create a clone of the now hidden main element that will be absolute positioned 3308 // within a wrapper div off the -left and -top equal to size of our pieces 3309 element 3310 .clone() 3311 .appendTo( "body" ) 3312 .wrap( "<div></div>" ) 3313 .css( { 3314 position: "absolute", 3315 visibility: "visible", 3316 left: -j * width, 3317 top: -i * height 3318 } ) 3319 3320 // Select the wrapper - make it overflow: hidden and absolute positioned based on 3321 // where the original was located +left and +top equal to the size of pieces 3322 .parent() 3323 .addClass( "ui-effects-explode" ) 3324 .css( { 3325 position: "absolute", 3326 overflow: "hidden", 3327 width: width, 3328 height: height, 3329 left: left + ( show ? mx * width : 0 ), 3330 top: top + ( show ? my * height : 0 ), 3331 opacity: show ? 0 : 1 3332 } ) 3333 .animate( { 3334 left: left + ( show ? 0 : mx * width ), 3335 top: top + ( show ? 0 : my * height ), 3336 opacity: show ? 1 : 0 3337 }, options.duration || 500, options.easing, childComplete ); 3338 } 3339 } 3340 3341 function animComplete() { 3342 element.css( { 3343 visibility: "visible" 3344 } ); 3345 $( pieces ).remove(); 3346 done(); 3347 } 3348} ); 3349 3350 3351/*! 3352 * jQuery UI Effects Fade 1.13.3 3353 * https://jqueryui.com 3354 * 3355 * Copyright OpenJS Foundation and other contributors 3356 * Released under the MIT license. 3357 * https://jquery.org/license 3358 */ 3359 3360//>>label: Fade Effect 3361//>>group: Effects 3362//>>description: Fades the element. 3363//>>docs: https://api.jqueryui.com/fade-effect/ 3364//>>demos: https://jqueryui.com/effect/ 3365 3366 3367var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) { 3368 var show = options.mode === "show"; 3369 3370 $( this ) 3371 .css( "opacity", show ? 0 : 1 ) 3372 .animate( { 3373 opacity: show ? 1 : 0 3374 }, { 3375 queue: false, 3376 duration: options.duration, 3377 easing: options.easing, 3378 complete: done 3379 } ); 3380} ); 3381 3382 3383/*! 3384 * jQuery UI Effects Fold 1.13.3 3385 * https://jqueryui.com 3386 * 3387 * Copyright OpenJS Foundation and other contributors 3388 * Released under the MIT license. 3389 * https://jquery.org/license 3390 */ 3391 3392//>>label: Fold Effect 3393//>>group: Effects 3394//>>description: Folds an element first horizontally and then vertically. 3395//>>docs: https://api.jqueryui.com/fold-effect/ 3396//>>demos: https://jqueryui.com/effect/ 3397 3398 3399var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) { 3400 3401 // Create element 3402 var element = $( this ), 3403 mode = options.mode, 3404 show = mode === "show", 3405 hide = mode === "hide", 3406 size = options.size || 15, 3407 percent = /([0-9]+)%/.exec( size ), 3408 horizFirst = !!options.horizFirst, 3409 ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ], 3410 duration = options.duration / 2, 3411 3412 placeholder = $.effects.createPlaceholder( element ), 3413 3414 start = element.cssClip(), 3415 animation1 = { clip: $.extend( {}, start ) }, 3416 animation2 = { clip: $.extend( {}, start ) }, 3417 3418 distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ], 3419 3420 queuelen = element.queue().length; 3421 3422 if ( percent ) { 3423 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; 3424 } 3425 animation1.clip[ ref[ 0 ] ] = size; 3426 animation2.clip[ ref[ 0 ] ] = size; 3427 animation2.clip[ ref[ 1 ] ] = 0; 3428 3429 if ( show ) { 3430 element.cssClip( animation2.clip ); 3431 if ( placeholder ) { 3432 placeholder.css( $.effects.clipToBox( animation2 ) ); 3433 } 3434 3435 animation2.clip = start; 3436 } 3437 3438 // Animate 3439 element 3440 .queue( function( next ) { 3441 if ( placeholder ) { 3442 placeholder 3443 .animate( $.effects.clipToBox( animation1 ), duration, options.easing ) 3444 .animate( $.effects.clipToBox( animation2 ), duration, options.easing ); 3445 } 3446 3447 next(); 3448 } ) 3449 .animate( animation1, duration, options.easing ) 3450 .animate( animation2, duration, options.easing ) 3451 .queue( done ); 3452 3453 $.effects.unshift( element, queuelen, 4 ); 3454} ); 3455 3456 3457/*! 3458 * jQuery UI Effects Highlight 1.13.3 3459 * https://jqueryui.com 3460 * 3461 * Copyright OpenJS Foundation and other contributors 3462 * Released under the MIT license. 3463 * https://jquery.org/license 3464 */ 3465 3466//>>label: Highlight Effect 3467//>>group: Effects 3468//>>description: Highlights the background of an element in a defined color for a custom duration. 3469//>>docs: https://api.jqueryui.com/highlight-effect/ 3470//>>demos: https://jqueryui.com/effect/ 3471 3472 3473var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) { 3474 var element = $( this ), 3475 animation = { 3476 backgroundColor: element.css( "backgroundColor" ) 3477 }; 3478 3479 if ( options.mode === "hide" ) { 3480 animation.opacity = 0; 3481 } 3482 3483 $.effects.saveStyle( element ); 3484 3485 element 3486 .css( { 3487 backgroundImage: "none", 3488 backgroundColor: options.color || "#ffff99" 3489 } ) 3490 .animate( animation, { 3491 queue: false, 3492 duration: options.duration, 3493 easing: options.easing, 3494 complete: done 3495 } ); 3496} ); 3497 3498 3499/*! 3500 * jQuery UI Effects Size 1.13.3 3501 * https://jqueryui.com 3502 * 3503 * Copyright OpenJS Foundation and other contributors 3504 * Released under the MIT license. 3505 * https://jquery.org/license 3506 */ 3507 3508//>>label: Size Effect 3509//>>group: Effects 3510//>>description: Resize an element to a specified width and height. 3511//>>docs: https://api.jqueryui.com/size-effect/ 3512//>>demos: https://jqueryui.com/effect/ 3513 3514 3515var effectsEffectSize = $.effects.define( "size", function( options, done ) { 3516 3517 // Create element 3518 var baseline, factor, temp, 3519 element = $( this ), 3520 3521 // Copy for children 3522 cProps = [ "fontSize" ], 3523 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], 3524 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], 3525 3526 // Set options 3527 mode = options.mode, 3528 restore = mode !== "effect", 3529 scale = options.scale || "both", 3530 origin = options.origin || [ "middle", "center" ], 3531 position = element.css( "position" ), 3532 pos = element.position(), 3533 original = $.effects.scaledDimensions( element ), 3534 from = options.from || original, 3535 to = options.to || $.effects.scaledDimensions( element, 0 ); 3536 3537 $.effects.createPlaceholder( element ); 3538 3539 if ( mode === "show" ) { 3540 temp = from; 3541 from = to; 3542 to = temp; 3543 } 3544 3545 // Set scaling factor 3546 factor = { 3547 from: { 3548 y: from.height / original.height, 3549 x: from.width / original.width 3550 }, 3551 to: { 3552 y: to.height / original.height, 3553 x: to.width / original.width 3554 } 3555 }; 3556 3557 // Scale the css box 3558 if ( scale === "box" || scale === "both" ) { 3559 3560 // Vertical props scaling 3561 if ( factor.from.y !== factor.to.y ) { 3562 from = $.effects.setTransition( element, vProps, factor.from.y, from ); 3563 to = $.effects.setTransition( element, vProps, factor.to.y, to ); 3564 } 3565 3566 // Horizontal props scaling 3567 if ( factor.from.x !== factor.to.x ) { 3568 from = $.effects.setTransition( element, hProps, factor.from.x, from ); 3569 to = $.effects.setTransition( element, hProps, factor.to.x, to ); 3570 } 3571 } 3572 3573 // Scale the content 3574 if ( scale === "content" || scale === "both" ) { 3575 3576 // Vertical props scaling 3577 if ( factor.from.y !== factor.to.y ) { 3578 from = $.effects.setTransition( element, cProps, factor.from.y, from ); 3579 to = $.effects.setTransition( element, cProps, factor.to.y, to ); 3580 } 3581 } 3582 3583 // Adjust the position properties based on the provided origin points 3584 if ( origin ) { 3585 baseline = $.effects.getBaseline( origin, original ); 3586 from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top; 3587 from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left; 3588 to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top; 3589 to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left; 3590 } 3591 delete from.outerHeight; 3592 delete from.outerWidth; 3593 element.css( from ); 3594 3595 // Animate the children if desired 3596 if ( scale === "content" || scale === "both" ) { 3597 3598 vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps ); 3599 hProps = hProps.concat( [ "marginLeft", "marginRight" ] ); 3600 3601 // Only animate children with width attributes specified 3602 // TODO: is this right? should we include anything with css width specified as well 3603 element.find( "*[width]" ).each( function() { 3604 var child = $( this ), 3605 childOriginal = $.effects.scaledDimensions( child ), 3606 childFrom = { 3607 height: childOriginal.height * factor.from.y, 3608 width: childOriginal.width * factor.from.x, 3609 outerHeight: childOriginal.outerHeight * factor.from.y, 3610 outerWidth: childOriginal.outerWidth * factor.from.x 3611 }, 3612 childTo = { 3613 height: childOriginal.height * factor.to.y, 3614 width: childOriginal.width * factor.to.x, 3615 outerHeight: childOriginal.height * factor.to.y, 3616 outerWidth: childOriginal.width * factor.to.x 3617 }; 3618 3619 // Vertical props scaling 3620 if ( factor.from.y !== factor.to.y ) { 3621 childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom ); 3622 childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo ); 3623 } 3624 3625 // Horizontal props scaling 3626 if ( factor.from.x !== factor.to.x ) { 3627 childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom ); 3628 childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo ); 3629 } 3630 3631 if ( restore ) { 3632 $.effects.saveStyle( child ); 3633 } 3634 3635 // Animate children 3636 child.css( childFrom ); 3637 child.animate( childTo, options.duration, options.easing, function() { 3638 3639 // Restore children 3640 if ( restore ) { 3641 $.effects.restoreStyle( child ); 3642 } 3643 } ); 3644 } ); 3645 } 3646 3647 // Animate 3648 element.animate( to, { 3649 queue: false, 3650 duration: options.duration, 3651 easing: options.easing, 3652 complete: function() { 3653 3654 var offset = element.offset(); 3655 3656 if ( to.opacity === 0 ) { 3657 element.css( "opacity", from.opacity ); 3658 } 3659 3660 if ( !restore ) { 3661 element 3662 .css( "position", position === "static" ? "relative" : position ) 3663 .offset( offset ); 3664 3665 // Need to save style here so that automatic style restoration 3666 // doesn't restore to the original styles from before the animation. 3667 $.effects.saveStyle( element ); 3668 } 3669 3670 done(); 3671 } 3672 } ); 3673 3674} ); 3675 3676 3677/*! 3678 * jQuery UI Effects Scale 1.13.3 3679 * https://jqueryui.com 3680 * 3681 * Copyright OpenJS Foundation and other contributors 3682 * Released under the MIT license. 3683 * https://jquery.org/license 3684 */ 3685 3686//>>label: Scale Effect 3687//>>group: Effects 3688//>>description: Grows or shrinks an element and its content. 3689//>>docs: https://api.jqueryui.com/scale-effect/ 3690//>>demos: https://jqueryui.com/effect/ 3691 3692 3693var effectsEffectScale = $.effects.define( "scale", function( options, done ) { 3694 3695 // Create element 3696 var el = $( this ), 3697 mode = options.mode, 3698 percent = parseInt( options.percent, 10 ) || 3699 ( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ), 3700 3701 newOptions = $.extend( true, { 3702 from: $.effects.scaledDimensions( el ), 3703 to: $.effects.scaledDimensions( el, percent, options.direction || "both" ), 3704 origin: options.origin || [ "middle", "center" ] 3705 }, options ); 3706 3707 // Fade option to support puff 3708 if ( options.fade ) { 3709 newOptions.from.opacity = 1; 3710 newOptions.to.opacity = 0; 3711 } 3712 3713 $.effects.effect.size.call( this, newOptions, done ); 3714} ); 3715 3716 3717/*! 3718 * jQuery UI Effects Puff 1.13.3 3719 * https://jqueryui.com 3720 * 3721 * Copyright OpenJS Foundation and other contributors 3722 * Released under the MIT license. 3723 * https://jquery.org/license 3724 */ 3725 3726//>>label: Puff Effect 3727//>>group: Effects 3728//>>description: Creates a puff effect by scaling the element up and hiding it at the same time. 3729//>>docs: https://api.jqueryui.com/puff-effect/ 3730//>>demos: https://jqueryui.com/effect/ 3731 3732 3733var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) { 3734 var newOptions = $.extend( true, {}, options, { 3735 fade: true, 3736 percent: parseInt( options.percent, 10 ) || 150 3737 } ); 3738 3739 $.effects.effect.scale.call( this, newOptions, done ); 3740} ); 3741 3742 3743/*! 3744 * jQuery UI Effects Pulsate 1.13.3 3745 * https://jqueryui.com 3746 * 3747 * Copyright OpenJS Foundation and other contributors 3748 * Released under the MIT license. 3749 * https://jquery.org/license 3750 */ 3751 3752//>>label: Pulsate Effect 3753//>>group: Effects 3754//>>description: Pulsates an element n times by changing the opacity to zero and back. 3755//>>docs: https://api.jqueryui.com/pulsate-effect/ 3756//>>demos: https://jqueryui.com/effect/ 3757 3758 3759var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) { 3760 var element = $( this ), 3761 mode = options.mode, 3762 show = mode === "show", 3763 hide = mode === "hide", 3764 showhide = show || hide, 3765 3766 // Showing or hiding leaves off the "last" animation 3767 anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), 3768 duration = options.duration / anims, 3769 animateTo = 0, 3770 i = 1, 3771 queuelen = element.queue().length; 3772 3773 if ( show || !element.is( ":visible" ) ) { 3774 element.css( "opacity", 0 ).show(); 3775 animateTo = 1; 3776 } 3777 3778 // Anims - 1 opacity "toggles" 3779 for ( ; i < anims; i++ ) { 3780 element.animate( { opacity: animateTo }, duration, options.easing ); 3781 animateTo = 1 - animateTo; 3782 } 3783 3784 element.animate( { opacity: animateTo }, duration, options.easing ); 3785 3786 element.queue( done ); 3787 3788 $.effects.unshift( element, queuelen, anims + 1 ); 3789} ); 3790 3791 3792/*! 3793 * jQuery UI Effects Shake 1.13.3 3794 * https://jqueryui.com 3795 * 3796 * Copyright OpenJS Foundation and other contributors 3797 * Released under the MIT license. 3798 * https://jquery.org/license 3799 */ 3800 3801//>>label: Shake Effect 3802//>>group: Effects 3803//>>description: Shakes an element horizontally or vertically n times. 3804//>>docs: https://api.jqueryui.com/shake-effect/ 3805//>>demos: https://jqueryui.com/effect/ 3806 3807 3808var effectsEffectShake = $.effects.define( "shake", function( options, done ) { 3809 3810 var i = 1, 3811 element = $( this ), 3812 direction = options.direction || "left", 3813 distance = options.distance || 20, 3814 times = options.times || 3, 3815 anims = times * 2 + 1, 3816 speed = Math.round( options.duration / anims ), 3817 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 3818 positiveMotion = ( direction === "up" || direction === "left" ), 3819 animation = {}, 3820 animation1 = {}, 3821 animation2 = {}, 3822 3823 queuelen = element.queue().length; 3824 3825 $.effects.createPlaceholder( element ); 3826 3827 // Animation 3828 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; 3829 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; 3830 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; 3831 3832 // Animate 3833 element.animate( animation, speed, options.easing ); 3834 3835 // Shakes 3836 for ( ; i < times; i++ ) { 3837 element 3838 .animate( animation1, speed, options.easing ) 3839 .animate( animation2, speed, options.easing ); 3840 } 3841 3842 element 3843 .animate( animation1, speed, options.easing ) 3844 .animate( animation, speed / 2, options.easing ) 3845 .queue( done ); 3846 3847 $.effects.unshift( element, queuelen, anims + 1 ); 3848} ); 3849 3850 3851/*! 3852 * jQuery UI Effects Slide 1.13.3 3853 * https://jqueryui.com 3854 * 3855 * Copyright OpenJS Foundation and other contributors 3856 * Released under the MIT license. 3857 * https://jquery.org/license 3858 */ 3859 3860//>>label: Slide Effect 3861//>>group: Effects 3862//>>description: Slides an element in and out of the viewport. 3863//>>docs: https://api.jqueryui.com/slide-effect/ 3864//>>demos: https://jqueryui.com/effect/ 3865 3866 3867var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) { 3868 var startClip, startRef, 3869 element = $( this ), 3870 map = { 3871 up: [ "bottom", "top" ], 3872 down: [ "top", "bottom" ], 3873 left: [ "right", "left" ], 3874 right: [ "left", "right" ] 3875 }, 3876 mode = options.mode, 3877 direction = options.direction || "left", 3878 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 3879 positiveMotion = ( direction === "up" || direction === "left" ), 3880 distance = options.distance || 3881 element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ), 3882 animation = {}; 3883 3884 $.effects.createPlaceholder( element ); 3885 3886 startClip = element.cssClip(); 3887 startRef = element.position()[ ref ]; 3888 3889 // Define hide animation 3890 animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef; 3891 animation.clip = element.cssClip(); 3892 animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ]; 3893 3894 // Reverse the animation if we're showing 3895 if ( mode === "show" ) { 3896 element.cssClip( animation.clip ); 3897 element.css( ref, animation[ ref ] ); 3898 animation.clip = startClip; 3899 animation[ ref ] = startRef; 3900 } 3901 3902 // Actually animate 3903 element.animate( animation, { 3904 queue: false, 3905 duration: options.duration, 3906 easing: options.easing, 3907 complete: done 3908 } ); 3909} ); 3910 3911 3912/*! 3913 * jQuery UI Effects Transfer 1.13.3 3914 * https://jqueryui.com 3915 * 3916 * Copyright OpenJS Foundation and other contributors 3917 * Released under the MIT license. 3918 * https://jquery.org/license 3919 */ 3920 3921//>>label: Transfer Effect 3922//>>group: Effects 3923//>>description: Displays a transfer effect from one element to another. 3924//>>docs: https://api.jqueryui.com/transfer-effect/ 3925//>>demos: https://jqueryui.com/effect/ 3926 3927 3928var effect; 3929if ( $.uiBackCompat !== false ) { 3930 effect = $.effects.define( "transfer", function( options, done ) { 3931 $( this ).transfer( options, done ); 3932 } ); 3933} 3934var effectsEffectTransfer = effect; 3935 3936 3937/*! 3938 * jQuery UI Focusable 1.13.3 3939 * https://jqueryui.com 3940 * 3941 * Copyright OpenJS Foundation and other contributors 3942 * Released under the MIT license. 3943 * https://jquery.org/license 3944 */ 3945 3946//>>label: :focusable Selector 3947//>>group: Core 3948//>>description: Selects elements which can be focused. 3949//>>docs: https://api.jqueryui.com/focusable-selector/ 3950 3951 3952// Selectors 3953$.ui.focusable = function( element, hasTabindex ) { 3954 var map, mapName, img, focusableIfVisible, fieldset, 3955 nodeName = element.nodeName.toLowerCase(); 3956 3957 if ( "area" === nodeName ) { 3958 map = element.parentNode; 3959 mapName = map.name; 3960 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { 3961 return false; 3962 } 3963 img = $( "img[usemap='#" + mapName + "']" ); 3964 return img.length > 0 && img.is( ":visible" ); 3965 } 3966 3967 if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) { 3968 focusableIfVisible = !element.disabled; 3969 3970 if ( focusableIfVisible ) { 3971 3972 // Form controls within a disabled fieldset are disabled. 3973 // However, controls within the fieldset's legend do not get disabled. 3974 // Since controls generally aren't placed inside legends, we skip 3975 // this portion of the check. 3976 fieldset = $( element ).closest( "fieldset" )[ 0 ]; 3977 if ( fieldset ) { 3978 focusableIfVisible = !fieldset.disabled; 3979 } 3980 } 3981 } else if ( "a" === nodeName ) { 3982 focusableIfVisible = element.href || hasTabindex; 3983 } else { 3984 focusableIfVisible = hasTabindex; 3985 } 3986 3987 return focusableIfVisible && $( element ).is( ":visible" ) && visible( $( element ) ); 3988}; 3989 3990// Support: IE 8 only 3991// IE 8 doesn't resolve inherit to visible/hidden for computed values 3992function visible( element ) { 3993 var visibility = element.css( "visibility" ); 3994 while ( visibility === "inherit" ) { 3995 element = element.parent(); 3996 visibility = element.css( "visibility" ); 3997 } 3998 return visibility === "visible"; 3999} 4000 4001$.extend( $.expr.pseudos, { 4002 focusable: function( element ) { 4003 return $.ui.focusable( element, $.attr( element, "tabindex" ) != null ); 4004 } 4005} ); 4006 4007var focusable = $.ui.focusable; 4008 4009 4010 4011// Support: IE8 Only 4012// IE8 does not support the form attribute and when it is supplied. It overwrites the form prop 4013// with a string, so we need to find the proper form. 4014var form = $.fn._form = function() { 4015 return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form ); 4016}; 4017 4018 4019/*! 4020 * jQuery UI Form Reset Mixin 1.13.3 4021 * https://jqueryui.com 4022 * 4023 * Copyright OpenJS Foundation and other contributors 4024 * Released under the MIT license. 4025 * https://jquery.org/license 4026 */ 4027 4028//>>label: Form Reset Mixin 4029//>>group: Core 4030//>>description: Refresh input widgets when their form is reset 4031//>>docs: https://api.jqueryui.com/form-reset-mixin/ 4032 4033 4034var formResetMixin = $.ui.formResetMixin = { 4035 _formResetHandler: function() { 4036 var form = $( this ); 4037 4038 // Wait for the form reset to actually happen before refreshing 4039 setTimeout( function() { 4040 var instances = form.data( "ui-form-reset-instances" ); 4041 $.each( instances, function() { 4042 this.refresh(); 4043 } ); 4044 } ); 4045 }, 4046 4047 _bindFormResetHandler: function() { 4048 this.form = this.element._form(); 4049 if ( !this.form.length ) { 4050 return; 4051 } 4052 4053 var instances = this.form.data( "ui-form-reset-instances" ) || []; 4054 if ( !instances.length ) { 4055 4056 // We don't use _on() here because we use a single event handler per form 4057 this.form.on( "reset.ui-form-reset", this._formResetHandler ); 4058 } 4059 instances.push( this ); 4060 this.form.data( "ui-form-reset-instances", instances ); 4061 }, 4062 4063 _unbindFormResetHandler: function() { 4064 if ( !this.form.length ) { 4065 return; 4066 } 4067 4068 var instances = this.form.data( "ui-form-reset-instances" ); 4069 instances.splice( $.inArray( this, instances ), 1 ); 4070 if ( instances.length ) { 4071 this.form.data( "ui-form-reset-instances", instances ); 4072 } else { 4073 this.form 4074 .removeData( "ui-form-reset-instances" ) 4075 .off( "reset.ui-form-reset" ); 4076 } 4077 } 4078}; 4079 4080 4081/*! 4082 * jQuery UI Support for jQuery core 1.8.x and newer 1.13.3 4083 * https://jqueryui.com 4084 * 4085 * Copyright OpenJS Foundation and other contributors 4086 * Released under the MIT license. 4087 * https://jquery.org/license 4088 * 4089 */ 4090 4091//>>label: jQuery 1.8+ Support 4092//>>group: Core 4093//>>description: Support version 1.8.x and newer of jQuery core 4094 4095 4096// Support: jQuery 1.9.x or older 4097// $.expr[ ":" ] is deprecated. 4098if ( !$.expr.pseudos ) { 4099 $.expr.pseudos = $.expr[ ":" ]; 4100} 4101 4102// Support: jQuery 1.11.x or older 4103// $.unique has been renamed to $.uniqueSort 4104if ( !$.uniqueSort ) { 4105 $.uniqueSort = $.unique; 4106} 4107 4108// Support: jQuery 2.2.x or older. 4109// This method has been defined in jQuery 3.0.0. 4110// Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js 4111if ( !$.escapeSelector ) { 4112 4113 // CSS string/identifier serialization 4114 // https://drafts.csswg.org/cssom/#common-serializing-idioms 4115 var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g; 4116 4117 var fcssescape = function( ch, asCodePoint ) { 4118 if ( asCodePoint ) { 4119 4120 // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER 4121 if ( ch === "\0" ) { 4122 return "\uFFFD"; 4123 } 4124 4125 // Control characters and (dependent upon position) numbers get escaped as code points 4126 return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; 4127 } 4128 4129 // Other potentially-special ASCII characters get backslash-escaped 4130 return "\\" + ch; 4131 }; 4132 4133 $.escapeSelector = function( sel ) { 4134 return ( sel + "" ).replace( rcssescape, fcssescape ); 4135 }; 4136} 4137 4138// Support: jQuery 3.4.x or older 4139// These methods have been defined in jQuery 3.5.0. 4140if ( !$.fn.even || !$.fn.odd ) { 4141 $.fn.extend( { 4142 even: function() { 4143 return this.filter( function( i ) { 4144 return i % 2 === 0; 4145 } ); 4146 }, 4147 odd: function() { 4148 return this.filter( function( i ) { 4149 return i % 2 === 1; 4150 } ); 4151 } 4152 } ); 4153} 4154 4155; 4156/*! 4157 * jQuery UI Keycode 1.13.3 4158 * https://jqueryui.com 4159 * 4160 * Copyright OpenJS Foundation and other contributors 4161 * Released under the MIT license. 4162 * https://jquery.org/license 4163 */ 4164 4165//>>label: Keycode 4166//>>group: Core 4167//>>description: Provide keycodes as keynames 4168//>>docs: https://api.jqueryui.com/jQuery.ui.keyCode/ 4169 4170 4171var keycode = $.ui.keyCode = { 4172 BACKSPACE: 8, 4173 COMMA: 188, 4174 DELETE: 46, 4175 DOWN: 40, 4176 END: 35, 4177 ENTER: 13, 4178 ESCAPE: 27, 4179 HOME: 36, 4180 LEFT: 37, 4181 PAGE_DOWN: 34, 4182 PAGE_UP: 33, 4183 PERIOD: 190, 4184 RIGHT: 39, 4185 SPACE: 32, 4186 TAB: 9, 4187 UP: 38 4188}; 4189 4190 4191/*! 4192 * jQuery UI Labels 1.13.3 4193 * https://jqueryui.com 4194 * 4195 * Copyright OpenJS Foundation and other contributors 4196 * Released under the MIT license. 4197 * https://jquery.org/license 4198 */ 4199 4200//>>label: labels 4201//>>group: Core 4202//>>description: Find all the labels associated with a given input 4203//>>docs: https://api.jqueryui.com/labels/ 4204 4205 4206var labels = $.fn.labels = function() { 4207 var ancestor, selector, id, labels, ancestors; 4208 4209 if ( !this.length ) { 4210 return this.pushStack( [] ); 4211 } 4212 4213 // Check control.labels first 4214 if ( this[ 0 ].labels && this[ 0 ].labels.length ) { 4215 return this.pushStack( this[ 0 ].labels ); 4216 } 4217 4218 // Support: IE <= 11, FF <= 37, Android <= 2.3 only 4219 // Above browsers do not support control.labels. Everything below is to support them 4220 // as well as document fragments. control.labels does not work on document fragments 4221 labels = this.eq( 0 ).parents( "label" ); 4222 4223 // Look for the label based on the id 4224 id = this.attr( "id" ); 4225 if ( id ) { 4226 4227 // We don't search against the document in case the element 4228 // is disconnected from the DOM 4229 ancestor = this.eq( 0 ).parents().last(); 4230 4231 // Get a full set of top level ancestors 4232 ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() ); 4233 4234 // Create a selector for the label based on the id 4235 selector = "label[for='" + $.escapeSelector( id ) + "']"; 4236 4237 labels = labels.add( ancestors.find( selector ).addBack( selector ) ); 4238 4239 } 4240 4241 // Return whatever we have found for labels 4242 return this.pushStack( labels ); 4243}; 4244 4245 4246/*! 4247 * jQuery UI Scroll Parent 1.13.3 4248 * https://jqueryui.com 4249 * 4250 * Copyright OpenJS Foundation and other contributors 4251 * Released under the MIT license. 4252 * https://jquery.org/license 4253 */ 4254 4255//>>label: scrollParent 4256//>>group: Core 4257//>>description: Get the closest ancestor element that is scrollable. 4258//>>docs: https://api.jqueryui.com/scrollParent/ 4259 4260 4261var scrollParent = $.fn.scrollParent = function( includeHidden ) { 4262 var position = this.css( "position" ), 4263 excludeStaticParent = position === "absolute", 4264 overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/, 4265 scrollParent = this.parents().filter( function() { 4266 var parent = $( this ); 4267 if ( excludeStaticParent && parent.css( "position" ) === "static" ) { 4268 return false; 4269 } 4270 return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + 4271 parent.css( "overflow-x" ) ); 4272 } ).eq( 0 ); 4273 4274 return position === "fixed" || !scrollParent.length ? 4275 $( this[ 0 ].ownerDocument || document ) : 4276 scrollParent; 4277}; 4278 4279 4280/*! 4281 * jQuery UI Tabbable 1.13.3 4282 * https://jqueryui.com 4283 * 4284 * Copyright OpenJS Foundation and other contributors 4285 * Released under the MIT license. 4286 * https://jquery.org/license 4287 */ 4288 4289//>>label: :tabbable Selector 4290//>>group: Core 4291//>>description: Selects elements which can be tabbed to. 4292//>>docs: https://api.jqueryui.com/tabbable-selector/ 4293 4294 4295var tabbable = $.extend( $.expr.pseudos, { 4296 tabbable: function( element ) { 4297 var tabIndex = $.attr( element, "tabindex" ), 4298 hasTabindex = tabIndex != null; 4299 return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex ); 4300 } 4301} ); 4302 4303 4304/*! 4305 * jQuery UI Unique ID 1.13.3 4306 * https://jqueryui.com 4307 * 4308 * Copyright OpenJS Foundation and other contributors 4309 * Released under the MIT license. 4310 * https://jquery.org/license 4311 */ 4312 4313//>>label: uniqueId 4314//>>group: Core 4315//>>description: Functions to generate and remove uniqueId's 4316//>>docs: https://api.jqueryui.com/uniqueId/ 4317 4318 4319var uniqueId = $.fn.extend( { 4320 uniqueId: ( function() { 4321 var uuid = 0; 4322 4323 return function() { 4324 return this.each( function() { 4325 if ( !this.id ) { 4326 this.id = "ui-id-" + ( ++uuid ); 4327 } 4328 } ); 4329 }; 4330 } )(), 4331 4332 removeUniqueId: function() { 4333 return this.each( function() { 4334 if ( /^ui-id-\d+$/.test( this.id ) ) { 4335 $( this ).removeAttr( "id" ); 4336 } 4337 } ); 4338 } 4339} ); 4340 4341 4342/*! 4343 * jQuery UI Accordion 1.13.3 4344 * https://jqueryui.com 4345 * 4346 * Copyright OpenJS Foundation and other contributors 4347 * Released under the MIT license. 4348 * https://jquery.org/license 4349 */ 4350 4351//>>label: Accordion 4352//>>group: Widgets 4353/* eslint-disable max-len */ 4354//>>description: Displays collapsible content panels for presenting information in a limited amount of space. 4355/* eslint-enable max-len */ 4356//>>docs: https://api.jqueryui.com/accordion/ 4357//>>demos: https://jqueryui.com/accordion/ 4358//>>css.structure: ../../themes/base/core.css 4359//>>css.structure: ../../themes/base/accordion.css 4360//>>css.theme: ../../themes/base/theme.css 4361 4362 4363var widgetsAccordion = $.widget( "ui.accordion", { 4364 version: "1.13.3", 4365 options: { 4366 active: 0, 4367 animate: {}, 4368 classes: { 4369 "ui-accordion-header": "ui-corner-top", 4370 "ui-accordion-header-collapsed": "ui-corner-all", 4371 "ui-accordion-content": "ui-corner-bottom" 4372 }, 4373 collapsible: false, 4374 event: "click", 4375 header: function( elem ) { 4376 return elem.find( "> li > :first-child" ).add( elem.find( "> :not(li)" ).even() ); 4377 }, 4378 heightStyle: "auto", 4379 icons: { 4380 activeHeader: "ui-icon-triangle-1-s", 4381 header: "ui-icon-triangle-1-e" 4382 }, 4383 4384 // Callbacks 4385 activate: null, 4386 beforeActivate: null 4387 }, 4388 4389 hideProps: { 4390 borderTopWidth: "hide", 4391 borderBottomWidth: "hide", 4392 paddingTop: "hide", 4393 paddingBottom: "hide", 4394 height: "hide" 4395 }, 4396 4397 showProps: { 4398 borderTopWidth: "show", 4399 borderBottomWidth: "show", 4400 paddingTop: "show", 4401 paddingBottom: "show", 4402 height: "show" 4403 }, 4404 4405 _create: function() { 4406 var options = this.options; 4407 4408 this.prevShow = this.prevHide = $(); 4409 this._addClass( "ui-accordion", "ui-widget ui-helper-reset" ); 4410 this.element.attr( "role", "tablist" ); 4411 4412 // Don't allow collapsible: false and active: false / null 4413 if ( !options.collapsible && ( options.active === false || options.active == null ) ) { 4414 options.active = 0; 4415 } 4416 4417 this._processPanels(); 4418 4419 // handle negative values 4420 if ( options.active < 0 ) { 4421 options.active += this.headers.length; 4422 } 4423 this._refresh(); 4424 }, 4425 4426 _getCreateEventData: function() { 4427 return { 4428 header: this.active, 4429 panel: !this.active.length ? $() : this.active.next() 4430 }; 4431 }, 4432 4433 _createIcons: function() { 4434 var icon, children, 4435 icons = this.options.icons; 4436 4437 if ( icons ) { 4438 icon = $( "<span>" ); 4439 this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header ); 4440 icon.prependTo( this.headers ); 4441 children = this.active.children( ".ui-accordion-header-icon" ); 4442 this._removeClass( children, icons.header ) 4443 ._addClass( children, null, icons.activeHeader ) 4444 ._addClass( this.headers, "ui-accordion-icons" ); 4445 } 4446 }, 4447 4448 _destroyIcons: function() { 4449 this._removeClass( this.headers, "ui-accordion-icons" ); 4450 this.headers.children( ".ui-accordion-header-icon" ).remove(); 4451 }, 4452 4453 _destroy: function() { 4454 var contents; 4455 4456 // Clean up main element 4457 this.element.removeAttr( "role" ); 4458 4459 // Clean up headers 4460 this.headers 4461 .removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" ) 4462 .removeUniqueId(); 4463 4464 this._destroyIcons(); 4465 4466 // Clean up content panels 4467 contents = this.headers.next() 4468 .css( "display", "" ) 4469 .removeAttr( "role aria-hidden aria-labelledby" ) 4470 .removeUniqueId(); 4471 4472 if ( this.options.heightStyle !== "content" ) { 4473 contents.css( "height", "" ); 4474 } 4475 }, 4476 4477 _setOption: function( key, value ) { 4478 if ( key === "active" ) { 4479 4480 // _activate() will handle invalid values and update this.options 4481 this._activate( value ); 4482 return; 4483 } 4484 4485 if ( key === "event" ) { 4486 if ( this.options.event ) { 4487 this._off( this.headers, this.options.event ); 4488 } 4489 this._setupEvents( value ); 4490 } 4491 4492 this._super( key, value ); 4493 4494 // Setting collapsible: false while collapsed; open first panel 4495 if ( key === "collapsible" && !value && this.options.active === false ) { 4496 this._activate( 0 ); 4497 } 4498 4499 if ( key === "icons" ) { 4500 this._destroyIcons(); 4501 if ( value ) { 4502 this._createIcons(); 4503 } 4504 } 4505 }, 4506 4507 _setOptionDisabled: function( value ) { 4508 this._super( value ); 4509 4510 this.element.attr( "aria-disabled", value ); 4511 4512 // Support: IE8 Only 4513 // #5332 / #6059 - opacity doesn't cascade to positioned elements in IE 4514 // so we need to add the disabled class to the headers and panels 4515 this._toggleClass( null, "ui-state-disabled", !!value ); 4516 this._toggleClass( this.headers.add( this.headers.next() ), null, "ui-state-disabled", 4517 !!value ); 4518 }, 4519 4520 _keydown: function( event ) { 4521 if ( event.altKey || event.ctrlKey ) { 4522 return; 4523 } 4524 4525 var keyCode = $.ui.keyCode, 4526 length = this.headers.length, 4527 currentIndex = this.headers.index( event.target ), 4528 toFocus = false; 4529 4530 switch ( event.keyCode ) { 4531 case keyCode.RIGHT: 4532 case keyCode.DOWN: 4533 toFocus = this.headers[ ( currentIndex + 1 ) % length ]; 4534 break; 4535 case keyCode.LEFT: 4536 case keyCode.UP: 4537 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; 4538 break; 4539 case keyCode.SPACE: 4540 case keyCode.ENTER: 4541 this._eventHandler( event ); 4542 break; 4543 case keyCode.HOME: 4544 toFocus = this.headers[ 0 ]; 4545 break; 4546 case keyCode.END: 4547 toFocus = this.headers[ length - 1 ]; 4548 break; 4549 } 4550 4551 if ( toFocus ) { 4552 $( event.target ).attr( "tabIndex", -1 ); 4553 $( toFocus ).attr( "tabIndex", 0 ); 4554 $( toFocus ).trigger( "focus" ); 4555 event.preventDefault(); 4556 } 4557 }, 4558 4559 _panelKeyDown: function( event ) { 4560 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { 4561 $( event.currentTarget ).prev().trigger( "focus" ); 4562 } 4563 }, 4564 4565 refresh: function() { 4566 var options = this.options; 4567 this._processPanels(); 4568 4569 // Was collapsed or no panel 4570 if ( ( options.active === false && options.collapsible === true ) || 4571 !this.headers.length ) { 4572 options.active = false; 4573 this.active = $(); 4574 4575 // active false only when collapsible is true 4576 } else if ( options.active === false ) { 4577 this._activate( 0 ); 4578 4579 // was active, but active panel is gone 4580 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 4581 4582 // all remaining panel are disabled 4583 if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) { 4584 options.active = false; 4585 this.active = $(); 4586 4587 // activate previous panel 4588 } else { 4589 this._activate( Math.max( 0, options.active - 1 ) ); 4590 } 4591 4592 // was active, active panel still exists 4593 } else { 4594 4595 // make sure active index is correct 4596 options.active = this.headers.index( this.active ); 4597 } 4598 4599 this._destroyIcons(); 4600 4601 this._refresh(); 4602 }, 4603 4604 _processPanels: function() { 4605 var prevHeaders = this.headers, 4606 prevPanels = this.panels; 4607 4608 if ( typeof this.options.header === "function" ) { 4609 this.headers = this.options.header( this.element ); 4610 } else { 4611 this.headers = this.element.find( this.options.header ); 4612 } 4613 this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed", 4614 "ui-state-default" ); 4615 4616 this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide(); 4617 this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" ); 4618 4619 // Avoid memory leaks (#10056) 4620 if ( prevPanels ) { 4621 this._off( prevHeaders.not( this.headers ) ); 4622 this._off( prevPanels.not( this.panels ) ); 4623 } 4624 }, 4625 4626 _refresh: function() { 4627 var maxHeight, 4628 options = this.options, 4629 heightStyle = options.heightStyle, 4630 parent = this.element.parent(); 4631 4632 this.active = this._findActive( options.active ); 4633 this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" ) 4634 ._removeClass( this.active, "ui-accordion-header-collapsed" ); 4635 this._addClass( this.active.next(), "ui-accordion-content-active" ); 4636 this.active.next().show(); 4637 4638 this.headers 4639 .attr( "role", "tab" ) 4640 .each( function() { 4641 var header = $( this ), 4642 headerId = header.uniqueId().attr( "id" ), 4643 panel = header.next(), 4644 panelId = panel.uniqueId().attr( "id" ); 4645 header.attr( "aria-controls", panelId ); 4646 panel.attr( "aria-labelledby", headerId ); 4647 } ) 4648 .next() 4649 .attr( "role", "tabpanel" ); 4650 4651 this.headers 4652 .not( this.active ) 4653 .attr( { 4654 "aria-selected": "false", 4655 "aria-expanded": "false", 4656 tabIndex: -1 4657 } ) 4658 .next() 4659 .attr( { 4660 "aria-hidden": "true" 4661 } ) 4662 .hide(); 4663 4664 // Make sure at least one header is in the tab order 4665 if ( !this.active.length ) { 4666 this.headers.eq( 0 ).attr( "tabIndex", 0 ); 4667 } else { 4668 this.active.attr( { 4669 "aria-selected": "true", 4670 "aria-expanded": "true", 4671 tabIndex: 0 4672 } ) 4673 .next() 4674 .attr( { 4675 "aria-hidden": "false" 4676 } ); 4677 } 4678 4679 this._createIcons(); 4680 4681 this._setupEvents( options.event ); 4682 4683 if ( heightStyle === "fill" ) { 4684 maxHeight = parent.height(); 4685 this.element.siblings( ":visible" ).each( function() { 4686 var elem = $( this ), 4687 position = elem.css( "position" ); 4688 4689 if ( position === "absolute" || position === "fixed" ) { 4690 return; 4691 } 4692 maxHeight -= elem.outerHeight( true ); 4693 } ); 4694 4695 this.headers.each( function() { 4696 maxHeight -= $( this ).outerHeight( true ); 4697 } ); 4698 4699 this.headers.next() 4700 .each( function() { 4701 $( this ).height( Math.max( 0, maxHeight - 4702 $( this ).innerHeight() + $( this ).height() ) ); 4703 } ) 4704 .css( "overflow", "auto" ); 4705 } else if ( heightStyle === "auto" ) { 4706 maxHeight = 0; 4707 this.headers.next() 4708 .each( function() { 4709 var isVisible = $( this ).is( ":visible" ); 4710 if ( !isVisible ) { 4711 $( this ).show(); 4712 } 4713 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); 4714 if ( !isVisible ) { 4715 $( this ).hide(); 4716 } 4717 } ) 4718 .height( maxHeight ); 4719 } 4720 }, 4721 4722 _activate: function( index ) { 4723 var active = this._findActive( index )[ 0 ]; 4724 4725 // Trying to activate the already active panel 4726 if ( active === this.active[ 0 ] ) { 4727 return; 4728 } 4729 4730 // Trying to collapse, simulate a click on the currently active header 4731 active = active || this.active[ 0 ]; 4732 4733 this._eventHandler( { 4734 target: active, 4735 currentTarget: active, 4736 preventDefault: $.noop 4737 } ); 4738 }, 4739 4740 _findActive: function( selector ) { 4741 return typeof selector === "number" ? this.headers.eq( selector ) : $(); 4742 }, 4743 4744 _setupEvents: function( event ) { 4745 var events = { 4746 keydown: "_keydown" 4747 }; 4748 if ( event ) { 4749 $.each( event.split( " " ), function( index, eventName ) { 4750 events[ eventName ] = "_eventHandler"; 4751 } ); 4752 } 4753 4754 this._off( this.headers.add( this.headers.next() ) ); 4755 this._on( this.headers, events ); 4756 this._on( this.headers.next(), { keydown: "_panelKeyDown" } ); 4757 this._hoverable( this.headers ); 4758 this._focusable( this.headers ); 4759 }, 4760 4761 _eventHandler: function( event ) { 4762 var activeChildren, clickedChildren, 4763 options = this.options, 4764 active = this.active, 4765 clicked = $( event.currentTarget ), 4766 clickedIsActive = clicked[ 0 ] === active[ 0 ], 4767 collapsing = clickedIsActive && options.collapsible, 4768 toShow = collapsing ? $() : clicked.next(), 4769 toHide = active.next(), 4770 eventData = { 4771 oldHeader: active, 4772 oldPanel: toHide, 4773 newHeader: collapsing ? $() : clicked, 4774 newPanel: toShow 4775 }; 4776 4777 event.preventDefault(); 4778 4779 if ( 4780 4781 // click on active header, but not collapsible 4782 ( clickedIsActive && !options.collapsible ) || 4783 4784 // allow canceling activation 4785 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 4786 return; 4787 } 4788 4789 options.active = collapsing ? false : this.headers.index( clicked ); 4790 4791 // When the call to ._toggle() comes after the class changes 4792 // it causes a very odd bug in IE 8 (see #6720) 4793 this.active = clickedIsActive ? $() : clicked; 4794 this._toggle( eventData ); 4795 4796 // Switch classes 4797 // corner classes on the previously active header stay after the animation 4798 this._removeClass( active, "ui-accordion-header-active", "ui-state-active" ); 4799 if ( options.icons ) { 4800 activeChildren = active.children( ".ui-accordion-header-icon" ); 4801 this._removeClass( activeChildren, null, options.icons.activeHeader ) 4802 ._addClass( activeChildren, null, options.icons.header ); 4803 } 4804 4805 if ( !clickedIsActive ) { 4806 this._removeClass( clicked, "ui-accordion-header-collapsed" ) 4807 ._addClass( clicked, "ui-accordion-header-active", "ui-state-active" ); 4808 if ( options.icons ) { 4809 clickedChildren = clicked.children( ".ui-accordion-header-icon" ); 4810 this._removeClass( clickedChildren, null, options.icons.header ) 4811 ._addClass( clickedChildren, null, options.icons.activeHeader ); 4812 } 4813 4814 this._addClass( clicked.next(), "ui-accordion-content-active" ); 4815 } 4816 }, 4817 4818 _toggle: function( data ) { 4819 var toShow = data.newPanel, 4820 toHide = this.prevShow.length ? this.prevShow : data.oldPanel; 4821 4822 // Handle activating a panel during the animation for another activation 4823 this.prevShow.add( this.prevHide ).stop( true, true ); 4824 this.prevShow = toShow; 4825 this.prevHide = toHide; 4826 4827 if ( this.options.animate ) { 4828 this._animate( toShow, toHide, data ); 4829 } else { 4830 toHide.hide(); 4831 toShow.show(); 4832 this._toggleComplete( data ); 4833 } 4834 4835 toHide.attr( { 4836 "aria-hidden": "true" 4837 } ); 4838 toHide.prev().attr( { 4839 "aria-selected": "false", 4840 "aria-expanded": "false" 4841 } ); 4842 4843 // if we're switching panels, remove the old header from the tab order 4844 // if we're opening from collapsed state, remove the previous header from the tab order 4845 // if we're collapsing, then keep the collapsing header in the tab order 4846 if ( toShow.length && toHide.length ) { 4847 toHide.prev().attr( { 4848 "tabIndex": -1, 4849 "aria-expanded": "false" 4850 } ); 4851 } else if ( toShow.length ) { 4852 this.headers.filter( function() { 4853 return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0; 4854 } ) 4855 .attr( "tabIndex", -1 ); 4856 } 4857 4858 toShow 4859 .attr( "aria-hidden", "false" ) 4860 .prev() 4861 .attr( { 4862 "aria-selected": "true", 4863 "aria-expanded": "true", 4864 tabIndex: 0 4865 } ); 4866 }, 4867 4868 _animate: function( toShow, toHide, data ) { 4869 var total, easing, duration, 4870 that = this, 4871 adjust = 0, 4872 boxSizing = toShow.css( "box-sizing" ), 4873 down = toShow.length && 4874 ( !toHide.length || ( toShow.index() < toHide.index() ) ), 4875 animate = this.options.animate || {}, 4876 options = down && animate.down || animate, 4877 complete = function() { 4878 that._toggleComplete( data ); 4879 }; 4880 4881 if ( typeof options === "number" ) { 4882 duration = options; 4883 } 4884 if ( typeof options === "string" ) { 4885 easing = options; 4886 } 4887 4888 // fall back from options to animation in case of partial down settings 4889 easing = easing || options.easing || animate.easing; 4890 duration = duration || options.duration || animate.duration; 4891 4892 if ( !toHide.length ) { 4893 return toShow.animate( this.showProps, duration, easing, complete ); 4894 } 4895 if ( !toShow.length ) { 4896 return toHide.animate( this.hideProps, duration, easing, complete ); 4897 } 4898 4899 total = toShow.show().outerHeight(); 4900 toHide.animate( this.hideProps, { 4901 duration: duration, 4902 easing: easing, 4903 step: function( now, fx ) { 4904 fx.now = Math.round( now ); 4905 } 4906 } ); 4907 toShow 4908 .hide() 4909 .animate( this.showProps, { 4910 duration: duration, 4911 easing: easing, 4912 complete: complete, 4913 step: function( now, fx ) { 4914 fx.now = Math.round( now ); 4915 if ( fx.prop !== "height" ) { 4916 if ( boxSizing === "content-box" ) { 4917 adjust += fx.now; 4918 } 4919 } else if ( that.options.heightStyle !== "content" ) { 4920 fx.now = Math.round( total - toHide.outerHeight() - adjust ); 4921 adjust = 0; 4922 } 4923 } 4924 } ); 4925 }, 4926 4927 _toggleComplete: function( data ) { 4928 var toHide = data.oldPanel, 4929 prev = toHide.prev(); 4930 4931 this._removeClass( toHide, "ui-accordion-content-active" ); 4932 this._removeClass( prev, "ui-accordion-header-active" ) 4933 ._addClass( prev, "ui-accordion-header-collapsed" ); 4934 4935 // Work around for rendering bug in IE (#5421) 4936 if ( toHide.length ) { 4937 toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className; 4938 } 4939 this._trigger( "activate", null, data ); 4940 } 4941} ); 4942 4943 4944 4945var safeActiveElement = $.ui.safeActiveElement = function( document ) { 4946 var activeElement; 4947 4948 // Support: IE 9 only 4949 // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe> 4950 try { 4951 activeElement = document.activeElement; 4952 } catch ( error ) { 4953 activeElement = document.body; 4954 } 4955 4956 // Support: IE 9 - 11 only 4957 // IE may return null instead of an element 4958 // Interestingly, this only seems to occur when NOT in an iframe 4959 if ( !activeElement ) { 4960 activeElement = document.body; 4961 } 4962 4963 // Support: IE 11 only 4964 // IE11 returns a seemingly empty object in some cases when accessing 4965 // document.activeElement from an <iframe> 4966 if ( !activeElement.nodeName ) { 4967 activeElement = document.body; 4968 } 4969 4970 return activeElement; 4971}; 4972 4973 4974/*! 4975 * jQuery UI Menu 1.13.3 4976 * https://jqueryui.com 4977 * 4978 * Copyright OpenJS Foundation and other contributors 4979 * Released under the MIT license. 4980 * https://jquery.org/license 4981 */ 4982 4983//>>label: Menu 4984//>>group: Widgets 4985//>>description: Creates nestable menus. 4986//>>docs: https://api.jqueryui.com/menu/ 4987//>>demos: https://jqueryui.com/menu/ 4988//>>css.structure: ../../themes/base/core.css 4989//>>css.structure: ../../themes/base/menu.css 4990//>>css.theme: ../../themes/base/theme.css 4991 4992 4993var widgetsMenu = $.widget( "ui.menu", { 4994 version: "1.13.3", 4995 defaultElement: "<ul>", 4996 delay: 300, 4997 options: { 4998 icons: { 4999 submenu: "ui-icon-caret-1-e" 5000 }, 5001 items: "> *", 5002 menus: "ul", 5003 position: { 5004 my: "left top", 5005 at: "right top" 5006 }, 5007 role: "menu", 5008 5009 // Callbacks 5010 blur: null, 5011 focus: null, 5012 select: null 5013 }, 5014 5015 _create: function() { 5016 this.activeMenu = this.element; 5017 5018 // Flag used to prevent firing of the click handler 5019 // as the event bubbles up through nested menus 5020 this.mouseHandled = false; 5021 this.lastMousePosition = { x: null, y: null }; 5022 this.element 5023 .uniqueId() 5024 .attr( { 5025 role: this.options.role, 5026 tabIndex: 0 5027 } ); 5028 5029 this._addClass( "ui-menu", "ui-widget ui-widget-content" ); 5030 this._on( { 5031 5032 // Prevent focus from sticking to links inside menu after clicking 5033 // them (focus should always stay on UL during navigation). 5034 "mousedown .ui-menu-item": function( event ) { 5035 event.preventDefault(); 5036 5037 this._activateItem( event ); 5038 }, 5039 "click .ui-menu-item": function( event ) { 5040 var target = $( event.target ); 5041 var active = $( $.ui.safeActiveElement( this.document[ 0 ] ) ); 5042 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) { 5043 this.select( event ); 5044 5045 // Only set the mouseHandled flag if the event will bubble, see #9469. 5046 if ( !event.isPropagationStopped() ) { 5047 this.mouseHandled = true; 5048 } 5049 5050 // Open submenu on click 5051 if ( target.has( ".ui-menu" ).length ) { 5052 this.expand( event ); 5053 } else if ( !this.element.is( ":focus" ) && 5054 active.closest( ".ui-menu" ).length ) { 5055 5056 // Redirect focus to the menu 5057 this.element.trigger( "focus", [ true ] ); 5058 5059 // If the active item is on the top level, let it stay active. 5060 // Otherwise, blur the active item since it is no longer visible. 5061 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) { 5062 clearTimeout( this.timer ); 5063 } 5064 } 5065 } 5066 }, 5067 "mouseenter .ui-menu-item": "_activateItem", 5068 "mousemove .ui-menu-item": "_activateItem", 5069 mouseleave: "collapseAll", 5070 "mouseleave .ui-menu": "collapseAll", 5071 focus: function( event, keepActiveItem ) { 5072 5073 // If there's already an active item, keep it active 5074 // If not, activate the first item 5075 var item = this.active || this._menuItems().first(); 5076 5077 if ( !keepActiveItem ) { 5078 this.focus( event, item ); 5079 } 5080 }, 5081 blur: function( event ) { 5082 this._delay( function() { 5083 var notContained = !$.contains( 5084 this.element[ 0 ], 5085 $.ui.safeActiveElement( this.document[ 0 ] ) 5086 ); 5087 if ( notContained ) { 5088 this.collapseAll( event ); 5089 } 5090 } ); 5091 }, 5092 keydown: "_keydown" 5093 } ); 5094 5095 this.refresh(); 5096 5097 // Clicks outside of a menu collapse any open menus 5098 this._on( this.document, { 5099 click: function( event ) { 5100 if ( this._closeOnDocumentClick( event ) ) { 5101 this.collapseAll( event, true ); 5102 } 5103 5104 // Reset the mouseHandled flag 5105 this.mouseHandled = false; 5106 } 5107 } ); 5108 }, 5109 5110 _activateItem: function( event ) { 5111 5112 // Ignore mouse events while typeahead is active, see #10458. 5113 // Prevents focusing the wrong item when typeahead causes a scroll while the mouse 5114 // is over an item in the menu 5115 if ( this.previousFilter ) { 5116 return; 5117 } 5118 5119 // If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356) 5120 if ( event.clientX === this.lastMousePosition.x && 5121 event.clientY === this.lastMousePosition.y ) { 5122 return; 5123 } 5124 5125 this.lastMousePosition = { 5126 x: event.clientX, 5127 y: event.clientY 5128 }; 5129 5130 var actualTarget = $( event.target ).closest( ".ui-menu-item" ), 5131 target = $( event.currentTarget ); 5132 5133 // Ignore bubbled events on parent items, see #11641 5134 if ( actualTarget[ 0 ] !== target[ 0 ] ) { 5135 return; 5136 } 5137 5138 // If the item is already active, there's nothing to do 5139 if ( target.is( ".ui-state-active" ) ) { 5140 return; 5141 } 5142 5143 // Remove ui-state-active class from siblings of the newly focused menu item 5144 // to avoid a jump caused by adjacent elements both having a class with a border 5145 this._removeClass( target.siblings().children( ".ui-state-active" ), 5146 null, "ui-state-active" ); 5147 this.focus( event, target ); 5148 }, 5149 5150 _destroy: function() { 5151 var items = this.element.find( ".ui-menu-item" ) 5152 .removeAttr( "role aria-disabled" ), 5153 submenus = items.children( ".ui-menu-item-wrapper" ) 5154 .removeUniqueId() 5155 .removeAttr( "tabIndex role aria-haspopup" ); 5156 5157 // Destroy (sub)menus 5158 this.element 5159 .removeAttr( "aria-activedescendant" ) 5160 .find( ".ui-menu" ).addBack() 5161 .removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " + 5162 "tabIndex" ) 5163 .removeUniqueId() 5164 .show(); 5165 5166 submenus.children().each( function() { 5167 var elem = $( this ); 5168 if ( elem.data( "ui-menu-submenu-caret" ) ) { 5169 elem.remove(); 5170 } 5171 } ); 5172 }, 5173 5174 _keydown: function( event ) { 5175 var match, prev, character, skip, 5176 preventDefault = true; 5177 5178 switch ( event.keyCode ) { 5179 case $.ui.keyCode.PAGE_UP: 5180 this.previousPage( event ); 5181 break; 5182 case $.ui.keyCode.PAGE_DOWN: 5183 this.nextPage( event ); 5184 break; 5185 case $.ui.keyCode.HOME: 5186 this._move( "first", "first", event ); 5187 break; 5188 case $.ui.keyCode.END: 5189 this._move( "last", "last", event ); 5190 break; 5191 case $.ui.keyCode.UP: 5192 this.previous( event ); 5193 break; 5194 case $.ui.keyCode.DOWN: 5195 this.next( event ); 5196 break; 5197 case $.ui.keyCode.LEFT: 5198 this.collapse( event ); 5199 break; 5200 case $.ui.keyCode.RIGHT: 5201 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { 5202 this.expand( event ); 5203 } 5204 break; 5205 case $.ui.keyCode.ENTER: 5206 case $.ui.keyCode.SPACE: 5207 this._activate( event ); 5208 break; 5209 case $.ui.keyCode.ESCAPE: 5210 this.collapse( event ); 5211 break; 5212 default: 5213 preventDefault = false; 5214 prev = this.previousFilter || ""; 5215 skip = false; 5216 5217 // Support number pad values 5218 character = event.keyCode >= 96 && event.keyCode <= 105 ? 5219 ( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode ); 5220 5221 clearTimeout( this.filterTimer ); 5222 5223 if ( character === prev ) { 5224 skip = true; 5225 } else { 5226 character = prev + character; 5227 } 5228 5229 match = this._filterMenuItems( character ); 5230 match = skip && match.index( this.active.next() ) !== -1 ? 5231 this.active.nextAll( ".ui-menu-item" ) : 5232 match; 5233 5234 // If no matches on the current filter, reset to the last character pressed 5235 // to move down the menu to the first item that starts with that character 5236 if ( !match.length ) { 5237 character = String.fromCharCode( event.keyCode ); 5238 match = this._filterMenuItems( character ); 5239 } 5240 5241 if ( match.length ) { 5242 this.focus( event, match ); 5243 this.previousFilter = character; 5244 this.filterTimer = this._delay( function() { 5245 delete this.previousFilter; 5246 }, 1000 ); 5247 } else { 5248 delete this.previousFilter; 5249 } 5250 } 5251 5252 if ( preventDefault ) { 5253 event.preventDefault(); 5254 } 5255 }, 5256 5257 _activate: function( event ) { 5258 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { 5259 if ( this.active.children( "[aria-haspopup='true']" ).length ) { 5260 this.expand( event ); 5261 } else { 5262 this.select( event ); 5263 } 5264 } 5265 }, 5266 5267 refresh: function() { 5268 var menus, items, newSubmenus, newItems, newWrappers, 5269 that = this, 5270 icon = this.options.icons.submenu, 5271 submenus = this.element.find( this.options.menus ); 5272 5273 this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length ); 5274 5275 // Initialize nested menus 5276 newSubmenus = submenus.filter( ":not(.ui-menu)" ) 5277 .hide() 5278 .attr( { 5279 role: this.options.role, 5280 "aria-hidden": "true", 5281 "aria-expanded": "false" 5282 } ) 5283 .each( function() { 5284 var menu = $( this ), 5285 item = menu.prev(), 5286 submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true ); 5287 5288 that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon ); 5289 item 5290 .attr( "aria-haspopup", "true" ) 5291 .prepend( submenuCaret ); 5292 menu.attr( "aria-labelledby", item.attr( "id" ) ); 5293 } ); 5294 5295 this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" ); 5296 5297 menus = submenus.add( this.element ); 5298 items = menus.find( this.options.items ); 5299 5300 // Initialize menu-items containing spaces and/or dashes only as dividers 5301 items.not( ".ui-menu-item" ).each( function() { 5302 var item = $( this ); 5303 if ( that._isDivider( item ) ) { 5304 that._addClass( item, "ui-menu-divider", "ui-widget-content" ); 5305 } 5306 } ); 5307 5308 // Don't refresh list items that are already adapted 5309 newItems = items.not( ".ui-menu-item, .ui-menu-divider" ); 5310 newWrappers = newItems.children() 5311 .not( ".ui-menu" ) 5312 .uniqueId() 5313 .attr( { 5314 tabIndex: -1, 5315 role: this._itemRole() 5316 } ); 5317 this._addClass( newItems, "ui-menu-item" ) 5318 ._addClass( newWrappers, "ui-menu-item-wrapper" ); 5319 5320 // Add aria-disabled attribute to any disabled menu item 5321 items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); 5322 5323 // If the active item has been removed, blur the menu 5324 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 5325 this.blur(); 5326 } 5327 }, 5328 5329 _itemRole: function() { 5330 return { 5331 menu: "menuitem", 5332 listbox: "option" 5333 }[ this.options.role ]; 5334 }, 5335 5336 _setOption: function( key, value ) { 5337 if ( key === "icons" ) { 5338 var icons = this.element.find( ".ui-menu-icon" ); 5339 this._removeClass( icons, null, this.options.icons.submenu ) 5340 ._addClass( icons, null, value.submenu ); 5341 } 5342 this._super( key, value ); 5343 }, 5344 5345 _setOptionDisabled: function( value ) { 5346 this._super( value ); 5347 5348 this.element.attr( "aria-disabled", String( value ) ); 5349 this._toggleClass( null, "ui-state-disabled", !!value ); 5350 }, 5351 5352 focus: function( event, item ) { 5353 var nested, focused, activeParent; 5354 this.blur( event, event && event.type === "focus" ); 5355 5356 this._scrollIntoView( item ); 5357 5358 this.active = item.first(); 5359 5360 focused = this.active.children( ".ui-menu-item-wrapper" ); 5361 this._addClass( focused, null, "ui-state-active" ); 5362 5363 // Only update aria-activedescendant if there's a role 5364 // otherwise we assume focus is managed elsewhere 5365 if ( this.options.role ) { 5366 this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); 5367 } 5368 5369 // Highlight active parent menu item, if any 5370 activeParent = this.active 5371 .parent() 5372 .closest( ".ui-menu-item" ) 5373 .children( ".ui-menu-item-wrapper" ); 5374 this._addClass( activeParent, null, "ui-state-active" ); 5375 5376 if ( event && event.type === "keydown" ) { 5377 this._close(); 5378 } else { 5379 this.timer = this._delay( function() { 5380 this._close(); 5381 }, this.delay ); 5382 } 5383 5384 nested = item.children( ".ui-menu" ); 5385 if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) { 5386 this._startOpening( nested ); 5387 } 5388 this.activeMenu = item.parent(); 5389 5390 this._trigger( "focus", event, { item: item } ); 5391 }, 5392 5393 _scrollIntoView: function( item ) { 5394 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; 5395 if ( this._hasScroll() ) { 5396 borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0; 5397 paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0; 5398 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; 5399 scroll = this.activeMenu.scrollTop(); 5400 elementHeight = this.activeMenu.height(); 5401 itemHeight = item.outerHeight(); 5402 5403 if ( offset < 0 ) { 5404 this.activeMenu.scrollTop( scroll + offset ); 5405 } else if ( offset + itemHeight > elementHeight ) { 5406 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); 5407 } 5408 } 5409 }, 5410 5411 blur: function( event, fromFocus ) { 5412 if ( !fromFocus ) { 5413 clearTimeout( this.timer ); 5414 } 5415 5416 if ( !this.active ) { 5417 return; 5418 } 5419 5420 this._removeClass( this.active.children( ".ui-menu-item-wrapper" ), 5421 null, "ui-state-active" ); 5422 5423 this._trigger( "blur", event, { item: this.active } ); 5424 this.active = null; 5425 }, 5426 5427 _startOpening: function( submenu ) { 5428 clearTimeout( this.timer ); 5429 5430 // Don't open if already open fixes a Firefox bug that caused a .5 pixel 5431 // shift in the submenu position when mousing over the caret icon 5432 if ( submenu.attr( "aria-hidden" ) !== "true" ) { 5433 return; 5434 } 5435 5436 this.timer = this._delay( function() { 5437 this._close(); 5438 this._open( submenu ); 5439 }, this.delay ); 5440 }, 5441 5442 _open: function( submenu ) { 5443 var position = $.extend( { 5444 of: this.active 5445 }, this.options.position ); 5446 5447 clearTimeout( this.timer ); 5448 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) ) 5449 .hide() 5450 .attr( "aria-hidden", "true" ); 5451 5452 submenu 5453 .show() 5454 .removeAttr( "aria-hidden" ) 5455 .attr( "aria-expanded", "true" ) 5456 .position( position ); 5457 }, 5458 5459 collapseAll: function( event, all ) { 5460 clearTimeout( this.timer ); 5461 this.timer = this._delay( function() { 5462 5463 // If we were passed an event, look for the submenu that contains the event 5464 var currentMenu = all ? this.element : 5465 $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); 5466 5467 // If we found no valid submenu ancestor, use the main menu to close all 5468 // sub menus anyway 5469 if ( !currentMenu.length ) { 5470 currentMenu = this.element; 5471 } 5472 5473 this._close( currentMenu ); 5474 5475 this.blur( event ); 5476 5477 // Work around active item staying active after menu is blurred 5478 this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" ); 5479 5480 this.activeMenu = currentMenu; 5481 }, all ? 0 : this.delay ); 5482 }, 5483 5484 // With no arguments, closes the currently active menu - if nothing is active 5485 // it closes all menus. If passed an argument, it will search for menus BELOW 5486 _close: function( startMenu ) { 5487 if ( !startMenu ) { 5488 startMenu = this.active ? this.active.parent() : this.element; 5489 } 5490 5491 startMenu.find( ".ui-menu" ) 5492 .hide() 5493 .attr( "aria-hidden", "true" ) 5494 .attr( "aria-expanded", "false" ); 5495 }, 5496 5497 _closeOnDocumentClick: function( event ) { 5498 return !$( event.target ).closest( ".ui-menu" ).length; 5499 }, 5500 5501 _isDivider: function( item ) { 5502 5503 // Match hyphen, em dash, en dash 5504 return !/[^\-\u2014\u2013\s]/.test( item.text() ); 5505 }, 5506 5507 collapse: function( event ) { 5508 var newItem = this.active && 5509 this.active.parent().closest( ".ui-menu-item", this.element ); 5510 if ( newItem && newItem.length ) { 5511 this._close(); 5512 this.focus( event, newItem ); 5513 } 5514 }, 5515 5516 expand: function( event ) { 5517 var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first(); 5518 5519 if ( newItem && newItem.length ) { 5520 this._open( newItem.parent() ); 5521 5522 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT 5523 this._delay( function() { 5524 this.focus( event, newItem ); 5525 } ); 5526 } 5527 }, 5528 5529 next: function( event ) { 5530 this._move( "next", "first", event ); 5531 }, 5532 5533 previous: function( event ) { 5534 this._move( "prev", "last", event ); 5535 }, 5536 5537 isFirstItem: function() { 5538 return this.active && !this.active.prevAll( ".ui-menu-item" ).length; 5539 }, 5540 5541 isLastItem: function() { 5542 return this.active && !this.active.nextAll( ".ui-menu-item" ).length; 5543 }, 5544 5545 _menuItems: function( menu ) { 5546 return ( menu || this.element ) 5547 .find( this.options.items ) 5548 .filter( ".ui-menu-item" ); 5549 }, 5550 5551 _move: function( direction, filter, event ) { 5552 var next; 5553 if ( this.active ) { 5554 if ( direction === "first" || direction === "last" ) { 5555 next = this.active 5556 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) 5557 .last(); 5558 } else { 5559 next = this.active 5560 [ direction + "All" ]( ".ui-menu-item" ) 5561 .first(); 5562 } 5563 } 5564 if ( !next || !next.length || !this.active ) { 5565 next = this._menuItems( this.activeMenu )[ filter ](); 5566 } 5567 5568 this.focus( event, next ); 5569 }, 5570 5571 nextPage: function( event ) { 5572 var item, base, height; 5573 5574 if ( !this.active ) { 5575 this.next( event ); 5576 return; 5577 } 5578 if ( this.isLastItem() ) { 5579 return; 5580 } 5581 if ( this._hasScroll() ) { 5582 base = this.active.offset().top; 5583 height = this.element.innerHeight(); 5584 5585 // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back. 5586 if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) { 5587 height += this.element[ 0 ].offsetHeight - this.element.outerHeight(); 5588 } 5589 5590 this.active.nextAll( ".ui-menu-item" ).each( function() { 5591 item = $( this ); 5592 return item.offset().top - base - height < 0; 5593 } ); 5594 5595 this.focus( event, item ); 5596 } else { 5597 this.focus( event, this._menuItems( this.activeMenu ) 5598 [ !this.active ? "first" : "last" ]() ); 5599 } 5600 }, 5601 5602 previousPage: function( event ) { 5603 var item, base, height; 5604 if ( !this.active ) { 5605 this.next( event ); 5606 return; 5607 } 5608 if ( this.isFirstItem() ) { 5609 return; 5610 } 5611 if ( this._hasScroll() ) { 5612 base = this.active.offset().top; 5613 height = this.element.innerHeight(); 5614 5615 // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back. 5616 if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) { 5617 height += this.element[ 0 ].offsetHeight - this.element.outerHeight(); 5618 } 5619 5620 this.active.prevAll( ".ui-menu-item" ).each( function() { 5621 item = $( this ); 5622 return item.offset().top - base + height > 0; 5623 } ); 5624 5625 this.focus( event, item ); 5626 } else { 5627 this.focus( event, this._menuItems( this.activeMenu ).first() ); 5628 } 5629 }, 5630 5631 _hasScroll: function() { 5632 return this.element.outerHeight() < this.element.prop( "scrollHeight" ); 5633 }, 5634 5635 select: function( event ) { 5636 5637 // TODO: It should never be possible to not have an active item at this 5638 // point, but the tests don't trigger mouseenter before click. 5639 this.active = this.active || $( event.target ).closest( ".ui-menu-item" ); 5640 var ui = { item: this.active }; 5641 if ( !this.active.has( ".ui-menu" ).length ) { 5642 this.collapseAll( event, true ); 5643 } 5644 this._trigger( "select", event, ui ); 5645 }, 5646 5647 _filterMenuItems: function( character ) { 5648 var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ), 5649 regex = new RegExp( "^" + escapedCharacter, "i" ); 5650 5651 return this.activeMenu 5652 .find( this.options.items ) 5653 5654 // Only match on items, not dividers or other content (#10571) 5655 .filter( ".ui-menu-item" ) 5656 .filter( function() { 5657 return regex.test( 5658 String.prototype.trim.call( 5659 $( this ).children( ".ui-menu-item-wrapper" ).text() ) ); 5660 } ); 5661 } 5662} ); 5663 5664 5665/*! 5666 * jQuery UI Autocomplete 1.13.3 5667 * https://jqueryui.com 5668 * 5669 * Copyright OpenJS Foundation and other contributors 5670 * Released under the MIT license. 5671 * https://jquery.org/license 5672 */ 5673 5674//>>label: Autocomplete 5675//>>group: Widgets 5676//>>description: Lists suggested words as the user is typing. 5677//>>docs: https://api.jqueryui.com/autocomplete/ 5678//>>demos: https://jqueryui.com/autocomplete/ 5679//>>css.structure: ../../themes/base/core.css 5680//>>css.structure: ../../themes/base/autocomplete.css 5681//>>css.theme: ../../themes/base/theme.css 5682 5683 5684$.widget( "ui.autocomplete", { 5685 version: "1.13.3", 5686 defaultElement: "<input>", 5687 options: { 5688 appendTo: null, 5689 autoFocus: false, 5690 delay: 300, 5691 minLength: 1, 5692 position: { 5693 my: "left top", 5694 at: "left bottom", 5695 collision: "none" 5696 }, 5697 source: null, 5698 5699 // Callbacks 5700 change: null, 5701 close: null, 5702 focus: null, 5703 open: null, 5704 response: null, 5705 search: null, 5706 select: null 5707 }, 5708 5709 requestIndex: 0, 5710 pending: 0, 5711 liveRegionTimer: null, 5712 5713 _create: function() { 5714 5715 // Some browsers only repeat keydown events, not keypress events, 5716 // so we use the suppressKeyPress flag to determine if we've already 5717 // handled the keydown event. #7269 5718 // Unfortunately the code for & in keypress is the same as the up arrow, 5719 // so we use the suppressKeyPressRepeat flag to avoid handling keypress 5720 // events when we know the keydown event was used to modify the 5721 // search term. #7799 5722 var suppressKeyPress, suppressKeyPressRepeat, suppressInput, 5723 nodeName = this.element[ 0 ].nodeName.toLowerCase(), 5724 isTextarea = nodeName === "textarea", 5725 isInput = nodeName === "input"; 5726 5727 // Textareas are always multi-line 5728 // Inputs are always single-line, even if inside a contentEditable element 5729 // IE also treats inputs as contentEditable 5730 // All other element types are determined by whether or not they're contentEditable 5731 this.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element ); 5732 5733 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ]; 5734 this.isNewMenu = true; 5735 5736 this._addClass( "ui-autocomplete-input" ); 5737 this.element.attr( "autocomplete", "off" ); 5738 5739 this._on( this.element, { 5740 keydown: function( event ) { 5741 if ( this.element.prop( "readOnly" ) ) { 5742 suppressKeyPress = true; 5743 suppressInput = true; 5744 suppressKeyPressRepeat = true; 5745 return; 5746 } 5747 5748 suppressKeyPress = false; 5749 suppressInput = false; 5750 suppressKeyPressRepeat = false; 5751 var keyCode = $.ui.keyCode; 5752 switch ( event.keyCode ) { 5753 case keyCode.PAGE_UP: 5754 suppressKeyPress = true; 5755 this._move( "previousPage", event ); 5756 break; 5757 case keyCode.PAGE_DOWN: 5758 suppressKeyPress = true; 5759 this._move( "nextPage", event ); 5760 break; 5761 case keyCode.UP: 5762 suppressKeyPress = true; 5763 this._keyEvent( "previous", event ); 5764 break; 5765 case keyCode.DOWN: 5766 suppressKeyPress = true; 5767 this._keyEvent( "next", event ); 5768 break; 5769 case keyCode.ENTER: 5770 5771 // when menu is open and has focus 5772 if ( this.menu.active ) { 5773 5774 // #6055 - Opera still allows the keypress to occur 5775 // which causes forms to submit 5776 suppressKeyPress = true; 5777 event.preventDefault(); 5778 this.menu.select( event ); 5779 } 5780 break; 5781 case keyCode.TAB: 5782 if ( this.menu.active ) { 5783 this.menu.select( event ); 5784 } 5785 break; 5786 case keyCode.ESCAPE: 5787 if ( this.menu.element.is( ":visible" ) ) { 5788 if ( !this.isMultiLine ) { 5789 this._value( this.term ); 5790 } 5791 this.close( event ); 5792 5793 // Different browsers have different default behavior for escape 5794 // Single press can mean undo or clear 5795 // Double press in IE means clear the whole form 5796 event.preventDefault(); 5797 } 5798 break; 5799 default: 5800 suppressKeyPressRepeat = true; 5801 5802 // search timeout should be triggered before the input value is changed 5803 this._searchTimeout( event ); 5804 break; 5805 } 5806 }, 5807 keypress: function( event ) { 5808 if ( suppressKeyPress ) { 5809 suppressKeyPress = false; 5810 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 5811 event.preventDefault(); 5812 } 5813 return; 5814 } 5815 if ( suppressKeyPressRepeat ) { 5816 return; 5817 } 5818 5819 // Replicate some key handlers to allow them to repeat in Firefox and Opera 5820 var keyCode = $.ui.keyCode; 5821 switch ( event.keyCode ) { 5822 case keyCode.PAGE_UP: 5823 this._move( "previousPage", event ); 5824 break; 5825 case keyCode.PAGE_DOWN: 5826 this._move( "nextPage", event ); 5827 break; 5828 case keyCode.UP: 5829 this._keyEvent( "previous", event ); 5830 break; 5831 case keyCode.DOWN: 5832 this._keyEvent( "next", event ); 5833 break; 5834 } 5835 }, 5836 input: function( event ) { 5837 if ( suppressInput ) { 5838 suppressInput = false; 5839 event.preventDefault(); 5840 return; 5841 } 5842 this._searchTimeout( event ); 5843 }, 5844 focus: function() { 5845 this.selectedItem = null; 5846 this.previous = this._value(); 5847 }, 5848 blur: function( event ) { 5849 clearTimeout( this.searching ); 5850 this.close( event ); 5851 this._change( event ); 5852 } 5853 } ); 5854 5855 this._initSource(); 5856 this.menu = $( "<ul>" ) 5857 .appendTo( this._appendTo() ) 5858 .menu( { 5859 5860 // disable ARIA support, the live region takes care of that 5861 role: null 5862 } ) 5863 .hide() 5864 5865 // Support: IE 11 only, Edge <= 14 5866 // For other browsers, we preventDefault() on the mousedown event 5867 // to keep the dropdown from taking focus from the input. This doesn't 5868 // work for IE/Edge, causing problems with selection and scrolling (#9638) 5869 // Happily, IE and Edge support an "unselectable" attribute that 5870 // prevents an element from receiving focus, exactly what we want here. 5871 .attr( { 5872 "unselectable": "on" 5873 } ) 5874 .menu( "instance" ); 5875 5876 this._addClass( this.menu.element, "ui-autocomplete", "ui-front" ); 5877 this._on( this.menu.element, { 5878 mousedown: function( event ) { 5879 5880 // Prevent moving focus out of the text field 5881 event.preventDefault(); 5882 }, 5883 menufocus: function( event, ui ) { 5884 var label, item; 5885 5886 // support: Firefox 5887 // Prevent accidental activation of menu items in Firefox (#7024 #9118) 5888 if ( this.isNewMenu ) { 5889 this.isNewMenu = false; 5890 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) { 5891 this.menu.blur(); 5892 5893 this.document.one( "mousemove", function() { 5894 $( event.target ).trigger( event.originalEvent ); 5895 } ); 5896 5897 return; 5898 } 5899 } 5900 5901 item = ui.item.data( "ui-autocomplete-item" ); 5902 if ( false !== this._trigger( "focus", event, { item: item } ) ) { 5903 5904 // use value to match what will end up in the input, if it was a key event 5905 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) { 5906 this._value( item.value ); 5907 } 5908 } 5909 5910 // Announce the value in the liveRegion 5911 label = ui.item.attr( "aria-label" ) || item.value; 5912 if ( label && String.prototype.trim.call( label ).length ) { 5913 clearTimeout( this.liveRegionTimer ); 5914 this.liveRegionTimer = this._delay( function() { 5915 this.liveRegion.html( $( "<div>" ).text( label ) ); 5916 }, 100 ); 5917 } 5918 }, 5919 menuselect: function( event, ui ) { 5920 var item = ui.item.data( "ui-autocomplete-item" ), 5921 previous = this.previous; 5922 5923 // Only trigger when focus was lost (click on menu) 5924 if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) { 5925 this.element.trigger( "focus" ); 5926 this.previous = previous; 5927 5928 // #6109 - IE triggers two focus events and the second 5929 // is asynchronous, so we need to reset the previous 5930 // term synchronously and asynchronously :-( 5931 this._delay( function() { 5932 this.previous = previous; 5933 this.selectedItem = item; 5934 } ); 5935 } 5936 5937 if ( false !== this._trigger( "select", event, { item: item } ) ) { 5938 this._value( item.value ); 5939 } 5940 5941 // reset the term after the select event 5942 // this allows custom select handling to work properly 5943 this.term = this._value(); 5944 5945 this.close( event ); 5946 this.selectedItem = item; 5947 } 5948 } ); 5949 5950 this.liveRegion = $( "<div>", { 5951 role: "status", 5952 "aria-live": "assertive", 5953 "aria-relevant": "additions" 5954 } ) 5955 .appendTo( this.document[ 0 ].body ); 5956 5957 this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" ); 5958 5959 // Turning off autocomplete prevents the browser from remembering the 5960 // value when navigating through history, so we re-enable autocomplete 5961 // if the page is unloaded before the widget is destroyed. #7790 5962 this._on( this.window, { 5963 beforeunload: function() { 5964 this.element.removeAttr( "autocomplete" ); 5965 } 5966 } ); 5967 }, 5968 5969 _destroy: function() { 5970 clearTimeout( this.searching ); 5971 this.element.removeAttr( "autocomplete" ); 5972 this.menu.element.remove(); 5973 this.liveRegion.remove(); 5974 }, 5975 5976 _setOption: function( key, value ) { 5977 this._super( key, value ); 5978 if ( key === "source" ) { 5979 this._initSource(); 5980 } 5981 if ( key === "appendTo" ) { 5982 this.menu.element.appendTo( this._appendTo() ); 5983 } 5984 if ( key === "disabled" && value && this.xhr ) { 5985 this.xhr.abort(); 5986 } 5987 }, 5988 5989 _isEventTargetInWidget: function( event ) { 5990 var menuElement = this.menu.element[ 0 ]; 5991 5992 return event.target === this.element[ 0 ] || 5993 event.target === menuElement || 5994 $.contains( menuElement, event.target ); 5995 }, 5996 5997 _closeOnClickOutside: function( event ) { 5998 if ( !this._isEventTargetInWidget( event ) ) { 5999 this.close(); 6000 } 6001 }, 6002 6003 _appendTo: function() { 6004 var element = this.options.appendTo; 6005 6006 if ( element ) { 6007 element = element.jquery || element.nodeType ? 6008 $( element ) : 6009 this.document.find( element ).eq( 0 ); 6010 } 6011 6012 if ( !element || !element[ 0 ] ) { 6013 element = this.element.closest( ".ui-front, dialog" ); 6014 } 6015 6016 if ( !element.length ) { 6017 element = this.document[ 0 ].body; 6018 } 6019 6020 return element; 6021 }, 6022 6023 _initSource: function() { 6024 var array, url, 6025 that = this; 6026 if ( Array.isArray( this.options.source ) ) { 6027 array = this.options.source; 6028 this.source = function( request, response ) { 6029 response( $.ui.autocomplete.filter( array, request.term ) ); 6030 }; 6031 } else if ( typeof this.options.source === "string" ) { 6032 url = this.options.source; 6033 this.source = function( request, response ) { 6034 if ( that.xhr ) { 6035 that.xhr.abort(); 6036 } 6037 that.xhr = $.ajax( { 6038 url: url, 6039 data: request, 6040 dataType: "json", 6041 success: function( data ) { 6042 response( data ); 6043 }, 6044 error: function() { 6045 response( [] ); 6046 } 6047 } ); 6048 }; 6049 } else { 6050 this.source = this.options.source; 6051 } 6052 }, 6053 6054 _searchTimeout: function( event ) { 6055 clearTimeout( this.searching ); 6056 this.searching = this._delay( function() { 6057 6058 // Search if the value has changed, or if the user retypes the same value (see #7434) 6059 var equalValues = this.term === this._value(), 6060 menuVisible = this.menu.element.is( ":visible" ), 6061 modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey; 6062 6063 if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) { 6064 this.selectedItem = null; 6065 this.search( null, event ); 6066 } 6067 }, this.options.delay ); 6068 }, 6069 6070 search: function( value, event ) { 6071 value = value != null ? value : this._value(); 6072 6073 // Always save the actual value, not the one passed as an argument 6074 this.term = this._value(); 6075 6076 if ( value.length < this.options.minLength ) { 6077 return this.close( event ); 6078 } 6079 6080 if ( this._trigger( "search", event ) === false ) { 6081 return; 6082 } 6083 6084 return this._search( value ); 6085 }, 6086 6087 _search: function( value ) { 6088 this.pending++; 6089 this._addClass( "ui-autocomplete-loading" ); 6090 this.cancelSearch = false; 6091 6092 this.source( { term: value }, this._response() ); 6093 }, 6094 6095 _response: function() { 6096 var index = ++this.requestIndex; 6097 6098 return function( content ) { 6099 if ( index === this.requestIndex ) { 6100 this.__response( content ); 6101 } 6102 6103 this.pending--; 6104 if ( !this.pending ) { 6105 this._removeClass( "ui-autocomplete-loading" ); 6106 } 6107 }.bind( this ); 6108 }, 6109 6110 __response: function( content ) { 6111 if ( content ) { 6112 content = this._normalize( content ); 6113 } 6114 this._trigger( "response", null, { content: content } ); 6115 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) { 6116 this._suggest( content ); 6117 this._trigger( "open" ); 6118 } else { 6119 6120 // use ._close() instead of .close() so we don't cancel future searches 6121 this._close(); 6122 } 6123 }, 6124 6125 close: function( event ) { 6126 this.cancelSearch = true; 6127 this._close( event ); 6128 }, 6129 6130 _close: function( event ) { 6131 6132 // Remove the handler that closes the menu on outside clicks 6133 this._off( this.document, "mousedown" ); 6134 6135 if ( this.menu.element.is( ":visible" ) ) { 6136 this.menu.element.hide(); 6137 this.menu.blur(); 6138 this.isNewMenu = true; 6139 this._trigger( "close", event ); 6140 } 6141 }, 6142 6143 _change: function( event ) { 6144 if ( this.previous !== this._value() ) { 6145 this._trigger( "change", event, { item: this.selectedItem } ); 6146 } 6147 }, 6148 6149 _normalize: function( items ) { 6150 6151 // assume all items have the right format when the first item is complete 6152 if ( items.length && items[ 0 ].label && items[ 0 ].value ) { 6153 return items; 6154 } 6155 return $.map( items, function( item ) { 6156 if ( typeof item === "string" ) { 6157 return { 6158 label: item, 6159 value: item 6160 }; 6161 } 6162 return $.extend( {}, item, { 6163 label: item.label || item.value, 6164 value: item.value || item.label 6165 } ); 6166 } ); 6167 }, 6168 6169 _suggest: function( items ) { 6170 var ul = this.menu.element.empty(); 6171 this._renderMenu( ul, items ); 6172 this.isNewMenu = true; 6173 this.menu.refresh(); 6174 6175 // Size and position menu 6176 ul.show(); 6177 this._resizeMenu(); 6178 ul.position( $.extend( { 6179 of: this.element 6180 }, this.options.position ) ); 6181 6182 if ( this.options.autoFocus ) { 6183 this.menu.next(); 6184 } 6185 6186 // Listen for interactions outside of the widget (#6642) 6187 this._on( this.document, { 6188 mousedown: "_closeOnClickOutside" 6189 } ); 6190 }, 6191 6192 _resizeMenu: function() { 6193 var ul = this.menu.element; 6194 ul.outerWidth( Math.max( 6195 6196 // Firefox wraps long text (possibly a rounding bug) 6197 // so we add 1px to avoid the wrapping (#7513) 6198 ul.width( "" ).outerWidth() + 1, 6199 this.element.outerWidth() 6200 ) ); 6201 }, 6202 6203 _renderMenu: function( ul, items ) { 6204 var that = this; 6205 $.each( items, function( index, item ) { 6206 that._renderItemData( ul, item ); 6207 } ); 6208 }, 6209 6210 _renderItemData: function( ul, item ) { 6211 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item ); 6212 }, 6213 6214 _renderItem: function( ul, item ) { 6215 return $( "<li>" ) 6216 .append( $( "<div>" ).text( item.label ) ) 6217 .appendTo( ul ); 6218 }, 6219 6220 _move: function( direction, event ) { 6221 if ( !this.menu.element.is( ":visible" ) ) { 6222 this.search( null, event ); 6223 return; 6224 } 6225 if ( this.menu.isFirstItem() && /^previous/.test( direction ) || 6226 this.menu.isLastItem() && /^next/.test( direction ) ) { 6227 6228 if ( !this.isMultiLine ) { 6229 this._value( this.term ); 6230 } 6231 6232 this.menu.blur(); 6233 return; 6234 } 6235 this.menu[ direction ]( event ); 6236 }, 6237 6238 widget: function() { 6239 return this.menu.element; 6240 }, 6241 6242 _value: function() { 6243 return this.valueMethod.apply( this.element, arguments ); 6244 }, 6245 6246 _keyEvent: function( keyEvent, event ) { 6247 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 6248 this._move( keyEvent, event ); 6249 6250 // Prevents moving cursor to beginning/end of the text field in some browsers 6251 event.preventDefault(); 6252 } 6253 }, 6254 6255 // Support: Chrome <=50 6256 // We should be able to just use this.element.prop( "isContentEditable" ) 6257 // but hidden elements always report false in Chrome. 6258 // https://code.google.com/p/chromium/issues/detail?id=313082 6259 _isContentEditable: function( element ) { 6260 if ( !element.length ) { 6261 return false; 6262 } 6263 6264 var editable = element.prop( "contentEditable" ); 6265 6266 if ( editable === "inherit" ) { 6267 return this._isContentEditable( element.parent() ); 6268 } 6269 6270 return editable === "true"; 6271 } 6272} ); 6273 6274$.extend( $.ui.autocomplete, { 6275 escapeRegex: function( value ) { 6276 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ); 6277 }, 6278 filter: function( array, term ) { 6279 var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" ); 6280 return $.grep( array, function( value ) { 6281 return matcher.test( value.label || value.value || value ); 6282 } ); 6283 } 6284} ); 6285 6286// Live region extension, adding a `messages` option 6287// NOTE: This is an experimental API. We are still investigating 6288// a full solution for string manipulation and internationalization. 6289$.widget( "ui.autocomplete", $.ui.autocomplete, { 6290 options: { 6291 messages: { 6292 noResults: "No search results.", 6293 results: function( amount ) { 6294 return amount + ( amount > 1 ? " results are" : " result is" ) + 6295 " available, use up and down arrow keys to navigate."; 6296 } 6297 } 6298 }, 6299 6300 __response: function( content ) { 6301 var message; 6302 this._superApply( arguments ); 6303 if ( this.options.disabled || this.cancelSearch ) { 6304 return; 6305 } 6306 if ( content && content.length ) { 6307 message = this.options.messages.results( content.length ); 6308 } else { 6309 message = this.options.messages.noResults; 6310 } 6311 clearTimeout( this.liveRegionTimer ); 6312 this.liveRegionTimer = this._delay( function() { 6313 this.liveRegion.html( $( "<div>" ).text( message ) ); 6314 }, 100 ); 6315 } 6316} ); 6317 6318var widgetsAutocomplete = $.ui.autocomplete; 6319 6320 6321/*! 6322 * jQuery UI Controlgroup 1.13.3 6323 * https://jqueryui.com 6324 * 6325 * Copyright OpenJS Foundation and other contributors 6326 * Released under the MIT license. 6327 * https://jquery.org/license 6328 */ 6329 6330//>>label: Controlgroup 6331//>>group: Widgets 6332//>>description: Visually groups form control widgets 6333//>>docs: https://api.jqueryui.com/controlgroup/ 6334//>>demos: https://jqueryui.com/controlgroup/ 6335//>>css.structure: ../../themes/base/core.css 6336//>>css.structure: ../../themes/base/controlgroup.css 6337//>>css.theme: ../../themes/base/theme.css 6338 6339 6340var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g; 6341 6342var widgetsControlgroup = $.widget( "ui.controlgroup", { 6343 version: "1.13.3", 6344 defaultElement: "<div>", 6345 options: { 6346 direction: "horizontal", 6347 disabled: null, 6348 onlyVisible: true, 6349 items: { 6350 "button": "input[type=button], input[type=submit], input[type=reset], button, a", 6351 "controlgroupLabel": ".ui-controlgroup-label", 6352 "checkboxradio": "input[type='checkbox'], input[type='radio']", 6353 "selectmenu": "select", 6354 "spinner": ".ui-spinner-input" 6355 } 6356 }, 6357 6358 _create: function() { 6359 this._enhance(); 6360 }, 6361 6362 // To support the enhanced option in jQuery Mobile, we isolate DOM manipulation 6363 _enhance: function() { 6364 this.element.attr( "role", "toolbar" ); 6365 this.refresh(); 6366 }, 6367 6368 _destroy: function() { 6369 this._callChildMethod( "destroy" ); 6370 this.childWidgets.removeData( "ui-controlgroup-data" ); 6371 this.element.removeAttr( "role" ); 6372 if ( this.options.items.controlgroupLabel ) { 6373 this.element 6374 .find( this.options.items.controlgroupLabel ) 6375 .find( ".ui-controlgroup-label-contents" ) 6376 .contents().unwrap(); 6377 } 6378 }, 6379 6380 _initWidgets: function() { 6381 var that = this, 6382 childWidgets = []; 6383 6384 // First we iterate over each of the items options 6385 $.each( this.options.items, function( widget, selector ) { 6386 var labels; 6387 var options = {}; 6388 6389 // Make sure the widget has a selector set 6390 if ( !selector ) { 6391 return; 6392 } 6393 6394 if ( widget === "controlgroupLabel" ) { 6395 labels = that.element.find( selector ); 6396 labels.each( function() { 6397 var element = $( this ); 6398 6399 if ( element.children( ".ui-controlgroup-label-contents" ).length ) { 6400 return; 6401 } 6402 element.contents() 6403 .wrapAll( "<span class='ui-controlgroup-label-contents'></span>" ); 6404 } ); 6405 that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" ); 6406 childWidgets = childWidgets.concat( labels.get() ); 6407 return; 6408 } 6409 6410 // Make sure the widget actually exists 6411 if ( !$.fn[ widget ] ) { 6412 return; 6413 } 6414 6415 // We assume everything is in the middle to start because we can't determine 6416 // first / last elements until all enhancments are done. 6417 if ( that[ "_" + widget + "Options" ] ) { 6418 options = that[ "_" + widget + "Options" ]( "middle" ); 6419 } else { 6420 options = { classes: {} }; 6421 } 6422 6423 // Find instances of this widget inside controlgroup and init them 6424 that.element 6425 .find( selector ) 6426 .each( function() { 6427 var element = $( this ); 6428 var instance = element[ widget ]( "instance" ); 6429 6430 // We need to clone the default options for this type of widget to avoid 6431 // polluting the variable options which has a wider scope than a single widget. 6432 var instanceOptions = $.widget.extend( {}, options ); 6433 6434 // If the button is the child of a spinner ignore it 6435 // TODO: Find a more generic solution 6436 if ( widget === "button" && element.parent( ".ui-spinner" ).length ) { 6437 return; 6438 } 6439 6440 // Create the widget if it doesn't exist 6441 if ( !instance ) { 6442 instance = element[ widget ]()[ widget ]( "instance" ); 6443 } 6444 if ( instance ) { 6445 instanceOptions.classes = 6446 that._resolveClassesValues( instanceOptions.classes, instance ); 6447 } 6448 element[ widget ]( instanceOptions ); 6449 6450 // Store an instance of the controlgroup to be able to reference 6451 // from the outermost element for changing options and refresh 6452 var widgetElement = element[ widget ]( "widget" ); 6453 $.data( widgetElement[ 0 ], "ui-controlgroup-data", 6454 instance ? instance : element[ widget ]( "instance" ) ); 6455 6456 childWidgets.push( widgetElement[ 0 ] ); 6457 } ); 6458 } ); 6459 6460 this.childWidgets = $( $.uniqueSort( childWidgets ) ); 6461 this._addClass( this.childWidgets, "ui-controlgroup-item" ); 6462 }, 6463 6464 _callChildMethod: function( method ) { 6465 this.childWidgets.each( function() { 6466 var element = $( this ), 6467 data = element.data( "ui-controlgroup-data" ); 6468 if ( data && data[ method ] ) { 6469 data[ method ](); 6470 } 6471 } ); 6472 }, 6473 6474 _updateCornerClass: function( element, position ) { 6475 var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all"; 6476 var add = this._buildSimpleOptions( position, "label" ).classes.label; 6477 6478 this._removeClass( element, null, remove ); 6479 this._addClass( element, null, add ); 6480 }, 6481 6482 _buildSimpleOptions: function( position, key ) { 6483 var direction = this.options.direction === "vertical"; 6484 var result = { 6485 classes: {} 6486 }; 6487 result.classes[ key ] = { 6488 "middle": "", 6489 "first": "ui-corner-" + ( direction ? "top" : "left" ), 6490 "last": "ui-corner-" + ( direction ? "bottom" : "right" ), 6491 "only": "ui-corner-all" 6492 }[ position ]; 6493 6494 return result; 6495 }, 6496 6497 _spinnerOptions: function( position ) { 6498 var options = this._buildSimpleOptions( position, "ui-spinner" ); 6499 6500 options.classes[ "ui-spinner-up" ] = ""; 6501 options.classes[ "ui-spinner-down" ] = ""; 6502 6503 return options; 6504 }, 6505 6506 _buttonOptions: function( position ) { 6507 return this._buildSimpleOptions( position, "ui-button" ); 6508 }, 6509 6510 _checkboxradioOptions: function( position ) { 6511 return this._buildSimpleOptions( position, "ui-checkboxradio-label" ); 6512 }, 6513 6514 _selectmenuOptions: function( position ) { 6515 var direction = this.options.direction === "vertical"; 6516 return { 6517 width: direction ? "auto" : false, 6518 classes: { 6519 middle: { 6520 "ui-selectmenu-button-open": "", 6521 "ui-selectmenu-button-closed": "" 6522 }, 6523 first: { 6524 "ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ), 6525 "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" ) 6526 }, 6527 last: { 6528 "ui-selectmenu-button-open": direction ? "" : "ui-corner-tr", 6529 "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" ) 6530 }, 6531 only: { 6532 "ui-selectmenu-button-open": "ui-corner-top", 6533 "ui-selectmenu-button-closed": "ui-corner-all" 6534 } 6535 6536 }[ position ] 6537 }; 6538 }, 6539 6540 _resolveClassesValues: function( classes, instance ) { 6541 var result = {}; 6542 $.each( classes, function( key ) { 6543 var current = instance.options.classes[ key ] || ""; 6544 current = String.prototype.trim.call( current.replace( controlgroupCornerRegex, "" ) ); 6545 result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " ); 6546 } ); 6547 return result; 6548 }, 6549 6550 _setOption: function( key, value ) { 6551 if ( key === "direction" ) { 6552 this._removeClass( "ui-controlgroup-" + this.options.direction ); 6553 } 6554 6555 this._super( key, value ); 6556 if ( key === "disabled" ) { 6557 this._callChildMethod( value ? "disable" : "enable" ); 6558 return; 6559 } 6560 6561 this.refresh(); 6562 }, 6563 6564 refresh: function() { 6565 var children, 6566 that = this; 6567 6568 this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction ); 6569 6570 if ( this.options.direction === "horizontal" ) { 6571 this._addClass( null, "ui-helper-clearfix" ); 6572 } 6573 this._initWidgets(); 6574 6575 children = this.childWidgets; 6576 6577 // We filter here because we need to track all childWidgets not just the visible ones 6578 if ( this.options.onlyVisible ) { 6579 children = children.filter( ":visible" ); 6580 } 6581 6582 if ( children.length ) { 6583 6584 // We do this last because we need to make sure all enhancment is done 6585 // before determining first and last 6586 $.each( [ "first", "last" ], function( index, value ) { 6587 var instance = children[ value ]().data( "ui-controlgroup-data" ); 6588 6589 if ( instance && that[ "_" + instance.widgetName + "Options" ] ) { 6590 var options = that[ "_" + instance.widgetName + "Options" ]( 6591 children.length === 1 ? "only" : value 6592 ); 6593 options.classes = that._resolveClassesValues( options.classes, instance ); 6594 instance.element[ instance.widgetName ]( options ); 6595 } else { 6596 that._updateCornerClass( children[ value ](), value ); 6597 } 6598 } ); 6599 6600 // Finally call the refresh method on each of the child widgets. 6601 this._callChildMethod( "refresh" ); 6602 } 6603 } 6604} ); 6605 6606/*! 6607 * jQuery UI Checkboxradio 1.13.3 6608 * https://jqueryui.com 6609 * 6610 * Copyright OpenJS Foundation and other contributors 6611 * Released under the MIT license. 6612 * https://jquery.org/license 6613 */ 6614 6615//>>label: Checkboxradio 6616//>>group: Widgets 6617//>>description: Enhances a form with multiple themeable checkboxes or radio buttons. 6618//>>docs: https://api.jqueryui.com/checkboxradio/ 6619//>>demos: https://jqueryui.com/checkboxradio/ 6620//>>css.structure: ../../themes/base/core.css 6621//>>css.structure: ../../themes/base/button.css 6622//>>css.structure: ../../themes/base/checkboxradio.css 6623//>>css.theme: ../../themes/base/theme.css 6624 6625 6626$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, { 6627 version: "1.13.3", 6628 options: { 6629 disabled: null, 6630 label: null, 6631 icon: true, 6632 classes: { 6633 "ui-checkboxradio-label": "ui-corner-all", 6634 "ui-checkboxradio-icon": "ui-corner-all" 6635 } 6636 }, 6637 6638 _getCreateOptions: function() { 6639 var disabled, labels, labelContents; 6640 var options = this._super() || {}; 6641 6642 // We read the type here, because it makes more sense to throw a element type error first, 6643 // rather then the error for lack of a label. Often if its the wrong type, it 6644 // won't have a label (e.g. calling on a div, btn, etc) 6645 this._readType(); 6646 6647 labels = this.element.labels(); 6648 6649 // If there are multiple labels, use the last one 6650 this.label = $( labels[ labels.length - 1 ] ); 6651 if ( !this.label.length ) { 6652 $.error( "No label found for checkboxradio widget" ); 6653 } 6654 6655 this.originalLabel = ""; 6656 6657 // We need to get the label text but this may also need to make sure it does not contain the 6658 // input itself. 6659 // The label contents could be text, html, or a mix. We wrap all elements 6660 // and read the wrapper's `innerHTML` to get a string representation of 6661 // the label, without the input as part of it. 6662 labelContents = this.label.contents().not( this.element[ 0 ] ); 6663 6664 if ( labelContents.length ) { 6665 this.originalLabel += labelContents 6666 .clone() 6667 .wrapAll( "<div></div>" ) 6668 .parent() 6669 .html(); 6670 } 6671 6672 // Set the label option if we found label text 6673 if ( this.originalLabel ) { 6674 options.label = this.originalLabel; 6675 } 6676 6677 disabled = this.element[ 0 ].disabled; 6678 if ( disabled != null ) { 6679 options.disabled = disabled; 6680 } 6681 return options; 6682 }, 6683 6684 _create: function() { 6685 var checked = this.element[ 0 ].checked; 6686 6687 this._bindFormResetHandler(); 6688 6689 if ( this.options.disabled == null ) { 6690 this.options.disabled = this.element[ 0 ].disabled; 6691 } 6692 6693 this._setOption( "disabled", this.options.disabled ); 6694 this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" ); 6695 this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" ); 6696 6697 if ( this.type === "radio" ) { 6698 this._addClass( this.label, "ui-checkboxradio-radio-label" ); 6699 } 6700 6701 if ( this.options.label && this.options.label !== this.originalLabel ) { 6702 this._updateLabel(); 6703 } else if ( this.originalLabel ) { 6704 this.options.label = this.originalLabel; 6705 } 6706 6707 this._enhance(); 6708 6709 if ( checked ) { 6710 this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" ); 6711 } 6712 6713 this._on( { 6714 change: "_toggleClasses", 6715 focus: function() { 6716 this._addClass( this.label, null, "ui-state-focus ui-visual-focus" ); 6717 }, 6718 blur: function() { 6719 this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" ); 6720 } 6721 } ); 6722 }, 6723 6724 _readType: function() { 6725 var nodeName = this.element[ 0 ].nodeName.toLowerCase(); 6726 this.type = this.element[ 0 ].type; 6727 if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) { 6728 $.error( "Can't create checkboxradio on element.nodeName=" + nodeName + 6729 " and element.type=" + this.type ); 6730 } 6731 }, 6732 6733 // Support jQuery Mobile enhanced option 6734 _enhance: function() { 6735 this._updateIcon( this.element[ 0 ].checked ); 6736 }, 6737 6738 widget: function() { 6739 return this.label; 6740 }, 6741 6742 _getRadioGroup: function() { 6743 var group; 6744 var name = this.element[ 0 ].name; 6745 var nameSelector = "input[name='" + $.escapeSelector( name ) + "']"; 6746 6747 if ( !name ) { 6748 return $( [] ); 6749 } 6750 6751 if ( this.form.length ) { 6752 group = $( this.form[ 0 ].elements ).filter( nameSelector ); 6753 } else { 6754 6755 // Not inside a form, check all inputs that also are not inside a form 6756 group = $( nameSelector ).filter( function() { 6757 return $( this )._form().length === 0; 6758 } ); 6759 } 6760 6761 return group.not( this.element ); 6762 }, 6763 6764 _toggleClasses: function() { 6765 var checked = this.element[ 0 ].checked; 6766 this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked ); 6767 6768 if ( this.options.icon && this.type === "checkbox" ) { 6769 this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked ) 6770 ._toggleClass( this.icon, null, "ui-icon-blank", !checked ); 6771 } 6772 6773 if ( this.type === "radio" ) { 6774 this._getRadioGroup() 6775 .each( function() { 6776 var instance = $( this ).checkboxradio( "instance" ); 6777 6778 if ( instance ) { 6779 instance._removeClass( instance.label, 6780 "ui-checkboxradio-checked", "ui-state-active" ); 6781 } 6782 } ); 6783 } 6784 }, 6785 6786 _destroy: function() { 6787 this._unbindFormResetHandler(); 6788 6789 if ( this.icon ) { 6790 this.icon.remove(); 6791 this.iconSpace.remove(); 6792 } 6793 }, 6794 6795 _setOption: function( key, value ) { 6796 6797 // We don't allow the value to be set to nothing 6798 if ( key === "label" && !value ) { 6799 return; 6800 } 6801 6802 this._super( key, value ); 6803 6804 if ( key === "disabled" ) { 6805 this._toggleClass( this.label, null, "ui-state-disabled", value ); 6806 this.element[ 0 ].disabled = value; 6807 6808 // Don't refresh when setting disabled 6809 return; 6810 } 6811 this.refresh(); 6812 }, 6813 6814 _updateIcon: function( checked ) { 6815 var toAdd = "ui-icon ui-icon-background "; 6816 6817 if ( this.options.icon ) { 6818 if ( !this.icon ) { 6819 this.icon = $( "<span>" ); 6820 this.iconSpace = $( "<span> </span>" ); 6821 this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" ); 6822 } 6823 6824 if ( this.type === "checkbox" ) { 6825 toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank"; 6826 this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" ); 6827 } else { 6828 toAdd += "ui-icon-blank"; 6829 } 6830 this._addClass( this.icon, "ui-checkboxradio-icon", toAdd ); 6831 if ( !checked ) { 6832 this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" ); 6833 } 6834 this.icon.prependTo( this.label ).after( this.iconSpace ); 6835 } else if ( this.icon !== undefined ) { 6836 this.icon.remove(); 6837 this.iconSpace.remove(); 6838 delete this.icon; 6839 } 6840 }, 6841 6842 _updateLabel: function() { 6843 6844 // Remove the contents of the label ( minus the icon, icon space, and input ) 6845 var contents = this.label.contents().not( this.element[ 0 ] ); 6846 if ( this.icon ) { 6847 contents = contents.not( this.icon[ 0 ] ); 6848 } 6849 if ( this.iconSpace ) { 6850 contents = contents.not( this.iconSpace[ 0 ] ); 6851 } 6852 contents.remove(); 6853 6854 this.label.append( this.options.label ); 6855 }, 6856 6857 refresh: function() { 6858 var checked = this.element[ 0 ].checked, 6859 isDisabled = this.element[ 0 ].disabled; 6860 6861 this._updateIcon( checked ); 6862 this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked ); 6863 if ( this.options.label !== null ) { 6864 this._updateLabel(); 6865 } 6866 6867 if ( isDisabled !== this.options.disabled ) { 6868 this._setOptions( { "disabled": isDisabled } ); 6869 } 6870 } 6871 6872} ] ); 6873 6874var widgetsCheckboxradio = $.ui.checkboxradio; 6875 6876 6877/*! 6878 * jQuery UI Button 1.13.3 6879 * https://jqueryui.com 6880 * 6881 * Copyright OpenJS Foundation and other contributors 6882 * Released under the MIT license. 6883 * https://jquery.org/license 6884 */ 6885 6886//>>label: Button 6887//>>group: Widgets 6888//>>description: Enhances a form with themeable buttons. 6889//>>docs: https://api.jqueryui.com/button/ 6890//>>demos: https://jqueryui.com/button/ 6891//>>css.structure: ../../themes/base/core.css 6892//>>css.structure: ../../themes/base/button.css 6893//>>css.theme: ../../themes/base/theme.css 6894 6895 6896$.widget( "ui.button", { 6897 version: "1.13.3", 6898 defaultElement: "<button>", 6899 options: { 6900 classes: { 6901 "ui-button": "ui-corner-all" 6902 }, 6903 disabled: null, 6904 icon: null, 6905 iconPosition: "beginning", 6906 label: null, 6907 showLabel: true 6908 }, 6909 6910 _getCreateOptions: function() { 6911 var disabled, 6912 6913 // This is to support cases like in jQuery Mobile where the base widget does have 6914 // an implementation of _getCreateOptions 6915 options = this._super() || {}; 6916 6917 this.isInput = this.element.is( "input" ); 6918 6919 disabled = this.element[ 0 ].disabled; 6920 if ( disabled != null ) { 6921 options.disabled = disabled; 6922 } 6923 6924 this.originalLabel = this.isInput ? this.element.val() : this.element.html(); 6925 if ( this.originalLabel ) { 6926 options.label = this.originalLabel; 6927 } 6928 6929 return options; 6930 }, 6931 6932 _create: function() { 6933 if ( !this.option.showLabel & !this.options.icon ) { 6934 this.options.showLabel = true; 6935 } 6936 6937 // We have to check the option again here even though we did in _getCreateOptions, 6938 // because null may have been passed on init which would override what was set in 6939 // _getCreateOptions 6940 if ( this.options.disabled == null ) { 6941 this.options.disabled = this.element[ 0 ].disabled || false; 6942 } 6943 6944 this.hasTitle = !!this.element.attr( "title" ); 6945 6946 // Check to see if the label needs to be set or if its already correct 6947 if ( this.options.label && this.options.label !== this.originalLabel ) { 6948 if ( this.isInput ) { 6949 this.element.val( this.options.label ); 6950 } else { 6951 this.element.html( this.options.label ); 6952 } 6953 } 6954 this._addClass( "ui-button", "ui-widget" ); 6955 this._setOption( "disabled", this.options.disabled ); 6956 this._enhance(); 6957 6958 if ( this.element.is( "a" ) ) { 6959 this._on( { 6960 "keyup": function( event ) { 6961 if ( event.keyCode === $.ui.keyCode.SPACE ) { 6962 event.preventDefault(); 6963 6964 // Support: PhantomJS <= 1.9, IE 8 Only 6965 // If a native click is available use it so we actually cause navigation 6966 // otherwise just trigger a click event 6967 if ( this.element[ 0 ].click ) { 6968 this.element[ 0 ].click(); 6969 } else { 6970 this.element.trigger( "click" ); 6971 } 6972 } 6973 } 6974 } ); 6975 } 6976 }, 6977 6978 _enhance: function() { 6979 if ( !this.element.is( "button" ) ) { 6980 this.element.attr( "role", "button" ); 6981 } 6982 6983 if ( this.options.icon ) { 6984 this._updateIcon( "icon", this.options.icon ); 6985 this._updateTooltip(); 6986 } 6987 }, 6988 6989 _updateTooltip: function() { 6990 this.title = this.element.attr( "title" ); 6991 6992 if ( !this.options.showLabel && !this.title ) { 6993 this.element.attr( "title", this.options.label ); 6994 } 6995 }, 6996 6997 _updateIcon: function( option, value ) { 6998 var icon = option !== "iconPosition", 6999 position = icon ? this.options.iconPosition : value, 7000 displayBlock = position === "top" || position === "bottom"; 7001 7002 // Create icon 7003 if ( !this.icon ) { 7004 this.icon = $( "<span>" ); 7005 7006 this._addClass( this.icon, "ui-button-icon", "ui-icon" ); 7007 7008 if ( !this.options.showLabel ) { 7009 this._addClass( "ui-button-icon-only" ); 7010 } 7011 } else if ( icon ) { 7012 7013 // If we are updating the icon remove the old icon class 7014 this._removeClass( this.icon, null, this.options.icon ); 7015 } 7016 7017 // If we are updating the icon add the new icon class 7018 if ( icon ) { 7019 this._addClass( this.icon, null, value ); 7020 } 7021 7022 this._attachIcon( position ); 7023 7024 // If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove 7025 // the iconSpace if there is one. 7026 if ( displayBlock ) { 7027 this._addClass( this.icon, null, "ui-widget-icon-block" ); 7028 if ( this.iconSpace ) { 7029 this.iconSpace.remove(); 7030 } 7031 } else { 7032 7033 // Position is beginning or end so remove the ui-widget-icon-block class and add the 7034 // space if it does not exist 7035 if ( !this.iconSpace ) { 7036 this.iconSpace = $( "<span> </span>" ); 7037 this._addClass( this.iconSpace, "ui-button-icon-space" ); 7038 } 7039 this._removeClass( this.icon, null, "ui-wiget-icon-block" ); 7040 this._attachIconSpace( position ); 7041 } 7042 }, 7043 7044 _destroy: function() { 7045 this.element.removeAttr( "role" ); 7046 7047 if ( this.icon ) { 7048 this.icon.remove(); 7049 } 7050 if ( this.iconSpace ) { 7051 this.iconSpace.remove(); 7052 } 7053 if ( !this.hasTitle ) { 7054 this.element.removeAttr( "title" ); 7055 } 7056 }, 7057 7058 _attachIconSpace: function( iconPosition ) { 7059 this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace ); 7060 }, 7061 7062 _attachIcon: function( iconPosition ) { 7063 this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon ); 7064 }, 7065 7066 _setOptions: function( options ) { 7067 var newShowLabel = options.showLabel === undefined ? 7068 this.options.showLabel : 7069 options.showLabel, 7070 newIcon = options.icon === undefined ? this.options.icon : options.icon; 7071 7072 if ( !newShowLabel && !newIcon ) { 7073 options.showLabel = true; 7074 } 7075 this._super( options ); 7076 }, 7077 7078 _setOption: function( key, value ) { 7079 if ( key === "icon" ) { 7080 if ( value ) { 7081 this._updateIcon( key, value ); 7082 } else if ( this.icon ) { 7083 this.icon.remove(); 7084 if ( this.iconSpace ) { 7085 this.iconSpace.remove(); 7086 } 7087 } 7088 } 7089 7090 if ( key === "iconPosition" ) { 7091 this._updateIcon( key, value ); 7092 } 7093 7094 // Make sure we can't end up with a button that has neither text nor icon 7095 if ( key === "showLabel" ) { 7096 this._toggleClass( "ui-button-icon-only", null, !value ); 7097 this._updateTooltip(); 7098 } 7099 7100 if ( key === "label" ) { 7101 if ( this.isInput ) { 7102 this.element.val( value ); 7103 } else { 7104 7105 // If there is an icon, append it, else nothing then append the value 7106 // this avoids removal of the icon when setting label text 7107 this.element.html( value ); 7108 if ( this.icon ) { 7109 this._attachIcon( this.options.iconPosition ); 7110 this._attachIconSpace( this.options.iconPosition ); 7111 } 7112 } 7113 } 7114 7115 this._super( key, value ); 7116 7117 if ( key === "disabled" ) { 7118 this._toggleClass( null, "ui-state-disabled", value ); 7119 this.element[ 0 ].disabled = value; 7120 if ( value ) { 7121 this.element.trigger( "blur" ); 7122 } 7123 } 7124 }, 7125 7126 refresh: function() { 7127 7128 // Make sure to only check disabled if its an element that supports this otherwise 7129 // check for the disabled class to determine state 7130 var isDisabled = this.element.is( "input, button" ) ? 7131 this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" ); 7132 7133 if ( isDisabled !== this.options.disabled ) { 7134 this._setOptions( { disabled: isDisabled } ); 7135 } 7136 7137 this._updateTooltip(); 7138 } 7139} ); 7140 7141// DEPRECATED 7142if ( $.uiBackCompat !== false ) { 7143 7144 // Text and Icons options 7145 $.widget( "ui.button", $.ui.button, { 7146 options: { 7147 text: true, 7148 icons: { 7149 primary: null, 7150 secondary: null 7151 } 7152 }, 7153 7154 _create: function() { 7155 if ( this.options.showLabel && !this.options.text ) { 7156 this.options.showLabel = this.options.text; 7157 } 7158 if ( !this.options.showLabel && this.options.text ) { 7159 this.options.text = this.options.showLabel; 7160 } 7161 if ( !this.options.icon && ( this.options.icons.primary || 7162 this.options.icons.secondary ) ) { 7163 if ( this.options.icons.primary ) { 7164 this.options.icon = this.options.icons.primary; 7165 } else { 7166 this.options.icon = this.options.icons.secondary; 7167 this.options.iconPosition = "end"; 7168 } 7169 } else if ( this.options.icon ) { 7170 this.options.icons.primary = this.options.icon; 7171 } 7172 this._super(); 7173 }, 7174 7175 _setOption: function( key, value ) { 7176 if ( key === "text" ) { 7177 this._super( "showLabel", value ); 7178 return; 7179 } 7180 if ( key === "showLabel" ) { 7181 this.options.text = value; 7182 } 7183 if ( key === "icon" ) { 7184 this.options.icons.primary = value; 7185 } 7186 if ( key === "icons" ) { 7187 if ( value.primary ) { 7188 this._super( "icon", value.primary ); 7189 this._super( "iconPosition", "beginning" ); 7190 } else if ( value.secondary ) { 7191 this._super( "icon", value.secondary ); 7192 this._super( "iconPosition", "end" ); 7193 } 7194 } 7195 this._superApply( arguments ); 7196 } 7197 } ); 7198 7199 $.fn.button = ( function( orig ) { 7200 return function( options ) { 7201 var isMethodCall = typeof options === "string"; 7202 var args = Array.prototype.slice.call( arguments, 1 ); 7203 var returnValue = this; 7204 7205 if ( isMethodCall ) { 7206 7207 // If this is an empty collection, we need to have the instance method 7208 // return undefined instead of the jQuery instance 7209 if ( !this.length && options === "instance" ) { 7210 returnValue = undefined; 7211 } else { 7212 this.each( function() { 7213 var methodValue; 7214 var type = $( this ).attr( "type" ); 7215 var name = type !== "checkbox" && type !== "radio" ? 7216 "button" : 7217 "checkboxradio"; 7218 var instance = $.data( this, "ui-" + name ); 7219 7220 if ( options === "instance" ) { 7221 returnValue = instance; 7222 return false; 7223 } 7224 7225 if ( !instance ) { 7226 return $.error( "cannot call methods on button" + 7227 " prior to initialization; " + 7228 "attempted to call method '" + options + "'" ); 7229 } 7230 7231 if ( typeof instance[ options ] !== "function" || 7232 options.charAt( 0 ) === "_" ) { 7233 return $.error( "no such method '" + options + "' for button" + 7234 " widget instance" ); 7235 } 7236 7237 methodValue = instance[ options ].apply( instance, args ); 7238 7239 if ( methodValue !== instance && methodValue !== undefined ) { 7240 returnValue = methodValue && methodValue.jquery ? 7241 returnValue.pushStack( methodValue.get() ) : 7242 methodValue; 7243 return false; 7244 } 7245 } ); 7246 } 7247 } else { 7248 7249 // Allow multiple hashes to be passed on init 7250 if ( args.length ) { 7251 options = $.widget.extend.apply( null, [ options ].concat( args ) ); 7252 } 7253 7254 this.each( function() { 7255 var type = $( this ).attr( "type" ); 7256 var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio"; 7257 var instance = $.data( this, "ui-" + name ); 7258 7259 if ( instance ) { 7260 instance.option( options || {} ); 7261 if ( instance._init ) { 7262 instance._init(); 7263 } 7264 } else { 7265 if ( name === "button" ) { 7266 orig.call( $( this ), options ); 7267 return; 7268 } 7269 7270 $( this ).checkboxradio( $.extend( { icon: false }, options ) ); 7271 } 7272 } ); 7273 } 7274 7275 return returnValue; 7276 }; 7277 } )( $.fn.button ); 7278 7279 $.fn.buttonset = function() { 7280 if ( !$.ui.controlgroup ) { 7281 $.error( "Controlgroup widget missing" ); 7282 } 7283 if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) { 7284 return this.controlgroup.apply( this, 7285 [ arguments[ 0 ], "items.button", arguments[ 2 ] ] ); 7286 } 7287 if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) { 7288 return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] ); 7289 } 7290 if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) { 7291 arguments[ 0 ].items = { 7292 button: arguments[ 0 ].items 7293 }; 7294 } 7295 return this.controlgroup.apply( this, arguments ); 7296 }; 7297} 7298 7299var widgetsButton = $.ui.button; 7300 7301 7302/* eslint-disable max-len, camelcase */ 7303/*! 7304 * jQuery UI Datepicker 1.13.3 7305 * https://jqueryui.com 7306 * 7307 * Copyright OpenJS Foundation and other contributors 7308 * Released under the MIT license. 7309 * https://jquery.org/license 7310 */ 7311 7312//>>label: Datepicker 7313//>>group: Widgets 7314//>>description: Displays a calendar from an input or inline for selecting dates. 7315//>>docs: https://api.jqueryui.com/datepicker/ 7316//>>demos: https://jqueryui.com/datepicker/ 7317//>>css.structure: ../../themes/base/core.css 7318//>>css.structure: ../../themes/base/datepicker.css 7319//>>css.theme: ../../themes/base/theme.css 7320 7321 7322$.extend( $.ui, { datepicker: { version: "1.13.3" } } ); 7323 7324var datepicker_instActive; 7325 7326function datepicker_getZindex( elem ) { 7327 var position, value; 7328 while ( elem.length && elem[ 0 ] !== document ) { 7329 7330 // Ignore z-index if position is set to a value where z-index is ignored by the browser 7331 // This makes behavior of this function consistent across browsers 7332 // WebKit always returns auto if the element is positioned 7333 position = elem.css( "position" ); 7334 if ( position === "absolute" || position === "relative" || position === "fixed" ) { 7335 7336 // IE returns 0 when zIndex is not specified 7337 // other browsers return a string 7338 // we ignore the case of nested elements with an explicit value of 0 7339 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 7340 value = parseInt( elem.css( "zIndex" ), 10 ); 7341 if ( !isNaN( value ) && value !== 0 ) { 7342 return value; 7343 } 7344 } 7345 elem = elem.parent(); 7346 } 7347 7348 return 0; 7349} 7350 7351/* Date picker manager. 7352 Use the singleton instance of this class, $.datepicker, to interact with the date picker. 7353 Settings for (groups of) date pickers are maintained in an instance object, 7354 allowing multiple different settings on the same page. */ 7355 7356function Datepicker() { 7357 this._curInst = null; // The current instance in use 7358 this._keyEvent = false; // If the last event was a key event 7359 this._disabledInputs = []; // List of date picker inputs that have been disabled 7360 this._datepickerShowing = false; // True if the popup picker is showing , false if not 7361 this._inDialog = false; // True if showing within a "dialog", false if not 7362 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division 7363 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class 7364 this._appendClass = "ui-datepicker-append"; // The name of the append marker class 7365 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class 7366 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class 7367 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class 7368 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class 7369 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class 7370 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class 7371 this.regional = []; // Available regional settings, indexed by language code 7372 this.regional[ "" ] = { // Default regional settings 7373 closeText: "Done", // Display text for close link 7374 prevText: "Prev", // Display text for previous month link 7375 nextText: "Next", // Display text for next month link 7376 currentText: "Today", // Display text for current month link 7377 monthNames: [ "January", "February", "March", "April", "May", "June", 7378 "July", "August", "September", "October", "November", "December" ], // Names of months for drop-down and formatting 7379 monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting 7380 dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting 7381 dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting 7382 dayNamesMin: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], // Column headings for days starting at Sunday 7383 weekHeader: "Wk", // Column header for week of the year 7384 dateFormat: "mm/dd/yy", // See format options on parseDate 7385 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... 7386 isRTL: false, // True if right-to-left language, false if left-to-right 7387 showMonthAfterYear: false, // True if the year select precedes month, false for month then year 7388 yearSuffix: "", // Additional text to append to the year in the month headers, 7389 selectMonthLabel: "Select month", // Invisible label for month selector 7390 selectYearLabel: "Select year" // Invisible label for year selector 7391 }; 7392 this._defaults = { // Global defaults for all the date picker instances 7393 showOn: "focus", // "focus" for popup on focus, 7394 // "button" for trigger button, or "both" for either 7395 showAnim: "fadeIn", // Name of jQuery animation for popup 7396 showOptions: {}, // Options for enhanced animations 7397 defaultDate: null, // Used when field is blank: actual date, 7398 // +/-number for offset from today, null for today 7399 appendText: "", // Display text following the input box, e.g. showing the format 7400 buttonText: "...", // Text for trigger button 7401 buttonImage: "", // URL for trigger button image 7402 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button 7403 hideIfNoPrevNext: false, // True to hide next/previous month links 7404 // if not applicable, false to just disable them 7405 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links 7406 gotoCurrent: false, // True if today link goes back to current selection instead 7407 changeMonth: false, // True if month can be selected directly, false if only prev/next 7408 changeYear: false, // True if year can be selected directly, false if only prev/next 7409 yearRange: "c-10:c+10", // Range of years to display in drop-down, 7410 // either relative to today's year (-nn:+nn), relative to currently displayed year 7411 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) 7412 showOtherMonths: false, // True to show dates in other months, false to leave blank 7413 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable 7414 showWeek: false, // True to show week of the year, false to not show it 7415 calculateWeek: this.iso8601Week, // How to calculate the week of the year, 7416 // takes a Date and returns the number of the week for it 7417 shortYearCutoff: "+10", // Short year values < this are in the current century, 7418 // > this are in the previous century, 7419 // string value starting with "+" for current year + value 7420 minDate: null, // The earliest selectable date, or null for no limit 7421 maxDate: null, // The latest selectable date, or null for no limit 7422 duration: "fast", // Duration of display/closure 7423 beforeShowDay: null, // Function that takes a date and returns an array with 7424 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "", 7425 // [2] = cell title (optional), e.g. $.datepicker.noWeekends 7426 beforeShow: null, // Function that takes an input field and 7427 // returns a set of custom settings for the date picker 7428 onSelect: null, // Define a callback function when a date is selected 7429 onChangeMonthYear: null, // Define a callback function when the month or year is changed 7430 onClose: null, // Define a callback function when the datepicker is closed 7431 onUpdateDatepicker: null, // Define a callback function when the datepicker is updated 7432 numberOfMonths: 1, // Number of months to show at a time 7433 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) 7434 stepMonths: 1, // Number of months to step back/forward 7435 stepBigMonths: 12, // Number of months to step back/forward for the big links 7436 altField: "", // Selector for an alternate field to store selected dates into 7437 altFormat: "", // The date format to use for the alternate field 7438 constrainInput: true, // The input is constrained by the current date format 7439 showButtonPanel: false, // True to show button panel, false to not show it 7440 autoSize: false, // True to size the input for the date format, false to leave as is 7441 disabled: false // The initial disabled state 7442 }; 7443 $.extend( this._defaults, this.regional[ "" ] ); 7444 this.regional.en = $.extend( true, {}, this.regional[ "" ] ); 7445 this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en ); 7446 this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ); 7447} 7448 7449$.extend( Datepicker.prototype, { 7450 7451 /* Class name added to elements to indicate already configured with a date picker. */ 7452 markerClassName: "hasDatepicker", 7453 7454 //Keep track of the maximum number of rows displayed (see #7043) 7455 maxRows: 4, 7456 7457 // TODO rename to "widget" when switching to widget factory 7458 _widgetDatepicker: function() { 7459 return this.dpDiv; 7460 }, 7461 7462 /* Override the default settings for all instances of the date picker. 7463 * @param settings object - the new settings to use as defaults (anonymous object) 7464 * @return the manager object 7465 */ 7466 setDefaults: function( settings ) { 7467 datepicker_extendRemove( this._defaults, settings || {} ); 7468 return this; 7469 }, 7470 7471 /* Attach the date picker to a jQuery selection. 7472 * @param target element - the target input field or division or span 7473 * @param settings object - the new settings to use for this date picker instance (anonymous) 7474 */ 7475 _attachDatepicker: function( target, settings ) { 7476 var nodeName, inline, inst; 7477 nodeName = target.nodeName.toLowerCase(); 7478 inline = ( nodeName === "div" || nodeName === "span" ); 7479 if ( !target.id ) { 7480 this.uuid += 1; 7481 target.id = "dp" + this.uuid; 7482 } 7483 inst = this._newInst( $( target ), inline ); 7484 inst.settings = $.extend( {}, settings || {} ); 7485 if ( nodeName === "input" ) { 7486 this._connectDatepicker( target, inst ); 7487 } else if ( inline ) { 7488 this._inlineDatepicker( target, inst ); 7489 } 7490 }, 7491 7492 /* Create a new instance object. */ 7493 _newInst: function( target, inline ) { 7494 var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars 7495 return { id: id, input: target, // associated target 7496 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection 7497 drawMonth: 0, drawYear: 0, // month being drawn 7498 inline: inline, // is datepicker inline or not 7499 dpDiv: ( !inline ? this.dpDiv : // presentation div 7500 datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) }; 7501 }, 7502 7503 /* Attach the date picker to an input field. */ 7504 _connectDatepicker: function( target, inst ) { 7505 var input = $( target ); 7506 inst.append = $( [] ); 7507 inst.trigger = $( [] ); 7508 if ( input.hasClass( this.markerClassName ) ) { 7509 return; 7510 } 7511 this._attachments( input, inst ); 7512 input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ). 7513 on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp ); 7514 this._autoSize( inst ); 7515 $.data( target, "datepicker", inst ); 7516 7517 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) 7518 if ( inst.settings.disabled ) { 7519 this._disableDatepicker( target ); 7520 } 7521 }, 7522 7523 /* Make attachments based on settings. */ 7524 _attachments: function( input, inst ) { 7525 var showOn, buttonText, buttonImage, 7526 appendText = this._get( inst, "appendText" ), 7527 isRTL = this._get( inst, "isRTL" ); 7528 7529 if ( inst.append ) { 7530 inst.append.remove(); 7531 } 7532 if ( appendText ) { 7533 inst.append = $( "<span>" ) 7534 .addClass( this._appendClass ) 7535 .text( appendText ); 7536 input[ isRTL ? "before" : "after" ]( inst.append ); 7537 } 7538 7539 input.off( "focus", this._showDatepicker ); 7540 7541 if ( inst.trigger ) { 7542 inst.trigger.remove(); 7543 } 7544 7545 showOn = this._get( inst, "showOn" ); 7546 if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field 7547 input.on( "focus", this._showDatepicker ); 7548 } 7549 if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked 7550 buttonText = this._get( inst, "buttonText" ); 7551 buttonImage = this._get( inst, "buttonImage" ); 7552 7553 if ( this._get( inst, "buttonImageOnly" ) ) { 7554 inst.trigger = $( "<img>" ) 7555 .addClass( this._triggerClass ) 7556 .attr( { 7557 src: buttonImage, 7558 alt: buttonText, 7559 title: buttonText 7560 } ); 7561 } else { 7562 inst.trigger = $( "<button type='button'>" ) 7563 .addClass( this._triggerClass ); 7564 if ( buttonImage ) { 7565 inst.trigger.html( 7566 $( "<img>" ) 7567 .attr( { 7568 src: buttonImage, 7569 alt: buttonText, 7570 title: buttonText 7571 } ) 7572 ); 7573 } else { 7574 inst.trigger.text( buttonText ); 7575 } 7576 } 7577 7578 input[ isRTL ? "before" : "after" ]( inst.trigger ); 7579 inst.trigger.on( "click", function() { 7580 if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) { 7581 $.datepicker._hideDatepicker(); 7582 } else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) { 7583 $.datepicker._hideDatepicker(); 7584 $.datepicker._showDatepicker( input[ 0 ] ); 7585 } else { 7586 $.datepicker._showDatepicker( input[ 0 ] ); 7587 } 7588 return false; 7589 } ); 7590 } 7591 }, 7592 7593 /* Apply the maximum length for the date format. */ 7594 _autoSize: function( inst ) { 7595 if ( this._get( inst, "autoSize" ) && !inst.inline ) { 7596 var findMax, max, maxI, i, 7597 date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits 7598 dateFormat = this._get( inst, "dateFormat" ); 7599 7600 if ( dateFormat.match( /[DM]/ ) ) { 7601 findMax = function( names ) { 7602 max = 0; 7603 maxI = 0; 7604 for ( i = 0; i < names.length; i++ ) { 7605 if ( names[ i ].length > max ) { 7606 max = names[ i ].length; 7607 maxI = i; 7608 } 7609 } 7610 return maxI; 7611 }; 7612 date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ? 7613 "monthNames" : "monthNamesShort" ) ) ) ); 7614 date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ? 7615 "dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() ); 7616 } 7617 inst.input.attr( "size", this._formatDate( inst, date ).length ); 7618 } 7619 }, 7620 7621 /* Attach an inline date picker to a div. */ 7622 _inlineDatepicker: function( target, inst ) { 7623 var divSpan = $( target ); 7624 if ( divSpan.hasClass( this.markerClassName ) ) { 7625 return; 7626 } 7627 divSpan.addClass( this.markerClassName ).append( inst.dpDiv ); 7628 $.data( target, "datepicker", inst ); 7629 this._setDate( inst, this._getDefaultDate( inst ), true ); 7630 this._updateDatepicker( inst ); 7631 this._updateAlternate( inst ); 7632 7633 //If disabled option is true, disable the datepicker before showing it (see ticket #5665) 7634 if ( inst.settings.disabled ) { 7635 this._disableDatepicker( target ); 7636 } 7637 7638 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements 7639 // https://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height 7640 inst.dpDiv.css( "display", "block" ); 7641 }, 7642 7643 /* Pop-up the date picker in a "dialog" box. 7644 * @param input element - ignored 7645 * @param date string or Date - the initial date to display 7646 * @param onSelect function - the function to call when a date is selected 7647 * @param settings object - update the dialog date picker instance's settings (anonymous object) 7648 * @param pos int[2] - coordinates for the dialog's position within the screen or 7649 * event - with x/y coordinates or 7650 * leave empty for default (screen centre) 7651 * @return the manager object 7652 */ 7653 _dialogDatepicker: function( input, date, onSelect, settings, pos ) { 7654 var id, browserWidth, browserHeight, scrollX, scrollY, 7655 inst = this._dialogInst; // internal instance 7656 7657 if ( !inst ) { 7658 this.uuid += 1; 7659 id = "dp" + this.uuid; 7660 this._dialogInput = $( "<input type='text' id='" + id + 7661 "' style='position: absolute; top: -100px; width: 0px;'/>" ); 7662 this._dialogInput.on( "keydown", this._doKeyDown ); 7663 $( "body" ).append( this._dialogInput ); 7664 inst = this._dialogInst = this._newInst( this._dialogInput, false ); 7665 inst.settings = {}; 7666 $.data( this._dialogInput[ 0 ], "datepicker", inst ); 7667 } 7668 datepicker_extendRemove( inst.settings, settings || {} ); 7669 date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date ); 7670 this._dialogInput.val( date ); 7671 7672 this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null ); 7673 if ( !this._pos ) { 7674 browserWidth = document.documentElement.clientWidth; 7675 browserHeight = document.documentElement.clientHeight; 7676 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; 7677 scrollY = document.documentElement.scrollTop || document.body.scrollTop; 7678 this._pos = // should use actual width/height below 7679 [ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ]; 7680 } 7681 7682 // Move input on screen for focus, but hidden behind dialog 7683 this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" ); 7684 inst.settings.onSelect = onSelect; 7685 this._inDialog = true; 7686 this.dpDiv.addClass( this._dialogClass ); 7687 this._showDatepicker( this._dialogInput[ 0 ] ); 7688 if ( $.blockUI ) { 7689 $.blockUI( this.dpDiv ); 7690 } 7691 $.data( this._dialogInput[ 0 ], "datepicker", inst ); 7692 return this; 7693 }, 7694 7695 /* Detach a datepicker from its control. 7696 * @param target element - the target input field or division or span 7697 */ 7698 _destroyDatepicker: function( target ) { 7699 var nodeName, 7700 $target = $( target ), 7701 inst = $.data( target, "datepicker" ); 7702 7703 if ( !$target.hasClass( this.markerClassName ) ) { 7704 return; 7705 } 7706 7707 nodeName = target.nodeName.toLowerCase(); 7708 $.removeData( target, "datepicker" ); 7709 if ( nodeName === "input" ) { 7710 inst.append.remove(); 7711 inst.trigger.remove(); 7712 $target.removeClass( this.markerClassName ). 7713 off( "focus", this._showDatepicker ). 7714 off( "keydown", this._doKeyDown ). 7715 off( "keypress", this._doKeyPress ). 7716 off( "keyup", this._doKeyUp ); 7717 } else if ( nodeName === "div" || nodeName === "span" ) { 7718 $target.removeClass( this.markerClassName ).empty(); 7719 } 7720 7721 if ( datepicker_instActive === inst ) { 7722 datepicker_instActive = null; 7723 this._curInst = null; 7724 } 7725 }, 7726 7727 /* Enable the date picker to a jQuery selection. 7728 * @param target element - the target input field or division or span 7729 */ 7730 _enableDatepicker: function( target ) { 7731 var nodeName, inline, 7732 $target = $( target ), 7733 inst = $.data( target, "datepicker" ); 7734 7735 if ( !$target.hasClass( this.markerClassName ) ) { 7736 return; 7737 } 7738 7739 nodeName = target.nodeName.toLowerCase(); 7740 if ( nodeName === "input" ) { 7741 target.disabled = false; 7742 inst.trigger.filter( "button" ). 7743 each( function() { 7744 this.disabled = false; 7745 } ).end(). 7746 filter( "img" ).css( { opacity: "1.0", cursor: "" } ); 7747 } else if ( nodeName === "div" || nodeName === "span" ) { 7748 inline = $target.children( "." + this._inlineClass ); 7749 inline.children().removeClass( "ui-state-disabled" ); 7750 inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ). 7751 prop( "disabled", false ); 7752 } 7753 this._disabledInputs = $.map( this._disabledInputs, 7754 7755 // Delete entry 7756 function( value ) { 7757 return ( value === target ? null : value ); 7758 } ); 7759 }, 7760 7761 /* Disable the date picker to a jQuery selection. 7762 * @param target element - the target input field or division or span 7763 */ 7764 _disableDatepicker: function( target ) { 7765 var nodeName, inline, 7766 $target = $( target ), 7767 inst = $.data( target, "datepicker" ); 7768 7769 if ( !$target.hasClass( this.markerClassName ) ) { 7770 return; 7771 } 7772 7773 nodeName = target.nodeName.toLowerCase(); 7774 if ( nodeName === "input" ) { 7775 target.disabled = true; 7776 inst.trigger.filter( "button" ). 7777 each( function() { 7778 this.disabled = true; 7779 } ).end(). 7780 filter( "img" ).css( { opacity: "0.5", cursor: "default" } ); 7781 } else if ( nodeName === "div" || nodeName === "span" ) { 7782 inline = $target.children( "." + this._inlineClass ); 7783 inline.children().addClass( "ui-state-disabled" ); 7784 inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ). 7785 prop( "disabled", true ); 7786 } 7787 this._disabledInputs = $.map( this._disabledInputs, 7788 7789 // Delete entry 7790 function( value ) { 7791 return ( value === target ? null : value ); 7792 } ); 7793 this._disabledInputs[ this._disabledInputs.length ] = target; 7794 }, 7795 7796 /* Is the first field in a jQuery collection disabled as a datepicker? 7797 * @param target element - the target input field or division or span 7798 * @return boolean - true if disabled, false if enabled 7799 */ 7800 _isDisabledDatepicker: function( target ) { 7801 if ( !target ) { 7802 return false; 7803 } 7804 for ( var i = 0; i < this._disabledInputs.length; i++ ) { 7805 if ( this._disabledInputs[ i ] === target ) { 7806 return true; 7807 } 7808 } 7809 return false; 7810 }, 7811 7812 /* Retrieve the instance data for the target control. 7813 * @param target element - the target input field or division or span 7814 * @return object - the associated instance data 7815 * @throws error if a jQuery problem getting data 7816 */ 7817 _getInst: function( target ) { 7818 try { 7819 return $.data( target, "datepicker" ); 7820 } catch ( err ) { 7821 throw "Missing instance data for this datepicker"; 7822 } 7823 }, 7824 7825 /* Update or retrieve the settings for a date picker attached to an input field or division. 7826 * @param target element - the target input field or division or span 7827 * @param name object - the new settings to update or 7828 * string - the name of the setting to change or retrieve, 7829 * when retrieving also "all" for all instance settings or 7830 * "defaults" for all global defaults 7831 * @param value any - the new value for the setting 7832 * (omit if above is an object or to retrieve a value) 7833 */ 7834 _optionDatepicker: function( target, name, value ) { 7835 var settings, date, minDate, maxDate, 7836 inst = this._getInst( target ); 7837 7838 if ( arguments.length === 2 && typeof name === "string" ) { 7839 return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) : 7840 ( inst ? ( name === "all" ? $.extend( {}, inst.settings ) : 7841 this._get( inst, name ) ) : null ) ); 7842 } 7843 7844 settings = name || {}; 7845 if ( typeof name === "string" ) { 7846 settings = {}; 7847 settings[ name ] = value; 7848 } 7849 7850 if ( inst ) { 7851 if ( this._curInst === inst ) { 7852 this._hideDatepicker(); 7853 } 7854 7855 date = this._getDateDatepicker( target, true ); 7856 minDate = this._getMinMaxDate( inst, "min" ); 7857 maxDate = this._getMinMaxDate( inst, "max" ); 7858 datepicker_extendRemove( inst.settings, settings ); 7859 7860 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided 7861 if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) { 7862 inst.settings.minDate = this._formatDate( inst, minDate ); 7863 } 7864 if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) { 7865 inst.settings.maxDate = this._formatDate( inst, maxDate ); 7866 } 7867 if ( "disabled" in settings ) { 7868 if ( settings.disabled ) { 7869 this._disableDatepicker( target ); 7870 } else { 7871 this._enableDatepicker( target ); 7872 } 7873 } 7874 this._attachments( $( target ), inst ); 7875 this._autoSize( inst ); 7876 this._setDate( inst, date ); 7877 this._updateAlternate( inst ); 7878 this._updateDatepicker( inst ); 7879 } 7880 }, 7881 7882 // Change method deprecated 7883 _changeDatepicker: function( target, name, value ) { 7884 this._optionDatepicker( target, name, value ); 7885 }, 7886 7887 /* Redraw the date picker attached to an input field or division. 7888 * @param target element - the target input field or division or span 7889 */ 7890 _refreshDatepicker: function( target ) { 7891 var inst = this._getInst( target ); 7892 if ( inst ) { 7893 this._updateDatepicker( inst ); 7894 } 7895 }, 7896 7897 /* Set the dates for a jQuery selection. 7898 * @param target element - the target input field or division or span 7899 * @param date Date - the new date 7900 */ 7901 _setDateDatepicker: function( target, date ) { 7902 var inst = this._getInst( target ); 7903 if ( inst ) { 7904 this._setDate( inst, date ); 7905 this._updateDatepicker( inst ); 7906 this._updateAlternate( inst ); 7907 } 7908 }, 7909 7910 /* Get the date(s) for the first entry in a jQuery selection. 7911 * @param target element - the target input field or division or span 7912 * @param noDefault boolean - true if no default date is to be used 7913 * @return Date - the current date 7914 */ 7915 _getDateDatepicker: function( target, noDefault ) { 7916 var inst = this._getInst( target ); 7917 if ( inst && !inst.inline ) { 7918 this._setDateFromField( inst, noDefault ); 7919 } 7920 return ( inst ? this._getDate( inst ) : null ); 7921 }, 7922 7923 /* Handle keystrokes. */ 7924 _doKeyDown: function( event ) { 7925 var onSelect, dateStr, sel, 7926 inst = $.datepicker._getInst( event.target ), 7927 handled = true, 7928 isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" ); 7929 7930 inst._keyEvent = true; 7931 if ( $.datepicker._datepickerShowing ) { 7932 switch ( event.keyCode ) { 7933 case 9: $.datepicker._hideDatepicker(); 7934 handled = false; 7935 break; // hide on tab out 7936 case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." + 7937 $.datepicker._currentClass + ")", inst.dpDiv ); 7938 if ( sel[ 0 ] ) { 7939 $.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] ); 7940 } 7941 7942 onSelect = $.datepicker._get( inst, "onSelect" ); 7943 if ( onSelect ) { 7944 dateStr = $.datepicker._formatDate( inst ); 7945 7946 // Trigger custom callback 7947 onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] ); 7948 } else { 7949 $.datepicker._hideDatepicker(); 7950 } 7951 7952 return false; // don't submit the form 7953 case 27: $.datepicker._hideDatepicker(); 7954 break; // hide on escape 7955 case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 7956 -$.datepicker._get( inst, "stepBigMonths" ) : 7957 -$.datepicker._get( inst, "stepMonths" ) ), "M" ); 7958 break; // previous month/year on page up/+ ctrl 7959 case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 7960 +$.datepicker._get( inst, "stepBigMonths" ) : 7961 +$.datepicker._get( inst, "stepMonths" ) ), "M" ); 7962 break; // next month/year on page down/+ ctrl 7963 case 35: if ( event.ctrlKey || event.metaKey ) { 7964 $.datepicker._clearDate( event.target ); 7965 } 7966 handled = event.ctrlKey || event.metaKey; 7967 break; // clear on ctrl or command +end 7968 case 36: if ( event.ctrlKey || event.metaKey ) { 7969 $.datepicker._gotoToday( event.target ); 7970 } 7971 handled = event.ctrlKey || event.metaKey; 7972 break; // current on ctrl or command +home 7973 case 37: if ( event.ctrlKey || event.metaKey ) { 7974 $.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" ); 7975 } 7976 handled = event.ctrlKey || event.metaKey; 7977 7978 // -1 day on ctrl or command +left 7979 if ( event.originalEvent.altKey ) { 7980 $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 7981 -$.datepicker._get( inst, "stepBigMonths" ) : 7982 -$.datepicker._get( inst, "stepMonths" ) ), "M" ); 7983 } 7984 7985 // next month/year on alt +left on Mac 7986 break; 7987 case 38: if ( event.ctrlKey || event.metaKey ) { 7988 $.datepicker._adjustDate( event.target, -7, "D" ); 7989 } 7990 handled = event.ctrlKey || event.metaKey; 7991 break; // -1 week on ctrl or command +up 7992 case 39: if ( event.ctrlKey || event.metaKey ) { 7993 $.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" ); 7994 } 7995 handled = event.ctrlKey || event.metaKey; 7996 7997 // +1 day on ctrl or command +right 7998 if ( event.originalEvent.altKey ) { 7999 $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 8000 +$.datepicker._get( inst, "stepBigMonths" ) : 8001 +$.datepicker._get( inst, "stepMonths" ) ), "M" ); 8002 } 8003 8004 // next month/year on alt +right 8005 break; 8006 case 40: if ( event.ctrlKey || event.metaKey ) { 8007 $.datepicker._adjustDate( event.target, +7, "D" ); 8008 } 8009 handled = event.ctrlKey || event.metaKey; 8010 break; // +1 week on ctrl or command +down 8011 default: handled = false; 8012 } 8013 } else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home 8014 $.datepicker._showDatepicker( this ); 8015 } else { 8016 handled = false; 8017 } 8018 8019 if ( handled ) { 8020 event.preventDefault(); 8021 event.stopPropagation(); 8022 } 8023 }, 8024 8025 /* Filter entered characters - based on date format. */ 8026 _doKeyPress: function( event ) { 8027 var chars, chr, 8028 inst = $.datepicker._getInst( event.target ); 8029 8030 if ( $.datepicker._get( inst, "constrainInput" ) ) { 8031 chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) ); 8032 chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode ); 8033 return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 ); 8034 } 8035 }, 8036 8037 /* Synchronise manual entry and field/alternate field. */ 8038 _doKeyUp: function( event ) { 8039 var date, 8040 inst = $.datepicker._getInst( event.target ); 8041 8042 if ( inst.input.val() !== inst.lastVal ) { 8043 try { 8044 date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ), 8045 ( inst.input ? inst.input.val() : null ), 8046 $.datepicker._getFormatConfig( inst ) ); 8047 8048 if ( date ) { // only if valid 8049 $.datepicker._setDateFromField( inst ); 8050 $.datepicker._updateAlternate( inst ); 8051 $.datepicker._updateDatepicker( inst ); 8052 } 8053 } catch ( err ) { 8054 } 8055 } 8056 return true; 8057 }, 8058 8059 /* Pop-up the date picker for a given input field. 8060 * If false returned from beforeShow event handler do not show. 8061 * @param input element - the input field attached to the date picker or 8062 * event - if triggered by focus 8063 */ 8064 _showDatepicker: function( input ) { 8065 input = input.target || input; 8066 if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger 8067 input = $( "input", input.parentNode )[ 0 ]; 8068 } 8069 8070 if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here 8071 return; 8072 } 8073 8074 var inst, beforeShow, beforeShowSettings, isFixed, 8075 offset, showAnim, duration; 8076 8077 inst = $.datepicker._getInst( input ); 8078 if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) { 8079 $.datepicker._curInst.dpDiv.stop( true, true ); 8080 if ( inst && $.datepicker._datepickerShowing ) { 8081 $.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] ); 8082 } 8083 } 8084 8085 beforeShow = $.datepicker._get( inst, "beforeShow" ); 8086 beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {}; 8087 if ( beforeShowSettings === false ) { 8088 return; 8089 } 8090 datepicker_extendRemove( inst.settings, beforeShowSettings ); 8091 8092 inst.lastVal = null; 8093 $.datepicker._lastInput = input; 8094 $.datepicker._setDateFromField( inst ); 8095 8096 if ( $.datepicker._inDialog ) { // hide cursor 8097 input.value = ""; 8098 } 8099 if ( !$.datepicker._pos ) { // position below input 8100 $.datepicker._pos = $.datepicker._findPos( input ); 8101 $.datepicker._pos[ 1 ] += input.offsetHeight; // add the height 8102 } 8103 8104 isFixed = false; 8105 $( input ).parents().each( function() { 8106 isFixed |= $( this ).css( "position" ) === "fixed"; 8107 return !isFixed; 8108 } ); 8109 8110 offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] }; 8111 $.datepicker._pos = null; 8112 8113 //to avoid flashes on Firefox 8114 inst.dpDiv.empty(); 8115 8116 // determine sizing offscreen 8117 inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } ); 8118 $.datepicker._updateDatepicker( inst ); 8119 8120 // fix width for dynamic number of date pickers 8121 // and adjust position before showing 8122 offset = $.datepicker._checkOffset( inst, offset, isFixed ); 8123 inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ? 8124 "static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none", 8125 left: offset.left + "px", top: offset.top + "px" } ); 8126 8127 if ( !inst.inline ) { 8128 showAnim = $.datepicker._get( inst, "showAnim" ); 8129 duration = $.datepicker._get( inst, "duration" ); 8130 inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 ); 8131 $.datepicker._datepickerShowing = true; 8132 8133 if ( $.effects && $.effects.effect[ showAnim ] ) { 8134 inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration ); 8135 } else { 8136 inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null ); 8137 } 8138 8139 if ( $.datepicker._shouldFocusInput( inst ) ) { 8140 inst.input.trigger( "focus" ); 8141 } 8142 8143 $.datepicker._curInst = inst; 8144 } 8145 }, 8146 8147 /* Generate the date picker content. */ 8148 _updateDatepicker: function( inst ) { 8149 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) 8150 datepicker_instActive = inst; // for delegate hover events 8151 inst.dpDiv.empty().append( this._generateHTML( inst ) ); 8152 this._attachHandlers( inst ); 8153 8154 var origyearshtml, 8155 numMonths = this._getNumberOfMonths( inst ), 8156 cols = numMonths[ 1 ], 8157 width = 17, 8158 activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ), 8159 onUpdateDatepicker = $.datepicker._get( inst, "onUpdateDatepicker" ); 8160 8161 if ( activeCell.length > 0 ) { 8162 datepicker_handleMouseover.apply( activeCell.get( 0 ) ); 8163 } 8164 8165 inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" ); 8166 if ( cols > 1 ) { 8167 inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" ); 8168 } 8169 inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) + 8170 "Class" ]( "ui-datepicker-multi" ); 8171 inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) + 8172 "Class" ]( "ui-datepicker-rtl" ); 8173 8174 if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) { 8175 inst.input.trigger( "focus" ); 8176 } 8177 8178 // Deffered render of the years select (to avoid flashes on Firefox) 8179 if ( inst.yearshtml ) { 8180 origyearshtml = inst.yearshtml; 8181 setTimeout( function() { 8182 8183 //assure that inst.yearshtml didn't change. 8184 if ( origyearshtml === inst.yearshtml && inst.yearshtml ) { 8185 inst.dpDiv.find( "select.ui-datepicker-year" ).first().replaceWith( inst.yearshtml ); 8186 } 8187 origyearshtml = inst.yearshtml = null; 8188 }, 0 ); 8189 } 8190 8191 if ( onUpdateDatepicker ) { 8192 onUpdateDatepicker.apply( ( inst.input ? inst.input[ 0 ] : null ), [ inst ] ); 8193 } 8194 }, 8195 8196 // #6694 - don't focus the input if it's already focused 8197 // this breaks the change event in IE 8198 // Support: IE and jQuery <1.9 8199 _shouldFocusInput: function( inst ) { 8200 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" ); 8201 }, 8202 8203 /* Check positioning to remain on screen. */ 8204 _checkOffset: function( inst, offset, isFixed ) { 8205 var dpWidth = inst.dpDiv.outerWidth(), 8206 dpHeight = inst.dpDiv.outerHeight(), 8207 inputWidth = inst.input ? inst.input.outerWidth() : 0, 8208 inputHeight = inst.input ? inst.input.outerHeight() : 0, 8209 viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ), 8210 viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() ); 8211 8212 offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 ); 8213 offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0; 8214 offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0; 8215 8216 // Now check if datepicker is showing outside window viewport - move to a better place if so. 8217 offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ? 8218 Math.abs( offset.left + dpWidth - viewWidth ) : 0 ); 8219 offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ? 8220 Math.abs( dpHeight + inputHeight ) : 0 ); 8221 8222 return offset; 8223 }, 8224 8225 /* Find an object's position on the screen. */ 8226 _findPos: function( obj ) { 8227 var position, 8228 inst = this._getInst( obj ), 8229 isRTL = this._get( inst, "isRTL" ); 8230 8231 while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden( obj ) ) ) { 8232 obj = obj[ isRTL ? "previousSibling" : "nextSibling" ]; 8233 } 8234 8235 position = $( obj ).offset(); 8236 return [ position.left, position.top ]; 8237 }, 8238 8239 /* Hide the date picker from view. 8240 * @param input element - the input field attached to the date picker 8241 */ 8242 _hideDatepicker: function( input ) { 8243 var showAnim, duration, postProcess, onClose, 8244 inst = this._curInst; 8245 8246 if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) { 8247 return; 8248 } 8249 8250 if ( this._datepickerShowing ) { 8251 showAnim = this._get( inst, "showAnim" ); 8252 duration = this._get( inst, "duration" ); 8253 postProcess = function() { 8254 $.datepicker._tidyDialog( inst ); 8255 }; 8256 8257 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed 8258 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) { 8259 inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess ); 8260 } else { 8261 inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" : 8262 ( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess ); 8263 } 8264 8265 if ( !showAnim ) { 8266 postProcess(); 8267 } 8268 this._datepickerShowing = false; 8269 8270 onClose = this._get( inst, "onClose" ); 8271 if ( onClose ) { 8272 onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] ); 8273 } 8274 8275 this._lastInput = null; 8276 if ( this._inDialog ) { 8277 this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } ); 8278 if ( $.blockUI ) { 8279 $.unblockUI(); 8280 $( "body" ).append( this.dpDiv ); 8281 } 8282 } 8283 this._inDialog = false; 8284 } 8285 }, 8286 8287 /* Tidy up after a dialog display. */ 8288 _tidyDialog: function( inst ) { 8289 inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" ); 8290 }, 8291 8292 /* Close date picker if clicked elsewhere. */ 8293 _checkExternalClick: function( event ) { 8294 if ( !$.datepicker._curInst ) { 8295 return; 8296 } 8297 8298 var $target = $( event.target ), 8299 inst = $.datepicker._getInst( $target[ 0 ] ); 8300 8301 if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId && 8302 $target.parents( "#" + $.datepicker._mainDivId ).length === 0 && 8303 !$target.hasClass( $.datepicker.markerClassName ) && 8304 !$target.closest( "." + $.datepicker._triggerClass ).length && 8305 $.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) || 8306 ( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) { 8307 $.datepicker._hideDatepicker(); 8308 } 8309 }, 8310 8311 /* Adjust one of the date sub-fields. */ 8312 _adjustDate: function( id, offset, period ) { 8313 var target = $( id ), 8314 inst = this._getInst( target[ 0 ] ); 8315 8316 if ( this._isDisabledDatepicker( target[ 0 ] ) ) { 8317 return; 8318 } 8319 this._adjustInstDate( inst, offset, period ); 8320 this._updateDatepicker( inst ); 8321 }, 8322 8323 /* Action for current link. */ 8324 _gotoToday: function( id ) { 8325 var date, 8326 target = $( id ), 8327 inst = this._getInst( target[ 0 ] ); 8328 8329 if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) { 8330 inst.selectedDay = inst.currentDay; 8331 inst.drawMonth = inst.selectedMonth = inst.currentMonth; 8332 inst.drawYear = inst.selectedYear = inst.currentYear; 8333 } else { 8334 date = new Date(); 8335 inst.selectedDay = date.getDate(); 8336 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8337 inst.drawYear = inst.selectedYear = date.getFullYear(); 8338 } 8339 this._notifyChange( inst ); 8340 this._adjustDate( target ); 8341 }, 8342 8343 /* Action for selecting a new month/year. */ 8344 _selectMonthYear: function( id, select, period ) { 8345 var target = $( id ), 8346 inst = this._getInst( target[ 0 ] ); 8347 8348 inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] = 8349 inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] = 8350 parseInt( select.options[ select.selectedIndex ].value, 10 ); 8351 8352 this._notifyChange( inst ); 8353 this._adjustDate( target ); 8354 }, 8355 8356 /* Action for selecting a day. */ 8357 _selectDay: function( id, month, year, td ) { 8358 var inst, 8359 target = $( id ); 8360 8361 if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) { 8362 return; 8363 } 8364 8365 inst = this._getInst( target[ 0 ] ); 8366 inst.selectedDay = inst.currentDay = parseInt( $( "a", td ).attr( "data-date" ) ); 8367 inst.selectedMonth = inst.currentMonth = month; 8368 inst.selectedYear = inst.currentYear = year; 8369 this._selectDate( id, this._formatDate( inst, 8370 inst.currentDay, inst.currentMonth, inst.currentYear ) ); 8371 }, 8372 8373 /* Erase the input field and hide the date picker. */ 8374 _clearDate: function( id ) { 8375 var target = $( id ); 8376 this._selectDate( target, "" ); 8377 }, 8378 8379 /* Update the input field with the selected date. */ 8380 _selectDate: function( id, dateStr ) { 8381 var onSelect, 8382 target = $( id ), 8383 inst = this._getInst( target[ 0 ] ); 8384 8385 dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) ); 8386 if ( inst.input ) { 8387 inst.input.val( dateStr ); 8388 } 8389 this._updateAlternate( inst ); 8390 8391 onSelect = this._get( inst, "onSelect" ); 8392 if ( onSelect ) { 8393 onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] ); // trigger custom callback 8394 } else if ( inst.input ) { 8395 inst.input.trigger( "change" ); // fire the change event 8396 } 8397 8398 if ( inst.inline ) { 8399 this._updateDatepicker( inst ); 8400 } else { 8401 this._hideDatepicker(); 8402 this._lastInput = inst.input[ 0 ]; 8403 if ( typeof( inst.input[ 0 ] ) !== "object" ) { 8404 inst.input.trigger( "focus" ); // restore focus 8405 } 8406 this._lastInput = null; 8407 } 8408 }, 8409 8410 /* Update any alternate field to synchronise with the main field. */ 8411 _updateAlternate: function( inst ) { 8412 var altFormat, date, dateStr, 8413 altField = this._get( inst, "altField" ); 8414 8415 if ( altField ) { // update alternate field too 8416 altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" ); 8417 date = this._getDate( inst ); 8418 dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) ); 8419 $( document ).find( altField ).val( dateStr ); 8420 } 8421 }, 8422 8423 /* Set as beforeShowDay function to prevent selection of weekends. 8424 * @param date Date - the date to customise 8425 * @return [boolean, string] - is this date selectable?, what is its CSS class? 8426 */ 8427 noWeekends: function( date ) { 8428 var day = date.getDay(); 8429 return [ ( day > 0 && day < 6 ), "" ]; 8430 }, 8431 8432 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. 8433 * @param date Date - the date to get the week for 8434 * @return number - the number of the week within the year that contains this date 8435 */ 8436 iso8601Week: function( date ) { 8437 var time, 8438 checkDate = new Date( date.getTime() ); 8439 8440 // Find Thursday of this week starting on Monday 8441 checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) ); 8442 8443 time = checkDate.getTime(); 8444 checkDate.setMonth( 0 ); // Compare with Jan 1 8445 checkDate.setDate( 1 ); 8446 return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1; 8447 }, 8448 8449 /* Parse a string value into a date object. 8450 * See formatDate below for the possible formats. 8451 * 8452 * @param format string - the expected format of the date 8453 * @param value string - the date in the above format 8454 * @param settings Object - attributes include: 8455 * shortYearCutoff number - the cutoff year for determining the century (optional) 8456 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 8457 * dayNames string[7] - names of the days from Sunday (optional) 8458 * monthNamesShort string[12] - abbreviated names of the months (optional) 8459 * monthNames string[12] - names of the months (optional) 8460 * @return Date - the extracted date value or null if value is blank 8461 */ 8462 parseDate: function( format, value, settings ) { 8463 if ( format == null || value == null ) { 8464 throw "Invalid arguments"; 8465 } 8466 8467 value = ( typeof value === "object" ? value.toString() : value + "" ); 8468 if ( value === "" ) { 8469 return null; 8470 } 8471 8472 var iFormat, dim, extra, 8473 iValue = 0, 8474 shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff, 8475 shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp : 8476 new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ), 8477 dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort, 8478 dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames, 8479 monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort, 8480 monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames, 8481 year = -1, 8482 month = -1, 8483 day = -1, 8484 doy = -1, 8485 literal = false, 8486 date, 8487 8488 // Check whether a format character is doubled 8489 lookAhead = function( match ) { 8490 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match ); 8491 if ( matches ) { 8492 iFormat++; 8493 } 8494 return matches; 8495 }, 8496 8497 // Extract a number from the string value 8498 getNumber = function( match ) { 8499 var isDoubled = lookAhead( match ), 8500 size = ( match === "@" ? 14 : ( match === "!" ? 20 : 8501 ( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ), 8502 minSize = ( match === "y" ? size : 1 ), 8503 digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ), 8504 num = value.substring( iValue ).match( digits ); 8505 if ( !num ) { 8506 throw "Missing number at position " + iValue; 8507 } 8508 iValue += num[ 0 ].length; 8509 return parseInt( num[ 0 ], 10 ); 8510 }, 8511 8512 // Extract a name from the string value and convert to an index 8513 getName = function( match, shortNames, longNames ) { 8514 var index = -1, 8515 names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) { 8516 return [ [ k, v ] ]; 8517 } ).sort( function( a, b ) { 8518 return -( a[ 1 ].length - b[ 1 ].length ); 8519 } ); 8520 8521 $.each( names, function( i, pair ) { 8522 var name = pair[ 1 ]; 8523 if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) { 8524 index = pair[ 0 ]; 8525 iValue += name.length; 8526 return false; 8527 } 8528 } ); 8529 if ( index !== -1 ) { 8530 return index + 1; 8531 } else { 8532 throw "Unknown name at position " + iValue; 8533 } 8534 }, 8535 8536 // Confirm that a literal character matches the string value 8537 checkLiteral = function() { 8538 if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) { 8539 throw "Unexpected literal at position " + iValue; 8540 } 8541 iValue++; 8542 }; 8543 8544 for ( iFormat = 0; iFormat < format.length; iFormat++ ) { 8545 if ( literal ) { 8546 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) { 8547 literal = false; 8548 } else { 8549 checkLiteral(); 8550 } 8551 } else { 8552 switch ( format.charAt( iFormat ) ) { 8553 case "d": 8554 day = getNumber( "d" ); 8555 break; 8556 case "D": 8557 getName( "D", dayNamesShort, dayNames ); 8558 break; 8559 case "o": 8560 doy = getNumber( "o" ); 8561 break; 8562 case "m": 8563 month = getNumber( "m" ); 8564 break; 8565 case "M": 8566 month = getName( "M", monthNamesShort, monthNames ); 8567 break; 8568 case "y": 8569 year = getNumber( "y" ); 8570 break; 8571 case "@": 8572 date = new Date( getNumber( "@" ) ); 8573 year = date.getFullYear(); 8574 month = date.getMonth() + 1; 8575 day = date.getDate(); 8576 break; 8577 case "!": 8578 date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 ); 8579 year = date.getFullYear(); 8580 month = date.getMonth() + 1; 8581 day = date.getDate(); 8582 break; 8583 case "'": 8584 if ( lookAhead( "'" ) ) { 8585 checkLiteral(); 8586 } else { 8587 literal = true; 8588 } 8589 break; 8590 default: 8591 checkLiteral(); 8592 } 8593 } 8594 } 8595 8596 if ( iValue < value.length ) { 8597 extra = value.substr( iValue ); 8598 if ( !/^\s+/.test( extra ) ) { 8599 throw "Extra/unparsed characters found in date: " + extra; 8600 } 8601 } 8602 8603 if ( year === -1 ) { 8604 year = new Date().getFullYear(); 8605 } else if ( year < 100 ) { 8606 year += new Date().getFullYear() - new Date().getFullYear() % 100 + 8607 ( year <= shortYearCutoff ? 0 : -100 ); 8608 } 8609 8610 if ( doy > -1 ) { 8611 month = 1; 8612 day = doy; 8613 do { 8614 dim = this._getDaysInMonth( year, month - 1 ); 8615 if ( day <= dim ) { 8616 break; 8617 } 8618 month++; 8619 day -= dim; 8620 } while ( true ); 8621 } 8622 8623 date = this._daylightSavingAdjust( new Date( year, month - 1, day ) ); 8624 if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) { 8625 throw "Invalid date"; // E.g. 31/02/00 8626 } 8627 return date; 8628 }, 8629 8630 /* Standard date formats. */ 8631 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601) 8632 COOKIE: "D, dd M yy", 8633 ISO_8601: "yy-mm-dd", 8634 RFC_822: "D, d M y", 8635 RFC_850: "DD, dd-M-y", 8636 RFC_1036: "D, d M y", 8637 RFC_1123: "D, d M yy", 8638 RFC_2822: "D, d M yy", 8639 RSS: "D, d M y", // RFC 822 8640 TICKS: "!", 8641 TIMESTAMP: "@", 8642 W3C: "yy-mm-dd", // ISO 8601 8643 8644 _ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) + 8645 Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ), 8646 8647 /* Format a date object into a string value. 8648 * The format can be combinations of the following: 8649 * d - day of month (no leading zero) 8650 * dd - day of month (two digit) 8651 * o - day of year (no leading zeros) 8652 * oo - day of year (three digit) 8653 * D - day name short 8654 * DD - day name long 8655 * m - month of year (no leading zero) 8656 * mm - month of year (two digit) 8657 * M - month name short 8658 * MM - month name long 8659 * y - year (two digit) 8660 * yy - year (four digit) 8661 * @ - Unix timestamp (ms since 01/01/1970) 8662 * ! - Windows ticks (100ns since 01/01/0001) 8663 * "..." - literal text 8664 * '' - single quote 8665 * 8666 * @param format string - the desired format of the date 8667 * @param date Date - the date value to format 8668 * @param settings Object - attributes include: 8669 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 8670 * dayNames string[7] - names of the days from Sunday (optional) 8671 * monthNamesShort string[12] - abbreviated names of the months (optional) 8672 * monthNames string[12] - names of the months (optional) 8673 * @return string - the date in the above format 8674 */ 8675 formatDate: function( format, date, settings ) { 8676 if ( !date ) { 8677 return ""; 8678 } 8679 8680 var iFormat, 8681 dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort, 8682 dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames, 8683 monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort, 8684 monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames, 8685 8686 // Check whether a format character is doubled 8687 lookAhead = function( match ) { 8688 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match ); 8689 if ( matches ) { 8690 iFormat++; 8691 } 8692 return matches; 8693 }, 8694 8695 // Format a number, with leading zero if necessary 8696 formatNumber = function( match, value, len ) { 8697 var num = "" + value; 8698 if ( lookAhead( match ) ) { 8699 while ( num.length < len ) { 8700 num = "0" + num; 8701 } 8702 } 8703 return num; 8704 }, 8705 8706 // Format a name, short or long as requested 8707 formatName = function( match, value, shortNames, longNames ) { 8708 return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] ); 8709 }, 8710 output = "", 8711 literal = false; 8712 8713 if ( date ) { 8714 for ( iFormat = 0; iFormat < format.length; iFormat++ ) { 8715 if ( literal ) { 8716 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) { 8717 literal = false; 8718 } else { 8719 output += format.charAt( iFormat ); 8720 } 8721 } else { 8722 switch ( format.charAt( iFormat ) ) { 8723 case "d": 8724 output += formatNumber( "d", date.getDate(), 2 ); 8725 break; 8726 case "D": 8727 output += formatName( "D", date.getDay(), dayNamesShort, dayNames ); 8728 break; 8729 case "o": 8730 output += formatNumber( "o", 8731 Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 ); 8732 break; 8733 case "m": 8734 output += formatNumber( "m", date.getMonth() + 1, 2 ); 8735 break; 8736 case "M": 8737 output += formatName( "M", date.getMonth(), monthNamesShort, monthNames ); 8738 break; 8739 case "y": 8740 output += ( lookAhead( "y" ) ? date.getFullYear() : 8741 ( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 ); 8742 break; 8743 case "@": 8744 output += date.getTime(); 8745 break; 8746 case "!": 8747 output += date.getTime() * 10000 + this._ticksTo1970; 8748 break; 8749 case "'": 8750 if ( lookAhead( "'" ) ) { 8751 output += "'"; 8752 } else { 8753 literal = true; 8754 } 8755 break; 8756 default: 8757 output += format.charAt( iFormat ); 8758 } 8759 } 8760 } 8761 } 8762 return output; 8763 }, 8764 8765 /* Extract all possible characters from the date format. */ 8766 _possibleChars: function( format ) { 8767 var iFormat, 8768 chars = "", 8769 literal = false, 8770 8771 // Check whether a format character is doubled 8772 lookAhead = function( match ) { 8773 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match ); 8774 if ( matches ) { 8775 iFormat++; 8776 } 8777 return matches; 8778 }; 8779 8780 for ( iFormat = 0; iFormat < format.length; iFormat++ ) { 8781 if ( literal ) { 8782 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) { 8783 literal = false; 8784 } else { 8785 chars += format.charAt( iFormat ); 8786 } 8787 } else { 8788 switch ( format.charAt( iFormat ) ) { 8789 case "d": case "m": case "y": case "@": 8790 chars += "0123456789"; 8791 break; 8792 case "D": case "M": 8793 return null; // Accept anything 8794 case "'": 8795 if ( lookAhead( "'" ) ) { 8796 chars += "'"; 8797 } else { 8798 literal = true; 8799 } 8800 break; 8801 default: 8802 chars += format.charAt( iFormat ); 8803 } 8804 } 8805 } 8806 return chars; 8807 }, 8808 8809 /* Get a setting value, defaulting if necessary. */ 8810 _get: function( inst, name ) { 8811 return inst.settings[ name ] !== undefined ? 8812 inst.settings[ name ] : this._defaults[ name ]; 8813 }, 8814 8815 /* Parse existing date and initialise date picker. */ 8816 _setDateFromField: function( inst, noDefault ) { 8817 if ( inst.input.val() === inst.lastVal ) { 8818 return; 8819 } 8820 8821 var dateFormat = this._get( inst, "dateFormat" ), 8822 dates = inst.lastVal = inst.input ? inst.input.val() : null, 8823 defaultDate = this._getDefaultDate( inst ), 8824 date = defaultDate, 8825 settings = this._getFormatConfig( inst ); 8826 8827 try { 8828 date = this.parseDate( dateFormat, dates, settings ) || defaultDate; 8829 } catch ( event ) { 8830 dates = ( noDefault ? "" : dates ); 8831 } 8832 inst.selectedDay = date.getDate(); 8833 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8834 inst.drawYear = inst.selectedYear = date.getFullYear(); 8835 inst.currentDay = ( dates ? date.getDate() : 0 ); 8836 inst.currentMonth = ( dates ? date.getMonth() : 0 ); 8837 inst.currentYear = ( dates ? date.getFullYear() : 0 ); 8838 this._adjustInstDate( inst ); 8839 }, 8840 8841 /* Retrieve the default date shown on opening. */ 8842 _getDefaultDate: function( inst ) { 8843 return this._restrictMinMax( inst, 8844 this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) ); 8845 }, 8846 8847 /* A date may be specified as an exact value or a relative one. */ 8848 _determineDate: function( inst, date, defaultDate ) { 8849 var offsetNumeric = function( offset ) { 8850 var date = new Date(); 8851 date.setDate( date.getDate() + offset ); 8852 return date; 8853 }, 8854 offsetString = function( offset ) { 8855 try { 8856 return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ), 8857 offset, $.datepicker._getFormatConfig( inst ) ); 8858 } catch ( e ) { 8859 8860 // Ignore 8861 } 8862 8863 var date = ( offset.toLowerCase().match( /^c/ ) ? 8864 $.datepicker._getDate( inst ) : null ) || new Date(), 8865 year = date.getFullYear(), 8866 month = date.getMonth(), 8867 day = date.getDate(), 8868 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, 8869 matches = pattern.exec( offset ); 8870 8871 while ( matches ) { 8872 switch ( matches[ 2 ] || "d" ) { 8873 case "d" : case "D" : 8874 day += parseInt( matches[ 1 ], 10 ); break; 8875 case "w" : case "W" : 8876 day += parseInt( matches[ 1 ], 10 ) * 7; break; 8877 case "m" : case "M" : 8878 month += parseInt( matches[ 1 ], 10 ); 8879 day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) ); 8880 break; 8881 case "y": case "Y" : 8882 year += parseInt( matches[ 1 ], 10 ); 8883 day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) ); 8884 break; 8885 } 8886 matches = pattern.exec( offset ); 8887 } 8888 return new Date( year, month, day ); 8889 }, 8890 newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) : 8891 ( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) ); 8892 8893 newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate ); 8894 if ( newDate ) { 8895 newDate.setHours( 0 ); 8896 newDate.setMinutes( 0 ); 8897 newDate.setSeconds( 0 ); 8898 newDate.setMilliseconds( 0 ); 8899 } 8900 return this._daylightSavingAdjust( newDate ); 8901 }, 8902 8903 /* Handle switch to/from daylight saving. 8904 * Hours may be non-zero on daylight saving cut-over: 8905 * > 12 when midnight changeover, but then cannot generate 8906 * midnight datetime, so jump to 1AM, otherwise reset. 8907 * @param date (Date) the date to check 8908 * @return (Date) the corrected date 8909 */ 8910 _daylightSavingAdjust: function( date ) { 8911 if ( !date ) { 8912 return null; 8913 } 8914 date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 ); 8915 return date; 8916 }, 8917 8918 /* Set the date(s) directly. */ 8919 _setDate: function( inst, date, noChange ) { 8920 var clear = !date, 8921 origMonth = inst.selectedMonth, 8922 origYear = inst.selectedYear, 8923 newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) ); 8924 8925 inst.selectedDay = inst.currentDay = newDate.getDate(); 8926 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); 8927 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); 8928 if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) { 8929 this._notifyChange( inst ); 8930 } 8931 this._adjustInstDate( inst ); 8932 if ( inst.input ) { 8933 inst.input.val( clear ? "" : this._formatDate( inst ) ); 8934 } 8935 }, 8936 8937 /* Retrieve the date(s) directly. */ 8938 _getDate: function( inst ) { 8939 var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null : 8940 this._daylightSavingAdjust( new Date( 8941 inst.currentYear, inst.currentMonth, inst.currentDay ) ) ); 8942 return startDate; 8943 }, 8944 8945 /* Attach the onxxx handlers. These are declared statically so 8946 * they work with static code transformers like Caja. 8947 */ 8948 _attachHandlers: function( inst ) { 8949 var stepMonths = this._get( inst, "stepMonths" ), 8950 id = "#" + inst.id.replace( /\\\\/g, "\\" ); 8951 inst.dpDiv.find( "[data-handler]" ).map( function() { 8952 var handler = { 8953 prev: function() { 8954 $.datepicker._adjustDate( id, -stepMonths, "M" ); 8955 }, 8956 next: function() { 8957 $.datepicker._adjustDate( id, +stepMonths, "M" ); 8958 }, 8959 hide: function() { 8960 $.datepicker._hideDatepicker(); 8961 }, 8962 today: function() { 8963 $.datepicker._gotoToday( id ); 8964 }, 8965 selectDay: function() { 8966 $.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this ); 8967 return false; 8968 }, 8969 selectMonth: function() { 8970 $.datepicker._selectMonthYear( id, this, "M" ); 8971 return false; 8972 }, 8973 selectYear: function() { 8974 $.datepicker._selectMonthYear( id, this, "Y" ); 8975 return false; 8976 } 8977 }; 8978 $( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] ); 8979 } ); 8980 }, 8981 8982 /* Generate the HTML for the current state of the date picker. */ 8983 _generateHTML: function( inst ) { 8984 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate, 8985 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin, 8986 monthNames, monthNamesShort, beforeShowDay, showOtherMonths, 8987 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate, 8988 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows, 8989 printDate, dRow, tbody, daySettings, otherMonth, unselectable, 8990 tempDate = new Date(), 8991 today = this._daylightSavingAdjust( 8992 new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time 8993 isRTL = this._get( inst, "isRTL" ), 8994 showButtonPanel = this._get( inst, "showButtonPanel" ), 8995 hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ), 8996 navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ), 8997 numMonths = this._getNumberOfMonths( inst ), 8998 showCurrentAtPos = this._get( inst, "showCurrentAtPos" ), 8999 stepMonths = this._get( inst, "stepMonths" ), 9000 isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ), 9001 currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) : 9002 new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ), 9003 minDate = this._getMinMaxDate( inst, "min" ), 9004 maxDate = this._getMinMaxDate( inst, "max" ), 9005 drawMonth = inst.drawMonth - showCurrentAtPos, 9006 drawYear = inst.drawYear; 9007 9008 if ( drawMonth < 0 ) { 9009 drawMonth += 12; 9010 drawYear--; 9011 } 9012 if ( maxDate ) { 9013 maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(), 9014 maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) ); 9015 maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw ); 9016 while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) { 9017 drawMonth--; 9018 if ( drawMonth < 0 ) { 9019 drawMonth = 11; 9020 drawYear--; 9021 } 9022 } 9023 } 9024 inst.drawMonth = drawMonth; 9025 inst.drawYear = drawYear; 9026 9027 prevText = this._get( inst, "prevText" ); 9028 prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText, 9029 this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ), 9030 this._getFormatConfig( inst ) ) ); 9031 9032 if ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ) { 9033 prev = $( "<a>" ) 9034 .attr( { 9035 "class": "ui-datepicker-prev ui-corner-all", 9036 "data-handler": "prev", 9037 "data-event": "click", 9038 title: prevText 9039 } ) 9040 .append( 9041 $( "<span>" ) 9042 .addClass( "ui-icon ui-icon-circle-triangle-" + 9043 ( isRTL ? "e" : "w" ) ) 9044 .text( prevText ) 9045 )[ 0 ].outerHTML; 9046 } else if ( hideIfNoPrevNext ) { 9047 prev = ""; 9048 } else { 9049 prev = $( "<a>" ) 9050 .attr( { 9051 "class": "ui-datepicker-prev ui-corner-all ui-state-disabled", 9052 title: prevText 9053 } ) 9054 .append( 9055 $( "<span>" ) 9056 .addClass( "ui-icon ui-icon-circle-triangle-" + 9057 ( isRTL ? "e" : "w" ) ) 9058 .text( prevText ) 9059 )[ 0 ].outerHTML; 9060 } 9061 9062 nextText = this._get( inst, "nextText" ); 9063 nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText, 9064 this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ), 9065 this._getFormatConfig( inst ) ) ); 9066 9067 if ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ) { 9068 next = $( "<a>" ) 9069 .attr( { 9070 "class": "ui-datepicker-next ui-corner-all", 9071 "data-handler": "next", 9072 "data-event": "click", 9073 title: nextText 9074 } ) 9075 .append( 9076 $( "<span>" ) 9077 .addClass( "ui-icon ui-icon-circle-triangle-" + 9078 ( isRTL ? "w" : "e" ) ) 9079 .text( nextText ) 9080 )[ 0 ].outerHTML; 9081 } else if ( hideIfNoPrevNext ) { 9082 next = ""; 9083 } else { 9084 next = $( "<a>" ) 9085 .attr( { 9086 "class": "ui-datepicker-next ui-corner-all ui-state-disabled", 9087 title: nextText 9088 } ) 9089 .append( 9090 $( "<span>" ) 9091 .attr( "class", "ui-icon ui-icon-circle-triangle-" + 9092 ( isRTL ? "w" : "e" ) ) 9093 .text( nextText ) 9094 )[ 0 ].outerHTML; 9095 } 9096 9097 currentText = this._get( inst, "currentText" ); 9098 gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today ); 9099 currentText = ( !navigationAsDateFormat ? currentText : 9100 this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) ); 9101 9102 controls = ""; 9103 if ( !inst.inline ) { 9104 controls = $( "<button>" ) 9105 .attr( { 9106 type: "button", 9107 "class": "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all", 9108 "data-handler": "hide", 9109 "data-event": "click" 9110 } ) 9111 .text( this._get( inst, "closeText" ) )[ 0 ].outerHTML; 9112 } 9113 9114 buttonPanel = ""; 9115 if ( showButtonPanel ) { 9116 buttonPanel = $( "<div class='ui-datepicker-buttonpane ui-widget-content'>" ) 9117 .append( isRTL ? controls : "" ) 9118 .append( this._isInRange( inst, gotoDate ) ? 9119 $( "<button>" ) 9120 .attr( { 9121 type: "button", 9122 "class": "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all", 9123 "data-handler": "today", 9124 "data-event": "click" 9125 } ) 9126 .text( currentText ) : 9127 "" ) 9128 .append( isRTL ? "" : controls )[ 0 ].outerHTML; 9129 } 9130 9131 firstDay = parseInt( this._get( inst, "firstDay" ), 10 ); 9132 firstDay = ( isNaN( firstDay ) ? 0 : firstDay ); 9133 9134 showWeek = this._get( inst, "showWeek" ); 9135 dayNames = this._get( inst, "dayNames" ); 9136 dayNamesMin = this._get( inst, "dayNamesMin" ); 9137 monthNames = this._get( inst, "monthNames" ); 9138 monthNamesShort = this._get( inst, "monthNamesShort" ); 9139 beforeShowDay = this._get( inst, "beforeShowDay" ); 9140 showOtherMonths = this._get( inst, "showOtherMonths" ); 9141 selectOtherMonths = this._get( inst, "selectOtherMonths" ); 9142 defaultDate = this._getDefaultDate( inst ); 9143 html = ""; 9144 9145 for ( row = 0; row < numMonths[ 0 ]; row++ ) { 9146 group = ""; 9147 this.maxRows = 4; 9148 for ( col = 0; col < numMonths[ 1 ]; col++ ) { 9149 selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) ); 9150 cornerClass = " ui-corner-all"; 9151 calender = ""; 9152 if ( isMultiMonth ) { 9153 calender += "<div class='ui-datepicker-group"; 9154 if ( numMonths[ 1 ] > 1 ) { 9155 switch ( col ) { 9156 case 0: calender += " ui-datepicker-group-first"; 9157 cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break; 9158 case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last"; 9159 cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break; 9160 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break; 9161 } 9162 } 9163 calender += "'>"; 9164 } 9165 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" + 9166 ( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) + 9167 ( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) + 9168 this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate, 9169 row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers 9170 "</div><table class='ui-datepicker-calendar'><thead>" + 9171 "<tr>"; 9172 thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" ); 9173 for ( dow = 0; dow < 7; dow++ ) { // days of the week 9174 day = ( dow + firstDay ) % 7; 9175 thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" + 9176 "<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>"; 9177 } 9178 calender += thead + "</tr></thead><tbody>"; 9179 daysInMonth = this._getDaysInMonth( drawYear, drawMonth ); 9180 if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) { 9181 inst.selectedDay = Math.min( inst.selectedDay, daysInMonth ); 9182 } 9183 leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7; 9184 curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate 9185 numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043) 9186 this.maxRows = numRows; 9187 printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) ); 9188 for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows 9189 calender += "<tr>"; 9190 tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" + 9191 this._get( inst, "calculateWeek" )( printDate ) + "</td>" ); 9192 for ( dow = 0; dow < 7; dow++ ) { // create date picker days 9193 daySettings = ( beforeShowDay ? 9194 beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] ); 9195 otherMonth = ( printDate.getMonth() !== drawMonth ); 9196 unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] || 9197 ( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate ); 9198 tbody += "<td class='" + 9199 ( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends 9200 ( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months 9201 ( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key 9202 ( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ? 9203 9204 // or defaultDate is current printedDate and defaultDate is selectedDate 9205 " " + this._dayOverClass : "" ) + // highlight selected day 9206 ( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) + // highlight unselectable days 9207 ( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates 9208 ( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day 9209 ( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different) 9210 ( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "'" ) + "'" : "" ) + // cell title 9211 ( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions 9212 ( otherMonth && !showOtherMonths ? " " : // display for other months 9213 ( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" + 9214 ( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) + 9215 ( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day 9216 ( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months 9217 "' href='#' aria-current='" + ( printDate.getTime() === currentDate.getTime() ? "true" : "false" ) + // mark date as selected for screen reader 9218 "' data-date='" + printDate.getDate() + // store date as data 9219 "'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date 9220 printDate.setDate( printDate.getDate() + 1 ); 9221 printDate = this._daylightSavingAdjust( printDate ); 9222 } 9223 calender += tbody + "</tr>"; 9224 } 9225 drawMonth++; 9226 if ( drawMonth > 11 ) { 9227 drawMonth = 0; 9228 drawYear++; 9229 } 9230 calender += "</tbody></table>" + ( isMultiMonth ? "</div>" + 9231 ( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" ); 9232 group += calender; 9233 } 9234 html += group; 9235 } 9236 html += buttonPanel; 9237 inst._keyEvent = false; 9238 return html; 9239 }, 9240 9241 /* Generate the month and year header. */ 9242 _generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate, 9243 secondary, monthNames, monthNamesShort ) { 9244 9245 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear, 9246 changeMonth = this._get( inst, "changeMonth" ), 9247 changeYear = this._get( inst, "changeYear" ), 9248 showMonthAfterYear = this._get( inst, "showMonthAfterYear" ), 9249 selectMonthLabel = this._get( inst, "selectMonthLabel" ), 9250 selectYearLabel = this._get( inst, "selectYearLabel" ), 9251 html = "<div class='ui-datepicker-title'>", 9252 monthHtml = ""; 9253 9254 // Month selection 9255 if ( secondary || !changeMonth ) { 9256 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>"; 9257 } else { 9258 inMinYear = ( minDate && minDate.getFullYear() === drawYear ); 9259 inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear ); 9260 monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>"; 9261 for ( month = 0; month < 12; month++ ) { 9262 if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) { 9263 monthHtml += "<option value='" + month + "'" + 9264 ( month === drawMonth ? " selected='selected'" : "" ) + 9265 ">" + monthNamesShort[ month ] + "</option>"; 9266 } 9267 } 9268 monthHtml += "</select>"; 9269 } 9270 9271 if ( !showMonthAfterYear ) { 9272 html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? " " : "" ); 9273 } 9274 9275 // Year selection 9276 if ( !inst.yearshtml ) { 9277 inst.yearshtml = ""; 9278 if ( secondary || !changeYear ) { 9279 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>"; 9280 } else { 9281 9282 // determine range of years to display 9283 years = this._get( inst, "yearRange" ).split( ":" ); 9284 thisYear = new Date().getFullYear(); 9285 determineYear = function( value ) { 9286 var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) : 9287 ( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) : 9288 parseInt( value, 10 ) ) ); 9289 return ( isNaN( year ) ? thisYear : year ); 9290 }; 9291 year = determineYear( years[ 0 ] ); 9292 endYear = Math.max( year, determineYear( years[ 1 ] || "" ) ); 9293 year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year ); 9294 endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear ); 9295 inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>"; 9296 for ( ; year <= endYear; year++ ) { 9297 inst.yearshtml += "<option value='" + year + "'" + 9298 ( year === drawYear ? " selected='selected'" : "" ) + 9299 ">" + year + "</option>"; 9300 } 9301 inst.yearshtml += "</select>"; 9302 9303 html += inst.yearshtml; 9304 inst.yearshtml = null; 9305 } 9306 } 9307 9308 html += this._get( inst, "yearSuffix" ); 9309 if ( showMonthAfterYear ) { 9310 html += ( secondary || !( changeMonth && changeYear ) ? " " : "" ) + monthHtml; 9311 } 9312 html += "</div>"; // Close datepicker_header 9313 return html; 9314 }, 9315 9316 /* Adjust one of the date sub-fields. */ 9317 _adjustInstDate: function( inst, offset, period ) { 9318 var year = inst.selectedYear + ( period === "Y" ? offset : 0 ), 9319 month = inst.selectedMonth + ( period === "M" ? offset : 0 ), 9320 day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ), 9321 date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) ); 9322 9323 inst.selectedDay = date.getDate(); 9324 inst.drawMonth = inst.selectedMonth = date.getMonth(); 9325 inst.drawYear = inst.selectedYear = date.getFullYear(); 9326 if ( period === "M" || period === "Y" ) { 9327 this._notifyChange( inst ); 9328 } 9329 }, 9330 9331 /* Ensure a date is within any min/max bounds. */ 9332 _restrictMinMax: function( inst, date ) { 9333 var minDate = this._getMinMaxDate( inst, "min" ), 9334 maxDate = this._getMinMaxDate( inst, "max" ), 9335 newDate = ( minDate && date < minDate ? minDate : date ); 9336 return ( maxDate && newDate > maxDate ? maxDate : newDate ); 9337 }, 9338 9339 /* Notify change of month/year. */ 9340 _notifyChange: function( inst ) { 9341 var onChange = this._get( inst, "onChangeMonthYear" ); 9342 if ( onChange ) { 9343 onChange.apply( ( inst.input ? inst.input[ 0 ] : null ), 9344 [ inst.selectedYear, inst.selectedMonth + 1, inst ] ); 9345 } 9346 }, 9347 9348 /* Determine the number of months to show. */ 9349 _getNumberOfMonths: function( inst ) { 9350 var numMonths = this._get( inst, "numberOfMonths" ); 9351 return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) ); 9352 }, 9353 9354 /* Determine the current maximum date - ensure no time components are set. */ 9355 _getMinMaxDate: function( inst, minMax ) { 9356 return this._determineDate( inst, this._get( inst, minMax + "Date" ), null ); 9357 }, 9358 9359 /* Find the number of days in a given month. */ 9360 _getDaysInMonth: function( year, month ) { 9361 return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate(); 9362 }, 9363 9364 /* Find the day of the week of the first of a month. */ 9365 _getFirstDayOfMonth: function( year, month ) { 9366 return new Date( year, month, 1 ).getDay(); 9367 }, 9368 9369 /* Determines if we should allow a "next/prev" month display change. */ 9370 _canAdjustMonth: function( inst, offset, curYear, curMonth ) { 9371 var numMonths = this._getNumberOfMonths( inst ), 9372 date = this._daylightSavingAdjust( new Date( curYear, 9373 curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) ); 9374 9375 if ( offset < 0 ) { 9376 date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) ); 9377 } 9378 return this._isInRange( inst, date ); 9379 }, 9380 9381 /* Is the given date in the accepted range? */ 9382 _isInRange: function( inst, date ) { 9383 var yearSplit, currentYear, 9384 minDate = this._getMinMaxDate( inst, "min" ), 9385 maxDate = this._getMinMaxDate( inst, "max" ), 9386 minYear = null, 9387 maxYear = null, 9388 years = this._get( inst, "yearRange" ); 9389 if ( years ) { 9390 yearSplit = years.split( ":" ); 9391 currentYear = new Date().getFullYear(); 9392 minYear = parseInt( yearSplit[ 0 ], 10 ); 9393 maxYear = parseInt( yearSplit[ 1 ], 10 ); 9394 if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) { 9395 minYear += currentYear; 9396 } 9397 if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) { 9398 maxYear += currentYear; 9399 } 9400 } 9401 9402 return ( ( !minDate || date.getTime() >= minDate.getTime() ) && 9403 ( !maxDate || date.getTime() <= maxDate.getTime() ) && 9404 ( !minYear || date.getFullYear() >= minYear ) && 9405 ( !maxYear || date.getFullYear() <= maxYear ) ); 9406 }, 9407 9408 /* Provide the configuration settings for formatting/parsing. */ 9409 _getFormatConfig: function( inst ) { 9410 var shortYearCutoff = this._get( inst, "shortYearCutoff" ); 9411 shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff : 9412 new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) ); 9413 return { shortYearCutoff: shortYearCutoff, 9414 dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ), 9415 monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) }; 9416 }, 9417 9418 /* Format the given date for display. */ 9419 _formatDate: function( inst, day, month, year ) { 9420 if ( !day ) { 9421 inst.currentDay = inst.selectedDay; 9422 inst.currentMonth = inst.selectedMonth; 9423 inst.currentYear = inst.selectedYear; 9424 } 9425 var date = ( day ? ( typeof day === "object" ? day : 9426 this._daylightSavingAdjust( new Date( year, month, day ) ) ) : 9427 this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ); 9428 return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) ); 9429 } 9430} ); 9431 9432/* 9433 * Bind hover events for datepicker elements. 9434 * Done via delegate so the binding only occurs once in the lifetime of the parent div. 9435 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. 9436 */ 9437function datepicker_bindHover( dpDiv ) { 9438 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a"; 9439 return dpDiv.on( "mouseout", selector, function() { 9440 $( this ).removeClass( "ui-state-hover" ); 9441 if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) { 9442 $( this ).removeClass( "ui-datepicker-prev-hover" ); 9443 } 9444 if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) { 9445 $( this ).removeClass( "ui-datepicker-next-hover" ); 9446 } 9447 } ) 9448 .on( "mouseover", selector, datepicker_handleMouseover ); 9449} 9450 9451function datepicker_handleMouseover() { 9452 if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) { 9453 $( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" ); 9454 $( this ).addClass( "ui-state-hover" ); 9455 if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) { 9456 $( this ).addClass( "ui-datepicker-prev-hover" ); 9457 } 9458 if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) { 9459 $( this ).addClass( "ui-datepicker-next-hover" ); 9460 } 9461 } 9462} 9463 9464/* jQuery extend now ignores nulls! */ 9465function datepicker_extendRemove( target, props ) { 9466 $.extend( target, props ); 9467 for ( var name in props ) { 9468 if ( props[ name ] == null ) { 9469 target[ name ] = props[ name ]; 9470 } 9471 } 9472 return target; 9473} 9474 9475/* Invoke the datepicker functionality. 9476 @param options string - a command, optionally followed by additional parameters or 9477 Object - settings for attaching new datepicker functionality 9478 @return jQuery object */ 9479$.fn.datepicker = function( options ) { 9480 9481 /* Verify an empty collection wasn't passed - Fixes #6976 */ 9482 if ( !this.length ) { 9483 return this; 9484 } 9485 9486 /* Initialise the date picker. */ 9487 if ( !$.datepicker.initialized ) { 9488 $( document ).on( "mousedown", $.datepicker._checkExternalClick ); 9489 $.datepicker.initialized = true; 9490 } 9491 9492 /* Append datepicker main container to body if not exist. */ 9493 if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) { 9494 $( "body" ).append( $.datepicker.dpDiv ); 9495 } 9496 9497 var otherArgs = Array.prototype.slice.call( arguments, 1 ); 9498 if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) { 9499 return $.datepicker[ "_" + options + "Datepicker" ]. 9500 apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) ); 9501 } 9502 if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) { 9503 return $.datepicker[ "_" + options + "Datepicker" ]. 9504 apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) ); 9505 } 9506 return this.each( function() { 9507 if ( typeof options === "string" ) { 9508 $.datepicker[ "_" + options + "Datepicker" ] 9509 .apply( $.datepicker, [ this ].concat( otherArgs ) ); 9510 } else { 9511 $.datepicker._attachDatepicker( this, options ); 9512 } 9513 } ); 9514}; 9515 9516$.datepicker = new Datepicker(); // singleton instance 9517$.datepicker.initialized = false; 9518$.datepicker.uuid = new Date().getTime(); 9519$.datepicker.version = "1.13.3"; 9520 9521var widgetsDatepicker = $.datepicker; 9522 9523 9524 9525// This file is deprecated 9526var ie = $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ); 9527 9528/*! 9529 * jQuery UI Mouse 1.13.3 9530 * https://jqueryui.com 9531 * 9532 * Copyright OpenJS Foundation and other contributors 9533 * Released under the MIT license. 9534 * https://jquery.org/license 9535 */ 9536 9537//>>label: Mouse 9538//>>group: Widgets 9539//>>description: Abstracts mouse-based interactions to assist in creating certain widgets. 9540//>>docs: https://api.jqueryui.com/mouse/ 9541 9542 9543var mouseHandled = false; 9544$( document ).on( "mouseup", function() { 9545 mouseHandled = false; 9546} ); 9547 9548var widgetsMouse = $.widget( "ui.mouse", { 9549 version: "1.13.3", 9550 options: { 9551 cancel: "input, textarea, button, select, option", 9552 distance: 1, 9553 delay: 0 9554 }, 9555 _mouseInit: function() { 9556 var that = this; 9557 9558 this.element 9559 .on( "mousedown." + this.widgetName, function( event ) { 9560 return that._mouseDown( event ); 9561 } ) 9562 .on( "click." + this.widgetName, function( event ) { 9563 if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) { 9564 $.removeData( event.target, that.widgetName + ".preventClickEvent" ); 9565 event.stopImmediatePropagation(); 9566 return false; 9567 } 9568 } ); 9569 9570 this.started = false; 9571 }, 9572 9573 // TODO: make sure destroying one instance of mouse doesn't mess with 9574 // other instances of mouse 9575 _mouseDestroy: function() { 9576 this.element.off( "." + this.widgetName ); 9577 if ( this._mouseMoveDelegate ) { 9578 this.document 9579 .off( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 9580 .off( "mouseup." + this.widgetName, this._mouseUpDelegate ); 9581 } 9582 }, 9583 9584 _mouseDown: function( event ) { 9585 9586 // don't let more than one widget handle mouseStart 9587 if ( mouseHandled ) { 9588 return; 9589 } 9590 9591 this._mouseMoved = false; 9592 9593 // We may have missed mouseup (out of window) 9594 if ( this._mouseStarted ) { 9595 this._mouseUp( event ); 9596 } 9597 9598 this._mouseDownEvent = event; 9599 9600 var that = this, 9601 btnIsLeft = ( event.which === 1 ), 9602 9603 // event.target.nodeName works around a bug in IE 8 with 9604 // disabled inputs (#7620) 9605 elIsCancel = ( typeof this.options.cancel === "string" && event.target.nodeName ? 9606 $( event.target ).closest( this.options.cancel ).length : false ); 9607 if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) { 9608 return true; 9609 } 9610 9611 this.mouseDelayMet = !this.options.delay; 9612 if ( !this.mouseDelayMet ) { 9613 this._mouseDelayTimer = setTimeout( function() { 9614 that.mouseDelayMet = true; 9615 }, this.options.delay ); 9616 } 9617 9618 if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) { 9619 this._mouseStarted = ( this._mouseStart( event ) !== false ); 9620 if ( !this._mouseStarted ) { 9621 event.preventDefault(); 9622 return true; 9623 } 9624 } 9625 9626 // Click event may never have fired (Gecko & Opera) 9627 if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) { 9628 $.removeData( event.target, this.widgetName + ".preventClickEvent" ); 9629 } 9630 9631 // These delegates are required to keep context 9632 this._mouseMoveDelegate = function( event ) { 9633 return that._mouseMove( event ); 9634 }; 9635 this._mouseUpDelegate = function( event ) { 9636 return that._mouseUp( event ); 9637 }; 9638 9639 this.document 9640 .on( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 9641 .on( "mouseup." + this.widgetName, this._mouseUpDelegate ); 9642 9643 event.preventDefault(); 9644 9645 mouseHandled = true; 9646 return true; 9647 }, 9648 9649 _mouseMove: function( event ) { 9650 9651 // Only check for mouseups outside the document if you've moved inside the document 9652 // at least once. This prevents the firing of mouseup in the case of IE<9, which will 9653 // fire a mousemove event if content is placed under the cursor. See #7778 9654 // Support: IE <9 9655 if ( this._mouseMoved ) { 9656 9657 // IE mouseup check - mouseup happened when mouse was out of window 9658 if ( $.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && 9659 !event.button ) { 9660 return this._mouseUp( event ); 9661 9662 // Iframe mouseup check - mouseup occurred in another document 9663 } else if ( !event.which ) { 9664 9665 // Support: Safari <=8 - 9 9666 // Safari sets which to 0 if you press any of the following keys 9667 // during a drag (#14461) 9668 if ( event.originalEvent.altKey || event.originalEvent.ctrlKey || 9669 event.originalEvent.metaKey || event.originalEvent.shiftKey ) { 9670 this.ignoreMissingWhich = true; 9671 } else if ( !this.ignoreMissingWhich ) { 9672 return this._mouseUp( event ); 9673 } 9674 } 9675 } 9676 9677 if ( event.which || event.button ) { 9678 this._mouseMoved = true; 9679 } 9680 9681 if ( this._mouseStarted ) { 9682 this._mouseDrag( event ); 9683 return event.preventDefault(); 9684 } 9685 9686 if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) { 9687 this._mouseStarted = 9688 ( this._mouseStart( this._mouseDownEvent, event ) !== false ); 9689 if ( this._mouseStarted ) { 9690 this._mouseDrag( event ); 9691 } else { 9692 this._mouseUp( event ); 9693 } 9694 } 9695 9696 return !this._mouseStarted; 9697 }, 9698 9699 _mouseUp: function( event ) { 9700 this.document 9701 .off( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 9702 .off( "mouseup." + this.widgetName, this._mouseUpDelegate ); 9703 9704 if ( this._mouseStarted ) { 9705 this._mouseStarted = false; 9706 9707 if ( event.target === this._mouseDownEvent.target ) { 9708 $.data( event.target, this.widgetName + ".preventClickEvent", true ); 9709 } 9710 9711 this._mouseStop( event ); 9712 } 9713 9714 if ( this._mouseDelayTimer ) { 9715 clearTimeout( this._mouseDelayTimer ); 9716 delete this._mouseDelayTimer; 9717 } 9718 9719 this.ignoreMissingWhich = false; 9720 mouseHandled = false; 9721 event.preventDefault(); 9722 }, 9723 9724 _mouseDistanceMet: function( event ) { 9725 return ( Math.max( 9726 Math.abs( this._mouseDownEvent.pageX - event.pageX ), 9727 Math.abs( this._mouseDownEvent.pageY - event.pageY ) 9728 ) >= this.options.distance 9729 ); 9730 }, 9731 9732 _mouseDelayMet: function( /* event */ ) { 9733 return this.mouseDelayMet; 9734 }, 9735 9736 // These are placeholder methods, to be overriden by extending plugin 9737 _mouseStart: function( /* event */ ) {}, 9738 _mouseDrag: function( /* event */ ) {}, 9739 _mouseStop: function( /* event */ ) {}, 9740 _mouseCapture: function( /* event */ ) { 9741 return true; 9742 } 9743} ); 9744 9745 9746 9747// $.ui.plugin is deprecated. Use $.widget() extensions instead. 9748var plugin = $.ui.plugin = { 9749 add: function( module, option, set ) { 9750 var i, 9751 proto = $.ui[ module ].prototype; 9752 for ( i in set ) { 9753 proto.plugins[ i ] = proto.plugins[ i ] || []; 9754 proto.plugins[ i ].push( [ option, set[ i ] ] ); 9755 } 9756 }, 9757 call: function( instance, name, args, allowDisconnected ) { 9758 var i, 9759 set = instance.plugins[ name ]; 9760 9761 if ( !set ) { 9762 return; 9763 } 9764 9765 if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || 9766 instance.element[ 0 ].parentNode.nodeType === 11 ) ) { 9767 return; 9768 } 9769 9770 for ( i = 0; i < set.length; i++ ) { 9771 if ( instance.options[ set[ i ][ 0 ] ] ) { 9772 set[ i ][ 1 ].apply( instance.element, args ); 9773 } 9774 } 9775 } 9776}; 9777 9778 9779 9780var safeBlur = $.ui.safeBlur = function( element ) { 9781 9782 // Support: IE9 - 10 only 9783 // If the <body> is blurred, IE will switch windows, see #9420 9784 if ( element && element.nodeName.toLowerCase() !== "body" ) { 9785 $( element ).trigger( "blur" ); 9786 } 9787}; 9788 9789 9790/*! 9791 * jQuery UI Draggable 1.13.3 9792 * https://jqueryui.com 9793 * 9794 * Copyright OpenJS Foundation and other contributors 9795 * Released under the MIT license. 9796 * https://jquery.org/license 9797 */ 9798 9799//>>label: Draggable 9800//>>group: Interactions 9801//>>description: Enables dragging functionality for any element. 9802//>>docs: https://api.jqueryui.com/draggable/ 9803//>>demos: https://jqueryui.com/draggable/ 9804//>>css.structure: ../../themes/base/draggable.css 9805 9806 9807$.widget( "ui.draggable", $.ui.mouse, { 9808 version: "1.13.3", 9809 widgetEventPrefix: "drag", 9810 options: { 9811 addClasses: true, 9812 appendTo: "parent", 9813 axis: false, 9814 connectToSortable: false, 9815 containment: false, 9816 cursor: "auto", 9817 cursorAt: false, 9818 grid: false, 9819 handle: false, 9820 helper: "original", 9821 iframeFix: false, 9822 opacity: false, 9823 refreshPositions: false, 9824 revert: false, 9825 revertDuration: 500, 9826 scope: "default", 9827 scroll: true, 9828 scrollSensitivity: 20, 9829 scrollSpeed: 20, 9830 snap: false, 9831 snapMode: "both", 9832 snapTolerance: 20, 9833 stack: false, 9834 zIndex: false, 9835 9836 // Callbacks 9837 drag: null, 9838 start: null, 9839 stop: null 9840 }, 9841 _create: function() { 9842 9843 if ( this.options.helper === "original" ) { 9844 this._setPositionRelative(); 9845 } 9846 if ( this.options.addClasses ) { 9847 this._addClass( "ui-draggable" ); 9848 } 9849 this._setHandleClassName(); 9850 9851 this._mouseInit(); 9852 }, 9853 9854 _setOption: function( key, value ) { 9855 this._super( key, value ); 9856 if ( key === "handle" ) { 9857 this._removeHandleClassName(); 9858 this._setHandleClassName(); 9859 } 9860 }, 9861 9862 _destroy: function() { 9863 if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) { 9864 this.destroyOnClear = true; 9865 return; 9866 } 9867 this._removeHandleClassName(); 9868 this._mouseDestroy(); 9869 }, 9870 9871 _mouseCapture: function( event ) { 9872 var o = this.options; 9873 9874 // Among others, prevent a drag on a resizable-handle 9875 if ( this.helper || o.disabled || 9876 $( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) { 9877 return false; 9878 } 9879 9880 //Quit if we're not on a valid handle 9881 this.handle = this._getHandle( event ); 9882 if ( !this.handle ) { 9883 return false; 9884 } 9885 9886 this._blurActiveElement( event ); 9887 9888 this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix ); 9889 9890 return true; 9891 9892 }, 9893 9894 _blockFrames: function( selector ) { 9895 this.iframeBlocks = this.document.find( selector ).map( function() { 9896 var iframe = $( this ); 9897 9898 return $( "<div>" ) 9899 .css( "position", "absolute" ) 9900 .appendTo( iframe.parent() ) 9901 .outerWidth( iframe.outerWidth() ) 9902 .outerHeight( iframe.outerHeight() ) 9903 .offset( iframe.offset() )[ 0 ]; 9904 } ); 9905 }, 9906 9907 _unblockFrames: function() { 9908 if ( this.iframeBlocks ) { 9909 this.iframeBlocks.remove(); 9910 delete this.iframeBlocks; 9911 } 9912 }, 9913 9914 _blurActiveElement: function( event ) { 9915 var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ), 9916 target = $( event.target ); 9917 9918 // Don't blur if the event occurred on an element that is within 9919 // the currently focused element 9920 // See #10527, #12472 9921 if ( target.closest( activeElement ).length ) { 9922 return; 9923 } 9924 9925 // Blur any element that currently has focus, see #4261 9926 $.ui.safeBlur( activeElement ); 9927 }, 9928 9929 _mouseStart: function( event ) { 9930 9931 var o = this.options; 9932 9933 //Create and append the visible helper 9934 this.helper = this._createHelper( event ); 9935 9936 this._addClass( this.helper, "ui-draggable-dragging" ); 9937 9938 //Cache the helper size 9939 this._cacheHelperProportions(); 9940 9941 //If ddmanager is used for droppables, set the global draggable 9942 if ( $.ui.ddmanager ) { 9943 $.ui.ddmanager.current = this; 9944 } 9945 9946 /* 9947 * - Position generation - 9948 * This block generates everything position related - it's the core of draggables. 9949 */ 9950 9951 //Cache the margins of the original element 9952 this._cacheMargins(); 9953 9954 //Store the helper's css position 9955 this.cssPosition = this.helper.css( "position" ); 9956 this.scrollParent = this.helper.scrollParent( true ); 9957 this.offsetParent = this.helper.offsetParent(); 9958 this.hasFixedAncestor = this.helper.parents().filter( function() { 9959 return $( this ).css( "position" ) === "fixed"; 9960 } ).length > 0; 9961 9962 //The element's absolute position on the page minus margins 9963 this.positionAbs = this.element.offset(); 9964 this._refreshOffsets( event ); 9965 9966 //Generate the original position 9967 this.originalPosition = this.position = this._generatePosition( event, false ); 9968 this.originalPageX = event.pageX; 9969 this.originalPageY = event.pageY; 9970 9971 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 9972 if ( o.cursorAt ) { 9973 this._adjustOffsetFromHelper( o.cursorAt ); 9974 } 9975 9976 //Set a containment if given in the options 9977 this._setContainment(); 9978 9979 //Trigger event + callbacks 9980 if ( this._trigger( "start", event ) === false ) { 9981 this._clear(); 9982 return false; 9983 } 9984 9985 //Recache the helper size 9986 this._cacheHelperProportions(); 9987 9988 //Prepare the droppable offsets 9989 if ( $.ui.ddmanager && !o.dropBehaviour ) { 9990 $.ui.ddmanager.prepareOffsets( this, event ); 9991 } 9992 9993 // Execute the drag once - this causes the helper not to be visible before getting its 9994 // correct position 9995 this._mouseDrag( event, true ); 9996 9997 // If the ddmanager is used for droppables, inform the manager that dragging has started 9998 // (see #5003) 9999 if ( $.ui.ddmanager ) { 10000 $.ui.ddmanager.dragStart( this, event ); 10001 } 10002 10003 return true; 10004 }, 10005 10006 _refreshOffsets: function( event ) { 10007 this.offset = { 10008 top: this.positionAbs.top - this.margins.top, 10009 left: this.positionAbs.left - this.margins.left, 10010 scroll: false, 10011 parent: this._getParentOffset(), 10012 relative: this._getRelativeOffset() 10013 }; 10014 10015 this.offset.click = { 10016 left: event.pageX - this.offset.left, 10017 top: event.pageY - this.offset.top 10018 }; 10019 }, 10020 10021 _mouseDrag: function( event, noPropagation ) { 10022 10023 // reset any necessary cached properties (see #5009) 10024 if ( this.hasFixedAncestor ) { 10025 this.offset.parent = this._getParentOffset(); 10026 } 10027 10028 //Compute the helpers position 10029 this.position = this._generatePosition( event, true ); 10030 this.positionAbs = this._convertPositionTo( "absolute" ); 10031 10032 //Call plugins and callbacks and use the resulting position if something is returned 10033 if ( !noPropagation ) { 10034 var ui = this._uiHash(); 10035 if ( this._trigger( "drag", event, ui ) === false ) { 10036 this._mouseUp( new $.Event( "mouseup", event ) ); 10037 return false; 10038 } 10039 this.position = ui.position; 10040 } 10041 10042 this.helper[ 0 ].style.left = this.position.left + "px"; 10043 this.helper[ 0 ].style.top = this.position.top + "px"; 10044 10045 if ( $.ui.ddmanager ) { 10046 $.ui.ddmanager.drag( this, event ); 10047 } 10048 10049 return false; 10050 }, 10051 10052 _mouseStop: function( event ) { 10053 10054 //If we are using droppables, inform the manager about the drop 10055 var that = this, 10056 dropped = false; 10057 if ( $.ui.ddmanager && !this.options.dropBehaviour ) { 10058 dropped = $.ui.ddmanager.drop( this, event ); 10059 } 10060 10061 //if a drop comes from outside (a sortable) 10062 if ( this.dropped ) { 10063 dropped = this.dropped; 10064 this.dropped = false; 10065 } 10066 10067 if ( ( this.options.revert === "invalid" && !dropped ) || 10068 ( this.options.revert === "valid" && dropped ) || 10069 this.options.revert === true || ( typeof this.options.revert === "function" && 10070 this.options.revert.call( this.element, dropped ) ) 10071 ) { 10072 $( this.helper ).animate( 10073 this.originalPosition, 10074 parseInt( this.options.revertDuration, 10 ), 10075 function() { 10076 if ( that._trigger( "stop", event ) !== false ) { 10077 that._clear(); 10078 } 10079 } 10080 ); 10081 } else { 10082 if ( this._trigger( "stop", event ) !== false ) { 10083 this._clear(); 10084 } 10085 } 10086 10087 return false; 10088 }, 10089 10090 _mouseUp: function( event ) { 10091 this._unblockFrames(); 10092 10093 // If the ddmanager is used for droppables, inform the manager that dragging has stopped 10094 // (see #5003) 10095 if ( $.ui.ddmanager ) { 10096 $.ui.ddmanager.dragStop( this, event ); 10097 } 10098 10099 // Only need to focus if the event occurred on the draggable itself, see #10527 10100 if ( this.handleElement.is( event.target ) ) { 10101 10102 // The interaction is over; whether or not the click resulted in a drag, 10103 // focus the element 10104 this.element.trigger( "focus" ); 10105 } 10106 10107 return $.ui.mouse.prototype._mouseUp.call( this, event ); 10108 }, 10109 10110 cancel: function() { 10111 10112 if ( this.helper.is( ".ui-draggable-dragging" ) ) { 10113 this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) ); 10114 } else { 10115 this._clear(); 10116 } 10117 10118 return this; 10119 10120 }, 10121 10122 _getHandle: function( event ) { 10123 return this.options.handle ? 10124 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length : 10125 true; 10126 }, 10127 10128 _setHandleClassName: function() { 10129 this.handleElement = this.options.handle ? 10130 this.element.find( this.options.handle ) : this.element; 10131 this._addClass( this.handleElement, "ui-draggable-handle" ); 10132 }, 10133 10134 _removeHandleClassName: function() { 10135 this._removeClass( this.handleElement, "ui-draggable-handle" ); 10136 }, 10137 10138 _createHelper: function( event ) { 10139 10140 var o = this.options, 10141 helperIsFunction = typeof o.helper === "function", 10142 helper = helperIsFunction ? 10143 $( o.helper.apply( this.element[ 0 ], [ event ] ) ) : 10144 ( o.helper === "clone" ? 10145 this.element.clone().removeAttr( "id" ) : 10146 this.element ); 10147 10148 if ( !helper.parents( "body" ).length ) { 10149 helper.appendTo( ( o.appendTo === "parent" ? 10150 this.element[ 0 ].parentNode : 10151 o.appendTo ) ); 10152 } 10153 10154 // https://bugs.jqueryui.com/ticket/9446 10155 // a helper function can return the original element 10156 // which wouldn't have been set to relative in _create 10157 if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) { 10158 this._setPositionRelative(); 10159 } 10160 10161 if ( helper[ 0 ] !== this.element[ 0 ] && 10162 !( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) { 10163 helper.css( "position", "absolute" ); 10164 } 10165 10166 return helper; 10167 10168 }, 10169 10170 _setPositionRelative: function() { 10171 if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) { 10172 this.element[ 0 ].style.position = "relative"; 10173 } 10174 }, 10175 10176 _adjustOffsetFromHelper: function( obj ) { 10177 if ( typeof obj === "string" ) { 10178 obj = obj.split( " " ); 10179 } 10180 if ( Array.isArray( obj ) ) { 10181 obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 }; 10182 } 10183 if ( "left" in obj ) { 10184 this.offset.click.left = obj.left + this.margins.left; 10185 } 10186 if ( "right" in obj ) { 10187 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 10188 } 10189 if ( "top" in obj ) { 10190 this.offset.click.top = obj.top + this.margins.top; 10191 } 10192 if ( "bottom" in obj ) { 10193 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 10194 } 10195 }, 10196 10197 _isRootNode: function( element ) { 10198 return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ]; 10199 }, 10200 10201 _getParentOffset: function() { 10202 10203 //Get the offsetParent and cache its position 10204 var po = this.offsetParent.offset(), 10205 document = this.document[ 0 ]; 10206 10207 // This is a special case where we need to modify a offset calculated on start, since the 10208 // following happened: 10209 // 1. The position of the helper is absolute, so it's position is calculated based on the 10210 // next positioned parent 10211 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't 10212 // the document, which means that the scroll is included in the initial calculation of the 10213 // offset of the parent, and never recalculated upon drag 10214 if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document && 10215 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) { 10216 po.left += this.scrollParent.scrollLeft(); 10217 po.top += this.scrollParent.scrollTop(); 10218 } 10219 10220 if ( this._isRootNode( this.offsetParent[ 0 ] ) ) { 10221 po = { top: 0, left: 0 }; 10222 } 10223 10224 return { 10225 top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ), 10226 left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 ) 10227 }; 10228 10229 }, 10230 10231 _getRelativeOffset: function() { 10232 if ( this.cssPosition !== "relative" ) { 10233 return { top: 0, left: 0 }; 10234 } 10235 10236 var p = this.element.position(), 10237 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ); 10238 10239 return { 10240 top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) + 10241 ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ), 10242 left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) + 10243 ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 ) 10244 }; 10245 10246 }, 10247 10248 _cacheMargins: function() { 10249 this.margins = { 10250 left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ), 10251 top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ), 10252 right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ), 10253 bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 ) 10254 }; 10255 }, 10256 10257 _cacheHelperProportions: function() { 10258 this.helperProportions = { 10259 width: this.helper.outerWidth(), 10260 height: this.helper.outerHeight() 10261 }; 10262 }, 10263 10264 _setContainment: function() { 10265 10266 var isUserScrollable, c, ce, 10267 o = this.options, 10268 document = this.document[ 0 ]; 10269 10270 this.relativeContainer = null; 10271 10272 if ( !o.containment ) { 10273 this.containment = null; 10274 return; 10275 } 10276 10277 if ( o.containment === "window" ) { 10278 this.containment = [ 10279 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left, 10280 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top, 10281 $( window ).scrollLeft() + $( window ).width() - 10282 this.helperProportions.width - this.margins.left, 10283 $( window ).scrollTop() + 10284 ( $( window ).height() || document.body.parentNode.scrollHeight ) - 10285 this.helperProportions.height - this.margins.top 10286 ]; 10287 return; 10288 } 10289 10290 if ( o.containment === "document" ) { 10291 this.containment = [ 10292 0, 10293 0, 10294 $( document ).width() - this.helperProportions.width - this.margins.left, 10295 ( $( document ).height() || document.body.parentNode.scrollHeight ) - 10296 this.helperProportions.height - this.margins.top 10297 ]; 10298 return; 10299 } 10300 10301 if ( o.containment.constructor === Array ) { 10302 this.containment = o.containment; 10303 return; 10304 } 10305 10306 if ( o.containment === "parent" ) { 10307 o.containment = this.helper[ 0 ].parentNode; 10308 } 10309 10310 c = $( o.containment ); 10311 ce = c[ 0 ]; 10312 10313 if ( !ce ) { 10314 return; 10315 } 10316 10317 isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) ); 10318 10319 this.containment = [ 10320 ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + 10321 ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ), 10322 ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + 10323 ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ), 10324 ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - 10325 ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - 10326 ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - 10327 this.helperProportions.width - 10328 this.margins.left - 10329 this.margins.right, 10330 ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - 10331 ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - 10332 ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - 10333 this.helperProportions.height - 10334 this.margins.top - 10335 this.margins.bottom 10336 ]; 10337 this.relativeContainer = c; 10338 }, 10339 10340 _convertPositionTo: function( d, pos ) { 10341 10342 if ( !pos ) { 10343 pos = this.position; 10344 } 10345 10346 var mod = d === "absolute" ? 1 : -1, 10347 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ); 10348 10349 return { 10350 top: ( 10351 10352 // The absolute mouse position 10353 pos.top + 10354 10355 // Only for relative positioned nodes: Relative offset from element to offset parent 10356 this.offset.relative.top * mod + 10357 10358 // The offsetParent's offset without borders (offset + border) 10359 this.offset.parent.top * mod - 10360 ( ( this.cssPosition === "fixed" ? 10361 -this.offset.scroll.top : 10362 ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod ) 10363 ), 10364 left: ( 10365 10366 // The absolute mouse position 10367 pos.left + 10368 10369 // Only for relative positioned nodes: Relative offset from element to offset parent 10370 this.offset.relative.left * mod + 10371 10372 // The offsetParent's offset without borders (offset + border) 10373 this.offset.parent.left * mod - 10374 ( ( this.cssPosition === "fixed" ? 10375 -this.offset.scroll.left : 10376 ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod ) 10377 ) 10378 }; 10379 10380 }, 10381 10382 _generatePosition: function( event, constrainPosition ) { 10383 10384 var containment, co, top, left, 10385 o = this.options, 10386 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ), 10387 pageX = event.pageX, 10388 pageY = event.pageY; 10389 10390 // Cache the scroll 10391 if ( !scrollIsRootNode || !this.offset.scroll ) { 10392 this.offset.scroll = { 10393 top: this.scrollParent.scrollTop(), 10394 left: this.scrollParent.scrollLeft() 10395 }; 10396 } 10397 10398 /* 10399 * - Position constraining - 10400 * Constrain the position to a mix of grid, containment. 10401 */ 10402 10403 // If we are not dragging yet, we won't check for options 10404 if ( constrainPosition ) { 10405 if ( this.containment ) { 10406 if ( this.relativeContainer ) { 10407 co = this.relativeContainer.offset(); 10408 containment = [ 10409 this.containment[ 0 ] + co.left, 10410 this.containment[ 1 ] + co.top, 10411 this.containment[ 2 ] + co.left, 10412 this.containment[ 3 ] + co.top 10413 ]; 10414 } else { 10415 containment = this.containment; 10416 } 10417 10418 if ( event.pageX - this.offset.click.left < containment[ 0 ] ) { 10419 pageX = containment[ 0 ] + this.offset.click.left; 10420 } 10421 if ( event.pageY - this.offset.click.top < containment[ 1 ] ) { 10422 pageY = containment[ 1 ] + this.offset.click.top; 10423 } 10424 if ( event.pageX - this.offset.click.left > containment[ 2 ] ) { 10425 pageX = containment[ 2 ] + this.offset.click.left; 10426 } 10427 if ( event.pageY - this.offset.click.top > containment[ 3 ] ) { 10428 pageY = containment[ 3 ] + this.offset.click.top; 10429 } 10430 } 10431 10432 if ( o.grid ) { 10433 10434 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid 10435 // argument errors in IE (see ticket #6950) 10436 top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY - 10437 this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY; 10438 pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] || 10439 top - this.offset.click.top > containment[ 3 ] ) ? 10440 top : 10441 ( ( top - this.offset.click.top >= containment[ 1 ] ) ? 10442 top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top; 10443 10444 left = o.grid[ 0 ] ? this.originalPageX + 10445 Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] : 10446 this.originalPageX; 10447 pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] || 10448 left - this.offset.click.left > containment[ 2 ] ) ? 10449 left : 10450 ( ( left - this.offset.click.left >= containment[ 0 ] ) ? 10451 left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left; 10452 } 10453 10454 if ( o.axis === "y" ) { 10455 pageX = this.originalPageX; 10456 } 10457 10458 if ( o.axis === "x" ) { 10459 pageY = this.originalPageY; 10460 } 10461 } 10462 10463 return { 10464 top: ( 10465 10466 // The absolute mouse position 10467 pageY - 10468 10469 // Click offset (relative to the element) 10470 this.offset.click.top - 10471 10472 // Only for relative positioned nodes: Relative offset from element to offset parent 10473 this.offset.relative.top - 10474 10475 // The offsetParent's offset without borders (offset + border) 10476 this.offset.parent.top + 10477 ( this.cssPosition === "fixed" ? 10478 -this.offset.scroll.top : 10479 ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) 10480 ), 10481 left: ( 10482 10483 // The absolute mouse position 10484 pageX - 10485 10486 // Click offset (relative to the element) 10487 this.offset.click.left - 10488 10489 // Only for relative positioned nodes: Relative offset from element to offset parent 10490 this.offset.relative.left - 10491 10492 // The offsetParent's offset without borders (offset + border) 10493 this.offset.parent.left + 10494 ( this.cssPosition === "fixed" ? 10495 -this.offset.scroll.left : 10496 ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) 10497 ) 10498 }; 10499 10500 }, 10501 10502 _clear: function() { 10503 this._removeClass( this.helper, "ui-draggable-dragging" ); 10504 if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) { 10505 this.helper.remove(); 10506 } 10507 this.helper = null; 10508 this.cancelHelperRemoval = false; 10509 if ( this.destroyOnClear ) { 10510 this.destroy(); 10511 } 10512 }, 10513 10514 // From now on bulk stuff - mainly helpers 10515 10516 _trigger: function( type, event, ui ) { 10517 ui = ui || this._uiHash(); 10518 $.ui.plugin.call( this, type, [ event, ui, this ], true ); 10519 10520 // Absolute position and offset (see #6884 ) have to be recalculated after plugins 10521 if ( /^(drag|start|stop)/.test( type ) ) { 10522 this.positionAbs = this._convertPositionTo( "absolute" ); 10523 ui.offset = this.positionAbs; 10524 } 10525 return $.Widget.prototype._trigger.call( this, type, event, ui ); 10526 }, 10527 10528 plugins: {}, 10529 10530 _uiHash: function() { 10531 return { 10532 helper: this.helper, 10533 position: this.position, 10534 originalPosition: this.originalPosition, 10535 offset: this.positionAbs 10536 }; 10537 } 10538 10539} ); 10540 10541$.ui.plugin.add( "draggable", "connectToSortable", { 10542 start: function( event, ui, draggable ) { 10543 var uiSortable = $.extend( {}, ui, { 10544 item: draggable.element 10545 } ); 10546 10547 draggable.sortables = []; 10548 $( draggable.options.connectToSortable ).each( function() { 10549 var sortable = $( this ).sortable( "instance" ); 10550 10551 if ( sortable && !sortable.options.disabled ) { 10552 draggable.sortables.push( sortable ); 10553 10554 // RefreshPositions is called at drag start to refresh the containerCache 10555 // which is used in drag. This ensures it's initialized and synchronized 10556 // with any changes that might have happened on the page since initialization. 10557 sortable.refreshPositions(); 10558 sortable._trigger( "activate", event, uiSortable ); 10559 } 10560 } ); 10561 }, 10562 stop: function( event, ui, draggable ) { 10563 var uiSortable = $.extend( {}, ui, { 10564 item: draggable.element 10565 } ); 10566 10567 draggable.cancelHelperRemoval = false; 10568 10569 $.each( draggable.sortables, function() { 10570 var sortable = this; 10571 10572 if ( sortable.isOver ) { 10573 sortable.isOver = 0; 10574 10575 // Allow this sortable to handle removing the helper 10576 draggable.cancelHelperRemoval = true; 10577 sortable.cancelHelperRemoval = false; 10578 10579 // Use _storedCSS To restore properties in the sortable, 10580 // as this also handles revert (#9675) since the draggable 10581 // may have modified them in unexpected ways (#8809) 10582 sortable._storedCSS = { 10583 position: sortable.placeholder.css( "position" ), 10584 top: sortable.placeholder.css( "top" ), 10585 left: sortable.placeholder.css( "left" ) 10586 }; 10587 10588 sortable._mouseStop( event ); 10589 10590 // Once drag has ended, the sortable should return to using 10591 // its original helper, not the shared helper from draggable 10592 sortable.options.helper = sortable.options._helper; 10593 } else { 10594 10595 // Prevent this Sortable from removing the helper. 10596 // However, don't set the draggable to remove the helper 10597 // either as another connected Sortable may yet handle the removal. 10598 sortable.cancelHelperRemoval = true; 10599 10600 sortable._trigger( "deactivate", event, uiSortable ); 10601 } 10602 } ); 10603 }, 10604 drag: function( event, ui, draggable ) { 10605 $.each( draggable.sortables, function() { 10606 var innermostIntersecting = false, 10607 sortable = this; 10608 10609 // Copy over variables that sortable's _intersectsWith uses 10610 sortable.positionAbs = draggable.positionAbs; 10611 sortable.helperProportions = draggable.helperProportions; 10612 sortable.offset.click = draggable.offset.click; 10613 10614 if ( sortable._intersectsWith( sortable.containerCache ) ) { 10615 innermostIntersecting = true; 10616 10617 $.each( draggable.sortables, function() { 10618 10619 // Copy over variables that sortable's _intersectsWith uses 10620 this.positionAbs = draggable.positionAbs; 10621 this.helperProportions = draggable.helperProportions; 10622 this.offset.click = draggable.offset.click; 10623 10624 if ( this !== sortable && 10625 this._intersectsWith( this.containerCache ) && 10626 $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) { 10627 innermostIntersecting = false; 10628 } 10629 10630 return innermostIntersecting; 10631 } ); 10632 } 10633 10634 if ( innermostIntersecting ) { 10635 10636 // If it intersects, we use a little isOver variable and set it once, 10637 // so that the move-in stuff gets fired only once. 10638 if ( !sortable.isOver ) { 10639 sortable.isOver = 1; 10640 10641 // Store draggable's parent in case we need to reappend to it later. 10642 draggable._parent = ui.helper.parent(); 10643 10644 sortable.currentItem = ui.helper 10645 .appendTo( sortable.element ) 10646 .data( "ui-sortable-item", true ); 10647 10648 // Store helper option to later restore it 10649 sortable.options._helper = sortable.options.helper; 10650 10651 sortable.options.helper = function() { 10652 return ui.helper[ 0 ]; 10653 }; 10654 10655 // Fire the start events of the sortable with our passed browser event, 10656 // and our own helper (so it doesn't create a new one) 10657 event.target = sortable.currentItem[ 0 ]; 10658 sortable._mouseCapture( event, true ); 10659 sortable._mouseStart( event, true, true ); 10660 10661 // Because the browser event is way off the new appended portlet, 10662 // modify necessary variables to reflect the changes 10663 sortable.offset.click.top = draggable.offset.click.top; 10664 sortable.offset.click.left = draggable.offset.click.left; 10665 sortable.offset.parent.left -= draggable.offset.parent.left - 10666 sortable.offset.parent.left; 10667 sortable.offset.parent.top -= draggable.offset.parent.top - 10668 sortable.offset.parent.top; 10669 10670 draggable._trigger( "toSortable", event ); 10671 10672 // Inform draggable that the helper is in a valid drop zone, 10673 // used solely in the revert option to handle "valid/invalid". 10674 draggable.dropped = sortable.element; 10675 10676 // Need to refreshPositions of all sortables in the case that 10677 // adding to one sortable changes the location of the other sortables (#9675) 10678 $.each( draggable.sortables, function() { 10679 this.refreshPositions(); 10680 } ); 10681 10682 // Hack so receive/update callbacks work (mostly) 10683 draggable.currentItem = draggable.element; 10684 sortable.fromOutside = draggable; 10685 } 10686 10687 if ( sortable.currentItem ) { 10688 sortable._mouseDrag( event ); 10689 10690 // Copy the sortable's position because the draggable's can potentially reflect 10691 // a relative position, while sortable is always absolute, which the dragged 10692 // element has now become. (#8809) 10693 ui.position = sortable.position; 10694 } 10695 } else { 10696 10697 // If it doesn't intersect with the sortable, and it intersected before, 10698 // we fake the drag stop of the sortable, but make sure it doesn't remove 10699 // the helper by using cancelHelperRemoval. 10700 if ( sortable.isOver ) { 10701 10702 sortable.isOver = 0; 10703 sortable.cancelHelperRemoval = true; 10704 10705 // Calling sortable's mouseStop would trigger a revert, 10706 // so revert must be temporarily false until after mouseStop is called. 10707 sortable.options._revert = sortable.options.revert; 10708 sortable.options.revert = false; 10709 10710 sortable._trigger( "out", event, sortable._uiHash( sortable ) ); 10711 sortable._mouseStop( event, true ); 10712 10713 // Restore sortable behaviors that were modfied 10714 // when the draggable entered the sortable area (#9481) 10715 sortable.options.revert = sortable.options._revert; 10716 sortable.options.helper = sortable.options._helper; 10717 10718 if ( sortable.placeholder ) { 10719 sortable.placeholder.remove(); 10720 } 10721 10722 // Restore and recalculate the draggable's offset considering the sortable 10723 // may have modified them in unexpected ways. (#8809, #10669) 10724 ui.helper.appendTo( draggable._parent ); 10725 draggable._refreshOffsets( event ); 10726 ui.position = draggable._generatePosition( event, true ); 10727 10728 draggable._trigger( "fromSortable", event ); 10729 10730 // Inform draggable that the helper is no longer in a valid drop zone 10731 draggable.dropped = false; 10732 10733 // Need to refreshPositions of all sortables just in case removing 10734 // from one sortable changes the location of other sortables (#9675) 10735 $.each( draggable.sortables, function() { 10736 this.refreshPositions(); 10737 } ); 10738 } 10739 } 10740 } ); 10741 } 10742} ); 10743 10744$.ui.plugin.add( "draggable", "cursor", { 10745 start: function( event, ui, instance ) { 10746 var t = $( "body" ), 10747 o = instance.options; 10748 10749 if ( t.css( "cursor" ) ) { 10750 o._cursor = t.css( "cursor" ); 10751 } 10752 t.css( "cursor", o.cursor ); 10753 }, 10754 stop: function( event, ui, instance ) { 10755 var o = instance.options; 10756 if ( o._cursor ) { 10757 $( "body" ).css( "cursor", o._cursor ); 10758 } 10759 } 10760} ); 10761 10762$.ui.plugin.add( "draggable", "opacity", { 10763 start: function( event, ui, instance ) { 10764 var t = $( ui.helper ), 10765 o = instance.options; 10766 if ( t.css( "opacity" ) ) { 10767 o._opacity = t.css( "opacity" ); 10768 } 10769 t.css( "opacity", o.opacity ); 10770 }, 10771 stop: function( event, ui, instance ) { 10772 var o = instance.options; 10773 if ( o._opacity ) { 10774 $( ui.helper ).css( "opacity", o._opacity ); 10775 } 10776 } 10777} ); 10778 10779$.ui.plugin.add( "draggable", "scroll", { 10780 start: function( event, ui, i ) { 10781 if ( !i.scrollParentNotHidden ) { 10782 i.scrollParentNotHidden = i.helper.scrollParent( false ); 10783 } 10784 10785 if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] && 10786 i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) { 10787 i.overflowOffset = i.scrollParentNotHidden.offset(); 10788 } 10789 }, 10790 drag: function( event, ui, i ) { 10791 10792 var o = i.options, 10793 scrolled = false, 10794 scrollParent = i.scrollParentNotHidden[ 0 ], 10795 document = i.document[ 0 ]; 10796 10797 if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) { 10798 if ( !o.axis || o.axis !== "x" ) { 10799 if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY < 10800 o.scrollSensitivity ) { 10801 scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed; 10802 } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) { 10803 scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed; 10804 } 10805 } 10806 10807 if ( !o.axis || o.axis !== "y" ) { 10808 if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX < 10809 o.scrollSensitivity ) { 10810 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed; 10811 } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) { 10812 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed; 10813 } 10814 } 10815 10816 } else { 10817 10818 if ( !o.axis || o.axis !== "x" ) { 10819 if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) { 10820 scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed ); 10821 } else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) < 10822 o.scrollSensitivity ) { 10823 scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed ); 10824 } 10825 } 10826 10827 if ( !o.axis || o.axis !== "y" ) { 10828 if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) { 10829 scrolled = $( document ).scrollLeft( 10830 $( document ).scrollLeft() - o.scrollSpeed 10831 ); 10832 } else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) < 10833 o.scrollSensitivity ) { 10834 scrolled = $( document ).scrollLeft( 10835 $( document ).scrollLeft() + o.scrollSpeed 10836 ); 10837 } 10838 } 10839 10840 } 10841 10842 if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) { 10843 $.ui.ddmanager.prepareOffsets( i, event ); 10844 } 10845 10846 } 10847} ); 10848 10849$.ui.plugin.add( "draggable", "snap", { 10850 start: function( event, ui, i ) { 10851 10852 var o = i.options; 10853 10854 i.snapElements = []; 10855 10856 $( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap ) 10857 .each( function() { 10858 var $t = $( this ), 10859 $o = $t.offset(); 10860 if ( this !== i.element[ 0 ] ) { 10861 i.snapElements.push( { 10862 item: this, 10863 width: $t.outerWidth(), height: $t.outerHeight(), 10864 top: $o.top, left: $o.left 10865 } ); 10866 } 10867 } ); 10868 10869 }, 10870 drag: function( event, ui, inst ) { 10871 10872 var ts, bs, ls, rs, l, r, t, b, i, first, 10873 o = inst.options, 10874 d = o.snapTolerance, 10875 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, 10876 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; 10877 10878 for ( i = inst.snapElements.length - 1; i >= 0; i-- ) { 10879 10880 l = inst.snapElements[ i ].left - inst.margins.left; 10881 r = l + inst.snapElements[ i ].width; 10882 t = inst.snapElements[ i ].top - inst.margins.top; 10883 b = t + inst.snapElements[ i ].height; 10884 10885 if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || 10886 !$.contains( inst.snapElements[ i ].item.ownerDocument, 10887 inst.snapElements[ i ].item ) ) { 10888 if ( inst.snapElements[ i ].snapping ) { 10889 if ( inst.options.snap.release ) { 10890 inst.options.snap.release.call( 10891 inst.element, 10892 event, 10893 $.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } ) 10894 ); 10895 } 10896 } 10897 inst.snapElements[ i ].snapping = false; 10898 continue; 10899 } 10900 10901 if ( o.snapMode !== "inner" ) { 10902 ts = Math.abs( t - y2 ) <= d; 10903 bs = Math.abs( b - y1 ) <= d; 10904 ls = Math.abs( l - x2 ) <= d; 10905 rs = Math.abs( r - x1 ) <= d; 10906 if ( ts ) { 10907 ui.position.top = inst._convertPositionTo( "relative", { 10908 top: t - inst.helperProportions.height, 10909 left: 0 10910 } ).top; 10911 } 10912 if ( bs ) { 10913 ui.position.top = inst._convertPositionTo( "relative", { 10914 top: b, 10915 left: 0 10916 } ).top; 10917 } 10918 if ( ls ) { 10919 ui.position.left = inst._convertPositionTo( "relative", { 10920 top: 0, 10921 left: l - inst.helperProportions.width 10922 } ).left; 10923 } 10924 if ( rs ) { 10925 ui.position.left = inst._convertPositionTo( "relative", { 10926 top: 0, 10927 left: r 10928 } ).left; 10929 } 10930 } 10931 10932 first = ( ts || bs || ls || rs ); 10933 10934 if ( o.snapMode !== "outer" ) { 10935 ts = Math.abs( t - y1 ) <= d; 10936 bs = Math.abs( b - y2 ) <= d; 10937 ls = Math.abs( l - x1 ) <= d; 10938 rs = Math.abs( r - x2 ) <= d; 10939 if ( ts ) { 10940 ui.position.top = inst._convertPositionTo( "relative", { 10941 top: t, 10942 left: 0 10943 } ).top; 10944 } 10945 if ( bs ) { 10946 ui.position.top = inst._convertPositionTo( "relative", { 10947 top: b - inst.helperProportions.height, 10948 left: 0 10949 } ).top; 10950 } 10951 if ( ls ) { 10952 ui.position.left = inst._convertPositionTo( "relative", { 10953 top: 0, 10954 left: l 10955 } ).left; 10956 } 10957 if ( rs ) { 10958 ui.position.left = inst._convertPositionTo( "relative", { 10959 top: 0, 10960 left: r - inst.helperProportions.width 10961 } ).left; 10962 } 10963 } 10964 10965 if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) { 10966 if ( inst.options.snap.snap ) { 10967 inst.options.snap.snap.call( 10968 inst.element, 10969 event, 10970 $.extend( inst._uiHash(), { 10971 snapItem: inst.snapElements[ i ].item 10972 } ) ); 10973 } 10974 } 10975 inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first ); 10976 10977 } 10978 10979 } 10980} ); 10981 10982$.ui.plugin.add( "draggable", "stack", { 10983 start: function( event, ui, instance ) { 10984 var min, 10985 o = instance.options, 10986 group = $.makeArray( $( o.stack ) ).sort( function( a, b ) { 10987 return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) - 10988 ( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 ); 10989 } ); 10990 10991 if ( !group.length ) { 10992 return; 10993 } 10994 10995 min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0; 10996 $( group ).each( function( i ) { 10997 $( this ).css( "zIndex", min + i ); 10998 } ); 10999 this.css( "zIndex", ( min + group.length ) ); 11000 } 11001} ); 11002 11003$.ui.plugin.add( "draggable", "zIndex", { 11004 start: function( event, ui, instance ) { 11005 var t = $( ui.helper ), 11006 o = instance.options; 11007 11008 if ( t.css( "zIndex" ) ) { 11009 o._zIndex = t.css( "zIndex" ); 11010 } 11011 t.css( "zIndex", o.zIndex ); 11012 }, 11013 stop: function( event, ui, instance ) { 11014 var o = instance.options; 11015 11016 if ( o._zIndex ) { 11017 $( ui.helper ).css( "zIndex", o._zIndex ); 11018 } 11019 } 11020} ); 11021 11022var widgetsDraggable = $.ui.draggable; 11023 11024 11025/*! 11026 * jQuery UI Resizable 1.13.3 11027 * https://jqueryui.com 11028 * 11029 * Copyright OpenJS Foundation and other contributors 11030 * Released under the MIT license. 11031 * https://jquery.org/license 11032 */ 11033 11034//>>label: Resizable 11035//>>group: Interactions 11036//>>description: Enables resize functionality for any element. 11037//>>docs: https://api.jqueryui.com/resizable/ 11038//>>demos: https://jqueryui.com/resizable/ 11039//>>css.structure: ../../themes/base/core.css 11040//>>css.structure: ../../themes/base/resizable.css 11041//>>css.theme: ../../themes/base/theme.css 11042 11043 11044$.widget( "ui.resizable", $.ui.mouse, { 11045 version: "1.13.3", 11046 widgetEventPrefix: "resize", 11047 options: { 11048 alsoResize: false, 11049 animate: false, 11050 animateDuration: "slow", 11051 animateEasing: "swing", 11052 aspectRatio: false, 11053 autoHide: false, 11054 classes: { 11055 "ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se" 11056 }, 11057 containment: false, 11058 ghost: false, 11059 grid: false, 11060 handles: "e,s,se", 11061 helper: false, 11062 maxHeight: null, 11063 maxWidth: null, 11064 minHeight: 10, 11065 minWidth: 10, 11066 11067 // See #7960 11068 zIndex: 90, 11069 11070 // Callbacks 11071 resize: null, 11072 start: null, 11073 stop: null 11074 }, 11075 11076 _num: function( value ) { 11077 return parseFloat( value ) || 0; 11078 }, 11079 11080 _isNumber: function( value ) { 11081 return !isNaN( parseFloat( value ) ); 11082 }, 11083 11084 _hasScroll: function( el, a ) { 11085 11086 if ( $( el ).css( "overflow" ) === "hidden" ) { 11087 return false; 11088 } 11089 11090 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", 11091 has = false; 11092 11093 if ( el[ scroll ] > 0 ) { 11094 return true; 11095 } 11096 11097 // TODO: determine which cases actually cause this to happen 11098 // if the element doesn't have the scroll set, see if it's possible to 11099 // set the scroll 11100 try { 11101 el[ scroll ] = 1; 11102 has = ( el[ scroll ] > 0 ); 11103 el[ scroll ] = 0; 11104 } catch ( e ) { 11105 11106 // `el` might be a string, then setting `scroll` will throw 11107 // an error in strict mode; ignore it. 11108 } 11109 return has; 11110 }, 11111 11112 _create: function() { 11113 11114 var margins, 11115 o = this.options, 11116 that = this; 11117 this._addClass( "ui-resizable" ); 11118 11119 $.extend( this, { 11120 _aspectRatio: !!( o.aspectRatio ), 11121 aspectRatio: o.aspectRatio, 11122 originalElement: this.element, 11123 _proportionallyResizeElements: [], 11124 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null 11125 } ); 11126 11127 // Wrap the element if it cannot hold child nodes 11128 if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) { 11129 11130 this.element.wrap( 11131 $( "<div class='ui-wrapper'></div>" ).css( { 11132 overflow: "hidden", 11133 position: this.element.css( "position" ), 11134 width: this.element.outerWidth(), 11135 height: this.element.outerHeight(), 11136 top: this.element.css( "top" ), 11137 left: this.element.css( "left" ) 11138 } ) 11139 ); 11140 11141 this.element = this.element.parent().data( 11142 "ui-resizable", this.element.resizable( "instance" ) 11143 ); 11144 11145 this.elementIsWrapper = true; 11146 11147 margins = { 11148 marginTop: this.originalElement.css( "marginTop" ), 11149 marginRight: this.originalElement.css( "marginRight" ), 11150 marginBottom: this.originalElement.css( "marginBottom" ), 11151 marginLeft: this.originalElement.css( "marginLeft" ) 11152 }; 11153 11154 this.element.css( margins ); 11155 this.originalElement.css( "margin", 0 ); 11156 11157 // support: Safari 11158 // Prevent Safari textarea resize 11159 this.originalResizeStyle = this.originalElement.css( "resize" ); 11160 this.originalElement.css( "resize", "none" ); 11161 11162 this._proportionallyResizeElements.push( this.originalElement.css( { 11163 position: "static", 11164 zoom: 1, 11165 display: "block" 11166 } ) ); 11167 11168 // Support: IE9 11169 // avoid IE jump (hard set the margin) 11170 this.originalElement.css( margins ); 11171 11172 this._proportionallyResize(); 11173 } 11174 11175 this._setupHandles(); 11176 11177 if ( o.autoHide ) { 11178 $( this.element ) 11179 .on( "mouseenter", function() { 11180 if ( o.disabled ) { 11181 return; 11182 } 11183 that._removeClass( "ui-resizable-autohide" ); 11184 that._handles.show(); 11185 } ) 11186 .on( "mouseleave", function() { 11187 if ( o.disabled ) { 11188 return; 11189 } 11190 if ( !that.resizing ) { 11191 that._addClass( "ui-resizable-autohide" ); 11192 that._handles.hide(); 11193 } 11194 } ); 11195 } 11196 11197 this._mouseInit(); 11198 }, 11199 11200 _destroy: function() { 11201 11202 this._mouseDestroy(); 11203 this._addedHandles.remove(); 11204 11205 var wrapper, 11206 _destroy = function( exp ) { 11207 $( exp ) 11208 .removeData( "resizable" ) 11209 .removeData( "ui-resizable" ) 11210 .off( ".resizable" ); 11211 }; 11212 11213 // TODO: Unwrap at same DOM position 11214 if ( this.elementIsWrapper ) { 11215 _destroy( this.element ); 11216 wrapper = this.element; 11217 this.originalElement.css( { 11218 position: wrapper.css( "position" ), 11219 width: wrapper.outerWidth(), 11220 height: wrapper.outerHeight(), 11221 top: wrapper.css( "top" ), 11222 left: wrapper.css( "left" ) 11223 } ).insertAfter( wrapper ); 11224 wrapper.remove(); 11225 } 11226 11227 this.originalElement.css( "resize", this.originalResizeStyle ); 11228 _destroy( this.originalElement ); 11229 11230 return this; 11231 }, 11232 11233 _setOption: function( key, value ) { 11234 this._super( key, value ); 11235 11236 switch ( key ) { 11237 case "handles": 11238 this._removeHandles(); 11239 this._setupHandles(); 11240 break; 11241 case "aspectRatio": 11242 this._aspectRatio = !!value; 11243 break; 11244 default: 11245 break; 11246 } 11247 }, 11248 11249 _setupHandles: function() { 11250 var o = this.options, handle, i, n, hname, axis, that = this; 11251 this.handles = o.handles || 11252 ( !$( ".ui-resizable-handle", this.element ).length ? 11253 "e,s,se" : { 11254 n: ".ui-resizable-n", 11255 e: ".ui-resizable-e", 11256 s: ".ui-resizable-s", 11257 w: ".ui-resizable-w", 11258 se: ".ui-resizable-se", 11259 sw: ".ui-resizable-sw", 11260 ne: ".ui-resizable-ne", 11261 nw: ".ui-resizable-nw" 11262 } ); 11263 11264 this._handles = $(); 11265 this._addedHandles = $(); 11266 if ( this.handles.constructor === String ) { 11267 11268 if ( this.handles === "all" ) { 11269 this.handles = "n,e,s,w,se,sw,ne,nw"; 11270 } 11271 11272 n = this.handles.split( "," ); 11273 this.handles = {}; 11274 11275 for ( i = 0; i < n.length; i++ ) { 11276 11277 handle = String.prototype.trim.call( n[ i ] ); 11278 hname = "ui-resizable-" + handle; 11279 axis = $( "<div>" ); 11280 this._addClass( axis, "ui-resizable-handle " + hname ); 11281 11282 axis.css( { zIndex: o.zIndex } ); 11283 11284 this.handles[ handle ] = ".ui-resizable-" + handle; 11285 if ( !this.element.children( this.handles[ handle ] ).length ) { 11286 this.element.append( axis ); 11287 this._addedHandles = this._addedHandles.add( axis ); 11288 } 11289 } 11290 11291 } 11292 11293 this._renderAxis = function( target ) { 11294 11295 var i, axis, padPos, padWrapper; 11296 11297 target = target || this.element; 11298 11299 for ( i in this.handles ) { 11300 11301 if ( this.handles[ i ].constructor === String ) { 11302 this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show(); 11303 } else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) { 11304 this.handles[ i ] = $( this.handles[ i ] ); 11305 this._on( this.handles[ i ], { "mousedown": that._mouseDown } ); 11306 } 11307 11308 if ( this.elementIsWrapper && 11309 this.originalElement[ 0 ] 11310 .nodeName 11311 .match( /^(textarea|input|select|button)$/i ) ) { 11312 axis = $( this.handles[ i ], this.element ); 11313 11314 padWrapper = /sw|ne|nw|se|n|s/.test( i ) ? 11315 axis.outerHeight() : 11316 axis.outerWidth(); 11317 11318 padPos = [ "padding", 11319 /ne|nw|n/.test( i ) ? "Top" : 11320 /se|sw|s/.test( i ) ? "Bottom" : 11321 /^e$/.test( i ) ? "Right" : "Left" ].join( "" ); 11322 11323 target.css( padPos, padWrapper ); 11324 11325 this._proportionallyResize(); 11326 } 11327 11328 this._handles = this._handles.add( this.handles[ i ] ); 11329 } 11330 }; 11331 11332 // TODO: make renderAxis a prototype function 11333 this._renderAxis( this.element ); 11334 11335 this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) ); 11336 this._handles.disableSelection(); 11337 11338 this._handles.on( "mouseover", function() { 11339 if ( !that.resizing ) { 11340 if ( this.className ) { 11341 axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i ); 11342 } 11343 that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se"; 11344 } 11345 } ); 11346 11347 if ( o.autoHide ) { 11348 this._handles.hide(); 11349 this._addClass( "ui-resizable-autohide" ); 11350 } 11351 }, 11352 11353 _removeHandles: function() { 11354 this._addedHandles.remove(); 11355 }, 11356 11357 _mouseCapture: function( event ) { 11358 var i, handle, 11359 capture = false; 11360 11361 for ( i in this.handles ) { 11362 handle = $( this.handles[ i ] )[ 0 ]; 11363 if ( handle === event.target || $.contains( handle, event.target ) ) { 11364 capture = true; 11365 } 11366 } 11367 11368 return !this.options.disabled && capture; 11369 }, 11370 11371 _mouseStart: function( event ) { 11372 11373 var curleft, curtop, cursor, 11374 o = this.options, 11375 el = this.element; 11376 11377 this.resizing = true; 11378 11379 this._renderProxy(); 11380 11381 curleft = this._num( this.helper.css( "left" ) ); 11382 curtop = this._num( this.helper.css( "top" ) ); 11383 11384 if ( o.containment ) { 11385 curleft += $( o.containment ).scrollLeft() || 0; 11386 curtop += $( o.containment ).scrollTop() || 0; 11387 } 11388 11389 this.offset = this.helper.offset(); 11390 this.position = { left: curleft, top: curtop }; 11391 11392 this.size = this._helper ? { 11393 width: this.helper.width(), 11394 height: this.helper.height() 11395 } : { 11396 width: el.width(), 11397 height: el.height() 11398 }; 11399 11400 this.originalSize = this._helper ? { 11401 width: el.outerWidth(), 11402 height: el.outerHeight() 11403 } : { 11404 width: el.width(), 11405 height: el.height() 11406 }; 11407 11408 this.sizeDiff = { 11409 width: el.outerWidth() - el.width(), 11410 height: el.outerHeight() - el.height() 11411 }; 11412 11413 this.originalPosition = { left: curleft, top: curtop }; 11414 this.originalMousePosition = { left: event.pageX, top: event.pageY }; 11415 11416 this.aspectRatio = ( typeof o.aspectRatio === "number" ) ? 11417 o.aspectRatio : 11418 ( ( this.originalSize.width / this.originalSize.height ) || 1 ); 11419 11420 cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" ); 11421 $( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor ); 11422 11423 this._addClass( "ui-resizable-resizing" ); 11424 this._propagate( "start", event ); 11425 return true; 11426 }, 11427 11428 _mouseDrag: function( event ) { 11429 11430 var data, props, 11431 smp = this.originalMousePosition, 11432 a = this.axis, 11433 dx = ( event.pageX - smp.left ) || 0, 11434 dy = ( event.pageY - smp.top ) || 0, 11435 trigger = this._change[ a ]; 11436 11437 this._updatePrevProperties(); 11438 11439 if ( !trigger ) { 11440 return false; 11441 } 11442 11443 data = trigger.apply( this, [ event, dx, dy ] ); 11444 11445 this._updateVirtualBoundaries( event.shiftKey ); 11446 if ( this._aspectRatio || event.shiftKey ) { 11447 data = this._updateRatio( data, event ); 11448 } 11449 11450 data = this._respectSize( data, event ); 11451 11452 this._updateCache( data ); 11453 11454 this._propagate( "resize", event ); 11455 11456 props = this._applyChanges(); 11457 11458 if ( !this._helper && this._proportionallyResizeElements.length ) { 11459 this._proportionallyResize(); 11460 } 11461 11462 if ( !$.isEmptyObject( props ) ) { 11463 this._updatePrevProperties(); 11464 this._trigger( "resize", event, this.ui() ); 11465 this._applyChanges(); 11466 } 11467 11468 return false; 11469 }, 11470 11471 _mouseStop: function( event ) { 11472 11473 this.resizing = false; 11474 var pr, ista, soffseth, soffsetw, s, left, top, 11475 o = this.options, that = this; 11476 11477 if ( this._helper ) { 11478 11479 pr = this._proportionallyResizeElements; 11480 ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ); 11481 soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height; 11482 soffsetw = ista ? 0 : that.sizeDiff.width; 11483 11484 s = { 11485 width: ( that.helper.width() - soffsetw ), 11486 height: ( that.helper.height() - soffseth ) 11487 }; 11488 left = ( parseFloat( that.element.css( "left" ) ) + 11489 ( that.position.left - that.originalPosition.left ) ) || null; 11490 top = ( parseFloat( that.element.css( "top" ) ) + 11491 ( that.position.top - that.originalPosition.top ) ) || null; 11492 11493 if ( !o.animate ) { 11494 this.element.css( $.extend( s, { top: top, left: left } ) ); 11495 } 11496 11497 that.helper.height( that.size.height ); 11498 that.helper.width( that.size.width ); 11499 11500 if ( this._helper && !o.animate ) { 11501 this._proportionallyResize(); 11502 } 11503 } 11504 11505 $( "body" ).css( "cursor", "auto" ); 11506 11507 this._removeClass( "ui-resizable-resizing" ); 11508 11509 this._propagate( "stop", event ); 11510 11511 if ( this._helper ) { 11512 this.helper.remove(); 11513 } 11514 11515 return false; 11516 11517 }, 11518 11519 _updatePrevProperties: function() { 11520 this.prevPosition = { 11521 top: this.position.top, 11522 left: this.position.left 11523 }; 11524 this.prevSize = { 11525 width: this.size.width, 11526 height: this.size.height 11527 }; 11528 }, 11529 11530 _applyChanges: function() { 11531 var props = {}; 11532 11533 if ( this.position.top !== this.prevPosition.top ) { 11534 props.top = this.position.top + "px"; 11535 } 11536 if ( this.position.left !== this.prevPosition.left ) { 11537 props.left = this.position.left + "px"; 11538 } 11539 11540 this.helper.css( props ); 11541 11542 if ( this.size.width !== this.prevSize.width ) { 11543 props.width = this.size.width + "px"; 11544 this.helper.width( props.width ); 11545 } 11546 if ( this.size.height !== this.prevSize.height ) { 11547 props.height = this.size.height + "px"; 11548 this.helper.height( props.height ); 11549 } 11550 11551 return props; 11552 }, 11553 11554 _updateVirtualBoundaries: function( forceAspectRatio ) { 11555 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b, 11556 o = this.options; 11557 11558 b = { 11559 minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0, 11560 maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity, 11561 minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0, 11562 maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity 11563 }; 11564 11565 if ( this._aspectRatio || forceAspectRatio ) { 11566 pMinWidth = b.minHeight * this.aspectRatio; 11567 pMinHeight = b.minWidth / this.aspectRatio; 11568 pMaxWidth = b.maxHeight * this.aspectRatio; 11569 pMaxHeight = b.maxWidth / this.aspectRatio; 11570 11571 if ( pMinWidth > b.minWidth ) { 11572 b.minWidth = pMinWidth; 11573 } 11574 if ( pMinHeight > b.minHeight ) { 11575 b.minHeight = pMinHeight; 11576 } 11577 if ( pMaxWidth < b.maxWidth ) { 11578 b.maxWidth = pMaxWidth; 11579 } 11580 if ( pMaxHeight < b.maxHeight ) { 11581 b.maxHeight = pMaxHeight; 11582 } 11583 } 11584 this._vBoundaries = b; 11585 }, 11586 11587 _updateCache: function( data ) { 11588 this.offset = this.helper.offset(); 11589 if ( this._isNumber( data.left ) ) { 11590 this.position.left = data.left; 11591 } 11592 if ( this._isNumber( data.top ) ) { 11593 this.position.top = data.top; 11594 } 11595 if ( this._isNumber( data.height ) ) { 11596 this.size.height = data.height; 11597 } 11598 if ( this._isNumber( data.width ) ) { 11599 this.size.width = data.width; 11600 } 11601 }, 11602 11603 _updateRatio: function( data ) { 11604 11605 var cpos = this.position, 11606 csize = this.size, 11607 a = this.axis; 11608 11609 if ( this._isNumber( data.height ) ) { 11610 data.width = ( data.height * this.aspectRatio ); 11611 } else if ( this._isNumber( data.width ) ) { 11612 data.height = ( data.width / this.aspectRatio ); 11613 } 11614 11615 if ( a === "sw" ) { 11616 data.left = cpos.left + ( csize.width - data.width ); 11617 data.top = null; 11618 } 11619 if ( a === "nw" ) { 11620 data.top = cpos.top + ( csize.height - data.height ); 11621 data.left = cpos.left + ( csize.width - data.width ); 11622 } 11623 11624 return data; 11625 }, 11626 11627 _respectSize: function( data ) { 11628 11629 var o = this._vBoundaries, 11630 a = this.axis, 11631 ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ), 11632 ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ), 11633 isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ), 11634 isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ), 11635 dw = this.originalPosition.left + this.originalSize.width, 11636 dh = this.originalPosition.top + this.originalSize.height, 11637 cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a ); 11638 if ( isminw ) { 11639 data.width = o.minWidth; 11640 } 11641 if ( isminh ) { 11642 data.height = o.minHeight; 11643 } 11644 if ( ismaxw ) { 11645 data.width = o.maxWidth; 11646 } 11647 if ( ismaxh ) { 11648 data.height = o.maxHeight; 11649 } 11650 11651 if ( isminw && cw ) { 11652 data.left = dw - o.minWidth; 11653 } 11654 if ( ismaxw && cw ) { 11655 data.left = dw - o.maxWidth; 11656 } 11657 if ( isminh && ch ) { 11658 data.top = dh - o.minHeight; 11659 } 11660 if ( ismaxh && ch ) { 11661 data.top = dh - o.maxHeight; 11662 } 11663 11664 // Fixing jump error on top/left - bug #2330 11665 if ( !data.width && !data.height && !data.left && data.top ) { 11666 data.top = null; 11667 } else if ( !data.width && !data.height && !data.top && data.left ) { 11668 data.left = null; 11669 } 11670 11671 return data; 11672 }, 11673 11674 _getPaddingPlusBorderDimensions: function( element ) { 11675 var i = 0, 11676 widths = [], 11677 borders = [ 11678 element.css( "borderTopWidth" ), 11679 element.css( "borderRightWidth" ), 11680 element.css( "borderBottomWidth" ), 11681 element.css( "borderLeftWidth" ) 11682 ], 11683 paddings = [ 11684 element.css( "paddingTop" ), 11685 element.css( "paddingRight" ), 11686 element.css( "paddingBottom" ), 11687 element.css( "paddingLeft" ) 11688 ]; 11689 11690 for ( ; i < 4; i++ ) { 11691 widths[ i ] = ( parseFloat( borders[ i ] ) || 0 ); 11692 widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 ); 11693 } 11694 11695 return { 11696 height: widths[ 0 ] + widths[ 2 ], 11697 width: widths[ 1 ] + widths[ 3 ] 11698 }; 11699 }, 11700 11701 _proportionallyResize: function() { 11702 11703 if ( !this._proportionallyResizeElements.length ) { 11704 return; 11705 } 11706 11707 var prel, 11708 i = 0, 11709 element = this.helper || this.element; 11710 11711 for ( ; i < this._proportionallyResizeElements.length; i++ ) { 11712 11713 prel = this._proportionallyResizeElements[ i ]; 11714 11715 // TODO: Seems like a bug to cache this.outerDimensions 11716 // considering that we are in a loop. 11717 if ( !this.outerDimensions ) { 11718 this.outerDimensions = this._getPaddingPlusBorderDimensions( prel ); 11719 } 11720 11721 prel.css( { 11722 height: ( element.height() - this.outerDimensions.height ) || 0, 11723 width: ( element.width() - this.outerDimensions.width ) || 0 11724 } ); 11725 11726 } 11727 11728 }, 11729 11730 _renderProxy: function() { 11731 11732 var el = this.element, o = this.options; 11733 this.elementOffset = el.offset(); 11734 11735 if ( this._helper ) { 11736 11737 this.helper = this.helper || $( "<div></div>" ).css( { overflow: "hidden" } ); 11738 11739 this._addClass( this.helper, this._helper ); 11740 this.helper.css( { 11741 width: this.element.outerWidth(), 11742 height: this.element.outerHeight(), 11743 position: "absolute", 11744 left: this.elementOffset.left + "px", 11745 top: this.elementOffset.top + "px", 11746 zIndex: ++o.zIndex //TODO: Don't modify option 11747 } ); 11748 11749 this.helper 11750 .appendTo( "body" ) 11751 .disableSelection(); 11752 11753 } else { 11754 this.helper = this.element; 11755 } 11756 11757 }, 11758 11759 _change: { 11760 e: function( event, dx ) { 11761 return { width: this.originalSize.width + dx }; 11762 }, 11763 w: function( event, dx ) { 11764 var cs = this.originalSize, sp = this.originalPosition; 11765 return { left: sp.left + dx, width: cs.width - dx }; 11766 }, 11767 n: function( event, dx, dy ) { 11768 var cs = this.originalSize, sp = this.originalPosition; 11769 return { top: sp.top + dy, height: cs.height - dy }; 11770 }, 11771 s: function( event, dx, dy ) { 11772 return { height: this.originalSize.height + dy }; 11773 }, 11774 se: function( event, dx, dy ) { 11775 return $.extend( this._change.s.apply( this, arguments ), 11776 this._change.e.apply( this, [ event, dx, dy ] ) ); 11777 }, 11778 sw: function( event, dx, dy ) { 11779 return $.extend( this._change.s.apply( this, arguments ), 11780 this._change.w.apply( this, [ event, dx, dy ] ) ); 11781 }, 11782 ne: function( event, dx, dy ) { 11783 return $.extend( this._change.n.apply( this, arguments ), 11784 this._change.e.apply( this, [ event, dx, dy ] ) ); 11785 }, 11786 nw: function( event, dx, dy ) { 11787 return $.extend( this._change.n.apply( this, arguments ), 11788 this._change.w.apply( this, [ event, dx, dy ] ) ); 11789 } 11790 }, 11791 11792 _propagate: function( n, event ) { 11793 $.ui.plugin.call( this, n, [ event, this.ui() ] ); 11794 if ( n !== "resize" ) { 11795 this._trigger( n, event, this.ui() ); 11796 } 11797 }, 11798 11799 plugins: {}, 11800 11801 ui: function() { 11802 return { 11803 originalElement: this.originalElement, 11804 element: this.element, 11805 helper: this.helper, 11806 position: this.position, 11807 size: this.size, 11808 originalSize: this.originalSize, 11809 originalPosition: this.originalPosition 11810 }; 11811 } 11812 11813} ); 11814 11815/* 11816 * Resizable Extensions 11817 */ 11818 11819$.ui.plugin.add( "resizable", "animate", { 11820 11821 stop: function( event ) { 11822 var that = $( this ).resizable( "instance" ), 11823 o = that.options, 11824 pr = that._proportionallyResizeElements, 11825 ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ), 11826 soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height, 11827 soffsetw = ista ? 0 : that.sizeDiff.width, 11828 style = { 11829 width: ( that.size.width - soffsetw ), 11830 height: ( that.size.height - soffseth ) 11831 }, 11832 left = ( parseFloat( that.element.css( "left" ) ) + 11833 ( that.position.left - that.originalPosition.left ) ) || null, 11834 top = ( parseFloat( that.element.css( "top" ) ) + 11835 ( that.position.top - that.originalPosition.top ) ) || null; 11836 11837 that.element.animate( 11838 $.extend( style, top && left ? { top: top, left: left } : {} ), { 11839 duration: o.animateDuration, 11840 easing: o.animateEasing, 11841 step: function() { 11842 11843 var data = { 11844 width: parseFloat( that.element.css( "width" ) ), 11845 height: parseFloat( that.element.css( "height" ) ), 11846 top: parseFloat( that.element.css( "top" ) ), 11847 left: parseFloat( that.element.css( "left" ) ) 11848 }; 11849 11850 if ( pr && pr.length ) { 11851 $( pr[ 0 ] ).css( { width: data.width, height: data.height } ); 11852 } 11853 11854 // Propagating resize, and updating values for each animation step 11855 that._updateCache( data ); 11856 that._propagate( "resize", event ); 11857 11858 } 11859 } 11860 ); 11861 } 11862 11863} ); 11864 11865$.ui.plugin.add( "resizable", "containment", { 11866 11867 start: function() { 11868 var element, p, co, ch, cw, width, height, 11869 that = $( this ).resizable( "instance" ), 11870 o = that.options, 11871 el = that.element, 11872 oc = o.containment, 11873 ce = ( oc instanceof $ ) ? 11874 oc.get( 0 ) : 11875 ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc; 11876 11877 if ( !ce ) { 11878 return; 11879 } 11880 11881 that.containerElement = $( ce ); 11882 11883 if ( /document/.test( oc ) || oc === document ) { 11884 that.containerOffset = { 11885 left: 0, 11886 top: 0 11887 }; 11888 that.containerPosition = { 11889 left: 0, 11890 top: 0 11891 }; 11892 11893 that.parentData = { 11894 element: $( document ), 11895 left: 0, 11896 top: 0, 11897 width: $( document ).width(), 11898 height: $( document ).height() || document.body.parentNode.scrollHeight 11899 }; 11900 } else { 11901 element = $( ce ); 11902 p = []; 11903 $( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) { 11904 p[ i ] = that._num( element.css( "padding" + name ) ); 11905 } ); 11906 11907 that.containerOffset = element.offset(); 11908 that.containerPosition = element.position(); 11909 that.containerSize = { 11910 height: ( element.innerHeight() - p[ 3 ] ), 11911 width: ( element.innerWidth() - p[ 1 ] ) 11912 }; 11913 11914 co = that.containerOffset; 11915 ch = that.containerSize.height; 11916 cw = that.containerSize.width; 11917 width = ( that._hasScroll( ce, "left" ) ? ce.scrollWidth : cw ); 11918 height = ( that._hasScroll( ce ) ? ce.scrollHeight : ch ); 11919 11920 that.parentData = { 11921 element: ce, 11922 left: co.left, 11923 top: co.top, 11924 width: width, 11925 height: height 11926 }; 11927 } 11928 }, 11929 11930 resize: function( event ) { 11931 var woset, hoset, isParent, isOffsetRelative, 11932 that = $( this ).resizable( "instance" ), 11933 o = that.options, 11934 co = that.containerOffset, 11935 cp = that.position, 11936 pRatio = that._aspectRatio || event.shiftKey, 11937 cop = { 11938 top: 0, 11939 left: 0 11940 }, 11941 ce = that.containerElement, 11942 continueResize = true; 11943 11944 if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) { 11945 cop = co; 11946 } 11947 11948 if ( cp.left < ( that._helper ? co.left : 0 ) ) { 11949 that.size.width = that.size.width + 11950 ( that._helper ? 11951 ( that.position.left - co.left ) : 11952 ( that.position.left - cop.left ) ); 11953 11954 if ( pRatio ) { 11955 that.size.height = that.size.width / that.aspectRatio; 11956 continueResize = false; 11957 } 11958 that.position.left = o.helper ? co.left : 0; 11959 } 11960 11961 if ( cp.top < ( that._helper ? co.top : 0 ) ) { 11962 that.size.height = that.size.height + 11963 ( that._helper ? 11964 ( that.position.top - co.top ) : 11965 that.position.top ); 11966 11967 if ( pRatio ) { 11968 that.size.width = that.size.height * that.aspectRatio; 11969 continueResize = false; 11970 } 11971 that.position.top = that._helper ? co.top : 0; 11972 } 11973 11974 isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 ); 11975 isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) ); 11976 11977 if ( isParent && isOffsetRelative ) { 11978 that.offset.left = that.parentData.left + that.position.left; 11979 that.offset.top = that.parentData.top + that.position.top; 11980 } else { 11981 that.offset.left = that.element.offset().left; 11982 that.offset.top = that.element.offset().top; 11983 } 11984 11985 woset = Math.abs( that.sizeDiff.width + 11986 ( that._helper ? 11987 that.offset.left - cop.left : 11988 ( that.offset.left - co.left ) ) ); 11989 11990 hoset = Math.abs( that.sizeDiff.height + 11991 ( that._helper ? 11992 that.offset.top - cop.top : 11993 ( that.offset.top - co.top ) ) ); 11994 11995 if ( woset + that.size.width >= that.parentData.width ) { 11996 that.size.width = that.parentData.width - woset; 11997 if ( pRatio ) { 11998 that.size.height = that.size.width / that.aspectRatio; 11999 continueResize = false; 12000 } 12001 } 12002 12003 if ( hoset + that.size.height >= that.parentData.height ) { 12004 that.size.height = that.parentData.height - hoset; 12005 if ( pRatio ) { 12006 that.size.width = that.size.height * that.aspectRatio; 12007 continueResize = false; 12008 } 12009 } 12010 12011 if ( !continueResize ) { 12012 that.position.left = that.prevPosition.left; 12013 that.position.top = that.prevPosition.top; 12014 that.size.width = that.prevSize.width; 12015 that.size.height = that.prevSize.height; 12016 } 12017 }, 12018 12019 stop: function() { 12020 var that = $( this ).resizable( "instance" ), 12021 o = that.options, 12022 co = that.containerOffset, 12023 cop = that.containerPosition, 12024 ce = that.containerElement, 12025 helper = $( that.helper ), 12026 ho = helper.offset(), 12027 w = helper.outerWidth() - that.sizeDiff.width, 12028 h = helper.outerHeight() - that.sizeDiff.height; 12029 12030 if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) { 12031 $( this ).css( { 12032 left: ho.left - cop.left - co.left, 12033 width: w, 12034 height: h 12035 } ); 12036 } 12037 12038 if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) { 12039 $( this ).css( { 12040 left: ho.left - cop.left - co.left, 12041 width: w, 12042 height: h 12043 } ); 12044 } 12045 } 12046} ); 12047 12048$.ui.plugin.add( "resizable", "alsoResize", { 12049 12050 start: function() { 12051 var that = $( this ).resizable( "instance" ), 12052 o = that.options; 12053 12054 $( o.alsoResize ).each( function() { 12055 var el = $( this ); 12056 el.data( "ui-resizable-alsoresize", { 12057 width: parseFloat( el.css( "width" ) ), height: parseFloat( el.css( "height" ) ), 12058 left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) ) 12059 } ); 12060 } ); 12061 }, 12062 12063 resize: function( event, ui ) { 12064 var that = $( this ).resizable( "instance" ), 12065 o = that.options, 12066 os = that.originalSize, 12067 op = that.originalPosition, 12068 delta = { 12069 height: ( that.size.height - os.height ) || 0, 12070 width: ( that.size.width - os.width ) || 0, 12071 top: ( that.position.top - op.top ) || 0, 12072 left: ( that.position.left - op.left ) || 0 12073 }; 12074 12075 $( o.alsoResize ).each( function() { 12076 var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {}, 12077 css = el.parents( ui.originalElement[ 0 ] ).length ? 12078 [ "width", "height" ] : 12079 [ "width", "height", "top", "left" ]; 12080 12081 $.each( css, function( i, prop ) { 12082 var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 ); 12083 if ( sum && sum >= 0 ) { 12084 style[ prop ] = sum || null; 12085 } 12086 } ); 12087 12088 el.css( style ); 12089 } ); 12090 }, 12091 12092 stop: function() { 12093 $( this ).removeData( "ui-resizable-alsoresize" ); 12094 } 12095} ); 12096 12097$.ui.plugin.add( "resizable", "ghost", { 12098 12099 start: function() { 12100 12101 var that = $( this ).resizable( "instance" ), cs = that.size; 12102 12103 that.ghost = that.originalElement.clone(); 12104 that.ghost.css( { 12105 opacity: 0.25, 12106 display: "block", 12107 position: "relative", 12108 height: cs.height, 12109 width: cs.width, 12110 margin: 0, 12111 left: 0, 12112 top: 0 12113 } ); 12114 12115 that._addClass( that.ghost, "ui-resizable-ghost" ); 12116 12117 // DEPRECATED 12118 // TODO: remove after 1.12 12119 if ( $.uiBackCompat !== false && typeof that.options.ghost === "string" ) { 12120 12121 // Ghost option 12122 that.ghost.addClass( this.options.ghost ); 12123 } 12124 12125 that.ghost.appendTo( that.helper ); 12126 12127 }, 12128 12129 resize: function() { 12130 var that = $( this ).resizable( "instance" ); 12131 if ( that.ghost ) { 12132 that.ghost.css( { 12133 position: "relative", 12134 height: that.size.height, 12135 width: that.size.width 12136 } ); 12137 } 12138 }, 12139 12140 stop: function() { 12141 var that = $( this ).resizable( "instance" ); 12142 if ( that.ghost && that.helper ) { 12143 that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) ); 12144 } 12145 } 12146 12147} ); 12148 12149$.ui.plugin.add( "resizable", "grid", { 12150 12151 resize: function() { 12152 var outerDimensions, 12153 that = $( this ).resizable( "instance" ), 12154 o = that.options, 12155 cs = that.size, 12156 os = that.originalSize, 12157 op = that.originalPosition, 12158 a = that.axis, 12159 grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid, 12160 gridX = ( grid[ 0 ] || 1 ), 12161 gridY = ( grid[ 1 ] || 1 ), 12162 ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX, 12163 oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY, 12164 newWidth = os.width + ox, 12165 newHeight = os.height + oy, 12166 isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ), 12167 isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ), 12168 isMinWidth = o.minWidth && ( o.minWidth > newWidth ), 12169 isMinHeight = o.minHeight && ( o.minHeight > newHeight ); 12170 12171 o.grid = grid; 12172 12173 if ( isMinWidth ) { 12174 newWidth += gridX; 12175 } 12176 if ( isMinHeight ) { 12177 newHeight += gridY; 12178 } 12179 if ( isMaxWidth ) { 12180 newWidth -= gridX; 12181 } 12182 if ( isMaxHeight ) { 12183 newHeight -= gridY; 12184 } 12185 12186 if ( /^(se|s|e)$/.test( a ) ) { 12187 that.size.width = newWidth; 12188 that.size.height = newHeight; 12189 } else if ( /^(ne)$/.test( a ) ) { 12190 that.size.width = newWidth; 12191 that.size.height = newHeight; 12192 that.position.top = op.top - oy; 12193 } else if ( /^(sw)$/.test( a ) ) { 12194 that.size.width = newWidth; 12195 that.size.height = newHeight; 12196 that.position.left = op.left - ox; 12197 } else { 12198 if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) { 12199 outerDimensions = that._getPaddingPlusBorderDimensions( this ); 12200 } 12201 12202 if ( newHeight - gridY > 0 ) { 12203 that.size.height = newHeight; 12204 that.position.top = op.top - oy; 12205 } else { 12206 newHeight = gridY - outerDimensions.height; 12207 that.size.height = newHeight; 12208 that.position.top = op.top + os.height - newHeight; 12209 } 12210 if ( newWidth - gridX > 0 ) { 12211 that.size.width = newWidth; 12212 that.position.left = op.left - ox; 12213 } else { 12214 newWidth = gridX - outerDimensions.width; 12215 that.size.width = newWidth; 12216 that.position.left = op.left + os.width - newWidth; 12217 } 12218 } 12219 } 12220 12221} ); 12222 12223var widgetsResizable = $.ui.resizable; 12224 12225 12226/*! 12227 * jQuery UI Dialog 1.13.3 12228 * https://jqueryui.com 12229 * 12230 * Copyright OpenJS Foundation and other contributors 12231 * Released under the MIT license. 12232 * https://jquery.org/license 12233 */ 12234 12235//>>label: Dialog 12236//>>group: Widgets 12237//>>description: Displays customizable dialog windows. 12238//>>docs: https://api.jqueryui.com/dialog/ 12239//>>demos: https://jqueryui.com/dialog/ 12240//>>css.structure: ../../themes/base/core.css 12241//>>css.structure: ../../themes/base/dialog.css 12242//>>css.theme: ../../themes/base/theme.css 12243 12244 12245$.widget( "ui.dialog", { 12246 version: "1.13.3", 12247 options: { 12248 appendTo: "body", 12249 autoOpen: true, 12250 buttons: [], 12251 classes: { 12252 "ui-dialog": "ui-corner-all", 12253 "ui-dialog-titlebar": "ui-corner-all" 12254 }, 12255 closeOnEscape: true, 12256 closeText: "Close", 12257 draggable: true, 12258 hide: null, 12259 height: "auto", 12260 maxHeight: null, 12261 maxWidth: null, 12262 minHeight: 150, 12263 minWidth: 150, 12264 modal: false, 12265 position: { 12266 my: "center", 12267 at: "center", 12268 of: window, 12269 collision: "fit", 12270 12271 // Ensure the titlebar is always visible 12272 using: function( pos ) { 12273 var topOffset = $( this ).css( pos ).offset().top; 12274 if ( topOffset < 0 ) { 12275 $( this ).css( "top", pos.top - topOffset ); 12276 } 12277 } 12278 }, 12279 resizable: true, 12280 show: null, 12281 title: null, 12282 width: 300, 12283 12284 // Callbacks 12285 beforeClose: null, 12286 close: null, 12287 drag: null, 12288 dragStart: null, 12289 dragStop: null, 12290 focus: null, 12291 open: null, 12292 resize: null, 12293 resizeStart: null, 12294 resizeStop: null 12295 }, 12296 12297 sizeRelatedOptions: { 12298 buttons: true, 12299 height: true, 12300 maxHeight: true, 12301 maxWidth: true, 12302 minHeight: true, 12303 minWidth: true, 12304 width: true 12305 }, 12306 12307 resizableRelatedOptions: { 12308 maxHeight: true, 12309 maxWidth: true, 12310 minHeight: true, 12311 minWidth: true 12312 }, 12313 12314 _create: function() { 12315 this.originalCss = { 12316 display: this.element[ 0 ].style.display, 12317 width: this.element[ 0 ].style.width, 12318 minHeight: this.element[ 0 ].style.minHeight, 12319 maxHeight: this.element[ 0 ].style.maxHeight, 12320 height: this.element[ 0 ].style.height 12321 }; 12322 this.originalPosition = { 12323 parent: this.element.parent(), 12324 index: this.element.parent().children().index( this.element ) 12325 }; 12326 this.originalTitle = this.element.attr( "title" ); 12327 if ( this.options.title == null && this.originalTitle != null ) { 12328 this.options.title = this.originalTitle; 12329 } 12330 12331 // Dialogs can't be disabled 12332 if ( this.options.disabled ) { 12333 this.options.disabled = false; 12334 } 12335 12336 this._createWrapper(); 12337 12338 this.element 12339 .show() 12340 .removeAttr( "title" ) 12341 .appendTo( this.uiDialog ); 12342 12343 this._addClass( "ui-dialog-content", "ui-widget-content" ); 12344 12345 this._createTitlebar(); 12346 this._createButtonPane(); 12347 12348 if ( this.options.draggable && $.fn.draggable ) { 12349 this._makeDraggable(); 12350 } 12351 if ( this.options.resizable && $.fn.resizable ) { 12352 this._makeResizable(); 12353 } 12354 12355 this._isOpen = false; 12356 12357 this._trackFocus(); 12358 }, 12359 12360 _init: function() { 12361 if ( this.options.autoOpen ) { 12362 this.open(); 12363 } 12364 }, 12365 12366 _appendTo: function() { 12367 var element = this.options.appendTo; 12368 if ( element && ( element.jquery || element.nodeType ) ) { 12369 return $( element ); 12370 } 12371 return this.document.find( element || "body" ).eq( 0 ); 12372 }, 12373 12374 _destroy: function() { 12375 var next, 12376 originalPosition = this.originalPosition; 12377 12378 this._untrackInstance(); 12379 this._destroyOverlay(); 12380 12381 this.element 12382 .removeUniqueId() 12383 .css( this.originalCss ) 12384 12385 // Without detaching first, the following becomes really slow 12386 .detach(); 12387 12388 this.uiDialog.remove(); 12389 12390 if ( this.originalTitle ) { 12391 this.element.attr( "title", this.originalTitle ); 12392 } 12393 12394 next = originalPosition.parent.children().eq( originalPosition.index ); 12395 12396 // Don't try to place the dialog next to itself (#8613) 12397 if ( next.length && next[ 0 ] !== this.element[ 0 ] ) { 12398 next.before( this.element ); 12399 } else { 12400 originalPosition.parent.append( this.element ); 12401 } 12402 }, 12403 12404 widget: function() { 12405 return this.uiDialog; 12406 }, 12407 12408 disable: $.noop, 12409 enable: $.noop, 12410 12411 close: function( event ) { 12412 var that = this; 12413 12414 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) { 12415 return; 12416 } 12417 12418 this._isOpen = false; 12419 this._focusedElement = null; 12420 this._destroyOverlay(); 12421 this._untrackInstance(); 12422 12423 if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) { 12424 12425 // Hiding a focused element doesn't trigger blur in WebKit 12426 // so in case we have nothing to focus on, explicitly blur the active element 12427 // https://bugs.webkit.org/show_bug.cgi?id=47182 12428 $.ui.safeBlur( $.ui.safeActiveElement( this.document[ 0 ] ) ); 12429 } 12430 12431 this._hide( this.uiDialog, this.options.hide, function() { 12432 that._trigger( "close", event ); 12433 } ); 12434 }, 12435 12436 isOpen: function() { 12437 return this._isOpen; 12438 }, 12439 12440 moveToTop: function() { 12441 this._moveToTop(); 12442 }, 12443 12444 _moveToTop: function( event, silent ) { 12445 var moved = false, 12446 zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() { 12447 return +$( this ).css( "z-index" ); 12448 } ).get(), 12449 zIndexMax = Math.max.apply( null, zIndices ); 12450 12451 if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) { 12452 this.uiDialog.css( "z-index", zIndexMax + 1 ); 12453 moved = true; 12454 } 12455 12456 if ( moved && !silent ) { 12457 this._trigger( "focus", event ); 12458 } 12459 return moved; 12460 }, 12461 12462 open: function() { 12463 var that = this; 12464 if ( this._isOpen ) { 12465 if ( this._moveToTop() ) { 12466 this._focusTabbable(); 12467 } 12468 return; 12469 } 12470 12471 this._isOpen = true; 12472 this.opener = $( $.ui.safeActiveElement( this.document[ 0 ] ) ); 12473 12474 this._size(); 12475 this._position(); 12476 this._createOverlay(); 12477 this._moveToTop( null, true ); 12478 12479 // Ensure the overlay is moved to the top with the dialog, but only when 12480 // opening. The overlay shouldn't move after the dialog is open so that 12481 // modeless dialogs opened after the modal dialog stack properly. 12482 if ( this.overlay ) { 12483 this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 ); 12484 } 12485 12486 this._show( this.uiDialog, this.options.show, function() { 12487 that._focusTabbable(); 12488 that._trigger( "focus" ); 12489 } ); 12490 12491 // Track the dialog immediately upon opening in case a focus event 12492 // somehow occurs outside of the dialog before an element inside the 12493 // dialog is focused (#10152) 12494 this._makeFocusTarget(); 12495 12496 this._trigger( "open" ); 12497 }, 12498 12499 _focusTabbable: function() { 12500 12501 // Set focus to the first match: 12502 // 1. An element that was focused previously 12503 // 2. First element inside the dialog matching [autofocus] 12504 // 3. Tabbable element inside the content element 12505 // 4. Tabbable element inside the buttonpane 12506 // 5. The close button 12507 // 6. The dialog itself 12508 var hasFocus = this._focusedElement; 12509 if ( !hasFocus ) { 12510 hasFocus = this.element.find( "[autofocus]" ); 12511 } 12512 if ( !hasFocus.length ) { 12513 hasFocus = this.element.find( ":tabbable" ); 12514 } 12515 if ( !hasFocus.length ) { 12516 hasFocus = this.uiDialogButtonPane.find( ":tabbable" ); 12517 } 12518 if ( !hasFocus.length ) { 12519 hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" ); 12520 } 12521 if ( !hasFocus.length ) { 12522 hasFocus = this.uiDialog; 12523 } 12524 hasFocus.eq( 0 ).trigger( "focus" ); 12525 }, 12526 12527 _restoreTabbableFocus: function() { 12528 var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ), 12529 isActive = this.uiDialog[ 0 ] === activeElement || 12530 $.contains( this.uiDialog[ 0 ], activeElement ); 12531 if ( !isActive ) { 12532 this._focusTabbable(); 12533 } 12534 }, 12535 12536 _keepFocus: function( event ) { 12537 event.preventDefault(); 12538 this._restoreTabbableFocus(); 12539 12540 // support: IE 12541 // IE <= 8 doesn't prevent moving focus even with event.preventDefault() 12542 // so we check again later 12543 this._delay( this._restoreTabbableFocus ); 12544 }, 12545 12546 _createWrapper: function() { 12547 this.uiDialog = $( "<div>" ) 12548 .hide() 12549 .attr( { 12550 12551 // Setting tabIndex makes the div focusable 12552 tabIndex: -1, 12553 role: "dialog" 12554 } ) 12555 .appendTo( this._appendTo() ); 12556 12557 this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" ); 12558 this._on( this.uiDialog, { 12559 keydown: function( event ) { 12560 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && 12561 event.keyCode === $.ui.keyCode.ESCAPE ) { 12562 event.preventDefault(); 12563 this.close( event ); 12564 return; 12565 } 12566 12567 // Prevent tabbing out of dialogs 12568 if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) { 12569 return; 12570 } 12571 var tabbables = this.uiDialog.find( ":tabbable" ), 12572 first = tabbables.first(), 12573 last = tabbables.last(); 12574 12575 if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) && 12576 !event.shiftKey ) { 12577 this._delay( function() { 12578 first.trigger( "focus" ); 12579 } ); 12580 event.preventDefault(); 12581 } else if ( ( event.target === first[ 0 ] || 12582 event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) { 12583 this._delay( function() { 12584 last.trigger( "focus" ); 12585 } ); 12586 event.preventDefault(); 12587 } 12588 }, 12589 mousedown: function( event ) { 12590 if ( this._moveToTop( event ) ) { 12591 this._focusTabbable(); 12592 } 12593 } 12594 } ); 12595 12596 // We assume that any existing aria-describedby attribute means 12597 // that the dialog content is marked up properly 12598 // otherwise we brute force the content as the description 12599 if ( !this.element.find( "[aria-describedby]" ).length ) { 12600 this.uiDialog.attr( { 12601 "aria-describedby": this.element.uniqueId().attr( "id" ) 12602 } ); 12603 } 12604 }, 12605 12606 _createTitlebar: function() { 12607 var uiDialogTitle; 12608 12609 this.uiDialogTitlebar = $( "<div>" ); 12610 this._addClass( this.uiDialogTitlebar, 12611 "ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" ); 12612 this._on( this.uiDialogTitlebar, { 12613 mousedown: function( event ) { 12614 12615 // Don't prevent click on close button (#8838) 12616 // Focusing a dialog that is partially scrolled out of view 12617 // causes the browser to scroll it into view, preventing the click event 12618 if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) { 12619 12620 // Dialog isn't getting focus when dragging (#8063) 12621 this.uiDialog.trigger( "focus" ); 12622 } 12623 } 12624 } ); 12625 12626 // Support: IE 12627 // Use type="button" to prevent enter keypresses in textboxes from closing the 12628 // dialog in IE (#9312) 12629 this.uiDialogTitlebarClose = $( "<button type='button'></button>" ) 12630 .button( { 12631 label: $( "<a>" ).text( this.options.closeText ).html(), 12632 icon: "ui-icon-closethick", 12633 showLabel: false 12634 } ) 12635 .appendTo( this.uiDialogTitlebar ); 12636 12637 this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" ); 12638 this._on( this.uiDialogTitlebarClose, { 12639 click: function( event ) { 12640 event.preventDefault(); 12641 this.close( event ); 12642 } 12643 } ); 12644 12645 uiDialogTitle = $( "<span>" ).uniqueId().prependTo( this.uiDialogTitlebar ); 12646 this._addClass( uiDialogTitle, "ui-dialog-title" ); 12647 this._title( uiDialogTitle ); 12648 12649 this.uiDialogTitlebar.prependTo( this.uiDialog ); 12650 12651 this.uiDialog.attr( { 12652 "aria-labelledby": uiDialogTitle.attr( "id" ) 12653 } ); 12654 }, 12655 12656 _title: function( title ) { 12657 if ( this.options.title ) { 12658 title.text( this.options.title ); 12659 } else { 12660 title.html( " " ); 12661 } 12662 }, 12663 12664 _createButtonPane: function() { 12665 this.uiDialogButtonPane = $( "<div>" ); 12666 this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane", 12667 "ui-widget-content ui-helper-clearfix" ); 12668 12669 this.uiButtonSet = $( "<div>" ) 12670 .appendTo( this.uiDialogButtonPane ); 12671 this._addClass( this.uiButtonSet, "ui-dialog-buttonset" ); 12672 12673 this._createButtons(); 12674 }, 12675 12676 _createButtons: function() { 12677 var that = this, 12678 buttons = this.options.buttons; 12679 12680 // If we already have a button pane, remove it 12681 this.uiDialogButtonPane.remove(); 12682 this.uiButtonSet.empty(); 12683 12684 if ( $.isEmptyObject( buttons ) || ( Array.isArray( buttons ) && !buttons.length ) ) { 12685 this._removeClass( this.uiDialog, "ui-dialog-buttons" ); 12686 return; 12687 } 12688 12689 $.each( buttons, function( name, props ) { 12690 var click, buttonOptions; 12691 props = typeof props === "function" ? 12692 { click: props, text: name } : 12693 props; 12694 12695 // Default to a non-submitting button 12696 props = $.extend( { type: "button" }, props ); 12697 12698 // Change the context for the click callback to be the main element 12699 click = props.click; 12700 buttonOptions = { 12701 icon: props.icon, 12702 iconPosition: props.iconPosition, 12703 showLabel: props.showLabel, 12704 12705 // Deprecated options 12706 icons: props.icons, 12707 text: props.text 12708 }; 12709 12710 delete props.click; 12711 delete props.icon; 12712 delete props.iconPosition; 12713 delete props.showLabel; 12714 12715 // Deprecated options 12716 delete props.icons; 12717 if ( typeof props.text === "boolean" ) { 12718 delete props.text; 12719 } 12720 12721 $( "<button></button>", props ) 12722 .button( buttonOptions ) 12723 .appendTo( that.uiButtonSet ) 12724 .on( "click", function() { 12725 click.apply( that.element[ 0 ], arguments ); 12726 } ); 12727 } ); 12728 this._addClass( this.uiDialog, "ui-dialog-buttons" ); 12729 this.uiDialogButtonPane.appendTo( this.uiDialog ); 12730 }, 12731 12732 _makeDraggable: function() { 12733 var that = this, 12734 options = this.options; 12735 12736 function filteredUi( ui ) { 12737 return { 12738 position: ui.position, 12739 offset: ui.offset 12740 }; 12741 } 12742 12743 this.uiDialog.draggable( { 12744 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", 12745 handle: ".ui-dialog-titlebar", 12746 containment: "document", 12747 start: function( event, ui ) { 12748 that._addClass( $( this ), "ui-dialog-dragging" ); 12749 that._blockFrames(); 12750 that._trigger( "dragStart", event, filteredUi( ui ) ); 12751 }, 12752 drag: function( event, ui ) { 12753 that._trigger( "drag", event, filteredUi( ui ) ); 12754 }, 12755 stop: function( event, ui ) { 12756 var left = ui.offset.left - that.document.scrollLeft(), 12757 top = ui.offset.top - that.document.scrollTop(); 12758 12759 options.position = { 12760 my: "left top", 12761 at: "left" + ( left >= 0 ? "+" : "" ) + left + " " + 12762 "top" + ( top >= 0 ? "+" : "" ) + top, 12763 of: that.window 12764 }; 12765 that._removeClass( $( this ), "ui-dialog-dragging" ); 12766 that._unblockFrames(); 12767 that._trigger( "dragStop", event, filteredUi( ui ) ); 12768 } 12769 } ); 12770 }, 12771 12772 _makeResizable: function() { 12773 var that = this, 12774 options = this.options, 12775 handles = options.resizable, 12776 12777 // .ui-resizable has position: relative defined in the stylesheet 12778 // but dialogs have to use absolute or fixed positioning 12779 position = this.uiDialog.css( "position" ), 12780 resizeHandles = typeof handles === "string" ? 12781 handles : 12782 "n,e,s,w,se,sw,ne,nw"; 12783 12784 function filteredUi( ui ) { 12785 return { 12786 originalPosition: ui.originalPosition, 12787 originalSize: ui.originalSize, 12788 position: ui.position, 12789 size: ui.size 12790 }; 12791 } 12792 12793 this.uiDialog.resizable( { 12794 cancel: ".ui-dialog-content", 12795 containment: "document", 12796 alsoResize: this.element, 12797 maxWidth: options.maxWidth, 12798 maxHeight: options.maxHeight, 12799 minWidth: options.minWidth, 12800 minHeight: this._minHeight(), 12801 handles: resizeHandles, 12802 start: function( event, ui ) { 12803 that._addClass( $( this ), "ui-dialog-resizing" ); 12804 that._blockFrames(); 12805 that._trigger( "resizeStart", event, filteredUi( ui ) ); 12806 }, 12807 resize: function( event, ui ) { 12808 that._trigger( "resize", event, filteredUi( ui ) ); 12809 }, 12810 stop: function( event, ui ) { 12811 var offset = that.uiDialog.offset(), 12812 left = offset.left - that.document.scrollLeft(), 12813 top = offset.top - that.document.scrollTop(); 12814 12815 options.height = that.uiDialog.height(); 12816 options.width = that.uiDialog.width(); 12817 options.position = { 12818 my: "left top", 12819 at: "left" + ( left >= 0 ? "+" : "" ) + left + " " + 12820 "top" + ( top >= 0 ? "+" : "" ) + top, 12821 of: that.window 12822 }; 12823 that._removeClass( $( this ), "ui-dialog-resizing" ); 12824 that._unblockFrames(); 12825 that._trigger( "resizeStop", event, filteredUi( ui ) ); 12826 } 12827 } ) 12828 .css( "position", position ); 12829 }, 12830 12831 _trackFocus: function() { 12832 this._on( this.widget(), { 12833 focusin: function( event ) { 12834 this._makeFocusTarget(); 12835 this._focusedElement = $( event.target ); 12836 } 12837 } ); 12838 }, 12839 12840 _makeFocusTarget: function() { 12841 this._untrackInstance(); 12842 this._trackingInstances().unshift( this ); 12843 }, 12844 12845 _untrackInstance: function() { 12846 var instances = this._trackingInstances(), 12847 exists = $.inArray( this, instances ); 12848 if ( exists !== -1 ) { 12849 instances.splice( exists, 1 ); 12850 } 12851 }, 12852 12853 _trackingInstances: function() { 12854 var instances = this.document.data( "ui-dialog-instances" ); 12855 if ( !instances ) { 12856 instances = []; 12857 this.document.data( "ui-dialog-instances", instances ); 12858 } 12859 return instances; 12860 }, 12861 12862 _minHeight: function() { 12863 var options = this.options; 12864 12865 return options.height === "auto" ? 12866 options.minHeight : 12867 Math.min( options.minHeight, options.height ); 12868 }, 12869 12870 _position: function() { 12871 12872 // Need to show the dialog to get the actual offset in the position plugin 12873 var isVisible = this.uiDialog.is( ":visible" ); 12874 if ( !isVisible ) { 12875 this.uiDialog.show(); 12876 } 12877 this.uiDialog.position( this.options.position ); 12878 if ( !isVisible ) { 12879 this.uiDialog.hide(); 12880 } 12881 }, 12882 12883 _setOptions: function( options ) { 12884 var that = this, 12885 resize = false, 12886 resizableOptions = {}; 12887 12888 $.each( options, function( key, value ) { 12889 that._setOption( key, value ); 12890 12891 if ( key in that.sizeRelatedOptions ) { 12892 resize = true; 12893 } 12894 if ( key in that.resizableRelatedOptions ) { 12895 resizableOptions[ key ] = value; 12896 } 12897 } ); 12898 12899 if ( resize ) { 12900 this._size(); 12901 this._position(); 12902 } 12903 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) { 12904 this.uiDialog.resizable( "option", resizableOptions ); 12905 } 12906 }, 12907 12908 _setOption: function( key, value ) { 12909 var isDraggable, isResizable, 12910 uiDialog = this.uiDialog; 12911 12912 if ( key === "disabled" ) { 12913 return; 12914 } 12915 12916 this._super( key, value ); 12917 12918 if ( key === "appendTo" ) { 12919 this.uiDialog.appendTo( this._appendTo() ); 12920 } 12921 12922 if ( key === "buttons" ) { 12923 this._createButtons(); 12924 } 12925 12926 if ( key === "closeText" ) { 12927 this.uiDialogTitlebarClose.button( { 12928 12929 // Ensure that we always pass a string 12930 label: $( "<a>" ).text( "" + this.options.closeText ).html() 12931 } ); 12932 } 12933 12934 if ( key === "draggable" ) { 12935 isDraggable = uiDialog.is( ":data(ui-draggable)" ); 12936 if ( isDraggable && !value ) { 12937 uiDialog.draggable( "destroy" ); 12938 } 12939 12940 if ( !isDraggable && value ) { 12941 this._makeDraggable(); 12942 } 12943 } 12944 12945 if ( key === "position" ) { 12946 this._position(); 12947 } 12948 12949 if ( key === "resizable" ) { 12950 12951 // currently resizable, becoming non-resizable 12952 isResizable = uiDialog.is( ":data(ui-resizable)" ); 12953 if ( isResizable && !value ) { 12954 uiDialog.resizable( "destroy" ); 12955 } 12956 12957 // Currently resizable, changing handles 12958 if ( isResizable && typeof value === "string" ) { 12959 uiDialog.resizable( "option", "handles", value ); 12960 } 12961 12962 // Currently non-resizable, becoming resizable 12963 if ( !isResizable && value !== false ) { 12964 this._makeResizable(); 12965 } 12966 } 12967 12968 if ( key === "title" ) { 12969 this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) ); 12970 } 12971 }, 12972 12973 _size: function() { 12974 12975 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content 12976 // divs will both have width and height set, so we need to reset them 12977 var nonContentHeight, minContentHeight, maxContentHeight, 12978 options = this.options; 12979 12980 // Reset content sizing 12981 this.element.show().css( { 12982 width: "auto", 12983 minHeight: 0, 12984 maxHeight: "none", 12985 height: 0 12986 } ); 12987 12988 if ( options.minWidth > options.width ) { 12989 options.width = options.minWidth; 12990 } 12991 12992 // Reset wrapper sizing 12993 // determine the height of all the non-content elements 12994 nonContentHeight = this.uiDialog.css( { 12995 height: "auto", 12996 width: options.width 12997 } ) 12998 .outerHeight(); 12999 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); 13000 maxContentHeight = typeof options.maxHeight === "number" ? 13001 Math.max( 0, options.maxHeight - nonContentHeight ) : 13002 "none"; 13003 13004 if ( options.height === "auto" ) { 13005 this.element.css( { 13006 minHeight: minContentHeight, 13007 maxHeight: maxContentHeight, 13008 height: "auto" 13009 } ); 13010 } else { 13011 this.element.height( Math.max( 0, options.height - nonContentHeight ) ); 13012 } 13013 13014 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) { 13015 this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); 13016 } 13017 }, 13018 13019 _blockFrames: function() { 13020 this.iframeBlocks = this.document.find( "iframe" ).map( function() { 13021 var iframe = $( this ); 13022 13023 return $( "<div>" ) 13024 .css( { 13025 position: "absolute", 13026 width: iframe.outerWidth(), 13027 height: iframe.outerHeight() 13028 } ) 13029 .appendTo( iframe.parent() ) 13030 .offset( iframe.offset() )[ 0 ]; 13031 } ); 13032 }, 13033 13034 _unblockFrames: function() { 13035 if ( this.iframeBlocks ) { 13036 this.iframeBlocks.remove(); 13037 delete this.iframeBlocks; 13038 } 13039 }, 13040 13041 _allowInteraction: function( event ) { 13042 if ( $( event.target ).closest( ".ui-dialog" ).length ) { 13043 return true; 13044 } 13045 13046 // TODO: Remove hack when datepicker implements 13047 // the .ui-front logic (#8989) 13048 return !!$( event.target ).closest( ".ui-datepicker" ).length; 13049 }, 13050 13051 _createOverlay: function() { 13052 if ( !this.options.modal ) { 13053 return; 13054 } 13055 13056 var jqMinor = $.fn.jquery.substring( 0, 4 ); 13057 13058 // We use a delay in case the overlay is created from an 13059 // event that we're going to be cancelling (#2804) 13060 var isOpening = true; 13061 this._delay( function() { 13062 isOpening = false; 13063 } ); 13064 13065 if ( !this.document.data( "ui-dialog-overlays" ) ) { 13066 13067 // Prevent use of anchors and inputs 13068 // This doesn't use `_on()` because it is a shared event handler 13069 // across all open modal dialogs. 13070 this.document.on( "focusin.ui-dialog", function( event ) { 13071 if ( isOpening ) { 13072 return; 13073 } 13074 13075 var instance = this._trackingInstances()[ 0 ]; 13076 if ( !instance._allowInteraction( event ) ) { 13077 event.preventDefault(); 13078 instance._focusTabbable(); 13079 13080 // Support: jQuery >=3.4 <3.7 only 13081 // In jQuery 3.4-3.6, there are multiple issues with focus/blur 13082 // trigger chains or when triggering is done on a hidden element 13083 // at least once. 13084 // Trigger focus in a delay in addition if needed to avoid the issues. 13085 // See https://github.com/jquery/jquery/issues/4382 13086 // See https://github.com/jquery/jquery/issues/4856 13087 // See https://github.com/jquery/jquery/issues/4950 13088 if ( jqMinor === "3.4." || jqMinor === "3.5." || jqMinor === "3.6." ) { 13089 instance._delay( instance._restoreTabbableFocus ); 13090 } 13091 } 13092 }.bind( this ) ); 13093 } 13094 13095 this.overlay = $( "<div>" ) 13096 .appendTo( this._appendTo() ); 13097 13098 this._addClass( this.overlay, null, "ui-widget-overlay ui-front" ); 13099 this._on( this.overlay, { 13100 mousedown: "_keepFocus" 13101 } ); 13102 this.document.data( "ui-dialog-overlays", 13103 ( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 ); 13104 }, 13105 13106 _destroyOverlay: function() { 13107 if ( !this.options.modal ) { 13108 return; 13109 } 13110 13111 if ( this.overlay ) { 13112 var overlays = this.document.data( "ui-dialog-overlays" ) - 1; 13113 13114 if ( !overlays ) { 13115 this.document.off( "focusin.ui-dialog" ); 13116 this.document.removeData( "ui-dialog-overlays" ); 13117 } else { 13118 this.document.data( "ui-dialog-overlays", overlays ); 13119 } 13120 13121 this.overlay.remove(); 13122 this.overlay = null; 13123 } 13124 } 13125} ); 13126 13127// DEPRECATED 13128// TODO: switch return back to widget declaration at top of file when this is removed 13129if ( $.uiBackCompat !== false ) { 13130 13131 // Backcompat for dialogClass option 13132 $.widget( "ui.dialog", $.ui.dialog, { 13133 options: { 13134 dialogClass: "" 13135 }, 13136 _createWrapper: function() { 13137 this._super(); 13138 this.uiDialog.addClass( this.options.dialogClass ); 13139 }, 13140 _setOption: function( key, value ) { 13141 if ( key === "dialogClass" ) { 13142 this.uiDialog 13143 .removeClass( this.options.dialogClass ) 13144 .addClass( value ); 13145 } 13146 this._superApply( arguments ); 13147 } 13148 } ); 13149} 13150 13151var widgetsDialog = $.ui.dialog; 13152 13153 13154/*! 13155 * jQuery UI Droppable 1.13.3 13156 * https://jqueryui.com 13157 * 13158 * Copyright OpenJS Foundation and other contributors 13159 * Released under the MIT license. 13160 * https://jquery.org/license 13161 */ 13162 13163//>>label: Droppable 13164//>>group: Interactions 13165//>>description: Enables drop targets for draggable elements. 13166//>>docs: https://api.jqueryui.com/droppable/ 13167//>>demos: https://jqueryui.com/droppable/ 13168 13169 13170$.widget( "ui.droppable", { 13171 version: "1.13.3", 13172 widgetEventPrefix: "drop", 13173 options: { 13174 accept: "*", 13175 addClasses: true, 13176 greedy: false, 13177 scope: "default", 13178 tolerance: "intersect", 13179 13180 // Callbacks 13181 activate: null, 13182 deactivate: null, 13183 drop: null, 13184 out: null, 13185 over: null 13186 }, 13187 _create: function() { 13188 13189 var proportions, 13190 o = this.options, 13191 accept = o.accept; 13192 13193 this.isover = false; 13194 this.isout = true; 13195 13196 this.accept = typeof accept === "function" ? accept : function( d ) { 13197 return d.is( accept ); 13198 }; 13199 13200 this.proportions = function( /* valueToWrite */ ) { 13201 if ( arguments.length ) { 13202 13203 // Store the droppable's proportions 13204 proportions = arguments[ 0 ]; 13205 } else { 13206 13207 // Retrieve or derive the droppable's proportions 13208 return proportions ? 13209 proportions : 13210 proportions = { 13211 width: this.element[ 0 ].offsetWidth, 13212 height: this.element[ 0 ].offsetHeight 13213 }; 13214 } 13215 }; 13216 13217 this._addToManager( o.scope ); 13218 13219 if ( o.addClasses ) { 13220 this._addClass( "ui-droppable" ); 13221 } 13222 13223 }, 13224 13225 _addToManager: function( scope ) { 13226 13227 // Add the reference and positions to the manager 13228 $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || []; 13229 $.ui.ddmanager.droppables[ scope ].push( this ); 13230 }, 13231 13232 _splice: function( drop ) { 13233 var i = 0; 13234 for ( ; i < drop.length; i++ ) { 13235 if ( drop[ i ] === this ) { 13236 drop.splice( i, 1 ); 13237 } 13238 } 13239 }, 13240 13241 _destroy: function() { 13242 var drop = $.ui.ddmanager.droppables[ this.options.scope ]; 13243 13244 this._splice( drop ); 13245 }, 13246 13247 _setOption: function( key, value ) { 13248 13249 if ( key === "accept" ) { 13250 this.accept = typeof value === "function" ? value : function( d ) { 13251 return d.is( value ); 13252 }; 13253 } else if ( key === "scope" ) { 13254 var drop = $.ui.ddmanager.droppables[ this.options.scope ]; 13255 13256 this._splice( drop ); 13257 this._addToManager( value ); 13258 } 13259 13260 this._super( key, value ); 13261 }, 13262 13263 _activate: function( event ) { 13264 var draggable = $.ui.ddmanager.current; 13265 13266 this._addActiveClass(); 13267 if ( draggable ) { 13268 this._trigger( "activate", event, this.ui( draggable ) ); 13269 } 13270 }, 13271 13272 _deactivate: function( event ) { 13273 var draggable = $.ui.ddmanager.current; 13274 13275 this._removeActiveClass(); 13276 if ( draggable ) { 13277 this._trigger( "deactivate", event, this.ui( draggable ) ); 13278 } 13279 }, 13280 13281 _over: function( event ) { 13282 13283 var draggable = $.ui.ddmanager.current; 13284 13285 // Bail if draggable and droppable are same element 13286 if ( !draggable || ( draggable.currentItem || 13287 draggable.element )[ 0 ] === this.element[ 0 ] ) { 13288 return; 13289 } 13290 13291 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || 13292 draggable.element ) ) ) { 13293 this._addHoverClass(); 13294 this._trigger( "over", event, this.ui( draggable ) ); 13295 } 13296 13297 }, 13298 13299 _out: function( event ) { 13300 13301 var draggable = $.ui.ddmanager.current; 13302 13303 // Bail if draggable and droppable are same element 13304 if ( !draggable || ( draggable.currentItem || 13305 draggable.element )[ 0 ] === this.element[ 0 ] ) { 13306 return; 13307 } 13308 13309 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || 13310 draggable.element ) ) ) { 13311 this._removeHoverClass(); 13312 this._trigger( "out", event, this.ui( draggable ) ); 13313 } 13314 13315 }, 13316 13317 _drop: function( event, custom ) { 13318 13319 var draggable = custom || $.ui.ddmanager.current, 13320 childrenIntersection = false; 13321 13322 // Bail if draggable and droppable are same element 13323 if ( !draggable || ( draggable.currentItem || 13324 draggable.element )[ 0 ] === this.element[ 0 ] ) { 13325 return false; 13326 } 13327 13328 this.element 13329 .find( ":data(ui-droppable)" ) 13330 .not( ".ui-draggable-dragging" ) 13331 .each( function() { 13332 var inst = $( this ).droppable( "instance" ); 13333 if ( 13334 inst.options.greedy && 13335 !inst.options.disabled && 13336 inst.options.scope === draggable.options.scope && 13337 inst.accept.call( 13338 inst.element[ 0 ], ( draggable.currentItem || draggable.element ) 13339 ) && 13340 $.ui.intersect( 13341 draggable, 13342 $.extend( inst, { offset: inst.element.offset() } ), 13343 inst.options.tolerance, event 13344 ) 13345 ) { 13346 childrenIntersection = true; 13347 return false; 13348 } 13349 } ); 13350 if ( childrenIntersection ) { 13351 return false; 13352 } 13353 13354 if ( this.accept.call( this.element[ 0 ], 13355 ( draggable.currentItem || draggable.element ) ) ) { 13356 this._removeActiveClass(); 13357 this._removeHoverClass(); 13358 13359 this._trigger( "drop", event, this.ui( draggable ) ); 13360 return this.element; 13361 } 13362 13363 return false; 13364 13365 }, 13366 13367 ui: function( c ) { 13368 return { 13369 draggable: ( c.currentItem || c.element ), 13370 helper: c.helper, 13371 position: c.position, 13372 offset: c.positionAbs 13373 }; 13374 }, 13375 13376 // Extension points just to make backcompat sane and avoid duplicating logic 13377 // TODO: Remove in 1.14 along with call to it below 13378 _addHoverClass: function() { 13379 this._addClass( "ui-droppable-hover" ); 13380 }, 13381 13382 _removeHoverClass: function() { 13383 this._removeClass( "ui-droppable-hover" ); 13384 }, 13385 13386 _addActiveClass: function() { 13387 this._addClass( "ui-droppable-active" ); 13388 }, 13389 13390 _removeActiveClass: function() { 13391 this._removeClass( "ui-droppable-active" ); 13392 } 13393} ); 13394 13395$.ui.intersect = ( function() { 13396 function isOverAxis( x, reference, size ) { 13397 return ( x >= reference ) && ( x < ( reference + size ) ); 13398 } 13399 13400 return function( draggable, droppable, toleranceMode, event ) { 13401 13402 if ( !droppable.offset ) { 13403 return false; 13404 } 13405 13406 var x1 = ( draggable.positionAbs || 13407 draggable.position.absolute ).left + draggable.margins.left, 13408 y1 = ( draggable.positionAbs || 13409 draggable.position.absolute ).top + draggable.margins.top, 13410 x2 = x1 + draggable.helperProportions.width, 13411 y2 = y1 + draggable.helperProportions.height, 13412 l = droppable.offset.left, 13413 t = droppable.offset.top, 13414 r = l + droppable.proportions().width, 13415 b = t + droppable.proportions().height; 13416 13417 switch ( toleranceMode ) { 13418 case "fit": 13419 return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b ); 13420 case "intersect": 13421 return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half 13422 x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half 13423 t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half 13424 y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half 13425 case "pointer": 13426 return isOverAxis( event.pageY, t, droppable.proportions().height ) && 13427 isOverAxis( event.pageX, l, droppable.proportions().width ); 13428 case "touch": 13429 return ( 13430 ( y1 >= t && y1 <= b ) || // Top edge touching 13431 ( y2 >= t && y2 <= b ) || // Bottom edge touching 13432 ( y1 < t && y2 > b ) // Surrounded vertically 13433 ) && ( 13434 ( x1 >= l && x1 <= r ) || // Left edge touching 13435 ( x2 >= l && x2 <= r ) || // Right edge touching 13436 ( x1 < l && x2 > r ) // Surrounded horizontally 13437 ); 13438 default: 13439 return false; 13440 } 13441 }; 13442} )(); 13443 13444/* 13445 This manager tracks offsets of draggables and droppables 13446*/ 13447$.ui.ddmanager = { 13448 current: null, 13449 droppables: { "default": [] }, 13450 prepareOffsets: function( t, event ) { 13451 13452 var i, j, 13453 m = $.ui.ddmanager.droppables[ t.options.scope ] || [], 13454 type = event ? event.type : null, // workaround for #2317 13455 list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack(); 13456 13457 droppablesLoop: for ( i = 0; i < m.length; i++ ) { 13458 13459 // No disabled and non-accepted 13460 if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], 13461 ( t.currentItem || t.element ) ) ) ) { 13462 continue; 13463 } 13464 13465 // Filter out elements in the current dragged item 13466 for ( j = 0; j < list.length; j++ ) { 13467 if ( list[ j ] === m[ i ].element[ 0 ] ) { 13468 m[ i ].proportions().height = 0; 13469 continue droppablesLoop; 13470 } 13471 } 13472 13473 m[ i ].visible = m[ i ].element.css( "display" ) !== "none"; 13474 if ( !m[ i ].visible ) { 13475 continue; 13476 } 13477 13478 // Activate the droppable if used directly from draggables 13479 if ( type === "mousedown" ) { 13480 m[ i ]._activate.call( m[ i ], event ); 13481 } 13482 13483 m[ i ].offset = m[ i ].element.offset(); 13484 m[ i ].proportions( { 13485 width: m[ i ].element[ 0 ].offsetWidth, 13486 height: m[ i ].element[ 0 ].offsetHeight 13487 } ); 13488 13489 } 13490 13491 }, 13492 drop: function( draggable, event ) { 13493 13494 var dropped = false; 13495 13496 // Create a copy of the droppables in case the list changes during the drop (#9116) 13497 $.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() { 13498 13499 if ( !this.options ) { 13500 return; 13501 } 13502 if ( !this.options.disabled && this.visible && 13503 $.ui.intersect( draggable, this, this.options.tolerance, event ) ) { 13504 dropped = this._drop.call( this, event ) || dropped; 13505 } 13506 13507 if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ], 13508 ( draggable.currentItem || draggable.element ) ) ) { 13509 this.isout = true; 13510 this.isover = false; 13511 this._deactivate.call( this, event ); 13512 } 13513 13514 } ); 13515 return dropped; 13516 13517 }, 13518 dragStart: function( draggable, event ) { 13519 13520 // Listen for scrolling so that if the dragging causes scrolling the position of the 13521 // droppables can be recalculated (see #5003) 13522 draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() { 13523 if ( !draggable.options.refreshPositions ) { 13524 $.ui.ddmanager.prepareOffsets( draggable, event ); 13525 } 13526 } ); 13527 }, 13528 drag: function( draggable, event ) { 13529 13530 // If you have a highly dynamic page, you might try this option. It renders positions 13531 // every time you move the mouse. 13532 if ( draggable.options.refreshPositions ) { 13533 $.ui.ddmanager.prepareOffsets( draggable, event ); 13534 } 13535 13536 // Run through all droppables and check their positions based on specific tolerance options 13537 $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() { 13538 13539 if ( this.options.disabled || this.greedyChild || !this.visible ) { 13540 return; 13541 } 13542 13543 var parentInstance, scope, parent, 13544 intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ), 13545 c = !intersects && this.isover ? 13546 "isout" : 13547 ( intersects && !this.isover ? "isover" : null ); 13548 if ( !c ) { 13549 return; 13550 } 13551 13552 if ( this.options.greedy ) { 13553 13554 // find droppable parents with same scope 13555 scope = this.options.scope; 13556 parent = this.element.parents( ":data(ui-droppable)" ).filter( function() { 13557 return $( this ).droppable( "instance" ).options.scope === scope; 13558 } ); 13559 13560 if ( parent.length ) { 13561 parentInstance = $( parent[ 0 ] ).droppable( "instance" ); 13562 parentInstance.greedyChild = ( c === "isover" ); 13563 } 13564 } 13565 13566 // We just moved into a greedy child 13567 if ( parentInstance && c === "isover" ) { 13568 parentInstance.isover = false; 13569 parentInstance.isout = true; 13570 parentInstance._out.call( parentInstance, event ); 13571 } 13572 13573 this[ c ] = true; 13574 this[ c === "isout" ? "isover" : "isout" ] = false; 13575 this[ c === "isover" ? "_over" : "_out" ].call( this, event ); 13576 13577 // We just moved out of a greedy child 13578 if ( parentInstance && c === "isout" ) { 13579 parentInstance.isout = false; 13580 parentInstance.isover = true; 13581 parentInstance._over.call( parentInstance, event ); 13582 } 13583 } ); 13584 13585 }, 13586 dragStop: function( draggable, event ) { 13587 draggable.element.parentsUntil( "body" ).off( "scroll.droppable" ); 13588 13589 // Call prepareOffsets one final time since IE does not fire return scroll events when 13590 // overflow was caused by drag (see #5003) 13591 if ( !draggable.options.refreshPositions ) { 13592 $.ui.ddmanager.prepareOffsets( draggable, event ); 13593 } 13594 } 13595}; 13596 13597// DEPRECATED 13598// TODO: switch return back to widget declaration at top of file when this is removed 13599if ( $.uiBackCompat !== false ) { 13600 13601 // Backcompat for activeClass and hoverClass options 13602 $.widget( "ui.droppable", $.ui.droppable, { 13603 options: { 13604 hoverClass: false, 13605 activeClass: false 13606 }, 13607 _addActiveClass: function() { 13608 this._super(); 13609 if ( this.options.activeClass ) { 13610 this.element.addClass( this.options.activeClass ); 13611 } 13612 }, 13613 _removeActiveClass: function() { 13614 this._super(); 13615 if ( this.options.activeClass ) { 13616 this.element.removeClass( this.options.activeClass ); 13617 } 13618 }, 13619 _addHoverClass: function() { 13620 this._super(); 13621 if ( this.options.hoverClass ) { 13622 this.element.addClass( this.options.hoverClass ); 13623 } 13624 }, 13625 _removeHoverClass: function() { 13626 this._super(); 13627 if ( this.options.hoverClass ) { 13628 this.element.removeClass( this.options.hoverClass ); 13629 } 13630 } 13631 } ); 13632} 13633 13634var widgetsDroppable = $.ui.droppable; 13635 13636 13637/*! 13638 * jQuery UI Progressbar 1.13.3 13639 * https://jqueryui.com 13640 * 13641 * Copyright OpenJS Foundation and other contributors 13642 * Released under the MIT license. 13643 * https://jquery.org/license 13644 */ 13645 13646//>>label: Progressbar 13647//>>group: Widgets 13648/* eslint-disable max-len */ 13649//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators. 13650/* eslint-enable max-len */ 13651//>>docs: https://api.jqueryui.com/progressbar/ 13652//>>demos: https://jqueryui.com/progressbar/ 13653//>>css.structure: ../../themes/base/core.css 13654//>>css.structure: ../../themes/base/progressbar.css 13655//>>css.theme: ../../themes/base/theme.css 13656 13657 13658var widgetsProgressbar = $.widget( "ui.progressbar", { 13659 version: "1.13.3", 13660 options: { 13661 classes: { 13662 "ui-progressbar": "ui-corner-all", 13663 "ui-progressbar-value": "ui-corner-left", 13664 "ui-progressbar-complete": "ui-corner-right" 13665 }, 13666 max: 100, 13667 value: 0, 13668 13669 change: null, 13670 complete: null 13671 }, 13672 13673 min: 0, 13674 13675 _create: function() { 13676 13677 // Constrain initial value 13678 this.oldValue = this.options.value = this._constrainedValue(); 13679 13680 this.element.attr( { 13681 13682 // Only set static values; aria-valuenow and aria-valuemax are 13683 // set inside _refreshValue() 13684 role: "progressbar", 13685 "aria-valuemin": this.min 13686 } ); 13687 this._addClass( "ui-progressbar", "ui-widget ui-widget-content" ); 13688 13689 this.valueDiv = $( "<div>" ).appendTo( this.element ); 13690 this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" ); 13691 this._refreshValue(); 13692 }, 13693 13694 _destroy: function() { 13695 this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" ); 13696 13697 this.valueDiv.remove(); 13698 }, 13699 13700 value: function( newValue ) { 13701 if ( newValue === undefined ) { 13702 return this.options.value; 13703 } 13704 13705 this.options.value = this._constrainedValue( newValue ); 13706 this._refreshValue(); 13707 }, 13708 13709 _constrainedValue: function( newValue ) { 13710 if ( newValue === undefined ) { 13711 newValue = this.options.value; 13712 } 13713 13714 this.indeterminate = newValue === false; 13715 13716 // Sanitize value 13717 if ( typeof newValue !== "number" ) { 13718 newValue = 0; 13719 } 13720 13721 return this.indeterminate ? false : 13722 Math.min( this.options.max, Math.max( this.min, newValue ) ); 13723 }, 13724 13725 _setOptions: function( options ) { 13726 13727 // Ensure "value" option is set after other values (like max) 13728 var value = options.value; 13729 delete options.value; 13730 13731 this._super( options ); 13732 13733 this.options.value = this._constrainedValue( value ); 13734 this._refreshValue(); 13735 }, 13736 13737 _setOption: function( key, value ) { 13738 if ( key === "max" ) { 13739 13740 // Don't allow a max less than min 13741 value = Math.max( this.min, value ); 13742 } 13743 this._super( key, value ); 13744 }, 13745 13746 _setOptionDisabled: function( value ) { 13747 this._super( value ); 13748 13749 this.element.attr( "aria-disabled", value ); 13750 this._toggleClass( null, "ui-state-disabled", !!value ); 13751 }, 13752 13753 _percentage: function() { 13754 return this.indeterminate ? 13755 100 : 13756 100 * ( this.options.value - this.min ) / ( this.options.max - this.min ); 13757 }, 13758 13759 _refreshValue: function() { 13760 var value = this.options.value, 13761 percentage = this._percentage(); 13762 13763 this.valueDiv 13764 .toggle( this.indeterminate || value > this.min ) 13765 .width( percentage.toFixed( 0 ) + "%" ); 13766 13767 this 13768 ._toggleClass( this.valueDiv, "ui-progressbar-complete", null, 13769 value === this.options.max ) 13770 ._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate ); 13771 13772 if ( this.indeterminate ) { 13773 this.element.removeAttr( "aria-valuenow" ); 13774 if ( !this.overlayDiv ) { 13775 this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv ); 13776 this._addClass( this.overlayDiv, "ui-progressbar-overlay" ); 13777 } 13778 } else { 13779 this.element.attr( { 13780 "aria-valuemax": this.options.max, 13781 "aria-valuenow": value 13782 } ); 13783 if ( this.overlayDiv ) { 13784 this.overlayDiv.remove(); 13785 this.overlayDiv = null; 13786 } 13787 } 13788 13789 if ( this.oldValue !== value ) { 13790 this.oldValue = value; 13791 this._trigger( "change" ); 13792 } 13793 if ( value === this.options.max ) { 13794 this._trigger( "complete" ); 13795 } 13796 } 13797} ); 13798 13799 13800/*! 13801 * jQuery UI Selectable 1.13.3 13802 * https://jqueryui.com 13803 * 13804 * Copyright OpenJS Foundation and other contributors 13805 * Released under the MIT license. 13806 * https://jquery.org/license 13807 */ 13808 13809//>>label: Selectable 13810//>>group: Interactions 13811//>>description: Allows groups of elements to be selected with the mouse. 13812//>>docs: https://api.jqueryui.com/selectable/ 13813//>>demos: https://jqueryui.com/selectable/ 13814//>>css.structure: ../../themes/base/selectable.css 13815 13816 13817var widgetsSelectable = $.widget( "ui.selectable", $.ui.mouse, { 13818 version: "1.13.3", 13819 options: { 13820 appendTo: "body", 13821 autoRefresh: true, 13822 distance: 0, 13823 filter: "*", 13824 tolerance: "touch", 13825 13826 // Callbacks 13827 selected: null, 13828 selecting: null, 13829 start: null, 13830 stop: null, 13831 unselected: null, 13832 unselecting: null 13833 }, 13834 _create: function() { 13835 var that = this; 13836 13837 this._addClass( "ui-selectable" ); 13838 13839 this.dragged = false; 13840 13841 // Cache selectee children based on filter 13842 this.refresh = function() { 13843 that.elementPos = $( that.element[ 0 ] ).offset(); 13844 that.selectees = $( that.options.filter, that.element[ 0 ] ); 13845 that._addClass( that.selectees, "ui-selectee" ); 13846 that.selectees.each( function() { 13847 var $this = $( this ), 13848 selecteeOffset = $this.offset(), 13849 pos = { 13850 left: selecteeOffset.left - that.elementPos.left, 13851 top: selecteeOffset.top - that.elementPos.top 13852 }; 13853 $.data( this, "selectable-item", { 13854 element: this, 13855 $element: $this, 13856 left: pos.left, 13857 top: pos.top, 13858 right: pos.left + $this.outerWidth(), 13859 bottom: pos.top + $this.outerHeight(), 13860 startselected: false, 13861 selected: $this.hasClass( "ui-selected" ), 13862 selecting: $this.hasClass( "ui-selecting" ), 13863 unselecting: $this.hasClass( "ui-unselecting" ) 13864 } ); 13865 } ); 13866 }; 13867 this.refresh(); 13868 13869 this._mouseInit(); 13870 13871 this.helper = $( "<div>" ); 13872 this._addClass( this.helper, "ui-selectable-helper" ); 13873 }, 13874 13875 _destroy: function() { 13876 this.selectees.removeData( "selectable-item" ); 13877 this._mouseDestroy(); 13878 }, 13879 13880 _mouseStart: function( event ) { 13881 var that = this, 13882 options = this.options; 13883 13884 this.opos = [ event.pageX, event.pageY ]; 13885 this.elementPos = $( this.element[ 0 ] ).offset(); 13886 13887 if ( this.options.disabled ) { 13888 return; 13889 } 13890 13891 this.selectees = $( options.filter, this.element[ 0 ] ); 13892 13893 this._trigger( "start", event ); 13894 13895 $( options.appendTo ).append( this.helper ); 13896 13897 // position helper (lasso) 13898 this.helper.css( { 13899 "left": event.pageX, 13900 "top": event.pageY, 13901 "width": 0, 13902 "height": 0 13903 } ); 13904 13905 if ( options.autoRefresh ) { 13906 this.refresh(); 13907 } 13908 13909 this.selectees.filter( ".ui-selected" ).each( function() { 13910 var selectee = $.data( this, "selectable-item" ); 13911 selectee.startselected = true; 13912 if ( !event.metaKey && !event.ctrlKey ) { 13913 that._removeClass( selectee.$element, "ui-selected" ); 13914 selectee.selected = false; 13915 that._addClass( selectee.$element, "ui-unselecting" ); 13916 selectee.unselecting = true; 13917 13918 // selectable UNSELECTING callback 13919 that._trigger( "unselecting", event, { 13920 unselecting: selectee.element 13921 } ); 13922 } 13923 } ); 13924 13925 $( event.target ).parents().addBack().each( function() { 13926 var doSelect, 13927 selectee = $.data( this, "selectable-item" ); 13928 if ( selectee ) { 13929 doSelect = ( !event.metaKey && !event.ctrlKey ) || 13930 !selectee.$element.hasClass( "ui-selected" ); 13931 that._removeClass( selectee.$element, doSelect ? "ui-unselecting" : "ui-selected" ) 13932 ._addClass( selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting" ); 13933 selectee.unselecting = !doSelect; 13934 selectee.selecting = doSelect; 13935 selectee.selected = doSelect; 13936 13937 // selectable (UN)SELECTING callback 13938 if ( doSelect ) { 13939 that._trigger( "selecting", event, { 13940 selecting: selectee.element 13941 } ); 13942 } else { 13943 that._trigger( "unselecting", event, { 13944 unselecting: selectee.element 13945 } ); 13946 } 13947 return false; 13948 } 13949 } ); 13950 13951 }, 13952 13953 _mouseDrag: function( event ) { 13954 13955 this.dragged = true; 13956 13957 if ( this.options.disabled ) { 13958 return; 13959 } 13960 13961 var tmp, 13962 that = this, 13963 options = this.options, 13964 x1 = this.opos[ 0 ], 13965 y1 = this.opos[ 1 ], 13966 x2 = event.pageX, 13967 y2 = event.pageY; 13968 13969 if ( x1 > x2 ) { 13970 tmp = x2; x2 = x1; x1 = tmp; 13971 } 13972 if ( y1 > y2 ) { 13973 tmp = y2; y2 = y1; y1 = tmp; 13974 } 13975 this.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } ); 13976 13977 this.selectees.each( function() { 13978 var selectee = $.data( this, "selectable-item" ), 13979 hit = false, 13980 offset = {}; 13981 13982 //prevent helper from being selected if appendTo: selectable 13983 if ( !selectee || selectee.element === that.element[ 0 ] ) { 13984 return; 13985 } 13986 13987 offset.left = selectee.left + that.elementPos.left; 13988 offset.right = selectee.right + that.elementPos.left; 13989 offset.top = selectee.top + that.elementPos.top; 13990 offset.bottom = selectee.bottom + that.elementPos.top; 13991 13992 if ( options.tolerance === "touch" ) { 13993 hit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 || 13994 offset.bottom < y1 ) ); 13995 } else if ( options.tolerance === "fit" ) { 13996 hit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 && 13997 offset.bottom < y2 ); 13998 } 13999 14000 if ( hit ) { 14001 14002 // SELECT 14003 if ( selectee.selected ) { 14004 that._removeClass( selectee.$element, "ui-selected" ); 14005 selectee.selected = false; 14006 } 14007 if ( selectee.unselecting ) { 14008 that._removeClass( selectee.$element, "ui-unselecting" ); 14009 selectee.unselecting = false; 14010 } 14011 if ( !selectee.selecting ) { 14012 that._addClass( selectee.$element, "ui-selecting" ); 14013 selectee.selecting = true; 14014 14015 // selectable SELECTING callback 14016 that._trigger( "selecting", event, { 14017 selecting: selectee.element 14018 } ); 14019 } 14020 } else { 14021 14022 // UNSELECT 14023 if ( selectee.selecting ) { 14024 if ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) { 14025 that._removeClass( selectee.$element, "ui-selecting" ); 14026 selectee.selecting = false; 14027 that._addClass( selectee.$element, "ui-selected" ); 14028 selectee.selected = true; 14029 } else { 14030 that._removeClass( selectee.$element, "ui-selecting" ); 14031 selectee.selecting = false; 14032 if ( selectee.startselected ) { 14033 that._addClass( selectee.$element, "ui-unselecting" ); 14034 selectee.unselecting = true; 14035 } 14036 14037 // selectable UNSELECTING callback 14038 that._trigger( "unselecting", event, { 14039 unselecting: selectee.element 14040 } ); 14041 } 14042 } 14043 if ( selectee.selected ) { 14044 if ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) { 14045 that._removeClass( selectee.$element, "ui-selected" ); 14046 selectee.selected = false; 14047 14048 that._addClass( selectee.$element, "ui-unselecting" ); 14049 selectee.unselecting = true; 14050 14051 // selectable UNSELECTING callback 14052 that._trigger( "unselecting", event, { 14053 unselecting: selectee.element 14054 } ); 14055 } 14056 } 14057 } 14058 } ); 14059 14060 return false; 14061 }, 14062 14063 _mouseStop: function( event ) { 14064 var that = this; 14065 14066 this.dragged = false; 14067 14068 $( ".ui-unselecting", this.element[ 0 ] ).each( function() { 14069 var selectee = $.data( this, "selectable-item" ); 14070 that._removeClass( selectee.$element, "ui-unselecting" ); 14071 selectee.unselecting = false; 14072 selectee.startselected = false; 14073 that._trigger( "unselected", event, { 14074 unselected: selectee.element 14075 } ); 14076 } ); 14077 $( ".ui-selecting", this.element[ 0 ] ).each( function() { 14078 var selectee = $.data( this, "selectable-item" ); 14079 that._removeClass( selectee.$element, "ui-selecting" ) 14080 ._addClass( selectee.$element, "ui-selected" ); 14081 selectee.selecting = false; 14082 selectee.selected = true; 14083 selectee.startselected = true; 14084 that._trigger( "selected", event, { 14085 selected: selectee.element 14086 } ); 14087 } ); 14088 this._trigger( "stop", event ); 14089 14090 this.helper.remove(); 14091 14092 return false; 14093 } 14094 14095} ); 14096 14097 14098/*! 14099 * jQuery UI Selectmenu 1.13.3 14100 * https://jqueryui.com 14101 * 14102 * Copyright OpenJS Foundation and other contributors 14103 * Released under the MIT license. 14104 * https://jquery.org/license 14105 */ 14106 14107//>>label: Selectmenu 14108//>>group: Widgets 14109/* eslint-disable max-len */ 14110//>>description: Duplicates and extends the functionality of a native HTML select element, allowing it to be customizable in behavior and appearance far beyond the limitations of a native select. 14111/* eslint-enable max-len */ 14112//>>docs: https://api.jqueryui.com/selectmenu/ 14113//>>demos: https://jqueryui.com/selectmenu/ 14114//>>css.structure: ../../themes/base/core.css 14115//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css 14116//>>css.theme: ../../themes/base/theme.css 14117 14118 14119var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, { 14120 version: "1.13.3", 14121 defaultElement: "<select>", 14122 options: { 14123 appendTo: null, 14124 classes: { 14125 "ui-selectmenu-button-open": "ui-corner-top", 14126 "ui-selectmenu-button-closed": "ui-corner-all" 14127 }, 14128 disabled: null, 14129 icons: { 14130 button: "ui-icon-triangle-1-s" 14131 }, 14132 position: { 14133 my: "left top", 14134 at: "left bottom", 14135 collision: "none" 14136 }, 14137 width: false, 14138 14139 // Callbacks 14140 change: null, 14141 close: null, 14142 focus: null, 14143 open: null, 14144 select: null 14145 }, 14146 14147 _create: function() { 14148 var selectmenuId = this.element.uniqueId().attr( "id" ); 14149 this.ids = { 14150 element: selectmenuId, 14151 button: selectmenuId + "-button", 14152 menu: selectmenuId + "-menu" 14153 }; 14154 14155 this._drawButton(); 14156 this._drawMenu(); 14157 this._bindFormResetHandler(); 14158 14159 this._rendered = false; 14160 this.menuItems = $(); 14161 }, 14162 14163 _drawButton: function() { 14164 var icon, 14165 that = this, 14166 item = this._parseOption( 14167 this.element.find( "option:selected" ), 14168 this.element[ 0 ].selectedIndex 14169 ); 14170 14171 // Associate existing label with the new button 14172 this.labels = this.element.labels().attr( "for", this.ids.button ); 14173 this._on( this.labels, { 14174 click: function( event ) { 14175 this.button.trigger( "focus" ); 14176 event.preventDefault(); 14177 } 14178 } ); 14179 14180 // Hide original select element 14181 this.element.hide(); 14182 14183 // Create button 14184 this.button = $( "<span>", { 14185 tabindex: this.options.disabled ? -1 : 0, 14186 id: this.ids.button, 14187 role: "combobox", 14188 "aria-expanded": "false", 14189 "aria-autocomplete": "list", 14190 "aria-owns": this.ids.menu, 14191 "aria-haspopup": "true", 14192 title: this.element.attr( "title" ) 14193 } ) 14194 .insertAfter( this.element ); 14195 14196 this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed", 14197 "ui-button ui-widget" ); 14198 14199 icon = $( "<span>" ).appendTo( this.button ); 14200 this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button ); 14201 this.buttonItem = this._renderButtonItem( item ) 14202 .appendTo( this.button ); 14203 14204 if ( this.options.width !== false ) { 14205 this._resizeButton(); 14206 } 14207 14208 this._on( this.button, this._buttonEvents ); 14209 this.button.one( "focusin", function() { 14210 14211 // Delay rendering the menu items until the button receives focus. 14212 // The menu may have already been rendered via a programmatic open. 14213 if ( !that._rendered ) { 14214 that._refreshMenu(); 14215 } 14216 } ); 14217 }, 14218 14219 _drawMenu: function() { 14220 var that = this; 14221 14222 // Create menu 14223 this.menu = $( "<ul>", { 14224 "aria-hidden": "true", 14225 "aria-labelledby": this.ids.button, 14226 id: this.ids.menu 14227 } ); 14228 14229 // Wrap menu 14230 this.menuWrap = $( "<div>" ).append( this.menu ); 14231 this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" ); 14232 this.menuWrap.appendTo( this._appendTo() ); 14233 14234 // Initialize menu widget 14235 this.menuInstance = this.menu 14236 .menu( { 14237 classes: { 14238 "ui-menu": "ui-corner-bottom" 14239 }, 14240 role: "listbox", 14241 select: function( event, ui ) { 14242 event.preventDefault(); 14243 14244 // Support: IE8 14245 // If the item was selected via a click, the text selection 14246 // will be destroyed in IE 14247 that._setSelection(); 14248 14249 that._select( ui.item.data( "ui-selectmenu-item" ), event ); 14250 }, 14251 focus: function( event, ui ) { 14252 var item = ui.item.data( "ui-selectmenu-item" ); 14253 14254 // Prevent inital focus from firing and check if its a newly focused item 14255 if ( that.focusIndex != null && item.index !== that.focusIndex ) { 14256 that._trigger( "focus", event, { item: item } ); 14257 if ( !that.isOpen ) { 14258 that._select( item, event ); 14259 } 14260 } 14261 that.focusIndex = item.index; 14262 14263 that.button.attr( "aria-activedescendant", 14264 that.menuItems.eq( item.index ).attr( "id" ) ); 14265 } 14266 } ) 14267 .menu( "instance" ); 14268 14269 // Don't close the menu on mouseleave 14270 this.menuInstance._off( this.menu, "mouseleave" ); 14271 14272 // Cancel the menu's collapseAll on document click 14273 this.menuInstance._closeOnDocumentClick = function() { 14274 return false; 14275 }; 14276 14277 // Selects often contain empty items, but never contain dividers 14278 this.menuInstance._isDivider = function() { 14279 return false; 14280 }; 14281 }, 14282 14283 refresh: function() { 14284 this._refreshMenu(); 14285 this.buttonItem.replaceWith( 14286 this.buttonItem = this._renderButtonItem( 14287 14288 // Fall back to an empty object in case there are no options 14289 this._getSelectedItem().data( "ui-selectmenu-item" ) || {} 14290 ) 14291 ); 14292 if ( this.options.width === null ) { 14293 this._resizeButton(); 14294 } 14295 }, 14296 14297 _refreshMenu: function() { 14298 var item, 14299 options = this.element.find( "option" ); 14300 14301 this.menu.empty(); 14302 14303 this._parseOptions( options ); 14304 this._renderMenu( this.menu, this.items ); 14305 14306 this.menuInstance.refresh(); 14307 this.menuItems = this.menu.find( "li" ) 14308 .not( ".ui-selectmenu-optgroup" ) 14309 .find( ".ui-menu-item-wrapper" ); 14310 14311 this._rendered = true; 14312 14313 if ( !options.length ) { 14314 return; 14315 } 14316 14317 item = this._getSelectedItem(); 14318 14319 // Update the menu to have the correct item focused 14320 this.menuInstance.focus( null, item ); 14321 this._setAria( item.data( "ui-selectmenu-item" ) ); 14322 14323 // Set disabled state 14324 this._setOption( "disabled", this.element.prop( "disabled" ) ); 14325 }, 14326 14327 open: function( event ) { 14328 if ( this.options.disabled ) { 14329 return; 14330 } 14331 14332 // If this is the first time the menu is being opened, render the items 14333 if ( !this._rendered ) { 14334 this._refreshMenu(); 14335 } else { 14336 14337 // Menu clears focus on close, reset focus to selected item 14338 this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" ); 14339 this.menuInstance.focus( null, this._getSelectedItem() ); 14340 } 14341 14342 // If there are no options, don't open the menu 14343 if ( !this.menuItems.length ) { 14344 return; 14345 } 14346 14347 this.isOpen = true; 14348 this._toggleAttr(); 14349 this._resizeMenu(); 14350 this._position(); 14351 14352 this._on( this.document, this._documentClick ); 14353 14354 this._trigger( "open", event ); 14355 }, 14356 14357 _position: function() { 14358 this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) ); 14359 }, 14360 14361 close: function( event ) { 14362 if ( !this.isOpen ) { 14363 return; 14364 } 14365 14366 this.isOpen = false; 14367 this._toggleAttr(); 14368 14369 this.range = null; 14370 this._off( this.document ); 14371 14372 this._trigger( "close", event ); 14373 }, 14374 14375 widget: function() { 14376 return this.button; 14377 }, 14378 14379 menuWidget: function() { 14380 return this.menu; 14381 }, 14382 14383 _renderButtonItem: function( item ) { 14384 var buttonItem = $( "<span>" ); 14385 14386 this._setText( buttonItem, item.label ); 14387 this._addClass( buttonItem, "ui-selectmenu-text" ); 14388 14389 return buttonItem; 14390 }, 14391 14392 _renderMenu: function( ul, items ) { 14393 var that = this, 14394 currentOptgroup = ""; 14395 14396 $.each( items, function( index, item ) { 14397 var li; 14398 14399 if ( item.optgroup !== currentOptgroup ) { 14400 li = $( "<li>", { 14401 text: item.optgroup 14402 } ); 14403 that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" + 14404 ( item.element.parent( "optgroup" ).prop( "disabled" ) ? 14405 " ui-state-disabled" : 14406 "" ) ); 14407 14408 li.appendTo( ul ); 14409 14410 currentOptgroup = item.optgroup; 14411 } 14412 14413 that._renderItemData( ul, item ); 14414 } ); 14415 }, 14416 14417 _renderItemData: function( ul, item ) { 14418 return this._renderItem( ul, item ).data( "ui-selectmenu-item", item ); 14419 }, 14420 14421 _renderItem: function( ul, item ) { 14422 var li = $( "<li>" ), 14423 wrapper = $( "<div>", { 14424 title: item.element.attr( "title" ) 14425 } ); 14426 14427 if ( item.disabled ) { 14428 this._addClass( li, null, "ui-state-disabled" ); 14429 } 14430 14431 if ( item.hidden ) { 14432 li.prop( "hidden", true ); 14433 } else { 14434 this._setText( wrapper, item.label ); 14435 } 14436 14437 return li.append( wrapper ).appendTo( ul ); 14438 }, 14439 14440 _setText: function( element, value ) { 14441 if ( value ) { 14442 element.text( value ); 14443 } else { 14444 element.html( " " ); 14445 } 14446 }, 14447 14448 _move: function( direction, event ) { 14449 var item, next, 14450 filter = ".ui-menu-item"; 14451 14452 if ( this.isOpen ) { 14453 item = this.menuItems.eq( this.focusIndex ).parent( "li" ); 14454 } else { 14455 item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" ); 14456 filter += ":not(.ui-state-disabled)"; 14457 } 14458 14459 if ( direction === "first" || direction === "last" ) { 14460 next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 ); 14461 } else { 14462 next = item[ direction + "All" ]( filter ).eq( 0 ); 14463 } 14464 14465 if ( next.length ) { 14466 this.menuInstance.focus( event, next ); 14467 } 14468 }, 14469 14470 _getSelectedItem: function() { 14471 return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" ); 14472 }, 14473 14474 _toggle: function( event ) { 14475 this[ this.isOpen ? "close" : "open" ]( event ); 14476 }, 14477 14478 _setSelection: function() { 14479 var selection; 14480 14481 if ( !this.range ) { 14482 return; 14483 } 14484 14485 if ( window.getSelection ) { 14486 selection = window.getSelection(); 14487 selection.removeAllRanges(); 14488 selection.addRange( this.range ); 14489 14490 // Support: IE8 14491 } else { 14492 this.range.select(); 14493 } 14494 14495 // Support: IE 14496 // Setting the text selection kills the button focus in IE, but 14497 // restoring the focus doesn't kill the selection. 14498 this.button.trigger( "focus" ); 14499 }, 14500 14501 _documentClick: { 14502 mousedown: function( event ) { 14503 if ( !this.isOpen ) { 14504 return; 14505 } 14506 14507 if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" + 14508 $.escapeSelector( this.ids.button ) ).length ) { 14509 this.close( event ); 14510 } 14511 } 14512 }, 14513 14514 _buttonEvents: { 14515 14516 // Prevent text selection from being reset when interacting with the selectmenu (#10144) 14517 mousedown: function() { 14518 var selection; 14519 14520 if ( window.getSelection ) { 14521 selection = window.getSelection(); 14522 if ( selection.rangeCount ) { 14523 this.range = selection.getRangeAt( 0 ); 14524 } 14525 14526 // Support: IE8 14527 } else { 14528 this.range = document.selection.createRange(); 14529 } 14530 }, 14531 14532 click: function( event ) { 14533 this._setSelection(); 14534 this._toggle( event ); 14535 }, 14536 14537 keydown: function( event ) { 14538 var preventDefault = true; 14539 switch ( event.keyCode ) { 14540 case $.ui.keyCode.TAB: 14541 case $.ui.keyCode.ESCAPE: 14542 this.close( event ); 14543 preventDefault = false; 14544 break; 14545 case $.ui.keyCode.ENTER: 14546 if ( this.isOpen ) { 14547 this._selectFocusedItem( event ); 14548 } 14549 break; 14550 case $.ui.keyCode.UP: 14551 if ( event.altKey ) { 14552 this._toggle( event ); 14553 } else { 14554 this._move( "prev", event ); 14555 } 14556 break; 14557 case $.ui.keyCode.DOWN: 14558 if ( event.altKey ) { 14559 this._toggle( event ); 14560 } else { 14561 this._move( "next", event ); 14562 } 14563 break; 14564 case $.ui.keyCode.SPACE: 14565 if ( this.isOpen ) { 14566 this._selectFocusedItem( event ); 14567 } else { 14568 this._toggle( event ); 14569 } 14570 break; 14571 case $.ui.keyCode.LEFT: 14572 this._move( "prev", event ); 14573 break; 14574 case $.ui.keyCode.RIGHT: 14575 this._move( "next", event ); 14576 break; 14577 case $.ui.keyCode.HOME: 14578 case $.ui.keyCode.PAGE_UP: 14579 this._move( "first", event ); 14580 break; 14581 case $.ui.keyCode.END: 14582 case $.ui.keyCode.PAGE_DOWN: 14583 this._move( "last", event ); 14584 break; 14585 default: 14586 this.menu.trigger( event ); 14587 preventDefault = false; 14588 } 14589 14590 if ( preventDefault ) { 14591 event.preventDefault(); 14592 } 14593 } 14594 }, 14595 14596 _selectFocusedItem: function( event ) { 14597 var item = this.menuItems.eq( this.focusIndex ).parent( "li" ); 14598 if ( !item.hasClass( "ui-state-disabled" ) ) { 14599 this._select( item.data( "ui-selectmenu-item" ), event ); 14600 } 14601 }, 14602 14603 _select: function( item, event ) { 14604 var oldIndex = this.element[ 0 ].selectedIndex; 14605 14606 // Change native select element 14607 this.element[ 0 ].selectedIndex = item.index; 14608 this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) ); 14609 this._setAria( item ); 14610 this._trigger( "select", event, { item: item } ); 14611 14612 if ( item.index !== oldIndex ) { 14613 this._trigger( "change", event, { item: item } ); 14614 } 14615 14616 this.close( event ); 14617 }, 14618 14619 _setAria: function( item ) { 14620 var id = this.menuItems.eq( item.index ).attr( "id" ); 14621 14622 this.button.attr( { 14623 "aria-labelledby": id, 14624 "aria-activedescendant": id 14625 } ); 14626 this.menu.attr( "aria-activedescendant", id ); 14627 }, 14628 14629 _setOption: function( key, value ) { 14630 if ( key === "icons" ) { 14631 var icon = this.button.find( "span.ui-icon" ); 14632 this._removeClass( icon, null, this.options.icons.button ) 14633 ._addClass( icon, null, value.button ); 14634 } 14635 14636 this._super( key, value ); 14637 14638 if ( key === "appendTo" ) { 14639 this.menuWrap.appendTo( this._appendTo() ); 14640 } 14641 14642 if ( key === "width" ) { 14643 this._resizeButton(); 14644 } 14645 }, 14646 14647 _setOptionDisabled: function( value ) { 14648 this._super( value ); 14649 14650 this.menuInstance.option( "disabled", value ); 14651 this.button.attr( "aria-disabled", value ); 14652 this._toggleClass( this.button, null, "ui-state-disabled", value ); 14653 14654 this.element.prop( "disabled", value ); 14655 if ( value ) { 14656 this.button.attr( "tabindex", -1 ); 14657 this.close(); 14658 } else { 14659 this.button.attr( "tabindex", 0 ); 14660 } 14661 }, 14662 14663 _appendTo: function() { 14664 var element = this.options.appendTo; 14665 14666 if ( element ) { 14667 element = element.jquery || element.nodeType ? 14668 $( element ) : 14669 this.document.find( element ).eq( 0 ); 14670 } 14671 14672 if ( !element || !element[ 0 ] ) { 14673 element = this.element.closest( ".ui-front, dialog" ); 14674 } 14675 14676 if ( !element.length ) { 14677 element = this.document[ 0 ].body; 14678 } 14679 14680 return element; 14681 }, 14682 14683 _toggleAttr: function() { 14684 this.button.attr( "aria-expanded", this.isOpen ); 14685 14686 // We can't use two _toggleClass() calls here, because we need to make sure 14687 // we always remove classes first and add them second, otherwise if both classes have the 14688 // same theme class, it will be removed after we add it. 14689 this._removeClass( this.button, "ui-selectmenu-button-" + 14690 ( this.isOpen ? "closed" : "open" ) ) 14691 ._addClass( this.button, "ui-selectmenu-button-" + 14692 ( this.isOpen ? "open" : "closed" ) ) 14693 ._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen ); 14694 14695 this.menu.attr( "aria-hidden", !this.isOpen ); 14696 }, 14697 14698 _resizeButton: function() { 14699 var width = this.options.width; 14700 14701 // For `width: false`, just remove inline style and stop 14702 if ( width === false ) { 14703 this.button.css( "width", "" ); 14704 return; 14705 } 14706 14707 // For `width: null`, match the width of the original element 14708 if ( width === null ) { 14709 width = this.element.show().outerWidth(); 14710 this.element.hide(); 14711 } 14712 14713 this.button.outerWidth( width ); 14714 }, 14715 14716 _resizeMenu: function() { 14717 this.menu.outerWidth( Math.max( 14718 this.button.outerWidth(), 14719 14720 // Support: IE10 14721 // IE10 wraps long text (possibly a rounding bug) 14722 // so we add 1px to avoid the wrapping 14723 this.menu.width( "" ).outerWidth() + 1 14724 ) ); 14725 }, 14726 14727 _getCreateOptions: function() { 14728 var options = this._super(); 14729 14730 options.disabled = this.element.prop( "disabled" ); 14731 14732 return options; 14733 }, 14734 14735 _parseOptions: function( options ) { 14736 var that = this, 14737 data = []; 14738 options.each( function( index, item ) { 14739 data.push( that._parseOption( $( item ), index ) ); 14740 } ); 14741 this.items = data; 14742 }, 14743 14744 _parseOption: function( option, index ) { 14745 var optgroup = option.parent( "optgroup" ); 14746 14747 return { 14748 element: option, 14749 index: index, 14750 value: option.val(), 14751 label: option.text(), 14752 hidden: optgroup.prop( "hidden" ) || option.prop( "hidden" ), 14753 optgroup: optgroup.attr( "label" ) || "", 14754 disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" ) 14755 }; 14756 }, 14757 14758 _destroy: function() { 14759 this._unbindFormResetHandler(); 14760 this.menuWrap.remove(); 14761 this.button.remove(); 14762 this.element.show(); 14763 this.element.removeUniqueId(); 14764 this.labels.attr( "for", this.ids.element ); 14765 } 14766} ] ); 14767 14768 14769/*! 14770 * jQuery UI Slider 1.13.3 14771 * https://jqueryui.com 14772 * 14773 * Copyright OpenJS Foundation and other contributors 14774 * Released under the MIT license. 14775 * https://jquery.org/license 14776 */ 14777 14778//>>label: Slider 14779//>>group: Widgets 14780//>>description: Displays a flexible slider with ranges and accessibility via keyboard. 14781//>>docs: https://api.jqueryui.com/slider/ 14782//>>demos: https://jqueryui.com/slider/ 14783//>>css.structure: ../../themes/base/core.css 14784//>>css.structure: ../../themes/base/slider.css 14785//>>css.theme: ../../themes/base/theme.css 14786 14787 14788var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, { 14789 version: "1.13.3", 14790 widgetEventPrefix: "slide", 14791 14792 options: { 14793 animate: false, 14794 classes: { 14795 "ui-slider": "ui-corner-all", 14796 "ui-slider-handle": "ui-corner-all", 14797 14798 // Note: ui-widget-header isn't the most fittingly semantic framework class for this 14799 // element, but worked best visually with a variety of themes 14800 "ui-slider-range": "ui-corner-all ui-widget-header" 14801 }, 14802 distance: 0, 14803 max: 100, 14804 min: 0, 14805 orientation: "horizontal", 14806 range: false, 14807 step: 1, 14808 value: 0, 14809 values: null, 14810 14811 // Callbacks 14812 change: null, 14813 slide: null, 14814 start: null, 14815 stop: null 14816 }, 14817 14818 // Number of pages in a slider 14819 // (how many times can you page up/down to go through the whole range) 14820 numPages: 5, 14821 14822 _create: function() { 14823 this._keySliding = false; 14824 this._mouseSliding = false; 14825 this._animateOff = true; 14826 this._handleIndex = null; 14827 this._detectOrientation(); 14828 this._mouseInit(); 14829 this._calculateNewMax(); 14830 14831 this._addClass( "ui-slider ui-slider-" + this.orientation, 14832 "ui-widget ui-widget-content" ); 14833 14834 this._refresh(); 14835 14836 this._animateOff = false; 14837 }, 14838 14839 _refresh: function() { 14840 this._createRange(); 14841 this._createHandles(); 14842 this._setupEvents(); 14843 this._refreshValue(); 14844 }, 14845 14846 _createHandles: function() { 14847 var i, handleCount, 14848 options = this.options, 14849 existingHandles = this.element.find( ".ui-slider-handle" ), 14850 handle = "<span tabindex='0'></span>", 14851 handles = []; 14852 14853 handleCount = ( options.values && options.values.length ) || 1; 14854 14855 if ( existingHandles.length > handleCount ) { 14856 existingHandles.slice( handleCount ).remove(); 14857 existingHandles = existingHandles.slice( 0, handleCount ); 14858 } 14859 14860 for ( i = existingHandles.length; i < handleCount; i++ ) { 14861 handles.push( handle ); 14862 } 14863 14864 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) ); 14865 14866 this._addClass( this.handles, "ui-slider-handle", "ui-state-default" ); 14867 14868 this.handle = this.handles.eq( 0 ); 14869 14870 this.handles.each( function( i ) { 14871 $( this ) 14872 .data( "ui-slider-handle-index", i ) 14873 .attr( "tabIndex", 0 ); 14874 } ); 14875 }, 14876 14877 _createRange: function() { 14878 var options = this.options; 14879 14880 if ( options.range ) { 14881 if ( options.range === true ) { 14882 if ( !options.values ) { 14883 options.values = [ this._valueMin(), this._valueMin() ]; 14884 } else if ( options.values.length && options.values.length !== 2 ) { 14885 options.values = [ options.values[ 0 ], options.values[ 0 ] ]; 14886 } else if ( Array.isArray( options.values ) ) { 14887 options.values = options.values.slice( 0 ); 14888 } 14889 } 14890 14891 if ( !this.range || !this.range.length ) { 14892 this.range = $( "<div>" ) 14893 .appendTo( this.element ); 14894 14895 this._addClass( this.range, "ui-slider-range" ); 14896 } else { 14897 this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" ); 14898 14899 // Handle range switching from true to min/max 14900 this.range.css( { 14901 "left": "", 14902 "bottom": "" 14903 } ); 14904 } 14905 if ( options.range === "min" || options.range === "max" ) { 14906 this._addClass( this.range, "ui-slider-range-" + options.range ); 14907 } 14908 } else { 14909 if ( this.range ) { 14910 this.range.remove(); 14911 } 14912 this.range = null; 14913 } 14914 }, 14915 14916 _setupEvents: function() { 14917 this._off( this.handles ); 14918 this._on( this.handles, this._handleEvents ); 14919 this._hoverable( this.handles ); 14920 this._focusable( this.handles ); 14921 }, 14922 14923 _destroy: function() { 14924 this.handles.remove(); 14925 if ( this.range ) { 14926 this.range.remove(); 14927 } 14928 14929 this._mouseDestroy(); 14930 }, 14931 14932 _mouseCapture: function( event ) { 14933 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, 14934 that = this, 14935 o = this.options; 14936 14937 if ( o.disabled ) { 14938 return false; 14939 } 14940 14941 this.elementSize = { 14942 width: this.element.outerWidth(), 14943 height: this.element.outerHeight() 14944 }; 14945 this.elementOffset = this.element.offset(); 14946 14947 position = { x: event.pageX, y: event.pageY }; 14948 normValue = this._normValueFromMouse( position ); 14949 distance = this._valueMax() - this._valueMin() + 1; 14950 this.handles.each( function( i ) { 14951 var thisDistance = Math.abs( normValue - that.values( i ) ); 14952 if ( ( distance > thisDistance ) || 14953 ( distance === thisDistance && 14954 ( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) { 14955 distance = thisDistance; 14956 closestHandle = $( this ); 14957 index = i; 14958 } 14959 } ); 14960 14961 allowed = this._start( event, index ); 14962 if ( allowed === false ) { 14963 return false; 14964 } 14965 this._mouseSliding = true; 14966 14967 this._handleIndex = index; 14968 14969 this._addClass( closestHandle, null, "ui-state-active" ); 14970 closestHandle.trigger( "focus" ); 14971 14972 offset = closestHandle.offset(); 14973 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" ); 14974 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { 14975 left: event.pageX - offset.left - ( closestHandle.width() / 2 ), 14976 top: event.pageY - offset.top - 14977 ( closestHandle.height() / 2 ) - 14978 ( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) - 14979 ( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) + 14980 ( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 ) 14981 }; 14982 14983 if ( !this.handles.hasClass( "ui-state-hover" ) ) { 14984 this._slide( event, index, normValue ); 14985 } 14986 this._animateOff = true; 14987 return true; 14988 }, 14989 14990 _mouseStart: function() { 14991 return true; 14992 }, 14993 14994 _mouseDrag: function( event ) { 14995 var position = { x: event.pageX, y: event.pageY }, 14996 normValue = this._normValueFromMouse( position ); 14997 14998 this._slide( event, this._handleIndex, normValue ); 14999 15000 return false; 15001 }, 15002 15003 _mouseStop: function( event ) { 15004 this._removeClass( this.handles, null, "ui-state-active" ); 15005 this._mouseSliding = false; 15006 15007 this._stop( event, this._handleIndex ); 15008 this._change( event, this._handleIndex ); 15009 15010 this._handleIndex = null; 15011 this._clickOffset = null; 15012 this._animateOff = false; 15013 15014 return false; 15015 }, 15016 15017 _detectOrientation: function() { 15018 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; 15019 }, 15020 15021 _normValueFromMouse: function( position ) { 15022 var pixelTotal, 15023 pixelMouse, 15024 percentMouse, 15025 valueTotal, 15026 valueMouse; 15027 15028 if ( this.orientation === "horizontal" ) { 15029 pixelTotal = this.elementSize.width; 15030 pixelMouse = position.x - this.elementOffset.left - 15031 ( this._clickOffset ? this._clickOffset.left : 0 ); 15032 } else { 15033 pixelTotal = this.elementSize.height; 15034 pixelMouse = position.y - this.elementOffset.top - 15035 ( this._clickOffset ? this._clickOffset.top : 0 ); 15036 } 15037 15038 percentMouse = ( pixelMouse / pixelTotal ); 15039 if ( percentMouse > 1 ) { 15040 percentMouse = 1; 15041 } 15042 if ( percentMouse < 0 ) { 15043 percentMouse = 0; 15044 } 15045 if ( this.orientation === "vertical" ) { 15046 percentMouse = 1 - percentMouse; 15047 } 15048 15049 valueTotal = this._valueMax() - this._valueMin(); 15050 valueMouse = this._valueMin() + percentMouse * valueTotal; 15051 15052 return this._trimAlignValue( valueMouse ); 15053 }, 15054 15055 _uiHash: function( index, value, values ) { 15056 var uiHash = { 15057 handle: this.handles[ index ], 15058 handleIndex: index, 15059 value: value !== undefined ? value : this.value() 15060 }; 15061 15062 if ( this._hasMultipleValues() ) { 15063 uiHash.value = value !== undefined ? value : this.values( index ); 15064 uiHash.values = values || this.values(); 15065 } 15066 15067 return uiHash; 15068 }, 15069 15070 _hasMultipleValues: function() { 15071 return this.options.values && this.options.values.length; 15072 }, 15073 15074 _start: function( event, index ) { 15075 return this._trigger( "start", event, this._uiHash( index ) ); 15076 }, 15077 15078 _slide: function( event, index, newVal ) { 15079 var allowed, otherVal, 15080 currentValue = this.value(), 15081 newValues = this.values(); 15082 15083 if ( this._hasMultipleValues() ) { 15084 otherVal = this.values( index ? 0 : 1 ); 15085 currentValue = this.values( index ); 15086 15087 if ( this.options.values.length === 2 && this.options.range === true ) { 15088 newVal = index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal ); 15089 } 15090 15091 newValues[ index ] = newVal; 15092 } 15093 15094 if ( newVal === currentValue ) { 15095 return; 15096 } 15097 15098 allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) ); 15099 15100 // A slide can be canceled by returning false from the slide callback 15101 if ( allowed === false ) { 15102 return; 15103 } 15104 15105 if ( this._hasMultipleValues() ) { 15106 this.values( index, newVal ); 15107 } else { 15108 this.value( newVal ); 15109 } 15110 }, 15111 15112 _stop: function( event, index ) { 15113 this._trigger( "stop", event, this._uiHash( index ) ); 15114 }, 15115 15116 _change: function( event, index ) { 15117 if ( !this._keySliding && !this._mouseSliding ) { 15118 15119 //store the last changed value index for reference when handles overlap 15120 this._lastChangedValue = index; 15121 this._trigger( "change", event, this._uiHash( index ) ); 15122 } 15123 }, 15124 15125 value: function( newValue ) { 15126 if ( arguments.length ) { 15127 this.options.value = this._trimAlignValue( newValue ); 15128 this._refreshValue(); 15129 this._change( null, 0 ); 15130 return; 15131 } 15132 15133 return this._value(); 15134 }, 15135 15136 values: function( index, newValue ) { 15137 var vals, 15138 newValues, 15139 i; 15140 15141 if ( arguments.length > 1 ) { 15142 this.options.values[ index ] = this._trimAlignValue( newValue ); 15143 this._refreshValue(); 15144 this._change( null, index ); 15145 return; 15146 } 15147 15148 if ( arguments.length ) { 15149 if ( Array.isArray( arguments[ 0 ] ) ) { 15150 vals = this.options.values; 15151 newValues = arguments[ 0 ]; 15152 for ( i = 0; i < vals.length; i += 1 ) { 15153 vals[ i ] = this._trimAlignValue( newValues[ i ] ); 15154 this._change( null, i ); 15155 } 15156 this._refreshValue(); 15157 } else { 15158 if ( this._hasMultipleValues() ) { 15159 return this._values( index ); 15160 } else { 15161 return this.value(); 15162 } 15163 } 15164 } else { 15165 return this._values(); 15166 } 15167 }, 15168 15169 _setOption: function( key, value ) { 15170 var i, 15171 valsLength = 0; 15172 15173 if ( key === "range" && this.options.range === true ) { 15174 if ( value === "min" ) { 15175 this.options.value = this._values( 0 ); 15176 this.options.values = null; 15177 } else if ( value === "max" ) { 15178 this.options.value = this._values( this.options.values.length - 1 ); 15179 this.options.values = null; 15180 } 15181 } 15182 15183 if ( Array.isArray( this.options.values ) ) { 15184 valsLength = this.options.values.length; 15185 } 15186 15187 this._super( key, value ); 15188 15189 switch ( key ) { 15190 case "orientation": 15191 this._detectOrientation(); 15192 this._removeClass( "ui-slider-horizontal ui-slider-vertical" ) 15193 ._addClass( "ui-slider-" + this.orientation ); 15194 this._refreshValue(); 15195 if ( this.options.range ) { 15196 this._refreshRange( value ); 15197 } 15198 15199 // Reset positioning from previous orientation 15200 this.handles.css( value === "horizontal" ? "bottom" : "left", "" ); 15201 break; 15202 case "value": 15203 this._animateOff = true; 15204 this._refreshValue(); 15205 this._change( null, 0 ); 15206 this._animateOff = false; 15207 break; 15208 case "values": 15209 this._animateOff = true; 15210 this._refreshValue(); 15211 15212 // Start from the last handle to prevent unreachable handles (#9046) 15213 for ( i = valsLength - 1; i >= 0; i-- ) { 15214 this._change( null, i ); 15215 } 15216 this._animateOff = false; 15217 break; 15218 case "step": 15219 case "min": 15220 case "max": 15221 this._animateOff = true; 15222 this._calculateNewMax(); 15223 this._refreshValue(); 15224 this._animateOff = false; 15225 break; 15226 case "range": 15227 this._animateOff = true; 15228 this._refresh(); 15229 this._animateOff = false; 15230 break; 15231 } 15232 }, 15233 15234 _setOptionDisabled: function( value ) { 15235 this._super( value ); 15236 15237 this._toggleClass( null, "ui-state-disabled", !!value ); 15238 }, 15239 15240 //internal value getter 15241 // _value() returns value trimmed by min and max, aligned by step 15242 _value: function() { 15243 var val = this.options.value; 15244 val = this._trimAlignValue( val ); 15245 15246 return val; 15247 }, 15248 15249 //internal values getter 15250 // _values() returns array of values trimmed by min and max, aligned by step 15251 // _values( index ) returns single value trimmed by min and max, aligned by step 15252 _values: function( index ) { 15253 var val, 15254 vals, 15255 i; 15256 15257 if ( arguments.length ) { 15258 val = this.options.values[ index ]; 15259 val = this._trimAlignValue( val ); 15260 15261 return val; 15262 } else if ( this._hasMultipleValues() ) { 15263 15264 // .slice() creates a copy of the array 15265 // this copy gets trimmed by min and max and then returned 15266 vals = this.options.values.slice(); 15267 for ( i = 0; i < vals.length; i += 1 ) { 15268 vals[ i ] = this._trimAlignValue( vals[ i ] ); 15269 } 15270 15271 return vals; 15272 } else { 15273 return []; 15274 } 15275 }, 15276 15277 // Returns the step-aligned value that val is closest to, between (inclusive) min and max 15278 _trimAlignValue: function( val ) { 15279 if ( val <= this._valueMin() ) { 15280 return this._valueMin(); 15281 } 15282 if ( val >= this._valueMax() ) { 15283 return this._valueMax(); 15284 } 15285 var step = ( this.options.step > 0 ) ? this.options.step : 1, 15286 valModStep = ( val - this._valueMin() ) % step, 15287 alignValue = val - valModStep; 15288 15289 if ( Math.abs( valModStep ) * 2 >= step ) { 15290 alignValue += ( valModStep > 0 ) ? step : ( -step ); 15291 } 15292 15293 // Since JavaScript has problems with large floats, round 15294 // the final value to 5 digits after the decimal point (see #4124) 15295 return parseFloat( alignValue.toFixed( 5 ) ); 15296 }, 15297 15298 _calculateNewMax: function() { 15299 var max = this.options.max, 15300 min = this._valueMin(), 15301 step = this.options.step, 15302 aboveMin = Math.round( ( max - min ) / step ) * step; 15303 max = aboveMin + min; 15304 if ( max > this.options.max ) { 15305 15306 //If max is not divisible by step, rounding off may increase its value 15307 max -= step; 15308 } 15309 this.max = parseFloat( max.toFixed( this._precision() ) ); 15310 }, 15311 15312 _precision: function() { 15313 var precision = this._precisionOf( this.options.step ); 15314 if ( this.options.min !== null ) { 15315 precision = Math.max( precision, this._precisionOf( this.options.min ) ); 15316 } 15317 return precision; 15318 }, 15319 15320 _precisionOf: function( num ) { 15321 var str = num.toString(), 15322 decimal = str.indexOf( "." ); 15323 return decimal === -1 ? 0 : str.length - decimal - 1; 15324 }, 15325 15326 _valueMin: function() { 15327 return this.options.min; 15328 }, 15329 15330 _valueMax: function() { 15331 return this.max; 15332 }, 15333 15334 _refreshRange: function( orientation ) { 15335 if ( orientation === "vertical" ) { 15336 this.range.css( { "width": "", "left": "" } ); 15337 } 15338 if ( orientation === "horizontal" ) { 15339 this.range.css( { "height": "", "bottom": "" } ); 15340 } 15341 }, 15342 15343 _refreshValue: function() { 15344 var lastValPercent, valPercent, value, valueMin, valueMax, 15345 oRange = this.options.range, 15346 o = this.options, 15347 that = this, 15348 animate = ( !this._animateOff ) ? o.animate : false, 15349 _set = {}; 15350 15351 if ( this._hasMultipleValues() ) { 15352 this.handles.each( function( i ) { 15353 valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() - 15354 that._valueMin() ) * 100; 15355 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 15356 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 15357 if ( that.options.range === true ) { 15358 if ( that.orientation === "horizontal" ) { 15359 if ( i === 0 ) { 15360 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 15361 left: valPercent + "%" 15362 }, o.animate ); 15363 } 15364 if ( i === 1 ) { 15365 that.range[ animate ? "animate" : "css" ]( { 15366 width: ( valPercent - lastValPercent ) + "%" 15367 }, { 15368 queue: false, 15369 duration: o.animate 15370 } ); 15371 } 15372 } else { 15373 if ( i === 0 ) { 15374 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 15375 bottom: ( valPercent ) + "%" 15376 }, o.animate ); 15377 } 15378 if ( i === 1 ) { 15379 that.range[ animate ? "animate" : "css" ]( { 15380 height: ( valPercent - lastValPercent ) + "%" 15381 }, { 15382 queue: false, 15383 duration: o.animate 15384 } ); 15385 } 15386 } 15387 } 15388 lastValPercent = valPercent; 15389 } ); 15390 } else { 15391 value = this.value(); 15392 valueMin = this._valueMin(); 15393 valueMax = this._valueMax(); 15394 valPercent = ( valueMax !== valueMin ) ? 15395 ( value - valueMin ) / ( valueMax - valueMin ) * 100 : 15396 0; 15397 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 15398 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 15399 15400 if ( oRange === "min" && this.orientation === "horizontal" ) { 15401 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 15402 width: valPercent + "%" 15403 }, o.animate ); 15404 } 15405 if ( oRange === "max" && this.orientation === "horizontal" ) { 15406 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 15407 width: ( 100 - valPercent ) + "%" 15408 }, o.animate ); 15409 } 15410 if ( oRange === "min" && this.orientation === "vertical" ) { 15411 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 15412 height: valPercent + "%" 15413 }, o.animate ); 15414 } 15415 if ( oRange === "max" && this.orientation === "vertical" ) { 15416 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 15417 height: ( 100 - valPercent ) + "%" 15418 }, o.animate ); 15419 } 15420 } 15421 }, 15422 15423 _handleEvents: { 15424 keydown: function( event ) { 15425 var allowed, curVal, newVal, step, 15426 index = $( event.target ).data( "ui-slider-handle-index" ); 15427 15428 switch ( event.keyCode ) { 15429 case $.ui.keyCode.HOME: 15430 case $.ui.keyCode.END: 15431 case $.ui.keyCode.PAGE_UP: 15432 case $.ui.keyCode.PAGE_DOWN: 15433 case $.ui.keyCode.UP: 15434 case $.ui.keyCode.RIGHT: 15435 case $.ui.keyCode.DOWN: 15436 case $.ui.keyCode.LEFT: 15437 event.preventDefault(); 15438 if ( !this._keySliding ) { 15439 this._keySliding = true; 15440 this._addClass( $( event.target ), null, "ui-state-active" ); 15441 allowed = this._start( event, index ); 15442 if ( allowed === false ) { 15443 return; 15444 } 15445 } 15446 break; 15447 } 15448 15449 step = this.options.step; 15450 if ( this._hasMultipleValues() ) { 15451 curVal = newVal = this.values( index ); 15452 } else { 15453 curVal = newVal = this.value(); 15454 } 15455 15456 switch ( event.keyCode ) { 15457 case $.ui.keyCode.HOME: 15458 newVal = this._valueMin(); 15459 break; 15460 case $.ui.keyCode.END: 15461 newVal = this._valueMax(); 15462 break; 15463 case $.ui.keyCode.PAGE_UP: 15464 newVal = this._trimAlignValue( 15465 curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages ) 15466 ); 15467 break; 15468 case $.ui.keyCode.PAGE_DOWN: 15469 newVal = this._trimAlignValue( 15470 curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) ); 15471 break; 15472 case $.ui.keyCode.UP: 15473 case $.ui.keyCode.RIGHT: 15474 if ( curVal === this._valueMax() ) { 15475 return; 15476 } 15477 newVal = this._trimAlignValue( curVal + step ); 15478 break; 15479 case $.ui.keyCode.DOWN: 15480 case $.ui.keyCode.LEFT: 15481 if ( curVal === this._valueMin() ) { 15482 return; 15483 } 15484 newVal = this._trimAlignValue( curVal - step ); 15485 break; 15486 } 15487 15488 this._slide( event, index, newVal ); 15489 }, 15490 keyup: function( event ) { 15491 var index = $( event.target ).data( "ui-slider-handle-index" ); 15492 15493 if ( this._keySliding ) { 15494 this._keySliding = false; 15495 this._stop( event, index ); 15496 this._change( event, index ); 15497 this._removeClass( $( event.target ), null, "ui-state-active" ); 15498 } 15499 } 15500 } 15501} ); 15502 15503 15504/*! 15505 * jQuery UI Sortable 1.13.3 15506 * https://jqueryui.com 15507 * 15508 * Copyright OpenJS Foundation and other contributors 15509 * Released under the MIT license. 15510 * https://jquery.org/license 15511 */ 15512 15513//>>label: Sortable 15514//>>group: Interactions 15515//>>description: Enables items in a list to be sorted using the mouse. 15516//>>docs: https://api.jqueryui.com/sortable/ 15517//>>demos: https://jqueryui.com/sortable/ 15518//>>css.structure: ../../themes/base/sortable.css 15519 15520 15521var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, { 15522 version: "1.13.3", 15523 widgetEventPrefix: "sort", 15524 ready: false, 15525 options: { 15526 appendTo: "parent", 15527 axis: false, 15528 connectWith: false, 15529 containment: false, 15530 cursor: "auto", 15531 cursorAt: false, 15532 dropOnEmpty: true, 15533 forcePlaceholderSize: false, 15534 forceHelperSize: false, 15535 grid: false, 15536 handle: false, 15537 helper: "original", 15538 items: "> *", 15539 opacity: false, 15540 placeholder: false, 15541 revert: false, 15542 scroll: true, 15543 scrollSensitivity: 20, 15544 scrollSpeed: 20, 15545 scope: "default", 15546 tolerance: "intersect", 15547 zIndex: 1000, 15548 15549 // Callbacks 15550 activate: null, 15551 beforeStop: null, 15552 change: null, 15553 deactivate: null, 15554 out: null, 15555 over: null, 15556 receive: null, 15557 remove: null, 15558 sort: null, 15559 start: null, 15560 stop: null, 15561 update: null 15562 }, 15563 15564 _isOverAxis: function( x, reference, size ) { 15565 return ( x >= reference ) && ( x < ( reference + size ) ); 15566 }, 15567 15568 _isFloating: function( item ) { 15569 return ( /left|right/ ).test( item.css( "float" ) ) || 15570 ( /inline|table-cell/ ).test( item.css( "display" ) ); 15571 }, 15572 15573 _create: function() { 15574 this.containerCache = {}; 15575 this._addClass( "ui-sortable" ); 15576 15577 //Get the items 15578 this.refresh(); 15579 15580 //Let's determine the parent's offset 15581 this.offset = this.element.offset(); 15582 15583 //Initialize mouse events for interaction 15584 this._mouseInit(); 15585 15586 this._setHandleClassName(); 15587 15588 //We're ready to go 15589 this.ready = true; 15590 15591 }, 15592 15593 _setOption: function( key, value ) { 15594 this._super( key, value ); 15595 15596 if ( key === "handle" ) { 15597 this._setHandleClassName(); 15598 } 15599 }, 15600 15601 _setHandleClassName: function() { 15602 var that = this; 15603 this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" ); 15604 $.each( this.items, function() { 15605 that._addClass( 15606 this.instance.options.handle ? 15607 this.item.find( this.instance.options.handle ) : 15608 this.item, 15609 "ui-sortable-handle" 15610 ); 15611 } ); 15612 }, 15613 15614 _destroy: function() { 15615 this._mouseDestroy(); 15616 15617 for ( var i = this.items.length - 1; i >= 0; i-- ) { 15618 this.items[ i ].item.removeData( this.widgetName + "-item" ); 15619 } 15620 15621 return this; 15622 }, 15623 15624 _mouseCapture: function( event, overrideHandle ) { 15625 var currentItem = null, 15626 validHandle = false, 15627 that = this; 15628 15629 if ( this.reverting ) { 15630 return false; 15631 } 15632 15633 if ( this.options.disabled || this.options.type === "static" ) { 15634 return false; 15635 } 15636 15637 //We have to refresh the items data once first 15638 this._refreshItems( event ); 15639 15640 //Find out if the clicked node (or one of its parents) is a actual item in this.items 15641 $( event.target ).parents().each( function() { 15642 if ( $.data( this, that.widgetName + "-item" ) === that ) { 15643 currentItem = $( this ); 15644 return false; 15645 } 15646 } ); 15647 if ( $.data( event.target, that.widgetName + "-item" ) === that ) { 15648 currentItem = $( event.target ); 15649 } 15650 15651 if ( !currentItem ) { 15652 return false; 15653 } 15654 if ( this.options.handle && !overrideHandle ) { 15655 $( this.options.handle, currentItem ).find( "*" ).addBack().each( function() { 15656 if ( this === event.target ) { 15657 validHandle = true; 15658 } 15659 } ); 15660 if ( !validHandle ) { 15661 return false; 15662 } 15663 } 15664 15665 this.currentItem = currentItem; 15666 this._removeCurrentsFromItems(); 15667 return true; 15668 15669 }, 15670 15671 _mouseStart: function( event, overrideHandle, noActivation ) { 15672 15673 var i, body, 15674 o = this.options; 15675 15676 this.currentContainer = this; 15677 15678 //We only need to call refreshPositions, because the refreshItems call has been moved to 15679 // mouseCapture 15680 this.refreshPositions(); 15681 15682 //Prepare the dragged items parent 15683 this.appendTo = $( o.appendTo !== "parent" ? 15684 o.appendTo : 15685 this.currentItem.parent() ); 15686 15687 //Create and append the visible helper 15688 this.helper = this._createHelper( event ); 15689 15690 //Cache the helper size 15691 this._cacheHelperProportions(); 15692 15693 /* 15694 * - Position generation - 15695 * This block generates everything position related - it's the core of draggables. 15696 */ 15697 15698 //Cache the margins of the original element 15699 this._cacheMargins(); 15700 15701 //The element's absolute position on the page minus margins 15702 this.offset = this.currentItem.offset(); 15703 this.offset = { 15704 top: this.offset.top - this.margins.top, 15705 left: this.offset.left - this.margins.left 15706 }; 15707 15708 $.extend( this.offset, { 15709 click: { //Where the click happened, relative to the element 15710 left: event.pageX - this.offset.left, 15711 top: event.pageY - this.offset.top 15712 }, 15713 15714 // This is a relative to absolute position minus the actual position calculation - 15715 // only used for relative positioned helper 15716 relative: this._getRelativeOffset() 15717 } ); 15718 15719 // After we get the helper offset, but before we get the parent offset we can 15720 // change the helper's position to absolute 15721 // TODO: Still need to figure out a way to make relative sorting possible 15722 this.helper.css( "position", "absolute" ); 15723 this.cssPosition = this.helper.css( "position" ); 15724 15725 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 15726 if ( o.cursorAt ) { 15727 this._adjustOffsetFromHelper( o.cursorAt ); 15728 } 15729 15730 //Cache the former DOM position 15731 this.domPosition = { 15732 prev: this.currentItem.prev()[ 0 ], 15733 parent: this.currentItem.parent()[ 0 ] 15734 }; 15735 15736 // If the helper is not the original, hide the original so it's not playing any role during 15737 // the drag, won't cause anything bad this way 15738 if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) { 15739 this.currentItem.hide(); 15740 } 15741 15742 //Create the placeholder 15743 this._createPlaceholder(); 15744 15745 //Get the next scrolling parent 15746 this.scrollParent = this.placeholder.scrollParent(); 15747 15748 $.extend( this.offset, { 15749 parent: this._getParentOffset() 15750 } ); 15751 15752 //Set a containment if given in the options 15753 if ( o.containment ) { 15754 this._setContainment(); 15755 } 15756 15757 if ( o.cursor && o.cursor !== "auto" ) { // cursor option 15758 body = this.document.find( "body" ); 15759 15760 // Support: IE 15761 this.storedCursor = body.css( "cursor" ); 15762 body.css( "cursor", o.cursor ); 15763 15764 this.storedStylesheet = 15765 $( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body ); 15766 } 15767 15768 // We need to make sure to grab the zIndex before setting the 15769 // opacity, because setting the opacity to anything lower than 1 15770 // causes the zIndex to change from "auto" to 0. 15771 if ( o.zIndex ) { // zIndex option 15772 if ( this.helper.css( "zIndex" ) ) { 15773 this._storedZIndex = this.helper.css( "zIndex" ); 15774 } 15775 this.helper.css( "zIndex", o.zIndex ); 15776 } 15777 15778 if ( o.opacity ) { // opacity option 15779 if ( this.helper.css( "opacity" ) ) { 15780 this._storedOpacity = this.helper.css( "opacity" ); 15781 } 15782 this.helper.css( "opacity", o.opacity ); 15783 } 15784 15785 //Prepare scrolling 15786 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && 15787 this.scrollParent[ 0 ].tagName !== "HTML" ) { 15788 this.overflowOffset = this.scrollParent.offset(); 15789 } 15790 15791 //Call callbacks 15792 this._trigger( "start", event, this._uiHash() ); 15793 15794 //Recache the helper size 15795 if ( !this._preserveHelperProportions ) { 15796 this._cacheHelperProportions(); 15797 } 15798 15799 //Post "activate" events to possible containers 15800 if ( !noActivation ) { 15801 for ( i = this.containers.length - 1; i >= 0; i-- ) { 15802 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); 15803 } 15804 } 15805 15806 //Prepare possible droppables 15807 if ( $.ui.ddmanager ) { 15808 $.ui.ddmanager.current = this; 15809 } 15810 15811 if ( $.ui.ddmanager && !o.dropBehaviour ) { 15812 $.ui.ddmanager.prepareOffsets( this, event ); 15813 } 15814 15815 this.dragging = true; 15816 15817 this._addClass( this.helper, "ui-sortable-helper" ); 15818 15819 //Move the helper, if needed 15820 if ( !this.helper.parent().is( this.appendTo ) ) { 15821 this.helper.detach().appendTo( this.appendTo ); 15822 15823 //Update position 15824 this.offset.parent = this._getParentOffset(); 15825 } 15826 15827 //Generate the original position 15828 this.position = this.originalPosition = this._generatePosition( event ); 15829 this.originalPageX = event.pageX; 15830 this.originalPageY = event.pageY; 15831 this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" ); 15832 15833 this._mouseDrag( event ); 15834 15835 return true; 15836 15837 }, 15838 15839 _scroll: function( event ) { 15840 var o = this.options, 15841 scrolled = false; 15842 15843 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && 15844 this.scrollParent[ 0 ].tagName !== "HTML" ) { 15845 15846 if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) - 15847 event.pageY < o.scrollSensitivity ) { 15848 this.scrollParent[ 0 ].scrollTop = 15849 scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed; 15850 } else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) { 15851 this.scrollParent[ 0 ].scrollTop = 15852 scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed; 15853 } 15854 15855 if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) - 15856 event.pageX < o.scrollSensitivity ) { 15857 this.scrollParent[ 0 ].scrollLeft = scrolled = 15858 this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed; 15859 } else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) { 15860 this.scrollParent[ 0 ].scrollLeft = scrolled = 15861 this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed; 15862 } 15863 15864 } else { 15865 15866 if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) { 15867 scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed ); 15868 } else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) < 15869 o.scrollSensitivity ) { 15870 scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed ); 15871 } 15872 15873 if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) { 15874 scrolled = this.document.scrollLeft( 15875 this.document.scrollLeft() - o.scrollSpeed 15876 ); 15877 } else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) < 15878 o.scrollSensitivity ) { 15879 scrolled = this.document.scrollLeft( 15880 this.document.scrollLeft() + o.scrollSpeed 15881 ); 15882 } 15883 15884 } 15885 15886 return scrolled; 15887 }, 15888 15889 _mouseDrag: function( event ) { 15890 var i, item, itemElement, intersection, 15891 o = this.options; 15892 15893 //Compute the helpers position 15894 this.position = this._generatePosition( event ); 15895 this.positionAbs = this._convertPositionTo( "absolute" ); 15896 15897 //Set the helper position 15898 if ( !this.options.axis || this.options.axis !== "y" ) { 15899 this.helper[ 0 ].style.left = this.position.left + "px"; 15900 } 15901 if ( !this.options.axis || this.options.axis !== "x" ) { 15902 this.helper[ 0 ].style.top = this.position.top + "px"; 15903 } 15904 15905 //Do scrolling 15906 if ( o.scroll ) { 15907 if ( this._scroll( event ) !== false ) { 15908 15909 //Update item positions used in position checks 15910 this._refreshItemPositions( true ); 15911 15912 if ( $.ui.ddmanager && !o.dropBehaviour ) { 15913 $.ui.ddmanager.prepareOffsets( this, event ); 15914 } 15915 } 15916 } 15917 15918 this.dragDirection = { 15919 vertical: this._getDragVerticalDirection(), 15920 horizontal: this._getDragHorizontalDirection() 15921 }; 15922 15923 //Rearrange 15924 for ( i = this.items.length - 1; i >= 0; i-- ) { 15925 15926 //Cache variables and intersection, continue if no intersection 15927 item = this.items[ i ]; 15928 itemElement = item.item[ 0 ]; 15929 intersection = this._intersectsWithPointer( item ); 15930 if ( !intersection ) { 15931 continue; 15932 } 15933 15934 // Only put the placeholder inside the current Container, skip all 15935 // items from other containers. This works because when moving 15936 // an item from one container to another the 15937 // currentContainer is switched before the placeholder is moved. 15938 // 15939 // Without this, moving items in "sub-sortables" can cause 15940 // the placeholder to jitter between the outer and inner container. 15941 if ( item.instance !== this.currentContainer ) { 15942 continue; 15943 } 15944 15945 // Cannot intersect with itself 15946 // no useless actions that have been done before 15947 // no action if the item moved is the parent of the item checked 15948 if ( itemElement !== this.currentItem[ 0 ] && 15949 this.placeholder[ intersection === 1 ? 15950 "next" : "prev" ]()[ 0 ] !== itemElement && 15951 !$.contains( this.placeholder[ 0 ], itemElement ) && 15952 ( this.options.type === "semi-dynamic" ? 15953 !$.contains( this.element[ 0 ], itemElement ) : 15954 true 15955 ) 15956 ) { 15957 15958 this.direction = intersection === 1 ? "down" : "up"; 15959 15960 if ( this.options.tolerance === "pointer" || 15961 this._intersectsWithSides( item ) ) { 15962 this._rearrange( event, item ); 15963 } else { 15964 break; 15965 } 15966 15967 this._trigger( "change", event, this._uiHash() ); 15968 break; 15969 } 15970 } 15971 15972 //Post events to containers 15973 this._contactContainers( event ); 15974 15975 //Interconnect with droppables 15976 if ( $.ui.ddmanager ) { 15977 $.ui.ddmanager.drag( this, event ); 15978 } 15979 15980 //Call callbacks 15981 this._trigger( "sort", event, this._uiHash() ); 15982 15983 this.lastPositionAbs = this.positionAbs; 15984 return false; 15985 15986 }, 15987 15988 _mouseStop: function( event, noPropagation ) { 15989 15990 if ( !event ) { 15991 return; 15992 } 15993 15994 //If we are using droppables, inform the manager about the drop 15995 if ( $.ui.ddmanager && !this.options.dropBehaviour ) { 15996 $.ui.ddmanager.drop( this, event ); 15997 } 15998 15999 if ( this.options.revert ) { 16000 var that = this, 16001 cur = this.placeholder.offset(), 16002 axis = this.options.axis, 16003 animation = {}; 16004 16005 if ( !axis || axis === "x" ) { 16006 animation.left = cur.left - this.offset.parent.left - this.margins.left + 16007 ( this.offsetParent[ 0 ] === this.document[ 0 ].body ? 16008 0 : 16009 this.offsetParent[ 0 ].scrollLeft 16010 ); 16011 } 16012 if ( !axis || axis === "y" ) { 16013 animation.top = cur.top - this.offset.parent.top - this.margins.top + 16014 ( this.offsetParent[ 0 ] === this.document[ 0 ].body ? 16015 0 : 16016 this.offsetParent[ 0 ].scrollTop 16017 ); 16018 } 16019 this.reverting = true; 16020 $( this.helper ).animate( 16021 animation, 16022 parseInt( this.options.revert, 10 ) || 500, 16023 function() { 16024 that._clear( event ); 16025 } 16026 ); 16027 } else { 16028 this._clear( event, noPropagation ); 16029 } 16030 16031 return false; 16032 16033 }, 16034 16035 cancel: function() { 16036 16037 if ( this.dragging ) { 16038 16039 this._mouseUp( new $.Event( "mouseup", { target: null } ) ); 16040 16041 if ( this.options.helper === "original" ) { 16042 this.currentItem.css( this._storedCSS ); 16043 this._removeClass( this.currentItem, "ui-sortable-helper" ); 16044 } else { 16045 this.currentItem.show(); 16046 } 16047 16048 //Post deactivating events to containers 16049 for ( var i = this.containers.length - 1; i >= 0; i-- ) { 16050 this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) ); 16051 if ( this.containers[ i ].containerCache.over ) { 16052 this.containers[ i ]._trigger( "out", null, this._uiHash( this ) ); 16053 this.containers[ i ].containerCache.over = 0; 16054 } 16055 } 16056 16057 } 16058 16059 if ( this.placeholder ) { 16060 16061 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, 16062 // it unbinds ALL events from the original node! 16063 if ( this.placeholder[ 0 ].parentNode ) { 16064 this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] ); 16065 } 16066 if ( this.options.helper !== "original" && this.helper && 16067 this.helper[ 0 ].parentNode ) { 16068 this.helper.remove(); 16069 } 16070 16071 $.extend( this, { 16072 helper: null, 16073 dragging: false, 16074 reverting: false, 16075 _noFinalSort: null 16076 } ); 16077 16078 if ( this.domPosition.prev ) { 16079 $( this.domPosition.prev ).after( this.currentItem ); 16080 } else { 16081 $( this.domPosition.parent ).prepend( this.currentItem ); 16082 } 16083 } 16084 16085 return this; 16086 16087 }, 16088 16089 serialize: function( o ) { 16090 16091 var items = this._getItemsAsjQuery( o && o.connected ), 16092 str = []; 16093 o = o || {}; 16094 16095 $( items ).each( function() { 16096 var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" ) 16097 .match( o.expression || ( /(.+)[\-=_](.+)/ ) ); 16098 if ( res ) { 16099 str.push( 16100 ( o.key || res[ 1 ] + "[]" ) + 16101 "=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) ); 16102 } 16103 } ); 16104 16105 if ( !str.length && o.key ) { 16106 str.push( o.key + "=" ); 16107 } 16108 16109 return str.join( "&" ); 16110 16111 }, 16112 16113 toArray: function( o ) { 16114 16115 var items = this._getItemsAsjQuery( o && o.connected ), 16116 ret = []; 16117 16118 o = o || {}; 16119 16120 items.each( function() { 16121 ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" ); 16122 } ); 16123 return ret; 16124 16125 }, 16126 16127 /* Be careful with the following core functions */ 16128 _intersectsWith: function( item ) { 16129 16130 var x1 = this.positionAbs.left, 16131 x2 = x1 + this.helperProportions.width, 16132 y1 = this.positionAbs.top, 16133 y2 = y1 + this.helperProportions.height, 16134 l = item.left, 16135 r = l + item.width, 16136 t = item.top, 16137 b = t + item.height, 16138 dyClick = this.offset.click.top, 16139 dxClick = this.offset.click.left, 16140 isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && 16141 ( y1 + dyClick ) < b ), 16142 isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && 16143 ( x1 + dxClick ) < r ), 16144 isOverElement = isOverElementHeight && isOverElementWidth; 16145 16146 if ( this.options.tolerance === "pointer" || 16147 this.options.forcePointerForContainers || 16148 ( this.options.tolerance !== "pointer" && 16149 this.helperProportions[ this.floating ? "width" : "height" ] > 16150 item[ this.floating ? "width" : "height" ] ) 16151 ) { 16152 return isOverElement; 16153 } else { 16154 16155 return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half 16156 x2 - ( this.helperProportions.width / 2 ) < r && // Left Half 16157 t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half 16158 y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half 16159 16160 } 16161 }, 16162 16163 _intersectsWithPointer: function( item ) { 16164 var verticalDirection, horizontalDirection, 16165 isOverElementHeight = ( this.options.axis === "x" ) || 16166 this._isOverAxis( 16167 this.positionAbs.top + this.offset.click.top, item.top, item.height ), 16168 isOverElementWidth = ( this.options.axis === "y" ) || 16169 this._isOverAxis( 16170 this.positionAbs.left + this.offset.click.left, item.left, item.width ), 16171 isOverElement = isOverElementHeight && isOverElementWidth; 16172 16173 if ( !isOverElement ) { 16174 return false; 16175 } 16176 16177 verticalDirection = this.dragDirection.vertical; 16178 horizontalDirection = this.dragDirection.horizontal; 16179 16180 return this.floating ? 16181 ( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) : 16182 ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) ); 16183 16184 }, 16185 16186 _intersectsWithSides: function( item ) { 16187 16188 var isOverBottomHalf = this._isOverAxis( this.positionAbs.top + 16189 this.offset.click.top, item.top + ( item.height / 2 ), item.height ), 16190 isOverRightHalf = this._isOverAxis( this.positionAbs.left + 16191 this.offset.click.left, item.left + ( item.width / 2 ), item.width ), 16192 verticalDirection = this.dragDirection.vertical, 16193 horizontalDirection = this.dragDirection.horizontal; 16194 16195 if ( this.floating && horizontalDirection ) { 16196 return ( ( horizontalDirection === "right" && isOverRightHalf ) || 16197 ( horizontalDirection === "left" && !isOverRightHalf ) ); 16198 } else { 16199 return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) || 16200 ( verticalDirection === "up" && !isOverBottomHalf ) ); 16201 } 16202 16203 }, 16204 16205 _getDragVerticalDirection: function() { 16206 var delta = this.positionAbs.top - this.lastPositionAbs.top; 16207 return delta !== 0 && ( delta > 0 ? "down" : "up" ); 16208 }, 16209 16210 _getDragHorizontalDirection: function() { 16211 var delta = this.positionAbs.left - this.lastPositionAbs.left; 16212 return delta !== 0 && ( delta > 0 ? "right" : "left" ); 16213 }, 16214 16215 refresh: function( event ) { 16216 this._refreshItems( event ); 16217 this._setHandleClassName(); 16218 this.refreshPositions(); 16219 return this; 16220 }, 16221 16222 _connectWith: function() { 16223 var options = this.options; 16224 return options.connectWith.constructor === String ? 16225 [ options.connectWith ] : 16226 options.connectWith; 16227 }, 16228 16229 _getItemsAsjQuery: function( connected ) { 16230 16231 var i, j, cur, inst, 16232 items = [], 16233 queries = [], 16234 connectWith = this._connectWith(); 16235 16236 if ( connectWith && connected ) { 16237 for ( i = connectWith.length - 1; i >= 0; i-- ) { 16238 cur = $( connectWith[ i ], this.document[ 0 ] ); 16239 for ( j = cur.length - 1; j >= 0; j-- ) { 16240 inst = $.data( cur[ j ], this.widgetFullName ); 16241 if ( inst && inst !== this && !inst.options.disabled ) { 16242 queries.push( [ typeof inst.options.items === "function" ? 16243 inst.options.items.call( inst.element ) : 16244 $( inst.options.items, inst.element ) 16245 .not( ".ui-sortable-helper" ) 16246 .not( ".ui-sortable-placeholder" ), inst ] ); 16247 } 16248 } 16249 } 16250 } 16251 16252 queries.push( [ typeof this.options.items === "function" ? 16253 this.options.items 16254 .call( this.element, null, { options: this.options, item: this.currentItem } ) : 16255 $( this.options.items, this.element ) 16256 .not( ".ui-sortable-helper" ) 16257 .not( ".ui-sortable-placeholder" ), this ] ); 16258 16259 function addItems() { 16260 items.push( this ); 16261 } 16262 for ( i = queries.length - 1; i >= 0; i-- ) { 16263 queries[ i ][ 0 ].each( addItems ); 16264 } 16265 16266 return $( items ); 16267 16268 }, 16269 16270 _removeCurrentsFromItems: function() { 16271 16272 var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" ); 16273 16274 this.items = $.grep( this.items, function( item ) { 16275 for ( var j = 0; j < list.length; j++ ) { 16276 if ( list[ j ] === item.item[ 0 ] ) { 16277 return false; 16278 } 16279 } 16280 return true; 16281 } ); 16282 16283 }, 16284 16285 _refreshItems: function( event ) { 16286 16287 this.items = []; 16288 this.containers = [ this ]; 16289 16290 var i, j, cur, inst, targetData, _queries, item, queriesLength, 16291 items = this.items, 16292 queries = [ [ typeof this.options.items === "function" ? 16293 this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) : 16294 $( this.options.items, this.element ), this ] ], 16295 connectWith = this._connectWith(); 16296 16297 //Shouldn't be run the first time through due to massive slow-down 16298 if ( connectWith && this.ready ) { 16299 for ( i = connectWith.length - 1; i >= 0; i-- ) { 16300 cur = $( connectWith[ i ], this.document[ 0 ] ); 16301 for ( j = cur.length - 1; j >= 0; j-- ) { 16302 inst = $.data( cur[ j ], this.widgetFullName ); 16303 if ( inst && inst !== this && !inst.options.disabled ) { 16304 queries.push( [ typeof inst.options.items === "function" ? 16305 inst.options.items 16306 .call( inst.element[ 0 ], event, { item: this.currentItem } ) : 16307 $( inst.options.items, inst.element ), inst ] ); 16308 this.containers.push( inst ); 16309 } 16310 } 16311 } 16312 } 16313 16314 for ( i = queries.length - 1; i >= 0; i-- ) { 16315 targetData = queries[ i ][ 1 ]; 16316 _queries = queries[ i ][ 0 ]; 16317 16318 for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) { 16319 item = $( _queries[ j ] ); 16320 16321 // Data for target checking (mouse manager) 16322 item.data( this.widgetName + "-item", targetData ); 16323 16324 items.push( { 16325 item: item, 16326 instance: targetData, 16327 width: 0, height: 0, 16328 left: 0, top: 0 16329 } ); 16330 } 16331 } 16332 16333 }, 16334 16335 _refreshItemPositions: function( fast ) { 16336 var i, item, t, p; 16337 16338 for ( i = this.items.length - 1; i >= 0; i-- ) { 16339 item = this.items[ i ]; 16340 16341 //We ignore calculating positions of all connected containers when we're not over them 16342 if ( this.currentContainer && item.instance !== this.currentContainer && 16343 item.item[ 0 ] !== this.currentItem[ 0 ] ) { 16344 continue; 16345 } 16346 16347 t = this.options.toleranceElement ? 16348 $( this.options.toleranceElement, item.item ) : 16349 item.item; 16350 16351 if ( !fast ) { 16352 item.width = t.outerWidth(); 16353 item.height = t.outerHeight(); 16354 } 16355 16356 p = t.offset(); 16357 item.left = p.left; 16358 item.top = p.top; 16359 } 16360 }, 16361 16362 refreshPositions: function( fast ) { 16363 16364 // Determine whether items are being displayed horizontally 16365 this.floating = this.items.length ? 16366 this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) : 16367 false; 16368 16369 // This has to be redone because due to the item being moved out/into the offsetParent, 16370 // the offsetParent's position will change 16371 if ( this.offsetParent && this.helper ) { 16372 this.offset.parent = this._getParentOffset(); 16373 } 16374 16375 this._refreshItemPositions( fast ); 16376 16377 var i, p; 16378 16379 if ( this.options.custom && this.options.custom.refreshContainers ) { 16380 this.options.custom.refreshContainers.call( this ); 16381 } else { 16382 for ( i = this.containers.length - 1; i >= 0; i-- ) { 16383 p = this.containers[ i ].element.offset(); 16384 this.containers[ i ].containerCache.left = p.left; 16385 this.containers[ i ].containerCache.top = p.top; 16386 this.containers[ i ].containerCache.width = 16387 this.containers[ i ].element.outerWidth(); 16388 this.containers[ i ].containerCache.height = 16389 this.containers[ i ].element.outerHeight(); 16390 } 16391 } 16392 16393 return this; 16394 }, 16395 16396 _createPlaceholder: function( that ) { 16397 that = that || this; 16398 var className, nodeName, 16399 o = that.options; 16400 16401 if ( !o.placeholder || o.placeholder.constructor === String ) { 16402 className = o.placeholder; 16403 nodeName = that.currentItem[ 0 ].nodeName.toLowerCase(); 16404 o.placeholder = { 16405 element: function() { 16406 16407 var element = $( "<" + nodeName + ">", that.document[ 0 ] ); 16408 16409 that._addClass( element, "ui-sortable-placeholder", 16410 className || that.currentItem[ 0 ].className ) 16411 ._removeClass( element, "ui-sortable-helper" ); 16412 16413 if ( nodeName === "tbody" ) { 16414 that._createTrPlaceholder( 16415 that.currentItem.find( "tr" ).eq( 0 ), 16416 $( "<tr>", that.document[ 0 ] ).appendTo( element ) 16417 ); 16418 } else if ( nodeName === "tr" ) { 16419 that._createTrPlaceholder( that.currentItem, element ); 16420 } else if ( nodeName === "img" ) { 16421 element.attr( "src", that.currentItem.attr( "src" ) ); 16422 } 16423 16424 if ( !className ) { 16425 element.css( "visibility", "hidden" ); 16426 } 16427 16428 return element; 16429 }, 16430 update: function( container, p ) { 16431 16432 // 1. If a className is set as 'placeholder option, we don't force sizes - 16433 // the class is responsible for that 16434 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a 16435 // class name is specified 16436 if ( className && !o.forcePlaceholderSize ) { 16437 return; 16438 } 16439 16440 // If the element doesn't have a actual height or width by itself (without 16441 // styles coming from a stylesheet), it receives the inline height and width 16442 // from the dragged item. Or, if it's a tbody or tr, it's going to have a height 16443 // anyway since we're populating them with <td>s above, but they're unlikely to 16444 // be the correct height on their own if the row heights are dynamic, so we'll 16445 // always assign the height of the dragged item given forcePlaceholderSize 16446 // is true. 16447 if ( !p.height() || ( o.forcePlaceholderSize && 16448 ( nodeName === "tbody" || nodeName === "tr" ) ) ) { 16449 p.height( 16450 that.currentItem.innerHeight() - 16451 parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) - 16452 parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) ); 16453 } 16454 if ( !p.width() ) { 16455 p.width( 16456 that.currentItem.innerWidth() - 16457 parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) - 16458 parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) ); 16459 } 16460 } 16461 }; 16462 } 16463 16464 //Create the placeholder 16465 that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) ); 16466 16467 //Append it after the actual current item 16468 that.currentItem.after( that.placeholder ); 16469 16470 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) 16471 o.placeholder.update( that, that.placeholder ); 16472 16473 }, 16474 16475 _createTrPlaceholder: function( sourceTr, targetTr ) { 16476 var that = this; 16477 16478 sourceTr.children().each( function() { 16479 $( "<td> </td>", that.document[ 0 ] ) 16480 .attr( "colspan", $( this ).attr( "colspan" ) || 1 ) 16481 .appendTo( targetTr ); 16482 } ); 16483 }, 16484 16485 _contactContainers: function( event ) { 16486 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, 16487 floating, axis, 16488 innermostContainer = null, 16489 innermostIndex = null; 16490 16491 // Get innermost container that intersects with item 16492 for ( i = this.containers.length - 1; i >= 0; i-- ) { 16493 16494 // Never consider a container that's located within the item itself 16495 if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) { 16496 continue; 16497 } 16498 16499 if ( this._intersectsWith( this.containers[ i ].containerCache ) ) { 16500 16501 // If we've already found a container and it's more "inner" than this, then continue 16502 if ( innermostContainer && 16503 $.contains( 16504 this.containers[ i ].element[ 0 ], 16505 innermostContainer.element[ 0 ] ) ) { 16506 continue; 16507 } 16508 16509 innermostContainer = this.containers[ i ]; 16510 innermostIndex = i; 16511 16512 } else { 16513 16514 // container doesn't intersect. trigger "out" event if necessary 16515 if ( this.containers[ i ].containerCache.over ) { 16516 this.containers[ i ]._trigger( "out", event, this._uiHash( this ) ); 16517 this.containers[ i ].containerCache.over = 0; 16518 } 16519 } 16520 16521 } 16522 16523 // If no intersecting containers found, return 16524 if ( !innermostContainer ) { 16525 return; 16526 } 16527 16528 // Move the item into the container if it's not there already 16529 if ( this.containers.length === 1 ) { 16530 if ( !this.containers[ innermostIndex ].containerCache.over ) { 16531 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) ); 16532 this.containers[ innermostIndex ].containerCache.over = 1; 16533 } 16534 } else { 16535 16536 // When entering a new container, we will find the item with the least distance and 16537 // append our item near it 16538 dist = 10000; 16539 itemWithLeastDistance = null; 16540 floating = innermostContainer.floating || this._isFloating( this.currentItem ); 16541 posProperty = floating ? "left" : "top"; 16542 sizeProperty = floating ? "width" : "height"; 16543 axis = floating ? "pageX" : "pageY"; 16544 16545 for ( j = this.items.length - 1; j >= 0; j-- ) { 16546 if ( !$.contains( 16547 this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] ) 16548 ) { 16549 continue; 16550 } 16551 if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) { 16552 continue; 16553 } 16554 16555 cur = this.items[ j ].item.offset()[ posProperty ]; 16556 nearBottom = false; 16557 if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) { 16558 nearBottom = true; 16559 } 16560 16561 if ( Math.abs( event[ axis ] - cur ) < dist ) { 16562 dist = Math.abs( event[ axis ] - cur ); 16563 itemWithLeastDistance = this.items[ j ]; 16564 this.direction = nearBottom ? "up" : "down"; 16565 } 16566 } 16567 16568 //Check if dropOnEmpty is enabled 16569 if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) { 16570 return; 16571 } 16572 16573 if ( this.currentContainer === this.containers[ innermostIndex ] ) { 16574 if ( !this.currentContainer.containerCache.over ) { 16575 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() ); 16576 this.currentContainer.containerCache.over = 1; 16577 } 16578 return; 16579 } 16580 16581 if ( itemWithLeastDistance ) { 16582 this._rearrange( event, itemWithLeastDistance, null, true ); 16583 } else { 16584 this._rearrange( event, null, this.containers[ innermostIndex ].element, true ); 16585 } 16586 this._trigger( "change", event, this._uiHash() ); 16587 this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) ); 16588 this.currentContainer = this.containers[ innermostIndex ]; 16589 16590 //Update the placeholder 16591 this.options.placeholder.update( this.currentContainer, this.placeholder ); 16592 16593 //Update scrollParent 16594 this.scrollParent = this.placeholder.scrollParent(); 16595 16596 //Update overflowOffset 16597 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && 16598 this.scrollParent[ 0 ].tagName !== "HTML" ) { 16599 this.overflowOffset = this.scrollParent.offset(); 16600 } 16601 16602 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) ); 16603 this.containers[ innermostIndex ].containerCache.over = 1; 16604 } 16605 16606 }, 16607 16608 _createHelper: function( event ) { 16609 16610 var o = this.options, 16611 helper = typeof o.helper === "function" ? 16612 $( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) : 16613 ( o.helper === "clone" ? this.currentItem.clone() : this.currentItem ); 16614 16615 //Add the helper to the DOM if that didn't happen already 16616 if ( !helper.parents( "body" ).length ) { 16617 this.appendTo[ 0 ].appendChild( helper[ 0 ] ); 16618 } 16619 16620 if ( helper[ 0 ] === this.currentItem[ 0 ] ) { 16621 this._storedCSS = { 16622 width: this.currentItem[ 0 ].style.width, 16623 height: this.currentItem[ 0 ].style.height, 16624 position: this.currentItem.css( "position" ), 16625 top: this.currentItem.css( "top" ), 16626 left: this.currentItem.css( "left" ) 16627 }; 16628 } 16629 16630 if ( !helper[ 0 ].style.width || o.forceHelperSize ) { 16631 helper.width( this.currentItem.width() ); 16632 } 16633 if ( !helper[ 0 ].style.height || o.forceHelperSize ) { 16634 helper.height( this.currentItem.height() ); 16635 } 16636 16637 return helper; 16638 16639 }, 16640 16641 _adjustOffsetFromHelper: function( obj ) { 16642 if ( typeof obj === "string" ) { 16643 obj = obj.split( " " ); 16644 } 16645 if ( Array.isArray( obj ) ) { 16646 obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 }; 16647 } 16648 if ( "left" in obj ) { 16649 this.offset.click.left = obj.left + this.margins.left; 16650 } 16651 if ( "right" in obj ) { 16652 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 16653 } 16654 if ( "top" in obj ) { 16655 this.offset.click.top = obj.top + this.margins.top; 16656 } 16657 if ( "bottom" in obj ) { 16658 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 16659 } 16660 }, 16661 16662 _getParentOffset: function() { 16663 16664 //Get the offsetParent and cache its position 16665 this.offsetParent = this.helper.offsetParent(); 16666 var po = this.offsetParent.offset(); 16667 16668 // This is a special case where we need to modify a offset calculated on start, since the 16669 // following happened: 16670 // 1. The position of the helper is absolute, so it's position is calculated based on the 16671 // next positioned parent 16672 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't 16673 // the document, which means that the scroll is included in the initial calculation of the 16674 // offset of the parent, and never recalculated upon drag 16675 if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] && 16676 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) { 16677 po.left += this.scrollParent.scrollLeft(); 16678 po.top += this.scrollParent.scrollTop(); 16679 } 16680 16681 // This needs to be actually done for all browsers, since pageX/pageY includes this 16682 // information with an ugly IE fix 16683 if ( this.offsetParent[ 0 ] === this.document[ 0 ].body || 16684 ( this.offsetParent[ 0 ].tagName && 16685 this.offsetParent[ 0 ].tagName.toLowerCase() === "html" && $.ui.ie ) ) { 16686 po = { top: 0, left: 0 }; 16687 } 16688 16689 return { 16690 top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ), 16691 left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 ) 16692 }; 16693 16694 }, 16695 16696 _getRelativeOffset: function() { 16697 16698 if ( this.cssPosition === "relative" ) { 16699 var p = this.currentItem.position(); 16700 return { 16701 top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) + 16702 this.scrollParent.scrollTop(), 16703 left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) + 16704 this.scrollParent.scrollLeft() 16705 }; 16706 } else { 16707 return { top: 0, left: 0 }; 16708 } 16709 16710 }, 16711 16712 _cacheMargins: function() { 16713 this.margins = { 16714 left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ), 16715 top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 ) 16716 }; 16717 }, 16718 16719 _cacheHelperProportions: function() { 16720 this.helperProportions = { 16721 width: this.helper.outerWidth(), 16722 height: this.helper.outerHeight() 16723 }; 16724 }, 16725 16726 _setContainment: function() { 16727 16728 var ce, co, over, 16729 o = this.options; 16730 if ( o.containment === "parent" ) { 16731 o.containment = this.helper[ 0 ].parentNode; 16732 } 16733 if ( o.containment === "document" || o.containment === "window" ) { 16734 this.containment = [ 16735 0 - this.offset.relative.left - this.offset.parent.left, 16736 0 - this.offset.relative.top - this.offset.parent.top, 16737 o.containment === "document" ? 16738 this.document.width() : 16739 this.window.width() - this.helperProportions.width - this.margins.left, 16740 ( o.containment === "document" ? 16741 ( this.document.height() || document.body.parentNode.scrollHeight ) : 16742 this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight 16743 ) - this.helperProportions.height - this.margins.top 16744 ]; 16745 } 16746 16747 if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) { 16748 ce = $( o.containment )[ 0 ]; 16749 co = $( o.containment ).offset(); 16750 over = ( $( ce ).css( "overflow" ) !== "hidden" ); 16751 16752 this.containment = [ 16753 co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) + 16754 ( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left, 16755 co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) + 16756 ( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top, 16757 co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - 16758 ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) - 16759 ( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) - 16760 this.helperProportions.width - this.margins.left, 16761 co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - 16762 ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) - 16763 ( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) - 16764 this.helperProportions.height - this.margins.top 16765 ]; 16766 } 16767 16768 }, 16769 16770 _convertPositionTo: function( d, pos ) { 16771 16772 if ( !pos ) { 16773 pos = this.position; 16774 } 16775 var mod = d === "absolute" ? 1 : -1, 16776 scroll = this.cssPosition === "absolute" && 16777 !( this.scrollParent[ 0 ] !== this.document[ 0 ] && 16778 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? 16779 this.offsetParent : 16780 this.scrollParent, 16781 scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName ); 16782 16783 return { 16784 top: ( 16785 16786 // The absolute mouse position 16787 pos.top + 16788 16789 // Only for relative positioned nodes: Relative offset from element to offset parent 16790 this.offset.relative.top * mod + 16791 16792 // The offsetParent's offset without borders (offset + border) 16793 this.offset.parent.top * mod - 16794 ( ( this.cssPosition === "fixed" ? 16795 -this.scrollParent.scrollTop() : 16796 ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod ) 16797 ), 16798 left: ( 16799 16800 // The absolute mouse position 16801 pos.left + 16802 16803 // Only for relative positioned nodes: Relative offset from element to offset parent 16804 this.offset.relative.left * mod + 16805 16806 // The offsetParent's offset without borders (offset + border) 16807 this.offset.parent.left * mod - 16808 ( ( this.cssPosition === "fixed" ? 16809 -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : 16810 scroll.scrollLeft() ) * mod ) 16811 ) 16812 }; 16813 16814 }, 16815 16816 _generatePosition: function( event ) { 16817 16818 var top, left, 16819 o = this.options, 16820 pageX = event.pageX, 16821 pageY = event.pageY, 16822 scroll = this.cssPosition === "absolute" && 16823 !( this.scrollParent[ 0 ] !== this.document[ 0 ] && 16824 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? 16825 this.offsetParent : 16826 this.scrollParent, 16827 scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName ); 16828 16829 // This is another very weird special case that only happens for relative elements: 16830 // 1. If the css position is relative 16831 // 2. and the scroll parent is the document or similar to the offset parent 16832 // we have to refresh the relative offset during the scroll so there are no jumps 16833 if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] && 16834 this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) { 16835 this.offset.relative = this._getRelativeOffset(); 16836 } 16837 16838 /* 16839 * - Position constraining - 16840 * Constrain the position to a mix of grid, containment. 16841 */ 16842 16843 if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options 16844 16845 if ( this.containment ) { 16846 if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) { 16847 pageX = this.containment[ 0 ] + this.offset.click.left; 16848 } 16849 if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) { 16850 pageY = this.containment[ 1 ] + this.offset.click.top; 16851 } 16852 if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) { 16853 pageX = this.containment[ 2 ] + this.offset.click.left; 16854 } 16855 if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) { 16856 pageY = this.containment[ 3 ] + this.offset.click.top; 16857 } 16858 } 16859 16860 if ( o.grid ) { 16861 top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) / 16862 o.grid[ 1 ] ) * o.grid[ 1 ]; 16863 pageY = this.containment ? 16864 ( ( top - this.offset.click.top >= this.containment[ 1 ] && 16865 top - this.offset.click.top <= this.containment[ 3 ] ) ? 16866 top : 16867 ( ( top - this.offset.click.top >= this.containment[ 1 ] ) ? 16868 top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : 16869 top; 16870 16871 left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) / 16872 o.grid[ 0 ] ) * o.grid[ 0 ]; 16873 pageX = this.containment ? 16874 ( ( left - this.offset.click.left >= this.containment[ 0 ] && 16875 left - this.offset.click.left <= this.containment[ 2 ] ) ? 16876 left : 16877 ( ( left - this.offset.click.left >= this.containment[ 0 ] ) ? 16878 left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : 16879 left; 16880 } 16881 16882 } 16883 16884 return { 16885 top: ( 16886 16887 // The absolute mouse position 16888 pageY - 16889 16890 // Click offset (relative to the element) 16891 this.offset.click.top - 16892 16893 // Only for relative positioned nodes: Relative offset from element to offset parent 16894 this.offset.relative.top - 16895 16896 // The offsetParent's offset without borders (offset + border) 16897 this.offset.parent.top + 16898 ( ( this.cssPosition === "fixed" ? 16899 -this.scrollParent.scrollTop() : 16900 ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) ) 16901 ), 16902 left: ( 16903 16904 // The absolute mouse position 16905 pageX - 16906 16907 // Click offset (relative to the element) 16908 this.offset.click.left - 16909 16910 // Only for relative positioned nodes: Relative offset from element to offset parent 16911 this.offset.relative.left - 16912 16913 // The offsetParent's offset without borders (offset + border) 16914 this.offset.parent.left + 16915 ( ( this.cssPosition === "fixed" ? 16916 -this.scrollParent.scrollLeft() : 16917 scrollIsRootNode ? 0 : scroll.scrollLeft() ) ) 16918 ) 16919 }; 16920 16921 }, 16922 16923 _rearrange: function( event, i, a, hardRefresh ) { 16924 16925 if ( a ) { 16926 a[ 0 ].appendChild( this.placeholder[ 0 ] ); 16927 } else { 16928 i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ], 16929 ( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) ); 16930 } 16931 16932 //Various things done here to improve the performance: 16933 // 1. we create a setTimeout, that calls refreshPositions 16934 // 2. on the instance, we have a counter variable, that get's higher after every append 16935 // 3. on the local scope, we copy the counter variable, and check in the timeout, 16936 // if it's still the same 16937 // 4. this lets only the last addition to the timeout stack through 16938 this.counter = this.counter ? ++this.counter : 1; 16939 var counter = this.counter; 16940 16941 this._delay( function() { 16942 if ( counter === this.counter ) { 16943 16944 //Precompute after each DOM insertion, NOT on mousemove 16945 this.refreshPositions( !hardRefresh ); 16946 } 16947 } ); 16948 16949 }, 16950 16951 _clear: function( event, noPropagation ) { 16952 16953 this.reverting = false; 16954 16955 // We delay all events that have to be triggered to after the point where the placeholder 16956 // has been removed and everything else normalized again 16957 var i, 16958 delayedTriggers = []; 16959 16960 // We first have to update the dom position of the actual currentItem 16961 // Note: don't do it if the current item is already removed (by a user), or it gets 16962 // reappended (see #4088) 16963 if ( !this._noFinalSort && this.currentItem.parent().length ) { 16964 this.placeholder.before( this.currentItem ); 16965 } 16966 this._noFinalSort = null; 16967 16968 if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) { 16969 for ( i in this._storedCSS ) { 16970 if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) { 16971 this._storedCSS[ i ] = ""; 16972 } 16973 } 16974 this.currentItem.css( this._storedCSS ); 16975 this._removeClass( this.currentItem, "ui-sortable-helper" ); 16976 } else { 16977 this.currentItem.show(); 16978 } 16979 16980 if ( this.fromOutside && !noPropagation ) { 16981 delayedTriggers.push( function( event ) { 16982 this._trigger( "receive", event, this._uiHash( this.fromOutside ) ); 16983 } ); 16984 } 16985 if ( ( this.fromOutside || 16986 this.domPosition.prev !== 16987 this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] || 16988 this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) { 16989 16990 // Trigger update callback if the DOM position has changed 16991 delayedTriggers.push( function( event ) { 16992 this._trigger( "update", event, this._uiHash() ); 16993 } ); 16994 } 16995 16996 // Check if the items Container has Changed and trigger appropriate 16997 // events. 16998 if ( this !== this.currentContainer ) { 16999 if ( !noPropagation ) { 17000 delayedTriggers.push( function( event ) { 17001 this._trigger( "remove", event, this._uiHash() ); 17002 } ); 17003 delayedTriggers.push( ( function( c ) { 17004 return function( event ) { 17005 c._trigger( "receive", event, this._uiHash( this ) ); 17006 }; 17007 } ).call( this, this.currentContainer ) ); 17008 delayedTriggers.push( ( function( c ) { 17009 return function( event ) { 17010 c._trigger( "update", event, this._uiHash( this ) ); 17011 }; 17012 } ).call( this, this.currentContainer ) ); 17013 } 17014 } 17015 17016 //Post events to containers 17017 function delayEvent( type, instance, container ) { 17018 return function( event ) { 17019 container._trigger( type, event, instance._uiHash( instance ) ); 17020 }; 17021 } 17022 for ( i = this.containers.length - 1; i >= 0; i-- ) { 17023 if ( !noPropagation ) { 17024 delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) ); 17025 } 17026 if ( this.containers[ i ].containerCache.over ) { 17027 delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) ); 17028 this.containers[ i ].containerCache.over = 0; 17029 } 17030 } 17031 17032 //Do what was originally in plugins 17033 if ( this.storedCursor ) { 17034 this.document.find( "body" ).css( "cursor", this.storedCursor ); 17035 this.storedStylesheet.remove(); 17036 } 17037 if ( this._storedOpacity ) { 17038 this.helper.css( "opacity", this._storedOpacity ); 17039 } 17040 if ( this._storedZIndex ) { 17041 this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex ); 17042 } 17043 17044 this.dragging = false; 17045 17046 if ( !noPropagation ) { 17047 this._trigger( "beforeStop", event, this._uiHash() ); 17048 } 17049 17050 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, 17051 // it unbinds ALL events from the original node! 17052 this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] ); 17053 17054 if ( !this.cancelHelperRemoval ) { 17055 if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) { 17056 this.helper.remove(); 17057 } 17058 this.helper = null; 17059 } 17060 17061 if ( !noPropagation ) { 17062 for ( i = 0; i < delayedTriggers.length; i++ ) { 17063 17064 // Trigger all delayed events 17065 delayedTriggers[ i ].call( this, event ); 17066 } 17067 this._trigger( "stop", event, this._uiHash() ); 17068 } 17069 17070 this.fromOutside = false; 17071 return !this.cancelHelperRemoval; 17072 17073 }, 17074 17075 _trigger: function() { 17076 if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) { 17077 this.cancel(); 17078 } 17079 }, 17080 17081 _uiHash: function( _inst ) { 17082 var inst = _inst || this; 17083 return { 17084 helper: inst.helper, 17085 placeholder: inst.placeholder || $( [] ), 17086 position: inst.position, 17087 originalPosition: inst.originalPosition, 17088 offset: inst.positionAbs, 17089 item: inst.currentItem, 17090 sender: _inst ? _inst.element : null 17091 }; 17092 } 17093 17094} ); 17095 17096 17097/*! 17098 * jQuery UI Spinner 1.13.3 17099 * https://jqueryui.com 17100 * 17101 * Copyright OpenJS Foundation and other contributors 17102 * Released under the MIT license. 17103 * https://jquery.org/license 17104 */ 17105 17106//>>label: Spinner 17107//>>group: Widgets 17108//>>description: Displays buttons to easily input numbers via the keyboard or mouse. 17109//>>docs: https://api.jqueryui.com/spinner/ 17110//>>demos: https://jqueryui.com/spinner/ 17111//>>css.structure: ../../themes/base/core.css 17112//>>css.structure: ../../themes/base/spinner.css 17113//>>css.theme: ../../themes/base/theme.css 17114 17115 17116function spinnerModifier( fn ) { 17117 return function() { 17118 var previous = this.element.val(); 17119 fn.apply( this, arguments ); 17120 this._refresh(); 17121 if ( previous !== this.element.val() ) { 17122 this._trigger( "change" ); 17123 } 17124 }; 17125} 17126 17127$.widget( "ui.spinner", { 17128 version: "1.13.3", 17129 defaultElement: "<input>", 17130 widgetEventPrefix: "spin", 17131 options: { 17132 classes: { 17133 "ui-spinner": "ui-corner-all", 17134 "ui-spinner-down": "ui-corner-br", 17135 "ui-spinner-up": "ui-corner-tr" 17136 }, 17137 culture: null, 17138 icons: { 17139 down: "ui-icon-triangle-1-s", 17140 up: "ui-icon-triangle-1-n" 17141 }, 17142 incremental: true, 17143 max: null, 17144 min: null, 17145 numberFormat: null, 17146 page: 10, 17147 step: 1, 17148 17149 change: null, 17150 spin: null, 17151 start: null, 17152 stop: null 17153 }, 17154 17155 _create: function() { 17156 17157 // handle string values that need to be parsed 17158 this._setOption( "max", this.options.max ); 17159 this._setOption( "min", this.options.min ); 17160 this._setOption( "step", this.options.step ); 17161 17162 // Only format if there is a value, prevents the field from being marked 17163 // as invalid in Firefox, see #9573. 17164 if ( this.value() !== "" ) { 17165 17166 // Format the value, but don't constrain. 17167 this._value( this.element.val(), true ); 17168 } 17169 17170 this._draw(); 17171 this._on( this._events ); 17172 this._refresh(); 17173 17174 // Turning off autocomplete prevents the browser from remembering the 17175 // value when navigating through history, so we re-enable autocomplete 17176 // if the page is unloaded before the widget is destroyed. #7790 17177 this._on( this.window, { 17178 beforeunload: function() { 17179 this.element.removeAttr( "autocomplete" ); 17180 } 17181 } ); 17182 }, 17183 17184 _getCreateOptions: function() { 17185 var options = this._super(); 17186 var element = this.element; 17187 17188 $.each( [ "min", "max", "step" ], function( i, option ) { 17189 var value = element.attr( option ); 17190 if ( value != null && value.length ) { 17191 options[ option ] = value; 17192 } 17193 } ); 17194 17195 return options; 17196 }, 17197 17198 _events: { 17199 keydown: function( event ) { 17200 if ( this._start( event ) && this._keydown( event ) ) { 17201 event.preventDefault(); 17202 } 17203 }, 17204 keyup: "_stop", 17205 focus: function() { 17206 this.previous = this.element.val(); 17207 }, 17208 blur: function( event ) { 17209 if ( this.cancelBlur ) { 17210 delete this.cancelBlur; 17211 return; 17212 } 17213 17214 this._stop(); 17215 this._refresh(); 17216 if ( this.previous !== this.element.val() ) { 17217 this._trigger( "change", event ); 17218 } 17219 }, 17220 mousewheel: function( event, delta ) { 17221 var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ); 17222 var isActive = this.element[ 0 ] === activeElement; 17223 17224 if ( !isActive || !delta ) { 17225 return; 17226 } 17227 17228 if ( !this.spinning && !this._start( event ) ) { 17229 return false; 17230 } 17231 17232 this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event ); 17233 clearTimeout( this.mousewheelTimer ); 17234 this.mousewheelTimer = this._delay( function() { 17235 if ( this.spinning ) { 17236 this._stop( event ); 17237 } 17238 }, 100 ); 17239 event.preventDefault(); 17240 }, 17241 "mousedown .ui-spinner-button": function( event ) { 17242 var previous; 17243 17244 // We never want the buttons to have focus; whenever the user is 17245 // interacting with the spinner, the focus should be on the input. 17246 // If the input is focused then this.previous is properly set from 17247 // when the input first received focus. If the input is not focused 17248 // then we need to set this.previous based on the value before spinning. 17249 previous = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] ) ? 17250 this.previous : this.element.val(); 17251 function checkFocus() { 17252 var isActive = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] ); 17253 if ( !isActive ) { 17254 this.element.trigger( "focus" ); 17255 this.previous = previous; 17256 17257 // support: IE 17258 // IE sets focus asynchronously, so we need to check if focus 17259 // moved off of the input because the user clicked on the button. 17260 this._delay( function() { 17261 this.previous = previous; 17262 } ); 17263 } 17264 } 17265 17266 // Ensure focus is on (or stays on) the text field 17267 event.preventDefault(); 17268 checkFocus.call( this ); 17269 17270 // Support: IE 17271 // IE doesn't prevent moving focus even with event.preventDefault() 17272 // so we set a flag to know when we should ignore the blur event 17273 // and check (again) if focus moved off of the input. 17274 this.cancelBlur = true; 17275 this._delay( function() { 17276 delete this.cancelBlur; 17277 checkFocus.call( this ); 17278 } ); 17279 17280 if ( this._start( event ) === false ) { 17281 return; 17282 } 17283 17284 this._repeat( null, $( event.currentTarget ) 17285 .hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 17286 }, 17287 "mouseup .ui-spinner-button": "_stop", 17288 "mouseenter .ui-spinner-button": function( event ) { 17289 17290 // button will add ui-state-active if mouse was down while mouseleave and kept down 17291 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) { 17292 return; 17293 } 17294 17295 if ( this._start( event ) === false ) { 17296 return false; 17297 } 17298 this._repeat( null, $( event.currentTarget ) 17299 .hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 17300 }, 17301 17302 // TODO: do we really want to consider this a stop? 17303 // shouldn't we just stop the repeater and wait until mouseup before 17304 // we trigger the stop event? 17305 "mouseleave .ui-spinner-button": "_stop" 17306 }, 17307 17308 // Support mobile enhanced option and make backcompat more sane 17309 _enhance: function() { 17310 this.uiSpinner = this.element 17311 .attr( "autocomplete", "off" ) 17312 .wrap( "<span>" ) 17313 .parent() 17314 17315 // Add buttons 17316 .append( 17317 "<a></a><a></a>" 17318 ); 17319 }, 17320 17321 _draw: function() { 17322 this._enhance(); 17323 17324 this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" ); 17325 this._addClass( "ui-spinner-input" ); 17326 17327 this.element.attr( "role", "spinbutton" ); 17328 17329 // Button bindings 17330 this.buttons = this.uiSpinner.children( "a" ) 17331 .attr( "tabIndex", -1 ) 17332 .attr( "aria-hidden", true ) 17333 .button( { 17334 classes: { 17335 "ui-button": "" 17336 } 17337 } ); 17338 17339 // TODO: Right now button does not support classes this is already updated in button PR 17340 this._removeClass( this.buttons, "ui-corner-all" ); 17341 17342 this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" ); 17343 this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" ); 17344 this.buttons.first().button( { 17345 "icon": this.options.icons.up, 17346 "showLabel": false 17347 } ); 17348 this.buttons.last().button( { 17349 "icon": this.options.icons.down, 17350 "showLabel": false 17351 } ); 17352 17353 // IE 6 doesn't understand height: 50% for the buttons 17354 // unless the wrapper has an explicit height 17355 if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) && 17356 this.uiSpinner.height() > 0 ) { 17357 this.uiSpinner.height( this.uiSpinner.height() ); 17358 } 17359 }, 17360 17361 _keydown: function( event ) { 17362 var options = this.options, 17363 keyCode = $.ui.keyCode; 17364 17365 switch ( event.keyCode ) { 17366 case keyCode.UP: 17367 this._repeat( null, 1, event ); 17368 return true; 17369 case keyCode.DOWN: 17370 this._repeat( null, -1, event ); 17371 return true; 17372 case keyCode.PAGE_UP: 17373 this._repeat( null, options.page, event ); 17374 return true; 17375 case keyCode.PAGE_DOWN: 17376 this._repeat( null, -options.page, event ); 17377 return true; 17378 } 17379 17380 return false; 17381 }, 17382 17383 _start: function( event ) { 17384 if ( !this.spinning && this._trigger( "start", event ) === false ) { 17385 return false; 17386 } 17387 17388 if ( !this.counter ) { 17389 this.counter = 1; 17390 } 17391 this.spinning = true; 17392 return true; 17393 }, 17394 17395 _repeat: function( i, steps, event ) { 17396 i = i || 500; 17397 17398 clearTimeout( this.timer ); 17399 this.timer = this._delay( function() { 17400 this._repeat( 40, steps, event ); 17401 }, i ); 17402 17403 this._spin( steps * this.options.step, event ); 17404 }, 17405 17406 _spin: function( step, event ) { 17407 var value = this.value() || 0; 17408 17409 if ( !this.counter ) { 17410 this.counter = 1; 17411 } 17412 17413 value = this._adjustValue( value + step * this._increment( this.counter ) ); 17414 17415 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) { 17416 this._value( value ); 17417 this.counter++; 17418 } 17419 }, 17420 17421 _increment: function( i ) { 17422 var incremental = this.options.incremental; 17423 17424 if ( incremental ) { 17425 return typeof incremental === "function" ? 17426 incremental( i ) : 17427 Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 ); 17428 } 17429 17430 return 1; 17431 }, 17432 17433 _precision: function() { 17434 var precision = this._precisionOf( this.options.step ); 17435 if ( this.options.min !== null ) { 17436 precision = Math.max( precision, this._precisionOf( this.options.min ) ); 17437 } 17438 return precision; 17439 }, 17440 17441 _precisionOf: function( num ) { 17442 var str = num.toString(), 17443 decimal = str.indexOf( "." ); 17444 return decimal === -1 ? 0 : str.length - decimal - 1; 17445 }, 17446 17447 _adjustValue: function( value ) { 17448 var base, aboveMin, 17449 options = this.options; 17450 17451 // Make sure we're at a valid step 17452 // - find out where we are relative to the base (min or 0) 17453 base = options.min !== null ? options.min : 0; 17454 aboveMin = value - base; 17455 17456 // - round to the nearest step 17457 aboveMin = Math.round( aboveMin / options.step ) * options.step; 17458 17459 // - rounding is based on 0, so adjust back to our base 17460 value = base + aboveMin; 17461 17462 // Fix precision from bad JS floating point math 17463 value = parseFloat( value.toFixed( this._precision() ) ); 17464 17465 // Clamp the value 17466 if ( options.max !== null && value > options.max ) { 17467 return options.max; 17468 } 17469 if ( options.min !== null && value < options.min ) { 17470 return options.min; 17471 } 17472 17473 return value; 17474 }, 17475 17476 _stop: function( event ) { 17477 if ( !this.spinning ) { 17478 return; 17479 } 17480 17481 clearTimeout( this.timer ); 17482 clearTimeout( this.mousewheelTimer ); 17483 this.counter = 0; 17484 this.spinning = false; 17485 this._trigger( "stop", event ); 17486 }, 17487 17488 _setOption: function( key, value ) { 17489 var prevValue, first, last; 17490 17491 if ( key === "culture" || key === "numberFormat" ) { 17492 prevValue = this._parse( this.element.val() ); 17493 this.options[ key ] = value; 17494 this.element.val( this._format( prevValue ) ); 17495 return; 17496 } 17497 17498 if ( key === "max" || key === "min" || key === "step" ) { 17499 if ( typeof value === "string" ) { 17500 value = this._parse( value ); 17501 } 17502 } 17503 if ( key === "icons" ) { 17504 first = this.buttons.first().find( ".ui-icon" ); 17505 this._removeClass( first, null, this.options.icons.up ); 17506 this._addClass( first, null, value.up ); 17507 last = this.buttons.last().find( ".ui-icon" ); 17508 this._removeClass( last, null, this.options.icons.down ); 17509 this._addClass( last, null, value.down ); 17510 } 17511 17512 this._super( key, value ); 17513 }, 17514 17515 _setOptionDisabled: function( value ) { 17516 this._super( value ); 17517 17518 this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value ); 17519 this.element.prop( "disabled", !!value ); 17520 this.buttons.button( value ? "disable" : "enable" ); 17521 }, 17522 17523 _setOptions: spinnerModifier( function( options ) { 17524 this._super( options ); 17525 } ), 17526 17527 _parse: function( val ) { 17528 if ( typeof val === "string" && val !== "" ) { 17529 val = window.Globalize && this.options.numberFormat ? 17530 Globalize.parseFloat( val, 10, this.options.culture ) : +val; 17531 } 17532 return val === "" || isNaN( val ) ? null : val; 17533 }, 17534 17535 _format: function( value ) { 17536 if ( value === "" ) { 17537 return ""; 17538 } 17539 return window.Globalize && this.options.numberFormat ? 17540 Globalize.format( value, this.options.numberFormat, this.options.culture ) : 17541 value; 17542 }, 17543 17544 _refresh: function() { 17545 this.element.attr( { 17546 "aria-valuemin": this.options.min, 17547 "aria-valuemax": this.options.max, 17548 17549 // TODO: what should we do with values that can't be parsed? 17550 "aria-valuenow": this._parse( this.element.val() ) 17551 } ); 17552 }, 17553 17554 isValid: function() { 17555 var value = this.value(); 17556 17557 // Null is invalid 17558 if ( value === null ) { 17559 return false; 17560 } 17561 17562 // If value gets adjusted, it's invalid 17563 return value === this._adjustValue( value ); 17564 }, 17565 17566 // Update the value without triggering change 17567 _value: function( value, allowAny ) { 17568 var parsed; 17569 if ( value !== "" ) { 17570 parsed = this._parse( value ); 17571 if ( parsed !== null ) { 17572 if ( !allowAny ) { 17573 parsed = this._adjustValue( parsed ); 17574 } 17575 value = this._format( parsed ); 17576 } 17577 } 17578 this.element.val( value ); 17579 this._refresh(); 17580 }, 17581 17582 _destroy: function() { 17583 this.element 17584 .prop( "disabled", false ) 17585 .removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" ); 17586 17587 this.uiSpinner.replaceWith( this.element ); 17588 }, 17589 17590 stepUp: spinnerModifier( function( steps ) { 17591 this._stepUp( steps ); 17592 } ), 17593 _stepUp: function( steps ) { 17594 if ( this._start() ) { 17595 this._spin( ( steps || 1 ) * this.options.step ); 17596 this._stop(); 17597 } 17598 }, 17599 17600 stepDown: spinnerModifier( function( steps ) { 17601 this._stepDown( steps ); 17602 } ), 17603 _stepDown: function( steps ) { 17604 if ( this._start() ) { 17605 this._spin( ( steps || 1 ) * -this.options.step ); 17606 this._stop(); 17607 } 17608 }, 17609 17610 pageUp: spinnerModifier( function( pages ) { 17611 this._stepUp( ( pages || 1 ) * this.options.page ); 17612 } ), 17613 17614 pageDown: spinnerModifier( function( pages ) { 17615 this._stepDown( ( pages || 1 ) * this.options.page ); 17616 } ), 17617 17618 value: function( newVal ) { 17619 if ( !arguments.length ) { 17620 return this._parse( this.element.val() ); 17621 } 17622 spinnerModifier( this._value ).call( this, newVal ); 17623 }, 17624 17625 widget: function() { 17626 return this.uiSpinner; 17627 } 17628} ); 17629 17630// DEPRECATED 17631// TODO: switch return back to widget declaration at top of file when this is removed 17632if ( $.uiBackCompat !== false ) { 17633 17634 // Backcompat for spinner html extension points 17635 $.widget( "ui.spinner", $.ui.spinner, { 17636 _enhance: function() { 17637 this.uiSpinner = this.element 17638 .attr( "autocomplete", "off" ) 17639 .wrap( this._uiSpinnerHtml() ) 17640 .parent() 17641 17642 // Add buttons 17643 .append( this._buttonHtml() ); 17644 }, 17645 _uiSpinnerHtml: function() { 17646 return "<span>"; 17647 }, 17648 17649 _buttonHtml: function() { 17650 return "<a></a><a></a>"; 17651 } 17652 } ); 17653} 17654 17655var widgetsSpinner = $.ui.spinner; 17656 17657 17658/*! 17659 * jQuery UI Tabs 1.13.3 17660 * https://jqueryui.com 17661 * 17662 * Copyright OpenJS Foundation and other contributors 17663 * Released under the MIT license. 17664 * https://jquery.org/license 17665 */ 17666 17667//>>label: Tabs 17668//>>group: Widgets 17669//>>description: Transforms a set of container elements into a tab structure. 17670//>>docs: https://api.jqueryui.com/tabs/ 17671//>>demos: https://jqueryui.com/tabs/ 17672//>>css.structure: ../../themes/base/core.css 17673//>>css.structure: ../../themes/base/tabs.css 17674//>>css.theme: ../../themes/base/theme.css 17675 17676 17677$.widget( "ui.tabs", { 17678 version: "1.13.3", 17679 delay: 300, 17680 options: { 17681 active: null, 17682 classes: { 17683 "ui-tabs": "ui-corner-all", 17684 "ui-tabs-nav": "ui-corner-all", 17685 "ui-tabs-panel": "ui-corner-bottom", 17686 "ui-tabs-tab": "ui-corner-top" 17687 }, 17688 collapsible: false, 17689 event: "click", 17690 heightStyle: "content", 17691 hide: null, 17692 show: null, 17693 17694 // Callbacks 17695 activate: null, 17696 beforeActivate: null, 17697 beforeLoad: null, 17698 load: null 17699 }, 17700 17701 _isLocal: ( function() { 17702 var rhash = /#.*$/; 17703 17704 return function( anchor ) { 17705 var anchorUrl, locationUrl; 17706 17707 anchorUrl = anchor.href.replace( rhash, "" ); 17708 locationUrl = location.href.replace( rhash, "" ); 17709 17710 // Decoding may throw an error if the URL isn't UTF-8 (#9518) 17711 try { 17712 anchorUrl = decodeURIComponent( anchorUrl ); 17713 } catch ( error ) {} 17714 try { 17715 locationUrl = decodeURIComponent( locationUrl ); 17716 } catch ( error ) {} 17717 17718 return anchor.hash.length > 1 && anchorUrl === locationUrl; 17719 }; 17720 } )(), 17721 17722 _create: function() { 17723 var that = this, 17724 options = this.options; 17725 17726 this.running = false; 17727 17728 this._addClass( "ui-tabs", "ui-widget ui-widget-content" ); 17729 this._toggleClass( "ui-tabs-collapsible", null, options.collapsible ); 17730 17731 this._processTabs(); 17732 options.active = this._initialActive(); 17733 17734 // Take disabling tabs via class attribute from HTML 17735 // into account and update option properly. 17736 if ( Array.isArray( options.disabled ) ) { 17737 options.disabled = $.uniqueSort( options.disabled.concat( 17738 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { 17739 return that.tabs.index( li ); 17740 } ) 17741 ) ).sort(); 17742 } 17743 17744 // Check for length avoids error when initializing empty list 17745 if ( this.options.active !== false && this.anchors.length ) { 17746 this.active = this._findActive( options.active ); 17747 } else { 17748 this.active = $(); 17749 } 17750 17751 this._refresh(); 17752 17753 if ( this.active.length ) { 17754 this.load( options.active ); 17755 } 17756 }, 17757 17758 _initialActive: function() { 17759 var active = this.options.active, 17760 collapsible = this.options.collapsible, 17761 locationHash = location.hash.substring( 1 ); 17762 17763 if ( active === null ) { 17764 17765 // check the fragment identifier in the URL 17766 if ( locationHash ) { 17767 this.tabs.each( function( i, tab ) { 17768 if ( $( tab ).attr( "aria-controls" ) === locationHash ) { 17769 active = i; 17770 return false; 17771 } 17772 } ); 17773 } 17774 17775 // Check for a tab marked active via a class 17776 if ( active === null ) { 17777 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); 17778 } 17779 17780 // No active tab, set to false 17781 if ( active === null || active === -1 ) { 17782 active = this.tabs.length ? 0 : false; 17783 } 17784 } 17785 17786 // Handle numbers: negative, out of range 17787 if ( active !== false ) { 17788 active = this.tabs.index( this.tabs.eq( active ) ); 17789 if ( active === -1 ) { 17790 active = collapsible ? false : 0; 17791 } 17792 } 17793 17794 // Don't allow collapsible: false and active: false 17795 if ( !collapsible && active === false && this.anchors.length ) { 17796 active = 0; 17797 } 17798 17799 return active; 17800 }, 17801 17802 _getCreateEventData: function() { 17803 return { 17804 tab: this.active, 17805 panel: !this.active.length ? $() : this._getPanelForTab( this.active ) 17806 }; 17807 }, 17808 17809 _tabKeydown: function( event ) { 17810 var focusedTab = $( $.ui.safeActiveElement( this.document[ 0 ] ) ).closest( "li" ), 17811 selectedIndex = this.tabs.index( focusedTab ), 17812 goingForward = true; 17813 17814 if ( this._handlePageNav( event ) ) { 17815 return; 17816 } 17817 17818 switch ( event.keyCode ) { 17819 case $.ui.keyCode.RIGHT: 17820 case $.ui.keyCode.DOWN: 17821 selectedIndex++; 17822 break; 17823 case $.ui.keyCode.UP: 17824 case $.ui.keyCode.LEFT: 17825 goingForward = false; 17826 selectedIndex--; 17827 break; 17828 case $.ui.keyCode.END: 17829 selectedIndex = this.anchors.length - 1; 17830 break; 17831 case $.ui.keyCode.HOME: 17832 selectedIndex = 0; 17833 break; 17834 case $.ui.keyCode.SPACE: 17835 17836 // Activate only, no collapsing 17837 event.preventDefault(); 17838 clearTimeout( this.activating ); 17839 this._activate( selectedIndex ); 17840 return; 17841 case $.ui.keyCode.ENTER: 17842 17843 // Toggle (cancel delayed activation, allow collapsing) 17844 event.preventDefault(); 17845 clearTimeout( this.activating ); 17846 17847 // Determine if we should collapse or activate 17848 this._activate( selectedIndex === this.options.active ? false : selectedIndex ); 17849 return; 17850 default: 17851 return; 17852 } 17853 17854 // Focus the appropriate tab, based on which key was pressed 17855 event.preventDefault(); 17856 clearTimeout( this.activating ); 17857 selectedIndex = this._focusNextTab( selectedIndex, goingForward ); 17858 17859 // Navigating with control/command key will prevent automatic activation 17860 if ( !event.ctrlKey && !event.metaKey ) { 17861 17862 // Update aria-selected immediately so that AT think the tab is already selected. 17863 // Otherwise AT may confuse the user by stating that they need to activate the tab, 17864 // but the tab will already be activated by the time the announcement finishes. 17865 focusedTab.attr( "aria-selected", "false" ); 17866 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); 17867 17868 this.activating = this._delay( function() { 17869 this.option( "active", selectedIndex ); 17870 }, this.delay ); 17871 } 17872 }, 17873 17874 _panelKeydown: function( event ) { 17875 if ( this._handlePageNav( event ) ) { 17876 return; 17877 } 17878 17879 // Ctrl+up moves focus to the current tab 17880 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { 17881 event.preventDefault(); 17882 this.active.trigger( "focus" ); 17883 } 17884 }, 17885 17886 // Alt+page up/down moves focus to the previous/next tab (and activates) 17887 _handlePageNav: function( event ) { 17888 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { 17889 this._activate( this._focusNextTab( this.options.active - 1, false ) ); 17890 return true; 17891 } 17892 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { 17893 this._activate( this._focusNextTab( this.options.active + 1, true ) ); 17894 return true; 17895 } 17896 }, 17897 17898 _findNextTab: function( index, goingForward ) { 17899 var lastTabIndex = this.tabs.length - 1; 17900 17901 function constrain() { 17902 if ( index > lastTabIndex ) { 17903 index = 0; 17904 } 17905 if ( index < 0 ) { 17906 index = lastTabIndex; 17907 } 17908 return index; 17909 } 17910 17911 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { 17912 index = goingForward ? index + 1 : index - 1; 17913 } 17914 17915 return index; 17916 }, 17917 17918 _focusNextTab: function( index, goingForward ) { 17919 index = this._findNextTab( index, goingForward ); 17920 this.tabs.eq( index ).trigger( "focus" ); 17921 return index; 17922 }, 17923 17924 _setOption: function( key, value ) { 17925 if ( key === "active" ) { 17926 17927 // _activate() will handle invalid values and update this.options 17928 this._activate( value ); 17929 return; 17930 } 17931 17932 this._super( key, value ); 17933 17934 if ( key === "collapsible" ) { 17935 this._toggleClass( "ui-tabs-collapsible", null, value ); 17936 17937 // Setting collapsible: false while collapsed; open first panel 17938 if ( !value && this.options.active === false ) { 17939 this._activate( 0 ); 17940 } 17941 } 17942 17943 if ( key === "event" ) { 17944 this._setupEvents( value ); 17945 } 17946 17947 if ( key === "heightStyle" ) { 17948 this._setupHeightStyle( value ); 17949 } 17950 }, 17951 17952 _sanitizeSelector: function( hash ) { 17953 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : ""; 17954 }, 17955 17956 refresh: function() { 17957 var options = this.options, 17958 lis = this.tablist.children( ":has(a[href])" ); 17959 17960 // Get disabled tabs from class attribute from HTML 17961 // this will get converted to a boolean if needed in _refresh() 17962 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { 17963 return lis.index( tab ); 17964 } ); 17965 17966 this._processTabs(); 17967 17968 // Was collapsed or no tabs 17969 if ( options.active === false || !this.anchors.length ) { 17970 options.active = false; 17971 this.active = $(); 17972 17973 // was active, but active tab is gone 17974 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { 17975 17976 // all remaining tabs are disabled 17977 if ( this.tabs.length === options.disabled.length ) { 17978 options.active = false; 17979 this.active = $(); 17980 17981 // activate previous tab 17982 } else { 17983 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); 17984 } 17985 17986 // was active, active tab still exists 17987 } else { 17988 17989 // make sure active index is correct 17990 options.active = this.tabs.index( this.active ); 17991 } 17992 17993 this._refresh(); 17994 }, 17995 17996 _refresh: function() { 17997 this._setOptionDisabled( this.options.disabled ); 17998 this._setupEvents( this.options.event ); 17999 this._setupHeightStyle( this.options.heightStyle ); 18000 18001 this.tabs.not( this.active ).attr( { 18002 "aria-selected": "false", 18003 "aria-expanded": "false", 18004 tabIndex: -1 18005 } ); 18006 this.panels.not( this._getPanelForTab( this.active ) ) 18007 .hide() 18008 .attr( { 18009 "aria-hidden": "true" 18010 } ); 18011 18012 // Make sure one tab is in the tab order 18013 if ( !this.active.length ) { 18014 this.tabs.eq( 0 ).attr( "tabIndex", 0 ); 18015 } else { 18016 this.active 18017 .attr( { 18018 "aria-selected": "true", 18019 "aria-expanded": "true", 18020 tabIndex: 0 18021 } ); 18022 this._addClass( this.active, "ui-tabs-active", "ui-state-active" ); 18023 this._getPanelForTab( this.active ) 18024 .show() 18025 .attr( { 18026 "aria-hidden": "false" 18027 } ); 18028 } 18029 }, 18030 18031 _processTabs: function() { 18032 var that = this, 18033 prevTabs = this.tabs, 18034 prevAnchors = this.anchors, 18035 prevPanels = this.panels; 18036 18037 this.tablist = this._getList().attr( "role", "tablist" ); 18038 this._addClass( this.tablist, "ui-tabs-nav", 18039 "ui-helper-reset ui-helper-clearfix ui-widget-header" ); 18040 18041 // Prevent users from focusing disabled tabs via click 18042 this.tablist 18043 .on( "mousedown" + this.eventNamespace, "> li", function( event ) { 18044 if ( $( this ).is( ".ui-state-disabled" ) ) { 18045 event.preventDefault(); 18046 } 18047 } ) 18048 18049 // Support: IE <9 18050 // Preventing the default action in mousedown doesn't prevent IE 18051 // from focusing the element, so if the anchor gets focused, blur. 18052 // We don't have to worry about focusing the previously focused 18053 // element since clicking on a non-focusable element should focus 18054 // the body anyway. 18055 .on( "focus" + this.eventNamespace, ".ui-tabs-anchor", function() { 18056 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) { 18057 this.blur(); 18058 } 18059 } ); 18060 18061 this.tabs = this.tablist.find( "> li:has(a[href])" ) 18062 .attr( { 18063 role: "tab", 18064 tabIndex: -1 18065 } ); 18066 this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" ); 18067 18068 this.anchors = this.tabs.map( function() { 18069 return $( "a", this )[ 0 ]; 18070 } ) 18071 .attr( { 18072 tabIndex: -1 18073 } ); 18074 this._addClass( this.anchors, "ui-tabs-anchor" ); 18075 18076 this.panels = $(); 18077 18078 this.anchors.each( function( i, anchor ) { 18079 var selector, panel, panelId, 18080 anchorId = $( anchor ).uniqueId().attr( "id" ), 18081 tab = $( anchor ).closest( "li" ), 18082 originalAriaControls = tab.attr( "aria-controls" ); 18083 18084 // Inline tab 18085 if ( that._isLocal( anchor ) ) { 18086 selector = anchor.hash; 18087 panelId = selector.substring( 1 ); 18088 panel = that.element.find( that._sanitizeSelector( selector ) ); 18089 18090 // remote tab 18091 } else { 18092 18093 // If the tab doesn't already have aria-controls, 18094 // generate an id by using a throw-away element 18095 panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id; 18096 selector = "#" + panelId; 18097 panel = that.element.find( selector ); 18098 if ( !panel.length ) { 18099 panel = that._createPanel( panelId ); 18100 panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); 18101 } 18102 panel.attr( "aria-live", "polite" ); 18103 } 18104 18105 if ( panel.length ) { 18106 that.panels = that.panels.add( panel ); 18107 } 18108 if ( originalAriaControls ) { 18109 tab.data( "ui-tabs-aria-controls", originalAriaControls ); 18110 } 18111 tab.attr( { 18112 "aria-controls": panelId, 18113 "aria-labelledby": anchorId 18114 } ); 18115 panel.attr( "aria-labelledby", anchorId ); 18116 } ); 18117 18118 this.panels.attr( "role", "tabpanel" ); 18119 this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" ); 18120 18121 // Avoid memory leaks (#10056) 18122 if ( prevTabs ) { 18123 this._off( prevTabs.not( this.tabs ) ); 18124 this._off( prevAnchors.not( this.anchors ) ); 18125 this._off( prevPanels.not( this.panels ) ); 18126 } 18127 }, 18128 18129 // Allow overriding how to find the list for rare usage scenarios (#7715) 18130 _getList: function() { 18131 return this.tablist || this.element.find( "ol, ul" ).eq( 0 ); 18132 }, 18133 18134 _createPanel: function( id ) { 18135 return $( "<div>" ) 18136 .attr( "id", id ) 18137 .data( "ui-tabs-destroy", true ); 18138 }, 18139 18140 _setOptionDisabled: function( disabled ) { 18141 var currentItem, li, i; 18142 18143 if ( Array.isArray( disabled ) ) { 18144 if ( !disabled.length ) { 18145 disabled = false; 18146 } else if ( disabled.length === this.anchors.length ) { 18147 disabled = true; 18148 } 18149 } 18150 18151 // Disable tabs 18152 for ( i = 0; ( li = this.tabs[ i ] ); i++ ) { 18153 currentItem = $( li ); 18154 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { 18155 currentItem.attr( "aria-disabled", "true" ); 18156 this._addClass( currentItem, null, "ui-state-disabled" ); 18157 } else { 18158 currentItem.removeAttr( "aria-disabled" ); 18159 this._removeClass( currentItem, null, "ui-state-disabled" ); 18160 } 18161 } 18162 18163 this.options.disabled = disabled; 18164 18165 this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, 18166 disabled === true ); 18167 }, 18168 18169 _setupEvents: function( event ) { 18170 var events = {}; 18171 if ( event ) { 18172 $.each( event.split( " " ), function( index, eventName ) { 18173 events[ eventName ] = "_eventHandler"; 18174 } ); 18175 } 18176 18177 this._off( this.anchors.add( this.tabs ).add( this.panels ) ); 18178 18179 // Always prevent the default action, even when disabled 18180 this._on( true, this.anchors, { 18181 click: function( event ) { 18182 event.preventDefault(); 18183 } 18184 } ); 18185 this._on( this.anchors, events ); 18186 this._on( this.tabs, { keydown: "_tabKeydown" } ); 18187 this._on( this.panels, { keydown: "_panelKeydown" } ); 18188 18189 this._focusable( this.tabs ); 18190 this._hoverable( this.tabs ); 18191 }, 18192 18193 _setupHeightStyle: function( heightStyle ) { 18194 var maxHeight, 18195 parent = this.element.parent(); 18196 18197 if ( heightStyle === "fill" ) { 18198 maxHeight = parent.height(); 18199 maxHeight -= this.element.outerHeight() - this.element.height(); 18200 18201 this.element.siblings( ":visible" ).each( function() { 18202 var elem = $( this ), 18203 position = elem.css( "position" ); 18204 18205 if ( position === "absolute" || position === "fixed" ) { 18206 return; 18207 } 18208 maxHeight -= elem.outerHeight( true ); 18209 } ); 18210 18211 this.element.children().not( this.panels ).each( function() { 18212 maxHeight -= $( this ).outerHeight( true ); 18213 } ); 18214 18215 this.panels.each( function() { 18216 $( this ).height( Math.max( 0, maxHeight - 18217 $( this ).innerHeight() + $( this ).height() ) ); 18218 } ) 18219 .css( "overflow", "auto" ); 18220 } else if ( heightStyle === "auto" ) { 18221 maxHeight = 0; 18222 this.panels.each( function() { 18223 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); 18224 } ).height( maxHeight ); 18225 } 18226 }, 18227 18228 _eventHandler: function( event ) { 18229 var options = this.options, 18230 active = this.active, 18231 anchor = $( event.currentTarget ), 18232 tab = anchor.closest( "li" ), 18233 clickedIsActive = tab[ 0 ] === active[ 0 ], 18234 collapsing = clickedIsActive && options.collapsible, 18235 toShow = collapsing ? $() : this._getPanelForTab( tab ), 18236 toHide = !active.length ? $() : this._getPanelForTab( active ), 18237 eventData = { 18238 oldTab: active, 18239 oldPanel: toHide, 18240 newTab: collapsing ? $() : tab, 18241 newPanel: toShow 18242 }; 18243 18244 event.preventDefault(); 18245 18246 if ( tab.hasClass( "ui-state-disabled" ) || 18247 18248 // tab is already loading 18249 tab.hasClass( "ui-tabs-loading" ) || 18250 18251 // can't switch durning an animation 18252 this.running || 18253 18254 // click on active header, but not collapsible 18255 ( clickedIsActive && !options.collapsible ) || 18256 18257 // allow canceling activation 18258 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 18259 return; 18260 } 18261 18262 options.active = collapsing ? false : this.tabs.index( tab ); 18263 18264 this.active = clickedIsActive ? $() : tab; 18265 if ( this.xhr ) { 18266 this.xhr.abort(); 18267 } 18268 18269 if ( !toHide.length && !toShow.length ) { 18270 $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); 18271 } 18272 18273 if ( toShow.length ) { 18274 this.load( this.tabs.index( tab ), event ); 18275 } 18276 this._toggle( event, eventData ); 18277 }, 18278 18279 // Handles show/hide for selecting tabs 18280 _toggle: function( event, eventData ) { 18281 var that = this, 18282 toShow = eventData.newPanel, 18283 toHide = eventData.oldPanel; 18284 18285 this.running = true; 18286 18287 function complete() { 18288 that.running = false; 18289 that._trigger( "activate", event, eventData ); 18290 } 18291 18292 function show() { 18293 that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" ); 18294 18295 if ( toShow.length && that.options.show ) { 18296 that._show( toShow, that.options.show, complete ); 18297 } else { 18298 toShow.show(); 18299 complete(); 18300 } 18301 } 18302 18303 // Start out by hiding, then showing, then completing 18304 if ( toHide.length && this.options.hide ) { 18305 this._hide( toHide, this.options.hide, function() { 18306 that._removeClass( eventData.oldTab.closest( "li" ), 18307 "ui-tabs-active", "ui-state-active" ); 18308 show(); 18309 } ); 18310 } else { 18311 this._removeClass( eventData.oldTab.closest( "li" ), 18312 "ui-tabs-active", "ui-state-active" ); 18313 toHide.hide(); 18314 show(); 18315 } 18316 18317 toHide.attr( "aria-hidden", "true" ); 18318 eventData.oldTab.attr( { 18319 "aria-selected": "false", 18320 "aria-expanded": "false" 18321 } ); 18322 18323 // If we're switching tabs, remove the old tab from the tab order. 18324 // If we're opening from collapsed state, remove the previous tab from the tab order. 18325 // If we're collapsing, then keep the collapsing tab in the tab order. 18326 if ( toShow.length && toHide.length ) { 18327 eventData.oldTab.attr( "tabIndex", -1 ); 18328 } else if ( toShow.length ) { 18329 this.tabs.filter( function() { 18330 return $( this ).attr( "tabIndex" ) === 0; 18331 } ) 18332 .attr( "tabIndex", -1 ); 18333 } 18334 18335 toShow.attr( "aria-hidden", "false" ); 18336 eventData.newTab.attr( { 18337 "aria-selected": "true", 18338 "aria-expanded": "true", 18339 tabIndex: 0 18340 } ); 18341 }, 18342 18343 _activate: function( index ) { 18344 var anchor, 18345 active = this._findActive( index ); 18346 18347 // Trying to activate the already active panel 18348 if ( active[ 0 ] === this.active[ 0 ] ) { 18349 return; 18350 } 18351 18352 // Trying to collapse, simulate a click on the current active header 18353 if ( !active.length ) { 18354 active = this.active; 18355 } 18356 18357 anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; 18358 this._eventHandler( { 18359 target: anchor, 18360 currentTarget: anchor, 18361 preventDefault: $.noop 18362 } ); 18363 }, 18364 18365 _findActive: function( index ) { 18366 return index === false ? $() : this.tabs.eq( index ); 18367 }, 18368 18369 _getIndex: function( index ) { 18370 18371 // meta-function to give users option to provide a href string instead of a numerical index. 18372 if ( typeof index === "string" ) { 18373 index = this.anchors.index( this.anchors.filter( "[href$='" + 18374 $.escapeSelector( index ) + "']" ) ); 18375 } 18376 18377 return index; 18378 }, 18379 18380 _destroy: function() { 18381 if ( this.xhr ) { 18382 this.xhr.abort(); 18383 } 18384 18385 this.tablist 18386 .removeAttr( "role" ) 18387 .off( this.eventNamespace ); 18388 18389 this.anchors 18390 .removeAttr( "role tabIndex" ) 18391 .removeUniqueId(); 18392 18393 this.tabs.add( this.panels ).each( function() { 18394 if ( $.data( this, "ui-tabs-destroy" ) ) { 18395 $( this ).remove(); 18396 } else { 18397 $( this ).removeAttr( "role tabIndex " + 18398 "aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" ); 18399 } 18400 } ); 18401 18402 this.tabs.each( function() { 18403 var li = $( this ), 18404 prev = li.data( "ui-tabs-aria-controls" ); 18405 if ( prev ) { 18406 li 18407 .attr( "aria-controls", prev ) 18408 .removeData( "ui-tabs-aria-controls" ); 18409 } else { 18410 li.removeAttr( "aria-controls" ); 18411 } 18412 } ); 18413 18414 this.panels.show(); 18415 18416 if ( this.options.heightStyle !== "content" ) { 18417 this.panels.css( "height", "" ); 18418 } 18419 }, 18420 18421 enable: function( index ) { 18422 var disabled = this.options.disabled; 18423 if ( disabled === false ) { 18424 return; 18425 } 18426 18427 if ( index === undefined ) { 18428 disabled = false; 18429 } else { 18430 index = this._getIndex( index ); 18431 if ( Array.isArray( disabled ) ) { 18432 disabled = $.map( disabled, function( num ) { 18433 return num !== index ? num : null; 18434 } ); 18435 } else { 18436 disabled = $.map( this.tabs, function( li, num ) { 18437 return num !== index ? num : null; 18438 } ); 18439 } 18440 } 18441 this._setOptionDisabled( disabled ); 18442 }, 18443 18444 disable: function( index ) { 18445 var disabled = this.options.disabled; 18446 if ( disabled === true ) { 18447 return; 18448 } 18449 18450 if ( index === undefined ) { 18451 disabled = true; 18452 } else { 18453 index = this._getIndex( index ); 18454 if ( $.inArray( index, disabled ) !== -1 ) { 18455 return; 18456 } 18457 if ( Array.isArray( disabled ) ) { 18458 disabled = $.merge( [ index ], disabled ).sort(); 18459 } else { 18460 disabled = [ index ]; 18461 } 18462 } 18463 this._setOptionDisabled( disabled ); 18464 }, 18465 18466 load: function( index, event ) { 18467 index = this._getIndex( index ); 18468 var that = this, 18469 tab = this.tabs.eq( index ), 18470 anchor = tab.find( ".ui-tabs-anchor" ), 18471 panel = this._getPanelForTab( tab ), 18472 eventData = { 18473 tab: tab, 18474 panel: panel 18475 }, 18476 complete = function( jqXHR, status ) { 18477 if ( status === "abort" ) { 18478 that.panels.stop( false, true ); 18479 } 18480 18481 that._removeClass( tab, "ui-tabs-loading" ); 18482 panel.removeAttr( "aria-busy" ); 18483 18484 if ( jqXHR === that.xhr ) { 18485 delete that.xhr; 18486 } 18487 }; 18488 18489 // Not remote 18490 if ( this._isLocal( anchor[ 0 ] ) ) { 18491 return; 18492 } 18493 18494 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); 18495 18496 // Support: jQuery <1.8 18497 // jQuery <1.8 returns false if the request is canceled in beforeSend, 18498 // but as of 1.8, $.ajax() always returns a jqXHR object. 18499 if ( this.xhr && this.xhr.statusText !== "canceled" ) { 18500 this._addClass( tab, "ui-tabs-loading" ); 18501 panel.attr( "aria-busy", "true" ); 18502 18503 this.xhr 18504 .done( function( response, status, jqXHR ) { 18505 18506 // support: jQuery <1.8 18507 // https://bugs.jquery.com/ticket/11778 18508 setTimeout( function() { 18509 panel.html( response ); 18510 that._trigger( "load", event, eventData ); 18511 18512 complete( jqXHR, status ); 18513 }, 1 ); 18514 } ) 18515 .fail( function( jqXHR, status ) { 18516 18517 // support: jQuery <1.8 18518 // https://bugs.jquery.com/ticket/11778 18519 setTimeout( function() { 18520 complete( jqXHR, status ); 18521 }, 1 ); 18522 } ); 18523 } 18524 }, 18525 18526 _ajaxSettings: function( anchor, event, eventData ) { 18527 var that = this; 18528 return { 18529 18530 // Support: IE <11 only 18531 // Strip any hash that exists to prevent errors with the Ajax request 18532 url: anchor.attr( "href" ).replace( /#.*$/, "" ), 18533 beforeSend: function( jqXHR, settings ) { 18534 return that._trigger( "beforeLoad", event, 18535 $.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) ); 18536 } 18537 }; 18538 }, 18539 18540 _getPanelForTab: function( tab ) { 18541 var id = $( tab ).attr( "aria-controls" ); 18542 return this.element.find( this._sanitizeSelector( "#" + id ) ); 18543 } 18544} ); 18545 18546// DEPRECATED 18547// TODO: Switch return back to widget declaration at top of file when this is removed 18548if ( $.uiBackCompat !== false ) { 18549 18550 // Backcompat for ui-tab class (now ui-tabs-tab) 18551 $.widget( "ui.tabs", $.ui.tabs, { 18552 _processTabs: function() { 18553 this._superApply( arguments ); 18554 this._addClass( this.tabs, "ui-tab" ); 18555 } 18556 } ); 18557} 18558 18559var widgetsTabs = $.ui.tabs; 18560 18561 18562/*! 18563 * jQuery UI Tooltip 1.13.3 18564 * https://jqueryui.com 18565 * 18566 * Copyright OpenJS Foundation and other contributors 18567 * Released under the MIT license. 18568 * https://jquery.org/license 18569 */ 18570 18571//>>label: Tooltip 18572//>>group: Widgets 18573//>>description: Shows additional information for any element on hover or focus. 18574//>>docs: https://api.jqueryui.com/tooltip/ 18575//>>demos: https://jqueryui.com/tooltip/ 18576//>>css.structure: ../../themes/base/core.css 18577//>>css.structure: ../../themes/base/tooltip.css 18578//>>css.theme: ../../themes/base/theme.css 18579 18580 18581$.widget( "ui.tooltip", { 18582 version: "1.13.3", 18583 options: { 18584 classes: { 18585 "ui-tooltip": "ui-corner-all ui-widget-shadow" 18586 }, 18587 content: function() { 18588 var title = $( this ).attr( "title" ); 18589 18590 // Escape title, since we're going from an attribute to raw HTML 18591 return $( "<a>" ).text( title ).html(); 18592 }, 18593 hide: true, 18594 18595 // Disabled elements have inconsistent behavior across browsers (#8661) 18596 items: "[title]:not([disabled])", 18597 position: { 18598 my: "left top+15", 18599 at: "left bottom", 18600 collision: "flipfit flip" 18601 }, 18602 show: true, 18603 track: false, 18604 18605 // Callbacks 18606 close: null, 18607 open: null 18608 }, 18609 18610 _addDescribedBy: function( elem, id ) { 18611 var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ); 18612 describedby.push( id ); 18613 elem 18614 .data( "ui-tooltip-id", id ) 18615 .attr( "aria-describedby", String.prototype.trim.call( describedby.join( " " ) ) ); 18616 }, 18617 18618 _removeDescribedBy: function( elem ) { 18619 var id = elem.data( "ui-tooltip-id" ), 18620 describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ), 18621 index = $.inArray( id, describedby ); 18622 18623 if ( index !== -1 ) { 18624 describedby.splice( index, 1 ); 18625 } 18626 18627 elem.removeData( "ui-tooltip-id" ); 18628 describedby = String.prototype.trim.call( describedby.join( " " ) ); 18629 if ( describedby ) { 18630 elem.attr( "aria-describedby", describedby ); 18631 } else { 18632 elem.removeAttr( "aria-describedby" ); 18633 } 18634 }, 18635 18636 _create: function() { 18637 this._on( { 18638 mouseover: "open", 18639 focusin: "open" 18640 } ); 18641 18642 // IDs of generated tooltips, needed for destroy 18643 this.tooltips = {}; 18644 18645 // IDs of parent tooltips where we removed the title attribute 18646 this.parents = {}; 18647 18648 // Append the aria-live region so tooltips announce correctly 18649 this.liveRegion = $( "<div>" ) 18650 .attr( { 18651 role: "log", 18652 "aria-live": "assertive", 18653 "aria-relevant": "additions" 18654 } ) 18655 .appendTo( this.document[ 0 ].body ); 18656 this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" ); 18657 18658 this.disabledTitles = $( [] ); 18659 }, 18660 18661 _setOption: function( key, value ) { 18662 var that = this; 18663 18664 this._super( key, value ); 18665 18666 if ( key === "content" ) { 18667 $.each( this.tooltips, function( id, tooltipData ) { 18668 that._updateContent( tooltipData.element ); 18669 } ); 18670 } 18671 }, 18672 18673 _setOptionDisabled: function( value ) { 18674 this[ value ? "_disable" : "_enable" ](); 18675 }, 18676 18677 _disable: function() { 18678 var that = this; 18679 18680 // Close open tooltips 18681 $.each( this.tooltips, function( id, tooltipData ) { 18682 var event = $.Event( "blur" ); 18683 event.target = event.currentTarget = tooltipData.element[ 0 ]; 18684 that.close( event, true ); 18685 } ); 18686 18687 // Remove title attributes to prevent native tooltips 18688 this.disabledTitles = this.disabledTitles.add( 18689 this.element.find( this.options.items ).addBack() 18690 .filter( function() { 18691 var element = $( this ); 18692 if ( element.is( "[title]" ) ) { 18693 return element 18694 .data( "ui-tooltip-title", element.attr( "title" ) ) 18695 .removeAttr( "title" ); 18696 } 18697 } ) 18698 ); 18699 }, 18700 18701 _enable: function() { 18702 18703 // restore title attributes 18704 this.disabledTitles.each( function() { 18705 var element = $( this ); 18706 if ( element.data( "ui-tooltip-title" ) ) { 18707 element.attr( "title", element.data( "ui-tooltip-title" ) ); 18708 } 18709 } ); 18710 this.disabledTitles = $( [] ); 18711 }, 18712 18713 open: function( event ) { 18714 var that = this, 18715 target = $( event ? event.target : this.element ) 18716 18717 // we need closest here due to mouseover bubbling, 18718 // but always pointing at the same event target 18719 .closest( this.options.items ); 18720 18721 // No element to show a tooltip for or the tooltip is already open 18722 if ( !target.length || target.data( "ui-tooltip-id" ) ) { 18723 return; 18724 } 18725 18726 if ( target.attr( "title" ) ) { 18727 target.data( "ui-tooltip-title", target.attr( "title" ) ); 18728 } 18729 18730 target.data( "ui-tooltip-open", true ); 18731 18732 // Kill parent tooltips, custom or native, for hover 18733 if ( event && event.type === "mouseover" ) { 18734 target.parents().each( function() { 18735 var parent = $( this ), 18736 blurEvent; 18737 if ( parent.data( "ui-tooltip-open" ) ) { 18738 blurEvent = $.Event( "blur" ); 18739 blurEvent.target = blurEvent.currentTarget = this; 18740 that.close( blurEvent, true ); 18741 } 18742 if ( parent.attr( "title" ) ) { 18743 parent.uniqueId(); 18744 that.parents[ this.id ] = { 18745 element: this, 18746 title: parent.attr( "title" ) 18747 }; 18748 parent.attr( "title", "" ); 18749 } 18750 } ); 18751 } 18752 18753 this._registerCloseHandlers( event, target ); 18754 this._updateContent( target, event ); 18755 }, 18756 18757 _updateContent: function( target, event ) { 18758 var content, 18759 contentOption = this.options.content, 18760 that = this, 18761 eventType = event ? event.type : null; 18762 18763 if ( typeof contentOption === "string" || contentOption.nodeType || 18764 contentOption.jquery ) { 18765 return this._open( event, target, contentOption ); 18766 } 18767 18768 content = contentOption.call( target[ 0 ], function( response ) { 18769 18770 // IE may instantly serve a cached response for ajax requests 18771 // delay this call to _open so the other call to _open runs first 18772 that._delay( function() { 18773 18774 // Ignore async response if tooltip was closed already 18775 if ( !target.data( "ui-tooltip-open" ) ) { 18776 return; 18777 } 18778 18779 // JQuery creates a special event for focusin when it doesn't 18780 // exist natively. To improve performance, the native event 18781 // object is reused and the type is changed. Therefore, we can't 18782 // rely on the type being correct after the event finished 18783 // bubbling, so we set it back to the previous value. (#8740) 18784 if ( event ) { 18785 event.type = eventType; 18786 } 18787 this._open( event, target, response ); 18788 } ); 18789 } ); 18790 if ( content ) { 18791 this._open( event, target, content ); 18792 } 18793 }, 18794 18795 _open: function( event, target, content ) { 18796 var tooltipData, tooltip, delayedShow, a11yContent, 18797 positionOption = $.extend( {}, this.options.position ); 18798 18799 if ( !content ) { 18800 return; 18801 } 18802 18803 // Content can be updated multiple times. If the tooltip already 18804 // exists, then just update the content and bail. 18805 tooltipData = this._find( target ); 18806 if ( tooltipData ) { 18807 tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content ); 18808 return; 18809 } 18810 18811 // If we have a title, clear it to prevent the native tooltip 18812 // we have to check first to avoid defining a title if none exists 18813 // (we don't want to cause an element to start matching [title]) 18814 // 18815 // We use removeAttr only for key events, to allow IE to export the correct 18816 // accessible attributes. For mouse events, set to empty string to avoid 18817 // native tooltip showing up (happens only when removing inside mouseover). 18818 if ( target.is( "[title]" ) ) { 18819 if ( event && event.type === "mouseover" ) { 18820 target.attr( "title", "" ); 18821 } else { 18822 target.removeAttr( "title" ); 18823 } 18824 } 18825 18826 tooltipData = this._tooltip( target ); 18827 tooltip = tooltipData.tooltip; 18828 this._addDescribedBy( target, tooltip.attr( "id" ) ); 18829 tooltip.find( ".ui-tooltip-content" ).html( content ); 18830 18831 // Support: Voiceover on OS X, JAWS on IE <= 9 18832 // JAWS announces deletions even when aria-relevant="additions" 18833 // Voiceover will sometimes re-read the entire log region's contents from the beginning 18834 this.liveRegion.children().hide(); 18835 a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() ); 18836 a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" ); 18837 a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" ); 18838 a11yContent.appendTo( this.liveRegion ); 18839 18840 function position( event ) { 18841 positionOption.of = event; 18842 if ( tooltip.is( ":hidden" ) ) { 18843 return; 18844 } 18845 tooltip.position( positionOption ); 18846 } 18847 if ( this.options.track && event && /^mouse/.test( event.type ) ) { 18848 this._on( this.document, { 18849 mousemove: position 18850 } ); 18851 18852 // trigger once to override element-relative positioning 18853 position( event ); 18854 } else { 18855 tooltip.position( $.extend( { 18856 of: target 18857 }, this.options.position ) ); 18858 } 18859 18860 tooltip.hide(); 18861 18862 this._show( tooltip, this.options.show ); 18863 18864 // Handle tracking tooltips that are shown with a delay (#8644). As soon 18865 // as the tooltip is visible, position the tooltip using the most recent 18866 // event. 18867 // Adds the check to add the timers only when both delay and track options are set (#14682) 18868 if ( this.options.track && this.options.show && this.options.show.delay ) { 18869 delayedShow = this.delayedShow = setInterval( function() { 18870 if ( tooltip.is( ":visible" ) ) { 18871 position( positionOption.of ); 18872 clearInterval( delayedShow ); 18873 } 18874 }, 13 ); 18875 } 18876 18877 this._trigger( "open", event, { tooltip: tooltip } ); 18878 }, 18879 18880 _registerCloseHandlers: function( event, target ) { 18881 var events = { 18882 keyup: function( event ) { 18883 if ( event.keyCode === $.ui.keyCode.ESCAPE ) { 18884 var fakeEvent = $.Event( event ); 18885 fakeEvent.currentTarget = target[ 0 ]; 18886 this.close( fakeEvent, true ); 18887 } 18888 } 18889 }; 18890 18891 // Only bind remove handler for delegated targets. Non-delegated 18892 // tooltips will handle this in destroy. 18893 if ( target[ 0 ] !== this.element[ 0 ] ) { 18894 events.remove = function() { 18895 var targetElement = this._find( target ); 18896 if ( targetElement ) { 18897 this._removeTooltip( targetElement.tooltip ); 18898 } 18899 }; 18900 } 18901 18902 if ( !event || event.type === "mouseover" ) { 18903 events.mouseleave = "close"; 18904 } 18905 if ( !event || event.type === "focusin" ) { 18906 events.focusout = "close"; 18907 } 18908 this._on( true, target, events ); 18909 }, 18910 18911 close: function( event ) { 18912 var tooltip, 18913 that = this, 18914 target = $( event ? event.currentTarget : this.element ), 18915 tooltipData = this._find( target ); 18916 18917 // The tooltip may already be closed 18918 if ( !tooltipData ) { 18919 18920 // We set ui-tooltip-open immediately upon open (in open()), but only set the 18921 // additional data once there's actually content to show (in _open()). So even if the 18922 // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in 18923 // the period between open() and _open(). 18924 target.removeData( "ui-tooltip-open" ); 18925 return; 18926 } 18927 18928 tooltip = tooltipData.tooltip; 18929 18930 // Disabling closes the tooltip, so we need to track when we're closing 18931 // to avoid an infinite loop in case the tooltip becomes disabled on close 18932 if ( tooltipData.closing ) { 18933 return; 18934 } 18935 18936 // Clear the interval for delayed tracking tooltips 18937 clearInterval( this.delayedShow ); 18938 18939 // Only set title if we had one before (see comment in _open()) 18940 // If the title attribute has changed since open(), don't restore 18941 if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) { 18942 target.attr( "title", target.data( "ui-tooltip-title" ) ); 18943 } 18944 18945 this._removeDescribedBy( target ); 18946 18947 tooltipData.hiding = true; 18948 tooltip.stop( true ); 18949 this._hide( tooltip, this.options.hide, function() { 18950 that._removeTooltip( $( this ) ); 18951 } ); 18952 18953 target.removeData( "ui-tooltip-open" ); 18954 this._off( target, "mouseleave focusout keyup" ); 18955 18956 // Remove 'remove' binding only on delegated targets 18957 if ( target[ 0 ] !== this.element[ 0 ] ) { 18958 this._off( target, "remove" ); 18959 } 18960 this._off( this.document, "mousemove" ); 18961 18962 if ( event && event.type === "mouseleave" ) { 18963 $.each( this.parents, function( id, parent ) { 18964 $( parent.element ).attr( "title", parent.title ); 18965 delete that.parents[ id ]; 18966 } ); 18967 } 18968 18969 tooltipData.closing = true; 18970 this._trigger( "close", event, { tooltip: tooltip } ); 18971 if ( !tooltipData.hiding ) { 18972 tooltipData.closing = false; 18973 } 18974 }, 18975 18976 _tooltip: function( element ) { 18977 var tooltip = $( "<div>" ).attr( "role", "tooltip" ), 18978 content = $( "<div>" ).appendTo( tooltip ), 18979 id = tooltip.uniqueId().attr( "id" ); 18980 18981 this._addClass( content, "ui-tooltip-content" ); 18982 this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" ); 18983 18984 tooltip.appendTo( this._appendTo( element ) ); 18985 18986 return this.tooltips[ id ] = { 18987 element: element, 18988 tooltip: tooltip 18989 }; 18990 }, 18991 18992 _find: function( target ) { 18993 var id = target.data( "ui-tooltip-id" ); 18994 return id ? this.tooltips[ id ] : null; 18995 }, 18996 18997 _removeTooltip: function( tooltip ) { 18998 18999 // Clear the interval for delayed tracking tooltips 19000 clearInterval( this.delayedShow ); 19001 19002 tooltip.remove(); 19003 delete this.tooltips[ tooltip.attr( "id" ) ]; 19004 }, 19005 19006 _appendTo: function( target ) { 19007 var element = target.closest( ".ui-front, dialog" ); 19008 19009 if ( !element.length ) { 19010 element = this.document[ 0 ].body; 19011 } 19012 19013 return element; 19014 }, 19015 19016 _destroy: function() { 19017 var that = this; 19018 19019 // Close open tooltips 19020 $.each( this.tooltips, function( id, tooltipData ) { 19021 19022 // Delegate to close method to handle common cleanup 19023 var event = $.Event( "blur" ), 19024 element = tooltipData.element; 19025 event.target = event.currentTarget = element[ 0 ]; 19026 that.close( event, true ); 19027 19028 // Remove immediately; destroying an open tooltip doesn't use the 19029 // hide animation 19030 $( "#" + id ).remove(); 19031 19032 // Restore the title 19033 if ( element.data( "ui-tooltip-title" ) ) { 19034 19035 // If the title attribute has changed since open(), don't restore 19036 if ( !element.attr( "title" ) ) { 19037 element.attr( "title", element.data( "ui-tooltip-title" ) ); 19038 } 19039 element.removeData( "ui-tooltip-title" ); 19040 } 19041 } ); 19042 this.liveRegion.remove(); 19043 } 19044} ); 19045 19046// DEPRECATED 19047// TODO: Switch return back to widget declaration at top of file when this is removed 19048if ( $.uiBackCompat !== false ) { 19049 19050 // Backcompat for tooltipClass option 19051 $.widget( "ui.tooltip", $.ui.tooltip, { 19052 options: { 19053 tooltipClass: null 19054 }, 19055 _tooltip: function() { 19056 var tooltipData = this._superApply( arguments ); 19057 if ( this.options.tooltipClass ) { 19058 tooltipData.tooltip.addClass( this.options.tooltipClass ); 19059 } 19060 return tooltipData; 19061 } 19062 } ); 19063} 19064 19065var widgetsTooltip = $.ui.tooltip; 19066 19067 19068 19069 19070} );
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.