vendor: 558,056 bytes, lines 1-16235
1/*! jQuery UI - v1.14.1 - 2024-10-30 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 4* Copyright OpenJS Foundation and other contributors; Licensed MIT */ 5 6// enable 1.11 API 7$.uiBackCompat = true; 8 9( function( factory ) { 10 "use strict"; 11 12 if ( typeof define === "function" && define.amd ) { 13 14 // AMD. Register as an anonymous module. 15 define( [ "jquery" ], factory ); 16 } else { 17 18 // Browser globals 19 factory( jQuery ); 20 } 21} )( function( $ ) { 22"use strict"; 23 24$.ui = $.ui || {}; 25 26var version = $.ui.version = "1.14.1"; 27 28/*! 29 * jQuery UI Widget 1.14.1 30 * https://jqueryui.com 31 * 32 * Copyright OpenJS Foundation and other contributors 33 * Released under the MIT license. 34 * https://jquery.org/license 35 */ 36 37//>>label: Widget 38//>>group: Core 39//>>description: Provides a factory for creating stateful widgets with a common API. 40//>>docs: https://api.jqueryui.com/jQuery.widget/ 41//>>demos: https://jqueryui.com/widget/ 42 43 44var widgetUuid = 0; 45var widgetHasOwnProperty = Array.prototype.hasOwnProperty; 46var widgetSlice = Array.prototype.slice; 47 48$.cleanData = ( function( orig ) { 49 return function( elems ) { 50 var events, elem, i; 51 for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) { 52 53 // Only trigger remove when necessary to save time 54 events = $._data( elem, "events" ); 55 if ( events && events.remove ) { 56 $( elem ).triggerHandler( "remove" ); 57 } 58 } 59 orig( elems ); 60 }; 61} )( $.cleanData ); 62 63$.widget = function( name, base, prototype ) { 64 var existingConstructor, constructor, basePrototype; 65 66 // ProxiedPrototype allows the provided prototype to remain unmodified 67 // so that it can be used as a mixin for multiple widgets (#8876) 68 var proxiedPrototype = {}; 69 70 var namespace = name.split( "." )[ 0 ]; 71 name = name.split( "." )[ 1 ]; 72 if ( name === "__proto__" || name === "constructor" ) { 73 return $.error( "Invalid widget name: " + name ); 74 } 75 var fullName = namespace + "-" + name; 76 77 if ( !prototype ) { 78 prototype = base; 79 base = $.Widget; 80 } 81 82 if ( Array.isArray( prototype ) ) { 83 prototype = $.extend.apply( null, [ {} ].concat( prototype ) ); 84 } 85 86 // Create selector for plugin 87 $.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) { 88 return !!$.data( elem, fullName ); 89 }; 90 91 $[ namespace ] = $[ namespace ] || {}; 92 existingConstructor = $[ namespace ][ name ]; 93 constructor = $[ namespace ][ name ] = function( options, element ) { 94 95 // Allow instantiation without "new" keyword 96 if ( !this || !this._createWidget ) { 97 return new constructor( options, element ); 98 } 99 100 // Allow instantiation without initializing for simple inheritance 101 // must use "new" keyword (the code above always passes args) 102 if ( arguments.length ) { 103 this._createWidget( options, element ); 104 } 105 }; 106 107 // Extend with the existing constructor to carry over any static properties 108 $.extend( constructor, existingConstructor, { 109 version: prototype.version, 110 111 // Copy the object used to create the prototype in case we need to 112 // redefine the widget later 113 _proto: $.extend( {}, prototype ), 114 115 // Track widgets that inherit from this widget in case this widget is 116 // redefined after a widget inherits from it 117 _childConstructors: [] 118 } ); 119 120 basePrototype = new base(); 121 122 // We need to make the options hash a property directly on the new instance 123 // otherwise we'll modify the options hash on the prototype that we're 124 // inheriting from 125 basePrototype.options = $.widget.extend( {}, basePrototype.options ); 126 $.each( prototype, function( prop, value ) { 127 if ( typeof value !== "function" ) { 128 proxiedPrototype[ prop ] = value; 129 return; 130 } 131 proxiedPrototype[ prop ] = ( function() { 132 function _super() { 133 return base.prototype[ prop ].apply( this, arguments ); 134 } 135 136 function _superApply( args ) { 137 return base.prototype[ prop ].apply( this, args ); 138 } 139 140 return function() { 141 var __super = this._super; 142 var __superApply = this._superApply; 143 var returnValue; 144 145 this._super = _super; 146 this._superApply = _superApply; 147 148 returnValue = value.apply( this, arguments ); 149 150 this._super = __super; 151 this._superApply = __superApply; 152 153 return returnValue; 154 }; 155 } )(); 156 } ); 157 constructor.prototype = $.widget.extend( basePrototype, { 158 159 // TODO: remove support for widgetEventPrefix 160 // always use the name + a colon as the prefix, e.g., draggable:start 161 // don't prefix for widgets that aren't DOM-based 162 widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name 163 }, proxiedPrototype, { 164 constructor: constructor, 165 namespace: namespace, 166 widgetName: name, 167 widgetFullName: fullName 168 } ); 169 170 // If this widget is being redefined then we need to find all widgets that 171 // are inheriting from it and redefine all of them so that they inherit from 172 // the new version of this widget. We're essentially trying to replace one 173 // level in the prototype chain. 174 if ( existingConstructor ) { 175 $.each( existingConstructor._childConstructors, function( i, child ) { 176 var childPrototype = child.prototype; 177 178 // Redefine the child widget using the same prototype that was 179 // originally used, but inherit from the new version of the base 180 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, 181 child._proto ); 182 } ); 183 184 // Remove the list of existing child constructors from the old constructor 185 // so the old child constructors can be garbage collected 186 delete existingConstructor._childConstructors; 187 } else { 188 base._childConstructors.push( constructor ); 189 } 190 191 $.widget.bridge( name, constructor ); 192 193 return constructor; 194}; 195 196$.widget.extend = function( target ) { 197 var input = widgetSlice.call( arguments, 1 ); 198 var inputIndex = 0; 199 var inputLength = input.length; 200 var key; 201 var value; 202 203 for ( ; inputIndex < inputLength; inputIndex++ ) { 204 for ( key in input[ inputIndex ] ) { 205 value = input[ inputIndex ][ key ]; 206 if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) { 207 208 // Clone objects 209 if ( $.isPlainObject( value ) ) { 210 target[ key ] = $.isPlainObject( target[ key ] ) ? 211 $.widget.extend( {}, target[ key ], value ) : 212 213 // Don't extend strings, arrays, etc. with objects 214 $.widget.extend( {}, value ); 215 216 // Copy everything else by reference 217 } else { 218 target[ key ] = value; 219 } 220 } 221 } 222 } 223 return target; 224}; 225 226$.widget.bridge = function( name, object ) { 227 var fullName = object.prototype.widgetFullName || name; 228 $.fn[ name ] = function( options ) { 229 var isMethodCall = typeof options === "string"; 230 var args = widgetSlice.call( arguments, 1 ); 231 var returnValue = this; 232 233 if ( isMethodCall ) { 234 235 // If this is an empty collection, we need to have the instance method 236 // return undefined instead of the jQuery instance 237 if ( !this.length && options === "instance" ) { 238 returnValue = undefined; 239 } else { 240 this.each( function() { 241 var methodValue; 242 var instance = $.data( this, fullName ); 243 244 if ( options === "instance" ) { 245 returnValue = instance; 246 return false; 247 } 248 249 if ( !instance ) { 250 return $.error( "cannot call methods on " + name + 251 " prior to initialization; " + 252 "attempted to call method '" + options + "'" ); 253 } 254 255 if ( typeof instance[ options ] !== "function" || 256 options.charAt( 0 ) === "_" ) { 257 return $.error( "no such method '" + options + "' for " + name + 258 " widget instance" ); 259 } 260 261 methodValue = instance[ options ].apply( instance, args ); 262 263 if ( methodValue !== instance && methodValue !== undefined ) { 264 returnValue = methodValue && methodValue.jquery ? 265 returnValue.pushStack( methodValue.get() ) : 266 methodValue; 267 return false; 268 } 269 } ); 270 } 271 } else { 272 273 // Allow multiple hashes to be passed on init 274 if ( args.length ) { 275 options = $.widget.extend.apply( null, [ options ].concat( args ) ); 276 } 277 278 this.each( function() { 279 var instance = $.data( this, fullName ); 280 if ( instance ) { 281 instance.option( options || {} ); 282 if ( instance._init ) { 283 instance._init(); 284 } 285 } else { 286 $.data( this, fullName, new object( options, this ) ); 287 } 288 } ); 289 } 290 291 return returnValue; 292 }; 293}; 294 295$.Widget = function( /* options, element */ ) {}; 296$.Widget._childConstructors = []; 297 298$.Widget.prototype = { 299 widgetName: "widget", 300 widgetEventPrefix: "", 301 defaultElement: "<div>", 302 303 options: { 304 classes: {}, 305 disabled: false, 306 307 // Callbacks 308 create: null 309 }, 310 311 _createWidget: function( options, element ) { 312 element = $( element || this.defaultElement || this )[ 0 ]; 313 this.element = $( element ); 314 this.uuid = widgetUuid++; 315 this.eventNamespace = "." + this.widgetName + this.uuid; 316 317 this.bindings = $(); 318 this.hoverable = $(); 319 this.focusable = $(); 320 this.classesElementLookup = {}; 321 322 if ( element !== this ) { 323 $.data( element, this.widgetFullName, this ); 324 this._on( true, this.element, { 325 remove: function( event ) { 326 if ( event.target === element ) { 327 this.destroy(); 328 } 329 } 330 } ); 331 this.document = $( element.style ? 332 333 // Element within the document 334 element.ownerDocument : 335 336 // Element is window or document 337 element.document || element ); 338 this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow ); 339 } 340 341 this.options = $.widget.extend( {}, 342 this.options, 343 this._getCreateOptions(), 344 options ); 345 346 this._create(); 347 348 if ( this.options.disabled ) { 349 this._setOptionDisabled( this.options.disabled ); 350 } 351 352 this._trigger( "create", null, this._getCreateEventData() ); 353 this._init(); 354 }, 355 356 _getCreateOptions: function() { 357 return {}; 358 }, 359 360 _getCreateEventData: $.noop, 361 362 _create: $.noop, 363 364 _init: $.noop, 365 366 destroy: function() { 367 var that = this; 368 369 this._destroy(); 370 $.each( this.classesElementLookup, function( key, value ) { 371 that._removeClass( value, key ); 372 } ); 373 374 // We can probably remove the unbind calls in 2.0 375 // all event bindings should go through this._on() 376 this.element 377 .off( this.eventNamespace ) 378 .removeData( this.widgetFullName ); 379 this.widget() 380 .off( this.eventNamespace ) 381 .removeAttr( "aria-disabled" ); 382 383 // Clean up events and states 384 this.bindings.off( this.eventNamespace ); 385 }, 386 387 _destroy: $.noop, 388 389 widget: function() { 390 return this.element; 391 }, 392 393 option: function( key, value ) { 394 var options = key; 395 var parts; 396 var curOption; 397 var i; 398 399 if ( arguments.length === 0 ) { 400 401 // Don't return a reference to the internal hash 402 return $.widget.extend( {}, this.options ); 403 } 404 405 if ( typeof key === "string" ) { 406 407 // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } 408 options = {}; 409 parts = key.split( "." ); 410 key = parts.shift(); 411 if ( parts.length ) { 412 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); 413 for ( i = 0; i < parts.length - 1; i++ ) { 414 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; 415 curOption = curOption[ parts[ i ] ]; 416 } 417 key = parts.pop(); 418 if ( arguments.length === 1 ) { 419 return curOption[ key ] === undefined ? null : curOption[ key ]; 420 } 421 curOption[ key ] = value; 422 } else { 423 if ( arguments.length === 1 ) { 424 return this.options[ key ] === undefined ? null : this.options[ key ]; 425 } 426 options[ key ] = value; 427 } 428 } 429 430 this._setOptions( options ); 431 432 return this; 433 }, 434 435 _setOptions: function( options ) { 436 var key; 437 438 for ( key in options ) { 439 this._setOption( key, options[ key ] ); 440 } 441 442 return this; 443 }, 444 445 _setOption: function( key, value ) { 446 if ( key === "classes" ) { 447 this._setOptionClasses( value ); 448 } 449 450 this.options[ key ] = value; 451 452 if ( key === "disabled" ) { 453 this._setOptionDisabled( value ); 454 } 455 456 return this; 457 }, 458 459 _setOptionClasses: function( value ) { 460 var classKey, elements, currentElements; 461 462 for ( classKey in value ) { 463 currentElements = this.classesElementLookup[ classKey ]; 464 if ( value[ classKey ] === this.options.classes[ classKey ] || 465 !currentElements || 466 !currentElements.length ) { 467 continue; 468 } 469 470 // We are doing this to create a new jQuery object because the _removeClass() call 471 // on the next line is going to destroy the reference to the current elements being 472 // tracked. We need to save a copy of this collection so that we can add the new classes 473 // below. 474 elements = $( currentElements.get() ); 475 this._removeClass( currentElements, classKey ); 476 477 // We don't use _addClass() here, because that uses this.options.classes 478 // for generating the string of classes. We want to use the value passed in from 479 // _setOption(), this is the new value of the classes option which was passed to 480 // _setOption(). We pass this value directly to _classes(). 481 elements.addClass( this._classes( { 482 element: elements, 483 keys: classKey, 484 classes: value, 485 add: true 486 } ) ); 487 } 488 }, 489 490 _setOptionDisabled: function( value ) { 491 this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value ); 492 493 // If the widget is becoming disabled, then nothing is interactive 494 if ( value ) { 495 this._removeClass( this.hoverable, null, "ui-state-hover" ); 496 this._removeClass( this.focusable, null, "ui-state-focus" ); 497 } 498 }, 499 500 enable: function() { 501 return this._setOptions( { disabled: false } ); 502 }, 503 504 disable: function() { 505 return this._setOptions( { disabled: true } ); 506 }, 507 508 _classes: function( options ) { 509 var full = []; 510 var that = this; 511 512 options = $.extend( { 513 element: this.element, 514 classes: this.options.classes || {} 515 }, options ); 516 517 function bindRemoveEvent() { 518 var nodesToBind = []; 519 520 options.element.each( function( _, element ) { 521 var isTracked = $.map( that.classesElementLookup, function( elements ) { 522 return elements; 523 } ) 524 .some( function( elements ) { 525 return elements.is( element ); 526 } ); 527 528 if ( !isTracked ) { 529 nodesToBind.push( element ); 530 } 531 } ); 532 533 that._on( $( nodesToBind ), { 534 remove: "_untrackClassesElement" 535 } ); 536 } 537 538 function processClassString( classes, checkOption ) { 539 var current, i; 540 for ( i = 0; i < classes.length; i++ ) { 541 current = that.classesElementLookup[ classes[ i ] ] || $(); 542 if ( options.add ) { 543 bindRemoveEvent(); 544 current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) ); 545 } else { 546 current = $( current.not( options.element ).get() ); 547 } 548 that.classesElementLookup[ classes[ i ] ] = current; 549 full.push( classes[ i ] ); 550 if ( checkOption && options.classes[ classes[ i ] ] ) { 551 full.push( options.classes[ classes[ i ] ] ); 552 } 553 } 554 } 555 556 if ( options.keys ) { 557 processClassString( options.keys.match( /\S+/g ) || [], true ); 558 } 559 if ( options.extra ) { 560 processClassString( options.extra.match( /\S+/g ) || [] ); 561 } 562 563 return full.join( " " ); 564 }, 565 566 _untrackClassesElement: function( event ) { 567 var that = this; 568 $.each( that.classesElementLookup, function( key, value ) { 569 if ( $.inArray( event.target, value ) !== -1 ) { 570 that.classesElementLookup[ key ] = $( value.not( event.target ).get() ); 571 } 572 } ); 573 574 this._off( $( event.target ) ); 575 }, 576 577 _removeClass: function( element, keys, extra ) { 578 return this._toggleClass( element, keys, extra, false ); 579 }, 580 581 _addClass: function( element, keys, extra ) { 582 return this._toggleClass( element, keys, extra, true ); 583 }, 584 585 _toggleClass: function( element, keys, extra, add ) { 586 add = ( typeof add === "boolean" ) ? add : extra; 587 var shift = ( typeof element === "string" || element === null ), 588 options = { 589 extra: shift ? keys : extra, 590 keys: shift ? element : keys, 591 element: shift ? this.element : element, 592 add: add 593 }; 594 options.element.toggleClass( this._classes( options ), add ); 595 return this; 596 }, 597 598 _on: function( suppressDisabledCheck, element, handlers ) { 599 var delegateElement; 600 var instance = this; 601 602 // No suppressDisabledCheck flag, shuffle arguments 603 if ( typeof suppressDisabledCheck !== "boolean" ) { 604 handlers = element; 605 element = suppressDisabledCheck; 606 suppressDisabledCheck = false; 607 } 608 609 // No element argument, shuffle and use this.element 610 if ( !handlers ) { 611 handlers = element; 612 element = this.element; 613 delegateElement = this.widget(); 614 } else { 615 element = delegateElement = $( element ); 616 this.bindings = this.bindings.add( element ); 617 } 618 619 $.each( handlers, function( event, handler ) { 620 function handlerProxy() { 621 622 // Allow widgets to customize the disabled handling 623 // - disabled as an array instead of boolean 624 // - disabled class as method for disabling individual parts 625 if ( !suppressDisabledCheck && 626 ( instance.options.disabled === true || 627 $( this ).hasClass( "ui-state-disabled" ) ) ) { 628 return; 629 } 630 return ( typeof handler === "string" ? instance[ handler ] : handler ) 631 .apply( instance, arguments ); 632 } 633 634 // Copy the guid so direct unbinding works 635 if ( typeof handler !== "string" ) { 636 handlerProxy.guid = handler.guid = 637 handler.guid || handlerProxy.guid || $.guid++; 638 } 639 640 var match = event.match( /^([\w:-]*)\s*(.*)$/ ); 641 var eventName = match[ 1 ] + instance.eventNamespace; 642 var selector = match[ 2 ]; 643 644 if ( selector ) { 645 delegateElement.on( eventName, selector, handlerProxy ); 646 } else { 647 element.on( eventName, handlerProxy ); 648 } 649 } ); 650 }, 651 652 _off: function( element, eventName ) { 653 eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) + 654 this.eventNamespace; 655 element.off( eventName ); 656 657 // Clear the stack to avoid memory leaks (#10056) 658 this.bindings = $( this.bindings.not( element ).get() ); 659 this.focusable = $( this.focusable.not( element ).get() ); 660 this.hoverable = $( this.hoverable.not( element ).get() ); 661 }, 662 663 _delay: function( handler, delay ) { 664 function handlerProxy() { 665 return ( typeof handler === "string" ? instance[ handler ] : handler ) 666 .apply( instance, arguments ); 667 } 668 var instance = this; 669 return setTimeout( handlerProxy, delay || 0 ); 670 }, 671 672 _hoverable: function( element ) { 673 this.hoverable = this.hoverable.add( element ); 674 this._on( element, { 675 mouseenter: function( event ) { 676 this._addClass( $( event.currentTarget ), null, "ui-state-hover" ); 677 }, 678 mouseleave: function( event ) { 679 this._removeClass( $( event.currentTarget ), null, "ui-state-hover" ); 680 } 681 } ); 682 }, 683 684 _focusable: function( element ) { 685 this.focusable = this.focusable.add( element ); 686 this._on( element, { 687 focusin: function( event ) { 688 this._addClass( $( event.currentTarget ), null, "ui-state-focus" ); 689 }, 690 focusout: function( event ) { 691 this._removeClass( $( event.currentTarget ), null, "ui-state-focus" ); 692 } 693 } ); 694 }, 695 696 _trigger: function( type, event, data ) { 697 var prop, orig; 698 var callback = this.options[ type ]; 699 700 data = data || {}; 701 event = $.Event( event ); 702 event.type = ( type === this.widgetEventPrefix ? 703 type : 704 this.widgetEventPrefix + type ).toLowerCase(); 705 706 // The original event may come from any element 707 // so we need to reset the target on the new event 708 event.target = this.element[ 0 ]; 709 710 // Copy original event properties over to the new event 711 orig = event.originalEvent; 712 if ( orig ) { 713 for ( prop in orig ) { 714 if ( !( prop in event ) ) { 715 event[ prop ] = orig[ prop ]; 716 } 717 } 718 } 719 720 this.element.trigger( event, data ); 721 return !( typeof callback === "function" && 722 callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false || 723 event.isDefaultPrevented() ); 724 } 725}; 726 727$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { 728 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { 729 if ( typeof options === "string" ) { 730 options = { effect: options }; 731 } 732 733 var hasOptions; 734 var effectName = !options ? 735 method : 736 options === true || typeof options === "number" ? 737 defaultEffect : 738 options.effect || defaultEffect; 739 740 options = options || {}; 741 if ( typeof options === "number" ) { 742 options = { duration: options }; 743 } else if ( options === true ) { 744 options = {}; 745 } 746 747 hasOptions = !$.isEmptyObject( options ); 748 options.complete = callback; 749 750 if ( options.delay ) { 751 element.delay( options.delay ); 752 } 753 754 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { 755 element[ method ]( options ); 756 } else if ( effectName !== method && element[ effectName ] ) { 757 element[ effectName ]( options.duration, options.easing, callback ); 758 } else { 759 element.queue( function( next ) { 760 $( this )[ method ](); 761 if ( callback ) { 762 callback.call( element[ 0 ] ); 763 } 764 next(); 765 } ); 766 } 767 }; 768} ); 769 770var widget = $.widget; 771 772 773/*! 774 * jQuery UI Position 1.14.1 775 * https://jqueryui.com 776 * 777 * Copyright OpenJS Foundation and other contributors 778 * Released under the MIT license. 779 * https://jquery.org/license 780 * 781 * https://api.jqueryui.com/position/ 782 */ 783 784//>>label: Position 785//>>group: Core 786//>>description: Positions elements relative to other elements. 787//>>docs: https://api.jqueryui.com/position/ 788//>>demos: https://jqueryui.com/position/ 789 790 791( function() { 792var cachedScrollbarWidth, 793 max = Math.max, 794 abs = Math.abs, 795 rhorizontal = /left|center|right/, 796 rvertical = /top|center|bottom/, 797 roffset = /[\+\-]\d+(\.[\d]+)?%?/, 798 rposition = /^\w+/, 799 rpercent = /%$/, 800 _position = $.fn.position; 801 802function getOffsets( offsets, width, height ) { 803 return [ 804 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), 805 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) 806 ]; 807} 808 809function parseCss( element, property ) { 810 return parseInt( $.css( element, property ), 10 ) || 0; 811} 812 813function isWindow( obj ) { 814 return obj != null && obj === obj.window; 815} 816 817function getDimensions( elem ) { 818 var raw = elem[ 0 ]; 819 if ( raw.nodeType === 9 ) { 820 return { 821 width: elem.width(), 822 height: elem.height(), 823 offset: { top: 0, left: 0 } 824 }; 825 } 826 if ( isWindow( raw ) ) { 827 return { 828 width: elem.width(), 829 height: elem.height(), 830 offset: { top: elem.scrollTop(), left: elem.scrollLeft() } 831 }; 832 } 833 if ( raw.preventDefault ) { 834 return { 835 width: 0, 836 height: 0, 837 offset: { top: raw.pageY, left: raw.pageX } 838 }; 839 } 840 return { 841 width: elem.outerWidth(), 842 height: elem.outerHeight(), 843 offset: elem.offset() 844 }; 845} 846 847$.position = { 848 scrollbarWidth: function() { 849 if ( cachedScrollbarWidth !== undefined ) { 850 return cachedScrollbarWidth; 851 } 852 var w1, w2, 853 div = $( "<div style=" + 854 "'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" + 855 "<div style='height:300px;width:auto;'></div></div>" ), 856 innerDiv = div.children()[ 0 ]; 857 858 $( "body" ).append( div ); 859 w1 = innerDiv.offsetWidth; 860 div.css( "overflow", "scroll" ); 861 862 w2 = innerDiv.offsetWidth; 863 864 if ( w1 === w2 ) { 865 w2 = div[ 0 ].clientWidth; 866 } 867 868 div.remove(); 869 870 return ( cachedScrollbarWidth = w1 - w2 ); 871 }, 872 getScrollInfo: function( within ) { 873 var overflowX = within.isWindow || within.isDocument ? "" : 874 within.element.css( "overflow-x" ), 875 overflowY = within.isWindow || within.isDocument ? "" : 876 within.element.css( "overflow-y" ), 877 hasOverflowX = overflowX === "scroll" || 878 ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ), 879 hasOverflowY = overflowY === "scroll" || 880 ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight ); 881 return { 882 width: hasOverflowY ? $.position.scrollbarWidth() : 0, 883 height: hasOverflowX ? $.position.scrollbarWidth() : 0 884 }; 885 }, 886 getWithinInfo: function( element ) { 887 var withinElement = $( element || window ), 888 isElemWindow = isWindow( withinElement[ 0 ] ), 889 isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9, 890 hasOffset = !isElemWindow && !isDocument; 891 return { 892 element: withinElement, 893 isWindow: isElemWindow, 894 isDocument: isDocument, 895 offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 }, 896 scrollLeft: withinElement.scrollLeft(), 897 scrollTop: withinElement.scrollTop(), 898 width: withinElement.outerWidth(), 899 height: withinElement.outerHeight() 900 }; 901 } 902}; 903 904$.fn.position = function( options ) { 905 if ( !options || !options.of ) { 906 return _position.apply( this, arguments ); 907 } 908 909 // Make a copy, we don't want to modify arguments 910 options = $.extend( {}, options ); 911 912 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, 913 914 // Make sure string options are treated as CSS selectors 915 target = typeof options.of === "string" ? 916 $( document ).find( options.of ) : 917 $( options.of ), 918 919 within = $.position.getWithinInfo( options.within ), 920 scrollInfo = $.position.getScrollInfo( within ), 921 collision = ( options.collision || "flip" ).split( " " ), 922 offsets = {}; 923 924 dimensions = getDimensions( target ); 925 if ( target[ 0 ].preventDefault ) { 926 927 // Force left top to allow flipping 928 options.at = "left top"; 929 } 930 targetWidth = dimensions.width; 931 targetHeight = dimensions.height; 932 targetOffset = dimensions.offset; 933 934 // Clone to reuse original targetOffset later 935 basePosition = $.extend( {}, targetOffset ); 936 937 // Force my and at to have valid horizontal and vertical positions 938 // if a value is missing or invalid, it will be converted to center 939 $.each( [ "my", "at" ], function() { 940 var pos = ( options[ this ] || "" ).split( " " ), 941 horizontalOffset, 942 verticalOffset; 943 944 if ( pos.length === 1 ) { 945 pos = rhorizontal.test( pos[ 0 ] ) ? 946 pos.concat( [ "center" ] ) : 947 rvertical.test( pos[ 0 ] ) ? 948 [ "center" ].concat( pos ) : 949 [ "center", "center" ]; 950 } 951 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; 952 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; 953 954 // Calculate offsets 955 horizontalOffset = roffset.exec( pos[ 0 ] ); 956 verticalOffset = roffset.exec( pos[ 1 ] ); 957 offsets[ this ] = [ 958 horizontalOffset ? horizontalOffset[ 0 ] : 0, 959 verticalOffset ? verticalOffset[ 0 ] : 0 960 ]; 961 962 // Reduce to just the positions without the offsets 963 options[ this ] = [ 964 rposition.exec( pos[ 0 ] )[ 0 ], 965 rposition.exec( pos[ 1 ] )[ 0 ] 966 ]; 967 } ); 968 969 // Normalize collision option 970 if ( collision.length === 1 ) { 971 collision[ 1 ] = collision[ 0 ]; 972 } 973 974 if ( options.at[ 0 ] === "right" ) { 975 basePosition.left += targetWidth; 976 } else if ( options.at[ 0 ] === "center" ) { 977 basePosition.left += targetWidth / 2; 978 } 979 980 if ( options.at[ 1 ] === "bottom" ) { 981 basePosition.top += targetHeight; 982 } else if ( options.at[ 1 ] === "center" ) { 983 basePosition.top += targetHeight / 2; 984 } 985 986 atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); 987 basePosition.left += atOffset[ 0 ]; 988 basePosition.top += atOffset[ 1 ]; 989 990 return this.each( function() { 991 var collisionPosition, using, 992 elem = $( this ), 993 elemWidth = elem.outerWidth(), 994 elemHeight = elem.outerHeight(), 995 marginLeft = parseCss( this, "marginLeft" ), 996 marginTop = parseCss( this, "marginTop" ), 997 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + 998 scrollInfo.width, 999 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + 1000 scrollInfo.height, 1001 position = $.extend( {}, basePosition ), 1002 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); 1003 1004 if ( options.my[ 0 ] === "right" ) { 1005 position.left -= elemWidth; 1006 } else if ( options.my[ 0 ] === "center" ) { 1007 position.left -= elemWidth / 2; 1008 } 1009 1010 if ( options.my[ 1 ] === "bottom" ) { 1011 position.top -= elemHeight; 1012 } else if ( options.my[ 1 ] === "center" ) { 1013 position.top -= elemHeight / 2; 1014 } 1015 1016 position.left += myOffset[ 0 ]; 1017 position.top += myOffset[ 1 ]; 1018 1019 collisionPosition = { 1020 marginLeft: marginLeft, 1021 marginTop: marginTop 1022 }; 1023 1024 $.each( [ "left", "top" ], function( i, dir ) { 1025 if ( $.ui.position[ collision[ i ] ] ) { 1026 $.ui.position[ collision[ i ] ][ dir ]( position, { 1027 targetWidth: targetWidth, 1028 targetHeight: targetHeight, 1029 elemWidth: elemWidth, 1030 elemHeight: elemHeight, 1031 collisionPosition: collisionPosition, 1032 collisionWidth: collisionWidth, 1033 collisionHeight: collisionHeight, 1034 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], 1035 my: options.my, 1036 at: options.at, 1037 within: within, 1038 elem: elem 1039 } ); 1040 } 1041 } ); 1042 1043 if ( options.using ) { 1044 1045 // Adds feedback as second argument to using callback, if present 1046 using = function( props ) { 1047 var left = targetOffset.left - position.left, 1048 right = left + targetWidth - elemWidth, 1049 top = targetOffset.top - position.top, 1050 bottom = top + targetHeight - elemHeight, 1051 feedback = { 1052 target: { 1053 element: target, 1054 left: targetOffset.left, 1055 top: targetOffset.top, 1056 width: targetWidth, 1057 height: targetHeight 1058 }, 1059 element: { 1060 element: elem, 1061 left: position.left, 1062 top: position.top, 1063 width: elemWidth, 1064 height: elemHeight 1065 }, 1066 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", 1067 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" 1068 }; 1069 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { 1070 feedback.horizontal = "center"; 1071 } 1072 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { 1073 feedback.vertical = "middle"; 1074 } 1075 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { 1076 feedback.important = "horizontal"; 1077 } else { 1078 feedback.important = "vertical"; 1079 } 1080 options.using.call( this, props, feedback ); 1081 }; 1082 } 1083 1084 elem.offset( $.extend( position, { using: using } ) ); 1085 } ); 1086}; 1087 1088$.ui.position = { 1089 fit: { 1090 left: function( position, data ) { 1091 var within = data.within, 1092 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, 1093 outerWidth = within.width, 1094 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 1095 overLeft = withinOffset - collisionPosLeft, 1096 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, 1097 newOverRight; 1098 1099 // Element is wider than within 1100 if ( data.collisionWidth > outerWidth ) { 1101 1102 // Element is initially over the left side of within 1103 if ( overLeft > 0 && overRight <= 0 ) { 1104 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - 1105 withinOffset; 1106 position.left += overLeft - newOverRight; 1107 1108 // Element is initially over right side of within 1109 } else if ( overRight > 0 && overLeft <= 0 ) { 1110 position.left = withinOffset; 1111 1112 // Element is initially over both left and right sides of within 1113 } else { 1114 if ( overLeft > overRight ) { 1115 position.left = withinOffset + outerWidth - data.collisionWidth; 1116 } else { 1117 position.left = withinOffset; 1118 } 1119 } 1120 1121 // Too far left -> align with left edge 1122 } else if ( overLeft > 0 ) { 1123 position.left += overLeft; 1124 1125 // Too far right -> align with right edge 1126 } else if ( overRight > 0 ) { 1127 position.left -= overRight; 1128 1129 // Adjust based on position and margin 1130 } else { 1131 position.left = max( position.left - collisionPosLeft, position.left ); 1132 } 1133 }, 1134 top: function( position, data ) { 1135 var within = data.within, 1136 withinOffset = within.isWindow ? within.scrollTop : within.offset.top, 1137 outerHeight = data.within.height, 1138 collisionPosTop = position.top - data.collisionPosition.marginTop, 1139 overTop = withinOffset - collisionPosTop, 1140 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, 1141 newOverBottom; 1142 1143 // Element is taller than within 1144 if ( data.collisionHeight > outerHeight ) { 1145 1146 // Element is initially over the top of within 1147 if ( overTop > 0 && overBottom <= 0 ) { 1148 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - 1149 withinOffset; 1150 position.top += overTop - newOverBottom; 1151 1152 // Element is initially over bottom of within 1153 } else if ( overBottom > 0 && overTop <= 0 ) { 1154 position.top = withinOffset; 1155 1156 // Element is initially over both top and bottom of within 1157 } else { 1158 if ( overTop > overBottom ) { 1159 position.top = withinOffset + outerHeight - data.collisionHeight; 1160 } else { 1161 position.top = withinOffset; 1162 } 1163 } 1164 1165 // Too far up -> align with top 1166 } else if ( overTop > 0 ) { 1167 position.top += overTop; 1168 1169 // Too far down -> align with bottom edge 1170 } else if ( overBottom > 0 ) { 1171 position.top -= overBottom; 1172 1173 // Adjust based on position and margin 1174 } else { 1175 position.top = max( position.top - collisionPosTop, position.top ); 1176 } 1177 } 1178 }, 1179 flip: { 1180 left: function( position, data ) { 1181 var within = data.within, 1182 withinOffset = within.offset.left + within.scrollLeft, 1183 outerWidth = within.width, 1184 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, 1185 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 1186 overLeft = collisionPosLeft - offsetLeft, 1187 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, 1188 myOffset = data.my[ 0 ] === "left" ? 1189 -data.elemWidth : 1190 data.my[ 0 ] === "right" ? 1191 data.elemWidth : 1192 0, 1193 atOffset = data.at[ 0 ] === "left" ? 1194 data.targetWidth : 1195 data.at[ 0 ] === "right" ? 1196 -data.targetWidth : 1197 0, 1198 offset = -2 * data.offset[ 0 ], 1199 newOverRight, 1200 newOverLeft; 1201 1202 if ( overLeft < 0 ) { 1203 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - 1204 outerWidth - withinOffset; 1205 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { 1206 position.left += myOffset + atOffset + offset; 1207 } 1208 } else if ( overRight > 0 ) { 1209 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + 1210 atOffset + offset - offsetLeft; 1211 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { 1212 position.left += myOffset + atOffset + offset; 1213 } 1214 } 1215 }, 1216 top: function( position, data ) { 1217 var within = data.within, 1218 withinOffset = within.offset.top + within.scrollTop, 1219 outerHeight = within.height, 1220 offsetTop = within.isWindow ? within.scrollTop : within.offset.top, 1221 collisionPosTop = position.top - data.collisionPosition.marginTop, 1222 overTop = collisionPosTop - offsetTop, 1223 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, 1224 top = data.my[ 1 ] === "top", 1225 myOffset = top ? 1226 -data.elemHeight : 1227 data.my[ 1 ] === "bottom" ? 1228 data.elemHeight : 1229 0, 1230 atOffset = data.at[ 1 ] === "top" ? 1231 data.targetHeight : 1232 data.at[ 1 ] === "bottom" ? 1233 -data.targetHeight : 1234 0, 1235 offset = -2 * data.offset[ 1 ], 1236 newOverTop, 1237 newOverBottom; 1238 if ( overTop < 0 ) { 1239 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - 1240 outerHeight - withinOffset; 1241 if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) { 1242 position.top += myOffset + atOffset + offset; 1243 } 1244 } else if ( overBottom > 0 ) { 1245 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + 1246 offset - offsetTop; 1247 if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) { 1248 position.top += myOffset + atOffset + offset; 1249 } 1250 } 1251 } 1252 }, 1253 flipfit: { 1254 left: function() { 1255 $.ui.position.flip.left.apply( this, arguments ); 1256 $.ui.position.fit.left.apply( this, arguments ); 1257 }, 1258 top: function() { 1259 $.ui.position.flip.top.apply( this, arguments ); 1260 $.ui.position.fit.top.apply( this, arguments ); 1261 } 1262 } 1263}; 1264 1265} )(); 1266 1267var position = $.ui.position; 1268 1269 1270/*! 1271 * jQuery UI :data 1.14.1 1272 * https://jqueryui.com 1273 * 1274 * Copyright OpenJS Foundation and other contributors 1275 * Released under the MIT license. 1276 * https://jquery.org/license 1277 */ 1278 1279//>>label: :data Selector 1280//>>group: Core 1281//>>description: Selects elements which have data stored under the specified key. 1282//>>docs: https://api.jqueryui.com/data-selector/ 1283 1284 1285var data = $.extend( $.expr.pseudos, { 1286 data: $.expr.createPseudo( function( dataName ) { 1287 return function( elem ) { 1288 return !!$.data( elem, dataName ); 1289 }; 1290 } ) 1291} ); 1292 1293/*! 1294 * jQuery UI Disable Selection 1.14.1 1295 * https://jqueryui.com 1296 * 1297 * Copyright OpenJS Foundation and other contributors 1298 * Released under the MIT license. 1299 * https://jquery.org/license 1300 */ 1301 1302//>>label: disableSelection 1303//>>group: Core 1304//>>description: Disable selection of text content within the set of matched elements. 1305//>>docs: https://api.jqueryui.com/disableSelection/ 1306 1307// This file is deprecated 1308 1309var disableSelection = $.fn.extend( { 1310 disableSelection: ( function() { 1311 var eventType = "onselectstart" in document.createElement( "div" ) ? 1312 "selectstart" : 1313 "mousedown"; 1314 1315 return function() { 1316 return this.on( eventType + ".ui-disableSelection", function( event ) { 1317 event.preventDefault(); 1318 } ); 1319 }; 1320 } )(), 1321 1322 enableSelection: function() { 1323 return this.off( ".ui-disableSelection" ); 1324 } 1325} ); 1326 1327 1328 1329// Create a local jQuery because jQuery Color relies on it and the 1330// global may not exist with AMD and a custom build (#10199). 1331// This module is a noop if used as a regular AMD module. 1332// eslint-disable-next-line no-unused-vars 1333var jQuery = $; 1334 1335 1336/*! 1337 * jQuery Color Animations v3.0.0 1338 * https://github.com/jquery/jquery-color 1339 * 1340 * Copyright OpenJS Foundation and other contributors 1341 * Released under the MIT license. 1342 * https://jquery.org/license 1343 * 1344 * Date: Wed May 15 16:49:44 2024 +0200 1345 */ 1346 1347 1348 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " + 1349 "borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", 1350 1351 class2type = {}, 1352 toString = class2type.toString, 1353 1354 // plusequals test for += 100 -= 100 1355 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, 1356 1357 // a set of RE's that can match strings and generate color tuples. 1358 stringParsers = [ { 1359 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 1360 parse: function( execResult ) { 1361 return [ 1362 execResult[ 1 ], 1363 execResult[ 2 ], 1364 execResult[ 3 ], 1365 execResult[ 4 ] 1366 ]; 1367 } 1368 }, { 1369 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 1370 parse: function( execResult ) { 1371 return [ 1372 execResult[ 1 ] * 2.55, 1373 execResult[ 2 ] * 2.55, 1374 execResult[ 3 ] * 2.55, 1375 execResult[ 4 ] 1376 ]; 1377 } 1378 }, { 1379 1380 // this regex ignores A-F because it's compared against an already lowercased string 1381 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?/, 1382 parse: function( execResult ) { 1383 return [ 1384 parseInt( execResult[ 1 ], 16 ), 1385 parseInt( execResult[ 2 ], 16 ), 1386 parseInt( execResult[ 3 ], 16 ), 1387 execResult[ 4 ] ? 1388 ( parseInt( execResult[ 4 ], 16 ) / 255 ).toFixed( 2 ) : 1389 1 1390 ]; 1391 } 1392 }, { 1393 1394 // this regex ignores A-F because it's compared against an already lowercased string 1395 re: /#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?/, 1396 parse: function( execResult ) { 1397 return [ 1398 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), 1399 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), 1400 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ), 1401 execResult[ 4 ] ? 1402 ( parseInt( execResult[ 4 ] + execResult[ 4 ], 16 ) / 255 ) 1403 .toFixed( 2 ) : 1404 1 1405 ]; 1406 } 1407 }, { 1408 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 1409 space: "hsla", 1410 parse: function( execResult ) { 1411 return [ 1412 execResult[ 1 ], 1413 execResult[ 2 ] / 100, 1414 execResult[ 3 ] / 100, 1415 execResult[ 4 ] 1416 ]; 1417 } 1418 } ], 1419 1420 // jQuery.Color( ) 1421 color = jQuery.Color = function( color, green, blue, alpha ) { 1422 return new jQuery.Color.fn.parse( color, green, blue, alpha ); 1423 }, 1424 spaces = { 1425 rgba: { 1426 props: { 1427 red: { 1428 idx: 0, 1429 type: "byte" 1430 }, 1431 green: { 1432 idx: 1, 1433 type: "byte" 1434 }, 1435 blue: { 1436 idx: 2, 1437 type: "byte" 1438 } 1439 } 1440 }, 1441 1442 hsla: { 1443 props: { 1444 hue: { 1445 idx: 0, 1446 type: "degrees" 1447 }, 1448 saturation: { 1449 idx: 1, 1450 type: "percent" 1451 }, 1452 lightness: { 1453 idx: 2, 1454 type: "percent" 1455 } 1456 } 1457 } 1458 }, 1459 propTypes = { 1460 "byte": { 1461 floor: true, 1462 max: 255 1463 }, 1464 "percent": { 1465 max: 1 1466 }, 1467 "degrees": { 1468 mod: 360, 1469 floor: true 1470 } 1471 }, 1472 1473 // colors = jQuery.Color.names 1474 colors, 1475 1476 // local aliases of functions called often 1477 each = jQuery.each; 1478 1479// define cache name and alpha properties 1480// for rgba and hsla spaces 1481each( spaces, function( spaceName, space ) { 1482 space.cache = "_" + spaceName; 1483 space.props.alpha = { 1484 idx: 3, 1485 type: "percent", 1486 def: 1 1487 }; 1488} ); 1489 1490// Populate the class2type map 1491jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), 1492 function( _i, name ) { 1493 class2type[ "[object " + name + "]" ] = name.toLowerCase(); 1494 } ); 1495 1496function getType( obj ) { 1497 if ( obj == null ) { 1498 return obj + ""; 1499 } 1500 1501 return typeof obj === "object" ? 1502 class2type[ toString.call( obj ) ] || "object" : 1503 typeof obj; 1504} 1505 1506function clamp( value, prop, allowEmpty ) { 1507 var type = propTypes[ prop.type ] || {}; 1508 1509 if ( value == null ) { 1510 return ( allowEmpty || !prop.def ) ? null : prop.def; 1511 } 1512 1513 // ~~ is an short way of doing floor for positive numbers 1514 value = type.floor ? ~~value : parseFloat( value ); 1515 1516 if ( type.mod ) { 1517 1518 // we add mod before modding to make sure that negatives values 1519 // get converted properly: -10 -> 350 1520 return ( value + type.mod ) % type.mod; 1521 } 1522 1523 // for now all property types without mod have min and max 1524 return Math.min( type.max, Math.max( 0, value ) ); 1525} 1526 1527function stringParse( string ) { 1528 var inst = color(), 1529 rgba = inst._rgba = []; 1530 1531 string = string.toLowerCase(); 1532 1533 each( stringParsers, function( _i, parser ) { 1534 var parsed, 1535 match = parser.re.exec( string ), 1536 values = match && parser.parse( match ), 1537 spaceName = parser.space || "rgba"; 1538 1539 if ( values ) { 1540 parsed = inst[ spaceName ]( values ); 1541 1542 // if this was an rgba parse the assignment might happen twice 1543 // oh well.... 1544 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; 1545 rgba = inst._rgba = parsed._rgba; 1546 1547 // exit each( stringParsers ) here because we matched 1548 return false; 1549 } 1550 } ); 1551 1552 // Found a stringParser that handled it 1553 if ( rgba.length ) { 1554 1555 // if this came from a parsed string, force "transparent" when alpha is 0 1556 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) 1557 if ( rgba.join() === "0,0,0,0" ) { 1558 jQuery.extend( rgba, colors.transparent ); 1559 } 1560 return inst; 1561 } 1562 1563 // named colors 1564 return colors[ string ]; 1565} 1566 1567color.fn = jQuery.extend( color.prototype, { 1568 parse: function( red, green, blue, alpha ) { 1569 if ( red === undefined ) { 1570 this._rgba = [ null, null, null, null ]; 1571 return this; 1572 } 1573 if ( red.jquery || red.nodeType ) { 1574 red = jQuery( red ).css( green ); 1575 green = undefined; 1576 } 1577 1578 var inst = this, 1579 type = getType( red ), 1580 rgba = this._rgba = []; 1581 1582 // more than 1 argument specified - assume ( red, green, blue, alpha ) 1583 if ( green !== undefined ) { 1584 red = [ red, green, blue, alpha ]; 1585 type = "array"; 1586 } 1587 1588 if ( type === "string" ) { 1589 return this.parse( stringParse( red ) || colors._default ); 1590 } 1591 1592 if ( type === "array" ) { 1593 each( spaces.rgba.props, function( _key, prop ) { 1594 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); 1595 } ); 1596 return this; 1597 } 1598 1599 if ( type === "object" ) { 1600 if ( red instanceof color ) { 1601 each( spaces, function( _spaceName, space ) { 1602 if ( red[ space.cache ] ) { 1603 inst[ space.cache ] = red[ space.cache ].slice(); 1604 } 1605 } ); 1606 } else { 1607 each( spaces, function( _spaceName, space ) { 1608 var cache = space.cache; 1609 each( space.props, function( key, prop ) { 1610 1611 // if the cache doesn't exist, and we know how to convert 1612 if ( !inst[ cache ] && space.to ) { 1613 1614 // if the value was null, we don't need to copy it 1615 // if the key was alpha, we don't need to copy it either 1616 if ( key === "alpha" || red[ key ] == null ) { 1617 return; 1618 } 1619 inst[ cache ] = space.to( inst._rgba ); 1620 } 1621 1622 // this is the only case where we allow nulls for ALL properties. 1623 // call clamp with alwaysAllowEmpty 1624 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); 1625 } ); 1626 1627 // everything defined but alpha? 1628 if ( inst[ cache ] && jQuery.inArray( 1629 null, 1630 inst[ cache ].slice( 0, 3 ) 1631 ) < 0 ) { 1632 1633 // use the default of 1 1634 if ( inst[ cache ][ 3 ] == null ) { 1635 inst[ cache ][ 3 ] = 1; 1636 } 1637 1638 if ( space.from ) { 1639 inst._rgba = space.from( inst[ cache ] ); 1640 } 1641 } 1642 } ); 1643 } 1644 return this; 1645 } 1646 }, 1647 is: function( compare ) { 1648 var is = color( compare ), 1649 same = true, 1650 inst = this; 1651 1652 each( spaces, function( _, space ) { 1653 var localCache, 1654 isCache = is[ space.cache ]; 1655 if ( isCache ) { 1656 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; 1657 each( space.props, function( _, prop ) { 1658 if ( isCache[ prop.idx ] != null ) { 1659 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); 1660 return same; 1661 } 1662 } ); 1663 } 1664 return same; 1665 } ); 1666 return same; 1667 }, 1668 _space: function() { 1669 var used = [], 1670 inst = this; 1671 each( spaces, function( spaceName, space ) { 1672 if ( inst[ space.cache ] ) { 1673 used.push( spaceName ); 1674 } 1675 } ); 1676 return used.pop(); 1677 }, 1678 transition: function( other, distance ) { 1679 var end = color( other ), 1680 spaceName = end._space(), 1681 space = spaces[ spaceName ], 1682 startColor = this.alpha() === 0 ? color( "transparent" ) : this, 1683 start = startColor[ space.cache ] || space.to( startColor._rgba ), 1684 result = start.slice(); 1685 1686 end = end[ space.cache ]; 1687 each( space.props, function( _key, prop ) { 1688 var index = prop.idx, 1689 startValue = start[ index ], 1690 endValue = end[ index ], 1691 type = propTypes[ prop.type ] || {}; 1692 1693 // if null, don't override start value 1694 if ( endValue === null ) { 1695 return; 1696 } 1697 1698 // if null - use end 1699 if ( startValue === null ) { 1700 result[ index ] = endValue; 1701 } else { 1702 if ( type.mod ) { 1703 if ( endValue - startValue > type.mod / 2 ) { 1704 startValue += type.mod; 1705 } else if ( startValue - endValue > type.mod / 2 ) { 1706 startValue -= type.mod; 1707 } 1708 } 1709 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); 1710 } 1711 } ); 1712 return this[ spaceName ]( result ); 1713 }, 1714 blend: function( opaque ) { 1715 1716 // if we are already opaque - return ourself 1717 if ( this._rgba[ 3 ] === 1 ) { 1718 return this; 1719 } 1720 1721 var rgb = this._rgba.slice(), 1722 a = rgb.pop(), 1723 blend = color( opaque )._rgba; 1724 1725 return color( jQuery.map( rgb, function( v, i ) { 1726 return ( 1 - a ) * blend[ i ] + a * v; 1727 } ) ); 1728 }, 1729 toRgbaString: function() { 1730 var prefix = "rgba(", 1731 rgba = jQuery.map( this._rgba, function( v, i ) { 1732 if ( v != null ) { 1733 return v; 1734 } 1735 return i > 2 ? 1 : 0; 1736 } ); 1737 1738 if ( rgba[ 3 ] === 1 ) { 1739 rgba.pop(); 1740 prefix = "rgb("; 1741 } 1742 1743 return prefix + rgba.join( ", " ) + ")"; 1744 }, 1745 toHslaString: function() { 1746 var prefix = "hsla(", 1747 hsla = jQuery.map( this.hsla(), function( v, i ) { 1748 if ( v == null ) { 1749 v = i > 2 ? 1 : 0; 1750 } 1751 1752 // catch 1 and 2 1753 if ( i && i < 3 ) { 1754 v = Math.round( v * 100 ) + "%"; 1755 } 1756 return v; 1757 } ); 1758 1759 if ( hsla[ 3 ] === 1 ) { 1760 hsla.pop(); 1761 prefix = "hsl("; 1762 } 1763 return prefix + hsla.join( ", " ) + ")"; 1764 }, 1765 toHexString: function( includeAlpha ) { 1766 var rgba = this._rgba.slice(), 1767 alpha = rgba.pop(); 1768 1769 if ( includeAlpha ) { 1770 rgba.push( ~~( alpha * 255 ) ); 1771 } 1772 1773 return "#" + jQuery.map( rgba, function( v ) { 1774 1775 // default to 0 when nulls exist 1776 return ( "0" + ( v || 0 ).toString( 16 ) ).substr( -2 ); 1777 } ).join( "" ); 1778 }, 1779 toString: function() { 1780 return this.toRgbaString(); 1781 } 1782} ); 1783color.fn.parse.prototype = color.fn; 1784 1785// hsla conversions adapted from: 1786// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 1787 1788function hue2rgb( p, q, h ) { 1789 h = ( h + 1 ) % 1; 1790 if ( h * 6 < 1 ) { 1791 return p + ( q - p ) * h * 6; 1792 } 1793 if ( h * 2 < 1 ) { 1794 return q; 1795 } 1796 if ( h * 3 < 2 ) { 1797 return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6; 1798 } 1799 return p; 1800} 1801 1802spaces.hsla.to = function( rgba ) { 1803 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { 1804 return [ null, null, null, rgba[ 3 ] ]; 1805 } 1806 var r = rgba[ 0 ] / 255, 1807 g = rgba[ 1 ] / 255, 1808 b = rgba[ 2 ] / 255, 1809 a = rgba[ 3 ], 1810 max = Math.max( r, g, b ), 1811 min = Math.min( r, g, b ), 1812 diff = max - min, 1813 add = max + min, 1814 l = add * 0.5, 1815 h, s; 1816 1817 if ( min === max ) { 1818 h = 0; 1819 } else if ( r === max ) { 1820 h = ( 60 * ( g - b ) / diff ) + 360; 1821 } else if ( g === max ) { 1822 h = ( 60 * ( b - r ) / diff ) + 120; 1823 } else { 1824 h = ( 60 * ( r - g ) / diff ) + 240; 1825 } 1826 1827 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0% 1828 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) 1829 if ( diff === 0 ) { 1830 s = 0; 1831 } else if ( l <= 0.5 ) { 1832 s = diff / add; 1833 } else { 1834 s = diff / ( 2 - add ); 1835 } 1836 return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ]; 1837}; 1838 1839spaces.hsla.from = function( hsla ) { 1840 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { 1841 return [ null, null, null, hsla[ 3 ] ]; 1842 } 1843 var h = hsla[ 0 ] / 360, 1844 s = hsla[ 1 ], 1845 l = hsla[ 2 ], 1846 a = hsla[ 3 ], 1847 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, 1848 p = 2 * l - q; 1849 1850 return [ 1851 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), 1852 Math.round( hue2rgb( p, q, h ) * 255 ), 1853 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), 1854 a 1855 ]; 1856}; 1857 1858 1859each( spaces, function( spaceName, space ) { 1860 var props = space.props, 1861 cache = space.cache, 1862 to = space.to, 1863 from = space.from; 1864 1865 // makes rgba() and hsla() 1866 color.fn[ spaceName ] = function( value ) { 1867 1868 // generate a cache for this space if it doesn't exist 1869 if ( to && !this[ cache ] ) { 1870 this[ cache ] = to( this._rgba ); 1871 } 1872 if ( value === undefined ) { 1873 return this[ cache ].slice(); 1874 } 1875 1876 var ret, 1877 type = getType( value ), 1878 arr = ( type === "array" || type === "object" ) ? value : arguments, 1879 local = this[ cache ].slice(); 1880 1881 each( props, function( key, prop ) { 1882 var val = arr[ type === "object" ? key : prop.idx ]; 1883 if ( val == null ) { 1884 val = local[ prop.idx ]; 1885 } 1886 local[ prop.idx ] = clamp( val, prop ); 1887 } ); 1888 1889 if ( from ) { 1890 ret = color( from( local ) ); 1891 ret[ cache ] = local; 1892 return ret; 1893 } else { 1894 return color( local ); 1895 } 1896 }; 1897 1898 // makes red() green() blue() alpha() hue() saturation() lightness() 1899 each( props, function( key, prop ) { 1900 1901 // alpha is included in more than one space 1902 if ( color.fn[ key ] ) { 1903 return; 1904 } 1905 color.fn[ key ] = function( value ) { 1906 var local, cur, match, fn, 1907 vtype = getType( value ); 1908 1909 if ( key === "alpha" ) { 1910 fn = this._hsla ? "hsla" : "rgba"; 1911 } else { 1912 fn = spaceName; 1913 } 1914 local = this[ fn ](); 1915 cur = local[ prop.idx ]; 1916 1917 if ( vtype === "undefined" ) { 1918 return cur; 1919 } 1920 1921 if ( vtype === "function" ) { 1922 value = value.call( this, cur ); 1923 vtype = getType( value ); 1924 } 1925 if ( value == null && prop.empty ) { 1926 return this; 1927 } 1928 if ( vtype === "string" ) { 1929 match = rplusequals.exec( value ); 1930 if ( match ) { 1931 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); 1932 } 1933 } 1934 local[ prop.idx ] = value; 1935 return this[ fn ]( local ); 1936 }; 1937 } ); 1938} ); 1939 1940// add cssHook and .fx.step function for each named hook. 1941// accept a space separated string of properties 1942color.hook = function( hook ) { 1943 var hooks = hook.split( " " ); 1944 each( hooks, function( _i, hook ) { 1945 jQuery.cssHooks[ hook ] = { 1946 set: function( elem, value ) { 1947 var parsed; 1948 1949 if ( value !== "transparent" && 1950 ( getType( value ) !== "string" || 1951 ( parsed = stringParse( value ) ) ) ) { 1952 value = color( parsed || value ); 1953 value = value.toRgbaString(); 1954 } 1955 elem.style[ hook ] = value; 1956 } 1957 }; 1958 jQuery.fx.step[ hook ] = function( fx ) { 1959 if ( !fx.colorInit ) { 1960 fx.start = color( fx.elem, hook ); 1961 fx.end = color( fx.end ); 1962 fx.colorInit = true; 1963 } 1964 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); 1965 }; 1966 } ); 1967 1968}; 1969 1970color.hook( stepHooks ); 1971 1972jQuery.cssHooks.borderColor = { 1973 expand: function( value ) { 1974 var expanded = {}; 1975 1976 each( [ "Top", "Right", "Bottom", "Left" ], function( _i, part ) { 1977 expanded[ "border" + part + "Color" ] = value; 1978 } ); 1979 return expanded; 1980 } 1981}; 1982 1983// Basic color names only. 1984// Usage of any of the other color names requires adding yourself or including 1985// jquery.color.svg-names.js. 1986colors = jQuery.Color.names = { 1987 1988 // 4.1. Basic color keywords 1989 aqua: "#00ffff", 1990 black: "#000000", 1991 blue: "#0000ff", 1992 fuchsia: "#ff00ff", 1993 gray: "#808080", 1994 green: "#008000", 1995 lime: "#00ff00", 1996 maroon: "#800000", 1997 navy: "#000080", 1998 olive: "#808000", 1999 purple: "#800080", 2000 red: "#ff0000", 2001 silver: "#c0c0c0", 2002 teal: "#008080", 2003 white: "#ffffff", 2004 yellow: "#ffff00", 2005 2006 // 4.2.3. "transparent" color keyword 2007 transparent: [ null, null, null, 0 ], 2008 2009 _default: "#ffffff" 2010}; 2011 2012 2013/*! 2014 * jQuery UI Effects 1.14.1 2015 * https://jqueryui.com 2016 * 2017 * Copyright OpenJS Foundation and other contributors 2018 * Released under the MIT license. 2019 * https://jquery.org/license 2020 */ 2021 2022//>>label: Effects Core 2023//>>group: Effects 2024/* eslint-disable max-len */ 2025//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects. 2026/* eslint-enable max-len */ 2027//>>docs: https://api.jqueryui.com/category/effects-core/ 2028//>>demos: https://jqueryui.com/effect/ 2029 2030 2031var dataSpace = "ui-effects-", 2032 dataSpaceStyle = "ui-effects-style", 2033 dataSpaceAnimated = "ui-effects-animated"; 2034 2035$.effects = { 2036 effect: {} 2037}; 2038 2039/******************************************************************************/ 2040/****************************** CLASS ANIMATIONS ******************************/ 2041/******************************************************************************/ 2042( function() { 2043 2044var classAnimationActions = [ "add", "remove", "toggle" ], 2045 shorthandStyles = { 2046 border: 1, 2047 borderBottom: 1, 2048 borderColor: 1, 2049 borderLeft: 1, 2050 borderRight: 1, 2051 borderTop: 1, 2052 borderWidth: 1, 2053 margin: 1, 2054 padding: 1 2055 }; 2056 2057$.each( 2058 [ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], 2059 function( _, prop ) { 2060 $.fx.step[ prop ] = function( fx ) { 2061 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { 2062 jQuery.style( fx.elem, prop, fx.end ); 2063 fx.setAttr = true; 2064 } 2065 }; 2066 } 2067); 2068 2069function camelCase( string ) { 2070 return string.replace( /-([\da-z])/gi, function( all, letter ) { 2071 return letter.toUpperCase(); 2072 } ); 2073} 2074 2075function getElementStyles( elem ) { 2076 var key, len, 2077 style = elem.ownerDocument.defaultView.getComputedStyle( elem ), 2078 styles = {}; 2079 2080 len = style.length; 2081 while ( len-- ) { 2082 key = style[ len ]; 2083 if ( typeof style[ key ] === "string" ) { 2084 styles[ camelCase( key ) ] = style[ key ]; 2085 } 2086 } 2087 2088 return styles; 2089} 2090 2091function styleDifference( oldStyle, newStyle ) { 2092 var diff = {}, 2093 name, value; 2094 2095 for ( name in newStyle ) { 2096 value = newStyle[ name ]; 2097 if ( oldStyle[ name ] !== value ) { 2098 if ( !shorthandStyles[ name ] ) { 2099 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { 2100 diff[ name ] = value; 2101 } 2102 } 2103 } 2104 } 2105 2106 return diff; 2107} 2108 2109$.effects.animateClass = function( value, duration, easing, callback ) { 2110 var o = $.speed( duration, easing, callback ); 2111 2112 return this.queue( function() { 2113 var animated = $( this ), 2114 baseClass = animated.attr( "class" ) || "", 2115 applyClassChange, 2116 allAnimations = o.children ? animated.find( "*" ).addBack() : animated; 2117 2118 // Map the animated objects to store the original styles. 2119 allAnimations = allAnimations.map( function() { 2120 var el = $( this ); 2121 return { 2122 el: el, 2123 start: getElementStyles( this ) 2124 }; 2125 } ); 2126 2127 // Apply class change 2128 applyClassChange = function() { 2129 $.each( classAnimationActions, function( i, action ) { 2130 if ( value[ action ] ) { 2131 animated[ action + "Class" ]( value[ action ] ); 2132 } 2133 } ); 2134 }; 2135 applyClassChange(); 2136 2137 // Map all animated objects again - calculate new styles and diff 2138 allAnimations = allAnimations.map( function() { 2139 this.end = getElementStyles( this.el[ 0 ] ); 2140 this.diff = styleDifference( this.start, this.end ); 2141 return this; 2142 } ); 2143 2144 // Apply original class 2145 animated.attr( "class", baseClass ); 2146 2147 // Map all animated objects again - this time collecting a promise 2148 allAnimations = allAnimations.map( function() { 2149 var styleInfo = this, 2150 dfd = $.Deferred(), 2151 opts = $.extend( {}, o, { 2152 queue: false, 2153 complete: function() { 2154 dfd.resolve( styleInfo ); 2155 } 2156 } ); 2157 2158 this.el.animate( this.diff, opts ); 2159 return dfd.promise(); 2160 } ); 2161 2162 // Once all animations have completed: 2163 $.when.apply( $, allAnimations.get() ).done( function() { 2164 2165 // Set the final class 2166 applyClassChange(); 2167 2168 // For each animated element, 2169 // clear all css properties that were animated 2170 $.each( arguments, function() { 2171 var el = this.el; 2172 $.each( this.diff, function( key ) { 2173 el.css( key, "" ); 2174 } ); 2175 } ); 2176 2177 // This is guarnteed to be there if you use jQuery.speed() 2178 // it also handles dequeuing the next anim... 2179 o.complete.call( animated[ 0 ] ); 2180 } ); 2181 } ); 2182}; 2183 2184$.fn.extend( { 2185 addClass: ( function( orig ) { 2186 return function( classNames, speed, easing, callback ) { 2187 return speed ? 2188 $.effects.animateClass.call( this, 2189 { add: classNames }, speed, easing, callback ) : 2190 orig.apply( this, arguments ); 2191 }; 2192 } )( $.fn.addClass ), 2193 2194 removeClass: ( function( orig ) { 2195 return function( classNames, speed, easing, callback ) { 2196 return arguments.length > 1 ? 2197 $.effects.animateClass.call( this, 2198 { remove: classNames }, speed, easing, callback ) : 2199 orig.apply( this, arguments ); 2200 }; 2201 } )( $.fn.removeClass ), 2202 2203 toggleClass: ( function( orig ) { 2204 return function( classNames, force, speed, easing, callback ) { 2205 if ( typeof force === "boolean" || force === undefined ) { 2206 if ( !speed ) { 2207 2208 // Without speed parameter 2209 return orig.apply( this, arguments ); 2210 } else { 2211 return $.effects.animateClass.call( this, 2212 ( force ? { add: classNames } : { remove: classNames } ), 2213 speed, easing, callback ); 2214 } 2215 } else { 2216 2217 // Without force parameter 2218 return $.effects.animateClass.call( this, 2219 { toggle: classNames }, force, speed, easing ); 2220 } 2221 }; 2222 } )( $.fn.toggleClass ), 2223 2224 switchClass: function( remove, add, speed, easing, callback ) { 2225 return $.effects.animateClass.call( this, { 2226 add: add, 2227 remove: remove 2228 }, speed, easing, callback ); 2229 } 2230} ); 2231 2232} )(); 2233 2234/******************************************************************************/ 2235/*********************************** EFFECTS **********************************/ 2236/******************************************************************************/ 2237 2238( function() { 2239 2240if ( $.expr && $.expr.pseudos && $.expr.pseudos.animated ) { 2241 $.expr.pseudos.animated = ( function( orig ) { 2242 return function( elem ) { 2243 return !!$( elem ).data( dataSpaceAnimated ) || orig( elem ); 2244 }; 2245 } )( $.expr.pseudos.animated ); 2246} 2247 2248if ( $.uiBackCompat === true ) { 2249 $.extend( $.effects, { 2250 2251 // Saves a set of properties in a data storage 2252 save: function( element, set ) { 2253 var i = 0, length = set.length; 2254 for ( ; i < length; i++ ) { 2255 if ( set[ i ] !== null ) { 2256 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); 2257 } 2258 } 2259 }, 2260 2261 // Restores a set of previously saved properties from a data storage 2262 restore: function( element, set ) { 2263 var val, i = 0, length = set.length; 2264 for ( ; i < length; i++ ) { 2265 if ( set[ i ] !== null ) { 2266 val = element.data( dataSpace + set[ i ] ); 2267 element.css( set[ i ], val ); 2268 } 2269 } 2270 }, 2271 2272 setMode: function( el, mode ) { 2273 if ( mode === "toggle" ) { 2274 mode = el.is( ":hidden" ) ? "show" : "hide"; 2275 } 2276 return mode; 2277 }, 2278 2279 // Wraps the element around a wrapper that copies position properties 2280 createWrapper: function( element ) { 2281 2282 // If the element is already wrapped, return it 2283 if ( element.parent().is( ".ui-effects-wrapper" ) ) { 2284 return element.parent(); 2285 } 2286 2287 // Wrap the element 2288 var props = { 2289 width: element.outerWidth( true ), 2290 height: element.outerHeight( true ), 2291 "float": element.css( "float" ) 2292 }, 2293 wrapper = $( "<div></div>" ) 2294 .addClass( "ui-effects-wrapper" ) 2295 .css( { 2296 fontSize: "100%", 2297 background: "transparent", 2298 border: "none", 2299 margin: 0, 2300 padding: 0 2301 } ), 2302 2303 // Store the size in case width/height are defined in % - Fixes #5245 2304 size = { 2305 width: element.width(), 2306 height: element.height() 2307 }, 2308 active = document.activeElement; 2309 2310 // Support: Firefox 2311 // Firefox incorrectly exposes anonymous content 2312 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 2313 try { 2314 // eslint-disable-next-line no-unused-expressions 2315 active.id; 2316 } catch ( e ) { 2317 active = document.body; 2318 } 2319 2320 element.wrap( wrapper ); 2321 2322 // Fixes #7595 - Elements lose focus when wrapped. 2323 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 2324 $( active ).trigger( "focus" ); 2325 } 2326 2327 // Hotfix for jQuery 1.4 since some change in wrap() seems to actually 2328 // lose the reference to the wrapped element 2329 wrapper = element.parent(); 2330 2331 // Transfer positioning properties to the wrapper 2332 if ( element.css( "position" ) === "static" ) { 2333 wrapper.css( { position: "relative" } ); 2334 element.css( { position: "relative" } ); 2335 } else { 2336 $.extend( props, { 2337 position: element.css( "position" ), 2338 zIndex: element.css( "z-index" ) 2339 } ); 2340 $.each( [ "top", "left", "bottom", "right" ], function( i, pos ) { 2341 props[ pos ] = element.css( pos ); 2342 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { 2343 props[ pos ] = "auto"; 2344 } 2345 } ); 2346 element.css( { 2347 position: "relative", 2348 top: 0, 2349 left: 0, 2350 right: "auto", 2351 bottom: "auto" 2352 } ); 2353 } 2354 element.css( size ); 2355 2356 return wrapper.css( props ).show(); 2357 }, 2358 2359 removeWrapper: function( element ) { 2360 var active = document.activeElement; 2361 2362 if ( element.parent().is( ".ui-effects-wrapper" ) ) { 2363 element.parent().replaceWith( element ); 2364 2365 // Fixes #7595 - Elements lose focus when wrapped. 2366 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 2367 $( active ).trigger( "focus" ); 2368 } 2369 } 2370 2371 return element; 2372 } 2373 } ); 2374} 2375 2376$.extend( $.effects, { 2377 version: "1.14.1", 2378 2379 define: function( name, mode, effect ) { 2380 if ( !effect ) { 2381 effect = mode; 2382 mode = "effect"; 2383 } 2384 2385 $.effects.effect[ name ] = effect; 2386 $.effects.effect[ name ].mode = mode; 2387 2388 return effect; 2389 }, 2390 2391 scaledDimensions: function( element, percent, direction ) { 2392 if ( percent === 0 ) { 2393 return { 2394 height: 0, 2395 width: 0, 2396 outerHeight: 0, 2397 outerWidth: 0 2398 }; 2399 } 2400 2401 var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1, 2402 y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1; 2403 2404 return { 2405 height: element.height() * y, 2406 width: element.width() * x, 2407 outerHeight: element.outerHeight() * y, 2408 outerWidth: element.outerWidth() * x 2409 }; 2410 2411 }, 2412 2413 clipToBox: function( animation ) { 2414 return { 2415 width: animation.clip.right - animation.clip.left, 2416 height: animation.clip.bottom - animation.clip.top, 2417 left: animation.clip.left, 2418 top: animation.clip.top 2419 }; 2420 }, 2421 2422 // Injects recently queued functions to be first in line (after "inprogress") 2423 unshift: function( element, queueLength, count ) { 2424 var queue = element.queue(); 2425 2426 if ( queueLength > 1 ) { 2427 queue.splice.apply( queue, 2428 [ 1, 0 ].concat( queue.splice( queueLength, count ) ) ); 2429 } 2430 element.dequeue(); 2431 }, 2432 2433 saveStyle: function( element ) { 2434 element.data( dataSpaceStyle, element[ 0 ].style.cssText ); 2435 }, 2436 2437 restoreStyle: function( element ) { 2438 element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || ""; 2439 element.removeData( dataSpaceStyle ); 2440 }, 2441 2442 mode: function( element, mode ) { 2443 var hidden = element.is( ":hidden" ); 2444 2445 if ( mode === "toggle" ) { 2446 mode = hidden ? "show" : "hide"; 2447 } 2448 if ( hidden ? mode === "hide" : mode === "show" ) { 2449 mode = "none"; 2450 } 2451 return mode; 2452 }, 2453 2454 // Translates a [top,left] array into a baseline value 2455 getBaseline: function( origin, original ) { 2456 var y, x; 2457 2458 switch ( origin[ 0 ] ) { 2459 case "top": 2460 y = 0; 2461 break; 2462 case "middle": 2463 y = 0.5; 2464 break; 2465 case "bottom": 2466 y = 1; 2467 break; 2468 default: 2469 y = origin[ 0 ] / original.height; 2470 } 2471 2472 switch ( origin[ 1 ] ) { 2473 case "left": 2474 x = 0; 2475 break; 2476 case "center": 2477 x = 0.5; 2478 break; 2479 case "right": 2480 x = 1; 2481 break; 2482 default: 2483 x = origin[ 1 ] / original.width; 2484 } 2485 2486 return { 2487 x: x, 2488 y: y 2489 }; 2490 }, 2491 2492 // Creates a placeholder element so that the original element can be made absolute 2493 createPlaceholder: function( element ) { 2494 var placeholder, 2495 cssPosition = element.css( "position" ), 2496 position = element.position(); 2497 2498 // Lock in margins first to account for form elements, which 2499 // will change margin if you explicitly set height 2500 // see: https://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380 2501 // Support: Safari 2502 element.css( { 2503 marginTop: element.css( "marginTop" ), 2504 marginBottom: element.css( "marginBottom" ), 2505 marginLeft: element.css( "marginLeft" ), 2506 marginRight: element.css( "marginRight" ) 2507 } ) 2508 .outerWidth( element.outerWidth() ) 2509 .outerHeight( element.outerHeight() ); 2510 2511 if ( /^(static|relative)/.test( cssPosition ) ) { 2512 cssPosition = "absolute"; 2513 2514 placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( { 2515 2516 // Convert inline to inline block to account for inline elements 2517 // that turn to inline block based on content (like img) 2518 display: /^(inline|ruby)/.test( element.css( "display" ) ) ? 2519 "inline-block" : 2520 "block", 2521 visibility: "hidden", 2522 2523 // Margins need to be set to account for margin collapse 2524 marginTop: element.css( "marginTop" ), 2525 marginBottom: element.css( "marginBottom" ), 2526 marginLeft: element.css( "marginLeft" ), 2527 marginRight: element.css( "marginRight" ), 2528 "float": element.css( "float" ) 2529 } ) 2530 .outerWidth( element.outerWidth() ) 2531 .outerHeight( element.outerHeight() ) 2532 .addClass( "ui-effects-placeholder" ); 2533 2534 element.data( dataSpace + "placeholder", placeholder ); 2535 } 2536 2537 element.css( { 2538 position: cssPosition, 2539 left: position.left, 2540 top: position.top 2541 } ); 2542 2543 return placeholder; 2544 }, 2545 2546 removePlaceholder: function( element ) { 2547 var dataKey = dataSpace + "placeholder", 2548 placeholder = element.data( dataKey ); 2549 2550 if ( placeholder ) { 2551 placeholder.remove(); 2552 element.removeData( dataKey ); 2553 } 2554 }, 2555 2556 // Removes a placeholder if it exists and restores 2557 // properties that were modified during placeholder creation 2558 cleanUp: function( element ) { 2559 $.effects.restoreStyle( element ); 2560 $.effects.removePlaceholder( element ); 2561 }, 2562 2563 setTransition: function( element, list, factor, value ) { 2564 value = value || {}; 2565 $.each( list, function( i, x ) { 2566 var unit = element.cssUnit( x ); 2567 if ( unit[ 0 ] > 0 ) { 2568 value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; 2569 } 2570 } ); 2571 return value; 2572 } 2573} ); 2574 2575// Return an effect options object for the given parameters: 2576function _normalizeArguments( effect, options, speed, callback ) { 2577 2578 // Allow passing all options as the first parameter 2579 if ( $.isPlainObject( effect ) ) { 2580 options = effect; 2581 effect = effect.effect; 2582 } 2583 2584 // Convert to an object 2585 effect = { effect: effect }; 2586 2587 // Catch (effect, null, ...) 2588 if ( options == null ) { 2589 options = {}; 2590 } 2591 2592 // Catch (effect, callback) 2593 if ( typeof options === "function" ) { 2594 callback = options; 2595 speed = null; 2596 options = {}; 2597 } 2598 2599 // Catch (effect, speed, ?) 2600 if ( typeof options === "number" || $.fx.speeds[ options ] ) { 2601 callback = speed; 2602 speed = options; 2603 options = {}; 2604 } 2605 2606 // Catch (effect, options, callback) 2607 if ( typeof speed === "function" ) { 2608 callback = speed; 2609 speed = null; 2610 } 2611 2612 // Add options to effect 2613 if ( options ) { 2614 $.extend( effect, options ); 2615 } 2616 2617 speed = speed || options.duration; 2618 effect.duration = $.fx.off ? 0 : 2619 typeof speed === "number" ? speed : 2620 speed in $.fx.speeds ? $.fx.speeds[ speed ] : 2621 $.fx.speeds._default; 2622 2623 effect.complete = callback || options.complete; 2624 2625 return effect; 2626} 2627 2628function standardAnimationOption( option ) { 2629 2630 // Valid standard speeds (nothing, number, named speed) 2631 if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) { 2632 return true; 2633 } 2634 2635 // Invalid strings - treat as "normal" speed 2636 if ( typeof option === "string" && !$.effects.effect[ option ] ) { 2637 return true; 2638 } 2639 2640 // Complete callback 2641 if ( typeof option === "function" ) { 2642 return true; 2643 } 2644 2645 // Options hash (but not naming an effect) 2646 if ( typeof option === "object" && !option.effect ) { 2647 return true; 2648 } 2649 2650 // Didn't match any standard API 2651 return false; 2652} 2653 2654$.fn.extend( { 2655 effect: function( /* effect, options, speed, callback */ ) { 2656 var args = _normalizeArguments.apply( this, arguments ), 2657 effectMethod = $.effects.effect[ args.effect ], 2658 defaultMode = effectMethod.mode, 2659 queue = args.queue, 2660 queueName = queue || "fx", 2661 complete = args.complete, 2662 mode = args.mode, 2663 modes = [], 2664 prefilter = function( next ) { 2665 var el = $( this ), 2666 normalizedMode = $.effects.mode( el, mode ) || defaultMode; 2667 2668 // Sentinel for duck-punching the :animated pseudo-selector 2669 el.data( dataSpaceAnimated, true ); 2670 2671 // Save effect mode for later use, 2672 // we can't just call $.effects.mode again later, 2673 // as the .show() below destroys the initial state 2674 modes.push( normalizedMode ); 2675 2676 // See $.uiBackCompat inside of run() for removal of defaultMode in 1.14 2677 if ( defaultMode && ( normalizedMode === "show" || 2678 ( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) { 2679 el.show(); 2680 } 2681 2682 if ( !defaultMode || normalizedMode !== "none" ) { 2683 $.effects.saveStyle( el ); 2684 } 2685 2686 if ( typeof next === "function" ) { 2687 next(); 2688 } 2689 }; 2690 2691 if ( $.fx.off || !effectMethod ) { 2692 2693 // Delegate to the original method (e.g., .show()) if possible 2694 if ( mode ) { 2695 return this[ mode ]( args.duration, complete ); 2696 } else { 2697 return this.each( function() { 2698 if ( complete ) { 2699 complete.call( this ); 2700 } 2701 } ); 2702 } 2703 } 2704 2705 function run( next ) { 2706 var elem = $( this ); 2707 2708 function cleanup() { 2709 elem.removeData( dataSpaceAnimated ); 2710 2711 $.effects.cleanUp( elem ); 2712 2713 if ( args.mode === "hide" ) { 2714 elem.hide(); 2715 } 2716 2717 done(); 2718 } 2719 2720 function done() { 2721 if ( typeof complete === "function" ) { 2722 complete.call( elem[ 0 ] ); 2723 } 2724 2725 if ( typeof next === "function" ) { 2726 next(); 2727 } 2728 } 2729 2730 // Override mode option on a per element basis, 2731 // as toggle can be either show or hide depending on element state 2732 args.mode = modes.shift(); 2733 2734 if ( $.uiBackCompat === true && !defaultMode ) { 2735 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { 2736 2737 // Call the core method to track "olddisplay" properly 2738 elem[ mode ](); 2739 done(); 2740 } else { 2741 effectMethod.call( elem[ 0 ], args, done ); 2742 } 2743 } else { 2744 if ( args.mode === "none" ) { 2745 2746 // Call the core method to track "olddisplay" properly 2747 elem[ mode ](); 2748 done(); 2749 } else { 2750 effectMethod.call( elem[ 0 ], args, cleanup ); 2751 } 2752 } 2753 } 2754 2755 // Run prefilter on all elements first to ensure that 2756 // any showing or hiding happens before placeholder creation, 2757 // which ensures that any layout changes are correctly captured. 2758 return queue === false ? 2759 this.each( prefilter ).each( run ) : 2760 this.queue( queueName, prefilter ).queue( queueName, run ); 2761 }, 2762 2763 show: ( function( orig ) { 2764 return function( option ) { 2765 if ( standardAnimationOption( option ) ) { 2766 return orig.apply( this, arguments ); 2767 } else { 2768 var args = _normalizeArguments.apply( this, arguments ); 2769 args.mode = "show"; 2770 return this.effect.call( this, args ); 2771 } 2772 }; 2773 } )( $.fn.show ), 2774 2775 hide: ( function( orig ) { 2776 return function( option ) { 2777 if ( standardAnimationOption( option ) ) { 2778 return orig.apply( this, arguments ); 2779 } else { 2780 var args = _normalizeArguments.apply( this, arguments ); 2781 args.mode = "hide"; 2782 return this.effect.call( this, args ); 2783 } 2784 }; 2785 } )( $.fn.hide ), 2786 2787 toggle: ( function( orig ) { 2788 return function( option ) { 2789 if ( standardAnimationOption( option ) || typeof option === "boolean" ) { 2790 return orig.apply( this, arguments ); 2791 } else { 2792 var args = _normalizeArguments.apply( this, arguments ); 2793 args.mode = "toggle"; 2794 return this.effect.call( this, args ); 2795 } 2796 }; 2797 } )( $.fn.toggle ), 2798 2799 cssUnit: function( key ) { 2800 var style = this.css( key ), 2801 val = []; 2802 2803 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { 2804 if ( style.indexOf( unit ) > 0 ) { 2805 val = [ parseFloat( style ), unit ]; 2806 } 2807 } ); 2808 return val; 2809 }, 2810 2811 cssClip: function( clipObj ) { 2812 if ( clipObj ) { 2813 return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " + 2814 clipObj.bottom + "px " + clipObj.left + "px)" ); 2815 } 2816 return parseClip( this.css( "clip" ), this ); 2817 }, 2818 2819 transfer: function( options, done ) { 2820 var element = $( this ), 2821 target = $( options.to ), 2822 targetFixed = target.css( "position" ) === "fixed", 2823 body = $( "body" ), 2824 fixTop = targetFixed ? body.scrollTop() : 0, 2825 fixLeft = targetFixed ? body.scrollLeft() : 0, 2826 endPosition = target.offset(), 2827 animation = { 2828 top: endPosition.top - fixTop, 2829 left: endPosition.left - fixLeft, 2830 height: target.innerHeight(), 2831 width: target.innerWidth() 2832 }, 2833 startPosition = element.offset(), 2834 transfer = $( "<div class='ui-effects-transfer'></div>" ); 2835 2836 transfer 2837 .appendTo( "body" ) 2838 .addClass( options.className ) 2839 .css( { 2840 top: startPosition.top - fixTop, 2841 left: startPosition.left - fixLeft, 2842 height: element.innerHeight(), 2843 width: element.innerWidth(), 2844 position: targetFixed ? "fixed" : "absolute" 2845 } ) 2846 .animate( animation, options.duration, options.easing, function() { 2847 transfer.remove(); 2848 if ( typeof done === "function" ) { 2849 done(); 2850 } 2851 } ); 2852 } 2853} ); 2854 2855function parseClip( str, element ) { 2856 var outerWidth = element.outerWidth(), 2857 outerHeight = element.outerHeight(), 2858 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)\)$/, 2859 values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ]; 2860 2861 return { 2862 top: parseFloat( values[ 1 ] ) || 0, 2863 right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ), 2864 bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ), 2865 left: parseFloat( values[ 4 ] ) || 0 2866 }; 2867} 2868 2869$.fx.step.clip = function( fx ) { 2870 if ( !fx.clipInit ) { 2871 fx.start = $( fx.elem ).cssClip(); 2872 if ( typeof fx.end === "string" ) { 2873 fx.end = parseClip( fx.end, fx.elem ); 2874 } 2875 fx.clipInit = true; 2876 } 2877 2878 $( fx.elem ).cssClip( { 2879 top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top, 2880 right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right, 2881 bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom, 2882 left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left 2883 } ); 2884}; 2885 2886} )(); 2887 2888/******************************************************************************/ 2889/*********************************** EASING ***********************************/ 2890/******************************************************************************/ 2891 2892( function() { 2893 2894// Based on easing equations from Robert Penner (http://robertpenner.com/easing) 2895 2896var baseEasings = {}; 2897 2898$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { 2899 baseEasings[ name ] = function( p ) { 2900 return Math.pow( p, i + 2 ); 2901 }; 2902} ); 2903 2904$.extend( baseEasings, { 2905 Sine: function( p ) { 2906 return 1 - Math.cos( p * Math.PI / 2 ); 2907 }, 2908 Circ: function( p ) { 2909 return 1 - Math.sqrt( 1 - p * p ); 2910 }, 2911 Elastic: function( p ) { 2912 return p === 0 || p === 1 ? p : 2913 -Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 ); 2914 }, 2915 Back: function( p ) { 2916 return p * p * ( 3 * p - 2 ); 2917 }, 2918 Bounce: function( p ) { 2919 var pow2, 2920 bounce = 4; 2921 2922 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} 2923 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); 2924 } 2925} ); 2926 2927$.each( baseEasings, function( name, easeIn ) { 2928 $.easing[ "easeIn" + name ] = easeIn; 2929 $.easing[ "easeOut" + name ] = function( p ) { 2930 return 1 - easeIn( 1 - p ); 2931 }; 2932 $.easing[ "easeInOut" + name ] = function( p ) { 2933 return p < 0.5 ? 2934 easeIn( p * 2 ) / 2 : 2935 1 - easeIn( p * -2 + 2 ) / 2; 2936 }; 2937} ); 2938 2939} )(); 2940 2941var effect = $.effects; 2942 2943 2944/*! 2945 * jQuery UI Effects Blind 1.14.1 2946 * https://jqueryui.com 2947 * 2948 * Copyright OpenJS Foundation and other contributors 2949 * Released under the MIT license. 2950 * https://jquery.org/license 2951 */ 2952 2953//>>label: Blind Effect 2954//>>group: Effects 2955//>>description: Blinds the element. 2956//>>docs: https://api.jqueryui.com/blind-effect/ 2957//>>demos: https://jqueryui.com/effect/ 2958 2959 2960var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) { 2961 var map = { 2962 up: [ "bottom", "top" ], 2963 vertical: [ "bottom", "top" ], 2964 down: [ "top", "bottom" ], 2965 left: [ "right", "left" ], 2966 horizontal: [ "right", "left" ], 2967 right: [ "left", "right" ] 2968 }, 2969 element = $( this ), 2970 direction = options.direction || "up", 2971 start = element.cssClip(), 2972 animate = { clip: $.extend( {}, start ) }, 2973 placeholder = $.effects.createPlaceholder( element ); 2974 2975 animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ]; 2976 2977 if ( options.mode === "show" ) { 2978 element.cssClip( animate.clip ); 2979 if ( placeholder ) { 2980 placeholder.css( $.effects.clipToBox( animate ) ); 2981 } 2982 2983 animate.clip = start; 2984 } 2985 2986 if ( placeholder ) { 2987 placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing ); 2988 } 2989 2990 element.animate( animate, { 2991 queue: false, 2992 duration: options.duration, 2993 easing: options.easing, 2994 complete: done 2995 } ); 2996} ); 2997 2998 2999/*! 3000 * jQuery UI Effects Bounce 1.14.1 3001 * https://jqueryui.com 3002 * 3003 * Copyright OpenJS Foundation and other contributors 3004 * Released under the MIT license. 3005 * https://jquery.org/license 3006 */ 3007 3008//>>label: Bounce Effect 3009//>>group: Effects 3010//>>description: Bounces an element horizontally or vertically n times. 3011//>>docs: https://api.jqueryui.com/bounce-effect/ 3012//>>demos: https://jqueryui.com/effect/ 3013 3014 3015var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) { 3016 var upAnim, downAnim, refValue, 3017 element = $( this ), 3018 3019 // Defaults: 3020 mode = options.mode, 3021 hide = mode === "hide", 3022 show = mode === "show", 3023 direction = options.direction || "up", 3024 distance = options.distance, 3025 times = options.times || 5, 3026 3027 // Number of internal animations 3028 anims = times * 2 + ( show || hide ? 1 : 0 ), 3029 speed = options.duration / anims, 3030 easing = options.easing, 3031 3032 // Utility: 3033 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 3034 motion = ( direction === "up" || direction === "left" ), 3035 i = 0, 3036 3037 queuelen = element.queue().length; 3038 3039 $.effects.createPlaceholder( element ); 3040 3041 refValue = element.css( ref ); 3042 3043 // Default distance for the BIGGEST bounce is the outer Distance / 3 3044 if ( !distance ) { 3045 distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; 3046 } 3047 3048 if ( show ) { 3049 downAnim = { opacity: 1 }; 3050 downAnim[ ref ] = refValue; 3051 3052 // If we are showing, force opacity 0 and set the initial position 3053 // then do the "first" animation 3054 element 3055 .css( "opacity", 0 ) 3056 .css( ref, motion ? -distance * 2 : distance * 2 ) 3057 .animate( downAnim, speed, easing ); 3058 } 3059 3060 // Start at the smallest distance if we are hiding 3061 if ( hide ) { 3062 distance = distance / Math.pow( 2, times - 1 ); 3063 } 3064 3065 downAnim = {}; 3066 downAnim[ ref ] = refValue; 3067 3068 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here 3069 for ( ; i < times; i++ ) { 3070 upAnim = {}; 3071 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 3072 3073 element 3074 .animate( upAnim, speed, easing ) 3075 .animate( downAnim, speed, easing ); 3076 3077 distance = hide ? distance * 2 : distance / 2; 3078 } 3079 3080 // Last Bounce when Hiding 3081 if ( hide ) { 3082 upAnim = { opacity: 0 }; 3083 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 3084 3085 element.animate( upAnim, speed, easing ); 3086 } 3087 3088 element.queue( done ); 3089 3090 $.effects.unshift( element, queuelen, anims + 1 ); 3091} ); 3092 3093 3094/*! 3095 * jQuery UI Effects Clip 1.14.1 3096 * https://jqueryui.com 3097 * 3098 * Copyright OpenJS Foundation and other contributors 3099 * Released under the MIT license. 3100 * https://jquery.org/license 3101 */ 3102 3103//>>label: Clip Effect 3104//>>group: Effects 3105//>>description: Clips the element on and off like an old TV. 3106//>>docs: https://api.jqueryui.com/clip-effect/ 3107//>>demos: https://jqueryui.com/effect/ 3108 3109 3110var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) { 3111 var start, 3112 animate = {}, 3113 element = $( this ), 3114 direction = options.direction || "vertical", 3115 both = direction === "both", 3116 horizontal = both || direction === "horizontal", 3117 vertical = both || direction === "vertical"; 3118 3119 start = element.cssClip(); 3120 animate.clip = { 3121 top: vertical ? ( start.bottom - start.top ) / 2 : start.top, 3122 right: horizontal ? ( start.right - start.left ) / 2 : start.right, 3123 bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom, 3124 left: horizontal ? ( start.right - start.left ) / 2 : start.left 3125 }; 3126 3127 $.effects.createPlaceholder( element ); 3128 3129 if ( options.mode === "show" ) { 3130 element.cssClip( animate.clip ); 3131 animate.clip = start; 3132 } 3133 3134 element.animate( animate, { 3135 queue: false, 3136 duration: options.duration, 3137 easing: options.easing, 3138 complete: done 3139 } ); 3140 3141} ); 3142 3143 3144/*! 3145 * jQuery UI Effects Drop 1.14.1 3146 * https://jqueryui.com 3147 * 3148 * Copyright OpenJS Foundation and other contributors 3149 * Released under the MIT license. 3150 * https://jquery.org/license 3151 */ 3152 3153//>>label: Drop Effect 3154//>>group: Effects 3155//>>description: Moves an element in one direction and hides it at the same time. 3156//>>docs: https://api.jqueryui.com/drop-effect/ 3157//>>demos: https://jqueryui.com/effect/ 3158 3159 3160var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) { 3161 3162 var distance, 3163 element = $( this ), 3164 mode = options.mode, 3165 show = mode === "show", 3166 direction = options.direction || "left", 3167 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 3168 motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=", 3169 oppositeMotion = ( motion === "+=" ) ? "-=" : "+=", 3170 animation = { 3171 opacity: 0 3172 }; 3173 3174 $.effects.createPlaceholder( element ); 3175 3176 distance = options.distance || 3177 element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2; 3178 3179 animation[ ref ] = motion + distance; 3180 3181 if ( show ) { 3182 element.css( animation ); 3183 3184 animation[ ref ] = oppositeMotion + distance; 3185 animation.opacity = 1; 3186 } 3187 3188 // Animate 3189 element.animate( animation, { 3190 queue: false, 3191 duration: options.duration, 3192 easing: options.easing, 3193 complete: done 3194 } ); 3195} ); 3196 3197 3198/*! 3199 * jQuery UI Effects Explode 1.14.1 3200 * https://jqueryui.com 3201 * 3202 * Copyright OpenJS Foundation and other contributors 3203 * Released under the MIT license. 3204 * https://jquery.org/license 3205 */ 3206 3207//>>label: Explode Effect 3208//>>group: Effects 3209/* eslint-disable max-len */ 3210//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness. 3211/* eslint-enable max-len */ 3212//>>docs: https://api.jqueryui.com/explode-effect/ 3213//>>demos: https://jqueryui.com/effect/ 3214 3215 3216var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) { 3217 3218 var i, j, left, top, mx, my, 3219 rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3, 3220 cells = rows, 3221 element = $( this ), 3222 mode = options.mode, 3223 show = mode === "show", 3224 3225 // Show and then visibility:hidden the element before calculating offset 3226 offset = element.show().css( "visibility", "hidden" ).offset(), 3227 3228 // Width and height of a piece 3229 width = Math.ceil( element.outerWidth() / cells ), 3230 height = Math.ceil( element.outerHeight() / rows ), 3231 pieces = []; 3232 3233 // Children animate complete: 3234 function childComplete() { 3235 pieces.push( this ); 3236 if ( pieces.length === rows * cells ) { 3237 animComplete(); 3238 } 3239 } 3240 3241 // Clone the element for each row and cell. 3242 for ( i = 0; i < rows; i++ ) { // ===> 3243 top = offset.top + i * height; 3244 my = i - ( rows - 1 ) / 2; 3245 3246 for ( j = 0; j < cells; j++ ) { // ||| 3247 left = offset.left + j * width; 3248 mx = j - ( cells - 1 ) / 2; 3249 3250 // Create a clone of the now hidden main element that will be absolute positioned 3251 // within a wrapper div off the -left and -top equal to size of our pieces 3252 element 3253 .clone() 3254 .appendTo( "body" ) 3255 .wrap( "<div></div>" ) 3256 .css( { 3257 position: "absolute", 3258 visibility: "visible", 3259 left: -j * width, 3260 top: -i * height 3261 } ) 3262 3263 // Select the wrapper - make it overflow: hidden and absolute positioned based on 3264 // where the original was located +left and +top equal to the size of pieces 3265 .parent() 3266 .addClass( "ui-effects-explode" ) 3267 .css( { 3268 position: "absolute", 3269 overflow: "hidden", 3270 width: width, 3271 height: height, 3272 left: left + ( show ? mx * width : 0 ), 3273 top: top + ( show ? my * height : 0 ), 3274 opacity: show ? 0 : 1 3275 } ) 3276 .animate( { 3277 left: left + ( show ? 0 : mx * width ), 3278 top: top + ( show ? 0 : my * height ), 3279 opacity: show ? 1 : 0 3280 }, options.duration || 500, options.easing, childComplete ); 3281 } 3282 } 3283 3284 function animComplete() { 3285 element.css( { 3286 visibility: "visible" 3287 } ); 3288 $( pieces ).remove(); 3289 done(); 3290 } 3291} ); 3292 3293 3294/*! 3295 * jQuery UI Effects Fade 1.14.1 3296 * https://jqueryui.com 3297 * 3298 * Copyright OpenJS Foundation and other contributors 3299 * Released under the MIT license. 3300 * https://jquery.org/license 3301 */ 3302 3303//>>label: Fade Effect 3304//>>group: Effects 3305//>>description: Fades the element. 3306//>>docs: https://api.jqueryui.com/fade-effect/ 3307//>>demos: https://jqueryui.com/effect/ 3308 3309 3310var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) { 3311 var show = options.mode === "show"; 3312 3313 $( this ) 3314 .css( "opacity", show ? 0 : 1 ) 3315 .animate( { 3316 opacity: show ? 1 : 0 3317 }, { 3318 queue: false, 3319 duration: options.duration, 3320 easing: options.easing, 3321 complete: done 3322 } ); 3323} ); 3324 3325 3326/*! 3327 * jQuery UI Effects Fold 1.14.1 3328 * https://jqueryui.com 3329 * 3330 * Copyright OpenJS Foundation and other contributors 3331 * Released under the MIT license. 3332 * https://jquery.org/license 3333 */ 3334 3335//>>label: Fold Effect 3336//>>group: Effects 3337//>>description: Folds an element first horizontally and then vertically. 3338//>>docs: https://api.jqueryui.com/fold-effect/ 3339//>>demos: https://jqueryui.com/effect/ 3340 3341 3342var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) { 3343 3344 // Create element 3345 var element = $( this ), 3346 mode = options.mode, 3347 show = mode === "show", 3348 hide = mode === "hide", 3349 size = options.size || 15, 3350 percent = /([0-9]+)%/.exec( size ), 3351 horizFirst = !!options.horizFirst, 3352 ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ], 3353 duration = options.duration / 2, 3354 3355 placeholder = $.effects.createPlaceholder( element ), 3356 3357 start = element.cssClip(), 3358 animation1 = { clip: $.extend( {}, start ) }, 3359 animation2 = { clip: $.extend( {}, start ) }, 3360 3361 distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ], 3362 3363 queuelen = element.queue().length; 3364 3365 if ( percent ) { 3366 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; 3367 } 3368 animation1.clip[ ref[ 0 ] ] = size; 3369 animation2.clip[ ref[ 0 ] ] = size; 3370 animation2.clip[ ref[ 1 ] ] = 0; 3371 3372 if ( show ) { 3373 element.cssClip( animation2.clip ); 3374 if ( placeholder ) { 3375 placeholder.css( $.effects.clipToBox( animation2 ) ); 3376 } 3377 3378 animation2.clip = start; 3379 } 3380 3381 // Animate 3382 element 3383 .queue( function( next ) { 3384 if ( placeholder ) { 3385 placeholder 3386 .animate( $.effects.clipToBox( animation1 ), duration, options.easing ) 3387 .animate( $.effects.clipToBox( animation2 ), duration, options.easing ); 3388 } 3389 3390 next(); 3391 } ) 3392 .animate( animation1, duration, options.easing ) 3393 .animate( animation2, duration, options.easing ) 3394 .queue( done ); 3395 3396 $.effects.unshift( element, queuelen, 4 ); 3397} ); 3398 3399 3400/*! 3401 * jQuery UI Effects Highlight 1.14.1 3402 * https://jqueryui.com 3403 * 3404 * Copyright OpenJS Foundation and other contributors 3405 * Released under the MIT license. 3406 * https://jquery.org/license 3407 */ 3408 3409//>>label: Highlight Effect 3410//>>group: Effects 3411//>>description: Highlights the background of an element in a defined color for a custom duration. 3412//>>docs: https://api.jqueryui.com/highlight-effect/ 3413//>>demos: https://jqueryui.com/effect/ 3414 3415 3416var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) { 3417 var element = $( this ), 3418 animation = { 3419 backgroundColor: element.css( "backgroundColor" ) 3420 }; 3421 3422 if ( options.mode === "hide" ) { 3423 animation.opacity = 0; 3424 } 3425 3426 $.effects.saveStyle( element ); 3427 3428 element 3429 .css( { 3430 backgroundImage: "none", 3431 backgroundColor: options.color || "#ffff99" 3432 } ) 3433 .animate( animation, { 3434 queue: false, 3435 duration: options.duration, 3436 easing: options.easing, 3437 complete: done 3438 } ); 3439} ); 3440 3441 3442/*! 3443 * jQuery UI Effects Size 1.14.1 3444 * https://jqueryui.com 3445 * 3446 * Copyright OpenJS Foundation and other contributors 3447 * Released under the MIT license. 3448 * https://jquery.org/license 3449 */ 3450 3451//>>label: Size Effect 3452//>>group: Effects 3453//>>description: Resize an element to a specified width and height. 3454//>>docs: https://api.jqueryui.com/size-effect/ 3455//>>demos: https://jqueryui.com/effect/ 3456 3457 3458var effectsEffectSize = $.effects.define( "size", function( options, done ) { 3459 3460 // Create element 3461 var baseline, factor, temp, 3462 element = $( this ), 3463 3464 // Copy for children 3465 cProps = [ "fontSize" ], 3466 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], 3467 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], 3468 3469 // Set options 3470 mode = options.mode, 3471 restore = mode !== "effect", 3472 scale = options.scale || "both", 3473 origin = options.origin || [ "middle", "center" ], 3474 position = element.css( "position" ), 3475 pos = element.position(), 3476 original = $.effects.scaledDimensions( element ), 3477 from = options.from || original, 3478 to = options.to || $.effects.scaledDimensions( element, 0 ); 3479 3480 $.effects.createPlaceholder( element ); 3481 3482 if ( mode === "show" ) { 3483 temp = from; 3484 from = to; 3485 to = temp; 3486 } 3487 3488 // Set scaling factor 3489 factor = { 3490 from: { 3491 y: from.height / original.height, 3492 x: from.width / original.width 3493 }, 3494 to: { 3495 y: to.height / original.height, 3496 x: to.width / original.width 3497 } 3498 }; 3499 3500 // Scale the css box 3501 if ( scale === "box" || scale === "both" ) { 3502 3503 // Vertical props scaling 3504 if ( factor.from.y !== factor.to.y ) { 3505 from = $.effects.setTransition( element, vProps, factor.from.y, from ); 3506 to = $.effects.setTransition( element, vProps, factor.to.y, to ); 3507 } 3508 3509 // Horizontal props scaling 3510 if ( factor.from.x !== factor.to.x ) { 3511 from = $.effects.setTransition( element, hProps, factor.from.x, from ); 3512 to = $.effects.setTransition( element, hProps, factor.to.x, to ); 3513 } 3514 } 3515 3516 // Scale the content 3517 if ( scale === "content" || scale === "both" ) { 3518 3519 // Vertical props scaling 3520 if ( factor.from.y !== factor.to.y ) { 3521 from = $.effects.setTransition( element, cProps, factor.from.y, from ); 3522 to = $.effects.setTransition( element, cProps, factor.to.y, to ); 3523 } 3524 } 3525 3526 // Adjust the position properties based on the provided origin points 3527 if ( origin ) { 3528 baseline = $.effects.getBaseline( origin, original ); 3529 from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top; 3530 from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left; 3531 to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top; 3532 to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left; 3533 } 3534 delete from.outerHeight; 3535 delete from.outerWidth; 3536 element.css( from ); 3537 3538 // Animate the children if desired 3539 if ( scale === "content" || scale === "both" ) { 3540 3541 vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps ); 3542 hProps = hProps.concat( [ "marginLeft", "marginRight" ] ); 3543 3544 // Only animate children with width attributes specified 3545 // TODO: is this right? should we include anything with css width specified as well 3546 element.find( "*[width]" ).each( function() { 3547 var child = $( this ), 3548 childOriginal = $.effects.scaledDimensions( child ), 3549 childFrom = { 3550 height: childOriginal.height * factor.from.y, 3551 width: childOriginal.width * factor.from.x, 3552 outerHeight: childOriginal.outerHeight * factor.from.y, 3553 outerWidth: childOriginal.outerWidth * factor.from.x 3554 }, 3555 childTo = { 3556 height: childOriginal.height * factor.to.y, 3557 width: childOriginal.width * factor.to.x, 3558 outerHeight: childOriginal.height * factor.to.y, 3559 outerWidth: childOriginal.width * factor.to.x 3560 }; 3561 3562 // Vertical props scaling 3563 if ( factor.from.y !== factor.to.y ) { 3564 childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom ); 3565 childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo ); 3566 } 3567 3568 // Horizontal props scaling 3569 if ( factor.from.x !== factor.to.x ) { 3570 childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom ); 3571 childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo ); 3572 } 3573 3574 if ( restore ) { 3575 $.effects.saveStyle( child ); 3576 } 3577 3578 // Animate children 3579 child.css( childFrom ); 3580 child.animate( childTo, options.duration, options.easing, function() { 3581 3582 // Restore children 3583 if ( restore ) { 3584 $.effects.restoreStyle( child ); 3585 } 3586 } ); 3587 } ); 3588 } 3589 3590 // Animate 3591 element.animate( to, { 3592 queue: false, 3593 duration: options.duration, 3594 easing: options.easing, 3595 complete: function() { 3596 3597 var offset = element.offset(); 3598 3599 if ( to.opacity === 0 ) { 3600 element.css( "opacity", from.opacity ); 3601 } 3602 3603 if ( !restore ) { 3604 element 3605 .css( "position", position === "static" ? "relative" : position ) 3606 .offset( offset ); 3607 3608 // Need to save style here so that automatic style restoration 3609 // doesn't restore to the original styles from before the animation. 3610 $.effects.saveStyle( element ); 3611 } 3612 3613 done(); 3614 } 3615 } ); 3616 3617} ); 3618 3619 3620/*! 3621 * jQuery UI Effects Scale 1.14.1 3622 * https://jqueryui.com 3623 * 3624 * Copyright OpenJS Foundation and other contributors 3625 * Released under the MIT license. 3626 * https://jquery.org/license 3627 */ 3628 3629//>>label: Scale Effect 3630//>>group: Effects 3631//>>description: Grows or shrinks an element and its content. 3632//>>docs: https://api.jqueryui.com/scale-effect/ 3633//>>demos: https://jqueryui.com/effect/ 3634 3635 3636var effectsEffectScale = $.effects.define( "scale", function( options, done ) { 3637 3638 // Create element 3639 var el = $( this ), 3640 mode = options.mode, 3641 percent = parseInt( options.percent, 10 ) || 3642 ( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ), 3643 3644 newOptions = $.extend( true, { 3645 from: $.effects.scaledDimensions( el ), 3646 to: $.effects.scaledDimensions( el, percent, options.direction || "both" ), 3647 origin: options.origin || [ "middle", "center" ] 3648 }, options ); 3649 3650 // Fade option to support puff 3651 if ( options.fade ) { 3652 newOptions.from.opacity = 1; 3653 newOptions.to.opacity = 0; 3654 } 3655 3656 $.effects.effect.size.call( this, newOptions, done ); 3657} ); 3658 3659 3660/*! 3661 * jQuery UI Effects Puff 1.14.1 3662 * https://jqueryui.com 3663 * 3664 * Copyright OpenJS Foundation and other contributors 3665 * Released under the MIT license. 3666 * https://jquery.org/license 3667 */ 3668 3669//>>label: Puff Effect 3670//>>group: Effects 3671//>>description: Creates a puff effect by scaling the element up and hiding it at the same time. 3672//>>docs: https://api.jqueryui.com/puff-effect/ 3673//>>demos: https://jqueryui.com/effect/ 3674 3675 3676var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) { 3677 var newOptions = $.extend( true, {}, options, { 3678 fade: true, 3679 percent: parseInt( options.percent, 10 ) || 150 3680 } ); 3681 3682 $.effects.effect.scale.call( this, newOptions, done ); 3683} ); 3684 3685 3686/*! 3687 * jQuery UI Effects Pulsate 1.14.1 3688 * https://jqueryui.com 3689 * 3690 * Copyright OpenJS Foundation and other contributors 3691 * Released under the MIT license. 3692 * https://jquery.org/license 3693 */ 3694 3695//>>label: Pulsate Effect 3696//>>group: Effects 3697//>>description: Pulsates an element n times by changing the opacity to zero and back. 3698//>>docs: https://api.jqueryui.com/pulsate-effect/ 3699//>>demos: https://jqueryui.com/effect/ 3700 3701 3702var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) { 3703 var element = $( this ), 3704 mode = options.mode, 3705 show = mode === "show", 3706 hide = mode === "hide", 3707 showhide = show || hide, 3708 3709 // Showing or hiding leaves off the "last" animation 3710 anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), 3711 duration = options.duration / anims, 3712 animateTo = 0, 3713 i = 1, 3714 queuelen = element.queue().length; 3715 3716 if ( show || !element.is( ":visible" ) ) { 3717 element.css( "opacity", 0 ).show(); 3718 animateTo = 1; 3719 } 3720 3721 // Anims - 1 opacity "toggles" 3722 for ( ; i < anims; i++ ) { 3723 element.animate( { opacity: animateTo }, duration, options.easing ); 3724 animateTo = 1 - animateTo; 3725 } 3726 3727 element.animate( { opacity: animateTo }, duration, options.easing ); 3728 3729 element.queue( done ); 3730 3731 $.effects.unshift( element, queuelen, anims + 1 ); 3732} ); 3733 3734 3735/*! 3736 * jQuery UI Effects Shake 1.14.1 3737 * https://jqueryui.com 3738 * 3739 * Copyright OpenJS Foundation and other contributors 3740 * Released under the MIT license. 3741 * https://jquery.org/license 3742 */ 3743 3744//>>label: Shake Effect 3745//>>group: Effects 3746//>>description: Shakes an element horizontally or vertically n times. 3747//>>docs: https://api.jqueryui.com/shake-effect/ 3748//>>demos: https://jqueryui.com/effect/ 3749 3750 3751var effectsEffectShake = $.effects.define( "shake", function( options, done ) { 3752 3753 var i = 1, 3754 element = $( this ), 3755 direction = options.direction || "left", 3756 distance = options.distance || 20, 3757 times = options.times || 3, 3758 anims = times * 2 + 1, 3759 speed = Math.round( options.duration / anims ), 3760 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 3761 positiveMotion = ( direction === "up" || direction === "left" ), 3762 animation = {}, 3763 animation1 = {}, 3764 animation2 = {}, 3765 3766 queuelen = element.queue().length; 3767 3768 $.effects.createPlaceholder( element ); 3769 3770 // Animation 3771 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; 3772 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; 3773 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; 3774 3775 // Animate 3776 element.animate( animation, speed, options.easing ); 3777 3778 // Shakes 3779 for ( ; i < times; i++ ) { 3780 element 3781 .animate( animation1, speed, options.easing ) 3782 .animate( animation2, speed, options.easing ); 3783 } 3784 3785 element 3786 .animate( animation1, speed, options.easing ) 3787 .animate( animation, speed / 2, options.easing ) 3788 .queue( done ); 3789 3790 $.effects.unshift( element, queuelen, anims + 1 ); 3791} ); 3792 3793 3794/*! 3795 * jQuery UI Effects Slide 1.14.1 3796 * https://jqueryui.com 3797 * 3798 * Copyright OpenJS Foundation and other contributors 3799 * Released under the MIT license. 3800 * https://jquery.org/license 3801 */ 3802 3803//>>label: Slide Effect 3804//>>group: Effects 3805//>>description: Slides an element in and out of the viewport. 3806//>>docs: https://api.jqueryui.com/slide-effect/ 3807//>>demos: https://jqueryui.com/effect/ 3808 3809 3810var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) { 3811 var startClip, startRef, 3812 element = $( this ), 3813 map = { 3814 up: [ "bottom", "top" ], 3815 down: [ "top", "bottom" ], 3816 left: [ "right", "left" ], 3817 right: [ "left", "right" ] 3818 }, 3819 mode = options.mode, 3820 direction = options.direction || "left", 3821 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 3822 positiveMotion = ( direction === "up" || direction === "left" ), 3823 distance = options.distance || 3824 element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ), 3825 animation = {}; 3826 3827 $.effects.createPlaceholder( element ); 3828 3829 startClip = element.cssClip(); 3830 startRef = element.position()[ ref ]; 3831 3832 // Define hide animation 3833 animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef; 3834 animation.clip = element.cssClip(); 3835 animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ]; 3836 3837 // Reverse the animation if we're showing 3838 if ( mode === "show" ) { 3839 element.cssClip( animation.clip ); 3840 element.css( ref, animation[ ref ] ); 3841 animation.clip = startClip; 3842 animation[ ref ] = startRef; 3843 } 3844 3845 // Actually animate 3846 element.animate( animation, { 3847 queue: false, 3848 duration: options.duration, 3849 easing: options.easing, 3850 complete: done 3851 } ); 3852} ); 3853 3854 3855/*! 3856 * jQuery UI Effects Transfer 1.14.1 3857 * https://jqueryui.com 3858 * 3859 * Copyright OpenJS Foundation and other contributors 3860 * Released under the MIT license. 3861 * https://jquery.org/license 3862 */ 3863 3864//>>label: Transfer Effect 3865//>>group: Effects 3866//>>description: Displays a transfer effect from one element to another. 3867//>>docs: https://api.jqueryui.com/transfer-effect/ 3868//>>demos: https://jqueryui.com/effect/ 3869 3870 3871var effect; 3872if ( $.uiBackCompat === true ) { 3873 effect = $.effects.define( "transfer", function( options, done ) { 3874 $( this ).transfer( options, done ); 3875 } ); 3876} 3877var effectsEffectTransfer = effect; 3878 3879 3880/*! 3881 * jQuery UI Focusable 1.14.1 3882 * https://jqueryui.com 3883 * 3884 * Copyright OpenJS Foundation and other contributors 3885 * Released under the MIT license. 3886 * https://jquery.org/license 3887 */ 3888 3889//>>label: :focusable Selector 3890//>>group: Core 3891//>>description: Selects elements which can be focused. 3892//>>docs: https://api.jqueryui.com/focusable-selector/ 3893 3894 3895// Selectors 3896$.ui.focusable = function( element, hasTabindex ) { 3897 var map, mapName, img, focusableIfVisible, fieldset, 3898 nodeName = element.nodeName.toLowerCase(); 3899 3900 if ( "area" === nodeName ) { 3901 map = element.parentNode; 3902 mapName = map.name; 3903 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { 3904 return false; 3905 } 3906 img = $( "img[usemap='#" + mapName + "']" ); 3907 return img.length > 0 && img.is( ":visible" ); 3908 } 3909 3910 if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) { 3911 focusableIfVisible = !element.disabled; 3912 3913 if ( focusableIfVisible ) { 3914 3915 // Form controls within a disabled fieldset are disabled. 3916 // However, controls within the fieldset's legend do not get disabled. 3917 // Since controls generally aren't placed inside legends, we skip 3918 // this portion of the check. 3919 fieldset = $( element ).closest( "fieldset" )[ 0 ]; 3920 if ( fieldset ) { 3921 focusableIfVisible = !fieldset.disabled; 3922 } 3923 } 3924 } else if ( "a" === nodeName ) { 3925 focusableIfVisible = element.href || hasTabindex; 3926 } else { 3927 focusableIfVisible = hasTabindex; 3928 } 3929 3930 return focusableIfVisible && $( element ).is( ":visible" ) && 3931 $( element ).css( "visibility" ) === "visible"; 3932}; 3933 3934$.extend( $.expr.pseudos, { 3935 focusable: function( element ) { 3936 return $.ui.focusable( element, $.attr( element, "tabindex" ) != null ); 3937 } 3938} ); 3939 3940var focusable = $.ui.focusable; 3941 3942 3943/*! 3944 * jQuery UI Form Reset Mixin 1.14.1 3945 * https://jqueryui.com 3946 * 3947 * Copyright OpenJS Foundation and other contributors 3948 * Released under the MIT license. 3949 * https://jquery.org/license 3950 */ 3951 3952//>>label: Form Reset Mixin 3953//>>group: Core 3954//>>description: Refresh input widgets when their form is reset 3955//>>docs: https://api.jqueryui.com/form-reset-mixin/ 3956 3957 3958var formResetMixin = $.ui.formResetMixin = { 3959 _formResetHandler: function() { 3960 var form = $( this ); 3961 3962 // Wait for the form reset to actually happen before refreshing 3963 setTimeout( function() { 3964 var instances = form.data( "ui-form-reset-instances" ); 3965 $.each( instances, function() { 3966 this.refresh(); 3967 } ); 3968 } ); 3969 }, 3970 3971 _bindFormResetHandler: function() { 3972 this.form = $( this.element.prop( "form" ) ); 3973 if ( !this.form.length ) { 3974 return; 3975 } 3976 3977 var instances = this.form.data( "ui-form-reset-instances" ) || []; 3978 if ( !instances.length ) { 3979 3980 // We don't use _on() here because we use a single event handler per form 3981 this.form.on( "reset.ui-form-reset", this._formResetHandler ); 3982 } 3983 instances.push( this ); 3984 this.form.data( "ui-form-reset-instances", instances ); 3985 }, 3986 3987 _unbindFormResetHandler: function() { 3988 if ( !this.form.length ) { 3989 return; 3990 } 3991 3992 var instances = this.form.data( "ui-form-reset-instances" ); 3993 instances.splice( $.inArray( this, instances ), 1 ); 3994 if ( instances.length ) { 3995 this.form.data( "ui-form-reset-instances", instances ); 3996 } else { 3997 this.form 3998 .removeData( "ui-form-reset-instances" ) 3999 .off( "reset.ui-form-reset" ); 4000 } 4001 } 4002}; 4003 4004 4005/*! 4006 * jQuery UI Legacy jQuery Core patches 1.14.1 4007 * https://jqueryui.com 4008 * 4009 * Copyright OpenJS Foundation and other contributors 4010 * Released under the MIT license. 4011 * https://jquery.org/license 4012 * 4013 */ 4014 4015//>>label: Legacy jQuery Core patches 4016//>>group: Core 4017//>>description: Backport `.even()`, `.odd()` and `$.escapeSelector` to older jQuery Core versions (deprecated) 4018 4019 4020// Support: jQuery 2.2.x or older. 4021// This method has been defined in jQuery 3.0.0. 4022// Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js 4023if ( !$.escapeSelector ) { 4024 $.escapeSelector = function( id ) { 4025 return CSS.escape( id + "" ); 4026 }; 4027} 4028 4029// Support: jQuery 3.4.x or older 4030// These methods have been defined in jQuery 3.5.0. 4031if ( !$.fn.even || !$.fn.odd ) { 4032 $.fn.extend( { 4033 even: function() { 4034 return this.filter( function( i ) { 4035 return i % 2 === 0; 4036 } ); 4037 }, 4038 odd: function() { 4039 return this.filter( function( i ) { 4040 return i % 2 === 1; 4041 } ); 4042 } 4043 } ); 4044} 4045 4046; 4047/*! 4048 * jQuery UI Keycode 1.14.1 4049 * https://jqueryui.com 4050 * 4051 * Copyright OpenJS Foundation and other contributors 4052 * Released under the MIT license. 4053 * https://jquery.org/license 4054 */ 4055 4056//>>label: Keycode 4057//>>group: Core 4058//>>description: Provide keycodes as keynames 4059//>>docs: https://api.jqueryui.com/jQuery.ui.keyCode/ 4060 4061 4062var keycode = $.ui.keyCode = { 4063 BACKSPACE: 8, 4064 COMMA: 188, 4065 DELETE: 46, 4066 DOWN: 40, 4067 END: 35, 4068 ENTER: 13, 4069 ESCAPE: 27, 4070 HOME: 36, 4071 LEFT: 37, 4072 PAGE_DOWN: 34, 4073 PAGE_UP: 33, 4074 PERIOD: 190, 4075 RIGHT: 39, 4076 SPACE: 32, 4077 TAB: 9, 4078 UP: 38 4079}; 4080 4081 4082/*! 4083 * jQuery UI Labels 1.14.1 4084 * https://jqueryui.com 4085 * 4086 * Copyright OpenJS Foundation and other contributors 4087 * Released under the MIT license. 4088 * https://jquery.org/license 4089 */ 4090 4091//>>label: labels 4092//>>group: Core 4093//>>description: Find all the labels associated with a given input 4094//>>docs: https://api.jqueryui.com/labels/ 4095 4096 4097var labels = $.fn.labels = function() { 4098 var ancestor, selector, id, labels, ancestors; 4099 4100 if ( !this.length ) { 4101 return this.pushStack( [] ); 4102 } 4103 4104 // Check control.labels first 4105 if ( this[ 0 ].labels && this[ 0 ].labels.length ) { 4106 return this.pushStack( this[ 0 ].labels ); 4107 } 4108 4109 // If `control.labels` is empty - e.g. inside of document fragments - find 4110 // the labels manually 4111 labels = this.eq( 0 ).parents( "label" ); 4112 4113 // Look for the label based on the id 4114 id = this.attr( "id" ); 4115 if ( id ) { 4116 4117 // We don't search against the document in case the element 4118 // is disconnected from the DOM 4119 ancestor = this.eq( 0 ).parents().last(); 4120 4121 // Get a full set of top level ancestors 4122 ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() ); 4123 4124 // Create a selector for the label based on the id 4125 selector = "label[for='" + CSS.escape( id ) + "']"; 4126 4127 labels = labels.add( ancestors.find( selector ).addBack( selector ) ); 4128 4129 } 4130 4131 // Return whatever we have found for labels 4132 return this.pushStack( labels ); 4133}; 4134 4135 4136/*! 4137 * jQuery UI Scroll Parent 1.14.1 4138 * https://jqueryui.com 4139 * 4140 * Copyright OpenJS Foundation and other contributors 4141 * Released under the MIT license. 4142 * https://jquery.org/license 4143 */ 4144 4145//>>label: scrollParent 4146//>>group: Core 4147//>>description: Get the closest ancestor element that is scrollable. 4148//>>docs: https://api.jqueryui.com/scrollParent/ 4149 4150 4151var scrollParent = $.fn.scrollParent = function( includeHidden ) { 4152 var position = this.css( "position" ), 4153 excludeStaticParent = position === "absolute", 4154 overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/, 4155 scrollParent = this.parents().filter( function() { 4156 var parent = $( this ); 4157 if ( excludeStaticParent && parent.css( "position" ) === "static" ) { 4158 return false; 4159 } 4160 return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + 4161 parent.css( "overflow-x" ) ); 4162 } ).eq( 0 ); 4163 4164 return position === "fixed" || !scrollParent.length ? 4165 $( this[ 0 ].ownerDocument || document ) : 4166 scrollParent; 4167}; 4168 4169 4170/*! 4171 * jQuery UI Tabbable 1.14.1 4172 * https://jqueryui.com 4173 * 4174 * Copyright OpenJS Foundation and other contributors 4175 * Released under the MIT license. 4176 * https://jquery.org/license 4177 */ 4178 4179//>>label: :tabbable Selector 4180//>>group: Core 4181//>>description: Selects elements which can be tabbed to. 4182//>>docs: https://api.jqueryui.com/tabbable-selector/ 4183 4184 4185var tabbable = $.extend( $.expr.pseudos, { 4186 tabbable: function( element ) { 4187 var tabIndex = $.attr( element, "tabindex" ), 4188 hasTabindex = tabIndex != null; 4189 return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex ); 4190 } 4191} ); 4192 4193 4194/*! 4195 * jQuery UI Unique ID 1.14.1 4196 * https://jqueryui.com 4197 * 4198 * Copyright OpenJS Foundation and other contributors 4199 * Released under the MIT license. 4200 * https://jquery.org/license 4201 */ 4202 4203//>>label: uniqueId 4204//>>group: Core 4205//>>description: Functions to generate and remove uniqueId's 4206//>>docs: https://api.jqueryui.com/uniqueId/ 4207 4208 4209var uniqueId = $.fn.extend( { 4210 uniqueId: ( function() { 4211 var uuid = 0; 4212 4213 return function() { 4214 return this.each( function() { 4215 if ( !this.id ) { 4216 this.id = "ui-id-" + ( ++uuid ); 4217 } 4218 } ); 4219 }; 4220 } )(), 4221 4222 removeUniqueId: function() { 4223 return this.each( function() { 4224 if ( /^ui-id-\d+$/.test( this.id ) ) { 4225 $( this ).removeAttr( "id" ); 4226 } 4227 } ); 4228 } 4229} ); 4230 4231 4232/*! 4233 * jQuery UI Accordion 1.14.1 4234 * https://jqueryui.com 4235 * 4236 * Copyright OpenJS Foundation and other contributors 4237 * Released under the MIT license. 4238 * https://jquery.org/license 4239 */ 4240 4241//>>label: Accordion 4242//>>group: Widgets 4243/* eslint-disable max-len */ 4244//>>description: Displays collapsible content panels for presenting information in a limited amount of space. 4245/* eslint-enable max-len */ 4246//>>docs: https://api.jqueryui.com/accordion/ 4247//>>demos: https://jqueryui.com/accordion/ 4248//>>css.structure: ../../themes/base/core.css 4249//>>css.structure: ../../themes/base/accordion.css 4250//>>css.theme: ../../themes/base/theme.css 4251 4252 4253var widgetsAccordion = $.widget( "ui.accordion", { 4254 version: "1.14.1", 4255 options: { 4256 active: 0, 4257 animate: {}, 4258 classes: { 4259 "ui-accordion-header": "ui-corner-top", 4260 "ui-accordion-header-collapsed": "ui-corner-all", 4261 "ui-accordion-content": "ui-corner-bottom" 4262 }, 4263 collapsible: false, 4264 event: "click", 4265 header: function( elem ) { 4266 return elem 4267 .find( "> li > :first-child" ) 4268 .add( 4269 elem.find( "> :not(li)" ) 4270 4271 // Support: jQuery <3.5 only 4272 // We could use `.even()` but that's unavailable in older jQuery. 4273 .filter( function( i ) { 4274 return i % 2 === 0; 4275 } ) 4276 ); 4277 }, 4278 heightStyle: "auto", 4279 icons: { 4280 activeHeader: "ui-icon-triangle-1-s", 4281 header: "ui-icon-triangle-1-e" 4282 }, 4283 4284 // Callbacks 4285 activate: null, 4286 beforeActivate: null 4287 }, 4288 4289 hideProps: { 4290 borderTopWidth: "hide", 4291 borderBottomWidth: "hide", 4292 paddingTop: "hide", 4293 paddingBottom: "hide", 4294 height: "hide" 4295 }, 4296 4297 showProps: { 4298 borderTopWidth: "show", 4299 borderBottomWidth: "show", 4300 paddingTop: "show", 4301 paddingBottom: "show", 4302 height: "show" 4303 }, 4304 4305 _create: function() { 4306 var options = this.options; 4307 4308 this.prevShow = this.prevHide = $(); 4309 this._addClass( "ui-accordion", "ui-widget ui-helper-reset" ); 4310 this.element.attr( "role", "tablist" ); 4311 4312 // Don't allow collapsible: false and active: false / null 4313 if ( !options.collapsible && ( options.active === false || options.active == null ) ) { 4314 options.active = 0; 4315 } 4316 4317 this._processPanels(); 4318 4319 // handle negative values 4320 if ( options.active < 0 ) { 4321 options.active += this.headers.length; 4322 } 4323 this._refresh(); 4324 }, 4325 4326 _getCreateEventData: function() { 4327 return { 4328 header: this.active, 4329 panel: !this.active.length ? $() : this.active.next() 4330 }; 4331 }, 4332 4333 _createIcons: function() { 4334 var icon, children, 4335 icons = this.options.icons; 4336 4337 if ( icons ) { 4338 icon = $( "<span>" ); 4339 this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header ); 4340 icon.prependTo( this.headers ); 4341 children = this.active.children( ".ui-accordion-header-icon" ); 4342 this._removeClass( children, icons.header ) 4343 ._addClass( children, null, icons.activeHeader ) 4344 ._addClass( this.headers, "ui-accordion-icons" ); 4345 } 4346 }, 4347 4348 _destroyIcons: function() { 4349 this._removeClass( this.headers, "ui-accordion-icons" ); 4350 this.headers.children( ".ui-accordion-header-icon" ).remove(); 4351 }, 4352 4353 _destroy: function() { 4354 var contents; 4355 4356 // Clean up main element 4357 this.element.removeAttr( "role" ); 4358 4359 // Clean up headers 4360 this.headers 4361 .removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" ) 4362 .removeUniqueId(); 4363 4364 this._destroyIcons(); 4365 4366 // Clean up content panels 4367 contents = this.headers.next() 4368 .css( "display", "" ) 4369 .removeAttr( "role aria-hidden aria-labelledby" ) 4370 .removeUniqueId(); 4371 4372 if ( this.options.heightStyle !== "content" ) { 4373 contents.css( "height", "" ); 4374 } 4375 }, 4376 4377 _setOption: function( key, value ) { 4378 if ( key === "active" ) { 4379 4380 // _activate() will handle invalid values and update this.options 4381 this._activate( value ); 4382 return; 4383 } 4384 4385 if ( key === "event" ) { 4386 if ( this.options.event ) { 4387 this._off( this.headers, this.options.event ); 4388 } 4389 this._setupEvents( value ); 4390 } 4391 4392 this._super( key, value ); 4393 4394 // Setting collapsible: false while collapsed; open first panel 4395 if ( key === "collapsible" && !value && this.options.active === false ) { 4396 this._activate( 0 ); 4397 } 4398 4399 if ( key === "icons" ) { 4400 this._destroyIcons(); 4401 if ( value ) { 4402 this._createIcons(); 4403 } 4404 } 4405 }, 4406 4407 _setOptionDisabled: function( value ) { 4408 this._super( value ); 4409 4410 this.element.attr( "aria-disabled", value ); 4411 this._toggleClass( null, "ui-state-disabled", !!value ); 4412 }, 4413 4414 _keydown: function( event ) { 4415 if ( event.altKey || event.ctrlKey ) { 4416 return; 4417 } 4418 4419 var keyCode = $.ui.keyCode, 4420 length = this.headers.length, 4421 currentIndex = this.headers.index( event.target ), 4422 toFocus = false; 4423 4424 switch ( event.keyCode ) { 4425 case keyCode.RIGHT: 4426 case keyCode.DOWN: 4427 toFocus = this.headers[ ( currentIndex + 1 ) % length ]; 4428 break; 4429 case keyCode.LEFT: 4430 case keyCode.UP: 4431 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; 4432 break; 4433 case keyCode.SPACE: 4434 case keyCode.ENTER: 4435 this._eventHandler( event ); 4436 break; 4437 case keyCode.HOME: 4438 toFocus = this.headers[ 0 ]; 4439 break; 4440 case keyCode.END: 4441 toFocus = this.headers[ length - 1 ]; 4442 break; 4443 } 4444 4445 if ( toFocus ) { 4446 $( event.target ).attr( "tabIndex", -1 ); 4447 $( toFocus ).attr( "tabIndex", 0 ); 4448 $( toFocus ).trigger( "focus" ); 4449 event.preventDefault(); 4450 } 4451 }, 4452 4453 _panelKeyDown: function( event ) { 4454 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { 4455 $( event.currentTarget ).prev().trigger( "focus" ); 4456 } 4457 }, 4458 4459 refresh: function() { 4460 var options = this.options; 4461 this._processPanels(); 4462 4463 // Was collapsed or no panel 4464 if ( ( options.active === false && options.collapsible === true ) || 4465 !this.headers.length ) { 4466 options.active = false; 4467 this.active = $(); 4468 4469 // active false only when collapsible is true 4470 } else if ( options.active === false ) { 4471 this._activate( 0 ); 4472 4473 // was active, but active panel is gone 4474 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 4475 4476 // all remaining panel are disabled 4477 if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) { 4478 options.active = false; 4479 this.active = $(); 4480 4481 // activate previous panel 4482 } else { 4483 this._activate( Math.max( 0, options.active - 1 ) ); 4484 } 4485 4486 // was active, active panel still exists 4487 } else { 4488 4489 // make sure active index is correct 4490 options.active = this.headers.index( this.active ); 4491 } 4492 4493 this._destroyIcons(); 4494 4495 this._refresh(); 4496 }, 4497 4498 _processPanels: function() { 4499 var prevHeaders = this.headers, 4500 prevPanels = this.panels; 4501 4502 if ( typeof this.options.header === "function" ) { 4503 this.headers = this.options.header( this.element ); 4504 } else { 4505 this.headers = this.element.find( this.options.header ); 4506 } 4507 this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed", 4508 "ui-state-default" ); 4509 4510 this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide(); 4511 this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" ); 4512 4513 // Avoid memory leaks (#10056) 4514 if ( prevPanels ) { 4515 this._off( prevHeaders.not( this.headers ) ); 4516 this._off( prevPanels.not( this.panels ) ); 4517 } 4518 }, 4519 4520 _refresh: function() { 4521 var maxHeight, 4522 options = this.options, 4523 heightStyle = options.heightStyle, 4524 parent = this.element.parent(); 4525 4526 this.active = this._findActive( options.active ); 4527 this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" ) 4528 ._removeClass( this.active, "ui-accordion-header-collapsed" ); 4529 this._addClass( this.active.next(), "ui-accordion-content-active" ); 4530 this.active.next().show(); 4531 4532 this.headers 4533 .attr( "role", "tab" ) 4534 .each( function() { 4535 var header = $( this ), 4536 headerId = header.uniqueId().attr( "id" ), 4537 panel = header.next(), 4538 panelId = panel.uniqueId().attr( "id" ); 4539 header.attr( "aria-controls", panelId ); 4540 panel.attr( "aria-labelledby", headerId ); 4541 } ) 4542 .next() 4543 .attr( "role", "tabpanel" ); 4544 4545 this.headers 4546 .not( this.active ) 4547 .attr( { 4548 "aria-selected": "false", 4549 "aria-expanded": "false", 4550 tabIndex: -1 4551 } ) 4552 .next() 4553 .attr( { 4554 "aria-hidden": "true" 4555 } ) 4556 .hide(); 4557 4558 // Make sure at least one header is in the tab order 4559 if ( !this.active.length ) { 4560 this.headers.eq( 0 ).attr( "tabIndex", 0 ); 4561 } else { 4562 this.active.attr( { 4563 "aria-selected": "true", 4564 "aria-expanded": "true", 4565 tabIndex: 0 4566 } ) 4567 .next() 4568 .attr( { 4569 "aria-hidden": "false" 4570 } ); 4571 } 4572 4573 this._createIcons(); 4574 4575 this._setupEvents( options.event ); 4576 4577 if ( heightStyle === "fill" ) { 4578 maxHeight = parent.height(); 4579 this.element.siblings( ":visible" ).each( function() { 4580 var elem = $( this ), 4581 position = elem.css( "position" ); 4582 4583 if ( position === "absolute" || position === "fixed" ) { 4584 return; 4585 } 4586 maxHeight -= elem.outerHeight( true ); 4587 } ); 4588 4589 this.headers.each( function() { 4590 maxHeight -= $( this ).outerHeight( true ); 4591 } ); 4592 4593 this.headers.next() 4594 .each( function() { 4595 $( this ).height( Math.max( 0, maxHeight - 4596 $( this ).innerHeight() + $( this ).height() ) ); 4597 } ) 4598 .css( "overflow", "auto" ); 4599 } else if ( heightStyle === "auto" ) { 4600 maxHeight = 0; 4601 this.headers.next() 4602 .each( function() { 4603 var isVisible = $( this ).is( ":visible" ); 4604 if ( !isVisible ) { 4605 $( this ).show(); 4606 } 4607 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); 4608 if ( !isVisible ) { 4609 $( this ).hide(); 4610 } 4611 } ) 4612 .height( maxHeight ); 4613 } 4614 }, 4615 4616 _activate: function( index ) { 4617 var active = this._findActive( index )[ 0 ]; 4618 4619 // Trying to activate the already active panel 4620 if ( active === this.active[ 0 ] ) { 4621 return; 4622 } 4623 4624 // Trying to collapse, simulate a click on the currently active header 4625 active = active || this.active[ 0 ]; 4626 4627 this._eventHandler( { 4628 target: active, 4629 currentTarget: active, 4630 preventDefault: $.noop 4631 } ); 4632 }, 4633 4634 _findActive: function( selector ) { 4635 return typeof selector === "number" ? this.headers.eq( selector ) : $(); 4636 }, 4637 4638 _setupEvents: function( event ) { 4639 var events = { 4640 keydown: "_keydown" 4641 }; 4642 if ( event ) { 4643 $.each( event.split( " " ), function( index, eventName ) { 4644 events[ eventName ] = "_eventHandler"; 4645 } ); 4646 } 4647 4648 this._off( this.headers.add( this.headers.next() ) ); 4649 this._on( this.headers, events ); 4650 this._on( this.headers.next(), { keydown: "_panelKeyDown" } ); 4651 this._hoverable( this.headers ); 4652 this._focusable( this.headers ); 4653 }, 4654 4655 _eventHandler: function( event ) { 4656 var activeChildren, clickedChildren, 4657 options = this.options, 4658 active = this.active, 4659 clicked = $( event.currentTarget ), 4660 clickedIsActive = clicked[ 0 ] === active[ 0 ], 4661 collapsing = clickedIsActive && options.collapsible, 4662 toShow = collapsing ? $() : clicked.next(), 4663 toHide = active.next(), 4664 eventData = { 4665 oldHeader: active, 4666 oldPanel: toHide, 4667 newHeader: collapsing ? $() : clicked, 4668 newPanel: toShow 4669 }; 4670 4671 event.preventDefault(); 4672 4673 if ( 4674 4675 // click on active header, but not collapsible 4676 ( clickedIsActive && !options.collapsible ) || 4677 4678 // allow canceling activation 4679 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 4680 return; 4681 } 4682 4683 options.active = collapsing ? false : this.headers.index( clicked ); 4684 4685 // When the call to ._toggle() comes after the class changes 4686 // it causes a very odd bug in IE 8 (see #6720) 4687 this.active = clickedIsActive ? $() : clicked; 4688 this._toggle( eventData ); 4689 4690 // Switch classes 4691 // corner classes on the previously active header stay after the animation 4692 this._removeClass( active, "ui-accordion-header-active", "ui-state-active" ); 4693 if ( options.icons ) { 4694 activeChildren = active.children( ".ui-accordion-header-icon" ); 4695 this._removeClass( activeChildren, null, options.icons.activeHeader ) 4696 ._addClass( activeChildren, null, options.icons.header ); 4697 } 4698 4699 if ( !clickedIsActive ) { 4700 this._removeClass( clicked, "ui-accordion-header-collapsed" ) 4701 ._addClass( clicked, "ui-accordion-header-active", "ui-state-active" ); 4702 if ( options.icons ) { 4703 clickedChildren = clicked.children( ".ui-accordion-header-icon" ); 4704 this._removeClass( clickedChildren, null, options.icons.header ) 4705 ._addClass( clickedChildren, null, options.icons.activeHeader ); 4706 } 4707 4708 this._addClass( clicked.next(), "ui-accordion-content-active" ); 4709 } 4710 }, 4711 4712 _toggle: function( data ) { 4713 var toShow = data.newPanel, 4714 toHide = this.prevShow.length ? this.prevShow : data.oldPanel; 4715 4716 // Handle activating a panel during the animation for another activation 4717 this.prevShow.add( this.prevHide ).stop( true, true ); 4718 this.prevShow = toShow; 4719 this.prevHide = toHide; 4720 4721 if ( this.options.animate ) { 4722 this._animate( toShow, toHide, data ); 4723 } else { 4724 toHide.hide(); 4725 toShow.show(); 4726 this._toggleComplete( data ); 4727 } 4728 4729 toHide.attr( { 4730 "aria-hidden": "true" 4731 } ); 4732 toHide.prev().attr( { 4733 "aria-selected": "false", 4734 "aria-expanded": "false" 4735 } ); 4736 4737 // if we're switching panels, remove the old header from the tab order 4738 // if we're opening from collapsed state, remove the previous header from the tab order 4739 // if we're collapsing, then keep the collapsing header in the tab order 4740 if ( toShow.length && toHide.length ) { 4741 toHide.prev().attr( { 4742 "tabIndex": -1, 4743 "aria-expanded": "false" 4744 } ); 4745 } else if ( toShow.length ) { 4746 this.headers.filter( function() { 4747 return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0; 4748 } ) 4749 .attr( "tabIndex", -1 ); 4750 } 4751 4752 toShow 4753 .attr( "aria-hidden", "false" ) 4754 .prev() 4755 .attr( { 4756 "aria-selected": "true", 4757 "aria-expanded": "true", 4758 tabIndex: 0 4759 } ); 4760 }, 4761 4762 _animate: function( toShow, toHide, data ) { 4763 var total, easing, duration, 4764 that = this, 4765 adjust = 0, 4766 boxSizing = toShow.css( "box-sizing" ), 4767 down = toShow.length && 4768 ( !toHide.length || ( toShow.index() < toHide.index() ) ), 4769 animate = this.options.animate || {}, 4770 options = down && animate.down || animate, 4771 complete = function() { 4772 that._toggleComplete( data ); 4773 }; 4774 4775 if ( typeof options === "number" ) { 4776 duration = options; 4777 } 4778 if ( typeof options === "string" ) { 4779 easing = options; 4780 } 4781 4782 // fall back from options to animation in case of partial down settings 4783 easing = easing || options.easing || animate.easing; 4784 duration = duration || options.duration || animate.duration; 4785 4786 if ( !toHide.length ) { 4787 return toShow.animate( this.showProps, duration, easing, complete ); 4788 } 4789 if ( !toShow.length ) { 4790 return toHide.animate( this.hideProps, duration, easing, complete ); 4791 } 4792 4793 total = toShow.show().outerHeight(); 4794 toHide.animate( this.hideProps, { 4795 duration: duration, 4796 easing: easing, 4797 step: function( now, fx ) { 4798 fx.now = Math.round( now ); 4799 } 4800 } ); 4801 toShow 4802 .hide() 4803 .animate( this.showProps, { 4804 duration: duration, 4805 easing: easing, 4806 complete: complete, 4807 step: function( now, fx ) { 4808 fx.now = Math.round( now ); 4809 if ( fx.prop !== "height" ) { 4810 if ( boxSizing === "content-box" ) { 4811 adjust += fx.now; 4812 } 4813 } else if ( that.options.heightStyle !== "content" ) { 4814 fx.now = Math.round( total - toHide.outerHeight() - adjust ); 4815 adjust = 0; 4816 } 4817 } 4818 } ); 4819 }, 4820 4821 _toggleComplete: function( data ) { 4822 var toHide = data.oldPanel, 4823 prev = toHide.prev(); 4824 4825 this._removeClass( toHide, "ui-accordion-content-active" ); 4826 this._removeClass( prev, "ui-accordion-header-active" ) 4827 ._addClass( prev, "ui-accordion-header-collapsed" ); 4828 4829 this._trigger( "activate", null, data ); 4830 } 4831} ); 4832 4833 4834/*! 4835 * jQuery UI Menu 1.14.1 4836 * https://jqueryui.com 4837 * 4838 * Copyright OpenJS Foundation and other contributors 4839 * Released under the MIT license. 4840 * https://jquery.org/license 4841 */ 4842 4843//>>label: Menu 4844//>>group: Widgets 4845//>>description: Creates nestable menus. 4846//>>docs: https://api.jqueryui.com/menu/ 4847//>>demos: https://jqueryui.com/menu/ 4848//>>css.structure: ../../themes/base/core.css 4849//>>css.structure: ../../themes/base/menu.css 4850//>>css.theme: ../../themes/base/theme.css 4851 4852 4853var widgetsMenu = $.widget( "ui.menu", { 4854 version: "1.14.1", 4855 defaultElement: "<ul>", 4856 delay: 300, 4857 options: { 4858 icons: { 4859 submenu: "ui-icon-caret-1-e" 4860 }, 4861 items: "> *", 4862 menus: "ul", 4863 position: { 4864 my: "left top", 4865 at: "right top" 4866 }, 4867 role: "menu", 4868 4869 // Callbacks 4870 blur: null, 4871 focus: null, 4872 select: null 4873 }, 4874 4875 _create: function() { 4876 this.activeMenu = this.element; 4877 4878 // Flag used to prevent firing of the click handler 4879 // as the event bubbles up through nested menus 4880 this.mouseHandled = false; 4881 this.lastMousePosition = { x: null, y: null }; 4882 this.element 4883 .uniqueId() 4884 .attr( { 4885 role: this.options.role, 4886 tabIndex: 0 4887 } ); 4888 4889 this._addClass( "ui-menu", "ui-widget ui-widget-content" ); 4890 this._on( { 4891 4892 // Prevent focus from sticking to links inside menu after clicking 4893 // them (focus should always stay on UL during navigation). 4894 "mousedown .ui-menu-item": function( event ) { 4895 event.preventDefault(); 4896 4897 this._activateItem( event ); 4898 }, 4899 "click .ui-menu-item": function( event ) { 4900 var target = $( event.target ); 4901 var active = $( this.document[ 0 ].activeElement ); 4902 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) { 4903 this.select( event ); 4904 4905 // Only set the mouseHandled flag if the event will bubble, see #9469. 4906 if ( !event.isPropagationStopped() ) { 4907 this.mouseHandled = true; 4908 } 4909 4910 // Open submenu on click 4911 if ( target.has( ".ui-menu" ).length ) { 4912 this.expand( event ); 4913 } else if ( !this.element.is( ":focus" ) && 4914 active.closest( ".ui-menu" ).length ) { 4915 4916 // Redirect focus to the menu 4917 this.element.trigger( "focus", [ true ] ); 4918 4919 // If the active item is on the top level, let it stay active. 4920 // Otherwise, blur the active item since it is no longer visible. 4921 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) { 4922 clearTimeout( this.timer ); 4923 } 4924 } 4925 } 4926 }, 4927 "mouseenter .ui-menu-item": "_activateItem", 4928 "mousemove .ui-menu-item": "_activateItem", 4929 mouseleave: "collapseAll", 4930 "mouseleave .ui-menu": "collapseAll", 4931 focus: function( event, keepActiveItem ) { 4932 4933 // If there's already an active item, keep it active 4934 // If not, activate the first item 4935 var item = this.active || this._menuItems().first(); 4936 4937 if ( !keepActiveItem ) { 4938 this.focus( event, item ); 4939 } 4940 }, 4941 blur: function( event ) { 4942 this._delay( function() { 4943 var notContained = !$.contains( 4944 this.element[ 0 ], 4945 this.document[ 0 ].activeElement 4946 ); 4947 if ( notContained ) { 4948 this.collapseAll( event ); 4949 } 4950 } ); 4951 }, 4952 keydown: "_keydown" 4953 } ); 4954 4955 this.refresh(); 4956 4957 // Clicks outside of a menu collapse any open menus 4958 this._on( this.document, { 4959 click: function( event ) { 4960 if ( this._closeOnDocumentClick( event ) ) { 4961 this.collapseAll( event, true ); 4962 } 4963 4964 // Reset the mouseHandled flag 4965 this.mouseHandled = false; 4966 } 4967 } ); 4968 }, 4969 4970 _activateItem: function( event ) { 4971 4972 // Ignore mouse events while typeahead is active, see #10458. 4973 // Prevents focusing the wrong item when typeahead causes a scroll while the mouse 4974 // is over an item in the menu 4975 if ( this.previousFilter ) { 4976 return; 4977 } 4978 4979 // If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356) 4980 if ( event.clientX === this.lastMousePosition.x && 4981 event.clientY === this.lastMousePosition.y ) { 4982 return; 4983 } 4984 4985 this.lastMousePosition = { 4986 x: event.clientX, 4987 y: event.clientY 4988 }; 4989 4990 var actualTarget = $( event.target ).closest( ".ui-menu-item" ), 4991 target = $( event.currentTarget ); 4992 4993 // Ignore bubbled events on parent items, see #11641 4994 if ( actualTarget[ 0 ] !== target[ 0 ] ) { 4995 return; 4996 } 4997 4998 // If the item is already active, there's nothing to do 4999 if ( target.is( ".ui-state-active" ) ) { 5000 return; 5001 } 5002 5003 // Remove ui-state-active class from siblings of the newly focused menu item 5004 // to avoid a jump caused by adjacent elements both having a class with a border 5005 this._removeClass( target.siblings().children( ".ui-state-active" ), 5006 null, "ui-state-active" ); 5007 this.focus( event, target ); 5008 }, 5009 5010 _destroy: function() { 5011 var items = this.element.find( ".ui-menu-item" ) 5012 .removeAttr( "role aria-disabled" ), 5013 submenus = items.children( ".ui-menu-item-wrapper" ) 5014 .removeUniqueId() 5015 .removeAttr( "tabIndex role aria-haspopup" ); 5016 5017 // Destroy (sub)menus 5018 this.element 5019 .removeAttr( "aria-activedescendant" ) 5020 .find( ".ui-menu" ).addBack() 5021 .removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " + 5022 "tabIndex" ) 5023 .removeUniqueId() 5024 .show(); 5025 5026 submenus.children().each( function() { 5027 var elem = $( this ); 5028 if ( elem.data( "ui-menu-submenu-caret" ) ) { 5029 elem.remove(); 5030 } 5031 } ); 5032 }, 5033 5034 _keydown: function( event ) { 5035 var match, prev, character, skip, 5036 preventDefault = true; 5037 5038 switch ( event.keyCode ) { 5039 case $.ui.keyCode.PAGE_UP: 5040 this.previousPage( event ); 5041 break; 5042 case $.ui.keyCode.PAGE_DOWN: 5043 this.nextPage( event ); 5044 break; 5045 case $.ui.keyCode.HOME: 5046 this._move( "first", "first", event ); 5047 break; 5048 case $.ui.keyCode.END: 5049 this._move( "last", "last", event ); 5050 break; 5051 case $.ui.keyCode.UP: 5052 this.previous( event ); 5053 break; 5054 case $.ui.keyCode.DOWN: 5055 this.next( event ); 5056 break; 5057 case $.ui.keyCode.LEFT: 5058 this.collapse( event ); 5059 break; 5060 case $.ui.keyCode.RIGHT: 5061 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { 5062 this.expand( event ); 5063 } 5064 break; 5065 case $.ui.keyCode.ENTER: 5066 case $.ui.keyCode.SPACE: 5067 this._activate( event ); 5068 break; 5069 case $.ui.keyCode.ESCAPE: 5070 this.collapse( event ); 5071 break; 5072 default: 5073 preventDefault = false; 5074 prev = this.previousFilter || ""; 5075 skip = false; 5076 5077 // Support number pad values 5078 character = event.keyCode >= 96 && event.keyCode <= 105 ? 5079 ( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode ); 5080 5081 clearTimeout( this.filterTimer ); 5082 5083 if ( character === prev ) { 5084 skip = true; 5085 } else { 5086 character = prev + character; 5087 } 5088 5089 match = this._filterMenuItems( character ); 5090 match = skip && match.index( this.active.next() ) !== -1 ? 5091 this.active.nextAll( ".ui-menu-item" ) : 5092 match; 5093 5094 // If no matches on the current filter, reset to the last character pressed 5095 // to move down the menu to the first item that starts with that character 5096 if ( !match.length ) { 5097 character = String.fromCharCode( event.keyCode ); 5098 match = this._filterMenuItems( character ); 5099 } 5100 5101 if ( match.length ) { 5102 this.focus( event, match ); 5103 this.previousFilter = character; 5104 this.filterTimer = this._delay( function() { 5105 delete this.previousFilter; 5106 }, 1000 ); 5107 } else { 5108 delete this.previousFilter; 5109 } 5110 } 5111 5112 if ( preventDefault ) { 5113 event.preventDefault(); 5114 } 5115 }, 5116 5117 _activate: function( event ) { 5118 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { 5119 if ( this.active.children( "[aria-haspopup='true']" ).length ) { 5120 this.expand( event ); 5121 } else { 5122 this.select( event ); 5123 } 5124 } 5125 }, 5126 5127 refresh: function() { 5128 var menus, items, newSubmenus, newItems, newWrappers, 5129 that = this, 5130 icon = this.options.icons.submenu, 5131 submenus = this.element.find( this.options.menus ); 5132 5133 this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length ); 5134 5135 // Initialize nested menus 5136 newSubmenus = submenus.filter( ":not(.ui-menu)" ) 5137 .hide() 5138 .attr( { 5139 role: this.options.role, 5140 "aria-hidden": "true", 5141 "aria-expanded": "false" 5142 } ) 5143 .each( function() { 5144 var menu = $( this ), 5145 item = menu.prev(), 5146 submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true ); 5147 5148 that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon ); 5149 item 5150 .attr( "aria-haspopup", "true" ) 5151 .prepend( submenuCaret ); 5152 menu.attr( "aria-labelledby", item.attr( "id" ) ); 5153 } ); 5154 5155 this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" ); 5156 5157 menus = submenus.add( this.element ); 5158 items = menus.find( this.options.items ); 5159 5160 // Initialize menu-items containing spaces and/or dashes only as dividers 5161 items.not( ".ui-menu-item" ).each( function() { 5162 var item = $( this ); 5163 if ( that._isDivider( item ) ) { 5164 that._addClass( item, "ui-menu-divider", "ui-widget-content" ); 5165 } 5166 } ); 5167 5168 // Don't refresh list items that are already adapted 5169 newItems = items.not( ".ui-menu-item, .ui-menu-divider" ); 5170 newWrappers = newItems.children() 5171 .not( ".ui-menu" ) 5172 .uniqueId() 5173 .attr( { 5174 tabIndex: -1, 5175 role: this._itemRole() 5176 } ); 5177 this._addClass( newItems, "ui-menu-item" ) 5178 ._addClass( newWrappers, "ui-menu-item-wrapper" ); 5179 5180 // Add aria-disabled attribute to any disabled menu item 5181 items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); 5182 5183 // If the active item has been removed, blur the menu 5184 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 5185 this.blur(); 5186 } 5187 }, 5188 5189 _itemRole: function() { 5190 return { 5191 menu: "menuitem", 5192 listbox: "option" 5193 }[ this.options.role ]; 5194 }, 5195 5196 _setOption: function( key, value ) { 5197 if ( key === "icons" ) { 5198 var icons = this.element.find( ".ui-menu-icon" ); 5199 this._removeClass( icons, null, this.options.icons.submenu ) 5200 ._addClass( icons, null, value.submenu ); 5201 } 5202 this._super( key, value ); 5203 }, 5204 5205 _setOptionDisabled: function( value ) { 5206 this._super( value ); 5207 5208 this.element.attr( "aria-disabled", String( value ) ); 5209 this._toggleClass( null, "ui-state-disabled", !!value ); 5210 }, 5211 5212 focus: function( event, item ) { 5213 var nested, focused, activeParent; 5214 this.blur( event, event && event.type === "focus" ); 5215 5216 this._scrollIntoView( item ); 5217 5218 this.active = item.first(); 5219 5220 focused = this.active.children( ".ui-menu-item-wrapper" ); 5221 this._addClass( focused, null, "ui-state-active" ); 5222 5223 // Only update aria-activedescendant if there's a role 5224 // otherwise we assume focus is managed elsewhere 5225 if ( this.options.role ) { 5226 this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); 5227 } 5228 5229 // Highlight active parent menu item, if any 5230 activeParent = this.active 5231 .parent() 5232 .closest( ".ui-menu-item" ) 5233 .children( ".ui-menu-item-wrapper" ); 5234 this._addClass( activeParent, null, "ui-state-active" ); 5235 5236 if ( event && event.type === "keydown" ) { 5237 this._close(); 5238 } else { 5239 this.timer = this._delay( function() { 5240 this._close(); 5241 }, this.delay ); 5242 } 5243 5244 nested = item.children( ".ui-menu" ); 5245 if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) { 5246 this._startOpening( nested ); 5247 } 5248 this.activeMenu = item.parent(); 5249 5250 this._trigger( "focus", event, { item: item } ); 5251 }, 5252 5253 _scrollIntoView: function( item ) { 5254 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; 5255 if ( this._hasScroll() ) { 5256 borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0; 5257 paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0; 5258 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; 5259 scroll = this.activeMenu.scrollTop(); 5260 elementHeight = this.activeMenu.height(); 5261 itemHeight = item.outerHeight(); 5262 5263 if ( offset < 0 ) { 5264 this.activeMenu.scrollTop( scroll + offset ); 5265 } else if ( offset + itemHeight > elementHeight ) { 5266 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); 5267 } 5268 } 5269 }, 5270 5271 blur: function( event, fromFocus ) { 5272 if ( !fromFocus ) { 5273 clearTimeout( this.timer ); 5274 } 5275 5276 if ( !this.active ) { 5277 return; 5278 } 5279 5280 this._removeClass( this.active.children( ".ui-menu-item-wrapper" ), 5281 null, "ui-state-active" ); 5282 5283 this._trigger( "blur", event, { item: this.active } ); 5284 this.active = null; 5285 }, 5286 5287 _startOpening: function( submenu ) { 5288 clearTimeout( this.timer ); 5289 5290 // Don't open if already open fixes a Firefox bug that caused a .5 pixel 5291 // shift in the submenu position when mousing over the caret icon 5292 if ( submenu.attr( "aria-hidden" ) !== "true" ) { 5293 return; 5294 } 5295 5296 this.timer = this._delay( function() { 5297 this._close(); 5298 this._open( submenu ); 5299 }, this.delay ); 5300 }, 5301 5302 _open: function( submenu ) { 5303 var position = $.extend( { 5304 of: this.active 5305 }, this.options.position ); 5306 5307 clearTimeout( this.timer ); 5308 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) ) 5309 .hide() 5310 .attr( "aria-hidden", "true" ); 5311 5312 submenu 5313 .show() 5314 .removeAttr( "aria-hidden" ) 5315 .attr( "aria-expanded", "true" ) 5316 .position( position ); 5317 }, 5318 5319 collapseAll: function( event, all ) { 5320 clearTimeout( this.timer ); 5321 this.timer = this._delay( function() { 5322 5323 // If we were passed an event, look for the submenu that contains the event 5324 var currentMenu = all ? this.element : 5325 $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); 5326 5327 // If we found no valid submenu ancestor, use the main menu to close all 5328 // sub menus anyway 5329 if ( !currentMenu.length ) { 5330 currentMenu = this.element; 5331 } 5332 5333 this._close( currentMenu ); 5334 5335 this.blur( event ); 5336 5337 // Work around active item staying active after menu is blurred 5338 this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" ); 5339 5340 this.activeMenu = currentMenu; 5341 }, all ? 0 : this.delay ); 5342 }, 5343 5344 // With no arguments, closes the currently active menu - if nothing is active 5345 // it closes all menus. If passed an argument, it will search for menus BELOW 5346 _close: function( startMenu ) { 5347 if ( !startMenu ) { 5348 startMenu = this.active ? this.active.parent() : this.element; 5349 } 5350 5351 startMenu.find( ".ui-menu" ) 5352 .hide() 5353 .attr( "aria-hidden", "true" ) 5354 .attr( "aria-expanded", "false" ); 5355 }, 5356 5357 _closeOnDocumentClick: function( event ) { 5358 return !$( event.target ).closest( ".ui-menu" ).length; 5359 }, 5360 5361 _isDivider: function( item ) { 5362 5363 // Match hyphen, em dash, en dash 5364 return !/[^\-\u2014\u2013\s]/.test( item.text() ); 5365 }, 5366 5367 collapse: function( event ) { 5368 var newItem = this.active && 5369 this.active.parent().closest( ".ui-menu-item", this.element ); 5370 if ( newItem && newItem.length ) { 5371 this._close(); 5372 this.focus( event, newItem ); 5373 } 5374 }, 5375 5376 expand: function( event ) { 5377 var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first(); 5378 5379 if ( newItem && newItem.length ) { 5380 this._open( newItem.parent() ); 5381 5382 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT 5383 this._delay( function() { 5384 this.focus( event, newItem ); 5385 } ); 5386 } 5387 }, 5388 5389 next: function( event ) { 5390 this._move( "next", "first", event ); 5391 }, 5392 5393 previous: function( event ) { 5394 this._move( "prev", "last", event ); 5395 }, 5396 5397 isFirstItem: function() { 5398 return this.active && !this.active.prevAll( ".ui-menu-item" ).length; 5399 }, 5400 5401 isLastItem: function() { 5402 return this.active && !this.active.nextAll( ".ui-menu-item" ).length; 5403 }, 5404 5405 _menuItems: function( menu ) { 5406 return ( menu || this.element ) 5407 .find( this.options.items ) 5408 .filter( ".ui-menu-item" ); 5409 }, 5410 5411 _move: function( direction, filter, event ) { 5412 var next; 5413 if ( this.active ) { 5414 if ( direction === "first" || direction === "last" ) { 5415 next = this.active 5416 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) 5417 .last(); 5418 } else { 5419 next = this.active 5420 [ direction + "All" ]( ".ui-menu-item" ) 5421 .first(); 5422 } 5423 } 5424 if ( !next || !next.length || !this.active ) { 5425 next = this._menuItems( this.activeMenu )[ filter ](); 5426 } 5427 5428 this.focus( event, next ); 5429 }, 5430 5431 nextPage: function( event ) { 5432 var item, base, height; 5433 5434 if ( !this.active ) { 5435 this.next( event ); 5436 return; 5437 } 5438 if ( this.isLastItem() ) { 5439 return; 5440 } 5441 if ( this._hasScroll() ) { 5442 base = this.active.offset().top; 5443 height = this.element.innerHeight(); 5444 5445 // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back. 5446 if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) { 5447 height += this.element[ 0 ].offsetHeight - this.element.outerHeight(); 5448 } 5449 5450 this.active.nextAll( ".ui-menu-item" ).each( function() { 5451 item = $( this ); 5452 return item.offset().top - base - height < 0; 5453 } ); 5454 5455 this.focus( event, item ); 5456 } else { 5457 this.focus( event, this._menuItems( this.activeMenu ) 5458 [ !this.active ? "first" : "last" ]() ); 5459 } 5460 }, 5461 5462 previousPage: function( event ) { 5463 var item, base, height; 5464 if ( !this.active ) { 5465 this.next( event ); 5466 return; 5467 } 5468 if ( this.isFirstItem() ) { 5469 return; 5470 } 5471 if ( this._hasScroll() ) { 5472 base = this.active.offset().top; 5473 height = this.element.innerHeight(); 5474 5475 // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back. 5476 if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) { 5477 height += this.element[ 0 ].offsetHeight - this.element.outerHeight(); 5478 } 5479 5480 this.active.prevAll( ".ui-menu-item" ).each( function() { 5481 item = $( this ); 5482 return item.offset().top - base + height > 0; 5483 } ); 5484 5485 this.focus( event, item ); 5486 } else { 5487 this.focus( event, this._menuItems( this.activeMenu ).first() ); 5488 } 5489 }, 5490 5491 _hasScroll: function() { 5492 return this.element.outerHeight() < this.element.prop( "scrollHeight" ); 5493 }, 5494 5495 select: function( event ) { 5496 5497 // TODO: It should never be possible to not have an active item at this 5498 // point, but the tests don't trigger mouseenter before click. 5499 this.active = this.active || $( event.target ).closest( ".ui-menu-item" ); 5500 var ui = { item: this.active }; 5501 if ( !this.active.has( ".ui-menu" ).length ) { 5502 this.collapseAll( event, true ); 5503 } 5504 this._trigger( "select", event, ui ); 5505 }, 5506 5507 _filterMenuItems: function( character ) { 5508 var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ), 5509 regex = new RegExp( "^" + escapedCharacter, "i" ); 5510 5511 return this.activeMenu 5512 .find( this.options.items ) 5513 5514 // Only match on items, not dividers or other content (#10571) 5515 .filter( ".ui-menu-item" ) 5516 .filter( function() { 5517 return regex.test( 5518 String.prototype.trim.call( 5519 $( this ).children( ".ui-menu-item-wrapper" ).text() ) ); 5520 } ); 5521 } 5522} ); 5523 5524 5525/*! 5526 * jQuery UI Autocomplete 1.14.1 5527 * https://jqueryui.com 5528 * 5529 * Copyright OpenJS Foundation and other contributors 5530 * Released under the MIT license. 5531 * https://jquery.org/license 5532 */ 5533 5534//>>label: Autocomplete 5535//>>group: Widgets 5536//>>description: Lists suggested words as the user is typing. 5537//>>docs: https://api.jqueryui.com/autocomplete/ 5538//>>demos: https://jqueryui.com/autocomplete/ 5539//>>css.structure: ../../themes/base/core.css 5540//>>css.structure: ../../themes/base/autocomplete.css 5541//>>css.theme: ../../themes/base/theme.css 5542 5543 5544$.widget( "ui.autocomplete", { 5545 version: "1.14.1", 5546 defaultElement: "<input>", 5547 options: { 5548 appendTo: null, 5549 autoFocus: false, 5550 delay: 300, 5551 minLength: 1, 5552 position: { 5553 my: "left top", 5554 at: "left bottom", 5555 collision: "none" 5556 }, 5557 source: null, 5558 5559 // Callbacks 5560 change: null, 5561 close: null, 5562 focus: null, 5563 open: null, 5564 response: null, 5565 search: null, 5566 select: null 5567 }, 5568 5569 requestIndex: 0, 5570 pending: 0, 5571 liveRegionTimer: null, 5572 5573 _create: function() { 5574 5575 // Some browsers only repeat keydown events, not keypress events, 5576 // so we use the suppressKeyPress flag to determine if we've already 5577 // handled the keydown event. #7269 5578 // Unfortunately the code for & in keypress is the same as the up arrow, 5579 // so we use the suppressKeyPressRepeat flag to avoid handling keypress 5580 // events when we know the keydown event was used to modify the 5581 // search term. #7799 5582 var suppressKeyPress, suppressKeyPressRepeat, suppressInput, 5583 nodeName = this.element[ 0 ].nodeName.toLowerCase(), 5584 isTextarea = nodeName === "textarea", 5585 isInput = nodeName === "input"; 5586 5587 // Textareas are always multi-line 5588 // Inputs are always single-line, even if inside a contentEditable element 5589 // All other element types are determined by whether they're contentEditable 5590 this.isMultiLine = isTextarea || 5591 !isInput && this.element.prop( "contentEditable" ) === "true"; 5592 5593 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ]; 5594 this.isNewMenu = true; 5595 5596 this._addClass( "ui-autocomplete-input" ); 5597 this.element.attr( "autocomplete", "off" ); 5598 5599 this._on( this.element, { 5600 keydown: function( event ) { 5601 if ( this.element.prop( "readOnly" ) ) { 5602 suppressKeyPress = true; 5603 suppressInput = true; 5604 suppressKeyPressRepeat = true; 5605 return; 5606 } 5607 5608 suppressKeyPress = false; 5609 suppressInput = false; 5610 suppressKeyPressRepeat = false; 5611 var keyCode = $.ui.keyCode; 5612 switch ( event.keyCode ) { 5613 case keyCode.PAGE_UP: 5614 suppressKeyPress = true; 5615 this._move( "previousPage", event ); 5616 break; 5617 case keyCode.PAGE_DOWN: 5618 suppressKeyPress = true; 5619 this._move( "nextPage", event ); 5620 break; 5621 case keyCode.UP: 5622 suppressKeyPress = true; 5623 this._keyEvent( "previous", event ); 5624 break; 5625 case keyCode.DOWN: 5626 suppressKeyPress = true; 5627 this._keyEvent( "next", event ); 5628 break; 5629 case keyCode.ENTER: 5630 5631 // when menu is open and has focus 5632 if ( this.menu.active ) { 5633 5634 // #6055 - Opera still allows the keypress to occur 5635 // which causes forms to submit 5636 suppressKeyPress = true; 5637 event.preventDefault(); 5638 this.menu.select( event ); 5639 } 5640 break; 5641 case keyCode.TAB: 5642 if ( this.menu.active ) { 5643 this.menu.select( event ); 5644 } 5645 break; 5646 case keyCode.ESCAPE: 5647 if ( this.menu.element.is( ":visible" ) ) { 5648 if ( !this.isMultiLine ) { 5649 this._value( this.term ); 5650 } 5651 this.close( event ); 5652 5653 // Different browsers have different default behavior for escape 5654 // Single press can mean undo or clear 5655 event.preventDefault(); 5656 } 5657 break; 5658 default: 5659 suppressKeyPressRepeat = true; 5660 5661 // search timeout should be triggered before the input value is changed 5662 this._searchTimeout( event ); 5663 break; 5664 } 5665 }, 5666 keypress: function( event ) { 5667 if ( suppressKeyPress ) { 5668 suppressKeyPress = false; 5669 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 5670 event.preventDefault(); 5671 } 5672 return; 5673 } 5674 if ( suppressKeyPressRepeat ) { 5675 return; 5676 } 5677 5678 // Replicate some key handlers to allow them to repeat in Firefox and Opera 5679 var keyCode = $.ui.keyCode; 5680 switch ( event.keyCode ) { 5681 case keyCode.PAGE_UP: 5682 this._move( "previousPage", event ); 5683 break; 5684 case keyCode.PAGE_DOWN: 5685 this._move( "nextPage", event ); 5686 break; 5687 case keyCode.UP: 5688 this._keyEvent( "previous", event ); 5689 break; 5690 case keyCode.DOWN: 5691 this._keyEvent( "next", event ); 5692 break; 5693 } 5694 }, 5695 input: function( event ) { 5696 if ( suppressInput ) { 5697 suppressInput = false; 5698 event.preventDefault(); 5699 return; 5700 } 5701 this._searchTimeout( event ); 5702 }, 5703 focus: function() { 5704 this.selectedItem = null; 5705 this.previous = this._value(); 5706 }, 5707 blur: function( event ) { 5708 clearTimeout( this.searching ); 5709 this.close( event ); 5710 this._change( event ); 5711 } 5712 } ); 5713 5714 this._initSource(); 5715 this.menu = $( "<ul>" ) 5716 .appendTo( this._appendTo() ) 5717 .menu( { 5718 5719 // disable ARIA support, the live region takes care of that 5720 role: null 5721 } ) 5722 .hide() 5723 .menu( "instance" ); 5724 5725 this._addClass( this.menu.element, "ui-autocomplete", "ui-front" ); 5726 this._on( this.menu.element, { 5727 mousedown: function( event ) { 5728 5729 // Prevent moving focus out of the text field 5730 event.preventDefault(); 5731 }, 5732 menufocus: function( event, ui ) { 5733 var label, item; 5734 5735 // Support: Firefox 5736 // Prevent accidental activation of menu items in Firefox (#7024 #9118) 5737 if ( this.isNewMenu ) { 5738 this.isNewMenu = false; 5739 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) { 5740 this.menu.blur(); 5741 5742 this.document.one( "mousemove", function() { 5743 $( event.target ).trigger( event.originalEvent ); 5744 } ); 5745 5746 return; 5747 } 5748 } 5749 5750 item = ui.item.data( "ui-autocomplete-item" ); 5751 if ( false !== this._trigger( "focus", event, { item: item } ) ) { 5752 5753 // use value to match what will end up in the input, if it was a key event 5754 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) { 5755 this._value( item.value ); 5756 } 5757 } 5758 5759 // Announce the value in the liveRegion 5760 label = ui.item.attr( "aria-label" ) || item.value; 5761 if ( label && String.prototype.trim.call( label ).length ) { 5762 clearTimeout( this.liveRegionTimer ); 5763 this.liveRegionTimer = this._delay( function() { 5764 this.liveRegion.html( $( "<div>" ).text( label ) ); 5765 }, 100 ); 5766 } 5767 }, 5768 menuselect: function( event, ui ) { 5769 var item = ui.item.data( "ui-autocomplete-item" ), 5770 previous = this.previous; 5771 5772 // Only trigger when focus was lost (click on menu) 5773 if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) { 5774 this.element.trigger( "focus" ); 5775 this.previous = previous; 5776 } 5777 5778 if ( false !== this._trigger( "select", event, { item: item } ) ) { 5779 this._value( item.value ); 5780 } 5781 5782 // reset the term after the select event 5783 // this allows custom select handling to work properly 5784 this.term = this._value(); 5785 5786 this.close( event ); 5787 this.selectedItem = item; 5788 } 5789 } ); 5790 5791 this.liveRegion = $( "<div>", { 5792 role: "status", 5793 "aria-live": "assertive", 5794 "aria-relevant": "additions" 5795 } ) 5796 .appendTo( this.document[ 0 ].body ); 5797 5798 this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" ); 5799 5800 // Turning off autocomplete prevents the browser from remembering the 5801 // value when navigating through history, so we re-enable autocomplete 5802 // if the page is unloaded before the widget is destroyed. #7790 5803 this._on( this.window, { 5804 beforeunload: function() { 5805 this.element.removeAttr( "autocomplete" ); 5806 } 5807 } ); 5808 }, 5809 5810 _destroy: function() { 5811 clearTimeout( this.searching ); 5812 this.element.removeAttr( "autocomplete" ); 5813 this.menu.element.remove(); 5814 this.liveRegion.remove(); 5815 }, 5816 5817 _setOption: function( key, value ) { 5818 this._super( key, value ); 5819 if ( key === "source" ) { 5820 this._initSource(); 5821 } 5822 if ( key === "appendTo" ) { 5823 this.menu.element.appendTo( this._appendTo() ); 5824 } 5825 if ( key === "disabled" && value && this.xhr ) { 5826 this.xhr.abort(); 5827 } 5828 }, 5829 5830 _isEventTargetInWidget: function( event ) { 5831 var menuElement = this.menu.element[ 0 ]; 5832 5833 return event.target === this.element[ 0 ] || 5834 event.target === menuElement || 5835 $.contains( menuElement, event.target ); 5836 }, 5837 5838 _closeOnClickOutside: function( event ) { 5839 if ( !this._isEventTargetInWidget( event ) ) { 5840 this.close(); 5841 } 5842 }, 5843 5844 _appendTo: function() { 5845 var element = this.options.appendTo; 5846 5847 if ( element ) { 5848 element = element.jquery || element.nodeType ? 5849 $( element ) : 5850 this.document.find( element ).eq( 0 ); 5851 } 5852 5853 if ( !element || !element[ 0 ] ) { 5854 element = this.element.closest( ".ui-front, dialog" ); 5855 } 5856 5857 if ( !element.length ) { 5858 element = this.document[ 0 ].body; 5859 } 5860 5861 return element; 5862 }, 5863 5864 _initSource: function() { 5865 var array, url, 5866 that = this; 5867 if ( Array.isArray( this.options.source ) ) { 5868 array = this.options.source; 5869 this.source = function( request, response ) { 5870 response( $.ui.autocomplete.filter( array, request.term ) ); 5871 }; 5872 } else if ( typeof this.options.source === "string" ) { 5873 url = this.options.source; 5874 this.source = function( request, response ) { 5875 if ( that.xhr ) { 5876 that.xhr.abort(); 5877 } 5878 that.xhr = $.ajax( { 5879 url: url, 5880 data: request, 5881 dataType: "json", 5882 success: function( data ) { 5883 response( data ); 5884 }, 5885 error: function() { 5886 response( [] ); 5887 } 5888 } ); 5889 }; 5890 } else { 5891 this.source = this.options.source; 5892 } 5893 }, 5894 5895 _searchTimeout: function( event ) { 5896 clearTimeout( this.searching ); 5897 this.searching = this._delay( function() { 5898 5899 // Search if the value has changed, or if the user retypes the same value (see #7434) 5900 var equalValues = this.term === this._value(), 5901 menuVisible = this.menu.element.is( ":visible" ), 5902 modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey; 5903 5904 if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) { 5905 this.selectedItem = null; 5906 this.search( null, event ); 5907 } 5908 }, this.options.delay ); 5909 }, 5910 5911 search: function( value, event ) { 5912 value = value != null ? value : this._value(); 5913 5914 // Always save the actual value, not the one passed as an argument 5915 this.term = this._value(); 5916 5917 if ( value.length < this.options.minLength ) { 5918 return this.close( event ); 5919 } 5920 5921 if ( this._trigger( "search", event ) === false ) { 5922 return; 5923 } 5924 5925 return this._search( value ); 5926 }, 5927 5928 _search: function( value ) { 5929 this.pending++; 5930 this._addClass( "ui-autocomplete-loading" ); 5931 this.cancelSearch = false; 5932 5933 this.source( { term: value }, this._response() ); 5934 }, 5935 5936 _response: function() { 5937 var index = ++this.requestIndex; 5938 5939 return function( content ) { 5940 if ( index === this.requestIndex ) { 5941 this.__response( content ); 5942 } 5943 5944 this.pending--; 5945 if ( !this.pending ) { 5946 this._removeClass( "ui-autocomplete-loading" ); 5947 } 5948 }.bind( this ); 5949 }, 5950 5951 __response: function( content ) { 5952 if ( content ) { 5953 content = this._normalize( content ); 5954 } 5955 this._trigger( "response", null, { content: content } ); 5956 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) { 5957 this._suggest( content ); 5958 this._trigger( "open" ); 5959 } else { 5960 5961 // use ._close() instead of .close() so we don't cancel future searches 5962 this._close(); 5963 } 5964 }, 5965 5966 close: function( event ) { 5967 this.cancelSearch = true; 5968 this._close( event ); 5969 }, 5970 5971 _close: function( event ) { 5972 5973 // Remove the handler that closes the menu on outside clicks 5974 this._off( this.document, "mousedown" ); 5975 5976 if ( this.menu.element.is( ":visible" ) ) { 5977 this.menu.element.hide(); 5978 this.menu.blur(); 5979 this.isNewMenu = true; 5980 this._trigger( "close", event ); 5981 } 5982 }, 5983 5984 _change: function( event ) { 5985 if ( this.previous !== this._value() ) { 5986 this._trigger( "change", event, { item: this.selectedItem } ); 5987 } 5988 }, 5989 5990 _normalize: function( items ) { 5991 5992 // assume all items have the right format when the first item is complete 5993 if ( items.length && items[ 0 ].label && items[ 0 ].value ) { 5994 return items; 5995 } 5996 return $.map( items, function( item ) { 5997 if ( typeof item === "string" ) { 5998 return { 5999 label: item, 6000 value: item 6001 }; 6002 } 6003 return $.extend( {}, item, { 6004 label: item.label || item.value, 6005 value: item.value || item.label 6006 } ); 6007 } ); 6008 }, 6009 6010 _suggest: function( items ) { 6011 var ul = this.menu.element.empty(); 6012 this._renderMenu( ul, items ); 6013 this.isNewMenu = true; 6014 this.menu.refresh(); 6015 6016 // Size and position menu 6017 ul.show(); 6018 this._resizeMenu(); 6019 ul.position( $.extend( { 6020 of: this.element 6021 }, this.options.position ) ); 6022 6023 if ( this.options.autoFocus ) { 6024 this.menu.next(); 6025 } 6026 6027 // Listen for interactions outside of the widget (#6642) 6028 this._on( this.document, { 6029 mousedown: "_closeOnClickOutside" 6030 } ); 6031 }, 6032 6033 _resizeMenu: function() { 6034 var ul = this.menu.element; 6035 ul.outerWidth( Math.max( 6036 6037 // Firefox wraps long text (possibly a rounding bug) 6038 // so we add 1px to avoid the wrapping (#7513) 6039 ul.width( "" ).outerWidth() + 1, 6040 this.element.outerWidth() 6041 ) ); 6042 }, 6043 6044 _renderMenu: function( ul, items ) { 6045 var that = this; 6046 $.each( items, function( index, item ) { 6047 that._renderItemData( ul, item ); 6048 } ); 6049 }, 6050 6051 _renderItemData: function( ul, item ) { 6052 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item ); 6053 }, 6054 6055 _renderItem: function( ul, item ) { 6056 return $( "<li>" ) 6057 .append( $( "<div>" ).text( item.label ) ) 6058 .appendTo( ul ); 6059 }, 6060 6061 _move: function( direction, event ) { 6062 if ( !this.menu.element.is( ":visible" ) ) { 6063 this.search( null, event ); 6064 return; 6065 } 6066 if ( this.menu.isFirstItem() && /^previous/.test( direction ) || 6067 this.menu.isLastItem() && /^next/.test( direction ) ) { 6068 6069 if ( !this.isMultiLine ) { 6070 this._value( this.term ); 6071 } 6072 6073 this.menu.blur(); 6074 return; 6075 } 6076 this.menu[ direction ]( event ); 6077 }, 6078 6079 widget: function() { 6080 return this.menu.element; 6081 }, 6082 6083 _value: function() { 6084 return this.valueMethod.apply( this.element, arguments ); 6085 }, 6086 6087 _keyEvent: function( keyEvent, event ) { 6088 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 6089 this._move( keyEvent, event ); 6090 6091 // Prevents moving cursor to beginning/end of the text field in some browsers 6092 event.preventDefault(); 6093 } 6094 } 6095} ); 6096 6097$.extend( $.ui.autocomplete, { 6098 escapeRegex: function( value ) { 6099 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ); 6100 }, 6101 filter: function( array, term ) { 6102 var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" ); 6103 return $.grep( array, function( value ) { 6104 return matcher.test( value.label || value.value || value ); 6105 } ); 6106 } 6107} ); 6108 6109// Live region extension, adding a `messages` option 6110// NOTE: This is an experimental API. We are still investigating 6111// a full solution for string manipulation and internationalization. 6112$.widget( "ui.autocomplete", $.ui.autocomplete, { 6113 options: { 6114 messages: { 6115 noResults: "No search results.", 6116 results: function( amount ) { 6117 return amount + ( amount > 1 ? " results are" : " result is" ) + 6118 " available, use up and down arrow keys to navigate."; 6119 } 6120 } 6121 }, 6122 6123 __response: function( content ) { 6124 var message; 6125 this._superApply( arguments ); 6126 if ( this.options.disabled || this.cancelSearch ) { 6127 return; 6128 } 6129 if ( content && content.length ) { 6130 message = this.options.messages.results( content.length ); 6131 } else { 6132 message = this.options.messages.noResults; 6133 } 6134 clearTimeout( this.liveRegionTimer ); 6135 this.liveRegionTimer = this._delay( function() { 6136 this.liveRegion.html( $( "<div>" ).text( message ) ); 6137 }, 100 ); 6138 } 6139} ); 6140 6141var widgetsAutocomplete = $.ui.autocomplete; 6142 6143 6144/*! 6145 * jQuery UI Controlgroup 1.14.1 6146 * https://jqueryui.com 6147 * 6148 * Copyright OpenJS Foundation and other contributors 6149 * Released under the MIT license. 6150 * https://jquery.org/license 6151 */ 6152 6153//>>label: Controlgroup 6154//>>group: Widgets 6155//>>description: Visually groups form control widgets 6156//>>docs: https://api.jqueryui.com/controlgroup/ 6157//>>demos: https://jqueryui.com/controlgroup/ 6158//>>css.structure: ../../themes/base/core.css 6159//>>css.structure: ../../themes/base/controlgroup.css 6160//>>css.theme: ../../themes/base/theme.css 6161 6162 6163var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g; 6164 6165var widgetsControlgroup = $.widget( "ui.controlgroup", { 6166 version: "1.14.1", 6167 defaultElement: "<div>", 6168 options: { 6169 direction: "horizontal", 6170 disabled: null, 6171 onlyVisible: true, 6172 items: { 6173 "button": "input[type=button], input[type=submit], input[type=reset], button, a", 6174 "controlgroupLabel": ".ui-controlgroup-label", 6175 "checkboxradio": "input[type='checkbox'], input[type='radio']", 6176 "selectmenu": "select", 6177 "spinner": ".ui-spinner-input" 6178 } 6179 }, 6180 6181 _create: function() { 6182 this._enhance(); 6183 }, 6184 6185 // To support the enhanced option in jQuery Mobile, we isolate DOM manipulation 6186 _enhance: function() { 6187 this.element.attr( "role", "toolbar" ); 6188 this.refresh(); 6189 }, 6190 6191 _destroy: function() { 6192 this._callChildMethod( "destroy" ); 6193 this.childWidgets.removeData( "ui-controlgroup-data" ); 6194 this.element.removeAttr( "role" ); 6195 if ( this.options.items.controlgroupLabel ) { 6196 this.element 6197 .find( this.options.items.controlgroupLabel ) 6198 .find( ".ui-controlgroup-label-contents" ) 6199 .contents().unwrap(); 6200 } 6201 }, 6202 6203 _initWidgets: function() { 6204 var that = this, 6205 childWidgets = []; 6206 6207 // First we iterate over each of the items options 6208 $.each( this.options.items, function( widget, selector ) { 6209 var labels; 6210 var options = {}; 6211 6212 // Make sure the widget has a selector set 6213 if ( !selector ) { 6214 return; 6215 } 6216 6217 if ( widget === "controlgroupLabel" ) { 6218 labels = that.element.find( selector ); 6219 labels.each( function() { 6220 var element = $( this ); 6221 6222 if ( element.children( ".ui-controlgroup-label-contents" ).length ) { 6223 return; 6224 } 6225 element.contents() 6226 .wrapAll( "<span class='ui-controlgroup-label-contents'></span>" ); 6227 } ); 6228 that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" ); 6229 childWidgets = childWidgets.concat( labels.get() ); 6230 return; 6231 } 6232 6233 // Make sure the widget actually exists 6234 if ( !$.fn[ widget ] ) { 6235 return; 6236 } 6237 6238 // We assume everything is in the middle to start because we can't determine 6239 // first / last elements until all enhancments are done. 6240 if ( that[ "_" + widget + "Options" ] ) { 6241 options = that[ "_" + widget + "Options" ]( "middle" ); 6242 } else { 6243 options = { classes: {} }; 6244 } 6245 6246 // Find instances of this widget inside controlgroup and init them 6247 that.element 6248 .find( selector ) 6249 .each( function() { 6250 var element = $( this ); 6251 var instance = element[ widget ]( "instance" ); 6252 6253 // We need to clone the default options for this type of widget to avoid 6254 // polluting the variable options which has a wider scope than a single widget. 6255 var instanceOptions = $.widget.extend( {}, options ); 6256 6257 // If the button is the child of a spinner ignore it 6258 // TODO: Find a more generic solution 6259 if ( widget === "button" && element.parent( ".ui-spinner" ).length ) { 6260 return; 6261 } 6262 6263 // Create the widget if it doesn't exist 6264 if ( !instance ) { 6265 instance = element[ widget ]()[ widget ]( "instance" ); 6266 } 6267 if ( instance ) { 6268 instanceOptions.classes = 6269 that._resolveClassesValues( instanceOptions.classes, instance ); 6270 } 6271 element[ widget ]( instanceOptions ); 6272 6273 // Store an instance of the controlgroup to be able to reference 6274 // from the outermost element for changing options and refresh 6275 var widgetElement = element[ widget ]( "widget" ); 6276 $.data( widgetElement[ 0 ], "ui-controlgroup-data", 6277 instance ? instance : element[ widget ]( "instance" ) ); 6278 6279 childWidgets.push( widgetElement[ 0 ] ); 6280 } ); 6281 } ); 6282 6283 this.childWidgets = $( $.uniqueSort( childWidgets ) ); 6284 this._addClass( this.childWidgets, "ui-controlgroup-item" ); 6285 }, 6286 6287 _callChildMethod: function( method ) { 6288 this.childWidgets.each( function() { 6289 var element = $( this ), 6290 data = element.data( "ui-controlgroup-data" ); 6291 if ( data && data[ method ] ) { 6292 data[ method ](); 6293 } 6294 } ); 6295 }, 6296 6297 _updateCornerClass: function( element, position ) { 6298 var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all"; 6299 var add = this._buildSimpleOptions( position, "label" ).classes.label; 6300 6301 this._removeClass( element, null, remove ); 6302 this._addClass( element, null, add ); 6303 }, 6304 6305 _buildSimpleOptions: function( position, key ) { 6306 var direction = this.options.direction === "vertical"; 6307 var result = { 6308 classes: {} 6309 }; 6310 result.classes[ key ] = { 6311 "middle": "", 6312 "first": "ui-corner-" + ( direction ? "top" : "left" ), 6313 "last": "ui-corner-" + ( direction ? "bottom" : "right" ), 6314 "only": "ui-corner-all" 6315 }[ position ]; 6316 6317 return result; 6318 }, 6319 6320 _spinnerOptions: function( position ) { 6321 var options = this._buildSimpleOptions( position, "ui-spinner" ); 6322 6323 options.classes[ "ui-spinner-up" ] = ""; 6324 options.classes[ "ui-spinner-down" ] = ""; 6325 6326 return options; 6327 }, 6328 6329 _buttonOptions: function( position ) { 6330 return this._buildSimpleOptions( position, "ui-button" ); 6331 }, 6332 6333 _checkboxradioOptions: function( position ) { 6334 return this._buildSimpleOptions( position, "ui-checkboxradio-label" ); 6335 }, 6336 6337 _selectmenuOptions: function( position ) { 6338 var direction = this.options.direction === "vertical"; 6339 return { 6340 width: direction ? "auto" : false, 6341 classes: { 6342 middle: { 6343 "ui-selectmenu-button-open": "", 6344 "ui-selectmenu-button-closed": "" 6345 }, 6346 first: { 6347 "ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ), 6348 "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" ) 6349 }, 6350 last: { 6351 "ui-selectmenu-button-open": direction ? "" : "ui-corner-tr", 6352 "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" ) 6353 }, 6354 only: { 6355 "ui-selectmenu-button-open": "ui-corner-top", 6356 "ui-selectmenu-button-closed": "ui-corner-all" 6357 } 6358 6359 }[ position ] 6360 }; 6361 }, 6362 6363 _resolveClassesValues: function( classes, instance ) { 6364 var result = {}; 6365 $.each( classes, function( key ) { 6366 var current = instance.options.classes[ key ] || ""; 6367 current = String.prototype.trim.call( current.replace( controlgroupCornerRegex, "" ) ); 6368 result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " ); 6369 } ); 6370 return result; 6371 }, 6372 6373 _setOption: function( key, value ) { 6374 if ( key === "direction" ) { 6375 this._removeClass( "ui-controlgroup-" + this.options.direction ); 6376 } 6377 6378 this._super( key, value ); 6379 if ( key === "disabled" ) { 6380 this._callChildMethod( value ? "disable" : "enable" ); 6381 return; 6382 } 6383 6384 this.refresh(); 6385 }, 6386 6387 refresh: function() { 6388 var children, 6389 that = this; 6390 6391 this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction ); 6392 6393 if ( this.options.direction === "horizontal" ) { 6394 this._addClass( null, "ui-helper-clearfix" ); 6395 } 6396 this._initWidgets(); 6397 6398 children = this.childWidgets; 6399 6400 // We filter here because we need to track all childWidgets not just the visible ones 6401 if ( this.options.onlyVisible ) { 6402 children = children.filter( ":visible" ); 6403 } 6404 6405 if ( children.length ) { 6406 6407 // We do this last because we need to make sure all enhancment is done 6408 // before determining first and last 6409 $.each( [ "first", "last" ], function( index, value ) { 6410 var instance = children[ value ]().data( "ui-controlgroup-data" ); 6411 6412 if ( instance && that[ "_" + instance.widgetName + "Options" ] ) { 6413 var options = that[ "_" + instance.widgetName + "Options" ]( 6414 children.length === 1 ? "only" : value 6415 ); 6416 options.classes = that._resolveClassesValues( options.classes, instance ); 6417 instance.element[ instance.widgetName ]( options ); 6418 } else { 6419 that._updateCornerClass( children[ value ](), value ); 6420 } 6421 } ); 6422 6423 // Finally call the refresh method on each of the child widgets. 6424 this._callChildMethod( "refresh" ); 6425 } 6426 } 6427} ); 6428 6429/*! 6430 * jQuery UI Checkboxradio 1.14.1 6431 * https://jqueryui.com 6432 * 6433 * Copyright OpenJS Foundation and other contributors 6434 * Released under the MIT license. 6435 * https://jquery.org/license 6436 */ 6437 6438//>>label: Checkboxradio 6439//>>group: Widgets 6440//>>description: Enhances a form with multiple themeable checkboxes or radio buttons. 6441//>>docs: https://api.jqueryui.com/checkboxradio/ 6442//>>demos: https://jqueryui.com/checkboxradio/ 6443//>>css.structure: ../../themes/base/core.css 6444//>>css.structure: ../../themes/base/button.css 6445//>>css.structure: ../../themes/base/checkboxradio.css 6446//>>css.theme: ../../themes/base/theme.css 6447 6448 6449$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, { 6450 version: "1.14.1", 6451 options: { 6452 disabled: null, 6453 label: null, 6454 icon: true, 6455 classes: { 6456 "ui-checkboxradio-label": "ui-corner-all", 6457 "ui-checkboxradio-icon": "ui-corner-all" 6458 } 6459 }, 6460 6461 _getCreateOptions: function() { 6462 var disabled, labels, labelContents; 6463 var options = this._super() || {}; 6464 6465 // We read the type here, because it makes more sense to throw a element type error first, 6466 // rather then the error for lack of a label. Often if its the wrong type, it 6467 // won't have a label (e.g. calling on a div, btn, etc) 6468 this._readType(); 6469 6470 labels = this.element.labels(); 6471 6472 // If there are multiple labels, use the last one 6473 this.label = $( labels[ labels.length - 1 ] ); 6474 if ( !this.label.length ) { 6475 $.error( "No label found for checkboxradio widget" ); 6476 } 6477 6478 this.originalLabel = ""; 6479 6480 // We need to get the label text but this may also need to make sure it does not contain the 6481 // input itself. 6482 // The label contents could be text, html, or a mix. We wrap all elements 6483 // and read the wrapper's `innerHTML` to get a string representation of 6484 // the label, without the input as part of it. 6485 labelContents = this.label.contents().not( this.element[ 0 ] ); 6486 6487 if ( labelContents.length ) { 6488 this.originalLabel += labelContents 6489 .clone() 6490 .wrapAll( "<div></div>" ) 6491 .parent() 6492 .html(); 6493 } 6494 6495 // Set the label option if we found label text 6496 if ( this.originalLabel ) { 6497 options.label = this.originalLabel; 6498 } 6499 6500 disabled = this.element[ 0 ].disabled; 6501 if ( disabled != null ) { 6502 options.disabled = disabled; 6503 } 6504 return options; 6505 }, 6506 6507 _create: function() { 6508 var checked = this.element[ 0 ].checked; 6509 6510 this._bindFormResetHandler(); 6511 6512 if ( this.options.disabled == null ) { 6513 this.options.disabled = this.element[ 0 ].disabled; 6514 } 6515 6516 this._setOption( "disabled", this.options.disabled ); 6517 this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" ); 6518 this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" ); 6519 6520 if ( this.type === "radio" ) { 6521 this._addClass( this.label, "ui-checkboxradio-radio-label" ); 6522 } 6523 6524 if ( this.options.label && this.options.label !== this.originalLabel ) { 6525 this._updateLabel(); 6526 } else if ( this.originalLabel ) { 6527 this.options.label = this.originalLabel; 6528 } 6529 6530 this._enhance(); 6531 6532 if ( checked ) { 6533 this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" ); 6534 } 6535 6536 this._on( { 6537 change: "_toggleClasses", 6538 focus: function() { 6539 this._addClass( this.label, null, "ui-state-focus ui-visual-focus" ); 6540 }, 6541 blur: function() { 6542 this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" ); 6543 } 6544 } ); 6545 }, 6546 6547 _readType: function() { 6548 var nodeName = this.element[ 0 ].nodeName.toLowerCase(); 6549 this.type = this.element[ 0 ].type; 6550 if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) { 6551 $.error( "Can't create checkboxradio on element.nodeName=" + nodeName + 6552 " and element.type=" + this.type ); 6553 } 6554 }, 6555 6556 // Support jQuery Mobile enhanced option 6557 _enhance: function() { 6558 this._updateIcon( this.element[ 0 ].checked ); 6559 }, 6560 6561 widget: function() { 6562 return this.label; 6563 }, 6564 6565 _getRadioGroup: function() { 6566 var group; 6567 var name = this.element[ 0 ].name; 6568 var nameSelector = "input[name='" + CSS.escape( name ) + "']"; 6569 6570 if ( !name ) { 6571 return $( [] ); 6572 } 6573 6574 if ( this.form.length ) { 6575 group = $( this.form[ 0 ].elements ).filter( nameSelector ); 6576 } else { 6577 6578 // Not inside a form, check all inputs that also are not inside a form 6579 group = $( nameSelector ).filter( function() { 6580 return $( $( this ).prop( "form" ) ).length === 0; 6581 } ); 6582 } 6583 6584 return group.not( this.element ); 6585 }, 6586 6587 _toggleClasses: function() { 6588 var checked = this.element[ 0 ].checked; 6589 this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked ); 6590 6591 if ( this.options.icon && this.type === "checkbox" ) { 6592 this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked ) 6593 ._toggleClass( this.icon, null, "ui-icon-blank", !checked ); 6594 } 6595 6596 if ( this.type === "radio" ) { 6597 this._getRadioGroup() 6598 .each( function() { 6599 var instance = $( this ).checkboxradio( "instance" ); 6600 6601 if ( instance ) { 6602 instance._removeClass( instance.label, 6603 "ui-checkboxradio-checked", "ui-state-active" ); 6604 } 6605 } ); 6606 } 6607 }, 6608 6609 _destroy: function() { 6610 this._unbindFormResetHandler(); 6611 6612 if ( this.icon ) { 6613 this.icon.remove(); 6614 this.iconSpace.remove(); 6615 } 6616 }, 6617 6618 _setOption: function( key, value ) { 6619 6620 // We don't allow the value to be set to nothing 6621 if ( key === "label" && !value ) { 6622 return; 6623 } 6624 6625 this._super( key, value ); 6626 6627 if ( key === "disabled" ) { 6628 this._toggleClass( this.label, null, "ui-state-disabled", value ); 6629 this.element[ 0 ].disabled = value; 6630 6631 // Don't refresh when setting disabled 6632 return; 6633 } 6634 this.refresh(); 6635 }, 6636 6637 _updateIcon: function( checked ) { 6638 var toAdd = "ui-icon ui-icon-background "; 6639 6640 if ( this.options.icon ) { 6641 if ( !this.icon ) { 6642 this.icon = $( "<span>" ); 6643 this.iconSpace = $( "<span> </span>" ); 6644 this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" ); 6645 } 6646 6647 if ( this.type === "checkbox" ) { 6648 toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank"; 6649 this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" ); 6650 } else { 6651 toAdd += "ui-icon-blank"; 6652 } 6653 this._addClass( this.icon, "ui-checkboxradio-icon", toAdd ); 6654 if ( !checked ) { 6655 this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" ); 6656 } 6657 this.icon.prependTo( this.label ).after( this.iconSpace ); 6658 } else if ( this.icon !== undefined ) { 6659 this.icon.remove(); 6660 this.iconSpace.remove(); 6661 delete this.icon; 6662 } 6663 }, 6664 6665 _updateLabel: function() { 6666 6667 // Remove the contents of the label ( minus the icon, icon space, and input ) 6668 var contents = this.label.contents().not( this.element[ 0 ] ); 6669 if ( this.icon ) { 6670 contents = contents.not( this.icon[ 0 ] ); 6671 } 6672 if ( this.iconSpace ) { 6673 contents = contents.not( this.iconSpace[ 0 ] ); 6674 } 6675 contents.remove(); 6676 6677 this.label.append( this.options.label ); 6678 }, 6679 6680 refresh: function() { 6681 var checked = this.element[ 0 ].checked, 6682 isDisabled = this.element[ 0 ].disabled; 6683 6684 this._updateIcon( checked ); 6685 this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked ); 6686 if ( this.options.label !== null ) { 6687 this._updateLabel(); 6688 } 6689 6690 if ( isDisabled !== this.options.disabled ) { 6691 this._setOptions( { "disabled": isDisabled } ); 6692 } 6693 } 6694 6695} ] ); 6696 6697var widgetsCheckboxradio = $.ui.checkboxradio; 6698 6699 6700/*! 6701 * jQuery UI Button 1.14.1 6702 * https://jqueryui.com 6703 * 6704 * Copyright OpenJS Foundation and other contributors 6705 * Released under the MIT license. 6706 * https://jquery.org/license 6707 */ 6708 6709//>>label: Button 6710//>>group: Widgets 6711//>>description: Enhances a form with themeable buttons. 6712//>>docs: https://api.jqueryui.com/button/ 6713//>>demos: https://jqueryui.com/button/ 6714//>>css.structure: ../../themes/base/core.css 6715//>>css.structure: ../../themes/base/button.css 6716//>>css.theme: ../../themes/base/theme.css 6717 6718 6719$.widget( "ui.button", { 6720 version: "1.14.1", 6721 defaultElement: "<button>", 6722 options: { 6723 classes: { 6724 "ui-button": "ui-corner-all" 6725 }, 6726 disabled: null, 6727 icon: null, 6728 iconPosition: "beginning", 6729 label: null, 6730 showLabel: true 6731 }, 6732 6733 _getCreateOptions: function() { 6734 var disabled, 6735 6736 // This is to support cases like in jQuery Mobile where the base widget does have 6737 // an implementation of _getCreateOptions 6738 options = this._super() || {}; 6739 6740 this.isInput = this.element.is( "input" ); 6741 6742 disabled = this.element[ 0 ].disabled; 6743 if ( disabled != null ) { 6744 options.disabled = disabled; 6745 } 6746 6747 this.originalLabel = this.isInput ? this.element.val() : this.element.html(); 6748 if ( this.originalLabel ) { 6749 options.label = this.originalLabel; 6750 } 6751 6752 return options; 6753 }, 6754 6755 _create: function() { 6756 if ( !this.option.showLabel & !this.options.icon ) { 6757 this.options.showLabel = true; 6758 } 6759 6760 // We have to check the option again here even though we did in _getCreateOptions, 6761 // because null may have been passed on init which would override what was set in 6762 // _getCreateOptions 6763 if ( this.options.disabled == null ) { 6764 this.options.disabled = this.element[ 0 ].disabled || false; 6765 } 6766 6767 this.hasTitle = !!this.element.attr( "title" ); 6768 6769 // Check to see if the label needs to be set or if its already correct 6770 if ( this.options.label && this.options.label !== this.originalLabel ) { 6771 if ( this.isInput ) { 6772 this.element.val( this.options.label ); 6773 } else { 6774 this.element.html( this.options.label ); 6775 } 6776 } 6777 this._addClass( "ui-button", "ui-widget" ); 6778 this._setOption( "disabled", this.options.disabled ); 6779 this._enhance(); 6780 6781 if ( this.element.is( "a" ) ) { 6782 this._on( { 6783 "keyup": function( event ) { 6784 if ( event.keyCode === $.ui.keyCode.SPACE ) { 6785 event.preventDefault(); 6786 6787 // If a native click is available use it, so we 6788 // actually cause navigation. Otherwise, just trigger 6789 // a click event. 6790 if ( this.element[ 0 ].click ) { 6791 this.element[ 0 ].click(); 6792 } else { 6793 this.element.trigger( "click" ); 6794 } 6795 } 6796 } 6797 } ); 6798 } 6799 }, 6800 6801 _enhance: function() { 6802 if ( !this.element.is( "button" ) ) { 6803 this.element.attr( "role", "button" ); 6804 } 6805 6806 if ( this.options.icon ) { 6807 this._updateIcon( "icon", this.options.icon ); 6808 this._updateTooltip(); 6809 } 6810 }, 6811 6812 _updateTooltip: function() { 6813 this.title = this.element.attr( "title" ); 6814 6815 if ( !this.options.showLabel && !this.title ) { 6816 this.element.attr( "title", this.options.label ); 6817 } 6818 }, 6819 6820 _updateIcon: function( option, value ) { 6821 var icon = option !== "iconPosition", 6822 position = icon ? this.options.iconPosition : value, 6823 displayBlock = position === "top" || position === "bottom"; 6824 6825 // Create icon 6826 if ( !this.icon ) { 6827 this.icon = $( "<span>" ); 6828 6829 this._addClass( this.icon, "ui-button-icon", "ui-icon" ); 6830 6831 if ( !this.options.showLabel ) { 6832 this._addClass( "ui-button-icon-only" ); 6833 } 6834 } else if ( icon ) { 6835 6836 // If we are updating the icon remove the old icon class 6837 this._removeClass( this.icon, null, this.options.icon ); 6838 } 6839 6840 // If we are updating the icon add the new icon class 6841 if ( icon ) { 6842 this._addClass( this.icon, null, value ); 6843 } 6844 6845 this._attachIcon( position ); 6846 6847 // If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove 6848 // the iconSpace if there is one. 6849 if ( displayBlock ) { 6850 this._addClass( this.icon, null, "ui-widget-icon-block" ); 6851 if ( this.iconSpace ) { 6852 this.iconSpace.remove(); 6853 } 6854 } else { 6855 6856 // Position is beginning or end so remove the ui-widget-icon-block class and add the 6857 // space if it does not exist 6858 if ( !this.iconSpace ) { 6859 this.iconSpace = $( "<span> </span>" ); 6860 this._addClass( this.iconSpace, "ui-button-icon-space" ); 6861 } 6862 this._removeClass( this.icon, null, "ui-wiget-icon-block" ); 6863 this._attachIconSpace( position ); 6864 } 6865 }, 6866 6867 _destroy: function() { 6868 this.element.removeAttr( "role" ); 6869 6870 if ( this.icon ) { 6871 this.icon.remove(); 6872 } 6873 if ( this.iconSpace ) { 6874 this.iconSpace.remove(); 6875 } 6876 if ( !this.hasTitle ) { 6877 this.element.removeAttr( "title" ); 6878 } 6879 }, 6880 6881 _attachIconSpace: function( iconPosition ) { 6882 this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace ); 6883 }, 6884 6885 _attachIcon: function( iconPosition ) { 6886 this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon ); 6887 }, 6888 6889 _setOptions: function( options ) { 6890 var newShowLabel = options.showLabel === undefined ? 6891 this.options.showLabel : 6892 options.showLabel, 6893 newIcon = options.icon === undefined ? this.options.icon : options.icon; 6894 6895 if ( !newShowLabel && !newIcon ) { 6896 options.showLabel = true; 6897 } 6898 this._super( options ); 6899 }, 6900 6901 _setOption: function( key, value ) { 6902 if ( key === "icon" ) { 6903 if ( value ) { 6904 this._updateIcon( key, value ); 6905 } else if ( this.icon ) { 6906 this.icon.remove(); 6907 if ( this.iconSpace ) { 6908 this.iconSpace.remove(); 6909 } 6910 } 6911 } 6912 6913 if ( key === "iconPosition" ) { 6914 this._updateIcon( key, value ); 6915 } 6916 6917 // Make sure we can't end up with a button that has neither text nor icon 6918 if ( key === "showLabel" ) { 6919 this._toggleClass( "ui-button-icon-only", null, !value ); 6920 this._updateTooltip(); 6921 } 6922 6923 if ( key === "label" ) { 6924 if ( this.isInput ) { 6925 this.element.val( value ); 6926 } else { 6927 6928 // If there is an icon, append it, else nothing then append the value 6929 // this avoids removal of the icon when setting label text 6930 this.element.html( value ); 6931 if ( this.icon ) { 6932 this._attachIcon( this.options.iconPosition ); 6933 this._attachIconSpace( this.options.iconPosition ); 6934 } 6935 } 6936 } 6937 6938 this._super( key, value ); 6939 6940 if ( key === "disabled" ) { 6941 this._toggleClass( null, "ui-state-disabled", value ); 6942 this.element[ 0 ].disabled = value; 6943 if ( value ) { 6944 this.element.trigger( "blur" ); 6945 } 6946 } 6947 }, 6948 6949 refresh: function() { 6950 6951 // Make sure to only check disabled if its an element that supports this otherwise 6952 // check for the disabled class to determine state 6953 var isDisabled = this.element.is( "input, button" ) ? 6954 this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" ); 6955 6956 if ( isDisabled !== this.options.disabled ) { 6957 this._setOptions( { disabled: isDisabled } ); 6958 } 6959 6960 this._updateTooltip(); 6961 } 6962} ); 6963 6964// DEPRECATED 6965if ( $.uiBackCompat === true ) { 6966 6967 // Text and Icons options 6968 $.widget( "ui.button", $.ui.button, { 6969 options: { 6970 text: true, 6971 icons: { 6972 primary: null, 6973 secondary: null 6974 } 6975 }, 6976 6977 _create: function() { 6978 if ( this.options.showLabel && !this.options.text ) { 6979 this.options.showLabel = this.options.text; 6980 } 6981 if ( !this.options.showLabel && this.options.text ) { 6982 this.options.text = this.options.showLabel; 6983 } 6984 if ( !this.options.icon && ( this.options.icons.primary || 6985 this.options.icons.secondary ) ) { 6986 if ( this.options.icons.primary ) { 6987 this.options.icon = this.options.icons.primary; 6988 } else { 6989 this.options.icon = this.options.icons.secondary; 6990 this.options.iconPosition = "end"; 6991 } 6992 } else if ( this.options.icon ) { 6993 this.options.icons.primary = this.options.icon; 6994 } 6995 this._super(); 6996 }, 6997 6998 _setOption: function( key, value ) { 6999 if ( key === "text" ) { 7000 this._super( "showLabel", value ); 7001 return; 7002 } 7003 if ( key === "showLabel" ) { 7004 this.options.text = value; 7005 } 7006 if ( key === "icon" ) { 7007 this.options.icons.primary = value; 7008 } 7009 if ( key === "icons" ) { 7010 if ( value.primary ) { 7011 this._super( "icon", value.primary ); 7012 this._super( "iconPosition", "beginning" ); 7013 } else if ( value.secondary ) { 7014 this._super( "icon", value.secondary ); 7015 this._super( "iconPosition", "end" ); 7016 } 7017 } 7018 this._superApply( arguments ); 7019 } 7020 } ); 7021 7022 $.fn.button = ( function( orig ) { 7023 return function( options ) { 7024 var isMethodCall = typeof options === "string"; 7025 var args = Array.prototype.slice.call( arguments, 1 ); 7026 var returnValue = this; 7027 7028 if ( isMethodCall ) { 7029 7030 // If this is an empty collection, we need to have the instance method 7031 // return undefined instead of the jQuery instance 7032 if ( !this.length && options === "instance" ) { 7033 returnValue = undefined; 7034 } else { 7035 this.each( function() { 7036 var methodValue; 7037 var type = $( this ).attr( "type" ); 7038 var name = type !== "checkbox" && type !== "radio" ? 7039 "button" : 7040 "checkboxradio"; 7041 var instance = $.data( this, "ui-" + name ); 7042 7043 if ( options === "instance" ) { 7044 returnValue = instance; 7045 return false; 7046 } 7047 7048 if ( !instance ) { 7049 return $.error( "cannot call methods on button" + 7050 " prior to initialization; " + 7051 "attempted to call method '" + options + "'" ); 7052 } 7053 7054 if ( typeof instance[ options ] !== "function" || 7055 options.charAt( 0 ) === "_" ) { 7056 return $.error( "no such method '" + options + "' for button" + 7057 " widget instance" ); 7058 } 7059 7060 methodValue = instance[ options ].apply( instance, args ); 7061 7062 if ( methodValue !== instance && methodValue !== undefined ) { 7063 returnValue = methodValue && methodValue.jquery ? 7064 returnValue.pushStack( methodValue.get() ) : 7065 methodValue; 7066 return false; 7067 } 7068 } ); 7069 } 7070 } else { 7071 7072 // Allow multiple hashes to be passed on init 7073 if ( args.length ) { 7074 options = $.widget.extend.apply( null, [ options ].concat( args ) ); 7075 } 7076 7077 this.each( function() { 7078 var type = $( this ).attr( "type" ); 7079 var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio"; 7080 var instance = $.data( this, "ui-" + name ); 7081 7082 if ( instance ) { 7083 instance.option( options || {} ); 7084 if ( instance._init ) { 7085 instance._init(); 7086 } 7087 } else { 7088 if ( name === "button" ) { 7089 orig.call( $( this ), options ); 7090 return; 7091 } 7092 7093 $( this ).checkboxradio( $.extend( { icon: false }, options ) ); 7094 } 7095 } ); 7096 } 7097 7098 return returnValue; 7099 }; 7100 } )( $.fn.button ); 7101 7102 $.fn.buttonset = function() { 7103 if ( !$.ui.controlgroup ) { 7104 $.error( "Controlgroup widget missing" ); 7105 } 7106 if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) { 7107 return this.controlgroup.apply( this, 7108 [ arguments[ 0 ], "items.button", arguments[ 2 ] ] ); 7109 } 7110 if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) { 7111 return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] ); 7112 } 7113 if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) { 7114 arguments[ 0 ].items = { 7115 button: arguments[ 0 ].items 7116 }; 7117 } 7118 return this.controlgroup.apply( this, arguments ); 7119 }; 7120} 7121 7122var widgetsButton = $.ui.button; 7123 7124 7125/* eslint-disable max-len, camelcase */ 7126/*! 7127 * jQuery UI Datepicker 1.14.1 7128 * https://jqueryui.com 7129 * 7130 * Copyright OpenJS Foundation and other contributors 7131 * Released under the MIT license. 7132 * https://jquery.org/license 7133 */ 7134 7135//>>label: Datepicker 7136//>>group: Widgets 7137//>>description: Displays a calendar from an input or inline for selecting dates. 7138//>>docs: https://api.jqueryui.com/datepicker/ 7139//>>demos: https://jqueryui.com/datepicker/ 7140//>>css.structure: ../../themes/base/core.css 7141//>>css.structure: ../../themes/base/datepicker.css 7142//>>css.theme: ../../themes/base/theme.css 7143 7144 7145$.extend( $.ui, { datepicker: { version: "1.14.1" } } ); 7146 7147var datepicker_instActive; 7148 7149function datepicker_getZindex( elem ) { 7150 var position, value; 7151 while ( elem.length && elem[ 0 ] !== document ) { 7152 7153 // Ignore z-index if position is set to a value where z-index is ignored by the browser 7154 // This makes behavior of this function consistent across browsers 7155 // WebKit always returns auto if the element is positioned 7156 position = elem.css( "position" ); 7157 if ( position === "absolute" || position === "relative" || position === "fixed" ) { 7158 7159 // IE returns 0 when zIndex is not specified 7160 // other browsers return a string 7161 // we ignore the case of nested elements with an explicit value of 0 7162 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 7163 value = parseInt( elem.css( "zIndex" ), 10 ); 7164 if ( !isNaN( value ) && value !== 0 ) { 7165 return value; 7166 } 7167 } 7168 elem = elem.parent(); 7169 } 7170 7171 return 0; 7172} 7173 7174/* Date picker manager. 7175 Use the singleton instance of this class, $.datepicker, to interact with the date picker. 7176 Settings for (groups of) date pickers are maintained in an instance object, 7177 allowing multiple different settings on the same page. */ 7178 7179function Datepicker() { 7180 this._curInst = null; // The current instance in use 7181 this._keyEvent = false; // If the last event was a key event 7182 this._disabledInputs = []; // List of date picker inputs that have been disabled 7183 this._datepickerShowing = false; // True if the popup picker is showing , false if not 7184 this._inDialog = false; // True if showing within a "dialog", false if not 7185 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division 7186 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class 7187 this._appendClass = "ui-datepicker-append"; // The name of the append marker class 7188 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class 7189 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class 7190 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class 7191 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class 7192 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class 7193 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class 7194 this.regional = []; // Available regional settings, indexed by language code 7195 this.regional[ "" ] = { // Default regional settings 7196 closeText: "Done", // Display text for close link 7197 prevText: "Prev", // Display text for previous month link 7198 nextText: "Next", // Display text for next month link 7199 currentText: "Today", // Display text for current month link 7200 monthNames: [ "January", "February", "March", "April", "May", "June", 7201 "July", "August", "September", "October", "November", "December" ], // Names of months for drop-down and formatting 7202 monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting 7203 dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting 7204 dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting 7205 dayNamesMin: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], // Column headings for days starting at Sunday 7206 weekHeader: "Wk", // Column header for week of the year 7207 dateFormat: "mm/dd/yy", // See format options on parseDate 7208 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... 7209 isRTL: false, // True if right-to-left language, false if left-to-right 7210 showMonthAfterYear: false, // True if the year select precedes month, false for month then year 7211 yearSuffix: "", // Additional text to append to the year in the month headers, 7212 selectMonthLabel: "Select month", // Invisible label for month selector 7213 selectYearLabel: "Select year" // Invisible label for year selector 7214 }; 7215 this._defaults = { // Global defaults for all the date picker instances 7216 showOn: "focus", // "focus" for popup on focus, 7217 // "button" for trigger button, or "both" for either 7218 showAnim: "fadeIn", // Name of jQuery animation for popup 7219 showOptions: {}, // Options for enhanced animations 7220 defaultDate: null, // Used when field is blank: actual date, 7221 // +/-number for offset from today, null for today 7222 appendText: "", // Display text following the input box, e.g. showing the format 7223 buttonText: "...", // Text for trigger button 7224 buttonImage: "", // URL for trigger button image 7225 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button 7226 hideIfNoPrevNext: false, // True to hide next/previous month links 7227 // if not applicable, false to just disable them 7228 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links 7229 gotoCurrent: false, // True if today link goes back to current selection instead 7230 changeMonth: false, // True if month can be selected directly, false if only prev/next 7231 changeYear: false, // True if year can be selected directly, false if only prev/next 7232 yearRange: "c-10:c+10", // Range of years to display in drop-down, 7233 // either relative to today's year (-nn:+nn), relative to currently displayed year 7234 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) 7235 showOtherMonths: false, // True to show dates in other months, false to leave blank 7236 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable 7237 showWeek: false, // True to show week of the year, false to not show it 7238 calculateWeek: this.iso8601Week, // How to calculate the week of the year, 7239 // takes a Date and returns the number of the week for it 7240 shortYearCutoff: "+10", // Short year values < this are in the current century, 7241 // > this are in the previous century, 7242 // string value starting with "+" for current year + value 7243 minDate: null, // The earliest selectable date, or null for no limit 7244 maxDate: null, // The latest selectable date, or null for no limit 7245 duration: "fast", // Duration of display/closure 7246 beforeShowDay: null, // Function that takes a date and returns an array with 7247 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "", 7248 // [2] = cell title (optional), e.g. $.datepicker.noWeekends 7249 beforeShow: null, // Function that takes an input field and 7250 // returns a set of custom settings for the date picker 7251 onSelect: null, // Define a callback function when a date is selected 7252 onChangeMonthYear: null, // Define a callback function when the month or year is changed 7253 onClose: null, // Define a callback function when the datepicker is closed 7254 onUpdateDatepicker: null, // Define a callback function when the datepicker is updated 7255 numberOfMonths: 1, // Number of months to show at a time 7256 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) 7257 stepMonths: 1, // Number of months to step back/forward 7258 stepBigMonths: 12, // Number of months to step back/forward for the big links 7259 altField: "", // Selector for an alternate field to store selected dates into 7260 altFormat: "", // The date format to use for the alternate field 7261 constrainInput: true, // The input is constrained by the current date format 7262 showButtonPanel: false, // True to show button panel, false to not show it 7263 autoSize: false, // True to size the input for the date format, false to leave as is 7264 disabled: false // The initial disabled state 7265 }; 7266 $.extend( this._defaults, this.regional[ "" ] ); 7267 this.regional.en = $.extend( true, {}, this.regional[ "" ] ); 7268 this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en ); 7269 this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ); 7270} 7271 7272$.extend( Datepicker.prototype, { 7273 7274 /* Class name added to elements to indicate already configured with a date picker. */ 7275 markerClassName: "hasDatepicker", 7276 7277 //Keep track of the maximum number of rows displayed (see #7043) 7278 maxRows: 4, 7279 7280 // TODO rename to "widget" when switching to widget factory 7281 _widgetDatepicker: function() { 7282 return this.dpDiv; 7283 }, 7284 7285 /* Override the default settings for all instances of the date picker. 7286 * @param settings object - the new settings to use as defaults (anonymous object) 7287 * @return the manager object 7288 */ 7289 setDefaults: function( settings ) { 7290 datepicker_extendRemove( this._defaults, settings || {} ); 7291 return this; 7292 }, 7293 7294 /* Attach the date picker to a jQuery selection. 7295 * @param target element - the target input field or division or span 7296 * @param settings object - the new settings to use for this date picker instance (anonymous) 7297 */ 7298 _attachDatepicker: function( target, settings ) { 7299 var nodeName, inline, inst; 7300 nodeName = target.nodeName.toLowerCase(); 7301 inline = ( nodeName === "div" || nodeName === "span" ); 7302 if ( !target.id ) { 7303 this.uuid += 1; 7304 target.id = "dp" + this.uuid; 7305 } 7306 inst = this._newInst( $( target ), inline ); 7307 inst.settings = $.extend( {}, settings || {} ); 7308 if ( nodeName === "input" ) { 7309 this._connectDatepicker( target, inst ); 7310 } else if ( inline ) { 7311 this._inlineDatepicker( target, inst ); 7312 } 7313 }, 7314 7315 /* Create a new instance object. */ 7316 _newInst: function( target, inline ) { 7317 var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars 7318 return { id: id, input: target, // associated target 7319 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection 7320 drawMonth: 0, drawYear: 0, // month being drawn 7321 inline: inline, // is datepicker inline or not 7322 dpDiv: ( !inline ? this.dpDiv : // presentation div 7323 datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) }; 7324 }, 7325 7326 /* Attach the date picker to an input field. */ 7327 _connectDatepicker: function( target, inst ) { 7328 var input = $( target ); 7329 inst.append = $( [] ); 7330 inst.trigger = $( [] ); 7331 if ( input.hasClass( this.markerClassName ) ) { 7332 return; 7333 } 7334 this._attachments( input, inst ); 7335 input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ). 7336 on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp ); 7337 this._autoSize( inst ); 7338 $.data( target, "datepicker", inst ); 7339 7340 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) 7341 if ( inst.settings.disabled ) { 7342 this._disableDatepicker( target ); 7343 } 7344 }, 7345 7346 /* Make attachments based on settings. */ 7347 _attachments: function( input, inst ) { 7348 var showOn, buttonText, buttonImage, 7349 appendText = this._get( inst, "appendText" ), 7350 isRTL = this._get( inst, "isRTL" ); 7351 7352 if ( inst.append ) { 7353 inst.append.remove(); 7354 } 7355 if ( appendText ) { 7356 inst.append = $( "<span>" ) 7357 .addClass( this._appendClass ) 7358 .text( appendText ); 7359 input[ isRTL ? "before" : "after" ]( inst.append ); 7360 } 7361 7362 input.off( "focus", this._showDatepicker ); 7363 7364 if ( inst.trigger ) { 7365 inst.trigger.remove(); 7366 } 7367 7368 showOn = this._get( inst, "showOn" ); 7369 if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field 7370 input.on( "focus", this._showDatepicker ); 7371 } 7372 if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked 7373 buttonText = this._get( inst, "buttonText" ); 7374 buttonImage = this._get( inst, "buttonImage" ); 7375 7376 if ( this._get( inst, "buttonImageOnly" ) ) { 7377 inst.trigger = $( "<img>" ) 7378 .addClass( this._triggerClass ) 7379 .attr( { 7380 src: buttonImage, 7381 alt: buttonText, 7382 title: buttonText 7383 } ); 7384 } else { 7385 inst.trigger = $( "<button type='button'>" ) 7386 .addClass( this._triggerClass ); 7387 if ( buttonImage ) { 7388 inst.trigger.html( 7389 $( "<img>" ) 7390 .attr( { 7391 src: buttonImage, 7392 alt: buttonText, 7393 title: buttonText 7394 } ) 7395 ); 7396 } else { 7397 inst.trigger.text( buttonText ); 7398 } 7399 } 7400 7401 input[ isRTL ? "before" : "after" ]( inst.trigger ); 7402 inst.trigger.on( "click", function() { 7403 if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) { 7404 $.datepicker._hideDatepicker(); 7405 } else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) { 7406 $.datepicker._hideDatepicker(); 7407 $.datepicker._showDatepicker( input[ 0 ] ); 7408 } else { 7409 $.datepicker._showDatepicker( input[ 0 ] ); 7410 } 7411 return false; 7412 } ); 7413 } 7414 }, 7415 7416 /* Apply the maximum length for the date format. */ 7417 _autoSize: function( inst ) { 7418 if ( this._get( inst, "autoSize" ) && !inst.inline ) { 7419 var findMax, max, maxI, i, 7420 date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits 7421 dateFormat = this._get( inst, "dateFormat" ); 7422 7423 if ( dateFormat.match( /[DM]/ ) ) { 7424 findMax = function( names ) { 7425 max = 0; 7426 maxI = 0; 7427 for ( i = 0; i < names.length; i++ ) { 7428 if ( names[ i ].length > max ) { 7429 max = names[ i ].length; 7430 maxI = i; 7431 } 7432 } 7433 return maxI; 7434 }; 7435 date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ? 7436 "monthNames" : "monthNamesShort" ) ) ) ); 7437 date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ? 7438 "dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() ); 7439 } 7440 inst.input.attr( "size", this._formatDate( inst, date ).length ); 7441 } 7442 }, 7443 7444 /* Attach an inline date picker to a div. */ 7445 _inlineDatepicker: function( target, inst ) { 7446 var divSpan = $( target ); 7447 if ( divSpan.hasClass( this.markerClassName ) ) { 7448 return; 7449 } 7450 divSpan.addClass( this.markerClassName ).append( inst.dpDiv ); 7451 $.data( target, "datepicker", inst ); 7452 this._setDate( inst, this._getDefaultDate( inst ), true ); 7453 this._updateDatepicker( inst ); 7454 this._updateAlternate( inst ); 7455 7456 //If disabled option is true, disable the datepicker before showing it (see ticket #5665) 7457 if ( inst.settings.disabled ) { 7458 this._disableDatepicker( target ); 7459 } 7460 7461 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements 7462 // https://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height 7463 inst.dpDiv.css( "display", "block" ); 7464 }, 7465 7466 /* Pop-up the date picker in a "dialog" box. 7467 * @param input element - ignored 7468 * @param date string or Date - the initial date to display 7469 * @param onSelect function - the function to call when a date is selected 7470 * @param settings object - update the dialog date picker instance's settings (anonymous object) 7471 * @param pos int[2] - coordinates for the dialog's position within the screen or 7472 * event - with x/y coordinates or 7473 * leave empty for default (screen centre) 7474 * @return the manager object 7475 */ 7476 _dialogDatepicker: function( input, date, onSelect, settings, pos ) { 7477 var id, browserWidth, browserHeight, scrollX, scrollY, 7478 inst = this._dialogInst; // internal instance 7479 7480 if ( !inst ) { 7481 this.uuid += 1; 7482 id = "dp" + this.uuid; 7483 this._dialogInput = $( "<input type='text' id='" + id + 7484 "' style='position: absolute; top: -100px; width: 0px;'/>" ); 7485 this._dialogInput.on( "keydown", this._doKeyDown ); 7486 $( "body" ).append( this._dialogInput ); 7487 inst = this._dialogInst = this._newInst( this._dialogInput, false ); 7488 inst.settings = {}; 7489 $.data( this._dialogInput[ 0 ], "datepicker", inst ); 7490 } 7491 datepicker_extendRemove( inst.settings, settings || {} ); 7492 date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date ); 7493 this._dialogInput.val( date ); 7494 7495 this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null ); 7496 if ( !this._pos ) { 7497 browserWidth = document.documentElement.clientWidth; 7498 browserHeight = document.documentElement.clientHeight; 7499 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; 7500 scrollY = document.documentElement.scrollTop || document.body.scrollTop; 7501 this._pos = // should use actual width/height below 7502 [ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ]; 7503 } 7504 7505 // Move input on screen for focus, but hidden behind dialog 7506 this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" ); 7507 inst.settings.onSelect = onSelect; 7508 this._inDialog = true; 7509 this.dpDiv.addClass( this._dialogClass ); 7510 this._showDatepicker( this._dialogInput[ 0 ] ); 7511 if ( $.blockUI ) { 7512 $.blockUI( this.dpDiv ); 7513 } 7514 $.data( this._dialogInput[ 0 ], "datepicker", inst ); 7515 return this; 7516 }, 7517 7518 /* Detach a datepicker from its control. 7519 * @param target element - the target input field or division or span 7520 */ 7521 _destroyDatepicker: function( target ) { 7522 var nodeName, 7523 $target = $( target ), 7524 inst = $.data( target, "datepicker" ); 7525 7526 if ( !$target.hasClass( this.markerClassName ) ) { 7527 return; 7528 } 7529 7530 nodeName = target.nodeName.toLowerCase(); 7531 $.removeData( target, "datepicker" ); 7532 if ( nodeName === "input" ) { 7533 inst.append.remove(); 7534 inst.trigger.remove(); 7535 $target.removeClass( this.markerClassName ). 7536 off( "focus", this._showDatepicker ). 7537 off( "keydown", this._doKeyDown ). 7538 off( "keypress", this._doKeyPress ). 7539 off( "keyup", this._doKeyUp ); 7540 } else if ( nodeName === "div" || nodeName === "span" ) { 7541 $target.removeClass( this.markerClassName ).empty(); 7542 } 7543 7544 $.datepicker._hideDatepicker(); 7545 if ( datepicker_instActive === inst ) { 7546 datepicker_instActive = null; 7547 this._curInst = null; 7548 } 7549 }, 7550 7551 /* Enable the date picker to a jQuery selection. 7552 * @param target element - the target input field or division or span 7553 */ 7554 _enableDatepicker: function( target ) { 7555 var nodeName, inline, 7556 $target = $( target ), 7557 inst = $.data( target, "datepicker" ); 7558 7559 if ( !$target.hasClass( this.markerClassName ) ) { 7560 return; 7561 } 7562 7563 nodeName = target.nodeName.toLowerCase(); 7564 if ( nodeName === "input" ) { 7565 target.disabled = false; 7566 inst.trigger.filter( "button" ). 7567 each( function() { 7568 this.disabled = false; 7569 } ).end(). 7570 filter( "img" ).css( { opacity: "1.0", cursor: "" } ); 7571 } else if ( nodeName === "div" || nodeName === "span" ) { 7572 inline = $target.children( "." + this._inlineClass ); 7573 inline.children().removeClass( "ui-state-disabled" ); 7574 inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ). 7575 prop( "disabled", false ); 7576 } 7577 this._disabledInputs = $.map( this._disabledInputs, 7578 7579 // Delete entry 7580 function( value ) { 7581 return ( value === target ? null : value ); 7582 } ); 7583 }, 7584 7585 /* Disable the date picker to a jQuery selection. 7586 * @param target element - the target input field or division or span 7587 */ 7588 _disableDatepicker: function( target ) { 7589 var nodeName, inline, 7590 $target = $( target ), 7591 inst = $.data( target, "datepicker" ); 7592 7593 if ( !$target.hasClass( this.markerClassName ) ) { 7594 return; 7595 } 7596 7597 nodeName = target.nodeName.toLowerCase(); 7598 if ( nodeName === "input" ) { 7599 target.disabled = true; 7600 inst.trigger.filter( "button" ). 7601 each( function() { 7602 this.disabled = true; 7603 } ).end(). 7604 filter( "img" ).css( { opacity: "0.5", cursor: "default" } ); 7605 } else if ( nodeName === "div" || nodeName === "span" ) { 7606 inline = $target.children( "." + this._inlineClass ); 7607 inline.children().addClass( "ui-state-disabled" ); 7608 inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ). 7609 prop( "disabled", true ); 7610 } 7611 this._disabledInputs = $.map( this._disabledInputs, 7612 7613 // Delete entry 7614 function( value ) { 7615 return ( value === target ? null : value ); 7616 } ); 7617 this._disabledInputs[ this._disabledInputs.length ] = target; 7618 }, 7619 7620 /* Is the first field in a jQuery collection disabled as a datepicker? 7621 * @param target element - the target input field or division or span 7622 * @return boolean - true if disabled, false if enabled 7623 */ 7624 _isDisabledDatepicker: function( target ) { 7625 if ( !target ) { 7626 return false; 7627 } 7628 for ( var i = 0; i < this._disabledInputs.length; i++ ) { 7629 if ( this._disabledInputs[ i ] === target ) { 7630 return true; 7631 } 7632 } 7633 return false; 7634 }, 7635 7636 /* Retrieve the instance data for the target control. 7637 * @param target element - the target input field or division or span 7638 * @return object - the associated instance data 7639 * @throws error if a jQuery problem getting data 7640 */ 7641 _getInst: function( target ) { 7642 try { 7643 return $.data( target, "datepicker" ); 7644 } catch ( err ) { 7645 throw "Missing instance data for this datepicker"; 7646 } 7647 }, 7648 7649 /* Update or retrieve the settings for a date picker attached to an input field or division. 7650 * @param target element - the target input field or division or span 7651 * @param name object - the new settings to update or 7652 * string - the name of the setting to change or retrieve, 7653 * when retrieving also "all" for all instance settings or 7654 * "defaults" for all global defaults 7655 * @param value any - the new value for the setting 7656 * (omit if above is an object or to retrieve a value) 7657 */ 7658 _optionDatepicker: function( target, name, value ) { 7659 var settings, date, minDate, maxDate, 7660 inst = this._getInst( target ); 7661 7662 if ( arguments.length === 2 && typeof name === "string" ) { 7663 return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) : 7664 ( inst ? ( name === "all" ? $.extend( {}, inst.settings ) : 7665 this._get( inst, name ) ) : null ) ); 7666 } 7667 7668 settings = name || {}; 7669 if ( typeof name === "string" ) { 7670 settings = {}; 7671 settings[ name ] = value; 7672 } 7673 7674 if ( inst ) { 7675 if ( this._curInst === inst ) { 7676 this._hideDatepicker(); 7677 } 7678 7679 date = this._getDateDatepicker( target, true ); 7680 minDate = this._getMinMaxDate( inst, "min" ); 7681 maxDate = this._getMinMaxDate( inst, "max" ); 7682 datepicker_extendRemove( inst.settings, settings ); 7683 7684 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided 7685 if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) { 7686 inst.settings.minDate = this._formatDate( inst, minDate ); 7687 } 7688 if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) { 7689 inst.settings.maxDate = this._formatDate( inst, maxDate ); 7690 } 7691 if ( "disabled" in settings ) { 7692 if ( settings.disabled ) { 7693 this._disableDatepicker( target ); 7694 } else { 7695 this._enableDatepicker( target ); 7696 } 7697 } 7698 this._attachments( $( target ), inst ); 7699 this._autoSize( inst ); 7700 this._setDate( inst, date ); 7701 this._updateAlternate( inst ); 7702 this._updateDatepicker( inst ); 7703 } 7704 }, 7705 7706 // Change method deprecated 7707 _changeDatepicker: function( target, name, value ) { 7708 this._optionDatepicker( target, name, value ); 7709 }, 7710 7711 /* Redraw the date picker attached to an input field or division. 7712 * @param target element - the target input field or division or span 7713 */ 7714 _refreshDatepicker: function( target ) { 7715 var inst = this._getInst( target ); 7716 if ( inst ) { 7717 this._updateDatepicker( inst ); 7718 } 7719 }, 7720 7721 /* Set the dates for a jQuery selection. 7722 * @param target element - the target input field or division or span 7723 * @param date Date - the new date 7724 */ 7725 _setDateDatepicker: function( target, date ) { 7726 var inst = this._getInst( target ); 7727 if ( inst ) { 7728 this._setDate( inst, date ); 7729 this._updateDatepicker( inst ); 7730 this._updateAlternate( inst ); 7731 } 7732 }, 7733 7734 /* Get the date(s) for the first entry in a jQuery selection. 7735 * @param target element - the target input field or division or span 7736 * @param noDefault boolean - true if no default date is to be used 7737 * @return Date - the current date 7738 */ 7739 _getDateDatepicker: function( target, noDefault ) { 7740 var inst = this._getInst( target ); 7741 if ( inst && !inst.inline ) { 7742 this._setDateFromField( inst, noDefault ); 7743 } 7744 return ( inst ? this._getDate( inst ) : null ); 7745 }, 7746 7747 /* Handle keystrokes. */ 7748 _doKeyDown: function( event ) { 7749 var onSelect, dateStr, sel, 7750 inst = $.datepicker._getInst( event.target ), 7751 handled = true, 7752 isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" ); 7753 7754 inst._keyEvent = true; 7755 if ( $.datepicker._datepickerShowing ) { 7756 switch ( event.keyCode ) { 7757 case 9: $.datepicker._hideDatepicker(); 7758 handled = false; 7759 break; // hide on tab out 7760 case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." + 7761 $.datepicker._currentClass + ")", inst.dpDiv ); 7762 if ( sel[ 0 ] ) { 7763 $.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] ); 7764 } 7765 7766 onSelect = $.datepicker._get( inst, "onSelect" ); 7767 if ( onSelect ) { 7768 dateStr = $.datepicker._formatDate( inst ); 7769 7770 // Trigger custom callback 7771 onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] ); 7772 } else { 7773 $.datepicker._hideDatepicker(); 7774 } 7775 7776 return false; // don't submit the form 7777 case 27: $.datepicker._hideDatepicker(); 7778 break; // hide on escape 7779 case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 7780 -$.datepicker._get( inst, "stepBigMonths" ) : 7781 -$.datepicker._get( inst, "stepMonths" ) ), "M" ); 7782 break; // previous month/year on page up/+ ctrl 7783 case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 7784 +$.datepicker._get( inst, "stepBigMonths" ) : 7785 +$.datepicker._get( inst, "stepMonths" ) ), "M" ); 7786 break; // next month/year on page down/+ ctrl 7787 case 35: if ( event.ctrlKey || event.metaKey ) { 7788 $.datepicker._clearDate( event.target ); 7789 } 7790 handled = event.ctrlKey || event.metaKey; 7791 break; // clear on ctrl or command +end 7792 case 36: if ( event.ctrlKey || event.metaKey ) { 7793 $.datepicker._gotoToday( event.target ); 7794 } 7795 handled = event.ctrlKey || event.metaKey; 7796 break; // current on ctrl or command +home 7797 case 37: if ( event.ctrlKey || event.metaKey ) { 7798 $.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" ); 7799 } 7800 handled = event.ctrlKey || event.metaKey; 7801 7802 // -1 day on ctrl or command +left 7803 if ( event.originalEvent.altKey ) { 7804 $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 7805 -$.datepicker._get( inst, "stepBigMonths" ) : 7806 -$.datepicker._get( inst, "stepMonths" ) ), "M" ); 7807 } 7808 7809 // next month/year on alt +left on Mac 7810 break; 7811 case 38: if ( event.ctrlKey || event.metaKey ) { 7812 $.datepicker._adjustDate( event.target, -7, "D" ); 7813 } 7814 handled = event.ctrlKey || event.metaKey; 7815 break; // -1 week on ctrl or command +up 7816 case 39: if ( event.ctrlKey || event.metaKey ) { 7817 $.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" ); 7818 } 7819 handled = event.ctrlKey || event.metaKey; 7820 7821 // +1 day on ctrl or command +right 7822 if ( event.originalEvent.altKey ) { 7823 $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 7824 +$.datepicker._get( inst, "stepBigMonths" ) : 7825 +$.datepicker._get( inst, "stepMonths" ) ), "M" ); 7826 } 7827 7828 // next month/year on alt +right 7829 break; 7830 case 40: if ( event.ctrlKey || event.metaKey ) { 7831 $.datepicker._adjustDate( event.target, +7, "D" ); 7832 } 7833 handled = event.ctrlKey || event.metaKey; 7834 break; // +1 week on ctrl or command +down 7835 default: handled = false; 7836 } 7837 } else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home 7838 $.datepicker._showDatepicker( this ); 7839 } else { 7840 handled = false; 7841 } 7842 7843 if ( handled ) { 7844 event.preventDefault(); 7845 event.stopPropagation(); 7846 } 7847 }, 7848 7849 /* Filter entered characters - based on date format. */ 7850 _doKeyPress: function( event ) { 7851 var chars, chr, 7852 inst = $.datepicker._getInst( event.target ); 7853 7854 if ( $.datepicker._get( inst, "constrainInput" ) ) { 7855 chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) ); 7856 chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode ); 7857 return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 ); 7858 } 7859 }, 7860 7861 /* Synchronise manual entry and field/alternate field. */ 7862 _doKeyUp: function( event ) { 7863 var date, 7864 inst = $.datepicker._getInst( event.target ); 7865 7866 if ( inst.input.val() !== inst.lastVal ) { 7867 try { 7868 date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ), 7869 ( inst.input ? inst.input.val() : null ), 7870 $.datepicker._getFormatConfig( inst ) ); 7871 7872 if ( date ) { // only if valid 7873 $.datepicker._setDateFromField( inst ); 7874 $.datepicker._updateAlternate( inst ); 7875 $.datepicker._updateDatepicker( inst ); 7876 } 7877 } catch ( err ) { 7878 } 7879 } 7880 return true; 7881 }, 7882 7883 /* Pop-up the date picker for a given input field. 7884 * If false returned from beforeShow event handler do not show. 7885 * @param input element - the input field attached to the date picker or 7886 * event - if triggered by focus 7887 */ 7888 _showDatepicker: function( input ) { 7889 input = input.target || input; 7890 if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger 7891 input = $( "input", input.parentNode )[ 0 ]; 7892 } 7893 7894 if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here 7895 return; 7896 } 7897 7898 var inst, beforeShow, beforeShowSettings, isFixed, 7899 offset, showAnim, duration; 7900 7901 inst = $.datepicker._getInst( input ); 7902 if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) { 7903 $.datepicker._curInst.dpDiv.stop( true, true ); 7904 if ( inst && $.datepicker._datepickerShowing ) { 7905 $.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] ); 7906 } 7907 } 7908 7909 beforeShow = $.datepicker._get( inst, "beforeShow" ); 7910 beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {}; 7911 if ( beforeShowSettings === false ) { 7912 return; 7913 } 7914 datepicker_extendRemove( inst.settings, beforeShowSettings ); 7915 7916 inst.lastVal = null; 7917 $.datepicker._lastInput = input; 7918 $.datepicker._setDateFromField( inst ); 7919 7920 if ( $.datepicker._inDialog ) { // hide cursor 7921 input.value = ""; 7922 } 7923 if ( !$.datepicker._pos ) { // position below input 7924 $.datepicker._pos = $.datepicker._findPos( input ); 7925 $.datepicker._pos[ 1 ] += input.offsetHeight; // add the height 7926 } 7927 7928 isFixed = false; 7929 $( input ).parents().each( function() { 7930 isFixed |= $( this ).css( "position" ) === "fixed"; 7931 return !isFixed; 7932 } ); 7933 7934 offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] }; 7935 $.datepicker._pos = null; 7936 7937 //to avoid flashes on Firefox 7938 inst.dpDiv.empty(); 7939 7940 // determine sizing offscreen 7941 inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } ); 7942 $.datepicker._updateDatepicker( inst ); 7943 7944 // fix width for dynamic number of date pickers 7945 // and adjust position before showing 7946 offset = $.datepicker._checkOffset( inst, offset, isFixed ); 7947 inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ? 7948 "static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none", 7949 left: offset.left + "px", top: offset.top + "px" } ); 7950 7951 if ( !inst.inline ) { 7952 showAnim = $.datepicker._get( inst, "showAnim" ); 7953 duration = $.datepicker._get( inst, "duration" ); 7954 inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 ); 7955 $.datepicker._datepickerShowing = true; 7956 7957 if ( $.effects && $.effects.effect[ showAnim ] ) { 7958 inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration ); 7959 } else { 7960 inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null ); 7961 } 7962 7963 if ( $.datepicker._shouldFocusInput( inst ) ) { 7964 inst.input.trigger( "focus" ); 7965 } 7966 7967 $.datepicker._curInst = inst; 7968 } 7969 }, 7970 7971 /* Generate the date picker content. */ 7972 _updateDatepicker: function( inst ) { 7973 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) 7974 datepicker_instActive = inst; // for delegate hover events 7975 inst.dpDiv.empty().append( this._generateHTML( inst ) ); 7976 this._attachHandlers( inst ); 7977 7978 var origyearshtml, 7979 numMonths = this._getNumberOfMonths( inst ), 7980 cols = numMonths[ 1 ], 7981 width = 17, 7982 activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ), 7983 onUpdateDatepicker = $.datepicker._get( inst, "onUpdateDatepicker" ); 7984 7985 if ( activeCell.length > 0 ) { 7986 datepicker_handleMouseover.apply( activeCell.get( 0 ) ); 7987 } 7988 7989 inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" ); 7990 if ( cols > 1 ) { 7991 inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" ); 7992 } 7993 inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) + 7994 "Class" ]( "ui-datepicker-multi" ); 7995 inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) + 7996 "Class" ]( "ui-datepicker-rtl" ); 7997 7998 if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) { 7999 inst.input.trigger( "focus" ); 8000 } 8001 8002 // Deffered render of the years select (to avoid flashes on Firefox) 8003 if ( inst.yearshtml ) { 8004 origyearshtml = inst.yearshtml; 8005 setTimeout( function() { 8006 8007 //assure that inst.yearshtml didn't change. 8008 if ( origyearshtml === inst.yearshtml && inst.yearshtml ) { 8009 inst.dpDiv.find( "select.ui-datepicker-year" ).first().replaceWith( inst.yearshtml ); 8010 } 8011 origyearshtml = inst.yearshtml = null; 8012 }, 0 ); 8013 } 8014 8015 if ( onUpdateDatepicker ) { 8016 onUpdateDatepicker.apply( ( inst.input ? inst.input[ 0 ] : null ), [ inst ] ); 8017 } 8018 }, 8019 8020 _shouldFocusInput: function( inst ) { 8021 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ); 8022 }, 8023 8024 /* Check positioning to remain on screen. */ 8025 _checkOffset: function( inst, offset, isFixed ) { 8026 var dpWidth = inst.dpDiv.outerWidth(), 8027 dpHeight = inst.dpDiv.outerHeight(), 8028 inputWidth = inst.input ? inst.input.outerWidth() : 0, 8029 inputHeight = inst.input ? inst.input.outerHeight() : 0, 8030 viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ), 8031 viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() ); 8032 8033 offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 ); 8034 offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0; 8035 offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0; 8036 8037 // Now check if datepicker is showing outside window viewport - move to a better place if so. 8038 offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ? 8039 Math.abs( offset.left + dpWidth - viewWidth ) : 0 ); 8040 offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ? 8041 Math.abs( dpHeight + inputHeight ) : 0 ); 8042 8043 return offset; 8044 }, 8045 8046 /* Find an object's position on the screen. */ 8047 _findPos: function( obj ) { 8048 var position, 8049 inst = this._getInst( obj ), 8050 isRTL = this._get( inst, "isRTL" ); 8051 8052 while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden( obj ) ) ) { 8053 obj = obj[ isRTL ? "previousSibling" : "nextSibling" ]; 8054 } 8055 8056 position = $( obj ).offset(); 8057 return [ position.left, position.top ]; 8058 }, 8059 8060 /* Hide the date picker from view. 8061 * @param input element - the input field attached to the date picker 8062 */ 8063 _hideDatepicker: function( input ) { 8064 var showAnim, duration, postProcess, onClose, 8065 inst = this._curInst; 8066 8067 if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) { 8068 return; 8069 } 8070 8071 if ( this._datepickerShowing ) { 8072 showAnim = this._get( inst, "showAnim" ); 8073 duration = this._get( inst, "duration" ); 8074 postProcess = function() { 8075 $.datepicker._tidyDialog( inst ); 8076 }; 8077 8078 if ( $.effects && ( $.effects.effect[ showAnim ] ) ) { 8079 inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess ); 8080 } else { 8081 inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" : 8082 ( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess ); 8083 } 8084 8085 if ( !showAnim ) { 8086 postProcess(); 8087 } 8088 this._datepickerShowing = false; 8089 8090 onClose = this._get( inst, "onClose" ); 8091 if ( onClose ) { 8092 onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] ); 8093 } 8094 8095 this._lastInput = null; 8096 if ( this._inDialog ) { 8097 this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } ); 8098 if ( $.blockUI ) { 8099 $.unblockUI(); 8100 $( "body" ).append( this.dpDiv ); 8101 } 8102 } 8103 this._inDialog = false; 8104 } 8105 }, 8106 8107 /* Tidy up after a dialog display. */ 8108 _tidyDialog: function( inst ) { 8109 inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" ); 8110 }, 8111 8112 /* Close date picker if clicked elsewhere. */ 8113 _checkExternalClick: function( event ) { 8114 if ( !$.datepicker._curInst ) { 8115 return; 8116 } 8117 8118 var $target = $( event.target ), 8119 inst = $.datepicker._getInst( $target[ 0 ] ); 8120 8121 if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId && 8122 $target.parents( "#" + $.datepicker._mainDivId ).length === 0 && 8123 !$target.hasClass( $.datepicker.markerClassName ) && 8124 !$target.closest( "." + $.datepicker._triggerClass ).length && 8125 $.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) || 8126 ( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) { 8127 $.datepicker._hideDatepicker(); 8128 } 8129 }, 8130 8131 /* Adjust one of the date sub-fields. */ 8132 _adjustDate: function( id, offset, period ) { 8133 var target = $( id ), 8134 inst = this._getInst( target[ 0 ] ); 8135 8136 if ( this._isDisabledDatepicker( target[ 0 ] ) ) { 8137 return; 8138 } 8139 this._adjustInstDate( inst, offset, period ); 8140 this._updateDatepicker( inst ); 8141 }, 8142 8143 /* Action for current link. */ 8144 _gotoToday: function( id ) { 8145 var date, 8146 target = $( id ), 8147 inst = this._getInst( target[ 0 ] ); 8148 8149 if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) { 8150 inst.selectedDay = inst.currentDay; 8151 inst.drawMonth = inst.selectedMonth = inst.currentMonth; 8152 inst.drawYear = inst.selectedYear = inst.currentYear; 8153 } else { 8154 date = new Date(); 8155 inst.selectedDay = date.getDate(); 8156 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8157 inst.drawYear = inst.selectedYear = date.getFullYear(); 8158 } 8159 this._notifyChange( inst ); 8160 this._adjustDate( target ); 8161 }, 8162 8163 /* Action for selecting a new month/year. */ 8164 _selectMonthYear: function( id, select, period ) { 8165 var target = $( id ), 8166 inst = this._getInst( target[ 0 ] ); 8167 8168 inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] = 8169 inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] = 8170 parseInt( select.options[ select.selectedIndex ].value, 10 ); 8171 8172 this._notifyChange( inst ); 8173 this._adjustDate( target ); 8174 }, 8175 8176 /* Action for selecting a day. */ 8177 _selectDay: function( id, month, year, td ) { 8178 var inst, 8179 target = $( id ); 8180 8181 if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) { 8182 return; 8183 } 8184 8185 inst = this._getInst( target[ 0 ] ); 8186 inst.selectedDay = inst.currentDay = parseInt( $( "a", td ).attr( "data-date" ) ); 8187 inst.selectedMonth = inst.currentMonth = month; 8188 inst.selectedYear = inst.currentYear = year; 8189 this._selectDate( id, this._formatDate( inst, 8190 inst.currentDay, inst.currentMonth, inst.currentYear ) ); 8191 }, 8192 8193 /* Erase the input field and hide the date picker. */ 8194 _clearDate: function( id ) { 8195 var target = $( id ); 8196 this._selectDate( target, "" ); 8197 }, 8198 8199 /* Update the input field with the selected date. */ 8200 _selectDate: function( id, dateStr ) { 8201 var onSelect, 8202 target = $( id ), 8203 inst = this._getInst( target[ 0 ] ); 8204 8205 dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) ); 8206 if ( inst.input ) { 8207 inst.input.val( dateStr ); 8208 } 8209 this._updateAlternate( inst ); 8210 8211 onSelect = this._get( inst, "onSelect" ); 8212 if ( onSelect ) { 8213 onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] ); // trigger custom callback 8214 } else if ( inst.input ) { 8215 inst.input.trigger( "change" ); // fire the change event 8216 } 8217 8218 if ( inst.inline ) { 8219 this._updateDatepicker( inst ); 8220 } else { 8221 this._hideDatepicker(); 8222 this._lastInput = inst.input[ 0 ]; 8223 if ( typeof( inst.input[ 0 ] ) !== "object" ) { 8224 inst.input.trigger( "focus" ); // restore focus 8225 } 8226 this._lastInput = null; 8227 } 8228 }, 8229 8230 /* Update any alternate field to synchronise with the main field. */ 8231 _updateAlternate: function( inst ) { 8232 var altFormat, date, dateStr, 8233 altField = this._get( inst, "altField" ); 8234 8235 if ( altField ) { // update alternate field too 8236 altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" ); 8237 date = this._getDate( inst ); 8238 dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) ); 8239 $( document ).find( altField ).val( dateStr ); 8240 } 8241 }, 8242 8243 /* Set as beforeShowDay function to prevent selection of weekends. 8244 * @param date Date - the date to customise 8245 * @return [boolean, string] - is this date selectable?, what is its CSS class? 8246 */ 8247 noWeekends: function( date ) { 8248 var day = date.getDay(); 8249 return [ ( day > 0 && day < 6 ), "" ]; 8250 }, 8251 8252 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. 8253 * @param date Date - the date to get the week for 8254 * @return number - the number of the week within the year that contains this date 8255 */ 8256 iso8601Week: function( date ) { 8257 var time, 8258 checkDate = new Date( date.getTime() ); 8259 8260 // Find Thursday of this week starting on Monday 8261 checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) ); 8262 8263 time = checkDate.getTime(); 8264 checkDate.setMonth( 0 ); // Compare with Jan 1 8265 checkDate.setDate( 1 ); 8266 return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1; 8267 }, 8268 8269 /* Parse a string value into a date object. 8270 * See formatDate below for the possible formats. 8271 * 8272 * @param format string - the expected format of the date 8273 * @param value string - the date in the above format 8274 * @param settings Object - attributes include: 8275 * shortYearCutoff number - the cutoff year for determining the century (optional) 8276 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 8277 * dayNames string[7] - names of the days from Sunday (optional) 8278 * monthNamesShort string[12] - abbreviated names of the months (optional) 8279 * monthNames string[12] - names of the months (optional) 8280 * @return Date - the extracted date value or null if value is blank 8281 */ 8282 parseDate: function( format, value, settings ) { 8283 if ( format == null || value == null ) { 8284 throw "Invalid arguments"; 8285 } 8286 8287 value = ( typeof value === "object" ? value.toString() : value + "" ); 8288 if ( value === "" ) { 8289 return null; 8290 } 8291 8292 var iFormat, dim, extra, 8293 iValue = 0, 8294 shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff, 8295 shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp : 8296 new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ), 8297 dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort, 8298 dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames, 8299 monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort, 8300 monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames, 8301 year = -1, 8302 month = -1, 8303 day = -1, 8304 doy = -1, 8305 literal = false, 8306 date, 8307 8308 // Check whether a format character is doubled 8309 lookAhead = function( match ) { 8310 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match ); 8311 if ( matches ) { 8312 iFormat++; 8313 } 8314 return matches; 8315 }, 8316 8317 // Extract a number from the string value 8318 getNumber = function( match ) { 8319 var isDoubled = lookAhead( match ), 8320 size = ( match === "@" ? 14 : ( match === "!" ? 20 : 8321 ( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ), 8322 minSize = ( match === "y" ? size : 1 ), 8323 digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ), 8324 num = value.substring( iValue ).match( digits ); 8325 if ( !num ) { 8326 throw "Missing number at position " + iValue; 8327 } 8328 iValue += num[ 0 ].length; 8329 return parseInt( num[ 0 ], 10 ); 8330 }, 8331 8332 // Extract a name from the string value and convert to an index 8333 getName = function( match, shortNames, longNames ) { 8334 var index = -1, 8335 names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) { 8336 return [ [ k, v ] ]; 8337 } ).sort( function( a, b ) { 8338 return -( a[ 1 ].length - b[ 1 ].length ); 8339 } ); 8340 8341 $.each( names, function( i, pair ) { 8342 var name = pair[ 1 ]; 8343 if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) { 8344 index = pair[ 0 ]; 8345 iValue += name.length; 8346 return false; 8347 } 8348 } ); 8349 if ( index !== -1 ) { 8350 return index + 1; 8351 } else { 8352 throw "Unknown name at position " + iValue; 8353 } 8354 }, 8355 8356 // Confirm that a literal character matches the string value 8357 checkLiteral = function() { 8358 if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) { 8359 throw "Unexpected literal at position " + iValue; 8360 } 8361 iValue++; 8362 }; 8363 8364 for ( iFormat = 0; iFormat < format.length; iFormat++ ) { 8365 if ( literal ) { 8366 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) { 8367 literal = false; 8368 } else { 8369 checkLiteral(); 8370 } 8371 } else { 8372 switch ( format.charAt( iFormat ) ) { 8373 case "d": 8374 day = getNumber( "d" ); 8375 break; 8376 case "D": 8377 getName( "D", dayNamesShort, dayNames ); 8378 break; 8379 case "o": 8380 doy = getNumber( "o" ); 8381 break; 8382 case "m": 8383 month = getNumber( "m" ); 8384 break; 8385 case "M": 8386 month = getName( "M", monthNamesShort, monthNames ); 8387 break; 8388 case "y": 8389 year = getNumber( "y" ); 8390 break; 8391 case "@": 8392 date = new Date( getNumber( "@" ) ); 8393 year = date.getFullYear(); 8394 month = date.getMonth() + 1; 8395 day = date.getDate(); 8396 break; 8397 case "!": 8398 date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 ); 8399 year = date.getFullYear(); 8400 month = date.getMonth() + 1; 8401 day = date.getDate(); 8402 break; 8403 case "'": 8404 if ( lookAhead( "'" ) ) { 8405 checkLiteral(); 8406 } else { 8407 literal = true; 8408 } 8409 break; 8410 default: 8411 checkLiteral(); 8412 } 8413 } 8414 } 8415 8416 if ( iValue < value.length ) { 8417 extra = value.substr( iValue ); 8418 if ( !/^\s+/.test( extra ) ) { 8419 throw "Extra/unparsed characters found in date: " + extra; 8420 } 8421 } 8422 8423 if ( year === -1 ) { 8424 year = new Date().getFullYear(); 8425 } else if ( year < 100 ) { 8426 year += new Date().getFullYear() - new Date().getFullYear() % 100 + 8427 ( year <= shortYearCutoff ? 0 : -100 ); 8428 } 8429 8430 if ( doy > -1 ) { 8431 month = 1; 8432 day = doy; 8433 do { 8434 dim = this._getDaysInMonth( year, month - 1 ); 8435 if ( day <= dim ) { 8436 break; 8437 } 8438 month++; 8439 day -= dim; 8440 } while ( true ); 8441 } 8442 8443 date = this._daylightSavingAdjust( new Date( year, month - 1, day ) ); 8444 if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) { 8445 throw "Invalid date"; // E.g. 31/02/00 8446 } 8447 return date; 8448 }, 8449 8450 /* Standard date formats. */ 8451 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601) 8452 COOKIE: "D, dd M yy", 8453 ISO_8601: "yy-mm-dd", 8454 RFC_822: "D, d M y", 8455 RFC_850: "DD, dd-M-y", 8456 RFC_1036: "D, d M y", 8457 RFC_1123: "D, d M yy", 8458 RFC_2822: "D, d M yy", 8459 RSS: "D, d M y", // RFC 822 8460 TICKS: "!", 8461 TIMESTAMP: "@", 8462 W3C: "yy-mm-dd", // ISO 8601 8463 8464 _ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) + 8465 Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ), 8466 8467 /* Format a date object into a string value. 8468 * The format can be combinations of the following: 8469 * d - day of month (no leading zero) 8470 * dd - day of month (two digit) 8471 * o - day of year (no leading zeros) 8472 * oo - day of year (three digit) 8473 * D - day name short 8474 * DD - day name long 8475 * m - month of year (no leading zero) 8476 * mm - month of year (two digit) 8477 * M - month name short 8478 * MM - month name long 8479 * y - year (two digit) 8480 * yy - year (four digit) 8481 * @ - Unix timestamp (ms since 01/01/1970) 8482 * ! - Windows ticks (100ns since 01/01/0001) 8483 * "..." - literal text 8484 * '' - single quote 8485 * 8486 * @param format string - the desired format of the date 8487 * @param date Date - the date value to format 8488 * @param settings Object - attributes include: 8489 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 8490 * dayNames string[7] - names of the days from Sunday (optional) 8491 * monthNamesShort string[12] - abbreviated names of the months (optional) 8492 * monthNames string[12] - names of the months (optional) 8493 * @return string - the date in the above format 8494 */ 8495 formatDate: function( format, date, settings ) { 8496 if ( !date ) { 8497 return ""; 8498 } 8499 8500 var iFormat, 8501 dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort, 8502 dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames, 8503 monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort, 8504 monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames, 8505 8506 // Check whether a format character is doubled 8507 lookAhead = function( match ) { 8508 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match ); 8509 if ( matches ) { 8510 iFormat++; 8511 } 8512 return matches; 8513 }, 8514 8515 // Format a number, with leading zero if necessary 8516 formatNumber = function( match, value, len ) { 8517 var num = "" + value; 8518 if ( lookAhead( match ) ) { 8519 while ( num.length < len ) { 8520 num = "0" + num; 8521 } 8522 } 8523 return num; 8524 }, 8525 8526 // Format a name, short or long as requested 8527 formatName = function( match, value, shortNames, longNames ) { 8528 return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] ); 8529 }, 8530 output = "", 8531 literal = false; 8532 8533 if ( date ) { 8534 for ( iFormat = 0; iFormat < format.length; iFormat++ ) { 8535 if ( literal ) { 8536 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) { 8537 literal = false; 8538 } else { 8539 output += format.charAt( iFormat ); 8540 } 8541 } else { 8542 switch ( format.charAt( iFormat ) ) { 8543 case "d": 8544 output += formatNumber( "d", date.getDate(), 2 ); 8545 break; 8546 case "D": 8547 output += formatName( "D", date.getDay(), dayNamesShort, dayNames ); 8548 break; 8549 case "o": 8550 output += formatNumber( "o", 8551 Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 ); 8552 break; 8553 case "m": 8554 output += formatNumber( "m", date.getMonth() + 1, 2 ); 8555 break; 8556 case "M": 8557 output += formatName( "M", date.getMonth(), monthNamesShort, monthNames ); 8558 break; 8559 case "y": 8560 output += ( lookAhead( "y" ) ? date.getFullYear() : 8561 ( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 ); 8562 break; 8563 case "@": 8564 output += date.getTime(); 8565 break; 8566 case "!": 8567 output += date.getTime() * 10000 + this._ticksTo1970; 8568 break; 8569 case "'": 8570 if ( lookAhead( "'" ) ) { 8571 output += "'"; 8572 } else { 8573 literal = true; 8574 } 8575 break; 8576 default: 8577 output += format.charAt( iFormat ); 8578 } 8579 } 8580 } 8581 } 8582 return output; 8583 }, 8584 8585 /* Extract all possible characters from the date format. */ 8586 _possibleChars: function( format ) { 8587 var iFormat, 8588 chars = "", 8589 literal = false, 8590 8591 // Check whether a format character is doubled 8592 lookAhead = function( match ) { 8593 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match ); 8594 if ( matches ) { 8595 iFormat++; 8596 } 8597 return matches; 8598 }; 8599 8600 for ( iFormat = 0; iFormat < format.length; iFormat++ ) { 8601 if ( literal ) { 8602 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) { 8603 literal = false; 8604 } else { 8605 chars += format.charAt( iFormat ); 8606 } 8607 } else { 8608 switch ( format.charAt( iFormat ) ) { 8609 case "d": case "m": case "y": case "@": 8610 chars += "0123456789"; 8611 break; 8612 case "D": case "M": 8613 return null; // Accept anything 8614 case "'": 8615 if ( lookAhead( "'" ) ) { 8616 chars += "'"; 8617 } else { 8618 literal = true; 8619 } 8620 break; 8621 default: 8622 chars += format.charAt( iFormat ); 8623 } 8624 } 8625 } 8626 return chars; 8627 }, 8628 8629 /* Get a setting value, defaulting if necessary. */ 8630 _get: function( inst, name ) { 8631 return inst.settings[ name ] !== undefined ? 8632 inst.settings[ name ] : this._defaults[ name ]; 8633 }, 8634 8635 /* Parse existing date and initialise date picker. */ 8636 _setDateFromField: function( inst, noDefault ) { 8637 if ( inst.input.val() === inst.lastVal ) { 8638 return; 8639 } 8640 8641 var dateFormat = this._get( inst, "dateFormat" ), 8642 dates = inst.lastVal = inst.input ? inst.input.val() : null, 8643 defaultDate = this._getDefaultDate( inst ), 8644 date = defaultDate, 8645 settings = this._getFormatConfig( inst ); 8646 8647 try { 8648 date = this.parseDate( dateFormat, dates, settings ) || defaultDate; 8649 } catch ( event ) { 8650 dates = ( noDefault ? "" : dates ); 8651 } 8652 inst.selectedDay = date.getDate(); 8653 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8654 inst.drawYear = inst.selectedYear = date.getFullYear(); 8655 inst.currentDay = ( dates ? date.getDate() : 0 ); 8656 inst.currentMonth = ( dates ? date.getMonth() : 0 ); 8657 inst.currentYear = ( dates ? date.getFullYear() : 0 ); 8658 this._adjustInstDate( inst ); 8659 }, 8660 8661 /* Retrieve the default date shown on opening. */ 8662 _getDefaultDate: function( inst ) { 8663 return this._restrictMinMax( inst, 8664 this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) ); 8665 }, 8666 8667 /* A date may be specified as an exact value or a relative one. */ 8668 _determineDate: function( inst, date, defaultDate ) { 8669 var offsetNumeric = function( offset ) { 8670 var date = new Date(); 8671 date.setDate( date.getDate() + offset ); 8672 return date; 8673 }, 8674 offsetString = function( offset ) { 8675 try { 8676 return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ), 8677 offset, $.datepicker._getFormatConfig( inst ) ); 8678 } catch ( e ) { 8679 8680 // Ignore 8681 } 8682 8683 var date = ( offset.toLowerCase().match( /^c/ ) ? 8684 $.datepicker._getDate( inst ) : null ) || new Date(), 8685 year = date.getFullYear(), 8686 month = date.getMonth(), 8687 day = date.getDate(), 8688 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, 8689 matches = pattern.exec( offset ); 8690 8691 while ( matches ) { 8692 switch ( matches[ 2 ] || "d" ) { 8693 case "d" : case "D" : 8694 day += parseInt( matches[ 1 ], 10 ); break; 8695 case "w" : case "W" : 8696 day += parseInt( matches[ 1 ], 10 ) * 7; break; 8697 case "m" : case "M" : 8698 month += parseInt( matches[ 1 ], 10 ); 8699 day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) ); 8700 break; 8701 case "y": case "Y" : 8702 year += parseInt( matches[ 1 ], 10 ); 8703 day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) ); 8704 break; 8705 } 8706 matches = pattern.exec( offset ); 8707 } 8708 return new Date( year, month, day ); 8709 }, 8710 newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) : 8711 ( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) ); 8712 8713 newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate ); 8714 if ( newDate ) { 8715 newDate.setHours( 0 ); 8716 newDate.setMinutes( 0 ); 8717 newDate.setSeconds( 0 ); 8718 newDate.setMilliseconds( 0 ); 8719 } 8720 return this._daylightSavingAdjust( newDate ); 8721 }, 8722 8723 /* Handle switch to/from daylight saving. 8724 * Hours may be non-zero on daylight saving cut-over: 8725 * > 12 when midnight changeover, but then cannot generate 8726 * midnight datetime, so jump to 1AM, otherwise reset. 8727 * @param date (Date) the date to check 8728 * @return (Date) the corrected date 8729 */ 8730 _daylightSavingAdjust: function( date ) { 8731 if ( !date ) { 8732 return null; 8733 } 8734 date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 ); 8735 return date; 8736 }, 8737 8738 /* Set the date(s) directly. */ 8739 _setDate: function( inst, date, noChange ) { 8740 var clear = !date, 8741 origMonth = inst.selectedMonth, 8742 origYear = inst.selectedYear, 8743 newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) ); 8744 8745 inst.selectedDay = inst.currentDay = newDate.getDate(); 8746 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); 8747 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); 8748 if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) { 8749 this._notifyChange( inst ); 8750 } 8751 this._adjustInstDate( inst ); 8752 if ( inst.input ) { 8753 inst.input.val( clear ? "" : this._formatDate( inst ) ); 8754 } 8755 }, 8756 8757 /* Retrieve the date(s) directly. */ 8758 _getDate: function( inst ) { 8759 var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null : 8760 this._daylightSavingAdjust( new Date( 8761 inst.currentYear, inst.currentMonth, inst.currentDay ) ) ); 8762 return startDate; 8763 }, 8764 8765 /* Attach the onxxx handlers. These are declared statically so 8766 * they work with static code transformers like Caja. 8767 */ 8768 _attachHandlers: function( inst ) { 8769 var stepMonths = this._get( inst, "stepMonths" ), 8770 id = "#" + inst.id.replace( /\\\\/g, "\\" ); 8771 inst.dpDiv.find( "[data-handler]" ).map( function() { 8772 var handler = { 8773 prev: function() { 8774 $.datepicker._adjustDate( id, -stepMonths, "M" ); 8775 }, 8776 next: function() { 8777 $.datepicker._adjustDate( id, +stepMonths, "M" ); 8778 }, 8779 hide: function() { 8780 $.datepicker._hideDatepicker(); 8781 }, 8782 today: function() { 8783 $.datepicker._gotoToday( id ); 8784 }, 8785 selectDay: function() { 8786 $.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this ); 8787 return false; 8788 }, 8789 selectMonth: function() { 8790 $.datepicker._selectMonthYear( id, this, "M" ); 8791 return false; 8792 }, 8793 selectYear: function() { 8794 $.datepicker._selectMonthYear( id, this, "Y" ); 8795 return false; 8796 } 8797 }; 8798 $( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] ); 8799 } ); 8800 }, 8801 8802 /* Generate the HTML for the current state of the date picker. */ 8803 _generateHTML: function( inst ) { 8804 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate, 8805 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin, 8806 monthNames, monthNamesShort, beforeShowDay, showOtherMonths, 8807 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate, 8808 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows, 8809 printDate, dRow, tbody, daySettings, otherMonth, unselectable, 8810 tempDate = new Date(), 8811 today = this._daylightSavingAdjust( 8812 new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time 8813 isRTL = this._get( inst, "isRTL" ), 8814 showButtonPanel = this._get( inst, "showButtonPanel" ), 8815 hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ), 8816 navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ), 8817 numMonths = this._getNumberOfMonths( inst ), 8818 showCurrentAtPos = this._get( inst, "showCurrentAtPos" ), 8819 stepMonths = this._get( inst, "stepMonths" ), 8820 isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ), 8821 currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) : 8822 new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ), 8823 minDate = this._getMinMaxDate( inst, "min" ), 8824 maxDate = this._getMinMaxDate( inst, "max" ), 8825 drawMonth = inst.drawMonth - showCurrentAtPos, 8826 drawYear = inst.drawYear; 8827 8828 if ( drawMonth < 0 ) { 8829 drawMonth += 12; 8830 drawYear--; 8831 } 8832 if ( maxDate ) { 8833 maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(), 8834 maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) ); 8835 maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw ); 8836 while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) { 8837 drawMonth--; 8838 if ( drawMonth < 0 ) { 8839 drawMonth = 11; 8840 drawYear--; 8841 } 8842 } 8843 } 8844 inst.drawMonth = drawMonth; 8845 inst.drawYear = drawYear; 8846 8847 prevText = this._get( inst, "prevText" ); 8848 prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText, 8849 this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ), 8850 this._getFormatConfig( inst ) ) ); 8851 8852 if ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ) { 8853 prev = $( "<a>" ) 8854 .attr( { 8855 "class": "ui-datepicker-prev ui-corner-all", 8856 "data-handler": "prev", 8857 "data-event": "click", 8858 title: prevText 8859 } ) 8860 .append( 8861 $( "<span>" ) 8862 .addClass( "ui-icon ui-icon-circle-triangle-" + 8863 ( isRTL ? "e" : "w" ) ) 8864 .text( prevText ) 8865 )[ 0 ].outerHTML; 8866 } else if ( hideIfNoPrevNext ) { 8867 prev = ""; 8868 } else { 8869 prev = $( "<a>" ) 8870 .attr( { 8871 "class": "ui-datepicker-prev ui-corner-all ui-state-disabled", 8872 title: prevText 8873 } ) 8874 .append( 8875 $( "<span>" ) 8876 .addClass( "ui-icon ui-icon-circle-triangle-" + 8877 ( isRTL ? "e" : "w" ) ) 8878 .text( prevText ) 8879 )[ 0 ].outerHTML; 8880 } 8881 8882 nextText = this._get( inst, "nextText" ); 8883 nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText, 8884 this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ), 8885 this._getFormatConfig( inst ) ) ); 8886 8887 if ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ) { 8888 next = $( "<a>" ) 8889 .attr( { 8890 "class": "ui-datepicker-next ui-corner-all", 8891 "data-handler": "next", 8892 "data-event": "click", 8893 title: nextText 8894 } ) 8895 .append( 8896 $( "<span>" ) 8897 .addClass( "ui-icon ui-icon-circle-triangle-" + 8898 ( isRTL ? "w" : "e" ) ) 8899 .text( nextText ) 8900 )[ 0 ].outerHTML; 8901 } else if ( hideIfNoPrevNext ) { 8902 next = ""; 8903 } else { 8904 next = $( "<a>" ) 8905 .attr( { 8906 "class": "ui-datepicker-next ui-corner-all ui-state-disabled", 8907 title: nextText 8908 } ) 8909 .append( 8910 $( "<span>" ) 8911 .attr( "class", "ui-icon ui-icon-circle-triangle-" + 8912 ( isRTL ? "w" : "e" ) ) 8913 .text( nextText ) 8914 )[ 0 ].outerHTML; 8915 } 8916 8917 currentText = this._get( inst, "currentText" ); 8918 gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today ); 8919 currentText = ( !navigationAsDateFormat ? currentText : 8920 this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) ); 8921 8922 controls = ""; 8923 if ( !inst.inline ) { 8924 controls = $( "<button>" ) 8925 .attr( { 8926 type: "button", 8927 "class": "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all", 8928 "data-handler": "hide", 8929 "data-event": "click" 8930 } ) 8931 .text( this._get( inst, "closeText" ) )[ 0 ].outerHTML; 8932 } 8933 8934 buttonPanel = ""; 8935 if ( showButtonPanel ) { 8936 buttonPanel = $( "<div class='ui-datepicker-buttonpane ui-widget-content'>" ) 8937 .append( isRTL ? controls : "" ) 8938 .append( this._isInRange( inst, gotoDate ) ? 8939 $( "<button>" ) 8940 .attr( { 8941 type: "button", 8942 "class": "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all", 8943 "data-handler": "today", 8944 "data-event": "click" 8945 } ) 8946 .text( currentText ) : 8947 "" ) 8948 .append( isRTL ? "" : controls )[ 0 ].outerHTML; 8949 } 8950 8951 firstDay = parseInt( this._get( inst, "firstDay" ), 10 ); 8952 firstDay = ( isNaN( firstDay ) ? 0 : firstDay ); 8953 8954 showWeek = this._get( inst, "showWeek" ); 8955 dayNames = this._get( inst, "dayNames" ); 8956 dayNamesMin = this._get( inst, "dayNamesMin" ); 8957 monthNames = this._get( inst, "monthNames" ); 8958 monthNamesShort = this._get( inst, "monthNamesShort" ); 8959 beforeShowDay = this._get( inst, "beforeShowDay" ); 8960 showOtherMonths = this._get( inst, "showOtherMonths" ); 8961 selectOtherMonths = this._get( inst, "selectOtherMonths" ); 8962 defaultDate = this._getDefaultDate( inst ); 8963 html = ""; 8964 8965 for ( row = 0; row < numMonths[ 0 ]; row++ ) { 8966 group = ""; 8967 this.maxRows = 4; 8968 for ( col = 0; col < numMonths[ 1 ]; col++ ) { 8969 selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) ); 8970 cornerClass = " ui-corner-all"; 8971 calender = ""; 8972 if ( isMultiMonth ) { 8973 calender += "<div class='ui-datepicker-group"; 8974 if ( numMonths[ 1 ] > 1 ) { 8975 switch ( col ) { 8976 case 0: calender += " ui-datepicker-group-first"; 8977 cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break; 8978 case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last"; 8979 cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break; 8980 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break; 8981 } 8982 } 8983 calender += "'>"; 8984 } 8985 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" + 8986 ( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) + 8987 ( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) + 8988 this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate, 8989 row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers 8990 "</div><table class='ui-datepicker-calendar'><thead>" + 8991 "<tr>"; 8992 thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" ); 8993 for ( dow = 0; dow < 7; dow++ ) { // days of the week 8994 day = ( dow + firstDay ) % 7; 8995 thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" + 8996 "<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>"; 8997 } 8998 calender += thead + "</tr></thead><tbody>"; 8999 daysInMonth = this._getDaysInMonth( drawYear, drawMonth ); 9000 if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) { 9001 inst.selectedDay = Math.min( inst.selectedDay, daysInMonth ); 9002 } 9003 leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7; 9004 curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate 9005 numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043) 9006 this.maxRows = numRows; 9007 printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) ); 9008 for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows 9009 calender += "<tr>"; 9010 tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" + 9011 this._get( inst, "calculateWeek" )( printDate ) + "</td>" ); 9012 for ( dow = 0; dow < 7; dow++ ) { // create date picker days 9013 daySettings = ( beforeShowDay ? 9014 beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] ); 9015 otherMonth = ( printDate.getMonth() !== drawMonth ); 9016 unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] || 9017 ( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate ); 9018 tbody += "<td class='" + 9019 ( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends 9020 ( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months 9021 ( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key 9022 ( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ? 9023 9024 // or defaultDate is current printedDate and defaultDate is selectedDate 9025 " " + this._dayOverClass : "" ) + // highlight selected day 9026 ( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) + // highlight unselectable days 9027 ( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates 9028 ( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day 9029 ( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different) 9030 ( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "'" ) + "'" : "" ) + // cell title 9031 ( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions 9032 ( otherMonth && !showOtherMonths ? " " : // display for other months 9033 ( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" + 9034 ( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) + 9035 ( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day 9036 ( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months 9037 "' href='#' aria-current='" + ( printDate.getTime() === currentDate.getTime() ? "true" : "false" ) + // mark date as selected for screen reader 9038 "' data-date='" + printDate.getDate() + // store date as data 9039 "'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date 9040 printDate.setDate( printDate.getDate() + 1 ); 9041 printDate = this._daylightSavingAdjust( printDate ); 9042 } 9043 calender += tbody + "</tr>"; 9044 } 9045 drawMonth++; 9046 if ( drawMonth > 11 ) { 9047 drawMonth = 0; 9048 drawYear++; 9049 } 9050 calender += "</tbody></table>" + ( isMultiMonth ? "</div>" + 9051 ( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" ); 9052 group += calender; 9053 } 9054 html += group; 9055 } 9056 html += buttonPanel; 9057 inst._keyEvent = false; 9058 return html; 9059 }, 9060 9061 /* Generate the month and year header. */ 9062 _generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate, 9063 secondary, monthNames, monthNamesShort ) { 9064 9065 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear, 9066 changeMonth = this._get( inst, "changeMonth" ), 9067 changeYear = this._get( inst, "changeYear" ), 9068 showMonthAfterYear = this._get( inst, "showMonthAfterYear" ), 9069 selectMonthLabel = this._get( inst, "selectMonthLabel" ), 9070 selectYearLabel = this._get( inst, "selectYearLabel" ), 9071 html = "<div class='ui-datepicker-title'>", 9072 monthHtml = ""; 9073 9074 // Month selection 9075 if ( secondary || !changeMonth ) { 9076 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>"; 9077 } else { 9078 inMinYear = ( minDate && minDate.getFullYear() === drawYear ); 9079 inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear ); 9080 monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>"; 9081 for ( month = 0; month < 12; month++ ) { 9082 if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) { 9083 monthHtml += "<option value='" + month + "'" + 9084 ( month === drawMonth ? " selected='selected'" : "" ) + 9085 ">" + monthNamesShort[ month ] + "</option>"; 9086 } 9087 } 9088 monthHtml += "</select>"; 9089 } 9090 9091 if ( !showMonthAfterYear ) { 9092 html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? " " : "" ); 9093 } 9094 9095 // Year selection 9096 if ( !inst.yearshtml ) { 9097 inst.yearshtml = ""; 9098 if ( secondary || !changeYear ) { 9099 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>"; 9100 } else { 9101 9102 // determine range of years to display 9103 years = this._get( inst, "yearRange" ).split( ":" ); 9104 thisYear = new Date().getFullYear(); 9105 determineYear = function( value ) { 9106 var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) : 9107 ( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) : 9108 parseInt( value, 10 ) ) ); 9109 return ( isNaN( year ) ? thisYear : year ); 9110 }; 9111 year = determineYear( years[ 0 ] ); 9112 endYear = Math.max( year, determineYear( years[ 1 ] || "" ) ); 9113 year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year ); 9114 endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear ); 9115 inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>"; 9116 for ( ; year <= endYear; year++ ) { 9117 inst.yearshtml += "<option value='" + year + "'" + 9118 ( year === drawYear ? " selected='selected'" : "" ) + 9119 ">" + year + "</option>"; 9120 } 9121 inst.yearshtml += "</select>"; 9122 9123 html += inst.yearshtml; 9124 inst.yearshtml = null; 9125 } 9126 } 9127 9128 html += this._get( inst, "yearSuffix" ); 9129 if ( showMonthAfterYear ) { 9130 html += ( secondary || !( changeMonth && changeYear ) ? " " : "" ) + monthHtml; 9131 } 9132 html += "</div>"; // Close datepicker_header 9133 return html; 9134 }, 9135 9136 /* Adjust one of the date sub-fields. */ 9137 _adjustInstDate: function( inst, offset, period ) { 9138 var year = inst.selectedYear + ( period === "Y" ? offset : 0 ), 9139 month = inst.selectedMonth + ( period === "M" ? offset : 0 ), 9140 day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ), 9141 date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) ); 9142 9143 inst.selectedDay = date.getDate(); 9144 inst.drawMonth = inst.selectedMonth = date.getMonth(); 9145 inst.drawYear = inst.selectedYear = date.getFullYear(); 9146 if ( period === "M" || period === "Y" ) { 9147 this._notifyChange( inst ); 9148 } 9149 }, 9150 9151 /* Ensure a date is within any min/max bounds. */ 9152 _restrictMinMax: function( inst, date ) { 9153 var minDate = this._getMinMaxDate( inst, "min" ), 9154 maxDate = this._getMinMaxDate( inst, "max" ), 9155 newDate = ( minDate && date < minDate ? minDate : date ); 9156 return ( maxDate && newDate > maxDate ? maxDate : newDate ); 9157 }, 9158 9159 /* Notify change of month/year. */ 9160 _notifyChange: function( inst ) { 9161 var onChange = this._get( inst, "onChangeMonthYear" ); 9162 if ( onChange ) { 9163 onChange.apply( ( inst.input ? inst.input[ 0 ] : null ), 9164 [ inst.selectedYear, inst.selectedMonth + 1, inst ] ); 9165 } 9166 }, 9167 9168 /* Determine the number of months to show. */ 9169 _getNumberOfMonths: function( inst ) { 9170 var numMonths = this._get( inst, "numberOfMonths" ); 9171 return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) ); 9172 }, 9173 9174 /* Determine the current maximum date - ensure no time components are set. */ 9175 _getMinMaxDate: function( inst, minMax ) { 9176 return this._determineDate( inst, this._get( inst, minMax + "Date" ), null ); 9177 }, 9178 9179 /* Find the number of days in a given month. */ 9180 _getDaysInMonth: function( year, month ) { 9181 return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate(); 9182 }, 9183 9184 /* Find the day of the week of the first of a month. */ 9185 _getFirstDayOfMonth: function( year, month ) { 9186 return new Date( year, month, 1 ).getDay(); 9187 }, 9188 9189 /* Determines if we should allow a "next/prev" month display change. */ 9190 _canAdjustMonth: function( inst, offset, curYear, curMonth ) { 9191 var numMonths = this._getNumberOfMonths( inst ), 9192 date = this._daylightSavingAdjust( new Date( curYear, 9193 curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) ); 9194 9195 if ( offset < 0 ) { 9196 date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) ); 9197 } 9198 return this._isInRange( inst, date ); 9199 }, 9200 9201 /* Is the given date in the accepted range? */ 9202 _isInRange: function( inst, date ) { 9203 var yearSplit, currentYear, 9204 minDate = this._getMinMaxDate( inst, "min" ), 9205 maxDate = this._getMinMaxDate( inst, "max" ), 9206 minYear = null, 9207 maxYear = null, 9208 years = this._get( inst, "yearRange" ); 9209 if ( years ) { 9210 yearSplit = years.split( ":" ); 9211 currentYear = new Date().getFullYear(); 9212 minYear = parseInt( yearSplit[ 0 ], 10 ); 9213 maxYear = parseInt( yearSplit[ 1 ], 10 ); 9214 if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) { 9215 minYear += currentYear; 9216 } 9217 if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) { 9218 maxYear += currentYear; 9219 } 9220 } 9221 9222 return ( ( !minDate || date.getTime() >= minDate.getTime() ) && 9223 ( !maxDate || date.getTime() <= maxDate.getTime() ) && 9224 ( !minYear || date.getFullYear() >= minYear ) && 9225 ( !maxYear || date.getFullYear() <= maxYear ) ); 9226 }, 9227 9228 /* Provide the configuration settings for formatting/parsing. */ 9229 _getFormatConfig: function( inst ) { 9230 var shortYearCutoff = this._get( inst, "shortYearCutoff" ); 9231 shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff : 9232 new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) ); 9233 return { shortYearCutoff: shortYearCutoff, 9234 dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ), 9235 monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) }; 9236 }, 9237 9238 /* Format the given date for display. */ 9239 _formatDate: function( inst, day, month, year ) { 9240 if ( !day ) { 9241 inst.currentDay = inst.selectedDay; 9242 inst.currentMonth = inst.selectedMonth; 9243 inst.currentYear = inst.selectedYear; 9244 } 9245 var date = ( day ? ( typeof day === "object" ? day : 9246 this._daylightSavingAdjust( new Date( year, month, day ) ) ) : 9247 this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ); 9248 return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) ); 9249 } 9250} ); 9251 9252/* 9253 * Bind hover events for datepicker elements. 9254 * Done via delegate so the binding only occurs once in the lifetime of the parent div. 9255 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. 9256 */ 9257function datepicker_bindHover( dpDiv ) { 9258 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a"; 9259 return dpDiv.on( "mouseout", selector, function() { 9260 $( this ).removeClass( "ui-state-hover" ); 9261 if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) { 9262 $( this ).removeClass( "ui-datepicker-prev-hover" ); 9263 } 9264 if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) { 9265 $( this ).removeClass( "ui-datepicker-next-hover" ); 9266 } 9267 } ) 9268 .on( "mouseover", selector, datepicker_handleMouseover ); 9269} 9270 9271function datepicker_handleMouseover() { 9272 if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) { 9273 $( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" ); 9274 $( this ).addClass( "ui-state-hover" ); 9275 if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) { 9276 $( this ).addClass( "ui-datepicker-prev-hover" ); 9277 } 9278 if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) { 9279 $( this ).addClass( "ui-datepicker-next-hover" ); 9280 } 9281 } 9282} 9283 9284/* jQuery extend now ignores nulls! */ 9285function datepicker_extendRemove( target, props ) { 9286 $.extend( target, props ); 9287 for ( var name in props ) { 9288 if ( props[ name ] == null ) { 9289 target[ name ] = props[ name ]; 9290 } 9291 } 9292 return target; 9293} 9294 9295/* Invoke the datepicker functionality. 9296 @param options string - a command, optionally followed by additional parameters or 9297 Object - settings for attaching new datepicker functionality 9298 @return jQuery object */ 9299$.fn.datepicker = function( options ) { 9300 9301 /* Verify an empty collection wasn't passed - Fixes #6976 */ 9302 if ( !this.length ) { 9303 return this; 9304 } 9305 9306 /* Initialise the date picker. */ 9307 if ( !$.datepicker.initialized ) { 9308 $( document ).on( "mousedown", $.datepicker._checkExternalClick ); 9309 $.datepicker.initialized = true; 9310 } 9311 9312 /* Append datepicker main container to body if not exist. */ 9313 if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) { 9314 $( "body" ).append( $.datepicker.dpDiv ); 9315 } 9316 9317 var otherArgs = Array.prototype.slice.call( arguments, 1 ); 9318 if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) { 9319 return $.datepicker[ "_" + options + "Datepicker" ]. 9320 apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) ); 9321 } 9322 if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) { 9323 return $.datepicker[ "_" + options + "Datepicker" ]. 9324 apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) ); 9325 } 9326 return this.each( function() { 9327 if ( typeof options === "string" ) { 9328 $.datepicker[ "_" + options + "Datepicker" ] 9329 .apply( $.datepicker, [ this ].concat( otherArgs ) ); 9330 } else { 9331 $.datepicker._attachDatepicker( this, options ); 9332 } 9333 } ); 9334}; 9335 9336$.datepicker = new Datepicker(); // singleton instance 9337$.datepicker.initialized = false; 9338$.datepicker.uuid = new Date().getTime(); 9339$.datepicker.version = "1.14.1"; 9340 9341var widgetsDatepicker = $.datepicker; 9342 9343 9344/*! 9345 * jQuery UI Mouse 1.14.1 9346 * https://jqueryui.com 9347 * 9348 * Copyright OpenJS Foundation and other contributors 9349 * Released under the MIT license. 9350 * https://jquery.org/license 9351 */ 9352 9353//>>label: Mouse 9354//>>group: Widgets 9355//>>description: Abstracts mouse-based interactions to assist in creating certain widgets. 9356//>>docs: https://api.jqueryui.com/mouse/ 9357 9358 9359var mouseHandled = false; 9360$( document ).on( "mouseup", function() { 9361 mouseHandled = false; 9362} ); 9363 9364var widgetsMouse = $.widget( "ui.mouse", { 9365 version: "1.14.1", 9366 options: { 9367 cancel: "input, textarea, button, select, option", 9368 distance: 1, 9369 delay: 0 9370 }, 9371 _mouseInit: function() { 9372 var that = this; 9373 9374 this.element 9375 .on( "mousedown." + this.widgetName, function( event ) { 9376 return that._mouseDown( event ); 9377 } ) 9378 .on( "click." + this.widgetName, function( event ) { 9379 if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) { 9380 $.removeData( event.target, that.widgetName + ".preventClickEvent" ); 9381 event.stopImmediatePropagation(); 9382 return false; 9383 } 9384 } ); 9385 9386 this.started = false; 9387 }, 9388 9389 // TODO: make sure destroying one instance of mouse doesn't mess with 9390 // other instances of mouse 9391 _mouseDestroy: function() { 9392 this.element.off( "." + this.widgetName ); 9393 if ( this._mouseMoveDelegate ) { 9394 this.document 9395 .off( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 9396 .off( "mouseup." + this.widgetName, this._mouseUpDelegate ); 9397 } 9398 }, 9399 9400 _mouseDown: function( event ) { 9401 9402 // don't let more than one widget handle mouseStart 9403 if ( mouseHandled ) { 9404 return; 9405 } 9406 9407 this._mouseMoved = false; 9408 9409 // We may have missed mouseup (out of window) 9410 if ( this._mouseStarted ) { 9411 this._mouseUp( event ); 9412 } 9413 9414 this._mouseDownEvent = event; 9415 9416 var that = this, 9417 btnIsLeft = event.which === 1, 9418 elIsCancel = typeof this.options.cancel === "string" ? 9419 $( event.target ).closest( this.options.cancel ).length : 9420 false; 9421 if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) { 9422 return true; 9423 } 9424 9425 this.mouseDelayMet = !this.options.delay; 9426 if ( !this.mouseDelayMet ) { 9427 this._mouseDelayTimer = setTimeout( function() { 9428 that.mouseDelayMet = true; 9429 }, this.options.delay ); 9430 } 9431 9432 if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) { 9433 this._mouseStarted = ( this._mouseStart( event ) !== false ); 9434 if ( !this._mouseStarted ) { 9435 event.preventDefault(); 9436 return true; 9437 } 9438 } 9439 9440 // Click event may never have fired (Gecko & Opera) 9441 if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) { 9442 $.removeData( event.target, this.widgetName + ".preventClickEvent" ); 9443 } 9444 9445 // These delegates are required to keep context 9446 this._mouseMoveDelegate = function( event ) { 9447 return that._mouseMove( event ); 9448 }; 9449 this._mouseUpDelegate = function( event ) { 9450 return that._mouseUp( event ); 9451 }; 9452 9453 this.document 9454 .on( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 9455 .on( "mouseup." + this.widgetName, this._mouseUpDelegate ); 9456 9457 event.preventDefault(); 9458 9459 mouseHandled = true; 9460 return true; 9461 }, 9462 9463 _mouseMove: function( event ) { 9464 9465 // Only check for mouseups outside the document if you've moved inside the document 9466 // at least once. 9467 if ( this._mouseMoved && !event.which ) { 9468 9469 // Support: Safari <=8 - 9 9470 // Safari sets which to 0 if you press any of the following keys 9471 // during a drag (#14461) 9472 if ( event.originalEvent.altKey || event.originalEvent.ctrlKey || 9473 event.originalEvent.metaKey || event.originalEvent.shiftKey ) { 9474 this.ignoreMissingWhich = true; 9475 } else if ( !this.ignoreMissingWhich ) { 9476 return this._mouseUp( event ); 9477 } 9478 } 9479 9480 if ( event.which || event.button ) { 9481 this._mouseMoved = true; 9482 } 9483 9484 if ( this._mouseStarted ) { 9485 this._mouseDrag( event ); 9486 return event.preventDefault(); 9487 } 9488 9489 if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) { 9490 this._mouseStarted = 9491 ( this._mouseStart( this._mouseDownEvent, event ) !== false ); 9492 if ( this._mouseStarted ) { 9493 this._mouseDrag( event ); 9494 } else { 9495 this._mouseUp( event ); 9496 } 9497 } 9498 9499 return !this._mouseStarted; 9500 }, 9501 9502 _mouseUp: function( event ) { 9503 this.document 9504 .off( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 9505 .off( "mouseup." + this.widgetName, this._mouseUpDelegate ); 9506 9507 if ( this._mouseStarted ) { 9508 this._mouseStarted = false; 9509 9510 if ( event.target === this._mouseDownEvent.target ) { 9511 $.data( event.target, this.widgetName + ".preventClickEvent", true ); 9512 } 9513 9514 this._mouseStop( event ); 9515 } 9516 9517 if ( this._mouseDelayTimer ) { 9518 clearTimeout( this._mouseDelayTimer ); 9519 delete this._mouseDelayTimer; 9520 } 9521 9522 this.ignoreMissingWhich = false; 9523 mouseHandled = false; 9524 event.preventDefault(); 9525 }, 9526 9527 _mouseDistanceMet: function( event ) { 9528 return ( Math.max( 9529 Math.abs( this._mouseDownEvent.pageX - event.pageX ), 9530 Math.abs( this._mouseDownEvent.pageY - event.pageY ) 9531 ) >= this.options.distance 9532 ); 9533 }, 9534 9535 _mouseDelayMet: function( /* event */ ) { 9536 return this.mouseDelayMet; 9537 }, 9538 9539 // These are placeholder methods, to be overriden by extending plugin 9540 _mouseStart: function( /* event */ ) {}, 9541 _mouseDrag: function( /* event */ ) {}, 9542 _mouseStop: function( /* event */ ) {}, 9543 _mouseCapture: function( /* event */ ) { 9544 return true; 9545 } 9546} ); 9547 9548 9549 9550// $.ui.plugin is deprecated. Use $.widget() extensions instead. 9551var plugin = $.ui.plugin = { 9552 add: function( module, option, set ) { 9553 var i, 9554 proto = $.ui[ module ].prototype; 9555 for ( i in set ) { 9556 proto.plugins[ i ] = proto.plugins[ i ] || []; 9557 proto.plugins[ i ].push( [ option, set[ i ] ] ); 9558 } 9559 }, 9560 call: function( instance, name, args, allowDisconnected ) { 9561 var i, 9562 set = instance.plugins[ name ]; 9563 9564 if ( !set ) { 9565 return; 9566 } 9567 9568 if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || 9569 instance.element[ 0 ].parentNode.nodeType === 11 ) ) { 9570 return; 9571 } 9572 9573 for ( i = 0; i < set.length; i++ ) { 9574 if ( instance.options[ set[ i ][ 0 ] ] ) { 9575 set[ i ][ 1 ].apply( instance.element, args ); 9576 } 9577 } 9578 } 9579}; 9580 9581 9582/*! 9583 * jQuery UI Draggable 1.14.1 9584 * https://jqueryui.com 9585 * 9586 * Copyright OpenJS Foundation and other contributors 9587 * Released under the MIT license. 9588 * https://jquery.org/license 9589 */ 9590 9591//>>label: Draggable 9592//>>group: Interactions 9593//>>description: Enables dragging functionality for any element. 9594//>>docs: https://api.jqueryui.com/draggable/ 9595//>>demos: https://jqueryui.com/draggable/ 9596//>>css.structure: ../../themes/base/draggable.css 9597 9598 9599$.widget( "ui.draggable", $.ui.mouse, { 9600 version: "1.14.1", 9601 widgetEventPrefix: "drag", 9602 options: { 9603 addClasses: true, 9604 appendTo: "parent", 9605 axis: false, 9606 connectToSortable: false, 9607 containment: false, 9608 cursor: "auto", 9609 cursorAt: false, 9610 grid: false, 9611 handle: false, 9612 helper: "original", 9613 iframeFix: false, 9614 opacity: false, 9615 refreshPositions: false, 9616 revert: false, 9617 revertDuration: 500, 9618 scope: "default", 9619 scroll: true, 9620 scrollSensitivity: 20, 9621 scrollSpeed: 20, 9622 snap: false, 9623 snapMode: "both", 9624 snapTolerance: 20, 9625 stack: false, 9626 zIndex: false, 9627 9628 // Callbacks 9629 drag: null, 9630 start: null, 9631 stop: null 9632 }, 9633 _create: function() { 9634 9635 if ( this.options.helper === "original" ) { 9636 this._setPositionRelative(); 9637 } 9638 if ( this.options.addClasses ) { 9639 this._addClass( "ui-draggable" ); 9640 } 9641 this._setHandleClassName(); 9642 9643 this._mouseInit(); 9644 }, 9645 9646 _setOption: function( key, value ) { 9647 this._super( key, value ); 9648 if ( key === "handle" ) { 9649 this._removeHandleClassName(); 9650 this._setHandleClassName(); 9651 } 9652 }, 9653 9654 _destroy: function() { 9655 if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) { 9656 this.destroyOnClear = true; 9657 return; 9658 } 9659 this._removeHandleClassName(); 9660 this._mouseDestroy(); 9661 }, 9662 9663 _mouseCapture: function( event ) { 9664 var o = this.options; 9665 9666 // Among others, prevent a drag on a resizable-handle 9667 if ( this.helper || o.disabled || 9668 $( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) { 9669 return false; 9670 } 9671 9672 //Quit if we're not on a valid handle 9673 this.handle = this._getHandle( event ); 9674 if ( !this.handle ) { 9675 return false; 9676 } 9677 9678 this._blurActiveElement( event ); 9679 9680 this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix ); 9681 9682 return true; 9683 9684 }, 9685 9686 _blockFrames: function( selector ) { 9687 this.iframeBlocks = this.document.find( selector ).map( function() { 9688 var iframe = $( this ); 9689 9690 return $( "<div>" ) 9691 .css( "position", "absolute" ) 9692 .appendTo( iframe.parent() ) 9693 .outerWidth( iframe.outerWidth() ) 9694 .outerHeight( iframe.outerHeight() ) 9695 .offset( iframe.offset() )[ 0 ]; 9696 } ); 9697 }, 9698 9699 _unblockFrames: function() { 9700 if ( this.iframeBlocks ) { 9701 this.iframeBlocks.remove(); 9702 delete this.iframeBlocks; 9703 } 9704 }, 9705 9706 _blurActiveElement: function( event ) { 9707 var activeElement = this.document[ 0 ].activeElement, 9708 target = $( event.target ); 9709 9710 // Don't blur if the event occurred on an element that is within 9711 // the currently focused element 9712 // See #10527, #12472 9713 if ( target.closest( activeElement ).length ) { 9714 return; 9715 } 9716 9717 // Blur any element that currently has focus, see #4261 9718 $( activeElement ).trigger( "blur" ); 9719 }, 9720 9721 _mouseStart: function( event ) { 9722 9723 var o = this.options; 9724 9725 //Create and append the visible helper 9726 this.helper = this._createHelper( event ); 9727 9728 this._addClass( this.helper, "ui-draggable-dragging" ); 9729 9730 //Cache the helper size 9731 this._cacheHelperProportions(); 9732 9733 //If ddmanager is used for droppables, set the global draggable 9734 if ( $.ui.ddmanager ) { 9735 $.ui.ddmanager.current = this; 9736 } 9737 9738 /* 9739 * - Position generation - 9740 * This block generates everything position related - it's the core of draggables. 9741 */ 9742 9743 //Cache the margins of the original element 9744 this._cacheMargins(); 9745 9746 //Store the helper's css position 9747 this.cssPosition = this.helper.css( "position" ); 9748 this.scrollParent = this.helper.scrollParent( true ); 9749 this.offsetParent = this.helper.offsetParent(); 9750 this.hasFixedAncestor = this.helper.parents().filter( function() { 9751 return $( this ).css( "position" ) === "fixed"; 9752 } ).length > 0; 9753 9754 //The element's absolute position on the page minus margins 9755 this.positionAbs = this.element.offset(); 9756 this._refreshOffsets( event ); 9757 9758 //Generate the original position 9759 this.originalPosition = this.position = this._generatePosition( event, false ); 9760 this.originalPageX = event.pageX; 9761 this.originalPageY = event.pageY; 9762 9763 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 9764 if ( o.cursorAt ) { 9765 this._adjustOffsetFromHelper( o.cursorAt ); 9766 } 9767 9768 //Set a containment if given in the options 9769 this._setContainment(); 9770 9771 //Trigger event + callbacks 9772 if ( this._trigger( "start", event ) === false ) { 9773 this._clear(); 9774 return false; 9775 } 9776 9777 //Recache the helper size 9778 this._cacheHelperProportions(); 9779 9780 //Prepare the droppable offsets 9781 if ( $.ui.ddmanager && !o.dropBehaviour ) { 9782 $.ui.ddmanager.prepareOffsets( this, event ); 9783 } 9784 9785 // Execute the drag once - this causes the helper not to be visible before getting its 9786 // correct position 9787 this._mouseDrag( event, true ); 9788 9789 // If the ddmanager is used for droppables, inform the manager that dragging has started 9790 // (see #5003) 9791 if ( $.ui.ddmanager ) { 9792 $.ui.ddmanager.dragStart( this, event ); 9793 } 9794 9795 return true; 9796 }, 9797 9798 _refreshOffsets: function( event ) { 9799 this.offset = { 9800 top: this.positionAbs.top - this.margins.top, 9801 left: this.positionAbs.left - this.margins.left, 9802 scroll: false, 9803 parent: this._getParentOffset(), 9804 relative: this._getRelativeOffset() 9805 }; 9806 9807 this.offset.click = { 9808 left: event.pageX - this.offset.left, 9809 top: event.pageY - this.offset.top 9810 }; 9811 }, 9812 9813 _mouseDrag: function( event, noPropagation ) { 9814 9815 // reset any necessary cached properties (see #5009) 9816 if ( this.hasFixedAncestor ) { 9817 this.offset.parent = this._getParentOffset(); 9818 } 9819 9820 //Compute the helpers position 9821 this.position = this._generatePosition( event, true ); 9822 this.positionAbs = this._convertPositionTo( "absolute" ); 9823 9824 //Call plugins and callbacks and use the resulting position if something is returned 9825 if ( !noPropagation ) { 9826 var ui = this._uiHash(); 9827 if ( this._trigger( "drag", event, ui ) === false ) { 9828 this._mouseUp( new $.Event( "mouseup", event ) ); 9829 return false; 9830 } 9831 this.position = ui.position; 9832 } 9833 9834 this.helper[ 0 ].style.left = this.position.left + "px"; 9835 this.helper[ 0 ].style.top = this.position.top + "px"; 9836 9837 if ( $.ui.ddmanager ) { 9838 $.ui.ddmanager.drag( this, event ); 9839 } 9840 9841 return false; 9842 }, 9843 9844 _mouseStop: function( event ) { 9845 9846 //If we are using droppables, inform the manager about the drop 9847 var that = this, 9848 dropped = false; 9849 if ( $.ui.ddmanager && !this.options.dropBehaviour ) { 9850 dropped = $.ui.ddmanager.drop( this, event ); 9851 } 9852 9853 //if a drop comes from outside (a sortable) 9854 if ( this.dropped ) { 9855 dropped = this.dropped; 9856 this.dropped = false; 9857 } 9858 9859 if ( ( this.options.revert === "invalid" && !dropped ) || 9860 ( this.options.revert === "valid" && dropped ) || 9861 this.options.revert === true || ( typeof this.options.revert === "function" && 9862 this.options.revert.call( this.element, dropped ) ) 9863 ) { 9864 $( this.helper ).animate( 9865 this.originalPosition, 9866 parseInt( this.options.revertDuration, 10 ), 9867 function() { 9868 if ( that._trigger( "stop", event ) !== false ) { 9869 that._clear(); 9870 } 9871 } 9872 ); 9873 } else { 9874 if ( this._trigger( "stop", event ) !== false ) { 9875 this._clear(); 9876 } 9877 } 9878 9879 return false; 9880 }, 9881 9882 _mouseUp: function( event ) { 9883 this._unblockFrames(); 9884 9885 // If the ddmanager is used for droppables, inform the manager that dragging has stopped 9886 // (see #5003) 9887 if ( $.ui.ddmanager ) { 9888 $.ui.ddmanager.dragStop( this, event ); 9889 } 9890 9891 // Only need to focus if the event occurred on the draggable itself, see #10527 9892 if ( this.handleElement.is( event.target ) ) { 9893 9894 // The interaction is over; whether or not the click resulted in a drag, 9895 // focus the element 9896 this.element.trigger( "focus" ); 9897 } 9898 9899 return $.ui.mouse.prototype._mouseUp.call( this, event ); 9900 }, 9901 9902 cancel: function() { 9903 9904 if ( this.helper.is( ".ui-draggable-dragging" ) ) { 9905 this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) ); 9906 } else { 9907 this._clear(); 9908 } 9909 9910 return this; 9911 9912 }, 9913 9914 _getHandle: function( event ) { 9915 return this.options.handle ? 9916 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length : 9917 true; 9918 }, 9919 9920 _setHandleClassName: function() { 9921 this.handleElement = this.options.handle ? 9922 this.element.find( this.options.handle ) : this.element; 9923 this._addClass( this.handleElement, "ui-draggable-handle" ); 9924 }, 9925 9926 _removeHandleClassName: function() { 9927 this._removeClass( this.handleElement, "ui-draggable-handle" ); 9928 }, 9929 9930 _createHelper: function( event ) { 9931 9932 var o = this.options, 9933 helperIsFunction = typeof o.helper === "function", 9934 helper = helperIsFunction ? 9935 $( o.helper.apply( this.element[ 0 ], [ event ] ) ) : 9936 ( o.helper === "clone" ? 9937 this.element.clone().removeAttr( "id" ) : 9938 this.element ); 9939 9940 if ( !helper.parents( "body" ).length ) { 9941 helper.appendTo( ( o.appendTo === "parent" ? 9942 this.element[ 0 ].parentNode : 9943 o.appendTo ) ); 9944 } 9945 9946 // https://bugs.jqueryui.com/ticket/9446 9947 // a helper function can return the original element 9948 // which wouldn't have been set to relative in _create 9949 if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) { 9950 this._setPositionRelative(); 9951 } 9952 9953 if ( helper[ 0 ] !== this.element[ 0 ] && 9954 !( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) { 9955 helper.css( "position", "absolute" ); 9956 } 9957 9958 return helper; 9959 9960 }, 9961 9962 _setPositionRelative: function() { 9963 if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) { 9964 this.element[ 0 ].style.position = "relative"; 9965 } 9966 }, 9967 9968 _adjustOffsetFromHelper: function( obj ) { 9969 if ( typeof obj === "string" ) { 9970 obj = obj.split( " " ); 9971 } 9972 if ( Array.isArray( obj ) ) { 9973 obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 }; 9974 } 9975 if ( "left" in obj ) { 9976 this.offset.click.left = obj.left + this.margins.left; 9977 } 9978 if ( "right" in obj ) { 9979 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 9980 } 9981 if ( "top" in obj ) { 9982 this.offset.click.top = obj.top + this.margins.top; 9983 } 9984 if ( "bottom" in obj ) { 9985 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 9986 } 9987 }, 9988 9989 _isRootNode: function( element ) { 9990 return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ]; 9991 }, 9992 9993 _getParentOffset: function() { 9994 9995 //Get the offsetParent and cache its position 9996 var po = this.offsetParent.offset(), 9997 document = this.document[ 0 ]; 9998 9999 // This is a special case where we need to modify a offset calculated on start, since the 10000 // following happened: 10001 // 1. The position of the helper is absolute, so it's position is calculated based on the 10002 // next positioned parent 10003 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't 10004 // the document, which means that the scroll is included in the initial calculation of the 10005 // offset of the parent, and never recalculated upon drag 10006 if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document && 10007 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) { 10008 po.left += this.scrollParent.scrollLeft(); 10009 po.top += this.scrollParent.scrollTop(); 10010 } 10011 10012 if ( this._isRootNode( this.offsetParent[ 0 ] ) ) { 10013 po = { top: 0, left: 0 }; 10014 } 10015 10016 return { 10017 top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ), 10018 left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 ) 10019 }; 10020 10021 }, 10022 10023 _getRelativeOffset: function() { 10024 if ( this.cssPosition !== "relative" ) { 10025 return { top: 0, left: 0 }; 10026 } 10027 10028 var p = this.element.position(), 10029 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ); 10030 10031 return { 10032 top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) + 10033 ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ), 10034 left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) + 10035 ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 ) 10036 }; 10037 10038 }, 10039 10040 _cacheMargins: function() { 10041 this.margins = { 10042 left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ), 10043 top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ), 10044 right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ), 10045 bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 ) 10046 }; 10047 }, 10048 10049 _cacheHelperProportions: function() { 10050 this.helperProportions = { 10051 width: this.helper.outerWidth(), 10052 height: this.helper.outerHeight() 10053 }; 10054 }, 10055 10056 _setContainment: function() { 10057 10058 var isUserScrollable, c, ce, 10059 o = this.options, 10060 document = this.document[ 0 ]; 10061 10062 this.relativeContainer = null; 10063 10064 if ( !o.containment ) { 10065 this.containment = null; 10066 return; 10067 } 10068 10069 if ( o.containment === "window" ) { 10070 this.containment = [ 10071 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left, 10072 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top, 10073 $( window ).scrollLeft() + $( window ).width() - 10074 this.helperProportions.width - this.margins.left, 10075 $( window ).scrollTop() + 10076 ( $( window ).height() || document.body.parentNode.scrollHeight ) - 10077 this.helperProportions.height - this.margins.top 10078 ]; 10079 return; 10080 } 10081 10082 if ( o.containment === "document" ) { 10083 this.containment = [ 10084 0, 10085 0, 10086 $( document ).width() - this.helperProportions.width - this.margins.left, 10087 ( $( document ).height() || document.body.parentNode.scrollHeight ) - 10088 this.helperProportions.height - this.margins.top 10089 ]; 10090 return; 10091 } 10092 10093 if ( o.containment.constructor === Array ) { 10094 this.containment = o.containment; 10095 return; 10096 } 10097 10098 if ( o.containment === "parent" ) { 10099 o.containment = this.helper[ 0 ].parentNode; 10100 } 10101 10102 c = $( o.containment ); 10103 ce = c[ 0 ]; 10104 10105 if ( !ce ) { 10106 return; 10107 } 10108 10109 isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) ); 10110 10111 this.containment = [ 10112 ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + 10113 ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ), 10114 ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + 10115 ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ), 10116 ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - 10117 ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - 10118 ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - 10119 this.helperProportions.width - 10120 this.margins.left - 10121 this.margins.right, 10122 ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - 10123 ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - 10124 ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - 10125 this.helperProportions.height - 10126 this.margins.top - 10127 this.margins.bottom 10128 ]; 10129 this.relativeContainer = c; 10130 }, 10131 10132 _convertPositionTo: function( d, pos ) { 10133 10134 if ( !pos ) { 10135 pos = this.position; 10136 } 10137 10138 var mod = d === "absolute" ? 1 : -1, 10139 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ); 10140 10141 return { 10142 top: ( 10143 10144 // The absolute mouse position 10145 pos.top + 10146 10147 // Only for relative positioned nodes: Relative offset from element to offset parent 10148 this.offset.relative.top * mod + 10149 10150 // The offsetParent's offset without borders (offset + border) 10151 this.offset.parent.top * mod - 10152 ( ( this.cssPosition === "fixed" ? 10153 -this.offset.scroll.top : 10154 ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod ) 10155 ), 10156 left: ( 10157 10158 // The absolute mouse position 10159 pos.left + 10160 10161 // Only for relative positioned nodes: Relative offset from element to offset parent 10162 this.offset.relative.left * mod + 10163 10164 // The offsetParent's offset without borders (offset + border) 10165 this.offset.parent.left * mod - 10166 ( ( this.cssPosition === "fixed" ? 10167 -this.offset.scroll.left : 10168 ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod ) 10169 ) 10170 }; 10171 10172 }, 10173 10174 _generatePosition: function( event, constrainPosition ) { 10175 10176 var containment, co, top, left, 10177 o = this.options, 10178 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ), 10179 pageX = event.pageX, 10180 pageY = event.pageY; 10181 10182 // Cache the scroll 10183 if ( !scrollIsRootNode || !this.offset.scroll ) { 10184 this.offset.scroll = { 10185 top: this.scrollParent.scrollTop(), 10186 left: this.scrollParent.scrollLeft() 10187 }; 10188 } 10189 10190 /* 10191 * - Position constraining - 10192 * Constrain the position to a mix of grid, containment. 10193 */ 10194 10195 // If we are not dragging yet, we won't check for options 10196 if ( constrainPosition ) { 10197 if ( this.containment ) { 10198 if ( this.relativeContainer ) { 10199 co = this.relativeContainer.offset(); 10200 containment = [ 10201 this.containment[ 0 ] + co.left, 10202 this.containment[ 1 ] + co.top, 10203 this.containment[ 2 ] + co.left, 10204 this.containment[ 3 ] + co.top 10205 ]; 10206 } else { 10207 containment = this.containment; 10208 } 10209 10210 if ( event.pageX - this.offset.click.left < containment[ 0 ] ) { 10211 pageX = containment[ 0 ] + this.offset.click.left; 10212 } 10213 if ( event.pageY - this.offset.click.top < containment[ 1 ] ) { 10214 pageY = containment[ 1 ] + this.offset.click.top; 10215 } 10216 if ( event.pageX - this.offset.click.left > containment[ 2 ] ) { 10217 pageX = containment[ 2 ] + this.offset.click.left; 10218 } 10219 if ( event.pageY - this.offset.click.top > containment[ 3 ] ) { 10220 pageY = containment[ 3 ] + this.offset.click.top; 10221 } 10222 } 10223 10224 if ( o.grid ) { 10225 10226 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid 10227 // argument errors in IE (see ticket #6950) 10228 top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY - 10229 this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY; 10230 pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] || 10231 top - this.offset.click.top > containment[ 3 ] ) ? 10232 top : 10233 ( ( top - this.offset.click.top >= containment[ 1 ] ) ? 10234 top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top; 10235 10236 left = o.grid[ 0 ] ? this.originalPageX + 10237 Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] : 10238 this.originalPageX; 10239 pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] || 10240 left - this.offset.click.left > containment[ 2 ] ) ? 10241 left : 10242 ( ( left - this.offset.click.left >= containment[ 0 ] ) ? 10243 left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left; 10244 } 10245 10246 if ( o.axis === "y" ) { 10247 pageX = this.originalPageX; 10248 } 10249 10250 if ( o.axis === "x" ) { 10251 pageY = this.originalPageY; 10252 } 10253 } 10254 10255 return { 10256 top: ( 10257 10258 // The absolute mouse position 10259 pageY - 10260 10261 // Click offset (relative to the element) 10262 this.offset.click.top - 10263 10264 // Only for relative positioned nodes: Relative offset from element to offset parent 10265 this.offset.relative.top - 10266 10267 // The offsetParent's offset without borders (offset + border) 10268 this.offset.parent.top + 10269 ( this.cssPosition === "fixed" ? 10270 -this.offset.scroll.top : 10271 ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) 10272 ), 10273 left: ( 10274 10275 // The absolute mouse position 10276 pageX - 10277 10278 // Click offset (relative to the element) 10279 this.offset.click.left - 10280 10281 // Only for relative positioned nodes: Relative offset from element to offset parent 10282 this.offset.relative.left - 10283 10284 // The offsetParent's offset without borders (offset + border) 10285 this.offset.parent.left + 10286 ( this.cssPosition === "fixed" ? 10287 -this.offset.scroll.left : 10288 ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) 10289 ) 10290 }; 10291 10292 }, 10293 10294 _clear: function() { 10295 this._removeClass( this.helper, "ui-draggable-dragging" ); 10296 if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) { 10297 this.helper.remove(); 10298 } 10299 this.helper = null; 10300 this.cancelHelperRemoval = false; 10301 if ( this.destroyOnClear ) { 10302 this.destroy(); 10303 } 10304 }, 10305 10306 // From now on bulk stuff - mainly helpers 10307 10308 _trigger: function( type, event, ui ) { 10309 ui = ui || this._uiHash(); 10310 $.ui.plugin.call( this, type, [ event, ui, this ], true ); 10311 10312 // Absolute position and offset (see #6884 ) have to be recalculated after plugins 10313 if ( /^(drag|start|stop)/.test( type ) ) { 10314 this.positionAbs = this._convertPositionTo( "absolute" ); 10315 ui.offset = this.positionAbs; 10316 } 10317 return $.Widget.prototype._trigger.call( this, type, event, ui ); 10318 }, 10319 10320 plugins: {}, 10321 10322 _uiHash: function() { 10323 return { 10324 helper: this.helper, 10325 position: this.position, 10326 originalPosition: this.originalPosition, 10327 offset: this.positionAbs 10328 }; 10329 } 10330 10331} ); 10332 10333$.ui.plugin.add( "draggable", "connectToSortable", { 10334 start: function( event, ui, draggable ) { 10335 var uiSortable = $.extend( {}, ui, { 10336 item: draggable.element 10337 } ); 10338 10339 draggable.sortables = []; 10340 $( draggable.options.connectToSortable ).each( function() { 10341 var sortable = $( this ).sortable( "instance" ); 10342 10343 if ( sortable && !sortable.options.disabled ) { 10344 draggable.sortables.push( sortable ); 10345 10346 // RefreshPositions is called at drag start to refresh the containerCache 10347 // which is used in drag. This ensures it's initialized and synchronized 10348 // with any changes that might have happened on the page since initialization. 10349 sortable.refreshPositions(); 10350 sortable._trigger( "activate", event, uiSortable ); 10351 } 10352 } ); 10353 }, 10354 stop: function( event, ui, draggable ) { 10355 var uiSortable = $.extend( {}, ui, { 10356 item: draggable.element 10357 } ); 10358 10359 draggable.cancelHelperRemoval = false; 10360 10361 $.each( draggable.sortables, function() { 10362 var sortable = this; 10363 10364 if ( sortable.isOver ) { 10365 sortable.isOver = 0; 10366 10367 // Allow this sortable to handle removing the helper 10368 draggable.cancelHelperRemoval = true; 10369 sortable.cancelHelperRemoval = false; 10370 10371 // Use _storedCSS To restore properties in the sortable, 10372 // as this also handles revert (#9675) since the draggable 10373 // may have modified them in unexpected ways (#8809) 10374 sortable._storedCSS = { 10375 position: sortable.placeholder.css( "position" ), 10376 top: sortable.placeholder.css( "top" ), 10377 left: sortable.placeholder.css( "left" ) 10378 }; 10379 10380 sortable._mouseStop( event ); 10381 10382 // Once drag has ended, the sortable should return to using 10383 // its original helper, not the shared helper from draggable 10384 sortable.options.helper = sortable.options._helper; 10385 } else { 10386 10387 // Prevent this Sortable from removing the helper. 10388 // However, don't set the draggable to remove the helper 10389 // either as another connected Sortable may yet handle the removal. 10390 sortable.cancelHelperRemoval = true; 10391 10392 sortable._trigger( "deactivate", event, uiSortable ); 10393 } 10394 } ); 10395 }, 10396 drag: function( event, ui, draggable ) { 10397 $.each( draggable.sortables, function() { 10398 var innermostIntersecting = false, 10399 sortable = this; 10400 10401 // Copy over variables that sortable's _intersectsWith uses 10402 sortable.positionAbs = draggable.positionAbs; 10403 sortable.helperProportions = draggable.helperProportions; 10404 sortable.offset.click = draggable.offset.click; 10405 10406 if ( sortable._intersectsWith( sortable.containerCache ) ) { 10407 innermostIntersecting = true; 10408 10409 $.each( draggable.sortables, function() { 10410 10411 // Copy over variables that sortable's _intersectsWith uses 10412 this.positionAbs = draggable.positionAbs; 10413 this.helperProportions = draggable.helperProportions; 10414 this.offset.click = draggable.offset.click; 10415 10416 if ( this !== sortable && 10417 this._intersectsWith( this.containerCache ) && 10418 $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) { 10419 innermostIntersecting = false; 10420 } 10421 10422 return innermostIntersecting; 10423 } ); 10424 } 10425 10426 if ( innermostIntersecting ) { 10427 10428 // If it intersects, we use a little isOver variable and set it once, 10429 // so that the move-in stuff gets fired only once. 10430 if ( !sortable.isOver ) { 10431 sortable.isOver = 1; 10432 10433 // Store draggable's parent in case we need to reappend to it later. 10434 draggable._parent = ui.helper.parent(); 10435 10436 sortable.currentItem = ui.helper 10437 .appendTo( sortable.element ) 10438 .data( "ui-sortable-item", true ); 10439 10440 // Store helper option to later restore it 10441 sortable.options._helper = sortable.options.helper; 10442 10443 sortable.options.helper = function() { 10444 return ui.helper[ 0 ]; 10445 }; 10446 10447 // Fire the start events of the sortable with our passed browser event, 10448 // and our own helper (so it doesn't create a new one) 10449 event.target = sortable.currentItem[ 0 ]; 10450 sortable._mouseCapture( event, true ); 10451 sortable._mouseStart( event, true, true ); 10452 10453 // Because the browser event is way off the new appended portlet, 10454 // modify necessary variables to reflect the changes 10455 sortable.offset.click.top = draggable.offset.click.top; 10456 sortable.offset.click.left = draggable.offset.click.left; 10457 sortable.offset.parent.left -= draggable.offset.parent.left - 10458 sortable.offset.parent.left; 10459 sortable.offset.parent.top -= draggable.offset.parent.top - 10460 sortable.offset.parent.top; 10461 10462 draggable._trigger( "toSortable", event ); 10463 10464 // Inform draggable that the helper is in a valid drop zone, 10465 // used solely in the revert option to handle "valid/invalid". 10466 draggable.dropped = sortable.element; 10467 10468 // Need to refreshPositions of all sortables in the case that 10469 // adding to one sortable changes the location of the other sortables (#9675) 10470 $.each( draggable.sortables, function() { 10471 this.refreshPositions(); 10472 } ); 10473 10474 // Hack so receive/update callbacks work (mostly) 10475 draggable.currentItem = draggable.element; 10476 sortable.fromOutside = draggable; 10477 } 10478 10479 if ( sortable.currentItem ) { 10480 sortable._mouseDrag( event ); 10481 10482 // Copy the sortable's position because the draggable's can potentially reflect 10483 // a relative position, while sortable is always absolute, which the dragged 10484 // element has now become. (#8809) 10485 ui.position = sortable.position; 10486 } 10487 } else { 10488 10489 // If it doesn't intersect with the sortable, and it intersected before, 10490 // we fake the drag stop of the sortable, but make sure it doesn't remove 10491 // the helper by using cancelHelperRemoval. 10492 if ( sortable.isOver ) { 10493 10494 sortable.isOver = 0; 10495 sortable.cancelHelperRemoval = true; 10496 10497 // Calling sortable's mouseStop would trigger a revert, 10498 // so revert must be temporarily false until after mouseStop is called. 10499 sortable.options._revert = sortable.options.revert; 10500 sortable.options.revert = false; 10501 10502 sortable._trigger( "out", event, sortable._uiHash( sortable ) ); 10503 sortable._mouseStop( event, true ); 10504 10505 // Restore sortable behaviors that were modfied 10506 // when the draggable entered the sortable area (#9481) 10507 sortable.options.revert = sortable.options._revert; 10508 sortable.options.helper = sortable.options._helper; 10509 10510 if ( sortable.placeholder ) { 10511 sortable.placeholder.remove(); 10512 } 10513 10514 // Restore and recalculate the draggable's offset considering the sortable 10515 // may have modified them in unexpected ways. (#8809, #10669) 10516 ui.helper.appendTo( draggable._parent ); 10517 draggable._refreshOffsets( event ); 10518 ui.position = draggable._generatePosition( event, true ); 10519 10520 draggable._trigger( "fromSortable", event ); 10521 10522 // Inform draggable that the helper is no longer in a valid drop zone 10523 draggable.dropped = false; 10524 10525 // Need to refreshPositions of all sortables just in case removing 10526 // from one sortable changes the location of other sortables (#9675) 10527 $.each( draggable.sortables, function() { 10528 this.refreshPositions(); 10529 } ); 10530 } 10531 } 10532 } ); 10533 } 10534} ); 10535 10536$.ui.plugin.add( "draggable", "cursor", { 10537 start: function( event, ui, instance ) { 10538 var t = $( "body" ), 10539 o = instance.options; 10540 10541 if ( t.css( "cursor" ) ) { 10542 o._cursor = t.css( "cursor" ); 10543 } 10544 t.css( "cursor", o.cursor ); 10545 }, 10546 stop: function( event, ui, instance ) { 10547 var o = instance.options; 10548 if ( o._cursor ) { 10549 $( "body" ).css( "cursor", o._cursor ); 10550 } 10551 } 10552} ); 10553 10554$.ui.plugin.add( "draggable", "opacity", { 10555 start: function( event, ui, instance ) { 10556 var t = $( ui.helper ), 10557 o = instance.options; 10558 if ( t.css( "opacity" ) ) { 10559 o._opacity = t.css( "opacity" ); 10560 } 10561 t.css( "opacity", o.opacity ); 10562 }, 10563 stop: function( event, ui, instance ) { 10564 var o = instance.options; 10565 if ( o._opacity ) { 10566 $( ui.helper ).css( "opacity", o._opacity ); 10567 } 10568 } 10569} ); 10570 10571$.ui.plugin.add( "draggable", "scroll", { 10572 start: function( event, ui, i ) { 10573 if ( !i.scrollParentNotHidden ) { 10574 i.scrollParentNotHidden = i.helper.scrollParent( false ); 10575 } 10576 10577 if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] && 10578 i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) { 10579 i.overflowOffset = i.scrollParentNotHidden.offset(); 10580 } 10581 }, 10582 drag: function( event, ui, i ) { 10583 10584 var o = i.options, 10585 scrolled = false, 10586 scrollParent = i.scrollParentNotHidden[ 0 ], 10587 document = i.document[ 0 ]; 10588 10589 if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) { 10590 if ( !o.axis || o.axis !== "x" ) { 10591 if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY < 10592 o.scrollSensitivity ) { 10593 scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed; 10594 } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) { 10595 scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed; 10596 } 10597 } 10598 10599 if ( !o.axis || o.axis !== "y" ) { 10600 if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX < 10601 o.scrollSensitivity ) { 10602 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed; 10603 } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) { 10604 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed; 10605 } 10606 } 10607 10608 } else { 10609 10610 if ( !o.axis || o.axis !== "x" ) { 10611 if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) { 10612 scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed ); 10613 } else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) < 10614 o.scrollSensitivity ) { 10615 scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed ); 10616 } 10617 } 10618 10619 if ( !o.axis || o.axis !== "y" ) { 10620 if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) { 10621 scrolled = $( document ).scrollLeft( 10622 $( document ).scrollLeft() - o.scrollSpeed 10623 ); 10624 } else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) < 10625 o.scrollSensitivity ) { 10626 scrolled = $( document ).scrollLeft( 10627 $( document ).scrollLeft() + o.scrollSpeed 10628 ); 10629 } 10630 } 10631 10632 } 10633 10634 if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) { 10635 $.ui.ddmanager.prepareOffsets( i, event ); 10636 } 10637 10638 } 10639} ); 10640 10641$.ui.plugin.add( "draggable", "snap", { 10642 start: function( event, ui, i ) { 10643 10644 var o = i.options; 10645 10646 i.snapElements = []; 10647 10648 $( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap ) 10649 .each( function() { 10650 var $t = $( this ), 10651 $o = $t.offset(); 10652 if ( this !== i.element[ 0 ] ) { 10653 i.snapElements.push( { 10654 item: this, 10655 width: $t.outerWidth(), height: $t.outerHeight(), 10656 top: $o.top, left: $o.left 10657 } ); 10658 } 10659 } ); 10660 10661 }, 10662 drag: function( event, ui, inst ) { 10663 10664 var ts, bs, ls, rs, l, r, t, b, i, first, 10665 o = inst.options, 10666 d = o.snapTolerance, 10667 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, 10668 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; 10669 10670 for ( i = inst.snapElements.length - 1; i >= 0; i-- ) { 10671 10672 l = inst.snapElements[ i ].left - inst.margins.left; 10673 r = l + inst.snapElements[ i ].width; 10674 t = inst.snapElements[ i ].top - inst.margins.top; 10675 b = t + inst.snapElements[ i ].height; 10676 10677 if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || 10678 !$.contains( inst.snapElements[ i ].item.ownerDocument, 10679 inst.snapElements[ i ].item ) ) { 10680 if ( inst.snapElements[ i ].snapping ) { 10681 if ( inst.options.snap.release ) { 10682 inst.options.snap.release.call( 10683 inst.element, 10684 event, 10685 $.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } ) 10686 ); 10687 } 10688 } 10689 inst.snapElements[ i ].snapping = false; 10690 continue; 10691 } 10692 10693 if ( o.snapMode !== "inner" ) { 10694 ts = Math.abs( t - y2 ) <= d; 10695 bs = Math.abs( b - y1 ) <= d; 10696 ls = Math.abs( l - x2 ) <= d; 10697 rs = Math.abs( r - x1 ) <= d; 10698 if ( ts ) { 10699 ui.position.top = inst._convertPositionTo( "relative", { 10700 top: t - inst.helperProportions.height, 10701 left: 0 10702 } ).top; 10703 } 10704 if ( bs ) { 10705 ui.position.top = inst._convertPositionTo( "relative", { 10706 top: b, 10707 left: 0 10708 } ).top; 10709 } 10710 if ( ls ) { 10711 ui.position.left = inst._convertPositionTo( "relative", { 10712 top: 0, 10713 left: l - inst.helperProportions.width 10714 } ).left; 10715 } 10716 if ( rs ) { 10717 ui.position.left = inst._convertPositionTo( "relative", { 10718 top: 0, 10719 left: r 10720 } ).left; 10721 } 10722 } 10723 10724 first = ( ts || bs || ls || rs ); 10725 10726 if ( o.snapMode !== "outer" ) { 10727 ts = Math.abs( t - y1 ) <= d; 10728 bs = Math.abs( b - y2 ) <= d; 10729 ls = Math.abs( l - x1 ) <= d; 10730 rs = Math.abs( r - x2 ) <= d; 10731 if ( ts ) { 10732 ui.position.top = inst._convertPositionTo( "relative", { 10733 top: t, 10734 left: 0 10735 } ).top; 10736 } 10737 if ( bs ) { 10738 ui.position.top = inst._convertPositionTo( "relative", { 10739 top: b - inst.helperProportions.height, 10740 left: 0 10741 } ).top; 10742 } 10743 if ( ls ) { 10744 ui.position.left = inst._convertPositionTo( "relative", { 10745 top: 0, 10746 left: l 10747 } ).left; 10748 } 10749 if ( rs ) { 10750 ui.position.left = inst._convertPositionTo( "relative", { 10751 top: 0, 10752 left: r - inst.helperProportions.width 10753 } ).left; 10754 } 10755 } 10756 10757 if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) { 10758 if ( inst.options.snap.snap ) { 10759 inst.options.snap.snap.call( 10760 inst.element, 10761 event, 10762 $.extend( inst._uiHash(), { 10763 snapItem: inst.snapElements[ i ].item 10764 } ) ); 10765 } 10766 } 10767 inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first ); 10768 10769 } 10770 10771 } 10772} ); 10773 10774$.ui.plugin.add( "draggable", "stack", { 10775 start: function( event, ui, instance ) { 10776 var min, 10777 o = instance.options, 10778 group = $.makeArray( $( o.stack ) ).sort( function( a, b ) { 10779 return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) - 10780 ( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 ); 10781 } ); 10782 10783 if ( !group.length ) { 10784 return; 10785 } 10786 10787 min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0; 10788 $( group ).each( function( i ) { 10789 $( this ).css( "zIndex", min + i ); 10790 } ); 10791 this.css( "zIndex", ( min + group.length ) ); 10792 } 10793} ); 10794 10795$.ui.plugin.add( "draggable", "zIndex", { 10796 start: function( event, ui, instance ) { 10797 var t = $( ui.helper ), 10798 o = instance.options; 10799 10800 if ( t.css( "zIndex" ) ) { 10801 o._zIndex = t.css( "zIndex" ); 10802 } 10803 t.css( "zIndex", o.zIndex ); 10804 }, 10805 stop: function( event, ui, instance ) { 10806 var o = instance.options; 10807 10808 if ( o._zIndex ) { 10809 $( ui.helper ).css( "zIndex", o._zIndex ); 10810 } 10811 } 10812} ); 10813 10814var widgetsDraggable = $.ui.draggable; 10815 10816 10817/*! 10818 * jQuery UI Resizable 1.14.1 10819 * https://jqueryui.com 10820 * 10821 * Copyright OpenJS Foundation and other contributors 10822 * Released under the MIT license. 10823 * https://jquery.org/license 10824 */ 10825 10826//>>label: Resizable 10827//>>group: Interactions 10828//>>description: Enables resize functionality for any element. 10829//>>docs: https://api.jqueryui.com/resizable/ 10830//>>demos: https://jqueryui.com/resizable/ 10831//>>css.structure: ../../themes/base/core.css 10832//>>css.structure: ../../themes/base/resizable.css 10833//>>css.theme: ../../themes/base/theme.css 10834 10835 10836$.widget( "ui.resizable", $.ui.mouse, { 10837 version: "1.14.1", 10838 widgetEventPrefix: "resize", 10839 options: { 10840 alsoResize: false, 10841 animate: false, 10842 animateDuration: "slow", 10843 animateEasing: "swing", 10844 aspectRatio: false, 10845 autoHide: false, 10846 classes: { 10847 "ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se" 10848 }, 10849 containment: false, 10850 ghost: false, 10851 grid: false, 10852 handles: "e,s,se", 10853 helper: false, 10854 maxHeight: null, 10855 maxWidth: null, 10856 minHeight: 10, 10857 minWidth: 10, 10858 10859 // See #7960 10860 zIndex: 90, 10861 10862 // Callbacks 10863 resize: null, 10864 start: null, 10865 stop: null 10866 }, 10867 10868 _num: function( value ) { 10869 return parseFloat( value ) || 0; 10870 }, 10871 10872 _isNumber: function( value ) { 10873 return !isNaN( parseFloat( value ) ); 10874 }, 10875 10876 _hasScroll: function( el, a ) { 10877 10878 var scroll, 10879 has = false, 10880 overflow = $( el ).css( "overflow" ); 10881 10882 if ( overflow === "hidden" ) { 10883 return false; 10884 } 10885 if ( overflow === "scroll" ) { 10886 return true; 10887 } 10888 10889 scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop"; 10890 10891 if ( el[ scroll ] > 0 ) { 10892 return true; 10893 } 10894 10895 // TODO: determine which cases actually cause this to happen 10896 // if the element doesn't have the scroll set, see if it's possible to 10897 // set the scroll 10898 try { 10899 el[ scroll ] = 1; 10900 has = ( el[ scroll ] > 0 ); 10901 el[ scroll ] = 0; 10902 } catch ( e ) { 10903 10904 // `el` might be a string, then setting `scroll` will throw 10905 // an error in strict mode; ignore it. 10906 } 10907 return has; 10908 }, 10909 10910 _create: function() { 10911 10912 var margins, 10913 o = this.options, 10914 that = this; 10915 this._addClass( "ui-resizable" ); 10916 10917 $.extend( this, { 10918 _aspectRatio: !!( o.aspectRatio ), 10919 aspectRatio: o.aspectRatio, 10920 originalElement: this.element, 10921 _proportionallyResizeElements: [], 10922 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null 10923 } ); 10924 10925 // Wrap the element if it cannot hold child nodes 10926 if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) { 10927 10928 this.element.wrap( 10929 $( "<div class='ui-wrapper'></div>" ).css( { 10930 overflow: "hidden", 10931 position: this.element.css( "position" ), 10932 width: this.element.outerWidth(), 10933 height: this.element.outerHeight(), 10934 top: this.element.css( "top" ), 10935 left: this.element.css( "left" ) 10936 } ) 10937 ); 10938 10939 this.element = this.element.parent().data( 10940 "ui-resizable", this.element.resizable( "instance" ) 10941 ); 10942 10943 this.elementIsWrapper = true; 10944 10945 margins = { 10946 marginTop: this.originalElement.css( "marginTop" ), 10947 marginRight: this.originalElement.css( "marginRight" ), 10948 marginBottom: this.originalElement.css( "marginBottom" ), 10949 marginLeft: this.originalElement.css( "marginLeft" ) 10950 }; 10951 10952 this.element.css( margins ); 10953 10954 // Support: Safari 10955 // Prevent Safari textarea resize 10956 this.originalResizeStyle = this.originalElement.css( "resize" ); 10957 this.originalElement.css( "resize", "none" ); 10958 10959 this._proportionallyResizeElements.push( this.originalElement.css( { 10960 position: "static", 10961 zoom: 1, 10962 display: "block" 10963 } ) ); 10964 10965 this._proportionallyResize(); 10966 } 10967 10968 this._setupHandles(); 10969 10970 if ( o.autoHide ) { 10971 $( this.element ) 10972 .on( "mouseenter", function() { 10973 if ( o.disabled ) { 10974 return; 10975 } 10976 that._removeClass( "ui-resizable-autohide" ); 10977 that._handles.show(); 10978 } ) 10979 .on( "mouseleave", function() { 10980 if ( o.disabled ) { 10981 return; 10982 } 10983 if ( !that.resizing ) { 10984 that._addClass( "ui-resizable-autohide" ); 10985 that._handles.hide(); 10986 } 10987 } ); 10988 } 10989 10990 this._mouseInit(); 10991 }, 10992 10993 _destroy: function() { 10994 10995 this._mouseDestroy(); 10996 this._addedHandles.remove(); 10997 10998 var wrapper, 10999 _destroy = function( exp ) { 11000 $( exp ) 11001 .removeData( "resizable" ) 11002 .removeData( "ui-resizable" ) 11003 .off( ".resizable" ); 11004 }; 11005 11006 // TODO: Unwrap at same DOM position 11007 if ( this.elementIsWrapper ) { 11008 _destroy( this.element ); 11009 wrapper = this.element; 11010 this.originalElement.css( { 11011 position: wrapper.css( "position" ), 11012 width: wrapper.outerWidth(), 11013 height: wrapper.outerHeight(), 11014 top: wrapper.css( "top" ), 11015 left: wrapper.css( "left" ) 11016 } ).insertAfter( wrapper ); 11017 wrapper.remove(); 11018 } 11019 11020 this.originalElement.css( "resize", this.originalResizeStyle ); 11021 _destroy( this.originalElement ); 11022 11023 return this; 11024 }, 11025 11026 _setOption: function( key, value ) { 11027 this._super( key, value ); 11028 11029 switch ( key ) { 11030 case "handles": 11031 this._removeHandles(); 11032 this._setupHandles(); 11033 break; 11034 case "aspectRatio": 11035 this._aspectRatio = !!value; 11036 break; 11037 default: 11038 break; 11039 } 11040 }, 11041 11042 _setupHandles: function() { 11043 var o = this.options, handle, i, n, hname, axis, that = this; 11044 this.handles = o.handles || 11045 ( !$( ".ui-resizable-handle", this.element ).length ? 11046 "e,s,se" : { 11047 n: ".ui-resizable-n", 11048 e: ".ui-resizable-e", 11049 s: ".ui-resizable-s", 11050 w: ".ui-resizable-w", 11051 se: ".ui-resizable-se", 11052 sw: ".ui-resizable-sw", 11053 ne: ".ui-resizable-ne", 11054 nw: ".ui-resizable-nw" 11055 } ); 11056 11057 this._handles = $(); 11058 this._addedHandles = $(); 11059 if ( this.handles.constructor === String ) { 11060 11061 if ( this.handles === "all" ) { 11062 this.handles = "n,e,s,w,se,sw,ne,nw"; 11063 } 11064 11065 n = this.handles.split( "," ); 11066 this.handles = {}; 11067 11068 for ( i = 0; i < n.length; i++ ) { 11069 11070 handle = String.prototype.trim.call( n[ i ] ); 11071 hname = "ui-resizable-" + handle; 11072 axis = $( "<div>" ); 11073 this._addClass( axis, "ui-resizable-handle " + hname ); 11074 11075 axis.css( { zIndex: o.zIndex } ); 11076 11077 this.handles[ handle ] = ".ui-resizable-" + handle; 11078 if ( !this.element.children( this.handles[ handle ] ).length ) { 11079 this.element.append( axis ); 11080 this._addedHandles = this._addedHandles.add( axis ); 11081 } 11082 } 11083 11084 } 11085 11086 this._renderAxis = function( target ) { 11087 11088 var i, axis, padPos, padWrapper; 11089 11090 target = target || this.element; 11091 11092 for ( i in this.handles ) { 11093 11094 if ( this.handles[ i ].constructor === String ) { 11095 this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show(); 11096 } else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) { 11097 this.handles[ i ] = $( this.handles[ i ] ); 11098 this._on( this.handles[ i ], { "mousedown": that._mouseDown } ); 11099 } 11100 11101 if ( this.elementIsWrapper && 11102 this.originalElement[ 0 ] 11103 .nodeName 11104 .match( /^(textarea|input|select|button)$/i ) ) { 11105 axis = $( this.handles[ i ], this.element ); 11106 11107 padWrapper = /sw|ne|nw|se|n|s/.test( i ) ? 11108 axis.outerHeight() : 11109 axis.outerWidth(); 11110 11111 padPos = [ "padding", 11112 /ne|nw|n/.test( i ) ? "Top" : 11113 /se|sw|s/.test( i ) ? "Bottom" : 11114 /^e$/.test( i ) ? "Right" : "Left" ].join( "" ); 11115 11116 target.css( padPos, padWrapper ); 11117 11118 this._proportionallyResize(); 11119 } 11120 11121 this._handles = this._handles.add( this.handles[ i ] ); 11122 } 11123 }; 11124 11125 // TODO: make renderAxis a prototype function 11126 this._renderAxis( this.element ); 11127 11128 this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) ); 11129 this._handles.disableSelection(); 11130 11131 this._handles.on( "mouseover", function() { 11132 if ( !that.resizing ) { 11133 if ( this.className ) { 11134 axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i ); 11135 } 11136 that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se"; 11137 } 11138 } ); 11139 11140 if ( o.autoHide ) { 11141 this._handles.hide(); 11142 this._addClass( "ui-resizable-autohide" ); 11143 } 11144 }, 11145 11146 _removeHandles: function() { 11147 this._addedHandles.remove(); 11148 }, 11149 11150 _mouseCapture: function( event ) { 11151 var i, handle, 11152 capture = false; 11153 11154 for ( i in this.handles ) { 11155 handle = $( this.handles[ i ] )[ 0 ]; 11156 if ( handle === event.target || $.contains( handle, event.target ) ) { 11157 capture = true; 11158 } 11159 } 11160 11161 return !this.options.disabled && capture; 11162 }, 11163 11164 _mouseStart: function( event ) { 11165 11166 var curleft, curtop, cursor, calculatedSize, 11167 o = this.options, 11168 el = this.element; 11169 11170 this.resizing = true; 11171 11172 this._renderProxy(); 11173 11174 curleft = this._num( this.helper.css( "left" ) ); 11175 curtop = this._num( this.helper.css( "top" ) ); 11176 11177 if ( o.containment ) { 11178 curleft += $( o.containment ).scrollLeft() || 0; 11179 curtop += $( o.containment ).scrollTop() || 0; 11180 } 11181 11182 this.offset = this.helper.offset(); 11183 this.position = { left: curleft, top: curtop }; 11184 11185 if ( !this._helper ) { 11186 calculatedSize = this._calculateAdjustedElementDimensions( el ); 11187 } 11188 11189 this.size = this._helper ? { 11190 width: this.helper.width(), 11191 height: this.helper.height() 11192 } : { 11193 width: calculatedSize.width, 11194 height: calculatedSize.height 11195 }; 11196 11197 this.originalSize = this._helper ? { 11198 width: el.outerWidth(), 11199 height: el.outerHeight() 11200 } : { 11201 width: calculatedSize.width, 11202 height: calculatedSize.height 11203 }; 11204 11205 this.sizeDiff = { 11206 width: el.outerWidth() - el.width(), 11207 height: el.outerHeight() - el.height() 11208 }; 11209 11210 this.originalPosition = { left: curleft, top: curtop }; 11211 this.originalMousePosition = { left: event.pageX, top: event.pageY }; 11212 11213 this.aspectRatio = ( typeof o.aspectRatio === "number" ) ? 11214 o.aspectRatio : 11215 ( ( this.originalSize.width / this.originalSize.height ) || 1 ); 11216 11217 cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" ); 11218 $( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor ); 11219 11220 this._addClass( "ui-resizable-resizing" ); 11221 this._propagate( "start", event ); 11222 return true; 11223 }, 11224 11225 _mouseDrag: function( event ) { 11226 11227 var data, props, 11228 smp = this.originalMousePosition, 11229 a = this.axis, 11230 dx = ( event.pageX - smp.left ) || 0, 11231 dy = ( event.pageY - smp.top ) || 0, 11232 trigger = this._change[ a ]; 11233 11234 this._updatePrevProperties(); 11235 11236 if ( !trigger ) { 11237 return false; 11238 } 11239 11240 data = trigger.apply( this, [ event, dx, dy ] ); 11241 11242 this._updateVirtualBoundaries( event.shiftKey ); 11243 if ( this._aspectRatio || event.shiftKey ) { 11244 data = this._updateRatio( data, event ); 11245 } 11246 11247 data = this._respectSize( data, event ); 11248 11249 this._updateCache( data ); 11250 11251 this._propagate( "resize", event ); 11252 11253 props = this._applyChanges(); 11254 11255 if ( !this._helper && this._proportionallyResizeElements.length ) { 11256 this._proportionallyResize(); 11257 } 11258 11259 if ( !$.isEmptyObject( props ) ) { 11260 this._updatePrevProperties(); 11261 this._trigger( "resize", event, this.ui() ); 11262 this._applyChanges(); 11263 } 11264 11265 return false; 11266 }, 11267 11268 _mouseStop: function( event ) { 11269 11270 this.resizing = false; 11271 var pr, ista, soffseth, soffsetw, s, left, top, 11272 o = this.options, that = this; 11273 11274 if ( this._helper ) { 11275 11276 pr = this._proportionallyResizeElements; 11277 ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ); 11278 soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height; 11279 soffsetw = ista ? 0 : that.sizeDiff.width; 11280 11281 s = { 11282 width: ( that.helper.width() - soffsetw ), 11283 height: ( that.helper.height() - soffseth ) 11284 }; 11285 left = ( parseFloat( that.element.css( "left" ) ) + 11286 ( that.position.left - that.originalPosition.left ) ) || null; 11287 top = ( parseFloat( that.element.css( "top" ) ) + 11288 ( that.position.top - that.originalPosition.top ) ) || null; 11289 11290 if ( !o.animate ) { 11291 this.element.css( $.extend( s, { top: top, left: left } ) ); 11292 } 11293 11294 that.helper.height( that.size.height ); 11295 that.helper.width( that.size.width ); 11296 11297 if ( this._helper && !o.animate ) { 11298 this._proportionallyResize(); 11299 } 11300 } 11301 11302 $( "body" ).css( "cursor", "auto" ); 11303 11304 this._removeClass( "ui-resizable-resizing" ); 11305 11306 this._propagate( "stop", event ); 11307 11308 if ( this._helper ) { 11309 this.helper.remove(); 11310 } 11311 11312 return false; 11313 11314 }, 11315 11316 _updatePrevProperties: function() { 11317 this.prevPosition = { 11318 top: this.position.top, 11319 left: this.position.left 11320 }; 11321 this.prevSize = { 11322 width: this.size.width, 11323 height: this.size.height 11324 }; 11325 }, 11326 11327 _applyChanges: function() { 11328 var props = {}; 11329 11330 if ( this.position.top !== this.prevPosition.top ) { 11331 props.top = this.position.top + "px"; 11332 } 11333 if ( this.position.left !== this.prevPosition.left ) { 11334 props.left = this.position.left + "px"; 11335 } 11336 11337 this.helper.css( props ); 11338 11339 if ( this.size.width !== this.prevSize.width ) { 11340 props.width = this.size.width + "px"; 11341 this.helper.width( props.width ); 11342 } 11343 if ( this.size.height !== this.prevSize.height ) { 11344 props.height = this.size.height + "px"; 11345 this.helper.height( props.height ); 11346 } 11347 11348 return props; 11349 }, 11350 11351 _updateVirtualBoundaries: function( forceAspectRatio ) { 11352 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b, 11353 o = this.options; 11354 11355 b = { 11356 minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0, 11357 maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity, 11358 minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0, 11359 maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity 11360 }; 11361 11362 if ( this._aspectRatio || forceAspectRatio ) { 11363 pMinWidth = b.minHeight * this.aspectRatio; 11364 pMinHeight = b.minWidth / this.aspectRatio; 11365 pMaxWidth = b.maxHeight * this.aspectRatio; 11366 pMaxHeight = b.maxWidth / this.aspectRatio; 11367 11368 if ( pMinWidth > b.minWidth ) { 11369 b.minWidth = pMinWidth; 11370 } 11371 if ( pMinHeight > b.minHeight ) { 11372 b.minHeight = pMinHeight; 11373 } 11374 if ( pMaxWidth < b.maxWidth ) { 11375 b.maxWidth = pMaxWidth; 11376 } 11377 if ( pMaxHeight < b.maxHeight ) { 11378 b.maxHeight = pMaxHeight; 11379 } 11380 } 11381 this._vBoundaries = b; 11382 }, 11383 11384 _updateCache: function( data ) { 11385 this.offset = this.helper.offset(); 11386 if ( this._isNumber( data.left ) ) { 11387 this.position.left = data.left; 11388 } 11389 if ( this._isNumber( data.top ) ) { 11390 this.position.top = data.top; 11391 } 11392 if ( this._isNumber( data.height ) ) { 11393 this.size.height = data.height; 11394 } 11395 if ( this._isNumber( data.width ) ) { 11396 this.size.width = data.width; 11397 } 11398 }, 11399 11400 _updateRatio: function( data ) { 11401 11402 var cpos = this.position, 11403 csize = this.size, 11404 a = this.axis; 11405 11406 if ( this._isNumber( data.height ) ) { 11407 data.width = ( data.height * this.aspectRatio ); 11408 } else if ( this._isNumber( data.width ) ) { 11409 data.height = ( data.width / this.aspectRatio ); 11410 } 11411 11412 if ( a === "sw" ) { 11413 data.left = cpos.left + ( csize.width - data.width ); 11414 data.top = null; 11415 } 11416 if ( a === "nw" ) { 11417 data.top = cpos.top + ( csize.height - data.height ); 11418 data.left = cpos.left + ( csize.width - data.width ); 11419 } 11420 11421 return data; 11422 }, 11423 11424 _respectSize: function( data ) { 11425 11426 var o = this._vBoundaries, 11427 a = this.axis, 11428 ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ), 11429 ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ), 11430 isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ), 11431 isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ), 11432 dw = this.originalPosition.left + this.originalSize.width, 11433 dh = this.originalPosition.top + this.originalSize.height, 11434 cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a ); 11435 if ( isminw ) { 11436 data.width = o.minWidth; 11437 } 11438 if ( isminh ) { 11439 data.height = o.minHeight; 11440 } 11441 if ( ismaxw ) { 11442 data.width = o.maxWidth; 11443 } 11444 if ( ismaxh ) { 11445 data.height = o.maxHeight; 11446 } 11447 11448 if ( isminw && cw ) { 11449 data.left = dw - o.minWidth; 11450 } 11451 if ( ismaxw && cw ) { 11452 data.left = dw - o.maxWidth; 11453 } 11454 if ( isminh && ch ) { 11455 data.top = dh - o.minHeight; 11456 } 11457 if ( ismaxh && ch ) { 11458 data.top = dh - o.maxHeight; 11459 } 11460 11461 // Fixing jump error on top/left - bug #2330 11462 if ( !data.width && !data.height && !data.left && data.top ) { 11463 data.top = null; 11464 } else if ( !data.width && !data.height && !data.top && data.left ) { 11465 data.left = null; 11466 } 11467 11468 return data; 11469 }, 11470 11471 _getPaddingPlusBorderDimensions: function( element ) { 11472 var i = 0, 11473 widths = [], 11474 borders = [ 11475 element.css( "borderTopWidth" ), 11476 element.css( "borderRightWidth" ), 11477 element.css( "borderBottomWidth" ), 11478 element.css( "borderLeftWidth" ) 11479 ], 11480 paddings = [ 11481 element.css( "paddingTop" ), 11482 element.css( "paddingRight" ), 11483 element.css( "paddingBottom" ), 11484 element.css( "paddingLeft" ) 11485 ]; 11486 11487 for ( ; i < 4; i++ ) { 11488 widths[ i ] = ( parseFloat( borders[ i ] ) || 0 ); 11489 widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 ); 11490 } 11491 11492 return { 11493 height: widths[ 0 ] + widths[ 2 ], 11494 width: widths[ 1 ] + widths[ 3 ] 11495 }; 11496 }, 11497 11498 _calculateAdjustedElementDimensions: function( element ) { 11499 var elWidth, elHeight, paddingBorder, 11500 ce = element.get( 0 ); 11501 11502 if ( element.css( "box-sizing" ) !== "content-box" || 11503 ( !this._hasScroll( ce ) && !this._hasScroll( ce, "left" ) ) ) { 11504 return { 11505 height: parseFloat( element.css( "height" ) ), 11506 width: parseFloat( element.css( "width" ) ) 11507 }; 11508 } 11509 11510 // Check if CSS inline styles are set and use those (usually from previous resizes) 11511 elWidth = parseFloat( ce.style.width ); 11512 elHeight = parseFloat( ce.style.height ); 11513 11514 paddingBorder = this._getPaddingPlusBorderDimensions( element ); 11515 elWidth = isNaN( elWidth ) ? 11516 this._getElementTheoreticalSize( element, paddingBorder, "width" ) : 11517 elWidth; 11518 elHeight = isNaN( elHeight ) ? 11519 this._getElementTheoreticalSize( element, paddingBorder, "height" ) : 11520 elHeight; 11521 11522 return { 11523 height: elHeight, 11524 width: elWidth 11525 }; 11526 }, 11527 11528 _getElementTheoreticalSize: function( element, extraSize, dimension ) { 11529 11530 // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border 11531 var size = Math.max( 0, Math.ceil( 11532 element.get( 0 )[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - 11533 extraSize[ dimension ] - 11534 0.5 11535 11536 // If offsetWidth/offsetHeight is unknown, then we can't determine theoretical size. 11537 // Use an explicit zero to avoid NaN. 11538 // See https://github.com/jquery/jquery/issues/3964 11539 ) ) || 0; 11540 11541 return size; 11542 }, 11543 11544 _proportionallyResize: function() { 11545 11546 if ( !this._proportionallyResizeElements.length ) { 11547 return; 11548 } 11549 11550 var prel, 11551 i = 0, 11552 element = this.helper || this.element; 11553 11554 for ( ; i < this._proportionallyResizeElements.length; i++ ) { 11555 11556 prel = this._proportionallyResizeElements[ i ]; 11557 11558 // TODO: Seems like a bug to cache this.outerDimensions 11559 // considering that we are in a loop. 11560 if ( !this.outerDimensions ) { 11561 this.outerDimensions = this._getPaddingPlusBorderDimensions( prel ); 11562 } 11563 11564 prel.css( { 11565 height: ( element.height() - this.outerDimensions.height ) || 0, 11566 width: ( element.width() - this.outerDimensions.width ) || 0 11567 } ); 11568 11569 } 11570 11571 }, 11572 11573 _renderProxy: function() { 11574 11575 var el = this.element, o = this.options; 11576 this.elementOffset = el.offset(); 11577 11578 if ( this._helper ) { 11579 11580 this.helper = this.helper || $( "<div></div>" ).css( { overflow: "hidden" } ); 11581 11582 this._addClass( this.helper, this._helper ); 11583 this.helper.css( { 11584 width: this.element.outerWidth(), 11585 height: this.element.outerHeight(), 11586 position: "absolute", 11587 left: this.elementOffset.left + "px", 11588 top: this.elementOffset.top + "px", 11589 zIndex: ++o.zIndex //TODO: Don't modify option 11590 } ); 11591 11592 this.helper 11593 .appendTo( "body" ) 11594 .disableSelection(); 11595 11596 } else { 11597 this.helper = this.element; 11598 } 11599 11600 }, 11601 11602 _change: { 11603 e: function( event, dx ) { 11604 return { width: this.originalSize.width + dx }; 11605 }, 11606 w: function( event, dx ) { 11607 var cs = this.originalSize, sp = this.originalPosition; 11608 return { left: sp.left + dx, width: cs.width - dx }; 11609 }, 11610 n: function( event, dx, dy ) { 11611 var cs = this.originalSize, sp = this.originalPosition; 11612 return { top: sp.top + dy, height: cs.height - dy }; 11613 }, 11614 s: function( event, dx, dy ) { 11615 return { height: this.originalSize.height + dy }; 11616 }, 11617 se: function( event, dx, dy ) { 11618 return $.extend( this._change.s.apply( this, arguments ), 11619 this._change.e.apply( this, [ event, dx, dy ] ) ); 11620 }, 11621 sw: function( event, dx, dy ) { 11622 return $.extend( this._change.s.apply( this, arguments ), 11623 this._change.w.apply( this, [ event, dx, dy ] ) ); 11624 }, 11625 ne: function( event, dx, dy ) { 11626 return $.extend( this._change.n.apply( this, arguments ), 11627 this._change.e.apply( this, [ event, dx, dy ] ) ); 11628 }, 11629 nw: function( event, dx, dy ) { 11630 return $.extend( this._change.n.apply( this, arguments ), 11631 this._change.w.apply( this, [ event, dx, dy ] ) ); 11632 } 11633 }, 11634 11635 _propagate: function( n, event ) { 11636 $.ui.plugin.call( this, n, [ event, this.ui() ] ); 11637 if ( n !== "resize" ) { 11638 this._trigger( n, event, this.ui() ); 11639 } 11640 }, 11641 11642 plugins: {}, 11643 11644 ui: function() { 11645 return { 11646 originalElement: this.originalElement, 11647 element: this.element, 11648 helper: this.helper, 11649 position: this.position, 11650 size: this.size, 11651 originalSize: this.originalSize, 11652 originalPosition: this.originalPosition 11653 }; 11654 } 11655 11656} ); 11657 11658/* 11659 * Resizable Extensions 11660 */ 11661 11662$.ui.plugin.add( "resizable", "animate", { 11663 11664 stop: function( event ) { 11665 var that = $( this ).resizable( "instance" ), 11666 o = that.options, 11667 pr = that._proportionallyResizeElements, 11668 ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ), 11669 soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height, 11670 soffsetw = ista ? 0 : that.sizeDiff.width, 11671 style = { 11672 width: ( that.size.width - soffsetw ), 11673 height: ( that.size.height - soffseth ) 11674 }, 11675 left = ( parseFloat( that.element.css( "left" ) ) + 11676 ( that.position.left - that.originalPosition.left ) ) || null, 11677 top = ( parseFloat( that.element.css( "top" ) ) + 11678 ( that.position.top - that.originalPosition.top ) ) || null; 11679 11680 that.element.animate( 11681 $.extend( style, top && left ? { top: top, left: left } : {} ), { 11682 duration: o.animateDuration, 11683 easing: o.animateEasing, 11684 step: function() { 11685 11686 var data = { 11687 width: parseFloat( that.element.css( "width" ) ), 11688 height: parseFloat( that.element.css( "height" ) ), 11689 top: parseFloat( that.element.css( "top" ) ), 11690 left: parseFloat( that.element.css( "left" ) ) 11691 }; 11692 11693 if ( pr && pr.length ) { 11694 $( pr[ 0 ] ).css( { width: data.width, height: data.height } ); 11695 } 11696 11697 // Propagating resize, and updating values for each animation step 11698 that._updateCache( data ); 11699 that._propagate( "resize", event ); 11700 11701 } 11702 } 11703 ); 11704 } 11705 11706} ); 11707 11708$.ui.plugin.add( "resizable", "containment", { 11709 11710 start: function() { 11711 var element, p, co, ch, cw, width, height, 11712 that = $( this ).resizable( "instance" ), 11713 o = that.options, 11714 el = that.element, 11715 oc = o.containment, 11716 ce = ( oc instanceof $ ) ? 11717 oc.get( 0 ) : 11718 ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc; 11719 11720 if ( !ce ) { 11721 return; 11722 } 11723 11724 that.containerElement = $( ce ); 11725 11726 if ( /document/.test( oc ) || oc === document ) { 11727 that.containerOffset = { 11728 left: 0, 11729 top: 0 11730 }; 11731 that.containerPosition = { 11732 left: 0, 11733 top: 0 11734 }; 11735 11736 that.parentData = { 11737 element: $( document ), 11738 left: 0, 11739 top: 0, 11740 width: $( document ).width(), 11741 height: $( document ).height() || document.body.parentNode.scrollHeight 11742 }; 11743 } else { 11744 element = $( ce ); 11745 p = []; 11746 $( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) { 11747 p[ i ] = that._num( element.css( "padding" + name ) ); 11748 } ); 11749 11750 that.containerOffset = element.offset(); 11751 that.containerPosition = element.position(); 11752 that.containerSize = { 11753 height: ( element.innerHeight() - p[ 3 ] ), 11754 width: ( element.innerWidth() - p[ 1 ] ) 11755 }; 11756 11757 co = that.containerOffset; 11758 ch = that.containerSize.height; 11759 cw = that.containerSize.width; 11760 width = ( that._hasScroll( ce, "left" ) ? ce.scrollWidth : cw ); 11761 height = ( that._hasScroll( ce ) ? ce.scrollHeight : ch ); 11762 11763 that.parentData = { 11764 element: ce, 11765 left: co.left, 11766 top: co.top, 11767 width: width, 11768 height: height 11769 }; 11770 } 11771 }, 11772 11773 resize: function( event ) { 11774 var woset, hoset, isParent, isOffsetRelative, 11775 that = $( this ).resizable( "instance" ), 11776 o = that.options, 11777 co = that.containerOffset, 11778 cp = that.position, 11779 pRatio = that._aspectRatio || event.shiftKey, 11780 cop = { 11781 top: 0, 11782 left: 0 11783 }, 11784 ce = that.containerElement, 11785 continueResize = true; 11786 11787 if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) { 11788 cop = co; 11789 } 11790 11791 if ( cp.left < ( that._helper ? co.left : 0 ) ) { 11792 that.size.width = that.size.width + 11793 ( that._helper ? 11794 ( that.position.left - co.left ) : 11795 ( that.position.left - cop.left ) ); 11796 11797 if ( pRatio ) { 11798 that.size.height = that.size.width / that.aspectRatio; 11799 continueResize = false; 11800 } 11801 that.position.left = o.helper ? co.left : 0; 11802 } 11803 11804 if ( cp.top < ( that._helper ? co.top : 0 ) ) { 11805 that.size.height = that.size.height + 11806 ( that._helper ? 11807 ( that.position.top - co.top ) : 11808 that.position.top ); 11809 11810 if ( pRatio ) { 11811 that.size.width = that.size.height * that.aspectRatio; 11812 continueResize = false; 11813 } 11814 that.position.top = that._helper ? co.top : 0; 11815 } 11816 11817 isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 ); 11818 isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) ); 11819 11820 if ( isParent && isOffsetRelative ) { 11821 that.offset.left = that.parentData.left + that.position.left; 11822 that.offset.top = that.parentData.top + that.position.top; 11823 } else { 11824 that.offset.left = that.element.offset().left; 11825 that.offset.top = that.element.offset().top; 11826 } 11827 11828 woset = Math.abs( that.sizeDiff.width + 11829 ( that._helper ? 11830 that.offset.left - cop.left : 11831 ( that.offset.left - co.left ) ) ); 11832 11833 hoset = Math.abs( that.sizeDiff.height + 11834 ( that._helper ? 11835 that.offset.top - cop.top : 11836 ( that.offset.top - co.top ) ) ); 11837 11838 if ( woset + that.size.width >= that.parentData.width ) { 11839 that.size.width = that.parentData.width - woset; 11840 if ( pRatio ) { 11841 that.size.height = that.size.width / that.aspectRatio; 11842 continueResize = false; 11843 } 11844 } 11845 11846 if ( hoset + that.size.height >= that.parentData.height ) { 11847 that.size.height = that.parentData.height - hoset; 11848 if ( pRatio ) { 11849 that.size.width = that.size.height * that.aspectRatio; 11850 continueResize = false; 11851 } 11852 } 11853 11854 if ( !continueResize ) { 11855 that.position.left = that.prevPosition.left; 11856 that.position.top = that.prevPosition.top; 11857 that.size.width = that.prevSize.width; 11858 that.size.height = that.prevSize.height; 11859 } 11860 }, 11861 11862 stop: function() { 11863 var that = $( this ).resizable( "instance" ), 11864 o = that.options, 11865 co = that.containerOffset, 11866 cop = that.containerPosition, 11867 ce = that.containerElement, 11868 helper = $( that.helper ), 11869 ho = helper.offset(), 11870 w = helper.outerWidth() - that.sizeDiff.width, 11871 h = helper.outerHeight() - that.sizeDiff.height; 11872 11873 if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) { 11874 $( this ).css( { 11875 left: ho.left - cop.left - co.left, 11876 width: w, 11877 height: h 11878 } ); 11879 } 11880 11881 if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) { 11882 $( this ).css( { 11883 left: ho.left - cop.left - co.left, 11884 width: w, 11885 height: h 11886 } ); 11887 } 11888 } 11889} ); 11890 11891$.ui.plugin.add( "resizable", "alsoResize", { 11892 11893 start: function() { 11894 var that = $( this ).resizable( "instance" ), 11895 o = that.options; 11896 11897 $( o.alsoResize ).each( function() { 11898 var el = $( this ), 11899 elSize = that._calculateAdjustedElementDimensions( el ); 11900 11901 el.data( "ui-resizable-alsoresize", { 11902 width: elSize.width, height: elSize.height, 11903 left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) ) 11904 } ); 11905 } ); 11906 }, 11907 11908 resize: function( event, ui ) { 11909 var that = $( this ).resizable( "instance" ), 11910 o = that.options, 11911 os = that.originalSize, 11912 op = that.originalPosition, 11913 delta = { 11914 height: ( that.size.height - os.height ) || 0, 11915 width: ( that.size.width - os.width ) || 0, 11916 top: ( that.position.top - op.top ) || 0, 11917 left: ( that.position.left - op.left ) || 0 11918 }; 11919 11920 $( o.alsoResize ).each( function() { 11921 var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {}, 11922 css = el.parents( ui.originalElement[ 0 ] ).length ? 11923 [ "width", "height" ] : 11924 [ "width", "height", "top", "left" ]; 11925 11926 $.each( css, function( i, prop ) { 11927 var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 ); 11928 if ( sum && sum >= 0 ) { 11929 style[ prop ] = sum || null; 11930 } 11931 } ); 11932 11933 el.css( style ); 11934 } ); 11935 }, 11936 11937 stop: function() { 11938 $( this ).removeData( "ui-resizable-alsoresize" ); 11939 } 11940} ); 11941 11942$.ui.plugin.add( "resizable", "ghost", { 11943 11944 start: function() { 11945 11946 var that = $( this ).resizable( "instance" ), cs = that.size; 11947 11948 that.ghost = that.originalElement.clone(); 11949 that.ghost.css( { 11950 opacity: 0.25, 11951 display: "block", 11952 position: "relative", 11953 height: cs.height, 11954 width: cs.width, 11955 margin: 0, 11956 left: 0, 11957 top: 0 11958 } ); 11959 11960 that._addClass( that.ghost, "ui-resizable-ghost" ); 11961 11962 // DEPRECATED 11963 // TODO: remove after 1.12 11964 if ( $.uiBackCompat === true && typeof that.options.ghost === "string" ) { 11965 11966 // Ghost option 11967 that.ghost.addClass( this.options.ghost ); 11968 } 11969 11970 that.ghost.appendTo( that.helper ); 11971 11972 }, 11973 11974 resize: function() { 11975 var that = $( this ).resizable( "instance" ); 11976 if ( that.ghost ) { 11977 that.ghost.css( { 11978 position: "relative", 11979 height: that.size.height, 11980 width: that.size.width 11981 } ); 11982 } 11983 }, 11984 11985 stop: function() { 11986 var that = $( this ).resizable( "instance" ); 11987 if ( that.ghost && that.helper ) { 11988 that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) ); 11989 } 11990 } 11991 11992} ); 11993 11994$.ui.plugin.add( "resizable", "grid", { 11995 11996 resize: function() { 11997 var outerDimensions, 11998 that = $( this ).resizable( "instance" ), 11999 o = that.options, 12000 cs = that.size, 12001 os = that.originalSize, 12002 op = that.originalPosition, 12003 a = that.axis, 12004 grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid, 12005 gridX = ( grid[ 0 ] || 1 ), 12006 gridY = ( grid[ 1 ] || 1 ), 12007 ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX, 12008 oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY, 12009 newWidth = os.width + ox, 12010 newHeight = os.height + oy, 12011 isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ), 12012 isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ), 12013 isMinWidth = o.minWidth && ( o.minWidth > newWidth ), 12014 isMinHeight = o.minHeight && ( o.minHeight > newHeight ); 12015 12016 o.grid = grid; 12017 12018 if ( isMinWidth ) { 12019 newWidth += gridX; 12020 } 12021 if ( isMinHeight ) { 12022 newHeight += gridY; 12023 } 12024 if ( isMaxWidth ) { 12025 newWidth -= gridX; 12026 } 12027 if ( isMaxHeight ) { 12028 newHeight -= gridY; 12029 } 12030 12031 if ( /^(se|s|e)$/.test( a ) ) { 12032 that.size.width = newWidth; 12033 that.size.height = newHeight; 12034 } else if ( /^(ne)$/.test( a ) ) { 12035 that.size.width = newWidth; 12036 that.size.height = newHeight; 12037 that.position.top = op.top - oy; 12038 } else if ( /^(sw)$/.test( a ) ) { 12039 that.size.width = newWidth; 12040 that.size.height = newHeight; 12041 that.position.left = op.left - ox; 12042 } else { 12043 if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) { 12044 outerDimensions = that._getPaddingPlusBorderDimensions( this ); 12045 } 12046 12047 if ( newHeight - gridY > 0 ) { 12048 that.size.height = newHeight; 12049 that.position.top = op.top - oy; 12050 } else { 12051 newHeight = gridY - outerDimensions.height; 12052 that.size.height = newHeight; 12053 that.position.top = op.top + os.height - newHeight; 12054 } 12055 if ( newWidth - gridX > 0 ) { 12056 that.size.width = newWidth; 12057 that.position.left = op.left - ox; 12058 } else { 12059 newWidth = gridX - outerDimensions.width; 12060 that.size.width = newWidth; 12061 that.position.left = op.left + os.width - newWidth; 12062 } 12063 } 12064 } 12065 12066} ); 12067 12068var widgetsResizable = $.ui.resizable; 12069 12070 12071/*! 12072 * jQuery UI Dialog 1.14.1 12073 * https://jqueryui.com 12074 * 12075 * Copyright OpenJS Foundation and other contributors 12076 * Released under the MIT license. 12077 * https://jquery.org/license 12078 */ 12079 12080//>>label: Dialog 12081//>>group: Widgets 12082//>>description: Displays customizable dialog windows. 12083//>>docs: https://api.jqueryui.com/dialog/ 12084//>>demos: https://jqueryui.com/dialog/ 12085//>>css.structure: ../../themes/base/core.css 12086//>>css.structure: ../../themes/base/dialog.css 12087//>>css.theme: ../../themes/base/theme.css 12088 12089 12090$.widget( "ui.dialog", { 12091 version: "1.14.1", 12092 options: { 12093 appendTo: "body", 12094 autoOpen: true, 12095 buttons: [], 12096 classes: { 12097 "ui-dialog": "ui-corner-all", 12098 "ui-dialog-titlebar": "ui-corner-all" 12099 }, 12100 closeOnEscape: true, 12101 closeText: "Close", 12102 draggable: true, 12103 hide: null, 12104 height: "auto", 12105 maxHeight: null, 12106 maxWidth: null, 12107 minHeight: 150, 12108 minWidth: 150, 12109 modal: false, 12110 position: { 12111 my: "center", 12112 at: "center", 12113 of: window, 12114 collision: "fit", 12115 12116 // Ensure the titlebar is always visible 12117 using: function( pos ) { 12118 var topOffset = $( this ).css( pos ).offset().top; 12119 if ( topOffset < 0 ) { 12120 $( this ).css( "top", pos.top - topOffset ); 12121 } 12122 } 12123 }, 12124 resizable: true, 12125 show: null, 12126 title: null, 12127 uiDialogTitleHeadingLevel: 0, 12128 width: 300, 12129 12130 // Callbacks 12131 beforeClose: null, 12132 close: null, 12133 drag: null, 12134 dragStart: null, 12135 dragStop: null, 12136 focus: null, 12137 open: null, 12138 resize: null, 12139 resizeStart: null, 12140 resizeStop: null 12141 }, 12142 12143 sizeRelatedOptions: { 12144 buttons: true, 12145 height: true, 12146 maxHeight: true, 12147 maxWidth: true, 12148 minHeight: true, 12149 minWidth: true, 12150 width: true 12151 }, 12152 12153 resizableRelatedOptions: { 12154 maxHeight: true, 12155 maxWidth: true, 12156 minHeight: true, 12157 minWidth: true 12158 }, 12159 12160 _create: function() { 12161 this.originalCss = { 12162 display: this.element[ 0 ].style.display, 12163 width: this.element[ 0 ].style.width, 12164 minHeight: this.element[ 0 ].style.minHeight, 12165 maxHeight: this.element[ 0 ].style.maxHeight, 12166 height: this.element[ 0 ].style.height 12167 }; 12168 this.originalPosition = { 12169 parent: this.element.parent(), 12170 index: this.element.parent().children().index( this.element ) 12171 }; 12172 this.originalTitle = this.element.attr( "title" ); 12173 if ( this.options.title == null && this.originalTitle != null ) { 12174 this.options.title = this.originalTitle; 12175 } 12176 12177 // Dialogs can't be disabled 12178 if ( this.options.disabled ) { 12179 this.options.disabled = false; 12180 } 12181 12182 this._createWrapper(); 12183 12184 this.element 12185 .show() 12186 .removeAttr( "title" ) 12187 .appendTo( this.uiDialog ); 12188 12189 this._addClass( "ui-dialog-content", "ui-widget-content" ); 12190 12191 this._createTitlebar(); 12192 this._createButtonPane(); 12193 12194 if ( this.options.draggable && $.fn.draggable ) { 12195 this._makeDraggable(); 12196 } 12197 if ( this.options.resizable && $.fn.resizable ) { 12198 this._makeResizable(); 12199 } 12200 12201 this._isOpen = false; 12202 12203 this._trackFocus(); 12204 }, 12205 12206 _init: function() { 12207 if ( this.options.autoOpen ) { 12208 this.open(); 12209 } 12210 }, 12211 12212 _appendTo: function() { 12213 var element = this.options.appendTo; 12214 if ( element && ( element.jquery || element.nodeType ) ) { 12215 return $( element ); 12216 } 12217 return this.document.find( element || "body" ).eq( 0 ); 12218 }, 12219 12220 _destroy: function() { 12221 var next, 12222 originalPosition = this.originalPosition; 12223 12224 this._untrackInstance(); 12225 this._destroyOverlay(); 12226 12227 this.element 12228 .removeUniqueId() 12229 .css( this.originalCss ) 12230 12231 // Without detaching first, the following becomes really slow 12232 .detach(); 12233 12234 this.uiDialog.remove(); 12235 12236 if ( this.originalTitle ) { 12237 this.element.attr( "title", this.originalTitle ); 12238 } 12239 12240 next = originalPosition.parent.children().eq( originalPosition.index ); 12241 12242 // Don't try to place the dialog next to itself (#8613) 12243 if ( next.length && next[ 0 ] !== this.element[ 0 ] ) { 12244 next.before( this.element ); 12245 } else { 12246 originalPosition.parent.append( this.element ); 12247 } 12248 }, 12249 12250 widget: function() { 12251 return this.uiDialog; 12252 }, 12253 12254 disable: $.noop, 12255 enable: $.noop, 12256 12257 close: function( event ) { 12258 var that = this; 12259 12260 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) { 12261 return; 12262 } 12263 12264 this._isOpen = false; 12265 this._focusedElement = null; 12266 this._destroyOverlay(); 12267 this._untrackInstance(); 12268 12269 if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) { 12270 12271 // Hiding a focused element doesn't trigger blur in WebKit 12272 // so in case we have nothing to focus on, explicitly blur the active element 12273 // https://bugs.webkit.org/show_bug.cgi?id=47182 12274 $( this.document[ 0 ].activeElement ).trigger( "blur" ); 12275 } 12276 12277 this._hide( this.uiDialog, this.options.hide, function() { 12278 that._trigger( "close", event ); 12279 } ); 12280 }, 12281 12282 isOpen: function() { 12283 return this._isOpen; 12284 }, 12285 12286 moveToTop: function() { 12287 this._moveToTop(); 12288 }, 12289 12290 _moveToTop: function( event, silent ) { 12291 var moved = false, 12292 zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() { 12293 return +$( this ).css( "z-index" ); 12294 } ).get(), 12295 zIndexMax = Math.max.apply( null, zIndices ); 12296 12297 if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) { 12298 this.uiDialog.css( "z-index", zIndexMax + 1 ); 12299 moved = true; 12300 } 12301 12302 if ( moved && !silent ) { 12303 this._trigger( "focus", event ); 12304 } 12305 return moved; 12306 }, 12307 12308 open: function() { 12309 var that = this; 12310 if ( this._isOpen ) { 12311 if ( this._moveToTop() ) { 12312 this._focusTabbable(); 12313 } 12314 return; 12315 } 12316 12317 this._isOpen = true; 12318 this.opener = $( this.document[ 0 ].activeElement ); 12319 12320 this._size(); 12321 this._position(); 12322 this._createOverlay(); 12323 this._moveToTop( null, true ); 12324 12325 // Ensure the overlay is moved to the top with the dialog, but only when 12326 // opening. The overlay shouldn't move after the dialog is open so that 12327 // modeless dialogs opened after the modal dialog stack properly. 12328 if ( this.overlay ) { 12329 this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 ); 12330 } 12331 12332 this._show( this.uiDialog, this.options.show, function() { 12333 that._focusTabbable(); 12334 that._trigger( "focus" ); 12335 } ); 12336 12337 // Track the dialog immediately upon opening in case a focus event 12338 // somehow occurs outside of the dialog before an element inside the 12339 // dialog is focused (#10152) 12340 this._makeFocusTarget(); 12341 12342 this._trigger( "open" ); 12343 }, 12344 12345 _focusTabbable: function() { 12346 12347 // Set focus to the first match: 12348 // 1. An element that was focused previously 12349 // 2. First element inside the dialog matching [autofocus] 12350 // 3. Tabbable element inside the content element 12351 // 4. Tabbable element inside the buttonpane 12352 // 5. The close button 12353 // 6. The dialog itself 12354 var hasFocus = this._focusedElement; 12355 if ( !hasFocus ) { 12356 hasFocus = this.element.find( "[autofocus]" ); 12357 } 12358 if ( !hasFocus.length ) { 12359 hasFocus = this.element.find( ":tabbable" ); 12360 } 12361 if ( !hasFocus.length ) { 12362 hasFocus = this.uiDialogButtonPane.find( ":tabbable" ); 12363 } 12364 if ( !hasFocus.length ) { 12365 hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" ); 12366 } 12367 if ( !hasFocus.length ) { 12368 hasFocus = this.uiDialog; 12369 } 12370 hasFocus.eq( 0 ).trigger( "focus" ); 12371 }, 12372 12373 _restoreTabbableFocus: function() { 12374 var activeElement = this.document[ 0 ].activeElement, 12375 isActive = this.uiDialog[ 0 ] === activeElement || 12376 $.contains( this.uiDialog[ 0 ], activeElement ); 12377 if ( !isActive ) { 12378 this._focusTabbable(); 12379 } 12380 }, 12381 12382 _keepFocus: function( event ) { 12383 event.preventDefault(); 12384 this._restoreTabbableFocus(); 12385 }, 12386 12387 _createWrapper: function() { 12388 this.uiDialog = $( "<div>" ) 12389 .hide() 12390 .attr( { 12391 12392 // Setting tabIndex makes the div focusable 12393 tabIndex: -1, 12394 role: "dialog", 12395 "aria-modal": this.options.modal ? "true" : null 12396 } ) 12397 .appendTo( this._appendTo() ); 12398 12399 this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" ); 12400 this._on( this.uiDialog, { 12401 keydown: function( event ) { 12402 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && 12403 event.keyCode === $.ui.keyCode.ESCAPE ) { 12404 event.preventDefault(); 12405 this.close( event ); 12406 return; 12407 } 12408 12409 // Prevent tabbing out of dialogs 12410 if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) { 12411 return; 12412 } 12413 var tabbables = this.uiDialog.find( ":tabbable" ), 12414 first = tabbables.first(), 12415 last = tabbables.last(); 12416 12417 if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) && 12418 !event.shiftKey ) { 12419 this._delay( function() { 12420 first.trigger( "focus" ); 12421 } ); 12422 event.preventDefault(); 12423 } else if ( ( event.target === first[ 0 ] || 12424 event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) { 12425 this._delay( function() { 12426 last.trigger( "focus" ); 12427 } ); 12428 event.preventDefault(); 12429 } 12430 }, 12431 mousedown: function( event ) { 12432 if ( this._moveToTop( event ) ) { 12433 this._focusTabbable(); 12434 } 12435 } 12436 } ); 12437 12438 // We assume that any existing aria-describedby attribute means 12439 // that the dialog content is marked up properly 12440 // otherwise we brute force the content as the description 12441 if ( !this.element.find( "[aria-describedby]" ).length ) { 12442 this.uiDialog.attr( { 12443 "aria-describedby": this.element.uniqueId().attr( "id" ) 12444 } ); 12445 } 12446 }, 12447 12448 _createTitlebar: function() { 12449 var uiDialogTitle; 12450 12451 this.uiDialogTitlebar = $( "<div>" ); 12452 this._addClass( this.uiDialogTitlebar, 12453 "ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" ); 12454 this._on( this.uiDialogTitlebar, { 12455 mousedown: function( event ) { 12456 12457 // Don't prevent click on close button (#8838) 12458 // Focusing a dialog that is partially scrolled out of view 12459 // causes the browser to scroll it into view, preventing the click event 12460 if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) { 12461 12462 // Dialog isn't getting focus when dragging (#8063) 12463 this.uiDialog.trigger( "focus" ); 12464 } 12465 } 12466 } ); 12467 12468 this.uiDialogTitlebarClose = $( "<button type='button'></button>" ) 12469 .button( { 12470 label: $( "<a>" ).text( this.options.closeText ).html(), 12471 icon: "ui-icon-closethick", 12472 showLabel: false 12473 } ) 12474 .appendTo( this.uiDialogTitlebar ); 12475 12476 this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" ); 12477 this._on( this.uiDialogTitlebarClose, { 12478 click: function( event ) { 12479 event.preventDefault(); 12480 this.close( event ); 12481 } 12482 } ); 12483 12484 var uiDialogHeadingLevel = Number.isInteger( this.options.uiDialogTitleHeadingLevel ) && 12485 this.options.uiDialogTitleHeadingLevel > 0 && 12486 this.options.uiDialogTitleHeadingLevel <= 6 ? 12487 "h" + this.options.uiDialogTitleHeadingLevel : "span"; 12488 12489 uiDialogTitle = $( "<" + uiDialogHeadingLevel + ">" ) 12490 .uniqueId().prependTo( this.uiDialogTitlebar ); 12491 this._addClass( uiDialogTitle, "ui-dialog-title" ); 12492 this._title( uiDialogTitle ); 12493 12494 this.uiDialogTitlebar.prependTo( this.uiDialog ); 12495 12496 this.uiDialog.attr( { 12497 "aria-labelledby": uiDialogTitle.attr( "id" ) 12498 } ); 12499 }, 12500 12501 _title: function( title ) { 12502 if ( this.options.title ) { 12503 title.text( this.options.title ); 12504 } else { 12505 title.html( " " ); 12506 } 12507 }, 12508 12509 _createButtonPane: function() { 12510 this.uiDialogButtonPane = $( "<div>" ); 12511 this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane", 12512 "ui-widget-content ui-helper-clearfix" ); 12513 12514 this.uiButtonSet = $( "<div>" ) 12515 .appendTo( this.uiDialogButtonPane ); 12516 this._addClass( this.uiButtonSet, "ui-dialog-buttonset" ); 12517 12518 this._createButtons(); 12519 }, 12520 12521 _createButtons: function() { 12522 var that = this, 12523 buttons = this.options.buttons; 12524 12525 // If we already have a button pane, remove it 12526 this.uiDialogButtonPane.remove(); 12527 this.uiButtonSet.empty(); 12528 12529 if ( $.isEmptyObject( buttons ) || ( Array.isArray( buttons ) && !buttons.length ) ) { 12530 this._removeClass( this.uiDialog, "ui-dialog-buttons" ); 12531 return; 12532 } 12533 12534 $.each( buttons, function( name, props ) { 12535 var click, buttonOptions; 12536 props = typeof props === "function" ? 12537 { click: props, text: name } : 12538 props; 12539 12540 // Default to a non-submitting button 12541 props = $.extend( { type: "button" }, props ); 12542 12543 // Change the context for the click callback to be the main element 12544 click = props.click; 12545 buttonOptions = { 12546 icon: props.icon, 12547 iconPosition: props.iconPosition, 12548 showLabel: props.showLabel, 12549 12550 // Deprecated options 12551 icons: props.icons, 12552 text: props.text 12553 }; 12554 12555 delete props.click; 12556 delete props.icon; 12557 delete props.iconPosition; 12558 delete props.showLabel; 12559 12560 // Deprecated options 12561 delete props.icons; 12562 if ( typeof props.text === "boolean" ) { 12563 delete props.text; 12564 } 12565 12566 $( "<button></button>", props ) 12567 .button( buttonOptions ) 12568 .appendTo( that.uiButtonSet ) 12569 .on( "click", function() { 12570 click.apply( that.element[ 0 ], arguments ); 12571 } ); 12572 } ); 12573 this._addClass( this.uiDialog, "ui-dialog-buttons" ); 12574 this.uiDialogButtonPane.appendTo( this.uiDialog ); 12575 }, 12576 12577 _makeDraggable: function() { 12578 var that = this, 12579 options = this.options; 12580 12581 function filteredUi( ui ) { 12582 return { 12583 position: ui.position, 12584 offset: ui.offset 12585 }; 12586 } 12587 12588 this.uiDialog.draggable( { 12589 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", 12590 handle: ".ui-dialog-titlebar", 12591 containment: "document", 12592 start: function( event, ui ) { 12593 that._addClass( $( this ), "ui-dialog-dragging" ); 12594 that._blockFrames(); 12595 that._trigger( "dragStart", event, filteredUi( ui ) ); 12596 }, 12597 drag: function( event, ui ) { 12598 that._trigger( "drag", event, filteredUi( ui ) ); 12599 }, 12600 stop: function( event, ui ) { 12601 var left = ui.offset.left - that.document.scrollLeft(), 12602 top = ui.offset.top - that.document.scrollTop(); 12603 12604 options.position = { 12605 my: "left top", 12606 at: "left" + ( left >= 0 ? "+" : "" ) + left + " " + 12607 "top" + ( top >= 0 ? "+" : "" ) + top, 12608 of: that.window 12609 }; 12610 that._removeClass( $( this ), "ui-dialog-dragging" ); 12611 that._unblockFrames(); 12612 that._trigger( "dragStop", event, filteredUi( ui ) ); 12613 } 12614 } ); 12615 }, 12616 12617 _makeResizable: function() { 12618 var that = this, 12619 options = this.options, 12620 handles = options.resizable, 12621 12622 // .ui-resizable has position: relative defined in the stylesheet 12623 // but dialogs have to use absolute or fixed positioning 12624 position = this.uiDialog.css( "position" ), 12625 resizeHandles = typeof handles === "string" ? 12626 handles : 12627 "n,e,s,w,se,sw,ne,nw"; 12628 12629 function filteredUi( ui ) { 12630 return { 12631 originalPosition: ui.originalPosition, 12632 originalSize: ui.originalSize, 12633 position: ui.position, 12634 size: ui.size 12635 }; 12636 } 12637 12638 this.uiDialog.resizable( { 12639 cancel: ".ui-dialog-content", 12640 containment: "document", 12641 alsoResize: this.element, 12642 maxWidth: options.maxWidth, 12643 maxHeight: options.maxHeight, 12644 minWidth: options.minWidth, 12645 minHeight: this._minHeight(), 12646 handles: resizeHandles, 12647 start: function( event, ui ) { 12648 that._addClass( $( this ), "ui-dialog-resizing" ); 12649 that._blockFrames(); 12650 that._trigger( "resizeStart", event, filteredUi( ui ) ); 12651 }, 12652 resize: function( event, ui ) { 12653 that._trigger( "resize", event, filteredUi( ui ) ); 12654 }, 12655 stop: function( event, ui ) { 12656 var offset = that.uiDialog.offset(), 12657 left = offset.left - that.document.scrollLeft(), 12658 top = offset.top - that.document.scrollTop(); 12659 12660 options.height = that.uiDialog.height(); 12661 options.width = that.uiDialog.width(); 12662 options.position = { 12663 my: "left top", 12664 at: "left" + ( left >= 0 ? "+" : "" ) + left + " " + 12665 "top" + ( top >= 0 ? "+" : "" ) + top, 12666 of: that.window 12667 }; 12668 that._removeClass( $( this ), "ui-dialog-resizing" ); 12669 that._unblockFrames(); 12670 that._trigger( "resizeStop", event, filteredUi( ui ) ); 12671 } 12672 } ) 12673 .css( "position", position ); 12674 }, 12675 12676 _trackFocus: function() { 12677 this._on( this.widget(), { 12678 focusin: function( event ) { 12679 this._makeFocusTarget(); 12680 this._focusedElement = $( event.target ); 12681 } 12682 } ); 12683 }, 12684 12685 _makeFocusTarget: function() { 12686 this._untrackInstance(); 12687 this._trackingInstances().unshift( this ); 12688 }, 12689 12690 _untrackInstance: function() { 12691 var instances = this._trackingInstances(), 12692 exists = $.inArray( this, instances ); 12693 if ( exists !== -1 ) { 12694 instances.splice( exists, 1 ); 12695 } 12696 }, 12697 12698 _trackingInstances: function() { 12699 var instances = this.document.data( "ui-dialog-instances" ); 12700 if ( !instances ) { 12701 instances = []; 12702 this.document.data( "ui-dialog-instances", instances ); 12703 } 12704 return instances; 12705 }, 12706 12707 _minHeight: function() { 12708 var options = this.options; 12709 12710 return options.height === "auto" ? 12711 options.minHeight : 12712 Math.min( options.minHeight, options.height ); 12713 }, 12714 12715 _position: function() { 12716 12717 // Need to show the dialog to get the actual offset in the position plugin 12718 var isVisible = this.uiDialog.is( ":visible" ); 12719 if ( !isVisible ) { 12720 this.uiDialog.show(); 12721 } 12722 this.uiDialog.position( this.options.position ); 12723 if ( !isVisible ) { 12724 this.uiDialog.hide(); 12725 } 12726 }, 12727 12728 _setOptions: function( options ) { 12729 var that = this, 12730 resize = false, 12731 resizableOptions = {}; 12732 12733 $.each( options, function( key, value ) { 12734 that._setOption( key, value ); 12735 12736 if ( key in that.sizeRelatedOptions ) { 12737 resize = true; 12738 } 12739 if ( key in that.resizableRelatedOptions ) { 12740 resizableOptions[ key ] = value; 12741 } 12742 } ); 12743 12744 if ( resize ) { 12745 this._size(); 12746 this._position(); 12747 } 12748 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) { 12749 this.uiDialog.resizable( "option", resizableOptions ); 12750 } 12751 }, 12752 12753 _setOption: function( key, value ) { 12754 var isDraggable, isResizable, 12755 uiDialog = this.uiDialog; 12756 12757 if ( key === "disabled" ) { 12758 return; 12759 } 12760 12761 this._super( key, value ); 12762 12763 if ( key === "appendTo" ) { 12764 this.uiDialog.appendTo( this._appendTo() ); 12765 } 12766 12767 if ( key === "buttons" ) { 12768 this._createButtons(); 12769 } 12770 12771 if ( key === "closeText" ) { 12772 this.uiDialogTitlebarClose.button( { 12773 12774 // Ensure that we always pass a string 12775 label: $( "<a>" ).text( "" + this.options.closeText ).html() 12776 } ); 12777 } 12778 12779 if ( key === "draggable" ) { 12780 isDraggable = uiDialog.is( ":data(ui-draggable)" ); 12781 if ( isDraggable && !value ) { 12782 uiDialog.draggable( "destroy" ); 12783 } 12784 12785 if ( !isDraggable && value ) { 12786 this._makeDraggable(); 12787 } 12788 } 12789 12790 if ( key === "position" ) { 12791 this._position(); 12792 } 12793 12794 if ( key === "resizable" ) { 12795 12796 // currently resizable, becoming non-resizable 12797 isResizable = uiDialog.is( ":data(ui-resizable)" ); 12798 if ( isResizable && !value ) { 12799 uiDialog.resizable( "destroy" ); 12800 } 12801 12802 // Currently resizable, changing handles 12803 if ( isResizable && typeof value === "string" ) { 12804 uiDialog.resizable( "option", "handles", value ); 12805 } 12806 12807 // Currently non-resizable, becoming resizable 12808 if ( !isResizable && value !== false ) { 12809 this._makeResizable(); 12810 } 12811 } 12812 12813 if ( key === "title" ) { 12814 this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) ); 12815 } 12816 12817 if ( key === "modal" ) { 12818 uiDialog.attr( "aria-modal", value ? "true" : null ); 12819 } 12820 }, 12821 12822 _size: function() { 12823 12824 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content 12825 // divs will both have width and height set, so we need to reset them 12826 var nonContentHeight, minContentHeight, maxContentHeight, 12827 options = this.options; 12828 12829 // Reset content sizing 12830 this.element.show().css( { 12831 width: "auto", 12832 minHeight: 0, 12833 maxHeight: "none", 12834 height: 0 12835 } ); 12836 12837 if ( options.minWidth > options.width ) { 12838 options.width = options.minWidth; 12839 } 12840 12841 // Reset wrapper sizing 12842 // determine the height of all the non-content elements 12843 nonContentHeight = this.uiDialog.css( { 12844 height: "auto", 12845 width: options.width 12846 } ) 12847 .outerHeight(); 12848 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); 12849 maxContentHeight = typeof options.maxHeight === "number" ? 12850 Math.max( 0, options.maxHeight - nonContentHeight ) : 12851 "none"; 12852 12853 if ( options.height === "auto" ) { 12854 this.element.css( { 12855 minHeight: minContentHeight, 12856 maxHeight: maxContentHeight, 12857 height: "auto" 12858 } ); 12859 } else { 12860 this.element.height( Math.max( 0, options.height - nonContentHeight ) ); 12861 } 12862 12863 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) { 12864 this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); 12865 } 12866 }, 12867 12868 _blockFrames: function() { 12869 this.iframeBlocks = this.document.find( "iframe" ).map( function() { 12870 var iframe = $( this ); 12871 12872 return $( "<div>" ) 12873 .css( { 12874 position: "absolute", 12875 width: iframe.outerWidth(), 12876 height: iframe.outerHeight() 12877 } ) 12878 .appendTo( iframe.parent() ) 12879 .offset( iframe.offset() )[ 0 ]; 12880 } ); 12881 }, 12882 12883 _unblockFrames: function() { 12884 if ( this.iframeBlocks ) { 12885 this.iframeBlocks.remove(); 12886 delete this.iframeBlocks; 12887 } 12888 }, 12889 12890 _allowInteraction: function( event ) { 12891 if ( $( event.target ).closest( ".ui-dialog" ).length ) { 12892 return true; 12893 } 12894 12895 // TODO: Remove hack when datepicker implements 12896 // the .ui-front logic (#8989) 12897 return !!$( event.target ).closest( ".ui-datepicker" ).length; 12898 }, 12899 12900 _createOverlay: function() { 12901 if ( !this.options.modal ) { 12902 return; 12903 } 12904 12905 // We use a delay in case the overlay is created from an 12906 // event that we're going to be cancelling (#2804) 12907 var isOpening = true; 12908 this._delay( function() { 12909 isOpening = false; 12910 } ); 12911 12912 if ( !this.document.data( "ui-dialog-overlays" ) ) { 12913 12914 // Prevent use of anchors and inputs 12915 // This doesn't use `_on()` because it is a shared event handler 12916 // across all open modal dialogs. 12917 this.document.on( "focusin.ui-dialog", function( event ) { 12918 if ( isOpening ) { 12919 return; 12920 } 12921 12922 var instance = this._trackingInstances()[ 0 ]; 12923 if ( !instance._allowInteraction( event ) ) { 12924 event.preventDefault(); 12925 instance._focusTabbable(); 12926 } 12927 }.bind( this ) ); 12928 } 12929 12930 this.overlay = $( "<div>" ) 12931 .appendTo( this._appendTo() ); 12932 12933 this._addClass( this.overlay, null, "ui-widget-overlay ui-front" ); 12934 this._on( this.overlay, { 12935 mousedown: "_keepFocus" 12936 } ); 12937 this.document.data( "ui-dialog-overlays", 12938 ( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 ); 12939 }, 12940 12941 _destroyOverlay: function() { 12942 if ( !this.options.modal ) { 12943 return; 12944 } 12945 12946 if ( this.overlay ) { 12947 var overlays = this.document.data( "ui-dialog-overlays" ) - 1; 12948 12949 if ( !overlays ) { 12950 this.document.off( "focusin.ui-dialog" ); 12951 this.document.removeData( "ui-dialog-overlays" ); 12952 } else { 12953 this.document.data( "ui-dialog-overlays", overlays ); 12954 } 12955 12956 this.overlay.remove(); 12957 this.overlay = null; 12958 } 12959 } 12960} ); 12961 12962// DEPRECATED 12963// TODO: switch return back to widget declaration at top of file when this is removed 12964if ( $.uiBackCompat === true ) { 12965 12966 // Backcompat for dialogClass option 12967 $.widget( "ui.dialog", $.ui.dialog, { 12968 options: { 12969 dialogClass: "" 12970 }, 12971 _createWrapper: function() { 12972 this._super(); 12973 this.uiDialog.addClass( this.options.dialogClass ); 12974 }, 12975 _setOption: function( key, value ) { 12976 if ( key === "dialogClass" ) { 12977 this.uiDialog 12978 .removeClass( this.options.dialogClass ) 12979 .addClass( value ); 12980 } 12981 this._superApply( arguments ); 12982 } 12983 } ); 12984} 12985 12986var widgetsDialog = $.ui.dialog; 12987 12988 12989/*! 12990 * jQuery UI Droppable 1.14.1 12991 * https://jqueryui.com 12992 * 12993 * Copyright OpenJS Foundation and other contributors 12994 * Released under the MIT license. 12995 * https://jquery.org/license 12996 */ 12997 12998//>>label: Droppable 12999//>>group: Interactions 13000//>>description: Enables drop targets for draggable elements. 13001//>>docs: https://api.jqueryui.com/droppable/ 13002//>>demos: https://jqueryui.com/droppable/ 13003 13004 13005$.widget( "ui.droppable", { 13006 version: "1.14.1", 13007 widgetEventPrefix: "drop", 13008 options: { 13009 accept: "*", 13010 addClasses: true, 13011 greedy: false, 13012 scope: "default", 13013 tolerance: "intersect", 13014 13015 // Callbacks 13016 activate: null, 13017 deactivate: null, 13018 drop: null, 13019 out: null, 13020 over: null 13021 }, 13022 _create: function() { 13023 13024 var proportions, 13025 o = this.options, 13026 accept = o.accept; 13027 13028 this.isover = false; 13029 this.isout = true; 13030 13031 this.accept = typeof accept === "function" ? accept : function( d ) { 13032 return d.is( accept ); 13033 }; 13034 13035 this.proportions = function( /* valueToWrite */ ) { 13036 if ( arguments.length ) { 13037 13038 // Store the droppable's proportions 13039 proportions = arguments[ 0 ]; 13040 } else { 13041 13042 // Retrieve or derive the droppable's proportions 13043 return proportions ? 13044 proportions : 13045 proportions = { 13046 width: this.element[ 0 ].offsetWidth, 13047 height: this.element[ 0 ].offsetHeight 13048 }; 13049 } 13050 }; 13051 13052 this._addToManager( o.scope ); 13053 13054 if ( o.addClasses ) { 13055 this._addClass( "ui-droppable" ); 13056 } 13057 13058 }, 13059 13060 _addToManager: function( scope ) { 13061 13062 // Add the reference and positions to the manager 13063 $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || []; 13064 $.ui.ddmanager.droppables[ scope ].push( this ); 13065 }, 13066 13067 _splice: function( drop ) { 13068 var i = 0; 13069 for ( ; i < drop.length; i++ ) { 13070 if ( drop[ i ] === this ) { 13071 drop.splice( i, 1 ); 13072 } 13073 } 13074 }, 13075 13076 _destroy: function() { 13077 var drop = $.ui.ddmanager.droppables[ this.options.scope ]; 13078 13079 this._splice( drop ); 13080 }, 13081 13082 _setOption: function( key, value ) { 13083 13084 if ( key === "accept" ) { 13085 this.accept = typeof value === "function" ? value : function( d ) { 13086 return d.is( value ); 13087 }; 13088 } else if ( key === "scope" ) { 13089 var drop = $.ui.ddmanager.droppables[ this.options.scope ]; 13090 13091 this._splice( drop ); 13092 this._addToManager( value ); 13093 } 13094 13095 this._super( key, value ); 13096 }, 13097 13098 _activate: function( event ) { 13099 var draggable = $.ui.ddmanager.current; 13100 13101 this._addActiveClass(); 13102 if ( draggable ) { 13103 this._trigger( "activate", event, this.ui( draggable ) ); 13104 } 13105 }, 13106 13107 _deactivate: function( event ) { 13108 var draggable = $.ui.ddmanager.current; 13109 13110 this._removeActiveClass(); 13111 if ( draggable ) { 13112 this._trigger( "deactivate", event, this.ui( draggable ) ); 13113 } 13114 }, 13115 13116 _over: function( event ) { 13117 13118 var draggable = $.ui.ddmanager.current; 13119 13120 // Bail if draggable and droppable are same element 13121 if ( !draggable || ( draggable.currentItem || 13122 draggable.element )[ 0 ] === this.element[ 0 ] ) { 13123 return; 13124 } 13125 13126 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || 13127 draggable.element ) ) ) { 13128 this._addHoverClass(); 13129 this._trigger( "over", event, this.ui( draggable ) ); 13130 } 13131 13132 }, 13133 13134 _out: function( event ) { 13135 13136 var draggable = $.ui.ddmanager.current; 13137 13138 // Bail if draggable and droppable are same element 13139 if ( !draggable || ( draggable.currentItem || 13140 draggable.element )[ 0 ] === this.element[ 0 ] ) { 13141 return; 13142 } 13143 13144 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || 13145 draggable.element ) ) ) { 13146 this._removeHoverClass(); 13147 this._trigger( "out", event, this.ui( draggable ) ); 13148 } 13149 13150 }, 13151 13152 _drop: function( event, custom ) { 13153 13154 var draggable = custom || $.ui.ddmanager.current, 13155 childrenIntersection = false; 13156 13157 // Bail if draggable and droppable are same element 13158 if ( !draggable || ( draggable.currentItem || 13159 draggable.element )[ 0 ] === this.element[ 0 ] ) { 13160 return false; 13161 } 13162 13163 this.element 13164 .find( ":data(ui-droppable)" ) 13165 .not( ".ui-draggable-dragging" ) 13166 .each( function() { 13167 var inst = $( this ).droppable( "instance" ); 13168 if ( 13169 inst.options.greedy && 13170 !inst.options.disabled && 13171 inst.options.scope === draggable.options.scope && 13172 inst.accept.call( 13173 inst.element[ 0 ], ( draggable.currentItem || draggable.element ) 13174 ) && 13175 $.ui.intersect( 13176 draggable, 13177 $.extend( inst, { offset: inst.element.offset() } ), 13178 inst.options.tolerance, event 13179 ) 13180 ) { 13181 childrenIntersection = true; 13182 return false; 13183 } 13184 } ); 13185 if ( childrenIntersection ) { 13186 return false; 13187 } 13188 13189 if ( this.accept.call( this.element[ 0 ], 13190 ( draggable.currentItem || draggable.element ) ) ) { 13191 this._removeActiveClass(); 13192 this._removeHoverClass(); 13193 13194 this._trigger( "drop", event, this.ui( draggable ) ); 13195 return this.element; 13196 } 13197 13198 return false; 13199 13200 }, 13201 13202 ui: function( c ) { 13203 return { 13204 draggable: ( c.currentItem || c.element ), 13205 helper: c.helper, 13206 position: c.position, 13207 offset: c.positionAbs 13208 }; 13209 }, 13210 13211 // Extension points just to make backcompat sane and avoid duplicating logic 13212 // TODO: Remove in 1.14 along with call to it below 13213 _addHoverClass: function() { 13214 this._addClass( "ui-droppable-hover" ); 13215 }, 13216 13217 _removeHoverClass: function() { 13218 this._removeClass( "ui-droppable-hover" ); 13219 }, 13220 13221 _addActiveClass: function() { 13222 this._addClass( "ui-droppable-active" ); 13223 }, 13224 13225 _removeActiveClass: function() { 13226 this._removeClass( "ui-droppable-active" ); 13227 } 13228} ); 13229 13230$.ui.intersect = ( function() { 13231 function isOverAxis( x, reference, size ) { 13232 return ( x >= reference ) && ( x < ( reference + size ) ); 13233 } 13234 13235 return function( draggable, droppable, toleranceMode, event ) { 13236 13237 if ( !droppable.offset ) { 13238 return false; 13239 } 13240 13241 var x1 = ( draggable.positionAbs || 13242 draggable.position.absolute ).left + draggable.margins.left, 13243 y1 = ( draggable.positionAbs || 13244 draggable.position.absolute ).top + draggable.margins.top, 13245 x2 = x1 + draggable.helperProportions.width, 13246 y2 = y1 + draggable.helperProportions.height, 13247 l = droppable.offset.left, 13248 t = droppable.offset.top, 13249 r = l + droppable.proportions().width, 13250 b = t + droppable.proportions().height; 13251 13252 switch ( toleranceMode ) { 13253 case "fit": 13254 return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b ); 13255 case "intersect": 13256 return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half 13257 x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half 13258 t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half 13259 y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half 13260 case "pointer": 13261 return isOverAxis( event.pageY, t, droppable.proportions().height ) && 13262 isOverAxis( event.pageX, l, droppable.proportions().width ); 13263 case "touch": 13264 return ( 13265 ( y1 >= t && y1 <= b ) || // Top edge touching 13266 ( y2 >= t && y2 <= b ) || // Bottom edge touching 13267 ( y1 < t && y2 > b ) // Surrounded vertically 13268 ) && ( 13269 ( x1 >= l && x1 <= r ) || // Left edge touching 13270 ( x2 >= l && x2 <= r ) || // Right edge touching 13271 ( x1 < l && x2 > r ) // Surrounded horizontally 13272 ); 13273 default: 13274 return false; 13275 } 13276 }; 13277} )(); 13278 13279/* 13280 This manager tracks offsets of draggables and droppables 13281*/ 13282$.ui.ddmanager = { 13283 current: null, 13284 droppables: { "default": [] }, 13285 prepareOffsets: function( t, event ) { 13286 13287 var i, j, 13288 m = $.ui.ddmanager.droppables[ t.options.scope ] || [], 13289 type = event ? event.type : null, // workaround for #2317 13290 list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack(); 13291 13292 droppablesLoop: for ( i = 0; i < m.length; i++ ) { 13293 13294 // No disabled and non-accepted 13295 if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], 13296 ( t.currentItem || t.element ) ) ) ) { 13297 continue; 13298 } 13299 13300 // Filter out elements in the current dragged item 13301 for ( j = 0; j < list.length; j++ ) { 13302 if ( list[ j ] === m[ i ].element[ 0 ] ) { 13303 m[ i ].proportions().height = 0; 13304 continue droppablesLoop; 13305 } 13306 } 13307 13308 m[ i ].visible = m[ i ].element.css( "display" ) !== "none"; 13309 if ( !m[ i ].visible ) { 13310 continue; 13311 } 13312 13313 // Activate the droppable if used directly from draggables 13314 if ( type === "mousedown" ) { 13315 m[ i ]._activate.call( m[ i ], event ); 13316 } 13317 13318 m[ i ].offset = m[ i ].element.offset(); 13319 m[ i ].proportions( { 13320 width: m[ i ].element[ 0 ].offsetWidth, 13321 height: m[ i ].element[ 0 ].offsetHeight 13322 } ); 13323 13324 } 13325 13326 }, 13327 drop: function( draggable, event ) { 13328 13329 var dropped = false; 13330 13331 // Create a copy of the droppables in case the list changes during the drop (#9116) 13332 $.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() { 13333 13334 if ( !this.options ) { 13335 return; 13336 } 13337 if ( !this.options.disabled && this.visible && 13338 $.ui.intersect( draggable, this, this.options.tolerance, event ) ) { 13339 dropped = this._drop.call( this, event ) || dropped; 13340 } 13341 13342 if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ], 13343 ( draggable.currentItem || draggable.element ) ) ) { 13344 this.isout = true; 13345 this.isover = false; 13346 this._deactivate.call( this, event ); 13347 } 13348 13349 } ); 13350 return dropped; 13351 13352 }, 13353 dragStart: function( draggable, event ) { 13354 13355 // Listen for scrolling so that if the dragging causes scrolling the position of the 13356 // droppables can be recalculated (see #5003) 13357 draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() { 13358 if ( !draggable.options.refreshPositions ) { 13359 $.ui.ddmanager.prepareOffsets( draggable, event ); 13360 } 13361 } ); 13362 }, 13363 drag: function( draggable, event ) { 13364 13365 // If you have a highly dynamic page, you might try this option. It renders positions 13366 // every time you move the mouse. 13367 if ( draggable.options.refreshPositions ) { 13368 $.ui.ddmanager.prepareOffsets( draggable, event ); 13369 } 13370 13371 // Run through all droppables and check their positions based on specific tolerance options 13372 $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() { 13373 13374 if ( this.options.disabled || this.greedyChild || !this.visible ) { 13375 return; 13376 } 13377 13378 var parentInstance, scope, parent, 13379 intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ), 13380 c = !intersects && this.isover ? 13381 "isout" : 13382 ( intersects && !this.isover ? "isover" : null ); 13383 if ( !c ) { 13384 return; 13385 } 13386 13387 if ( this.options.greedy ) { 13388 13389 // find droppable parents with same scope 13390 scope = this.options.scope; 13391 parent = this.element.parents( ":data(ui-droppable)" ).filter( function() { 13392 return $( this ).droppable( "instance" ).options.scope === scope; 13393 } ); 13394 13395 if ( parent.length ) { 13396 parentInstance = $( parent[ 0 ] ).droppable( "instance" ); 13397 parentInstance.greedyChild = ( c === "isover" ); 13398 } 13399 } 13400 13401 // We just moved into a greedy child 13402 if ( parentInstance && c === "isover" ) { 13403 parentInstance.isover = false; 13404 parentInstance.isout = true; 13405 parentInstance._out.call( parentInstance, event ); 13406 } 13407 13408 this[ c ] = true; 13409 this[ c === "isout" ? "isover" : "isout" ] = false; 13410 this[ c === "isover" ? "_over" : "_out" ].call( this, event ); 13411 13412 // We just moved out of a greedy child 13413 if ( parentInstance && c === "isout" ) { 13414 parentInstance.isout = false; 13415 parentInstance.isover = true; 13416 parentInstance._over.call( parentInstance, event ); 13417 } 13418 } ); 13419 13420 }, 13421 dragStop: function( draggable, event ) { 13422 draggable.element.parentsUntil( "body" ).off( "scroll.droppable" ); 13423 13424 // Call prepareOffsets one final time since IE does not fire return scroll events when 13425 // overflow was caused by drag (see #5003) 13426 if ( !draggable.options.refreshPositions ) { 13427 $.ui.ddmanager.prepareOffsets( draggable, event ); 13428 } 13429 } 13430}; 13431 13432// DEPRECATED 13433// TODO: switch return back to widget declaration at top of file when this is removed 13434if ( $.uiBackCompat === true ) { 13435 13436 // Backcompat for activeClass and hoverClass options 13437 $.widget( "ui.droppable", $.ui.droppable, { 13438 options: { 13439 hoverClass: false, 13440 activeClass: false 13441 }, 13442 _addActiveClass: function() { 13443 this._super(); 13444 if ( this.options.activeClass ) { 13445 this.element.addClass( this.options.activeClass ); 13446 } 13447 }, 13448 _removeActiveClass: function() { 13449 this._super(); 13450 if ( this.options.activeClass ) { 13451 this.element.removeClass( this.options.activeClass ); 13452 } 13453 }, 13454 _addHoverClass: function() { 13455 this._super(); 13456 if ( this.options.hoverClass ) { 13457 this.element.addClass( this.options.hoverClass ); 13458 } 13459 }, 13460 _removeHoverClass: function() { 13461 this._super(); 13462 if ( this.options.hoverClass ) { 13463 this.element.removeClass( this.options.hoverClass ); 13464 } 13465 } 13466 } ); 13467} 13468 13469var widgetsDroppable = $.ui.droppable; 13470 13471 13472/*! 13473 * jQuery UI Progressbar 1.14.1 13474 * https://jqueryui.com 13475 * 13476 * Copyright OpenJS Foundation and other contributors 13477 * Released under the MIT license. 13478 * https://jquery.org/license 13479 */ 13480 13481//>>label: Progressbar 13482//>>group: Widgets 13483/* eslint-disable max-len */ 13484//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators. 13485/* eslint-enable max-len */ 13486//>>docs: https://api.jqueryui.com/progressbar/ 13487//>>demos: https://jqueryui.com/progressbar/ 13488//>>css.structure: ../../themes/base/core.css 13489//>>css.structure: ../../themes/base/progressbar.css 13490//>>css.theme: ../../themes/base/theme.css 13491 13492 13493var widgetsProgressbar = $.widget( "ui.progressbar", { 13494 version: "1.14.1", 13495 options: { 13496 classes: { 13497 "ui-progressbar": "ui-corner-all", 13498 "ui-progressbar-value": "ui-corner-left", 13499 "ui-progressbar-complete": "ui-corner-right" 13500 }, 13501 max: 100, 13502 value: 0, 13503 13504 change: null, 13505 complete: null 13506 }, 13507 13508 min: 0, 13509 13510 _create: function() { 13511 13512 // Constrain initial value 13513 this.oldValue = this.options.value = this._constrainedValue(); 13514 13515 this.element.attr( { 13516 13517 // Only set static values; aria-valuenow and aria-valuemax are 13518 // set inside _refreshValue() 13519 role: "progressbar", 13520 "aria-valuemin": this.min 13521 } ); 13522 this._addClass( "ui-progressbar", "ui-widget ui-widget-content" ); 13523 13524 this.valueDiv = $( "<div>" ).appendTo( this.element ); 13525 this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" ); 13526 this._refreshValue(); 13527 }, 13528 13529 _destroy: function() { 13530 this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" ); 13531 13532 this.valueDiv.remove(); 13533 }, 13534 13535 value: function( newValue ) { 13536 if ( newValue === undefined ) { 13537 return this.options.value; 13538 } 13539 13540 this.options.value = this._constrainedValue( newValue ); 13541 this._refreshValue(); 13542 }, 13543 13544 _constrainedValue: function( newValue ) { 13545 if ( newValue === undefined ) { 13546 newValue = this.options.value; 13547 } 13548 13549 this.indeterminate = newValue === false; 13550 13551 // Sanitize value 13552 if ( typeof newValue !== "number" ) { 13553 newValue = 0; 13554 } 13555 13556 return this.indeterminate ? false : 13557 Math.min( this.options.max, Math.max( this.min, newValue ) ); 13558 }, 13559 13560 _setOptions: function( options ) { 13561 13562 // Ensure "value" option is set after other values (like max) 13563 var value = options.value; 13564 delete options.value; 13565 13566 this._super( options ); 13567 13568 this.options.value = this._constrainedValue( value ); 13569 this._refreshValue(); 13570 }, 13571 13572 _setOption: function( key, value ) { 13573 if ( key === "max" ) { 13574 13575 // Don't allow a max less than min 13576 value = Math.max( this.min, value ); 13577 } 13578 this._super( key, value ); 13579 }, 13580 13581 _setOptionDisabled: function( value ) { 13582 this._super( value ); 13583 13584 this.element.attr( "aria-disabled", value ); 13585 this._toggleClass( null, "ui-state-disabled", !!value ); 13586 }, 13587 13588 _percentage: function() { 13589 return this.indeterminate ? 13590 100 : 13591 100 * ( this.options.value - this.min ) / ( this.options.max - this.min ); 13592 }, 13593 13594 _refreshValue: function() { 13595 var value = this.options.value, 13596 percentage = this._percentage(); 13597 13598 this.valueDiv 13599 .toggle( this.indeterminate || value > this.min ) 13600 .width( percentage.toFixed( 0 ) + "%" ); 13601 13602 this 13603 ._toggleClass( this.valueDiv, "ui-progressbar-complete", null, 13604 value === this.options.max ) 13605 ._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate ); 13606 13607 if ( this.indeterminate ) { 13608 this.element.removeAttr( "aria-valuenow" ); 13609 if ( !this.overlayDiv ) { 13610 this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv ); 13611 this._addClass( this.overlayDiv, "ui-progressbar-overlay" ); 13612 } 13613 } else { 13614 this.element.attr( { 13615 "aria-valuemax": this.options.max, 13616 "aria-valuenow": value 13617 } ); 13618 if ( this.overlayDiv ) { 13619 this.overlayDiv.remove(); 13620 this.overlayDiv = null; 13621 } 13622 } 13623 13624 if ( this.oldValue !== value ) { 13625 this.oldValue = value; 13626 this._trigger( "change" ); 13627 } 13628 if ( value === this.options.max ) { 13629 this._trigger( "complete" ); 13630 } 13631 } 13632} ); 13633 13634 13635/*! 13636 * jQuery UI Selectable 1.14.1 13637 * https://jqueryui.com 13638 * 13639 * Copyright OpenJS Foundation and other contributors 13640 * Released under the MIT license. 13641 * https://jquery.org/license 13642 */ 13643 13644//>>label: Selectable 13645//>>group: Interactions 13646//>>description: Allows groups of elements to be selected with the mouse. 13647//>>docs: https://api.jqueryui.com/selectable/ 13648//>>demos: https://jqueryui.com/selectable/ 13649//>>css.structure: ../../themes/base/selectable.css 13650 13651 13652var widgetsSelectable = $.widget( "ui.selectable", $.ui.mouse, { 13653 version: "1.14.1", 13654 options: { 13655 appendTo: "body", 13656 autoRefresh: true, 13657 distance: 0, 13658 filter: "*", 13659 tolerance: "touch", 13660 13661 // Callbacks 13662 selected: null, 13663 selecting: null, 13664 start: null, 13665 stop: null, 13666 unselected: null, 13667 unselecting: null 13668 }, 13669 _create: function() { 13670 var that = this; 13671 13672 this._addClass( "ui-selectable" ); 13673 13674 this.dragged = false; 13675 13676 // Cache selectee children based on filter 13677 this.refresh = function() { 13678 that.elementPos = $( that.element[ 0 ] ).offset(); 13679 that.selectees = $( that.options.filter, that.element[ 0 ] ); 13680 that._addClass( that.selectees, "ui-selectee" ); 13681 that.selectees.each( function() { 13682 var $this = $( this ), 13683 selecteeOffset = $this.offset(), 13684 pos = { 13685 left: selecteeOffset.left - that.elementPos.left, 13686 top: selecteeOffset.top - that.elementPos.top 13687 }; 13688 $.data( this, "selectable-item", { 13689 element: this, 13690 $element: $this, 13691 left: pos.left, 13692 top: pos.top, 13693 right: pos.left + $this.outerWidth(), 13694 bottom: pos.top + $this.outerHeight(), 13695 startselected: false, 13696 selected: $this.hasClass( "ui-selected" ), 13697 selecting: $this.hasClass( "ui-selecting" ), 13698 unselecting: $this.hasClass( "ui-unselecting" ) 13699 } ); 13700 } ); 13701 }; 13702 this.refresh(); 13703 13704 this._mouseInit(); 13705 13706 this.helper = $( "<div>" ); 13707 this._addClass( this.helper, "ui-selectable-helper" ); 13708 }, 13709 13710 _destroy: function() { 13711 this.selectees.removeData( "selectable-item" ); 13712 this._mouseDestroy(); 13713 }, 13714 13715 _mouseStart: function( event ) { 13716 var that = this, 13717 options = this.options; 13718 13719 this.opos = [ event.pageX, event.pageY ]; 13720 this.elementPos = $( this.element[ 0 ] ).offset(); 13721 13722 if ( this.options.disabled ) { 13723 return; 13724 } 13725 13726 this.selectees = $( options.filter, this.element[ 0 ] ); 13727 13728 this._trigger( "start", event ); 13729 13730 $( options.appendTo ).append( this.helper ); 13731 13732 // position helper (lasso) 13733 this.helper.css( { 13734 "left": event.pageX, 13735 "top": event.pageY, 13736 "width": 0, 13737 "height": 0 13738 } ); 13739 13740 if ( options.autoRefresh ) { 13741 this.refresh(); 13742 } 13743 13744 this.selectees.filter( ".ui-selected" ).each( function() { 13745 var selectee = $.data( this, "selectable-item" ); 13746 selectee.startselected = true; 13747 if ( !event.metaKey && !event.ctrlKey ) { 13748 that._removeClass( selectee.$element, "ui-selected" ); 13749 selectee.selected = false; 13750 that._addClass( selectee.$element, "ui-unselecting" ); 13751 selectee.unselecting = true; 13752 13753 // selectable UNSELECTING callback 13754 that._trigger( "unselecting", event, { 13755 unselecting: selectee.element 13756 } ); 13757 } 13758 } ); 13759 13760 $( event.target ).parents().addBack().each( function() { 13761 var doSelect, 13762 selectee = $.data( this, "selectable-item" ); 13763 if ( selectee ) { 13764 doSelect = ( !event.metaKey && !event.ctrlKey ) || 13765 !selectee.$element.hasClass( "ui-selected" ); 13766 that._removeClass( selectee.$element, doSelect ? "ui-unselecting" : "ui-selected" ) 13767 ._addClass( selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting" ); 13768 selectee.unselecting = !doSelect; 13769 selectee.selecting = doSelect; 13770 selectee.selected = doSelect; 13771 13772 // selectable (UN)SELECTING callback 13773 if ( doSelect ) { 13774 that._trigger( "selecting", event, { 13775 selecting: selectee.element 13776 } ); 13777 } else { 13778 that._trigger( "unselecting", event, { 13779 unselecting: selectee.element 13780 } ); 13781 } 13782 return false; 13783 } 13784 } ); 13785 13786 }, 13787 13788 _mouseDrag: function( event ) { 13789 13790 this.dragged = true; 13791 13792 if ( this.options.disabled ) { 13793 return; 13794 } 13795 13796 var tmp, 13797 that = this, 13798 options = this.options, 13799 x1 = this.opos[ 0 ], 13800 y1 = this.opos[ 1 ], 13801 x2 = event.pageX, 13802 y2 = event.pageY; 13803 13804 if ( x1 > x2 ) { 13805 tmp = x2; x2 = x1; x1 = tmp; 13806 } 13807 if ( y1 > y2 ) { 13808 tmp = y2; y2 = y1; y1 = tmp; 13809 } 13810 this.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } ); 13811 13812 this.selectees.each( function() { 13813 var selectee = $.data( this, "selectable-item" ), 13814 hit = false, 13815 offset = {}; 13816 13817 //prevent helper from being selected if appendTo: selectable 13818 if ( !selectee || selectee.element === that.element[ 0 ] ) { 13819 return; 13820 } 13821 13822 offset.left = selectee.left + that.elementPos.left; 13823 offset.right = selectee.right + that.elementPos.left; 13824 offset.top = selectee.top + that.elementPos.top; 13825 offset.bottom = selectee.bottom + that.elementPos.top; 13826 13827 if ( options.tolerance === "touch" ) { 13828 hit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 || 13829 offset.bottom < y1 ) ); 13830 } else if ( options.tolerance === "fit" ) { 13831 hit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 && 13832 offset.bottom < y2 ); 13833 } 13834 13835 if ( hit ) { 13836 13837 // SELECT 13838 if ( selectee.selected ) { 13839 that._removeClass( selectee.$element, "ui-selected" ); 13840 selectee.selected = false; 13841 } 13842 if ( selectee.unselecting ) { 13843 that._removeClass( selectee.$element, "ui-unselecting" ); 13844 selectee.unselecting = false; 13845 } 13846 if ( !selectee.selecting ) { 13847 that._addClass( selectee.$element, "ui-selecting" ); 13848 selectee.selecting = true; 13849 13850 // selectable SELECTING callback 13851 that._trigger( "selecting", event, { 13852 selecting: selectee.element 13853 } ); 13854 } 13855 } else { 13856 13857 // UNSELECT 13858 if ( selectee.selecting ) { 13859 if ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) { 13860 that._removeClass( selectee.$element, "ui-selecting" ); 13861 selectee.selecting = false; 13862 that._addClass( selectee.$element, "ui-selected" ); 13863 selectee.selected = true; 13864 } else { 13865 that._removeClass( selectee.$element, "ui-selecting" ); 13866 selectee.selecting = false; 13867 if ( selectee.startselected ) { 13868 that._addClass( selectee.$element, "ui-unselecting" ); 13869 selectee.unselecting = true; 13870 } 13871 13872 // selectable UNSELECTING callback 13873 that._trigger( "unselecting", event, { 13874 unselecting: selectee.element 13875 } ); 13876 } 13877 } 13878 if ( selectee.selected ) { 13879 if ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) { 13880 that._removeClass( selectee.$element, "ui-selected" ); 13881 selectee.selected = false; 13882 13883 that._addClass( selectee.$element, "ui-unselecting" ); 13884 selectee.unselecting = true; 13885 13886 // selectable UNSELECTING callback 13887 that._trigger( "unselecting", event, { 13888 unselecting: selectee.element 13889 } ); 13890 } 13891 } 13892 } 13893 } ); 13894 13895 return false; 13896 }, 13897 13898 _mouseStop: function( event ) { 13899 var that = this; 13900 13901 this.dragged = false; 13902 13903 $( ".ui-unselecting", this.element[ 0 ] ).each( function() { 13904 var selectee = $.data( this, "selectable-item" ); 13905 that._removeClass( selectee.$element, "ui-unselecting" ); 13906 selectee.unselecting = false; 13907 selectee.startselected = false; 13908 that._trigger( "unselected", event, { 13909 unselected: selectee.element 13910 } ); 13911 } ); 13912 $( ".ui-selecting", this.element[ 0 ] ).each( function() { 13913 var selectee = $.data( this, "selectable-item" ); 13914 that._removeClass( selectee.$element, "ui-selecting" ) 13915 ._addClass( selectee.$element, "ui-selected" ); 13916 selectee.selecting = false; 13917 selectee.selected = true; 13918 selectee.startselected = true; 13919 that._trigger( "selected", event, { 13920 selected: selectee.element 13921 } ); 13922 } ); 13923 this._trigger( "stop", event ); 13924 13925 this.helper.remove(); 13926 13927 return false; 13928 } 13929 13930} ); 13931 13932 13933/*! 13934 * jQuery UI Selectmenu 1.14.1 13935 * https://jqueryui.com 13936 * 13937 * Copyright OpenJS Foundation and other contributors 13938 * Released under the MIT license. 13939 * https://jquery.org/license 13940 */ 13941 13942//>>label: Selectmenu 13943//>>group: Widgets 13944/* eslint-disable max-len */ 13945//>>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. 13946/* eslint-enable max-len */ 13947//>>docs: https://api.jqueryui.com/selectmenu/ 13948//>>demos: https://jqueryui.com/selectmenu/ 13949//>>css.structure: ../../themes/base/core.css 13950//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css 13951//>>css.theme: ../../themes/base/theme.css 13952 13953 13954var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, { 13955 version: "1.14.1", 13956 defaultElement: "<select>", 13957 options: { 13958 appendTo: null, 13959 classes: { 13960 "ui-selectmenu-button-open": "ui-corner-top", 13961 "ui-selectmenu-button-closed": "ui-corner-all" 13962 }, 13963 disabled: null, 13964 icons: { 13965 button: "ui-icon-triangle-1-s" 13966 }, 13967 position: { 13968 my: "left top", 13969 at: "left bottom", 13970 collision: "none" 13971 }, 13972 width: false, 13973 13974 // Callbacks 13975 change: null, 13976 close: null, 13977 focus: null, 13978 open: null, 13979 select: null 13980 }, 13981 13982 _create: function() { 13983 var selectmenuId = this.element.uniqueId().attr( "id" ); 13984 this.ids = { 13985 element: selectmenuId, 13986 button: selectmenuId + "-button", 13987 menu: selectmenuId + "-menu" 13988 }; 13989 13990 this._drawButton(); 13991 this._drawMenu(); 13992 this._bindFormResetHandler(); 13993 13994 this._rendered = false; 13995 this.menuItems = $(); 13996 }, 13997 13998 _drawButton: function() { 13999 var icon, 14000 that = this, 14001 item = this._parseOption( 14002 this.element.find( "option:selected" ), 14003 this.element[ 0 ].selectedIndex 14004 ); 14005 14006 // Associate existing label with the new button 14007 this.labels = this.element.labels().attr( "for", this.ids.button ); 14008 this._on( this.labels, { 14009 click: function( event ) { 14010 this.button.trigger( "focus" ); 14011 event.preventDefault(); 14012 } 14013 } ); 14014 14015 // Hide original select element 14016 this.element.hide(); 14017 14018 // Create button 14019 this.button = $( "<span>", { 14020 tabindex: this.options.disabled ? -1 : 0, 14021 id: this.ids.button, 14022 role: "combobox", 14023 "aria-expanded": "false", 14024 "aria-autocomplete": "list", 14025 "aria-owns": this.ids.menu, 14026 "aria-haspopup": "true", 14027 title: this.element.attr( "title" ) 14028 } ) 14029 .insertAfter( this.element ); 14030 14031 this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed", 14032 "ui-button ui-widget" ); 14033 14034 icon = $( "<span>" ).appendTo( this.button ); 14035 this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button ); 14036 this.buttonItem = this._renderButtonItem( item ) 14037 .appendTo( this.button ); 14038 14039 if ( this.options.width !== false ) { 14040 this._resizeButton(); 14041 } 14042 14043 this._on( this.button, this._buttonEvents ); 14044 this.button.one( "focusin", function() { 14045 14046 // Delay rendering the menu items until the button receives focus. 14047 // The menu may have already been rendered via a programmatic open. 14048 if ( !that._rendered ) { 14049 that._refreshMenu(); 14050 } 14051 } ); 14052 }, 14053 14054 _drawMenu: function() { 14055 var that = this; 14056 14057 // Create menu 14058 this.menu = $( "<ul>", { 14059 "aria-hidden": "true", 14060 "aria-labelledby": this.ids.button, 14061 id: this.ids.menu 14062 } ); 14063 14064 // Wrap menu 14065 this.menuWrap = $( "<div>" ).append( this.menu ); 14066 this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" ); 14067 this.menuWrap.appendTo( this._appendTo() ); 14068 14069 // Initialize menu widget 14070 this.menuInstance = this.menu 14071 .menu( { 14072 classes: { 14073 "ui-menu": "ui-corner-bottom" 14074 }, 14075 role: "listbox", 14076 select: function( event, ui ) { 14077 event.preventDefault(); 14078 that._select( ui.item.data( "ui-selectmenu-item" ), event ); 14079 }, 14080 focus: function( event, ui ) { 14081 var item = ui.item.data( "ui-selectmenu-item" ); 14082 14083 // Prevent inital focus from firing and check if its a newly focused item 14084 if ( that.focusIndex != null && item.index !== that.focusIndex ) { 14085 that._trigger( "focus", event, { item: item } ); 14086 if ( !that.isOpen ) { 14087 that._select( item, event ); 14088 } 14089 } 14090 that.focusIndex = item.index; 14091 14092 that.button.attr( "aria-activedescendant", 14093 that.menuItems.eq( item.index ).attr( "id" ) ); 14094 } 14095 } ) 14096 .menu( "instance" ); 14097 14098 // Don't close the menu on mouseleave 14099 this.menuInstance._off( this.menu, "mouseleave" ); 14100 14101 // Cancel the menu's collapseAll on document click 14102 this.menuInstance._closeOnDocumentClick = function() { 14103 return false; 14104 }; 14105 14106 // Selects often contain empty items, but never contain dividers 14107 this.menuInstance._isDivider = function() { 14108 return false; 14109 }; 14110 }, 14111 14112 refresh: function() { 14113 this._refreshMenu(); 14114 this.buttonItem.replaceWith( 14115 this.buttonItem = this._renderButtonItem( 14116 14117 // Fall back to an empty object in case there are no options 14118 this._getSelectedItem().data( "ui-selectmenu-item" ) || {} 14119 ) 14120 ); 14121 if ( this.options.width === null ) { 14122 this._resizeButton(); 14123 } 14124 }, 14125 14126 _refreshMenu: function() { 14127 var item, 14128 options = this.element.find( "option" ); 14129 14130 this.menu.empty(); 14131 14132 this._parseOptions( options ); 14133 this._renderMenu( this.menu, this.items ); 14134 14135 this.menuInstance.refresh(); 14136 this.menuItems = this.menu.find( "li" ) 14137 .not( ".ui-selectmenu-optgroup" ) 14138 .find( ".ui-menu-item-wrapper" ); 14139 14140 this._rendered = true; 14141 14142 if ( !options.length ) { 14143 return; 14144 } 14145 14146 item = this._getSelectedItem(); 14147 14148 // Update the menu to have the correct item focused 14149 this.menuInstance.focus( null, item ); 14150 this._setAria( item.data( "ui-selectmenu-item" ) ); 14151 14152 // Set disabled state 14153 this._setOption( "disabled", this.element.prop( "disabled" ) ); 14154 }, 14155 14156 open: function( event ) { 14157 if ( this.options.disabled ) { 14158 return; 14159 } 14160 14161 // If this is the first time the menu is being opened, render the items 14162 if ( !this._rendered ) { 14163 this._refreshMenu(); 14164 } else { 14165 14166 // Menu clears focus on close, reset focus to selected item 14167 this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" ); 14168 this.menuInstance.focus( null, this._getSelectedItem() ); 14169 } 14170 14171 // If there are no options, don't open the menu 14172 if ( !this.menuItems.length ) { 14173 return; 14174 } 14175 14176 this.isOpen = true; 14177 this._toggleAttr(); 14178 this._resizeMenu(); 14179 this._position(); 14180 14181 this._on( this.document, this._documentClick ); 14182 14183 this._trigger( "open", event ); 14184 }, 14185 14186 _position: function() { 14187 this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) ); 14188 }, 14189 14190 close: function( event ) { 14191 if ( !this.isOpen ) { 14192 return; 14193 } 14194 14195 this.isOpen = false; 14196 this._toggleAttr(); 14197 14198 this.range = null; 14199 this._off( this.document ); 14200 14201 this._trigger( "close", event ); 14202 }, 14203 14204 widget: function() { 14205 return this.button; 14206 }, 14207 14208 menuWidget: function() { 14209 return this.menu; 14210 }, 14211 14212 _renderButtonItem: function( item ) { 14213 var buttonItem = $( "<span>" ); 14214 14215 this._setText( buttonItem, item.label ); 14216 this._addClass( buttonItem, "ui-selectmenu-text" ); 14217 14218 return buttonItem; 14219 }, 14220 14221 _renderMenu: function( ul, items ) { 14222 var that = this, 14223 currentOptgroup = ""; 14224 14225 $.each( items, function( index, item ) { 14226 var li; 14227 14228 if ( item.optgroup !== currentOptgroup ) { 14229 li = $( "<li>", { 14230 text: item.optgroup 14231 } ); 14232 that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" + 14233 ( item.element.parent( "optgroup" ).prop( "disabled" ) ? 14234 " ui-state-disabled" : 14235 "" ) ); 14236 14237 li.appendTo( ul ); 14238 14239 currentOptgroup = item.optgroup; 14240 } 14241 14242 that._renderItemData( ul, item ); 14243 } ); 14244 }, 14245 14246 _renderItemData: function( ul, item ) { 14247 return this._renderItem( ul, item ).data( "ui-selectmenu-item", item ); 14248 }, 14249 14250 _renderItem: function( ul, item ) { 14251 var li = $( "<li>" ), 14252 wrapper = $( "<div>", { 14253 title: item.element.attr( "title" ) 14254 } ); 14255 14256 if ( item.disabled ) { 14257 this._addClass( li, null, "ui-state-disabled" ); 14258 } 14259 14260 if ( item.hidden ) { 14261 li.prop( "hidden", true ); 14262 } else { 14263 this._setText( wrapper, item.label ); 14264 } 14265 14266 return li.append( wrapper ).appendTo( ul ); 14267 }, 14268 14269 _setText: function( element, value ) { 14270 if ( value ) { 14271 element.text( value ); 14272 } else { 14273 element.html( " " ); 14274 } 14275 }, 14276 14277 _move: function( direction, event ) { 14278 var item, next, 14279 filter = ".ui-menu-item"; 14280 14281 if ( this.isOpen ) { 14282 item = this.menuItems.eq( this.focusIndex ).parent( "li" ); 14283 } else { 14284 item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" ); 14285 filter += ":not(.ui-state-disabled)"; 14286 } 14287 14288 if ( direction === "first" || direction === "last" ) { 14289 next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 ); 14290 } else { 14291 next = item[ direction + "All" ]( filter ).eq( 0 ); 14292 } 14293 14294 if ( next.length ) { 14295 this.menuInstance.focus( event, next ); 14296 } 14297 }, 14298 14299 _getSelectedItem: function() { 14300 return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" ); 14301 }, 14302 14303 _toggle: function( event ) { 14304 this[ this.isOpen ? "close" : "open" ]( event ); 14305 }, 14306 14307 _setSelection: function() { 14308 var selection; 14309 14310 if ( !this.range ) { 14311 return; 14312 } 14313 14314 selection = window.getSelection(); 14315 selection.removeAllRanges(); 14316 selection.addRange( this.range ); 14317 }, 14318 14319 _documentClick: { 14320 mousedown: function( event ) { 14321 if ( !this.isOpen ) { 14322 return; 14323 } 14324 14325 if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" + 14326 CSS.escape( this.ids.button ) ).length ) { 14327 this.close( event ); 14328 } 14329 } 14330 }, 14331 14332 _buttonEvents: { 14333 14334 // Prevent text selection from being reset when interacting with the selectmenu (#10144) 14335 mousedown: function() { 14336 var selection = window.getSelection(); 14337 if ( selection.rangeCount ) { 14338 this.range = selection.getRangeAt( 0 ); 14339 } 14340 }, 14341 14342 click: function( event ) { 14343 this._setSelection(); 14344 this._toggle( event ); 14345 }, 14346 14347 keydown: function( event ) { 14348 var preventDefault = true; 14349 switch ( event.keyCode ) { 14350 case $.ui.keyCode.TAB: 14351 case $.ui.keyCode.ESCAPE: 14352 this.close( event ); 14353 preventDefault = false; 14354 break; 14355 case $.ui.keyCode.ENTER: 14356 if ( this.isOpen ) { 14357 this._selectFocusedItem( event ); 14358 } 14359 break; 14360 case $.ui.keyCode.UP: 14361 if ( event.altKey ) { 14362 this._toggle( event ); 14363 } else { 14364 this._move( "prev", event ); 14365 } 14366 break; 14367 case $.ui.keyCode.DOWN: 14368 if ( event.altKey ) { 14369 this._toggle( event ); 14370 } else { 14371 this._move( "next", event ); 14372 } 14373 break; 14374 case $.ui.keyCode.SPACE: 14375 if ( this.isOpen ) { 14376 this._selectFocusedItem( event ); 14377 } else { 14378 this._toggle( event ); 14379 } 14380 break; 14381 case $.ui.keyCode.LEFT: 14382 this._move( "prev", event ); 14383 break; 14384 case $.ui.keyCode.RIGHT: 14385 this._move( "next", event ); 14386 break; 14387 case $.ui.keyCode.HOME: 14388 case $.ui.keyCode.PAGE_UP: 14389 this._move( "first", event ); 14390 break; 14391 case $.ui.keyCode.END: 14392 case $.ui.keyCode.PAGE_DOWN: 14393 this._move( "last", event ); 14394 break; 14395 default: 14396 this.menu.trigger( event ); 14397 preventDefault = false; 14398 } 14399 14400 if ( preventDefault ) { 14401 event.preventDefault(); 14402 } 14403 } 14404 }, 14405 14406 _selectFocusedItem: function( event ) { 14407 var item = this.menuItems.eq( this.focusIndex ).parent( "li" ); 14408 if ( !item.hasClass( "ui-state-disabled" ) ) { 14409 this._select( item.data( "ui-selectmenu-item" ), event ); 14410 } 14411 }, 14412 14413 _select: function( item, event ) { 14414 var oldIndex = this.element[ 0 ].selectedIndex; 14415 14416 // Change native select element 14417 this.element[ 0 ].selectedIndex = item.index; 14418 this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) ); 14419 this._setAria( item ); 14420 this._trigger( "select", event, { item: item } ); 14421 14422 if ( item.index !== oldIndex ) { 14423 this._trigger( "change", event, { item: item } ); 14424 } 14425 14426 this.close( event ); 14427 }, 14428 14429 _setAria: function( item ) { 14430 var id = this.menuItems.eq( item.index ).attr( "id" ); 14431 14432 this.button.attr( { 14433 "aria-labelledby": id, 14434 "aria-activedescendant": id 14435 } ); 14436 this.menu.attr( "aria-activedescendant", id ); 14437 }, 14438 14439 _setOption: function( key, value ) { 14440 if ( key === "icons" ) { 14441 var icon = this.button.find( "span.ui-icon" ); 14442 this._removeClass( icon, null, this.options.icons.button ) 14443 ._addClass( icon, null, value.button ); 14444 } 14445 14446 this._super( key, value ); 14447 14448 if ( key === "appendTo" ) { 14449 this.menuWrap.appendTo( this._appendTo() ); 14450 } 14451 14452 if ( key === "width" ) { 14453 this._resizeButton(); 14454 } 14455 }, 14456 14457 _setOptionDisabled: function( value ) { 14458 this._super( value ); 14459 14460 this.menuInstance.option( "disabled", value ); 14461 this.button.attr( "aria-disabled", value ); 14462 this._toggleClass( this.button, null, "ui-state-disabled", value ); 14463 14464 this.element.prop( "disabled", value ); 14465 if ( value ) { 14466 this.button.attr( "tabindex", -1 ); 14467 this.close(); 14468 } else { 14469 this.button.attr( "tabindex", 0 ); 14470 } 14471 }, 14472 14473 _appendTo: function() { 14474 var element = this.options.appendTo; 14475 14476 if ( element ) { 14477 element = element.jquery || element.nodeType ? 14478 $( element ) : 14479 this.document.find( element ).eq( 0 ); 14480 } 14481 14482 if ( !element || !element[ 0 ] ) { 14483 element = this.element.closest( ".ui-front, dialog" ); 14484 } 14485 14486 if ( !element.length ) { 14487 element = this.document[ 0 ].body; 14488 } 14489 14490 return element; 14491 }, 14492 14493 _toggleAttr: function() { 14494 this.button.attr( "aria-expanded", this.isOpen ); 14495 14496 // We can't use two _toggleClass() calls here, because we need to make sure 14497 // we always remove classes first and add them second, otherwise if both classes have the 14498 // same theme class, it will be removed after we add it. 14499 this._removeClass( this.button, "ui-selectmenu-button-" + 14500 ( this.isOpen ? "closed" : "open" ) ) 14501 ._addClass( this.button, "ui-selectmenu-button-" + 14502 ( this.isOpen ? "open" : "closed" ) ) 14503 ._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen ); 14504 14505 this.menu.attr( "aria-hidden", !this.isOpen ); 14506 }, 14507 14508 _resizeButton: function() { 14509 var width = this.options.width; 14510 14511 // For `width: false`, just remove inline style and stop 14512 if ( width === false ) { 14513 this.button.css( "width", "" ); 14514 return; 14515 } 14516 14517 // For `width: null`, match the width of the original element 14518 if ( width === null ) { 14519 width = this.element.show().outerWidth(); 14520 this.element.hide(); 14521 } 14522 14523 this.button.outerWidth( width ); 14524 }, 14525 14526 _resizeMenu: function() { 14527 this.menu.outerWidth( Math.max( 14528 this.button.outerWidth(), 14529 this.menu.width( "" ).outerWidth() 14530 ) ); 14531 }, 14532 14533 _getCreateOptions: function() { 14534 var options = this._super(); 14535 14536 options.disabled = this.element.prop( "disabled" ); 14537 14538 return options; 14539 }, 14540 14541 _parseOptions: function( options ) { 14542 var that = this, 14543 data = []; 14544 options.each( function( index, item ) { 14545 data.push( that._parseOption( $( item ), index ) ); 14546 } ); 14547 this.items = data; 14548 }, 14549 14550 _parseOption: function( option, index ) { 14551 var optgroup = option.parent( "optgroup" ); 14552 14553 return { 14554 element: option, 14555 index: index, 14556 value: option.val(), 14557 label: option.text(), 14558 hidden: optgroup.prop( "hidden" ) || option.prop( "hidden" ), 14559 optgroup: optgroup.attr( "label" ) || "", 14560 disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" ) 14561 }; 14562 }, 14563 14564 _destroy: function() { 14565 this._unbindFormResetHandler(); 14566 this.menuWrap.remove(); 14567 this.button.remove(); 14568 this.element.show(); 14569 this.element.removeUniqueId(); 14570 this.labels.attr( "for", this.ids.element ); 14571 } 14572} ] ); 14573 14574 14575/*! 14576 * jQuery UI Slider 1.14.1 14577 * https://jqueryui.com 14578 * 14579 * Copyright OpenJS Foundation and other contributors 14580 * Released under the MIT license. 14581 * https://jquery.org/license 14582 */ 14583 14584//>>label: Slider 14585//>>group: Widgets 14586//>>description: Displays a flexible slider with ranges and accessibility via keyboard. 14587//>>docs: https://api.jqueryui.com/slider/ 14588//>>demos: https://jqueryui.com/slider/ 14589//>>css.structure: ../../themes/base/core.css 14590//>>css.structure: ../../themes/base/slider.css 14591//>>css.theme: ../../themes/base/theme.css 14592 14593 14594var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, { 14595 version: "1.14.1", 14596 widgetEventPrefix: "slide", 14597 14598 options: { 14599 animate: false, 14600 classes: { 14601 "ui-slider": "ui-corner-all", 14602 "ui-slider-handle": "ui-corner-all", 14603 14604 // Note: ui-widget-header isn't the most fittingly semantic framework class for this 14605 // element, but worked best visually with a variety of themes 14606 "ui-slider-range": "ui-corner-all ui-widget-header" 14607 }, 14608 distance: 0, 14609 max: 100, 14610 min: 0, 14611 orientation: "horizontal", 14612 range: false, 14613 step: 1, 14614 value: 0, 14615 values: null, 14616 14617 // Callbacks 14618 change: null, 14619 slide: null, 14620 start: null, 14621 stop: null 14622 }, 14623 14624 // Number of pages in a slider 14625 // (how many times can you page up/down to go through the whole range) 14626 numPages: 5, 14627 14628 _create: function() { 14629 this._keySliding = false; 14630 this._mouseSliding = false; 14631 this._animateOff = true; 14632 this._handleIndex = null; 14633 this._detectOrientation(); 14634 this._mouseInit(); 14635 this._calculateNewMax(); 14636 14637 this._addClass( "ui-slider ui-slider-" + this.orientation, 14638 "ui-widget ui-widget-content" ); 14639 14640 this._refresh(); 14641 14642 this._animateOff = false; 14643 }, 14644 14645 _refresh: function() { 14646 this._createRange(); 14647 this._createHandles(); 14648 this._setupEvents(); 14649 this._refreshValue(); 14650 }, 14651 14652 _createHandles: function() { 14653 var i, handleCount, 14654 options = this.options, 14655 existingHandles = this.element.find( ".ui-slider-handle" ), 14656 handle = "<span tabindex='0'></span>", 14657 handles = []; 14658 14659 handleCount = ( options.values && options.values.length ) || 1; 14660 14661 if ( existingHandles.length > handleCount ) { 14662 existingHandles.slice( handleCount ).remove(); 14663 existingHandles = existingHandles.slice( 0, handleCount ); 14664 } 14665 14666 for ( i = existingHandles.length; i < handleCount; i++ ) { 14667 handles.push( handle ); 14668 } 14669 14670 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) ); 14671 14672 this._addClass( this.handles, "ui-slider-handle", "ui-state-default" ); 14673 14674 this.handle = this.handles.eq( 0 ); 14675 14676 this.handles.each( function( i ) { 14677 $( this ) 14678 .data( "ui-slider-handle-index", i ) 14679 .attr( "tabIndex", 0 ); 14680 } ); 14681 }, 14682 14683 _createRange: function() { 14684 var options = this.options; 14685 14686 if ( options.range ) { 14687 if ( options.range === true ) { 14688 if ( !options.values ) { 14689 options.values = [ this._valueMin(), this._valueMin() ]; 14690 } else if ( options.values.length && options.values.length !== 2 ) { 14691 options.values = [ options.values[ 0 ], options.values[ 0 ] ]; 14692 } else if ( Array.isArray( options.values ) ) { 14693 options.values = options.values.slice( 0 ); 14694 } 14695 } 14696 14697 if ( !this.range || !this.range.length ) { 14698 this.range = $( "<div>" ) 14699 .appendTo( this.element ); 14700 14701 this._addClass( this.range, "ui-slider-range" ); 14702 } else { 14703 this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" ); 14704 14705 // Handle range switching from true to min/max 14706 this.range.css( { 14707 "left": "", 14708 "bottom": "" 14709 } ); 14710 } 14711 if ( options.range === "min" || options.range === "max" ) { 14712 this._addClass( this.range, "ui-slider-range-" + options.range ); 14713 } 14714 } else { 14715 if ( this.range ) { 14716 this.range.remove(); 14717 } 14718 this.range = null; 14719 } 14720 }, 14721 14722 _setupEvents: function() { 14723 this._off( this.handles ); 14724 this._on( this.handles, this._handleEvents ); 14725 this._hoverable( this.handles ); 14726 this._focusable( this.handles ); 14727 }, 14728 14729 _destroy: function() { 14730 this.handles.remove(); 14731 if ( this.range ) { 14732 this.range.remove(); 14733 } 14734 14735 this._mouseDestroy(); 14736 }, 14737 14738 _mouseCapture: function( event ) { 14739 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, 14740 that = this, 14741 o = this.options; 14742 14743 if ( o.disabled ) { 14744 return false; 14745 } 14746 14747 this.elementSize = { 14748 width: this.element.outerWidth(), 14749 height: this.element.outerHeight() 14750 }; 14751 this.elementOffset = this.element.offset(); 14752 14753 position = { x: event.pageX, y: event.pageY }; 14754 normValue = this._normValueFromMouse( position ); 14755 distance = this._valueMax() - this._valueMin() + 1; 14756 this.handles.each( function( i ) { 14757 var thisDistance = Math.abs( normValue - that.values( i ) ); 14758 if ( ( distance > thisDistance ) || 14759 ( distance === thisDistance && 14760 ( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) { 14761 distance = thisDistance; 14762 closestHandle = $( this ); 14763 index = i; 14764 } 14765 } ); 14766 14767 allowed = this._start( event, index ); 14768 if ( allowed === false ) { 14769 return false; 14770 } 14771 this._mouseSliding = true; 14772 14773 this._handleIndex = index; 14774 14775 this._addClass( closestHandle, null, "ui-state-active" ); 14776 closestHandle.trigger( "focus" ); 14777 14778 offset = closestHandle.offset(); 14779 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" ); 14780 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { 14781 left: event.pageX - offset.left - ( closestHandle.width() / 2 ), 14782 top: event.pageY - offset.top - 14783 ( closestHandle.height() / 2 ) - 14784 ( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) - 14785 ( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) + 14786 ( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 ) 14787 }; 14788 14789 if ( !this.handles.hasClass( "ui-state-hover" ) ) { 14790 this._slide( event, index, normValue ); 14791 } 14792 this._animateOff = true; 14793 return true; 14794 }, 14795 14796 _mouseStart: function() { 14797 return true; 14798 }, 14799 14800 _mouseDrag: function( event ) { 14801 var position = { x: event.pageX, y: event.pageY }, 14802 normValue = this._normValueFromMouse( position ); 14803 14804 this._slide( event, this._handleIndex, normValue ); 14805 14806 return false; 14807 }, 14808 14809 _mouseStop: function( event ) { 14810 this._removeClass( this.handles, null, "ui-state-active" ); 14811 this._mouseSliding = false; 14812 14813 this._stop( event, this._handleIndex ); 14814 this._change( event, this._handleIndex ); 14815 14816 this._handleIndex = null; 14817 this._clickOffset = null; 14818 this._animateOff = false; 14819 14820 return false; 14821 }, 14822 14823 _detectOrientation: function() { 14824 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; 14825 }, 14826 14827 _normValueFromMouse: function( position ) { 14828 var pixelTotal, 14829 pixelMouse, 14830 percentMouse, 14831 valueTotal, 14832 valueMouse; 14833 14834 if ( this.orientation === "horizontal" ) { 14835 pixelTotal = this.elementSize.width; 14836 pixelMouse = position.x - this.elementOffset.left - 14837 ( this._clickOffset ? this._clickOffset.left : 0 ); 14838 } else { 14839 pixelTotal = this.elementSize.height; 14840 pixelMouse = position.y - this.elementOffset.top - 14841 ( this._clickOffset ? this._clickOffset.top : 0 ); 14842 } 14843 14844 percentMouse = ( pixelMouse / pixelTotal ); 14845 if ( percentMouse > 1 ) { 14846 percentMouse = 1; 14847 } 14848 if ( percentMouse < 0 ) { 14849 percentMouse = 0; 14850 } 14851 if ( this.orientation === "vertical" ) { 14852 percentMouse = 1 - percentMouse; 14853 } 14854 14855 valueTotal = this._valueMax() - this._valueMin(); 14856 valueMouse = this._valueMin() + percentMouse * valueTotal; 14857 14858 return this._trimAlignValue( valueMouse ); 14859 }, 14860 14861 _uiHash: function( index, value, values ) { 14862 var uiHash = { 14863 handle: this.handles[ index ], 14864 handleIndex: index, 14865 value: value !== undefined ? value : this.value() 14866 }; 14867 14868 if ( this._hasMultipleValues() ) { 14869 uiHash.value = value !== undefined ? value : this.values( index ); 14870 uiHash.values = values || this.values(); 14871 } 14872 14873 return uiHash; 14874 }, 14875 14876 _hasMultipleValues: function() { 14877 return this.options.values && this.options.values.length; 14878 }, 14879 14880 _start: function( event, index ) { 14881 return this._trigger( "start", event, this._uiHash( index ) ); 14882 }, 14883 14884 _slide: function( event, index, newVal ) { 14885 var allowed, otherVal, 14886 currentValue = this.value(), 14887 newValues = this.values(); 14888 14889 if ( this._hasMultipleValues() ) { 14890 otherVal = this.values( index ? 0 : 1 ); 14891 currentValue = this.values( index ); 14892 14893 if ( this.options.values.length === 2 && this.options.range === true ) { 14894 newVal = index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal ); 14895 } 14896 14897 newValues[ index ] = newVal; 14898 } 14899 14900 if ( newVal === currentValue ) { 14901 return; 14902 } 14903 14904 allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) ); 14905 14906 // A slide can be canceled by returning false from the slide callback 14907 if ( allowed === false ) { 14908 return; 14909 } 14910 14911 if ( this._hasMultipleValues() ) { 14912 this.values( index, newVal ); 14913 } else { 14914 this.value( newVal ); 14915 } 14916 }, 14917 14918 _stop: function( event, index ) { 14919 this._trigger( "stop", event, this._uiHash( index ) ); 14920 }, 14921 14922 _change: function( event, index ) { 14923 if ( !this._keySliding && !this._mouseSliding ) { 14924 14925 //store the last changed value index for reference when handles overlap 14926 this._lastChangedValue = index; 14927 this._trigger( "change", event, this._uiHash( index ) ); 14928 } 14929 }, 14930 14931 value: function( newValue ) { 14932 if ( arguments.length ) { 14933 this.options.value = this._trimAlignValue( newValue ); 14934 this._refreshValue(); 14935 this._change( null, 0 ); 14936 return; 14937 } 14938 14939 return this._value(); 14940 }, 14941 14942 values: function( index, newValue ) { 14943 var vals, 14944 newValues, 14945 i; 14946 14947 if ( arguments.length > 1 ) { 14948 this.options.values[ index ] = this._trimAlignValue( newValue ); 14949 this._refreshValue(); 14950 this._change( null, index ); 14951 return; 14952 } 14953 14954 if ( arguments.length ) { 14955 if ( Array.isArray( arguments[ 0 ] ) ) { 14956 vals = this.options.values; 14957 newValues = arguments[ 0 ]; 14958 for ( i = 0; i < vals.length; i += 1 ) { 14959 vals[ i ] = this._trimAlignValue( newValues[ i ] ); 14960 this._change( null, i ); 14961 } 14962 this._refreshValue(); 14963 } else { 14964 if ( this._hasMultipleValues() ) { 14965 return this._values( index ); 14966 } else { 14967 return this.value(); 14968 } 14969 } 14970 } else { 14971 return this._values(); 14972 } 14973 }, 14974 14975 _setOption: function( key, value ) { 14976 var i, 14977 valsLength = 0; 14978 14979 if ( key === "range" && this.options.range === true ) { 14980 if ( value === "min" ) { 14981 this.options.value = this._values( 0 ); 14982 this.options.values = null; 14983 } else if ( value === "max" ) { 14984 this.options.value = this._values( this.options.values.length - 1 ); 14985 this.options.values = null; 14986 } 14987 } 14988 14989 if ( Array.isArray( this.options.values ) ) { 14990 valsLength = this.options.values.length; 14991 } 14992 14993 this._super( key, value ); 14994 14995 switch ( key ) { 14996 case "orientation": 14997 this._detectOrientation(); 14998 this._removeClass( "ui-slider-horizontal ui-slider-vertical" ) 14999 ._addClass( "ui-slider-" + this.orientation ); 15000 this._refreshValue(); 15001 if ( this.options.range ) { 15002 this._refreshRange( value ); 15003 } 15004 15005 // Reset positioning from previous orientation 15006 this.handles.css( value === "horizontal" ? "bottom" : "left", "" ); 15007 break; 15008 case "value": 15009 this._animateOff = true; 15010 this._refreshValue(); 15011 this._change( null, 0 ); 15012 this._animateOff = false; 15013 break; 15014 case "values": 15015 this._animateOff = true; 15016 this._refreshValue(); 15017 15018 // Start from the last handle to prevent unreachable handles (#9046) 15019 for ( i = valsLength - 1; i >= 0; i-- ) { 15020 this._change( null, i ); 15021 } 15022 this._animateOff = false; 15023 break; 15024 case "step": 15025 case "min": 15026 case "max": 15027 this._animateOff = true; 15028 this._calculateNewMax(); 15029 this._refreshValue(); 15030 this._animateOff = false; 15031 break; 15032 case "range": 15033 this._animateOff = true; 15034 this._refresh(); 15035 this._animateOff = false; 15036 break; 15037 } 15038 }, 15039 15040 _setOptionDisabled: function( value ) { 15041 this._super( value ); 15042 15043 this._toggleClass( null, "ui-state-disabled", !!value ); 15044 }, 15045 15046 //internal value getter 15047 // _value() returns value trimmed by min and max, aligned by step 15048 _value: function() { 15049 var val = this.options.value; 15050 val = this._trimAlignValue( val ); 15051 15052 return val; 15053 }, 15054 15055 //internal values getter 15056 // _values() returns array of values trimmed by min and max, aligned by step 15057 // _values( index ) returns single value trimmed by min and max, aligned by step 15058 _values: function( index ) { 15059 var val, 15060 vals, 15061 i; 15062 15063 if ( arguments.length ) { 15064 val = this.options.values[ index ]; 15065 val = this._trimAlignValue( val ); 15066 15067 return val; 15068 } else if ( this._hasMultipleValues() ) { 15069 15070 // .slice() creates a copy of the array 15071 // this copy gets trimmed by min and max and then returned 15072 vals = this.options.values.slice(); 15073 for ( i = 0; i < vals.length; i += 1 ) { 15074 vals[ i ] = this._trimAlignValue( vals[ i ] ); 15075 } 15076 15077 return vals; 15078 } else { 15079 return []; 15080 } 15081 }, 15082 15083 // Returns the step-aligned value that val is closest to, between (inclusive) min and max 15084 _trimAlignValue: function( val ) { 15085 if ( val <= this._valueMin() ) { 15086 return this._valueMin(); 15087 } 15088 if ( val >= this._valueMax() ) { 15089 return this._valueMax(); 15090 } 15091 var step = ( this.options.step > 0 ) ? this.options.step : 1, 15092 valModStep = ( val - this._valueMin() ) % step, 15093 alignValue = val - valModStep; 15094 15095 if ( Math.abs( valModStep ) * 2 >= step ) { 15096 alignValue += ( valModStep > 0 ) ? step : ( -step ); 15097 } 15098 15099 // Since JavaScript has problems with large floats, round 15100 // the final value to 5 digits after the decimal point (see #4124) 15101 return parseFloat( alignValue.toFixed( 5 ) ); 15102 }, 15103 15104 _calculateNewMax: function() { 15105 var max = this.options.max, 15106 min = this._valueMin(), 15107 step = this.options.step, 15108 aboveMin = Math.round( ( max - min ) / step ) * step; 15109 max = aboveMin + min; 15110 if ( max > this.options.max ) { 15111 15112 //If max is not divisible by step, rounding off may increase its value 15113 max -= step; 15114 } 15115 this.max = parseFloat( max.toFixed( this._precision() ) ); 15116 }, 15117 15118 _precision: function() { 15119 var precision = this._precisionOf( this.options.step ); 15120 if ( this.options.min !== null ) { 15121 precision = Math.max( precision, this._precisionOf( this.options.min ) ); 15122 } 15123 return precision; 15124 }, 15125 15126 _precisionOf: function( num ) { 15127 var str = num.toString(), 15128 decimal = str.indexOf( "." ); 15129 return decimal === -1 ? 0 : str.length - decimal - 1; 15130 }, 15131 15132 _valueMin: function() { 15133 return this.options.min; 15134 }, 15135 15136 _valueMax: function() { 15137 return this.max; 15138 }, 15139 15140 _refreshRange: function( orientation ) { 15141 if ( orientation === "vertical" ) { 15142 this.range.css( { "width": "", "left": "" } ); 15143 } 15144 if ( orientation === "horizontal" ) { 15145 this.range.css( { "height": "", "bottom": "" } ); 15146 } 15147 }, 15148 15149 _refreshValue: function() { 15150 var lastValPercent, valPercent, value, valueMin, valueMax, 15151 oRange = this.options.range, 15152 o = this.options, 15153 that = this, 15154 animate = ( !this._animateOff ) ? o.animate : false, 15155 _set = {}; 15156 15157 if ( this._hasMultipleValues() ) { 15158 this.handles.each( function( i ) { 15159 valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() - 15160 that._valueMin() ) * 100; 15161 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 15162 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 15163 if ( that.options.range === true ) { 15164 if ( that.orientation === "horizontal" ) { 15165 if ( i === 0 ) { 15166 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 15167 left: valPercent + "%" 15168 }, o.animate ); 15169 } 15170 if ( i === 1 ) { 15171 that.range[ animate ? "animate" : "css" ]( { 15172 width: ( valPercent - lastValPercent ) + "%" 15173 }, { 15174 queue: false, 15175 duration: o.animate 15176 } ); 15177 } 15178 } else { 15179 if ( i === 0 ) { 15180 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 15181 bottom: ( valPercent ) + "%" 15182 }, o.animate ); 15183 } 15184 if ( i === 1 ) { 15185 that.range[ animate ? "animate" : "css" ]( { 15186 height: ( valPercent - lastValPercent ) + "%" 15187 }, { 15188 queue: false, 15189 duration: o.animate 15190 } ); 15191 } 15192 } 15193 } 15194 lastValPercent = valPercent; 15195 } ); 15196 } else { 15197 value = this.value(); 15198 valueMin = this._valueMin(); 15199 valueMax = this._valueMax(); 15200 valPercent = ( valueMax !== valueMin ) ? 15201 ( value - valueMin ) / ( valueMax - valueMin ) * 100 : 15202 0; 15203 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 15204 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 15205 15206 if ( oRange === "min" && this.orientation === "horizontal" ) { 15207 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 15208 width: valPercent + "%" 15209 }, o.animate ); 15210 } 15211 if ( oRange === "max" && this.orientation === "horizontal" ) { 15212 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 15213 width: ( 100 - valPercent ) + "%" 15214 }, o.animate ); 15215 } 15216 if ( oRange === "min" && this.orientation === "vertical" ) { 15217 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 15218 height: valPercent + "%" 15219 }, o.animate ); 15220 } 15221 if ( oRange === "max" && this.orientation === "vertical" ) { 15222 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 15223 height: ( 100 - valPercent ) + "%" 15224 }, o.animate ); 15225 } 15226 } 15227 }, 15228 15229 _handleEvents: { 15230 keydown: function( event ) { 15231 var allowed, curVal, newVal, step, 15232 index = $( event.target ).data( "ui-slider-handle-index" ); 15233 15234 switch ( event.keyCode ) { 15235 case $.ui.keyCode.HOME: 15236 case $.ui.keyCode.END: 15237 case $.ui.keyCode.PAGE_UP: 15238 case $.ui.keyCode.PAGE_DOWN: 15239 case $.ui.keyCode.UP: 15240 case $.ui.keyCode.RIGHT: 15241 case $.ui.keyCode.DOWN: 15242 case $.ui.keyCode.LEFT: 15243 event.preventDefault(); 15244 if ( !this._keySliding ) { 15245 this._keySliding = true; 15246 this._addClass( $( event.target ), null, "ui-state-active" ); 15247 allowed = this._start( event, index ); 15248 if ( allowed === false ) { 15249 return; 15250 } 15251 } 15252 break; 15253 } 15254 15255 step = this.options.step; 15256 if ( this._hasMultipleValues() ) { 15257 curVal = newVal = this.values( index ); 15258 } else { 15259 curVal = newVal = this.value(); 15260 } 15261 15262 switch ( event.keyCode ) { 15263 case $.ui.keyCode.HOME: 15264 newVal = this._valueMin(); 15265 break; 15266 case $.ui.keyCode.END: 15267 newVal = this._valueMax(); 15268 break; 15269 case $.ui.keyCode.PAGE_UP: 15270 newVal = this._trimAlignValue( 15271 curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages ) 15272 ); 15273 break; 15274 case $.ui.keyCode.PAGE_DOWN: 15275 newVal = this._trimAlignValue( 15276 curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) ); 15277 break; 15278 case $.ui.keyCode.UP: 15279 case $.ui.keyCode.RIGHT: 15280 if ( curVal === this._valueMax() ) { 15281 return; 15282 } 15283 newVal = this._trimAlignValue( curVal + step ); 15284 break; 15285 case $.ui.keyCode.DOWN: 15286 case $.ui.keyCode.LEFT: 15287 if ( curVal === this._valueMin() ) { 15288 return; 15289 } 15290 newVal = this._trimAlignValue( curVal - step ); 15291 break; 15292 } 15293 15294 this._slide( event, index, newVal ); 15295 }, 15296 keyup: function( event ) { 15297 var index = $( event.target ).data( "ui-slider-handle-index" ); 15298 15299 if ( this._keySliding ) { 15300 this._keySliding = false; 15301 this._stop( event, index ); 15302 this._change( event, index ); 15303 this._removeClass( $( event.target ), null, "ui-state-active" ); 15304 } 15305 } 15306 } 15307} ); 15308 15309 15310/*! 15311 * jQuery UI Sortable 1.14.1 15312 * https://jqueryui.com 15313 * 15314 * Copyright OpenJS Foundation and other contributors 15315 * Released under the MIT license. 15316 * https://jquery.org/license 15317 */ 15318 15319//>>label: Sortable 15320//>>group: Interactions 15321//>>description: Enables items in a list to be sorted using the mouse. 15322//>>docs: https://api.jqueryui.com/sortable/ 15323//>>demos: https://jqueryui.com/sortable/ 15324//>>css.structure: ../../themes/base/sortable.css 15325 15326 15327var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, { 15328 version: "1.14.1", 15329 widgetEventPrefix: "sort", 15330 ready: false, 15331 options: { 15332 appendTo: "parent", 15333 axis: false, 15334 connectWith: false, 15335 containment: false, 15336 cursor: "auto", 15337 cursorAt: false, 15338 dropOnEmpty: true, 15339 forcePlaceholderSize: false, 15340 forceHelperSize: false, 15341 grid: false, 15342 handle: false, 15343 helper: "original", 15344 items: "> *", 15345 opacity: false, 15346 placeholder: false, 15347 revert: false, 15348 scroll: true, 15349 scrollSensitivity: 20, 15350 scrollSpeed: 20, 15351 scope: "default", 15352 tolerance: "intersect", 15353 zIndex: 1000, 15354 15355 // Callbacks 15356 activate: null, 15357 beforeStop: null, 15358 change: null, 15359 deactivate: null, 15360 out: null, 15361 over: null, 15362 receive: null, 15363 remove: null, 15364 sort: null, 15365 start: null, 15366 stop: null, 15367 update: null 15368 }, 15369 15370 _isOverAxis: function( x, reference, size ) { 15371 return ( x >= reference ) && ( x < ( reference + size ) ); 15372 }, 15373 15374 _isFloating: function( item ) { 15375 return ( /left|right/ ).test( item.css( "float" ) ) || 15376 ( /inline|table-cell/ ).test( item.css( "display" ) ); 15377 }, 15378 15379 _create: function() { 15380 this.containerCache = {}; 15381 this._addClass( "ui-sortable" ); 15382 15383 //Get the items 15384 this.refresh(); 15385 15386 //Let's determine the parent's offset 15387 this.offset = this.element.offset(); 15388 15389 //Initialize mouse events for interaction 15390 this._mouseInit(); 15391 15392 this._setHandleClassName(); 15393 15394 //We're ready to go 15395 this.ready = true; 15396 15397 }, 15398 15399 _setOption: function( key, value ) { 15400 this._super( key, value ); 15401 15402 if ( key === "handle" ) { 15403 this._setHandleClassName(); 15404 } 15405 }, 15406 15407 _setHandleClassName: function() { 15408 var that = this; 15409 this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" ); 15410 $.each( this.items, function() { 15411 that._addClass( 15412 this.instance.options.handle ? 15413 this.item.find( this.instance.options.handle ) : 15414 this.item, 15415 "ui-sortable-handle" 15416 ); 15417 } ); 15418 }, 15419 15420 _destroy: function() { 15421 this._mouseDestroy(); 15422 15423 for ( var i = this.items.length - 1; i >= 0; i-- ) { 15424 this.items[ i ].item.removeData( this.widgetName + "-item" ); 15425 } 15426 15427 return this; 15428 }, 15429 15430 _mouseCapture: function( event, overrideHandle ) { 15431 var currentItem = null, 15432 validHandle = false, 15433 that = this; 15434 15435 if ( this.reverting ) { 15436 return false; 15437 } 15438 15439 if ( this.options.disabled || this.options.type === "static" ) { 15440 return false; 15441 } 15442 15443 //We have to refresh the items data once first 15444 this._refreshItems( event ); 15445 15446 //Find out if the clicked node (or one of its parents) is a actual item in this.items 15447 $( event.target ).parents().each( function() { 15448 if ( $.data( this, that.widgetName + "-item" ) === that ) { 15449 currentItem = $( this ); 15450 return false; 15451 } 15452 } ); 15453 if ( $.data( event.target, that.widgetName + "-item" ) === that ) { 15454 currentItem = $( event.target ); 15455 } 15456 15457 if ( !currentItem ) { 15458 return false; 15459 } 15460 if ( this.options.handle && !overrideHandle ) { 15461 $( this.options.handle, currentItem ).find( "*" ).addBack().each( function() { 15462 if ( this === event.target ) { 15463 validHandle = true; 15464 } 15465 } ); 15466 if ( !validHandle ) { 15467 return false; 15468 } 15469 } 15470 15471 this.currentItem = currentItem; 15472 this._removeCurrentsFromItems(); 15473 return true; 15474 15475 }, 15476 15477 _mouseStart: function( event, overrideHandle, noActivation ) { 15478 15479 var i, body, 15480 o = this.options; 15481 15482 this.currentContainer = this; 15483 15484 //We only need to call refreshPositions, because the refreshItems call has been moved to 15485 // mouseCapture 15486 this.refreshPositions(); 15487 15488 //Prepare the dragged items parent 15489 this.appendTo = $( o.appendTo !== "parent" ? 15490 o.appendTo : 15491 this.currentItem.parent() ); 15492 15493 //Create and append the visible helper 15494 this.helper = this._createHelper( event ); 15495 15496 //Cache the helper size 15497 this._cacheHelperProportions(); 15498 15499 /* 15500 * - Position generation - 15501 * This block generates everything position related - it's the core of draggables. 15502 */ 15503 15504 //Cache the margins of the original element 15505 this._cacheMargins(); 15506 15507 //The element's absolute position on the page minus margins 15508 this.offset = this.currentItem.offset(); 15509 this.offset = { 15510 top: this.offset.top - this.margins.top, 15511 left: this.offset.left - this.margins.left 15512 }; 15513 15514 $.extend( this.offset, { 15515 click: { //Where the click happened, relative to the element 15516 left: event.pageX - this.offset.left, 15517 top: event.pageY - this.offset.top 15518 }, 15519 15520 // This is a relative to absolute position minus the actual position calculation - 15521 // only used for relative positioned helper 15522 relative: this._getRelativeOffset() 15523 } ); 15524 15525 // After we get the helper offset, but before we get the parent offset we can 15526 // change the helper's position to absolute 15527 // TODO: Still need to figure out a way to make relative sorting possible 15528 this.helper.css( "position", "absolute" ); 15529 this.cssPosition = this.helper.css( "position" ); 15530 15531 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 15532 if ( o.cursorAt ) { 15533 this._adjustOffsetFromHelper( o.cursorAt ); 15534 } 15535 15536 //Cache the former DOM position 15537 this.domPosition = { 15538 prev: this.currentItem.prev()[ 0 ], 15539 parent: this.currentItem.parent()[ 0 ] 15540 }; 15541 15542 // If the helper is not the original, hide the original so it's not playing any role during 15543 // the drag, won't cause anything bad this way 15544 if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) { 15545 this.currentItem.hide(); 15546 } 15547 15548 //Create the placeholder 15549 this._createPlaceholder(); 15550 15551 //Get the next scrolling parent 15552 this.scrollParent = this.placeholder.scrollParent(); 15553 15554 $.extend( this.offset, { 15555 parent: this._getParentOffset() 15556 } ); 15557 15558 //Set a containment if given in the options 15559 if ( o.containment ) { 15560 this._setContainment(); 15561 } 15562 15563 if ( o.cursor && o.cursor !== "auto" ) { // cursor option 15564 body = this.document.find( "body" ); 15565 15566 this._storedStylesheet = 15567 $( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body ); 15568 } 15569 15570 // We need to make sure to grab the zIndex before setting the 15571 // opacity, because setting the opacity to anything lower than 1 15572 // causes the zIndex to change from "auto" to 0. 15573 if ( o.zIndex ) { // zIndex option 15574 if ( this.helper.css( "zIndex" ) ) { 15575 this._storedZIndex = this.helper.css( "zIndex" ); 15576 } 15577 this.helper.css( "zIndex", o.zIndex ); 15578 } 15579 15580 if ( o.opacity ) { // opacity option 15581 if ( this.helper.css( "opacity" ) ) { 15582 this._storedOpacity = this.helper.css( "opacity" ); 15583 } 15584 this.helper.css( "opacity", o.opacity ); 15585 } 15586 15587 //Prepare scrolling 15588 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && 15589 this.scrollParent[ 0 ].tagName !== "HTML" ) { 15590 this.overflowOffset = this.scrollParent.offset(); 15591 } 15592 15593 //Call callbacks 15594 this._trigger( "start", event, this._uiHash() ); 15595 15596 //Recache the helper size 15597 if ( !this._preserveHelperProportions ) { 15598 this._cacheHelperProportions(); 15599 } 15600 15601 //Post "activate" events to possible containers 15602 if ( !noActivation ) { 15603 for ( i = this.containers.length - 1; i >= 0; i-- ) { 15604 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); 15605 } 15606 } 15607 15608 //Prepare possible droppables 15609 if ( $.ui.ddmanager ) { 15610 $.ui.ddmanager.current = this; 15611 } 15612 15613 if ( $.ui.ddmanager && !o.dropBehaviour ) { 15614 $.ui.ddmanager.prepareOffsets( this, event ); 15615 } 15616 15617 this.dragging = true; 15618 15619 this._addClass( this.helper, "ui-sortable-helper" ); 15620 15621 //Move the helper, if needed 15622 if ( !this.helper.parent().is( this.appendTo ) ) { 15623 this.helper.detach().appendTo( this.appendTo ); 15624 15625 //Update position 15626 this.offset.parent = this._getParentOffset(); 15627 } 15628 15629 //Generate the original position 15630 this.position = this.originalPosition = this._generatePosition( event ); 15631 this.originalPageX = event.pageX; 15632 this.originalPageY = event.pageY; 15633 this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" ); 15634 15635 this._mouseDrag( event ); 15636 15637 return true; 15638 15639 }, 15640 15641 _scroll: function( event ) { 15642 var o = this.options, 15643 scrolled = false; 15644 15645 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && 15646 this.scrollParent[ 0 ].tagName !== "HTML" ) { 15647 15648 if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) - 15649 event.pageY < o.scrollSensitivity ) { 15650 this.scrollParent[ 0 ].scrollTop = 15651 scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed; 15652 } else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) { 15653 this.scrollParent[ 0 ].scrollTop = 15654 scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed; 15655 } 15656 15657 if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) - 15658 event.pageX < o.scrollSensitivity ) { 15659 this.scrollParent[ 0 ].scrollLeft = scrolled = 15660 this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed; 15661 } else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) { 15662 this.scrollParent[ 0 ].scrollLeft = scrolled = 15663 this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed; 15664 } 15665 15666 } else { 15667 15668 if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) { 15669 scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed ); 15670 } else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) < 15671 o.scrollSensitivity ) { 15672 scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed ); 15673 } 15674 15675 if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) { 15676 scrolled = this.document.scrollLeft( 15677 this.document.scrollLeft() - o.scrollSpeed 15678 ); 15679 } else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) < 15680 o.scrollSensitivity ) { 15681 scrolled = this.document.scrollLeft( 15682 this.document.scrollLeft() + o.scrollSpeed 15683 ); 15684 } 15685 15686 } 15687 15688 return scrolled; 15689 }, 15690 15691 _mouseDrag: function( event ) { 15692 var i, item, itemElement, intersection, 15693 o = this.options; 15694 15695 //Compute the helpers position 15696 this.position = this._generatePosition( event ); 15697 this.positionAbs = this._convertPositionTo( "absolute" ); 15698 15699 //Set the helper position 15700 if ( !this.options.axis || this.options.axis !== "y" ) { 15701 this.helper[ 0 ].style.left = this.position.left + "px"; 15702 } 15703 if ( !this.options.axis || this.options.axis !== "x" ) { 15704 this.helper[ 0 ].style.top = this.position.top + "px"; 15705 } 15706 15707 //Do scrolling 15708 if ( o.scroll ) { 15709 if ( this._scroll( event ) !== false ) { 15710 15711 //Update item positions used in position checks 15712 this._refreshItemPositions( true ); 15713 15714 if ( $.ui.ddmanager && !o.dropBehaviour ) { 15715 $.ui.ddmanager.prepareOffsets( this, event ); 15716 } 15717 } 15718 } 15719 15720 this.dragDirection = { 15721 vertical: this._getDragVerticalDirection(), 15722 horizontal: this._getDragHorizontalDirection() 15723 }; 15724 15725 //Rearrange 15726 for ( i = this.items.length - 1; i >= 0; i-- ) { 15727 15728 //Cache variables and intersection, continue if no intersection 15729 item = this.items[ i ]; 15730 itemElement = item.item[ 0 ]; 15731 intersection = this._intersectsWithPointer( item ); 15732 if ( !intersection ) { 15733 continue; 15734 } 15735 15736 // Only put the placeholder inside the current Container, skip all 15737 // items from other containers. This works because when moving 15738 // an item from one container to another the 15739 // currentContainer is switched before the placeholder is moved. 15740 // 15741 // Without this, moving items in "sub-sortables" can cause 15742 // the placeholder to jitter between the outer and inner container. 15743 if ( item.instance !== this.currentContainer ) { 15744 continue; 15745 } 15746 15747 // Cannot intersect with itself 15748 // no useless actions that have been done before 15749 // no action if the item moved is the parent of the item checked 15750 if ( itemElement !== this.currentItem[ 0 ] && 15751 this.placeholder[ intersection === 1 ? 15752 "next" : "prev" ]()[ 0 ] !== itemElement && 15753 !$.contains( this.placeholder[ 0 ], itemElement ) && 15754 ( this.options.type === "semi-dynamic" ? 15755 !$.contains( this.element[ 0 ], itemElement ) : 15756 true 15757 ) 15758 ) { 15759 15760 this.direction = intersection === 1 ? "down" : "up"; 15761 15762 if ( this.options.tolerance === "pointer" || 15763 this._intersectsWithSides( item ) ) { 15764 this._rearrange( event, item ); 15765 } else { 15766 break; 15767 } 15768 15769 this._trigger( "change", event, this._uiHash() ); 15770 break; 15771 } 15772 } 15773 15774 //Post events to containers 15775 this._contactContainers( event ); 15776 15777 //Interconnect with droppables 15778 if ( $.ui.ddmanager ) { 15779 $.ui.ddmanager.drag( this, event ); 15780 } 15781 15782 //Call callbacks 15783 this._trigger( "sort", event, this._uiHash() ); 15784 15785 this.lastPositionAbs = this.positionAbs; 15786 return false; 15787 15788 }, 15789 15790 _mouseStop: function( event, noPropagation ) { 15791 15792 if ( !event ) { 15793 return; 15794 } 15795 15796 //If we are using droppables, inform the manager about the drop 15797 if ( $.ui.ddmanager && !this.options.dropBehaviour ) { 15798 $.ui.ddmanager.drop( this, event ); 15799 } 15800 15801 if ( this.options.revert ) { 15802 var that = this, 15803 cur = this.placeholder.offset(), 15804 axis = this.options.axis, 15805 animation = {}; 15806 15807 if ( !axis || axis === "x" ) { 15808 animation.left = cur.left - this.offset.parent.left - this.margins.left + 15809 ( this.offsetParent[ 0 ] === this.document[ 0 ].body ? 15810 0 : 15811 this.offsetParent[ 0 ].scrollLeft 15812 ); 15813 } 15814 if ( !axis || axis === "y" ) { 15815 animation.top = cur.top - this.offset.parent.top - this.margins.top + 15816 ( this.offsetParent[ 0 ] === this.document[ 0 ].body ? 15817 0 : 15818 this.offsetParent[ 0 ].scrollTop 15819 ); 15820 } 15821 this.reverting = true; 15822 $( this.helper ).animate( 15823 animation, 15824 parseInt( this.options.revert, 10 ) || 500, 15825 function() { 15826 that._clear( event ); 15827 } 15828 ); 15829 } else { 15830 this._clear( event, noPropagation ); 15831 } 15832 15833 return false; 15834 15835 }, 15836 15837 cancel: function() { 15838 15839 if ( this.dragging ) { 15840 15841 this._mouseUp( new $.Event( "mouseup", { target: null } ) ); 15842 15843 if ( this.options.helper === "original" ) { 15844 this.currentItem.css( this._storedCSS ); 15845 this._removeClass( this.currentItem, "ui-sortable-helper" ); 15846 } else { 15847 this.currentItem.show(); 15848 } 15849 15850 //Post deactivating events to containers 15851 for ( var i = this.containers.length - 1; i >= 0; i-- ) { 15852 this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) ); 15853 if ( this.containers[ i ].containerCache.over ) { 15854 this.containers[ i ]._trigger( "out", null, this._uiHash( this ) ); 15855 this.containers[ i ].containerCache.over = 0; 15856 } 15857 } 15858 15859 } 15860 15861 if ( this.placeholder ) { 15862 15863 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, 15864 // it unbinds ALL events from the original node! 15865 if ( this.placeholder[ 0 ].parentNode ) { 15866 this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] ); 15867 } 15868 if ( this.options.helper !== "original" && this.helper && 15869 this.helper[ 0 ].parentNode ) { 15870 this.helper.remove(); 15871 } 15872 15873 $.extend( this, { 15874 helper: null, 15875 dragging: false, 15876 reverting: false, 15877 _noFinalSort: null 15878 } ); 15879 15880 if ( this.domPosition.prev ) { 15881 $( this.domPosition.prev ).after( this.currentItem ); 15882 } else { 15883 $( this.domPosition.parent ).prepend( this.currentItem ); 15884 } 15885 } 15886 15887 return this; 15888 15889 }, 15890 15891 serialize: function( o ) { 15892 15893 var items = this._getItemsAsjQuery( o && o.connected ), 15894 str = []; 15895 o = o || {}; 15896 15897 $( items ).each( function() { 15898 var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" ) 15899 .match( o.expression || ( /(.+)[\-=_](.+)/ ) ); 15900 if ( res ) { 15901 str.push( 15902 ( o.key || res[ 1 ] + "[]" ) + 15903 "=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) ); 15904 } 15905 } ); 15906 15907 if ( !str.length && o.key ) { 15908 str.push( o.key + "=" ); 15909 } 15910 15911 return str.join( "&" ); 15912 15913 }, 15914 15915 toArray: function( o ) { 15916 15917 var items = this._getItemsAsjQuery( o && o.connected ), 15918 ret = []; 15919 15920 o = o || {}; 15921 15922 items.each( function() { 15923 ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" ); 15924 } ); 15925 return ret; 15926 15927 }, 15928 15929 /* Be careful with the following core functions */ 15930 _intersectsWith: function( item ) { 15931 15932 var x1 = this.positionAbs.left, 15933 x2 = x1 + this.helperProportions.width, 15934 y1 = this.positionAbs.top, 15935 y2 = y1 + this.helperProportions.height, 15936 l = item.left, 15937 r = l + item.width, 15938 t = item.top, 15939 b = t + item.height, 15940 dyClick = this.offset.click.top, 15941 dxClick = this.offset.click.left, 15942 isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && 15943 ( y1 + dyClick ) < b ), 15944 isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && 15945 ( x1 + dxClick ) < r ), 15946 isOverElement = isOverElementHeight && isOverElementWidth; 15947 15948 if ( this.options.tolerance === "pointer" || 15949 this.options.forcePointerForContainers || 15950 ( this.options.tolerance !== "pointer" && 15951 this.helperProportions[ this.floating ? "width" : "height" ] > 15952 item[ this.floating ? "width" : "height" ] ) 15953 ) { 15954 return isOverElement; 15955 } else { 15956 15957 return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half 15958 x2 - ( this.helperProportions.width / 2 ) < r && // Left Half 15959 t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half 15960 y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half 15961 15962 } 15963 }, 15964 15965 _intersectsWithPointer: function( item ) { 15966 var verticalDirection, horizontalDirection, 15967 isOverElementHeight = ( this.options.axis === "x" ) || 15968 this._isOverAxis( 15969 this.positionAbs.top + this.offset.click.top, item.top, item.height ), 15970 isOverElementWidth = ( this.options.axis === "y" ) || 15971 this._isOverAxis( 15972 this.positionAbs.left + this.offset.click.left, item.left, item.width ), 15973 isOverElement = isOverElementHeight && isOverElementWidth; 15974 15975 if ( !isOverElement ) { 15976 return false; 15977 } 15978 15979 verticalDirection = this.dragDirection.vertical; 15980 horizontalDirection = this.dragDirection.horizontal; 15981 15982 return this.floating ? 15983 ( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) : 15984 ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) ); 15985 15986 }, 15987 15988 _intersectsWithSides: function( item ) { 15989 15990 var isOverBottomHalf = this._isOverAxis( this.positionAbs.top + 15991 this.offset.click.top, item.top + ( item.height / 2 ), item.height ), 15992 isOverRightHalf = this._isOverAxis( this.positionAbs.left + 15993 this.offset.click.left, item.left + ( item.width / 2 ), item.width ), 15994 verticalDirection = this.dragDirection.vertical, 15995 horizontalDirection = this.dragDirection.horizontal; 15996 15997 if ( this.floating && horizontalDirection ) { 15998 return ( ( horizontalDirection === "right" && isOverRightHalf ) || 15999 ( horizontalDirection === "left" && !isOverRightHalf ) ); 16000 } else { 16001 return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) || 16002 ( verticalDirection === "up" && !isOverBottomHalf ) ); 16003 } 16004 16005 }, 16006 16007 _getDragVerticalDirection: function() { 16008 var delta = this.positionAbs.top - this.lastPositionAbs.top; 16009 return delta !== 0 && ( delta > 0 ? "down" : "up" ); 16010 }, 16011 16012 _getDragHorizontalDirection: function() { 16013 var delta = this.positionAbs.left - this.lastPositionAbs.left; 16014 return delta !== 0 && ( delta > 0 ? "right" : "left" ); 16015 }, 16016 16017 refresh: function( event ) { 16018 this._refreshItems( event ); 16019 this._setHandleClassName(); 16020 this.refreshPositions(); 16021 return this; 16022 }, 16023 16024 _connectWith: function() { 16025 var options = this.options; 16026 return options.connectWith.constructor === String ? 16027 [ options.connectWith ] : 16028 options.connectWith; 16029 }, 16030 16031 _getItemsAsjQuery: function( connected ) { 16032 16033 var i, j, cur, inst, 16034 items = [], 16035 queries = [], 16036 connectWith = this._connectWith(); 16037 16038 if ( connectWith && connected ) { 16039 for ( i = connectWith.length - 1; i >= 0; i-- ) { 16040 cur = $( connectWith[ i ], this.document[ 0 ] ); 16041 for ( j = cur.length - 1; j >= 0; j-- ) { 16042 inst = $.data( cur[ j ], this.widgetFullName ); 16043 if ( inst && inst !== this && !inst.options.disabled ) { 16044 queries.push( [ typeof inst.options.items === "function" ? 16045 inst.options.items.call( inst.element ) : 16046 $( inst.options.items, inst.element ) 16047 .not( ".ui-sortable-helper" ) 16048 .not( ".ui-sortable-placeholder" ), inst ] ); 16049 } 16050 } 16051 } 16052 } 16053 16054 queries.push( [ typeof this.options.items === "function" ? 16055 this.options.items 16056 .call( this.element, null, { options: this.options, item: this.currentItem } ) : 16057 $( this.options.items, this.element ) 16058 .not( ".ui-sortable-helper" ) 16059 .not( ".ui-sortable-placeholder" ), this ] ); 16060 16061 function addItems() { 16062 items.push( this ); 16063 } 16064 for ( i = queries.length - 1; i >= 0; i-- ) { 16065 queries[ i ][ 0 ].each( addItems ); 16066 } 16067 16068 return $( items ); 16069 16070 }, 16071 16072 _removeCurrentsFromItems: function() { 16073 16074 var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" ); 16075 16076 this.items = $.grep( this.items, function( item ) { 16077 for ( var j = 0; j < list.length; j++ ) { 16078 if ( list[ j ] === item.item[ 0 ] ) { 16079 return false; 16080 } 16081 } 16082 return true; 16083 } ); 16084 16085 }, 16086 16087 _refreshItems: function( event ) { 16088 16089 this.items = []; 16090 this.containers = [ this ]; 16091 16092 var i, j, cur, inst, targetData, _queries, item, queriesLength, 16093 items = this.items, 16094 queries = [ [ typeof this.options.items === "function" ? 16095 this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) : 16096 $( this.options.items, this.element ), this ] ], 16097 connectWith = this._connectWith(); 16098 16099 //Shouldn't be run the first time through due to massive slow-down 16100 if ( connectWith && this.ready ) { 16101 for ( i = connectWith.length - 1; i >= 0; i-- ) { 16102 cur = $( connectWith[ i ], this.document[ 0 ] ); 16103 for ( j = cur.length - 1; j >= 0; j-- ) { 16104 inst = $.data( cur[ j ], this.widgetFullName ); 16105 if ( inst && inst !== this && !inst.options.disabled ) { 16106 queries.push( [ typeof inst.options.items === "function" ? 16107 inst.options.items 16108 .call( inst.element[ 0 ], event, { item: this.currentItem } ) : 16109 $( inst.options.items, inst.element ), inst ] ); 16110 this.containers.push( inst ); 16111 } 16112 } 16113 } 16114 } 16115 16116 for ( i = queries.length - 1; i >= 0; i-- ) { 16117 targetData = queries[ i ][ 1 ]; 16118 _queries = queries[ i ][ 0 ]; 16119 16120 for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) { 16121 item = $( _queries[ j ] ); 16122 16123 // Data for target checking (mouse manager) 16124 item.data( this.widgetName + "-item", targetData ); 16125 16126 items.push( { 16127 item: item, 16128 instance: targetData, 16129 width: 0, height: 0, 16130 left: 0, top: 0 16131 } ); 16132 } 16133 } 16134 16135 }, 16136 16137 _refreshItemPositions: function( fast ) { 16138 var i, item, t, p; 16139 16140 for ( i = this.items.length - 1; i >= 0; i-- ) { 16141 item = this.items[ i ]; 16142 16143 //We ignore calculating positions of all connected containers when we're not over them 16144 if ( this.currentContainer && item.instance !== this.currentContainer && 16145 item.item[ 0 ] !== this.currentItem[ 0 ] ) { 16146 continue; 16147 } 16148 16149 t = this.options.toleranceElement ? 16150 $( this.options.toleranceElement, item.item ) : 16151 item.item; 16152 16153 if ( !fast ) { 16154 item.width = t.outerWidth(); 16155 item.height = t.outerHeight(); 16156 } 16157 16158 p = t.offset(); 16159 item.left = p.left; 16160 item.top = p.top; 16161 } 16162 }, 16163 16164 refreshPositions: function( fast ) { 16165 16166 // Determine whether items are being displayed horizontally 16167 this.floating = this.items.length ? 16168 this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) : 16169 false; 16170 16171 // This has to be redone because due to the item being moved out/into the offsetParent, 16172 // the offsetParent's position will change 16173 if ( this.offsetParent && this.helper ) { 16174 this.offset.parent = this._getParentOffset(); 16175 } 16176 16177 this._refreshItemPositions( fast ); 16178 16179 var i, p; 16180 16181 if ( this.options.custom && this.options.custom.refreshContainers ) { 16182 this.options.custom.refreshContainers.call( this ); 16183 } else { 16184 for ( i = this.containers.length - 1; i >= 0; i-- ) { 16185 p = this.containers[ i ].element.offset(); 16186 this.containers[ i ].containerCache.left = p.left; 16187 this.containers[ i ].containerCache.top = p.top; 16188 this.containers[ i ].containerCache.width = 16189 this.containers[ i ].element.outerWidth(); 16190 this.containers[ i ].containerCache.height = 16191 this.containers[ i ].element.outerHeight(); 16192 } 16193 } 16194 16195 return this; 16196 }, 16197 16198 _createPlaceholder: function( that ) { 16199 that = that || this; 16200 var className, nodeName, 16201 o = that.options; 16202 16203 if ( !o.placeholder || o.placeholder.constructor === String ) { 16204 className = o.placeholder; 16205 nodeName = that.currentItem[ 0 ].nodeName.toLowerCase(); 16206 o.placeholder = { 16207 element: function() { 16208 16209 var element = $( "<" + nodeName + ">", that.document[ 0 ] ); 16210 16211 that._addClass( element, "ui-sortable-placeholder", 16212 className || that.currentItem[ 0 ].className ) 16213 ._removeClass( element, "ui-sortable-helper" ); 16214 16215 if ( nodeName === "tbody" ) { 16216 that._createTrPlaceholder( 16217 that.currentItem.find( "tr" ).eq( 0 ), 16218 $( "<tr>", that.document[ 0 ] ).appendTo( element ) 16219 ); 16220 } else if ( nodeName === "tr" ) { 16221 that._createTrPlaceholder( that.currentItem, element ); 16222 } else if ( nodeName === "img" ) { 16223 element.attr( "src", that.currentItem.attr( "src" ) ); 16224 } 16225 16226 if ( !className ) { 16227 element.css( "visibility", "hidden" ); 16228 } 16229 16230 return element; 16231 }, 16232 update: function( container, p ) { 16233 16234 // 1. If a className is set as 'placeholder option, we don't force sizes - 16235 // the class is responsible for that
16236 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a 16237 // class name is specified 16238 if ( className && !o.forcePlaceholderSize ) { 16239 return; 16240 } 16241 16242 // If the element doesn't have a actual height or width by itself (without 16243 // styles coming from a stylesheet), it receives the inline height and width 16244 // from the dragged item. Or, if it's a tbody or tr, it's going to have a height 16245 // anyway since we're populating them with <td>s above, but they're unlikely to 16246 // be the correct height on their own if the row heights are dynamic, so we'll 16247 // always assign the height of the dragged item given forcePlaceholderSize 16248 // is true. 16249 if ( !p.height() || ( o.forcePlaceholderSize && 16250 ( nodeName === "tbody" || nodeName === "tr" ) ) ) { 16251 p.height(
vendor: 39,394 bytes, lines 16252-17334
16252 that.currentItem.innerHeight() - 16253 parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) - 16254 parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) ); 16255 } 16256 if ( !p.width() ) { 16257 p.width( 16258 that.currentItem.innerWidth() - 16259 parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) - 16260 parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) ); 16261 } 16262 } 16263 }; 16264 } 16265 16266 //Create the placeholder 16267 that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) ); 16268 16269 //Append it after the actual current item 16270 that.currentItem.after( that.placeholder ); 16271 16272 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) 16273 o.placeholder.update( that, that.placeholder ); 16274 16275 }, 16276 16277 _createTrPlaceholder: function( sourceTr, targetTr ) { 16278 var that = this; 16279 16280 sourceTr.children().each( function() { 16281 $( "<td> </td>", that.document[ 0 ] ) 16282 .attr( "colspan", $( this ).attr( "colspan" ) || 1 ) 16283 .appendTo( targetTr ); 16284 } ); 16285 }, 16286 16287 _contactContainers: function( event ) { 16288 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, 16289 floating, axis, 16290 innermostContainer = null, 16291 innermostIndex = null; 16292 16293 // Get innermost container that intersects with item 16294 for ( i = this.containers.length - 1; i >= 0; i-- ) { 16295 16296 // Never consider a container that's located within the item itself 16297 if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) { 16298 continue; 16299 } 16300 16301 if ( this._intersectsWith( this.containers[ i ].containerCache ) ) { 16302 16303 // If we've already found a container and it's more "inner" than this, then continue 16304 if ( innermostContainer && 16305 $.contains( 16306 this.containers[ i ].element[ 0 ], 16307 innermostContainer.element[ 0 ] ) ) { 16308 continue; 16309 } 16310 16311 innermostContainer = this.containers[ i ]; 16312 innermostIndex = i; 16313 16314 } else { 16315 16316 // container doesn't intersect. trigger "out" event if necessary 16317 if ( this.containers[ i ].containerCache.over ) { 16318 this.containers[ i ]._trigger( "out", event, this._uiHash( this ) ); 16319 this.containers[ i ].containerCache.over = 0; 16320 } 16321 } 16322 16323 } 16324 16325 // If no intersecting containers found, return 16326 if ( !innermostContainer ) { 16327 return; 16328 } 16329 16330 // Move the item into the container if it's not there already 16331 if ( this.containers.length === 1 ) { 16332 if ( !this.containers[ innermostIndex ].containerCache.over ) { 16333 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) ); 16334 this.containers[ innermostIndex ].containerCache.over = 1; 16335 } 16336 } else { 16337 16338 // When entering a new container, we will find the item with the least distance and 16339 // append our item near it 16340 dist = 10000; 16341 itemWithLeastDistance = null; 16342 floating = innermostContainer.floating || this._isFloating( this.currentItem ); 16343 posProperty = floating ? "left" : "top"; 16344 sizeProperty = floating ? "width" : "height"; 16345 axis = floating ? "pageX" : "pageY"; 16346 16347 for ( j = this.items.length - 1; j >= 0; j-- ) { 16348 if ( !$.contains( 16349 this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] ) 16350 ) { 16351 continue; 16352 } 16353 if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) { 16354 continue; 16355 } 16356 16357 cur = this.items[ j ].item.offset()[ posProperty ]; 16358 nearBottom = false; 16359 if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) { 16360 nearBottom = true; 16361 } 16362 16363 if ( Math.abs( event[ axis ] - cur ) < dist ) { 16364 dist = Math.abs( event[ axis ] - cur ); 16365 itemWithLeastDistance = this.items[ j ]; 16366 this.direction = nearBottom ? "up" : "down"; 16367 } 16368 } 16369 16370 //Check if dropOnEmpty is enabled 16371 if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) { 16372 return; 16373 } 16374 16375 if ( this.currentContainer === this.containers[ innermostIndex ] ) { 16376 if ( !this.currentContainer.containerCache.over ) { 16377 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() ); 16378 this.currentContainer.containerCache.over = 1; 16379 } 16380 return; 16381 } 16382 16383 if ( itemWithLeastDistance ) { 16384 this._rearrange( event, itemWithLeastDistance, null, true ); 16385 } else { 16386 this._rearrange( event, null, this.containers[ innermostIndex ].element, true ); 16387 } 16388 this._trigger( "change", event, this._uiHash() ); 16389 this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) ); 16390 this.currentContainer = this.containers[ innermostIndex ]; 16391 16392 //Update the placeholder 16393 this.options.placeholder.update( this.currentContainer, this.placeholder ); 16394 16395 //Update scrollParent 16396 this.scrollParent = this.placeholder.scrollParent(); 16397 16398 //Update overflowOffset 16399 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && 16400 this.scrollParent[ 0 ].tagName !== "HTML" ) { 16401 this.overflowOffset = this.scrollParent.offset(); 16402 } 16403 16404 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) ); 16405 this.containers[ innermostIndex ].containerCache.over = 1; 16406 } 16407 16408 }, 16409 16410 _createHelper: function( event ) { 16411 16412 var o = this.options, 16413 helper = typeof o.helper === "function" ? 16414 $( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) : 16415 ( o.helper === "clone" ? this.currentItem.clone() : this.currentItem ); 16416 16417 //Add the helper to the DOM if that didn't happen already 16418 if ( !helper.parents( "body" ).length ) { 16419 this.appendTo[ 0 ].appendChild( helper[ 0 ] ); 16420 } 16421 16422 if ( helper[ 0 ] === this.currentItem[ 0 ] ) { 16423 this._storedCSS = { 16424 width: this.currentItem[ 0 ].style.width, 16425 height: this.currentItem[ 0 ].style.height, 16426 position: this.currentItem.css( "position" ), 16427 top: this.currentItem.css( "top" ), 16428 left: this.currentItem.css( "left" ) 16429 }; 16430 } 16431 16432 if ( !helper[ 0 ].style.width || o.forceHelperSize ) { 16433 helper.width( this.currentItem.width() ); 16434 } 16435 if ( !helper[ 0 ].style.height || o.forceHelperSize ) { 16436 helper.height( this.currentItem.height() ); 16437 } 16438 16439 return helper; 16440 16441 }, 16442 16443 _adjustOffsetFromHelper: function( obj ) { 16444 if ( typeof obj === "string" ) { 16445 obj = obj.split( " " ); 16446 } 16447 if ( Array.isArray( obj ) ) { 16448 obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 }; 16449 } 16450 if ( "left" in obj ) { 16451 this.offset.click.left = obj.left + this.margins.left; 16452 } 16453 if ( "right" in obj ) { 16454 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 16455 } 16456 if ( "top" in obj ) { 16457 this.offset.click.top = obj.top + this.margins.top; 16458 } 16459 if ( "bottom" in obj ) { 16460 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 16461 } 16462 }, 16463 16464 _getParentOffset: function() { 16465 16466 //Get the offsetParent and cache its position 16467 this.offsetParent = this.helper.offsetParent(); 16468 var po = this.offsetParent.offset(); 16469 16470 // This is a special case where we need to modify a offset calculated on start, since the 16471 // following happened: 16472 // 1. The position of the helper is absolute, so it's position is calculated based on the 16473 // next positioned parent 16474 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't 16475 // the document, which means that the scroll is included in the initial calculation of the 16476 // offset of the parent, and never recalculated upon drag 16477 if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] && 16478 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) { 16479 po.left += this.scrollParent.scrollLeft(); 16480 po.top += this.scrollParent.scrollTop(); 16481 } 16482 16483 // This needs to be actually done for all browsers, since pageX/pageY includes 16484 // this information. 16485 if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ) { 16486 po = { top: 0, left: 0 }; 16487 } 16488 16489 return { 16490 top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ), 16491 left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 ) 16492 }; 16493 16494 }, 16495 16496 _getRelativeOffset: function() { 16497 16498 if ( this.cssPosition === "relative" ) { 16499 var p = this.currentItem.position(); 16500 return { 16501 top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) + 16502 this.scrollParent.scrollTop(), 16503 left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) + 16504 this.scrollParent.scrollLeft() 16505 }; 16506 } else { 16507 return { top: 0, left: 0 }; 16508 } 16509 16510 }, 16511 16512 _cacheMargins: function() { 16513 this.margins = { 16514 left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ), 16515 top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 ) 16516 }; 16517 }, 16518 16519 _cacheHelperProportions: function() { 16520 this.helperProportions = { 16521 width: this.helper.outerWidth(), 16522 height: this.helper.outerHeight() 16523 }; 16524 }, 16525 16526 _setContainment: function() { 16527 16528 var ce, co, over, 16529 o = this.options; 16530 if ( o.containment === "parent" ) { 16531 o.containment = this.helper[ 0 ].parentNode; 16532 } 16533 if ( o.containment === "document" || o.containment === "window" ) { 16534 this.containment = [ 16535 0 - this.offset.relative.left - this.offset.parent.left, 16536 0 - this.offset.relative.top - this.offset.parent.top, 16537 o.containment === "document" ? 16538 this.document.width() : 16539 this.window.width() - this.helperProportions.width - this.margins.left, 16540 ( o.containment === "document" ? 16541 ( this.document.height() || document.body.parentNode.scrollHeight ) : 16542 this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight 16543 ) - this.helperProportions.height - this.margins.top 16544 ]; 16545 } 16546 16547 if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) { 16548 ce = $( o.containment )[ 0 ]; 16549 co = $( o.containment ).offset(); 16550 over = ( $( ce ).css( "overflow" ) !== "hidden" ); 16551 16552 this.containment = [ 16553 co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) + 16554 ( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left, 16555 co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) + 16556 ( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top, 16557 co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - 16558 ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) - 16559 ( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) - 16560 this.helperProportions.width - this.margins.left, 16561 co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - 16562 ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) - 16563 ( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) - 16564 this.helperProportions.height - this.margins.top 16565 ]; 16566 } 16567 16568 }, 16569 16570 _convertPositionTo: function( d, pos ) { 16571 16572 if ( !pos ) { 16573 pos = this.position; 16574 } 16575 var mod = d === "absolute" ? 1 : -1, 16576 scroll = this.cssPosition === "absolute" && 16577 !( this.scrollParent[ 0 ] !== this.document[ 0 ] && 16578 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? 16579 this.offsetParent : 16580 this.scrollParent, 16581 scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName ); 16582 16583 return { 16584 top: ( 16585 16586 // The absolute mouse position 16587 pos.top + 16588 16589 // Only for relative positioned nodes: Relative offset from element to offset parent 16590 this.offset.relative.top * mod + 16591 16592 // The offsetParent's offset without borders (offset + border) 16593 this.offset.parent.top * mod - 16594 ( ( this.cssPosition === "fixed" ? 16595 -this.scrollParent.scrollTop() : 16596 ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod ) 16597 ), 16598 left: ( 16599 16600 // The absolute mouse position 16601 pos.left + 16602 16603 // Only for relative positioned nodes: Relative offset from element to offset parent 16604 this.offset.relative.left * mod + 16605 16606 // The offsetParent's offset without borders (offset + border) 16607 this.offset.parent.left * mod - 16608 ( ( this.cssPosition === "fixed" ? 16609 -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : 16610 scroll.scrollLeft() ) * mod ) 16611 ) 16612 }; 16613 16614 }, 16615 16616 _generatePosition: function( event ) { 16617 16618 var top, left, 16619 o = this.options, 16620 pageX = event.pageX, 16621 pageY = event.pageY, 16622 scroll = this.cssPosition === "absolute" && 16623 !( this.scrollParent[ 0 ] !== this.document[ 0 ] && 16624 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? 16625 this.offsetParent : 16626 this.scrollParent, 16627 scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName ); 16628 16629 // This is another very weird special case that only happens for relative elements: 16630 // 1. If the css position is relative 16631 // 2. and the scroll parent is the document or similar to the offset parent 16632 // we have to refresh the relative offset during the scroll so there are no jumps 16633 if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] && 16634 this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) { 16635 this.offset.relative = this._getRelativeOffset(); 16636 } 16637 16638 /* 16639 * - Position constraining - 16640 * Constrain the position to a mix of grid, containment. 16641 */ 16642 16643 if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options 16644 16645 if ( this.containment ) { 16646 if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) { 16647 pageX = this.containment[ 0 ] + this.offset.click.left; 16648 } 16649 if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) { 16650 pageY = this.containment[ 1 ] + this.offset.click.top; 16651 } 16652 if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) { 16653 pageX = this.containment[ 2 ] + this.offset.click.left; 16654 } 16655 if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) { 16656 pageY = this.containment[ 3 ] + this.offset.click.top; 16657 } 16658 } 16659 16660 if ( o.grid ) { 16661 top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) / 16662 o.grid[ 1 ] ) * o.grid[ 1 ]; 16663 pageY = this.containment ? 16664 ( ( top - this.offset.click.top >= this.containment[ 1 ] && 16665 top - this.offset.click.top <= this.containment[ 3 ] ) ? 16666 top : 16667 ( ( top - this.offset.click.top >= this.containment[ 1 ] ) ? 16668 top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : 16669 top; 16670 16671 left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) / 16672 o.grid[ 0 ] ) * o.grid[ 0 ]; 16673 pageX = this.containment ? 16674 ( ( left - this.offset.click.left >= this.containment[ 0 ] && 16675 left - this.offset.click.left <= this.containment[ 2 ] ) ? 16676 left : 16677 ( ( left - this.offset.click.left >= this.containment[ 0 ] ) ? 16678 left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : 16679 left; 16680 } 16681 16682 } 16683 16684 return { 16685 top: ( 16686 16687 // The absolute mouse position 16688 pageY - 16689 16690 // Click offset (relative to the element) 16691 this.offset.click.top - 16692 16693 // Only for relative positioned nodes: Relative offset from element to offset parent 16694 this.offset.relative.top - 16695 16696 // The offsetParent's offset without borders (offset + border) 16697 this.offset.parent.top + 16698 ( ( this.cssPosition === "fixed" ? 16699 -this.scrollParent.scrollTop() : 16700 ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) ) 16701 ), 16702 left: ( 16703 16704 // The absolute mouse position 16705 pageX - 16706 16707 // Click offset (relative to the element) 16708 this.offset.click.left - 16709 16710 // Only for relative positioned nodes: Relative offset from element to offset parent 16711 this.offset.relative.left - 16712 16713 // The offsetParent's offset without borders (offset + border) 16714 this.offset.parent.left + 16715 ( ( this.cssPosition === "fixed" ? 16716 -this.scrollParent.scrollLeft() : 16717 scrollIsRootNode ? 0 : scroll.scrollLeft() ) ) 16718 ) 16719 }; 16720 16721 }, 16722 16723 _rearrange: function( event, i, a, hardRefresh ) { 16724 16725 if ( a ) { 16726 a[ 0 ].appendChild( this.placeholder[ 0 ] ); 16727 } else { 16728 i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ], 16729 ( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) ); 16730 } 16731 16732 //Various things done here to improve the performance: 16733 // 1. we create a setTimeout, that calls refreshPositions 16734 // 2. on the instance, we have a counter variable, that get's higher after every append 16735 // 3. on the local scope, we copy the counter variable, and check in the timeout, 16736 // if it's still the same 16737 // 4. this lets only the last addition to the timeout stack through 16738 this.counter = this.counter ? ++this.counter : 1; 16739 var counter = this.counter; 16740 16741 this._delay( function() { 16742 if ( counter === this.counter ) { 16743 16744 //Precompute after each DOM insertion, NOT on mousemove 16745 this.refreshPositions( !hardRefresh ); 16746 } 16747 } ); 16748 16749 }, 16750 16751 _clear: function( event, noPropagation ) { 16752 16753 this.reverting = false; 16754 16755 // We delay all events that have to be triggered to after the point where the placeholder 16756 // has been removed and everything else normalized again 16757 var i, 16758 delayedTriggers = []; 16759 16760 // We first have to update the dom position of the actual currentItem 16761 // Note: don't do it if the current item is already removed (by a user), or it gets 16762 // reappended (see #4088) 16763 if ( !this._noFinalSort && this.currentItem.parent().length ) { 16764 this.placeholder.before( this.currentItem ); 16765 } 16766 this._noFinalSort = null; 16767 16768 if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) { 16769 for ( i in this._storedCSS ) { 16770 if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) { 16771 this._storedCSS[ i ] = ""; 16772 } 16773 } 16774 this.currentItem.css( this._storedCSS ); 16775 this._removeClass( this.currentItem, "ui-sortable-helper" ); 16776 } else { 16777 this.currentItem.show(); 16778 } 16779 16780 if ( this.fromOutside && !noPropagation ) { 16781 delayedTriggers.push( function( event ) { 16782 this._trigger( "receive", event, this._uiHash( this.fromOutside ) ); 16783 } ); 16784 } 16785 if ( ( this.fromOutside || 16786 this.domPosition.prev !== 16787 this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] || 16788 this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) { 16789 16790 // Trigger update callback if the DOM position has changed 16791 delayedTriggers.push( function( event ) { 16792 this._trigger( "update", event, this._uiHash() ); 16793 } ); 16794 } 16795 16796 // Check if the items Container has Changed and trigger appropriate 16797 // events. 16798 if ( this !== this.currentContainer ) { 16799 if ( !noPropagation ) { 16800 delayedTriggers.push( function( event ) { 16801 this._trigger( "remove", event, this._uiHash() ); 16802 } ); 16803 delayedTriggers.push( ( function( c ) { 16804 return function( event ) { 16805 c._trigger( "receive", event, this._uiHash( this ) ); 16806 }; 16807 } ).call( this, this.currentContainer ) ); 16808 delayedTriggers.push( ( function( c ) { 16809 return function( event ) { 16810 c._trigger( "update", event, this._uiHash( this ) ); 16811 }; 16812 } ).call( this, this.currentContainer ) ); 16813 } 16814 } 16815 16816 //Post events to containers 16817 function delayEvent( type, instance, container ) { 16818 return function( event ) { 16819 container._trigger( type, event, instance._uiHash( instance ) ); 16820 }; 16821 } 16822 for ( i = this.containers.length - 1; i >= 0; i-- ) { 16823 if ( !noPropagation ) { 16824 delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) ); 16825 } 16826 if ( this.containers[ i ].containerCache.over ) { 16827 delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) ); 16828 this.containers[ i ].containerCache.over = 0; 16829 } 16830 } 16831 16832 //Do what was originally in plugins 16833 if ( this._storedStylesheet ) { 16834 this._storedStylesheet.remove(); 16835 this._storedStylesheet = null; 16836 } 16837 if ( this._storedOpacity ) { 16838 this.helper.css( "opacity", this._storedOpacity ); 16839 } 16840 if ( this._storedZIndex ) { 16841 this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex ); 16842 } 16843 16844 this.dragging = false; 16845 16846 if ( !noPropagation ) { 16847 this._trigger( "beforeStop", event, this._uiHash() ); 16848 } 16849 16850 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, 16851 // it unbinds ALL events from the original node! 16852 this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] ); 16853 16854 if ( !this.cancelHelperRemoval ) { 16855 if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) { 16856 this.helper.remove(); 16857 } 16858 this.helper = null; 16859 } 16860 16861 if ( !noPropagation ) { 16862 for ( i = 0; i < delayedTriggers.length; i++ ) { 16863 16864 // Trigger all delayed events 16865 delayedTriggers[ i ].call( this, event ); 16866 } 16867 this._trigger( "stop", event, this._uiHash() ); 16868 } 16869 16870 this.fromOutside = false; 16871 return !this.cancelHelperRemoval; 16872 16873 }, 16874 16875 _trigger: function() { 16876 if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) { 16877 this.cancel(); 16878 } 16879 }, 16880 16881 _uiHash: function( _inst ) { 16882 var inst = _inst || this; 16883 return { 16884 helper: inst.helper, 16885 placeholder: inst.placeholder || $( [] ), 16886 position: inst.position, 16887 originalPosition: inst.originalPosition, 16888 offset: inst.positionAbs, 16889 item: inst.currentItem, 16890 sender: _inst ? _inst.element : null 16891 }; 16892 } 16893 16894} ); 16895 16896 16897/*! 16898 * jQuery UI Spinner 1.14.1 16899 * https://jqueryui.com 16900 * 16901 * Copyright OpenJS Foundation and other contributors 16902 * Released under the MIT license. 16903 * https://jquery.org/license 16904 */ 16905 16906//>>label: Spinner 16907//>>group: Widgets 16908//>>description: Displays buttons to easily input numbers via the keyboard or mouse. 16909//>>docs: https://api.jqueryui.com/spinner/ 16910//>>demos: https://jqueryui.com/spinner/ 16911//>>css.structure: ../../themes/base/core.css 16912//>>css.structure: ../../themes/base/spinner.css 16913//>>css.theme: ../../themes/base/theme.css 16914 16915 16916function spinnerModifier( fn ) { 16917 return function() { 16918 var previous = this.element.val(); 16919 fn.apply( this, arguments ); 16920 this._refresh(); 16921 if ( previous !== this.element.val() ) { 16922 this._trigger( "change" ); 16923 } 16924 }; 16925} 16926 16927$.widget( "ui.spinner", { 16928 version: "1.14.1", 16929 defaultElement: "<input>", 16930 widgetEventPrefix: "spin", 16931 options: { 16932 classes: { 16933 "ui-spinner": "ui-corner-all", 16934 "ui-spinner-down": "ui-corner-br", 16935 "ui-spinner-up": "ui-corner-tr" 16936 }, 16937 culture: null, 16938 icons: { 16939 down: "ui-icon-triangle-1-s", 16940 up: "ui-icon-triangle-1-n" 16941 }, 16942 incremental: true, 16943 max: null, 16944 min: null, 16945 numberFormat: null, 16946 page: 10, 16947 step: 1, 16948 16949 change: null, 16950 spin: null, 16951 start: null, 16952 stop: null 16953 }, 16954 16955 _create: function() { 16956 16957 // handle string values that need to be parsed 16958 this._setOption( "max", this.options.max ); 16959 this._setOption( "min", this.options.min ); 16960 this._setOption( "step", this.options.step ); 16961 16962 // Only format if there is a value, prevents the field from being marked 16963 // as invalid in Firefox, see #9573. 16964 if ( this.value() !== "" ) { 16965 16966 // Format the value, but don't constrain. 16967 this._value( this.element.val(), true ); 16968 } 16969 16970 this._draw(); 16971 this._on( this._events ); 16972 this._refresh(); 16973 16974 // Turning off autocomplete prevents the browser from remembering the 16975 // value when navigating through history, so we re-enable autocomplete 16976 // if the page is unloaded before the widget is destroyed. #7790 16977 this._on( this.window, { 16978 beforeunload: function() { 16979 this.element.removeAttr( "autocomplete" ); 16980 } 16981 } ); 16982 }, 16983 16984 _getCreateOptions: function() { 16985 var options = this._super(); 16986 var element = this.element; 16987 16988 $.each( [ "min", "max", "step" ], function( i, option ) { 16989 var value = element.attr( option ); 16990 if ( value != null && value.length ) { 16991 options[ option ] = value; 16992 } 16993 } ); 16994 16995 return options; 16996 }, 16997 16998 _events: { 16999 keydown: function( event ) { 17000 if ( this._start( event ) && this._keydown( event ) ) { 17001 event.preventDefault(); 17002 } 17003 }, 17004 keyup: "_stop", 17005 focus: function() { 17006 this.previous = this.element.val(); 17007 }, 17008 blur: function( event ) { 17009 this._stop(); 17010 this._refresh(); 17011 if ( this.previous !== this.element.val() ) { 17012 this._trigger( "change", event ); 17013 } 17014 }, 17015 mousewheel: function( event, delta ) { 17016 var activeElement = this.document[ 0 ].activeElement; 17017 var isActive = this.element[ 0 ] === activeElement; 17018 17019 if ( !isActive || !delta ) { 17020 return; 17021 } 17022 17023 if ( !this.spinning && !this._start( event ) ) { 17024 return false; 17025 } 17026 17027 this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event ); 17028 clearTimeout( this.mousewheelTimer ); 17029 this.mousewheelTimer = this._delay( function() { 17030 if ( this.spinning ) { 17031 this._stop( event ); 17032 } 17033 }, 100 ); 17034 event.preventDefault(); 17035 }, 17036 "mousedown .ui-spinner-button": function( event ) { 17037 var previous; 17038 17039 // We never want the buttons to have focus; whenever the user is 17040 // interacting with the spinner, the focus should be on the input. 17041 // If the input is focused then this.previous is properly set from 17042 // when the input first received focus. If the input is not focused 17043 // then we need to set this.previous based on the value before spinning. 17044 previous = this.element[ 0 ] === this.document[ 0 ].activeElement ? 17045 this.previous : this.element.val(); 17046 function checkFocus() { 17047 var isActive = this.element[ 0 ] === this.document[ 0 ].activeElement; 17048 if ( !isActive ) { 17049 this.element.trigger( "focus" ); 17050 this.previous = previous; 17051 } 17052 } 17053 17054 // Ensure focus is on (or stays on) the text field 17055 event.preventDefault(); 17056 checkFocus.call( this ); 17057 17058 if ( this._start( event ) === false ) { 17059 return; 17060 } 17061 17062 this._repeat( null, $( event.currentTarget ) 17063 .hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 17064 }, 17065 "mouseup .ui-spinner-button": "_stop", 17066 "mouseenter .ui-spinner-button": function( event ) { 17067 17068 // button will add ui-state-active if mouse was down while mouseleave and kept down 17069 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) { 17070 return; 17071 } 17072 17073 if ( this._start( event ) === false ) { 17074 return false; 17075 } 17076 this._repeat( null, $( event.currentTarget ) 17077 .hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 17078 }, 17079 17080 // TODO: do we really want to consider this a stop? 17081 // shouldn't we just stop the repeater and wait until mouseup before 17082 // we trigger the stop event? 17083 "mouseleave .ui-spinner-button": "_stop" 17084 }, 17085 17086 // Support mobile enhanced option and make backcompat more sane 17087 _enhance: function() { 17088 this.uiSpinner = this.element 17089 .attr( "autocomplete", "off" ) 17090 .wrap( "<span>" ) 17091 .parent() 17092 17093 // Add buttons 17094 .append( 17095 "<a></a><a></a>" 17096 ); 17097 }, 17098 17099 _draw: function() { 17100 this._enhance(); 17101 17102 this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" ); 17103 this._addClass( "ui-spinner-input" ); 17104 17105 this.element.attr( "role", "spinbutton" ); 17106 17107 // Button bindings 17108 this.buttons = this.uiSpinner.children( "a" ) 17109 .attr( "tabIndex", -1 ) 17110 .attr( "aria-hidden", true ) 17111 .button( { 17112 classes: { 17113 "ui-button": "" 17114 } 17115 } ); 17116 17117 // TODO: Right now button does not support classes this is already updated in button PR 17118 this._removeClass( this.buttons, "ui-corner-all" ); 17119 17120 this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" ); 17121 this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" ); 17122 this.buttons.first().button( { 17123 "icon": this.options.icons.up, 17124 "showLabel": false 17125 } ); 17126 this.buttons.last().button( { 17127 "icon": this.options.icons.down, 17128 "showLabel": false 17129 } ); 17130 17131 // IE 6 doesn't understand height: 50% for the buttons 17132 // unless the wrapper has an explicit height 17133 if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) && 17134 this.uiSpinner.height() > 0 ) { 17135 this.uiSpinner.height( this.uiSpinner.height() ); 17136 } 17137 }, 17138 17139 _keydown: function( event ) { 17140 var options = this.options, 17141 keyCode = $.ui.keyCode; 17142 17143 switch ( event.keyCode ) { 17144 case keyCode.UP: 17145 this._repeat( null, 1, event ); 17146 return true; 17147 case keyCode.DOWN: 17148 this._repeat( null, -1, event ); 17149 return true; 17150 case keyCode.PAGE_UP: 17151 this._repeat( null, options.page, event ); 17152 return true; 17153 case keyCode.PAGE_DOWN: 17154 this._repeat( null, -options.page, event ); 17155 return true; 17156 } 17157 17158 return false; 17159 }, 17160 17161 _start: function( event ) { 17162 if ( !this.spinning && this._trigger( "start", event ) === false ) { 17163 return false; 17164 } 17165 17166 if ( !this.counter ) { 17167 this.counter = 1; 17168 } 17169 this.spinning = true; 17170 return true; 17171 }, 17172 17173 _repeat: function( i, steps, event ) { 17174 i = i || 500; 17175 17176 clearTimeout( this.timer ); 17177 this.timer = this._delay( function() { 17178 this._repeat( 40, steps, event ); 17179 }, i ); 17180 17181 this._spin( steps * this.options.step, event ); 17182 }, 17183 17184 _spin: function( step, event ) { 17185 var value = this.value() || 0; 17186 17187 if ( !this.counter ) { 17188 this.counter = 1; 17189 } 17190 17191 value = this._adjustValue( value + step * this._increment( this.counter ) ); 17192 17193 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) { 17194 this._value( value ); 17195 this.counter++; 17196 } 17197 }, 17198 17199 _increment: function( i ) { 17200 var incremental = this.options.incremental; 17201 17202 if ( incremental ) { 17203 return typeof incremental === "function" ? 17204 incremental( i ) : 17205 Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 ); 17206 } 17207 17208 return 1; 17209 }, 17210 17211 _precision: function() { 17212 var precision = this._precisionOf( this.options.step ); 17213 if ( this.options.min !== null ) { 17214 precision = Math.max( precision, this._precisionOf( this.options.min ) ); 17215 } 17216 return precision; 17217 }, 17218 17219 _precisionOf: function( num ) { 17220 var str = num.toString(), 17221 decimal = str.indexOf( "." ); 17222 return decimal === -1 ? 0 : str.length - decimal - 1; 17223 }, 17224 17225 _adjustValue: function( value ) { 17226 var base, aboveMin, 17227 options = this.options; 17228 17229 // Make sure we're at a valid step 17230 // - find out where we are relative to the base (min or 0) 17231 base = options.min !== null ? options.min : 0; 17232 aboveMin = value - base; 17233 17234 // - round to the nearest step 17235 aboveMin = Math.round( aboveMin / options.step ) * options.step; 17236 17237 // - rounding is based on 0, so adjust back to our base 17238 value = base + aboveMin; 17239 17240 // Fix precision from bad JS floating point math 17241 value = parseFloat( value.toFixed( this._precision() ) ); 17242 17243 // Clamp the value 17244 if ( options.max !== null && value > options.max ) { 17245 return options.max; 17246 } 17247 if ( options.min !== null && value < options.min ) { 17248 return options.min; 17249 } 17250 17251 return value; 17252 }, 17253 17254 _stop: function( event ) { 17255 if ( !this.spinning ) { 17256 return; 17257 } 17258 17259 clearTimeout( this.timer ); 17260 clearTimeout( this.mousewheelTimer ); 17261 this.counter = 0; 17262 this.spinning = false; 17263 this._trigger( "stop", event ); 17264 }, 17265 17266 _setOption: function( key, value ) { 17267 var prevValue, first, last; 17268 17269 if ( key === "culture" || key === "numberFormat" ) { 17270 prevValue = this._parse( this.element.val() ); 17271 this.options[ key ] = value; 17272 this.element.val( this._format( prevValue ) ); 17273 return; 17274 } 17275 17276 if ( key === "max" || key === "min" || key === "step" ) { 17277 if ( typeof value === "string" ) { 17278 value = this._parse( value ); 17279 } 17280 } 17281 if ( key === "icons" ) { 17282 first = this.buttons.first().find( ".ui-icon" ); 17283 this._removeClass( first, null, this.options.icons.up ); 17284 this._addClass( first, null, value.up ); 17285 last = this.buttons.last().find( ".ui-icon" ); 17286 this._removeClass( last, null, this.options.icons.down ); 17287 this._addClass( last, null, value.down ); 17288 } 17289 17290 this._super( key, value ); 17291 }, 17292 17293 _setOptionDisabled: function( value ) { 17294 this._super( value ); 17295 17296 this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value ); 17297 this.element.prop( "disabled", !!value ); 17298 this.buttons.button( value ? "disable" : "enable" ); 17299 }, 17300 17301 _setOptions: spinnerModifier( function( options ) { 17302 this._super( options ); 17303 } ), 17304 17305 _parse: function( val ) { 17306 if ( typeof val === "string" && val !== "" ) { 17307 val = window.Globalize && this.options.numberFormat ? 17308 Globalize.parseFloat( val, 10, this.options.culture ) : +val; 17309 } 17310 return val === "" || isNaN( val ) ? null : val; 17311 }, 17312 17313 _format: function( value ) { 17314 if ( value === "" ) { 17315 return ""; 17316 } 17317 return window.Globalize && this.options.numberFormat ? 17318 Globalize.format( value, this.options.numberFormat, this.options.culture ) : 17319 value; 17320 }, 17321 17322 _refresh: function() { 17323 this.element.attr( { 17324 "aria-valuemin": this.options.min, 17325 "aria-valuemax": this.options.max, 17326 17327 // TODO: what should we do with values that can't be parsed? 17328 "aria-valuenow": this._parse( this.element.val() ) 17329 } ); 17330 }, 17331 17332 isValid: function() { 17333 var value = this.value(); 17334
vendor: 4,519 bytes, lines 17335-17504
17335 // Null is invalid 17336 if ( value === null ) { 17337 return false; 17338 } 17339 17340 // If value gets adjusted, it's invalid 17341 return value === this._adjustValue( value ); 17342 }, 17343 17344 // Update the value without triggering change 17345 _value: function( value, allowAny ) { 17346 var parsed; 17347 if ( value !== "" ) { 17348 parsed = this._parse( value ); 17349 if ( parsed !== null ) { 17350 if ( !allowAny ) { 17351 parsed = this._adjustValue( parsed ); 17352 } 17353 value = this._format( parsed ); 17354 } 17355 } 17356 this.element.val( value ); 17357 this._refresh(); 17358 }, 17359 17360 _destroy: function() { 17361 this.element 17362 .prop( "disabled", false ) 17363 .removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" ); 17364 17365 this.uiSpinner.replaceWith( this.element ); 17366 }, 17367 17368 stepUp: spinnerModifier( function( steps ) { 17369 this._stepUp( steps ); 17370 } ), 17371 _stepUp: function( steps ) { 17372 if ( this._start() ) { 17373 this._spin( ( steps || 1 ) * this.options.step ); 17374 this._stop(); 17375 } 17376 }, 17377 17378 stepDown: spinnerModifier( function( steps ) { 17379 this._stepDown( steps ); 17380 } ), 17381 _stepDown: function( steps ) { 17382 if ( this._start() ) { 17383 this._spin( ( steps || 1 ) * -this.options.step ); 17384 this._stop(); 17385 } 17386 }, 17387 17388 pageUp: spinnerModifier( function( pages ) { 17389 this._stepUp( ( pages || 1 ) * this.options.page ); 17390 } ), 17391 17392 pageDown: spinnerModifier( function( pages ) { 17393 this._stepDown( ( pages || 1 ) * this.options.page ); 17394 } ), 17395 17396 value: function( newVal ) { 17397 if ( !arguments.length ) { 17398 return this._parse( this.element.val() ); 17399 } 17400 spinnerModifier( this._value ).call( this, newVal ); 17401 }, 17402 17403 widget: function() { 17404 return this.uiSpinner; 17405 } 17406} ); 17407 17408// DEPRECATED 17409// TODO: switch return back to widget declaration at top of file when this is removed 17410if ( $.uiBackCompat === true ) { 17411 17412 // Backcompat for spinner html extension points 17413 $.widget( "ui.spinner", $.ui.spinner, { 17414 _enhance: function() { 17415 this.uiSpinner = this.element 17416 .attr( "autocomplete", "off" ) 17417 .wrap( this._uiSpinnerHtml() ) 17418 .parent() 17419 17420 // Add buttons 17421 .append( this._buttonHtml() ); 17422 }, 17423 _uiSpinnerHtml: function() { 17424 return "<span>"; 17425 }, 17426 17427 _buttonHtml: function() { 17428 return "<a></a><a></a>"; 17429 } 17430 } ); 17431} 17432 17433var widgetsSpinner = $.ui.spinner; 17434 17435 17436/*! 17437 * jQuery UI Tabs 1.14.1 17438 * https://jqueryui.com 17439 * 17440 * Copyright OpenJS Foundation and other contributors 17441 * Released under the MIT license. 17442 * https://jquery.org/license 17443 */ 17444 17445//>>label: Tabs 17446//>>group: Widgets 17447//>>description: Transforms a set of container elements into a tab structure. 17448//>>docs: https://api.jqueryui.com/tabs/ 17449//>>demos: https://jqueryui.com/tabs/ 17450//>>css.structure: ../../themes/base/core.css 17451//>>css.structure: ../../themes/base/tabs.css 17452//>>css.theme: ../../themes/base/theme.css 17453 17454 17455$.widget( "ui.tabs", { 17456 version: "1.14.1", 17457 delay: 300, 17458 options: { 17459 active: null, 17460 classes: { 17461 "ui-tabs": "ui-corner-all", 17462 "ui-tabs-nav": "ui-corner-all", 17463 "ui-tabs-panel": "ui-corner-bottom", 17464 "ui-tabs-tab": "ui-corner-top" 17465 }, 17466 collapsible: false, 17467 event: "click", 17468 heightStyle: "content", 17469 hide: null, 17470 show: null, 17471 17472 // Callbacks 17473 activate: null, 17474 beforeActivate: null, 17475 beforeLoad: null, 17476 load: null 17477 }, 17478 17479 _isLocal: ( function() { 17480 var rhash = /#.*$/; 17481 17482 return function( anchor ) { 17483 var anchorUrl, locationUrl; 17484 17485 anchorUrl = anchor.href.replace( rhash, "" ); 17486 locationUrl = location.href.replace( rhash, "" ); 17487 17488 // Decoding may throw an error if the URL isn't UTF-8 (#9518) 17489 try { 17490 anchorUrl = decodeURIComponent( anchorUrl ); 17491 } catch ( error ) {} 17492 try { 17493 locationUrl = decodeURIComponent( locationUrl ); 17494 } catch ( error ) {} 17495 17496 return anchor.hash.length > 1 && anchorUrl === locationUrl; 17497 }; 17498 } )(), 17499 17500 _create: function() { 17501 var that = this, 17502 options = this.options; 17503 17504 this.running = false;
vendor: 25,994 bytes, lines 17505-18310
17505 17506 this._addClass( "ui-tabs", "ui-widget ui-widget-content" ); 17507 this._toggleClass( "ui-tabs-collapsible", null, options.collapsible ); 17508 17509 this._processTabs(); 17510 options.active = this._initialActive(); 17511 17512 // Take disabling tabs via class attribute from HTML 17513 // into account and update option properly. 17514 if ( Array.isArray( options.disabled ) ) { 17515 options.disabled = $.uniqueSort( options.disabled.concat( 17516 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { 17517 return that.tabs.index( li ); 17518 } ) 17519 ) ).sort(); 17520 } 17521 17522 // Check for length avoids error when initializing empty list 17523 if ( this.options.active !== false && this.anchors.length ) { 17524 this.active = this._findActive( options.active ); 17525 } else { 17526 this.active = $(); 17527 } 17528 17529 this._refresh(); 17530 17531 if ( this.active.length ) { 17532 this.load( options.active ); 17533 } 17534 }, 17535 17536 _initialActive: function() { 17537 var active = this.options.active, 17538 collapsible = this.options.collapsible, 17539 locationHashDecoded = decodeURIComponent( location.hash.substring( 1 ) ); 17540 17541 if ( active === null ) { 17542 17543 // check the fragment identifier in the URL 17544 if ( locationHashDecoded ) { 17545 this.tabs.each( function( i, tab ) { 17546 if ( $( tab ).attr( "aria-controls" ) === locationHashDecoded ) { 17547 active = i; 17548 return false; 17549 } 17550 } ); 17551 } 17552 17553 // Check for a tab marked active via a class 17554 if ( active === null ) { 17555 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); 17556 } 17557 17558 // No active tab, set to false 17559 if ( active === null || active === -1 ) { 17560 active = this.tabs.length ? 0 : false; 17561 } 17562 } 17563 17564 // Handle numbers: negative, out of range 17565 if ( active !== false ) { 17566 active = this.tabs.index( this.tabs.eq( active ) ); 17567 if ( active === -1 ) { 17568 active = collapsible ? false : 0; 17569 } 17570 } 17571 17572 // Don't allow collapsible: false and active: false 17573 if ( !collapsible && active === false && this.anchors.length ) { 17574 active = 0; 17575 } 17576 17577 return active; 17578 }, 17579 17580 _getCreateEventData: function() { 17581 return { 17582 tab: this.active, 17583 panel: !this.active.length ? $() : this._getPanelForTab( this.active ) 17584 }; 17585 }, 17586 17587 _tabKeydown: function( event ) { 17588 var focusedTab = $( this.document[ 0 ].activeElement ).closest( "li" ), 17589 selectedIndex = this.tabs.index( focusedTab ), 17590 goingForward = true; 17591 17592 if ( this._handlePageNav( event ) ) { 17593 return; 17594 } 17595 17596 switch ( event.keyCode ) { 17597 case $.ui.keyCode.RIGHT: 17598 case $.ui.keyCode.DOWN: 17599 selectedIndex++; 17600 break; 17601 case $.ui.keyCode.UP: 17602 case $.ui.keyCode.LEFT: 17603 goingForward = false; 17604 selectedIndex--; 17605 break; 17606 case $.ui.keyCode.END: 17607 selectedIndex = this.anchors.length - 1; 17608 break; 17609 case $.ui.keyCode.HOME: 17610 selectedIndex = 0; 17611 break; 17612 case $.ui.keyCode.SPACE: 17613 17614 // Activate only, no collapsing 17615 event.preventDefault(); 17616 clearTimeout( this.activating ); 17617 this._activate( selectedIndex ); 17618 return; 17619 case $.ui.keyCode.ENTER: 17620 17621 // Toggle (cancel delayed activation, allow collapsing) 17622 event.preventDefault(); 17623 clearTimeout( this.activating ); 17624 17625 // Determine if we should collapse or activate 17626 this._activate( selectedIndex === this.options.active ? false : selectedIndex ); 17627 return; 17628 default: 17629 return; 17630 } 17631 17632 // Focus the appropriate tab, based on which key was pressed 17633 event.preventDefault(); 17634 clearTimeout( this.activating ); 17635 selectedIndex = this._focusNextTab( selectedIndex, goingForward ); 17636 17637 // Navigating with control/command key will prevent automatic activation 17638 if ( !event.ctrlKey && !event.metaKey ) { 17639 17640 // Update aria-selected immediately so that AT think the tab is already selected. 17641 // Otherwise AT may confuse the user by stating that they need to activate the tab, 17642 // but the tab will already be activated by the time the announcement finishes. 17643 focusedTab.attr( "aria-selected", "false" ); 17644 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); 17645 17646 this.activating = this._delay( function() { 17647 this.option( "active", selectedIndex ); 17648 }, this.delay ); 17649 } 17650 }, 17651 17652 _panelKeydown: function( event ) { 17653 if ( this._handlePageNav( event ) ) { 17654 return; 17655 } 17656 17657 // Ctrl+up moves focus to the current tab 17658 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { 17659 event.preventDefault(); 17660 this.active.trigger( "focus" ); 17661 } 17662 }, 17663 17664 // Alt+page up/down moves focus to the previous/next tab (and activates) 17665 _handlePageNav: function( event ) { 17666 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { 17667 this._activate( this._focusNextTab( this.options.active - 1, false ) ); 17668 return true; 17669 } 17670 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { 17671 this._activate( this._focusNextTab( this.options.active + 1, true ) ); 17672 return true; 17673 } 17674 }, 17675 17676 _findNextTab: function( index, goingForward ) { 17677 var lastTabIndex = this.tabs.length - 1; 17678 17679 function constrain() { 17680 if ( index > lastTabIndex ) { 17681 index = 0; 17682 } 17683 if ( index < 0 ) { 17684 index = lastTabIndex; 17685 } 17686 return index; 17687 } 17688 17689 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { 17690 index = goingForward ? index + 1 : index - 1; 17691 } 17692 17693 return index; 17694 }, 17695 17696 _focusNextTab: function( index, goingForward ) { 17697 index = this._findNextTab( index, goingForward ); 17698 this.tabs.eq( index ).trigger( "focus" ); 17699 return index; 17700 }, 17701 17702 _setOption: function( key, value ) { 17703 if ( key === "active" ) { 17704 17705 // _activate() will handle invalid values and update this.options 17706 this._activate( value ); 17707 return; 17708 } 17709 17710 this._super( key, value ); 17711 17712 if ( key === "collapsible" ) { 17713 this._toggleClass( "ui-tabs-collapsible", null, value ); 17714 17715 // Setting collapsible: false while collapsed; open first panel 17716 if ( !value && this.options.active === false ) { 17717 this._activate( 0 ); 17718 } 17719 } 17720 17721 if ( key === "event" ) { 17722 this._setupEvents( value ); 17723 } 17724 17725 if ( key === "heightStyle" ) { 17726 this._setupHeightStyle( value ); 17727 } 17728 }, 17729 17730 refresh: function() { 17731 var options = this.options, 17732 lis = this.tablist.children( ":has(a[href])" ); 17733 17734 // Get disabled tabs from class attribute from HTML 17735 // this will get converted to a boolean if needed in _refresh() 17736 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { 17737 return lis.index( tab ); 17738 } ); 17739 17740 this._processTabs(); 17741 17742 // Was collapsed or no tabs 17743 if ( options.active === false || !this.anchors.length ) { 17744 options.active = false; 17745 this.active = $(); 17746 17747 // was active, but active tab is gone 17748 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { 17749 17750 // all remaining tabs are disabled 17751 if ( this.tabs.length === options.disabled.length ) { 17752 options.active = false; 17753 this.active = $(); 17754 17755 // activate previous tab 17756 } else { 17757 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); 17758 } 17759 17760 // was active, active tab still exists 17761 } else { 17762 17763 // make sure active index is correct 17764 options.active = this.tabs.index( this.active ); 17765 } 17766 17767 this._refresh(); 17768 }, 17769 17770 _refresh: function() { 17771 this._setOptionDisabled( this.options.disabled ); 17772 this._setupEvents( this.options.event ); 17773 this._setupHeightStyle( this.options.heightStyle ); 17774 17775 this.tabs.not( this.active ).attr( { 17776 "aria-selected": "false", 17777 "aria-expanded": "false", 17778 tabIndex: -1 17779 } ); 17780 this.panels.not( this._getPanelForTab( this.active ) ) 17781 .hide() 17782 .attr( { 17783 "aria-hidden": "true" 17784 } ); 17785 17786 // Make sure one tab is in the tab order 17787 if ( !this.active.length ) { 17788 this.tabs.eq( 0 ).attr( "tabIndex", 0 ); 17789 } else { 17790 this.active 17791 .attr( { 17792 "aria-selected": "true", 17793 "aria-expanded": "true", 17794 tabIndex: 0 17795 } ); 17796 this._addClass( this.active, "ui-tabs-active", "ui-state-active" ); 17797 this._getPanelForTab( this.active ) 17798 .show() 17799 .attr( { 17800 "aria-hidden": "false" 17801 } ); 17802 } 17803 }, 17804 17805 _processTabs: function() { 17806 var that = this, 17807 prevTabs = this.tabs, 17808 prevAnchors = this.anchors, 17809 prevPanels = this.panels; 17810 17811 this.tablist = this._getList().attr( "role", "tablist" ); 17812 this._addClass( this.tablist, "ui-tabs-nav", 17813 "ui-helper-reset ui-helper-clearfix ui-widget-header" ); 17814 17815 // Prevent users from focusing disabled tabs via click 17816 this.tablist 17817 .on( "mousedown" + this.eventNamespace, "> li", function( event ) { 17818 if ( $( this ).is( ".ui-state-disabled" ) ) { 17819 event.preventDefault(); 17820 } 17821 } ); 17822 17823 this.tabs = this.tablist.find( "> li:has(a[href])" ) 17824 .attr( { 17825 role: "tab", 17826 tabIndex: -1 17827 } ); 17828 this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" ); 17829 17830 this.anchors = this.tabs.map( function() { 17831 return $( "a", this )[ 0 ]; 17832 } ) 17833 .attr( { 17834 tabIndex: -1 17835 } ); 17836 this._addClass( this.anchors, "ui-tabs-anchor" ); 17837 17838 this.panels = $(); 17839 17840 this.anchors.each( function( i, anchor ) { 17841 var selector, panel, panelId, 17842 anchorId = $( anchor ).uniqueId().attr( "id" ), 17843 tab = $( anchor ).closest( "li" ), 17844 originalAriaControls = tab.attr( "aria-controls" ); 17845 17846 // Inline tab 17847 if ( that._isLocal( anchor ) ) { 17848 selector = decodeURIComponent( anchor.hash ); 17849 panelId = selector.substring( 1 ); 17850 panel = that.element.find( "#" + CSS.escape( panelId ) ); 17851 17852 // remote tab 17853 } else { 17854 17855 // If the tab doesn't already have aria-controls, 17856 // generate an id by using a throw-away element 17857 panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id; 17858 selector = "#" + panelId; 17859 panel = that.element.find( selector ); 17860 if ( !panel.length ) { 17861 panel = that._createPanel( panelId ); 17862 panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); 17863 } 17864 panel.attr( "aria-live", "polite" ); 17865 } 17866 17867 if ( panel.length ) { 17868 that.panels = that.panels.add( panel ); 17869 } 17870 if ( originalAriaControls ) { 17871 tab.data( "ui-tabs-aria-controls", originalAriaControls ); 17872 } 17873 tab.attr( { 17874 "aria-controls": panelId, 17875 "aria-labelledby": anchorId 17876 } ); 17877 panel.attr( "aria-labelledby", anchorId ); 17878 } ); 17879 17880 this.panels.attr( "role", "tabpanel" ); 17881 this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" ); 17882 17883 // Avoid memory leaks (#10056) 17884 if ( prevTabs ) { 17885 this._off( prevTabs.not( this.tabs ) ); 17886 this._off( prevAnchors.not( this.anchors ) ); 17887 this._off( prevPanels.not( this.panels ) ); 17888 } 17889 }, 17890 17891 // Allow overriding how to find the list for rare usage scenarios (#7715) 17892 _getList: function() { 17893 return this.tablist || this.element.find( "ol, ul" ).eq( 0 ); 17894 }, 17895 17896 _createPanel: function( id ) { 17897 return $( "<div>" ) 17898 .attr( "id", id ) 17899 .data( "ui-tabs-destroy", true ); 17900 }, 17901 17902 _setOptionDisabled: function( disabled ) { 17903 var currentItem, li, i; 17904 17905 if ( Array.isArray( disabled ) ) { 17906 if ( !disabled.length ) { 17907 disabled = false; 17908 } else if ( disabled.length === this.anchors.length ) { 17909 disabled = true; 17910 } 17911 } 17912 17913 // Disable tabs 17914 for ( i = 0; ( li = this.tabs[ i ] ); i++ ) { 17915 currentItem = $( li ); 17916 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { 17917 currentItem.attr( "aria-disabled", "true" ); 17918 this._addClass( currentItem, null, "ui-state-disabled" ); 17919 } else { 17920 currentItem.removeAttr( "aria-disabled" ); 17921 this._removeClass( currentItem, null, "ui-state-disabled" ); 17922 } 17923 } 17924 17925 this.options.disabled = disabled; 17926 17927 this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, 17928 disabled === true ); 17929 }, 17930 17931 _setupEvents: function( event ) { 17932 var events = {}; 17933 if ( event ) { 17934 $.each( event.split( " " ), function( index, eventName ) { 17935 events[ eventName ] = "_eventHandler"; 17936 } ); 17937 } 17938 17939 this._off( this.anchors.add( this.tabs ).add( this.panels ) ); 17940 17941 // Always prevent the default action, even when disabled 17942 this._on( true, this.anchors, { 17943 click: function( event ) { 17944 event.preventDefault(); 17945 } 17946 } ); 17947 this._on( this.anchors, events ); 17948 this._on( this.tabs, { keydown: "_tabKeydown" } ); 17949 this._on( this.panels, { keydown: "_panelKeydown" } ); 17950 17951 this._focusable( this.tabs ); 17952 this._hoverable( this.tabs ); 17953 }, 17954 17955 _setupHeightStyle: function( heightStyle ) { 17956 var maxHeight, 17957 parent = this.element.parent(); 17958 17959 if ( heightStyle === "fill" ) { 17960 maxHeight = parent.height(); 17961 maxHeight -= this.element.outerHeight() - this.element.height(); 17962 17963 this.element.siblings( ":visible" ).each( function() { 17964 var elem = $( this ), 17965 position = elem.css( "position" ); 17966 17967 if ( position === "absolute" || position === "fixed" ) { 17968 return; 17969 } 17970 maxHeight -= elem.outerHeight( true ); 17971 } ); 17972 17973 this.element.children().not( this.panels ).each( function() { 17974 maxHeight -= $( this ).outerHeight( true ); 17975 } ); 17976 17977 this.panels.each( function() { 17978 $( this ).height( Math.max( 0, maxHeight - 17979 $( this ).innerHeight() + $( this ).height() ) ); 17980 } ) 17981 .css( "overflow", "auto" ); 17982 } else if ( heightStyle === "auto" ) { 17983 maxHeight = 0; 17984 this.panels.each( function() { 17985 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); 17986 } ).height( maxHeight ); 17987 } 17988 }, 17989 17990 _eventHandler: function( event ) { 17991 var options = this.options, 17992 active = this.active, 17993 anchor = $( event.currentTarget ), 17994 tab = anchor.closest( "li" ), 17995 clickedIsActive = tab[ 0 ] === active[ 0 ], 17996 collapsing = clickedIsActive && options.collapsible, 17997 toShow = collapsing ? $() : this._getPanelForTab( tab ), 17998 toHide = !active.length ? $() : this._getPanelForTab( active ), 17999 eventData = { 18000 oldTab: active, 18001 oldPanel: toHide, 18002 newTab: collapsing ? $() : tab, 18003 newPanel: toShow 18004 }; 18005 18006 event.preventDefault(); 18007 18008 if ( tab.hasClass( "ui-state-disabled" ) || 18009 18010 // tab is already loading 18011 tab.hasClass( "ui-tabs-loading" ) || 18012 18013 // can't switch durning an animation 18014 this.running || 18015 18016 // click on active header, but not collapsible 18017 ( clickedIsActive && !options.collapsible ) || 18018 18019 // allow canceling activation 18020 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 18021 return; 18022 } 18023 18024 options.active = collapsing ? false : this.tabs.index( tab ); 18025 18026 this.active = clickedIsActive ? $() : tab; 18027 if ( this.xhr ) { 18028 this.xhr.abort(); 18029 } 18030 18031 if ( !toHide.length && !toShow.length ) { 18032 $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); 18033 } 18034 18035 if ( toShow.length ) { 18036 this.load( this.tabs.index( tab ), event ); 18037 } 18038 this._toggle( event, eventData ); 18039 }, 18040 18041 // Handles show/hide for selecting tabs 18042 _toggle: function( event, eventData ) { 18043 var that = this, 18044 toShow = eventData.newPanel, 18045 toHide = eventData.oldPanel; 18046 18047 this.running = true; 18048 18049 function complete() { 18050 that.running = false; 18051 that._trigger( "activate", event, eventData ); 18052 } 18053 18054 function show() { 18055 that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" ); 18056 18057 if ( toShow.length && that.options.show ) { 18058 that._show( toShow, that.options.show, complete ); 18059 } else { 18060 toShow.show(); 18061 complete(); 18062 } 18063 } 18064 18065 // Start out by hiding, then showing, then completing 18066 if ( toHide.length && this.options.hide ) { 18067 this._hide( toHide, this.options.hide, function() { 18068 that._removeClass( eventData.oldTab.closest( "li" ), 18069 "ui-tabs-active", "ui-state-active" ); 18070 show(); 18071 } ); 18072 } else { 18073 this._removeClass( eventData.oldTab.closest( "li" ), 18074 "ui-tabs-active", "ui-state-active" ); 18075 toHide.hide(); 18076 show(); 18077 } 18078 18079 toHide.attr( "aria-hidden", "true" ); 18080 eventData.oldTab.attr( { 18081 "aria-selected": "false", 18082 "aria-expanded": "false" 18083 } ); 18084 18085 // If we're switching tabs, remove the old tab from the tab order. 18086 // If we're opening from collapsed state, remove the previous tab from the tab order. 18087 // If we're collapsing, then keep the collapsing tab in the tab order. 18088 if ( toShow.length && toHide.length ) { 18089 eventData.oldTab.attr( "tabIndex", -1 ); 18090 } else if ( toShow.length ) { 18091 this.tabs.filter( function() { 18092 return $( this ).attr( "tabIndex" ) === 0; 18093 } ) 18094 .attr( "tabIndex", -1 ); 18095 } 18096 18097 toShow.attr( "aria-hidden", "false" ); 18098 eventData.newTab.attr( { 18099 "aria-selected": "true", 18100 "aria-expanded": "true", 18101 tabIndex: 0 18102 } ); 18103 }, 18104 18105 _activate: function( index ) { 18106 var anchor, 18107 active = this._findActive( index ); 18108 18109 // Trying to activate the already active panel 18110 if ( active[ 0 ] === this.active[ 0 ] ) { 18111 return; 18112 } 18113 18114 // Trying to collapse, simulate a click on the current active header 18115 if ( !active.length ) { 18116 active = this.active; 18117 } 18118 18119 anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; 18120 this._eventHandler( { 18121 target: anchor, 18122 currentTarget: anchor, 18123 preventDefault: $.noop 18124 } ); 18125 }, 18126 18127 _findActive: function( index ) { 18128 return index === false ? $() : this.tabs.eq( index ); 18129 }, 18130 18131 _getIndex: function( index ) { 18132 18133 // meta-function to give users option to provide a href string instead of a numerical index. 18134 if ( typeof index === "string" ) { 18135 index = this.anchors.index( this.anchors.filter( "[href$='" + 18136 CSS.escape( index ) + "']" ) ); 18137 } 18138 18139 return index; 18140 }, 18141 18142 _destroy: function() { 18143 if ( this.xhr ) { 18144 this.xhr.abort(); 18145 } 18146 18147 this.tablist 18148 .removeAttr( "role" ) 18149 .off( this.eventNamespace ); 18150 18151 this.anchors 18152 .removeAttr( "role tabIndex" ) 18153 .removeUniqueId(); 18154 18155 this.tabs.add( this.panels ).each( function() { 18156 if ( $.data( this, "ui-tabs-destroy" ) ) { 18157 $( this ).remove(); 18158 } else { 18159 $( this ).removeAttr( "role tabIndex " + 18160 "aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" ); 18161 } 18162 } ); 18163 18164 this.tabs.each( function() { 18165 var li = $( this ), 18166 prev = li.data( "ui-tabs-aria-controls" ); 18167 if ( prev ) { 18168 li 18169 .attr( "aria-controls", prev ) 18170 .removeData( "ui-tabs-aria-controls" ); 18171 } else { 18172 li.removeAttr( "aria-controls" ); 18173 } 18174 } ); 18175 18176 this.panels.show(); 18177 18178 if ( this.options.heightStyle !== "content" ) { 18179 this.panels.css( "height", "" ); 18180 } 18181 }, 18182 18183 enable: function( index ) { 18184 var disabled = this.options.disabled; 18185 if ( disabled === false ) { 18186 return; 18187 } 18188 18189 if ( index === undefined ) { 18190 disabled = false; 18191 } else { 18192 index = this._getIndex( index ); 18193 if ( Array.isArray( disabled ) ) { 18194 disabled = $.map( disabled, function( num ) { 18195 return num !== index ? num : null; 18196 } ); 18197 } else { 18198 disabled = $.map( this.tabs, function( li, num ) { 18199 return num !== index ? num : null; 18200 } ); 18201 } 18202 } 18203 this._setOptionDisabled( disabled ); 18204 }, 18205 18206 disable: function( index ) { 18207 var disabled = this.options.disabled; 18208 if ( disabled === true ) { 18209 return; 18210 } 18211 18212 if ( index === undefined ) { 18213 disabled = true; 18214 } else { 18215 index = this._getIndex( index ); 18216 if ( $.inArray( index, disabled ) !== -1 ) { 18217 return; 18218 } 18219 if ( Array.isArray( disabled ) ) { 18220 disabled = $.merge( [ index ], disabled ).sort(); 18221 } else { 18222 disabled = [ index ]; 18223 } 18224 } 18225 this._setOptionDisabled( disabled ); 18226 }, 18227 18228 load: function( index, event ) { 18229 index = this._getIndex( index ); 18230 var that = this, 18231 tab = this.tabs.eq( index ), 18232 anchor = tab.find( ".ui-tabs-anchor" ), 18233 panel = this._getPanelForTab( tab ), 18234 eventData = { 18235 tab: tab, 18236 panel: panel 18237 }, 18238 complete = function( jqXHR, status ) { 18239 if ( status === "abort" ) { 18240 that.panels.stop( false, true ); 18241 } 18242 18243 that._removeClass( tab, "ui-tabs-loading" ); 18244 panel.removeAttr( "aria-busy" ); 18245 18246 if ( jqXHR === that.xhr ) { 18247 delete that.xhr; 18248 } 18249 }; 18250 18251 // Not remote 18252 if ( this._isLocal( anchor[ 0 ] ) ) { 18253 return; 18254 } 18255 18256 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); 18257 18258 if ( this.xhr.statusText !== "canceled" ) { 18259 this._addClass( tab, "ui-tabs-loading" ); 18260 panel.attr( "aria-busy", "true" ); 18261 18262 this.xhr 18263 .done( function( response, status, jqXHR ) { 18264 panel.html( response ); 18265 that._trigger( "load", event, eventData ); 18266 18267 complete( jqXHR, status ); 18268 } ) 18269 .fail( function( jqXHR, status ) { 18270 complete( jqXHR, status ); 18271 } ); 18272 } 18273 }, 18274 18275 _ajaxSettings: function( anchor, event, eventData ) { 18276 var that = this; 18277 return { 18278 url: anchor.attr( "href" ), 18279 beforeSend: function( jqXHR, settings ) { 18280 return that._trigger( "beforeLoad", event, 18281 $.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) ); 18282 } 18283 }; 18284 }, 18285 18286 _getPanelForTab: function( tab ) { 18287 var id = $( tab ).attr( "aria-controls" ); 18288 return this.element.find( "#" + CSS.escape( id ) ); 18289 } 18290} ); 18291 18292// DEPRECATED 18293// TODO: Switch return back to widget declaration at top of file when this is removed 18294if ( $.uiBackCompat === true ) { 18295 18296 // Backcompat for ui-tab class (now ui-tabs-tab) 18297 $.widget( "ui.tabs", $.ui.tabs, { 18298 _processTabs: function() { 18299 this._superApply( arguments ); 18300 this._addClass( this.tabs, "ui-tab" ); 18301 } 18302 } ); 18303} 18304 18305var widgetsTabs = $.ui.tabs; 18306 18307 18308 18309 18310} );
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.