vendor: 4,941 bytes, lines 1-142
1/*! jQuery UI - v1.14.0 - 2024-08-05 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.14.0"; 24 25 26/*! 27 * jQuery UI Widget 1.14.0 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
vendor: 316,795 bytes, lines 143-10814
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.14.0 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.14.0 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( function( dataName ) { 1282 return function( elem ) { 1283 return !!$.data( elem, dataName ); 1284 }; 1285 } ) 1286} ); 1287 1288/*! 1289 * jQuery UI Disable Selection 1.14.0 1290 * https://jqueryui.com 1291 * 1292 * Copyright OpenJS Foundation and other contributors 1293 * Released under the MIT license. 1294 * https://jquery.org/license 1295 */ 1296 1297//>>label: disableSelection 1298//>>group: Core 1299//>>description: Disable selection of text content within the set of matched elements. 1300//>>docs: https://api.jqueryui.com/disableSelection/ 1301 1302// This file is deprecated 1303 1304var disableSelection = $.fn.extend( { 1305 disableSelection: ( function() { 1306 var eventType = "onselectstart" in document.createElement( "div" ) ? 1307 "selectstart" : 1308 "mousedown"; 1309 1310 return function() { 1311 return this.on( eventType + ".ui-disableSelection", function( event ) { 1312 event.preventDefault(); 1313 } ); 1314 }; 1315 } )(), 1316 1317 enableSelection: function() { 1318 return this.off( ".ui-disableSelection" ); 1319 } 1320} ); 1321 1322 1323 1324// Create a local jQuery because jQuery Color relies on it and the 1325// global may not exist with AMD and a custom build (#10199). 1326// This module is a noop if used as a regular AMD module. 1327// eslint-disable-next-line no-unused-vars 1328var jQuery = $; 1329 1330 1331/*! 1332 * jQuery Color Animations v3.0.0 1333 * https://github.com/jquery/jquery-color 1334 * 1335 * Copyright OpenJS Foundation and other contributors 1336 * Released under the MIT license. 1337 * https://jquery.org/license 1338 * 1339 * Date: Wed May 15 16:49:44 2024 +0200 1340 */ 1341 1342 1343 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " + 1344 "borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", 1345 1346 class2type = {}, 1347 toString = class2type.toString, 1348 1349 // plusequals test for += 100 -= 100 1350 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, 1351 1352 // a set of RE's that can match strings and generate color tuples. 1353 stringParsers = [ { 1354 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 1355 parse: function( execResult ) { 1356 return [ 1357 execResult[ 1 ], 1358 execResult[ 2 ], 1359 execResult[ 3 ], 1360 execResult[ 4 ] 1361 ]; 1362 } 1363 }, { 1364 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 1365 parse: function( execResult ) { 1366 return [ 1367 execResult[ 1 ] * 2.55, 1368 execResult[ 2 ] * 2.55, 1369 execResult[ 3 ] * 2.55, 1370 execResult[ 4 ] 1371 ]; 1372 } 1373 }, { 1374 1375 // this regex ignores A-F because it's compared against an already lowercased string 1376 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?/, 1377 parse: function( execResult ) { 1378 return [ 1379 parseInt( execResult[ 1 ], 16 ), 1380 parseInt( execResult[ 2 ], 16 ), 1381 parseInt( execResult[ 3 ], 16 ), 1382 execResult[ 4 ] ? 1383 ( parseInt( execResult[ 4 ], 16 ) / 255 ).toFixed( 2 ) : 1384 1 1385 ]; 1386 } 1387 }, { 1388 1389 // this regex ignores A-F because it's compared against an already lowercased string 1390 re: /#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?/, 1391 parse: function( execResult ) { 1392 return [ 1393 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), 1394 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), 1395 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ), 1396 execResult[ 4 ] ? 1397 ( parseInt( execResult[ 4 ] + execResult[ 4 ], 16 ) / 255 ) 1398 .toFixed( 2 ) : 1399 1 1400 ]; 1401 } 1402 }, { 1403 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 1404 space: "hsla", 1405 parse: function( execResult ) { 1406 return [ 1407 execResult[ 1 ], 1408 execResult[ 2 ] / 100, 1409 execResult[ 3 ] / 100, 1410 execResult[ 4 ] 1411 ]; 1412 } 1413 } ], 1414 1415 // jQuery.Color( ) 1416 color = jQuery.Color = function( color, green, blue, alpha ) { 1417 return new jQuery.Color.fn.parse( color, green, blue, alpha ); 1418 }, 1419 spaces = { 1420 rgba: { 1421 props: { 1422 red: { 1423 idx: 0, 1424 type: "byte" 1425 }, 1426 green: { 1427 idx: 1, 1428 type: "byte" 1429 }, 1430 blue: { 1431 idx: 2, 1432 type: "byte" 1433 } 1434 } 1435 }, 1436 1437 hsla: { 1438 props: { 1439 hue: { 1440 idx: 0, 1441 type: "degrees" 1442 }, 1443 saturation: { 1444 idx: 1, 1445 type: "percent" 1446 }, 1447 lightness: { 1448 idx: 2, 1449 type: "percent" 1450 } 1451 } 1452 } 1453 }, 1454 propTypes = { 1455 "byte": { 1456 floor: true, 1457 max: 255 1458 }, 1459 "percent": { 1460 max: 1 1461 }, 1462 "degrees": { 1463 mod: 360, 1464 floor: true 1465 } 1466 }, 1467 1468 // colors = jQuery.Color.names 1469 colors, 1470 1471 // local aliases of functions called often 1472 each = jQuery.each; 1473 1474// define cache name and alpha properties 1475// for rgba and hsla spaces 1476each( spaces, function( spaceName, space ) { 1477 space.cache = "_" + spaceName; 1478 space.props.alpha = { 1479 idx: 3, 1480 type: "percent", 1481 def: 1 1482 }; 1483} ); 1484 1485// Populate the class2type map 1486jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), 1487 function( _i, name ) { 1488 class2type[ "[object " + name + "]" ] = name.toLowerCase(); 1489 } ); 1490 1491function getType( obj ) { 1492 if ( obj == null ) { 1493 return obj + ""; 1494 } 1495 1496 return typeof obj === "object" ? 1497 class2type[ toString.call( obj ) ] || "object" : 1498 typeof obj; 1499} 1500 1501function clamp( value, prop, allowEmpty ) { 1502 var type = propTypes[ prop.type ] || {}; 1503 1504 if ( value == null ) { 1505 return ( allowEmpty || !prop.def ) ? null : prop.def; 1506 } 1507 1508 // ~~ is an short way of doing floor for positive numbers 1509 value = type.floor ? ~~value : parseFloat( value ); 1510 1511 if ( type.mod ) { 1512 1513 // we add mod before modding to make sure that negatives values 1514 // get converted properly: -10 -> 350 1515 return ( value + type.mod ) % type.mod; 1516 } 1517 1518 // for now all property types without mod have min and max 1519 return Math.min( type.max, Math.max( 0, value ) ); 1520} 1521 1522function stringParse( string ) { 1523 var inst = color(), 1524 rgba = inst._rgba = []; 1525 1526 string = string.toLowerCase(); 1527 1528 each( stringParsers, function( _i, parser ) { 1529 var parsed, 1530 match = parser.re.exec( string ), 1531 values = match && parser.parse( match ), 1532 spaceName = parser.space || "rgba"; 1533 1534 if ( values ) { 1535 parsed = inst[ spaceName ]( values ); 1536 1537 // if this was an rgba parse the assignment might happen twice 1538 // oh well.... 1539 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; 1540 rgba = inst._rgba = parsed._rgba; 1541 1542 // exit each( stringParsers ) here because we matched 1543 return false; 1544 } 1545 } ); 1546 1547 // Found a stringParser that handled it 1548 if ( rgba.length ) { 1549 1550 // if this came from a parsed string, force "transparent" when alpha is 0 1551 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) 1552 if ( rgba.join() === "0,0,0,0" ) { 1553 jQuery.extend( rgba, colors.transparent ); 1554 } 1555 return inst; 1556 } 1557 1558 // named colors 1559 return colors[ string ]; 1560} 1561 1562color.fn = jQuery.extend( color.prototype, { 1563 parse: function( red, green, blue, alpha ) { 1564 if ( red === undefined ) { 1565 this._rgba = [ null, null, null, null ]; 1566 return this; 1567 } 1568 if ( red.jquery || red.nodeType ) { 1569 red = jQuery( red ).css( green ); 1570 green = undefined; 1571 } 1572 1573 var inst = this, 1574 type = getType( red ), 1575 rgba = this._rgba = []; 1576 1577 // more than 1 argument specified - assume ( red, green, blue, alpha ) 1578 if ( green !== undefined ) { 1579 red = [ red, green, blue, alpha ]; 1580 type = "array"; 1581 } 1582 1583 if ( type === "string" ) { 1584 return this.parse( stringParse( red ) || colors._default ); 1585 } 1586 1587 if ( type === "array" ) { 1588 each( spaces.rgba.props, function( _key, prop ) { 1589 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); 1590 } ); 1591 return this; 1592 } 1593 1594 if ( type === "object" ) { 1595 if ( red instanceof color ) { 1596 each( spaces, function( _spaceName, space ) { 1597 if ( red[ space.cache ] ) { 1598 inst[ space.cache ] = red[ space.cache ].slice(); 1599 } 1600 } ); 1601 } else { 1602 each( spaces, function( _spaceName, space ) { 1603 var cache = space.cache; 1604 each( space.props, function( key, prop ) { 1605 1606 // if the cache doesn't exist, and we know how to convert 1607 if ( !inst[ cache ] && space.to ) { 1608 1609 // if the value was null, we don't need to copy it 1610 // if the key was alpha, we don't need to copy it either 1611 if ( key === "alpha" || red[ key ] == null ) { 1612 return; 1613 } 1614 inst[ cache ] = space.to( inst._rgba ); 1615 } 1616 1617 // this is the only case where we allow nulls for ALL properties. 1618 // call clamp with alwaysAllowEmpty 1619 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); 1620 } ); 1621 1622 // everything defined but alpha? 1623 if ( inst[ cache ] && jQuery.inArray( 1624 null, 1625 inst[ cache ].slice( 0, 3 ) 1626 ) < 0 ) { 1627 1628 // use the default of 1 1629 if ( inst[ cache ][ 3 ] == null ) { 1630 inst[ cache ][ 3 ] = 1; 1631 } 1632 1633 if ( space.from ) { 1634 inst._rgba = space.from( inst[ cache ] ); 1635 } 1636 } 1637 } ); 1638 } 1639 return this; 1640 } 1641 }, 1642 is: function( compare ) { 1643 var is = color( compare ), 1644 same = true, 1645 inst = this; 1646 1647 each( spaces, function( _, space ) { 1648 var localCache, 1649 isCache = is[ space.cache ]; 1650 if ( isCache ) { 1651 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; 1652 each( space.props, function( _, prop ) { 1653 if ( isCache[ prop.idx ] != null ) { 1654 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); 1655 return same; 1656 } 1657 } ); 1658 } 1659 return same; 1660 } ); 1661 return same; 1662 }, 1663 _space: function() { 1664 var used = [], 1665 inst = this; 1666 each( spaces, function( spaceName, space ) { 1667 if ( inst[ space.cache ] ) { 1668 used.push( spaceName ); 1669 } 1670 } ); 1671 return used.pop(); 1672 }, 1673 transition: function( other, distance ) { 1674 var end = color( other ), 1675 spaceName = end._space(), 1676 space = spaces[ spaceName ], 1677 startColor = this.alpha() === 0 ? color( "transparent" ) : this, 1678 start = startColor[ space.cache ] || space.to( startColor._rgba ), 1679 result = start.slice(); 1680 1681 end = end[ space.cache ]; 1682 each( space.props, function( _key, prop ) { 1683 var index = prop.idx, 1684 startValue = start[ index ], 1685 endValue = end[ index ], 1686 type = propTypes[ prop.type ] || {}; 1687 1688 // if null, don't override start value 1689 if ( endValue === null ) { 1690 return; 1691 } 1692 1693 // if null - use end 1694 if ( startValue === null ) { 1695 result[ index ] = endValue; 1696 } else { 1697 if ( type.mod ) { 1698 if ( endValue - startValue > type.mod / 2 ) { 1699 startValue += type.mod; 1700 } else if ( startValue - endValue > type.mod / 2 ) { 1701 startValue -= type.mod; 1702 } 1703 } 1704 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); 1705 } 1706 } ); 1707 return this[ spaceName ]( result ); 1708 }, 1709 blend: function( opaque ) { 1710 1711 // if we are already opaque - return ourself 1712 if ( this._rgba[ 3 ] === 1 ) { 1713 return this; 1714 } 1715 1716 var rgb = this._rgba.slice(), 1717 a = rgb.pop(), 1718 blend = color( opaque )._rgba; 1719 1720 return color( jQuery.map( rgb, function( v, i ) { 1721 return ( 1 - a ) * blend[ i ] + a * v; 1722 } ) ); 1723 }, 1724 toRgbaString: function() { 1725 var prefix = "rgba(", 1726 rgba = jQuery.map( this._rgba, function( v, i ) { 1727 if ( v != null ) { 1728 return v; 1729 } 1730 return i > 2 ? 1 : 0; 1731 } ); 1732 1733 if ( rgba[ 3 ] === 1 ) { 1734 rgba.pop(); 1735 prefix = "rgb("; 1736 } 1737 1738 return prefix + rgba.join( ", " ) + ")"; 1739 }, 1740 toHslaString: function() { 1741 var prefix = "hsla(", 1742 hsla = jQuery.map( this.hsla(), function( v, i ) { 1743 if ( v == null ) { 1744 v = i > 2 ? 1 : 0; 1745 } 1746 1747 // catch 1 and 2 1748 if ( i && i < 3 ) { 1749 v = Math.round( v * 100 ) + "%"; 1750 } 1751 return v; 1752 } ); 1753 1754 if ( hsla[ 3 ] === 1 ) { 1755 hsla.pop(); 1756 prefix = "hsl("; 1757 } 1758 return prefix + hsla.join( ", " ) + ")"; 1759 }, 1760 toHexString: function( includeAlpha ) { 1761 var rgba = this._rgba.slice(), 1762 alpha = rgba.pop(); 1763 1764 if ( includeAlpha ) { 1765 rgba.push( ~~( alpha * 255 ) ); 1766 } 1767 1768 return "#" + jQuery.map( rgba, function( v ) { 1769 1770 // default to 0 when nulls exist 1771 return ( "0" + ( v || 0 ).toString( 16 ) ).substr( -2 ); 1772 } ).join( "" ); 1773 }, 1774 toString: function() { 1775 return this.toRgbaString(); 1776 } 1777} ); 1778color.fn.parse.prototype = color.fn; 1779 1780// hsla conversions adapted from: 1781// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 1782 1783function hue2rgb( p, q, h ) { 1784 h = ( h + 1 ) % 1; 1785 if ( h * 6 < 1 ) { 1786 return p + ( q - p ) * h * 6; 1787 } 1788 if ( h * 2 < 1 ) { 1789 return q; 1790 } 1791 if ( h * 3 < 2 ) { 1792 return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6; 1793 } 1794 return p; 1795} 1796 1797spaces.hsla.to = function( rgba ) { 1798 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { 1799 return [ null, null, null, rgba[ 3 ] ]; 1800 } 1801 var r = rgba[ 0 ] / 255, 1802 g = rgba[ 1 ] / 255, 1803 b = rgba[ 2 ] / 255, 1804 a = rgba[ 3 ], 1805 max = Math.max( r, g, b ), 1806 min = Math.min( r, g, b ), 1807 diff = max - min, 1808 add = max + min, 1809 l = add * 0.5, 1810 h, s; 1811 1812 if ( min === max ) { 1813 h = 0; 1814 } else if ( r === max ) { 1815 h = ( 60 * ( g - b ) / diff ) + 360; 1816 } else if ( g === max ) { 1817 h = ( 60 * ( b - r ) / diff ) + 120; 1818 } else { 1819 h = ( 60 * ( r - g ) / diff ) + 240; 1820 } 1821 1822 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0% 1823 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) 1824 if ( diff === 0 ) { 1825 s = 0; 1826 } else if ( l <= 0.5 ) { 1827 s = diff / add; 1828 } else { 1829 s = diff / ( 2 - add ); 1830 } 1831 return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ]; 1832}; 1833 1834spaces.hsla.from = function( hsla ) { 1835 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { 1836 return [ null, null, null, hsla[ 3 ] ]; 1837 } 1838 var h = hsla[ 0 ] / 360, 1839 s = hsla[ 1 ], 1840 l = hsla[ 2 ], 1841 a = hsla[ 3 ], 1842 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, 1843 p = 2 * l - q; 1844 1845 return [ 1846 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), 1847 Math.round( hue2rgb( p, q, h ) * 255 ), 1848 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), 1849 a 1850 ]; 1851}; 1852 1853 1854each( spaces, function( spaceName, space ) { 1855 var props = space.props, 1856 cache = space.cache, 1857 to = space.to, 1858 from = space.from; 1859 1860 // makes rgba() and hsla() 1861 color.fn[ spaceName ] = function( value ) { 1862 1863 // generate a cache for this space if it doesn't exist 1864 if ( to && !this[ cache ] ) { 1865 this[ cache ] = to( this._rgba ); 1866 } 1867 if ( value === undefined ) { 1868 return this[ cache ].slice(); 1869 } 1870 1871 var ret, 1872 type = getType( value ), 1873 arr = ( type === "array" || type === "object" ) ? value : arguments, 1874 local = this[ cache ].slice(); 1875 1876 each( props, function( key, prop ) { 1877 var val = arr[ type === "object" ? key : prop.idx ]; 1878 if ( val == null ) { 1879 val = local[ prop.idx ]; 1880 } 1881 local[ prop.idx ] = clamp( val, prop ); 1882 } ); 1883 1884 if ( from ) { 1885 ret = color( from( local ) ); 1886 ret[ cache ] = local; 1887 return ret; 1888 } else { 1889 return color( local ); 1890 } 1891 }; 1892 1893 // makes red() green() blue() alpha() hue() saturation() lightness() 1894 each( props, function( key, prop ) { 1895 1896 // alpha is included in more than one space 1897 if ( color.fn[ key ] ) { 1898 return; 1899 } 1900 color.fn[ key ] = function( value ) { 1901 var local, cur, match, fn, 1902 vtype = getType( value ); 1903 1904 if ( key === "alpha" ) { 1905 fn = this._hsla ? "hsla" : "rgba"; 1906 } else { 1907 fn = spaceName; 1908 } 1909 local = this[ fn ](); 1910 cur = local[ prop.idx ]; 1911 1912 if ( vtype === "undefined" ) { 1913 return cur; 1914 } 1915 1916 if ( vtype === "function" ) { 1917 value = value.call( this, cur ); 1918 vtype = getType( value ); 1919 } 1920 if ( value == null && prop.empty ) { 1921 return this; 1922 } 1923 if ( vtype === "string" ) { 1924 match = rplusequals.exec( value ); 1925 if ( match ) { 1926 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); 1927 } 1928 } 1929 local[ prop.idx ] = value; 1930 return this[ fn ]( local ); 1931 }; 1932 } ); 1933} ); 1934 1935// add cssHook and .fx.step function for each named hook. 1936// accept a space separated string of properties 1937color.hook = function( hook ) { 1938 var hooks = hook.split( " " ); 1939 each( hooks, function( _i, hook ) { 1940 jQuery.cssHooks[ hook ] = { 1941 set: function( elem, value ) { 1942 var parsed; 1943 1944 if ( value !== "transparent" && 1945 ( getType( value ) !== "string" || 1946 ( parsed = stringParse( value ) ) ) ) { 1947 value = color( parsed || value ); 1948 value = value.toRgbaString(); 1949 } 1950 elem.style[ hook ] = value; 1951 } 1952 }; 1953 jQuery.fx.step[ hook ] = function( fx ) { 1954 if ( !fx.colorInit ) { 1955 fx.start = color( fx.elem, hook ); 1956 fx.end = color( fx.end ); 1957 fx.colorInit = true; 1958 } 1959 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); 1960 }; 1961 } ); 1962 1963}; 1964 1965color.hook( stepHooks ); 1966 1967jQuery.cssHooks.borderColor = { 1968 expand: function( value ) { 1969 var expanded = {}; 1970 1971 each( [ "Top", "Right", "Bottom", "Left" ], function( _i, part ) { 1972 expanded[ "border" + part + "Color" ] = value; 1973 } ); 1974 return expanded; 1975 } 1976}; 1977 1978// Basic color names only. 1979// Usage of any of the other color names requires adding yourself or including 1980// jquery.color.svg-names.js. 1981colors = jQuery.Color.names = { 1982 1983 // 4.1. Basic color keywords 1984 aqua: "#00ffff", 1985 black: "#000000", 1986 blue: "#0000ff", 1987 fuchsia: "#ff00ff", 1988 gray: "#808080", 1989 green: "#008000", 1990 lime: "#00ff00", 1991 maroon: "#800000", 1992 navy: "#000080", 1993 olive: "#808000", 1994 purple: "#800080", 1995 red: "#ff0000", 1996 silver: "#c0c0c0", 1997 teal: "#008080", 1998 white: "#ffffff", 1999 yellow: "#ffff00", 2000 2001 // 4.2.3. "transparent" color keyword 2002 transparent: [ null, null, null, 0 ], 2003 2004 _default: "#ffffff" 2005}; 2006 2007 2008/*! 2009 * jQuery UI Effects 1.14.0 2010 * https://jqueryui.com 2011 * 2012 * Copyright OpenJS Foundation and other contributors 2013 * Released under the MIT license. 2014 * https://jquery.org/license 2015 */ 2016 2017//>>label: Effects Core 2018//>>group: Effects 2019/* eslint-disable max-len */ 2020//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects. 2021/* eslint-enable max-len */ 2022//>>docs: https://api.jqueryui.com/category/effects-core/ 2023//>>demos: https://jqueryui.com/effect/ 2024 2025 2026var dataSpace = "ui-effects-", 2027 dataSpaceStyle = "ui-effects-style", 2028 dataSpaceAnimated = "ui-effects-animated"; 2029 2030$.effects = { 2031 effect: {} 2032}; 2033 2034/******************************************************************************/ 2035/****************************** CLASS ANIMATIONS ******************************/ 2036/******************************************************************************/ 2037( function() { 2038 2039var classAnimationActions = [ "add", "remove", "toggle" ], 2040 shorthandStyles = { 2041 border: 1, 2042 borderBottom: 1, 2043 borderColor: 1, 2044 borderLeft: 1, 2045 borderRight: 1, 2046 borderTop: 1, 2047 borderWidth: 1, 2048 margin: 1, 2049 padding: 1 2050 }; 2051 2052$.each( 2053 [ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], 2054 function( _, prop ) { 2055 $.fx.step[ prop ] = function( fx ) { 2056 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { 2057 jQuery.style( fx.elem, prop, fx.end ); 2058 fx.setAttr = true; 2059 } 2060 }; 2061 } 2062); 2063 2064function camelCase( string ) { 2065 return string.replace( /-([\da-z])/gi, function( all, letter ) { 2066 return letter.toUpperCase(); 2067 } ); 2068} 2069 2070function getElementStyles( elem ) { 2071 var key, len, 2072 style = elem.ownerDocument.defaultView.getComputedStyle( elem ), 2073 styles = {}; 2074 2075 len = style.length; 2076 while ( len-- ) { 2077 key = style[ len ]; 2078 if ( typeof style[ key ] === "string" ) { 2079 styles[ camelCase( key ) ] = style[ key ]; 2080 } 2081 } 2082 2083 return styles; 2084} 2085 2086function styleDifference( oldStyle, newStyle ) { 2087 var diff = {}, 2088 name, value; 2089 2090 for ( name in newStyle ) { 2091 value = newStyle[ name ]; 2092 if ( oldStyle[ name ] !== value ) { 2093 if ( !shorthandStyles[ name ] ) { 2094 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { 2095 diff[ name ] = value; 2096 } 2097 } 2098 } 2099 } 2100 2101 return diff; 2102} 2103 2104$.effects.animateClass = function( value, duration, easing, callback ) { 2105 var o = $.speed( duration, easing, callback ); 2106 2107 return this.queue( function() { 2108 var animated = $( this ), 2109 baseClass = animated.attr( "class" ) || "", 2110 applyClassChange, 2111 allAnimations = o.children ? animated.find( "*" ).addBack() : animated; 2112 2113 // Map the animated objects to store the original styles. 2114 allAnimations = allAnimations.map( function() { 2115 var el = $( this ); 2116 return { 2117 el: el, 2118 start: getElementStyles( this ) 2119 }; 2120 } ); 2121 2122 // Apply class change 2123 applyClassChange = function() { 2124 $.each( classAnimationActions, function( i, action ) { 2125 if ( value[ action ] ) { 2126 animated[ action + "Class" ]( value[ action ] ); 2127 } 2128 } ); 2129 }; 2130 applyClassChange(); 2131 2132 // Map all animated objects again - calculate new styles and diff 2133 allAnimations = allAnimations.map( function() { 2134 this.end = getElementStyles( this.el[ 0 ] ); 2135 this.diff = styleDifference( this.start, this.end ); 2136 return this; 2137 } ); 2138 2139 // Apply original class 2140 animated.attr( "class", baseClass ); 2141 2142 // Map all animated objects again - this time collecting a promise 2143 allAnimations = allAnimations.map( function() { 2144 var styleInfo = this, 2145 dfd = $.Deferred(), 2146 opts = $.extend( {}, o, { 2147 queue: false, 2148 complete: function() { 2149 dfd.resolve( styleInfo ); 2150 } 2151 } ); 2152 2153 this.el.animate( this.diff, opts ); 2154 return dfd.promise(); 2155 } ); 2156 2157 // Once all animations have completed: 2158 $.when.apply( $, allAnimations.get() ).done( function() { 2159 2160 // Set the final class 2161 applyClassChange(); 2162 2163 // For each animated element, 2164 // clear all css properties that were animated 2165 $.each( arguments, function() { 2166 var el = this.el; 2167 $.each( this.diff, function( key ) { 2168 el.css( key, "" ); 2169 } ); 2170 } ); 2171 2172 // This is guarnteed to be there if you use jQuery.speed() 2173 // it also handles dequeuing the next anim... 2174 o.complete.call( animated[ 0 ] ); 2175 } ); 2176 } ); 2177}; 2178 2179$.fn.extend( { 2180 addClass: ( function( orig ) { 2181 return function( classNames, speed, easing, callback ) { 2182 return speed ? 2183 $.effects.animateClass.call( this, 2184 { add: classNames }, speed, easing, callback ) : 2185 orig.apply( this, arguments ); 2186 }; 2187 } )( $.fn.addClass ), 2188 2189 removeClass: ( function( orig ) { 2190 return function( classNames, speed, easing, callback ) { 2191 return arguments.length > 1 ? 2192 $.effects.animateClass.call( this, 2193 { remove: classNames }, speed, easing, callback ) : 2194 orig.apply( this, arguments ); 2195 }; 2196 } )( $.fn.removeClass ), 2197 2198 toggleClass: ( function( orig ) { 2199 return function( classNames, force, speed, easing, callback ) { 2200 if ( typeof force === "boolean" || force === undefined ) { 2201 if ( !speed ) { 2202 2203 // Without speed parameter 2204 return orig.apply( this, arguments ); 2205 } else { 2206 return $.effects.animateClass.call( this, 2207 ( force ? { add: classNames } : { remove: classNames } ), 2208 speed, easing, callback ); 2209 } 2210 } else { 2211 2212 // Without force parameter 2213 return $.effects.animateClass.call( this, 2214 { toggle: classNames }, force, speed, easing ); 2215 } 2216 }; 2217 } )( $.fn.toggleClass ), 2218 2219 switchClass: function( remove, add, speed, easing, callback ) { 2220 return $.effects.animateClass.call( this, { 2221 add: add, 2222 remove: remove 2223 }, speed, easing, callback ); 2224 } 2225} ); 2226 2227} )(); 2228 2229/******************************************************************************/ 2230/*********************************** EFFECTS **********************************/ 2231/******************************************************************************/ 2232 2233( function() { 2234 2235if ( $.expr && $.expr.pseudos && $.expr.pseudos.animated ) { 2236 $.expr.pseudos.animated = ( function( orig ) { 2237 return function( elem ) { 2238 return !!$( elem ).data( dataSpaceAnimated ) || orig( elem ); 2239 }; 2240 } )( $.expr.pseudos.animated ); 2241} 2242 2243if ( $.uiBackCompat === true ) { 2244 $.extend( $.effects, { 2245 2246 // Saves a set of properties in a data storage 2247 save: function( element, set ) { 2248 var i = 0, length = set.length; 2249 for ( ; i < length; i++ ) { 2250 if ( set[ i ] !== null ) { 2251 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); 2252 } 2253 } 2254 }, 2255 2256 // Restores a set of previously saved properties from a data storage 2257 restore: function( element, set ) { 2258 var val, i = 0, length = set.length; 2259 for ( ; i < length; i++ ) { 2260 if ( set[ i ] !== null ) { 2261 val = element.data( dataSpace + set[ i ] ); 2262 element.css( set[ i ], val ); 2263 } 2264 } 2265 }, 2266 2267 setMode: function( el, mode ) { 2268 if ( mode === "toggle" ) { 2269 mode = el.is( ":hidden" ) ? "show" : "hide"; 2270 } 2271 return mode; 2272 }, 2273 2274 // Wraps the element around a wrapper that copies position properties 2275 createWrapper: function( element ) { 2276 2277 // If the element is already wrapped, return it 2278 if ( element.parent().is( ".ui-effects-wrapper" ) ) { 2279 return element.parent(); 2280 } 2281 2282 // Wrap the element 2283 var props = { 2284 width: element.outerWidth( true ), 2285 height: element.outerHeight( true ), 2286 "float": element.css( "float" ) 2287 }, 2288 wrapper = $( "<div></div>" ) 2289 .addClass( "ui-effects-wrapper" ) 2290 .css( { 2291 fontSize: "100%", 2292 background: "transparent", 2293 border: "none", 2294 margin: 0, 2295 padding: 0 2296 } ), 2297 2298 // Store the size in case width/height are defined in % - Fixes #5245 2299 size = { 2300 width: element.width(), 2301 height: element.height() 2302 }, 2303 active = document.activeElement; 2304 2305 // Support: Firefox 2306 // Firefox incorrectly exposes anonymous content 2307 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 2308 try { 2309 // eslint-disable-next-line no-unused-expressions 2310 active.id; 2311 } catch ( e ) { 2312 active = document.body; 2313 } 2314 2315 element.wrap( wrapper ); 2316 2317 // Fixes #7595 - Elements lose focus when wrapped. 2318 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 2319 $( active ).trigger( "focus" ); 2320 } 2321 2322 // Hotfix for jQuery 1.4 since some change in wrap() seems to actually 2323 // lose the reference to the wrapped element 2324 wrapper = element.parent(); 2325 2326 // Transfer positioning properties to the wrapper 2327 if ( element.css( "position" ) === "static" ) { 2328 wrapper.css( { position: "relative" } ); 2329 element.css( { position: "relative" } ); 2330 } else { 2331 $.extend( props, { 2332 position: element.css( "position" ), 2333 zIndex: element.css( "z-index" ) 2334 } ); 2335 $.each( [ "top", "left", "bottom", "right" ], function( i, pos ) { 2336 props[ pos ] = element.css( pos ); 2337 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { 2338 props[ pos ] = "auto"; 2339 } 2340 } ); 2341 element.css( { 2342 position: "relative", 2343 top: 0, 2344 left: 0, 2345 right: "auto", 2346 bottom: "auto" 2347 } ); 2348 } 2349 element.css( size ); 2350 2351 return wrapper.css( props ).show(); 2352 }, 2353 2354 removeWrapper: function( element ) { 2355 var active = document.activeElement; 2356 2357 if ( element.parent().is( ".ui-effects-wrapper" ) ) { 2358 element.parent().replaceWith( element ); 2359 2360 // Fixes #7595 - Elements lose focus when wrapped. 2361 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 2362 $( active ).trigger( "focus" ); 2363 } 2364 } 2365 2366 return element; 2367 } 2368 } ); 2369} 2370 2371$.extend( $.effects, { 2372 version: "1.14.0", 2373 2374 define: function( name, mode, effect ) { 2375 if ( !effect ) { 2376 effect = mode; 2377 mode = "effect"; 2378 } 2379 2380 $.effects.effect[ name ] = effect; 2381 $.effects.effect[ name ].mode = mode; 2382 2383 return effect; 2384 }, 2385 2386 scaledDimensions: function( element, percent, direction ) { 2387 if ( percent === 0 ) { 2388 return { 2389 height: 0, 2390 width: 0, 2391 outerHeight: 0, 2392 outerWidth: 0 2393 }; 2394 } 2395 2396 var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1, 2397 y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1; 2398 2399 return { 2400 height: element.height() * y, 2401 width: element.width() * x, 2402 outerHeight: element.outerHeight() * y, 2403 outerWidth: element.outerWidth() * x 2404 }; 2405 2406 }, 2407 2408 clipToBox: function( animation ) { 2409 return { 2410 width: animation.clip.right - animation.clip.left, 2411 height: animation.clip.bottom - animation.clip.top, 2412 left: animation.clip.left, 2413 top: animation.clip.top 2414 }; 2415 }, 2416 2417 // Injects recently queued functions to be first in line (after "inprogress") 2418 unshift: function( element, queueLength, count ) { 2419 var queue = element.queue(); 2420 2421 if ( queueLength > 1 ) { 2422 queue.splice.apply( queue, 2423 [ 1, 0 ].concat( queue.splice( queueLength, count ) ) ); 2424 } 2425 element.dequeue(); 2426 }, 2427 2428 saveStyle: function( element ) { 2429 element.data( dataSpaceStyle, element[ 0 ].style.cssText ); 2430 }, 2431 2432 restoreStyle: function( element ) { 2433 element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || ""; 2434 element.removeData( dataSpaceStyle ); 2435 }, 2436 2437 mode: function( element, mode ) { 2438 var hidden = element.is( ":hidden" ); 2439 2440 if ( mode === "toggle" ) { 2441 mode = hidden ? "show" : "hide"; 2442 } 2443 if ( hidden ? mode === "hide" : mode === "show" ) { 2444 mode = "none"; 2445 } 2446 return mode; 2447 }, 2448 2449 // Translates a [top,left] array into a baseline value 2450 getBaseline: function( origin, original ) { 2451 var y, x; 2452 2453 switch ( origin[ 0 ] ) { 2454 case "top": 2455 y = 0; 2456 break; 2457 case "middle": 2458 y = 0.5; 2459 break; 2460 case "bottom": 2461 y = 1; 2462 break; 2463 default: 2464 y = origin[ 0 ] / original.height; 2465 } 2466 2467 switch ( origin[ 1 ] ) { 2468 case "left": 2469 x = 0; 2470 break; 2471 case "center": 2472 x = 0.5; 2473 break; 2474 case "right": 2475 x = 1; 2476 break; 2477 default: 2478 x = origin[ 1 ] / original.width; 2479 } 2480 2481 return { 2482 x: x, 2483 y: y 2484 }; 2485 }, 2486 2487 // Creates a placeholder element so that the original element can be made absolute 2488 createPlaceholder: function( element ) { 2489 var placeholder, 2490 cssPosition = element.css( "position" ), 2491 position = element.position(); 2492 2493 // Lock in margins first to account for form elements, which 2494 // will change margin if you explicitly set height 2495 // see: https://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380 2496 // Support: Safari 2497 element.css( { 2498 marginTop: element.css( "marginTop" ), 2499 marginBottom: element.css( "marginBottom" ), 2500 marginLeft: element.css( "marginLeft" ), 2501 marginRight: element.css( "marginRight" ) 2502 } ) 2503 .outerWidth( element.outerWidth() ) 2504 .outerHeight( element.outerHeight() ); 2505 2506 if ( /^(static|relative)/.test( cssPosition ) ) { 2507 cssPosition = "absolute"; 2508 2509 placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( { 2510 2511 // Convert inline to inline block to account for inline elements 2512 // that turn to inline block based on content (like img) 2513 display: /^(inline|ruby)/.test( element.css( "display" ) ) ? 2514 "inline-block" : 2515 "block", 2516 visibility: "hidden", 2517 2518 // Margins need to be set to account for margin collapse 2519 marginTop: element.css( "marginTop" ), 2520 marginBottom: element.css( "marginBottom" ), 2521 marginLeft: element.css( "marginLeft" ), 2522 marginRight: element.css( "marginRight" ), 2523 "float": element.css( "float" ) 2524 } ) 2525 .outerWidth( element.outerWidth() ) 2526 .outerHeight( element.outerHeight() ) 2527 .addClass( "ui-effects-placeholder" ); 2528 2529 element.data( dataSpace + "placeholder", placeholder ); 2530 } 2531 2532 element.css( { 2533 position: cssPosition, 2534 left: position.left, 2535 top: position.top 2536 } ); 2537 2538 return placeholder; 2539 }, 2540 2541 removePlaceholder: function( element ) { 2542 var dataKey = dataSpace + "placeholder", 2543 placeholder = element.data( dataKey ); 2544 2545 if ( placeholder ) { 2546 placeholder.remove(); 2547 element.removeData( dataKey ); 2548 } 2549 }, 2550 2551 // Removes a placeholder if it exists and restores 2552 // properties that were modified during placeholder creation 2553 cleanUp: function( element ) { 2554 $.effects.restoreStyle( element ); 2555 $.effects.removePlaceholder( element ); 2556 }, 2557 2558 setTransition: function( element, list, factor, value ) { 2559 value = value || {}; 2560 $.each( list, function( i, x ) { 2561 var unit = element.cssUnit( x ); 2562 if ( unit[ 0 ] > 0 ) { 2563 value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; 2564 } 2565 } ); 2566 return value; 2567 } 2568} ); 2569 2570// Return an effect options object for the given parameters: 2571function _normalizeArguments( effect, options, speed, callback ) { 2572 2573 // Allow passing all options as the first parameter 2574 if ( $.isPlainObject( effect ) ) { 2575 options = effect; 2576 effect = effect.effect; 2577 } 2578 2579 // Convert to an object 2580 effect = { effect: effect }; 2581 2582 // Catch (effect, null, ...) 2583 if ( options == null ) { 2584 options = {}; 2585 } 2586 2587 // Catch (effect, callback) 2588 if ( typeof options === "function" ) { 2589 callback = options; 2590 speed = null; 2591 options = {}; 2592 } 2593 2594 // Catch (effect, speed, ?) 2595 if ( typeof options === "number" || $.fx.speeds[ options ] ) { 2596 callback = speed; 2597 speed = options; 2598 options = {}; 2599 } 2600 2601 // Catch (effect, options, callback) 2602 if ( typeof speed === "function" ) { 2603 callback = speed; 2604 speed = null; 2605 } 2606 2607 // Add options to effect 2608 if ( options ) { 2609 $.extend( effect, options ); 2610 } 2611 2612 speed = speed || options.duration; 2613 effect.duration = $.fx.off ? 0 : 2614 typeof speed === "number" ? speed : 2615 speed in $.fx.speeds ? $.fx.speeds[ speed ] : 2616 $.fx.speeds._default; 2617 2618 effect.complete = callback || options.complete; 2619 2620 return effect; 2621} 2622 2623function standardAnimationOption( option ) { 2624 2625 // Valid standard speeds (nothing, number, named speed) 2626 if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) { 2627 return true; 2628 } 2629 2630 // Invalid strings - treat as "normal" speed 2631 if ( typeof option === "string" && !$.effects.effect[ option ] ) { 2632 return true; 2633 } 2634 2635 // Complete callback 2636 if ( typeof option === "function" ) { 2637 return true; 2638 } 2639 2640 // Options hash (but not naming an effect) 2641 if ( typeof option === "object" && !option.effect ) { 2642 return true; 2643 } 2644 2645 // Didn't match any standard API 2646 return false; 2647} 2648 2649$.fn.extend( { 2650 effect: function( /* effect, options, speed, callback */ ) { 2651 var args = _normalizeArguments.apply( this, arguments ), 2652 effectMethod = $.effects.effect[ args.effect ], 2653 defaultMode = effectMethod.mode, 2654 queue = args.queue, 2655 queueName = queue || "fx", 2656 complete = args.complete, 2657 mode = args.mode, 2658 modes = [], 2659 prefilter = function( next ) { 2660 var el = $( this ), 2661 normalizedMode = $.effects.mode( el, mode ) || defaultMode; 2662 2663 // Sentinel for duck-punching the :animated pseudo-selector 2664 el.data( dataSpaceAnimated, true ); 2665 2666 // Save effect mode for later use, 2667 // we can't just call $.effects.mode again later, 2668 // as the .show() below destroys the initial state 2669 modes.push( normalizedMode ); 2670 2671 // See $.uiBackCompat inside of run() for removal of defaultMode in 1.14 2672 if ( defaultMode && ( normalizedMode === "show" || 2673 ( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) { 2674 el.show(); 2675 } 2676 2677 if ( !defaultMode || normalizedMode !== "none" ) { 2678 $.effects.saveStyle( el ); 2679 } 2680 2681 if ( typeof next === "function" ) { 2682 next(); 2683 } 2684 }; 2685 2686 if ( $.fx.off || !effectMethod ) { 2687 2688 // Delegate to the original method (e.g., .show()) if possible 2689 if ( mode ) { 2690 return this[ mode ]( args.duration, complete ); 2691 } else { 2692 return this.each( function() { 2693 if ( complete ) { 2694 complete.call( this ); 2695 } 2696 } ); 2697 } 2698 } 2699 2700 function run( next ) { 2701 var elem = $( this ); 2702 2703 function cleanup() { 2704 elem.removeData( dataSpaceAnimated ); 2705 2706 $.effects.cleanUp( elem ); 2707 2708 if ( args.mode === "hide" ) { 2709 elem.hide(); 2710 } 2711 2712 done(); 2713 } 2714 2715 function done() { 2716 if ( typeof complete === "function" ) { 2717 complete.call( elem[ 0 ] ); 2718 } 2719 2720 if ( typeof next === "function" ) { 2721 next(); 2722 } 2723 } 2724 2725 // Override mode option on a per element basis, 2726 // as toggle can be either show or hide depending on element state 2727 args.mode = modes.shift(); 2728 2729 if ( $.uiBackCompat === true && !defaultMode ) { 2730 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { 2731 2732 // Call the core method to track "olddisplay" properly 2733 elem[ mode ](); 2734 done(); 2735 } else { 2736 effectMethod.call( elem[ 0 ], args, done ); 2737 } 2738 } else { 2739 if ( args.mode === "none" ) { 2740 2741 // Call the core method to track "olddisplay" properly 2742 elem[ mode ](); 2743 done(); 2744 } else { 2745 effectMethod.call( elem[ 0 ], args, cleanup ); 2746 } 2747 } 2748 } 2749 2750 // Run prefilter on all elements first to ensure that 2751 // any showing or hiding happens before placeholder creation, 2752 // which ensures that any layout changes are correctly captured. 2753 return queue === false ? 2754 this.each( prefilter ).each( run ) : 2755 this.queue( queueName, prefilter ).queue( queueName, run ); 2756 }, 2757 2758 show: ( function( orig ) { 2759 return function( option ) { 2760 if ( standardAnimationOption( option ) ) { 2761 return orig.apply( this, arguments ); 2762 } else { 2763 var args = _normalizeArguments.apply( this, arguments ); 2764 args.mode = "show"; 2765 return this.effect.call( this, args ); 2766 } 2767 }; 2768 } )( $.fn.show ), 2769 2770 hide: ( function( orig ) { 2771 return function( option ) { 2772 if ( standardAnimationOption( option ) ) { 2773 return orig.apply( this, arguments ); 2774 } else { 2775 var args = _normalizeArguments.apply( this, arguments ); 2776 args.mode = "hide"; 2777 return this.effect.call( this, args ); 2778 } 2779 }; 2780 } )( $.fn.hide ), 2781 2782 toggle: ( function( orig ) { 2783 return function( option ) { 2784 if ( standardAnimationOption( option ) || typeof option === "boolean" ) { 2785 return orig.apply( this, arguments ); 2786 } else { 2787 var args = _normalizeArguments.apply( this, arguments ); 2788 args.mode = "toggle"; 2789 return this.effect.call( this, args ); 2790 } 2791 }; 2792 } )( $.fn.toggle ), 2793 2794 cssUnit: function( key ) { 2795 var style = this.css( key ), 2796 val = []; 2797 2798 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { 2799 if ( style.indexOf( unit ) > 0 ) { 2800 val = [ parseFloat( style ), unit ]; 2801 } 2802 } ); 2803 return val; 2804 }, 2805 2806 cssClip: function( clipObj ) { 2807 if ( clipObj ) { 2808 return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " + 2809 clipObj.bottom + "px " + clipObj.left + "px)" ); 2810 } 2811 return parseClip( this.css( "clip" ), this ); 2812 }, 2813 2814 transfer: function( options, done ) { 2815 var element = $( this ), 2816 target = $( options.to ), 2817 targetFixed = target.css( "position" ) === "fixed", 2818 body = $( "body" ), 2819 fixTop = targetFixed ? body.scrollTop() : 0, 2820 fixLeft = targetFixed ? body.scrollLeft() : 0, 2821 endPosition = target.offset(), 2822 animation = { 2823 top: endPosition.top - fixTop, 2824 left: endPosition.left - fixLeft, 2825 height: target.innerHeight(), 2826 width: target.innerWidth() 2827 }, 2828 startPosition = element.offset(), 2829 transfer = $( "<div class='ui-effects-transfer'></div>" ); 2830 2831 transfer 2832 .appendTo( "body" ) 2833 .addClass( options.className ) 2834 .css( { 2835 top: startPosition.top - fixTop, 2836 left: startPosition.left - fixLeft, 2837 height: element.innerHeight(), 2838 width: element.innerWidth(), 2839 position: targetFixed ? "fixed" : "absolute" 2840 } ) 2841 .animate( animation, options.duration, options.easing, function() { 2842 transfer.remove(); 2843 if ( typeof done === "function" ) { 2844 done(); 2845 } 2846 } ); 2847 } 2848} ); 2849 2850function parseClip( str, element ) { 2851 var outerWidth = element.outerWidth(), 2852 outerHeight = element.outerHeight(), 2853 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)\)$/, 2854 values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ]; 2855 2856 return { 2857 top: parseFloat( values[ 1 ] ) || 0, 2858 right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ), 2859 bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ), 2860 left: parseFloat( values[ 4 ] ) || 0 2861 }; 2862} 2863 2864$.fx.step.clip = function( fx ) { 2865 if ( !fx.clipInit ) { 2866 fx.start = $( fx.elem ).cssClip(); 2867 if ( typeof fx.end === "string" ) { 2868 fx.end = parseClip( fx.end, fx.elem ); 2869 } 2870 fx.clipInit = true; 2871 } 2872 2873 $( fx.elem ).cssClip( { 2874 top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top, 2875 right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right, 2876 bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom, 2877 left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left 2878 } ); 2879}; 2880 2881} )(); 2882 2883/******************************************************************************/ 2884/*********************************** EASING ***********************************/ 2885/******************************************************************************/ 2886 2887( function() { 2888 2889// Based on easing equations from Robert Penner (http://robertpenner.com/easing) 2890 2891var baseEasings = {}; 2892 2893$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { 2894 baseEasings[ name ] = function( p ) { 2895 return Math.pow( p, i + 2 ); 2896 }; 2897} ); 2898 2899$.extend( baseEasings, { 2900 Sine: function( p ) { 2901 return 1 - Math.cos( p * Math.PI / 2 ); 2902 }, 2903 Circ: function( p ) { 2904 return 1 - Math.sqrt( 1 - p * p ); 2905 }, 2906 Elastic: function( p ) { 2907 return p === 0 || p === 1 ? p : 2908 -Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 ); 2909 }, 2910 Back: function( p ) { 2911 return p * p * ( 3 * p - 2 ); 2912 }, 2913 Bounce: function( p ) { 2914 var pow2, 2915 bounce = 4; 2916 2917 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} 2918 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); 2919 } 2920} ); 2921 2922$.each( baseEasings, function( name, easeIn ) { 2923 $.easing[ "easeIn" + name ] = easeIn; 2924 $.easing[ "easeOut" + name ] = function( p ) { 2925 return 1 - easeIn( 1 - p ); 2926 }; 2927 $.easing[ "easeInOut" + name ] = function( p ) { 2928 return p < 0.5 ? 2929 easeIn( p * 2 ) / 2 : 2930 1 - easeIn( p * -2 + 2 ) / 2; 2931 }; 2932} ); 2933 2934} )(); 2935 2936var effect = $.effects; 2937 2938 2939/*! 2940 * jQuery UI Effects Blind 1.14.0 2941 * https://jqueryui.com 2942 * 2943 * Copyright OpenJS Foundation and other contributors 2944 * Released under the MIT license. 2945 * https://jquery.org/license 2946 */ 2947 2948//>>label: Blind Effect 2949//>>group: Effects 2950//>>description: Blinds the element. 2951//>>docs: https://api.jqueryui.com/blind-effect/ 2952//>>demos: https://jqueryui.com/effect/ 2953 2954 2955var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) { 2956 var map = { 2957 up: [ "bottom", "top" ], 2958 vertical: [ "bottom", "top" ], 2959 down: [ "top", "bottom" ], 2960 left: [ "right", "left" ], 2961 horizontal: [ "right", "left" ], 2962 right: [ "left", "right" ] 2963 }, 2964 element = $( this ), 2965 direction = options.direction || "up", 2966 start = element.cssClip(), 2967 animate = { clip: $.extend( {}, start ) }, 2968 placeholder = $.effects.createPlaceholder( element ); 2969 2970 animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ]; 2971 2972 if ( options.mode === "show" ) { 2973 element.cssClip( animate.clip ); 2974 if ( placeholder ) { 2975 placeholder.css( $.effects.clipToBox( animate ) ); 2976 } 2977 2978 animate.clip = start; 2979 } 2980 2981 if ( placeholder ) { 2982 placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing ); 2983 } 2984 2985 element.animate( animate, { 2986 queue: false, 2987 duration: options.duration, 2988 easing: options.easing, 2989 complete: done 2990 } ); 2991} ); 2992 2993 2994/*! 2995 * jQuery UI Effects Bounce 1.14.0 2996 * https://jqueryui.com 2997 * 2998 * Copyright OpenJS Foundation and other contributors 2999 * Released under the MIT license. 3000 * https://jquery.org/license 3001 */ 3002 3003//>>label: Bounce Effect 3004//>>group: Effects 3005//>>description: Bounces an element horizontally or vertically n times. 3006//>>docs: https://api.jqueryui.com/bounce-effect/ 3007//>>demos: https://jqueryui.com/effect/ 3008 3009 3010var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) { 3011 var upAnim, downAnim, refValue, 3012 element = $( this ), 3013 3014 // Defaults: 3015 mode = options.mode, 3016 hide = mode === "hide", 3017 show = mode === "show", 3018 direction = options.direction || "up", 3019 distance = options.distance, 3020 times = options.times || 5, 3021 3022 // Number of internal animations 3023 anims = times * 2 + ( show || hide ? 1 : 0 ), 3024 speed = options.duration / anims, 3025 easing = options.easing, 3026 3027 // Utility: 3028 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 3029 motion = ( direction === "up" || direction === "left" ), 3030 i = 0, 3031 3032 queuelen = element.queue().length; 3033 3034 $.effects.createPlaceholder( element ); 3035 3036 refValue = element.css( ref ); 3037 3038 // Default distance for the BIGGEST bounce is the outer Distance / 3 3039 if ( !distance ) { 3040 distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; 3041 } 3042 3043 if ( show ) { 3044 downAnim = { opacity: 1 }; 3045 downAnim[ ref ] = refValue; 3046 3047 // If we are showing, force opacity 0 and set the initial position 3048 // then do the "first" animation 3049 element 3050 .css( "opacity", 0 ) 3051 .css( ref, motion ? -distance * 2 : distance * 2 ) 3052 .animate( downAnim, speed, easing ); 3053 } 3054 3055 // Start at the smallest distance if we are hiding 3056 if ( hide ) { 3057 distance = distance / Math.pow( 2, times - 1 ); 3058 } 3059 3060 downAnim = {}; 3061 downAnim[ ref ] = refValue; 3062 3063 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here 3064 for ( ; i < times; i++ ) { 3065 upAnim = {}; 3066 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 3067 3068 element 3069 .animate( upAnim, speed, easing ) 3070 .animate( downAnim, speed, easing ); 3071 3072 distance = hide ? distance * 2 : distance / 2; 3073 } 3074 3075 // Last Bounce when Hiding 3076 if ( hide ) { 3077 upAnim = { opacity: 0 }; 3078 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 3079 3080 element.animate( upAnim, speed, easing ); 3081 } 3082 3083 element.queue( done ); 3084 3085 $.effects.unshift( element, queuelen, anims + 1 ); 3086} ); 3087 3088 3089/*! 3090 * jQuery UI Effects Clip 1.14.0 3091 * https://jqueryui.com 3092 * 3093 * Copyright OpenJS Foundation and other contributors 3094 * Released under the MIT license. 3095 * https://jquery.org/license 3096 */ 3097 3098//>>label: Clip Effect 3099//>>group: Effects 3100//>>description: Clips the element on and off like an old TV. 3101//>>docs: https://api.jqueryui.com/clip-effect/ 3102//>>demos: https://jqueryui.com/effect/ 3103 3104 3105var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) { 3106 var start, 3107 animate = {}, 3108 element = $( this ), 3109 direction = options.direction || "vertical", 3110 both = direction === "both", 3111 horizontal = both || direction === "horizontal", 3112 vertical = both || direction === "vertical"; 3113 3114 start = element.cssClip(); 3115 animate.clip = { 3116 top: vertical ? ( start.bottom - start.top ) / 2 : start.top, 3117 right: horizontal ? ( start.right - start.left ) / 2 : start.right, 3118 bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom, 3119 left: horizontal ? ( start.right - start.left ) / 2 : start.left 3120 }; 3121 3122 $.effects.createPlaceholder( element ); 3123 3124 if ( options.mode === "show" ) { 3125 element.cssClip( animate.clip ); 3126 animate.clip = start; 3127 } 3128 3129 element.animate( animate, { 3130 queue: false, 3131 duration: options.duration, 3132 easing: options.easing, 3133 complete: done 3134 } ); 3135 3136} ); 3137 3138 3139/*! 3140 * jQuery UI Effects Drop 1.14.0 3141 * https://jqueryui.com 3142 * 3143 * Copyright OpenJS Foundation and other contributors 3144 * Released under the MIT license. 3145 * https://jquery.org/license 3146 */ 3147 3148//>>label: Drop Effect 3149//>>group: Effects 3150//>>description: Moves an element in one direction and hides it at the same time. 3151//>>docs: https://api.jqueryui.com/drop-effect/ 3152//>>demos: https://jqueryui.com/effect/ 3153 3154 3155var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) { 3156 3157 var distance, 3158 element = $( this ), 3159 mode = options.mode, 3160 show = mode === "show", 3161 direction = options.direction || "left", 3162 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 3163 motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=", 3164 oppositeMotion = ( motion === "+=" ) ? "-=" : "+=", 3165 animation = { 3166 opacity: 0 3167 }; 3168 3169 $.effects.createPlaceholder( element ); 3170 3171 distance = options.distance || 3172 element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2; 3173 3174 animation[ ref ] = motion + distance; 3175 3176 if ( show ) { 3177 element.css( animation ); 3178 3179 animation[ ref ] = oppositeMotion + distance; 3180 animation.opacity = 1; 3181 } 3182 3183 // Animate 3184 element.animate( animation, { 3185 queue: false, 3186 duration: options.duration, 3187 easing: options.easing, 3188 complete: done 3189 } ); 3190} ); 3191 3192 3193/*! 3194 * jQuery UI Effects Explode 1.14.0 3195 * https://jqueryui.com 3196 * 3197 * Copyright OpenJS Foundation and other contributors 3198 * Released under the MIT license. 3199 * https://jquery.org/license 3200 */ 3201 3202//>>label: Explode Effect 3203//>>group: Effects 3204/* eslint-disable max-len */ 3205//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness. 3206/* eslint-enable max-len */ 3207//>>docs: https://api.jqueryui.com/explode-effect/ 3208//>>demos: https://jqueryui.com/effect/ 3209 3210 3211var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) { 3212 3213 var i, j, left, top, mx, my, 3214 rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3, 3215 cells = rows, 3216 element = $( this ), 3217 mode = options.mode, 3218 show = mode === "show", 3219 3220 // Show and then visibility:hidden the element before calculating offset 3221 offset = element.show().css( "visibility", "hidden" ).offset(), 3222 3223 // Width and height of a piece 3224 width = Math.ceil( element.outerWidth() / cells ), 3225 height = Math.ceil( element.outerHeight() / rows ), 3226 pieces = []; 3227 3228 // Children animate complete: 3229 function childComplete() { 3230 pieces.push( this ); 3231 if ( pieces.length === rows * cells ) { 3232 animComplete(); 3233 } 3234 } 3235 3236 // Clone the element for each row and cell. 3237 for ( i = 0; i < rows; i++ ) { // ===> 3238 top = offset.top + i * height; 3239 my = i - ( rows - 1 ) / 2; 3240 3241 for ( j = 0; j < cells; j++ ) { // ||| 3242 left = offset.left + j * width; 3243 mx = j - ( cells - 1 ) / 2; 3244 3245 // Create a clone of the now hidden main element that will be absolute positioned 3246 // within a wrapper div off the -left and -top equal to size of our pieces 3247 element 3248 .clone() 3249 .appendTo( "body" ) 3250 .wrap( "<div></div>" ) 3251 .css( { 3252 position: "absolute", 3253 visibility: "visible", 3254 left: -j * width, 3255 top: -i * height 3256 } ) 3257 3258 // Select the wrapper - make it overflow: hidden and absolute positioned based on 3259 // where the original was located +left and +top equal to the size of pieces 3260 .parent() 3261 .addClass( "ui-effects-explode" ) 3262 .css( { 3263 position: "absolute", 3264 overflow: "hidden", 3265 width: width, 3266 height: height, 3267 left: left + ( show ? mx * width : 0 ), 3268 top: top + ( show ? my * height : 0 ), 3269 opacity: show ? 0 : 1 3270 } ) 3271 .animate( { 3272 left: left + ( show ? 0 : mx * width ), 3273 top: top + ( show ? 0 : my * height ), 3274 opacity: show ? 1 : 0 3275 }, options.duration || 500, options.easing, childComplete ); 3276 } 3277 } 3278 3279 function animComplete() { 3280 element.css( { 3281 visibility: "visible" 3282 } ); 3283 $( pieces ).remove(); 3284 done(); 3285 } 3286} ); 3287 3288 3289/*! 3290 * jQuery UI Effects Fade 1.14.0 3291 * https://jqueryui.com 3292 * 3293 * Copyright OpenJS Foundation and other contributors 3294 * Released under the MIT license. 3295 * https://jquery.org/license 3296 */ 3297 3298//>>label: Fade Effect 3299//>>group: Effects 3300//>>description: Fades the element. 3301//>>docs: https://api.jqueryui.com/fade-effect/ 3302//>>demos: https://jqueryui.com/effect/ 3303 3304 3305var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) { 3306 var show = options.mode === "show"; 3307 3308 $( this ) 3309 .css( "opacity", show ? 0 : 1 ) 3310 .animate( { 3311 opacity: show ? 1 : 0 3312 }, { 3313 queue: false, 3314 duration: options.duration, 3315 easing: options.easing, 3316 complete: done 3317 } ); 3318} ); 3319 3320 3321/*! 3322 * jQuery UI Effects Fold 1.14.0 3323 * https://jqueryui.com 3324 * 3325 * Copyright OpenJS Foundation and other contributors 3326 * Released under the MIT license. 3327 * https://jquery.org/license 3328 */ 3329 3330//>>label: Fold Effect 3331//>>group: Effects 3332//>>description: Folds an element first horizontally and then vertically. 3333//>>docs: https://api.jqueryui.com/fold-effect/ 3334//>>demos: https://jqueryui.com/effect/ 3335 3336 3337var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) { 3338 3339 // Create element 3340 var element = $( this ), 3341 mode = options.mode, 3342 show = mode === "show", 3343 hide = mode === "hide", 3344 size = options.size || 15, 3345 percent = /([0-9]+)%/.exec( size ), 3346 horizFirst = !!options.horizFirst, 3347 ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ], 3348 duration = options.duration / 2, 3349 3350 placeholder = $.effects.createPlaceholder( element ), 3351 3352 start = element.cssClip(), 3353 animation1 = { clip: $.extend( {}, start ) }, 3354 animation2 = { clip: $.extend( {}, start ) }, 3355 3356 distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ], 3357 3358 queuelen = element.queue().length; 3359 3360 if ( percent ) { 3361 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; 3362 } 3363 animation1.clip[ ref[ 0 ] ] = size; 3364 animation2.clip[ ref[ 0 ] ] = size; 3365 animation2.clip[ ref[ 1 ] ] = 0; 3366 3367 if ( show ) { 3368 element.cssClip( animation2.clip ); 3369 if ( placeholder ) { 3370 placeholder.css( $.effects.clipToBox( animation2 ) ); 3371 } 3372 3373 animation2.clip = start; 3374 } 3375 3376 // Animate 3377 element 3378 .queue( function( next ) { 3379 if ( placeholder ) { 3380 placeholder 3381 .animate( $.effects.clipToBox( animation1 ), duration, options.easing ) 3382 .animate( $.effects.clipToBox( animation2 ), duration, options.easing ); 3383 } 3384 3385 next(); 3386 } ) 3387 .animate( animation1, duration, options.easing ) 3388 .animate( animation2, duration, options.easing ) 3389 .queue( done ); 3390 3391 $.effects.unshift( element, queuelen, 4 ); 3392} ); 3393 3394 3395/*! 3396 * jQuery UI Effects Highlight 1.14.0 3397 * https://jqueryui.com 3398 * 3399 * Copyright OpenJS Foundation and other contributors 3400 * Released under the MIT license. 3401 * https://jquery.org/license 3402 */ 3403 3404//>>label: Highlight Effect 3405//>>group: Effects 3406//>>description: Highlights the background of an element in a defined color for a custom duration. 3407//>>docs: https://api.jqueryui.com/highlight-effect/ 3408//>>demos: https://jqueryui.com/effect/ 3409 3410 3411var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) { 3412 var element = $( this ), 3413 animation = { 3414 backgroundColor: element.css( "backgroundColor" ) 3415 }; 3416 3417 if ( options.mode === "hide" ) { 3418 animation.opacity = 0; 3419 } 3420 3421 $.effects.saveStyle( element ); 3422 3423 element 3424 .css( { 3425 backgroundImage: "none", 3426 backgroundColor: options.color || "#ffff99" 3427 } ) 3428 .animate( animation, { 3429 queue: false, 3430 duration: options.duration, 3431 easing: options.easing, 3432 complete: done 3433 } ); 3434} ); 3435 3436 3437/*! 3438 * jQuery UI Effects Size 1.14.0 3439 * https://jqueryui.com 3440 * 3441 * Copyright OpenJS Foundation and other contributors 3442 * Released under the MIT license. 3443 * https://jquery.org/license 3444 */ 3445 3446//>>label: Size Effect 3447//>>group: Effects 3448//>>description: Resize an element to a specified width and height. 3449//>>docs: https://api.jqueryui.com/size-effect/ 3450//>>demos: https://jqueryui.com/effect/ 3451 3452 3453var effectsEffectSize = $.effects.define( "size", function( options, done ) { 3454 3455 // Create element 3456 var baseline, factor, temp, 3457 element = $( this ), 3458 3459 // Copy for children 3460 cProps = [ "fontSize" ], 3461 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], 3462 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], 3463 3464 // Set options 3465 mode = options.mode, 3466 restore = mode !== "effect", 3467 scale = options.scale || "both", 3468 origin = options.origin || [ "middle", "center" ], 3469 position = element.css( "position" ), 3470 pos = element.position(), 3471 original = $.effects.scaledDimensions( element ), 3472 from = options.from || original, 3473 to = options.to || $.effects.scaledDimensions( element, 0 ); 3474 3475 $.effects.createPlaceholder( element ); 3476 3477 if ( mode === "show" ) { 3478 temp = from; 3479 from = to; 3480 to = temp; 3481 } 3482 3483 // Set scaling factor 3484 factor = { 3485 from: { 3486 y: from.height / original.height, 3487 x: from.width / original.width 3488 }, 3489 to: { 3490 y: to.height / original.height, 3491 x: to.width / original.width 3492 } 3493 }; 3494 3495 // Scale the css box 3496 if ( scale === "box" || scale === "both" ) { 3497 3498 // Vertical props scaling 3499 if ( factor.from.y !== factor.to.y ) { 3500 from = $.effects.setTransition( element, vProps, factor.from.y, from ); 3501 to = $.effects.setTransition( element, vProps, factor.to.y, to ); 3502 } 3503 3504 // Horizontal props scaling 3505 if ( factor.from.x !== factor.to.x ) { 3506 from = $.effects.setTransition( element, hProps, factor.from.x, from ); 3507 to = $.effects.setTransition( element, hProps, factor.to.x, to ); 3508 } 3509 } 3510 3511 // Scale the content 3512 if ( scale === "content" || scale === "both" ) { 3513 3514 // Vertical props scaling 3515 if ( factor.from.y !== factor.to.y ) { 3516 from = $.effects.setTransition( element, cProps, factor.from.y, from ); 3517 to = $.effects.setTransition( element, cProps, factor.to.y, to ); 3518 } 3519 } 3520 3521 // Adjust the position properties based on the provided origin points 3522 if ( origin ) { 3523 baseline = $.effects.getBaseline( origin, original ); 3524 from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top; 3525 from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left; 3526 to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top; 3527 to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left; 3528 } 3529 delete from.outerHeight; 3530 delete from.outerWidth; 3531 element.css( from ); 3532 3533 // Animate the children if desired 3534 if ( scale === "content" || scale === "both" ) { 3535 3536 vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps ); 3537 hProps = hProps.concat( [ "marginLeft", "marginRight" ] ); 3538 3539 // Only animate children with width attributes specified 3540 // TODO: is this right? should we include anything with css width specified as well 3541 element.find( "*[width]" ).each( function() { 3542 var child = $( this ), 3543 childOriginal = $.effects.scaledDimensions( child ), 3544 childFrom = { 3545 height: childOriginal.height * factor.from.y, 3546 width: childOriginal.width * factor.from.x, 3547 outerHeight: childOriginal.outerHeight * factor.from.y, 3548 outerWidth: childOriginal.outerWidth * factor.from.x 3549 }, 3550 childTo = { 3551 height: childOriginal.height * factor.to.y, 3552 width: childOriginal.width * factor.to.x, 3553 outerHeight: childOriginal.height * factor.to.y, 3554 outerWidth: childOriginal.width * factor.to.x 3555 }; 3556 3557 // Vertical props scaling 3558 if ( factor.from.y !== factor.to.y ) { 3559 childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom ); 3560 childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo ); 3561 } 3562 3563 // Horizontal props scaling 3564 if ( factor.from.x !== factor.to.x ) { 3565 childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom ); 3566 childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo ); 3567 } 3568 3569 if ( restore ) { 3570 $.effects.saveStyle( child ); 3571 } 3572 3573 // Animate children 3574 child.css( childFrom ); 3575 child.animate( childTo, options.duration, options.easing, function() { 3576 3577 // Restore children 3578 if ( restore ) { 3579 $.effects.restoreStyle( child ); 3580 } 3581 } ); 3582 } ); 3583 } 3584 3585 // Animate 3586 element.animate( to, { 3587 queue: false, 3588 duration: options.duration, 3589 easing: options.easing, 3590 complete: function() { 3591 3592 var offset = element.offset(); 3593 3594 if ( to.opacity === 0 ) { 3595 element.css( "opacity", from.opacity ); 3596 } 3597 3598 if ( !restore ) { 3599 element 3600 .css( "position", position === "static" ? "relative" : position ) 3601 .offset( offset ); 3602 3603 // Need to save style here so that automatic style restoration 3604 // doesn't restore to the original styles from before the animation. 3605 $.effects.saveStyle( element ); 3606 } 3607 3608 done(); 3609 } 3610 } ); 3611 3612} ); 3613 3614 3615/*! 3616 * jQuery UI Effects Scale 1.14.0 3617 * https://jqueryui.com 3618 * 3619 * Copyright OpenJS Foundation and other contributors 3620 * Released under the MIT license. 3621 * https://jquery.org/license 3622 */ 3623 3624//>>label: Scale Effect 3625//>>group: Effects 3626//>>description: Grows or shrinks an element and its content. 3627//>>docs: https://api.jqueryui.com/scale-effect/ 3628//>>demos: https://jqueryui.com/effect/ 3629 3630 3631var effectsEffectScale = $.effects.define( "scale", function( options, done ) { 3632 3633 // Create element 3634 var el = $( this ), 3635 mode = options.mode, 3636 percent = parseInt( options.percent, 10 ) || 3637 ( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ), 3638 3639 newOptions = $.extend( true, { 3640 from: $.effects.scaledDimensions( el ), 3641 to: $.effects.scaledDimensions( el, percent, options.direction || "both" ), 3642 origin: options.origin || [ "middle", "center" ] 3643 }, options ); 3644 3645 // Fade option to support puff 3646 if ( options.fade ) { 3647 newOptions.from.opacity = 1; 3648 newOptions.to.opacity = 0; 3649 } 3650 3651 $.effects.effect.size.call( this, newOptions, done ); 3652} ); 3653 3654 3655/*! 3656 * jQuery UI Effects Puff 1.14.0 3657 * https://jqueryui.com 3658 * 3659 * Copyright OpenJS Foundation and other contributors 3660 * Released under the MIT license. 3661 * https://jquery.org/license 3662 */ 3663 3664//>>label: Puff Effect 3665//>>group: Effects 3666//>>description: Creates a puff effect by scaling the element up and hiding it at the same time. 3667//>>docs: https://api.jqueryui.com/puff-effect/ 3668//>>demos: https://jqueryui.com/effect/ 3669 3670 3671var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) { 3672 var newOptions = $.extend( true, {}, options, { 3673 fade: true, 3674 percent: parseInt( options.percent, 10 ) || 150 3675 } ); 3676 3677 $.effects.effect.scale.call( this, newOptions, done ); 3678} ); 3679 3680 3681/*! 3682 * jQuery UI Effects Pulsate 1.14.0 3683 * https://jqueryui.com 3684 * 3685 * Copyright OpenJS Foundation and other contributors 3686 * Released under the MIT license. 3687 * https://jquery.org/license 3688 */ 3689 3690//>>label: Pulsate Effect 3691//>>group: Effects 3692//>>description: Pulsates an element n times by changing the opacity to zero and back. 3693//>>docs: https://api.jqueryui.com/pulsate-effect/ 3694//>>demos: https://jqueryui.com/effect/ 3695 3696 3697var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) { 3698 var element = $( this ), 3699 mode = options.mode, 3700 show = mode === "show", 3701 hide = mode === "hide", 3702 showhide = show || hide, 3703 3704 // Showing or hiding leaves off the "last" animation 3705 anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), 3706 duration = options.duration / anims, 3707 animateTo = 0, 3708 i = 1, 3709 queuelen = element.queue().length; 3710 3711 if ( show || !element.is( ":visible" ) ) { 3712 element.css( "opacity", 0 ).show(); 3713 animateTo = 1; 3714 } 3715 3716 // Anims - 1 opacity "toggles" 3717 for ( ; i < anims; i++ ) { 3718 element.animate( { opacity: animateTo }, duration, options.easing ); 3719 animateTo = 1 - animateTo; 3720 } 3721 3722 element.animate( { opacity: animateTo }, duration, options.easing ); 3723 3724 element.queue( done ); 3725 3726 $.effects.unshift( element, queuelen, anims + 1 ); 3727} ); 3728 3729 3730/*! 3731 * jQuery UI Effects Shake 1.14.0 3732 * https://jqueryui.com 3733 * 3734 * Copyright OpenJS Foundation and other contributors 3735 * Released under the MIT license. 3736 * https://jquery.org/license 3737 */ 3738 3739//>>label: Shake Effect 3740//>>group: Effects 3741//>>description: Shakes an element horizontally or vertically n times. 3742//>>docs: https://api.jqueryui.com/shake-effect/ 3743//>>demos: https://jqueryui.com/effect/ 3744 3745 3746var effectsEffectShake = $.effects.define( "shake", function( options, done ) { 3747 3748 var i = 1, 3749 element = $( this ), 3750 direction = options.direction || "left", 3751 distance = options.distance || 20, 3752 times = options.times || 3, 3753 anims = times * 2 + 1, 3754 speed = Math.round( options.duration / anims ), 3755 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 3756 positiveMotion = ( direction === "up" || direction === "left" ), 3757 animation = {}, 3758 animation1 = {}, 3759 animation2 = {}, 3760 3761 queuelen = element.queue().length; 3762 3763 $.effects.createPlaceholder( element ); 3764 3765 // Animation 3766 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; 3767 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; 3768 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; 3769 3770 // Animate 3771 element.animate( animation, speed, options.easing ); 3772 3773 // Shakes 3774 for ( ; i < times; i++ ) { 3775 element 3776 .animate( animation1, speed, options.easing ) 3777 .animate( animation2, speed, options.easing ); 3778 } 3779 3780 element 3781 .animate( animation1, speed, options.easing ) 3782 .animate( animation, speed / 2, options.easing ) 3783 .queue( done ); 3784 3785 $.effects.unshift( element, queuelen, anims + 1 ); 3786} ); 3787 3788 3789/*! 3790 * jQuery UI Effects Slide 1.14.0 3791 * https://jqueryui.com 3792 * 3793 * Copyright OpenJS Foundation and other contributors 3794 * Released under the MIT license. 3795 * https://jquery.org/license 3796 */ 3797 3798//>>label: Slide Effect 3799//>>group: Effects 3800//>>description: Slides an element in and out of the viewport. 3801//>>docs: https://api.jqueryui.com/slide-effect/ 3802//>>demos: https://jqueryui.com/effect/ 3803 3804 3805var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) { 3806 var startClip, startRef, 3807 element = $( this ), 3808 map = { 3809 up: [ "bottom", "top" ], 3810 down: [ "top", "bottom" ], 3811 left: [ "right", "left" ], 3812 right: [ "left", "right" ] 3813 }, 3814 mode = options.mode, 3815 direction = options.direction || "left", 3816 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 3817 positiveMotion = ( direction === "up" || direction === "left" ), 3818 distance = options.distance || 3819 element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ), 3820 animation = {}; 3821 3822 $.effects.createPlaceholder( element ); 3823 3824 startClip = element.cssClip(); 3825 startRef = element.position()[ ref ]; 3826 3827 // Define hide animation 3828 animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef; 3829 animation.clip = element.cssClip(); 3830 animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ]; 3831 3832 // Reverse the animation if we're showing 3833 if ( mode === "show" ) { 3834 element.cssClip( animation.clip ); 3835 element.css( ref, animation[ ref ] ); 3836 animation.clip = startClip; 3837 animation[ ref ] = startRef; 3838 } 3839 3840 // Actually animate 3841 element.animate( animation, { 3842 queue: false, 3843 duration: options.duration, 3844 easing: options.easing, 3845 complete: done 3846 } ); 3847} ); 3848 3849 3850/*! 3851 * jQuery UI Effects Transfer 1.14.0 3852 * https://jqueryui.com 3853 * 3854 * Copyright OpenJS Foundation and other contributors 3855 * Released under the MIT license. 3856 * https://jquery.org/license 3857 */ 3858 3859//>>label: Transfer Effect 3860//>>group: Effects 3861//>>description: Displays a transfer effect from one element to another. 3862//>>docs: https://api.jqueryui.com/transfer-effect/ 3863//>>demos: https://jqueryui.com/effect/ 3864 3865 3866var effect; 3867if ( $.uiBackCompat === true ) { 3868 effect = $.effects.define( "transfer", function( options, done ) { 3869 $( this ).transfer( options, done ); 3870 } ); 3871} 3872var effectsEffectTransfer = effect; 3873 3874 3875/*! 3876 * jQuery UI Focusable 1.14.0 3877 * https://jqueryui.com 3878 * 3879 * Copyright OpenJS Foundation and other contributors 3880 * Released under the MIT license. 3881 * https://jquery.org/license 3882 */ 3883 3884//>>label: :focusable Selector 3885//>>group: Core 3886//>>description: Selects elements which can be focused. 3887//>>docs: https://api.jqueryui.com/focusable-selector/ 3888 3889 3890// Selectors 3891$.ui.focusable = function( element, hasTabindex ) { 3892 var map, mapName, img, focusableIfVisible, fieldset, 3893 nodeName = element.nodeName.toLowerCase(); 3894 3895 if ( "area" === nodeName ) { 3896 map = element.parentNode; 3897 mapName = map.name; 3898 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { 3899 return false; 3900 } 3901 img = $( "img[usemap='#" + mapName + "']" ); 3902 return img.length > 0 && img.is( ":visible" ); 3903 } 3904 3905 if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) { 3906 focusableIfVisible = !element.disabled; 3907 3908 if ( focusableIfVisible ) { 3909 3910 // Form controls within a disabled fieldset are disabled. 3911 // However, controls within the fieldset's legend do not get disabled. 3912 // Since controls generally aren't placed inside legends, we skip 3913 // this portion of the check. 3914 fieldset = $( element ).closest( "fieldset" )[ 0 ]; 3915 if ( fieldset ) { 3916 focusableIfVisible = !fieldset.disabled; 3917 } 3918 } 3919 } else if ( "a" === nodeName ) { 3920 focusableIfVisible = element.href || hasTabindex; 3921 } else { 3922 focusableIfVisible = hasTabindex; 3923 } 3924 3925 return focusableIfVisible && $( element ).is( ":visible" ) && 3926 $( element ).css( "visibility" ) === "visible"; 3927}; 3928 3929$.extend( $.expr.pseudos, { 3930 focusable: function( element ) { 3931 return $.ui.focusable( element, $.attr( element, "tabindex" ) != null ); 3932 } 3933} ); 3934 3935var focusable = $.ui.focusable; 3936 3937 3938/*! 3939 * jQuery UI Form Reset Mixin 1.14.0 3940 * https://jqueryui.com 3941 * 3942 * Copyright OpenJS Foundation and other contributors 3943 * Released under the MIT license. 3944 * https://jquery.org/license 3945 */ 3946 3947//>>label: Form Reset Mixin 3948//>>group: Core 3949//>>description: Refresh input widgets when their form is reset 3950//>>docs: https://api.jqueryui.com/form-reset-mixin/ 3951 3952 3953var formResetMixin = $.ui.formResetMixin = { 3954 _formResetHandler: function() { 3955 var form = $( this ); 3956 3957 // Wait for the form reset to actually happen before refreshing 3958 setTimeout( function() { 3959 var instances = form.data( "ui-form-reset-instances" ); 3960 $.each( instances, function() { 3961 this.refresh(); 3962 } ); 3963 } ); 3964 }, 3965 3966 _bindFormResetHandler: function() { 3967 this.form = $( this.element.prop( "form" ) ); 3968 if ( !this.form.length ) { 3969 return; 3970 } 3971 3972 var instances = this.form.data( "ui-form-reset-instances" ) || []; 3973 if ( !instances.length ) { 3974 3975 // We don't use _on() here because we use a single event handler per form 3976 this.form.on( "reset.ui-form-reset", this._formResetHandler ); 3977 } 3978 instances.push( this ); 3979 this.form.data( "ui-form-reset-instances", instances ); 3980 }, 3981 3982 _unbindFormResetHandler: function() { 3983 if ( !this.form.length ) { 3984 return; 3985 } 3986 3987 var instances = this.form.data( "ui-form-reset-instances" ); 3988 instances.splice( $.inArray( this, instances ), 1 ); 3989 if ( instances.length ) { 3990 this.form.data( "ui-form-reset-instances", instances ); 3991 } else { 3992 this.form 3993 .removeData( "ui-form-reset-instances" ) 3994 .off( "reset.ui-form-reset" ); 3995 } 3996 } 3997}; 3998 3999 4000/*! 4001 * jQuery UI Legacy jQuery Core patches 1.14.0 4002 * https://jqueryui.com 4003 * 4004 * Copyright OpenJS Foundation and other contributors 4005 * Released under the MIT license. 4006 * https://jquery.org/license 4007 * 4008 */ 4009 4010//>>label: Legacy jQuery Core patches 4011//>>group: Core 4012//>>description: Backport `.even()`, `.odd()` and `$.escapeSelector` to older jQuery Core versions (deprecated) 4013 4014 4015// Support: jQuery 2.2.x or older. 4016// This method has been defined in jQuery 3.0.0. 4017// Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js 4018if ( !$.escapeSelector ) { 4019 $.escapeSelector = function( id ) { 4020 return CSS.escape( id + "" ); 4021 }; 4022} 4023 4024// Support: jQuery 3.4.x or older 4025// These methods have been defined in jQuery 3.5.0. 4026if ( !$.fn.even || !$.fn.odd ) { 4027 $.fn.extend( { 4028 even: function() { 4029 return this.filter( function( i ) { 4030 return i % 2 === 0; 4031 } ); 4032 }, 4033 odd: function() { 4034 return this.filter( function( i ) { 4035 return i % 2 === 1; 4036 } ); 4037 } 4038 } ); 4039} 4040 4041; 4042/*! 4043 * jQuery UI Keycode 1.14.0 4044 * https://jqueryui.com 4045 * 4046 * Copyright OpenJS Foundation and other contributors 4047 * Released under the MIT license. 4048 * https://jquery.org/license 4049 */ 4050 4051//>>label: Keycode 4052//>>group: Core 4053//>>description: Provide keycodes as keynames 4054//>>docs: https://api.jqueryui.com/jQuery.ui.keyCode/ 4055 4056 4057var keycode = $.ui.keyCode = { 4058 BACKSPACE: 8, 4059 COMMA: 188, 4060 DELETE: 46, 4061 DOWN: 40, 4062 END: 35, 4063 ENTER: 13, 4064 ESCAPE: 27, 4065 HOME: 36, 4066 LEFT: 37, 4067 PAGE_DOWN: 34, 4068 PAGE_UP: 33, 4069 PERIOD: 190, 4070 RIGHT: 39, 4071 SPACE: 32, 4072 TAB: 9, 4073 UP: 38 4074}; 4075 4076 4077/*! 4078 * jQuery UI Labels 1.14.0 4079 * https://jqueryui.com 4080 * 4081 * Copyright OpenJS Foundation and other contributors 4082 * Released under the MIT license. 4083 * https://jquery.org/license 4084 */ 4085 4086//>>label: labels 4087//>>group: Core 4088//>>description: Find all the labels associated with a given input 4089//>>docs: https://api.jqueryui.com/labels/ 4090 4091 4092var labels = $.fn.labels = function() { 4093 var ancestor, selector, id, labels, ancestors; 4094 4095 if ( !this.length ) { 4096 return this.pushStack( [] ); 4097 } 4098 4099 // Check control.labels first 4100 if ( this[ 0 ].labels && this[ 0 ].labels.length ) { 4101 return this.pushStack( this[ 0 ].labels ); 4102 } 4103 4104 // If `control.labels` is empty - e.g. inside of document fragments - find 4105 // the labels manually 4106 labels = this.eq( 0 ).parents( "label" ); 4107 4108 // Look for the label based on the id 4109 id = this.attr( "id" ); 4110 if ( id ) { 4111 4112 // We don't search against the document in case the element 4113 // is disconnected from the DOM 4114 ancestor = this.eq( 0 ).parents().last(); 4115 4116 // Get a full set of top level ancestors 4117 ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() ); 4118 4119 // Create a selector for the label based on the id 4120 selector = "label[for='" + CSS.escape( id ) + "']"; 4121 4122 labels = labels.add( ancestors.find( selector ).addBack( selector ) ); 4123 4124 } 4125 4126 // Return whatever we have found for labels 4127 return this.pushStack( labels ); 4128}; 4129 4130 4131/*! 4132 * jQuery UI Scroll Parent 1.14.0 4133 * https://jqueryui.com 4134 * 4135 * Copyright OpenJS Foundation and other contributors 4136 * Released under the MIT license. 4137 * https://jquery.org/license 4138 */ 4139 4140//>>label: scrollParent 4141//>>group: Core 4142//>>description: Get the closest ancestor element that is scrollable. 4143//>>docs: https://api.jqueryui.com/scrollParent/ 4144 4145 4146var scrollParent = $.fn.scrollParent = function( includeHidden ) { 4147 var position = this.css( "position" ), 4148 excludeStaticParent = position === "absolute", 4149 overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/, 4150 scrollParent = this.parents().filter( function() { 4151 var parent = $( this ); 4152 if ( excludeStaticParent && parent.css( "position" ) === "static" ) { 4153 return false; 4154 } 4155 return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + 4156 parent.css( "overflow-x" ) ); 4157 } ).eq( 0 ); 4158 4159 return position === "fixed" || !scrollParent.length ? 4160 $( this[ 0 ].ownerDocument || document ) : 4161 scrollParent; 4162}; 4163 4164 4165/*! 4166 * jQuery UI Tabbable 1.14.0 4167 * https://jqueryui.com 4168 * 4169 * Copyright OpenJS Foundation and other contributors 4170 * Released under the MIT license. 4171 * https://jquery.org/license 4172 */ 4173 4174//>>label: :tabbable Selector 4175//>>group: Core 4176//>>description: Selects elements which can be tabbed to. 4177//>>docs: https://api.jqueryui.com/tabbable-selector/ 4178 4179 4180var tabbable = $.extend( $.expr.pseudos, { 4181 tabbable: function( element ) { 4182 var tabIndex = $.attr( element, "tabindex" ), 4183 hasTabindex = tabIndex != null; 4184 return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex ); 4185 } 4186} ); 4187 4188 4189/*! 4190 * jQuery UI Unique ID 1.14.0 4191 * https://jqueryui.com 4192 * 4193 * Copyright OpenJS Foundation and other contributors 4194 * Released under the MIT license. 4195 * https://jquery.org/license 4196 */ 4197 4198//>>label: uniqueId 4199//>>group: Core 4200//>>description: Functions to generate and remove uniqueId's 4201//>>docs: https://api.jqueryui.com/uniqueId/ 4202 4203 4204var uniqueId = $.fn.extend( { 4205 uniqueId: ( function() { 4206 var uuid = 0; 4207 4208 return function() { 4209 return this.each( function() { 4210 if ( !this.id ) { 4211 this.id = "ui-id-" + ( ++uuid ); 4212 } 4213 } ); 4214 }; 4215 } )(), 4216 4217 removeUniqueId: function() { 4218 return this.each( function() { 4219 if ( /^ui-id-\d+$/.test( this.id ) ) { 4220 $( this ).removeAttr( "id" ); 4221 } 4222 } ); 4223 } 4224} ); 4225 4226 4227/*! 4228 * jQuery UI Accordion 1.14.0 4229 * https://jqueryui.com 4230 * 4231 * Copyright OpenJS Foundation and other contributors 4232 * Released under the MIT license. 4233 * https://jquery.org/license 4234 */ 4235 4236//>>label: Accordion 4237//>>group: Widgets 4238/* eslint-disable max-len */ 4239//>>description: Displays collapsible content panels for presenting information in a limited amount of space. 4240/* eslint-enable max-len */ 4241//>>docs: https://api.jqueryui.com/accordion/ 4242//>>demos: https://jqueryui.com/accordion/ 4243//>>css.structure: ../../themes/base/core.css 4244//>>css.structure: ../../themes/base/accordion.css 4245//>>css.theme: ../../themes/base/theme.css 4246 4247 4248var widgetsAccordion = $.widget( "ui.accordion", { 4249 version: "1.14.0", 4250 options: { 4251 active: 0, 4252 animate: {}, 4253 classes: { 4254 "ui-accordion-header": "ui-corner-top", 4255 "ui-accordion-header-collapsed": "ui-corner-all", 4256 "ui-accordion-content": "ui-corner-bottom" 4257 }, 4258 collapsible: false, 4259 event: "click", 4260 header: function( elem ) { 4261 return elem 4262 .find( "> li > :first-child" ) 4263 .add( 4264 elem.find( "> :not(li)" ) 4265 4266 // Support: jQuery <3.5 only 4267 // We could use `.even()` but that's unavailable in older jQuery. 4268 .filter( function( i ) { 4269 return i % 2 === 0; 4270 } ) 4271 ); 4272 }, 4273 heightStyle: "auto", 4274 icons: { 4275 activeHeader: "ui-icon-triangle-1-s", 4276 header: "ui-icon-triangle-1-e" 4277 }, 4278 4279 // Callbacks 4280 activate: null, 4281 beforeActivate: null 4282 }, 4283 4284 hideProps: { 4285 borderTopWidth: "hide", 4286 borderBottomWidth: "hide", 4287 paddingTop: "hide", 4288 paddingBottom: "hide", 4289 height: "hide" 4290 }, 4291 4292 showProps: { 4293 borderTopWidth: "show", 4294 borderBottomWidth: "show", 4295 paddingTop: "show", 4296 paddingBottom: "show", 4297 height: "show" 4298 }, 4299 4300 _create: function() { 4301 var options = this.options; 4302 4303 this.prevShow = this.prevHide = $(); 4304 this._addClass( "ui-accordion", "ui-widget ui-helper-reset" ); 4305 this.element.attr( "role", "tablist" ); 4306 4307 // Don't allow collapsible: false and active: false / null 4308 if ( !options.collapsible && ( options.active === false || options.active == null ) ) { 4309 options.active = 0; 4310 } 4311 4312 this._processPanels(); 4313 4314 // handle negative values 4315 if ( options.active < 0 ) { 4316 options.active += this.headers.length; 4317 } 4318 this._refresh(); 4319 }, 4320 4321 _getCreateEventData: function() { 4322 return { 4323 header: this.active, 4324 panel: !this.active.length ? $() : this.active.next() 4325 }; 4326 }, 4327 4328 _createIcons: function() { 4329 var icon, children, 4330 icons = this.options.icons; 4331 4332 if ( icons ) { 4333 icon = $( "<span>" ); 4334 this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header ); 4335 icon.prependTo( this.headers ); 4336 children = this.active.children( ".ui-accordion-header-icon" ); 4337 this._removeClass( children, icons.header ) 4338 ._addClass( children, null, icons.activeHeader ) 4339 ._addClass( this.headers, "ui-accordion-icons" ); 4340 } 4341 }, 4342 4343 _destroyIcons: function() { 4344 this._removeClass( this.headers, "ui-accordion-icons" ); 4345 this.headers.children( ".ui-accordion-header-icon" ).remove(); 4346 }, 4347 4348 _destroy: function() { 4349 var contents; 4350 4351 // Clean up main element 4352 this.element.removeAttr( "role" ); 4353 4354 // Clean up headers 4355 this.headers 4356 .removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" ) 4357 .removeUniqueId(); 4358 4359 this._destroyIcons(); 4360 4361 // Clean up content panels 4362 contents = this.headers.next() 4363 .css( "display", "" ) 4364 .removeAttr( "role aria-hidden aria-labelledby" ) 4365 .removeUniqueId(); 4366 4367 if ( this.options.heightStyle !== "content" ) { 4368 contents.css( "height", "" ); 4369 } 4370 }, 4371 4372 _setOption: function( key, value ) { 4373 if ( key === "active" ) { 4374 4375 // _activate() will handle invalid values and update this.options 4376 this._activate( value ); 4377 return; 4378 } 4379 4380 if ( key === "event" ) { 4381 if ( this.options.event ) { 4382 this._off( this.headers, this.options.event ); 4383 } 4384 this._setupEvents( value ); 4385 } 4386 4387 this._super( key, value ); 4388 4389 // Setting collapsible: false while collapsed; open first panel 4390 if ( key === "collapsible" && !value && this.options.active === false ) { 4391 this._activate( 0 ); 4392 } 4393 4394 if ( key === "icons" ) { 4395 this._destroyIcons(); 4396 if ( value ) { 4397 this._createIcons(); 4398 } 4399 } 4400 }, 4401 4402 _setOptionDisabled: function( value ) { 4403 this._super( value ); 4404 4405 this.element.attr( "aria-disabled", value ); 4406 this._toggleClass( null, "ui-state-disabled", !!value ); 4407 }, 4408 4409 _keydown: function( event ) { 4410 if ( event.altKey || event.ctrlKey ) { 4411 return; 4412 } 4413 4414 var keyCode = $.ui.keyCode, 4415 length = this.headers.length, 4416 currentIndex = this.headers.index( event.target ), 4417 toFocus = false; 4418 4419 switch ( event.keyCode ) { 4420 case keyCode.RIGHT: 4421 case keyCode.DOWN: 4422 toFocus = this.headers[ ( currentIndex + 1 ) % length ]; 4423 break; 4424 case keyCode.LEFT: 4425 case keyCode.UP: 4426 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; 4427 break; 4428 case keyCode.SPACE: 4429 case keyCode.ENTER: 4430 this._eventHandler( event ); 4431 break; 4432 case keyCode.HOME: 4433 toFocus = this.headers[ 0 ]; 4434 break; 4435 case keyCode.END: 4436 toFocus = this.headers[ length - 1 ]; 4437 break; 4438 } 4439 4440 if ( toFocus ) { 4441 $( event.target ).attr( "tabIndex", -1 ); 4442 $( toFocus ).attr( "tabIndex", 0 ); 4443 $( toFocus ).trigger( "focus" ); 4444 event.preventDefault(); 4445 } 4446 }, 4447 4448 _panelKeyDown: function( event ) { 4449 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { 4450 $( event.currentTarget ).prev().trigger( "focus" ); 4451 } 4452 }, 4453 4454 refresh: function() { 4455 var options = this.options; 4456 this._processPanels(); 4457 4458 // Was collapsed or no panel 4459 if ( ( options.active === false && options.collapsible === true ) || 4460 !this.headers.length ) { 4461 options.active = false; 4462 this.active = $(); 4463 4464 // active false only when collapsible is true 4465 } else if ( options.active === false ) { 4466 this._activate( 0 ); 4467 4468 // was active, but active panel is gone 4469 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 4470 4471 // all remaining panel are disabled 4472 if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) { 4473 options.active = false; 4474 this.active = $(); 4475 4476 // activate previous panel 4477 } else { 4478 this._activate( Math.max( 0, options.active - 1 ) ); 4479 } 4480 4481 // was active, active panel still exists 4482 } else { 4483 4484 // make sure active index is correct 4485 options.active = this.headers.index( this.active ); 4486 } 4487 4488 this._destroyIcons(); 4489 4490 this._refresh(); 4491 }, 4492 4493 _processPanels: function() { 4494 var prevHeaders = this.headers, 4495 prevPanels = this.panels; 4496 4497 if ( typeof this.options.header === "function" ) { 4498 this.headers = this.options.header( this.element ); 4499 } else { 4500 this.headers = this.element.find( this.options.header ); 4501 } 4502 this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed", 4503 "ui-state-default" ); 4504 4505 this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide(); 4506 this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" ); 4507 4508 // Avoid memory leaks (#10056) 4509 if ( prevPanels ) { 4510 this._off( prevHeaders.not( this.headers ) ); 4511 this._off( prevPanels.not( this.panels ) ); 4512 } 4513 }, 4514 4515 _refresh: function() { 4516 var maxHeight, 4517 options = this.options, 4518 heightStyle = options.heightStyle, 4519 parent = this.element.parent(); 4520 4521 this.active = this._findActive( options.active ); 4522 this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" ) 4523 ._removeClass( this.active, "ui-accordion-header-collapsed" ); 4524 this._addClass( this.active.next(), "ui-accordion-content-active" ); 4525 this.active.next().show(); 4526 4527 this.headers 4528 .attr( "role", "tab" ) 4529 .each( function() { 4530 var header = $( this ), 4531 headerId = header.uniqueId().attr( "id" ), 4532 panel = header.next(), 4533 panelId = panel.uniqueId().attr( "id" ); 4534 header.attr( "aria-controls", panelId ); 4535 panel.attr( "aria-labelledby", headerId ); 4536 } ) 4537 .next() 4538 .attr( "role", "tabpanel" ); 4539 4540 this.headers 4541 .not( this.active ) 4542 .attr( { 4543 "aria-selected": "false", 4544 "aria-expanded": "false", 4545 tabIndex: -1 4546 } ) 4547 .next() 4548 .attr( { 4549 "aria-hidden": "true" 4550 } ) 4551 .hide(); 4552 4553 // Make sure at least one header is in the tab order 4554 if ( !this.active.length ) { 4555 this.headers.eq( 0 ).attr( "tabIndex", 0 ); 4556 } else { 4557 this.active.attr( { 4558 "aria-selected": "true", 4559 "aria-expanded": "true", 4560 tabIndex: 0 4561 } ) 4562 .next() 4563 .attr( { 4564 "aria-hidden": "false" 4565 } ); 4566 } 4567 4568 this._createIcons(); 4569 4570 this._setupEvents( options.event ); 4571 4572 if ( heightStyle === "fill" ) { 4573 maxHeight = parent.height(); 4574 this.element.siblings( ":visible" ).each( function() { 4575 var elem = $( this ), 4576 position = elem.css( "position" ); 4577 4578 if ( position === "absolute" || position === "fixed" ) { 4579 return; 4580 } 4581 maxHeight -= elem.outerHeight( true ); 4582 } ); 4583 4584 this.headers.each( function() { 4585 maxHeight -= $( this ).outerHeight( true ); 4586 } ); 4587 4588 this.headers.next() 4589 .each( function() { 4590 $( this ).height( Math.max( 0, maxHeight - 4591 $( this ).innerHeight() + $( this ).height() ) ); 4592 } ) 4593 .css( "overflow", "auto" ); 4594 } else if ( heightStyle === "auto" ) { 4595 maxHeight = 0; 4596 this.headers.next() 4597 .each( function() { 4598 var isVisible = $( this ).is( ":visible" ); 4599 if ( !isVisible ) { 4600 $( this ).show(); 4601 } 4602 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); 4603 if ( !isVisible ) { 4604 $( this ).hide(); 4605 } 4606 } ) 4607 .height( maxHeight ); 4608 } 4609 }, 4610 4611 _activate: function( index ) { 4612 var active = this._findActive( index )[ 0 ]; 4613 4614 // Trying to activate the already active panel 4615 if ( active === this.active[ 0 ] ) { 4616 return; 4617 } 4618 4619 // Trying to collapse, simulate a click on the currently active header 4620 active = active || this.active[ 0 ]; 4621 4622 this._eventHandler( { 4623 target: active, 4624 currentTarget: active, 4625 preventDefault: $.noop 4626 } ); 4627 }, 4628 4629 _findActive: function( selector ) { 4630 return typeof selector === "number" ? this.headers.eq( selector ) : $(); 4631 }, 4632 4633 _setupEvents: function( event ) { 4634 var events = { 4635 keydown: "_keydown" 4636 }; 4637 if ( event ) { 4638 $.each( event.split( " " ), function( index, eventName ) { 4639 events[ eventName ] = "_eventHandler"; 4640 } ); 4641 } 4642 4643 this._off( this.headers.add( this.headers.next() ) ); 4644 this._on( this.headers, events ); 4645 this._on( this.headers.next(), { keydown: "_panelKeyDown" } ); 4646 this._hoverable( this.headers ); 4647 this._focusable( this.headers ); 4648 }, 4649 4650 _eventHandler: function( event ) { 4651 var activeChildren, clickedChildren, 4652 options = this.options, 4653 active = this.active, 4654 clicked = $( event.currentTarget ), 4655 clickedIsActive = clicked[ 0 ] === active[ 0 ], 4656 collapsing = clickedIsActive && options.collapsible, 4657 toShow = collapsing ? $() : clicked.next(), 4658 toHide = active.next(), 4659 eventData = { 4660 oldHeader: active, 4661 oldPanel: toHide, 4662 newHeader: collapsing ? $() : clicked, 4663 newPanel: toShow 4664 }; 4665 4666 event.preventDefault(); 4667 4668 if ( 4669 4670 // click on active header, but not collapsible 4671 ( clickedIsActive && !options.collapsible ) || 4672 4673 // allow canceling activation 4674 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 4675 return; 4676 } 4677 4678 options.active = collapsing ? false : this.headers.index( clicked ); 4679 4680 // When the call to ._toggle() comes after the class changes 4681 // it causes a very odd bug in IE 8 (see #6720) 4682 this.active = clickedIsActive ? $() : clicked; 4683 this._toggle( eventData ); 4684 4685 // Switch classes 4686 // corner classes on the previously active header stay after the animation 4687 this._removeClass( active, "ui-accordion-header-active", "ui-state-active" ); 4688 if ( options.icons ) { 4689 activeChildren = active.children( ".ui-accordion-header-icon" ); 4690 this._removeClass( activeChildren, null, options.icons.activeHeader ) 4691 ._addClass( activeChildren, null, options.icons.header ); 4692 } 4693 4694 if ( !clickedIsActive ) { 4695 this._removeClass( clicked, "ui-accordion-header-collapsed" ) 4696 ._addClass( clicked, "ui-accordion-header-active", "ui-state-active" ); 4697 if ( options.icons ) { 4698 clickedChildren = clicked.children( ".ui-accordion-header-icon" ); 4699 this._removeClass( clickedChildren, null, options.icons.header ) 4700 ._addClass( clickedChildren, null, options.icons.activeHeader ); 4701 } 4702 4703 this._addClass( clicked.next(), "ui-accordion-content-active" ); 4704 } 4705 }, 4706 4707 _toggle: function( data ) { 4708 var toShow = data.newPanel, 4709 toHide = this.prevShow.length ? this.prevShow : data.oldPanel; 4710 4711 // Handle activating a panel during the animation for another activation 4712 this.prevShow.add( this.prevHide ).stop( true, true ); 4713 this.prevShow = toShow; 4714 this.prevHide = toHide; 4715 4716 if ( this.options.animate ) { 4717 this._animate( toShow, toHide, data ); 4718 } else { 4719 toHide.hide(); 4720 toShow.show(); 4721 this._toggleComplete( data ); 4722 } 4723 4724 toHide.attr( { 4725 "aria-hidden": "true" 4726 } ); 4727 toHide.prev().attr( { 4728 "aria-selected": "false", 4729 "aria-expanded": "false" 4730 } ); 4731 4732 // if we're switching panels, remove the old header from the tab order 4733 // if we're opening from collapsed state, remove the previous header from the tab order 4734 // if we're collapsing, then keep the collapsing header in the tab order 4735 if ( toShow.length && toHide.length ) { 4736 toHide.prev().attr( { 4737 "tabIndex": -1, 4738 "aria-expanded": "false" 4739 } ); 4740 } else if ( toShow.length ) { 4741 this.headers.filter( function() { 4742 return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0; 4743 } ) 4744 .attr( "tabIndex", -1 ); 4745 } 4746 4747 toShow 4748 .attr( "aria-hidden", "false" ) 4749 .prev() 4750 .attr( { 4751 "aria-selected": "true", 4752 "aria-expanded": "true", 4753 tabIndex: 0 4754 } ); 4755 }, 4756 4757 _animate: function( toShow, toHide, data ) { 4758 var total, easing, duration, 4759 that = this, 4760 adjust = 0, 4761 boxSizing = toShow.css( "box-sizing" ), 4762 down = toShow.length && 4763 ( !toHide.length || ( toShow.index() < toHide.index() ) ), 4764 animate = this.options.animate || {}, 4765 options = down && animate.down || animate, 4766 complete = function() { 4767 that._toggleComplete( data ); 4768 }; 4769 4770 if ( typeof options === "number" ) { 4771 duration = options; 4772 } 4773 if ( typeof options === "string" ) { 4774 easing = options; 4775 } 4776 4777 // fall back from options to animation in case of partial down settings 4778 easing = easing || options.easing || animate.easing; 4779 duration = duration || options.duration || animate.duration; 4780 4781 if ( !toHide.length ) { 4782 return toShow.animate( this.showProps, duration, easing, complete ); 4783 } 4784 if ( !toShow.length ) { 4785 return toHide.animate( this.hideProps, duration, easing, complete ); 4786 } 4787 4788 total = toShow.show().outerHeight(); 4789 toHide.animate( this.hideProps, { 4790 duration: duration, 4791 easing: easing, 4792 step: function( now, fx ) { 4793 fx.now = Math.round( now ); 4794 } 4795 } ); 4796 toShow 4797 .hide() 4798 .animate( this.showProps, { 4799 duration: duration, 4800 easing: easing, 4801 complete: complete, 4802 step: function( now, fx ) { 4803 fx.now = Math.round( now ); 4804 if ( fx.prop !== "height" ) { 4805 if ( boxSizing === "content-box" ) { 4806 adjust += fx.now; 4807 } 4808 } else if ( that.options.heightStyle !== "content" ) { 4809 fx.now = Math.round( total - toHide.outerHeight() - adjust ); 4810 adjust = 0; 4811 } 4812 } 4813 } ); 4814 }, 4815 4816 _toggleComplete: function( data ) { 4817 var toHide = data.oldPanel, 4818 prev = toHide.prev(); 4819 4820 this._removeClass( toHide, "ui-accordion-content-active" ); 4821 this._removeClass( prev, "ui-accordion-header-active" ) 4822 ._addClass( prev, "ui-accordion-header-collapsed" ); 4823 4824 this._trigger( "activate", null, data ); 4825 } 4826} ); 4827 4828 4829/*! 4830 * jQuery UI Menu 1.14.0 4831 * https://jqueryui.com 4832 * 4833 * Copyright OpenJS Foundation and other contributors 4834 * Released under the MIT license. 4835 * https://jquery.org/license 4836 */ 4837 4838//>>label: Menu 4839//>>group: Widgets 4840//>>description: Creates nestable menus. 4841//>>docs: https://api.jqueryui.com/menu/ 4842//>>demos: https://jqueryui.com/menu/ 4843//>>css.structure: ../../themes/base/core.css 4844//>>css.structure: ../../themes/base/menu.css 4845//>>css.theme: ../../themes/base/theme.css 4846 4847 4848var widgetsMenu = $.widget( "ui.menu", { 4849 version: "1.14.0", 4850 defaultElement: "<ul>", 4851 delay: 300, 4852 options: { 4853 icons: { 4854 submenu: "ui-icon-caret-1-e" 4855 }, 4856 items: "> *", 4857 menus: "ul", 4858 position: { 4859 my: "left top", 4860 at: "right top" 4861 }, 4862 role: "menu", 4863 4864 // Callbacks 4865 blur: null, 4866 focus: null, 4867 select: null 4868 }, 4869 4870 _create: function() { 4871 this.activeMenu = this.element; 4872 4873 // Flag used to prevent firing of the click handler 4874 // as the event bubbles up through nested menus 4875 this.mouseHandled = false; 4876 this.lastMousePosition = { x: null, y: null }; 4877 this.element 4878 .uniqueId() 4879 .attr( { 4880 role: this.options.role, 4881 tabIndex: 0 4882 } ); 4883 4884 this._addClass( "ui-menu", "ui-widget ui-widget-content" ); 4885 this._on( { 4886 4887 // Prevent focus from sticking to links inside menu after clicking 4888 // them (focus should always stay on UL during navigation). 4889 "mousedown .ui-menu-item": function( event ) { 4890 event.preventDefault(); 4891 4892 this._activateItem( event ); 4893 }, 4894 "click .ui-menu-item": function( event ) { 4895 var target = $( event.target ); 4896 var active = $( this.document[ 0 ].activeElement ); 4897 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) { 4898 this.select( event ); 4899 4900 // Only set the mouseHandled flag if the event will bubble, see #9469. 4901 if ( !event.isPropagationStopped() ) { 4902 this.mouseHandled = true; 4903 } 4904 4905 // Open submenu on click 4906 if ( target.has( ".ui-menu" ).length ) { 4907 this.expand( event ); 4908 } else if ( !this.element.is( ":focus" ) && 4909 active.closest( ".ui-menu" ).length ) { 4910 4911 // Redirect focus to the menu 4912 this.element.trigger( "focus", [ true ] ); 4913 4914 // If the active item is on the top level, let it stay active. 4915 // Otherwise, blur the active item since it is no longer visible. 4916 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) { 4917 clearTimeout( this.timer ); 4918 } 4919 } 4920 } 4921 }, 4922 "mouseenter .ui-menu-item": "_activateItem", 4923 "mousemove .ui-menu-item": "_activateItem", 4924 mouseleave: "collapseAll", 4925 "mouseleave .ui-menu": "collapseAll", 4926 focus: function( event, keepActiveItem ) { 4927 4928 // If there's already an active item, keep it active 4929 // If not, activate the first item 4930 var item = this.active || this._menuItems().first(); 4931 4932 if ( !keepActiveItem ) { 4933 this.focus( event, item ); 4934 } 4935 }, 4936 blur: function( event ) { 4937 this._delay( function() { 4938 var notContained = !$.contains( 4939 this.element[ 0 ], 4940 this.document[ 0 ].activeElement 4941 ); 4942 if ( notContained ) { 4943 this.collapseAll( event ); 4944 } 4945 } ); 4946 }, 4947 keydown: "_keydown" 4948 } ); 4949 4950 this.refresh(); 4951 4952 // Clicks outside of a menu collapse any open menus 4953 this._on( this.document, { 4954 click: function( event ) { 4955 if ( this._closeOnDocumentClick( event ) ) { 4956 this.collapseAll( event, true ); 4957 } 4958 4959 // Reset the mouseHandled flag 4960 this.mouseHandled = false; 4961 } 4962 } ); 4963 }, 4964 4965 _activateItem: function( event ) { 4966 4967 // Ignore mouse events while typeahead is active, see #10458. 4968 // Prevents focusing the wrong item when typeahead causes a scroll while the mouse 4969 // is over an item in the menu 4970 if ( this.previousFilter ) { 4971 return; 4972 } 4973 4974 // If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356) 4975 if ( event.clientX === this.lastMousePosition.x && 4976 event.clientY === this.lastMousePosition.y ) { 4977 return; 4978 } 4979 4980 this.lastMousePosition = { 4981 x: event.clientX, 4982 y: event.clientY 4983 }; 4984 4985 var actualTarget = $( event.target ).closest( ".ui-menu-item" ), 4986 target = $( event.currentTarget ); 4987 4988 // Ignore bubbled events on parent items, see #11641 4989 if ( actualTarget[ 0 ] !== target[ 0 ] ) { 4990 return; 4991 } 4992 4993 // If the item is already active, there's nothing to do 4994 if ( target.is( ".ui-state-active" ) ) { 4995 return; 4996 } 4997 4998 // Remove ui-state-active class from siblings of the newly focused menu item 4999 // to avoid a jump caused by adjacent elements both having a class with a border 5000 this._removeClass( target.siblings().children( ".ui-state-active" ), 5001 null, "ui-state-active" ); 5002 this.focus( event, target ); 5003 }, 5004 5005 _destroy: function() { 5006 var items = this.element.find( ".ui-menu-item" ) 5007 .removeAttr( "role aria-disabled" ), 5008 submenus = items.children( ".ui-menu-item-wrapper" ) 5009 .removeUniqueId() 5010 .removeAttr( "tabIndex role aria-haspopup" ); 5011 5012 // Destroy (sub)menus 5013 this.element 5014 .removeAttr( "aria-activedescendant" ) 5015 .find( ".ui-menu" ).addBack() 5016 .removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " + 5017 "tabIndex" ) 5018 .removeUniqueId() 5019 .show(); 5020 5021 submenus.children().each( function() { 5022 var elem = $( this ); 5023 if ( elem.data( "ui-menu-submenu-caret" ) ) { 5024 elem.remove(); 5025 } 5026 } ); 5027 }, 5028 5029 _keydown: function( event ) { 5030 var match, prev, character, skip, 5031 preventDefault = true; 5032 5033 switch ( event.keyCode ) { 5034 case $.ui.keyCode.PAGE_UP: 5035 this.previousPage( event ); 5036 break; 5037 case $.ui.keyCode.PAGE_DOWN: 5038 this.nextPage( event ); 5039 break; 5040 case $.ui.keyCode.HOME: 5041 this._move( "first", "first", event ); 5042 break; 5043 case $.ui.keyCode.END: 5044 this._move( "last", "last", event ); 5045 break; 5046 case $.ui.keyCode.UP: 5047 this.previous( event ); 5048 break; 5049 case $.ui.keyCode.DOWN: 5050 this.next( event ); 5051 break; 5052 case $.ui.keyCode.LEFT: 5053 this.collapse( event ); 5054 break; 5055 case $.ui.keyCode.RIGHT: 5056 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { 5057 this.expand( event ); 5058 } 5059 break; 5060 case $.ui.keyCode.ENTER: 5061 case $.ui.keyCode.SPACE: 5062 this._activate( event ); 5063 break; 5064 case $.ui.keyCode.ESCAPE: 5065 this.collapse( event ); 5066 break; 5067 default: 5068 preventDefault = false; 5069 prev = this.previousFilter || ""; 5070 skip = false; 5071 5072 // Support number pad values 5073 character = event.keyCode >= 96 && event.keyCode <= 105 ? 5074 ( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode ); 5075 5076 clearTimeout( this.filterTimer ); 5077 5078 if ( character === prev ) { 5079 skip = true; 5080 } else { 5081 character = prev + character; 5082 } 5083 5084 match = this._filterMenuItems( character ); 5085 match = skip && match.index( this.active.next() ) !== -1 ? 5086 this.active.nextAll( ".ui-menu-item" ) : 5087 match; 5088 5089 // If no matches on the current filter, reset to the last character pressed 5090 // to move down the menu to the first item that starts with that character 5091 if ( !match.length ) { 5092 character = String.fromCharCode( event.keyCode ); 5093 match = this._filterMenuItems( character ); 5094 } 5095 5096 if ( match.length ) { 5097 this.focus( event, match ); 5098 this.previousFilter = character; 5099 this.filterTimer = this._delay( function() { 5100 delete this.previousFilter; 5101 }, 1000 ); 5102 } else { 5103 delete this.previousFilter; 5104 } 5105 } 5106 5107 if ( preventDefault ) { 5108 event.preventDefault(); 5109 } 5110 }, 5111 5112 _activate: function( event ) { 5113 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { 5114 if ( this.active.children( "[aria-haspopup='true']" ).length ) { 5115 this.expand( event ); 5116 } else { 5117 this.select( event ); 5118 } 5119 } 5120 }, 5121 5122 refresh: function() { 5123 var menus, items, newSubmenus, newItems, newWrappers, 5124 that = this, 5125 icon = this.options.icons.submenu, 5126 submenus = this.element.find( this.options.menus ); 5127 5128 this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length ); 5129 5130 // Initialize nested menus 5131 newSubmenus = submenus.filter( ":not(.ui-menu)" ) 5132 .hide() 5133 .attr( { 5134 role: this.options.role, 5135 "aria-hidden": "true", 5136 "aria-expanded": "false" 5137 } ) 5138 .each( function() { 5139 var menu = $( this ), 5140 item = menu.prev(), 5141 submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true ); 5142 5143 that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon ); 5144 item 5145 .attr( "aria-haspopup", "true" ) 5146 .prepend( submenuCaret ); 5147 menu.attr( "aria-labelledby", item.attr( "id" ) ); 5148 } ); 5149 5150 this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" ); 5151 5152 menus = submenus.add( this.element ); 5153 items = menus.find( this.options.items ); 5154 5155 // Initialize menu-items containing spaces and/or dashes only as dividers 5156 items.not( ".ui-menu-item" ).each( function() { 5157 var item = $( this ); 5158 if ( that._isDivider( item ) ) { 5159 that._addClass( item, "ui-menu-divider", "ui-widget-content" ); 5160 } 5161 } ); 5162 5163 // Don't refresh list items that are already adapted 5164 newItems = items.not( ".ui-menu-item, .ui-menu-divider" ); 5165 newWrappers = newItems.children() 5166 .not( ".ui-menu" ) 5167 .uniqueId() 5168 .attr( { 5169 tabIndex: -1, 5170 role: this._itemRole() 5171 } ); 5172 this._addClass( newItems, "ui-menu-item" ) 5173 ._addClass( newWrappers, "ui-menu-item-wrapper" ); 5174 5175 // Add aria-disabled attribute to any disabled menu item 5176 items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); 5177 5178 // If the active item has been removed, blur the menu 5179 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 5180 this.blur(); 5181 } 5182 }, 5183 5184 _itemRole: function() { 5185 return { 5186 menu: "menuitem", 5187 listbox: "option" 5188 }[ this.options.role ]; 5189 }, 5190 5191 _setOption: function( key, value ) { 5192 if ( key === "icons" ) { 5193 var icons = this.element.find( ".ui-menu-icon" ); 5194 this._removeClass( icons, null, this.options.icons.submenu ) 5195 ._addClass( icons, null, value.submenu ); 5196 } 5197 this._super( key, value ); 5198 }, 5199 5200 _setOptionDisabled: function( value ) { 5201 this._super( value ); 5202 5203 this.element.attr( "aria-disabled", String( value ) ); 5204 this._toggleClass( null, "ui-state-disabled", !!value ); 5205 }, 5206 5207 focus: function( event, item ) { 5208 var nested, focused, activeParent; 5209 this.blur( event, event && event.type === "focus" ); 5210 5211 this._scrollIntoView( item ); 5212 5213 this.active = item.first(); 5214 5215 focused = this.active.children( ".ui-menu-item-wrapper" ); 5216 this._addClass( focused, null, "ui-state-active" ); 5217 5218 // Only update aria-activedescendant if there's a role 5219 // otherwise we assume focus is managed elsewhere 5220 if ( this.options.role ) { 5221 this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); 5222 } 5223 5224 // Highlight active parent menu item, if any 5225 activeParent = this.active 5226 .parent() 5227 .closest( ".ui-menu-item" ) 5228 .children( ".ui-menu-item-wrapper" ); 5229 this._addClass( activeParent, null, "ui-state-active" ); 5230 5231 if ( event && event.type === "keydown" ) { 5232 this._close(); 5233 } else { 5234 this.timer = this._delay( function() { 5235 this._close(); 5236 }, this.delay ); 5237 } 5238 5239 nested = item.children( ".ui-menu" ); 5240 if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) { 5241 this._startOpening( nested ); 5242 } 5243 this.activeMenu = item.parent(); 5244 5245 this._trigger( "focus", event, { item: item } ); 5246 }, 5247 5248 _scrollIntoView: function( item ) { 5249 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; 5250 if ( this._hasScroll() ) { 5251 borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0; 5252 paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0; 5253 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; 5254 scroll = this.activeMenu.scrollTop(); 5255 elementHeight = this.activeMenu.height(); 5256 itemHeight = item.outerHeight(); 5257 5258 if ( offset < 0 ) { 5259 this.activeMenu.scrollTop( scroll + offset ); 5260 } else if ( offset + itemHeight > elementHeight ) { 5261 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); 5262 } 5263 } 5264 }, 5265 5266 blur: function( event, fromFocus ) { 5267 if ( !fromFocus ) { 5268 clearTimeout( this.timer ); 5269 } 5270 5271 if ( !this.active ) { 5272 return; 5273 } 5274 5275 this._removeClass( this.active.children( ".ui-menu-item-wrapper" ), 5276 null, "ui-state-active" ); 5277 5278 this._trigger( "blur", event, { item: this.active } ); 5279 this.active = null; 5280 }, 5281 5282 _startOpening: function( submenu ) { 5283 clearTimeout( this.timer ); 5284 5285 // Don't open if already open fixes a Firefox bug that caused a .5 pixel 5286 // shift in the submenu position when mousing over the caret icon 5287 if ( submenu.attr( "aria-hidden" ) !== "true" ) { 5288 return; 5289 } 5290 5291 this.timer = this._delay( function() { 5292 this._close(); 5293 this._open( submenu ); 5294 }, this.delay ); 5295 }, 5296 5297 _open: function( submenu ) { 5298 var position = $.extend( { 5299 of: this.active 5300 }, this.options.position ); 5301 5302 clearTimeout( this.timer ); 5303 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) ) 5304 .hide() 5305 .attr( "aria-hidden", "true" ); 5306 5307 submenu 5308 .show() 5309 .removeAttr( "aria-hidden" ) 5310 .attr( "aria-expanded", "true" ) 5311 .position( position ); 5312 }, 5313 5314 collapseAll: function( event, all ) { 5315 clearTimeout( this.timer ); 5316 this.timer = this._delay( function() { 5317 5318 // If we were passed an event, look for the submenu that contains the event 5319 var currentMenu = all ? this.element : 5320 $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); 5321 5322 // If we found no valid submenu ancestor, use the main menu to close all 5323 // sub menus anyway 5324 if ( !currentMenu.length ) { 5325 currentMenu = this.element; 5326 } 5327 5328 this._close( currentMenu ); 5329 5330 this.blur( event ); 5331 5332 // Work around active item staying active after menu is blurred 5333 this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" ); 5334 5335 this.activeMenu = currentMenu; 5336 }, all ? 0 : this.delay ); 5337 }, 5338 5339 // With no arguments, closes the currently active menu - if nothing is active 5340 // it closes all menus. If passed an argument, it will search for menus BELOW 5341 _close: function( startMenu ) { 5342 if ( !startMenu ) { 5343 startMenu = this.active ? this.active.parent() : this.element; 5344 } 5345 5346 startMenu.find( ".ui-menu" ) 5347 .hide() 5348 .attr( "aria-hidden", "true" ) 5349 .attr( "aria-expanded", "false" ); 5350 }, 5351 5352 _closeOnDocumentClick: function( event ) { 5353 return !$( event.target ).closest( ".ui-menu" ).length; 5354 }, 5355 5356 _isDivider: function( item ) { 5357 5358 // Match hyphen, em dash, en dash 5359 return !/[^\-\u2014\u2013\s]/.test( item.text() ); 5360 }, 5361 5362 collapse: function( event ) { 5363 var newItem = this.active && 5364 this.active.parent().closest( ".ui-menu-item", this.element ); 5365 if ( newItem && newItem.length ) { 5366 this._close(); 5367 this.focus( event, newItem ); 5368 } 5369 }, 5370 5371 expand: function( event ) { 5372 var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first(); 5373 5374 if ( newItem && newItem.length ) { 5375 this._open( newItem.parent() ); 5376 5377 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT 5378 this._delay( function() { 5379 this.focus( event, newItem ); 5380 } ); 5381 } 5382 }, 5383 5384 next: function( event ) { 5385 this._move( "next", "first", event ); 5386 }, 5387 5388 previous: function( event ) { 5389 this._move( "prev", "last", event ); 5390 }, 5391 5392 isFirstItem: function() { 5393 return this.active && !this.active.prevAll( ".ui-menu-item" ).length; 5394 }, 5395 5396 isLastItem: function() { 5397 return this.active && !this.active.nextAll( ".ui-menu-item" ).length; 5398 }, 5399 5400 _menuItems: function( menu ) { 5401 return ( menu || this.element ) 5402 .find( this.options.items ) 5403 .filter( ".ui-menu-item" ); 5404 }, 5405 5406 _move: function( direction, filter, event ) { 5407 var next; 5408 if ( this.active ) { 5409 if ( direction === "first" || direction === "last" ) { 5410 next = this.active 5411 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) 5412 .last(); 5413 } else { 5414 next = this.active 5415 [ direction + "All" ]( ".ui-menu-item" ) 5416 .first(); 5417 } 5418 } 5419 if ( !next || !next.length || !this.active ) { 5420 next = this._menuItems( this.activeMenu )[ filter ](); 5421 } 5422 5423 this.focus( event, next ); 5424 }, 5425 5426 nextPage: function( event ) { 5427 var item, base, height; 5428 5429 if ( !this.active ) { 5430 this.next( event ); 5431 return; 5432 } 5433 if ( this.isLastItem() ) { 5434 return; 5435 } 5436 if ( this._hasScroll() ) { 5437 base = this.active.offset().top; 5438 height = this.element.innerHeight(); 5439 5440 // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back. 5441 if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) { 5442 height += this.element[ 0 ].offsetHeight - this.element.outerHeight(); 5443 } 5444 5445 this.active.nextAll( ".ui-menu-item" ).each( function() { 5446 item = $( this ); 5447 return item.offset().top - base - height < 0; 5448 } ); 5449 5450 this.focus( event, item ); 5451 } else { 5452 this.focus( event, this._menuItems( this.activeMenu ) 5453 [ !this.active ? "first" : "last" ]() ); 5454 } 5455 }, 5456 5457 previousPage: function( event ) { 5458 var item, base, height; 5459 if ( !this.active ) { 5460 this.next( event ); 5461 return; 5462 } 5463 if ( this.isFirstItem() ) { 5464 return; 5465 } 5466 if ( this._hasScroll() ) { 5467 base = this.active.offset().top; 5468 height = this.element.innerHeight(); 5469 5470 // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back. 5471 if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) { 5472 height += this.element[ 0 ].offsetHeight - this.element.outerHeight(); 5473 } 5474 5475 this.active.prevAll( ".ui-menu-item" ).each( function() { 5476 item = $( this ); 5477 return item.offset().top - base + height > 0; 5478 } ); 5479 5480 this.focus( event, item ); 5481 } else { 5482 this.focus( event, this._menuItems( this.activeMenu ).first() ); 5483 } 5484 }, 5485 5486 _hasScroll: function() { 5487 return this.element.outerHeight() < this.element.prop( "scrollHeight" ); 5488 }, 5489 5490 select: function( event ) { 5491 5492 // TODO: It should never be possible to not have an active item at this 5493 // point, but the tests don't trigger mouseenter before click. 5494 this.active = this.active || $( event.target ).closest( ".ui-menu-item" ); 5495 var ui = { item: this.active }; 5496 if ( !this.active.has( ".ui-menu" ).length ) { 5497 this.collapseAll( event, true ); 5498 } 5499 this._trigger( "select", event, ui ); 5500 }, 5501 5502 _filterMenuItems: function( character ) { 5503 var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ), 5504 regex = new RegExp( "^" + escapedCharacter, "i" ); 5505 5506 return this.activeMenu 5507 .find( this.options.items ) 5508 5509 // Only match on items, not dividers or other content (#10571) 5510 .filter( ".ui-menu-item" ) 5511 .filter( function() { 5512 return regex.test( 5513 String.prototype.trim.call( 5514 $( this ).children( ".ui-menu-item-wrapper" ).text() ) ); 5515 } ); 5516 } 5517} ); 5518 5519 5520/*! 5521 * jQuery UI Autocomplete 1.14.0 5522 * https://jqueryui.com 5523 * 5524 * Copyright OpenJS Foundation and other contributors 5525 * Released under the MIT license. 5526 * https://jquery.org/license 5527 */ 5528 5529//>>label: Autocomplete 5530//>>group: Widgets 5531//>>description: Lists suggested words as the user is typing. 5532//>>docs: https://api.jqueryui.com/autocomplete/ 5533//>>demos: https://jqueryui.com/autocomplete/ 5534//>>css.structure: ../../themes/base/core.css 5535//>>css.structure: ../../themes/base/autocomplete.css 5536//>>css.theme: ../../themes/base/theme.css 5537 5538 5539$.widget( "ui.autocomplete", { 5540 version: "1.14.0", 5541 defaultElement: "<input>", 5542 options: { 5543 appendTo: null, 5544 autoFocus: false, 5545 delay: 300, 5546 minLength: 1, 5547 position: { 5548 my: "left top", 5549 at: "left bottom", 5550 collision: "none" 5551 }, 5552 source: null, 5553 5554 // Callbacks 5555 change: null, 5556 close: null, 5557 focus: null, 5558 open: null, 5559 response: null, 5560 search: null, 5561 select: null 5562 }, 5563 5564 requestIndex: 0, 5565 pending: 0, 5566 liveRegionTimer: null, 5567 5568 _create: function() { 5569 5570 // Some browsers only repeat keydown events, not keypress events, 5571 // so we use the suppressKeyPress flag to determine if we've already 5572 // handled the keydown event. #7269 5573 // Unfortunately the code for & in keypress is the same as the up arrow, 5574 // so we use the suppressKeyPressRepeat flag to avoid handling keypress 5575 // events when we know the keydown event was used to modify the 5576 // search term. #7799 5577 var suppressKeyPress, suppressKeyPressRepeat, suppressInput, 5578 nodeName = this.element[ 0 ].nodeName.toLowerCase(), 5579 isTextarea = nodeName === "textarea", 5580 isInput = nodeName === "input"; 5581 5582 // Textareas are always multi-line 5583 // Inputs are always single-line, even if inside a contentEditable element 5584 // All other element types are determined by whether they're contentEditable 5585 this.isMultiLine = isTextarea || 5586 !isInput && this.element.prop( "contentEditable" ) === "true"; 5587 5588 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ]; 5589 this.isNewMenu = true; 5590 5591 this._addClass( "ui-autocomplete-input" ); 5592 this.element.attr( "autocomplete", "off" ); 5593 5594 this._on( this.element, { 5595 keydown: function( event ) { 5596 if ( this.element.prop( "readOnly" ) ) { 5597 suppressKeyPress = true; 5598 suppressInput = true; 5599 suppressKeyPressRepeat = true; 5600 return; 5601 } 5602 5603 suppressKeyPress = false; 5604 suppressInput = false; 5605 suppressKeyPressRepeat = false; 5606 var keyCode = $.ui.keyCode; 5607 switch ( event.keyCode ) { 5608 case keyCode.PAGE_UP: 5609 suppressKeyPress = true; 5610 this._move( "previousPage", event ); 5611 break; 5612 case keyCode.PAGE_DOWN: 5613 suppressKeyPress = true; 5614 this._move( "nextPage", event ); 5615 break; 5616 case keyCode.UP: 5617 suppressKeyPress = true; 5618 this._keyEvent( "previous", event ); 5619 break; 5620 case keyCode.DOWN: 5621 suppressKeyPress = true; 5622 this._keyEvent( "next", event ); 5623 break; 5624 case keyCode.ENTER: 5625 5626 // when menu is open and has focus 5627 if ( this.menu.active ) { 5628 5629 // #6055 - Opera still allows the keypress to occur 5630 // which causes forms to submit 5631 suppressKeyPress = true; 5632 event.preventDefault(); 5633 this.menu.select( event ); 5634 } 5635 break; 5636 case keyCode.TAB: 5637 if ( this.menu.active ) { 5638 this.menu.select( event ); 5639 } 5640 break; 5641 case keyCode.ESCAPE: 5642 if ( this.menu.element.is( ":visible" ) ) { 5643 if ( !this.isMultiLine ) { 5644 this._value( this.term ); 5645 } 5646 this.close( event ); 5647 5648 // Different browsers have different default behavior for escape 5649 // Single press can mean undo or clear 5650 event.preventDefault(); 5651 } 5652 break; 5653 default: 5654 suppressKeyPressRepeat = true; 5655 5656 // search timeout should be triggered before the input value is changed 5657 this._searchTimeout( event ); 5658 break; 5659 } 5660 }, 5661 keypress: function( event ) { 5662 if ( suppressKeyPress ) { 5663 suppressKeyPress = false; 5664 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 5665 event.preventDefault(); 5666 } 5667 return; 5668 } 5669 if ( suppressKeyPressRepeat ) { 5670 return; 5671 } 5672 5673 // Replicate some key handlers to allow them to repeat in Firefox and Opera 5674 var keyCode = $.ui.keyCode; 5675 switch ( event.keyCode ) { 5676 case keyCode.PAGE_UP: 5677 this._move( "previousPage", event ); 5678 break; 5679 case keyCode.PAGE_DOWN: 5680 this._move( "nextPage", event ); 5681 break; 5682 case keyCode.UP: 5683 this._keyEvent( "previous", event ); 5684 break; 5685 case keyCode.DOWN: 5686 this._keyEvent( "next", event ); 5687 break; 5688 } 5689 }, 5690 input: function( event ) { 5691 if ( suppressInput ) { 5692 suppressInput = false; 5693 event.preventDefault(); 5694 return; 5695 } 5696 this._searchTimeout( event ); 5697 }, 5698 focus: function() { 5699 this.selectedItem = null; 5700 this.previous = this._value(); 5701 }, 5702 blur: function( event ) { 5703 clearTimeout( this.searching ); 5704 this.close( event ); 5705 this._change( event ); 5706 } 5707 } ); 5708 5709 this._initSource(); 5710 this.menu = $( "<ul>" ) 5711 .appendTo( this._appendTo() ) 5712 .menu( { 5713 5714 // disable ARIA support, the live region takes care of that 5715 role: null 5716 } ) 5717 .hide() 5718 .menu( "instance" ); 5719 5720 this._addClass( this.menu.element, "ui-autocomplete", "ui-front" ); 5721 this._on( this.menu.element, { 5722 mousedown: function( event ) { 5723 5724 // Prevent moving focus out of the text field 5725 event.preventDefault(); 5726 }, 5727 menufocus: function( event, ui ) { 5728 var label, item; 5729 5730 // Support: Firefox 5731 // Prevent accidental activation of menu items in Firefox (#7024 #9118) 5732 if ( this.isNewMenu ) { 5733 this.isNewMenu = false; 5734 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) { 5735 this.menu.blur(); 5736 5737 this.document.one( "mousemove", function() { 5738 $( event.target ).trigger( event.originalEvent ); 5739 } ); 5740 5741 return; 5742 } 5743 } 5744 5745 item = ui.item.data( "ui-autocomplete-item" ); 5746 if ( false !== this._trigger( "focus", event, { item: item } ) ) { 5747 5748 // use value to match what will end up in the input, if it was a key event 5749 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) { 5750 this._value( item.value ); 5751 } 5752 } 5753 5754 // Announce the value in the liveRegion 5755 label = ui.item.attr( "aria-label" ) || item.value; 5756 if ( label && String.prototype.trim.call( label ).length ) { 5757 clearTimeout( this.liveRegionTimer ); 5758 this.liveRegionTimer = this._delay( function() { 5759 this.liveRegion.html( $( "<div>" ).text( label ) ); 5760 }, 100 ); 5761 } 5762 }, 5763 menuselect: function( event, ui ) { 5764 var item = ui.item.data( "ui-autocomplete-item" ), 5765 previous = this.previous; 5766 5767 // Only trigger when focus was lost (click on menu) 5768 if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) { 5769 this.element.trigger( "focus" ); 5770 this.previous = previous; 5771 } 5772 5773 if ( false !== this._trigger( "select", event, { item: item } ) ) { 5774 this._value( item.value ); 5775 } 5776 5777 // reset the term after the select event 5778 // this allows custom select handling to work properly 5779 this.term = this._value(); 5780 5781 this.close( event ); 5782 this.selectedItem = item; 5783 } 5784 } ); 5785 5786 this.liveRegion = $( "<div>", { 5787 role: "status", 5788 "aria-live": "assertive", 5789 "aria-relevant": "additions" 5790 } ) 5791 .appendTo( this.document[ 0 ].body ); 5792 5793 this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" ); 5794 5795 // Turning off autocomplete prevents the browser from remembering the 5796 // value when navigating through history, so we re-enable autocomplete 5797 // if the page is unloaded before the widget is destroyed. #7790 5798 this._on( this.window, { 5799 beforeunload: function() { 5800 this.element.removeAttr( "autocomplete" ); 5801 } 5802 } ); 5803 }, 5804 5805 _destroy: function() { 5806 clearTimeout( this.searching ); 5807 this.element.removeAttr( "autocomplete" ); 5808 this.menu.element.remove(); 5809 this.liveRegion.remove(); 5810 }, 5811 5812 _setOption: function( key, value ) { 5813 this._super( key, value ); 5814 if ( key === "source" ) { 5815 this._initSource(); 5816 } 5817 if ( key === "appendTo" ) { 5818 this.menu.element.appendTo( this._appendTo() ); 5819 } 5820 if ( key === "disabled" && value && this.xhr ) { 5821 this.xhr.abort(); 5822 } 5823 }, 5824 5825 _isEventTargetInWidget: function( event ) { 5826 var menuElement = this.menu.element[ 0 ]; 5827 5828 return event.target === this.element[ 0 ] || 5829 event.target === menuElement || 5830 $.contains( menuElement, event.target ); 5831 }, 5832 5833 _closeOnClickOutside: function( event ) { 5834 if ( !this._isEventTargetInWidget( event ) ) { 5835 this.close(); 5836 } 5837 }, 5838 5839 _appendTo: function() { 5840 var element = this.options.appendTo; 5841 5842 if ( element ) { 5843 element = element.jquery || element.nodeType ? 5844 $( element ) : 5845 this.document.find( element ).eq( 0 ); 5846 } 5847 5848 if ( !element || !element[ 0 ] ) { 5849 element = this.element.closest( ".ui-front, dialog" ); 5850 } 5851 5852 if ( !element.length ) { 5853 element = this.document[ 0 ].body; 5854 } 5855 5856 return element; 5857 }, 5858 5859 _initSource: function() { 5860 var array, url, 5861 that = this; 5862 if ( Array.isArray( this.options.source ) ) { 5863 array = this.options.source; 5864 this.source = function( request, response ) { 5865 response( $.ui.autocomplete.filter( array, request.term ) ); 5866 }; 5867 } else if ( typeof this.options.source === "string" ) { 5868 url = this.options.source; 5869 this.source = function( request, response ) { 5870 if ( that.xhr ) { 5871 that.xhr.abort(); 5872 } 5873 that.xhr = $.ajax( { 5874 url: url, 5875 data: request, 5876 dataType: "json", 5877 success: function( data ) { 5878 response( data ); 5879 }, 5880 error: function() { 5881 response( [] ); 5882 } 5883 } ); 5884 }; 5885 } else { 5886 this.source = this.options.source; 5887 } 5888 }, 5889 5890 _searchTimeout: function( event ) { 5891 clearTimeout( this.searching ); 5892 this.searching = this._delay( function() { 5893 5894 // Search if the value has changed, or if the user retypes the same value (see #7434) 5895 var equalValues = this.term === this._value(), 5896 menuVisible = this.menu.element.is( ":visible" ), 5897 modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey; 5898 5899 if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) { 5900 this.selectedItem = null; 5901 this.search( null, event ); 5902 } 5903 }, this.options.delay ); 5904 }, 5905 5906 search: function( value, event ) { 5907 value = value != null ? value : this._value(); 5908 5909 // Always save the actual value, not the one passed as an argument 5910 this.term = this._value(); 5911 5912 if ( value.length < this.options.minLength ) { 5913 return this.close( event ); 5914 } 5915 5916 if ( this._trigger( "search", event ) === false ) { 5917 return; 5918 } 5919 5920 return this._search( value ); 5921 }, 5922 5923 _search: function( value ) { 5924 this.pending++; 5925 this._addClass( "ui-autocomplete-loading" ); 5926 this.cancelSearch = false; 5927 5928 this.source( { term: value }, this._response() ); 5929 }, 5930 5931 _response: function() { 5932 var index = ++this.requestIndex; 5933 5934 return function( content ) { 5935 if ( index === this.requestIndex ) { 5936 this.__response( content ); 5937 } 5938 5939 this.pending--; 5940 if ( !this.pending ) { 5941 this._removeClass( "ui-autocomplete-loading" ); 5942 } 5943 }.bind( this ); 5944 }, 5945 5946 __response: function( content ) { 5947 if ( content ) { 5948 content = this._normalize( content ); 5949 } 5950 this._trigger( "response", null, { content: content } ); 5951 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) { 5952 this._suggest( content ); 5953 this._trigger( "open" ); 5954 } else { 5955 5956 // use ._close() instead of .close() so we don't cancel future searches 5957 this._close(); 5958 } 5959 }, 5960 5961 close: function( event ) { 5962 this.cancelSearch = true; 5963 this._close( event ); 5964 }, 5965 5966 _close: function( event ) { 5967 5968 // Remove the handler that closes the menu on outside clicks 5969 this._off( this.document, "mousedown" ); 5970 5971 if ( this.menu.element.is( ":visible" ) ) { 5972 this.menu.element.hide(); 5973 this.menu.blur(); 5974 this.isNewMenu = true; 5975 this._trigger( "close", event ); 5976 } 5977 }, 5978 5979 _change: function( event ) { 5980 if ( this.previous !== this._value() ) { 5981 this._trigger( "change", event, { item: this.selectedItem } ); 5982 } 5983 }, 5984 5985 _normalize: function( items ) { 5986 5987 // assume all items have the right format when the first item is complete 5988 if ( items.length && items[ 0 ].label && items[ 0 ].value ) { 5989 return items; 5990 } 5991 return $.map( items, function( item ) { 5992 if ( typeof item === "string" ) { 5993 return { 5994 label: item, 5995 value: item 5996 }; 5997 } 5998 return $.extend( {}, item, { 5999 label: item.label || item.value, 6000 value: item.value || item.label 6001 } ); 6002 } ); 6003 }, 6004 6005 _suggest: function( items ) { 6006 var ul = this.menu.element.empty(); 6007 this._renderMenu( ul, items ); 6008 this.isNewMenu = true; 6009 this.menu.refresh(); 6010 6011 // Size and position menu 6012 ul.show(); 6013 this._resizeMenu(); 6014 ul.position( $.extend( { 6015 of: this.element 6016 }, this.options.position ) ); 6017 6018 if ( this.options.autoFocus ) { 6019 this.menu.next(); 6020 } 6021 6022 // Listen for interactions outside of the widget (#6642) 6023 this._on( this.document, { 6024 mousedown: "_closeOnClickOutside" 6025 } ); 6026 }, 6027 6028 _resizeMenu: function() { 6029 var ul = this.menu.element; 6030 ul.outerWidth( Math.max( 6031 6032 // Firefox wraps long text (possibly a rounding bug) 6033 // so we add 1px to avoid the wrapping (#7513) 6034 ul.width( "" ).outerWidth() + 1, 6035 this.element.outerWidth() 6036 ) ); 6037 }, 6038 6039 _renderMenu: function( ul, items ) { 6040 var that = this; 6041 $.each( items, function( index, item ) { 6042 that._renderItemData( ul, item ); 6043 } ); 6044 }, 6045 6046 _renderItemData: function( ul, item ) { 6047 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item ); 6048 }, 6049 6050 _renderItem: function( ul, item ) { 6051 return $( "<li>" ) 6052 .append( $( "<div>" ).text( item.label ) ) 6053 .appendTo( ul ); 6054 }, 6055 6056 _move: function( direction, event ) { 6057 if ( !this.menu.element.is( ":visible" ) ) { 6058 this.search( null, event ); 6059 return; 6060 } 6061 if ( this.menu.isFirstItem() && /^previous/.test( direction ) || 6062 this.menu.isLastItem() && /^next/.test( direction ) ) { 6063 6064 if ( !this.isMultiLine ) { 6065 this._value( this.term ); 6066 } 6067 6068 this.menu.blur(); 6069 return; 6070 } 6071 this.menu[ direction ]( event ); 6072 }, 6073 6074 widget: function() { 6075 return this.menu.element; 6076 }, 6077 6078 _value: function() { 6079 return this.valueMethod.apply( this.element, arguments ); 6080 }, 6081 6082 _keyEvent: function( keyEvent, event ) { 6083 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 6084 this._move( keyEvent, event ); 6085 6086 // Prevents moving cursor to beginning/end of the text field in some browsers 6087 event.preventDefault(); 6088 } 6089 } 6090} ); 6091 6092$.extend( $.ui.autocomplete, { 6093 escapeRegex: function( value ) { 6094 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ); 6095 }, 6096 filter: function( array, term ) { 6097 var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" ); 6098 return $.grep( array, function( value ) { 6099 return matcher.test( value.label || value.value || value ); 6100 } ); 6101 } 6102} ); 6103 6104// Live region extension, adding a `messages` option 6105// NOTE: This is an experimental API. We are still investigating 6106// a full solution for string manipulation and internationalization. 6107$.widget( "ui.autocomplete", $.ui.autocomplete, { 6108 options: { 6109 messages: { 6110 noResults: "No search results.", 6111 results: function( amount ) { 6112 return amount + ( amount > 1 ? " results are" : " result is" ) + 6113 " available, use up and down arrow keys to navigate."; 6114 } 6115 } 6116 }, 6117 6118 __response: function( content ) { 6119 var message; 6120 this._superApply( arguments ); 6121 if ( this.options.disabled || this.cancelSearch ) { 6122 return; 6123 } 6124 if ( content && content.length ) { 6125 message = this.options.messages.results( content.length ); 6126 } else { 6127 message = this.options.messages.noResults; 6128 } 6129 clearTimeout( this.liveRegionTimer ); 6130 this.liveRegionTimer = this._delay( function() { 6131 this.liveRegion.html( $( "<div>" ).text( message ) ); 6132 }, 100 ); 6133 } 6134} ); 6135 6136var widgetsAutocomplete = $.ui.autocomplete; 6137 6138 6139/*! 6140 * jQuery UI Controlgroup 1.14.0 6141 * https://jqueryui.com 6142 * 6143 * Copyright OpenJS Foundation and other contributors 6144 * Released under the MIT license. 6145 * https://jquery.org/license 6146 */ 6147 6148//>>label: Controlgroup 6149//>>group: Widgets 6150//>>description: Visually groups form control widgets 6151//>>docs: https://api.jqueryui.com/controlgroup/ 6152//>>demos: https://jqueryui.com/controlgroup/ 6153//>>css.structure: ../../themes/base/core.css 6154//>>css.structure: ../../themes/base/controlgroup.css 6155//>>css.theme: ../../themes/base/theme.css 6156 6157 6158var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g; 6159 6160var widgetsControlgroup = $.widget( "ui.controlgroup", { 6161 version: "1.14.0", 6162 defaultElement: "<div>", 6163 options: { 6164 direction: "horizontal", 6165 disabled: null, 6166 onlyVisible: true, 6167 items: { 6168 "button": "input[type=button], input[type=submit], input[type=reset], button, a", 6169 "controlgroupLabel": ".ui-controlgroup-label", 6170 "checkboxradio": "input[type='checkbox'], input[type='radio']", 6171 "selectmenu": "select", 6172 "spinner": ".ui-spinner-input" 6173 } 6174 }, 6175 6176 _create: function() { 6177 this._enhance(); 6178 }, 6179 6180 // To support the enhanced option in jQuery Mobile, we isolate DOM manipulation 6181 _enhance: function() { 6182 this.element.attr( "role", "toolbar" ); 6183 this.refresh(); 6184 }, 6185 6186 _destroy: function() { 6187 this._callChildMethod( "destroy" ); 6188 this.childWidgets.removeData( "ui-controlgroup-data" ); 6189 this.element.removeAttr( "role" ); 6190 if ( this.options.items.controlgroupLabel ) { 6191 this.element 6192 .find( this.options.items.controlgroupLabel ) 6193 .find( ".ui-controlgroup-label-contents" ) 6194 .contents().unwrap(); 6195 } 6196 }, 6197 6198 _initWidgets: function() { 6199 var that = this, 6200 childWidgets = []; 6201 6202 // First we iterate over each of the items options 6203 $.each( this.options.items, function( widget, selector ) { 6204 var labels; 6205 var options = {}; 6206 6207 // Make sure the widget has a selector set 6208 if ( !selector ) { 6209 return; 6210 } 6211 6212 if ( widget === "controlgroupLabel" ) { 6213 labels = that.element.find( selector ); 6214 labels.each( function() { 6215 var element = $( this ); 6216 6217 if ( element.children( ".ui-controlgroup-label-contents" ).length ) { 6218 return; 6219 } 6220 element.contents() 6221 .wrapAll( "<span class='ui-controlgroup-label-contents'></span>" ); 6222 } ); 6223 that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" ); 6224 childWidgets = childWidgets.concat( labels.get() ); 6225 return; 6226 } 6227 6228 // Make sure the widget actually exists 6229 if ( !$.fn[ widget ] ) { 6230 return; 6231 } 6232 6233 // We assume everything is in the middle to start because we can't determine 6234 // first / last elements until all enhancments are done. 6235 if ( that[ "_" + widget + "Options" ] ) { 6236 options = that[ "_" + widget + "Options" ]( "middle" ); 6237 } else { 6238 options = { classes: {} }; 6239 } 6240 6241 // Find instances of this widget inside controlgroup and init them 6242 that.element 6243 .find( selector ) 6244 .each( function() { 6245 var element = $( this ); 6246 var instance = element[ widget ]( "instance" ); 6247 6248 // We need to clone the default options for this type of widget to avoid 6249 // polluting the variable options which has a wider scope than a single widget. 6250 var instanceOptions = $.widget.extend( {}, options ); 6251 6252 // If the button is the child of a spinner ignore it 6253 // TODO: Find a more generic solution 6254 if ( widget === "button" && element.parent( ".ui-spinner" ).length ) { 6255 return; 6256 } 6257 6258 // Create the widget if it doesn't exist 6259 if ( !instance ) { 6260 instance = element[ widget ]()[ widget ]( "instance" ); 6261 } 6262 if ( instance ) { 6263 instanceOptions.classes = 6264 that._resolveClassesValues( instanceOptions.classes, instance ); 6265 } 6266 element[ widget ]( instanceOptions ); 6267 6268 // Store an instance of the controlgroup to be able to reference 6269 // from the outermost element for changing options and refresh 6270 var widgetElement = element[ widget ]( "widget" ); 6271 $.data( widgetElement[ 0 ], "ui-controlgroup-data", 6272 instance ? instance : element[ widget ]( "instance" ) ); 6273 6274 childWidgets.push( widgetElement[ 0 ] ); 6275 } ); 6276 } ); 6277 6278 this.childWidgets = $( $.uniqueSort( childWidgets ) ); 6279 this._addClass( this.childWidgets, "ui-controlgroup-item" ); 6280 }, 6281 6282 _callChildMethod: function( method ) { 6283 this.childWidgets.each( function() { 6284 var element = $( this ), 6285 data = element.data( "ui-controlgroup-data" ); 6286 if ( data && data[ method ] ) { 6287 data[ method ](); 6288 } 6289 } ); 6290 }, 6291 6292 _updateCornerClass: function( element, position ) { 6293 var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all"; 6294 var add = this._buildSimpleOptions( position, "label" ).classes.label; 6295 6296 this._removeClass( element, null, remove ); 6297 this._addClass( element, null, add ); 6298 }, 6299 6300 _buildSimpleOptions: function( position, key ) { 6301 var direction = this.options.direction === "vertical"; 6302 var result = { 6303 classes: {} 6304 }; 6305 result.classes[ key ] = { 6306 "middle": "", 6307 "first": "ui-corner-" + ( direction ? "top" : "left" ), 6308 "last": "ui-corner-" + ( direction ? "bottom" : "right" ), 6309 "only": "ui-corner-all" 6310 }[ position ]; 6311 6312 return result; 6313 }, 6314 6315 _spinnerOptions: function( position ) { 6316 var options = this._buildSimpleOptions( position, "ui-spinner" ); 6317 6318 options.classes[ "ui-spinner-up" ] = ""; 6319 options.classes[ "ui-spinner-down" ] = ""; 6320 6321 return options; 6322 }, 6323 6324 _buttonOptions: function( position ) { 6325 return this._buildSimpleOptions( position, "ui-button" ); 6326 }, 6327 6328 _checkboxradioOptions: function( position ) { 6329 return this._buildSimpleOptions( position, "ui-checkboxradio-label" ); 6330 }, 6331 6332 _selectmenuOptions: function( position ) { 6333 var direction = this.options.direction === "vertical"; 6334 return { 6335 width: direction ? "auto" : false, 6336 classes: { 6337 middle: { 6338 "ui-selectmenu-button-open": "", 6339 "ui-selectmenu-button-closed": "" 6340 }, 6341 first: { 6342 "ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ), 6343 "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" ) 6344 }, 6345 last: { 6346 "ui-selectmenu-button-open": direction ? "" : "ui-corner-tr", 6347 "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" ) 6348 }, 6349 only: { 6350 "ui-selectmenu-button-open": "ui-corner-top", 6351 "ui-selectmenu-button-closed": "ui-corner-all" 6352 } 6353 6354 }[ position ] 6355 }; 6356 }, 6357 6358 _resolveClassesValues: function( classes, instance ) { 6359 var result = {}; 6360 $.each( classes, function( key ) { 6361 var current = instance.options.classes[ key ] || ""; 6362 current = String.prototype.trim.call( current.replace( controlgroupCornerRegex, "" ) ); 6363 result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " ); 6364 } ); 6365 return result; 6366 }, 6367 6368 _setOption: function( key, value ) { 6369 if ( key === "direction" ) { 6370 this._removeClass( "ui-controlgroup-" + this.options.direction ); 6371 } 6372 6373 this._super( key, value ); 6374 if ( key === "disabled" ) { 6375 this._callChildMethod( value ? "disable" : "enable" ); 6376 return; 6377 } 6378 6379 this.refresh(); 6380 }, 6381 6382 refresh: function() { 6383 var children, 6384 that = this; 6385 6386 this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction ); 6387 6388 if ( this.options.direction === "horizontal" ) { 6389 this._addClass( null, "ui-helper-clearfix" ); 6390 } 6391 this._initWidgets(); 6392 6393 children = this.childWidgets; 6394 6395 // We filter here because we need to track all childWidgets not just the visible ones 6396 if ( this.options.onlyVisible ) { 6397 children = children.filter( ":visible" ); 6398 } 6399 6400 if ( children.length ) { 6401 6402 // We do this last because we need to make sure all enhancment is done 6403 // before determining first and last 6404 $.each( [ "first", "last" ], function( index, value ) { 6405 var instance = children[ value ]().data( "ui-controlgroup-data" ); 6406 6407 if ( instance && that[ "_" + instance.widgetName + "Options" ] ) { 6408 var options = that[ "_" + instance.widgetName + "Options" ]( 6409 children.length === 1 ? "only" : value 6410 ); 6411 options.classes = that._resolveClassesValues( options.classes, instance ); 6412 instance.element[ instance.widgetName ]( options ); 6413 } else { 6414 that._updateCornerClass( children[ value ](), value ); 6415 } 6416 } ); 6417 6418 // Finally call the refresh method on each of the child widgets. 6419 this._callChildMethod( "refresh" ); 6420 } 6421 } 6422} ); 6423 6424/*! 6425 * jQuery UI Checkboxradio 1.14.0 6426 * https://jqueryui.com 6427 * 6428 * Copyright OpenJS Foundation and other contributors 6429 * Released under the MIT license. 6430 * https://jquery.org/license 6431 */ 6432 6433//>>label: Checkboxradio 6434//>>group: Widgets 6435//>>description: Enhances a form with multiple themeable checkboxes or radio buttons. 6436//>>docs: https://api.jqueryui.com/checkboxradio/ 6437//>>demos: https://jqueryui.com/checkboxradio/ 6438//>>css.structure: ../../themes/base/core.css 6439//>>css.structure: ../../themes/base/button.css 6440//>>css.structure: ../../themes/base/checkboxradio.css 6441//>>css.theme: ../../themes/base/theme.css 6442 6443 6444$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, { 6445 version: "1.14.0", 6446 options: { 6447 disabled: null, 6448 label: null, 6449 icon: true, 6450 classes: { 6451 "ui-checkboxradio-label": "ui-corner-all", 6452 "ui-checkboxradio-icon": "ui-corner-all" 6453 } 6454 }, 6455 6456 _getCreateOptions: function() { 6457 var disabled, labels, labelContents; 6458 var options = this._super() || {}; 6459 6460 // We read the type here, because it makes more sense to throw a element type error first, 6461 // rather then the error for lack of a label. Often if its the wrong type, it 6462 // won't have a label (e.g. calling on a div, btn, etc) 6463 this._readType(); 6464 6465 labels = this.element.labels(); 6466 6467 // If there are multiple labels, use the last one 6468 this.label = $( labels[ labels.length - 1 ] ); 6469 if ( !this.label.length ) { 6470 $.error( "No label found for checkboxradio widget" ); 6471 } 6472 6473 this.originalLabel = ""; 6474 6475 // We need to get the label text but this may also need to make sure it does not contain the 6476 // input itself. 6477 // The label contents could be text, html, or a mix. We wrap all elements 6478 // and read the wrapper's `innerHTML` to get a string representation of 6479 // the label, without the input as part of it. 6480 labelContents = this.label.contents().not( this.element[ 0 ] ); 6481 6482 if ( labelContents.length ) { 6483 this.originalLabel += labelContents 6484 .clone() 6485 .wrapAll( "<div></div>" ) 6486 .parent() 6487 .html(); 6488 } 6489 6490 // Set the label option if we found label text 6491 if ( this.originalLabel ) { 6492 options.label = this.originalLabel; 6493 } 6494 6495 disabled = this.element[ 0 ].disabled; 6496 if ( disabled != null ) { 6497 options.disabled = disabled; 6498 } 6499 return options; 6500 }, 6501 6502 _create: function() { 6503 var checked = this.element[ 0 ].checked; 6504 6505 this._bindFormResetHandler(); 6506 6507 if ( this.options.disabled == null ) { 6508 this.options.disabled = this.element[ 0 ].disabled; 6509 } 6510 6511 this._setOption( "disabled", this.options.disabled ); 6512 this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" ); 6513 this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" ); 6514 6515 if ( this.type === "radio" ) { 6516 this._addClass( this.label, "ui-checkboxradio-radio-label" ); 6517 } 6518 6519 if ( this.options.label && this.options.label !== this.originalLabel ) { 6520 this._updateLabel(); 6521 } else if ( this.originalLabel ) { 6522 this.options.label = this.originalLabel; 6523 } 6524 6525 this._enhance(); 6526 6527 if ( checked ) { 6528 this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" ); 6529 } 6530 6531 this._on( { 6532 change: "_toggleClasses", 6533 focus: function() { 6534 this._addClass( this.label, null, "ui-state-focus ui-visual-focus" ); 6535 }, 6536 blur: function() { 6537 this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" ); 6538 } 6539 } ); 6540 }, 6541 6542 _readType: function() { 6543 var nodeName = this.element[ 0 ].nodeName.toLowerCase(); 6544 this.type = this.element[ 0 ].type; 6545 if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) { 6546 $.error( "Can't create checkboxradio on element.nodeName=" + nodeName + 6547 " and element.type=" + this.type ); 6548 } 6549 }, 6550 6551 // Support jQuery Mobile enhanced option 6552 _enhance: function() { 6553 this._updateIcon( this.element[ 0 ].checked ); 6554 }, 6555 6556 widget: function() { 6557 return this.label; 6558 }, 6559 6560 _getRadioGroup: function() { 6561 var group; 6562 var name = this.element[ 0 ].name; 6563 var nameSelector = "input[name='" + CSS.escape( name ) + "']"; 6564 6565 if ( !name ) { 6566 return $( [] ); 6567 } 6568 6569 if ( this.form.length ) { 6570 group = $( this.form[ 0 ].elements ).filter( nameSelector ); 6571 } else { 6572 6573 // Not inside a form, check all inputs that also are not inside a form 6574 group = $( nameSelector ).filter( function() { 6575 return $( $( this ).prop( "form" ) ).length === 0; 6576 } ); 6577 } 6578 6579 return group.not( this.element ); 6580 }, 6581 6582 _toggleClasses: function() { 6583 var checked = this.element[ 0 ].checked; 6584 this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked ); 6585 6586 if ( this.options.icon && this.type === "checkbox" ) { 6587 this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked ) 6588 ._toggleClass( this.icon, null, "ui-icon-blank", !checked ); 6589 } 6590 6591 if ( this.type === "radio" ) { 6592 this._getRadioGroup() 6593 .each( function() { 6594 var instance = $( this ).checkboxradio( "instance" ); 6595 6596 if ( instance ) { 6597 instance._removeClass( instance.label, 6598 "ui-checkboxradio-checked", "ui-state-active" ); 6599 } 6600 } ); 6601 } 6602 }, 6603 6604 _destroy: function() { 6605 this._unbindFormResetHandler(); 6606 6607 if ( this.icon ) { 6608 this.icon.remove(); 6609 this.iconSpace.remove(); 6610 } 6611 }, 6612 6613 _setOption: function( key, value ) { 6614 6615 // We don't allow the value to be set to nothing 6616 if ( key === "label" && !value ) { 6617 return; 6618 } 6619 6620 this._super( key, value ); 6621 6622 if ( key === "disabled" ) { 6623 this._toggleClass( this.label, null, "ui-state-disabled", value ); 6624 this.element[ 0 ].disabled = value; 6625 6626 // Don't refresh when setting disabled 6627 return; 6628 } 6629 this.refresh(); 6630 }, 6631 6632 _updateIcon: function( checked ) { 6633 var toAdd = "ui-icon ui-icon-background "; 6634 6635 if ( this.options.icon ) { 6636 if ( !this.icon ) { 6637 this.icon = $( "<span>" ); 6638 this.iconSpace = $( "<span> </span>" ); 6639 this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" ); 6640 } 6641 6642 if ( this.type === "checkbox" ) { 6643 toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank"; 6644 this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" ); 6645 } else { 6646 toAdd += "ui-icon-blank"; 6647 } 6648 this._addClass( this.icon, "ui-checkboxradio-icon", toAdd ); 6649 if ( !checked ) { 6650 this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" ); 6651 } 6652 this.icon.prependTo( this.label ).after( this.iconSpace ); 6653 } else if ( this.icon !== undefined ) { 6654 this.icon.remove(); 6655 this.iconSpace.remove(); 6656 delete this.icon; 6657 } 6658 }, 6659 6660 _updateLabel: function() { 6661 6662 // Remove the contents of the label ( minus the icon, icon space, and input ) 6663 var contents = this.label.contents().not( this.element[ 0 ] ); 6664 if ( this.icon ) { 6665 contents = contents.not( this.icon[ 0 ] ); 6666 } 6667 if ( this.iconSpace ) { 6668 contents = contents.not( this.iconSpace[ 0 ] ); 6669 } 6670 contents.remove(); 6671 6672 this.label.append( this.options.label ); 6673 }, 6674 6675 refresh: function() { 6676 var checked = this.element[ 0 ].checked, 6677 isDisabled = this.element[ 0 ].disabled; 6678 6679 this._updateIcon( checked ); 6680 this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked ); 6681 if ( this.options.label !== null ) { 6682 this._updateLabel(); 6683 } 6684 6685 if ( isDisabled !== this.options.disabled ) { 6686 this._setOptions( { "disabled": isDisabled } ); 6687 } 6688 } 6689 6690} ] ); 6691 6692var widgetsCheckboxradio = $.ui.checkboxradio; 6693 6694 6695/*! 6696 * jQuery UI Button 1.14.0 6697 * https://jqueryui.com 6698 * 6699 * Copyright OpenJS Foundation and other contributors 6700 * Released under the MIT license. 6701 * https://jquery.org/license 6702 */ 6703 6704//>>label: Button 6705//>>group: Widgets 6706//>>description: Enhances a form with themeable buttons. 6707//>>docs: https://api.jqueryui.com/button/ 6708//>>demos: https://jqueryui.com/button/ 6709//>>css.structure: ../../themes/base/core.css 6710//>>css.structure: ../../themes/base/button.css 6711//>>css.theme: ../../themes/base/theme.css 6712 6713 6714$.widget( "ui.button", { 6715 version: "1.14.0", 6716 defaultElement: "<button>", 6717 options: { 6718 classes: { 6719 "ui-button": "ui-corner-all" 6720 }, 6721 disabled: null, 6722 icon: null, 6723 iconPosition: "beginning", 6724 label: null, 6725 showLabel: true 6726 }, 6727 6728 _getCreateOptions: function() { 6729 var disabled, 6730 6731 // This is to support cases like in jQuery Mobile where the base widget does have 6732 // an implementation of _getCreateOptions 6733 options = this._super() || {}; 6734 6735 this.isInput = this.element.is( "input" ); 6736 6737 disabled = this.element[ 0 ].disabled; 6738 if ( disabled != null ) { 6739 options.disabled = disabled; 6740 } 6741 6742 this.originalLabel = this.isInput ? this.element.val() : this.element.html(); 6743 if ( this.originalLabel ) { 6744 options.label = this.originalLabel; 6745 } 6746 6747 return options; 6748 }, 6749 6750 _create: function() { 6751 if ( !this.option.showLabel & !this.options.icon ) { 6752 this.options.showLabel = true; 6753 } 6754 6755 // We have to check the option again here even though we did in _getCreateOptions, 6756 // because null may have been passed on init which would override what was set in 6757 // _getCreateOptions 6758 if ( this.options.disabled == null ) { 6759 this.options.disabled = this.element[ 0 ].disabled || false; 6760 } 6761 6762 this.hasTitle = !!this.element.attr( "title" ); 6763 6764 // Check to see if the label needs to be set or if its already correct 6765 if ( this.options.label && this.options.label !== this.originalLabel ) { 6766 if ( this.isInput ) { 6767 this.element.val( this.options.label ); 6768 } else { 6769 this.element.html( this.options.label ); 6770 } 6771 } 6772 this._addClass( "ui-button", "ui-widget" ); 6773 this._setOption( "disabled", this.options.disabled ); 6774 this._enhance(); 6775 6776 if ( this.element.is( "a" ) ) { 6777 this._on( { 6778 "keyup": function( event ) { 6779 if ( event.keyCode === $.ui.keyCode.SPACE ) { 6780 event.preventDefault(); 6781 6782 // If a native click is available use it, so we 6783 // actually cause navigation. Otherwise, just trigger 6784 // a click event. 6785 if ( this.element[ 0 ].click ) { 6786 this.element[ 0 ].click(); 6787 } else { 6788 this.element.trigger( "click" ); 6789 } 6790 } 6791 } 6792 } ); 6793 } 6794 }, 6795 6796 _enhance: function() { 6797 if ( !this.element.is( "button" ) ) { 6798 this.element.attr( "role", "button" ); 6799 } 6800 6801 if ( this.options.icon ) { 6802 this._updateIcon( "icon", this.options.icon ); 6803 this._updateTooltip(); 6804 } 6805 }, 6806 6807 _updateTooltip: function() { 6808 this.title = this.element.attr( "title" ); 6809 6810 if ( !this.options.showLabel && !this.title ) { 6811 this.element.attr( "title", this.options.label ); 6812 } 6813 }, 6814 6815 _updateIcon: function( option, value ) { 6816 var icon = option !== "iconPosition", 6817 position = icon ? this.options.iconPosition : value, 6818 displayBlock = position === "top" || position === "bottom"; 6819 6820 // Create icon 6821 if ( !this.icon ) { 6822 this.icon = $( "<span>" ); 6823 6824 this._addClass( this.icon, "ui-button-icon", "ui-icon" ); 6825 6826 if ( !this.options.showLabel ) { 6827 this._addClass( "ui-button-icon-only" ); 6828 } 6829 } else if ( icon ) { 6830 6831 // If we are updating the icon remove the old icon class 6832 this._removeClass( this.icon, null, this.options.icon ); 6833 } 6834 6835 // If we are updating the icon add the new icon class 6836 if ( icon ) { 6837 this._addClass( this.icon, null, value ); 6838 } 6839 6840 this._attachIcon( position ); 6841 6842 // If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove 6843 // the iconSpace if there is one. 6844 if ( displayBlock ) { 6845 this._addClass( this.icon, null, "ui-widget-icon-block" ); 6846 if ( this.iconSpace ) { 6847 this.iconSpace.remove(); 6848 } 6849 } else { 6850 6851 // Position is beginning or end so remove the ui-widget-icon-block class and add the 6852 // space if it does not exist 6853 if ( !this.iconSpace ) { 6854 this.iconSpace = $( "<span> </span>" ); 6855 this._addClass( this.iconSpace, "ui-button-icon-space" ); 6856 } 6857 this._removeClass( this.icon, null, "ui-wiget-icon-block" ); 6858 this._attachIconSpace( position ); 6859 } 6860 }, 6861 6862 _destroy: function() { 6863 this.element.removeAttr( "role" ); 6864 6865 if ( this.icon ) { 6866 this.icon.remove(); 6867 } 6868 if ( this.iconSpace ) { 6869 this.iconSpace.remove(); 6870 } 6871 if ( !this.hasTitle ) { 6872 this.element.removeAttr( "title" ); 6873 } 6874 }, 6875 6876 _attachIconSpace: function( iconPosition ) { 6877 this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace ); 6878 }, 6879 6880 _attachIcon: function( iconPosition ) { 6881 this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon ); 6882 }, 6883 6884 _setOptions: function( options ) { 6885 var newShowLabel = options.showLabel === undefined ? 6886 this.options.showLabel : 6887 options.showLabel, 6888 newIcon = options.icon === undefined ? this.options.icon : options.icon; 6889 6890 if ( !newShowLabel && !newIcon ) { 6891 options.showLabel = true; 6892 } 6893 this._super( options ); 6894 }, 6895 6896 _setOption: function( key, value ) { 6897 if ( key === "icon" ) { 6898 if ( value ) { 6899 this._updateIcon( key, value ); 6900 } else if ( this.icon ) { 6901 this.icon.remove(); 6902 if ( this.iconSpace ) { 6903 this.iconSpace.remove(); 6904 } 6905 } 6906 } 6907 6908 if ( key === "iconPosition" ) { 6909 this._updateIcon( key, value ); 6910 } 6911 6912 // Make sure we can't end up with a button that has neither text nor icon 6913 if ( key === "showLabel" ) { 6914 this._toggleClass( "ui-button-icon-only", null, !value ); 6915 this._updateTooltip(); 6916 } 6917 6918 if ( key === "label" ) { 6919 if ( this.isInput ) { 6920 this.element.val( value ); 6921 } else { 6922 6923 // If there is an icon, append it, else nothing then append the value 6924 // this avoids removal of the icon when setting label text 6925 this.element.html( value ); 6926 if ( this.icon ) { 6927 this._attachIcon( this.options.iconPosition ); 6928 this._attachIconSpace( this.options.iconPosition ); 6929 } 6930 } 6931 } 6932 6933 this._super( key, value ); 6934 6935 if ( key === "disabled" ) { 6936 this._toggleClass( null, "ui-state-disabled", value ); 6937 this.element[ 0 ].disabled = value; 6938 if ( value ) { 6939 this.element.trigger( "blur" ); 6940 } 6941 } 6942 }, 6943 6944 refresh: function() { 6945 6946 // Make sure to only check disabled if its an element that supports this otherwise 6947 // check for the disabled class to determine state 6948 var isDisabled = this.element.is( "input, button" ) ? 6949 this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" ); 6950 6951 if ( isDisabled !== this.options.disabled ) { 6952 this._setOptions( { disabled: isDisabled } ); 6953 } 6954 6955 this._updateTooltip(); 6956 } 6957} ); 6958 6959// DEPRECATED 6960if ( $.uiBackCompat === true ) { 6961 6962 // Text and Icons options 6963 $.widget( "ui.button", $.ui.button, { 6964 options: { 6965 text: true, 6966 icons: { 6967 primary: null, 6968 secondary: null 6969 } 6970 }, 6971 6972 _create: function() { 6973 if ( this.options.showLabel && !this.options.text ) { 6974 this.options.showLabel = this.options.text; 6975 } 6976 if ( !this.options.showLabel && this.options.text ) { 6977 this.options.text = this.options.showLabel; 6978 } 6979 if ( !this.options.icon && ( this.options.icons.primary || 6980 this.options.icons.secondary ) ) { 6981 if ( this.options.icons.primary ) { 6982 this.options.icon = this.options.icons.primary; 6983 } else { 6984 this.options.icon = this.options.icons.secondary; 6985 this.options.iconPosition = "end"; 6986 } 6987 } else if ( this.options.icon ) { 6988 this.options.icons.primary = this.options.icon; 6989 } 6990 this._super(); 6991 }, 6992 6993 _setOption: function( key, value ) { 6994 if ( key === "text" ) { 6995 this._super( "showLabel", value ); 6996 return; 6997 } 6998 if ( key === "showLabel" ) { 6999 this.options.text = value; 7000 } 7001 if ( key === "icon" ) { 7002 this.options.icons.primary = value; 7003 } 7004 if ( key === "icons" ) { 7005 if ( value.primary ) { 7006 this._super( "icon", value.primary ); 7007 this._super( "iconPosition", "beginning" ); 7008 } else if ( value.secondary ) { 7009 this._super( "icon", value.secondary ); 7010 this._super( "iconPosition", "end" ); 7011 } 7012 } 7013 this._superApply( arguments ); 7014 } 7015 } ); 7016 7017 $.fn.button = ( function( orig ) { 7018 return function( options ) { 7019 var isMethodCall = typeof options === "string"; 7020 var args = Array.prototype.slice.call( arguments, 1 ); 7021 var returnValue = this; 7022 7023 if ( isMethodCall ) { 7024 7025 // If this is an empty collection, we need to have the instance method 7026 // return undefined instead of the jQuery instance 7027 if ( !this.length && options === "instance" ) { 7028 returnValue = undefined; 7029 } else { 7030 this.each( function() { 7031 var methodValue; 7032 var type = $( this ).attr( "type" ); 7033 var name = type !== "checkbox" && type !== "radio" ? 7034 "button" : 7035 "checkboxradio"; 7036 var instance = $.data( this, "ui-" + name ); 7037 7038 if ( options === "instance" ) { 7039 returnValue = instance; 7040 return false; 7041 } 7042 7043 if ( !instance ) { 7044 return $.error( "cannot call methods on button" + 7045 " prior to initialization; " + 7046 "attempted to call method '" + options + "'" ); 7047 } 7048 7049 if ( typeof instance[ options ] !== "function" || 7050 options.charAt( 0 ) === "_" ) { 7051 return $.error( "no such method '" + options + "' for button" + 7052 " widget instance" ); 7053 } 7054 7055 methodValue = instance[ options ].apply( instance, args ); 7056 7057 if ( methodValue !== instance && methodValue !== undefined ) { 7058 returnValue = methodValue && methodValue.jquery ? 7059 returnValue.pushStack( methodValue.get() ) : 7060 methodValue; 7061 return false; 7062 } 7063 } ); 7064 } 7065 } else { 7066 7067 // Allow multiple hashes to be passed on init 7068 if ( args.length ) { 7069 options = $.widget.extend.apply( null, [ options ].concat( args ) ); 7070 } 7071 7072 this.each( function() { 7073 var type = $( this ).attr( "type" ); 7074 var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio"; 7075 var instance = $.data( this, "ui-" + name ); 7076 7077 if ( instance ) { 7078 instance.option( options || {} ); 7079 if ( instance._init ) { 7080 instance._init(); 7081 } 7082 } else { 7083 if ( name === "button" ) { 7084 orig.call( $( this ), options ); 7085 return; 7086 } 7087 7088 $( this ).checkboxradio( $.extend( { icon: false }, options ) ); 7089 } 7090 } ); 7091 } 7092 7093 return returnValue; 7094 }; 7095 } )( $.fn.button ); 7096 7097 $.fn.buttonset = function() { 7098 if ( !$.ui.controlgroup ) { 7099 $.error( "Controlgroup widget missing" ); 7100 } 7101 if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) { 7102 return this.controlgroup.apply( this, 7103 [ arguments[ 0 ], "items.button", arguments[ 2 ] ] ); 7104 } 7105 if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) { 7106 return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] ); 7107 } 7108 if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) { 7109 arguments[ 0 ].items = { 7110 button: arguments[ 0 ].items 7111 }; 7112 } 7113 return this.controlgroup.apply( this, arguments ); 7114 }; 7115} 7116 7117var widgetsButton = $.ui.button; 7118 7119 7120/* eslint-disable max-len, camelcase */ 7121/*! 7122 * jQuery UI Datepicker 1.14.0 7123 * https://jqueryui.com 7124 * 7125 * Copyright OpenJS Foundation and other contributors 7126 * Released under the MIT license. 7127 * https://jquery.org/license 7128 */ 7129 7130//>>label: Datepicker 7131//>>group: Widgets 7132//>>description: Displays a calendar from an input or inline for selecting dates. 7133//>>docs: https://api.jqueryui.com/datepicker/ 7134//>>demos: https://jqueryui.com/datepicker/ 7135//>>css.structure: ../../themes/base/core.css 7136//>>css.structure: ../../themes/base/datepicker.css 7137//>>css.theme: ../../themes/base/theme.css 7138 7139 7140$.extend( $.ui, { datepicker: { version: "1.14.0" } } ); 7141 7142var datepicker_instActive; 7143 7144function datepicker_getZindex( elem ) { 7145 var position, value; 7146 while ( elem.length && elem[ 0 ] !== document ) { 7147 7148 // Ignore z-index if position is set to a value where z-index is ignored by the browser 7149 // This makes behavior of this function consistent across browsers 7150 // WebKit always returns auto if the element is positioned 7151 position = elem.css( "position" ); 7152 if ( position === "absolute" || position === "relative" || position === "fixed" ) { 7153 7154 // IE returns 0 when zIndex is not specified 7155 // other browsers return a string 7156 // we ignore the case of nested elements with an explicit value of 0 7157 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 7158 value = parseInt( elem.css( "zIndex" ), 10 ); 7159 if ( !isNaN( value ) && value !== 0 ) { 7160 return value; 7161 } 7162 } 7163 elem = elem.parent(); 7164 } 7165 7166 return 0; 7167} 7168 7169/* Date picker manager. 7170 Use the singleton instance of this class, $.datepicker, to interact with the date picker. 7171 Settings for (groups of) date pickers are maintained in an instance object, 7172 allowing multiple different settings on the same page. */ 7173 7174function Datepicker() { 7175 this._curInst = null; // The current instance in use 7176 this._keyEvent = false; // If the last event was a key event 7177 this._disabledInputs = []; // List of date picker inputs that have been disabled 7178 this._datepickerShowing = false; // True if the popup picker is showing , false if not 7179 this._inDialog = false; // True if showing within a "dialog", false if not 7180 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division 7181 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class 7182 this._appendClass = "ui-datepicker-append"; // The name of the append marker class 7183 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class 7184 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class 7185 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class 7186 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class 7187 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class 7188 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class 7189 this.regional = []; // Available regional settings, indexed by language code 7190 this.regional[ "" ] = { // Default regional settings 7191 closeText: "Done", // Display text for close link 7192 prevText: "Prev", // Display text for previous month link 7193 nextText: "Next", // Display text for next month link 7194 currentText: "Today", // Display text for current month link 7195 monthNames: [ "January", "February", "March", "April", "May", "June", 7196 "July", "August", "September", "October", "November", "December" ], // Names of months for drop-down and formatting 7197 monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting 7198 dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting 7199 dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting 7200 dayNamesMin: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], // Column headings for days starting at Sunday 7201 weekHeader: "Wk", // Column header for week of the year 7202 dateFormat: "mm/dd/yy", // See format options on parseDate 7203 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... 7204 isRTL: false, // True if right-to-left language, false if left-to-right 7205 showMonthAfterYear: false, // True if the year select precedes month, false for month then year 7206 yearSuffix: "", // Additional text to append to the year in the month headers, 7207 selectMonthLabel: "Select month", // Invisible label for month selector 7208 selectYearLabel: "Select year" // Invisible label for year selector 7209 }; 7210 this._defaults = { // Global defaults for all the date picker instances 7211 showOn: "focus", // "focus" for popup on focus, 7212 // "button" for trigger button, or "both" for either 7213 showAnim: "fadeIn", // Name of jQuery animation for popup 7214 showOptions: {}, // Options for enhanced animations 7215 defaultDate: null, // Used when field is blank: actual date, 7216 // +/-number for offset from today, null for today 7217 appendText: "", // Display text following the input box, e.g. showing the format 7218 buttonText: "...", // Text for trigger button 7219 buttonImage: "", // URL for trigger button image 7220 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button 7221 hideIfNoPrevNext: false, // True to hide next/previous month links 7222 // if not applicable, false to just disable them 7223 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links 7224 gotoCurrent: false, // True if today link goes back to current selection instead 7225 changeMonth: false, // True if month can be selected directly, false if only prev/next 7226 changeYear: false, // True if year can be selected directly, false if only prev/next 7227 yearRange: "c-10:c+10", // Range of years to display in drop-down, 7228 // either relative to today's year (-nn:+nn), relative to currently displayed year 7229 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) 7230 showOtherMonths: false, // True to show dates in other months, false to leave blank 7231 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable 7232 showWeek: false, // True to show week of the year, false to not show it 7233 calculateWeek: this.iso8601Week, // How to calculate the week of the year, 7234 // takes a Date and returns the number of the week for it 7235 shortYearCutoff: "+10", // Short year values < this are in the current century, 7236 // > this are in the previous century, 7237 // string value starting with "+" for current year + value 7238 minDate: null, // The earliest selectable date, or null for no limit 7239 maxDate: null, // The latest selectable date, or null for no limit 7240 duration: "fast", // Duration of display/closure 7241 beforeShowDay: null, // Function that takes a date and returns an array with 7242 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "", 7243 // [2] = cell title (optional), e.g. $.datepicker.noWeekends 7244 beforeShow: null, // Function that takes an input field and 7245 // returns a set of custom settings for the date picker 7246 onSelect: null, // Define a callback function when a date is selected 7247 onChangeMonthYear: null, // Define a callback function when the month or year is changed 7248 onClose: null, // Define a callback function when the datepicker is closed 7249 onUpdateDatepicker: null, // Define a callback function when the datepicker is updated 7250 numberOfMonths: 1, // Number of months to show at a time 7251 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) 7252 stepMonths: 1, // Number of months to step back/forward 7253 stepBigMonths: 12, // Number of months to step back/forward for the big links 7254 altField: "", // Selector for an alternate field to store selected dates into 7255 altFormat: "", // The date format to use for the alternate field 7256 constrainInput: true, // The input is constrained by the current date format 7257 showButtonPanel: false, // True to show button panel, false to not show it 7258 autoSize: false, // True to size the input for the date format, false to leave as is 7259 disabled: false // The initial disabled state 7260 }; 7261 $.extend( this._defaults, this.regional[ "" ] ); 7262 this.regional.en = $.extend( true, {}, this.regional[ "" ] ); 7263 this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en ); 7264 this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ); 7265} 7266 7267$.extend( Datepicker.prototype, { 7268 7269 /* Class name added to elements to indicate already configured with a date picker. */ 7270 markerClassName: "hasDatepicker", 7271 7272 //Keep track of the maximum number of rows displayed (see #7043) 7273 maxRows: 4, 7274 7275 // TODO rename to "widget" when switching to widget factory 7276 _widgetDatepicker: function() { 7277 return this.dpDiv; 7278 }, 7279 7280 /* Override the default settings for all instances of the date picker. 7281 * @param settings object - the new settings to use as defaults (anonymous object) 7282 * @return the manager object 7283 */ 7284 setDefaults: function( settings ) { 7285 datepicker_extendRemove( this._defaults, settings || {} ); 7286 return this; 7287 }, 7288 7289 /* Attach the date picker to a jQuery selection. 7290 * @param target element - the target input field or division or span 7291 * @param settings object - the new settings to use for this date picker instance (anonymous) 7292 */ 7293 _attachDatepicker: function( target, settings ) { 7294 var nodeName, inline, inst; 7295 nodeName = target.nodeName.toLowerCase(); 7296 inline = ( nodeName === "div" || nodeName === "span" ); 7297 if ( !target.id ) { 7298 this.uuid += 1; 7299 target.id = "dp" + this.uuid; 7300 } 7301 inst = this._newInst( $( target ), inline ); 7302 inst.settings = $.extend( {}, settings || {} ); 7303 if ( nodeName === "input" ) { 7304 this._connectDatepicker( target, inst ); 7305 } else if ( inline ) { 7306 this._inlineDatepicker( target, inst ); 7307 } 7308 }, 7309 7310 /* Create a new instance object. */ 7311 _newInst: function( target, inline ) { 7312 var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars 7313 return { id: id, input: target, // associated target 7314 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection 7315 drawMonth: 0, drawYear: 0, // month being drawn 7316 inline: inline, // is datepicker inline or not 7317 dpDiv: ( !inline ? this.dpDiv : // presentation div 7318 datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) }; 7319 }, 7320 7321 /* Attach the date picker to an input field. */ 7322 _connectDatepicker: function( target, inst ) { 7323 var input = $( target ); 7324 inst.append = $( [] ); 7325 inst.trigger = $( [] ); 7326 if ( input.hasClass( this.markerClassName ) ) { 7327 return; 7328 } 7329 this._attachments( input, inst ); 7330 input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ). 7331 on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp ); 7332 this._autoSize( inst ); 7333 $.data( target, "datepicker", inst ); 7334 7335 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) 7336 if ( inst.settings.disabled ) { 7337 this._disableDatepicker( target ); 7338 } 7339 }, 7340 7341 /* Make attachments based on settings. */ 7342 _attachments: function( input, inst ) { 7343 var showOn, buttonText, buttonImage, 7344 appendText = this._get( inst, "appendText" ), 7345 isRTL = this._get( inst, "isRTL" ); 7346 7347 if ( inst.append ) { 7348 inst.append.remove(); 7349 } 7350 if ( appendText ) { 7351 inst.append = $( "<span>" ) 7352 .addClass( this._appendClass ) 7353 .text( appendText ); 7354 input[ isRTL ? "before" : "after" ]( inst.append ); 7355 } 7356 7357 input.off( "focus", this._showDatepicker ); 7358 7359 if ( inst.trigger ) { 7360 inst.trigger.remove(); 7361 } 7362 7363 showOn = this._get( inst, "showOn" ); 7364 if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field 7365 input.on( "focus", this._showDatepicker ); 7366 } 7367 if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked 7368 buttonText = this._get( inst, "buttonText" ); 7369 buttonImage = this._get( inst, "buttonImage" ); 7370 7371 if ( this._get( inst, "buttonImageOnly" ) ) { 7372 inst.trigger = $( "<img>" ) 7373 .addClass( this._triggerClass ) 7374 .attr( { 7375 src: buttonImage, 7376 alt: buttonText, 7377 title: buttonText 7378 } ); 7379 } else { 7380 inst.trigger = $( "<button type='button'>" ) 7381 .addClass( this._triggerClass ); 7382 if ( buttonImage ) { 7383 inst.trigger.html( 7384 $( "<img>" ) 7385 .attr( { 7386 src: buttonImage, 7387 alt: buttonText, 7388 title: buttonText 7389 } ) 7390 ); 7391 } else { 7392 inst.trigger.text( buttonText ); 7393 } 7394 } 7395 7396 input[ isRTL ? "before" : "after" ]( inst.trigger ); 7397 inst.trigger.on( "click", function() { 7398 if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) { 7399 $.datepicker._hideDatepicker(); 7400 } else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) { 7401 $.datepicker._hideDatepicker(); 7402 $.datepicker._showDatepicker( input[ 0 ] ); 7403 } else { 7404 $.datepicker._showDatepicker( input[ 0 ] ); 7405 } 7406 return false; 7407 } ); 7408 } 7409 }, 7410 7411 /* Apply the maximum length for the date format. */ 7412 _autoSize: function( inst ) { 7413 if ( this._get( inst, "autoSize" ) && !inst.inline ) { 7414 var findMax, max, maxI, i, 7415 date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits 7416 dateFormat = this._get( inst, "dateFormat" ); 7417 7418 if ( dateFormat.match( /[DM]/ ) ) { 7419 findMax = function( names ) { 7420 max = 0; 7421 maxI = 0; 7422 for ( i = 0; i < names.length; i++ ) { 7423 if ( names[ i ].length > max ) { 7424 max = names[ i ].length; 7425 maxI = i; 7426 } 7427 } 7428 return maxI; 7429 }; 7430 date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ? 7431 "monthNames" : "monthNamesShort" ) ) ) ); 7432 date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ? 7433 "dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() ); 7434 } 7435 inst.input.attr( "size", this._formatDate( inst, date ).length ); 7436 } 7437 }, 7438 7439 /* Attach an inline date picker to a div. */ 7440 _inlineDatepicker: function( target, inst ) { 7441 var divSpan = $( target ); 7442 if ( divSpan.hasClass( this.markerClassName ) ) { 7443 return; 7444 } 7445 divSpan.addClass( this.markerClassName ).append( inst.dpDiv ); 7446 $.data( target, "datepicker", inst ); 7447 this._setDate( inst, this._getDefaultDate( inst ), true ); 7448 this._updateDatepicker( inst ); 7449 this._updateAlternate( inst ); 7450 7451 //If disabled option is true, disable the datepicker before showing it (see ticket #5665) 7452 if ( inst.settings.disabled ) { 7453 this._disableDatepicker( target ); 7454 } 7455 7456 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements 7457 // https://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height 7458 inst.dpDiv.css( "display", "block" ); 7459 }, 7460 7461 /* Pop-up the date picker in a "dialog" box. 7462 * @param input element - ignored 7463 * @param date string or Date - the initial date to display 7464 * @param onSelect function - the function to call when a date is selected 7465 * @param settings object - update the dialog date picker instance's settings (anonymous object) 7466 * @param pos int[2] - coordinates for the dialog's position within the screen or 7467 * event - with x/y coordinates or 7468 * leave empty for default (screen centre) 7469 * @return the manager object 7470 */ 7471 _dialogDatepicker: function( input, date, onSelect, settings, pos ) { 7472 var id, browserWidth, browserHeight, scrollX, scrollY, 7473 inst = this._dialogInst; // internal instance 7474 7475 if ( !inst ) { 7476 this.uuid += 1; 7477 id = "dp" + this.uuid; 7478 this._dialogInput = $( "<input type='text' id='" + id + 7479 "' style='position: absolute; top: -100px; width: 0px;'/>" ); 7480 this._dialogInput.on( "keydown", this._doKeyDown ); 7481 $( "body" ).append( this._dialogInput ); 7482 inst = this._dialogInst = this._newInst( this._dialogInput, false ); 7483 inst.settings = {}; 7484 $.data( this._dialogInput[ 0 ], "datepicker", inst ); 7485 } 7486 datepicker_extendRemove( inst.settings, settings || {} ); 7487 date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date ); 7488 this._dialogInput.val( date ); 7489 7490 this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null ); 7491 if ( !this._pos ) { 7492 browserWidth = document.documentElement.clientWidth; 7493 browserHeight = document.documentElement.clientHeight; 7494 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; 7495 scrollY = document.documentElement.scrollTop || document.body.scrollTop; 7496 this._pos = // should use actual width/height below 7497 [ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ]; 7498 } 7499 7500 // Move input on screen for focus, but hidden behind dialog 7501 this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" ); 7502 inst.settings.onSelect = onSelect; 7503 this._inDialog = true; 7504 this.dpDiv.addClass( this._dialogClass ); 7505 this._showDatepicker( this._dialogInput[ 0 ] ); 7506 if ( $.blockUI ) { 7507 $.blockUI( this.dpDiv ); 7508 } 7509 $.data( this._dialogInput[ 0 ], "datepicker", inst ); 7510 return this; 7511 }, 7512 7513 /* Detach a datepicker from its control. 7514 * @param target element - the target input field or division or span 7515 */ 7516 _destroyDatepicker: function( target ) { 7517 var nodeName, 7518 $target = $( target ), 7519 inst = $.data( target, "datepicker" ); 7520 7521 if ( !$target.hasClass( this.markerClassName ) ) { 7522 return; 7523 } 7524 7525 nodeName = target.nodeName.toLowerCase(); 7526 $.removeData( target, "datepicker" ); 7527 if ( nodeName === "input" ) { 7528 inst.append.remove(); 7529 inst.trigger.remove(); 7530 $target.removeClass( this.markerClassName ). 7531 off( "focus", this._showDatepicker ). 7532 off( "keydown", this._doKeyDown ). 7533 off( "keypress", this._doKeyPress ). 7534 off( "keyup", this._doKeyUp ); 7535 } else if ( nodeName === "div" || nodeName === "span" ) { 7536 $target.removeClass( this.markerClassName ).empty(); 7537 } 7538 7539 $.datepicker._hideDatepicker(); 7540 if ( datepicker_instActive === inst ) { 7541 datepicker_instActive = null; 7542 this._curInst = null; 7543 } 7544 }, 7545 7546 /* Enable the date picker to a jQuery selection. 7547 * @param target element - the target input field or division or span 7548 */ 7549 _enableDatepicker: function( target ) { 7550 var nodeName, inline, 7551 $target = $( target ), 7552 inst = $.data( target, "datepicker" ); 7553 7554 if ( !$target.hasClass( this.markerClassName ) ) { 7555 return; 7556 } 7557 7558 nodeName = target.nodeName.toLowerCase(); 7559 if ( nodeName === "input" ) { 7560 target.disabled = false; 7561 inst.trigger.filter( "button" ). 7562 each( function() { 7563 this.disabled = false; 7564 } ).end(). 7565 filter( "img" ).css( { opacity: "1.0", cursor: "" } ); 7566 } else if ( nodeName === "div" || nodeName === "span" ) { 7567 inline = $target.children( "." + this._inlineClass ); 7568 inline.children().removeClass( "ui-state-disabled" ); 7569 inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ). 7570 prop( "disabled", false ); 7571 } 7572 this._disabledInputs = $.map( this._disabledInputs, 7573 7574 // Delete entry 7575 function( value ) { 7576 return ( value === target ? null : value ); 7577 } ); 7578 }, 7579 7580 /* Disable the date picker to a jQuery selection. 7581 * @param target element - the target input field or division or span 7582 */ 7583 _disableDatepicker: function( target ) { 7584 var nodeName, inline, 7585 $target = $( target ), 7586 inst = $.data( target, "datepicker" ); 7587 7588 if ( !$target.hasClass( this.markerClassName ) ) { 7589 return; 7590 } 7591 7592 nodeName = target.nodeName.toLowerCase(); 7593 if ( nodeName === "input" ) { 7594 target.disabled = true; 7595 inst.trigger.filter( "button" ). 7596 each( function() { 7597 this.disabled = true; 7598 } ).end(). 7599 filter( "img" ).css( { opacity: "0.5", cursor: "default" } ); 7600 } else if ( nodeName === "div" || nodeName === "span" ) { 7601 inline = $target.children( "." + this._inlineClass ); 7602 inline.children().addClass( "ui-state-disabled" ); 7603 inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ). 7604 prop( "disabled", true ); 7605 } 7606 this._disabledInputs = $.map( this._disabledInputs, 7607 7608 // Delete entry 7609 function( value ) { 7610 return ( value === target ? null : value ); 7611 } ); 7612 this._disabledInputs[ this._disabledInputs.length ] = target; 7613 }, 7614 7615 /* Is the first field in a jQuery collection disabled as a datepicker? 7616 * @param target element - the target input field or division or span 7617 * @return boolean - true if disabled, false if enabled 7618 */ 7619 _isDisabledDatepicker: function( target ) { 7620 if ( !target ) { 7621 return false; 7622 } 7623 for ( var i = 0; i < this._disabledInputs.length; i++ ) { 7624 if ( this._disabledInputs[ i ] === target ) { 7625 return true; 7626 } 7627 } 7628 return false; 7629 }, 7630 7631 /* Retrieve the instance data for the target control. 7632 * @param target element - the target input field or division or span 7633 * @return object - the associated instance data 7634 * @throws error if a jQuery problem getting data 7635 */ 7636 _getInst: function( target ) { 7637 try { 7638 return $.data( target, "datepicker" ); 7639 } catch ( err ) { 7640 throw "Missing instance data for this datepicker"; 7641 } 7642 }, 7643 7644 /* Update or retrieve the settings for a date picker attached to an input field or division. 7645 * @param target element - the target input field or division or span 7646 * @param name object - the new settings to update or 7647 * string - the name of the setting to change or retrieve, 7648 * when retrieving also "all" for all instance settings or 7649 * "defaults" for all global defaults 7650 * @param value any - the new value for the setting 7651 * (omit if above is an object or to retrieve a value) 7652 */ 7653 _optionDatepicker: function( target, name, value ) { 7654 var settings, date, minDate, maxDate, 7655 inst = this._getInst( target ); 7656 7657 if ( arguments.length === 2 && typeof name === "string" ) { 7658 return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) : 7659 ( inst ? ( name === "all" ? $.extend( {}, inst.settings ) : 7660 this._get( inst, name ) ) : null ) ); 7661 } 7662 7663 settings = name || {}; 7664 if ( typeof name === "string" ) { 7665 settings = {}; 7666 settings[ name ] = value; 7667 } 7668 7669 if ( inst ) { 7670 if ( this._curInst === inst ) { 7671 this._hideDatepicker(); 7672 } 7673 7674 date = this._getDateDatepicker( target, true ); 7675 minDate = this._getMinMaxDate( inst, "min" ); 7676 maxDate = this._getMinMaxDate( inst, "max" ); 7677 datepicker_extendRemove( inst.settings, settings ); 7678 7679 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided 7680 if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) { 7681 inst.settings.minDate = this._formatDate( inst, minDate ); 7682 } 7683 if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) { 7684 inst.settings.maxDate = this._formatDate( inst, maxDate ); 7685 } 7686 if ( "disabled" in settings ) { 7687 if ( settings.disabled ) { 7688 this._disableDatepicker( target ); 7689 } else { 7690 this._enableDatepicker( target ); 7691 } 7692 } 7693 this._attachments( $( target ), inst ); 7694 this._autoSize( inst ); 7695 this._setDate( inst, date ); 7696 this._updateAlternate( inst ); 7697 this._updateDatepicker( inst ); 7698 } 7699 }, 7700 7701 // Change method deprecated 7702 _changeDatepicker: function( target, name, value ) { 7703 this._optionDatepicker( target, name, value ); 7704 }, 7705 7706 /* Redraw the date picker attached to an input field or division. 7707 * @param target element - the target input field or division or span 7708 */ 7709 _refreshDatepicker: function( target ) { 7710 var inst = this._getInst( target ); 7711 if ( inst ) { 7712 this._updateDatepicker( inst ); 7713 } 7714 }, 7715 7716 /* Set the dates for a jQuery selection. 7717 * @param target element - the target input field or division or span 7718 * @param date Date - the new date 7719 */ 7720 _setDateDatepicker: function( target, date ) { 7721 var inst = this._getInst( target ); 7722 if ( inst ) { 7723 this._setDate( inst, date ); 7724 this._updateDatepicker( inst ); 7725 this._updateAlternate( inst ); 7726 } 7727 }, 7728 7729 /* Get the date(s) for the first entry in a jQuery selection. 7730 * @param target element - the target input field or division or span 7731 * @param noDefault boolean - true if no default date is to be used 7732 * @return Date - the current date 7733 */ 7734 _getDateDatepicker: function( target, noDefault ) { 7735 var inst = this._getInst( target ); 7736 if ( inst && !inst.inline ) { 7737 this._setDateFromField( inst, noDefault ); 7738 } 7739 return ( inst ? this._getDate( inst ) : null ); 7740 }, 7741 7742 /* Handle keystrokes. */ 7743 _doKeyDown: function( event ) { 7744 var onSelect, dateStr, sel, 7745 inst = $.datepicker._getInst( event.target ), 7746 handled = true, 7747 isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" ); 7748 7749 inst._keyEvent = true; 7750 if ( $.datepicker._datepickerShowing ) { 7751 switch ( event.keyCode ) { 7752 case 9: $.datepicker._hideDatepicker(); 7753 handled = false; 7754 break; // hide on tab out 7755 case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." + 7756 $.datepicker._currentClass + ")", inst.dpDiv ); 7757 if ( sel[ 0 ] ) { 7758 $.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] ); 7759 } 7760 7761 onSelect = $.datepicker._get( inst, "onSelect" ); 7762 if ( onSelect ) { 7763 dateStr = $.datepicker._formatDate( inst ); 7764 7765 // Trigger custom callback 7766 onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] ); 7767 } else { 7768 $.datepicker._hideDatepicker(); 7769 } 7770 7771 return false; // don't submit the form 7772 case 27: $.datepicker._hideDatepicker(); 7773 break; // hide on escape 7774 case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 7775 -$.datepicker._get( inst, "stepBigMonths" ) : 7776 -$.datepicker._get( inst, "stepMonths" ) ), "M" ); 7777 break; // previous month/year on page up/+ ctrl 7778 case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 7779 +$.datepicker._get( inst, "stepBigMonths" ) : 7780 +$.datepicker._get( inst, "stepMonths" ) ), "M" ); 7781 break; // next month/year on page down/+ ctrl 7782 case 35: if ( event.ctrlKey || event.metaKey ) { 7783 $.datepicker._clearDate( event.target ); 7784 } 7785 handled = event.ctrlKey || event.metaKey; 7786 break; // clear on ctrl or command +end 7787 case 36: if ( event.ctrlKey || event.metaKey ) { 7788 $.datepicker._gotoToday( event.target ); 7789 } 7790 handled = event.ctrlKey || event.metaKey; 7791 break; // current on ctrl or command +home 7792 case 37: if ( event.ctrlKey || event.metaKey ) { 7793 $.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" ); 7794 } 7795 handled = event.ctrlKey || event.metaKey; 7796 7797 // -1 day on ctrl or command +left 7798 if ( event.originalEvent.altKey ) { 7799 $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 7800 -$.datepicker._get( inst, "stepBigMonths" ) : 7801 -$.datepicker._get( inst, "stepMonths" ) ), "M" ); 7802 } 7803 7804 // next month/year on alt +left on Mac 7805 break; 7806 case 38: if ( event.ctrlKey || event.metaKey ) { 7807 $.datepicker._adjustDate( event.target, -7, "D" ); 7808 } 7809 handled = event.ctrlKey || event.metaKey; 7810 break; // -1 week on ctrl or command +up 7811 case 39: if ( event.ctrlKey || event.metaKey ) { 7812 $.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" ); 7813 } 7814 handled = event.ctrlKey || event.metaKey; 7815 7816 // +1 day on ctrl or command +right 7817 if ( event.originalEvent.altKey ) { 7818 $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 7819 +$.datepicker._get( inst, "stepBigMonths" ) : 7820 +$.datepicker._get( inst, "stepMonths" ) ), "M" ); 7821 } 7822 7823 // next month/year on alt +right 7824 break; 7825 case 40: if ( event.ctrlKey || event.metaKey ) { 7826 $.datepicker._adjustDate( event.target, +7, "D" ); 7827 } 7828 handled = event.ctrlKey || event.metaKey; 7829 break; // +1 week on ctrl or command +down 7830 default: handled = false; 7831 } 7832 } else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home 7833 $.datepicker._showDatepicker( this ); 7834 } else { 7835 handled = false; 7836 } 7837 7838 if ( handled ) { 7839 event.preventDefault(); 7840 event.stopPropagation(); 7841 } 7842 }, 7843 7844 /* Filter entered characters - based on date format. */ 7845 _doKeyPress: function( event ) { 7846 var chars, chr, 7847 inst = $.datepicker._getInst( event.target ); 7848 7849 if ( $.datepicker._get( inst, "constrainInput" ) ) { 7850 chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) ); 7851 chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode ); 7852 return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 ); 7853 } 7854 }, 7855 7856 /* Synchronise manual entry and field/alternate field. */ 7857 _doKeyUp: function( event ) { 7858 var date, 7859 inst = $.datepicker._getInst( event.target ); 7860 7861 if ( inst.input.val() !== inst.lastVal ) { 7862 try { 7863 date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ), 7864 ( inst.input ? inst.input.val() : null ), 7865 $.datepicker._getFormatConfig( inst ) ); 7866 7867 if ( date ) { // only if valid 7868 $.datepicker._setDateFromField( inst ); 7869 $.datepicker._updateAlternate( inst ); 7870 $.datepicker._updateDatepicker( inst ); 7871 } 7872 } catch ( err ) { 7873 } 7874 } 7875 return true; 7876 }, 7877 7878 /* Pop-up the date picker for a given input field. 7879 * If false returned from beforeShow event handler do not show. 7880 * @param input element - the input field attached to the date picker or 7881 * event - if triggered by focus 7882 */ 7883 _showDatepicker: function( input ) { 7884 input = input.target || input; 7885 if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger 7886 input = $( "input", input.parentNode )[ 0 ]; 7887 } 7888 7889 if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here 7890 return; 7891 } 7892 7893 var inst, beforeShow, beforeShowSettings, isFixed, 7894 offset, showAnim, duration; 7895 7896 inst = $.datepicker._getInst( input ); 7897 if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) { 7898 $.datepicker._curInst.dpDiv.stop( true, true ); 7899 if ( inst && $.datepicker._datepickerShowing ) { 7900 $.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] ); 7901 } 7902 } 7903 7904 beforeShow = $.datepicker._get( inst, "beforeShow" ); 7905 beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {}; 7906 if ( beforeShowSettings === false ) { 7907 return; 7908 } 7909 datepicker_extendRemove( inst.settings, beforeShowSettings ); 7910 7911 inst.lastVal = null; 7912 $.datepicker._lastInput = input; 7913 $.datepicker._setDateFromField( inst ); 7914 7915 if ( $.datepicker._inDialog ) { // hide cursor 7916 input.value = ""; 7917 } 7918 if ( !$.datepicker._pos ) { // position below input 7919 $.datepicker._pos = $.datepicker._findPos( input ); 7920 $.datepicker._pos[ 1 ] += input.offsetHeight; // add the height 7921 } 7922 7923 isFixed = false; 7924 $( input ).parents().each( function() { 7925 isFixed |= $( this ).css( "position" ) === "fixed"; 7926 return !isFixed; 7927 } ); 7928 7929 offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] }; 7930 $.datepicker._pos = null; 7931 7932 //to avoid flashes on Firefox 7933 inst.dpDiv.empty(); 7934 7935 // determine sizing offscreen 7936 inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } ); 7937 $.datepicker._updateDatepicker( inst ); 7938 7939 // fix width for dynamic number of date pickers 7940 // and adjust position before showing 7941 offset = $.datepicker._checkOffset( inst, offset, isFixed ); 7942 inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ? 7943 "static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none", 7944 left: offset.left + "px", top: offset.top + "px" } ); 7945 7946 if ( !inst.inline ) { 7947 showAnim = $.datepicker._get( inst, "showAnim" ); 7948 duration = $.datepicker._get( inst, "duration" ); 7949 inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 ); 7950 $.datepicker._datepickerShowing = true; 7951 7952 if ( $.effects && $.effects.effect[ showAnim ] ) { 7953 inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration ); 7954 } else { 7955 inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null ); 7956 } 7957 7958 if ( $.datepicker._shouldFocusInput( inst ) ) { 7959 inst.input.trigger( "focus" ); 7960 } 7961 7962 $.datepicker._curInst = inst; 7963 } 7964 }, 7965 7966 /* Generate the date picker content. */ 7967 _updateDatepicker: function( inst ) { 7968 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) 7969 datepicker_instActive = inst; // for delegate hover events 7970 inst.dpDiv.empty().append( this._generateHTML( inst ) ); 7971 this._attachHandlers( inst ); 7972 7973 var origyearshtml, 7974 numMonths = this._getNumberOfMonths( inst ), 7975 cols = numMonths[ 1 ], 7976 width = 17, 7977 activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ), 7978 onUpdateDatepicker = $.datepicker._get( inst, "onUpdateDatepicker" ); 7979 7980 if ( activeCell.length > 0 ) { 7981 datepicker_handleMouseover.apply( activeCell.get( 0 ) ); 7982 } 7983 7984 inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" ); 7985 if ( cols > 1 ) { 7986 inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" ); 7987 } 7988 inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) + 7989 "Class" ]( "ui-datepicker-multi" ); 7990 inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) + 7991 "Class" ]( "ui-datepicker-rtl" ); 7992 7993 if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) { 7994 inst.input.trigger( "focus" ); 7995 } 7996 7997 // Deffered render of the years select (to avoid flashes on Firefox) 7998 if ( inst.yearshtml ) { 7999 origyearshtml = inst.yearshtml; 8000 setTimeout( function() { 8001 8002 //assure that inst.yearshtml didn't change. 8003 if ( origyearshtml === inst.yearshtml && inst.yearshtml ) { 8004 inst.dpDiv.find( "select.ui-datepicker-year" ).first().replaceWith( inst.yearshtml ); 8005 } 8006 origyearshtml = inst.yearshtml = null; 8007 }, 0 ); 8008 } 8009 8010 if ( onUpdateDatepicker ) { 8011 onUpdateDatepicker.apply( ( inst.input ? inst.input[ 0 ] : null ), [ inst ] ); 8012 } 8013 }, 8014 8015 _shouldFocusInput: function( inst ) { 8016 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ); 8017 }, 8018 8019 /* Check positioning to remain on screen. */ 8020 _checkOffset: function( inst, offset, isFixed ) { 8021 var dpWidth = inst.dpDiv.outerWidth(), 8022 dpHeight = inst.dpDiv.outerHeight(), 8023 inputWidth = inst.input ? inst.input.outerWidth() : 0, 8024 inputHeight = inst.input ? inst.input.outerHeight() : 0, 8025 viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ), 8026 viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() ); 8027 8028 offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 ); 8029 offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0; 8030 offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0; 8031 8032 // Now check if datepicker is showing outside window viewport - move to a better place if so. 8033 offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ? 8034 Math.abs( offset.left + dpWidth - viewWidth ) : 0 ); 8035 offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ? 8036 Math.abs( dpHeight + inputHeight ) : 0 ); 8037 8038 return offset; 8039 }, 8040 8041 /* Find an object's position on the screen. */ 8042 _findPos: function( obj ) { 8043 var position, 8044 inst = this._getInst( obj ), 8045 isRTL = this._get( inst, "isRTL" ); 8046 8047 while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden( obj ) ) ) { 8048 obj = obj[ isRTL ? "previousSibling" : "nextSibling" ]; 8049 } 8050 8051 position = $( obj ).offset(); 8052 return [ position.left, position.top ]; 8053 }, 8054 8055 /* Hide the date picker from view. 8056 * @param input element - the input field attached to the date picker 8057 */ 8058 _hideDatepicker: function( input ) { 8059 var showAnim, duration, postProcess, onClose, 8060 inst = this._curInst; 8061 8062 if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) { 8063 return; 8064 } 8065 8066 if ( this._datepickerShowing ) { 8067 showAnim = this._get( inst, "showAnim" ); 8068 duration = this._get( inst, "duration" ); 8069 postProcess = function() { 8070 $.datepicker._tidyDialog( inst ); 8071 }; 8072 8073 if ( $.effects && ( $.effects.effect[ showAnim ] ) ) { 8074 inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess ); 8075 } else { 8076 inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" : 8077 ( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess ); 8078 } 8079 8080 if ( !showAnim ) { 8081 postProcess(); 8082 } 8083 this._datepickerShowing = false; 8084 8085 onClose = this._get( inst, "onClose" ); 8086 if ( onClose ) { 8087 onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] ); 8088 } 8089 8090 this._lastInput = null; 8091 if ( this._inDialog ) { 8092 this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } ); 8093 if ( $.blockUI ) { 8094 $.unblockUI(); 8095 $( "body" ).append( this.dpDiv ); 8096 } 8097 } 8098 this._inDialog = false; 8099 } 8100 }, 8101 8102 /* Tidy up after a dialog display. */ 8103 _tidyDialog: function( inst ) { 8104 inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" ); 8105 }, 8106 8107 /* Close date picker if clicked elsewhere. */ 8108 _checkExternalClick: function( event ) { 8109 if ( !$.datepicker._curInst ) { 8110 return; 8111 } 8112 8113 var $target = $( event.target ), 8114 inst = $.datepicker._getInst( $target[ 0 ] ); 8115 8116 if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId && 8117 $target.parents( "#" + $.datepicker._mainDivId ).length === 0 && 8118 !$target.hasClass( $.datepicker.markerClassName ) && 8119 !$target.closest( "." + $.datepicker._triggerClass ).length && 8120 $.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) || 8121 ( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) { 8122 $.datepicker._hideDatepicker(); 8123 } 8124 }, 8125 8126 /* Adjust one of the date sub-fields. */ 8127 _adjustDate: function( id, offset, period ) { 8128 var target = $( id ), 8129 inst = this._getInst( target[ 0 ] ); 8130 8131 if ( this._isDisabledDatepicker( target[ 0 ] ) ) { 8132 return; 8133 } 8134 this._adjustInstDate( inst, offset, period ); 8135 this._updateDatepicker( inst ); 8136 }, 8137 8138 /* Action for current link. */ 8139 _gotoToday: function( id ) { 8140 var date, 8141 target = $( id ), 8142 inst = this._getInst( target[ 0 ] ); 8143 8144 if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) { 8145 inst.selectedDay = inst.currentDay; 8146 inst.drawMonth = inst.selectedMonth = inst.currentMonth; 8147 inst.drawYear = inst.selectedYear = inst.currentYear; 8148 } else { 8149 date = new Date(); 8150 inst.selectedDay = date.getDate(); 8151 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8152 inst.drawYear = inst.selectedYear = date.getFullYear(); 8153 } 8154 this._notifyChange( inst ); 8155 this._adjustDate( target ); 8156 }, 8157 8158 /* Action for selecting a new month/year. */ 8159 _selectMonthYear: function( id, select, period ) { 8160 var target = $( id ), 8161 inst = this._getInst( target[ 0 ] ); 8162 8163 inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] = 8164 inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] = 8165 parseInt( select.options[ select.selectedIndex ].value, 10 ); 8166 8167 this._notifyChange( inst ); 8168 this._adjustDate( target ); 8169 }, 8170 8171 /* Action for selecting a day. */ 8172 _selectDay: function( id, month, year, td ) { 8173 var inst, 8174 target = $( id ); 8175 8176 if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) { 8177 return; 8178 } 8179 8180 inst = this._getInst( target[ 0 ] ); 8181 inst.selectedDay = inst.currentDay = parseInt( $( "a", td ).attr( "data-date" ) ); 8182 inst.selectedMonth = inst.currentMonth = month; 8183 inst.selectedYear = inst.currentYear = year; 8184 this._selectDate( id, this._formatDate( inst, 8185 inst.currentDay, inst.currentMonth, inst.currentYear ) ); 8186 }, 8187 8188 /* Erase the input field and hide the date picker. */ 8189 _clearDate: function( id ) { 8190 var target = $( id ); 8191 this._selectDate( target, "" ); 8192 }, 8193 8194 /* Update the input field with the selected date. */ 8195 _selectDate: function( id, dateStr ) { 8196 var onSelect, 8197 target = $( id ), 8198 inst = this._getInst( target[ 0 ] ); 8199 8200 dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) ); 8201 if ( inst.input ) { 8202 inst.input.val( dateStr ); 8203 } 8204 this._updateAlternate( inst ); 8205 8206 onSelect = this._get( inst, "onSelect" ); 8207 if ( onSelect ) { 8208 onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] ); // trigger custom callback 8209 } else if ( inst.input ) { 8210 inst.input.trigger( "change" ); // fire the change event 8211 } 8212 8213 if ( inst.inline ) { 8214 this._updateDatepicker( inst ); 8215 } else { 8216 this._hideDatepicker(); 8217 this._lastInput = inst.input[ 0 ]; 8218 if ( typeof( inst.input[ 0 ] ) !== "object" ) { 8219 inst.input.trigger( "focus" ); // restore focus 8220 } 8221 this._lastInput = null; 8222 } 8223 }, 8224 8225 /* Update any alternate field to synchronise with the main field. */ 8226 _updateAlternate: function( inst ) { 8227 var altFormat, date, dateStr, 8228 altField = this._get( inst, "altField" ); 8229 8230 if ( altField ) { // update alternate field too 8231 altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" ); 8232 date = this._getDate( inst ); 8233 dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) ); 8234 $( document ).find( altField ).val( dateStr ); 8235 } 8236 }, 8237 8238 /* Set as beforeShowDay function to prevent selection of weekends. 8239 * @param date Date - the date to customise 8240 * @return [boolean, string] - is this date selectable?, what is its CSS class? 8241 */ 8242 noWeekends: function( date ) { 8243 var day = date.getDay(); 8244 return [ ( day > 0 && day < 6 ), "" ]; 8245 }, 8246 8247 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. 8248 * @param date Date - the date to get the week for 8249 * @return number - the number of the week within the year that contains this date 8250 */ 8251 iso8601Week: function( date ) { 8252 var time, 8253 checkDate = new Date( date.getTime() ); 8254 8255 // Find Thursday of this week starting on Monday 8256 checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) ); 8257 8258 time = checkDate.getTime(); 8259 checkDate.setMonth( 0 ); // Compare with Jan 1 8260 checkDate.setDate( 1 ); 8261 return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1; 8262 }, 8263 8264 /* Parse a string value into a date object. 8265 * See formatDate below for the possible formats. 8266 * 8267 * @param format string - the expected format of the date 8268 * @param value string - the date in the above format 8269 * @param settings Object - attributes include: 8270 * shortYearCutoff number - the cutoff year for determining the century (optional) 8271 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 8272 * dayNames string[7] - names of the days from Sunday (optional) 8273 * monthNamesShort string[12] - abbreviated names of the months (optional) 8274 * monthNames string[12] - names of the months (optional) 8275 * @return Date - the extracted date value or null if value is blank 8276 */ 8277 parseDate: function( format, value, settings ) { 8278 if ( format == null || value == null ) { 8279 throw "Invalid arguments"; 8280 } 8281 8282 value = ( typeof value === "object" ? value.toString() : value + "" ); 8283 if ( value === "" ) { 8284 return null; 8285 } 8286 8287 var iFormat, dim, extra, 8288 iValue = 0, 8289 shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff, 8290 shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp : 8291 new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ), 8292 dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort, 8293 dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames, 8294 monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort, 8295 monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames, 8296 year = -1, 8297 month = -1, 8298 day = -1, 8299 doy = -1, 8300 literal = false, 8301 date, 8302 8303 // Check whether a format character is doubled 8304 lookAhead = function( match ) { 8305 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match ); 8306 if ( matches ) { 8307 iFormat++; 8308 } 8309 return matches; 8310 }, 8311 8312 // Extract a number from the string value 8313 getNumber = function( match ) { 8314 var isDoubled = lookAhead( match ), 8315 size = ( match === "@" ? 14 : ( match === "!" ? 20 : 8316 ( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ), 8317 minSize = ( match === "y" ? size : 1 ), 8318 digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ), 8319 num = value.substring( iValue ).match( digits ); 8320 if ( !num ) { 8321 throw "Missing number at position " + iValue; 8322 } 8323 iValue += num[ 0 ].length; 8324 return parseInt( num[ 0 ], 10 ); 8325 }, 8326 8327 // Extract a name from the string value and convert to an index 8328 getName = function( match, shortNames, longNames ) { 8329 var index = -1, 8330 names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) { 8331 return [ [ k, v ] ]; 8332 } ).sort( function( a, b ) { 8333 return -( a[ 1 ].length - b[ 1 ].length ); 8334 } ); 8335 8336 $.each( names, function( i, pair ) { 8337 var name = pair[ 1 ]; 8338 if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) { 8339 index = pair[ 0 ]; 8340 iValue += name.length; 8341 return false; 8342 } 8343 } ); 8344 if ( index !== -1 ) { 8345 return index + 1; 8346 } else { 8347 throw "Unknown name at position " + iValue; 8348 } 8349 }, 8350 8351 // Confirm that a literal character matches the string value 8352 checkLiteral = function() { 8353 if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) { 8354 throw "Unexpected literal at position " + iValue; 8355 } 8356 iValue++; 8357 }; 8358 8359 for ( iFormat = 0; iFormat < format.length; iFormat++ ) { 8360 if ( literal ) { 8361 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) { 8362 literal = false; 8363 } else { 8364 checkLiteral(); 8365 } 8366 } else { 8367 switch ( format.charAt( iFormat ) ) { 8368 case "d": 8369 day = getNumber( "d" ); 8370 break; 8371 case "D": 8372 getName( "D", dayNamesShort, dayNames ); 8373 break; 8374 case "o": 8375 doy = getNumber( "o" ); 8376 break; 8377 case "m": 8378 month = getNumber( "m" ); 8379 break; 8380 case "M": 8381 month = getName( "M", monthNamesShort, monthNames ); 8382 break; 8383 case "y": 8384 year = getNumber( "y" ); 8385 break; 8386 case "@": 8387 date = new Date( getNumber( "@" ) ); 8388 year = date.getFullYear(); 8389 month = date.getMonth() + 1; 8390 day = date.getDate(); 8391 break; 8392 case "!": 8393 date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 ); 8394 year = date.getFullYear(); 8395 month = date.getMonth() + 1; 8396 day = date.getDate(); 8397 break; 8398 case "'": 8399 if ( lookAhead( "'" ) ) { 8400 checkLiteral(); 8401 } else { 8402 literal = true; 8403 } 8404 break; 8405 default: 8406 checkLiteral(); 8407 } 8408 } 8409 } 8410 8411 if ( iValue < value.length ) { 8412 extra = value.substr( iValue ); 8413 if ( !/^\s+/.test( extra ) ) { 8414 throw "Extra/unparsed characters found in date: " + extra; 8415 } 8416 } 8417 8418 if ( year === -1 ) { 8419 year = new Date().getFullYear(); 8420 } else if ( year < 100 ) { 8421 year += new Date().getFullYear() - new Date().getFullYear() % 100 + 8422 ( year <= shortYearCutoff ? 0 : -100 ); 8423 } 8424 8425 if ( doy > -1 ) { 8426 month = 1; 8427 day = doy; 8428 do { 8429 dim = this._getDaysInMonth( year, month - 1 ); 8430 if ( day <= dim ) { 8431 break; 8432 } 8433 month++; 8434 day -= dim; 8435 } while ( true ); 8436 } 8437 8438 date = this._daylightSavingAdjust( new Date( year, month - 1, day ) ); 8439 if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) { 8440 throw "Invalid date"; // E.g. 31/02/00 8441 } 8442 return date; 8443 }, 8444 8445 /* Standard date formats. */ 8446 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601) 8447 COOKIE: "D, dd M yy", 8448 ISO_8601: "yy-mm-dd", 8449 RFC_822: "D, d M y", 8450 RFC_850: "DD, dd-M-y", 8451 RFC_1036: "D, d M y", 8452 RFC_1123: "D, d M yy", 8453 RFC_2822: "D, d M yy", 8454 RSS: "D, d M y", // RFC 822 8455 TICKS: "!", 8456 TIMESTAMP: "@", 8457 W3C: "yy-mm-dd", // ISO 8601 8458 8459 _ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) + 8460 Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ), 8461 8462 /* Format a date object into a string value. 8463 * The format can be combinations of the following: 8464 * d - day of month (no leading zero) 8465 * dd - day of month (two digit) 8466 * o - day of year (no leading zeros) 8467 * oo - day of year (three digit) 8468 * D - day name short 8469 * DD - day name long 8470 * m - month of year (no leading zero) 8471 * mm - month of year (two digit) 8472 * M - month name short 8473 * MM - month name long 8474 * y - year (two digit) 8475 * yy - year (four digit) 8476 * @ - Unix timestamp (ms since 01/01/1970) 8477 * ! - Windows ticks (100ns since 01/01/0001) 8478 * "..." - literal text 8479 * '' - single quote 8480 * 8481 * @param format string - the desired format of the date 8482 * @param date Date - the date value to format 8483 * @param settings Object - attributes include: 8484 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 8485 * dayNames string[7] - names of the days from Sunday (optional) 8486 * monthNamesShort string[12] - abbreviated names of the months (optional) 8487 * monthNames string[12] - names of the months (optional) 8488 * @return string - the date in the above format 8489 */ 8490 formatDate: function( format, date, settings ) { 8491 if ( !date ) { 8492 return ""; 8493 } 8494 8495 var iFormat, 8496 dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort, 8497 dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames, 8498 monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort, 8499 monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames, 8500 8501 // Check whether a format character is doubled 8502 lookAhead = function( match ) { 8503 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match ); 8504 if ( matches ) { 8505 iFormat++; 8506 } 8507 return matches; 8508 }, 8509 8510 // Format a number, with leading zero if necessary 8511 formatNumber = function( match, value, len ) { 8512 var num = "" + value; 8513 if ( lookAhead( match ) ) { 8514 while ( num.length < len ) { 8515 num = "0" + num; 8516 } 8517 } 8518 return num; 8519 }, 8520 8521 // Format a name, short or long as requested 8522 formatName = function( match, value, shortNames, longNames ) { 8523 return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] ); 8524 }, 8525 output = "", 8526 literal = false; 8527 8528 if ( date ) { 8529 for ( iFormat = 0; iFormat < format.length; iFormat++ ) { 8530 if ( literal ) { 8531 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) { 8532 literal = false; 8533 } else { 8534 output += format.charAt( iFormat ); 8535 } 8536 } else { 8537 switch ( format.charAt( iFormat ) ) { 8538 case "d": 8539 output += formatNumber( "d", date.getDate(), 2 ); 8540 break; 8541 case "D": 8542 output += formatName( "D", date.getDay(), dayNamesShort, dayNames ); 8543 break; 8544 case "o": 8545 output += formatNumber( "o", 8546 Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 ); 8547 break; 8548 case "m": 8549 output += formatNumber( "m", date.getMonth() + 1, 2 ); 8550 break; 8551 case "M": 8552 output += formatName( "M", date.getMonth(), monthNamesShort, monthNames ); 8553 break; 8554 case "y": 8555 output += ( lookAhead( "y" ) ? date.getFullYear() : 8556 ( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 ); 8557 break; 8558 case "@": 8559 output += date.getTime(); 8560 break; 8561 case "!": 8562 output += date.getTime() * 10000 + this._ticksTo1970; 8563 break; 8564 case "'": 8565 if ( lookAhead( "'" ) ) { 8566 output += "'"; 8567 } else { 8568 literal = true; 8569 } 8570 break; 8571 default: 8572 output += format.charAt( iFormat ); 8573 } 8574 } 8575 } 8576 } 8577 return output; 8578 }, 8579 8580 /* Extract all possible characters from the date format. */ 8581 _possibleChars: function( format ) { 8582 var iFormat, 8583 chars = "", 8584 literal = false, 8585 8586 // Check whether a format character is doubled 8587 lookAhead = function( match ) { 8588 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match ); 8589 if ( matches ) { 8590 iFormat++; 8591 } 8592 return matches; 8593 }; 8594 8595 for ( iFormat = 0; iFormat < format.length; iFormat++ ) { 8596 if ( literal ) { 8597 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) { 8598 literal = false; 8599 } else { 8600 chars += format.charAt( iFormat ); 8601 } 8602 } else { 8603 switch ( format.charAt( iFormat ) ) { 8604 case "d": case "m": case "y": case "@": 8605 chars += "0123456789"; 8606 break; 8607 case "D": case "M": 8608 return null; // Accept anything 8609 case "'": 8610 if ( lookAhead( "'" ) ) { 8611 chars += "'"; 8612 } else { 8613 literal = true; 8614 } 8615 break; 8616 default: 8617 chars += format.charAt( iFormat ); 8618 } 8619 } 8620 } 8621 return chars; 8622 }, 8623 8624 /* Get a setting value, defaulting if necessary. */ 8625 _get: function( inst, name ) { 8626 return inst.settings[ name ] !== undefined ? 8627 inst.settings[ name ] : this._defaults[ name ]; 8628 }, 8629 8630 /* Parse existing date and initialise date picker. */ 8631 _setDateFromField: function( inst, noDefault ) { 8632 if ( inst.input.val() === inst.lastVal ) { 8633 return; 8634 } 8635 8636 var dateFormat = this._get( inst, "dateFormat" ), 8637 dates = inst.lastVal = inst.input ? inst.input.val() : null, 8638 defaultDate = this._getDefaultDate( inst ), 8639 date = defaultDate, 8640 settings = this._getFormatConfig( inst ); 8641 8642 try { 8643 date = this.parseDate( dateFormat, dates, settings ) || defaultDate; 8644 } catch ( event ) { 8645 dates = ( noDefault ? "" : dates ); 8646 } 8647 inst.selectedDay = date.getDate(); 8648 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8649 inst.drawYear = inst.selectedYear = date.getFullYear(); 8650 inst.currentDay = ( dates ? date.getDate() : 0 ); 8651 inst.currentMonth = ( dates ? date.getMonth() : 0 ); 8652 inst.currentYear = ( dates ? date.getFullYear() : 0 ); 8653 this._adjustInstDate( inst ); 8654 }, 8655 8656 /* Retrieve the default date shown on opening. */ 8657 _getDefaultDate: function( inst ) { 8658 return this._restrictMinMax( inst, 8659 this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) ); 8660 }, 8661 8662 /* A date may be specified as an exact value or a relative one. */ 8663 _determineDate: function( inst, date, defaultDate ) { 8664 var offsetNumeric = function( offset ) { 8665 var date = new Date(); 8666 date.setDate( date.getDate() + offset ); 8667 return date; 8668 }, 8669 offsetString = function( offset ) { 8670 try { 8671 return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ), 8672 offset, $.datepicker._getFormatConfig( inst ) ); 8673 } catch ( e ) { 8674 8675 // Ignore 8676 } 8677 8678 var date = ( offset.toLowerCase().match( /^c/ ) ? 8679 $.datepicker._getDate( inst ) : null ) || new Date(), 8680 year = date.getFullYear(), 8681 month = date.getMonth(), 8682 day = date.getDate(), 8683 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, 8684 matches = pattern.exec( offset ); 8685 8686 while ( matches ) { 8687 switch ( matches[ 2 ] || "d" ) { 8688 case "d" : case "D" : 8689 day += parseInt( matches[ 1 ], 10 ); break; 8690 case "w" : case "W" : 8691 day += parseInt( matches[ 1 ], 10 ) * 7; break; 8692 case "m" : case "M" : 8693 month += parseInt( matches[ 1 ], 10 ); 8694 day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) ); 8695 break; 8696 case "y": case "Y" : 8697 year += parseInt( matches[ 1 ], 10 ); 8698 day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) ); 8699 break; 8700 } 8701 matches = pattern.exec( offset ); 8702 } 8703 return new Date( year, month, day ); 8704 }, 8705 newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) : 8706 ( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) ); 8707 8708 newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate ); 8709 if ( newDate ) { 8710 newDate.setHours( 0 ); 8711 newDate.setMinutes( 0 ); 8712 newDate.setSeconds( 0 ); 8713 newDate.setMilliseconds( 0 ); 8714 } 8715 return this._daylightSavingAdjust( newDate ); 8716 }, 8717 8718 /* Handle switch to/from daylight saving. 8719 * Hours may be non-zero on daylight saving cut-over: 8720 * > 12 when midnight changeover, but then cannot generate 8721 * midnight datetime, so jump to 1AM, otherwise reset. 8722 * @param date (Date) the date to check 8723 * @return (Date) the corrected date 8724 */ 8725 _daylightSavingAdjust: function( date ) { 8726 if ( !date ) { 8727 return null; 8728 } 8729 date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 ); 8730 return date; 8731 }, 8732 8733 /* Set the date(s) directly. */ 8734 _setDate: function( inst, date, noChange ) { 8735 var clear = !date, 8736 origMonth = inst.selectedMonth, 8737 origYear = inst.selectedYear, 8738 newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) ); 8739 8740 inst.selectedDay = inst.currentDay = newDate.getDate(); 8741 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); 8742 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); 8743 if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) { 8744 this._notifyChange( inst ); 8745 } 8746 this._adjustInstDate( inst ); 8747 if ( inst.input ) { 8748 inst.input.val( clear ? "" : this._formatDate( inst ) ); 8749 } 8750 }, 8751 8752 /* Retrieve the date(s) directly. */ 8753 _getDate: function( inst ) { 8754 var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null : 8755 this._daylightSavingAdjust( new Date( 8756 inst.currentYear, inst.currentMonth, inst.currentDay ) ) ); 8757 return startDate; 8758 }, 8759 8760 /* Attach the onxxx handlers. These are declared statically so 8761 * they work with static code transformers like Caja. 8762 */ 8763 _attachHandlers: function( inst ) { 8764 var stepMonths = this._get( inst, "stepMonths" ), 8765 id = "#" + inst.id.replace( /\\\\/g, "\\" ); 8766 inst.dpDiv.find( "[data-handler]" ).map( function() { 8767 var handler = { 8768 prev: function() { 8769 $.datepicker._adjustDate( id, -stepMonths, "M" ); 8770 }, 8771 next: function() { 8772 $.datepicker._adjustDate( id, +stepMonths, "M" ); 8773 }, 8774 hide: function() { 8775 $.datepicker._hideDatepicker(); 8776 }, 8777 today: function() { 8778 $.datepicker._gotoToday( id ); 8779 }, 8780 selectDay: function() { 8781 $.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this ); 8782 return false; 8783 }, 8784 selectMonth: function() { 8785 $.datepicker._selectMonthYear( id, this, "M" ); 8786 return false; 8787 }, 8788 selectYear: function() { 8789 $.datepicker._selectMonthYear( id, this, "Y" ); 8790 return false; 8791 } 8792 }; 8793 $( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] ); 8794 } ); 8795 }, 8796 8797 /* Generate the HTML for the current state of the date picker. */ 8798 _generateHTML: function( inst ) { 8799 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate, 8800 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin, 8801 monthNames, monthNamesShort, beforeShowDay, showOtherMonths, 8802 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate, 8803 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows, 8804 printDate, dRow, tbody, daySettings, otherMonth, unselectable, 8805 tempDate = new Date(), 8806 today = this._daylightSavingAdjust( 8807 new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time 8808 isRTL = this._get( inst, "isRTL" ), 8809 showButtonPanel = this._get( inst, "showButtonPanel" ), 8810 hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ), 8811 navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ), 8812 numMonths = this._getNumberOfMonths( inst ), 8813 showCurrentAtPos = this._get( inst, "showCurrentAtPos" ), 8814 stepMonths = this._get( inst, "stepMonths" ), 8815 isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ), 8816 currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) : 8817 new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ), 8818 minDate = this._getMinMaxDate( inst, "min" ), 8819 maxDate = this._getMinMaxDate( inst, "max" ), 8820 drawMonth = inst.drawMonth - showCurrentAtPos, 8821 drawYear = inst.drawYear; 8822 8823 if ( drawMonth < 0 ) { 8824 drawMonth += 12; 8825 drawYear--; 8826 } 8827 if ( maxDate ) { 8828 maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(), 8829 maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) ); 8830 maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw ); 8831 while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) { 8832 drawMonth--; 8833 if ( drawMonth < 0 ) { 8834 drawMonth = 11; 8835 drawYear--; 8836 } 8837 } 8838 } 8839 inst.drawMonth = drawMonth; 8840 inst.drawYear = drawYear; 8841 8842 prevText = this._get( inst, "prevText" ); 8843 prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText, 8844 this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ), 8845 this._getFormatConfig( inst ) ) ); 8846 8847 if ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ) { 8848 prev = $( "<a>" ) 8849 .attr( { 8850 "class": "ui-datepicker-prev ui-corner-all", 8851 "data-handler": "prev", 8852 "data-event": "click", 8853 title: prevText 8854 } ) 8855 .append( 8856 $( "<span>" ) 8857 .addClass( "ui-icon ui-icon-circle-triangle-" + 8858 ( isRTL ? "e" : "w" ) ) 8859 .text( prevText ) 8860 )[ 0 ].outerHTML; 8861 } else if ( hideIfNoPrevNext ) { 8862 prev = ""; 8863 } else { 8864 prev = $( "<a>" ) 8865 .attr( { 8866 "class": "ui-datepicker-prev ui-corner-all ui-state-disabled", 8867 title: prevText 8868 } ) 8869 .append( 8870 $( "<span>" ) 8871 .addClass( "ui-icon ui-icon-circle-triangle-" + 8872 ( isRTL ? "e" : "w" ) ) 8873 .text( prevText ) 8874 )[ 0 ].outerHTML; 8875 } 8876 8877 nextText = this._get( inst, "nextText" ); 8878 nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText, 8879 this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ), 8880 this._getFormatConfig( inst ) ) ); 8881 8882 if ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ) { 8883 next = $( "<a>" ) 8884 .attr( { 8885 "class": "ui-datepicker-next ui-corner-all", 8886 "data-handler": "next", 8887 "data-event": "click", 8888 title: nextText 8889 } ) 8890 .append( 8891 $( "<span>" ) 8892 .addClass( "ui-icon ui-icon-circle-triangle-" + 8893 ( isRTL ? "w" : "e" ) ) 8894 .text( nextText ) 8895 )[ 0 ].outerHTML; 8896 } else if ( hideIfNoPrevNext ) { 8897 next = ""; 8898 } else { 8899 next = $( "<a>" ) 8900 .attr( { 8901 "class": "ui-datepicker-next ui-corner-all ui-state-disabled", 8902 title: nextText 8903 } ) 8904 .append( 8905 $( "<span>" ) 8906 .attr( "class", "ui-icon ui-icon-circle-triangle-" + 8907 ( isRTL ? "w" : "e" ) ) 8908 .text( nextText ) 8909 )[ 0 ].outerHTML; 8910 } 8911 8912 currentText = this._get( inst, "currentText" ); 8913 gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today ); 8914 currentText = ( !navigationAsDateFormat ? currentText : 8915 this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) ); 8916 8917 controls = ""; 8918 if ( !inst.inline ) { 8919 controls = $( "<button>" ) 8920 .attr( { 8921 type: "button", 8922 "class": "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all", 8923 "data-handler": "hide", 8924 "data-event": "click" 8925 } ) 8926 .text( this._get( inst, "closeText" ) )[ 0 ].outerHTML; 8927 } 8928 8929 buttonPanel = ""; 8930 if ( showButtonPanel ) { 8931 buttonPanel = $( "<div class='ui-datepicker-buttonpane ui-widget-content'>" ) 8932 .append( isRTL ? controls : "" ) 8933 .append( this._isInRange( inst, gotoDate ) ? 8934 $( "<button>" ) 8935 .attr( { 8936 type: "button", 8937 "class": "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all", 8938 "data-handler": "today", 8939 "data-event": "click" 8940 } ) 8941 .text( currentText ) : 8942 "" ) 8943 .append( isRTL ? "" : controls )[ 0 ].outerHTML; 8944 } 8945 8946 firstDay = parseInt( this._get( inst, "firstDay" ), 10 ); 8947 firstDay = ( isNaN( firstDay ) ? 0 : firstDay ); 8948 8949 showWeek = this._get( inst, "showWeek" ); 8950 dayNames = this._get( inst, "dayNames" ); 8951 dayNamesMin = this._get( inst, "dayNamesMin" ); 8952 monthNames = this._get( inst, "monthNames" ); 8953 monthNamesShort = this._get( inst, "monthNamesShort" ); 8954 beforeShowDay = this._get( inst, "beforeShowDay" ); 8955 showOtherMonths = this._get( inst, "showOtherMonths" ); 8956 selectOtherMonths = this._get( inst, "selectOtherMonths" ); 8957 defaultDate = this._getDefaultDate( inst ); 8958 html = ""; 8959 8960 for ( row = 0; row < numMonths[ 0 ]; row++ ) { 8961 group = ""; 8962 this.maxRows = 4; 8963 for ( col = 0; col < numMonths[ 1 ]; col++ ) { 8964 selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) ); 8965 cornerClass = " ui-corner-all"; 8966 calender = ""; 8967 if ( isMultiMonth ) { 8968 calender += "<div class='ui-datepicker-group"; 8969 if ( numMonths[ 1 ] > 1 ) { 8970 switch ( col ) { 8971 case 0: calender += " ui-datepicker-group-first"; 8972 cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break; 8973 case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last"; 8974 cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break; 8975 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break; 8976 } 8977 } 8978 calender += "'>"; 8979 } 8980 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" + 8981 ( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) + 8982 ( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) + 8983 this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate, 8984 row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers 8985 "</div><table class='ui-datepicker-calendar'><thead>" + 8986 "<tr>"; 8987 thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" ); 8988 for ( dow = 0; dow < 7; dow++ ) { // days of the week 8989 day = ( dow + firstDay ) % 7; 8990 thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" + 8991 "<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>"; 8992 } 8993 calender += thead + "</tr></thead><tbody>"; 8994 daysInMonth = this._getDaysInMonth( drawYear, drawMonth ); 8995 if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) { 8996 inst.selectedDay = Math.min( inst.selectedDay, daysInMonth ); 8997 } 8998 leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7; 8999 curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate 9000 numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043) 9001 this.maxRows = numRows; 9002 printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) ); 9003 for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows 9004 calender += "<tr>"; 9005 tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" + 9006 this._get( inst, "calculateWeek" )( printDate ) + "</td>" ); 9007 for ( dow = 0; dow < 7; dow++ ) { // create date picker days 9008 daySettings = ( beforeShowDay ? 9009 beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] ); 9010 otherMonth = ( printDate.getMonth() !== drawMonth ); 9011 unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] || 9012 ( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate ); 9013 tbody += "<td class='" + 9014 ( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends 9015 ( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months 9016 ( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key 9017 ( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ? 9018 9019 // or defaultDate is current printedDate and defaultDate is selectedDate 9020 " " + this._dayOverClass : "" ) + // highlight selected day 9021 ( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) + // highlight unselectable days 9022 ( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates 9023 ( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day 9024 ( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different) 9025 ( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "'" ) + "'" : "" ) + // cell title 9026 ( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions 9027 ( otherMonth && !showOtherMonths ? " " : // display for other months 9028 ( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" + 9029 ( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) + 9030 ( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day 9031 ( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months 9032 "' href='#' aria-current='" + ( printDate.getTime() === currentDate.getTime() ? "true" : "false" ) + // mark date as selected for screen reader 9033 "' data-date='" + printDate.getDate() + // store date as data 9034 "'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date 9035 printDate.setDate( printDate.getDate() + 1 ); 9036 printDate = this._daylightSavingAdjust( printDate ); 9037 } 9038 calender += tbody + "</tr>"; 9039 } 9040 drawMonth++; 9041 if ( drawMonth > 11 ) { 9042 drawMonth = 0; 9043 drawYear++; 9044 } 9045 calender += "</tbody></table>" + ( isMultiMonth ? "</div>" + 9046 ( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" ); 9047 group += calender; 9048 } 9049 html += group; 9050 } 9051 html += buttonPanel; 9052 inst._keyEvent = false; 9053 return html; 9054 }, 9055 9056 /* Generate the month and year header. */ 9057 _generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate, 9058 secondary, monthNames, monthNamesShort ) { 9059 9060 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear, 9061 changeMonth = this._get( inst, "changeMonth" ), 9062 changeYear = this._get( inst, "changeYear" ), 9063 showMonthAfterYear = this._get( inst, "showMonthAfterYear" ), 9064 selectMonthLabel = this._get( inst, "selectMonthLabel" ), 9065 selectYearLabel = this._get( inst, "selectYearLabel" ), 9066 html = "<div class='ui-datepicker-title'>", 9067 monthHtml = ""; 9068 9069 // Month selection 9070 if ( secondary || !changeMonth ) { 9071 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>"; 9072 } else { 9073 inMinYear = ( minDate && minDate.getFullYear() === drawYear ); 9074 inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear ); 9075 monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>"; 9076 for ( month = 0; month < 12; month++ ) { 9077 if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) { 9078 monthHtml += "<option value='" + month + "'" + 9079 ( month === drawMonth ? " selected='selected'" : "" ) + 9080 ">" + monthNamesShort[ month ] + "</option>"; 9081 } 9082 } 9083 monthHtml += "</select>"; 9084 } 9085 9086 if ( !showMonthAfterYear ) { 9087 html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? " " : "" ); 9088 } 9089 9090 // Year selection 9091 if ( !inst.yearshtml ) { 9092 inst.yearshtml = ""; 9093 if ( secondary || !changeYear ) { 9094 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>"; 9095 } else { 9096 9097 // determine range of years to display 9098 years = this._get( inst, "yearRange" ).split( ":" ); 9099 thisYear = new Date().getFullYear(); 9100 determineYear = function( value ) { 9101 var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) : 9102 ( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) : 9103 parseInt( value, 10 ) ) ); 9104 return ( isNaN( year ) ? thisYear : year ); 9105 }; 9106 year = determineYear( years[ 0 ] ); 9107 endYear = Math.max( year, determineYear( years[ 1 ] || "" ) ); 9108 year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year ); 9109 endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear ); 9110 inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>"; 9111 for ( ; year <= endYear; year++ ) { 9112 inst.yearshtml += "<option value='" + year + "'" + 9113 ( year === drawYear ? " selected='selected'" : "" ) + 9114 ">" + year + "</option>"; 9115 } 9116 inst.yearshtml += "</select>"; 9117 9118 html += inst.yearshtml; 9119 inst.yearshtml = null; 9120 } 9121 } 9122 9123 html += this._get( inst, "yearSuffix" ); 9124 if ( showMonthAfterYear ) { 9125 html += ( secondary || !( changeMonth && changeYear ) ? " " : "" ) + monthHtml; 9126 } 9127 html += "</div>"; // Close datepicker_header 9128 return html; 9129 }, 9130 9131 /* Adjust one of the date sub-fields. */ 9132 _adjustInstDate: function( inst, offset, period ) { 9133 var year = inst.selectedYear + ( period === "Y" ? offset : 0 ), 9134 month = inst.selectedMonth + ( period === "M" ? offset : 0 ), 9135 day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ), 9136 date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) ); 9137 9138 inst.selectedDay = date.getDate(); 9139 inst.drawMonth = inst.selectedMonth = date.getMonth(); 9140 inst.drawYear = inst.selectedYear = date.getFullYear(); 9141 if ( period === "M" || period === "Y" ) { 9142 this._notifyChange( inst ); 9143 } 9144 }, 9145 9146 /* Ensure a date is within any min/max bounds. */ 9147 _restrictMinMax: function( inst, date ) { 9148 var minDate = this._getMinMaxDate( inst, "min" ), 9149 maxDate = this._getMinMaxDate( inst, "max" ), 9150 newDate = ( minDate && date < minDate ? minDate : date ); 9151 return ( maxDate && newDate > maxDate ? maxDate : newDate ); 9152 }, 9153 9154 /* Notify change of month/year. */ 9155 _notifyChange: function( inst ) { 9156 var onChange = this._get( inst, "onChangeMonthYear" ); 9157 if ( onChange ) { 9158 onChange.apply( ( inst.input ? inst.input[ 0 ] : null ), 9159 [ inst.selectedYear, inst.selectedMonth + 1, inst ] ); 9160 } 9161 }, 9162 9163 /* Determine the number of months to show. */ 9164 _getNumberOfMonths: function( inst ) { 9165 var numMonths = this._get( inst, "numberOfMonths" ); 9166 return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) ); 9167 }, 9168 9169 /* Determine the current maximum date - ensure no time components are set. */ 9170 _getMinMaxDate: function( inst, minMax ) { 9171 return this._determineDate( inst, this._get( inst, minMax + "Date" ), null ); 9172 }, 9173 9174 /* Find the number of days in a given month. */ 9175 _getDaysInMonth: function( year, month ) { 9176 return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate(); 9177 }, 9178 9179 /* Find the day of the week of the first of a month. */ 9180 _getFirstDayOfMonth: function( year, month ) { 9181 return new Date( year, month, 1 ).getDay(); 9182 }, 9183 9184 /* Determines if we should allow a "next/prev" month display change. */ 9185 _canAdjustMonth: function( inst, offset, curYear, curMonth ) { 9186 var numMonths = this._getNumberOfMonths( inst ), 9187 date = this._daylightSavingAdjust( new Date( curYear, 9188 curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) ); 9189 9190 if ( offset < 0 ) { 9191 date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) ); 9192 } 9193 return this._isInRange( inst, date ); 9194 }, 9195 9196 /* Is the given date in the accepted range? */ 9197 _isInRange: function( inst, date ) { 9198 var yearSplit, currentYear, 9199 minDate = this._getMinMaxDate( inst, "min" ), 9200 maxDate = this._getMinMaxDate( inst, "max" ), 9201 minYear = null, 9202 maxYear = null, 9203 years = this._get( inst, "yearRange" ); 9204 if ( years ) { 9205 yearSplit = years.split( ":" ); 9206 currentYear = new Date().getFullYear(); 9207 minYear = parseInt( yearSplit[ 0 ], 10 ); 9208 maxYear = parseInt( yearSplit[ 1 ], 10 ); 9209 if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) { 9210 minYear += currentYear; 9211 } 9212 if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) { 9213 maxYear += currentYear; 9214 } 9215 } 9216 9217 return ( ( !minDate || date.getTime() >= minDate.getTime() ) && 9218 ( !maxDate || date.getTime() <= maxDate.getTime() ) && 9219 ( !minYear || date.getFullYear() >= minYear ) && 9220 ( !maxYear || date.getFullYear() <= maxYear ) ); 9221 }, 9222 9223 /* Provide the configuration settings for formatting/parsing. */ 9224 _getFormatConfig: function( inst ) { 9225 var shortYearCutoff = this._get( inst, "shortYearCutoff" ); 9226 shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff : 9227 new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) ); 9228 return { shortYearCutoff: shortYearCutoff, 9229 dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ), 9230 monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) }; 9231 }, 9232 9233 /* Format the given date for display. */ 9234 _formatDate: function( inst, day, month, year ) { 9235 if ( !day ) { 9236 inst.currentDay = inst.selectedDay; 9237 inst.currentMonth = inst.selectedMonth; 9238 inst.currentYear = inst.selectedYear; 9239 } 9240 var date = ( day ? ( typeof day === "object" ? day : 9241 this._daylightSavingAdjust( new Date( year, month, day ) ) ) : 9242 this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ); 9243 return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) ); 9244 } 9245} ); 9246 9247/* 9248 * Bind hover events for datepicker elements. 9249 * Done via delegate so the binding only occurs once in the lifetime of the parent div. 9250 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. 9251 */ 9252function datepicker_bindHover( dpDiv ) { 9253 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a"; 9254 return dpDiv.on( "mouseout", selector, function() { 9255 $( this ).removeClass( "ui-state-hover" ); 9256 if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) { 9257 $( this ).removeClass( "ui-datepicker-prev-hover" ); 9258 } 9259 if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) { 9260 $( this ).removeClass( "ui-datepicker-next-hover" ); 9261 } 9262 } ) 9263 .on( "mouseover", selector, datepicker_handleMouseover ); 9264} 9265 9266function datepicker_handleMouseover() { 9267 if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) { 9268 $( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" ); 9269 $( this ).addClass( "ui-state-hover" ); 9270 if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) { 9271 $( this ).addClass( "ui-datepicker-prev-hover" ); 9272 } 9273 if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) { 9274 $( this ).addClass( "ui-datepicker-next-hover" ); 9275 } 9276 } 9277} 9278 9279/* jQuery extend now ignores nulls! */ 9280function datepicker_extendRemove( target, props ) { 9281 $.extend( target, props ); 9282 for ( var name in props ) { 9283 if ( props[ name ] == null ) { 9284 target[ name ] = props[ name ]; 9285 } 9286 } 9287 return target; 9288} 9289 9290/* Invoke the datepicker functionality. 9291 @param options string - a command, optionally followed by additional parameters or 9292 Object - settings for attaching new datepicker functionality 9293 @return jQuery object */ 9294$.fn.datepicker = function( options ) { 9295 9296 /* Verify an empty collection wasn't passed - Fixes #6976 */ 9297 if ( !this.length ) { 9298 return this; 9299 } 9300 9301 /* Initialise the date picker. */ 9302 if ( !$.datepicker.initialized ) { 9303 $( document ).on( "mousedown", $.datepicker._checkExternalClick ); 9304 $.datepicker.initialized = true; 9305 } 9306 9307 /* Append datepicker main container to body if not exist. */ 9308 if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) { 9309 $( "body" ).append( $.datepicker.dpDiv ); 9310 } 9311 9312 var otherArgs = Array.prototype.slice.call( arguments, 1 ); 9313 if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) { 9314 return $.datepicker[ "_" + options + "Datepicker" ]. 9315 apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) ); 9316 } 9317 if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) { 9318 return $.datepicker[ "_" + options + "Datepicker" ]. 9319 apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) ); 9320 } 9321 return this.each( function() { 9322 if ( typeof options === "string" ) { 9323 $.datepicker[ "_" + options + "Datepicker" ] 9324 .apply( $.datepicker, [ this ].concat( otherArgs ) ); 9325 } else { 9326 $.datepicker._attachDatepicker( this, options ); 9327 } 9328 } ); 9329}; 9330 9331$.datepicker = new Datepicker(); // singleton instance 9332$.datepicker.initialized = false; 9333$.datepicker.uuid = new Date().getTime(); 9334$.datepicker.version = "1.14.0"; 9335 9336var widgetsDatepicker = $.datepicker; 9337 9338 9339/*! 9340 * jQuery UI Mouse 1.14.0 9341 * https://jqueryui.com 9342 * 9343 * Copyright OpenJS Foundation and other contributors 9344 * Released under the MIT license. 9345 * https://jquery.org/license 9346 */ 9347 9348//>>label: Mouse 9349//>>group: Widgets 9350//>>description: Abstracts mouse-based interactions to assist in creating certain widgets. 9351//>>docs: https://api.jqueryui.com/mouse/ 9352 9353 9354var mouseHandled = false; 9355$( document ).on( "mouseup", function() { 9356 mouseHandled = false; 9357} ); 9358 9359var widgetsMouse = $.widget( "ui.mouse", { 9360 version: "1.14.0", 9361 options: { 9362 cancel: "input, textarea, button, select, option", 9363 distance: 1, 9364 delay: 0 9365 }, 9366 _mouseInit: function() { 9367 var that = this; 9368 9369 this.element 9370 .on( "mousedown." + this.widgetName, function( event ) { 9371 return that._mouseDown( event ); 9372 } ) 9373 .on( "click." + this.widgetName, function( event ) { 9374 if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) { 9375 $.removeData( event.target, that.widgetName + ".preventClickEvent" ); 9376 event.stopImmediatePropagation(); 9377 return false; 9378 } 9379 } ); 9380 9381 this.started = false; 9382 }, 9383 9384 // TODO: make sure destroying one instance of mouse doesn't mess with 9385 // other instances of mouse 9386 _mouseDestroy: function() { 9387 this.element.off( "." + this.widgetName ); 9388 if ( this._mouseMoveDelegate ) { 9389 this.document 9390 .off( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 9391 .off( "mouseup." + this.widgetName, this._mouseUpDelegate ); 9392 } 9393 }, 9394 9395 _mouseDown: function( event ) { 9396 9397 // don't let more than one widget handle mouseStart 9398 if ( mouseHandled ) { 9399 return; 9400 } 9401 9402 this._mouseMoved = false; 9403 9404 // We may have missed mouseup (out of window) 9405 if ( this._mouseStarted ) { 9406 this._mouseUp( event ); 9407 } 9408 9409 this._mouseDownEvent = event; 9410 9411 var that = this, 9412 btnIsLeft = event.which === 1, 9413 elIsCancel = typeof this.options.cancel === "string" ? 9414 $( event.target ).closest( this.options.cancel ).length : 9415 false; 9416 if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) { 9417 return true; 9418 } 9419 9420 this.mouseDelayMet = !this.options.delay; 9421 if ( !this.mouseDelayMet ) { 9422 this._mouseDelayTimer = setTimeout( function() { 9423 that.mouseDelayMet = true; 9424 }, this.options.delay ); 9425 } 9426 9427 if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) { 9428 this._mouseStarted = ( this._mouseStart( event ) !== false ); 9429 if ( !this._mouseStarted ) { 9430 event.preventDefault(); 9431 return true; 9432 } 9433 } 9434 9435 // Click event may never have fired (Gecko & Opera) 9436 if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) { 9437 $.removeData( event.target, this.widgetName + ".preventClickEvent" ); 9438 } 9439 9440 // These delegates are required to keep context 9441 this._mouseMoveDelegate = function( event ) { 9442 return that._mouseMove( event ); 9443 }; 9444 this._mouseUpDelegate = function( event ) { 9445 return that._mouseUp( event ); 9446 }; 9447 9448 this.document 9449 .on( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 9450 .on( "mouseup." + this.widgetName, this._mouseUpDelegate ); 9451 9452 event.preventDefault(); 9453 9454 mouseHandled = true; 9455 return true; 9456 }, 9457 9458 _mouseMove: function( event ) { 9459 9460 // Only check for mouseups outside the document if you've moved inside the document 9461 // at least once. 9462 if ( this._mouseMoved && !event.which ) { 9463 9464 // Support: Safari <=8 - 9 9465 // Safari sets which to 0 if you press any of the following keys 9466 // during a drag (#14461) 9467 if ( event.originalEvent.altKey || event.originalEvent.ctrlKey || 9468 event.originalEvent.metaKey || event.originalEvent.shiftKey ) { 9469 this.ignoreMissingWhich = true; 9470 } else if ( !this.ignoreMissingWhich ) { 9471 return this._mouseUp( event ); 9472 } 9473 } 9474 9475 if ( event.which || event.button ) { 9476 this._mouseMoved = true; 9477 } 9478 9479 if ( this._mouseStarted ) { 9480 this._mouseDrag( event ); 9481 return event.preventDefault(); 9482 } 9483 9484 if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) { 9485 this._mouseStarted = 9486 ( this._mouseStart( this._mouseDownEvent, event ) !== false ); 9487 if ( this._mouseStarted ) { 9488 this._mouseDrag( event ); 9489 } else { 9490 this._mouseUp( event ); 9491 } 9492 } 9493 9494 return !this._mouseStarted; 9495 }, 9496 9497 _mouseUp: function( event ) { 9498 this.document 9499 .off( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 9500 .off( "mouseup." + this.widgetName, this._mouseUpDelegate ); 9501 9502 if ( this._mouseStarted ) { 9503 this._mouseStarted = false; 9504 9505 if ( event.target === this._mouseDownEvent.target ) { 9506 $.data( event.target, this.widgetName + ".preventClickEvent", true ); 9507 } 9508 9509 this._mouseStop( event ); 9510 } 9511 9512 if ( this._mouseDelayTimer ) { 9513 clearTimeout( this._mouseDelayTimer ); 9514 delete this._mouseDelayTimer; 9515 } 9516 9517 this.ignoreMissingWhich = false; 9518 mouseHandled = false; 9519 event.preventDefault(); 9520 }, 9521 9522 _mouseDistanceMet: function( event ) { 9523 return ( Math.max( 9524 Math.abs( this._mouseDownEvent.pageX - event.pageX ), 9525 Math.abs( this._mouseDownEvent.pageY - event.pageY ) 9526 ) >= this.options.distance 9527 ); 9528 }, 9529 9530 _mouseDelayMet: function( /* event */ ) { 9531 return this.mouseDelayMet; 9532 }, 9533 9534 // These are placeholder methods, to be overriden by extending plugin 9535 _mouseStart: function( /* event */ ) {}, 9536 _mouseDrag: function( /* event */ ) {}, 9537 _mouseStop: function( /* event */ ) {}, 9538 _mouseCapture: function( /* event */ ) { 9539 return true; 9540 } 9541} ); 9542 9543 9544 9545// $.ui.plugin is deprecated. Use $.widget() extensions instead. 9546var plugin = $.ui.plugin = { 9547 add: function( module, option, set ) { 9548 var i, 9549 proto = $.ui[ module ].prototype; 9550 for ( i in set ) { 9551 proto.plugins[ i ] = proto.plugins[ i ] || []; 9552 proto.plugins[ i ].push( [ option, set[ i ] ] ); 9553 } 9554 }, 9555 call: function( instance, name, args, allowDisconnected ) { 9556 var i, 9557 set = instance.plugins[ name ]; 9558 9559 if ( !set ) { 9560 return; 9561 } 9562 9563 if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || 9564 instance.element[ 0 ].parentNode.nodeType === 11 ) ) { 9565 return; 9566 } 9567 9568 for ( i = 0; i < set.length; i++ ) { 9569 if ( instance.options[ set[ i ][ 0 ] ] ) { 9570 set[ i ][ 1 ].apply( instance.element, args ); 9571 } 9572 } 9573 } 9574}; 9575 9576 9577/*! 9578 * jQuery UI Draggable 1.14.0 9579 * https://jqueryui.com 9580 * 9581 * Copyright OpenJS Foundation and other contributors 9582 * Released under the MIT license. 9583 * https://jquery.org/license 9584 */ 9585 9586//>>label: Draggable 9587//>>group: Interactions 9588//>>description: Enables dragging functionality for any element. 9589//>>docs: https://api.jqueryui.com/draggable/ 9590//>>demos: https://jqueryui.com/draggable/ 9591//>>css.structure: ../../themes/base/draggable.css 9592 9593 9594$.widget( "ui.draggable", $.ui.mouse, { 9595 version: "1.14.0", 9596 widgetEventPrefix: "drag", 9597 options: { 9598 addClasses: true, 9599 appendTo: "parent", 9600 axis: false, 9601 connectToSortable: false, 9602 containment: false, 9603 cursor: "auto", 9604 cursorAt: false, 9605 grid: false, 9606 handle: false, 9607 helper: "original", 9608 iframeFix: false, 9609 opacity: false, 9610 refreshPositions: false, 9611 revert: false, 9612 revertDuration: 500, 9613 scope: "default", 9614 scroll: true, 9615 scrollSensitivity: 20, 9616 scrollSpeed: 20, 9617 snap: false, 9618 snapMode: "both", 9619 snapTolerance: 20, 9620 stack: false, 9621 zIndex: false, 9622 9623 // Callbacks 9624 drag: null, 9625 start: null, 9626 stop: null 9627 }, 9628 _create: function() { 9629 9630 if ( this.options.helper === "original" ) { 9631 this._setPositionRelative(); 9632 } 9633 if ( this.options.addClasses ) { 9634 this._addClass( "ui-draggable" ); 9635 } 9636 this._setHandleClassName(); 9637 9638 this._mouseInit(); 9639 }, 9640 9641 _setOption: function( key, value ) { 9642 this._super( key, value ); 9643 if ( key === "handle" ) { 9644 this._removeHandleClassName(); 9645 this._setHandleClassName(); 9646 } 9647 }, 9648 9649 _destroy: function() { 9650 if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) { 9651 this.destroyOnClear = true; 9652 return; 9653 } 9654 this._removeHandleClassName(); 9655 this._mouseDestroy(); 9656 }, 9657 9658 _mouseCapture: function( event ) { 9659 var o = this.options; 9660 9661 // Among others, prevent a drag on a resizable-handle 9662 if ( this.helper || o.disabled || 9663 $( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) { 9664 return false; 9665 } 9666 9667 //Quit if we're not on a valid handle 9668 this.handle = this._getHandle( event ); 9669 if ( !this.handle ) { 9670 return false; 9671 } 9672 9673 this._blurActiveElement( event ); 9674 9675 this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix ); 9676 9677 return true; 9678 9679 }, 9680 9681 _blockFrames: function( selector ) { 9682 this.iframeBlocks = this.document.find( selector ).map( function() { 9683 var iframe = $( this ); 9684 9685 return $( "<div>" ) 9686 .css( "position", "absolute" ) 9687 .appendTo( iframe.parent() ) 9688 .outerWidth( iframe.outerWidth() ) 9689 .outerHeight( iframe.outerHeight() ) 9690 .offset( iframe.offset() )[ 0 ]; 9691 } ); 9692 }, 9693 9694 _unblockFrames: function() { 9695 if ( this.iframeBlocks ) { 9696 this.iframeBlocks.remove(); 9697 delete this.iframeBlocks; 9698 } 9699 }, 9700 9701 _blurActiveElement: function( event ) { 9702 var activeElement = this.document[ 0 ].activeElement, 9703 target = $( event.target ); 9704 9705 // Don't blur if the event occurred on an element that is within 9706 // the currently focused element 9707 // See #10527, #12472 9708 if ( target.closest( activeElement ).length ) { 9709 return; 9710 } 9711 9712 // Blur any element that currently has focus, see #4261 9713 $( activeElement ).trigger( "blur" ); 9714 }, 9715 9716 _mouseStart: function( event ) { 9717 9718 var o = this.options; 9719 9720 //Create and append the visible helper 9721 this.helper = this._createHelper( event ); 9722 9723 this._addClass( this.helper, "ui-draggable-dragging" ); 9724 9725 //Cache the helper size 9726 this._cacheHelperProportions(); 9727 9728 //If ddmanager is used for droppables, set the global draggable 9729 if ( $.ui.ddmanager ) { 9730 $.ui.ddmanager.current = this; 9731 } 9732 9733 /* 9734 * - Position generation - 9735 * This block generates everything position related - it's the core of draggables. 9736 */ 9737 9738 //Cache the margins of the original element 9739 this._cacheMargins(); 9740 9741 //Store the helper's css position 9742 this.cssPosition = this.helper.css( "position" ); 9743 this.scrollParent = this.helper.scrollParent( true ); 9744 this.offsetParent = this.helper.offsetParent(); 9745 this.hasFixedAncestor = this.helper.parents().filter( function() { 9746 return $( this ).css( "position" ) === "fixed"; 9747 } ).length > 0; 9748 9749 //The element's absolute position on the page minus margins 9750 this.positionAbs = this.element.offset(); 9751 this._refreshOffsets( event ); 9752 9753 //Generate the original position 9754 this.originalPosition = this.position = this._generatePosition( event, false ); 9755 this.originalPageX = event.pageX; 9756 this.originalPageY = event.pageY; 9757 9758 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 9759 if ( o.cursorAt ) { 9760 this._adjustOffsetFromHelper( o.cursorAt ); 9761 } 9762 9763 //Set a containment if given in the options 9764 this._setContainment(); 9765 9766 //Trigger event + callbacks 9767 if ( this._trigger( "start", event ) === false ) { 9768 this._clear(); 9769 return false; 9770 } 9771 9772 //Recache the helper size 9773 this._cacheHelperProportions(); 9774 9775 //Prepare the droppable offsets 9776 if ( $.ui.ddmanager && !o.dropBehaviour ) { 9777 $.ui.ddmanager.prepareOffsets( this, event ); 9778 } 9779 9780 // Execute the drag once - this causes the helper not to be visible before getting its 9781 // correct position 9782 this._mouseDrag( event, true ); 9783 9784 // If the ddmanager is used for droppables, inform the manager that dragging has started 9785 // (see #5003) 9786 if ( $.ui.ddmanager ) { 9787 $.ui.ddmanager.dragStart( this, event ); 9788 } 9789 9790 return true; 9791 }, 9792 9793 _refreshOffsets: function( event ) { 9794 this.offset = { 9795 top: this.positionAbs.top - this.margins.top, 9796 left: this.positionAbs.left - this.margins.left, 9797 scroll: false, 9798 parent: this._getParentOffset(), 9799 relative: this._getRelativeOffset() 9800 }; 9801 9802 this.offset.click = { 9803 left: event.pageX - this.offset.left, 9804 top: event.pageY - this.offset.top 9805 }; 9806 }, 9807 9808 _mouseDrag: function( event, noPropagation ) { 9809 9810 // reset any necessary cached properties (see #5009) 9811 if ( this.hasFixedAncestor ) { 9812 this.offset.parent = this._getParentOffset(); 9813 } 9814 9815 //Compute the helpers position 9816 this.position = this._generatePosition( event, true ); 9817 this.positionAbs = this._convertPositionTo( "absolute" ); 9818 9819 //Call plugins and callbacks and use the resulting position if something is returned 9820 if ( !noPropagation ) { 9821 var ui = this._uiHash(); 9822 if ( this._trigger( "drag", event, ui ) === false ) { 9823 this._mouseUp( new $.Event( "mouseup", event ) ); 9824 return false; 9825 } 9826 this.position = ui.position; 9827 } 9828 9829 this.helper[ 0 ].style.left = this.position.left + "px"; 9830 this.helper[ 0 ].style.top = this.position.top + "px"; 9831 9832 if ( $.ui.ddmanager ) { 9833 $.ui.ddmanager.drag( this, event ); 9834 } 9835 9836 return false; 9837 }, 9838 9839 _mouseStop: function( event ) { 9840 9841 //If we are using droppables, inform the manager about the drop 9842 var that = this, 9843 dropped = false; 9844 if ( $.ui.ddmanager && !this.options.dropBehaviour ) { 9845 dropped = $.ui.ddmanager.drop( this, event ); 9846 } 9847 9848 //if a drop comes from outside (a sortable) 9849 if ( this.dropped ) { 9850 dropped = this.dropped; 9851 this.dropped = false; 9852 } 9853 9854 if ( ( this.options.revert === "invalid" && !dropped ) || 9855 ( this.options.revert === "valid" && dropped ) || 9856 this.options.revert === true || ( typeof this.options.revert === "function" && 9857 this.options.revert.call( this.element, dropped ) ) 9858 ) { 9859 $( this.helper ).animate( 9860 this.originalPosition, 9861 parseInt( this.options.revertDuration, 10 ), 9862 function() { 9863 if ( that._trigger( "stop", event ) !== false ) { 9864 that._clear(); 9865 } 9866 } 9867 ); 9868 } else { 9869 if ( this._trigger( "stop", event ) !== false ) { 9870 this._clear(); 9871 } 9872 } 9873 9874 return false; 9875 }, 9876 9877 _mouseUp: function( event ) { 9878 this._unblockFrames(); 9879 9880 // If the ddmanager is used for droppables, inform the manager that dragging has stopped 9881 // (see #5003) 9882 if ( $.ui.ddmanager ) { 9883 $.ui.ddmanager.dragStop( this, event ); 9884 } 9885 9886 // Only need to focus if the event occurred on the draggable itself, see #10527 9887 if ( this.handleElement.is( event.target ) ) { 9888 9889 // The interaction is over; whether or not the click resulted in a drag, 9890 // focus the element 9891 this.element.trigger( "focus" ); 9892 } 9893 9894 return $.ui.mouse.prototype._mouseUp.call( this, event ); 9895 }, 9896 9897 cancel: function() { 9898 9899 if ( this.helper.is( ".ui-draggable-dragging" ) ) { 9900 this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) ); 9901 } else { 9902 this._clear(); 9903 } 9904 9905 return this; 9906 9907 }, 9908 9909 _getHandle: function( event ) { 9910 return this.options.handle ? 9911 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length : 9912 true; 9913 }, 9914 9915 _setHandleClassName: function() { 9916 this.handleElement = this.options.handle ? 9917 this.element.find( this.options.handle ) : this.element; 9918 this._addClass( this.handleElement, "ui-draggable-handle" ); 9919 }, 9920 9921 _removeHandleClassName: function() { 9922 this._removeClass( this.handleElement, "ui-draggable-handle" ); 9923 }, 9924 9925 _createHelper: function( event ) { 9926 9927 var o = this.options, 9928 helperIsFunction = typeof o.helper === "function", 9929 helper = helperIsFunction ? 9930 $( o.helper.apply( this.element[ 0 ], [ event ] ) ) : 9931 ( o.helper === "clone" ? 9932 this.element.clone().removeAttr( "id" ) : 9933 this.element ); 9934 9935 if ( !helper.parents( "body" ).length ) { 9936 helper.appendTo( ( o.appendTo === "parent" ? 9937 this.element[ 0 ].parentNode : 9938 o.appendTo ) ); 9939 } 9940 9941 // https://bugs.jqueryui.com/ticket/9446 9942 // a helper function can return the original element 9943 // which wouldn't have been set to relative in _create 9944 if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) { 9945 this._setPositionRelative(); 9946 } 9947 9948 if ( helper[ 0 ] !== this.element[ 0 ] && 9949 !( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) { 9950 helper.css( "position", "absolute" ); 9951 } 9952 9953 return helper; 9954 9955 }, 9956 9957 _setPositionRelative: function() { 9958 if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) { 9959 this.element[ 0 ].style.position = "relative"; 9960 } 9961 }, 9962 9963 _adjustOffsetFromHelper: function( obj ) { 9964 if ( typeof obj === "string" ) { 9965 obj = obj.split( " " ); 9966 } 9967 if ( Array.isArray( obj ) ) { 9968 obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 }; 9969 } 9970 if ( "left" in obj ) { 9971 this.offset.click.left = obj.left + this.margins.left; 9972 } 9973 if ( "right" in obj ) { 9974 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 9975 } 9976 if ( "top" in obj ) { 9977 this.offset.click.top = obj.top + this.margins.top; 9978 } 9979 if ( "bottom" in obj ) { 9980 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 9981 } 9982 }, 9983 9984 _isRootNode: function( element ) { 9985 return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ]; 9986 }, 9987 9988 _getParentOffset: function() { 9989 9990 //Get the offsetParent and cache its position 9991 var po = this.offsetParent.offset(), 9992 document = this.document[ 0 ]; 9993 9994 // This is a special case where we need to modify a offset calculated on start, since the 9995 // following happened: 9996 // 1. The position of the helper is absolute, so it's position is calculated based on the 9997 // next positioned parent 9998 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't 9999 // the document, which means that the scroll is included in the initial calculation of the 10000 // offset of the parent, and never recalculated upon drag 10001 if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document && 10002 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) { 10003 po.left += this.scrollParent.scrollLeft(); 10004 po.top += this.scrollParent.scrollTop(); 10005 } 10006 10007 if ( this._isRootNode( this.offsetParent[ 0 ] ) ) { 10008 po = { top: 0, left: 0 }; 10009 } 10010 10011 return { 10012 top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ), 10013 left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 ) 10014 }; 10015 10016 }, 10017 10018 _getRelativeOffset: function() { 10019 if ( this.cssPosition !== "relative" ) { 10020 return { top: 0, left: 0 }; 10021 } 10022 10023 var p = this.element.position(), 10024 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ); 10025 10026 return { 10027 top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) + 10028 ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ), 10029 left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) + 10030 ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 ) 10031 }; 10032 10033 }, 10034 10035 _cacheMargins: function() { 10036 this.margins = { 10037 left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ), 10038 top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ), 10039 right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ), 10040 bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 ) 10041 }; 10042 }, 10043 10044 _cacheHelperProportions: function() { 10045 this.helperProportions = { 10046 width: this.helper.outerWidth(), 10047 height: this.helper.outerHeight() 10048 }; 10049 }, 10050 10051 _setContainment: function() { 10052 10053 var isUserScrollable, c, ce, 10054 o = this.options, 10055 document = this.document[ 0 ]; 10056 10057 this.relativeContainer = null; 10058 10059 if ( !o.containment ) { 10060 this.containment = null; 10061 return; 10062 } 10063 10064 if ( o.containment === "window" ) { 10065 this.containment = [ 10066 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left, 10067 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top, 10068 $( window ).scrollLeft() + $( window ).width() - 10069 this.helperProportions.width - this.margins.left, 10070 $( window ).scrollTop() + 10071 ( $( window ).height() || document.body.parentNode.scrollHeight ) - 10072 this.helperProportions.height - this.margins.top 10073 ]; 10074 return; 10075 } 10076 10077 if ( o.containment === "document" ) { 10078 this.containment = [ 10079 0, 10080 0, 10081 $( document ).width() - this.helperProportions.width - this.margins.left, 10082 ( $( document ).height() || document.body.parentNode.scrollHeight ) - 10083 this.helperProportions.height - this.margins.top 10084 ]; 10085 return; 10086 } 10087 10088 if ( o.containment.constructor === Array ) { 10089 this.containment = o.containment; 10090 return; 10091 } 10092 10093 if ( o.containment === "parent" ) { 10094 o.containment = this.helper[ 0 ].parentNode; 10095 } 10096 10097 c = $( o.containment ); 10098 ce = c[ 0 ]; 10099 10100 if ( !ce ) { 10101 return; 10102 } 10103 10104 isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) ); 10105 10106 this.containment = [ 10107 ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + 10108 ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ), 10109 ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + 10110 ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ), 10111 ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - 10112 ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - 10113 ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - 10114 this.helperProportions.width - 10115 this.margins.left - 10116 this.margins.right, 10117 ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - 10118 ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - 10119 ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - 10120 this.helperProportions.height - 10121 this.margins.top - 10122 this.margins.bottom 10123 ]; 10124 this.relativeContainer = c; 10125 }, 10126 10127 _convertPositionTo: function( d, pos ) { 10128 10129 if ( !pos ) { 10130 pos = this.position; 10131 } 10132 10133 var mod = d === "absolute" ? 1 : -1, 10134 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ); 10135 10136 return { 10137 top: ( 10138 10139 // The absolute mouse position 10140 pos.top + 10141 10142 // Only for relative positioned nodes: Relative offset from element to offset parent 10143 this.offset.relative.top * mod + 10144 10145 // The offsetParent's offset without borders (offset + border) 10146 this.offset.parent.top * mod - 10147 ( ( this.cssPosition === "fixed" ? 10148 -this.offset.scroll.top : 10149 ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod ) 10150 ), 10151 left: ( 10152 10153 // The absolute mouse position 10154 pos.left + 10155 10156 // Only for relative positioned nodes: Relative offset from element to offset parent 10157 this.offset.relative.left * mod + 10158 10159 // The offsetParent's offset without borders (offset + border) 10160 this.offset.parent.left * mod - 10161 ( ( this.cssPosition === "fixed" ? 10162 -this.offset.scroll.left : 10163 ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod ) 10164 ) 10165 }; 10166 10167 }, 10168 10169 _generatePosition: function( event, constrainPosition ) { 10170 10171 var containment, co, top, left, 10172 o = this.options, 10173 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ), 10174 pageX = event.pageX, 10175 pageY = event.pageY; 10176 10177 // Cache the scroll 10178 if ( !scrollIsRootNode || !this.offset.scroll ) { 10179 this.offset.scroll = { 10180 top: this.scrollParent.scrollTop(), 10181 left: this.scrollParent.scrollLeft() 10182 }; 10183 } 10184 10185 /* 10186 * - Position constraining - 10187 * Constrain the position to a mix of grid, containment. 10188 */ 10189 10190 // If we are not dragging yet, we won't check for options 10191 if ( constrainPosition ) { 10192 if ( this.containment ) { 10193 if ( this.relativeContainer ) { 10194 co = this.relativeContainer.offset(); 10195 containment = [ 10196 this.containment[ 0 ] + co.left, 10197 this.containment[ 1 ] + co.top, 10198 this.containment[ 2 ] + co.left, 10199 this.containment[ 3 ] + co.top 10200 ]; 10201 } else { 10202 containment = this.containment; 10203 } 10204 10205 if ( event.pageX - this.offset.click.left < containment[ 0 ] ) { 10206 pageX = containment[ 0 ] + this.offset.click.left; 10207 } 10208 if ( event.pageY - this.offset.click.top < containment[ 1 ] ) { 10209 pageY = containment[ 1 ] + this.offset.click.top; 10210 } 10211 if ( event.pageX - this.offset.click.left > containment[ 2 ] ) { 10212 pageX = containment[ 2 ] + this.offset.click.left; 10213 } 10214 if ( event.pageY - this.offset.click.top > containment[ 3 ] ) { 10215 pageY = containment[ 3 ] + this.offset.click.top; 10216 } 10217 } 10218 10219 if ( o.grid ) { 10220 10221 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid 10222 // argument errors in IE (see ticket #6950) 10223 top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY - 10224 this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY; 10225 pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] || 10226 top - this.offset.click.top > containment[ 3 ] ) ? 10227 top : 10228 ( ( top - this.offset.click.top >= containment[ 1 ] ) ? 10229 top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top; 10230 10231 left = o.grid[ 0 ] ? this.originalPageX + 10232 Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] : 10233 this.originalPageX; 10234 pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] || 10235 left - this.offset.click.left > containment[ 2 ] ) ? 10236 left : 10237 ( ( left - this.offset.click.left >= containment[ 0 ] ) ? 10238 left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left; 10239 } 10240 10241 if ( o.axis === "y" ) { 10242 pageX = this.originalPageX; 10243 } 10244 10245 if ( o.axis === "x" ) { 10246 pageY = this.originalPageY; 10247 } 10248 } 10249 10250 return { 10251 top: ( 10252 10253 // The absolute mouse position 10254 pageY - 10255 10256 // Click offset (relative to the element) 10257 this.offset.click.top - 10258 10259 // Only for relative positioned nodes: Relative offset from element to offset parent 10260 this.offset.relative.top - 10261 10262 // The offsetParent's offset without borders (offset + border) 10263 this.offset.parent.top + 10264 ( this.cssPosition === "fixed" ? 10265 -this.offset.scroll.top : 10266 ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) 10267 ), 10268 left: ( 10269 10270 // The absolute mouse position 10271 pageX - 10272 10273 // Click offset (relative to the element) 10274 this.offset.click.left - 10275 10276 // Only for relative positioned nodes: Relative offset from element to offset parent 10277 this.offset.relative.left - 10278 10279 // The offsetParent's offset without borders (offset + border) 10280 this.offset.parent.left + 10281 ( this.cssPosition === "fixed" ? 10282 -this.offset.scroll.left : 10283 ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) 10284 ) 10285 }; 10286 10287 }, 10288 10289 _clear: function() { 10290 this._removeClass( this.helper, "ui-draggable-dragging" ); 10291 if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) { 10292 this.helper.remove(); 10293 } 10294 this.helper = null; 10295 this.cancelHelperRemoval = false; 10296 if ( this.destroyOnClear ) { 10297 this.destroy(); 10298 } 10299 }, 10300 10301 // From now on bulk stuff - mainly helpers 10302 10303 _trigger: function( type, event, ui ) { 10304 ui = ui || this._uiHash(); 10305 $.ui.plugin.call( this, type, [ event, ui, this ], true ); 10306 10307 // Absolute position and offset (see #6884 ) have to be recalculated after plugins 10308 if ( /^(drag|start|stop)/.test( type ) ) { 10309 this.positionAbs = this._convertPositionTo( "absolute" ); 10310 ui.offset = this.positionAbs; 10311 } 10312 return $.Widget.prototype._trigger.call( this, type, event, ui ); 10313 }, 10314 10315 plugins: {}, 10316 10317 _uiHash: function() { 10318 return { 10319 helper: this.helper, 10320 position: this.position, 10321 originalPosition: this.originalPosition, 10322 offset: this.positionAbs 10323 }; 10324 } 10325 10326} ); 10327 10328$.ui.plugin.add( "draggable", "connectToSortable", { 10329 start: function( event, ui, draggable ) { 10330 var uiSortable = $.extend( {}, ui, { 10331 item: draggable.element 10332 } ); 10333 10334 draggable.sortables = []; 10335 $( draggable.options.connectToSortable ).each( function() { 10336 var sortable = $( this ).sortable( "instance" ); 10337 10338 if ( sortable && !sortable.options.disabled ) { 10339 draggable.sortables.push( sortable ); 10340 10341 // RefreshPositions is called at drag start to refresh the containerCache 10342 // which is used in drag. This ensures it's initialized and synchronized 10343 // with any changes that might have happened on the page since initialization. 10344 sortable.refreshPositions(); 10345 sortable._trigger( "activate", event, uiSortable ); 10346 } 10347 } ); 10348 }, 10349 stop: function( event, ui, draggable ) { 10350 var uiSortable = $.extend( {}, ui, { 10351 item: draggable.element 10352 } ); 10353 10354 draggable.cancelHelperRemoval = false; 10355 10356 $.each( draggable.sortables, function() { 10357 var sortable = this; 10358 10359 if ( sortable.isOver ) { 10360 sortable.isOver = 0; 10361 10362 // Allow this sortable to handle removing the helper 10363 draggable.cancelHelperRemoval = true; 10364 sortable.cancelHelperRemoval = false; 10365 10366 // Use _storedCSS To restore properties in the sortable, 10367 // as this also handles revert (#9675) since the draggable 10368 // may have modified them in unexpected ways (#8809) 10369 sortable._storedCSS = { 10370 position: sortable.placeholder.css( "position" ), 10371 top: sortable.placeholder.css( "top" ), 10372 left: sortable.placeholder.css( "left" ) 10373 }; 10374 10375 sortable._mouseStop( event ); 10376 10377 // Once drag has ended, the sortable should return to using 10378 // its original helper, not the shared helper from draggable 10379 sortable.options.helper = sortable.options._helper; 10380 } else { 10381 10382 // Prevent this Sortable from removing the helper. 10383 // However, don't set the draggable to remove the helper 10384 // either as another connected Sortable may yet handle the removal. 10385 sortable.cancelHelperRemoval = true; 10386 10387 sortable._trigger( "deactivate", event, uiSortable ); 10388 } 10389 } ); 10390 }, 10391 drag: function( event, ui, draggable ) { 10392 $.each( draggable.sortables, function() { 10393 var innermostIntersecting = false, 10394 sortable = this; 10395 10396 // Copy over variables that sortable's _intersectsWith uses 10397 sortable.positionAbs = draggable.positionAbs; 10398 sortable.helperProportions = draggable.helperProportions; 10399 sortable.offset.click = draggable.offset.click; 10400 10401 if ( sortable._intersectsWith( sortable.containerCache ) ) { 10402 innermostIntersecting = true; 10403 10404 $.each( draggable.sortables, function() { 10405 10406 // Copy over variables that sortable's _intersectsWith uses 10407 this.positionAbs = draggable.positionAbs; 10408 this.helperProportions = draggable.helperProportions; 10409 this.offset.click = draggable.offset.click; 10410 10411 if ( this !== sortable && 10412 this._intersectsWith( this.containerCache ) && 10413 $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) { 10414 innermostIntersecting = false; 10415 } 10416 10417 return innermostIntersecting; 10418 } ); 10419 } 10420 10421 if ( innermostIntersecting ) { 10422 10423 // If it intersects, we use a little isOver variable and set it once, 10424 // so that the move-in stuff gets fired only once. 10425 if ( !sortable.isOver ) { 10426 sortable.isOver = 1; 10427 10428 // Store draggable's parent in case we need to reappend to it later. 10429 draggable._parent = ui.helper.parent(); 10430 10431 sortable.currentItem = ui.helper 10432 .appendTo( sortable.element ) 10433 .data( "ui-sortable-item", true ); 10434 10435 // Store helper option to later restore it 10436 sortable.options._helper = sortable.options.helper; 10437 10438 sortable.options.helper = function() { 10439 return ui.helper[ 0 ]; 10440 }; 10441 10442 // Fire the start events of the sortable with our passed browser event, 10443 // and our own helper (so it doesn't create a new one) 10444 event.target = sortable.currentItem[ 0 ]; 10445 sortable._mouseCapture( event, true ); 10446 sortable._mouseStart( event, true, true ); 10447 10448 // Because the browser event is way off the new appended portlet, 10449 // modify necessary variables to reflect the changes 10450 sortable.offset.click.top = draggable.offset.click.top; 10451 sortable.offset.click.left = draggable.offset.click.left; 10452 sortable.offset.parent.left -= draggable.offset.parent.left - 10453 sortable.offset.parent.left; 10454 sortable.offset.parent.top -= draggable.offset.parent.top - 10455 sortable.offset.parent.top; 10456 10457 draggable._trigger( "toSortable", event ); 10458 10459 // Inform draggable that the helper is in a valid drop zone, 10460 // used solely in the revert option to handle "valid/invalid". 10461 draggable.dropped = sortable.element; 10462 10463 // Need to refreshPositions of all sortables in the case that 10464 // adding to one sortable changes the location of the other sortables (#9675) 10465 $.each( draggable.sortables, function() { 10466 this.refreshPositions(); 10467 } ); 10468 10469 // Hack so receive/update callbacks work (mostly) 10470 draggable.currentItem = draggable.element; 10471 sortable.fromOutside = draggable; 10472 } 10473 10474 if ( sortable.currentItem ) { 10475 sortable._mouseDrag( event ); 10476 10477 // Copy the sortable's position because the draggable's can potentially reflect 10478 // a relative position, while sortable is always absolute, which the dragged 10479 // element has now become. (#8809) 10480 ui.position = sortable.position; 10481 } 10482 } else { 10483 10484 // If it doesn't intersect with the sortable, and it intersected before, 10485 // we fake the drag stop of the sortable, but make sure it doesn't remove 10486 // the helper by using cancelHelperRemoval. 10487 if ( sortable.isOver ) { 10488 10489 sortable.isOver = 0; 10490 sortable.cancelHelperRemoval = true; 10491 10492 // Calling sortable's mouseStop would trigger a revert, 10493 // so revert must be temporarily false until after mouseStop is called. 10494 sortable.options._revert = sortable.options.revert; 10495 sortable.options.revert = false; 10496 10497 sortable._trigger( "out", event, sortable._uiHash( sortable ) ); 10498 sortable._mouseStop( event, true ); 10499 10500 // Restore sortable behaviors that were modfied 10501 // when the draggable entered the sortable area (#9481) 10502 sortable.options.revert = sortable.options._revert; 10503 sortable.options.helper = sortable.options._helper; 10504 10505 if ( sortable.placeholder ) { 10506 sortable.placeholder.remove(); 10507 } 10508 10509 // Restore and recalculate the draggable's offset considering the sortable 10510 // may have modified them in unexpected ways. (#8809, #10669) 10511 ui.helper.appendTo( draggable._parent ); 10512 draggable._refreshOffsets( event ); 10513 ui.position = draggable._generatePosition( event, true ); 10514 10515 draggable._trigger( "fromSortable", event ); 10516 10517 // Inform draggable that the helper is no longer in a valid drop zone 10518 draggable.dropped = false; 10519 10520 // Need to refreshPositions of all sortables just in case removing 10521 // from one sortable changes the location of other sortables (#9675) 10522 $.each( draggable.sortables, function() { 10523 this.refreshPositions(); 10524 } ); 10525 } 10526 } 10527 } ); 10528 } 10529} ); 10530 10531$.ui.plugin.add( "draggable", "cursor", { 10532 start: function( event, ui, instance ) { 10533 var t = $( "body" ), 10534 o = instance.options; 10535 10536 if ( t.css( "cursor" ) ) { 10537 o._cursor = t.css( "cursor" ); 10538 } 10539 t.css( "cursor", o.cursor ); 10540 }, 10541 stop: function( event, ui, instance ) { 10542 var o = instance.options; 10543 if ( o._cursor ) { 10544 $( "body" ).css( "cursor", o._cursor ); 10545 } 10546 } 10547} ); 10548 10549$.ui.plugin.add( "draggable", "opacity", { 10550 start: function( event, ui, instance ) { 10551 var t = $( ui.helper ), 10552 o = instance.options; 10553 if ( t.css( "opacity" ) ) { 10554 o._opacity = t.css( "opacity" ); 10555 } 10556 t.css( "opacity", o.opacity ); 10557 }, 10558 stop: function( event, ui, instance ) { 10559 var o = instance.options; 10560 if ( o._opacity ) { 10561 $( ui.helper ).css( "opacity", o._opacity ); 10562 } 10563 } 10564} ); 10565 10566$.ui.plugin.add( "draggable", "scroll", { 10567 start: function( event, ui, i ) { 10568 if ( !i.scrollParentNotHidden ) { 10569 i.scrollParentNotHidden = i.helper.scrollParent( false ); 10570 } 10571 10572 if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] && 10573 i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) { 10574 i.overflowOffset = i.scrollParentNotHidden.offset(); 10575 } 10576 }, 10577 drag: function( event, ui, i ) { 10578 10579 var o = i.options, 10580 scrolled = false, 10581 scrollParent = i.scrollParentNotHidden[ 0 ], 10582 document = i.document[ 0 ]; 10583 10584 if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) { 10585 if ( !o.axis || o.axis !== "x" ) { 10586 if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY < 10587 o.scrollSensitivity ) { 10588 scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed; 10589 } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) { 10590 scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed; 10591 } 10592 } 10593 10594 if ( !o.axis || o.axis !== "y" ) { 10595 if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX < 10596 o.scrollSensitivity ) { 10597 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed; 10598 } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) { 10599 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed; 10600 } 10601 } 10602 10603 } else { 10604 10605 if ( !o.axis || o.axis !== "x" ) { 10606 if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) { 10607 scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed ); 10608 } else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) < 10609 o.scrollSensitivity ) { 10610 scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed ); 10611 } 10612 } 10613 10614 if ( !o.axis || o.axis !== "y" ) { 10615 if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) { 10616 scrolled = $( document ).scrollLeft( 10617 $( document ).scrollLeft() - o.scrollSpeed 10618 ); 10619 } else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) < 10620 o.scrollSensitivity ) { 10621 scrolled = $( document ).scrollLeft( 10622 $( document ).scrollLeft() + o.scrollSpeed 10623 ); 10624 } 10625 } 10626 10627 } 10628 10629 if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) { 10630 $.ui.ddmanager.prepareOffsets( i, event ); 10631 } 10632 10633 } 10634} ); 10635 10636$.ui.plugin.add( "draggable", "snap", { 10637 start: function( event, ui, i ) { 10638 10639 var o = i.options; 10640 10641 i.snapElements = []; 10642 10643 $( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap ) 10644 .each( function() { 10645 var $t = $( this ), 10646 $o = $t.offset(); 10647 if ( this !== i.element[ 0 ] ) { 10648 i.snapElements.push( { 10649 item: this, 10650 width: $t.outerWidth(), height: $t.outerHeight(), 10651 top: $o.top, left: $o.left 10652 } ); 10653 } 10654 } ); 10655 10656 }, 10657 drag: function( event, ui, inst ) { 10658 10659 var ts, bs, ls, rs, l, r, t, b, i, first, 10660 o = inst.options, 10661 d = o.snapTolerance, 10662 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, 10663 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; 10664 10665 for ( i = inst.snapElements.length - 1; i >= 0; i-- ) { 10666 10667 l = inst.snapElements[ i ].left - inst.margins.left; 10668 r = l + inst.snapElements[ i ].width; 10669 t = inst.snapElements[ i ].top - inst.margins.top; 10670 b = t + inst.snapElements[ i ].height; 10671 10672 if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || 10673 !$.contains( inst.snapElements[ i ].item.ownerDocument, 10674 inst.snapElements[ i ].item ) ) { 10675 if ( inst.snapElements[ i ].snapping ) { 10676 if ( inst.options.snap.release ) { 10677 inst.options.snap.release.call( 10678 inst.element, 10679 event, 10680 $.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } ) 10681 ); 10682 } 10683 } 10684 inst.snapElements[ i ].snapping = false; 10685 continue; 10686 } 10687 10688 if ( o.snapMode !== "inner" ) { 10689 ts = Math.abs( t - y2 ) <= d; 10690 bs = Math.abs( b - y1 ) <= d; 10691 ls = Math.abs( l - x2 ) <= d; 10692 rs = Math.abs( r - x1 ) <= d; 10693 if ( ts ) { 10694 ui.position.top = inst._convertPositionTo( "relative", { 10695 top: t - inst.helperProportions.height, 10696 left: 0 10697 } ).top; 10698 } 10699 if ( bs ) { 10700 ui.position.top = inst._convertPositionTo( "relative", { 10701 top: b, 10702 left: 0 10703 } ).top; 10704 } 10705 if ( ls ) { 10706 ui.position.left = inst._convertPositionTo( "relative", { 10707 top: 0, 10708 left: l - inst.helperProportions.width 10709 } ).left; 10710 } 10711 if ( rs ) { 10712 ui.position.left = inst._convertPositionTo( "relative", { 10713 top: 0, 10714 left: r 10715 } ).left; 10716 } 10717 } 10718 10719 first = ( ts || bs || ls || rs ); 10720 10721 if ( o.snapMode !== "outer" ) { 10722 ts = Math.abs( t - y1 ) <= d; 10723 bs = Math.abs( b - y2 ) <= d; 10724 ls = Math.abs( l - x1 ) <= d; 10725 rs = Math.abs( r - x2 ) <= d; 10726 if ( ts ) { 10727 ui.position.top = inst._convertPositionTo( "relative", { 10728 top: t, 10729 left: 0 10730 } ).top; 10731 } 10732 if ( bs ) { 10733 ui.position.top = inst._convertPositionTo( "relative", { 10734 top: b - inst.helperProportions.height, 10735 left: 0 10736 } ).top; 10737 } 10738 if ( ls ) { 10739 ui.position.left = inst._convertPositionTo( "relative", { 10740 top: 0, 10741 left: l 10742 } ).left; 10743 } 10744 if ( rs ) { 10745 ui.position.left = inst._convertPositionTo( "relative", { 10746 top: 0, 10747 left: r - inst.helperProportions.width 10748 } ).left; 10749 } 10750 } 10751 10752 if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) { 10753 if ( inst.options.snap.snap ) { 10754 inst.options.snap.snap.call( 10755 inst.element, 10756 event, 10757 $.extend( inst._uiHash(), { 10758 snapItem: inst.snapElements[ i ].item 10759 } ) ); 10760 } 10761 } 10762 inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first ); 10763 10764 } 10765 10766 } 10767} ); 10768 10769$.ui.plugin.add( "draggable", "stack", { 10770 start: function( event, ui, instance ) { 10771 var min, 10772 o = instance.options, 10773 group = $.makeArray( $( o.stack ) ).sort( function( a, b ) { 10774 return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) - 10775 ( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 ); 10776 } ); 10777 10778 if ( !group.length ) { 10779 return; 10780 } 10781 10782 min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0; 10783 $( group ).each( function( i ) { 10784 $( this ).css( "zIndex", min + i ); 10785 } ); 10786 this.css( "zIndex", ( min + group.length ) ); 10787 } 10788} ); 10789 10790$.ui.plugin.add( "draggable", "zIndex", { 10791 start: function( event, ui, instance ) { 10792 var t = $( ui.helper ), 10793 o = instance.options; 10794 10795 if ( t.css( "zIndex" ) ) { 10796 o._zIndex = t.css( "zIndex" ); 10797 } 10798 t.css( "zIndex", o.zIndex ); 10799 }, 10800 stop: function( event, ui, instance ) { 10801 var o = instance.options; 10802 10803 if ( o._zIndex ) { 10804 $( ui.helper ).css( "zIndex", o._zIndex ); 10805 } 10806 } 10807} ); 10808 10809var widgetsDraggable = $.ui.draggable; 10810 10811 10812/*! 10813 * jQuery UI Resizable 1.14.0 10814 * https://jqueryui.com
vendor: 18,093 bytes, lines 10815-11525
10815 * 10816 * Copyright OpenJS Foundation and other contributors 10817 * Released under the MIT license. 10818 * https://jquery.org/license 10819 */ 10820 10821//>>label: Resizable 10822//>>group: Interactions 10823//>>description: Enables resize functionality for any element. 10824//>>docs: https://api.jqueryui.com/resizable/ 10825//>>demos: https://jqueryui.com/resizable/ 10826//>>css.structure: ../../themes/base/core.css 10827//>>css.structure: ../../themes/base/resizable.css 10828//>>css.theme: ../../themes/base/theme.css 10829 10830 10831$.widget( "ui.resizable", $.ui.mouse, { 10832 version: "1.14.0", 10833 widgetEventPrefix: "resize", 10834 options: { 10835 alsoResize: false, 10836 animate: false, 10837 animateDuration: "slow", 10838 animateEasing: "swing", 10839 aspectRatio: false, 10840 autoHide: false, 10841 classes: { 10842 "ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se" 10843 }, 10844 containment: false, 10845 ghost: false, 10846 grid: false, 10847 handles: "e,s,se", 10848 helper: false, 10849 maxHeight: null, 10850 maxWidth: null, 10851 minHeight: 10, 10852 minWidth: 10, 10853 10854 // See #7960 10855 zIndex: 90, 10856 10857 // Callbacks 10858 resize: null, 10859 start: null, 10860 stop: null 10861 }, 10862 10863 _num: function( value ) { 10864 return parseFloat( value ) || 0; 10865 }, 10866 10867 _isNumber: function( value ) { 10868 return !isNaN( parseFloat( value ) ); 10869 }, 10870 10871 _hasScroll: function( el, a ) { 10872 10873 if ( $( el ).css( "overflow" ) === "hidden" ) { 10874 return false; 10875 } 10876 10877 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", 10878 has = false; 10879 10880 if ( el[ scroll ] > 0 ) { 10881 return true; 10882 } 10883 10884 // TODO: determine which cases actually cause this to happen 10885 // if the element doesn't have the scroll set, see if it's possible to 10886 // set the scroll 10887 try { 10888 el[ scroll ] = 1; 10889 has = ( el[ scroll ] > 0 ); 10890 el[ scroll ] = 0; 10891 } catch ( e ) { 10892 10893 // `el` might be a string, then setting `scroll` will throw 10894 // an error in strict mode; ignore it. 10895 } 10896 return has; 10897 }, 10898 10899 _create: function() { 10900 10901 var margins, 10902 o = this.options, 10903 that = this; 10904 this._addClass( "ui-resizable" ); 10905 10906 $.extend( this, { 10907 _aspectRatio: !!( o.aspectRatio ), 10908 aspectRatio: o.aspectRatio, 10909 originalElement: this.element, 10910 _proportionallyResizeElements: [], 10911 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null 10912 } ); 10913 10914 // Wrap the element if it cannot hold child nodes 10915 if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) { 10916 10917 this.element.wrap( 10918 $( "<div class='ui-wrapper'></div>" ).css( { 10919 overflow: "hidden", 10920 position: this.element.css( "position" ), 10921 width: this.element.outerWidth(), 10922 height: this.element.outerHeight(), 10923 top: this.element.css( "top" ), 10924 left: this.element.css( "left" ) 10925 } ) 10926 ); 10927 10928 this.element = this.element.parent().data( 10929 "ui-resizable", this.element.resizable( "instance" ) 10930 ); 10931 10932 this.elementIsWrapper = true; 10933 10934 margins = { 10935 marginTop: this.originalElement.css( "marginTop" ), 10936 marginRight: this.originalElement.css( "marginRight" ), 10937 marginBottom: this.originalElement.css( "marginBottom" ), 10938 marginLeft: this.originalElement.css( "marginLeft" ) 10939 }; 10940 10941 this.element.css( margins ); 10942 10943 // Support: Safari 10944 // Prevent Safari textarea resize 10945 this.originalResizeStyle = this.originalElement.css( "resize" ); 10946 this.originalElement.css( "resize", "none" ); 10947 10948 this._proportionallyResizeElements.push( this.originalElement.css( { 10949 position: "static", 10950 zoom: 1, 10951 display: "block" 10952 } ) ); 10953 10954 this._proportionallyResize(); 10955 } 10956 10957 this._setupHandles(); 10958 10959 if ( o.autoHide ) { 10960 $( this.element ) 10961 .on( "mouseenter", function() { 10962 if ( o.disabled ) { 10963 return; 10964 } 10965 that._removeClass( "ui-resizable-autohide" ); 10966 that._handles.show(); 10967 } ) 10968 .on( "mouseleave", function() { 10969 if ( o.disabled ) { 10970 return; 10971 } 10972 if ( !that.resizing ) { 10973 that._addClass( "ui-resizable-autohide" ); 10974 that._handles.hide(); 10975 } 10976 } ); 10977 } 10978 10979 this._mouseInit(); 10980 }, 10981 10982 _destroy: function() { 10983 10984 this._mouseDestroy(); 10985 this._addedHandles.remove(); 10986 10987 var wrapper, 10988 _destroy = function( exp ) { 10989 $( exp ) 10990 .removeData( "resizable" ) 10991 .removeData( "ui-resizable" ) 10992 .off( ".resizable" ); 10993 }; 10994 10995 // TODO: Unwrap at same DOM position 10996 if ( this.elementIsWrapper ) { 10997 _destroy( this.element ); 10998 wrapper = this.element; 10999 this.originalElement.css( { 11000 position: wrapper.css( "position" ), 11001 width: wrapper.outerWidth(), 11002 height: wrapper.outerHeight(), 11003 top: wrapper.css( "top" ), 11004 left: wrapper.css( "left" ) 11005 } ).insertAfter( wrapper ); 11006 wrapper.remove(); 11007 } 11008 11009 this.originalElement.css( "resize", this.originalResizeStyle ); 11010 _destroy( this.originalElement ); 11011 11012 return this; 11013 }, 11014 11015 _setOption: function( key, value ) { 11016 this._super( key, value ); 11017 11018 switch ( key ) { 11019 case "handles": 11020 this._removeHandles(); 11021 this._setupHandles(); 11022 break; 11023 case "aspectRatio": 11024 this._aspectRatio = !!value; 11025 break; 11026 default: 11027 break; 11028 } 11029 }, 11030 11031 _setupHandles: function() { 11032 var o = this.options, handle, i, n, hname, axis, that = this; 11033 this.handles = o.handles || 11034 ( !$( ".ui-resizable-handle", this.element ).length ? 11035 "e,s,se" : { 11036 n: ".ui-resizable-n", 11037 e: ".ui-resizable-e", 11038 s: ".ui-resizable-s", 11039 w: ".ui-resizable-w", 11040 se: ".ui-resizable-se", 11041 sw: ".ui-resizable-sw", 11042 ne: ".ui-resizable-ne", 11043 nw: ".ui-resizable-nw" 11044 } ); 11045 11046 this._handles = $(); 11047 this._addedHandles = $(); 11048 if ( this.handles.constructor === String ) { 11049 11050 if ( this.handles === "all" ) { 11051 this.handles = "n,e,s,w,se,sw,ne,nw"; 11052 } 11053 11054 n = this.handles.split( "," ); 11055 this.handles = {}; 11056 11057 for ( i = 0; i < n.length; i++ ) { 11058 11059 handle = String.prototype.trim.call( n[ i ] ); 11060 hname = "ui-resizable-" + handle; 11061 axis = $( "<div>" ); 11062 this._addClass( axis, "ui-resizable-handle " + hname ); 11063 11064 axis.css( { zIndex: o.zIndex } ); 11065 11066 this.handles[ handle ] = ".ui-resizable-" + handle; 11067 if ( !this.element.children( this.handles[ handle ] ).length ) { 11068 this.element.append( axis ); 11069 this._addedHandles = this._addedHandles.add( axis ); 11070 } 11071 } 11072 11073 } 11074 11075 this._renderAxis = function( target ) { 11076 11077 var i, axis, padPos, padWrapper; 11078 11079 target = target || this.element; 11080 11081 for ( i in this.handles ) { 11082 11083 if ( this.handles[ i ].constructor === String ) { 11084 this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show(); 11085 } else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) { 11086 this.handles[ i ] = $( this.handles[ i ] ); 11087 this._on( this.handles[ i ], { "mousedown": that._mouseDown } ); 11088 } 11089 11090 if ( this.elementIsWrapper && 11091 this.originalElement[ 0 ] 11092 .nodeName 11093 .match( /^(textarea|input|select|button)$/i ) ) { 11094 axis = $( this.handles[ i ], this.element ); 11095 11096 padWrapper = /sw|ne|nw|se|n|s/.test( i ) ? 11097 axis.outerHeight() : 11098 axis.outerWidth(); 11099 11100 padPos = [ "padding", 11101 /ne|nw|n/.test( i ) ? "Top" : 11102 /se|sw|s/.test( i ) ? "Bottom" : 11103 /^e$/.test( i ) ? "Right" : "Left" ].join( "" ); 11104 11105 target.css( padPos, padWrapper ); 11106 11107 this._proportionallyResize(); 11108 } 11109 11110 this._handles = this._handles.add( this.handles[ i ] ); 11111 } 11112 }; 11113 11114 // TODO: make renderAxis a prototype function 11115 this._renderAxis( this.element ); 11116 11117 this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) ); 11118 this._handles.disableSelection(); 11119 11120 this._handles.on( "mouseover", function() { 11121 if ( !that.resizing ) { 11122 if ( this.className ) { 11123 axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i ); 11124 } 11125 that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se"; 11126 } 11127 } ); 11128 11129 if ( o.autoHide ) { 11130 this._handles.hide(); 11131 this._addClass( "ui-resizable-autohide" ); 11132 } 11133 }, 11134 11135 _removeHandles: function() { 11136 this._addedHandles.remove(); 11137 }, 11138 11139 _mouseCapture: function( event ) { 11140 var i, handle, 11141 capture = false; 11142 11143 for ( i in this.handles ) { 11144 handle = $( this.handles[ i ] )[ 0 ]; 11145 if ( handle === event.target || $.contains( handle, event.target ) ) { 11146 capture = true; 11147 } 11148 } 11149 11150 return !this.options.disabled && capture; 11151 }, 11152 11153 _mouseStart: function( event ) { 11154 11155 var curleft, curtop, cursor, 11156 o = this.options, 11157 el = this.element; 11158 11159 this.resizing = true; 11160 11161 this._renderProxy(); 11162 11163 curleft = this._num( this.helper.css( "left" ) ); 11164 curtop = this._num( this.helper.css( "top" ) ); 11165 11166 if ( o.containment ) { 11167 curleft += $( o.containment ).scrollLeft() || 0; 11168 curtop += $( o.containment ).scrollTop() || 0; 11169 } 11170 11171 this.offset = this.helper.offset(); 11172 this.position = { left: curleft, top: curtop }; 11173 11174 this.size = this._helper ? { 11175 width: this.helper.width(), 11176 height: this.helper.height() 11177 } : { 11178 width: el.width(), 11179 height: el.height() 11180 }; 11181 11182 this.originalSize = this._helper ? { 11183 width: el.outerWidth(), 11184 height: el.outerHeight() 11185 } : { 11186 width: el.width(), 11187 height: el.height() 11188 }; 11189 11190 this.sizeDiff = { 11191 width: el.outerWidth() - el.width(), 11192 height: el.outerHeight() - el.height() 11193 }; 11194 11195 this.originalPosition = { left: curleft, top: curtop }; 11196 this.originalMousePosition = { left: event.pageX, top: event.pageY }; 11197 11198 this.aspectRatio = ( typeof o.aspectRatio === "number" ) ? 11199 o.aspectRatio : 11200 ( ( this.originalSize.width / this.originalSize.height ) || 1 ); 11201 11202 cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" ); 11203 $( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor ); 11204 11205 this._addClass( "ui-resizable-resizing" ); 11206 this._propagate( "start", event ); 11207 return true; 11208 }, 11209 11210 _mouseDrag: function( event ) { 11211 11212 var data, props, 11213 smp = this.originalMousePosition, 11214 a = this.axis, 11215 dx = ( event.pageX - smp.left ) || 0, 11216 dy = ( event.pageY - smp.top ) || 0, 11217 trigger = this._change[ a ]; 11218 11219 this._updatePrevProperties(); 11220 11221 if ( !trigger ) { 11222 return false; 11223 } 11224 11225 data = trigger.apply( this, [ event, dx, dy ] ); 11226 11227 this._updateVirtualBoundaries( event.shiftKey ); 11228 if ( this._aspectRatio || event.shiftKey ) { 11229 data = this._updateRatio( data, event ); 11230 } 11231 11232 data = this._respectSize( data, event ); 11233 11234 this._updateCache( data ); 11235 11236 this._propagate( "resize", event ); 11237 11238 props = this._applyChanges(); 11239 11240 if ( !this._helper && this._proportionallyResizeElements.length ) { 11241 this._proportionallyResize(); 11242 } 11243 11244 if ( !$.isEmptyObject( props ) ) { 11245 this._updatePrevProperties(); 11246 this._trigger( "resize", event, this.ui() ); 11247 this._applyChanges(); 11248 } 11249 11250 return false; 11251 }, 11252 11253 _mouseStop: function( event ) { 11254 11255 this.resizing = false; 11256 var pr, ista, soffseth, soffsetw, s, left, top, 11257 o = this.options, that = this; 11258 11259 if ( this._helper ) { 11260 11261 pr = this._proportionallyResizeElements; 11262 ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ); 11263 soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height; 11264 soffsetw = ista ? 0 : that.sizeDiff.width; 11265 11266 s = { 11267 width: ( that.helper.width() - soffsetw ), 11268 height: ( that.helper.height() - soffseth ) 11269 }; 11270 left = ( parseFloat( that.element.css( "left" ) ) + 11271 ( that.position.left - that.originalPosition.left ) ) || null; 11272 top = ( parseFloat( that.element.css( "top" ) ) + 11273 ( that.position.top - that.originalPosition.top ) ) || null; 11274 11275 if ( !o.animate ) { 11276 this.element.css( $.extend( s, { top: top, left: left } ) ); 11277 } 11278 11279 that.helper.height( that.size.height ); 11280 that.helper.width( that.size.width ); 11281 11282 if ( this._helper && !o.animate ) { 11283 this._proportionallyResize(); 11284 } 11285 } 11286 11287 $( "body" ).css( "cursor", "auto" ); 11288 11289 this._removeClass( "ui-resizable-resizing" ); 11290 11291 this._propagate( "stop", event ); 11292 11293 if ( this._helper ) { 11294 this.helper.remove(); 11295 } 11296 11297 return false; 11298 11299 }, 11300 11301 _updatePrevProperties: function() { 11302 this.prevPosition = { 11303 top: this.position.top, 11304 left: this.position.left 11305 }; 11306 this.prevSize = { 11307 width: this.size.width, 11308 height: this.size.height 11309 }; 11310 }, 11311 11312 _applyChanges: function() { 11313 var props = {}; 11314 11315 if ( this.position.top !== this.prevPosition.top ) { 11316 props.top = this.position.top + "px"; 11317 } 11318 if ( this.position.left !== this.prevPosition.left ) { 11319 props.left = this.position.left + "px"; 11320 } 11321 11322 this.helper.css( props ); 11323 11324 if ( this.size.width !== this.prevSize.width ) { 11325 props.width = this.size.width + "px"; 11326 this.helper.width( props.width ); 11327 } 11328 if ( this.size.height !== this.prevSize.height ) { 11329 props.height = this.size.height + "px"; 11330 this.helper.height( props.height ); 11331 } 11332 11333 return props; 11334 }, 11335 11336 _updateVirtualBoundaries: function( forceAspectRatio ) { 11337 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b, 11338 o = this.options; 11339 11340 b = { 11341 minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0, 11342 maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity, 11343 minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0, 11344 maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity 11345 }; 11346 11347 if ( this._aspectRatio || forceAspectRatio ) { 11348 pMinWidth = b.minHeight * this.aspectRatio; 11349 pMinHeight = b.minWidth / this.aspectRatio; 11350 pMaxWidth = b.maxHeight * this.aspectRatio; 11351 pMaxHeight = b.maxWidth / this.aspectRatio; 11352 11353 if ( pMinWidth > b.minWidth ) { 11354 b.minWidth = pMinWidth; 11355 } 11356 if ( pMinHeight > b.minHeight ) { 11357 b.minHeight = pMinHeight; 11358 } 11359 if ( pMaxWidth < b.maxWidth ) { 11360 b.maxWidth = pMaxWidth; 11361 } 11362 if ( pMaxHeight < b.maxHeight ) { 11363 b.maxHeight = pMaxHeight; 11364 } 11365 } 11366 this._vBoundaries = b; 11367 }, 11368 11369 _updateCache: function( data ) { 11370 this.offset = this.helper.offset(); 11371 if ( this._isNumber( data.left ) ) { 11372 this.position.left = data.left; 11373 } 11374 if ( this._isNumber( data.top ) ) { 11375 this.position.top = data.top; 11376 } 11377 if ( this._isNumber( data.height ) ) { 11378 this.size.height = data.height; 11379 } 11380 if ( this._isNumber( data.width ) ) { 11381 this.size.width = data.width; 11382 } 11383 }, 11384 11385 _updateRatio: function( data ) { 11386 11387 var cpos = this.position, 11388 csize = this.size, 11389 a = this.axis; 11390 11391 if ( this._isNumber( data.height ) ) { 11392 data.width = ( data.height * this.aspectRatio ); 11393 } else if ( this._isNumber( data.width ) ) { 11394 data.height = ( data.width / this.aspectRatio ); 11395 } 11396 11397 if ( a === "sw" ) { 11398 data.left = cpos.left + ( csize.width - data.width ); 11399 data.top = null; 11400 } 11401 if ( a === "nw" ) { 11402 data.top = cpos.top + ( csize.height - data.height ); 11403 data.left = cpos.left + ( csize.width - data.width ); 11404 } 11405 11406 return data; 11407 }, 11408 11409 _respectSize: function( data ) { 11410 11411 var o = this._vBoundaries, 11412 a = this.axis, 11413 ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ), 11414 ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ), 11415 isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ), 11416 isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ), 11417 dw = this.originalPosition.left + this.originalSize.width, 11418 dh = this.originalPosition.top + this.originalSize.height, 11419 cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a ); 11420 if ( isminw ) { 11421 data.width = o.minWidth; 11422 } 11423 if ( isminh ) { 11424 data.height = o.minHeight; 11425 } 11426 if ( ismaxw ) { 11427 data.width = o.maxWidth; 11428 } 11429 if ( ismaxh ) { 11430 data.height = o.maxHeight; 11431 } 11432 11433 if ( isminw && cw ) { 11434 data.left = dw - o.minWidth; 11435 } 11436 if ( ismaxw && cw ) { 11437 data.left = dw - o.maxWidth; 11438 } 11439 if ( isminh && ch ) { 11440 data.top = dh - o.minHeight; 11441 } 11442 if ( ismaxh && ch ) { 11443 data.top = dh - o.maxHeight; 11444 } 11445 11446 // Fixing jump error on top/left - bug #2330 11447 if ( !data.width && !data.height && !data.left && data.top ) { 11448 data.top = null; 11449 } else if ( !data.width && !data.height && !data.top && data.left ) { 11450 data.left = null; 11451 } 11452 11453 return data; 11454 }, 11455 11456 _getPaddingPlusBorderDimensions: function( element ) { 11457 var i = 0, 11458 widths = [], 11459 borders = [ 11460 element.css( "borderTopWidth" ), 11461 element.css( "borderRightWidth" ), 11462 element.css( "borderBottomWidth" ), 11463 element.css( "borderLeftWidth" ) 11464 ], 11465 paddings = [ 11466 element.css( "paddingTop" ), 11467 element.css( "paddingRight" ), 11468 element.css( "paddingBottom" ), 11469 element.css( "paddingLeft" ) 11470 ]; 11471 11472 for ( ; i < 4; i++ ) { 11473 widths[ i ] = ( parseFloat( borders[ i ] ) || 0 ); 11474 widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 ); 11475 } 11476 11477 return { 11478 height: widths[ 0 ] + widths[ 2 ], 11479 width: widths[ 1 ] + widths[ 3 ] 11480 }; 11481 }, 11482 11483 _proportionallyResize: function() { 11484 11485 if ( !this._proportionallyResizeElements.length ) { 11486 return; 11487 } 11488 11489 var prel, 11490 i = 0, 11491 element = this.helper || this.element; 11492 11493 for ( ; i < this._proportionallyResizeElements.length; i++ ) { 11494 11495 prel = this._proportionallyResizeElements[ i ]; 11496 11497 // TODO: Seems like a bug to cache this.outerDimensions 11498 // considering that we are in a loop. 11499 if ( !this.outerDimensions ) { 11500 this.outerDimensions = this._getPaddingPlusBorderDimensions( prel ); 11501 } 11502 11503 prel.css( { 11504 height: ( element.height() - this.outerDimensions.height ) || 0, 11505 width: ( element.width() - this.outerDimensions.width ) || 0 11506 } ); 11507 11508 } 11509 11510 }, 11511 11512 _renderProxy: function() { 11513 11514 var el = this.element, o = this.options; 11515 this.elementOffset = el.offset(); 11516 11517 if ( this._helper ) { 11518 11519 this.helper = this.helper || $( "<div></div>" ).css( { overflow: "hidden" } ); 11520 11521 this._addClass( this.helper, this._helper ); 11522 this.helper.css( { 11523 width: this.element.outerWidth(), 11524 height: this.element.outerHeight(), 11525 position: "absolute",
vendor: 6,636 bytes, lines 11526-11766
11526 left: this.elementOffset.left + "px", 11527 top: this.elementOffset.top + "px", 11528 zIndex: ++o.zIndex //TODO: Don't modify option 11529 } ); 11530 11531 this.helper 11532 .appendTo( "body" ) 11533 .disableSelection(); 11534 11535 } else { 11536 this.helper = this.element; 11537 } 11538 11539 }, 11540 11541 _change: { 11542 e: function( event, dx ) { 11543 return { width: this.originalSize.width + dx }; 11544 }, 11545 w: function( event, dx ) { 11546 var cs = this.originalSize, sp = this.originalPosition; 11547 return { left: sp.left + dx, width: cs.width - dx }; 11548 }, 11549 n: function( event, dx, dy ) { 11550 var cs = this.originalSize, sp = this.originalPosition; 11551 return { top: sp.top + dy, height: cs.height - dy }; 11552 }, 11553 s: function( event, dx, dy ) { 11554 return { height: this.originalSize.height + dy }; 11555 }, 11556 se: function( event, dx, dy ) { 11557 return $.extend( this._change.s.apply( this, arguments ), 11558 this._change.e.apply( this, [ event, dx, dy ] ) ); 11559 }, 11560 sw: function( event, dx, dy ) { 11561 return $.extend( this._change.s.apply( this, arguments ), 11562 this._change.w.apply( this, [ event, dx, dy ] ) ); 11563 }, 11564 ne: function( event, dx, dy ) { 11565 return $.extend( this._change.n.apply( this, arguments ), 11566 this._change.e.apply( this, [ event, dx, dy ] ) ); 11567 }, 11568 nw: function( event, dx, dy ) { 11569 return $.extend( this._change.n.apply( this, arguments ), 11570 this._change.w.apply( this, [ event, dx, dy ] ) ); 11571 } 11572 }, 11573 11574 _propagate: function( n, event ) { 11575 $.ui.plugin.call( this, n, [ event, this.ui() ] ); 11576 if ( n !== "resize" ) { 11577 this._trigger( n, event, this.ui() ); 11578 } 11579 }, 11580 11581 plugins: {}, 11582 11583 ui: function() { 11584 return { 11585 originalElement: this.originalElement, 11586 element: this.element, 11587 helper: this.helper, 11588 position: this.position, 11589 size: this.size, 11590 originalSize: this.originalSize, 11591 originalPosition: this.originalPosition 11592 }; 11593 } 11594 11595} ); 11596 11597/* 11598 * Resizable Extensions 11599 */ 11600 11601$.ui.plugin.add( "resizable", "animate", { 11602 11603 stop: function( event ) { 11604 var that = $( this ).resizable( "instance" ), 11605 o = that.options, 11606 pr = that._proportionallyResizeElements, 11607 ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ), 11608 soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height, 11609 soffsetw = ista ? 0 : that.sizeDiff.width, 11610 style = { 11611 width: ( that.size.width - soffsetw ), 11612 height: ( that.size.height - soffseth ) 11613 }, 11614 left = ( parseFloat( that.element.css( "left" ) ) + 11615 ( that.position.left - that.originalPosition.left ) ) || null, 11616 top = ( parseFloat( that.element.css( "top" ) ) + 11617 ( that.position.top - that.originalPosition.top ) ) || null; 11618 11619 that.element.animate( 11620 $.extend( style, top && left ? { top: top, left: left } : {} ), { 11621 duration: o.animateDuration, 11622 easing: o.animateEasing, 11623 step: function() { 11624 11625 var data = { 11626 width: parseFloat( that.element.css( "width" ) ), 11627 height: parseFloat( that.element.css( "height" ) ), 11628 top: parseFloat( that.element.css( "top" ) ), 11629 left: parseFloat( that.element.css( "left" ) ) 11630 }; 11631 11632 if ( pr && pr.length ) { 11633 $( pr[ 0 ] ).css( { width: data.width, height: data.height } ); 11634 } 11635 11636 // Propagating resize, and updating values for each animation step 11637 that._updateCache( data ); 11638 that._propagate( "resize", event ); 11639 11640 } 11641 } 11642 ); 11643 } 11644 11645} ); 11646 11647$.ui.plugin.add( "resizable", "containment", { 11648 11649 start: function() { 11650 var element, p, co, ch, cw, width, height, 11651 that = $( this ).resizable( "instance" ), 11652 o = that.options, 11653 el = that.element, 11654 oc = o.containment, 11655 ce = ( oc instanceof $ ) ? 11656 oc.get( 0 ) : 11657 ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc; 11658 11659 if ( !ce ) { 11660 return; 11661 } 11662 11663 that.containerElement = $( ce ); 11664 11665 if ( /document/.test( oc ) || oc === document ) { 11666 that.containerOffset = { 11667 left: 0, 11668 top: 0 11669 }; 11670 that.containerPosition = { 11671 left: 0, 11672 top: 0 11673 }; 11674 11675 that.parentData = { 11676 element: $( document ), 11677 left: 0, 11678 top: 0, 11679 width: $( document ).width(), 11680 height: $( document ).height() || document.body.parentNode.scrollHeight 11681 }; 11682 } else { 11683 element = $( ce ); 11684 p = []; 11685 $( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) { 11686 p[ i ] = that._num( element.css( "padding" + name ) ); 11687 } ); 11688 11689 that.containerOffset = element.offset(); 11690 that.containerPosition = element.position(); 11691 that.containerSize = { 11692 height: ( element.innerHeight() - p[ 3 ] ), 11693 width: ( element.innerWidth() - p[ 1 ] ) 11694 }; 11695 11696 co = that.containerOffset; 11697 ch = that.containerSize.height; 11698 cw = that.containerSize.width; 11699 width = ( that._hasScroll( ce, "left" ) ? ce.scrollWidth : cw ); 11700 height = ( that._hasScroll( ce ) ? ce.scrollHeight : ch ); 11701 11702 that.parentData = { 11703 element: ce, 11704 left: co.left, 11705 top: co.top, 11706 width: width, 11707 height: height 11708 }; 11709 } 11710 }, 11711 11712 resize: function( event ) { 11713 var woset, hoset, isParent, isOffsetRelative, 11714 that = $( this ).resizable( "instance" ), 11715 o = that.options, 11716 co = that.containerOffset, 11717 cp = that.position, 11718 pRatio = that._aspectRatio || event.shiftKey, 11719 cop = { 11720 top: 0, 11721 left: 0 11722 }, 11723 ce = that.containerElement, 11724 continueResize = true; 11725 11726 if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) { 11727 cop = co; 11728 } 11729 11730 if ( cp.left < ( that._helper ? co.left : 0 ) ) { 11731 that.size.width = that.size.width + 11732 ( that._helper ? 11733 ( that.position.left - co.left ) : 11734 ( that.position.left - cop.left ) ); 11735 11736 if ( pRatio ) { 11737 that.size.height = that.size.width / that.aspectRatio; 11738 continueResize = false; 11739 } 11740 that.position.left = o.helper ? co.left : 0; 11741 } 11742 11743 if ( cp.top < ( that._helper ? co.top : 0 ) ) { 11744 that.size.height = that.size.height + 11745 ( that._helper ? 11746 ( that.position.top - co.top ) : 11747 that.position.top ); 11748 11749 if ( pRatio ) { 11750 that.size.width = that.size.height * that.aspectRatio; 11751 continueResize = false; 11752 } 11753 that.position.top = that._helper ? co.top : 0; 11754 } 11755 11756 isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 ); 11757 isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) ); 11758 11759 if ( isParent && isOffsetRelative ) { 11760 that.offset.left = that.parentData.left + that.position.left; 11761 that.offset.top = that.parentData.top + that.position.top; 11762 } else { 11763 that.offset.left = that.element.offset().left; 11764 that.offset.top = that.element.offset().top; 11765 } 11766
vendor: 4,546 bytes, lines 11767-11941
11767 woset = Math.abs( that.sizeDiff.width + 11768 ( that._helper ? 11769 that.offset.left - cop.left : 11770 ( that.offset.left - co.left ) ) ); 11771 11772 hoset = Math.abs( that.sizeDiff.height + 11773 ( that._helper ? 11774 that.offset.top - cop.top : 11775 ( that.offset.top - co.top ) ) ); 11776 11777 if ( woset + that.size.width >= that.parentData.width ) { 11778 that.size.width = that.parentData.width - woset; 11779 if ( pRatio ) { 11780 that.size.height = that.size.width / that.aspectRatio; 11781 continueResize = false; 11782 } 11783 } 11784 11785 if ( hoset + that.size.height >= that.parentData.height ) { 11786 that.size.height = that.parentData.height - hoset; 11787 if ( pRatio ) { 11788 that.size.width = that.size.height * that.aspectRatio; 11789 continueResize = false; 11790 } 11791 } 11792 11793 if ( !continueResize ) { 11794 that.position.left = that.prevPosition.left; 11795 that.position.top = that.prevPosition.top; 11796 that.size.width = that.prevSize.width; 11797 that.size.height = that.prevSize.height; 11798 } 11799 }, 11800 11801 stop: function() { 11802 var that = $( this ).resizable( "instance" ), 11803 o = that.options, 11804 co = that.containerOffset, 11805 cop = that.containerPosition, 11806 ce = that.containerElement, 11807 helper = $( that.helper ), 11808 ho = helper.offset(), 11809 w = helper.outerWidth() - that.sizeDiff.width, 11810 h = helper.outerHeight() - that.sizeDiff.height; 11811 11812 if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) { 11813 $( this ).css( { 11814 left: ho.left - cop.left - co.left, 11815 width: w, 11816 height: h 11817 } ); 11818 } 11819 11820 if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) { 11821 $( this ).css( { 11822 left: ho.left - cop.left - co.left, 11823 width: w, 11824 height: h 11825 } ); 11826 } 11827 } 11828} ); 11829 11830$.ui.plugin.add( "resizable", "alsoResize", { 11831 11832 start: function() { 11833 var that = $( this ).resizable( "instance" ), 11834 o = that.options; 11835 11836 $( o.alsoResize ).each( function() { 11837 var el = $( this ); 11838 el.data( "ui-resizable-alsoresize", { 11839 width: parseFloat( el.css( "width" ) ), height: parseFloat( el.css( "height" ) ), 11840 left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) ) 11841 } ); 11842 } ); 11843 }, 11844 11845 resize: function( event, ui ) { 11846 var that = $( this ).resizable( "instance" ), 11847 o = that.options, 11848 os = that.originalSize, 11849 op = that.originalPosition, 11850 delta = { 11851 height: ( that.size.height - os.height ) || 0, 11852 width: ( that.size.width - os.width ) || 0, 11853 top: ( that.position.top - op.top ) || 0, 11854 left: ( that.position.left - op.left ) || 0 11855 }; 11856 11857 $( o.alsoResize ).each( function() { 11858 var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {}, 11859 css = el.parents( ui.originalElement[ 0 ] ).length ? 11860 [ "width", "height" ] : 11861 [ "width", "height", "top", "left" ]; 11862 11863 $.each( css, function( i, prop ) { 11864 var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 ); 11865 if ( sum && sum >= 0 ) { 11866 style[ prop ] = sum || null; 11867 } 11868 } ); 11869 11870 el.css( style ); 11871 } ); 11872 }, 11873 11874 stop: function() { 11875 $( this ).removeData( "ui-resizable-alsoresize" ); 11876 } 11877} ); 11878 11879$.ui.plugin.add( "resizable", "ghost", { 11880 11881 start: function() { 11882 11883 var that = $( this ).resizable( "instance" ), cs = that.size; 11884 11885 that.ghost = that.originalElement.clone(); 11886 that.ghost.css( { 11887 opacity: 0.25, 11888 display: "block", 11889 position: "relative", 11890 height: cs.height, 11891 width: cs.width, 11892 margin: 0, 11893 left: 0, 11894 top: 0 11895 } ); 11896 11897 that._addClass( that.ghost, "ui-resizable-ghost" ); 11898 11899 // DEPRECATED 11900 // TODO: remove after 1.12 11901 if ( $.uiBackCompat === true && typeof that.options.ghost === "string" ) { 11902 11903 // Ghost option 11904 that.ghost.addClass( this.options.ghost ); 11905 } 11906 11907 that.ghost.appendTo( that.helper ); 11908 11909 }, 11910 11911 resize: function() { 11912 var that = $( this ).resizable( "instance" ); 11913 if ( that.ghost ) { 11914 that.ghost.css( { 11915 position: "relative", 11916 height: that.size.height, 11917 width: that.size.width 11918 } ); 11919 } 11920 }, 11921 11922 stop: function() { 11923 var that = $( this ).resizable( "instance" ); 11924 if ( that.ghost && that.helper ) { 11925 that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) ); 11926 } 11927 } 11928 11929} ); 11930 11931$.ui.plugin.add( "resizable", "grid", { 11932 11933 resize: function() { 11934 var outerDimensions, 11935 that = $( this ).resizable( "instance" ), 11936 o = that.options, 11937 cs = that.size, 11938 os = that.originalSize, 11939 op = that.originalPosition, 11940 a = that.axis, 11941 grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
vendor: 10,346 bytes, lines 11942-12350
11942 gridX = ( grid[ 0 ] || 1 ), 11943 gridY = ( grid[ 1 ] || 1 ), 11944 ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX, 11945 oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY, 11946 newWidth = os.width + ox, 11947 newHeight = os.height + oy, 11948 isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ), 11949 isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ), 11950 isMinWidth = o.minWidth && ( o.minWidth > newWidth ), 11951 isMinHeight = o.minHeight && ( o.minHeight > newHeight ); 11952 11953 o.grid = grid; 11954 11955 if ( isMinWidth ) { 11956 newWidth += gridX; 11957 } 11958 if ( isMinHeight ) { 11959 newHeight += gridY; 11960 } 11961 if ( isMaxWidth ) { 11962 newWidth -= gridX; 11963 } 11964 if ( isMaxHeight ) { 11965 newHeight -= gridY; 11966 } 11967 11968 if ( /^(se|s|e)$/.test( a ) ) { 11969 that.size.width = newWidth; 11970 that.size.height = newHeight; 11971 } else if ( /^(ne)$/.test( a ) ) { 11972 that.size.width = newWidth; 11973 that.size.height = newHeight; 11974 that.position.top = op.top - oy; 11975 } else if ( /^(sw)$/.test( a ) ) { 11976 that.size.width = newWidth; 11977 that.size.height = newHeight; 11978 that.position.left = op.left - ox; 11979 } else { 11980 if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) { 11981 outerDimensions = that._getPaddingPlusBorderDimensions( this ); 11982 } 11983 11984 if ( newHeight - gridY > 0 ) { 11985 that.size.height = newHeight; 11986 that.position.top = op.top - oy; 11987 } else { 11988 newHeight = gridY - outerDimensions.height; 11989 that.size.height = newHeight; 11990 that.position.top = op.top + os.height - newHeight; 11991 } 11992 if ( newWidth - gridX > 0 ) { 11993 that.size.width = newWidth; 11994 that.position.left = op.left - ox; 11995 } else { 11996 newWidth = gridX - outerDimensions.width; 11997 that.size.width = newWidth; 11998 that.position.left = op.left + os.width - newWidth; 11999 } 12000 } 12001 } 12002 12003} ); 12004 12005var widgetsResizable = $.ui.resizable; 12006 12007 12008/*! 12009 * jQuery UI Dialog 1.14.0 12010 * https://jqueryui.com 12011 * 12012 * Copyright OpenJS Foundation and other contributors 12013 * Released under the MIT license. 12014 * https://jquery.org/license 12015 */ 12016 12017//>>label: Dialog 12018//>>group: Widgets 12019//>>description: Displays customizable dialog windows. 12020//>>docs: https://api.jqueryui.com/dialog/ 12021//>>demos: https://jqueryui.com/dialog/ 12022//>>css.structure: ../../themes/base/core.css 12023//>>css.structure: ../../themes/base/dialog.css 12024//>>css.theme: ../../themes/base/theme.css 12025 12026 12027$.widget( "ui.dialog", { 12028 version: "1.14.0", 12029 options: { 12030 appendTo: "body", 12031 autoOpen: true, 12032 buttons: [], 12033 classes: { 12034 "ui-dialog": "ui-corner-all", 12035 "ui-dialog-titlebar": "ui-corner-all" 12036 }, 12037 closeOnEscape: true, 12038 closeText: "Close", 12039 draggable: true, 12040 hide: null, 12041 height: "auto", 12042 maxHeight: null, 12043 maxWidth: null, 12044 minHeight: 150, 12045 minWidth: 150, 12046 modal: false, 12047 position: { 12048 my: "center", 12049 at: "center", 12050 of: window, 12051 collision: "fit", 12052 12053 // Ensure the titlebar is always visible 12054 using: function( pos ) { 12055 var topOffset = $( this ).css( pos ).offset().top; 12056 if ( topOffset < 0 ) { 12057 $( this ).css( "top", pos.top - topOffset ); 12058 } 12059 } 12060 }, 12061 resizable: true, 12062 show: null, 12063 title: null, 12064 width: 300, 12065 12066 // Callbacks 12067 beforeClose: null, 12068 close: null, 12069 drag: null, 12070 dragStart: null, 12071 dragStop: null, 12072 focus: null, 12073 open: null, 12074 resize: null, 12075 resizeStart: null, 12076 resizeStop: null 12077 }, 12078 12079 sizeRelatedOptions: { 12080 buttons: true, 12081 height: true, 12082 maxHeight: true, 12083 maxWidth: true, 12084 minHeight: true, 12085 minWidth: true, 12086 width: true 12087 }, 12088 12089 resizableRelatedOptions: { 12090 maxHeight: true, 12091 maxWidth: true, 12092 minHeight: true, 12093 minWidth: true 12094 }, 12095 12096 _create: function() { 12097 this.originalCss = { 12098 display: this.element[ 0 ].style.display, 12099 width: this.element[ 0 ].style.width, 12100 minHeight: this.element[ 0 ].style.minHeight, 12101 maxHeight: this.element[ 0 ].style.maxHeight, 12102 height: this.element[ 0 ].style.height 12103 }; 12104 this.originalPosition = { 12105 parent: this.element.parent(), 12106 index: this.element.parent().children().index( this.element ) 12107 }; 12108 this.originalTitle = this.element.attr( "title" ); 12109 if ( this.options.title == null && this.originalTitle != null ) { 12110 this.options.title = this.originalTitle; 12111 } 12112 12113 // Dialogs can't be disabled 12114 if ( this.options.disabled ) { 12115 this.options.disabled = false; 12116 } 12117 12118 this._createWrapper(); 12119 12120 this.element 12121 .show() 12122 .removeAttr( "title" ) 12123 .appendTo( this.uiDialog ); 12124 12125 this._addClass( "ui-dialog-content", "ui-widget-content" ); 12126 12127 this._createTitlebar(); 12128 this._createButtonPane(); 12129 12130 if ( this.options.draggable && $.fn.draggable ) { 12131 this._makeDraggable(); 12132 } 12133 if ( this.options.resizable && $.fn.resizable ) { 12134 this._makeResizable(); 12135 } 12136 12137 this._isOpen = false; 12138 12139 this._trackFocus(); 12140 }, 12141 12142 _init: function() { 12143 if ( this.options.autoOpen ) { 12144 this.open(); 12145 } 12146 }, 12147 12148 _appendTo: function() { 12149 var element = this.options.appendTo; 12150 if ( element && ( element.jquery || element.nodeType ) ) { 12151 return $( element ); 12152 } 12153 return this.document.find( element || "body" ).eq( 0 ); 12154 }, 12155 12156 _destroy: function() { 12157 var next, 12158 originalPosition = this.originalPosition; 12159 12160 this._untrackInstance(); 12161 this._destroyOverlay(); 12162 12163 this.element 12164 .removeUniqueId() 12165 .css( this.originalCss ) 12166 12167 // Without detaching first, the following becomes really slow 12168 .detach(); 12169 12170 this.uiDialog.remove(); 12171 12172 if ( this.originalTitle ) { 12173 this.element.attr( "title", this.originalTitle ); 12174 } 12175 12176 next = originalPosition.parent.children().eq( originalPosition.index ); 12177 12178 // Don't try to place the dialog next to itself (#8613) 12179 if ( next.length && next[ 0 ] !== this.element[ 0 ] ) { 12180 next.before( this.element ); 12181 } else { 12182 originalPosition.parent.append( this.element ); 12183 } 12184 }, 12185 12186 widget: function() { 12187 return this.uiDialog; 12188 }, 12189 12190 disable: $.noop, 12191 enable: $.noop, 12192 12193 close: function( event ) { 12194 var that = this; 12195 12196 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) { 12197 return; 12198 } 12199 12200 this._isOpen = false; 12201 this._focusedElement = null; 12202 this._destroyOverlay(); 12203 this._untrackInstance(); 12204 12205 if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) { 12206 12207 // Hiding a focused element doesn't trigger blur in WebKit 12208 // so in case we have nothing to focus on, explicitly blur the active element 12209 // https://bugs.webkit.org/show_bug.cgi?id=47182 12210 $( this.document[ 0 ].activeElement ).trigger( "blur" ); 12211 } 12212 12213 this._hide( this.uiDialog, this.options.hide, function() { 12214 that._trigger( "close", event ); 12215 } ); 12216 }, 12217 12218 isOpen: function() { 12219 return this._isOpen; 12220 }, 12221 12222 moveToTop: function() { 12223 this._moveToTop(); 12224 }, 12225 12226 _moveToTop: function( event, silent ) { 12227 var moved = false, 12228 zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() { 12229 return +$( this ).css( "z-index" ); 12230 } ).get(), 12231 zIndexMax = Math.max.apply( null, zIndices ); 12232 12233 if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) { 12234 this.uiDialog.css( "z-index", zIndexMax + 1 ); 12235 moved = true; 12236 } 12237 12238 if ( moved && !silent ) { 12239 this._trigger( "focus", event ); 12240 } 12241 return moved; 12242 }, 12243 12244 open: function() { 12245 var that = this; 12246 if ( this._isOpen ) { 12247 if ( this._moveToTop() ) { 12248 this._focusTabbable(); 12249 } 12250 return; 12251 } 12252 12253 this._isOpen = true; 12254 this.opener = $( this.document[ 0 ].activeElement ); 12255 12256 this._size(); 12257 this._position(); 12258 this._createOverlay(); 12259 this._moveToTop( null, true ); 12260 12261 // Ensure the overlay is moved to the top with the dialog, but only when 12262 // opening. The overlay shouldn't move after the dialog is open so that 12263 // modeless dialogs opened after the modal dialog stack properly. 12264 if ( this.overlay ) { 12265 this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 ); 12266 } 12267 12268 this._show( this.uiDialog, this.options.show, function() { 12269 that._focusTabbable(); 12270 that._trigger( "focus" ); 12271 } ); 12272 12273 // Track the dialog immediately upon opening in case a focus event 12274 // somehow occurs outside of the dialog before an element inside the 12275 // dialog is focused (#10152) 12276 this._makeFocusTarget(); 12277 12278 this._trigger( "open" ); 12279 }, 12280 12281 _focusTabbable: function() { 12282 12283 // Set focus to the first match: 12284 // 1. An element that was focused previously 12285 // 2. First element inside the dialog matching [autofocus] 12286 // 3. Tabbable element inside the content element 12287 // 4. Tabbable element inside the buttonpane 12288 // 5. The close button 12289 // 6. The dialog itself 12290 var hasFocus = this._focusedElement; 12291 if ( !hasFocus ) { 12292 hasFocus = this.element.find( "[autofocus]" ); 12293 } 12294 if ( !hasFocus.length ) { 12295 hasFocus = this.element.find( ":tabbable" ); 12296 } 12297 if ( !hasFocus.length ) { 12298 hasFocus = this.uiDialogButtonPane.find( ":tabbable" ); 12299 } 12300 if ( !hasFocus.length ) { 12301 hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" ); 12302 } 12303 if ( !hasFocus.length ) { 12304 hasFocus = this.uiDialog; 12305 } 12306 hasFocus.eq( 0 ).trigger( "focus" ); 12307 }, 12308 12309 _restoreTabbableFocus: function() { 12310 var activeElement = this.document[ 0 ].activeElement, 12311 isActive = this.uiDialog[ 0 ] === activeElement || 12312 $.contains( this.uiDialog[ 0 ], activeElement ); 12313 if ( !isActive ) { 12314 this._focusTabbable(); 12315 } 12316 }, 12317 12318 _keepFocus: function( event ) { 12319 event.preventDefault(); 12320 this._restoreTabbableFocus(); 12321 }, 12322 12323 _createWrapper: function() { 12324 this.uiDialog = $( "<div>" ) 12325 .hide() 12326 .attr( { 12327 12328 // Setting tabIndex makes the div focusable 12329 tabIndex: -1, 12330 role: "dialog", 12331 "aria-modal": this.options.modal ? "true" : null 12332 } ) 12333 .appendTo( this._appendTo() ); 12334 12335 this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" ); 12336 this._on( this.uiDialog, { 12337 keydown: function( event ) { 12338 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && 12339 event.keyCode === $.ui.keyCode.ESCAPE ) { 12340 event.preventDefault(); 12341 this.close( event ); 12342 return; 12343 } 12344 12345 // Prevent tabbing out of dialogs 12346 if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) { 12347 return; 12348 } 12349 var tabbables = this.uiDialog.find( ":tabbable" ), 12350 first = tabbables.first(),
vendor: 12,216 bytes, lines 12351-12804
12351 last = tabbables.last(); 12352 12353 if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) && 12354 !event.shiftKey ) { 12355 this._delay( function() { 12356 first.trigger( "focus" ); 12357 } ); 12358 event.preventDefault(); 12359 } else if ( ( event.target === first[ 0 ] || 12360 event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) { 12361 this._delay( function() { 12362 last.trigger( "focus" ); 12363 } ); 12364 event.preventDefault(); 12365 } 12366 }, 12367 mousedown: function( event ) { 12368 if ( this._moveToTop( event ) ) { 12369 this._focusTabbable(); 12370 } 12371 } 12372 } ); 12373 12374 // We assume that any existing aria-describedby attribute means 12375 // that the dialog content is marked up properly 12376 // otherwise we brute force the content as the description 12377 if ( !this.element.find( "[aria-describedby]" ).length ) { 12378 this.uiDialog.attr( { 12379 "aria-describedby": this.element.uniqueId().attr( "id" ) 12380 } ); 12381 } 12382 }, 12383 12384 _createTitlebar: function() { 12385 var uiDialogTitle; 12386 12387 this.uiDialogTitlebar = $( "<div>" ); 12388 this._addClass( this.uiDialogTitlebar, 12389 "ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" ); 12390 this._on( this.uiDialogTitlebar, { 12391 mousedown: function( event ) { 12392 12393 // Don't prevent click on close button (#8838) 12394 // Focusing a dialog that is partially scrolled out of view 12395 // causes the browser to scroll it into view, preventing the click event 12396 if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) { 12397 12398 // Dialog isn't getting focus when dragging (#8063) 12399 this.uiDialog.trigger( "focus" ); 12400 } 12401 } 12402 } ); 12403 12404 this.uiDialogTitlebarClose = $( "<button type='button'></button>" ) 12405 .button( { 12406 label: $( "<a>" ).text( this.options.closeText ).html(), 12407 icon: "ui-icon-closethick", 12408 showLabel: false 12409 } ) 12410 .appendTo( this.uiDialogTitlebar ); 12411 12412 this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" ); 12413 this._on( this.uiDialogTitlebarClose, { 12414 click: function( event ) { 12415 event.preventDefault(); 12416 this.close( event ); 12417 } 12418 } ); 12419 12420 uiDialogTitle = $( "<span>" ).uniqueId().prependTo( this.uiDialogTitlebar ); 12421 this._addClass( uiDialogTitle, "ui-dialog-title" ); 12422 this._title( uiDialogTitle ); 12423 12424 this.uiDialogTitlebar.prependTo( this.uiDialog ); 12425 12426 this.uiDialog.attr( { 12427 "aria-labelledby": uiDialogTitle.attr( "id" ) 12428 } ); 12429 }, 12430 12431 _title: function( title ) { 12432 if ( this.options.title ) { 12433 title.text( this.options.title ); 12434 } else { 12435 title.html( " " ); 12436 } 12437 }, 12438 12439 _createButtonPane: function() { 12440 this.uiDialogButtonPane = $( "<div>" ); 12441 this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane", 12442 "ui-widget-content ui-helper-clearfix" ); 12443 12444 this.uiButtonSet = $( "<div>" ) 12445 .appendTo( this.uiDialogButtonPane ); 12446 this._addClass( this.uiButtonSet, "ui-dialog-buttonset" ); 12447 12448 this._createButtons(); 12449 }, 12450 12451 _createButtons: function() { 12452 var that = this, 12453 buttons = this.options.buttons; 12454 12455 // If we already have a button pane, remove it 12456 this.uiDialogButtonPane.remove(); 12457 this.uiButtonSet.empty(); 12458 12459 if ( $.isEmptyObject( buttons ) || ( Array.isArray( buttons ) && !buttons.length ) ) { 12460 this._removeClass( this.uiDialog, "ui-dialog-buttons" ); 12461 return; 12462 } 12463 12464 $.each( buttons, function( name, props ) { 12465 var click, buttonOptions; 12466 props = typeof props === "function" ? 12467 { click: props, text: name } : 12468 props; 12469 12470 // Default to a non-submitting button 12471 props = $.extend( { type: "button" }, props ); 12472 12473 // Change the context for the click callback to be the main element 12474 click = props.click; 12475 buttonOptions = { 12476 icon: props.icon, 12477 iconPosition: props.iconPosition, 12478 showLabel: props.showLabel, 12479 12480 // Deprecated options 12481 icons: props.icons, 12482 text: props.text 12483 }; 12484 12485 delete props.click; 12486 delete props.icon; 12487 delete props.iconPosition; 12488 delete props.showLabel; 12489 12490 // Deprecated options 12491 delete props.icons; 12492 if ( typeof props.text === "boolean" ) { 12493 delete props.text; 12494 } 12495 12496 $( "<button></button>", props ) 12497 .button( buttonOptions ) 12498 .appendTo( that.uiButtonSet ) 12499 .on( "click", function() { 12500 click.apply( that.element[ 0 ], arguments ); 12501 } ); 12502 } ); 12503 this._addClass( this.uiDialog, "ui-dialog-buttons" ); 12504 this.uiDialogButtonPane.appendTo( this.uiDialog ); 12505 }, 12506 12507 _makeDraggable: function() { 12508 var that = this, 12509 options = this.options; 12510 12511 function filteredUi( ui ) { 12512 return { 12513 position: ui.position, 12514 offset: ui.offset 12515 }; 12516 } 12517 12518 this.uiDialog.draggable( { 12519 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", 12520 handle: ".ui-dialog-titlebar", 12521 containment: "document", 12522 start: function( event, ui ) { 12523 that._addClass( $( this ), "ui-dialog-dragging" ); 12524 that._blockFrames(); 12525 that._trigger( "dragStart", event, filteredUi( ui ) ); 12526 }, 12527 drag: function( event, ui ) { 12528 that._trigger( "drag", event, filteredUi( ui ) ); 12529 }, 12530 stop: function( event, ui ) { 12531 var left = ui.offset.left - that.document.scrollLeft(), 12532 top = ui.offset.top - that.document.scrollTop(); 12533 12534 options.position = { 12535 my: "left top", 12536 at: "left" + ( left >= 0 ? "+" : "" ) + left + " " + 12537 "top" + ( top >= 0 ? "+" : "" ) + top, 12538 of: that.window 12539 }; 12540 that._removeClass( $( this ), "ui-dialog-dragging" ); 12541 that._unblockFrames(); 12542 that._trigger( "dragStop", event, filteredUi( ui ) ); 12543 } 12544 } ); 12545 }, 12546 12547 _makeResizable: function() { 12548 var that = this, 12549 options = this.options, 12550 handles = options.resizable, 12551 12552 // .ui-resizable has position: relative defined in the stylesheet 12553 // but dialogs have to use absolute or fixed positioning 12554 position = this.uiDialog.css( "position" ), 12555 resizeHandles = typeof handles === "string" ? 12556 handles : 12557 "n,e,s,w,se,sw,ne,nw"; 12558 12559 function filteredUi( ui ) { 12560 return { 12561 originalPosition: ui.originalPosition, 12562 originalSize: ui.originalSize, 12563 position: ui.position, 12564 size: ui.size 12565 }; 12566 } 12567 12568 this.uiDialog.resizable( { 12569 cancel: ".ui-dialog-content", 12570 containment: "document", 12571 alsoResize: this.element, 12572 maxWidth: options.maxWidth, 12573 maxHeight: options.maxHeight, 12574 minWidth: options.minWidth, 12575 minHeight: this._minHeight(), 12576 handles: resizeHandles, 12577 start: function( event, ui ) { 12578 that._addClass( $( this ), "ui-dialog-resizing" ); 12579 that._blockFrames(); 12580 that._trigger( "resizeStart", event, filteredUi( ui ) ); 12581 }, 12582 resize: function( event, ui ) { 12583 that._trigger( "resize", event, filteredUi( ui ) ); 12584 }, 12585 stop: function( event, ui ) { 12586 var offset = that.uiDialog.offset(), 12587 left = offset.left - that.document.scrollLeft(), 12588 top = offset.top - that.document.scrollTop(); 12589 12590 options.height = that.uiDialog.height(); 12591 options.width = that.uiDialog.width(); 12592 options.position = { 12593 my: "left top", 12594 at: "left" + ( left >= 0 ? "+" : "" ) + left + " " + 12595 "top" + ( top >= 0 ? "+" : "" ) + top, 12596 of: that.window 12597 }; 12598 that._removeClass( $( this ), "ui-dialog-resizing" ); 12599 that._unblockFrames(); 12600 that._trigger( "resizeStop", event, filteredUi( ui ) ); 12601 } 12602 } ) 12603 .css( "position", position ); 12604 }, 12605 12606 _trackFocus: function() { 12607 this._on( this.widget(), { 12608 focusin: function( event ) { 12609 this._makeFocusTarget(); 12610 this._focusedElement = $( event.target ); 12611 } 12612 } ); 12613 }, 12614 12615 _makeFocusTarget: function() { 12616 this._untrackInstance(); 12617 this._trackingInstances().unshift( this ); 12618 }, 12619 12620 _untrackInstance: function() { 12621 var instances = this._trackingInstances(), 12622 exists = $.inArray( this, instances ); 12623 if ( exists !== -1 ) { 12624 instances.splice( exists, 1 ); 12625 } 12626 }, 12627 12628 _trackingInstances: function() { 12629 var instances = this.document.data( "ui-dialog-instances" ); 12630 if ( !instances ) { 12631 instances = []; 12632 this.document.data( "ui-dialog-instances", instances ); 12633 } 12634 return instances; 12635 }, 12636 12637 _minHeight: function() { 12638 var options = this.options; 12639 12640 return options.height === "auto" ? 12641 options.minHeight : 12642 Math.min( options.minHeight, options.height ); 12643 }, 12644 12645 _position: function() { 12646 12647 // Need to show the dialog to get the actual offset in the position plugin 12648 var isVisible = this.uiDialog.is( ":visible" ); 12649 if ( !isVisible ) { 12650 this.uiDialog.show(); 12651 } 12652 this.uiDialog.position( this.options.position ); 12653 if ( !isVisible ) { 12654 this.uiDialog.hide(); 12655 } 12656 }, 12657 12658 _setOptions: function( options ) { 12659 var that = this, 12660 resize = false, 12661 resizableOptions = {}; 12662 12663 $.each( options, function( key, value ) { 12664 that._setOption( key, value ); 12665 12666 if ( key in that.sizeRelatedOptions ) { 12667 resize = true; 12668 } 12669 if ( key in that.resizableRelatedOptions ) { 12670 resizableOptions[ key ] = value; 12671 } 12672 } ); 12673 12674 if ( resize ) { 12675 this._size(); 12676 this._position(); 12677 } 12678 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) { 12679 this.uiDialog.resizable( "option", resizableOptions ); 12680 } 12681 }, 12682 12683 _setOption: function( key, value ) { 12684 var isDraggable, isResizable, 12685 uiDialog = this.uiDialog; 12686 12687 if ( key === "disabled" ) { 12688 return; 12689 } 12690 12691 this._super( key, value ); 12692 12693 if ( key === "appendTo" ) { 12694 this.uiDialog.appendTo( this._appendTo() ); 12695 } 12696 12697 if ( key === "buttons" ) { 12698 this._createButtons(); 12699 } 12700 12701 if ( key === "closeText" ) { 12702 this.uiDialogTitlebarClose.button( { 12703 12704 // Ensure that we always pass a string 12705 label: $( "<a>" ).text( "" + this.options.closeText ).html() 12706 } ); 12707 } 12708 12709 if ( key === "draggable" ) { 12710 isDraggable = uiDialog.is( ":data(ui-draggable)" ); 12711 if ( isDraggable && !value ) { 12712 uiDialog.draggable( "destroy" ); 12713 } 12714 12715 if ( !isDraggable && value ) { 12716 this._makeDraggable(); 12717 } 12718 } 12719 12720 if ( key === "position" ) { 12721 this._position(); 12722 } 12723 12724 if ( key === "resizable" ) { 12725 12726 // currently resizable, becoming non-resizable 12727 isResizable = uiDialog.is( ":data(ui-resizable)" ); 12728 if ( isResizable && !value ) { 12729 uiDialog.resizable( "destroy" ); 12730 } 12731 12732 // Currently resizable, changing handles 12733 if ( isResizable && typeof value === "string" ) { 12734 uiDialog.resizable( "option", "handles", value ); 12735 } 12736 12737 // Currently non-resizable, becoming resizable 12738 if ( !isResizable && value !== false ) { 12739 this._makeResizable(); 12740 } 12741 } 12742 12743 if ( key === "title" ) { 12744 this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) ); 12745 } 12746 12747 if ( key === "modal" ) { 12748 uiDialog.attr( "aria-modal", value ? "true" : null ); 12749 } 12750 }, 12751 12752 _size: function() { 12753 12754 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content 12755 // divs will both have width and height set, so we need to reset them 12756 var nonContentHeight, minContentHeight, maxContentHeight, 12757 options = this.options; 12758 12759 // Reset content sizing 12760 this.element.show().css( { 12761 width: "auto", 12762 minHeight: 0, 12763 maxHeight: "none", 12764 height: 0 12765 } ); 12766 12767 if ( options.minWidth > options.width ) { 12768 options.width = options.minWidth; 12769 } 12770 12771 // Reset wrapper sizing 12772 // determine the height of all the non-content elements 12773 nonContentHeight = this.uiDialog.css( { 12774 height: "auto", 12775 width: options.width 12776 } ) 12777 .outerHeight(); 12778 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); 12779 maxContentHeight = typeof options.maxHeight === "number" ? 12780 Math.max( 0, options.maxHeight - nonContentHeight ) : 12781 "none"; 12782 12783 if ( options.height === "auto" ) { 12784 this.element.css( { 12785 minHeight: minContentHeight, 12786 maxHeight: maxContentHeight, 12787 height: "auto" 12788 } ); 12789 } else { 12790 this.element.height( Math.max( 0, options.height - nonContentHeight ) ); 12791 } 12792 12793 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) { 12794 this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); 12795 } 12796 }, 12797 12798 _blockFrames: function() { 12799 this.iframeBlocks = this.document.find( "iframe" ).map( function() { 12800 var iframe = $( this ); 12801 12802 return $( "<div>" ) 12803 .css( { 12804 position: "absolute",
vendor: 122,591 bytes, lines 12805-17205
12805 width: iframe.outerWidth(), 12806 height: iframe.outerHeight() 12807 } ) 12808 .appendTo( iframe.parent() ) 12809 .offset( iframe.offset() )[ 0 ]; 12810 } ); 12811 }, 12812 12813 _unblockFrames: function() { 12814 if ( this.iframeBlocks ) { 12815 this.iframeBlocks.remove(); 12816 delete this.iframeBlocks; 12817 } 12818 }, 12819 12820 _allowInteraction: function( event ) { 12821 if ( $( event.target ).closest( ".ui-dialog" ).length ) { 12822 return true; 12823 } 12824 12825 // TODO: Remove hack when datepicker implements 12826 // the .ui-front logic (#8989) 12827 return !!$( event.target ).closest( ".ui-datepicker" ).length; 12828 }, 12829 12830 _createOverlay: function() { 12831 if ( !this.options.modal ) { 12832 return; 12833 } 12834 12835 // We use a delay in case the overlay is created from an 12836 // event that we're going to be cancelling (#2804) 12837 var isOpening = true; 12838 this._delay( function() { 12839 isOpening = false; 12840 } ); 12841 12842 if ( !this.document.data( "ui-dialog-overlays" ) ) { 12843 12844 // Prevent use of anchors and inputs 12845 // This doesn't use `_on()` because it is a shared event handler 12846 // across all open modal dialogs. 12847 this.document.on( "focusin.ui-dialog", function( event ) { 12848 if ( isOpening ) { 12849 return; 12850 } 12851 12852 var instance = this._trackingInstances()[ 0 ]; 12853 if ( !instance._allowInteraction( event ) ) { 12854 event.preventDefault(); 12855 instance._focusTabbable(); 12856 } 12857 }.bind( this ) ); 12858 } 12859 12860 this.overlay = $( "<div>" ) 12861 .appendTo( this._appendTo() ); 12862 12863 this._addClass( this.overlay, null, "ui-widget-overlay ui-front" ); 12864 this._on( this.overlay, { 12865 mousedown: "_keepFocus" 12866 } ); 12867 this.document.data( "ui-dialog-overlays", 12868 ( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 ); 12869 }, 12870 12871 _destroyOverlay: function() { 12872 if ( !this.options.modal ) { 12873 return; 12874 } 12875 12876 if ( this.overlay ) { 12877 var overlays = this.document.data( "ui-dialog-overlays" ) - 1; 12878 12879 if ( !overlays ) { 12880 this.document.off( "focusin.ui-dialog" ); 12881 this.document.removeData( "ui-dialog-overlays" ); 12882 } else { 12883 this.document.data( "ui-dialog-overlays", overlays ); 12884 } 12885 12886 this.overlay.remove(); 12887 this.overlay = null; 12888 } 12889 } 12890} ); 12891 12892// DEPRECATED 12893// TODO: switch return back to widget declaration at top of file when this is removed 12894if ( $.uiBackCompat === true ) { 12895 12896 // Backcompat for dialogClass option 12897 $.widget( "ui.dialog", $.ui.dialog, { 12898 options: { 12899 dialogClass: "" 12900 }, 12901 _createWrapper: function() { 12902 this._super(); 12903 this.uiDialog.addClass( this.options.dialogClass ); 12904 }, 12905 _setOption: function( key, value ) { 12906 if ( key === "dialogClass" ) { 12907 this.uiDialog 12908 .removeClass( this.options.dialogClass ) 12909 .addClass( value ); 12910 } 12911 this._superApply( arguments ); 12912 } 12913 } ); 12914} 12915 12916var widgetsDialog = $.ui.dialog; 12917 12918 12919/*! 12920 * jQuery UI Droppable 1.14.0 12921 * https://jqueryui.com 12922 * 12923 * Copyright OpenJS Foundation and other contributors 12924 * Released under the MIT license. 12925 * https://jquery.org/license 12926 */ 12927 12928//>>label: Droppable 12929//>>group: Interactions 12930//>>description: Enables drop targets for draggable elements. 12931//>>docs: https://api.jqueryui.com/droppable/ 12932//>>demos: https://jqueryui.com/droppable/ 12933 12934 12935$.widget( "ui.droppable", { 12936 version: "1.14.0", 12937 widgetEventPrefix: "drop", 12938 options: { 12939 accept: "*", 12940 addClasses: true, 12941 greedy: false, 12942 scope: "default", 12943 tolerance: "intersect", 12944 12945 // Callbacks 12946 activate: null, 12947 deactivate: null, 12948 drop: null, 12949 out: null, 12950 over: null 12951 }, 12952 _create: function() { 12953 12954 var proportions, 12955 o = this.options, 12956 accept = o.accept; 12957 12958 this.isover = false; 12959 this.isout = true; 12960 12961 this.accept = typeof accept === "function" ? accept : function( d ) { 12962 return d.is( accept ); 12963 }; 12964 12965 this.proportions = function( /* valueToWrite */ ) { 12966 if ( arguments.length ) { 12967 12968 // Store the droppable's proportions 12969 proportions = arguments[ 0 ]; 12970 } else { 12971 12972 // Retrieve or derive the droppable's proportions 12973 return proportions ? 12974 proportions : 12975 proportions = { 12976 width: this.element[ 0 ].offsetWidth, 12977 height: this.element[ 0 ].offsetHeight 12978 }; 12979 } 12980 }; 12981 12982 this._addToManager( o.scope ); 12983 12984 if ( o.addClasses ) { 12985 this._addClass( "ui-droppable" ); 12986 } 12987 12988 }, 12989 12990 _addToManager: function( scope ) { 12991 12992 // Add the reference and positions to the manager 12993 $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || []; 12994 $.ui.ddmanager.droppables[ scope ].push( this ); 12995 }, 12996 12997 _splice: function( drop ) { 12998 var i = 0; 12999 for ( ; i < drop.length; i++ ) { 13000 if ( drop[ i ] === this ) { 13001 drop.splice( i, 1 ); 13002 } 13003 } 13004 }, 13005 13006 _destroy: function() { 13007 var drop = $.ui.ddmanager.droppables[ this.options.scope ]; 13008 13009 this._splice( drop ); 13010 }, 13011 13012 _setOption: function( key, value ) { 13013 13014 if ( key === "accept" ) { 13015 this.accept = typeof value === "function" ? value : function( d ) { 13016 return d.is( value ); 13017 }; 13018 } else if ( key === "scope" ) { 13019 var drop = $.ui.ddmanager.droppables[ this.options.scope ]; 13020 13021 this._splice( drop ); 13022 this._addToManager( value ); 13023 } 13024 13025 this._super( key, value ); 13026 }, 13027 13028 _activate: function( event ) { 13029 var draggable = $.ui.ddmanager.current; 13030 13031 this._addActiveClass(); 13032 if ( draggable ) { 13033 this._trigger( "activate", event, this.ui( draggable ) ); 13034 } 13035 }, 13036 13037 _deactivate: function( event ) { 13038 var draggable = $.ui.ddmanager.current; 13039 13040 this._removeActiveClass(); 13041 if ( draggable ) { 13042 this._trigger( "deactivate", event, this.ui( draggable ) ); 13043 } 13044 }, 13045 13046 _over: function( event ) { 13047 13048 var draggable = $.ui.ddmanager.current; 13049 13050 // Bail if draggable and droppable are same element 13051 if ( !draggable || ( draggable.currentItem || 13052 draggable.element )[ 0 ] === this.element[ 0 ] ) { 13053 return; 13054 } 13055 13056 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || 13057 draggable.element ) ) ) { 13058 this._addHoverClass(); 13059 this._trigger( "over", event, this.ui( draggable ) ); 13060 } 13061 13062 }, 13063 13064 _out: function( event ) { 13065 13066 var draggable = $.ui.ddmanager.current; 13067 13068 // Bail if draggable and droppable are same element 13069 if ( !draggable || ( draggable.currentItem || 13070 draggable.element )[ 0 ] === this.element[ 0 ] ) { 13071 return; 13072 } 13073 13074 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || 13075 draggable.element ) ) ) { 13076 this._removeHoverClass(); 13077 this._trigger( "out", event, this.ui( draggable ) ); 13078 } 13079 13080 }, 13081 13082 _drop: function( event, custom ) { 13083 13084 var draggable = custom || $.ui.ddmanager.current, 13085 childrenIntersection = false; 13086 13087 // Bail if draggable and droppable are same element 13088 if ( !draggable || ( draggable.currentItem || 13089 draggable.element )[ 0 ] === this.element[ 0 ] ) { 13090 return false; 13091 } 13092 13093 this.element 13094 .find( ":data(ui-droppable)" ) 13095 .not( ".ui-draggable-dragging" ) 13096 .each( function() { 13097 var inst = $( this ).droppable( "instance" ); 13098 if ( 13099 inst.options.greedy && 13100 !inst.options.disabled && 13101 inst.options.scope === draggable.options.scope && 13102 inst.accept.call( 13103 inst.element[ 0 ], ( draggable.currentItem || draggable.element ) 13104 ) && 13105 $.ui.intersect( 13106 draggable, 13107 $.extend( inst, { offset: inst.element.offset() } ), 13108 inst.options.tolerance, event 13109 ) 13110 ) { 13111 childrenIntersection = true; 13112 return false; 13113 } 13114 } ); 13115 if ( childrenIntersection ) { 13116 return false; 13117 } 13118 13119 if ( this.accept.call( this.element[ 0 ], 13120 ( draggable.currentItem || draggable.element ) ) ) { 13121 this._removeActiveClass(); 13122 this._removeHoverClass(); 13123 13124 this._trigger( "drop", event, this.ui( draggable ) ); 13125 return this.element; 13126 } 13127 13128 return false; 13129 13130 }, 13131 13132 ui: function( c ) { 13133 return { 13134 draggable: ( c.currentItem || c.element ), 13135 helper: c.helper, 13136 position: c.position, 13137 offset: c.positionAbs 13138 }; 13139 }, 13140 13141 // Extension points just to make backcompat sane and avoid duplicating logic 13142 // TODO: Remove in 1.14 along with call to it below 13143 _addHoverClass: function() { 13144 this._addClass( "ui-droppable-hover" ); 13145 }, 13146 13147 _removeHoverClass: function() { 13148 this._removeClass( "ui-droppable-hover" ); 13149 }, 13150 13151 _addActiveClass: function() { 13152 this._addClass( "ui-droppable-active" ); 13153 }, 13154 13155 _removeActiveClass: function() { 13156 this._removeClass( "ui-droppable-active" ); 13157 } 13158} ); 13159 13160$.ui.intersect = ( function() { 13161 function isOverAxis( x, reference, size ) { 13162 return ( x >= reference ) && ( x < ( reference + size ) ); 13163 } 13164 13165 return function( draggable, droppable, toleranceMode, event ) { 13166 13167 if ( !droppable.offset ) { 13168 return false; 13169 } 13170 13171 var x1 = ( draggable.positionAbs || 13172 draggable.position.absolute ).left + draggable.margins.left, 13173 y1 = ( draggable.positionAbs || 13174 draggable.position.absolute ).top + draggable.margins.top, 13175 x2 = x1 + draggable.helperProportions.width, 13176 y2 = y1 + draggable.helperProportions.height, 13177 l = droppable.offset.left, 13178 t = droppable.offset.top, 13179 r = l + droppable.proportions().width, 13180 b = t + droppable.proportions().height; 13181 13182 switch ( toleranceMode ) { 13183 case "fit": 13184 return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b ); 13185 case "intersect": 13186 return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half 13187 x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half 13188 t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half 13189 y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half 13190 case "pointer": 13191 return isOverAxis( event.pageY, t, droppable.proportions().height ) && 13192 isOverAxis( event.pageX, l, droppable.proportions().width ); 13193 case "touch": 13194 return ( 13195 ( y1 >= t && y1 <= b ) || // Top edge touching 13196 ( y2 >= t && y2 <= b ) || // Bottom edge touching 13197 ( y1 < t && y2 > b ) // Surrounded vertically 13198 ) && ( 13199 ( x1 >= l && x1 <= r ) || // Left edge touching 13200 ( x2 >= l && x2 <= r ) || // Right edge touching 13201 ( x1 < l && x2 > r ) // Surrounded horizontally 13202 ); 13203 default: 13204 return false; 13205 } 13206 }; 13207} )(); 13208 13209/* 13210 This manager tracks offsets of draggables and droppables 13211*/ 13212$.ui.ddmanager = { 13213 current: null, 13214 droppables: { "default": [] }, 13215 prepareOffsets: function( t, event ) { 13216 13217 var i, j, 13218 m = $.ui.ddmanager.droppables[ t.options.scope ] || [], 13219 type = event ? event.type : null, // workaround for #2317 13220 list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack(); 13221 13222 droppablesLoop: for ( i = 0; i < m.length; i++ ) { 13223 13224 // No disabled and non-accepted 13225 if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], 13226 ( t.currentItem || t.element ) ) ) ) { 13227 continue; 13228 } 13229 13230 // Filter out elements in the current dragged item 13231 for ( j = 0; j < list.length; j++ ) { 13232 if ( list[ j ] === m[ i ].element[ 0 ] ) { 13233 m[ i ].proportions().height = 0; 13234 continue droppablesLoop; 13235 } 13236 } 13237 13238 m[ i ].visible = m[ i ].element.css( "display" ) !== "none"; 13239 if ( !m[ i ].visible ) { 13240 continue; 13241 } 13242 13243 // Activate the droppable if used directly from draggables 13244 if ( type === "mousedown" ) { 13245 m[ i ]._activate.call( m[ i ], event ); 13246 } 13247 13248 m[ i ].offset = m[ i ].element.offset(); 13249 m[ i ].proportions( { 13250 width: m[ i ].element[ 0 ].offsetWidth, 13251 height: m[ i ].element[ 0 ].offsetHeight 13252 } ); 13253 13254 } 13255 13256 }, 13257 drop: function( draggable, event ) { 13258 13259 var dropped = false; 13260 13261 // Create a copy of the droppables in case the list changes during the drop (#9116) 13262 $.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() { 13263 13264 if ( !this.options ) { 13265 return; 13266 } 13267 if ( !this.options.disabled && this.visible && 13268 $.ui.intersect( draggable, this, this.options.tolerance, event ) ) { 13269 dropped = this._drop.call( this, event ) || dropped; 13270 } 13271 13272 if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ], 13273 ( draggable.currentItem || draggable.element ) ) ) { 13274 this.isout = true; 13275 this.isover = false; 13276 this._deactivate.call( this, event ); 13277 } 13278 13279 } ); 13280 return dropped; 13281 13282 }, 13283 dragStart: function( draggable, event ) { 13284 13285 // Listen for scrolling so that if the dragging causes scrolling the position of the 13286 // droppables can be recalculated (see #5003) 13287 draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() { 13288 if ( !draggable.options.refreshPositions ) { 13289 $.ui.ddmanager.prepareOffsets( draggable, event ); 13290 } 13291 } ); 13292 }, 13293 drag: function( draggable, event ) { 13294 13295 // If you have a highly dynamic page, you might try this option. It renders positions 13296 // every time you move the mouse. 13297 if ( draggable.options.refreshPositions ) { 13298 $.ui.ddmanager.prepareOffsets( draggable, event ); 13299 } 13300 13301 // Run through all droppables and check their positions based on specific tolerance options 13302 $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() { 13303 13304 if ( this.options.disabled || this.greedyChild || !this.visible ) { 13305 return; 13306 } 13307 13308 var parentInstance, scope, parent, 13309 intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ), 13310 c = !intersects && this.isover ? 13311 "isout" : 13312 ( intersects && !this.isover ? "isover" : null ); 13313 if ( !c ) { 13314 return; 13315 } 13316 13317 if ( this.options.greedy ) { 13318 13319 // find droppable parents with same scope 13320 scope = this.options.scope; 13321 parent = this.element.parents( ":data(ui-droppable)" ).filter( function() { 13322 return $( this ).droppable( "instance" ).options.scope === scope; 13323 } ); 13324 13325 if ( parent.length ) { 13326 parentInstance = $( parent[ 0 ] ).droppable( "instance" ); 13327 parentInstance.greedyChild = ( c === "isover" ); 13328 } 13329 } 13330 13331 // We just moved into a greedy child 13332 if ( parentInstance && c === "isover" ) { 13333 parentInstance.isover = false; 13334 parentInstance.isout = true; 13335 parentInstance._out.call( parentInstance, event ); 13336 } 13337 13338 this[ c ] = true; 13339 this[ c === "isout" ? "isover" : "isout" ] = false; 13340 this[ c === "isover" ? "_over" : "_out" ].call( this, event ); 13341 13342 // We just moved out of a greedy child 13343 if ( parentInstance && c === "isout" ) { 13344 parentInstance.isout = false; 13345 parentInstance.isover = true; 13346 parentInstance._over.call( parentInstance, event ); 13347 } 13348 } ); 13349 13350 }, 13351 dragStop: function( draggable, event ) { 13352 draggable.element.parentsUntil( "body" ).off( "scroll.droppable" ); 13353 13354 // Call prepareOffsets one final time since IE does not fire return scroll events when 13355 // overflow was caused by drag (see #5003) 13356 if ( !draggable.options.refreshPositions ) { 13357 $.ui.ddmanager.prepareOffsets( draggable, event ); 13358 } 13359 } 13360}; 13361 13362// DEPRECATED 13363// TODO: switch return back to widget declaration at top of file when this is removed 13364if ( $.uiBackCompat === true ) { 13365 13366 // Backcompat for activeClass and hoverClass options 13367 $.widget( "ui.droppable", $.ui.droppable, { 13368 options: { 13369 hoverClass: false, 13370 activeClass: false 13371 }, 13372 _addActiveClass: function() { 13373 this._super(); 13374 if ( this.options.activeClass ) { 13375 this.element.addClass( this.options.activeClass ); 13376 } 13377 }, 13378 _removeActiveClass: function() { 13379 this._super(); 13380 if ( this.options.activeClass ) { 13381 this.element.removeClass( this.options.activeClass ); 13382 } 13383 }, 13384 _addHoverClass: function() { 13385 this._super(); 13386 if ( this.options.hoverClass ) { 13387 this.element.addClass( this.options.hoverClass ); 13388 } 13389 }, 13390 _removeHoverClass: function() { 13391 this._super(); 13392 if ( this.options.hoverClass ) { 13393 this.element.removeClass( this.options.hoverClass ); 13394 } 13395 } 13396 } ); 13397} 13398 13399var widgetsDroppable = $.ui.droppable; 13400 13401 13402/*! 13403 * jQuery UI Progressbar 1.14.0 13404 * https://jqueryui.com 13405 * 13406 * Copyright OpenJS Foundation and other contributors 13407 * Released under the MIT license. 13408 * https://jquery.org/license 13409 */ 13410 13411//>>label: Progressbar 13412//>>group: Widgets 13413/* eslint-disable max-len */ 13414//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators. 13415/* eslint-enable max-len */ 13416//>>docs: https://api.jqueryui.com/progressbar/ 13417//>>demos: https://jqueryui.com/progressbar/ 13418//>>css.structure: ../../themes/base/core.css 13419//>>css.structure: ../../themes/base/progressbar.css 13420//>>css.theme: ../../themes/base/theme.css 13421 13422 13423var widgetsProgressbar = $.widget( "ui.progressbar", { 13424 version: "1.14.0", 13425 options: { 13426 classes: { 13427 "ui-progressbar": "ui-corner-all", 13428 "ui-progressbar-value": "ui-corner-left", 13429 "ui-progressbar-complete": "ui-corner-right" 13430 }, 13431 max: 100, 13432 value: 0, 13433 13434 change: null, 13435 complete: null 13436 }, 13437 13438 min: 0, 13439 13440 _create: function() { 13441 13442 // Constrain initial value 13443 this.oldValue = this.options.value = this._constrainedValue(); 13444 13445 this.element.attr( { 13446 13447 // Only set static values; aria-valuenow and aria-valuemax are 13448 // set inside _refreshValue() 13449 role: "progressbar", 13450 "aria-valuemin": this.min 13451 } ); 13452 this._addClass( "ui-progressbar", "ui-widget ui-widget-content" ); 13453 13454 this.valueDiv = $( "<div>" ).appendTo( this.element ); 13455 this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" ); 13456 this._refreshValue(); 13457 }, 13458 13459 _destroy: function() { 13460 this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" ); 13461 13462 this.valueDiv.remove(); 13463 }, 13464 13465 value: function( newValue ) { 13466 if ( newValue === undefined ) { 13467 return this.options.value; 13468 } 13469 13470 this.options.value = this._constrainedValue( newValue ); 13471 this._refreshValue(); 13472 }, 13473 13474 _constrainedValue: function( newValue ) { 13475 if ( newValue === undefined ) { 13476 newValue = this.options.value; 13477 } 13478 13479 this.indeterminate = newValue === false; 13480 13481 // Sanitize value 13482 if ( typeof newValue !== "number" ) { 13483 newValue = 0; 13484 } 13485 13486 return this.indeterminate ? false : 13487 Math.min( this.options.max, Math.max( this.min, newValue ) ); 13488 }, 13489 13490 _setOptions: function( options ) { 13491 13492 // Ensure "value" option is set after other values (like max) 13493 var value = options.value; 13494 delete options.value; 13495 13496 this._super( options ); 13497 13498 this.options.value = this._constrainedValue( value ); 13499 this._refreshValue(); 13500 }, 13501 13502 _setOption: function( key, value ) { 13503 if ( key === "max" ) { 13504 13505 // Don't allow a max less than min 13506 value = Math.max( this.min, value ); 13507 } 13508 this._super( key, value ); 13509 }, 13510 13511 _setOptionDisabled: function( value ) { 13512 this._super( value ); 13513 13514 this.element.attr( "aria-disabled", value ); 13515 this._toggleClass( null, "ui-state-disabled", !!value ); 13516 }, 13517 13518 _percentage: function() { 13519 return this.indeterminate ? 13520 100 : 13521 100 * ( this.options.value - this.min ) / ( this.options.max - this.min ); 13522 }, 13523 13524 _refreshValue: function() { 13525 var value = this.options.value, 13526 percentage = this._percentage(); 13527 13528 this.valueDiv 13529 .toggle( this.indeterminate || value > this.min ) 13530 .width( percentage.toFixed( 0 ) + "%" ); 13531 13532 this 13533 ._toggleClass( this.valueDiv, "ui-progressbar-complete", null, 13534 value === this.options.max ) 13535 ._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate ); 13536 13537 if ( this.indeterminate ) { 13538 this.element.removeAttr( "aria-valuenow" ); 13539 if ( !this.overlayDiv ) { 13540 this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv ); 13541 this._addClass( this.overlayDiv, "ui-progressbar-overlay" ); 13542 } 13543 } else { 13544 this.element.attr( { 13545 "aria-valuemax": this.options.max, 13546 "aria-valuenow": value 13547 } ); 13548 if ( this.overlayDiv ) { 13549 this.overlayDiv.remove(); 13550 this.overlayDiv = null; 13551 } 13552 } 13553 13554 if ( this.oldValue !== value ) { 13555 this.oldValue = value; 13556 this._trigger( "change" ); 13557 } 13558 if ( value === this.options.max ) { 13559 this._trigger( "complete" ); 13560 } 13561 } 13562} ); 13563 13564 13565/*! 13566 * jQuery UI Selectable 1.14.0 13567 * https://jqueryui.com 13568 * 13569 * Copyright OpenJS Foundation and other contributors 13570 * Released under the MIT license. 13571 * https://jquery.org/license 13572 */ 13573 13574//>>label: Selectable 13575//>>group: Interactions 13576//>>description: Allows groups of elements to be selected with the mouse. 13577//>>docs: https://api.jqueryui.com/selectable/ 13578//>>demos: https://jqueryui.com/selectable/ 13579//>>css.structure: ../../themes/base/selectable.css 13580 13581 13582var widgetsSelectable = $.widget( "ui.selectable", $.ui.mouse, { 13583 version: "1.14.0", 13584 options: { 13585 appendTo: "body", 13586 autoRefresh: true, 13587 distance: 0, 13588 filter: "*", 13589 tolerance: "touch", 13590 13591 // Callbacks 13592 selected: null, 13593 selecting: null, 13594 start: null, 13595 stop: null, 13596 unselected: null, 13597 unselecting: null 13598 }, 13599 _create: function() { 13600 var that = this; 13601 13602 this._addClass( "ui-selectable" ); 13603 13604 this.dragged = false; 13605 13606 // Cache selectee children based on filter 13607 this.refresh = function() { 13608 that.elementPos = $( that.element[ 0 ] ).offset(); 13609 that.selectees = $( that.options.filter, that.element[ 0 ] ); 13610 that._addClass( that.selectees, "ui-selectee" ); 13611 that.selectees.each( function() { 13612 var $this = $( this ), 13613 selecteeOffset = $this.offset(), 13614 pos = { 13615 left: selecteeOffset.left - that.elementPos.left, 13616 top: selecteeOffset.top - that.elementPos.top 13617 }; 13618 $.data( this, "selectable-item", { 13619 element: this, 13620 $element: $this, 13621 left: pos.left, 13622 top: pos.top, 13623 right: pos.left + $this.outerWidth(), 13624 bottom: pos.top + $this.outerHeight(), 13625 startselected: false, 13626 selected: $this.hasClass( "ui-selected" ), 13627 selecting: $this.hasClass( "ui-selecting" ), 13628 unselecting: $this.hasClass( "ui-unselecting" ) 13629 } ); 13630 } ); 13631 }; 13632 this.refresh(); 13633 13634 this._mouseInit(); 13635 13636 this.helper = $( "<div>" ); 13637 this._addClass( this.helper, "ui-selectable-helper" ); 13638 }, 13639 13640 _destroy: function() { 13641 this.selectees.removeData( "selectable-item" ); 13642 this._mouseDestroy(); 13643 }, 13644 13645 _mouseStart: function( event ) { 13646 var that = this, 13647 options = this.options; 13648 13649 this.opos = [ event.pageX, event.pageY ]; 13650 this.elementPos = $( this.element[ 0 ] ).offset(); 13651 13652 if ( this.options.disabled ) { 13653 return; 13654 } 13655 13656 this.selectees = $( options.filter, this.element[ 0 ] ); 13657 13658 this._trigger( "start", event ); 13659 13660 $( options.appendTo ).append( this.helper ); 13661 13662 // position helper (lasso) 13663 this.helper.css( { 13664 "left": event.pageX, 13665 "top": event.pageY, 13666 "width": 0, 13667 "height": 0 13668 } ); 13669 13670 if ( options.autoRefresh ) { 13671 this.refresh(); 13672 } 13673 13674 this.selectees.filter( ".ui-selected" ).each( function() { 13675 var selectee = $.data( this, "selectable-item" ); 13676 selectee.startselected = true; 13677 if ( !event.metaKey && !event.ctrlKey ) { 13678 that._removeClass( selectee.$element, "ui-selected" ); 13679 selectee.selected = false; 13680 that._addClass( selectee.$element, "ui-unselecting" ); 13681 selectee.unselecting = true; 13682 13683 // selectable UNSELECTING callback 13684 that._trigger( "unselecting", event, { 13685 unselecting: selectee.element 13686 } ); 13687 } 13688 } ); 13689 13690 $( event.target ).parents().addBack().each( function() { 13691 var doSelect, 13692 selectee = $.data( this, "selectable-item" ); 13693 if ( selectee ) { 13694 doSelect = ( !event.metaKey && !event.ctrlKey ) || 13695 !selectee.$element.hasClass( "ui-selected" ); 13696 that._removeClass( selectee.$element, doSelect ? "ui-unselecting" : "ui-selected" ) 13697 ._addClass( selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting" ); 13698 selectee.unselecting = !doSelect; 13699 selectee.selecting = doSelect; 13700 selectee.selected = doSelect; 13701 13702 // selectable (UN)SELECTING callback 13703 if ( doSelect ) { 13704 that._trigger( "selecting", event, { 13705 selecting: selectee.element 13706 } ); 13707 } else { 13708 that._trigger( "unselecting", event, { 13709 unselecting: selectee.element 13710 } ); 13711 } 13712 return false; 13713 } 13714 } ); 13715 13716 }, 13717 13718 _mouseDrag: function( event ) { 13719 13720 this.dragged = true; 13721 13722 if ( this.options.disabled ) { 13723 return; 13724 } 13725 13726 var tmp, 13727 that = this, 13728 options = this.options, 13729 x1 = this.opos[ 0 ], 13730 y1 = this.opos[ 1 ], 13731 x2 = event.pageX, 13732 y2 = event.pageY; 13733 13734 if ( x1 > x2 ) { 13735 tmp = x2; x2 = x1; x1 = tmp; 13736 } 13737 if ( y1 > y2 ) { 13738 tmp = y2; y2 = y1; y1 = tmp; 13739 } 13740 this.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } ); 13741 13742 this.selectees.each( function() { 13743 var selectee = $.data( this, "selectable-item" ), 13744 hit = false, 13745 offset = {}; 13746 13747 //prevent helper from being selected if appendTo: selectable 13748 if ( !selectee || selectee.element === that.element[ 0 ] ) { 13749 return; 13750 } 13751 13752 offset.left = selectee.left + that.elementPos.left; 13753 offset.right = selectee.right + that.elementPos.left; 13754 offset.top = selectee.top + that.elementPos.top; 13755 offset.bottom = selectee.bottom + that.elementPos.top; 13756 13757 if ( options.tolerance === "touch" ) { 13758 hit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 || 13759 offset.bottom < y1 ) ); 13760 } else if ( options.tolerance === "fit" ) { 13761 hit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 && 13762 offset.bottom < y2 ); 13763 } 13764 13765 if ( hit ) { 13766 13767 // SELECT 13768 if ( selectee.selected ) { 13769 that._removeClass( selectee.$element, "ui-selected" ); 13770 selectee.selected = false; 13771 } 13772 if ( selectee.unselecting ) { 13773 that._removeClass( selectee.$element, "ui-unselecting" ); 13774 selectee.unselecting = false; 13775 } 13776 if ( !selectee.selecting ) { 13777 that._addClass( selectee.$element, "ui-selecting" ); 13778 selectee.selecting = true; 13779 13780 // selectable SELECTING callback 13781 that._trigger( "selecting", event, { 13782 selecting: selectee.element 13783 } ); 13784 } 13785 } else { 13786 13787 // UNSELECT 13788 if ( selectee.selecting ) { 13789 if ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) { 13790 that._removeClass( selectee.$element, "ui-selecting" ); 13791 selectee.selecting = false; 13792 that._addClass( selectee.$element, "ui-selected" ); 13793 selectee.selected = true; 13794 } else { 13795 that._removeClass( selectee.$element, "ui-selecting" ); 13796 selectee.selecting = false; 13797 if ( selectee.startselected ) { 13798 that._addClass( selectee.$element, "ui-unselecting" ); 13799 selectee.unselecting = true; 13800 } 13801 13802 // selectable UNSELECTING callback 13803 that._trigger( "unselecting", event, { 13804 unselecting: selectee.element 13805 } ); 13806 } 13807 } 13808 if ( selectee.selected ) { 13809 if ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) { 13810 that._removeClass( selectee.$element, "ui-selected" ); 13811 selectee.selected = false; 13812 13813 that._addClass( selectee.$element, "ui-unselecting" ); 13814 selectee.unselecting = true; 13815 13816 // selectable UNSELECTING callback 13817 that._trigger( "unselecting", event, { 13818 unselecting: selectee.element 13819 } ); 13820 } 13821 } 13822 } 13823 } ); 13824 13825 return false; 13826 }, 13827 13828 _mouseStop: function( event ) { 13829 var that = this; 13830 13831 this.dragged = false; 13832 13833 $( ".ui-unselecting", this.element[ 0 ] ).each( function() { 13834 var selectee = $.data( this, "selectable-item" ); 13835 that._removeClass( selectee.$element, "ui-unselecting" ); 13836 selectee.unselecting = false; 13837 selectee.startselected = false; 13838 that._trigger( "unselected", event, { 13839 unselected: selectee.element 13840 } ); 13841 } ); 13842 $( ".ui-selecting", this.element[ 0 ] ).each( function() { 13843 var selectee = $.data( this, "selectable-item" ); 13844 that._removeClass( selectee.$element, "ui-selecting" ) 13845 ._addClass( selectee.$element, "ui-selected" ); 13846 selectee.selecting = false; 13847 selectee.selected = true; 13848 selectee.startselected = true; 13849 that._trigger( "selected", event, { 13850 selected: selectee.element 13851 } ); 13852 } ); 13853 this._trigger( "stop", event ); 13854 13855 this.helper.remove(); 13856 13857 return false; 13858 } 13859 13860} ); 13861 13862 13863/*! 13864 * jQuery UI Selectmenu 1.14.0 13865 * https://jqueryui.com 13866 * 13867 * Copyright OpenJS Foundation and other contributors 13868 * Released under the MIT license. 13869 * https://jquery.org/license 13870 */ 13871 13872//>>label: Selectmenu 13873//>>group: Widgets 13874/* eslint-disable max-len */ 13875//>>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. 13876/* eslint-enable max-len */ 13877//>>docs: https://api.jqueryui.com/selectmenu/ 13878//>>demos: https://jqueryui.com/selectmenu/ 13879//>>css.structure: ../../themes/base/core.css 13880//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css 13881//>>css.theme: ../../themes/base/theme.css 13882 13883 13884var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, { 13885 version: "1.14.0", 13886 defaultElement: "<select>", 13887 options: { 13888 appendTo: null, 13889 classes: { 13890 "ui-selectmenu-button-open": "ui-corner-top", 13891 "ui-selectmenu-button-closed": "ui-corner-all" 13892 }, 13893 disabled: null, 13894 icons: { 13895 button: "ui-icon-triangle-1-s" 13896 }, 13897 position: { 13898 my: "left top", 13899 at: "left bottom", 13900 collision: "none" 13901 }, 13902 width: false, 13903 13904 // Callbacks 13905 change: null, 13906 close: null, 13907 focus: null, 13908 open: null, 13909 select: null 13910 }, 13911 13912 _create: function() { 13913 var selectmenuId = this.element.uniqueId().attr( "id" ); 13914 this.ids = { 13915 element: selectmenuId, 13916 button: selectmenuId + "-button", 13917 menu: selectmenuId + "-menu" 13918 }; 13919 13920 this._drawButton(); 13921 this._drawMenu(); 13922 this._bindFormResetHandler(); 13923 13924 this._rendered = false; 13925 this.menuItems = $(); 13926 }, 13927 13928 _drawButton: function() { 13929 var icon, 13930 that = this, 13931 item = this._parseOption( 13932 this.element.find( "option:selected" ), 13933 this.element[ 0 ].selectedIndex 13934 ); 13935 13936 // Associate existing label with the new button 13937 this.labels = this.element.labels().attr( "for", this.ids.button ); 13938 this._on( this.labels, { 13939 click: function( event ) { 13940 this.button.trigger( "focus" ); 13941 event.preventDefault(); 13942 } 13943 } ); 13944 13945 // Hide original select element 13946 this.element.hide(); 13947 13948 // Create button 13949 this.button = $( "<span>", { 13950 tabindex: this.options.disabled ? -1 : 0, 13951 id: this.ids.button, 13952 role: "combobox", 13953 "aria-expanded": "false", 13954 "aria-autocomplete": "list", 13955 "aria-owns": this.ids.menu, 13956 "aria-haspopup": "true", 13957 title: this.element.attr( "title" ) 13958 } ) 13959 .insertAfter( this.element ); 13960 13961 this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed", 13962 "ui-button ui-widget" ); 13963 13964 icon = $( "<span>" ).appendTo( this.button ); 13965 this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button ); 13966 this.buttonItem = this._renderButtonItem( item ) 13967 .appendTo( this.button ); 13968 13969 if ( this.options.width !== false ) { 13970 this._resizeButton(); 13971 } 13972 13973 this._on( this.button, this._buttonEvents ); 13974 this.button.one( "focusin", function() { 13975 13976 // Delay rendering the menu items until the button receives focus. 13977 // The menu may have already been rendered via a programmatic open. 13978 if ( !that._rendered ) { 13979 that._refreshMenu(); 13980 } 13981 } ); 13982 }, 13983 13984 _drawMenu: function() { 13985 var that = this; 13986 13987 // Create menu 13988 this.menu = $( "<ul>", { 13989 "aria-hidden": "true", 13990 "aria-labelledby": this.ids.button, 13991 id: this.ids.menu 13992 } ); 13993 13994 // Wrap menu 13995 this.menuWrap = $( "<div>" ).append( this.menu ); 13996 this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" ); 13997 this.menuWrap.appendTo( this._appendTo() ); 13998 13999 // Initialize menu widget 14000 this.menuInstance = this.menu 14001 .menu( { 14002 classes: { 14003 "ui-menu": "ui-corner-bottom" 14004 }, 14005 role: "listbox", 14006 select: function( event, ui ) { 14007 event.preventDefault(); 14008 that._select( ui.item.data( "ui-selectmenu-item" ), event ); 14009 }, 14010 focus: function( event, ui ) { 14011 var item = ui.item.data( "ui-selectmenu-item" ); 14012 14013 // Prevent inital focus from firing and check if its a newly focused item 14014 if ( that.focusIndex != null && item.index !== that.focusIndex ) { 14015 that._trigger( "focus", event, { item: item } ); 14016 if ( !that.isOpen ) { 14017 that._select( item, event ); 14018 } 14019 } 14020 that.focusIndex = item.index; 14021 14022 that.button.attr( "aria-activedescendant", 14023 that.menuItems.eq( item.index ).attr( "id" ) ); 14024 } 14025 } ) 14026 .menu( "instance" ); 14027 14028 // Don't close the menu on mouseleave 14029 this.menuInstance._off( this.menu, "mouseleave" ); 14030 14031 // Cancel the menu's collapseAll on document click 14032 this.menuInstance._closeOnDocumentClick = function() { 14033 return false; 14034 }; 14035 14036 // Selects often contain empty items, but never contain dividers 14037 this.menuInstance._isDivider = function() { 14038 return false; 14039 }; 14040 }, 14041 14042 refresh: function() { 14043 this._refreshMenu(); 14044 this.buttonItem.replaceWith( 14045 this.buttonItem = this._renderButtonItem( 14046 14047 // Fall back to an empty object in case there are no options 14048 this._getSelectedItem().data( "ui-selectmenu-item" ) || {} 14049 ) 14050 ); 14051 if ( this.options.width === null ) { 14052 this._resizeButton(); 14053 } 14054 }, 14055 14056 _refreshMenu: function() { 14057 var item, 14058 options = this.element.find( "option" ); 14059 14060 this.menu.empty(); 14061 14062 this._parseOptions( options ); 14063 this._renderMenu( this.menu, this.items ); 14064 14065 this.menuInstance.refresh(); 14066 this.menuItems = this.menu.find( "li" ) 14067 .not( ".ui-selectmenu-optgroup" ) 14068 .find( ".ui-menu-item-wrapper" ); 14069 14070 this._rendered = true; 14071 14072 if ( !options.length ) { 14073 return; 14074 } 14075 14076 item = this._getSelectedItem(); 14077 14078 // Update the menu to have the correct item focused 14079 this.menuInstance.focus( null, item ); 14080 this._setAria( item.data( "ui-selectmenu-item" ) ); 14081 14082 // Set disabled state 14083 this._setOption( "disabled", this.element.prop( "disabled" ) ); 14084 }, 14085 14086 open: function( event ) { 14087 if ( this.options.disabled ) { 14088 return; 14089 } 14090 14091 // If this is the first time the menu is being opened, render the items 14092 if ( !this._rendered ) { 14093 this._refreshMenu(); 14094 } else { 14095 14096 // Menu clears focus on close, reset focus to selected item 14097 this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" ); 14098 this.menuInstance.focus( null, this._getSelectedItem() ); 14099 } 14100 14101 // If there are no options, don't open the menu 14102 if ( !this.menuItems.length ) { 14103 return; 14104 } 14105 14106 this.isOpen = true; 14107 this._toggleAttr(); 14108 this._resizeMenu(); 14109 this._position(); 14110 14111 this._on( this.document, this._documentClick ); 14112 14113 this._trigger( "open", event ); 14114 }, 14115 14116 _position: function() { 14117 this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) ); 14118 }, 14119 14120 close: function( event ) { 14121 if ( !this.isOpen ) { 14122 return; 14123 } 14124 14125 this.isOpen = false; 14126 this._toggleAttr(); 14127 14128 this.range = null; 14129 this._off( this.document ); 14130 14131 this._trigger( "close", event ); 14132 }, 14133 14134 widget: function() { 14135 return this.button; 14136 }, 14137 14138 menuWidget: function() { 14139 return this.menu; 14140 }, 14141 14142 _renderButtonItem: function( item ) { 14143 var buttonItem = $( "<span>" ); 14144 14145 this._setText( buttonItem, item.label ); 14146 this._addClass( buttonItem, "ui-selectmenu-text" ); 14147 14148 return buttonItem; 14149 }, 14150 14151 _renderMenu: function( ul, items ) { 14152 var that = this, 14153 currentOptgroup = ""; 14154 14155 $.each( items, function( index, item ) { 14156 var li; 14157 14158 if ( item.optgroup !== currentOptgroup ) { 14159 li = $( "<li>", { 14160 text: item.optgroup 14161 } ); 14162 that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" + 14163 ( item.element.parent( "optgroup" ).prop( "disabled" ) ? 14164 " ui-state-disabled" : 14165 "" ) ); 14166 14167 li.appendTo( ul ); 14168 14169 currentOptgroup = item.optgroup; 14170 } 14171 14172 that._renderItemData( ul, item ); 14173 } ); 14174 }, 14175 14176 _renderItemData: function( ul, item ) { 14177 return this._renderItem( ul, item ).data( "ui-selectmenu-item", item ); 14178 }, 14179 14180 _renderItem: function( ul, item ) { 14181 var li = $( "<li>" ), 14182 wrapper = $( "<div>", { 14183 title: item.element.attr( "title" ) 14184 } ); 14185 14186 if ( item.disabled ) { 14187 this._addClass( li, null, "ui-state-disabled" ); 14188 } 14189 14190 if ( item.hidden ) { 14191 li.prop( "hidden", true ); 14192 } else { 14193 this._setText( wrapper, item.label ); 14194 } 14195 14196 return li.append( wrapper ).appendTo( ul ); 14197 }, 14198 14199 _setText: function( element, value ) { 14200 if ( value ) { 14201 element.text( value ); 14202 } else { 14203 element.html( " " ); 14204 } 14205 }, 14206 14207 _move: function( direction, event ) { 14208 var item, next, 14209 filter = ".ui-menu-item"; 14210 14211 if ( this.isOpen ) { 14212 item = this.menuItems.eq( this.focusIndex ).parent( "li" ); 14213 } else { 14214 item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" ); 14215 filter += ":not(.ui-state-disabled)"; 14216 } 14217 14218 if ( direction === "first" || direction === "last" ) { 14219 next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 ); 14220 } else { 14221 next = item[ direction + "All" ]( filter ).eq( 0 ); 14222 } 14223 14224 if ( next.length ) { 14225 this.menuInstance.focus( event, next ); 14226 } 14227 }, 14228 14229 _getSelectedItem: function() { 14230 return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" ); 14231 }, 14232 14233 _toggle: function( event ) { 14234 this[ this.isOpen ? "close" : "open" ]( event ); 14235 }, 14236 14237 _setSelection: function() { 14238 var selection; 14239 14240 if ( !this.range ) { 14241 return; 14242 } 14243 14244 selection = window.getSelection(); 14245 selection.removeAllRanges(); 14246 selection.addRange( this.range ); 14247 }, 14248 14249 _documentClick: { 14250 mousedown: function( event ) { 14251 if ( !this.isOpen ) { 14252 return; 14253 } 14254 14255 if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" + 14256 CSS.escape( this.ids.button ) ).length ) { 14257 this.close( event ); 14258 } 14259 } 14260 }, 14261 14262 _buttonEvents: { 14263 14264 // Prevent text selection from being reset when interacting with the selectmenu (#10144) 14265 mousedown: function() { 14266 var selection = window.getSelection(); 14267 if ( selection.rangeCount ) { 14268 this.range = selection.getRangeAt( 0 ); 14269 } 14270 }, 14271 14272 click: function( event ) { 14273 this._setSelection(); 14274 this._toggle( event ); 14275 }, 14276 14277 keydown: function( event ) { 14278 var preventDefault = true; 14279 switch ( event.keyCode ) { 14280 case $.ui.keyCode.TAB: 14281 case $.ui.keyCode.ESCAPE: 14282 this.close( event ); 14283 preventDefault = false; 14284 break; 14285 case $.ui.keyCode.ENTER: 14286 if ( this.isOpen ) { 14287 this._selectFocusedItem( event ); 14288 } 14289 break; 14290 case $.ui.keyCode.UP: 14291 if ( event.altKey ) { 14292 this._toggle( event ); 14293 } else { 14294 this._move( "prev", event ); 14295 } 14296 break; 14297 case $.ui.keyCode.DOWN: 14298 if ( event.altKey ) { 14299 this._toggle( event ); 14300 } else { 14301 this._move( "next", event ); 14302 } 14303 break; 14304 case $.ui.keyCode.SPACE: 14305 if ( this.isOpen ) { 14306 this._selectFocusedItem( event ); 14307 } else { 14308 this._toggle( event ); 14309 } 14310 break; 14311 case $.ui.keyCode.LEFT: 14312 this._move( "prev", event ); 14313 break; 14314 case $.ui.keyCode.RIGHT: 14315 this._move( "next", event ); 14316 break; 14317 case $.ui.keyCode.HOME: 14318 case $.ui.keyCode.PAGE_UP: 14319 this._move( "first", event ); 14320 break; 14321 case $.ui.keyCode.END: 14322 case $.ui.keyCode.PAGE_DOWN: 14323 this._move( "last", event ); 14324 break; 14325 default: 14326 this.menu.trigger( event ); 14327 preventDefault = false; 14328 } 14329 14330 if ( preventDefault ) { 14331 event.preventDefault(); 14332 } 14333 } 14334 }, 14335 14336 _selectFocusedItem: function( event ) { 14337 var item = this.menuItems.eq( this.focusIndex ).parent( "li" ); 14338 if ( !item.hasClass( "ui-state-disabled" ) ) { 14339 this._select( item.data( "ui-selectmenu-item" ), event ); 14340 } 14341 }, 14342 14343 _select: function( item, event ) { 14344 var oldIndex = this.element[ 0 ].selectedIndex; 14345 14346 // Change native select element 14347 this.element[ 0 ].selectedIndex = item.index; 14348 this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) ); 14349 this._setAria( item ); 14350 this._trigger( "select", event, { item: item } ); 14351 14352 if ( item.index !== oldIndex ) { 14353 this._trigger( "change", event, { item: item } ); 14354 } 14355 14356 this.close( event ); 14357 }, 14358 14359 _setAria: function( item ) { 14360 var id = this.menuItems.eq( item.index ).attr( "id" ); 14361 14362 this.button.attr( { 14363 "aria-labelledby": id, 14364 "aria-activedescendant": id 14365 } ); 14366 this.menu.attr( "aria-activedescendant", id ); 14367 }, 14368 14369 _setOption: function( key, value ) { 14370 if ( key === "icons" ) { 14371 var icon = this.button.find( "span.ui-icon" ); 14372 this._removeClass( icon, null, this.options.icons.button ) 14373 ._addClass( icon, null, value.button ); 14374 } 14375 14376 this._super( key, value ); 14377 14378 if ( key === "appendTo" ) { 14379 this.menuWrap.appendTo( this._appendTo() ); 14380 } 14381 14382 if ( key === "width" ) { 14383 this._resizeButton(); 14384 } 14385 }, 14386 14387 _setOptionDisabled: function( value ) { 14388 this._super( value ); 14389 14390 this.menuInstance.option( "disabled", value ); 14391 this.button.attr( "aria-disabled", value ); 14392 this._toggleClass( this.button, null, "ui-state-disabled", value ); 14393 14394 this.element.prop( "disabled", value ); 14395 if ( value ) { 14396 this.button.attr( "tabindex", -1 ); 14397 this.close(); 14398 } else { 14399 this.button.attr( "tabindex", 0 ); 14400 } 14401 }, 14402 14403 _appendTo: function() { 14404 var element = this.options.appendTo; 14405 14406 if ( element ) { 14407 element = element.jquery || element.nodeType ? 14408 $( element ) : 14409 this.document.find( element ).eq( 0 ); 14410 } 14411 14412 if ( !element || !element[ 0 ] ) { 14413 element = this.element.closest( ".ui-front, dialog" ); 14414 } 14415 14416 if ( !element.length ) { 14417 element = this.document[ 0 ].body; 14418 } 14419 14420 return element; 14421 }, 14422 14423 _toggleAttr: function() { 14424 this.button.attr( "aria-expanded", this.isOpen ); 14425 14426 // We can't use two _toggleClass() calls here, because we need to make sure 14427 // we always remove classes first and add them second, otherwise if both classes have the 14428 // same theme class, it will be removed after we add it. 14429 this._removeClass( this.button, "ui-selectmenu-button-" + 14430 ( this.isOpen ? "closed" : "open" ) ) 14431 ._addClass( this.button, "ui-selectmenu-button-" + 14432 ( this.isOpen ? "open" : "closed" ) ) 14433 ._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen ); 14434 14435 this.menu.attr( "aria-hidden", !this.isOpen ); 14436 }, 14437 14438 _resizeButton: function() { 14439 var width = this.options.width; 14440 14441 // For `width: false`, just remove inline style and stop 14442 if ( width === false ) { 14443 this.button.css( "width", "" ); 14444 return; 14445 } 14446 14447 // For `width: null`, match the width of the original element 14448 if ( width === null ) { 14449 width = this.element.show().outerWidth(); 14450 this.element.hide(); 14451 } 14452 14453 this.button.outerWidth( width ); 14454 }, 14455 14456 _resizeMenu: function() { 14457 this.menu.outerWidth( Math.max( 14458 this.button.outerWidth(), 14459 this.menu.width( "" ).outerWidth() 14460 ) ); 14461 }, 14462 14463 _getCreateOptions: function() { 14464 var options = this._super(); 14465 14466 options.disabled = this.element.prop( "disabled" ); 14467 14468 return options; 14469 }, 14470 14471 _parseOptions: function( options ) { 14472 var that = this, 14473 data = []; 14474 options.each( function( index, item ) { 14475 data.push( that._parseOption( $( item ), index ) ); 14476 } ); 14477 this.items = data; 14478 }, 14479 14480 _parseOption: function( option, index ) { 14481 var optgroup = option.parent( "optgroup" ); 14482 14483 return { 14484 element: option, 14485 index: index, 14486 value: option.val(), 14487 label: option.text(), 14488 hidden: optgroup.prop( "hidden" ) || option.prop( "hidden" ), 14489 optgroup: optgroup.attr( "label" ) || "", 14490 disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" ) 14491 }; 14492 }, 14493 14494 _destroy: function() { 14495 this._unbindFormResetHandler(); 14496 this.menuWrap.remove(); 14497 this.button.remove(); 14498 this.element.show(); 14499 this.element.removeUniqueId(); 14500 this.labels.attr( "for", this.ids.element ); 14501 } 14502} ] ); 14503 14504 14505/*! 14506 * jQuery UI Slider 1.14.0 14507 * https://jqueryui.com 14508 * 14509 * Copyright OpenJS Foundation and other contributors 14510 * Released under the MIT license. 14511 * https://jquery.org/license 14512 */ 14513 14514//>>label: Slider 14515//>>group: Widgets 14516//>>description: Displays a flexible slider with ranges and accessibility via keyboard. 14517//>>docs: https://api.jqueryui.com/slider/ 14518//>>demos: https://jqueryui.com/slider/ 14519//>>css.structure: ../../themes/base/core.css 14520//>>css.structure: ../../themes/base/slider.css 14521//>>css.theme: ../../themes/base/theme.css 14522 14523 14524var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, { 14525 version: "1.14.0", 14526 widgetEventPrefix: "slide", 14527 14528 options: { 14529 animate: false, 14530 classes: { 14531 "ui-slider": "ui-corner-all", 14532 "ui-slider-handle": "ui-corner-all", 14533 14534 // Note: ui-widget-header isn't the most fittingly semantic framework class for this 14535 // element, but worked best visually with a variety of themes 14536 "ui-slider-range": "ui-corner-all ui-widget-header" 14537 }, 14538 distance: 0, 14539 max: 100, 14540 min: 0, 14541 orientation: "horizontal", 14542 range: false, 14543 step: 1, 14544 value: 0, 14545 values: null, 14546 14547 // Callbacks 14548 change: null, 14549 slide: null, 14550 start: null, 14551 stop: null 14552 }, 14553 14554 // Number of pages in a slider 14555 // (how many times can you page up/down to go through the whole range) 14556 numPages: 5, 14557 14558 _create: function() { 14559 this._keySliding = false; 14560 this._mouseSliding = false; 14561 this._animateOff = true; 14562 this._handleIndex = null; 14563 this._detectOrientation(); 14564 this._mouseInit(); 14565 this._calculateNewMax(); 14566 14567 this._addClass( "ui-slider ui-slider-" + this.orientation, 14568 "ui-widget ui-widget-content" ); 14569 14570 this._refresh(); 14571 14572 this._animateOff = false; 14573 }, 14574 14575 _refresh: function() { 14576 this._createRange(); 14577 this._createHandles(); 14578 this._setupEvents(); 14579 this._refreshValue(); 14580 }, 14581 14582 _createHandles: function() { 14583 var i, handleCount, 14584 options = this.options, 14585 existingHandles = this.element.find( ".ui-slider-handle" ), 14586 handle = "<span tabindex='0'></span>", 14587 handles = []; 14588 14589 handleCount = ( options.values && options.values.length ) || 1; 14590 14591 if ( existingHandles.length > handleCount ) { 14592 existingHandles.slice( handleCount ).remove(); 14593 existingHandles = existingHandles.slice( 0, handleCount ); 14594 } 14595 14596 for ( i = existingHandles.length; i < handleCount; i++ ) { 14597 handles.push( handle ); 14598 } 14599 14600 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) ); 14601 14602 this._addClass( this.handles, "ui-slider-handle", "ui-state-default" ); 14603 14604 this.handle = this.handles.eq( 0 ); 14605 14606 this.handles.each( function( i ) { 14607 $( this ) 14608 .data( "ui-slider-handle-index", i ) 14609 .attr( "tabIndex", 0 ); 14610 } ); 14611 }, 14612 14613 _createRange: function() { 14614 var options = this.options; 14615 14616 if ( options.range ) { 14617 if ( options.range === true ) { 14618 if ( !options.values ) { 14619 options.values = [ this._valueMin(), this._valueMin() ]; 14620 } else if ( options.values.length && options.values.length !== 2 ) { 14621 options.values = [ options.values[ 0 ], options.values[ 0 ] ]; 14622 } else if ( Array.isArray( options.values ) ) { 14623 options.values = options.values.slice( 0 ); 14624 } 14625 } 14626 14627 if ( !this.range || !this.range.length ) { 14628 this.range = $( "<div>" ) 14629 .appendTo( this.element ); 14630 14631 this._addClass( this.range, "ui-slider-range" ); 14632 } else { 14633 this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" ); 14634 14635 // Handle range switching from true to min/max 14636 this.range.css( { 14637 "left": "", 14638 "bottom": "" 14639 } ); 14640 } 14641 if ( options.range === "min" || options.range === "max" ) { 14642 this._addClass( this.range, "ui-slider-range-" + options.range ); 14643 } 14644 } else { 14645 if ( this.range ) { 14646 this.range.remove(); 14647 } 14648 this.range = null; 14649 } 14650 }, 14651 14652 _setupEvents: function() { 14653 this._off( this.handles ); 14654 this._on( this.handles, this._handleEvents ); 14655 this._hoverable( this.handles ); 14656 this._focusable( this.handles ); 14657 }, 14658 14659 _destroy: function() { 14660 this.handles.remove(); 14661 if ( this.range ) { 14662 this.range.remove(); 14663 } 14664 14665 this._mouseDestroy(); 14666 }, 14667 14668 _mouseCapture: function( event ) { 14669 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, 14670 that = this, 14671 o = this.options; 14672 14673 if ( o.disabled ) { 14674 return false; 14675 } 14676 14677 this.elementSize = { 14678 width: this.element.outerWidth(), 14679 height: this.element.outerHeight() 14680 }; 14681 this.elementOffset = this.element.offset(); 14682 14683 position = { x: event.pageX, y: event.pageY }; 14684 normValue = this._normValueFromMouse( position ); 14685 distance = this._valueMax() - this._valueMin() + 1; 14686 this.handles.each( function( i ) { 14687 var thisDistance = Math.abs( normValue - that.values( i ) ); 14688 if ( ( distance > thisDistance ) || 14689 ( distance === thisDistance && 14690 ( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) { 14691 distance = thisDistance; 14692 closestHandle = $( this ); 14693 index = i; 14694 } 14695 } ); 14696 14697 allowed = this._start( event, index ); 14698 if ( allowed === false ) { 14699 return false; 14700 } 14701 this._mouseSliding = true; 14702 14703 this._handleIndex = index; 14704 14705 this._addClass( closestHandle, null, "ui-state-active" ); 14706 closestHandle.trigger( "focus" ); 14707 14708 offset = closestHandle.offset(); 14709 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" ); 14710 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { 14711 left: event.pageX - offset.left - ( closestHandle.width() / 2 ), 14712 top: event.pageY - offset.top - 14713 ( closestHandle.height() / 2 ) - 14714 ( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) - 14715 ( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) + 14716 ( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 ) 14717 }; 14718 14719 if ( !this.handles.hasClass( "ui-state-hover" ) ) { 14720 this._slide( event, index, normValue ); 14721 } 14722 this._animateOff = true; 14723 return true; 14724 }, 14725 14726 _mouseStart: function() { 14727 return true; 14728 }, 14729 14730 _mouseDrag: function( event ) { 14731 var position = { x: event.pageX, y: event.pageY }, 14732 normValue = this._normValueFromMouse( position ); 14733 14734 this._slide( event, this._handleIndex, normValue ); 14735 14736 return false; 14737 }, 14738 14739 _mouseStop: function( event ) { 14740 this._removeClass( this.handles, null, "ui-state-active" ); 14741 this._mouseSliding = false; 14742 14743 this._stop( event, this._handleIndex ); 14744 this._change( event, this._handleIndex ); 14745 14746 this._handleIndex = null; 14747 this._clickOffset = null; 14748 this._animateOff = false; 14749 14750 return false; 14751 }, 14752 14753 _detectOrientation: function() { 14754 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; 14755 }, 14756 14757 _normValueFromMouse: function( position ) { 14758 var pixelTotal, 14759 pixelMouse, 14760 percentMouse, 14761 valueTotal, 14762 valueMouse; 14763 14764 if ( this.orientation === "horizontal" ) { 14765 pixelTotal = this.elementSize.width; 14766 pixelMouse = position.x - this.elementOffset.left - 14767 ( this._clickOffset ? this._clickOffset.left : 0 ); 14768 } else { 14769 pixelTotal = this.elementSize.height; 14770 pixelMouse = position.y - this.elementOffset.top - 14771 ( this._clickOffset ? this._clickOffset.top : 0 ); 14772 } 14773 14774 percentMouse = ( pixelMouse / pixelTotal ); 14775 if ( percentMouse > 1 ) { 14776 percentMouse = 1; 14777 } 14778 if ( percentMouse < 0 ) { 14779 percentMouse = 0; 14780 } 14781 if ( this.orientation === "vertical" ) { 14782 percentMouse = 1 - percentMouse; 14783 } 14784 14785 valueTotal = this._valueMax() - this._valueMin(); 14786 valueMouse = this._valueMin() + percentMouse * valueTotal; 14787 14788 return this._trimAlignValue( valueMouse ); 14789 }, 14790 14791 _uiHash: function( index, value, values ) { 14792 var uiHash = { 14793 handle: this.handles[ index ], 14794 handleIndex: index, 14795 value: value !== undefined ? value : this.value() 14796 }; 14797 14798 if ( this._hasMultipleValues() ) { 14799 uiHash.value = value !== undefined ? value : this.values( index ); 14800 uiHash.values = values || this.values(); 14801 } 14802 14803 return uiHash; 14804 }, 14805 14806 _hasMultipleValues: function() { 14807 return this.options.values && this.options.values.length; 14808 }, 14809 14810 _start: function( event, index ) { 14811 return this._trigger( "start", event, this._uiHash( index ) ); 14812 }, 14813 14814 _slide: function( event, index, newVal ) { 14815 var allowed, otherVal, 14816 currentValue = this.value(), 14817 newValues = this.values(); 14818 14819 if ( this._hasMultipleValues() ) { 14820 otherVal = this.values( index ? 0 : 1 ); 14821 currentValue = this.values( index ); 14822 14823 if ( this.options.values.length === 2 && this.options.range === true ) { 14824 newVal = index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal ); 14825 } 14826 14827 newValues[ index ] = newVal; 14828 } 14829 14830 if ( newVal === currentValue ) { 14831 return; 14832 } 14833 14834 allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) ); 14835 14836 // A slide can be canceled by returning false from the slide callback 14837 if ( allowed === false ) { 14838 return; 14839 } 14840 14841 if ( this._hasMultipleValues() ) { 14842 this.values( index, newVal ); 14843 } else { 14844 this.value( newVal ); 14845 } 14846 }, 14847 14848 _stop: function( event, index ) { 14849 this._trigger( "stop", event, this._uiHash( index ) ); 14850 }, 14851 14852 _change: function( event, index ) { 14853 if ( !this._keySliding && !this._mouseSliding ) { 14854 14855 //store the last changed value index for reference when handles overlap 14856 this._lastChangedValue = index; 14857 this._trigger( "change", event, this._uiHash( index ) ); 14858 } 14859 }, 14860 14861 value: function( newValue ) { 14862 if ( arguments.length ) { 14863 this.options.value = this._trimAlignValue( newValue ); 14864 this._refreshValue(); 14865 this._change( null, 0 ); 14866 return; 14867 } 14868 14869 return this._value(); 14870 }, 14871 14872 values: function( index, newValue ) { 14873 var vals, 14874 newValues, 14875 i; 14876 14877 if ( arguments.length > 1 ) { 14878 this.options.values[ index ] = this._trimAlignValue( newValue ); 14879 this._refreshValue(); 14880 this._change( null, index ); 14881 return; 14882 } 14883 14884 if ( arguments.length ) { 14885 if ( Array.isArray( arguments[ 0 ] ) ) { 14886 vals = this.options.values; 14887 newValues = arguments[ 0 ]; 14888 for ( i = 0; i < vals.length; i += 1 ) { 14889 vals[ i ] = this._trimAlignValue( newValues[ i ] ); 14890 this._change( null, i ); 14891 } 14892 this._refreshValue(); 14893 } else { 14894 if ( this._hasMultipleValues() ) { 14895 return this._values( index ); 14896 } else { 14897 return this.value(); 14898 } 14899 } 14900 } else { 14901 return this._values(); 14902 } 14903 }, 14904 14905 _setOption: function( key, value ) { 14906 var i, 14907 valsLength = 0; 14908 14909 if ( key === "range" && this.options.range === true ) { 14910 if ( value === "min" ) { 14911 this.options.value = this._values( 0 ); 14912 this.options.values = null; 14913 } else if ( value === "max" ) { 14914 this.options.value = this._values( this.options.values.length - 1 ); 14915 this.options.values = null; 14916 } 14917 } 14918 14919 if ( Array.isArray( this.options.values ) ) { 14920 valsLength = this.options.values.length; 14921 } 14922 14923 this._super( key, value ); 14924 14925 switch ( key ) { 14926 case "orientation": 14927 this._detectOrientation(); 14928 this._removeClass( "ui-slider-horizontal ui-slider-vertical" ) 14929 ._addClass( "ui-slider-" + this.orientation ); 14930 this._refreshValue(); 14931 if ( this.options.range ) { 14932 this._refreshRange( value ); 14933 } 14934 14935 // Reset positioning from previous orientation 14936 this.handles.css( value === "horizontal" ? "bottom" : "left", "" ); 14937 break; 14938 case "value": 14939 this._animateOff = true; 14940 this._refreshValue(); 14941 this._change( null, 0 ); 14942 this._animateOff = false; 14943 break; 14944 case "values": 14945 this._animateOff = true; 14946 this._refreshValue(); 14947 14948 // Start from the last handle to prevent unreachable handles (#9046) 14949 for ( i = valsLength - 1; i >= 0; i-- ) { 14950 this._change( null, i ); 14951 } 14952 this._animateOff = false; 14953 break; 14954 case "step": 14955 case "min": 14956 case "max": 14957 this._animateOff = true; 14958 this._calculateNewMax(); 14959 this._refreshValue(); 14960 this._animateOff = false; 14961 break; 14962 case "range": 14963 this._animateOff = true; 14964 this._refresh(); 14965 this._animateOff = false; 14966 break; 14967 } 14968 }, 14969 14970 _setOptionDisabled: function( value ) { 14971 this._super( value ); 14972 14973 this._toggleClass( null, "ui-state-disabled", !!value ); 14974 }, 14975 14976 //internal value getter 14977 // _value() returns value trimmed by min and max, aligned by step 14978 _value: function() { 14979 var val = this.options.value; 14980 val = this._trimAlignValue( val ); 14981 14982 return val; 14983 }, 14984 14985 //internal values getter 14986 // _values() returns array of values trimmed by min and max, aligned by step 14987 // _values( index ) returns single value trimmed by min and max, aligned by step 14988 _values: function( index ) { 14989 var val, 14990 vals, 14991 i; 14992 14993 if ( arguments.length ) { 14994 val = this.options.values[ index ]; 14995 val = this._trimAlignValue( val ); 14996 14997 return val; 14998 } else if ( this._hasMultipleValues() ) { 14999 15000 // .slice() creates a copy of the array 15001 // this copy gets trimmed by min and max and then returned 15002 vals = this.options.values.slice(); 15003 for ( i = 0; i < vals.length; i += 1 ) { 15004 vals[ i ] = this._trimAlignValue( vals[ i ] ); 15005 } 15006 15007 return vals; 15008 } else { 15009 return []; 15010 } 15011 }, 15012 15013 // Returns the step-aligned value that val is closest to, between (inclusive) min and max 15014 _trimAlignValue: function( val ) { 15015 if ( val <= this._valueMin() ) { 15016 return this._valueMin(); 15017 } 15018 if ( val >= this._valueMax() ) { 15019 return this._valueMax(); 15020 } 15021 var step = ( this.options.step > 0 ) ? this.options.step : 1, 15022 valModStep = ( val - this._valueMin() ) % step, 15023 alignValue = val - valModStep; 15024 15025 if ( Math.abs( valModStep ) * 2 >= step ) { 15026 alignValue += ( valModStep > 0 ) ? step : ( -step ); 15027 } 15028 15029 // Since JavaScript has problems with large floats, round 15030 // the final value to 5 digits after the decimal point (see #4124) 15031 return parseFloat( alignValue.toFixed( 5 ) ); 15032 }, 15033 15034 _calculateNewMax: function() { 15035 var max = this.options.max, 15036 min = this._valueMin(), 15037 step = this.options.step, 15038 aboveMin = Math.round( ( max - min ) / step ) * step; 15039 max = aboveMin + min; 15040 if ( max > this.options.max ) { 15041 15042 //If max is not divisible by step, rounding off may increase its value 15043 max -= step; 15044 } 15045 this.max = parseFloat( max.toFixed( this._precision() ) ); 15046 }, 15047 15048 _precision: function() { 15049 var precision = this._precisionOf( this.options.step ); 15050 if ( this.options.min !== null ) { 15051 precision = Math.max( precision, this._precisionOf( this.options.min ) ); 15052 } 15053 return precision; 15054 }, 15055 15056 _precisionOf: function( num ) { 15057 var str = num.toString(), 15058 decimal = str.indexOf( "." ); 15059 return decimal === -1 ? 0 : str.length - decimal - 1; 15060 }, 15061 15062 _valueMin: function() { 15063 return this.options.min; 15064 }, 15065 15066 _valueMax: function() { 15067 return this.max; 15068 }, 15069 15070 _refreshRange: function( orientation ) { 15071 if ( orientation === "vertical" ) { 15072 this.range.css( { "width": "", "left": "" } ); 15073 } 15074 if ( orientation === "horizontal" ) { 15075 this.range.css( { "height": "", "bottom": "" } ); 15076 } 15077 }, 15078 15079 _refreshValue: function() { 15080 var lastValPercent, valPercent, value, valueMin, valueMax, 15081 oRange = this.options.range, 15082 o = this.options, 15083 that = this, 15084 animate = ( !this._animateOff ) ? o.animate : false, 15085 _set = {}; 15086 15087 if ( this._hasMultipleValues() ) { 15088 this.handles.each( function( i ) { 15089 valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() - 15090 that._valueMin() ) * 100; 15091 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 15092 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 15093 if ( that.options.range === true ) { 15094 if ( that.orientation === "horizontal" ) { 15095 if ( i === 0 ) { 15096 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 15097 left: valPercent + "%" 15098 }, o.animate ); 15099 } 15100 if ( i === 1 ) { 15101 that.range[ animate ? "animate" : "css" ]( { 15102 width: ( valPercent - lastValPercent ) + "%" 15103 }, { 15104 queue: false, 15105 duration: o.animate 15106 } ); 15107 } 15108 } else { 15109 if ( i === 0 ) { 15110 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 15111 bottom: ( valPercent ) + "%" 15112 }, o.animate ); 15113 } 15114 if ( i === 1 ) { 15115 that.range[ animate ? "animate" : "css" ]( { 15116 height: ( valPercent - lastValPercent ) + "%" 15117 }, { 15118 queue: false, 15119 duration: o.animate 15120 } ); 15121 } 15122 } 15123 } 15124 lastValPercent = valPercent; 15125 } ); 15126 } else { 15127 value = this.value(); 15128 valueMin = this._valueMin(); 15129 valueMax = this._valueMax(); 15130 valPercent = ( valueMax !== valueMin ) ? 15131 ( value - valueMin ) / ( valueMax - valueMin ) * 100 : 15132 0; 15133 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 15134 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 15135 15136 if ( oRange === "min" && this.orientation === "horizontal" ) { 15137 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 15138 width: valPercent + "%" 15139 }, o.animate ); 15140 } 15141 if ( oRange === "max" && this.orientation === "horizontal" ) { 15142 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 15143 width: ( 100 - valPercent ) + "%" 15144 }, o.animate ); 15145 } 15146 if ( oRange === "min" && this.orientation === "vertical" ) { 15147 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 15148 height: valPercent + "%" 15149 }, o.animate ); 15150 } 15151 if ( oRange === "max" && this.orientation === "vertical" ) { 15152 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 15153 height: ( 100 - valPercent ) + "%" 15154 }, o.animate ); 15155 } 15156 } 15157 }, 15158 15159 _handleEvents: { 15160 keydown: function( event ) { 15161 var allowed, curVal, newVal, step, 15162 index = $( event.target ).data( "ui-slider-handle-index" ); 15163 15164 switch ( event.keyCode ) { 15165 case $.ui.keyCode.HOME: 15166 case $.ui.keyCode.END: 15167 case $.ui.keyCode.PAGE_UP: 15168 case $.ui.keyCode.PAGE_DOWN: 15169 case $.ui.keyCode.UP: 15170 case $.ui.keyCode.RIGHT: 15171 case $.ui.keyCode.DOWN: 15172 case $.ui.keyCode.LEFT: 15173 event.preventDefault(); 15174 if ( !this._keySliding ) { 15175 this._keySliding = true; 15176 this._addClass( $( event.target ), null, "ui-state-active" ); 15177 allowed = this._start( event, index ); 15178 if ( allowed === false ) { 15179 return; 15180 } 15181 } 15182 break; 15183 } 15184 15185 step = this.options.step; 15186 if ( this._hasMultipleValues() ) { 15187 curVal = newVal = this.values( index ); 15188 } else { 15189 curVal = newVal = this.value(); 15190 } 15191 15192 switch ( event.keyCode ) { 15193 case $.ui.keyCode.HOME: 15194 newVal = this._valueMin(); 15195 break; 15196 case $.ui.keyCode.END: 15197 newVal = this._valueMax(); 15198 break; 15199 case $.ui.keyCode.PAGE_UP: 15200 newVal = this._trimAlignValue( 15201 curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages ) 15202 ); 15203 break; 15204 case $.ui.keyCode.PAGE_DOWN: 15205 newVal = this._trimAlignValue( 15206 curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) ); 15207 break; 15208 case $.ui.keyCode.UP: 15209 case $.ui.keyCode.RIGHT: 15210 if ( curVal === this._valueMax() ) { 15211 return; 15212 } 15213 newVal = this._trimAlignValue( curVal + step ); 15214 break; 15215 case $.ui.keyCode.DOWN: 15216 case $.ui.keyCode.LEFT: 15217 if ( curVal === this._valueMin() ) { 15218 return; 15219 } 15220 newVal = this._trimAlignValue( curVal - step ); 15221 break; 15222 } 15223 15224 this._slide( event, index, newVal ); 15225 }, 15226 keyup: function( event ) { 15227 var index = $( event.target ).data( "ui-slider-handle-index" ); 15228 15229 if ( this._keySliding ) { 15230 this._keySliding = false; 15231 this._stop( event, index ); 15232 this._change( event, index ); 15233 this._removeClass( $( event.target ), null, "ui-state-active" ); 15234 } 15235 } 15236 } 15237} ); 15238 15239 15240/*! 15241 * jQuery UI Sortable 1.14.0 15242 * https://jqueryui.com 15243 * 15244 * Copyright OpenJS Foundation and other contributors 15245 * Released under the MIT license. 15246 * https://jquery.org/license 15247 */ 15248 15249//>>label: Sortable 15250//>>group: Interactions 15251//>>description: Enables items in a list to be sorted using the mouse. 15252//>>docs: https://api.jqueryui.com/sortable/ 15253//>>demos: https://jqueryui.com/sortable/ 15254//>>css.structure: ../../themes/base/sortable.css 15255 15256 15257var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, { 15258 version: "1.14.0", 15259 widgetEventPrefix: "sort", 15260 ready: false, 15261 options: { 15262 appendTo: "parent", 15263 axis: false, 15264 connectWith: false, 15265 containment: false, 15266 cursor: "auto", 15267 cursorAt: false, 15268 dropOnEmpty: true, 15269 forcePlaceholderSize: false, 15270 forceHelperSize: false, 15271 grid: false, 15272 handle: false, 15273 helper: "original", 15274 items: "> *", 15275 opacity: false, 15276 placeholder: false, 15277 revert: false, 15278 scroll: true, 15279 scrollSensitivity: 20, 15280 scrollSpeed: 20, 15281 scope: "default", 15282 tolerance: "intersect", 15283 zIndex: 1000, 15284 15285 // Callbacks 15286 activate: null, 15287 beforeStop: null, 15288 change: null, 15289 deactivate: null, 15290 out: null, 15291 over: null, 15292 receive: null, 15293 remove: null, 15294 sort: null, 15295 start: null, 15296 stop: null, 15297 update: null 15298 }, 15299 15300 _isOverAxis: function( x, reference, size ) { 15301 return ( x >= reference ) && ( x < ( reference + size ) ); 15302 }, 15303 15304 _isFloating: function( item ) { 15305 return ( /left|right/ ).test( item.css( "float" ) ) || 15306 ( /inline|table-cell/ ).test( item.css( "display" ) ); 15307 }, 15308 15309 _create: function() { 15310 this.containerCache = {}; 15311 this._addClass( "ui-sortable" ); 15312 15313 //Get the items 15314 this.refresh(); 15315 15316 //Let's determine the parent's offset 15317 this.offset = this.element.offset(); 15318 15319 //Initialize mouse events for interaction 15320 this._mouseInit(); 15321 15322 this._setHandleClassName(); 15323 15324 //We're ready to go 15325 this.ready = true; 15326 15327 }, 15328 15329 _setOption: function( key, value ) { 15330 this._super( key, value ); 15331 15332 if ( key === "handle" ) { 15333 this._setHandleClassName(); 15334 } 15335 }, 15336 15337 _setHandleClassName: function() { 15338 var that = this; 15339 this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" ); 15340 $.each( this.items, function() { 15341 that._addClass( 15342 this.instance.options.handle ? 15343 this.item.find( this.instance.options.handle ) : 15344 this.item, 15345 "ui-sortable-handle" 15346 ); 15347 } ); 15348 }, 15349 15350 _destroy: function() { 15351 this._mouseDestroy(); 15352 15353 for ( var i = this.items.length - 1; i >= 0; i-- ) { 15354 this.items[ i ].item.removeData( this.widgetName + "-item" ); 15355 } 15356 15357 return this; 15358 }, 15359 15360 _mouseCapture: function( event, overrideHandle ) { 15361 var currentItem = null, 15362 validHandle = false, 15363 that = this; 15364 15365 if ( this.reverting ) { 15366 return false; 15367 } 15368 15369 if ( this.options.disabled || this.options.type === "static" ) { 15370 return false; 15371 } 15372 15373 //We have to refresh the items data once first 15374 this._refreshItems( event ); 15375 15376 //Find out if the clicked node (or one of its parents) is a actual item in this.items 15377 $( event.target ).parents().each( function() { 15378 if ( $.data( this, that.widgetName + "-item" ) === that ) { 15379 currentItem = $( this ); 15380 return false; 15381 } 15382 } ); 15383 if ( $.data( event.target, that.widgetName + "-item" ) === that ) { 15384 currentItem = $( event.target ); 15385 } 15386 15387 if ( !currentItem ) { 15388 return false; 15389 } 15390 if ( this.options.handle && !overrideHandle ) { 15391 $( this.options.handle, currentItem ).find( "*" ).addBack().each( function() { 15392 if ( this === event.target ) { 15393 validHandle = true; 15394 } 15395 } ); 15396 if ( !validHandle ) { 15397 return false; 15398 } 15399 } 15400 15401 this.currentItem = currentItem; 15402 this._removeCurrentsFromItems(); 15403 return true; 15404 15405 }, 15406 15407 _mouseStart: function( event, overrideHandle, noActivation ) { 15408 15409 var i, body, 15410 o = this.options; 15411 15412 this.currentContainer = this; 15413 15414 //We only need to call refreshPositions, because the refreshItems call has been moved to 15415 // mouseCapture 15416 this.refreshPositions(); 15417 15418 //Prepare the dragged items parent 15419 this.appendTo = $( o.appendTo !== "parent" ? 15420 o.appendTo : 15421 this.currentItem.parent() ); 15422 15423 //Create and append the visible helper 15424 this.helper = this._createHelper( event ); 15425 15426 //Cache the helper size 15427 this._cacheHelperProportions(); 15428 15429 /* 15430 * - Position generation - 15431 * This block generates everything position related - it's the core of draggables. 15432 */ 15433 15434 //Cache the margins of the original element 15435 this._cacheMargins(); 15436 15437 //The element's absolute position on the page minus margins 15438 this.offset = this.currentItem.offset(); 15439 this.offset = { 15440 top: this.offset.top - this.margins.top, 15441 left: this.offset.left - this.margins.left 15442 }; 15443 15444 $.extend( this.offset, { 15445 click: { //Where the click happened, relative to the element 15446 left: event.pageX - this.offset.left, 15447 top: event.pageY - this.offset.top 15448 }, 15449 15450 // This is a relative to absolute position minus the actual position calculation - 15451 // only used for relative positioned helper 15452 relative: this._getRelativeOffset() 15453 } ); 15454 15455 // After we get the helper offset, but before we get the parent offset we can 15456 // change the helper's position to absolute 15457 // TODO: Still need to figure out a way to make relative sorting possible 15458 this.helper.css( "position", "absolute" ); 15459 this.cssPosition = this.helper.css( "position" ); 15460 15461 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 15462 if ( o.cursorAt ) { 15463 this._adjustOffsetFromHelper( o.cursorAt ); 15464 } 15465 15466 //Cache the former DOM position 15467 this.domPosition = { 15468 prev: this.currentItem.prev()[ 0 ], 15469 parent: this.currentItem.parent()[ 0 ] 15470 }; 15471 15472 // If the helper is not the original, hide the original so it's not playing any role during 15473 // the drag, won't cause anything bad this way 15474 if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) { 15475 this.currentItem.hide(); 15476 } 15477 15478 //Create the placeholder 15479 this._createPlaceholder(); 15480 15481 //Get the next scrolling parent 15482 this.scrollParent = this.placeholder.scrollParent(); 15483 15484 $.extend( this.offset, { 15485 parent: this._getParentOffset() 15486 } ); 15487 15488 //Set a containment if given in the options 15489 if ( o.containment ) { 15490 this._setContainment(); 15491 } 15492 15493 if ( o.cursor && o.cursor !== "auto" ) { // cursor option 15494 body = this.document.find( "body" ); 15495 15496 this._storedStylesheet = 15497 $( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body ); 15498 } 15499 15500 // We need to make sure to grab the zIndex before setting the 15501 // opacity, because setting the opacity to anything lower than 1 15502 // causes the zIndex to change from "auto" to 0. 15503 if ( o.zIndex ) { // zIndex option 15504 if ( this.helper.css( "zIndex" ) ) { 15505 this._storedZIndex = this.helper.css( "zIndex" ); 15506 } 15507 this.helper.css( "zIndex", o.zIndex ); 15508 } 15509 15510 if ( o.opacity ) { // opacity option 15511 if ( this.helper.css( "opacity" ) ) { 15512 this._storedOpacity = this.helper.css( "opacity" ); 15513 } 15514 this.helper.css( "opacity", o.opacity ); 15515 } 15516 15517 //Prepare scrolling 15518 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && 15519 this.scrollParent[ 0 ].tagName !== "HTML" ) { 15520 this.overflowOffset = this.scrollParent.offset(); 15521 } 15522 15523 //Call callbacks 15524 this._trigger( "start", event, this._uiHash() ); 15525 15526 //Recache the helper size 15527 if ( !this._preserveHelperProportions ) { 15528 this._cacheHelperProportions(); 15529 } 15530 15531 //Post "activate" events to possible containers 15532 if ( !noActivation ) { 15533 for ( i = this.containers.length - 1; i >= 0; i-- ) { 15534 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); 15535 } 15536 } 15537 15538 //Prepare possible droppables 15539 if ( $.ui.ddmanager ) { 15540 $.ui.ddmanager.current = this; 15541 } 15542 15543 if ( $.ui.ddmanager && !o.dropBehaviour ) { 15544 $.ui.ddmanager.prepareOffsets( this, event ); 15545 } 15546 15547 this.dragging = true; 15548 15549 this._addClass( this.helper, "ui-sortable-helper" ); 15550 15551 //Move the helper, if needed 15552 if ( !this.helper.parent().is( this.appendTo ) ) { 15553 this.helper.detach().appendTo( this.appendTo ); 15554 15555 //Update position 15556 this.offset.parent = this._getParentOffset(); 15557 } 15558 15559 //Generate the original position 15560 this.position = this.originalPosition = this._generatePosition( event ); 15561 this.originalPageX = event.pageX; 15562 this.originalPageY = event.pageY; 15563 this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" ); 15564 15565 this._mouseDrag( event ); 15566 15567 return true; 15568 15569 }, 15570 15571 _scroll: function( event ) { 15572 var o = this.options, 15573 scrolled = false; 15574 15575 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && 15576 this.scrollParent[ 0 ].tagName !== "HTML" ) { 15577 15578 if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) - 15579 event.pageY < o.scrollSensitivity ) { 15580 this.scrollParent[ 0 ].scrollTop = 15581 scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed; 15582 } else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) { 15583 this.scrollParent[ 0 ].scrollTop = 15584 scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed; 15585 } 15586 15587 if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) - 15588 event.pageX < o.scrollSensitivity ) { 15589 this.scrollParent[ 0 ].scrollLeft = scrolled = 15590 this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed; 15591 } else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) { 15592 this.scrollParent[ 0 ].scrollLeft = scrolled = 15593 this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed; 15594 } 15595 15596 } else { 15597 15598 if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) { 15599 scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed ); 15600 } else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) < 15601 o.scrollSensitivity ) { 15602 scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed ); 15603 } 15604 15605 if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) { 15606 scrolled = this.document.scrollLeft( 15607 this.document.scrollLeft() - o.scrollSpeed 15608 ); 15609 } else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) < 15610 o.scrollSensitivity ) { 15611 scrolled = this.document.scrollLeft( 15612 this.document.scrollLeft() + o.scrollSpeed 15613 ); 15614 } 15615 15616 } 15617 15618 return scrolled; 15619 }, 15620 15621 _mouseDrag: function( event ) { 15622 var i, item, itemElement, intersection, 15623 o = this.options; 15624 15625 //Compute the helpers position 15626 this.position = this._generatePosition( event ); 15627 this.positionAbs = this._convertPositionTo( "absolute" ); 15628 15629 //Set the helper position 15630 if ( !this.options.axis || this.options.axis !== "y" ) { 15631 this.helper[ 0 ].style.left = this.position.left + "px"; 15632 } 15633 if ( !this.options.axis || this.options.axis !== "x" ) { 15634 this.helper[ 0 ].style.top = this.position.top + "px"; 15635 } 15636 15637 //Do scrolling 15638 if ( o.scroll ) { 15639 if ( this._scroll( event ) !== false ) { 15640 15641 //Update item positions used in position checks 15642 this._refreshItemPositions( true ); 15643 15644 if ( $.ui.ddmanager && !o.dropBehaviour ) { 15645 $.ui.ddmanager.prepareOffsets( this, event ); 15646 } 15647 } 15648 } 15649 15650 this.dragDirection = { 15651 vertical: this._getDragVerticalDirection(), 15652 horizontal: this._getDragHorizontalDirection() 15653 }; 15654 15655 //Rearrange 15656 for ( i = this.items.length - 1; i >= 0; i-- ) { 15657 15658 //Cache variables and intersection, continue if no intersection 15659 item = this.items[ i ]; 15660 itemElement = item.item[ 0 ]; 15661 intersection = this._intersectsWithPointer( item ); 15662 if ( !intersection ) { 15663 continue; 15664 } 15665 15666 // Only put the placeholder inside the current Container, skip all 15667 // items from other containers. This works because when moving 15668 // an item from one container to another the 15669 // currentContainer is switched before the placeholder is moved. 15670 // 15671 // Without this, moving items in "sub-sortables" can cause 15672 // the placeholder to jitter between the outer and inner container. 15673 if ( item.instance !== this.currentContainer ) { 15674 continue; 15675 } 15676 15677 // Cannot intersect with itself 15678 // no useless actions that have been done before 15679 // no action if the item moved is the parent of the item checked 15680 if ( itemElement !== this.currentItem[ 0 ] && 15681 this.placeholder[ intersection === 1 ? 15682 "next" : "prev" ]()[ 0 ] !== itemElement && 15683 !$.contains( this.placeholder[ 0 ], itemElement ) && 15684 ( this.options.type === "semi-dynamic" ? 15685 !$.contains( this.element[ 0 ], itemElement ) : 15686 true 15687 ) 15688 ) { 15689 15690 this.direction = intersection === 1 ? "down" : "up"; 15691 15692 if ( this.options.tolerance === "pointer" || 15693 this._intersectsWithSides( item ) ) { 15694 this._rearrange( event, item ); 15695 } else { 15696 break; 15697 } 15698 15699 this._trigger( "change", event, this._uiHash() ); 15700 break; 15701 } 15702 } 15703 15704 //Post events to containers 15705 this._contactContainers( event ); 15706 15707 //Interconnect with droppables 15708 if ( $.ui.ddmanager ) { 15709 $.ui.ddmanager.drag( this, event ); 15710 } 15711 15712 //Call callbacks 15713 this._trigger( "sort", event, this._uiHash() ); 15714 15715 this.lastPositionAbs = this.positionAbs; 15716 return false; 15717 15718 }, 15719 15720 _mouseStop: function( event, noPropagation ) { 15721 15722 if ( !event ) { 15723 return; 15724 } 15725 15726 //If we are using droppables, inform the manager about the drop 15727 if ( $.ui.ddmanager && !this.options.dropBehaviour ) { 15728 $.ui.ddmanager.drop( this, event ); 15729 } 15730 15731 if ( this.options.revert ) { 15732 var that = this, 15733 cur = this.placeholder.offset(), 15734 axis = this.options.axis, 15735 animation = {}; 15736 15737 if ( !axis || axis === "x" ) { 15738 animation.left = cur.left - this.offset.parent.left - this.margins.left + 15739 ( this.offsetParent[ 0 ] === this.document[ 0 ].body ? 15740 0 : 15741 this.offsetParent[ 0 ].scrollLeft 15742 ); 15743 } 15744 if ( !axis || axis === "y" ) { 15745 animation.top = cur.top - this.offset.parent.top - this.margins.top + 15746 ( this.offsetParent[ 0 ] === this.document[ 0 ].body ? 15747 0 : 15748 this.offsetParent[ 0 ].scrollTop 15749 ); 15750 } 15751 this.reverting = true; 15752 $( this.helper ).animate( 15753 animation, 15754 parseInt( this.options.revert, 10 ) || 500, 15755 function() { 15756 that._clear( event ); 15757 } 15758 ); 15759 } else { 15760 this._clear( event, noPropagation ); 15761 } 15762 15763 return false; 15764 15765 }, 15766 15767 cancel: function() { 15768 15769 if ( this.dragging ) { 15770 15771 this._mouseUp( new $.Event( "mouseup", { target: null } ) ); 15772 15773 if ( this.options.helper === "original" ) { 15774 this.currentItem.css( this._storedCSS ); 15775 this._removeClass( this.currentItem, "ui-sortable-helper" ); 15776 } else { 15777 this.currentItem.show(); 15778 } 15779 15780 //Post deactivating events to containers 15781 for ( var i = this.containers.length - 1; i >= 0; i-- ) { 15782 this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) ); 15783 if ( this.containers[ i ].containerCache.over ) { 15784 this.containers[ i ]._trigger( "out", null, this._uiHash( this ) ); 15785 this.containers[ i ].containerCache.over = 0; 15786 } 15787 } 15788 15789 } 15790 15791 if ( this.placeholder ) { 15792 15793 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, 15794 // it unbinds ALL events from the original node! 15795 if ( this.placeholder[ 0 ].parentNode ) { 15796 this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] ); 15797 } 15798 if ( this.options.helper !== "original" && this.helper && 15799 this.helper[ 0 ].parentNode ) { 15800 this.helper.remove(); 15801 } 15802 15803 $.extend( this, { 15804 helper: null, 15805 dragging: false, 15806 reverting: false, 15807 _noFinalSort: null 15808 } ); 15809 15810 if ( this.domPosition.prev ) { 15811 $( this.domPosition.prev ).after( this.currentItem ); 15812 } else { 15813 $( this.domPosition.parent ).prepend( this.currentItem ); 15814 } 15815 } 15816 15817 return this; 15818 15819 }, 15820 15821 serialize: function( o ) { 15822 15823 var items = this._getItemsAsjQuery( o && o.connected ), 15824 str = []; 15825 o = o || {}; 15826 15827 $( items ).each( function() { 15828 var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" ) 15829 .match( o.expression || ( /(.+)[\-=_](.+)/ ) ); 15830 if ( res ) { 15831 str.push( 15832 ( o.key || res[ 1 ] + "[]" ) + 15833 "=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) ); 15834 } 15835 } ); 15836 15837 if ( !str.length && o.key ) { 15838 str.push( o.key + "=" ); 15839 } 15840 15841 return str.join( "&" ); 15842 15843 }, 15844 15845 toArray: function( o ) { 15846 15847 var items = this._getItemsAsjQuery( o && o.connected ), 15848 ret = []; 15849 15850 o = o || {}; 15851 15852 items.each( function() { 15853 ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" ); 15854 } ); 15855 return ret; 15856 15857 }, 15858 15859 /* Be careful with the following core functions */ 15860 _intersectsWith: function( item ) { 15861 15862 var x1 = this.positionAbs.left, 15863 x2 = x1 + this.helperProportions.width, 15864 y1 = this.positionAbs.top, 15865 y2 = y1 + this.helperProportions.height, 15866 l = item.left, 15867 r = l + item.width, 15868 t = item.top, 15869 b = t + item.height, 15870 dyClick = this.offset.click.top, 15871 dxClick = this.offset.click.left, 15872 isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && 15873 ( y1 + dyClick ) < b ), 15874 isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && 15875 ( x1 + dxClick ) < r ), 15876 isOverElement = isOverElementHeight && isOverElementWidth; 15877 15878 if ( this.options.tolerance === "pointer" || 15879 this.options.forcePointerForContainers || 15880 ( this.options.tolerance !== "pointer" && 15881 this.helperProportions[ this.floating ? "width" : "height" ] > 15882 item[ this.floating ? "width" : "height" ] ) 15883 ) { 15884 return isOverElement; 15885 } else { 15886 15887 return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half 15888 x2 - ( this.helperProportions.width / 2 ) < r && // Left Half 15889 t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half 15890 y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half 15891 15892 } 15893 }, 15894 15895 _intersectsWithPointer: function( item ) { 15896 var verticalDirection, horizontalDirection, 15897 isOverElementHeight = ( this.options.axis === "x" ) || 15898 this._isOverAxis( 15899 this.positionAbs.top + this.offset.click.top, item.top, item.height ), 15900 isOverElementWidth = ( this.options.axis === "y" ) || 15901 this._isOverAxis( 15902 this.positionAbs.left + this.offset.click.left, item.left, item.width ), 15903 isOverElement = isOverElementHeight && isOverElementWidth; 15904 15905 if ( !isOverElement ) { 15906 return false; 15907 } 15908 15909 verticalDirection = this.dragDirection.vertical; 15910 horizontalDirection = this.dragDirection.horizontal; 15911 15912 return this.floating ? 15913 ( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) : 15914 ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) ); 15915 15916 }, 15917 15918 _intersectsWithSides: function( item ) { 15919 15920 var isOverBottomHalf = this._isOverAxis( this.positionAbs.top + 15921 this.offset.click.top, item.top + ( item.height / 2 ), item.height ), 15922 isOverRightHalf = this._isOverAxis( this.positionAbs.left + 15923 this.offset.click.left, item.left + ( item.width / 2 ), item.width ), 15924 verticalDirection = this.dragDirection.vertical, 15925 horizontalDirection = this.dragDirection.horizontal; 15926 15927 if ( this.floating && horizontalDirection ) { 15928 return ( ( horizontalDirection === "right" && isOverRightHalf ) || 15929 ( horizontalDirection === "left" && !isOverRightHalf ) ); 15930 } else { 15931 return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) || 15932 ( verticalDirection === "up" && !isOverBottomHalf ) ); 15933 } 15934 15935 }, 15936 15937 _getDragVerticalDirection: function() { 15938 var delta = this.positionAbs.top - this.lastPositionAbs.top; 15939 return delta !== 0 && ( delta > 0 ? "down" : "up" ); 15940 }, 15941 15942 _getDragHorizontalDirection: function() { 15943 var delta = this.positionAbs.left - this.lastPositionAbs.left; 15944 return delta !== 0 && ( delta > 0 ? "right" : "left" ); 15945 }, 15946 15947 refresh: function( event ) { 15948 this._refreshItems( event ); 15949 this._setHandleClassName(); 15950 this.refreshPositions(); 15951 return this; 15952 }, 15953 15954 _connectWith: function() { 15955 var options = this.options; 15956 return options.connectWith.constructor === String ? 15957 [ options.connectWith ] : 15958 options.connectWith; 15959 }, 15960 15961 _getItemsAsjQuery: function( connected ) { 15962 15963 var i, j, cur, inst, 15964 items = [], 15965 queries = [], 15966 connectWith = this._connectWith(); 15967 15968 if ( connectWith && connected ) { 15969 for ( i = connectWith.length - 1; i >= 0; i-- ) { 15970 cur = $( connectWith[ i ], this.document[ 0 ] ); 15971 for ( j = cur.length - 1; j >= 0; j-- ) { 15972 inst = $.data( cur[ j ], this.widgetFullName ); 15973 if ( inst && inst !== this && !inst.options.disabled ) { 15974 queries.push( [ typeof inst.options.items === "function" ? 15975 inst.options.items.call( inst.element ) : 15976 $( inst.options.items, inst.element ) 15977 .not( ".ui-sortable-helper" ) 15978 .not( ".ui-sortable-placeholder" ), inst ] ); 15979 } 15980 } 15981 } 15982 } 15983 15984 queries.push( [ typeof this.options.items === "function" ? 15985 this.options.items 15986 .call( this.element, null, { options: this.options, item: this.currentItem } ) : 15987 $( this.options.items, this.element ) 15988 .not( ".ui-sortable-helper" ) 15989 .not( ".ui-sortable-placeholder" ), this ] ); 15990 15991 function addItems() { 15992 items.push( this ); 15993 } 15994 for ( i = queries.length - 1; i >= 0; i-- ) { 15995 queries[ i ][ 0 ].each( addItems ); 15996 } 15997 15998 return $( items ); 15999 16000 }, 16001 16002 _removeCurrentsFromItems: function() { 16003 16004 var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" ); 16005 16006 this.items = $.grep( this.items, function( item ) { 16007 for ( var j = 0; j < list.length; j++ ) { 16008 if ( list[ j ] === item.item[ 0 ] ) { 16009 return false; 16010 } 16011 } 16012 return true; 16013 } ); 16014 16015 }, 16016 16017 _refreshItems: function( event ) { 16018 16019 this.items = []; 16020 this.containers = [ this ]; 16021 16022 var i, j, cur, inst, targetData, _queries, item, queriesLength, 16023 items = this.items, 16024 queries = [ [ typeof this.options.items === "function" ? 16025 this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) : 16026 $( this.options.items, this.element ), this ] ], 16027 connectWith = this._connectWith(); 16028 16029 //Shouldn't be run the first time through due to massive slow-down 16030 if ( connectWith && this.ready ) { 16031 for ( i = connectWith.length - 1; i >= 0; i-- ) { 16032 cur = $( connectWith[ i ], this.document[ 0 ] ); 16033 for ( j = cur.length - 1; j >= 0; j-- ) { 16034 inst = $.data( cur[ j ], this.widgetFullName ); 16035 if ( inst && inst !== this && !inst.options.disabled ) { 16036 queries.push( [ typeof inst.options.items === "function" ? 16037 inst.options.items 16038 .call( inst.element[ 0 ], event, { item: this.currentItem } ) : 16039 $( inst.options.items, inst.element ), inst ] ); 16040 this.containers.push( inst ); 16041 } 16042 } 16043 } 16044 } 16045 16046 for ( i = queries.length - 1; i >= 0; i-- ) { 16047 targetData = queries[ i ][ 1 ]; 16048 _queries = queries[ i ][ 0 ]; 16049 16050 for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) { 16051 item = $( _queries[ j ] ); 16052 16053 // Data for target checking (mouse manager) 16054 item.data( this.widgetName + "-item", targetData ); 16055 16056 items.push( { 16057 item: item, 16058 instance: targetData, 16059 width: 0, height: 0, 16060 left: 0, top: 0 16061 } ); 16062 } 16063 } 16064 16065 }, 16066 16067 _refreshItemPositions: function( fast ) { 16068 var i, item, t, p; 16069 16070 for ( i = this.items.length - 1; i >= 0; i-- ) { 16071 item = this.items[ i ]; 16072 16073 //We ignore calculating positions of all connected containers when we're not over them 16074 if ( this.currentContainer && item.instance !== this.currentContainer && 16075 item.item[ 0 ] !== this.currentItem[ 0 ] ) { 16076 continue; 16077 } 16078 16079 t = this.options.toleranceElement ? 16080 $( this.options.toleranceElement, item.item ) : 16081 item.item; 16082 16083 if ( !fast ) { 16084 item.width = t.outerWidth(); 16085 item.height = t.outerHeight(); 16086 } 16087 16088 p = t.offset(); 16089 item.left = p.left; 16090 item.top = p.top; 16091 } 16092 }, 16093 16094 refreshPositions: function( fast ) { 16095 16096 // Determine whether items are being displayed horizontally 16097 this.floating = this.items.length ? 16098 this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) : 16099 false; 16100 16101 // This has to be redone because due to the item being moved out/into the offsetParent, 16102 // the offsetParent's position will change 16103 if ( this.offsetParent && this.helper ) { 16104 this.offset.parent = this._getParentOffset(); 16105 } 16106 16107 this._refreshItemPositions( fast ); 16108 16109 var i, p; 16110 16111 if ( this.options.custom && this.options.custom.refreshContainers ) { 16112 this.options.custom.refreshContainers.call( this ); 16113 } else { 16114 for ( i = this.containers.length - 1; i >= 0; i-- ) { 16115 p = this.containers[ i ].element.offset(); 16116 this.containers[ i ].containerCache.left = p.left; 16117 this.containers[ i ].containerCache.top = p.top; 16118 this.containers[ i ].containerCache.width = 16119 this.containers[ i ].element.outerWidth(); 16120 this.containers[ i ].containerCache.height = 16121 this.containers[ i ].element.outerHeight(); 16122 } 16123 } 16124 16125 return this; 16126 }, 16127 16128 _createPlaceholder: function( that ) { 16129 that = that || this; 16130 var className, nodeName, 16131 o = that.options; 16132 16133 if ( !o.placeholder || o.placeholder.constructor === String ) { 16134 className = o.placeholder; 16135 nodeName = that.currentItem[ 0 ].nodeName.toLowerCase(); 16136 o.placeholder = { 16137 element: function() { 16138 16139 var element = $( "<" + nodeName + ">", that.document[ 0 ] ); 16140 16141 that._addClass( element, "ui-sortable-placeholder", 16142 className || that.currentItem[ 0 ].className ) 16143 ._removeClass( element, "ui-sortable-helper" ); 16144 16145 if ( nodeName === "tbody" ) { 16146 that._createTrPlaceholder( 16147 that.currentItem.find( "tr" ).eq( 0 ), 16148 $( "<tr>", that.document[ 0 ] ).appendTo( element ) 16149 ); 16150 } else if ( nodeName === "tr" ) { 16151 that._createTrPlaceholder( that.currentItem, element ); 16152 } else if ( nodeName === "img" ) { 16153 element.attr( "src", that.currentItem.attr( "src" ) ); 16154 } 16155 16156 if ( !className ) { 16157 element.css( "visibility", "hidden" ); 16158 } 16159 16160 return element; 16161 }, 16162 update: function( container, p ) { 16163 16164 // 1. If a className is set as 'placeholder option, we don't force sizes - 16165 // the class is responsible for that 16166 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a 16167 // class name is specified 16168 if ( className && !o.forcePlaceholderSize ) { 16169 return; 16170 } 16171 16172 // If the element doesn't have a actual height or width by itself (without 16173 // styles coming from a stylesheet), it receives the inline height and width 16174 // from the dragged item. Or, if it's a tbody or tr, it's going to have a height 16175 // anyway since we're populating them with <td>s above, but they're unlikely to 16176 // be the correct height on their own if the row heights are dynamic, so we'll 16177 // always assign the height of the dragged item given forcePlaceholderSize 16178 // is true. 16179 if ( !p.height() || ( o.forcePlaceholderSize && 16180 ( nodeName === "tbody" || nodeName === "tr" ) ) ) { 16181 p.height( 16182 that.currentItem.innerHeight() - 16183 parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) - 16184 parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) ); 16185 } 16186 if ( !p.width() ) { 16187 p.width( 16188 that.currentItem.innerWidth() - 16189 parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) - 16190 parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) ); 16191 } 16192 } 16193 }; 16194 } 16195 16196 //Create the placeholder 16197 that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) ); 16198 16199 //Append it after the actual current item 16200 that.currentItem.after( that.placeholder ); 16201 16202 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) 16203 o.placeholder.update( that, that.placeholder ); 16204 16205 }, 16206 16207 _createTrPlaceholder: function( sourceTr, targetTr ) { 16208 var that = this; 16209 16210 sourceTr.children().each( function() { 16211 $( "<td> </td>", that.document[ 0 ] ) 16212 .attr( "colspan", $( this ).attr( "colspan" ) || 1 ) 16213 .appendTo( targetTr ); 16214 } ); 16215 }, 16216 16217 _contactContainers: function( event ) { 16218 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, 16219 floating, axis, 16220 innermostContainer = null, 16221 innermostIndex = null; 16222 16223 // Get innermost container that intersects with item 16224 for ( i = this.containers.length - 1; i >= 0; i-- ) { 16225 16226 // Never consider a container that's located within the item itself 16227 if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) { 16228 continue; 16229 } 16230 16231 if ( this._intersectsWith( this.containers[ i ].containerCache ) ) { 16232 16233 // If we've already found a container and it's more "inner" than this, then continue 16234 if ( innermostContainer && 16235 $.contains( 16236 this.containers[ i ].element[ 0 ], 16237 innermostContainer.element[ 0 ] ) ) { 16238 continue; 16239 } 16240 16241 innermostContainer = this.containers[ i ]; 16242 innermostIndex = i; 16243 16244 } else { 16245 16246 // container doesn't intersect. trigger "out" event if necessary 16247 if ( this.containers[ i ].containerCache.over ) { 16248 this.containers[ i ]._trigger( "out", event, this._uiHash( this ) ); 16249 this.containers[ i ].containerCache.over = 0; 16250 } 16251 } 16252 16253 } 16254 16255 // If no intersecting containers found, return 16256 if ( !innermostContainer ) { 16257 return; 16258 } 16259 16260 // Move the item into the container if it's not there already 16261 if ( this.containers.length === 1 ) { 16262 if ( !this.containers[ innermostIndex ].containerCache.over ) { 16263 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) ); 16264 this.containers[ innermostIndex ].containerCache.over = 1; 16265 } 16266 } else { 16267 16268 // When entering a new container, we will find the item with the least distance and 16269 // append our item near it 16270 dist = 10000; 16271 itemWithLeastDistance = null; 16272 floating = innermostContainer.floating || this._isFloating( this.currentItem ); 16273 posProperty = floating ? "left" : "top"; 16274 sizeProperty = floating ? "width" : "height"; 16275 axis = floating ? "pageX" : "pageY"; 16276 16277 for ( j = this.items.length - 1; j >= 0; j-- ) { 16278 if ( !$.contains( 16279 this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] ) 16280 ) { 16281 continue; 16282 } 16283 if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) { 16284 continue; 16285 } 16286 16287 cur = this.items[ j ].item.offset()[ posProperty ]; 16288 nearBottom = false; 16289 if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) { 16290 nearBottom = true; 16291 } 16292 16293 if ( Math.abs( event[ axis ] - cur ) < dist ) { 16294 dist = Math.abs( event[ axis ] - cur ); 16295 itemWithLeastDistance = this.items[ j ]; 16296 this.direction = nearBottom ? "up" : "down"; 16297 } 16298 } 16299 16300 //Check if dropOnEmpty is enabled 16301 if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) { 16302 return; 16303 } 16304 16305 if ( this.currentContainer === this.containers[ innermostIndex ] ) { 16306 if ( !this.currentContainer.containerCache.over ) { 16307 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() ); 16308 this.currentContainer.containerCache.over = 1; 16309 } 16310 return; 16311 } 16312 16313 if ( itemWithLeastDistance ) { 16314 this._rearrange( event, itemWithLeastDistance, null, true ); 16315 } else { 16316 this._rearrange( event, null, this.containers[ innermostIndex ].element, true ); 16317 } 16318 this._trigger( "change", event, this._uiHash() ); 16319 this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) ); 16320 this.currentContainer = this.containers[ innermostIndex ]; 16321 16322 //Update the placeholder 16323 this.options.placeholder.update( this.currentContainer, this.placeholder ); 16324 16325 //Update scrollParent 16326 this.scrollParent = this.placeholder.scrollParent(); 16327 16328 //Update overflowOffset 16329 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && 16330 this.scrollParent[ 0 ].tagName !== "HTML" ) { 16331 this.overflowOffset = this.scrollParent.offset(); 16332 } 16333 16334 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) ); 16335 this.containers[ innermostIndex ].containerCache.over = 1; 16336 } 16337 16338 }, 16339 16340 _createHelper: function( event ) { 16341 16342 var o = this.options, 16343 helper = typeof o.helper === "function" ? 16344 $( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) : 16345 ( o.helper === "clone" ? this.currentItem.clone() : this.currentItem ); 16346 16347 //Add the helper to the DOM if that didn't happen already 16348 if ( !helper.parents( "body" ).length ) { 16349 this.appendTo[ 0 ].appendChild( helper[ 0 ] ); 16350 } 16351 16352 if ( helper[ 0 ] === this.currentItem[ 0 ] ) { 16353 this._storedCSS = { 16354 width: this.currentItem[ 0 ].style.width, 16355 height: this.currentItem[ 0 ].style.height, 16356 position: this.currentItem.css( "position" ), 16357 top: this.currentItem.css( "top" ), 16358 left: this.currentItem.css( "left" ) 16359 }; 16360 } 16361 16362 if ( !helper[ 0 ].style.width || o.forceHelperSize ) { 16363 helper.width( this.currentItem.width() ); 16364 } 16365 if ( !helper[ 0 ].style.height || o.forceHelperSize ) { 16366 helper.height( this.currentItem.height() ); 16367 } 16368 16369 return helper; 16370 16371 }, 16372 16373 _adjustOffsetFromHelper: function( obj ) { 16374 if ( typeof obj === "string" ) { 16375 obj = obj.split( " " ); 16376 } 16377 if ( Array.isArray( obj ) ) { 16378 obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 }; 16379 } 16380 if ( "left" in obj ) { 16381 this.offset.click.left = obj.left + this.margins.left; 16382 } 16383 if ( "right" in obj ) { 16384 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 16385 } 16386 if ( "top" in obj ) { 16387 this.offset.click.top = obj.top + this.margins.top; 16388 } 16389 if ( "bottom" in obj ) { 16390 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 16391 } 16392 }, 16393 16394 _getParentOffset: function() { 16395 16396 //Get the offsetParent and cache its position 16397 this.offsetParent = this.helper.offsetParent(); 16398 var po = this.offsetParent.offset(); 16399 16400 // This is a special case where we need to modify a offset calculated on start, since the 16401 // following happened: 16402 // 1. The position of the helper is absolute, so it's position is calculated based on the 16403 // next positioned parent 16404 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't 16405 // the document, which means that the scroll is included in the initial calculation of the 16406 // offset of the parent, and never recalculated upon drag 16407 if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] && 16408 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) { 16409 po.left += this.scrollParent.scrollLeft(); 16410 po.top += this.scrollParent.scrollTop(); 16411 } 16412 16413 // This needs to be actually done for all browsers, since pageX/pageY includes 16414 // this information. 16415 if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ) { 16416 po = { top: 0, left: 0 }; 16417 } 16418 16419 return { 16420 top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ), 16421 left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 ) 16422 }; 16423 16424 }, 16425 16426 _getRelativeOffset: function() { 16427 16428 if ( this.cssPosition === "relative" ) { 16429 var p = this.currentItem.position(); 16430 return { 16431 top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) + 16432 this.scrollParent.scrollTop(), 16433 left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) + 16434 this.scrollParent.scrollLeft() 16435 }; 16436 } else { 16437 return { top: 0, left: 0 }; 16438 } 16439 16440 }, 16441 16442 _cacheMargins: function() { 16443 this.margins = { 16444 left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ), 16445 top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 ) 16446 }; 16447 }, 16448 16449 _cacheHelperProportions: function() { 16450 this.helperProportions = { 16451 width: this.helper.outerWidth(), 16452 height: this.helper.outerHeight() 16453 }; 16454 }, 16455 16456 _setContainment: function() { 16457 16458 var ce, co, over, 16459 o = this.options; 16460 if ( o.containment === "parent" ) { 16461 o.containment = this.helper[ 0 ].parentNode; 16462 } 16463 if ( o.containment === "document" || o.containment === "window" ) { 16464 this.containment = [ 16465 0 - this.offset.relative.left - this.offset.parent.left, 16466 0 - this.offset.relative.top - this.offset.parent.top, 16467 o.containment === "document" ? 16468 this.document.width() : 16469 this.window.width() - this.helperProportions.width - this.margins.left, 16470 ( o.containment === "document" ? 16471 ( this.document.height() || document.body.parentNode.scrollHeight ) : 16472 this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight 16473 ) - this.helperProportions.height - this.margins.top 16474 ]; 16475 } 16476 16477 if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) { 16478 ce = $( o.containment )[ 0 ]; 16479 co = $( o.containment ).offset(); 16480 over = ( $( ce ).css( "overflow" ) !== "hidden" ); 16481 16482 this.containment = [ 16483 co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) + 16484 ( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left, 16485 co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) + 16486 ( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top, 16487 co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - 16488 ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) - 16489 ( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) - 16490 this.helperProportions.width - this.margins.left, 16491 co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - 16492 ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) - 16493 ( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) - 16494 this.helperProportions.height - this.margins.top 16495 ]; 16496 } 16497 16498 }, 16499 16500 _convertPositionTo: function( d, pos ) { 16501 16502 if ( !pos ) { 16503 pos = this.position; 16504 } 16505 var mod = d === "absolute" ? 1 : -1, 16506 scroll = this.cssPosition === "absolute" && 16507 !( this.scrollParent[ 0 ] !== this.document[ 0 ] && 16508 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? 16509 this.offsetParent : 16510 this.scrollParent, 16511 scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName ); 16512 16513 return { 16514 top: ( 16515 16516 // The absolute mouse position 16517 pos.top + 16518 16519 // Only for relative positioned nodes: Relative offset from element to offset parent 16520 this.offset.relative.top * mod + 16521 16522 // The offsetParent's offset without borders (offset + border) 16523 this.offset.parent.top * mod - 16524 ( ( this.cssPosition === "fixed" ? 16525 -this.scrollParent.scrollTop() : 16526 ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod ) 16527 ), 16528 left: ( 16529 16530 // The absolute mouse position 16531 pos.left + 16532 16533 // Only for relative positioned nodes: Relative offset from element to offset parent 16534 this.offset.relative.left * mod + 16535 16536 // The offsetParent's offset without borders (offset + border) 16537 this.offset.parent.left * mod - 16538 ( ( this.cssPosition === "fixed" ? 16539 -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : 16540 scroll.scrollLeft() ) * mod ) 16541 ) 16542 }; 16543 16544 }, 16545 16546 _generatePosition: function( event ) { 16547 16548 var top, left, 16549 o = this.options, 16550 pageX = event.pageX, 16551 pageY = event.pageY, 16552 scroll = this.cssPosition === "absolute" && 16553 !( this.scrollParent[ 0 ] !== this.document[ 0 ] && 16554 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? 16555 this.offsetParent : 16556 this.scrollParent, 16557 scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName ); 16558 16559 // This is another very weird special case that only happens for relative elements: 16560 // 1. If the css position is relative 16561 // 2. and the scroll parent is the document or similar to the offset parent 16562 // we have to refresh the relative offset during the scroll so there are no jumps 16563 if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] && 16564 this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) { 16565 this.offset.relative = this._getRelativeOffset(); 16566 } 16567 16568 /* 16569 * - Position constraining - 16570 * Constrain the position to a mix of grid, containment. 16571 */ 16572 16573 if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options 16574 16575 if ( this.containment ) { 16576 if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) { 16577 pageX = this.containment[ 0 ] + this.offset.click.left; 16578 } 16579 if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) { 16580 pageY = this.containment[ 1 ] + this.offset.click.top; 16581 } 16582 if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) { 16583 pageX = this.containment[ 2 ] + this.offset.click.left; 16584 } 16585 if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) { 16586 pageY = this.containment[ 3 ] + this.offset.click.top; 16587 } 16588 } 16589 16590 if ( o.grid ) { 16591 top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) / 16592 o.grid[ 1 ] ) * o.grid[ 1 ]; 16593 pageY = this.containment ? 16594 ( ( top - this.offset.click.top >= this.containment[ 1 ] && 16595 top - this.offset.click.top <= this.containment[ 3 ] ) ? 16596 top : 16597 ( ( top - this.offset.click.top >= this.containment[ 1 ] ) ? 16598 top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : 16599 top; 16600 16601 left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) / 16602 o.grid[ 0 ] ) * o.grid[ 0 ]; 16603 pageX = this.containment ? 16604 ( ( left - this.offset.click.left >= this.containment[ 0 ] && 16605 left - this.offset.click.left <= this.containment[ 2 ] ) ? 16606 left : 16607 ( ( left - this.offset.click.left >= this.containment[ 0 ] ) ? 16608 left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : 16609 left; 16610 } 16611 16612 } 16613 16614 return { 16615 top: ( 16616 16617 // The absolute mouse position 16618 pageY - 16619 16620 // Click offset (relative to the element) 16621 this.offset.click.top - 16622 16623 // Only for relative positioned nodes: Relative offset from element to offset parent 16624 this.offset.relative.top - 16625 16626 // The offsetParent's offset without borders (offset + border) 16627 this.offset.parent.top + 16628 ( ( this.cssPosition === "fixed" ? 16629 -this.scrollParent.scrollTop() : 16630 ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) ) 16631 ), 16632 left: ( 16633 16634 // The absolute mouse position 16635 pageX - 16636 16637 // Click offset (relative to the element) 16638 this.offset.click.left - 16639 16640 // Only for relative positioned nodes: Relative offset from element to offset parent 16641 this.offset.relative.left - 16642 16643 // The offsetParent's offset without borders (offset + border) 16644 this.offset.parent.left + 16645 ( ( this.cssPosition === "fixed" ? 16646 -this.scrollParent.scrollLeft() : 16647 scrollIsRootNode ? 0 : scroll.scrollLeft() ) ) 16648 ) 16649 }; 16650 16651 }, 16652 16653 _rearrange: function( event, i, a, hardRefresh ) { 16654 16655 if ( a ) { 16656 a[ 0 ].appendChild( this.placeholder[ 0 ] ); 16657 } else { 16658 i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ], 16659 ( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) ); 16660 } 16661 16662 //Various things done here to improve the performance: 16663 // 1. we create a setTimeout, that calls refreshPositions 16664 // 2. on the instance, we have a counter variable, that get's higher after every append 16665 // 3. on the local scope, we copy the counter variable, and check in the timeout, 16666 // if it's still the same 16667 // 4. this lets only the last addition to the timeout stack through 16668 this.counter = this.counter ? ++this.counter : 1; 16669 var counter = this.counter; 16670 16671 this._delay( function() { 16672 if ( counter === this.counter ) { 16673 16674 //Precompute after each DOM insertion, NOT on mousemove 16675 this.refreshPositions( !hardRefresh ); 16676 } 16677 } ); 16678 16679 }, 16680 16681 _clear: function( event, noPropagation ) { 16682 16683 this.reverting = false; 16684 16685 // We delay all events that have to be triggered to after the point where the placeholder 16686 // has been removed and everything else normalized again 16687 var i, 16688 delayedTriggers = []; 16689 16690 // We first have to update the dom position of the actual currentItem 16691 // Note: don't do it if the current item is already removed (by a user), or it gets 16692 // reappended (see #4088) 16693 if ( !this._noFinalSort && this.currentItem.parent().length ) { 16694 this.placeholder.before( this.currentItem ); 16695 } 16696 this._noFinalSort = null; 16697 16698 if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) { 16699 for ( i in this._storedCSS ) { 16700 if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) { 16701 this._storedCSS[ i ] = ""; 16702 } 16703 } 16704 this.currentItem.css( this._storedCSS ); 16705 this._removeClass( this.currentItem, "ui-sortable-helper" ); 16706 } else { 16707 this.currentItem.show(); 16708 } 16709 16710 if ( this.fromOutside && !noPropagation ) { 16711 delayedTriggers.push( function( event ) { 16712 this._trigger( "receive", event, this._uiHash( this.fromOutside ) ); 16713 } ); 16714 } 16715 if ( ( this.fromOutside || 16716 this.domPosition.prev !== 16717 this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] || 16718 this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) { 16719 16720 // Trigger update callback if the DOM position has changed 16721 delayedTriggers.push( function( event ) { 16722 this._trigger( "update", event, this._uiHash() ); 16723 } ); 16724 } 16725 16726 // Check if the items Container has Changed and trigger appropriate 16727 // events. 16728 if ( this !== this.currentContainer ) { 16729 if ( !noPropagation ) { 16730 delayedTriggers.push( function( event ) { 16731 this._trigger( "remove", event, this._uiHash() ); 16732 } ); 16733 delayedTriggers.push( ( function( c ) { 16734 return function( event ) { 16735 c._trigger( "receive", event, this._uiHash( this ) ); 16736 }; 16737 } ).call( this, this.currentContainer ) ); 16738 delayedTriggers.push( ( function( c ) { 16739 return function( event ) { 16740 c._trigger( "update", event, this._uiHash( this ) ); 16741 }; 16742 } ).call( this, this.currentContainer ) ); 16743 } 16744 } 16745 16746 //Post events to containers 16747 function delayEvent( type, instance, container ) { 16748 return function( event ) { 16749 container._trigger( type, event, instance._uiHash( instance ) ); 16750 }; 16751 } 16752 for ( i = this.containers.length - 1; i >= 0; i-- ) { 16753 if ( !noPropagation ) { 16754 delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) ); 16755 } 16756 if ( this.containers[ i ].containerCache.over ) { 16757 delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) ); 16758 this.containers[ i ].containerCache.over = 0; 16759 } 16760 } 16761 16762 //Do what was originally in plugins 16763 if ( this._storedStylesheet ) { 16764 this._storedStylesheet.remove(); 16765 this._storedStylesheet = null; 16766 } 16767 if ( this._storedOpacity ) { 16768 this.helper.css( "opacity", this._storedOpacity ); 16769 } 16770 if ( this._storedZIndex ) { 16771 this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex ); 16772 } 16773 16774 this.dragging = false; 16775 16776 if ( !noPropagation ) { 16777 this._trigger( "beforeStop", event, this._uiHash() ); 16778 } 16779 16780 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, 16781 // it unbinds ALL events from the original node! 16782 this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] ); 16783 16784 if ( !this.cancelHelperRemoval ) { 16785 if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) { 16786 this.helper.remove(); 16787 } 16788 this.helper = null; 16789 } 16790 16791 if ( !noPropagation ) { 16792 for ( i = 0; i < delayedTriggers.length; i++ ) { 16793 16794 // Trigger all delayed events 16795 delayedTriggers[ i ].call( this, event ); 16796 } 16797 this._trigger( "stop", event, this._uiHash() ); 16798 } 16799 16800 this.fromOutside = false; 16801 return !this.cancelHelperRemoval; 16802 16803 }, 16804 16805 _trigger: function() { 16806 if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) { 16807 this.cancel(); 16808 } 16809 }, 16810 16811 _uiHash: function( _inst ) { 16812 var inst = _inst || this; 16813 return { 16814 helper: inst.helper, 16815 placeholder: inst.placeholder || $( [] ), 16816 position: inst.position, 16817 originalPosition: inst.originalPosition, 16818 offset: inst.positionAbs, 16819 item: inst.currentItem, 16820 sender: _inst ? _inst.element : null 16821 }; 16822 } 16823 16824} ); 16825 16826 16827/*! 16828 * jQuery UI Spinner 1.14.0 16829 * https://jqueryui.com 16830 * 16831 * Copyright OpenJS Foundation and other contributors 16832 * Released under the MIT license. 16833 * https://jquery.org/license 16834 */ 16835 16836//>>label: Spinner 16837//>>group: Widgets 16838//>>description: Displays buttons to easily input numbers via the keyboard or mouse. 16839//>>docs: https://api.jqueryui.com/spinner/ 16840//>>demos: https://jqueryui.com/spinner/ 16841//>>css.structure: ../../themes/base/core.css 16842//>>css.structure: ../../themes/base/spinner.css 16843//>>css.theme: ../../themes/base/theme.css 16844 16845 16846function spinnerModifier( fn ) { 16847 return function() { 16848 var previous = this.element.val(); 16849 fn.apply( this, arguments ); 16850 this._refresh(); 16851 if ( previous !== this.element.val() ) { 16852 this._trigger( "change" ); 16853 } 16854 }; 16855} 16856 16857$.widget( "ui.spinner", { 16858 version: "1.14.0", 16859 defaultElement: "<input>", 16860 widgetEventPrefix: "spin", 16861 options: { 16862 classes: { 16863 "ui-spinner": "ui-corner-all", 16864 "ui-spinner-down": "ui-corner-br", 16865 "ui-spinner-up": "ui-corner-tr" 16866 }, 16867 culture: null, 16868 icons: { 16869 down: "ui-icon-triangle-1-s", 16870 up: "ui-icon-triangle-1-n" 16871 }, 16872 incremental: true, 16873 max: null, 16874 min: null, 16875 numberFormat: null, 16876 page: 10, 16877 step: 1, 16878 16879 change: null, 16880 spin: null, 16881 start: null, 16882 stop: null 16883 }, 16884 16885 _create: function() { 16886 16887 // handle string values that need to be parsed 16888 this._setOption( "max", this.options.max ); 16889 this._setOption( "min", this.options.min ); 16890 this._setOption( "step", this.options.step ); 16891 16892 // Only format if there is a value, prevents the field from being marked 16893 // as invalid in Firefox, see #9573. 16894 if ( this.value() !== "" ) { 16895 16896 // Format the value, but don't constrain. 16897 this._value( this.element.val(), true ); 16898 } 16899 16900 this._draw(); 16901 this._on( this._events ); 16902 this._refresh(); 16903 16904 // Turning off autocomplete prevents the browser from remembering the 16905 // value when navigating through history, so we re-enable autocomplete 16906 // if the page is unloaded before the widget is destroyed. #7790 16907 this._on( this.window, { 16908 beforeunload: function() { 16909 this.element.removeAttr( "autocomplete" ); 16910 } 16911 } ); 16912 }, 16913 16914 _getCreateOptions: function() { 16915 var options = this._super(); 16916 var element = this.element; 16917 16918 $.each( [ "min", "max", "step" ], function( i, option ) { 16919 var value = element.attr( option ); 16920 if ( value != null && value.length ) { 16921 options[ option ] = value; 16922 } 16923 } ); 16924 16925 return options; 16926 }, 16927 16928 _events: { 16929 keydown: function( event ) { 16930 if ( this._start( event ) && this._keydown( event ) ) { 16931 event.preventDefault(); 16932 } 16933 }, 16934 keyup: "_stop", 16935 focus: function() { 16936 this.previous = this.element.val(); 16937 }, 16938 blur: function( event ) { 16939 this._stop(); 16940 this._refresh(); 16941 if ( this.previous !== this.element.val() ) { 16942 this._trigger( "change", event ); 16943 } 16944 }, 16945 mousewheel: function( event, delta ) { 16946 var activeElement = this.document[ 0 ].activeElement; 16947 var isActive = this.element[ 0 ] === activeElement; 16948 16949 if ( !isActive || !delta ) { 16950 return; 16951 } 16952 16953 if ( !this.spinning && !this._start( event ) ) { 16954 return false; 16955 } 16956 16957 this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event ); 16958 clearTimeout( this.mousewheelTimer ); 16959 this.mousewheelTimer = this._delay( function() { 16960 if ( this.spinning ) { 16961 this._stop( event ); 16962 } 16963 }, 100 ); 16964 event.preventDefault(); 16965 }, 16966 "mousedown .ui-spinner-button": function( event ) { 16967 var previous; 16968 16969 // We never want the buttons to have focus; whenever the user is 16970 // interacting with the spinner, the focus should be on the input. 16971 // If the input is focused then this.previous is properly set from 16972 // when the input first received focus. If the input is not focused 16973 // then we need to set this.previous based on the value before spinning. 16974 previous = this.element[ 0 ] === this.document[ 0 ].activeElement ? 16975 this.previous : this.element.val(); 16976 function checkFocus() { 16977 var isActive = this.element[ 0 ] === this.document[ 0 ].activeElement; 16978 if ( !isActive ) { 16979 this.element.trigger( "focus" ); 16980 this.previous = previous; 16981 } 16982 } 16983 16984 // Ensure focus is on (or stays on) the text field 16985 event.preventDefault(); 16986 checkFocus.call( this ); 16987 16988 if ( this._start( event ) === false ) { 16989 return; 16990 } 16991 16992 this._repeat( null, $( event.currentTarget ) 16993 .hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 16994 }, 16995 "mouseup .ui-spinner-button": "_stop", 16996 "mouseenter .ui-spinner-button": function( event ) { 16997 16998 // button will add ui-state-active if mouse was down while mouseleave and kept down 16999 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) { 17000 return; 17001 } 17002 17003 if ( this._start( event ) === false ) { 17004 return false; 17005 } 17006 this._repeat( null, $( event.currentTarget ) 17007 .hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 17008 }, 17009 17010 // TODO: do we really want to consider this a stop? 17011 // shouldn't we just stop the repeater and wait until mouseup before 17012 // we trigger the stop event? 17013 "mouseleave .ui-spinner-button": "_stop" 17014 }, 17015 17016 // Support mobile enhanced option and make backcompat more sane 17017 _enhance: function() { 17018 this.uiSpinner = this.element 17019 .attr( "autocomplete", "off" ) 17020 .wrap( "<span>" ) 17021 .parent() 17022 17023 // Add buttons 17024 .append( 17025 "<a></a><a></a>" 17026 ); 17027 }, 17028 17029 _draw: function() { 17030 this._enhance(); 17031 17032 this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" ); 17033 this._addClass( "ui-spinner-input" ); 17034 17035 this.element.attr( "role", "spinbutton" ); 17036 17037 // Button bindings 17038 this.buttons = this.uiSpinner.children( "a" ) 17039 .attr( "tabIndex", -1 ) 17040 .attr( "aria-hidden", true ) 17041 .button( { 17042 classes: { 17043 "ui-button": "" 17044 } 17045 } ); 17046 17047 // TODO: Right now button does not support classes this is already updated in button PR 17048 this._removeClass( this.buttons, "ui-corner-all" ); 17049 17050 this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" ); 17051 this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" ); 17052 this.buttons.first().button( { 17053 "icon": this.options.icons.up, 17054 "showLabel": false 17055 } ); 17056 this.buttons.last().button( { 17057 "icon": this.options.icons.down, 17058 "showLabel": false 17059 } ); 17060 17061 // IE 6 doesn't understand height: 50% for the buttons 17062 // unless the wrapper has an explicit height 17063 if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) && 17064 this.uiSpinner.height() > 0 ) { 17065 this.uiSpinner.height( this.uiSpinner.height() ); 17066 } 17067 }, 17068 17069 _keydown: function( event ) { 17070 var options = this.options, 17071 keyCode = $.ui.keyCode; 17072 17073 switch ( event.keyCode ) { 17074 case keyCode.UP: 17075 this._repeat( null, 1, event ); 17076 return true; 17077 case keyCode.DOWN: 17078 this._repeat( null, -1, event ); 17079 return true; 17080 case keyCode.PAGE_UP: 17081 this._repeat( null, options.page, event ); 17082 return true; 17083 case keyCode.PAGE_DOWN: 17084 this._repeat( null, -options.page, event ); 17085 return true; 17086 } 17087 17088 return false; 17089 }, 17090 17091 _start: function( event ) { 17092 if ( !this.spinning && this._trigger( "start", event ) === false ) { 17093 return false; 17094 } 17095 17096 if ( !this.counter ) { 17097 this.counter = 1; 17098 } 17099 this.spinning = true; 17100 return true; 17101 }, 17102 17103 _repeat: function( i, steps, event ) { 17104 i = i || 500; 17105 17106 clearTimeout( this.timer ); 17107 this.timer = this._delay( function() { 17108 this._repeat( 40, steps, event ); 17109 }, i ); 17110 17111 this._spin( steps * this.options.step, event ); 17112 }, 17113 17114 _spin: function( step, event ) { 17115 var value = this.value() || 0; 17116 17117 if ( !this.counter ) { 17118 this.counter = 1; 17119 } 17120 17121 value = this._adjustValue( value + step * this._increment( this.counter ) ); 17122 17123 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) { 17124 this._value( value ); 17125 this.counter++; 17126 } 17127 }, 17128 17129 _increment: function( i ) { 17130 var incremental = this.options.incremental; 17131 17132 if ( incremental ) { 17133 return typeof incremental === "function" ? 17134 incremental( i ) : 17135 Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 ); 17136 } 17137 17138 return 1; 17139 }, 17140 17141 _precision: function() { 17142 var precision = this._precisionOf( this.options.step ); 17143 if ( this.options.min !== null ) { 17144 precision = Math.max( precision, this._precisionOf( this.options.min ) ); 17145 } 17146 return precision; 17147 }, 17148 17149 _precisionOf: function( num ) { 17150 var str = num.toString(), 17151 decimal = str.indexOf( "." ); 17152 return decimal === -1 ? 0 : str.length - decimal - 1; 17153 }, 17154 17155 _adjustValue: function( value ) { 17156 var base, aboveMin, 17157 options = this.options; 17158 17159 // Make sure we're at a valid step 17160 // - find out where we are relative to the base (min or 0) 17161 base = options.min !== null ? options.min : 0; 17162 aboveMin = value - base; 17163 17164 // - round to the nearest step 17165 aboveMin = Math.round( aboveMin / options.step ) * options.step; 17166 17167 // - rounding is based on 0, so adjust back to our base 17168 value = base + aboveMin; 17169 17170 // Fix precision from bad JS floating point math 17171 value = parseFloat( value.toFixed( this._precision() ) ); 17172 17173 // Clamp the value 17174 if ( options.max !== null && value > options.max ) { 17175 return options.max; 17176 } 17177 if ( options.min !== null && value < options.min ) { 17178 return options.min; 17179 } 17180 17181 return value; 17182 }, 17183 17184 _stop: function( event ) { 17185 if ( !this.spinning ) { 17186 return; 17187 } 17188 17189 clearTimeout( this.timer ); 17190 clearTimeout( this.mousewheelTimer ); 17191 this.counter = 0; 17192 this.spinning = false; 17193 this._trigger( "stop", event ); 17194 }, 17195 17196 _setOption: function( key, value ) { 17197 var prevValue, first, last; 17198 17199 if ( key === "culture" || key === "numberFormat" ) { 17200 prevValue = this._parse( this.element.val() ); 17201 this.options[ key ] = value; 17202 this.element.val( this._format( prevValue ) ); 17203 return; 17204 } 17205
vendor: 12,923 bytes, lines 17206-17701
17206 if ( key === "max" || key === "min" || key === "step" ) { 17207 if ( typeof value === "string" ) { 17208 value = this._parse( value ); 17209 } 17210 } 17211 if ( key === "icons" ) { 17212 first = this.buttons.first().find( ".ui-icon" ); 17213 this._removeClass( first, null, this.options.icons.up ); 17214 this._addClass( first, null, value.up ); 17215 last = this.buttons.last().find( ".ui-icon" ); 17216 this._removeClass( last, null, this.options.icons.down ); 17217 this._addClass( last, null, value.down ); 17218 } 17219 17220 this._super( key, value ); 17221 }, 17222 17223 _setOptionDisabled: function( value ) { 17224 this._super( value ); 17225 17226 this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value ); 17227 this.element.prop( "disabled", !!value ); 17228 this.buttons.button( value ? "disable" : "enable" ); 17229 }, 17230 17231 _setOptions: spinnerModifier( function( options ) { 17232 this._super( options ); 17233 } ), 17234 17235 _parse: function( val ) { 17236 if ( typeof val === "string" && val !== "" ) { 17237 val = window.Globalize && this.options.numberFormat ? 17238 Globalize.parseFloat( val, 10, this.options.culture ) : +val; 17239 } 17240 return val === "" || isNaN( val ) ? null : val; 17241 }, 17242 17243 _format: function( value ) { 17244 if ( value === "" ) { 17245 return ""; 17246 } 17247 return window.Globalize && this.options.numberFormat ? 17248 Globalize.format( value, this.options.numberFormat, this.options.culture ) : 17249 value; 17250 }, 17251 17252 _refresh: function() { 17253 this.element.attr( { 17254 "aria-valuemin": this.options.min, 17255 "aria-valuemax": this.options.max, 17256 17257 // TODO: what should we do with values that can't be parsed? 17258 "aria-valuenow": this._parse( this.element.val() ) 17259 } ); 17260 }, 17261 17262 isValid: function() { 17263 var value = this.value(); 17264 17265 // Null is invalid 17266 if ( value === null ) { 17267 return false; 17268 } 17269 17270 // If value gets adjusted, it's invalid 17271 return value === this._adjustValue( value ); 17272 }, 17273 17274 // Update the value without triggering change 17275 _value: function( value, allowAny ) { 17276 var parsed; 17277 if ( value !== "" ) { 17278 parsed = this._parse( value ); 17279 if ( parsed !== null ) { 17280 if ( !allowAny ) { 17281 parsed = this._adjustValue( parsed ); 17282 } 17283 value = this._format( parsed ); 17284 } 17285 } 17286 this.element.val( value ); 17287 this._refresh(); 17288 }, 17289 17290 _destroy: function() { 17291 this.element 17292 .prop( "disabled", false ) 17293 .removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" ); 17294 17295 this.uiSpinner.replaceWith( this.element ); 17296 }, 17297 17298 stepUp: spinnerModifier( function( steps ) { 17299 this._stepUp( steps ); 17300 } ), 17301 _stepUp: function( steps ) { 17302 if ( this._start() ) { 17303 this._spin( ( steps || 1 ) * this.options.step ); 17304 this._stop(); 17305 } 17306 }, 17307 17308 stepDown: spinnerModifier( function( steps ) { 17309 this._stepDown( steps ); 17310 } ), 17311 _stepDown: function( steps ) { 17312 if ( this._start() ) { 17313 this._spin( ( steps || 1 ) * -this.options.step ); 17314 this._stop(); 17315 } 17316 }, 17317 17318 pageUp: spinnerModifier( function( pages ) { 17319 this._stepUp( ( pages || 1 ) * this.options.page ); 17320 } ), 17321 17322 pageDown: spinnerModifier( function( pages ) { 17323 this._stepDown( ( pages || 1 ) * this.options.page ); 17324 } ), 17325 17326 value: function( newVal ) { 17327 if ( !arguments.length ) { 17328 return this._parse( this.element.val() ); 17329 } 17330 spinnerModifier( this._value ).call( this, newVal ); 17331 }, 17332 17333 widget: function() { 17334 return this.uiSpinner; 17335 } 17336} ); 17337 17338// DEPRECATED 17339// TODO: switch return back to widget declaration at top of file when this is removed 17340if ( $.uiBackCompat === true ) { 17341 17342 // Backcompat for spinner html extension points 17343 $.widget( "ui.spinner", $.ui.spinner, { 17344 _enhance: function() { 17345 this.uiSpinner = this.element 17346 .attr( "autocomplete", "off" ) 17347 .wrap( this._uiSpinnerHtml() ) 17348 .parent() 17349 17350 // Add buttons 17351 .append( this._buttonHtml() ); 17352 }, 17353 _uiSpinnerHtml: function() { 17354 return "<span>"; 17355 }, 17356 17357 _buttonHtml: function() { 17358 return "<a></a><a></a>"; 17359 } 17360 } ); 17361} 17362 17363var widgetsSpinner = $.ui.spinner; 17364 17365 17366/*! 17367 * jQuery UI Tabs 1.14.0 17368 * https://jqueryui.com 17369 * 17370 * Copyright OpenJS Foundation and other contributors 17371 * Released under the MIT license. 17372 * https://jquery.org/license 17373 */ 17374 17375//>>label: Tabs 17376//>>group: Widgets 17377//>>description: Transforms a set of container elements into a tab structure. 17378//>>docs: https://api.jqueryui.com/tabs/ 17379//>>demos: https://jqueryui.com/tabs/ 17380//>>css.structure: ../../themes/base/core.css 17381//>>css.structure: ../../themes/base/tabs.css 17382//>>css.theme: ../../themes/base/theme.css 17383 17384 17385$.widget( "ui.tabs", { 17386 version: "1.14.0", 17387 delay: 300, 17388 options: { 17389 active: null, 17390 classes: { 17391 "ui-tabs": "ui-corner-all", 17392 "ui-tabs-nav": "ui-corner-all", 17393 "ui-tabs-panel": "ui-corner-bottom", 17394 "ui-tabs-tab": "ui-corner-top" 17395 }, 17396 collapsible: false, 17397 event: "click", 17398 heightStyle: "content", 17399 hide: null, 17400 show: null, 17401 17402 // Callbacks 17403 activate: null, 17404 beforeActivate: null, 17405 beforeLoad: null, 17406 load: null 17407 }, 17408 17409 _isLocal: ( function() { 17410 var rhash = /#.*$/; 17411 17412 return function( anchor ) { 17413 var anchorUrl, locationUrl; 17414 17415 anchorUrl = anchor.href.replace( rhash, "" ); 17416 locationUrl = location.href.replace( rhash, "" ); 17417 17418 // Decoding may throw an error if the URL isn't UTF-8 (#9518) 17419 try { 17420 anchorUrl = decodeURIComponent( anchorUrl ); 17421 } catch ( error ) {} 17422 try { 17423 locationUrl = decodeURIComponent( locationUrl ); 17424 } catch ( error ) {} 17425 17426 return anchor.hash.length > 1 && anchorUrl === locationUrl; 17427 }; 17428 } )(), 17429 17430 _create: function() { 17431 var that = this, 17432 options = this.options; 17433 17434 this.running = false; 17435 17436 this._addClass( "ui-tabs", "ui-widget ui-widget-content" ); 17437 this._toggleClass( "ui-tabs-collapsible", null, options.collapsible ); 17438 17439 this._processTabs(); 17440 options.active = this._initialActive(); 17441 17442 // Take disabling tabs via class attribute from HTML 17443 // into account and update option properly. 17444 if ( Array.isArray( options.disabled ) ) { 17445 options.disabled = $.uniqueSort( options.disabled.concat( 17446 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { 17447 return that.tabs.index( li ); 17448 } ) 17449 ) ).sort(); 17450 } 17451 17452 // Check for length avoids error when initializing empty list 17453 if ( this.options.active !== false && this.anchors.length ) { 17454 this.active = this._findActive( options.active ); 17455 } else { 17456 this.active = $(); 17457 } 17458 17459 this._refresh(); 17460 17461 if ( this.active.length ) { 17462 this.load( options.active ); 17463 } 17464 }, 17465 17466 _initialActive: function() { 17467 var active = this.options.active, 17468 collapsible = this.options.collapsible, 17469 locationHash = location.hash.substring( 1 ); 17470 17471 if ( active === null ) { 17472 17473 // check the fragment identifier in the URL 17474 if ( locationHash ) { 17475 this.tabs.each( function( i, tab ) { 17476 if ( $( tab ).attr( "aria-controls" ) === locationHash ) { 17477 active = i; 17478 return false; 17479 } 17480 } ); 17481 } 17482 17483 // Check for a tab marked active via a class 17484 if ( active === null ) { 17485 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); 17486 } 17487 17488 // No active tab, set to false 17489 if ( active === null || active === -1 ) { 17490 active = this.tabs.length ? 0 : false; 17491 } 17492 } 17493 17494 // Handle numbers: negative, out of range 17495 if ( active !== false ) { 17496 active = this.tabs.index( this.tabs.eq( active ) ); 17497 if ( active === -1 ) { 17498 active = collapsible ? false : 0; 17499 } 17500 } 17501 17502 // Don't allow collapsible: false and active: false 17503 if ( !collapsible && active === false && this.anchors.length ) { 17504 active = 0; 17505 } 17506 17507 return active; 17508 }, 17509 17510 _getCreateEventData: function() { 17511 return { 17512 tab: this.active, 17513 panel: !this.active.length ? $() : this._getPanelForTab( this.active ) 17514 }; 17515 }, 17516 17517 _tabKeydown: function( event ) { 17518 var focusedTab = $( this.document[ 0 ].activeElement ).closest( "li" ), 17519 selectedIndex = this.tabs.index( focusedTab ), 17520 goingForward = true; 17521 17522 if ( this._handlePageNav( event ) ) { 17523 return; 17524 } 17525 17526 switch ( event.keyCode ) { 17527 case $.ui.keyCode.RIGHT: 17528 case $.ui.keyCode.DOWN: 17529 selectedIndex++; 17530 break; 17531 case $.ui.keyCode.UP: 17532 case $.ui.keyCode.LEFT: 17533 goingForward = false; 17534 selectedIndex--; 17535 break; 17536 case $.ui.keyCode.END: 17537 selectedIndex = this.anchors.length - 1; 17538 break; 17539 case $.ui.keyCode.HOME: 17540 selectedIndex = 0; 17541 break; 17542 case $.ui.keyCode.SPACE: 17543 17544 // Activate only, no collapsing 17545 event.preventDefault(); 17546 clearTimeout( this.activating ); 17547 this._activate( selectedIndex ); 17548 return; 17549 case $.ui.keyCode.ENTER: 17550 17551 // Toggle (cancel delayed activation, allow collapsing) 17552 event.preventDefault(); 17553 clearTimeout( this.activating ); 17554 17555 // Determine if we should collapse or activate 17556 this._activate( selectedIndex === this.options.active ? false : selectedIndex ); 17557 return; 17558 default: 17559 return; 17560 } 17561 17562 // Focus the appropriate tab, based on which key was pressed 17563 event.preventDefault(); 17564 clearTimeout( this.activating ); 17565 selectedIndex = this._focusNextTab( selectedIndex, goingForward ); 17566 17567 // Navigating with control/command key will prevent automatic activation 17568 if ( !event.ctrlKey && !event.metaKey ) { 17569 17570 // Update aria-selected immediately so that AT think the tab is already selected. 17571 // Otherwise AT may confuse the user by stating that they need to activate the tab, 17572 // but the tab will already be activated by the time the announcement finishes. 17573 focusedTab.attr( "aria-selected", "false" ); 17574 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); 17575 17576 this.activating = this._delay( function() { 17577 this.option( "active", selectedIndex ); 17578 }, this.delay ); 17579 } 17580 }, 17581 17582 _panelKeydown: function( event ) { 17583 if ( this._handlePageNav( event ) ) { 17584 return; 17585 } 17586 17587 // Ctrl+up moves focus to the current tab 17588 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { 17589 event.preventDefault(); 17590 this.active.trigger( "focus" ); 17591 } 17592 }, 17593 17594 // Alt+page up/down moves focus to the previous/next tab (and activates) 17595 _handlePageNav: function( event ) { 17596 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { 17597 this._activate( this._focusNextTab( this.options.active - 1, false ) ); 17598 return true; 17599 } 17600 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { 17601 this._activate( this._focusNextTab( this.options.active + 1, true ) ); 17602 return true; 17603 } 17604 }, 17605 17606 _findNextTab: function( index, goingForward ) { 17607 var lastTabIndex = this.tabs.length - 1; 17608 17609 function constrain() { 17610 if ( index > lastTabIndex ) { 17611 index = 0; 17612 } 17613 if ( index < 0 ) { 17614 index = lastTabIndex; 17615 } 17616 return index; 17617 } 17618 17619 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { 17620 index = goingForward ? index + 1 : index - 1; 17621 } 17622 17623 return index; 17624 }, 17625 17626 _focusNextTab: function( index, goingForward ) { 17627 index = this._findNextTab( index, goingForward ); 17628 this.tabs.eq( index ).trigger( "focus" ); 17629 return index; 17630 }, 17631 17632 _setOption: function( key, value ) { 17633 if ( key === "active" ) { 17634 17635 // _activate() will handle invalid values and update this.options 17636 this._activate( value ); 17637 return; 17638 } 17639 17640 this._super( key, value ); 17641 17642 if ( key === "collapsible" ) { 17643 this._toggleClass( "ui-tabs-collapsible", null, value ); 17644 17645 // Setting collapsible: false while collapsed; open first panel 17646 if ( !value && this.options.active === false ) { 17647 this._activate( 0 ); 17648 } 17649 } 17650 17651 if ( key === "event" ) { 17652 this._setupEvents( value ); 17653 } 17654 17655 if ( key === "heightStyle" ) { 17656 this._setupHeightStyle( value ); 17657 } 17658 }, 17659 17660 _sanitizeSelector: function( hash ) { 17661 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : ""; 17662 }, 17663 17664 refresh: function() { 17665 var options = this.options, 17666 lis = this.tablist.children( ":has(a[href])" ); 17667 17668 // Get disabled tabs from class attribute from HTML 17669 // this will get converted to a boolean if needed in _refresh() 17670 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { 17671 return lis.index( tab ); 17672 } ); 17673 17674 this._processTabs(); 17675 17676 // Was collapsed or no tabs 17677 if ( options.active === false || !this.anchors.length ) { 17678 options.active = false; 17679 this.active = $(); 17680 17681 // was active, but active tab is gone 17682 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { 17683 17684 // all remaining tabs are disabled 17685 if ( this.tabs.length === options.disabled.length ) { 17686 options.active = false; 17687 this.active = $(); 17688 17689 // activate previous tab 17690 } else { 17691 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); 17692 } 17693 17694 // was active, active tab still exists 17695 } else { 17696 17697 // make sure active index is correct 17698 options.active = this.tabs.index( this.active ); 17699 } 17700 17701 this._refresh();
vendor: 28,652 bytes, lines 17702-18745
17702 }, 17703 17704 _refresh: function() { 17705 this._setOptionDisabled( this.options.disabled ); 17706 this._setupEvents( this.options.event ); 17707 this._setupHeightStyle( this.options.heightStyle ); 17708 17709 this.tabs.not( this.active ).attr( { 17710 "aria-selected": "false", 17711 "aria-expanded": "false", 17712 tabIndex: -1 17713 } ); 17714 this.panels.not( this._getPanelForTab( this.active ) ) 17715 .hide() 17716 .attr( { 17717 "aria-hidden": "true" 17718 } ); 17719 17720 // Make sure one tab is in the tab order 17721 if ( !this.active.length ) { 17722 this.tabs.eq( 0 ).attr( "tabIndex", 0 ); 17723 } else { 17724 this.active 17725 .attr( { 17726 "aria-selected": "true", 17727 "aria-expanded": "true", 17728 tabIndex: 0 17729 } ); 17730 this._addClass( this.active, "ui-tabs-active", "ui-state-active" ); 17731 this._getPanelForTab( this.active ) 17732 .show() 17733 .attr( { 17734 "aria-hidden": "false" 17735 } ); 17736 } 17737 }, 17738 17739 _processTabs: function() { 17740 var that = this, 17741 prevTabs = this.tabs, 17742 prevAnchors = this.anchors, 17743 prevPanels = this.panels; 17744 17745 this.tablist = this._getList().attr( "role", "tablist" ); 17746 this._addClass( this.tablist, "ui-tabs-nav", 17747 "ui-helper-reset ui-helper-clearfix ui-widget-header" ); 17748 17749 // Prevent users from focusing disabled tabs via click 17750 this.tablist 17751 .on( "mousedown" + this.eventNamespace, "> li", function( event ) { 17752 if ( $( this ).is( ".ui-state-disabled" ) ) { 17753 event.preventDefault(); 17754 } 17755 } ); 17756 17757 this.tabs = this.tablist.find( "> li:has(a[href])" ) 17758 .attr( { 17759 role: "tab", 17760 tabIndex: -1 17761 } ); 17762 this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" ); 17763 17764 this.anchors = this.tabs.map( function() { 17765 return $( "a", this )[ 0 ]; 17766 } ) 17767 .attr( { 17768 tabIndex: -1 17769 } ); 17770 this._addClass( this.anchors, "ui-tabs-anchor" ); 17771 17772 this.panels = $(); 17773 17774 this.anchors.each( function( i, anchor ) { 17775 var selector, panel, panelId, 17776 anchorId = $( anchor ).uniqueId().attr( "id" ), 17777 tab = $( anchor ).closest( "li" ), 17778 originalAriaControls = tab.attr( "aria-controls" ); 17779 17780 // Inline tab 17781 if ( that._isLocal( anchor ) ) { 17782 selector = anchor.hash; 17783 panelId = selector.substring( 1 ); 17784 panel = that.element.find( that._sanitizeSelector( selector ) ); 17785 17786 // remote tab 17787 } else { 17788 17789 // If the tab doesn't already have aria-controls, 17790 // generate an id by using a throw-away element 17791 panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id; 17792 selector = "#" + panelId; 17793 panel = that.element.find( selector ); 17794 if ( !panel.length ) { 17795 panel = that._createPanel( panelId ); 17796 panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); 17797 } 17798 panel.attr( "aria-live", "polite" ); 17799 } 17800 17801 if ( panel.length ) { 17802 that.panels = that.panels.add( panel ); 17803 } 17804 if ( originalAriaControls ) { 17805 tab.data( "ui-tabs-aria-controls", originalAriaControls ); 17806 } 17807 tab.attr( { 17808 "aria-controls": panelId, 17809 "aria-labelledby": anchorId 17810 } ); 17811 panel.attr( "aria-labelledby", anchorId ); 17812 } ); 17813 17814 this.panels.attr( "role", "tabpanel" ); 17815 this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" ); 17816 17817 // Avoid memory leaks (#10056) 17818 if ( prevTabs ) { 17819 this._off( prevTabs.not( this.tabs ) ); 17820 this._off( prevAnchors.not( this.anchors ) ); 17821 this._off( prevPanels.not( this.panels ) ); 17822 } 17823 }, 17824 17825 // Allow overriding how to find the list for rare usage scenarios (#7715) 17826 _getList: function() { 17827 return this.tablist || this.element.find( "ol, ul" ).eq( 0 ); 17828 }, 17829 17830 _createPanel: function( id ) { 17831 return $( "<div>" ) 17832 .attr( "id", id ) 17833 .data( "ui-tabs-destroy", true ); 17834 }, 17835 17836 _setOptionDisabled: function( disabled ) { 17837 var currentItem, li, i; 17838 17839 if ( Array.isArray( disabled ) ) { 17840 if ( !disabled.length ) { 17841 disabled = false; 17842 } else if ( disabled.length === this.anchors.length ) { 17843 disabled = true; 17844 } 17845 } 17846 17847 // Disable tabs 17848 for ( i = 0; ( li = this.tabs[ i ] ); i++ ) { 17849 currentItem = $( li ); 17850 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { 17851 currentItem.attr( "aria-disabled", "true" ); 17852 this._addClass( currentItem, null, "ui-state-disabled" ); 17853 } else { 17854 currentItem.removeAttr( "aria-disabled" ); 17855 this._removeClass( currentItem, null, "ui-state-disabled" ); 17856 } 17857 } 17858 17859 this.options.disabled = disabled; 17860 17861 this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, 17862 disabled === true ); 17863 }, 17864 17865 _setupEvents: function( event ) { 17866 var events = {}; 17867 if ( event ) { 17868 $.each( event.split( " " ), function( index, eventName ) { 17869 events[ eventName ] = "_eventHandler"; 17870 } ); 17871 } 17872 17873 this._off( this.anchors.add( this.tabs ).add( this.panels ) ); 17874 17875 // Always prevent the default action, even when disabled 17876 this._on( true, this.anchors, { 17877 click: function( event ) { 17878 event.preventDefault(); 17879 } 17880 } ); 17881 this._on( this.anchors, events ); 17882 this._on( this.tabs, { keydown: "_tabKeydown" } ); 17883 this._on( this.panels, { keydown: "_panelKeydown" } ); 17884 17885 this._focusable( this.tabs ); 17886 this._hoverable( this.tabs ); 17887 }, 17888 17889 _setupHeightStyle: function( heightStyle ) { 17890 var maxHeight, 17891 parent = this.element.parent(); 17892 17893 if ( heightStyle === "fill" ) { 17894 maxHeight = parent.height(); 17895 maxHeight -= this.element.outerHeight() - this.element.height(); 17896 17897 this.element.siblings( ":visible" ).each( function() { 17898 var elem = $( this ), 17899 position = elem.css( "position" ); 17900 17901 if ( position === "absolute" || position === "fixed" ) { 17902 return; 17903 } 17904 maxHeight -= elem.outerHeight( true ); 17905 } ); 17906 17907 this.element.children().not( this.panels ).each( function() { 17908 maxHeight -= $( this ).outerHeight( true ); 17909 } ); 17910 17911 this.panels.each( function() { 17912 $( this ).height( Math.max( 0, maxHeight - 17913 $( this ).innerHeight() + $( this ).height() ) ); 17914 } ) 17915 .css( "overflow", "auto" ); 17916 } else if ( heightStyle === "auto" ) { 17917 maxHeight = 0; 17918 this.panels.each( function() { 17919 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); 17920 } ).height( maxHeight ); 17921 } 17922 }, 17923 17924 _eventHandler: function( event ) { 17925 var options = this.options, 17926 active = this.active, 17927 anchor = $( event.currentTarget ), 17928 tab = anchor.closest( "li" ), 17929 clickedIsActive = tab[ 0 ] === active[ 0 ], 17930 collapsing = clickedIsActive && options.collapsible, 17931 toShow = collapsing ? $() : this._getPanelForTab( tab ), 17932 toHide = !active.length ? $() : this._getPanelForTab( active ), 17933 eventData = { 17934 oldTab: active, 17935 oldPanel: toHide, 17936 newTab: collapsing ? $() : tab, 17937 newPanel: toShow 17938 }; 17939 17940 event.preventDefault(); 17941 17942 if ( tab.hasClass( "ui-state-disabled" ) || 17943 17944 // tab is already loading 17945 tab.hasClass( "ui-tabs-loading" ) || 17946 17947 // can't switch durning an animation 17948 this.running || 17949 17950 // click on active header, but not collapsible 17951 ( clickedIsActive && !options.collapsible ) || 17952 17953 // allow canceling activation 17954 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 17955 return; 17956 } 17957 17958 options.active = collapsing ? false : this.tabs.index( tab ); 17959 17960 this.active = clickedIsActive ? $() : tab; 17961 if ( this.xhr ) { 17962 this.xhr.abort(); 17963 } 17964 17965 if ( !toHide.length && !toShow.length ) { 17966 $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); 17967 } 17968 17969 if ( toShow.length ) { 17970 this.load( this.tabs.index( tab ), event ); 17971 } 17972 this._toggle( event, eventData ); 17973 }, 17974 17975 // Handles show/hide for selecting tabs 17976 _toggle: function( event, eventData ) { 17977 var that = this, 17978 toShow = eventData.newPanel, 17979 toHide = eventData.oldPanel; 17980 17981 this.running = true; 17982 17983 function complete() { 17984 that.running = false; 17985 that._trigger( "activate", event, eventData ); 17986 } 17987 17988 function show() { 17989 that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" ); 17990 17991 if ( toShow.length && that.options.show ) { 17992 that._show( toShow, that.options.show, complete ); 17993 } else { 17994 toShow.show(); 17995 complete(); 17996 } 17997 } 17998 17999 // Start out by hiding, then showing, then completing 18000 if ( toHide.length && this.options.hide ) { 18001 this._hide( toHide, this.options.hide, function() { 18002 that._removeClass( eventData.oldTab.closest( "li" ), 18003 "ui-tabs-active", "ui-state-active" ); 18004 show(); 18005 } ); 18006 } else { 18007 this._removeClass( eventData.oldTab.closest( "li" ), 18008 "ui-tabs-active", "ui-state-active" ); 18009 toHide.hide(); 18010 show(); 18011 } 18012 18013 toHide.attr( "aria-hidden", "true" ); 18014 eventData.oldTab.attr( { 18015 "aria-selected": "false", 18016 "aria-expanded": "false" 18017 } ); 18018 18019 // If we're switching tabs, remove the old tab from the tab order. 18020 // If we're opening from collapsed state, remove the previous tab from the tab order. 18021 // If we're collapsing, then keep the collapsing tab in the tab order. 18022 if ( toShow.length && toHide.length ) { 18023 eventData.oldTab.attr( "tabIndex", -1 ); 18024 } else if ( toShow.length ) { 18025 this.tabs.filter( function() { 18026 return $( this ).attr( "tabIndex" ) === 0; 18027 } ) 18028 .attr( "tabIndex", -1 ); 18029 } 18030 18031 toShow.attr( "aria-hidden", "false" ); 18032 eventData.newTab.attr( { 18033 "aria-selected": "true", 18034 "aria-expanded": "true", 18035 tabIndex: 0 18036 } ); 18037 }, 18038 18039 _activate: function( index ) { 18040 var anchor, 18041 active = this._findActive( index ); 18042 18043 // Trying to activate the already active panel 18044 if ( active[ 0 ] === this.active[ 0 ] ) { 18045 return; 18046 } 18047 18048 // Trying to collapse, simulate a click on the current active header 18049 if ( !active.length ) { 18050 active = this.active; 18051 } 18052 18053 anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; 18054 this._eventHandler( { 18055 target: anchor, 18056 currentTarget: anchor, 18057 preventDefault: $.noop 18058 } ); 18059 }, 18060 18061 _findActive: function( index ) { 18062 return index === false ? $() : this.tabs.eq( index ); 18063 }, 18064 18065 _getIndex: function( index ) { 18066 18067 // meta-function to give users option to provide a href string instead of a numerical index. 18068 if ( typeof index === "string" ) { 18069 index = this.anchors.index( this.anchors.filter( "[href$='" + 18070 CSS.escape( index ) + "']" ) ); 18071 } 18072 18073 return index; 18074 }, 18075 18076 _destroy: function() { 18077 if ( this.xhr ) { 18078 this.xhr.abort(); 18079 } 18080 18081 this.tablist 18082 .removeAttr( "role" ) 18083 .off( this.eventNamespace ); 18084 18085 this.anchors 18086 .removeAttr( "role tabIndex" ) 18087 .removeUniqueId(); 18088 18089 this.tabs.add( this.panels ).each( function() { 18090 if ( $.data( this, "ui-tabs-destroy" ) ) { 18091 $( this ).remove(); 18092 } else { 18093 $( this ).removeAttr( "role tabIndex " + 18094 "aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" ); 18095 } 18096 } ); 18097 18098 this.tabs.each( function() { 18099 var li = $( this ), 18100 prev = li.data( "ui-tabs-aria-controls" ); 18101 if ( prev ) { 18102 li 18103 .attr( "aria-controls", prev ) 18104 .removeData( "ui-tabs-aria-controls" ); 18105 } else { 18106 li.removeAttr( "aria-controls" ); 18107 } 18108 } ); 18109 18110 this.panels.show(); 18111 18112 if ( this.options.heightStyle !== "content" ) { 18113 this.panels.css( "height", "" ); 18114 } 18115 }, 18116 18117 enable: function( index ) { 18118 var disabled = this.options.disabled; 18119 if ( disabled === false ) { 18120 return; 18121 } 18122 18123 if ( index === undefined ) { 18124 disabled = false; 18125 } else { 18126 index = this._getIndex( index ); 18127 if ( Array.isArray( disabled ) ) { 18128 disabled = $.map( disabled, function( num ) { 18129 return num !== index ? num : null; 18130 } ); 18131 } else { 18132 disabled = $.map( this.tabs, function( li, num ) { 18133 return num !== index ? num : null; 18134 } ); 18135 } 18136 } 18137 this._setOptionDisabled( disabled ); 18138 }, 18139 18140 disable: function( index ) { 18141 var disabled = this.options.disabled; 18142 if ( disabled === true ) { 18143 return; 18144 } 18145 18146 if ( index === undefined ) { 18147 disabled = true; 18148 } else { 18149 index = this._getIndex( index ); 18150 if ( $.inArray( index, disabled ) !== -1 ) { 18151 return; 18152 } 18153 if ( Array.isArray( disabled ) ) { 18154 disabled = $.merge( [ index ], disabled ).sort(); 18155 } else { 18156 disabled = [ index ]; 18157 } 18158 } 18159 this._setOptionDisabled( disabled ); 18160 }, 18161 18162 load: function( index, event ) { 18163 index = this._getIndex( index ); 18164 var that = this, 18165 tab = this.tabs.eq( index ), 18166 anchor = tab.find( ".ui-tabs-anchor" ), 18167 panel = this._getPanelForTab( tab ), 18168 eventData = { 18169 tab: tab, 18170 panel: panel 18171 }, 18172 complete = function( jqXHR, status ) { 18173 if ( status === "abort" ) { 18174 that.panels.stop( false, true ); 18175 } 18176 18177 that._removeClass( tab, "ui-tabs-loading" ); 18178 panel.removeAttr( "aria-busy" ); 18179 18180 if ( jqXHR === that.xhr ) { 18181 delete that.xhr; 18182 } 18183 }; 18184 18185 // Not remote 18186 if ( this._isLocal( anchor[ 0 ] ) ) { 18187 return; 18188 } 18189 18190 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); 18191 18192 if ( this.xhr.statusText !== "canceled" ) { 18193 this._addClass( tab, "ui-tabs-loading" ); 18194 panel.attr( "aria-busy", "true" ); 18195 18196 this.xhr 18197 .done( function( response, status, jqXHR ) { 18198 panel.html( response ); 18199 that._trigger( "load", event, eventData ); 18200 18201 complete( jqXHR, status ); 18202 } ) 18203 .fail( function( jqXHR, status ) { 18204 complete( jqXHR, status ); 18205 } ); 18206 } 18207 }, 18208 18209 _ajaxSettings: function( anchor, event, eventData ) { 18210 var that = this; 18211 return { 18212 url: anchor.attr( "href" ), 18213 beforeSend: function( jqXHR, settings ) { 18214 return that._trigger( "beforeLoad", event, 18215 $.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) ); 18216 } 18217 }; 18218 }, 18219 18220 _getPanelForTab: function( tab ) { 18221 var id = $( tab ).attr( "aria-controls" ); 18222 return this.element.find( this._sanitizeSelector( "#" + id ) ); 18223 } 18224} ); 18225 18226// DEPRECATED 18227// TODO: Switch return back to widget declaration at top of file when this is removed 18228if ( $.uiBackCompat === true ) { 18229 18230 // Backcompat for ui-tab class (now ui-tabs-tab) 18231 $.widget( "ui.tabs", $.ui.tabs, { 18232 _processTabs: function() { 18233 this._superApply( arguments ); 18234 this._addClass( this.tabs, "ui-tab" ); 18235 } 18236 } ); 18237} 18238 18239var widgetsTabs = $.ui.tabs; 18240 18241 18242/*! 18243 * jQuery UI Tooltip 1.14.0 18244 * https://jqueryui.com 18245 * 18246 * Copyright OpenJS Foundation and other contributors 18247 * Released under the MIT license. 18248 * https://jquery.org/license 18249 */ 18250 18251//>>label: Tooltip 18252//>>group: Widgets 18253//>>description: Shows additional information for any element on hover or focus. 18254//>>docs: https://api.jqueryui.com/tooltip/ 18255//>>demos: https://jqueryui.com/tooltip/ 18256//>>css.structure: ../../themes/base/core.css 18257//>>css.structure: ../../themes/base/tooltip.css 18258//>>css.theme: ../../themes/base/theme.css 18259 18260 18261$.widget( "ui.tooltip", { 18262 version: "1.14.0", 18263 options: { 18264 classes: { 18265 "ui-tooltip": "ui-corner-all ui-widget-shadow" 18266 }, 18267 content: function() { 18268 var title = $( this ).attr( "title" ); 18269 18270 // Escape title, since we're going from an attribute to raw HTML 18271 return $( "<a>" ).text( title ).html(); 18272 }, 18273 hide: true, 18274 18275 // Disabled elements have inconsistent behavior across browsers (#8661) 18276 items: "[title]:not([disabled])", 18277 position: { 18278 my: "left top+15", 18279 at: "left bottom", 18280 collision: "flipfit flip" 18281 }, 18282 show: true, 18283 track: false, 18284 18285 // Callbacks 18286 close: null, 18287 open: null 18288 }, 18289 18290 _addDescribedBy: function( elem, id ) { 18291 var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ); 18292 describedby.push( id ); 18293 elem 18294 .data( "ui-tooltip-id", id ) 18295 .attr( "aria-describedby", String.prototype.trim.call( describedby.join( " " ) ) ); 18296 }, 18297 18298 _removeDescribedBy: function( elem ) { 18299 var id = elem.data( "ui-tooltip-id" ), 18300 describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ), 18301 index = $.inArray( id, describedby ); 18302 18303 if ( index !== -1 ) { 18304 describedby.splice( index, 1 ); 18305 } 18306 18307 elem.removeData( "ui-tooltip-id" ); 18308 describedby = String.prototype.trim.call( describedby.join( " " ) ); 18309 if ( describedby ) { 18310 elem.attr( "aria-describedby", describedby ); 18311 } else { 18312 elem.removeAttr( "aria-describedby" ); 18313 } 18314 }, 18315 18316 _create: function() { 18317 this._on( { 18318 mouseover: "open", 18319 focusin: "open" 18320 } ); 18321 18322 // IDs of generated tooltips, needed for destroy 18323 this.tooltips = {}; 18324 18325 // IDs of parent tooltips where we removed the title attribute 18326 this.parents = {}; 18327 18328 // Append the aria-live region so tooltips announce correctly 18329 this.liveRegion = $( "<div>" ) 18330 .attr( { 18331 role: "log", 18332 "aria-live": "assertive", 18333 "aria-relevant": "additions" 18334 } ) 18335 .appendTo( this.document[ 0 ].body ); 18336 this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" ); 18337 18338 this.disabledTitles = $( [] ); 18339 }, 18340 18341 _setOption: function( key, value ) { 18342 var that = this; 18343 18344 this._super( key, value ); 18345 18346 if ( key === "content" ) { 18347 $.each( this.tooltips, function( id, tooltipData ) { 18348 that._updateContent( tooltipData.element ); 18349 } ); 18350 } 18351 }, 18352 18353 _setOptionDisabled: function( value ) { 18354 this[ value ? "_disable" : "_enable" ](); 18355 }, 18356 18357 _disable: function() { 18358 var that = this; 18359 18360 // Close open tooltips 18361 $.each( this.tooltips, function( id, tooltipData ) { 18362 var event = $.Event( "blur" ); 18363 event.target = event.currentTarget = tooltipData.element[ 0 ]; 18364 that.close( event, true ); 18365 } ); 18366 18367 // Remove title attributes to prevent native tooltips 18368 this.disabledTitles = this.disabledTitles.add( 18369 this.element.find( this.options.items ).addBack() 18370 .filter( function() { 18371 var element = $( this ); 18372 if ( element.is( "[title]" ) ) { 18373 return element 18374 .data( "ui-tooltip-title", element.attr( "title" ) ) 18375 .removeAttr( "title" ); 18376 } 18377 } ) 18378 ); 18379 }, 18380 18381 _enable: function() { 18382 18383 // restore title attributes 18384 this.disabledTitles.each( function() { 18385 var element = $( this ); 18386 if ( element.data( "ui-tooltip-title" ) ) { 18387 element.attr( "title", element.data( "ui-tooltip-title" ) ); 18388 } 18389 } ); 18390 this.disabledTitles = $( [] ); 18391 }, 18392 18393 open: function( event ) { 18394 var that = this, 18395 target = $( event ? event.target : this.element ) 18396 18397 // we need closest here due to mouseover bubbling, 18398 // but always pointing at the same event target 18399 .closest( this.options.items ); 18400 18401 // No element to show a tooltip for or the tooltip is already open 18402 if ( !target.length || target.data( "ui-tooltip-id" ) ) { 18403 return; 18404 } 18405 18406 if ( target.attr( "title" ) ) { 18407 target.data( "ui-tooltip-title", target.attr( "title" ) ); 18408 } 18409 18410 target.data( "ui-tooltip-open", true ); 18411 18412 // Kill parent tooltips, custom or native, for hover 18413 if ( event && event.type === "mouseover" ) { 18414 target.parents().each( function() { 18415 var parent = $( this ), 18416 blurEvent; 18417 if ( parent.data( "ui-tooltip-open" ) ) { 18418 blurEvent = $.Event( "blur" ); 18419 blurEvent.target = blurEvent.currentTarget = this; 18420 that.close( blurEvent, true ); 18421 } 18422 if ( parent.attr( "title" ) ) { 18423 parent.uniqueId(); 18424 that.parents[ this.id ] = { 18425 element: this, 18426 title: parent.attr( "title" ) 18427 }; 18428 parent.attr( "title", "" ); 18429 } 18430 } ); 18431 } 18432 18433 this._registerCloseHandlers( event, target ); 18434 this._updateContent( target, event ); 18435 }, 18436 18437 _updateContent: function( target, event ) { 18438 var content, 18439 contentOption = this.options.content, 18440 that = this, 18441 eventType = event ? event.type : null; 18442 18443 if ( typeof contentOption === "string" || contentOption.nodeType || 18444 contentOption.jquery ) { 18445 return this._open( event, target, contentOption ); 18446 } 18447 18448 content = contentOption.call( target[ 0 ], function( response ) { 18449 18450 // Ignore async response if tooltip was closed already 18451 if ( !target.data( "ui-tooltip-open" ) ) { 18452 return; 18453 } 18454 18455 // JQuery creates a special event for focusin when it doesn't 18456 // exist natively. To improve performance, the native event 18457 // object is reused and the type is changed. Therefore, we can't 18458 // rely on the type being correct after the event finished 18459 // bubbling, so we set it back to the previous value. (#8740) 18460 if ( event ) { 18461 event.type = eventType; 18462 } 18463 that._open( event, target, response ); 18464 } ); 18465 if ( content ) { 18466 this._open( event, target, content ); 18467 } 18468 }, 18469 18470 _open: function( event, target, content ) { 18471 var tooltipData, tooltip, delayedShow, a11yContent, 18472 positionOption = $.extend( {}, this.options.position ); 18473 18474 if ( !content ) { 18475 return; 18476 } 18477 18478 // Content can be updated multiple times. If the tooltip already 18479 // exists, then just update the content and bail. 18480 tooltipData = this._find( target ); 18481 if ( tooltipData ) { 18482 tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content ); 18483 return; 18484 } 18485 18486 // If we have a title, clear it to prevent the native tooltip 18487 // we have to check first to avoid defining a title if none exists 18488 // (we don't want to cause an element to start matching [title]) 18489 // 18490 // We use removeAttr only for key events, to allow IE to export the correct 18491 // accessible attributes. For mouse events, set to empty string to avoid 18492 // native tooltip showing up (happens only when removing inside mouseover). 18493 if ( target.is( "[title]" ) ) { 18494 if ( event && event.type === "mouseover" ) { 18495 target.attr( "title", "" ); 18496 } else { 18497 target.removeAttr( "title" ); 18498 } 18499 } 18500 18501 tooltipData = this._tooltip( target ); 18502 tooltip = tooltipData.tooltip; 18503 this._addDescribedBy( target, tooltip.attr( "id" ) ); 18504 tooltip.find( ".ui-tooltip-content" ).html( content ); 18505 18506 // Support: Voiceover on OS X, JAWS on IE <= 9 18507 // JAWS announces deletions even when aria-relevant="additions" 18508 // Voiceover will sometimes re-read the entire log region's contents from the beginning 18509 this.liveRegion.children().hide(); 18510 a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() ); 18511 a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" ); 18512 a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" ); 18513 a11yContent.appendTo( this.liveRegion ); 18514 18515 function position( event ) { 18516 positionOption.of = event; 18517 if ( tooltip.is( ":hidden" ) ) { 18518 return; 18519 } 18520 tooltip.position( positionOption ); 18521 } 18522 if ( this.options.track && event && /^mouse/.test( event.type ) ) { 18523 this._on( this.document, { 18524 mousemove: position 18525 } ); 18526 18527 // trigger once to override element-relative positioning 18528 position( event ); 18529 } else { 18530 tooltip.position( $.extend( { 18531 of: target 18532 }, this.options.position ) ); 18533 } 18534 18535 tooltip.hide(); 18536 18537 this._show( tooltip, this.options.show ); 18538 18539 // Handle tracking tooltips that are shown with a delay (#8644). As soon 18540 // as the tooltip is visible, position the tooltip using the most recent 18541 // event. 18542 // Adds the check to add the timers only when both delay and track options are set (#14682) 18543 if ( this.options.track && this.options.show && this.options.show.delay ) { 18544 delayedShow = this.delayedShow = setInterval( function() { 18545 if ( tooltip.is( ":visible" ) ) { 18546 position( positionOption.of ); 18547 clearInterval( delayedShow ); 18548 } 18549 }, 13 ); 18550 } 18551 18552 this._trigger( "open", event, { tooltip: tooltip } ); 18553 }, 18554 18555 _registerCloseHandlers: function( event, target ) { 18556 var events = { 18557 keyup: function( event ) { 18558 if ( event.keyCode === $.ui.keyCode.ESCAPE ) { 18559 var fakeEvent = $.Event( event ); 18560 fakeEvent.currentTarget = target[ 0 ]; 18561 this.close( fakeEvent, true ); 18562 } 18563 } 18564 }; 18565 18566 // Only bind remove handler for delegated targets. Non-delegated 18567 // tooltips will handle this in destroy. 18568 if ( target[ 0 ] !== this.element[ 0 ] ) { 18569 events.remove = function() { 18570 var targetElement = this._find( target ); 18571 if ( targetElement ) { 18572 this._removeTooltip( targetElement.tooltip ); 18573 } 18574 }; 18575 } 18576 18577 if ( !event || event.type === "mouseover" ) { 18578 events.mouseleave = "close"; 18579 } 18580 if ( !event || event.type === "focusin" ) { 18581 events.focusout = "close"; 18582 } 18583 this._on( true, target, events ); 18584 }, 18585 18586 close: function( event ) { 18587 var tooltip, 18588 that = this, 18589 target = $( event ? event.currentTarget : this.element ), 18590 tooltipData = this._find( target ); 18591 18592 // The tooltip may already be closed 18593 if ( !tooltipData ) { 18594 18595 // We set ui-tooltip-open immediately upon open (in open()), but only set the 18596 // additional data once there's actually content to show (in _open()). So even if the 18597 // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in 18598 // the period between open() and _open(). 18599 target.removeData( "ui-tooltip-open" ); 18600 return; 18601 } 18602 18603 tooltip = tooltipData.tooltip; 18604 18605 // Disabling closes the tooltip, so we need to track when we're closing 18606 // to avoid an infinite loop in case the tooltip becomes disabled on close 18607 if ( tooltipData.closing ) { 18608 return; 18609 } 18610 18611 // Clear the interval for delayed tracking tooltips 18612 clearInterval( this.delayedShow ); 18613 18614 // Only set title if we had one before (see comment in _open()) 18615 // If the title attribute has changed since open(), don't restore 18616 if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) { 18617 target.attr( "title", target.data( "ui-tooltip-title" ) ); 18618 } 18619 18620 this._removeDescribedBy( target ); 18621 18622 tooltipData.hiding = true; 18623 tooltip.stop( true ); 18624 this._hide( tooltip, this.options.hide, function() { 18625 that._removeTooltip( $( this ) ); 18626 } ); 18627 18628 target.removeData( "ui-tooltip-open" ); 18629 this._off( target, "mouseleave focusout keyup" ); 18630 18631 // Remove 'remove' binding only on delegated targets 18632 if ( target[ 0 ] !== this.element[ 0 ] ) { 18633 this._off( target, "remove" ); 18634 } 18635 this._off( this.document, "mousemove" ); 18636 18637 if ( event && event.type === "mouseleave" ) { 18638 $.each( this.parents, function( id, parent ) { 18639 $( parent.element ).attr( "title", parent.title ); 18640 delete that.parents[ id ]; 18641 } ); 18642 } 18643 18644 tooltipData.closing = true; 18645 this._trigger( "close", event, { tooltip: tooltip } ); 18646 if ( !tooltipData.hiding ) { 18647 tooltipData.closing = false; 18648 } 18649 }, 18650 18651 _tooltip: function( element ) { 18652 var tooltip = $( "<div>" ).attr( "role", "tooltip" ), 18653 content = $( "<div>" ).appendTo( tooltip ), 18654 id = tooltip.uniqueId().attr( "id" ); 18655 18656 this._addClass( content, "ui-tooltip-content" ); 18657 this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" ); 18658 18659 tooltip.appendTo( this._appendTo( element ) ); 18660 18661 return this.tooltips[ id ] = { 18662 element: element, 18663 tooltip: tooltip 18664 }; 18665 }, 18666 18667 _find: function( target ) { 18668 var id = target.data( "ui-tooltip-id" ); 18669 return id ? this.tooltips[ id ] : null; 18670 }, 18671 18672 _removeTooltip: function( tooltip ) { 18673 18674 // Clear the interval for delayed tracking tooltips 18675 clearInterval( this.delayedShow ); 18676 18677 tooltip.remove(); 18678 delete this.tooltips[ tooltip.attr( "id" ) ]; 18679 }, 18680 18681 _appendTo: function( target ) { 18682 var element = target.closest( ".ui-front, dialog" ); 18683 18684 if ( !element.length ) { 18685 element = this.document[ 0 ].body; 18686 } 18687 18688 return element; 18689 }, 18690 18691 _destroy: function() { 18692 var that = this; 18693 18694 // Close open tooltips 18695 $.each( this.tooltips, function( id, tooltipData ) { 18696 18697 // Delegate to close method to handle common cleanup 18698 var event = $.Event( "blur" ), 18699 element = tooltipData.element; 18700 event.target = event.currentTarget = element[ 0 ]; 18701 that.close( event, true ); 18702 18703 // Remove immediately; destroying an open tooltip doesn't use the 18704 // hide animation 18705 $( "#" + id ).remove(); 18706 18707 // Restore the title 18708 if ( element.data( "ui-tooltip-title" ) ) { 18709 18710 // If the title attribute has changed since open(), don't restore 18711 if ( !element.attr( "title" ) ) { 18712 element.attr( "title", element.data( "ui-tooltip-title" ) ); 18713 } 18714 element.removeData( "ui-tooltip-title" ); 18715 } 18716 } ); 18717 this.liveRegion.remove(); 18718 } 18719} ); 18720 18721// DEPRECATED 18722// TODO: Switch return back to widget declaration at top of file when this is removed 18723if ( $.uiBackCompat === true ) { 18724 18725 // Backcompat for tooltipClass option 18726 $.widget( "ui.tooltip", $.ui.tooltip, { 18727 options: { 18728 tooltipClass: null 18729 }, 18730 _tooltip: function() { 18731 var tooltipData = this._superApply( arguments ); 18732 if ( this.options.tooltipClass ) { 18733 tooltipData.tooltip.addClass( this.options.tooltipClass ); 18734 } 18735 return tooltipData; 18736 } 18737 } ); 18738} 18739 18740var widgetsTooltip = $.ui.tooltip; 18741 18742 18743 18744 18745} );
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.