vendor: 394,837 bytes, lines 1-13934
1/*! jQuery UI - v1.12.1 - 2016-09-14 2* http://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-1-7.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js 4* Copyright jQuery Foundation and other contributors; Licensed MIT */ 5 6(function( factory ) { 7 if ( typeof define === "function" && define.amd ) { 8 9 // AMD. Register as an anonymous module. 10 define([ "jquery" ], factory ); 11 } else { 12 13 // Browser globals 14 factory( jQuery ); 15 } 16}(function( $ ) { 17 18$.ui = $.ui || {}; 19 20var version = $.ui.version = "1.12.1"; 21 22 23/*! 24 * jQuery UI Widget 1.12.1 25 * http://jqueryui.com 26 * 27 * Copyright jQuery Foundation and other contributors 28 * Released under the MIT license. 29 * http://jquery.org/license 30 */ 31 32//>>label: Widget 33//>>group: Core 34//>>description: Provides a factory for creating stateful widgets with a common API. 35//>>docs: http://api.jqueryui.com/jQuery.widget/ 36//>>demos: http://jqueryui.com/widget/ 37 38 39 40var widgetUuid = 0; 41var widgetSlice = Array.prototype.slice; 42 43$.cleanData = ( function( orig ) { 44 return function( elems ) { 45 var events, elem, i; 46 for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) { 47 try { 48 49 // Only trigger remove when necessary to save time 50 events = $._data( elem, "events" ); 51 if ( events && events.remove ) { 52 $( elem ).triggerHandler( "remove" ); 53 } 54 55 // Http://bugs.jquery.com/ticket/8235 56 } catch ( e ) {} 57 } 58 orig( elems ); 59 }; 60} )( $.cleanData ); 61 62$.widget = function( name, base, prototype ) { 63 var existingConstructor, constructor, basePrototype; 64 65 // ProxiedPrototype allows the provided prototype to remain unmodified 66 // so that it can be used as a mixin for multiple widgets (#8876) 67 var proxiedPrototype = {}; 68 69 var namespace = name.split( "." )[ 0 ]; 70 name = name.split( "." )[ 1 ]; 71 var fullName = namespace + "-" + name; 72 73 if ( !prototype ) { 74 prototype = base; 75 base = $.Widget; 76 } 77 78 if ( $.isArray( prototype ) ) { 79 prototype = $.extend.apply( null, [ {} ].concat( prototype ) ); 80 } 81 82 // Create selector for plugin 83 $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { 84 return !!$.data( elem, fullName ); 85 }; 86 87 $[ namespace ] = $[ namespace ] || {}; 88 existingConstructor = $[ namespace ][ name ]; 89 constructor = $[ namespace ][ name ] = function( options, element ) { 90 91 // Allow instantiation without "new" keyword 92 if ( !this._createWidget ) { 93 return new constructor( options, element ); 94 } 95 96 // Allow instantiation without initializing for simple inheritance 97 // must use "new" keyword (the code above always passes args) 98 if ( arguments.length ) { 99 this._createWidget( options, element ); 100 } 101 }; 102 103 // Extend with the existing constructor to carry over any static properties 104 $.extend( constructor, existingConstructor, { 105 version: prototype.version, 106 107 // Copy the object used to create the prototype in case we need to 108 // redefine the widget later 109 _proto: $.extend( {}, prototype ), 110 111 // Track widgets that inherit from this widget in case this widget is 112 // redefined after a widget inherits from it 113 _childConstructors: [] 114 } ); 115 116 basePrototype = new base(); 117 118 // We need to make the options hash a property directly on the new instance 119 // otherwise we'll modify the options hash on the prototype that we're 120 // inheriting from 121 basePrototype.options = $.widget.extend( {}, basePrototype.options ); 122 $.each( prototype, function( prop, value ) { 123 if ( !$.isFunction( value ) ) { 124 proxiedPrototype[ prop ] = value; 125 return; 126 } 127 proxiedPrototype[ prop ] = ( function() { 128 function _super() { 129 return base.prototype[ prop ].apply( this, arguments ); 130 } 131 132 function _superApply( args ) { 133 return base.prototype[ prop ].apply( this, args ); 134 } 135 136 return function() { 137 var __super = this._super; 138 var __superApply = this._superApply; 139 var returnValue; 140 141 this._super = _super; 142 this._superApply = _superApply; 143 144 returnValue = value.apply( this, arguments ); 145 146 this._super = __super; 147 this._superApply = __superApply; 148 149 return returnValue; 150 }; 151 } )(); 152 } ); 153 constructor.prototype = $.widget.extend( basePrototype, { 154 155 // TODO: remove support for widgetEventPrefix 156 // always use the name + a colon as the prefix, e.g., draggable:start 157 // don't prefix for widgets that aren't DOM-based 158 widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name 159 }, proxiedPrototype, { 160 constructor: constructor, 161 namespace: namespace, 162 widgetName: name, 163 widgetFullName: fullName 164 } ); 165 166 // If this widget is being redefined then we need to find all widgets that 167 // are inheriting from it and redefine all of them so that they inherit from 168 // the new version of this widget. We're essentially trying to replace one 169 // level in the prototype chain. 170 if ( existingConstructor ) { 171 $.each( existingConstructor._childConstructors, function( i, child ) { 172 var childPrototype = child.prototype; 173 174 // Redefine the child widget using the same prototype that was 175 // originally used, but inherit from the new version of the base 176 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, 177 child._proto ); 178 } ); 179 180 // Remove the list of existing child constructors from the old constructor 181 // so the old child constructors can be garbage collected 182 delete existingConstructor._childConstructors; 183 } else { 184 base._childConstructors.push( constructor ); 185 } 186 187 $.widget.bridge( name, constructor ); 188 189 return constructor; 190}; 191 192$.widget.extend = function( target ) { 193 var input = widgetSlice.call( arguments, 1 ); 194 var inputIndex = 0; 195 var inputLength = input.length; 196 var key; 197 var value; 198 199 for ( ; inputIndex < inputLength; inputIndex++ ) { 200 for ( key in input[ inputIndex ] ) { 201 value = input[ inputIndex ][ key ]; 202 if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { 203 204 // Clone objects 205 if ( $.isPlainObject( value ) ) { 206 target[ key ] = $.isPlainObject( target[ key ] ) ? 207 $.widget.extend( {}, target[ key ], value ) : 208 209 // Don't extend strings, arrays, etc. with objects 210 $.widget.extend( {}, value ); 211 212 // Copy everything else by reference 213 } else { 214 target[ key ] = value; 215 } 216 } 217 } 218 } 219 return target; 220}; 221 222$.widget.bridge = function( name, object ) { 223 var fullName = object.prototype.widgetFullName || name; 224 $.fn[ name ] = function( options ) { 225 var isMethodCall = typeof options === "string"; 226 var args = widgetSlice.call( arguments, 1 ); 227 var returnValue = this; 228 229 if ( isMethodCall ) { 230 231 // If this is an empty collection, we need to have the instance method 232 // return undefined instead of the jQuery instance 233 if ( !this.length && options === "instance" ) { 234 returnValue = undefined; 235 } else { 236 this.each( function() { 237 var methodValue; 238 var instance = $.data( this, fullName ); 239 240 if ( options === "instance" ) { 241 returnValue = instance; 242 return false; 243 } 244 245 if ( !instance ) { 246 return $.error( "cannot call methods on " + name + 247 " prior to initialization; " + 248 "attempted to call method '" + options + "'" ); 249 } 250 251 if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) { 252 return $.error( "no such method '" + options + "' for " + name + 253 " widget instance" ); 254 } 255 256 methodValue = instance[ options ].apply( instance, args ); 257 258 if ( methodValue !== instance && methodValue !== undefined ) { 259 returnValue = methodValue && methodValue.jquery ? 260 returnValue.pushStack( methodValue.get() ) : 261 methodValue; 262 return false; 263 } 264 } ); 265 } 266 } else { 267 268 // Allow multiple hashes to be passed on init 269 if ( args.length ) { 270 options = $.widget.extend.apply( null, [ options ].concat( args ) ); 271 } 272 273 this.each( function() { 274 var instance = $.data( this, fullName ); 275 if ( instance ) { 276 instance.option( options || {} ); 277 if ( instance._init ) { 278 instance._init(); 279 } 280 } else { 281 $.data( this, fullName, new object( options, this ) ); 282 } 283 } ); 284 } 285 286 return returnValue; 287 }; 288}; 289 290$.Widget = function( /* options, element */ ) {}; 291$.Widget._childConstructors = []; 292 293$.Widget.prototype = { 294 widgetName: "widget", 295 widgetEventPrefix: "", 296 defaultElement: "<div>", 297 298 options: { 299 classes: {}, 300 disabled: false, 301 302 // Callbacks 303 create: null 304 }, 305 306 _createWidget: function( options, element ) { 307 element = $( element || this.defaultElement || this )[ 0 ]; 308 this.element = $( element ); 309 this.uuid = widgetUuid++; 310 this.eventNamespace = "." + this.widgetName + this.uuid; 311 312 this.bindings = $(); 313 this.hoverable = $(); 314 this.focusable = $(); 315 this.classesElementLookup = {}; 316 317 if ( element !== this ) { 318 $.data( element, this.widgetFullName, this ); 319 this._on( true, this.element, { 320 remove: function( event ) { 321 if ( event.target === element ) { 322 this.destroy(); 323 } 324 } 325 } ); 326 this.document = $( element.style ? 327 328 // Element within the document 329 element.ownerDocument : 330 331 // Element is window or document 332 element.document || element ); 333 this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow ); 334 } 335 336 this.options = $.widget.extend( {}, 337 this.options, 338 this._getCreateOptions(), 339 options ); 340 341 this._create(); 342 343 if ( this.options.disabled ) { 344 this._setOptionDisabled( this.options.disabled ); 345 } 346 347 this._trigger( "create", null, this._getCreateEventData() ); 348 this._init(); 349 }, 350 351 _getCreateOptions: function() { 352 return {}; 353 }, 354 355 _getCreateEventData: $.noop, 356 357 _create: $.noop, 358 359 _init: $.noop, 360 361 destroy: function() { 362 var that = this; 363 364 this._destroy(); 365 $.each( this.classesElementLookup, function( key, value ) { 366 that._removeClass( value, key ); 367 } ); 368 369 // We can probably remove the unbind calls in 2.0 370 // all event bindings should go through this._on() 371 this.element 372 .off( this.eventNamespace ) 373 .removeData( this.widgetFullName ); 374 this.widget() 375 .off( this.eventNamespace ) 376 .removeAttr( "aria-disabled" ); 377 378 // Clean up events and states 379 this.bindings.off( this.eventNamespace ); 380 }, 381 382 _destroy: $.noop, 383 384 widget: function() { 385 return this.element; 386 }, 387 388 option: function( key, value ) { 389 var options = key; 390 var parts; 391 var curOption; 392 var i; 393 394 if ( arguments.length === 0 ) { 395 396 // Don't return a reference to the internal hash 397 return $.widget.extend( {}, this.options ); 398 } 399 400 if ( typeof key === "string" ) { 401 402 // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } 403 options = {}; 404 parts = key.split( "." ); 405 key = parts.shift(); 406 if ( parts.length ) { 407 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); 408 for ( i = 0; i < parts.length - 1; i++ ) { 409 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; 410 curOption = curOption[ parts[ i ] ]; 411 } 412 key = parts.pop(); 413 if ( arguments.length === 1 ) { 414 return curOption[ key ] === undefined ? null : curOption[ key ]; 415 } 416 curOption[ key ] = value; 417 } else { 418 if ( arguments.length === 1 ) { 419 return this.options[ key ] === undefined ? null : this.options[ key ]; 420 } 421 options[ key ] = value; 422 } 423 } 424 425 this._setOptions( options ); 426 427 return this; 428 }, 429 430 _setOptions: function( options ) { 431 var key; 432 433 for ( key in options ) { 434 this._setOption( key, options[ key ] ); 435 } 436 437 return this; 438 }, 439 440 _setOption: function( key, value ) { 441 if ( key === "classes" ) { 442 this._setOptionClasses( value ); 443 } 444 445 this.options[ key ] = value; 446 447 if ( key === "disabled" ) { 448 this._setOptionDisabled( value ); 449 } 450 451 return this; 452 }, 453 454 _setOptionClasses: function( value ) { 455 var classKey, elements, currentElements; 456 457 for ( classKey in value ) { 458 currentElements = this.classesElementLookup[ classKey ]; 459 if ( value[ classKey ] === this.options.classes[ classKey ] || 460 !currentElements || 461 !currentElements.length ) { 462 continue; 463 } 464 465 // We are doing this to create a new jQuery object because the _removeClass() call 466 // on the next line is going to destroy the reference to the current elements being 467 // tracked. We need to save a copy of this collection so that we can add the new classes 468 // below. 469 elements = $( currentElements.get() ); 470 this._removeClass( currentElements, classKey ); 471 472 // We don't use _addClass() here, because that uses this.options.classes 473 // for generating the string of classes. We want to use the value passed in from 474 // _setOption(), this is the new value of the classes option which was passed to 475 // _setOption(). We pass this value directly to _classes(). 476 elements.addClass( this._classes( { 477 element: elements, 478 keys: classKey, 479 classes: value, 480 add: true 481 } ) ); 482 } 483 }, 484 485 _setOptionDisabled: function( value ) { 486 this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value ); 487 488 // If the widget is becoming disabled, then nothing is interactive 489 if ( value ) { 490 this._removeClass( this.hoverable, null, "ui-state-hover" ); 491 this._removeClass( this.focusable, null, "ui-state-focus" ); 492 } 493 }, 494 495 enable: function() { 496 return this._setOptions( { disabled: false } ); 497 }, 498 499 disable: function() { 500 return this._setOptions( { disabled: true } ); 501 }, 502 503 _classes: function( options ) { 504 var full = []; 505 var that = this; 506 507 options = $.extend( { 508 element: this.element, 509 classes: this.options.classes || {} 510 }, options ); 511 512 function processClassString( classes, checkOption ) { 513 var current, i; 514 for ( i = 0; i < classes.length; i++ ) { 515 current = that.classesElementLookup[ classes[ i ] ] || $(); 516 if ( options.add ) { 517 current = $( $.unique( current.get().concat( options.element.get() ) ) ); 518 } else { 519 current = $( current.not( options.element ).get() ); 520 } 521 that.classesElementLookup[ classes[ i ] ] = current; 522 full.push( classes[ i ] ); 523 if ( checkOption && options.classes[ classes[ i ] ] ) { 524 full.push( options.classes[ classes[ i ] ] ); 525 } 526 } 527 } 528 529 this._on( options.element, { 530 "remove": "_untrackClassesElement" 531 } ); 532 533 if ( options.keys ) { 534 processClassString( options.keys.match( /\S+/g ) || [], true ); 535 } 536 if ( options.extra ) { 537 processClassString( options.extra.match( /\S+/g ) || [] ); 538 } 539 540 return full.join( " " ); 541 }, 542 543 _untrackClassesElement: function( event ) { 544 var that = this; 545 $.each( that.classesElementLookup, function( key, value ) { 546 if ( $.inArray( event.target, value ) !== -1 ) { 547 that.classesElementLookup[ key ] = $( value.not( event.target ).get() ); 548 } 549 } ); 550 }, 551 552 _removeClass: function( element, keys, extra ) { 553 return this._toggleClass( element, keys, extra, false ); 554 }, 555 556 _addClass: function( element, keys, extra ) { 557 return this._toggleClass( element, keys, extra, true ); 558 }, 559 560 _toggleClass: function( element, keys, extra, add ) { 561 add = ( typeof add === "boolean" ) ? add : extra; 562 var shift = ( typeof element === "string" || element === null ), 563 options = { 564 extra: shift ? keys : extra, 565 keys: shift ? element : keys, 566 element: shift ? this.element : element, 567 add: add 568 }; 569 options.element.toggleClass( this._classes( options ), add ); 570 return this; 571 }, 572 573 _on: function( suppressDisabledCheck, element, handlers ) { 574 var delegateElement; 575 var instance = this; 576 577 // No suppressDisabledCheck flag, shuffle arguments 578 if ( typeof suppressDisabledCheck !== "boolean" ) { 579 handlers = element; 580 element = suppressDisabledCheck; 581 suppressDisabledCheck = false; 582 } 583 584 // No element argument, shuffle and use this.element 585 if ( !handlers ) { 586 handlers = element; 587 element = this.element; 588 delegateElement = this.widget(); 589 } else { 590 element = delegateElement = $( element ); 591 this.bindings = this.bindings.add( element ); 592 } 593 594 $.each( handlers, function( event, handler ) { 595 function handlerProxy() { 596 597 // Allow widgets to customize the disabled handling 598 // - disabled as an array instead of boolean 599 // - disabled class as method for disabling individual parts 600 if ( !suppressDisabledCheck && 601 ( instance.options.disabled === true || 602 $( this ).hasClass( "ui-state-disabled" ) ) ) { 603 return; 604 } 605 return ( typeof handler === "string" ? instance[ handler ] : handler ) 606 .apply( instance, arguments ); 607 } 608 609 // Copy the guid so direct unbinding works 610 if ( typeof handler !== "string" ) { 611 handlerProxy.guid = handler.guid = 612 handler.guid || handlerProxy.guid || $.guid++; 613 } 614 615 var match = event.match( /^([\w:-]*)\s*(.*)$/ ); 616 var eventName = match[ 1 ] + instance.eventNamespace; 617 var selector = match[ 2 ]; 618 619 if ( selector ) { 620 delegateElement.on( eventName, selector, handlerProxy ); 621 } else { 622 element.on( eventName, handlerProxy ); 623 } 624 } ); 625 }, 626 627 _off: function( element, eventName ) { 628 eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) + 629 this.eventNamespace; 630 element.off( eventName ).off( eventName ); 631 632 // Clear the stack to avoid memory leaks (#10056) 633 this.bindings = $( this.bindings.not( element ).get() ); 634 this.focusable = $( this.focusable.not( element ).get() ); 635 this.hoverable = $( this.hoverable.not( element ).get() ); 636 }, 637 638 _delay: function( handler, delay ) { 639 function handlerProxy() { 640 return ( typeof handler === "string" ? instance[ handler ] : handler ) 641 .apply( instance, arguments ); 642 } 643 var instance = this; 644 return setTimeout( handlerProxy, delay || 0 ); 645 }, 646 647 _hoverable: function( element ) { 648 this.hoverable = this.hoverable.add( element ); 649 this._on( element, { 650 mouseenter: function( event ) { 651 this._addClass( $( event.currentTarget ), null, "ui-state-hover" ); 652 }, 653 mouseleave: function( event ) { 654 this._removeClass( $( event.currentTarget ), null, "ui-state-hover" ); 655 } 656 } ); 657 }, 658 659 _focusable: function( element ) { 660 this.focusable = this.focusable.add( element ); 661 this._on( element, { 662 focusin: function( event ) { 663 this._addClass( $( event.currentTarget ), null, "ui-state-focus" ); 664 }, 665 focusout: function( event ) { 666 this._removeClass( $( event.currentTarget ), null, "ui-state-focus" ); 667 } 668 } ); 669 }, 670 671 _trigger: function( type, event, data ) { 672 var prop, orig; 673 var callback = this.options[ type ]; 674 675 data = data || {}; 676 event = $.Event( event ); 677 event.type = ( type === this.widgetEventPrefix ? 678 type : 679 this.widgetEventPrefix + type ).toLowerCase(); 680 681 // The original event may come from any element 682 // so we need to reset the target on the new event 683 event.target = this.element[ 0 ]; 684 685 // Copy original event properties over to the new event 686 orig = event.originalEvent; 687 if ( orig ) { 688 for ( prop in orig ) { 689 if ( !( prop in event ) ) { 690 event[ prop ] = orig[ prop ]; 691 } 692 } 693 } 694 695 this.element.trigger( event, data ); 696 return !( $.isFunction( callback ) && 697 callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false || 698 event.isDefaultPrevented() ); 699 } 700}; 701 702$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { 703 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { 704 if ( typeof options === "string" ) { 705 options = { effect: options }; 706 } 707 708 var hasOptions; 709 var effectName = !options ? 710 method : 711 options === true || typeof options === "number" ? 712 defaultEffect : 713 options.effect || defaultEffect; 714 715 options = options || {}; 716 if ( typeof options === "number" ) { 717 options = { duration: options }; 718 } 719 720 hasOptions = !$.isEmptyObject( options ); 721 options.complete = callback; 722 723 if ( options.delay ) { 724 element.delay( options.delay ); 725 } 726 727 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { 728 element[ method ]( options ); 729 } else if ( effectName !== method && element[ effectName ] ) { 730 element[ effectName ]( options.duration, options.easing, callback ); 731 } else { 732 element.queue( function( next ) { 733 $( this )[ method ](); 734 if ( callback ) { 735 callback.call( element[ 0 ] ); 736 } 737 next(); 738 } ); 739 } 740 }; 741} ); 742 743var widget = $.widget; 744 745 746/*! 747 * jQuery UI Position 1.12.1 748 * http://jqueryui.com 749 * 750 * Copyright jQuery Foundation and other contributors 751 * Released under the MIT license. 752 * http://jquery.org/license 753 * 754 * http://api.jqueryui.com/position/ 755 */ 756 757//>>label: Position 758//>>group: Core 759//>>description: Positions elements relative to other elements. 760//>>docs: http://api.jqueryui.com/position/ 761//>>demos: http://jqueryui.com/position/ 762 763 764( function() { 765var cachedScrollbarWidth, 766 max = Math.max, 767 abs = Math.abs, 768 rhorizontal = /left|center|right/, 769 rvertical = /top|center|bottom/, 770 roffset = /[\+\-]\d+(\.[\d]+)?%?/, 771 rposition = /^\w+/, 772 rpercent = /%$/, 773 _position = $.fn.position; 774 775function getOffsets( offsets, width, height ) { 776 return [ 777 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), 778 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) 779 ]; 780} 781 782function parseCss( element, property ) { 783 return parseInt( $.css( element, property ), 10 ) || 0; 784} 785 786function getDimensions( elem ) { 787 var raw = elem[ 0 ]; 788 if ( raw.nodeType === 9 ) { 789 return { 790 width: elem.width(), 791 height: elem.height(), 792 offset: { top: 0, left: 0 } 793 }; 794 } 795 if ( $.isWindow( raw ) ) { 796 return { 797 width: elem.width(), 798 height: elem.height(), 799 offset: { top: elem.scrollTop(), left: elem.scrollLeft() } 800 }; 801 } 802 if ( raw.preventDefault ) { 803 return { 804 width: 0, 805 height: 0, 806 offset: { top: raw.pageY, left: raw.pageX } 807 }; 808 } 809 return { 810 width: elem.outerWidth(), 811 height: elem.outerHeight(), 812 offset: elem.offset() 813 }; 814} 815 816$.position = { 817 scrollbarWidth: function() { 818 if ( cachedScrollbarWidth !== undefined ) { 819 return cachedScrollbarWidth; 820 } 821 var w1, w2, 822 div = $( "<div " + 823 "style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'>" + 824 "<div style='height:100px;width:auto;'></div></div>" ), 825 innerDiv = div.children()[ 0 ]; 826 827 $( "body" ).append( div ); 828 w1 = innerDiv.offsetWidth; 829 div.css( "overflow", "scroll" ); 830 831 w2 = innerDiv.offsetWidth; 832 833 if ( w1 === w2 ) { 834 w2 = div[ 0 ].clientWidth; 835 } 836 837 div.remove(); 838 839 return ( cachedScrollbarWidth = w1 - w2 ); 840 }, 841 getScrollInfo: function( within ) { 842 var overflowX = within.isWindow || within.isDocument ? "" : 843 within.element.css( "overflow-x" ), 844 overflowY = within.isWindow || within.isDocument ? "" : 845 within.element.css( "overflow-y" ), 846 hasOverflowX = overflowX === "scroll" || 847 ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ), 848 hasOverflowY = overflowY === "scroll" || 849 ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight ); 850 return { 851 width: hasOverflowY ? $.position.scrollbarWidth() : 0, 852 height: hasOverflowX ? $.position.scrollbarWidth() : 0 853 }; 854 }, 855 getWithinInfo: function( element ) { 856 var withinElement = $( element || window ), 857 isWindow = $.isWindow( withinElement[ 0 ] ), 858 isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9, 859 hasOffset = !isWindow && !isDocument; 860 return { 861 element: withinElement, 862 isWindow: isWindow, 863 isDocument: isDocument, 864 offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 }, 865 scrollLeft: withinElement.scrollLeft(), 866 scrollTop: withinElement.scrollTop(), 867 width: withinElement.outerWidth(), 868 height: withinElement.outerHeight() 869 }; 870 } 871}; 872 873$.fn.position = function( options ) { 874 if ( !options || !options.of ) { 875 return _position.apply( this, arguments ); 876 } 877 878 // Make a copy, we don't want to modify arguments 879 options = $.extend( {}, options ); 880 881 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, 882 target = $( options.of ), 883 within = $.position.getWithinInfo( options.within ), 884 scrollInfo = $.position.getScrollInfo( within ), 885 collision = ( options.collision || "flip" ).split( " " ), 886 offsets = {}; 887 888 dimensions = getDimensions( target ); 889 if ( target[ 0 ].preventDefault ) { 890 891 // Force left top to allow flipping 892 options.at = "left top"; 893 } 894 targetWidth = dimensions.width; 895 targetHeight = dimensions.height; 896 targetOffset = dimensions.offset; 897 898 // Clone to reuse original targetOffset later 899 basePosition = $.extend( {}, targetOffset ); 900 901 // Force my and at to have valid horizontal and vertical positions 902 // if a value is missing or invalid, it will be converted to center 903 $.each( [ "my", "at" ], function() { 904 var pos = ( options[ this ] || "" ).split( " " ), 905 horizontalOffset, 906 verticalOffset; 907 908 if ( pos.length === 1 ) { 909 pos = rhorizontal.test( pos[ 0 ] ) ? 910 pos.concat( [ "center" ] ) : 911 rvertical.test( pos[ 0 ] ) ? 912 [ "center" ].concat( pos ) : 913 [ "center", "center" ]; 914 } 915 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; 916 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; 917 918 // Calculate offsets 919 horizontalOffset = roffset.exec( pos[ 0 ] ); 920 verticalOffset = roffset.exec( pos[ 1 ] ); 921 offsets[ this ] = [ 922 horizontalOffset ? horizontalOffset[ 0 ] : 0, 923 verticalOffset ? verticalOffset[ 0 ] : 0 924 ]; 925 926 // Reduce to just the positions without the offsets 927 options[ this ] = [ 928 rposition.exec( pos[ 0 ] )[ 0 ], 929 rposition.exec( pos[ 1 ] )[ 0 ] 930 ]; 931 } ); 932 933 // Normalize collision option 934 if ( collision.length === 1 ) { 935 collision[ 1 ] = collision[ 0 ]; 936 } 937 938 if ( options.at[ 0 ] === "right" ) { 939 basePosition.left += targetWidth; 940 } else if ( options.at[ 0 ] === "center" ) { 941 basePosition.left += targetWidth / 2; 942 } 943 944 if ( options.at[ 1 ] === "bottom" ) { 945 basePosition.top += targetHeight; 946 } else if ( options.at[ 1 ] === "center" ) { 947 basePosition.top += targetHeight / 2; 948 } 949 950 atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); 951 basePosition.left += atOffset[ 0 ]; 952 basePosition.top += atOffset[ 1 ]; 953 954 return this.each( function() { 955 var collisionPosition, using, 956 elem = $( this ), 957 elemWidth = elem.outerWidth(), 958 elemHeight = elem.outerHeight(), 959 marginLeft = parseCss( this, "marginLeft" ), 960 marginTop = parseCss( this, "marginTop" ), 961 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + 962 scrollInfo.width, 963 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + 964 scrollInfo.height, 965 position = $.extend( {}, basePosition ), 966 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); 967 968 if ( options.my[ 0 ] === "right" ) { 969 position.left -= elemWidth; 970 } else if ( options.my[ 0 ] === "center" ) { 971 position.left -= elemWidth / 2; 972 } 973 974 if ( options.my[ 1 ] === "bottom" ) { 975 position.top -= elemHeight; 976 } else if ( options.my[ 1 ] === "center" ) { 977 position.top -= elemHeight / 2; 978 } 979 980 position.left += myOffset[ 0 ]; 981 position.top += myOffset[ 1 ]; 982 983 collisionPosition = { 984 marginLeft: marginLeft, 985 marginTop: marginTop 986 }; 987 988 $.each( [ "left", "top" ], function( i, dir ) { 989 if ( $.ui.position[ collision[ i ] ] ) { 990 $.ui.position[ collision[ i ] ][ dir ]( position, { 991 targetWidth: targetWidth, 992 targetHeight: targetHeight, 993 elemWidth: elemWidth, 994 elemHeight: elemHeight, 995 collisionPosition: collisionPosition, 996 collisionWidth: collisionWidth, 997 collisionHeight: collisionHeight, 998 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], 999 my: options.my, 1000 at: options.at, 1001 within: within, 1002 elem: elem 1003 } ); 1004 } 1005 } ); 1006 1007 if ( options.using ) { 1008 1009 // Adds feedback as second argument to using callback, if present 1010 using = function( props ) { 1011 var left = targetOffset.left - position.left, 1012 right = left + targetWidth - elemWidth, 1013 top = targetOffset.top - position.top, 1014 bottom = top + targetHeight - elemHeight, 1015 feedback = { 1016 target: { 1017 element: target, 1018 left: targetOffset.left, 1019 top: targetOffset.top, 1020 width: targetWidth, 1021 height: targetHeight 1022 }, 1023 element: { 1024 element: elem, 1025 left: position.left, 1026 top: position.top, 1027 width: elemWidth, 1028 height: elemHeight 1029 }, 1030 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", 1031 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" 1032 }; 1033 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { 1034 feedback.horizontal = "center"; 1035 } 1036 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { 1037 feedback.vertical = "middle"; 1038 } 1039 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { 1040 feedback.important = "horizontal"; 1041 } else { 1042 feedback.important = "vertical"; 1043 } 1044 options.using.call( this, props, feedback ); 1045 }; 1046 } 1047 1048 elem.offset( $.extend( position, { using: using } ) ); 1049 } ); 1050}; 1051 1052$.ui.position = { 1053 fit: { 1054 left: function( position, data ) { 1055 var within = data.within, 1056 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, 1057 outerWidth = within.width, 1058 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 1059 overLeft = withinOffset - collisionPosLeft, 1060 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, 1061 newOverRight; 1062 1063 // Element is wider than within 1064 if ( data.collisionWidth > outerWidth ) { 1065 1066 // Element is initially over the left side of within 1067 if ( overLeft > 0 && overRight <= 0 ) { 1068 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - 1069 withinOffset; 1070 position.left += overLeft - newOverRight; 1071 1072 // Element is initially over right side of within 1073 } else if ( overRight > 0 && overLeft <= 0 ) { 1074 position.left = withinOffset; 1075 1076 // Element is initially over both left and right sides of within 1077 } else { 1078 if ( overLeft > overRight ) { 1079 position.left = withinOffset + outerWidth - data.collisionWidth; 1080 } else { 1081 position.left = withinOffset; 1082 } 1083 } 1084 1085 // Too far left -> align with left edge 1086 } else if ( overLeft > 0 ) { 1087 position.left += overLeft; 1088 1089 // Too far right -> align with right edge 1090 } else if ( overRight > 0 ) { 1091 position.left -= overRight; 1092 1093 // Adjust based on position and margin 1094 } else { 1095 position.left = max( position.left - collisionPosLeft, position.left ); 1096 } 1097 }, 1098 top: function( position, data ) { 1099 var within = data.within, 1100 withinOffset = within.isWindow ? within.scrollTop : within.offset.top, 1101 outerHeight = data.within.height, 1102 collisionPosTop = position.top - data.collisionPosition.marginTop, 1103 overTop = withinOffset - collisionPosTop, 1104 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, 1105 newOverBottom; 1106 1107 // Element is taller than within 1108 if ( data.collisionHeight > outerHeight ) { 1109 1110 // Element is initially over the top of within 1111 if ( overTop > 0 && overBottom <= 0 ) { 1112 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - 1113 withinOffset; 1114 position.top += overTop - newOverBottom; 1115 1116 // Element is initially over bottom of within 1117 } else if ( overBottom > 0 && overTop <= 0 ) { 1118 position.top = withinOffset; 1119 1120 // Element is initially over both top and bottom of within 1121 } else { 1122 if ( overTop > overBottom ) { 1123 position.top = withinOffset + outerHeight - data.collisionHeight; 1124 } else { 1125 position.top = withinOffset; 1126 } 1127 } 1128 1129 // Too far up -> align with top 1130 } else if ( overTop > 0 ) { 1131 position.top += overTop; 1132 1133 // Too far down -> align with bottom edge 1134 } else if ( overBottom > 0 ) { 1135 position.top -= overBottom; 1136 1137 // Adjust based on position and margin 1138 } else { 1139 position.top = max( position.top - collisionPosTop, position.top ); 1140 } 1141 } 1142 }, 1143 flip: { 1144 left: function( position, data ) { 1145 var within = data.within, 1146 withinOffset = within.offset.left + within.scrollLeft, 1147 outerWidth = within.width, 1148 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, 1149 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 1150 overLeft = collisionPosLeft - offsetLeft, 1151 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, 1152 myOffset = data.my[ 0 ] === "left" ? 1153 -data.elemWidth : 1154 data.my[ 0 ] === "right" ? 1155 data.elemWidth : 1156 0, 1157 atOffset = data.at[ 0 ] === "left" ? 1158 data.targetWidth : 1159 data.at[ 0 ] === "right" ? 1160 -data.targetWidth : 1161 0, 1162 offset = -2 * data.offset[ 0 ], 1163 newOverRight, 1164 newOverLeft; 1165 1166 if ( overLeft < 0 ) { 1167 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - 1168 outerWidth - withinOffset; 1169 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { 1170 position.left += myOffset + atOffset + offset; 1171 } 1172 } else if ( overRight > 0 ) { 1173 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + 1174 atOffset + offset - offsetLeft; 1175 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { 1176 position.left += myOffset + atOffset + offset; 1177 } 1178 } 1179 }, 1180 top: function( position, data ) { 1181 var within = data.within, 1182 withinOffset = within.offset.top + within.scrollTop, 1183 outerHeight = within.height, 1184 offsetTop = within.isWindow ? within.scrollTop : within.offset.top, 1185 collisionPosTop = position.top - data.collisionPosition.marginTop, 1186 overTop = collisionPosTop - offsetTop, 1187 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, 1188 top = data.my[ 1 ] === "top", 1189 myOffset = top ? 1190 -data.elemHeight : 1191 data.my[ 1 ] === "bottom" ? 1192 data.elemHeight : 1193 0, 1194 atOffset = data.at[ 1 ] === "top" ? 1195 data.targetHeight : 1196 data.at[ 1 ] === "bottom" ? 1197 -data.targetHeight : 1198 0, 1199 offset = -2 * data.offset[ 1 ], 1200 newOverTop, 1201 newOverBottom; 1202 if ( overTop < 0 ) { 1203 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - 1204 outerHeight - withinOffset; 1205 if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) { 1206 position.top += myOffset + atOffset + offset; 1207 } 1208 } else if ( overBottom > 0 ) { 1209 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + 1210 offset - offsetTop; 1211 if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) { 1212 position.top += myOffset + atOffset + offset; 1213 } 1214 } 1215 } 1216 }, 1217 flipfit: { 1218 left: function() { 1219 $.ui.position.flip.left.apply( this, arguments ); 1220 $.ui.position.fit.left.apply( this, arguments ); 1221 }, 1222 top: function() { 1223 $.ui.position.flip.top.apply( this, arguments ); 1224 $.ui.position.fit.top.apply( this, arguments ); 1225 } 1226 } 1227}; 1228 1229} )(); 1230 1231var position = $.ui.position; 1232 1233 1234/*! 1235 * jQuery UI :data 1.12.1 1236 * http://jqueryui.com 1237 * 1238 * Copyright jQuery Foundation and other contributors 1239 * Released under the MIT license. 1240 * http://jquery.org/license 1241 */ 1242 1243//>>label: :data Selector 1244//>>group: Core 1245//>>description: Selects elements which have data stored under the specified key. 1246//>>docs: http://api.jqueryui.com/data-selector/ 1247 1248 1249var data = $.extend( $.expr[ ":" ], { 1250 data: $.expr.createPseudo ? 1251 $.expr.createPseudo( function( dataName ) { 1252 return function( elem ) { 1253 return !!$.data( elem, dataName ); 1254 }; 1255 } ) : 1256 1257 // Support: jQuery <1.8 1258 function( elem, i, match ) { 1259 return !!$.data( elem, match[ 3 ] ); 1260 } 1261} ); 1262 1263/*! 1264 * jQuery UI Disable Selection 1.12.1 1265 * http://jqueryui.com 1266 * 1267 * Copyright jQuery Foundation and other contributors 1268 * Released under the MIT license. 1269 * http://jquery.org/license 1270 */ 1271 1272//>>label: disableSelection 1273//>>group: Core 1274//>>description: Disable selection of text content within the set of matched elements. 1275//>>docs: http://api.jqueryui.com/disableSelection/ 1276 1277// This file is deprecated 1278 1279 1280var disableSelection = $.fn.extend( { 1281 disableSelection: ( function() { 1282 var eventType = "onselectstart" in document.createElement( "div" ) ? 1283 "selectstart" : 1284 "mousedown"; 1285 1286 return function() { 1287 return this.on( eventType + ".ui-disableSelection", function( event ) { 1288 event.preventDefault(); 1289 } ); 1290 }; 1291 } )(), 1292 1293 enableSelection: function() { 1294 return this.off( ".ui-disableSelection" ); 1295 } 1296} ); 1297 1298 1299/*! 1300 * jQuery UI Effects 1.12.1 1301 * http://jqueryui.com 1302 * 1303 * Copyright jQuery Foundation and other contributors 1304 * Released under the MIT license. 1305 * http://jquery.org/license 1306 */ 1307 1308//>>label: Effects Core 1309//>>group: Effects 1310// jscs:disable maximumLineLength 1311//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects. 1312// jscs:enable maximumLineLength 1313//>>docs: http://api.jqueryui.com/category/effects-core/ 1314//>>demos: http://jqueryui.com/effect/ 1315 1316 1317 1318var dataSpace = "ui-effects-", 1319 dataSpaceStyle = "ui-effects-style", 1320 dataSpaceAnimated = "ui-effects-animated", 1321 1322 // Create a local jQuery because jQuery Color relies on it and the 1323 // global may not exist with AMD and a custom build (#10199) 1324 jQuery = $; 1325 1326$.effects = { 1327 effect: {} 1328}; 1329 1330/*! 1331 * jQuery Color Animations v2.1.2 1332 * https://github.com/jquery/jquery-color 1333 * 1334 * Copyright 2014 jQuery Foundation and other contributors 1335 * Released under the MIT license. 1336 * http://jquery.org/license 1337 * 1338 * Date: Wed Jan 16 08:47:09 2013 -0600 1339 */ 1340( function( jQuery, undefined ) { 1341 1342 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " + 1343 "borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", 1344 1345 // Plusequals test for += 100 -= 100 1346 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, 1347 1348 // A set of RE's that can match strings and generate color tuples. 1349 stringParsers = [ { 1350 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 1351 parse: function( execResult ) { 1352 return [ 1353 execResult[ 1 ], 1354 execResult[ 2 ], 1355 execResult[ 3 ], 1356 execResult[ 4 ] 1357 ]; 1358 } 1359 }, { 1360 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 1361 parse: function( execResult ) { 1362 return [ 1363 execResult[ 1 ] * 2.55, 1364 execResult[ 2 ] * 2.55, 1365 execResult[ 3 ] * 2.55, 1366 execResult[ 4 ] 1367 ]; 1368 } 1369 }, { 1370 1371 // This regex ignores A-F because it's compared against an already lowercased string 1372 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/, 1373 parse: function( execResult ) { 1374 return [ 1375 parseInt( execResult[ 1 ], 16 ), 1376 parseInt( execResult[ 2 ], 16 ), 1377 parseInt( execResult[ 3 ], 16 ) 1378 ]; 1379 } 1380 }, { 1381 1382 // This regex ignores A-F because it's compared against an already lowercased string 1383 re: /#([a-f0-9])([a-f0-9])([a-f0-9])/, 1384 parse: function( execResult ) { 1385 return [ 1386 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), 1387 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), 1388 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ) 1389 ]; 1390 } 1391 }, { 1392 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 1393 space: "hsla", 1394 parse: function( execResult ) { 1395 return [ 1396 execResult[ 1 ], 1397 execResult[ 2 ] / 100, 1398 execResult[ 3 ] / 100, 1399 execResult[ 4 ] 1400 ]; 1401 } 1402 } ], 1403 1404 // JQuery.Color( ) 1405 color = jQuery.Color = function( color, green, blue, alpha ) { 1406 return new jQuery.Color.fn.parse( color, green, blue, alpha ); 1407 }, 1408 spaces = { 1409 rgba: { 1410 props: { 1411 red: { 1412 idx: 0, 1413 type: "byte" 1414 }, 1415 green: { 1416 idx: 1, 1417 type: "byte" 1418 }, 1419 blue: { 1420 idx: 2, 1421 type: "byte" 1422 } 1423 } 1424 }, 1425 1426 hsla: { 1427 props: { 1428 hue: { 1429 idx: 0, 1430 type: "degrees" 1431 }, 1432 saturation: { 1433 idx: 1, 1434 type: "percent" 1435 }, 1436 lightness: { 1437 idx: 2, 1438 type: "percent" 1439 } 1440 } 1441 } 1442 }, 1443 propTypes = { 1444 "byte": { 1445 floor: true, 1446 max: 255 1447 }, 1448 "percent": { 1449 max: 1 1450 }, 1451 "degrees": { 1452 mod: 360, 1453 floor: true 1454 } 1455 }, 1456 support = color.support = {}, 1457 1458 // Element for support tests 1459 supportElem = jQuery( "<p>" )[ 0 ], 1460 1461 // Colors = jQuery.Color.names 1462 colors, 1463 1464 // Local aliases of functions called often 1465 each = jQuery.each; 1466 1467// Determine rgba support immediately 1468supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; 1469support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; 1470 1471// Define cache name and alpha properties 1472// for rgba and hsla spaces 1473each( spaces, function( spaceName, space ) { 1474 space.cache = "_" + spaceName; 1475 space.props.alpha = { 1476 idx: 3, 1477 type: "percent", 1478 def: 1 1479 }; 1480} ); 1481 1482function clamp( value, prop, allowEmpty ) { 1483 var type = propTypes[ prop.type ] || {}; 1484 1485 if ( value == null ) { 1486 return ( allowEmpty || !prop.def ) ? null : prop.def; 1487 } 1488 1489 // ~~ is an short way of doing floor for positive numbers 1490 value = type.floor ? ~~value : parseFloat( value ); 1491 1492 // IE will pass in empty strings as value for alpha, 1493 // which will hit this case 1494 if ( isNaN( value ) ) { 1495 return prop.def; 1496 } 1497 1498 if ( type.mod ) { 1499 1500 // We add mod before modding to make sure that negatives values 1501 // get converted properly: -10 -> 350 1502 return ( value + type.mod ) % type.mod; 1503 } 1504 1505 // For now all property types without mod have min and max 1506 return 0 > value ? 0 : type.max < value ? type.max : value; 1507} 1508 1509function stringParse( string ) { 1510 var inst = color(), 1511 rgba = inst._rgba = []; 1512 1513 string = string.toLowerCase(); 1514 1515 each( stringParsers, function( i, parser ) { 1516 var parsed, 1517 match = parser.re.exec( string ), 1518 values = match && parser.parse( match ), 1519 spaceName = parser.space || "rgba"; 1520 1521 if ( values ) { 1522 parsed = inst[ spaceName ]( values ); 1523 1524 // If this was an rgba parse the assignment might happen twice 1525 // oh well.... 1526 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; 1527 rgba = inst._rgba = parsed._rgba; 1528 1529 // Exit each( stringParsers ) here because we matched 1530 return false; 1531 } 1532 } ); 1533 1534 // Found a stringParser that handled it 1535 if ( rgba.length ) { 1536 1537 // If this came from a parsed string, force "transparent" when alpha is 0 1538 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) 1539 if ( rgba.join() === "0,0,0,0" ) { 1540 jQuery.extend( rgba, colors.transparent ); 1541 } 1542 return inst; 1543 } 1544 1545 // Named colors 1546 return colors[ string ]; 1547} 1548 1549color.fn = jQuery.extend( color.prototype, { 1550 parse: function( red, green, blue, alpha ) { 1551 if ( red === undefined ) { 1552 this._rgba = [ null, null, null, null ]; 1553 return this; 1554 } 1555 if ( red.jquery || red.nodeType ) { 1556 red = jQuery( red ).css( green ); 1557 green = undefined; 1558 } 1559 1560 var inst = this, 1561 type = jQuery.type( red ), 1562 rgba = this._rgba = []; 1563 1564 // More than 1 argument specified - assume ( red, green, blue, alpha ) 1565 if ( green !== undefined ) { 1566 red = [ red, green, blue, alpha ]; 1567 type = "array"; 1568 } 1569 1570 if ( type === "string" ) { 1571 return this.parse( stringParse( red ) || colors._default ); 1572 } 1573 1574 if ( type === "array" ) { 1575 each( spaces.rgba.props, function( key, prop ) { 1576 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); 1577 } ); 1578 return this; 1579 } 1580 1581 if ( type === "object" ) { 1582 if ( red instanceof color ) { 1583 each( spaces, function( spaceName, space ) { 1584 if ( red[ space.cache ] ) { 1585 inst[ space.cache ] = red[ space.cache ].slice(); 1586 } 1587 } ); 1588 } else { 1589 each( spaces, function( spaceName, space ) { 1590 var cache = space.cache; 1591 each( space.props, function( key, prop ) { 1592 1593 // If the cache doesn't exist, and we know how to convert 1594 if ( !inst[ cache ] && space.to ) { 1595 1596 // If the value was null, we don't need to copy it 1597 // if the key was alpha, we don't need to copy it either 1598 if ( key === "alpha" || red[ key ] == null ) { 1599 return; 1600 } 1601 inst[ cache ] = space.to( inst._rgba ); 1602 } 1603 1604 // This is the only case where we allow nulls for ALL properties. 1605 // call clamp with alwaysAllowEmpty 1606 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); 1607 } ); 1608 1609 // Everything defined but alpha? 1610 if ( inst[ cache ] && 1611 jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { 1612 1613 // Use the default of 1 1614 inst[ cache ][ 3 ] = 1; 1615 if ( space.from ) { 1616 inst._rgba = space.from( inst[ cache ] ); 1617 } 1618 } 1619 } ); 1620 } 1621 return this; 1622 } 1623 }, 1624 is: function( compare ) { 1625 var is = color( compare ), 1626 same = true, 1627 inst = this; 1628 1629 each( spaces, function( _, space ) { 1630 var localCache, 1631 isCache = is[ space.cache ]; 1632 if ( isCache ) { 1633 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; 1634 each( space.props, function( _, prop ) { 1635 if ( isCache[ prop.idx ] != null ) { 1636 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); 1637 return same; 1638 } 1639 } ); 1640 } 1641 return same; 1642 } ); 1643 return same; 1644 }, 1645 _space: function() { 1646 var used = [], 1647 inst = this; 1648 each( spaces, function( spaceName, space ) { 1649 if ( inst[ space.cache ] ) { 1650 used.push( spaceName ); 1651 } 1652 } ); 1653 return used.pop(); 1654 }, 1655 transition: function( other, distance ) { 1656 var end = color( other ), 1657 spaceName = end._space(), 1658 space = spaces[ spaceName ], 1659 startColor = this.alpha() === 0 ? color( "transparent" ) : this, 1660 start = startColor[ space.cache ] || space.to( startColor._rgba ), 1661 result = start.slice(); 1662 1663 end = end[ space.cache ]; 1664 each( space.props, function( key, prop ) { 1665 var index = prop.idx, 1666 startValue = start[ index ], 1667 endValue = end[ index ], 1668 type = propTypes[ prop.type ] || {}; 1669 1670 // If null, don't override start value 1671 if ( endValue === null ) { 1672 return; 1673 } 1674 1675 // If null - use end 1676 if ( startValue === null ) { 1677 result[ index ] = endValue; 1678 } else { 1679 if ( type.mod ) { 1680 if ( endValue - startValue > type.mod / 2 ) { 1681 startValue += type.mod; 1682 } else if ( startValue - endValue > type.mod / 2 ) { 1683 startValue -= type.mod; 1684 } 1685 } 1686 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); 1687 } 1688 } ); 1689 return this[ spaceName ]( result ); 1690 }, 1691 blend: function( opaque ) { 1692 1693 // If we are already opaque - return ourself 1694 if ( this._rgba[ 3 ] === 1 ) { 1695 return this; 1696 } 1697 1698 var rgb = this._rgba.slice(), 1699 a = rgb.pop(), 1700 blend = color( opaque )._rgba; 1701 1702 return color( jQuery.map( rgb, function( v, i ) { 1703 return ( 1 - a ) * blend[ i ] + a * v; 1704 } ) ); 1705 }, 1706 toRgbaString: function() { 1707 var prefix = "rgba(", 1708 rgba = jQuery.map( this._rgba, function( v, i ) { 1709 return v == null ? ( i > 2 ? 1 : 0 ) : v; 1710 } ); 1711 1712 if ( rgba[ 3 ] === 1 ) { 1713 rgba.pop(); 1714 prefix = "rgb("; 1715 } 1716 1717 return prefix + rgba.join() + ")"; 1718 }, 1719 toHslaString: function() { 1720 var prefix = "hsla(", 1721 hsla = jQuery.map( this.hsla(), function( v, i ) { 1722 if ( v == null ) { 1723 v = i > 2 ? 1 : 0; 1724 } 1725 1726 // Catch 1 and 2 1727 if ( i && i < 3 ) { 1728 v = Math.round( v * 100 ) + "%"; 1729 } 1730 return v; 1731 } ); 1732 1733 if ( hsla[ 3 ] === 1 ) { 1734 hsla.pop(); 1735 prefix = "hsl("; 1736 } 1737 return prefix + hsla.join() + ")"; 1738 }, 1739 toHexString: function( includeAlpha ) { 1740 var rgba = this._rgba.slice(), 1741 alpha = rgba.pop(); 1742 1743 if ( includeAlpha ) { 1744 rgba.push( ~~( alpha * 255 ) ); 1745 } 1746 1747 return "#" + jQuery.map( rgba, function( v ) { 1748 1749 // Default to 0 when nulls exist 1750 v = ( v || 0 ).toString( 16 ); 1751 return v.length === 1 ? "0" + v : v; 1752 } ).join( "" ); 1753 }, 1754 toString: function() { 1755 return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); 1756 } 1757} ); 1758color.fn.parse.prototype = color.fn; 1759 1760// Hsla conversions adapted from: 1761// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 1762 1763function hue2rgb( p, q, h ) { 1764 h = ( h + 1 ) % 1; 1765 if ( h * 6 < 1 ) { 1766 return p + ( q - p ) * h * 6; 1767 } 1768 if ( h * 2 < 1 ) { 1769 return q; 1770 } 1771 if ( h * 3 < 2 ) { 1772 return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6; 1773 } 1774 return p; 1775} 1776 1777spaces.hsla.to = function( rgba ) { 1778 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { 1779 return [ null, null, null, rgba[ 3 ] ]; 1780 } 1781 var r = rgba[ 0 ] / 255, 1782 g = rgba[ 1 ] / 255, 1783 b = rgba[ 2 ] / 255, 1784 a = rgba[ 3 ], 1785 max = Math.max( r, g, b ), 1786 min = Math.min( r, g, b ), 1787 diff = max - min, 1788 add = max + min, 1789 l = add * 0.5, 1790 h, s; 1791 1792 if ( min === max ) { 1793 h = 0; 1794 } else if ( r === max ) { 1795 h = ( 60 * ( g - b ) / diff ) + 360; 1796 } else if ( g === max ) { 1797 h = ( 60 * ( b - r ) / diff ) + 120; 1798 } else { 1799 h = ( 60 * ( r - g ) / diff ) + 240; 1800 } 1801 1802 // Chroma (diff) == 0 means greyscale which, by definition, saturation = 0% 1803 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) 1804 if ( diff === 0 ) { 1805 s = 0; 1806 } else if ( l <= 0.5 ) { 1807 s = diff / add; 1808 } else { 1809 s = diff / ( 2 - add ); 1810 } 1811 return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ]; 1812}; 1813 1814spaces.hsla.from = function( hsla ) { 1815 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { 1816 return [ null, null, null, hsla[ 3 ] ]; 1817 } 1818 var h = hsla[ 0 ] / 360, 1819 s = hsla[ 1 ], 1820 l = hsla[ 2 ], 1821 a = hsla[ 3 ], 1822 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, 1823 p = 2 * l - q; 1824 1825 return [ 1826 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), 1827 Math.round( hue2rgb( p, q, h ) * 255 ), 1828 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), 1829 a 1830 ]; 1831}; 1832 1833each( spaces, function( spaceName, space ) { 1834 var props = space.props, 1835 cache = space.cache, 1836 to = space.to, 1837 from = space.from; 1838 1839 // Makes rgba() and hsla() 1840 color.fn[ spaceName ] = function( value ) { 1841 1842 // Generate a cache for this space if it doesn't exist 1843 if ( to && !this[ cache ] ) { 1844 this[ cache ] = to( this._rgba ); 1845 } 1846 if ( value === undefined ) { 1847 return this[ cache ].slice(); 1848 } 1849 1850 var ret, 1851 type = jQuery.type( value ), 1852 arr = ( type === "array" || type === "object" ) ? value : arguments, 1853 local = this[ cache ].slice(); 1854 1855 each( props, function( key, prop ) { 1856 var val = arr[ type === "object" ? key : prop.idx ]; 1857 if ( val == null ) { 1858 val = local[ prop.idx ]; 1859 } 1860 local[ prop.idx ] = clamp( val, prop ); 1861 } ); 1862 1863 if ( from ) { 1864 ret = color( from( local ) ); 1865 ret[ cache ] = local; 1866 return ret; 1867 } else { 1868 return color( local ); 1869 } 1870 }; 1871 1872 // Makes red() green() blue() alpha() hue() saturation() lightness() 1873 each( props, function( key, prop ) { 1874 1875 // Alpha is included in more than one space 1876 if ( color.fn[ key ] ) { 1877 return; 1878 } 1879 color.fn[ key ] = function( value ) { 1880 var vtype = jQuery.type( value ), 1881 fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ), 1882 local = this[ fn ](), 1883 cur = local[ prop.idx ], 1884 match; 1885 1886 if ( vtype === "undefined" ) { 1887 return cur; 1888 } 1889 1890 if ( vtype === "function" ) { 1891 value = value.call( this, cur ); 1892 vtype = jQuery.type( value ); 1893 } 1894 if ( value == null && prop.empty ) { 1895 return this; 1896 } 1897 if ( vtype === "string" ) { 1898 match = rplusequals.exec( value ); 1899 if ( match ) { 1900 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); 1901 } 1902 } 1903 local[ prop.idx ] = value; 1904 return this[ fn ]( local ); 1905 }; 1906 } ); 1907} ); 1908 1909// Add cssHook and .fx.step function for each named hook. 1910// accept a space separated string of properties 1911color.hook = function( hook ) { 1912 var hooks = hook.split( " " ); 1913 each( hooks, function( i, hook ) { 1914 jQuery.cssHooks[ hook ] = { 1915 set: function( elem, value ) { 1916 var parsed, curElem, 1917 backgroundColor = ""; 1918 1919 if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || 1920 ( parsed = stringParse( value ) ) ) ) { 1921 value = color( parsed || value ); 1922 if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { 1923 curElem = hook === "backgroundColor" ? elem.parentNode : elem; 1924 while ( 1925 ( backgroundColor === "" || backgroundColor === "transparent" ) && 1926 curElem && curElem.style 1927 ) { 1928 try { 1929 backgroundColor = jQuery.css( curElem, "backgroundColor" ); 1930 curElem = curElem.parentNode; 1931 } catch ( e ) { 1932 } 1933 } 1934 1935 value = value.blend( backgroundColor && backgroundColor !== "transparent" ? 1936 backgroundColor : 1937 "_default" ); 1938 } 1939 1940 value = value.toRgbaString(); 1941 } 1942 try { 1943 elem.style[ hook ] = value; 1944 } catch ( e ) { 1945 1946 // Wrapped to prevent IE from throwing errors on "invalid" values like 1947 // 'auto' or 'inherit' 1948 } 1949 } 1950 }; 1951 jQuery.fx.step[ hook ] = function( fx ) { 1952 if ( !fx.colorInit ) { 1953 fx.start = color( fx.elem, hook ); 1954 fx.end = color( fx.end ); 1955 fx.colorInit = true; 1956 } 1957 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); 1958 }; 1959 } ); 1960 1961}; 1962 1963color.hook( stepHooks ); 1964 1965jQuery.cssHooks.borderColor = { 1966 expand: function( value ) { 1967 var expanded = {}; 1968 1969 each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) { 1970 expanded[ "border" + part + "Color" ] = value; 1971 } ); 1972 return expanded; 1973 } 1974}; 1975 1976// Basic color names only. 1977// Usage of any of the other color names requires adding yourself or including 1978// jquery.color.svg-names.js. 1979colors = jQuery.Color.names = { 1980 1981 // 4.1. Basic color keywords 1982 aqua: "#00ffff", 1983 black: "#000000", 1984 blue: "#0000ff", 1985 fuchsia: "#ff00ff", 1986 gray: "#808080", 1987 green: "#008000", 1988 lime: "#00ff00", 1989 maroon: "#800000", 1990 navy: "#000080", 1991 olive: "#808000", 1992 purple: "#800080", 1993 red: "#ff0000", 1994 silver: "#c0c0c0", 1995 teal: "#008080", 1996 white: "#ffffff", 1997 yellow: "#ffff00", 1998 1999 // 4.2.3. "transparent" color keyword 2000 transparent: [ null, null, null, 0 ], 2001 2002 _default: "#ffffff" 2003}; 2004 2005} )( jQuery ); 2006 2007/******************************************************************************/ 2008/****************************** CLASS ANIMATIONS ******************************/ 2009/******************************************************************************/ 2010( function() { 2011 2012var classAnimationActions = [ "add", "remove", "toggle" ], 2013 shorthandStyles = { 2014 border: 1, 2015 borderBottom: 1, 2016 borderColor: 1, 2017 borderLeft: 1, 2018 borderRight: 1, 2019 borderTop: 1, 2020 borderWidth: 1, 2021 margin: 1, 2022 padding: 1 2023 }; 2024 2025$.each( 2026 [ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], 2027 function( _, prop ) { 2028 $.fx.step[ prop ] = function( fx ) { 2029 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { 2030 jQuery.style( fx.elem, prop, fx.end ); 2031 fx.setAttr = true; 2032 } 2033 }; 2034 } 2035); 2036 2037function getElementStyles( elem ) { 2038 var key, len, 2039 style = elem.ownerDocument.defaultView ? 2040 elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : 2041 elem.currentStyle, 2042 styles = {}; 2043 2044 if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { 2045 len = style.length; 2046 while ( len-- ) { 2047 key = style[ len ]; 2048 if ( typeof style[ key ] === "string" ) { 2049 styles[ $.camelCase( key ) ] = style[ key ]; 2050 } 2051 } 2052 2053 // Support: Opera, IE <9 2054 } else { 2055 for ( key in style ) { 2056 if ( typeof style[ key ] === "string" ) { 2057 styles[ key ] = style[ key ]; 2058 } 2059 } 2060 } 2061 2062 return styles; 2063} 2064 2065function styleDifference( oldStyle, newStyle ) { 2066 var diff = {}, 2067 name, value; 2068 2069 for ( name in newStyle ) { 2070 value = newStyle[ name ]; 2071 if ( oldStyle[ name ] !== value ) { 2072 if ( !shorthandStyles[ name ] ) { 2073 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { 2074 diff[ name ] = value; 2075 } 2076 } 2077 } 2078 } 2079 2080 return diff; 2081} 2082 2083// Support: jQuery <1.8 2084if ( !$.fn.addBack ) { 2085 $.fn.addBack = function( selector ) { 2086 return this.add( selector == null ? 2087 this.prevObject : this.prevObject.filter( selector ) 2088 ); 2089 }; 2090} 2091 2092$.effects.animateClass = function( value, duration, easing, callback ) { 2093 var o = $.speed( duration, easing, callback ); 2094 2095 return this.queue( function() { 2096 var animated = $( this ), 2097 baseClass = animated.attr( "class" ) || "", 2098 applyClassChange, 2099 allAnimations = o.children ? animated.find( "*" ).addBack() : animated; 2100 2101 // Map the animated objects to store the original styles. 2102 allAnimations = allAnimations.map( function() { 2103 var el = $( this ); 2104 return { 2105 el: el, 2106 start: getElementStyles( this ) 2107 }; 2108 } ); 2109 2110 // Apply class change 2111 applyClassChange = function() { 2112 $.each( classAnimationActions, function( i, action ) { 2113 if ( value[ action ] ) { 2114 animated[ action + "Class" ]( value[ action ] ); 2115 } 2116 } ); 2117 }; 2118 applyClassChange(); 2119 2120 // Map all animated objects again - calculate new styles and diff 2121 allAnimations = allAnimations.map( function() { 2122 this.end = getElementStyles( this.el[ 0 ] ); 2123 this.diff = styleDifference( this.start, this.end ); 2124 return this; 2125 } ); 2126 2127 // Apply original class 2128 animated.attr( "class", baseClass ); 2129 2130 // Map all animated objects again - this time collecting a promise 2131 allAnimations = allAnimations.map( function() { 2132 var styleInfo = this, 2133 dfd = $.Deferred(), 2134 opts = $.extend( {}, o, { 2135 queue: false, 2136 complete: function() { 2137 dfd.resolve( styleInfo ); 2138 } 2139 } ); 2140 2141 this.el.animate( this.diff, opts ); 2142 return dfd.promise(); 2143 } ); 2144 2145 // Once all animations have completed: 2146 $.when.apply( $, allAnimations.get() ).done( function() { 2147 2148 // Set the final class 2149 applyClassChange(); 2150 2151 // For each animated element, 2152 // clear all css properties that were animated 2153 $.each( arguments, function() { 2154 var el = this.el; 2155 $.each( this.diff, function( key ) { 2156 el.css( key, "" ); 2157 } ); 2158 } ); 2159 2160 // This is guarnteed to be there if you use jQuery.speed() 2161 // it also handles dequeuing the next anim... 2162 o.complete.call( animated[ 0 ] ); 2163 } ); 2164 } ); 2165}; 2166 2167$.fn.extend( { 2168 addClass: ( function( orig ) { 2169 return function( classNames, speed, easing, callback ) { 2170 return speed ? 2171 $.effects.animateClass.call( this, 2172 { add: classNames }, speed, easing, callback ) : 2173 orig.apply( this, arguments ); 2174 }; 2175 } )( $.fn.addClass ), 2176 2177 removeClass: ( function( orig ) { 2178 return function( classNames, speed, easing, callback ) { 2179 return arguments.length > 1 ? 2180 $.effects.animateClass.call( this, 2181 { remove: classNames }, speed, easing, callback ) : 2182 orig.apply( this, arguments ); 2183 }; 2184 } )( $.fn.removeClass ), 2185 2186 toggleClass: ( function( orig ) { 2187 return function( classNames, force, speed, easing, callback ) { 2188 if ( typeof force === "boolean" || force === undefined ) { 2189 if ( !speed ) { 2190 2191 // Without speed parameter 2192 return orig.apply( this, arguments ); 2193 } else { 2194 return $.effects.animateClass.call( this, 2195 ( force ? { add: classNames } : { remove: classNames } ), 2196 speed, easing, callback ); 2197 } 2198 } else { 2199 2200 // Without force parameter 2201 return $.effects.animateClass.call( this, 2202 { toggle: classNames }, force, speed, easing ); 2203 } 2204 }; 2205 } )( $.fn.toggleClass ), 2206 2207 switchClass: function( remove, add, speed, easing, callback ) { 2208 return $.effects.animateClass.call( this, { 2209 add: add, 2210 remove: remove 2211 }, speed, easing, callback ); 2212 } 2213} ); 2214 2215} )(); 2216 2217/******************************************************************************/ 2218/*********************************** EFFECTS **********************************/ 2219/******************************************************************************/ 2220 2221( function() { 2222 2223if ( $.expr && $.expr.filters && $.expr.filters.animated ) { 2224 $.expr.filters.animated = ( function( orig ) { 2225 return function( elem ) { 2226 return !!$( elem ).data( dataSpaceAnimated ) || orig( elem ); 2227 }; 2228 } )( $.expr.filters.animated ); 2229} 2230 2231if ( $.uiBackCompat !== false ) { 2232 $.extend( $.effects, { 2233 2234 // Saves a set of properties in a data storage 2235 save: function( element, set ) { 2236 var i = 0, length = set.length; 2237 for ( ; i < length; i++ ) { 2238 if ( set[ i ] !== null ) { 2239 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); 2240 } 2241 } 2242 }, 2243 2244 // Restores a set of previously saved properties from a data storage 2245 restore: function( element, set ) { 2246 var val, i = 0, length = set.length; 2247 for ( ; i < length; i++ ) { 2248 if ( set[ i ] !== null ) { 2249 val = element.data( dataSpace + set[ i ] ); 2250 element.css( set[ i ], val ); 2251 } 2252 } 2253 }, 2254 2255 setMode: function( el, mode ) { 2256 if ( mode === "toggle" ) { 2257 mode = el.is( ":hidden" ) ? "show" : "hide"; 2258 } 2259 return mode; 2260 }, 2261 2262 // Wraps the element around a wrapper that copies position properties 2263 createWrapper: function( element ) { 2264 2265 // If the element is already wrapped, return it 2266 if ( element.parent().is( ".ui-effects-wrapper" ) ) { 2267 return element.parent(); 2268 } 2269 2270 // Wrap the element 2271 var props = { 2272 width: element.outerWidth( true ), 2273 height: element.outerHeight( true ), 2274 "float": element.css( "float" ) 2275 }, 2276 wrapper = $( "<div></div>" ) 2277 .addClass( "ui-effects-wrapper" ) 2278 .css( { 2279 fontSize: "100%", 2280 background: "transparent", 2281 border: "none", 2282 margin: 0, 2283 padding: 0 2284 } ), 2285 2286 // Store the size in case width/height are defined in % - Fixes #5245 2287 size = { 2288 width: element.width(), 2289 height: element.height() 2290 }, 2291 active = document.activeElement; 2292 2293 // Support: Firefox 2294 // Firefox incorrectly exposes anonymous content 2295 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 2296 try { 2297 active.id; 2298 } catch ( e ) { 2299 active = document.body; 2300 } 2301 2302 element.wrap( wrapper ); 2303 2304 // Fixes #7595 - Elements lose focus when wrapped. 2305 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 2306 $( active ).trigger( "focus" ); 2307 } 2308 2309 // Hotfix for jQuery 1.4 since some change in wrap() seems to actually 2310 // lose the reference to the wrapped element 2311 wrapper = element.parent(); 2312 2313 // Transfer positioning properties to the wrapper 2314 if ( element.css( "position" ) === "static" ) { 2315 wrapper.css( { position: "relative" } ); 2316 element.css( { position: "relative" } ); 2317 } else { 2318 $.extend( props, { 2319 position: element.css( "position" ), 2320 zIndex: element.css( "z-index" ) 2321 } ); 2322 $.each( [ "top", "left", "bottom", "right" ], function( i, pos ) { 2323 props[ pos ] = element.css( pos ); 2324 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { 2325 props[ pos ] = "auto"; 2326 } 2327 } ); 2328 element.css( { 2329 position: "relative", 2330 top: 0, 2331 left: 0, 2332 right: "auto", 2333 bottom: "auto" 2334 } ); 2335 } 2336 element.css( size ); 2337 2338 return wrapper.css( props ).show(); 2339 }, 2340 2341 removeWrapper: function( element ) { 2342 var active = document.activeElement; 2343 2344 if ( element.parent().is( ".ui-effects-wrapper" ) ) { 2345 element.parent().replaceWith( element ); 2346 2347 // Fixes #7595 - Elements lose focus when wrapped. 2348 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 2349 $( active ).trigger( "focus" ); 2350 } 2351 } 2352 2353 return element; 2354 } 2355 } ); 2356} 2357 2358$.extend( $.effects, { 2359 version: "1.12.1", 2360 2361 define: function( name, mode, effect ) { 2362 if ( !effect ) { 2363 effect = mode; 2364 mode = "effect"; 2365 } 2366 2367 $.effects.effect[ name ] = effect; 2368 $.effects.effect[ name ].mode = mode; 2369 2370 return effect; 2371 }, 2372 2373 scaledDimensions: function( element, percent, direction ) { 2374 if ( percent === 0 ) { 2375 return { 2376 height: 0, 2377 width: 0, 2378 outerHeight: 0, 2379 outerWidth: 0 2380 }; 2381 } 2382 2383 var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1, 2384 y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1; 2385 2386 return { 2387 height: element.height() * y, 2388 width: element.width() * x, 2389 outerHeight: element.outerHeight() * y, 2390 outerWidth: element.outerWidth() * x 2391 }; 2392 2393 }, 2394 2395 clipToBox: function( animation ) { 2396 return { 2397 width: animation.clip.right - animation.clip.left, 2398 height: animation.clip.bottom - animation.clip.top, 2399 left: animation.clip.left, 2400 top: animation.clip.top 2401 }; 2402 }, 2403 2404 // Injects recently queued functions to be first in line (after "inprogress") 2405 unshift: function( element, queueLength, count ) { 2406 var queue = element.queue(); 2407 2408 if ( queueLength > 1 ) { 2409 queue.splice.apply( queue, 2410 [ 1, 0 ].concat( queue.splice( queueLength, count ) ) ); 2411 } 2412 element.dequeue(); 2413 }, 2414 2415 saveStyle: function( element ) { 2416 element.data( dataSpaceStyle, element[ 0 ].style.cssText ); 2417 }, 2418 2419 restoreStyle: function( element ) { 2420 element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || ""; 2421 element.removeData( dataSpaceStyle ); 2422 }, 2423 2424 mode: function( element, mode ) { 2425 var hidden = element.is( ":hidden" ); 2426 2427 if ( mode === "toggle" ) { 2428 mode = hidden ? "show" : "hide"; 2429 } 2430 if ( hidden ? mode === "hide" : mode === "show" ) { 2431 mode = "none"; 2432 } 2433 return mode; 2434 }, 2435 2436 // Translates a [top,left] array into a baseline value 2437 getBaseline: function( origin, original ) { 2438 var y, x; 2439 2440 switch ( origin[ 0 ] ) { 2441 case "top": 2442 y = 0; 2443 break; 2444 case "middle": 2445 y = 0.5; 2446 break; 2447 case "bottom": 2448 y = 1; 2449 break; 2450 default: 2451 y = origin[ 0 ] / original.height; 2452 } 2453 2454 switch ( origin[ 1 ] ) { 2455 case "left": 2456 x = 0; 2457 break; 2458 case "center": 2459 x = 0.5; 2460 break; 2461 case "right": 2462 x = 1; 2463 break; 2464 default: 2465 x = origin[ 1 ] / original.width; 2466 } 2467 2468 return { 2469 x: x, 2470 y: y 2471 }; 2472 }, 2473 2474 // Creates a placeholder element so that the original element can be made absolute 2475 createPlaceholder: function( element ) { 2476 var placeholder, 2477 cssPosition = element.css( "position" ), 2478 position = element.position(); 2479 2480 // Lock in margins first to account for form elements, which 2481 // will change margin if you explicitly set height 2482 // see: http://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380 2483 // Support: Safari 2484 element.css( { 2485 marginTop: element.css( "marginTop" ), 2486 marginBottom: element.css( "marginBottom" ), 2487 marginLeft: element.css( "marginLeft" ), 2488 marginRight: element.css( "marginRight" ) 2489 } ) 2490 .outerWidth( element.outerWidth() ) 2491 .outerHeight( element.outerHeight() ); 2492 2493 if ( /^(static|relative)/.test( cssPosition ) ) { 2494 cssPosition = "absolute"; 2495 2496 placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( { 2497 2498 // Convert inline to inline block to account for inline elements 2499 // that turn to inline block based on content (like img) 2500 display: /^(inline|ruby)/.test( element.css( "display" ) ) ? 2501 "inline-block" : 2502 "block", 2503 visibility: "hidden", 2504 2505 // Margins need to be set to account for margin collapse 2506 marginTop: element.css( "marginTop" ), 2507 marginBottom: element.css( "marginBottom" ), 2508 marginLeft: element.css( "marginLeft" ), 2509 marginRight: element.css( "marginRight" ), 2510 "float": element.css( "float" ) 2511 } ) 2512 .outerWidth( element.outerWidth() ) 2513 .outerHeight( element.outerHeight() ) 2514 .addClass( "ui-effects-placeholder" ); 2515 2516 element.data( dataSpace + "placeholder", placeholder ); 2517 } 2518 2519 element.css( { 2520 position: cssPosition, 2521 left: position.left, 2522 top: position.top 2523 } ); 2524 2525 return placeholder; 2526 }, 2527 2528 removePlaceholder: function( element ) { 2529 var dataKey = dataSpace + "placeholder", 2530 placeholder = element.data( dataKey ); 2531 2532 if ( placeholder ) { 2533 placeholder.remove(); 2534 element.removeData( dataKey ); 2535 } 2536 }, 2537 2538 // Removes a placeholder if it exists and restores 2539 // properties that were modified during placeholder creation 2540 cleanUp: function( element ) { 2541 $.effects.restoreStyle( element ); 2542 $.effects.removePlaceholder( element ); 2543 }, 2544 2545 setTransition: function( element, list, factor, value ) { 2546 value = value || {}; 2547 $.each( list, function( i, x ) { 2548 var unit = element.cssUnit( x ); 2549 if ( unit[ 0 ] > 0 ) { 2550 value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; 2551 } 2552 } ); 2553 return value; 2554 } 2555} ); 2556 2557// Return an effect options object for the given parameters: 2558function _normalizeArguments( effect, options, speed, callback ) { 2559 2560 // Allow passing all options as the first parameter 2561 if ( $.isPlainObject( effect ) ) { 2562 options = effect; 2563 effect = effect.effect; 2564 } 2565 2566 // Convert to an object 2567 effect = { effect: effect }; 2568 2569 // Catch (effect, null, ...) 2570 if ( options == null ) { 2571 options = {}; 2572 } 2573 2574 // Catch (effect, callback) 2575 if ( $.isFunction( options ) ) { 2576 callback = options; 2577 speed = null; 2578 options = {}; 2579 } 2580 2581 // Catch (effect, speed, ?) 2582 if ( typeof options === "number" || $.fx.speeds[ options ] ) { 2583 callback = speed; 2584 speed = options; 2585 options = {}; 2586 } 2587 2588 // Catch (effect, options, callback) 2589 if ( $.isFunction( speed ) ) { 2590 callback = speed; 2591 speed = null; 2592 } 2593 2594 // Add options to effect 2595 if ( options ) { 2596 $.extend( effect, options ); 2597 } 2598 2599 speed = speed || options.duration; 2600 effect.duration = $.fx.off ? 0 : 2601 typeof speed === "number" ? speed : 2602 speed in $.fx.speeds ? $.fx.speeds[ speed ] : 2603 $.fx.speeds._default; 2604 2605 effect.complete = callback || options.complete; 2606 2607 return effect; 2608} 2609 2610function standardAnimationOption( option ) { 2611 2612 // Valid standard speeds (nothing, number, named speed) 2613 if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) { 2614 return true; 2615 } 2616 2617 // Invalid strings - treat as "normal" speed 2618 if ( typeof option === "string" && !$.effects.effect[ option ] ) { 2619 return true; 2620 } 2621 2622 // Complete callback 2623 if ( $.isFunction( option ) ) { 2624 return true; 2625 } 2626 2627 // Options hash (but not naming an effect) 2628 if ( typeof option === "object" && !option.effect ) { 2629 return true; 2630 } 2631 2632 // Didn't match any standard API 2633 return false; 2634} 2635 2636$.fn.extend( { 2637 effect: function( /* effect, options, speed, callback */ ) { 2638 var args = _normalizeArguments.apply( this, arguments ), 2639 effectMethod = $.effects.effect[ args.effect ], 2640 defaultMode = effectMethod.mode, 2641 queue = args.queue, 2642 queueName = queue || "fx", 2643 complete = args.complete, 2644 mode = args.mode, 2645 modes = [], 2646 prefilter = function( next ) { 2647 var el = $( this ), 2648 normalizedMode = $.effects.mode( el, mode ) || defaultMode; 2649 2650 // Sentinel for duck-punching the :animated psuedo-selector 2651 el.data( dataSpaceAnimated, true ); 2652 2653 // Save effect mode for later use, 2654 // we can't just call $.effects.mode again later, 2655 // as the .show() below destroys the initial state 2656 modes.push( normalizedMode ); 2657 2658 // See $.uiBackCompat inside of run() for removal of defaultMode in 1.13 2659 if ( defaultMode && ( normalizedMode === "show" || 2660 ( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) { 2661 el.show(); 2662 } 2663 2664 if ( !defaultMode || normalizedMode !== "none" ) { 2665 $.effects.saveStyle( el ); 2666 } 2667 2668 if ( $.isFunction( next ) ) { 2669 next(); 2670 } 2671 }; 2672 2673 if ( $.fx.off || !effectMethod ) { 2674 2675 // Delegate to the original method (e.g., .show()) if possible 2676 if ( mode ) { 2677 return this[ mode ]( args.duration, complete ); 2678 } else { 2679 return this.each( function() { 2680 if ( complete ) { 2681 complete.call( this ); 2682 } 2683 } ); 2684 } 2685 } 2686 2687 function run( next ) { 2688 var elem = $( this ); 2689 2690 function cleanup() { 2691 elem.removeData( dataSpaceAnimated ); 2692 2693 $.effects.cleanUp( elem ); 2694 2695 if ( args.mode === "hide" ) { 2696 elem.hide(); 2697 } 2698 2699 done(); 2700 } 2701 2702 function done() { 2703 if ( $.isFunction( complete ) ) { 2704 complete.call( elem[ 0 ] ); 2705 } 2706 2707 if ( $.isFunction( next ) ) { 2708 next(); 2709 } 2710 } 2711 2712 // Override mode option on a per element basis, 2713 // as toggle can be either show or hide depending on element state 2714 args.mode = modes.shift(); 2715 2716 if ( $.uiBackCompat !== false && !defaultMode ) { 2717 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { 2718 2719 // Call the core method to track "olddisplay" properly 2720 elem[ mode ](); 2721 done(); 2722 } else { 2723 effectMethod.call( elem[ 0 ], args, done ); 2724 } 2725 } else { 2726 if ( args.mode === "none" ) { 2727 2728 // Call the core method to track "olddisplay" properly 2729 elem[ mode ](); 2730 done(); 2731 } else { 2732 effectMethod.call( elem[ 0 ], args, cleanup ); 2733 } 2734 } 2735 } 2736 2737 // Run prefilter on all elements first to ensure that 2738 // any showing or hiding happens before placeholder creation, 2739 // which ensures that any layout changes are correctly captured. 2740 return queue === false ? 2741 this.each( prefilter ).each( run ) : 2742 this.queue( queueName, prefilter ).queue( queueName, run ); 2743 }, 2744 2745 show: ( function( orig ) { 2746 return function( option ) { 2747 if ( standardAnimationOption( option ) ) { 2748 return orig.apply( this, arguments ); 2749 } else { 2750 var args = _normalizeArguments.apply( this, arguments ); 2751 args.mode = "show"; 2752 return this.effect.call( this, args ); 2753 } 2754 }; 2755 } )( $.fn.show ), 2756 2757 hide: ( function( orig ) { 2758 return function( option ) { 2759 if ( standardAnimationOption( option ) ) { 2760 return orig.apply( this, arguments ); 2761 } else { 2762 var args = _normalizeArguments.apply( this, arguments ); 2763 args.mode = "hide"; 2764 return this.effect.call( this, args ); 2765 } 2766 }; 2767 } )( $.fn.hide ), 2768 2769 toggle: ( function( orig ) { 2770 return function( option ) { 2771 if ( standardAnimationOption( option ) || typeof option === "boolean" ) { 2772 return orig.apply( this, arguments ); 2773 } else { 2774 var args = _normalizeArguments.apply( this, arguments ); 2775 args.mode = "toggle"; 2776 return this.effect.call( this, args ); 2777 } 2778 }; 2779 } )( $.fn.toggle ), 2780 2781 cssUnit: function( key ) { 2782 var style = this.css( key ), 2783 val = []; 2784 2785 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { 2786 if ( style.indexOf( unit ) > 0 ) { 2787 val = [ parseFloat( style ), unit ]; 2788 } 2789 } ); 2790 return val; 2791 }, 2792 2793 cssClip: function( clipObj ) { 2794 if ( clipObj ) { 2795 return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " + 2796 clipObj.bottom + "px " + clipObj.left + "px)" ); 2797 } 2798 return parseClip( this.css( "clip" ), this ); 2799 }, 2800 2801 transfer: function( options, done ) { 2802 var element = $( this ), 2803 target = $( options.to ), 2804 targetFixed = target.css( "position" ) === "fixed", 2805 body = $( "body" ), 2806 fixTop = targetFixed ? body.scrollTop() : 0, 2807 fixLeft = targetFixed ? body.scrollLeft() : 0, 2808 endPosition = target.offset(), 2809 animation = { 2810 top: endPosition.top - fixTop, 2811 left: endPosition.left - fixLeft, 2812 height: target.innerHeight(), 2813 width: target.innerWidth() 2814 }, 2815 startPosition = element.offset(), 2816 transfer = $( "<div class='ui-effects-transfer'></div>" ) 2817 .appendTo( "body" ) 2818 .addClass( options.className ) 2819 .css( { 2820 top: startPosition.top - fixTop, 2821 left: startPosition.left - fixLeft, 2822 height: element.innerHeight(), 2823 width: element.innerWidth(), 2824 position: targetFixed ? "fixed" : "absolute" 2825 } ) 2826 .animate( animation, options.duration, options.easing, function() { 2827 transfer.remove(); 2828 if ( $.isFunction( done ) ) { 2829 done(); 2830 } 2831 2832 } ); 2833 } 2834} ); 2835 2836function parseClip( str, element ) { 2837 var outerWidth = element.outerWidth(), 2838 outerHeight = element.outerHeight(), 2839 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)\)$/, 2840 values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ]; 2841 2842 return { 2843 top: parseFloat( values[ 1 ] ) || 0, 2844 right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ), 2845 bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ), 2846 left: parseFloat( values[ 4 ] ) || 0 2847 }; 2848} 2849 2850$.fx.step.clip = function( fx ) { 2851 if ( !fx.clipInit ) { 2852 fx.start = $( fx.elem ).cssClip(); 2853 if ( typeof fx.end === "string" ) { 2854 fx.end = parseClip( fx.end, fx.elem ); 2855 } 2856 fx.clipInit = true; 2857 } 2858 2859 $( fx.elem ).cssClip( { 2860 top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top, 2861 right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right, 2862 bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom, 2863 left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left 2864 } ); 2865}; 2866 2867} )(); 2868 2869/******************************************************************************/ 2870/*********************************** EASING ***********************************/ 2871/******************************************************************************/ 2872 2873( function() { 2874 2875// Based on easing equations from Robert Penner (http://www.robertpenner.com/easing) 2876 2877var baseEasings = {}; 2878 2879$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { 2880 baseEasings[ name ] = function( p ) { 2881 return Math.pow( p, i + 2 ); 2882 }; 2883} ); 2884 2885$.extend( baseEasings, { 2886 Sine: function( p ) { 2887 return 1 - Math.cos( p * Math.PI / 2 ); 2888 }, 2889 Circ: function( p ) { 2890 return 1 - Math.sqrt( 1 - p * p ); 2891 }, 2892 Elastic: function( p ) { 2893 return p === 0 || p === 1 ? p : 2894 -Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 ); 2895 }, 2896 Back: function( p ) { 2897 return p * p * ( 3 * p - 2 ); 2898 }, 2899 Bounce: function( p ) { 2900 var pow2, 2901 bounce = 4; 2902 2903 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} 2904 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); 2905 } 2906} ); 2907 2908$.each( baseEasings, function( name, easeIn ) { 2909 $.easing[ "easeIn" + name ] = easeIn; 2910 $.easing[ "easeOut" + name ] = function( p ) { 2911 return 1 - easeIn( 1 - p ); 2912 }; 2913 $.easing[ "easeInOut" + name ] = function( p ) { 2914 return p < 0.5 ? 2915 easeIn( p * 2 ) / 2 : 2916 1 - easeIn( p * -2 + 2 ) / 2; 2917 }; 2918} ); 2919 2920} )(); 2921 2922var effect = $.effects; 2923 2924 2925/*! 2926 * jQuery UI Effects Blind 1.12.1 2927 * http://jqueryui.com 2928 * 2929 * Copyright jQuery Foundation and other contributors 2930 * Released under the MIT license. 2931 * http://jquery.org/license 2932 */ 2933 2934//>>label: Blind Effect 2935//>>group: Effects 2936//>>description: Blinds the element. 2937//>>docs: http://api.jqueryui.com/blind-effect/ 2938//>>demos: http://jqueryui.com/effect/ 2939 2940 2941 2942var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) { 2943 var map = { 2944 up: [ "bottom", "top" ], 2945 vertical: [ "bottom", "top" ], 2946 down: [ "top", "bottom" ], 2947 left: [ "right", "left" ], 2948 horizontal: [ "right", "left" ], 2949 right: [ "left", "right" ] 2950 }, 2951 element = $( this ), 2952 direction = options.direction || "up", 2953 start = element.cssClip(), 2954 animate = { clip: $.extend( {}, start ) }, 2955 placeholder = $.effects.createPlaceholder( element ); 2956 2957 animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ]; 2958 2959 if ( options.mode === "show" ) { 2960 element.cssClip( animate.clip ); 2961 if ( placeholder ) { 2962 placeholder.css( $.effects.clipToBox( animate ) ); 2963 } 2964 2965 animate.clip = start; 2966 } 2967 2968 if ( placeholder ) { 2969 placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing ); 2970 } 2971 2972 element.animate( animate, { 2973 queue: false, 2974 duration: options.duration, 2975 easing: options.easing, 2976 complete: done 2977 } ); 2978} ); 2979 2980 2981/*! 2982 * jQuery UI Effects Bounce 1.12.1 2983 * http://jqueryui.com 2984 * 2985 * Copyright jQuery Foundation and other contributors 2986 * Released under the MIT license. 2987 * http://jquery.org/license 2988 */ 2989 2990//>>label: Bounce Effect 2991//>>group: Effects 2992//>>description: Bounces an element horizontally or vertically n times. 2993//>>docs: http://api.jqueryui.com/bounce-effect/ 2994//>>demos: http://jqueryui.com/effect/ 2995 2996 2997 2998var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) { 2999 var upAnim, downAnim, refValue, 3000 element = $( this ), 3001 3002 // Defaults: 3003 mode = options.mode, 3004 hide = mode === "hide", 3005 show = mode === "show", 3006 direction = options.direction || "up", 3007 distance = options.distance, 3008 times = options.times || 5, 3009 3010 // Number of internal animations 3011 anims = times * 2 + ( show || hide ? 1 : 0 ), 3012 speed = options.duration / anims, 3013 easing = options.easing, 3014 3015 // Utility: 3016 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 3017 motion = ( direction === "up" || direction === "left" ), 3018 i = 0, 3019 3020 queuelen = element.queue().length; 3021 3022 $.effects.createPlaceholder( element ); 3023 3024 refValue = element.css( ref ); 3025 3026 // Default distance for the BIGGEST bounce is the outer Distance / 3 3027 if ( !distance ) { 3028 distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; 3029 } 3030 3031 if ( show ) { 3032 downAnim = { opacity: 1 }; 3033 downAnim[ ref ] = refValue; 3034 3035 // If we are showing, force opacity 0 and set the initial position 3036 // then do the "first" animation 3037 element 3038 .css( "opacity", 0 ) 3039 .css( ref, motion ? -distance * 2 : distance * 2 ) 3040 .animate( downAnim, speed, easing ); 3041 } 3042 3043 // Start at the smallest distance if we are hiding 3044 if ( hide ) { 3045 distance = distance / Math.pow( 2, times - 1 ); 3046 } 3047 3048 downAnim = {}; 3049 downAnim[ ref ] = refValue; 3050 3051 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here 3052 for ( ; i < times; i++ ) { 3053 upAnim = {}; 3054 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 3055 3056 element 3057 .animate( upAnim, speed, easing ) 3058 .animate( downAnim, speed, easing ); 3059 3060 distance = hide ? distance * 2 : distance / 2; 3061 } 3062 3063 // Last Bounce when Hiding 3064 if ( hide ) { 3065 upAnim = { opacity: 0 }; 3066 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 3067 3068 element.animate( upAnim, speed, easing ); 3069 } 3070 3071 element.queue( done ); 3072 3073 $.effects.unshift( element, queuelen, anims + 1 ); 3074} ); 3075 3076 3077/*! 3078 * jQuery UI Effects Clip 1.12.1 3079 * http://jqueryui.com 3080 * 3081 * Copyright jQuery Foundation and other contributors 3082 * Released under the MIT license. 3083 * http://jquery.org/license 3084 */ 3085 3086//>>label: Clip Effect 3087//>>group: Effects 3088//>>description: Clips the element on and off like an old TV. 3089//>>docs: http://api.jqueryui.com/clip-effect/ 3090//>>demos: http://jqueryui.com/effect/ 3091 3092 3093 3094var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) { 3095 var start, 3096 animate = {}, 3097 element = $( this ), 3098 direction = options.direction || "vertical", 3099 both = direction === "both", 3100 horizontal = both || direction === "horizontal", 3101 vertical = both || direction === "vertical"; 3102 3103 start = element.cssClip(); 3104 animate.clip = { 3105 top: vertical ? ( start.bottom - start.top ) / 2 : start.top, 3106 right: horizontal ? ( start.right - start.left ) / 2 : start.right, 3107 bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom, 3108 left: horizontal ? ( start.right - start.left ) / 2 : start.left 3109 }; 3110 3111 $.effects.createPlaceholder( element ); 3112 3113 if ( options.mode === "show" ) { 3114 element.cssClip( animate.clip ); 3115 animate.clip = start; 3116 } 3117 3118 element.animate( animate, { 3119 queue: false, 3120 duration: options.duration, 3121 easing: options.easing, 3122 complete: done 3123 } ); 3124 3125} ); 3126 3127 3128/*! 3129 * jQuery UI Effects Drop 1.12.1 3130 * http://jqueryui.com 3131 * 3132 * Copyright jQuery Foundation and other contributors 3133 * Released under the MIT license. 3134 * http://jquery.org/license 3135 */ 3136 3137//>>label: Drop Effect 3138//>>group: Effects 3139//>>description: Moves an element in one direction and hides it at the same time. 3140//>>docs: http://api.jqueryui.com/drop-effect/ 3141//>>demos: http://jqueryui.com/effect/ 3142 3143 3144 3145var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) { 3146 3147 var distance, 3148 element = $( this ), 3149 mode = options.mode, 3150 show = mode === "show", 3151 direction = options.direction || "left", 3152 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 3153 motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=", 3154 oppositeMotion = ( motion === "+=" ) ? "-=" : "+=", 3155 animation = { 3156 opacity: 0 3157 }; 3158 3159 $.effects.createPlaceholder( element ); 3160 3161 distance = options.distance || 3162 element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2; 3163 3164 animation[ ref ] = motion + distance; 3165 3166 if ( show ) { 3167 element.css( animation ); 3168 3169 animation[ ref ] = oppositeMotion + distance; 3170 animation.opacity = 1; 3171 } 3172 3173 // Animate 3174 element.animate( animation, { 3175 queue: false, 3176 duration: options.duration, 3177 easing: options.easing, 3178 complete: done 3179 } ); 3180} ); 3181 3182 3183/*! 3184 * jQuery UI Effects Explode 1.12.1 3185 * http://jqueryui.com 3186 * 3187 * Copyright jQuery Foundation and other contributors 3188 * Released under the MIT license. 3189 * http://jquery.org/license 3190 */ 3191 3192//>>label: Explode Effect 3193//>>group: Effects 3194// jscs:disable maximumLineLength 3195//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness. 3196// jscs:enable maximumLineLength 3197//>>docs: http://api.jqueryui.com/explode-effect/ 3198//>>demos: http://jqueryui.com/effect/ 3199 3200 3201 3202var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) { 3203 3204 var i, j, left, top, mx, my, 3205 rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3, 3206 cells = rows, 3207 element = $( this ), 3208 mode = options.mode, 3209 show = mode === "show", 3210 3211 // Show and then visibility:hidden the element before calculating offset 3212 offset = element.show().css( "visibility", "hidden" ).offset(), 3213 3214 // Width and height of a piece 3215 width = Math.ceil( element.outerWidth() / cells ), 3216 height = Math.ceil( element.outerHeight() / rows ), 3217 pieces = []; 3218 3219 // Children animate complete: 3220 function childComplete() { 3221 pieces.push( this ); 3222 if ( pieces.length === rows * cells ) { 3223 animComplete(); 3224 } 3225 } 3226 3227 // Clone the element for each row and cell. 3228 for ( i = 0; i < rows; i++ ) { // ===> 3229 top = offset.top + i * height; 3230 my = i - ( rows - 1 ) / 2; 3231 3232 for ( j = 0; j < cells; j++ ) { // ||| 3233 left = offset.left + j * width; 3234 mx = j - ( cells - 1 ) / 2; 3235 3236 // Create a clone of the now hidden main element that will be absolute positioned 3237 // within a wrapper div off the -left and -top equal to size of our pieces 3238 element 3239 .clone() 3240 .appendTo( "body" ) 3241 .wrap( "<div></div>" ) 3242 .css( { 3243 position: "absolute", 3244 visibility: "visible", 3245 left: -j * width, 3246 top: -i * height 3247 } ) 3248 3249 // Select the wrapper - make it overflow: hidden and absolute positioned based on 3250 // where the original was located +left and +top equal to the size of pieces 3251 .parent() 3252 .addClass( "ui-effects-explode" ) 3253 .css( { 3254 position: "absolute", 3255 overflow: "hidden", 3256 width: width, 3257 height: height, 3258 left: left + ( show ? mx * width : 0 ), 3259 top: top + ( show ? my * height : 0 ), 3260 opacity: show ? 0 : 1 3261 } ) 3262 .animate( { 3263 left: left + ( show ? 0 : mx * width ), 3264 top: top + ( show ? 0 : my * height ), 3265 opacity: show ? 1 : 0 3266 }, options.duration || 500, options.easing, childComplete ); 3267 } 3268 } 3269 3270 function animComplete() { 3271 element.css( { 3272 visibility: "visible" 3273 } ); 3274 $( pieces ).remove(); 3275 done(); 3276 } 3277} ); 3278 3279 3280/*! 3281 * jQuery UI Effects Fade 1.12.1 3282 * http://jqueryui.com 3283 * 3284 * Copyright jQuery Foundation and other contributors 3285 * Released under the MIT license. 3286 * http://jquery.org/license 3287 */ 3288 3289//>>label: Fade Effect 3290//>>group: Effects 3291//>>description: Fades the element. 3292//>>docs: http://api.jqueryui.com/fade-effect/ 3293//>>demos: http://jqueryui.com/effect/ 3294 3295 3296 3297var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) { 3298 var show = options.mode === "show"; 3299 3300 $( this ) 3301 .css( "opacity", show ? 0 : 1 ) 3302 .animate( { 3303 opacity: show ? 1 : 0 3304 }, { 3305 queue: false, 3306 duration: options.duration, 3307 easing: options.easing, 3308 complete: done 3309 } ); 3310} ); 3311 3312 3313/*! 3314 * jQuery UI Effects Fold 1.12.1 3315 * http://jqueryui.com 3316 * 3317 * Copyright jQuery Foundation and other contributors 3318 * Released under the MIT license. 3319 * http://jquery.org/license 3320 */ 3321 3322//>>label: Fold Effect 3323//>>group: Effects 3324//>>description: Folds an element first horizontally and then vertically. 3325//>>docs: http://api.jqueryui.com/fold-effect/ 3326//>>demos: http://jqueryui.com/effect/ 3327 3328 3329 3330var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) { 3331 3332 // Create element 3333 var element = $( this ), 3334 mode = options.mode, 3335 show = mode === "show", 3336 hide = mode === "hide", 3337 size = options.size || 15, 3338 percent = /([0-9]+)%/.exec( size ), 3339 horizFirst = !!options.horizFirst, 3340 ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ], 3341 duration = options.duration / 2, 3342 3343 placeholder = $.effects.createPlaceholder( element ), 3344 3345 start = element.cssClip(), 3346 animation1 = { clip: $.extend( {}, start ) }, 3347 animation2 = { clip: $.extend( {}, start ) }, 3348 3349 distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ], 3350 3351 queuelen = element.queue().length; 3352 3353 if ( percent ) { 3354 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; 3355 } 3356 animation1.clip[ ref[ 0 ] ] = size; 3357 animation2.clip[ ref[ 0 ] ] = size; 3358 animation2.clip[ ref[ 1 ] ] = 0; 3359 3360 if ( show ) { 3361 element.cssClip( animation2.clip ); 3362 if ( placeholder ) { 3363 placeholder.css( $.effects.clipToBox( animation2 ) ); 3364 } 3365 3366 animation2.clip = start; 3367 } 3368 3369 // Animate 3370 element 3371 .queue( function( next ) { 3372 if ( placeholder ) { 3373 placeholder 3374 .animate( $.effects.clipToBox( animation1 ), duration, options.easing ) 3375 .animate( $.effects.clipToBox( animation2 ), duration, options.easing ); 3376 } 3377 3378 next(); 3379 } ) 3380 .animate( animation1, duration, options.easing ) 3381 .animate( animation2, duration, options.easing ) 3382 .queue( done ); 3383 3384 $.effects.unshift( element, queuelen, 4 ); 3385} ); 3386 3387 3388/*! 3389 * jQuery UI Effects Highlight 1.12.1 3390 * http://jqueryui.com 3391 * 3392 * Copyright jQuery Foundation and other contributors 3393 * Released under the MIT license. 3394 * http://jquery.org/license 3395 */ 3396 3397//>>label: Highlight Effect 3398//>>group: Effects 3399//>>description: Highlights the background of an element in a defined color for a custom duration. 3400//>>docs: http://api.jqueryui.com/highlight-effect/ 3401//>>demos: http://jqueryui.com/effect/ 3402 3403 3404 3405var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) { 3406 var element = $( this ), 3407 animation = { 3408 backgroundColor: element.css( "backgroundColor" ) 3409 }; 3410 3411 if ( options.mode === "hide" ) { 3412 animation.opacity = 0; 3413 } 3414 3415 $.effects.saveStyle( element ); 3416 3417 element 3418 .css( { 3419 backgroundImage: "none", 3420 backgroundColor: options.color || "#ffff99" 3421 } ) 3422 .animate( animation, { 3423 queue: false, 3424 duration: options.duration, 3425 easing: options.easing, 3426 complete: done 3427 } ); 3428} ); 3429 3430 3431/*! 3432 * jQuery UI Effects Size 1.12.1 3433 * http://jqueryui.com 3434 * 3435 * Copyright jQuery Foundation and other contributors 3436 * Released under the MIT license. 3437 * http://jquery.org/license 3438 */ 3439 3440//>>label: Size Effect 3441//>>group: Effects 3442//>>description: Resize an element to a specified width and height. 3443//>>docs: http://api.jqueryui.com/size-effect/ 3444//>>demos: http://jqueryui.com/effect/ 3445 3446 3447 3448var effectsEffectSize = $.effects.define( "size", function( options, done ) { 3449 3450 // Create element 3451 var baseline, factor, temp, 3452 element = $( this ), 3453 3454 // Copy for children 3455 cProps = [ "fontSize" ], 3456 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], 3457 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], 3458 3459 // Set options 3460 mode = options.mode, 3461 restore = mode !== "effect", 3462 scale = options.scale || "both", 3463 origin = options.origin || [ "middle", "center" ], 3464 position = element.css( "position" ), 3465 pos = element.position(), 3466 original = $.effects.scaledDimensions( element ), 3467 from = options.from || original, 3468 to = options.to || $.effects.scaledDimensions( element, 0 ); 3469 3470 $.effects.createPlaceholder( element ); 3471 3472 if ( mode === "show" ) { 3473 temp = from; 3474 from = to; 3475 to = temp; 3476 } 3477 3478 // Set scaling factor 3479 factor = { 3480 from: { 3481 y: from.height / original.height, 3482 x: from.width / original.width 3483 }, 3484 to: { 3485 y: to.height / original.height, 3486 x: to.width / original.width 3487 } 3488 }; 3489 3490 // Scale the css box 3491 if ( scale === "box" || scale === "both" ) { 3492 3493 // Vertical props scaling 3494 if ( factor.from.y !== factor.to.y ) { 3495 from = $.effects.setTransition( element, vProps, factor.from.y, from ); 3496 to = $.effects.setTransition( element, vProps, factor.to.y, to ); 3497 } 3498 3499 // Horizontal props scaling 3500 if ( factor.from.x !== factor.to.x ) { 3501 from = $.effects.setTransition( element, hProps, factor.from.x, from ); 3502 to = $.effects.setTransition( element, hProps, factor.to.x, to ); 3503 } 3504 } 3505 3506 // Scale the content 3507 if ( scale === "content" || scale === "both" ) { 3508 3509 // Vertical props scaling 3510 if ( factor.from.y !== factor.to.y ) { 3511 from = $.effects.setTransition( element, cProps, factor.from.y, from ); 3512 to = $.effects.setTransition( element, cProps, factor.to.y, to ); 3513 } 3514 } 3515 3516 // Adjust the position properties based on the provided origin points 3517 if ( origin ) { 3518 baseline = $.effects.getBaseline( origin, original ); 3519 from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top; 3520 from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left; 3521 to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top; 3522 to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left; 3523 } 3524 element.css( from ); 3525 3526 // Animate the children if desired 3527 if ( scale === "content" || scale === "both" ) { 3528 3529 vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps ); 3530 hProps = hProps.concat( [ "marginLeft", "marginRight" ] ); 3531 3532 // Only animate children with width attributes specified 3533 // TODO: is this right? should we include anything with css width specified as well 3534 element.find( "*[width]" ).each( function() { 3535 var child = $( this ), 3536 childOriginal = $.effects.scaledDimensions( child ), 3537 childFrom = { 3538 height: childOriginal.height * factor.from.y, 3539 width: childOriginal.width * factor.from.x, 3540 outerHeight: childOriginal.outerHeight * factor.from.y, 3541 outerWidth: childOriginal.outerWidth * factor.from.x 3542 }, 3543 childTo = { 3544 height: childOriginal.height * factor.to.y, 3545 width: childOriginal.width * factor.to.x, 3546 outerHeight: childOriginal.height * factor.to.y, 3547 outerWidth: childOriginal.width * factor.to.x 3548 }; 3549 3550 // Vertical props scaling 3551 if ( factor.from.y !== factor.to.y ) { 3552 childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom ); 3553 childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo ); 3554 } 3555 3556 // Horizontal props scaling 3557 if ( factor.from.x !== factor.to.x ) { 3558 childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom ); 3559 childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo ); 3560 } 3561 3562 if ( restore ) { 3563 $.effects.saveStyle( child ); 3564 } 3565 3566 // Animate children 3567 child.css( childFrom ); 3568 child.animate( childTo, options.duration, options.easing, function() { 3569 3570 // Restore children 3571 if ( restore ) { 3572 $.effects.restoreStyle( child ); 3573 } 3574 } ); 3575 } ); 3576 } 3577 3578 // Animate 3579 element.animate( to, { 3580 queue: false, 3581 duration: options.duration, 3582 easing: options.easing, 3583 complete: function() { 3584 3585 var offset = element.offset(); 3586 3587 if ( to.opacity === 0 ) { 3588 element.css( "opacity", from.opacity ); 3589 } 3590 3591 if ( !restore ) { 3592 element 3593 .css( "position", position === "static" ? "relative" : position ) 3594 .offset( offset ); 3595 3596 // Need to save style here so that automatic style restoration 3597 // doesn't restore to the original styles from before the animation. 3598 $.effects.saveStyle( element ); 3599 } 3600 3601 done(); 3602 } 3603 } ); 3604 3605} ); 3606 3607 3608/*! 3609 * jQuery UI Effects Scale 1.12.1 3610 * http://jqueryui.com 3611 * 3612 * Copyright jQuery Foundation and other contributors 3613 * Released under the MIT license. 3614 * http://jquery.org/license 3615 */ 3616 3617//>>label: Scale Effect 3618//>>group: Effects 3619//>>description: Grows or shrinks an element and its content. 3620//>>docs: http://api.jqueryui.com/scale-effect/ 3621//>>demos: http://jqueryui.com/effect/ 3622 3623 3624 3625var effectsEffectScale = $.effects.define( "scale", function( options, done ) { 3626 3627 // Create element 3628 var el = $( this ), 3629 mode = options.mode, 3630 percent = parseInt( options.percent, 10 ) || 3631 ( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ), 3632 3633 newOptions = $.extend( true, { 3634 from: $.effects.scaledDimensions( el ), 3635 to: $.effects.scaledDimensions( el, percent, options.direction || "both" ), 3636 origin: options.origin || [ "middle", "center" ] 3637 }, options ); 3638 3639 // Fade option to support puff 3640 if ( options.fade ) { 3641 newOptions.from.opacity = 1; 3642 newOptions.to.opacity = 0; 3643 } 3644 3645 $.effects.effect.size.call( this, newOptions, done ); 3646} ); 3647 3648 3649/*! 3650 * jQuery UI Effects Puff 1.12.1 3651 * http://jqueryui.com 3652 * 3653 * Copyright jQuery Foundation and other contributors 3654 * Released under the MIT license. 3655 * http://jquery.org/license 3656 */ 3657 3658//>>label: Puff Effect 3659//>>group: Effects 3660//>>description: Creates a puff effect by scaling the element up and hiding it at the same time. 3661//>>docs: http://api.jqueryui.com/puff-effect/ 3662//>>demos: http://jqueryui.com/effect/ 3663 3664 3665 3666var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) { 3667 var newOptions = $.extend( true, {}, options, { 3668 fade: true, 3669 percent: parseInt( options.percent, 10 ) || 150 3670 } ); 3671 3672 $.effects.effect.scale.call( this, newOptions, done ); 3673} ); 3674 3675 3676/*! 3677 * jQuery UI Effects Pulsate 1.12.1 3678 * http://jqueryui.com 3679 * 3680 * Copyright jQuery Foundation and other contributors 3681 * Released under the MIT license. 3682 * http://jquery.org/license 3683 */ 3684 3685//>>label: Pulsate Effect 3686//>>group: Effects 3687//>>description: Pulsates an element n times by changing the opacity to zero and back. 3688//>>docs: http://api.jqueryui.com/pulsate-effect/ 3689//>>demos: http://jqueryui.com/effect/ 3690 3691 3692 3693var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) { 3694 var element = $( this ), 3695 mode = options.mode, 3696 show = mode === "show", 3697 hide = mode === "hide", 3698 showhide = show || hide, 3699 3700 // Showing or hiding leaves off the "last" animation 3701 anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), 3702 duration = options.duration / anims, 3703 animateTo = 0, 3704 i = 1, 3705 queuelen = element.queue().length; 3706 3707 if ( show || !element.is( ":visible" ) ) { 3708 element.css( "opacity", 0 ).show(); 3709 animateTo = 1; 3710 } 3711 3712 // Anims - 1 opacity "toggles" 3713 for ( ; i < anims; i++ ) { 3714 element.animate( { opacity: animateTo }, duration, options.easing ); 3715 animateTo = 1 - animateTo; 3716 } 3717 3718 element.animate( { opacity: animateTo }, duration, options.easing ); 3719 3720 element.queue( done ); 3721 3722 $.effects.unshift( element, queuelen, anims + 1 ); 3723} ); 3724 3725 3726/*! 3727 * jQuery UI Effects Shake 1.12.1 3728 * http://jqueryui.com 3729 * 3730 * Copyright jQuery Foundation and other contributors 3731 * Released under the MIT license. 3732 * http://jquery.org/license 3733 */ 3734 3735//>>label: Shake Effect 3736//>>group: Effects 3737//>>description: Shakes an element horizontally or vertically n times. 3738//>>docs: http://api.jqueryui.com/shake-effect/ 3739//>>demos: http://jqueryui.com/effect/ 3740 3741 3742 3743var effectsEffectShake = $.effects.define( "shake", function( options, done ) { 3744 3745 var i = 1, 3746 element = $( this ), 3747 direction = options.direction || "left", 3748 distance = options.distance || 20, 3749 times = options.times || 3, 3750 anims = times * 2 + 1, 3751 speed = Math.round( options.duration / anims ), 3752 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 3753 positiveMotion = ( direction === "up" || direction === "left" ), 3754 animation = {}, 3755 animation1 = {}, 3756 animation2 = {}, 3757 3758 queuelen = element.queue().length; 3759 3760 $.effects.createPlaceholder( element ); 3761 3762 // Animation 3763 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; 3764 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; 3765 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; 3766 3767 // Animate 3768 element.animate( animation, speed, options.easing ); 3769 3770 // Shakes 3771 for ( ; i < times; i++ ) { 3772 element 3773 .animate( animation1, speed, options.easing ) 3774 .animate( animation2, speed, options.easing ); 3775 } 3776 3777 element 3778 .animate( animation1, speed, options.easing ) 3779 .animate( animation, speed / 2, options.easing ) 3780 .queue( done ); 3781 3782 $.effects.unshift( element, queuelen, anims + 1 ); 3783} ); 3784 3785 3786/*! 3787 * jQuery UI Effects Slide 1.12.1 3788 * http://jqueryui.com 3789 * 3790 * Copyright jQuery Foundation and other contributors 3791 * Released under the MIT license. 3792 * http://jquery.org/license 3793 */ 3794 3795//>>label: Slide Effect 3796//>>group: Effects 3797//>>description: Slides an element in and out of the viewport. 3798//>>docs: http://api.jqueryui.com/slide-effect/ 3799//>>demos: http://jqueryui.com/effect/ 3800 3801 3802 3803var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) { 3804 var startClip, startRef, 3805 element = $( this ), 3806 map = { 3807 up: [ "bottom", "top" ], 3808 down: [ "top", "bottom" ], 3809 left: [ "right", "left" ], 3810 right: [ "left", "right" ] 3811 }, 3812 mode = options.mode, 3813 direction = options.direction || "left", 3814 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 3815 positiveMotion = ( direction === "up" || direction === "left" ), 3816 distance = options.distance || 3817 element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ), 3818 animation = {}; 3819 3820 $.effects.createPlaceholder( element ); 3821 3822 startClip = element.cssClip(); 3823 startRef = element.position()[ ref ]; 3824 3825 // Define hide animation 3826 animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef; 3827 animation.clip = element.cssClip(); 3828 animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ]; 3829 3830 // Reverse the animation if we're showing 3831 if ( mode === "show" ) { 3832 element.cssClip( animation.clip ); 3833 element.css( ref, animation[ ref ] ); 3834 animation.clip = startClip; 3835 animation[ ref ] = startRef; 3836 } 3837 3838 // Actually animate 3839 element.animate( animation, { 3840 queue: false, 3841 duration: options.duration, 3842 easing: options.easing, 3843 complete: done 3844 } ); 3845} ); 3846 3847 3848/*! 3849 * jQuery UI Effects Transfer 1.12.1 3850 * http://jqueryui.com 3851 * 3852 * Copyright jQuery Foundation and other contributors 3853 * Released under the MIT license. 3854 * http://jquery.org/license 3855 */ 3856 3857//>>label: Transfer Effect 3858//>>group: Effects 3859//>>description: Displays a transfer effect from one element to another. 3860//>>docs: http://api.jqueryui.com/transfer-effect/ 3861//>>demos: http://jqueryui.com/effect/ 3862 3863 3864 3865var effect; 3866if ( $.uiBackCompat !== false ) { 3867 effect = $.effects.define( "transfer", function( options, done ) { 3868 $( this ).transfer( options, done ); 3869 } ); 3870} 3871var effectsEffectTransfer = effect; 3872 3873 3874/*! 3875 * jQuery UI Focusable 1.12.1 3876 * http://jqueryui.com 3877 * 3878 * Copyright jQuery Foundation and other contributors 3879 * Released under the MIT license. 3880 * http://jquery.org/license 3881 */ 3882 3883//>>label: :focusable Selector 3884//>>group: Core 3885//>>description: Selects elements which can be focused. 3886//>>docs: http://api.jqueryui.com/focusable-selector/ 3887 3888 3889 3890// Selectors 3891$.ui.focusable = function( element, hasTabindex ) { 3892 var map, mapName, img, focusableIfVisible, fieldset, 3893 nodeName = element.nodeName.toLowerCase(); 3894 3895 if ( "area" === nodeName ) { 3896 map = element.parentNode; 3897 mapName = map.name; 3898 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { 3899 return false; 3900 } 3901 img = $( "img[usemap='#" + mapName + "']" ); 3902 return img.length > 0 && img.is( ":visible" ); 3903 } 3904 3905 if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) { 3906 focusableIfVisible = !element.disabled; 3907 3908 if ( focusableIfVisible ) { 3909 3910 // Form controls within a disabled fieldset are disabled. 3911 // However, controls within the fieldset's legend do not get disabled. 3912 // Since controls generally aren't placed inside legends, we skip 3913 // this portion of the check. 3914 fieldset = $( element ).closest( "fieldset" )[ 0 ]; 3915 if ( fieldset ) { 3916 focusableIfVisible = !fieldset.disabled; 3917 } 3918 } 3919 } else if ( "a" === nodeName ) { 3920 focusableIfVisible = element.href || hasTabindex; 3921 } else { 3922 focusableIfVisible = hasTabindex; 3923 } 3924 3925 return focusableIfVisible && $( element ).is( ":visible" ) && visible( $( element ) ); 3926}; 3927 3928// Support: IE 8 only 3929// IE 8 doesn't resolve inherit to visible/hidden for computed values 3930function visible( element ) { 3931 var visibility = element.css( "visibility" ); 3932 while ( visibility === "inherit" ) { 3933 element = element.parent(); 3934 visibility = element.css( "visibility" ); 3935 } 3936 return visibility !== "hidden"; 3937} 3938 3939$.extend( $.expr[ ":" ], { 3940 focusable: function( element ) { 3941 return $.ui.focusable( element, $.attr( element, "tabindex" ) != null ); 3942 } 3943} ); 3944 3945var focusable = $.ui.focusable; 3946 3947 3948 3949 3950// Support: IE8 Only 3951// IE8 does not support the form attribute and when it is supplied. It overwrites the form prop 3952// with a string, so we need to find the proper form. 3953var form = $.fn.form = function() { 3954 return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form ); 3955}; 3956 3957 3958/*! 3959 * jQuery UI Form Reset Mixin 1.12.1 3960 * http://jqueryui.com 3961 * 3962 * Copyright jQuery Foundation and other contributors 3963 * Released under the MIT license. 3964 * http://jquery.org/license 3965 */ 3966 3967//>>label: Form Reset Mixin 3968//>>group: Core 3969//>>description: Refresh input widgets when their form is reset 3970//>>docs: http://api.jqueryui.com/form-reset-mixin/ 3971 3972 3973 3974var formResetMixin = $.ui.formResetMixin = { 3975 _formResetHandler: function() { 3976 var form = $( this ); 3977 3978 // Wait for the form reset to actually happen before refreshing 3979 setTimeout( function() { 3980 var instances = form.data( "ui-form-reset-instances" ); 3981 $.each( instances, function() { 3982 this.refresh(); 3983 } ); 3984 } ); 3985 }, 3986 3987 _bindFormResetHandler: function() { 3988 this.form = this.element.form(); 3989 if ( !this.form.length ) { 3990 return; 3991 } 3992 3993 var instances = this.form.data( "ui-form-reset-instances" ) || []; 3994 if ( !instances.length ) { 3995 3996 // We don't use _on() here because we use a single event handler per form 3997 this.form.on( "reset.ui-form-reset", this._formResetHandler ); 3998 } 3999 instances.push( this ); 4000 this.form.data( "ui-form-reset-instances", instances ); 4001 }, 4002 4003 _unbindFormResetHandler: function() { 4004 if ( !this.form.length ) { 4005 return; 4006 } 4007 4008 var instances = this.form.data( "ui-form-reset-instances" ); 4009 instances.splice( $.inArray( this, instances ), 1 ); 4010 if ( instances.length ) { 4011 this.form.data( "ui-form-reset-instances", instances ); 4012 } else { 4013 this.form 4014 .removeData( "ui-form-reset-instances" ) 4015 .off( "reset.ui-form-reset" ); 4016 } 4017 } 4018}; 4019 4020 4021/*! 4022 * jQuery UI Support for jQuery core 1.7.x 1.12.1 4023 * http://jqueryui.com 4024 * 4025 * Copyright jQuery Foundation and other contributors 4026 * Released under the MIT license. 4027 * http://jquery.org/license 4028 * 4029 */ 4030 4031//>>label: jQuery 1.7 Support 4032//>>group: Core 4033//>>description: Support version 1.7.x of jQuery core 4034 4035 4036 4037// Support: jQuery 1.7 only 4038// Not a great way to check versions, but since we only support 1.7+ and only 4039// need to detect <1.8, this is a simple check that should suffice. Checking 4040// for "1.7." would be a bit safer, but the version string is 1.7, not 1.7.0 4041// and we'll never reach 1.70.0 (if we do, we certainly won't be supporting 4042// 1.7 anymore). See #11197 for why we're not using feature detection. 4043if ( $.fn.jquery.substring( 0, 3 ) === "1.7" ) { 4044 4045 // Setters for .innerWidth(), .innerHeight(), .outerWidth(), .outerHeight() 4046 // Unlike jQuery Core 1.8+, these only support numeric values to set the 4047 // dimensions in pixels 4048 $.each( [ "Width", "Height" ], function( i, name ) { 4049 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], 4050 type = name.toLowerCase(), 4051 orig = { 4052 innerWidth: $.fn.innerWidth, 4053 innerHeight: $.fn.innerHeight, 4054 outerWidth: $.fn.outerWidth, 4055 outerHeight: $.fn.outerHeight 4056 }; 4057 4058 function reduce( elem, size, border, margin ) { 4059 $.each( side, function() { 4060 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; 4061 if ( border ) { 4062 size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; 4063 } 4064 if ( margin ) { 4065 size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; 4066 } 4067 } ); 4068 return size; 4069 } 4070 4071 $.fn[ "inner" + name ] = function( size ) { 4072 if ( size === undefined ) { 4073 return orig[ "inner" + name ].call( this ); 4074 } 4075 4076 return this.each( function() { 4077 $( this ).css( type, reduce( this, size ) + "px" ); 4078 } ); 4079 }; 4080 4081 $.fn[ "outer" + name ] = function( size, margin ) { 4082 if ( typeof size !== "number" ) { 4083 return orig[ "outer" + name ].call( this, size ); 4084 } 4085 4086 return this.each( function() { 4087 $( this ).css( type, reduce( this, size, true, margin ) + "px" ); 4088 } ); 4089 }; 4090 } ); 4091 4092 $.fn.addBack = function( selector ) { 4093 return this.add( selector == null ? 4094 this.prevObject : this.prevObject.filter( selector ) 4095 ); 4096 }; 4097} 4098 4099; 4100/*! 4101 * jQuery UI Keycode 1.12.1 4102 * http://jqueryui.com 4103 * 4104 * Copyright jQuery Foundation and other contributors 4105 * Released under the MIT license. 4106 * http://jquery.org/license 4107 */ 4108 4109//>>label: Keycode 4110//>>group: Core 4111//>>description: Provide keycodes as keynames 4112//>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/ 4113 4114 4115var keycode = $.ui.keyCode = { 4116 BACKSPACE: 8, 4117 COMMA: 188, 4118 DELETE: 46, 4119 DOWN: 40, 4120 END: 35, 4121 ENTER: 13, 4122 ESCAPE: 27, 4123 HOME: 36, 4124 LEFT: 37, 4125 PAGE_DOWN: 34, 4126 PAGE_UP: 33, 4127 PERIOD: 190, 4128 RIGHT: 39, 4129 SPACE: 32, 4130 TAB: 9, 4131 UP: 38 4132}; 4133 4134 4135 4136 4137// Internal use only 4138var escapeSelector = $.ui.escapeSelector = ( function() { 4139 var selectorEscape = /([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g; 4140 return function( selector ) { 4141 return selector.replace( selectorEscape, "\\$1" ); 4142 }; 4143} )(); 4144 4145 4146/*! 4147 * jQuery UI Labels 1.12.1 4148 * http://jqueryui.com 4149 * 4150 * Copyright jQuery Foundation and other contributors 4151 * Released under the MIT license. 4152 * http://jquery.org/license 4153 */ 4154 4155//>>label: labels 4156//>>group: Core 4157//>>description: Find all the labels associated with a given input 4158//>>docs: http://api.jqueryui.com/labels/ 4159 4160 4161 4162var labels = $.fn.labels = function() { 4163 var ancestor, selector, id, labels, ancestors; 4164 4165 // Check control.labels first 4166 if ( this[ 0 ].labels && this[ 0 ].labels.length ) { 4167 return this.pushStack( this[ 0 ].labels ); 4168 } 4169 4170 // Support: IE <= 11, FF <= 37, Android <= 2.3 only 4171 // Above browsers do not support control.labels. Everything below is to support them 4172 // as well as document fragments. control.labels does not work on document fragments 4173 labels = this.eq( 0 ).parents( "label" ); 4174 4175 // Look for the label based on the id 4176 id = this.attr( "id" ); 4177 if ( id ) { 4178 4179 // We don't search against the document in case the element 4180 // is disconnected from the DOM 4181 ancestor = this.eq( 0 ).parents().last(); 4182 4183 // Get a full set of top level ancestors 4184 ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() ); 4185 4186 // Create a selector for the label based on the id 4187 selector = "label[for='" + $.ui.escapeSelector( id ) + "']"; 4188 4189 labels = labels.add( ancestors.find( selector ).addBack( selector ) ); 4190 4191 } 4192 4193 // Return whatever we have found for labels 4194 return this.pushStack( labels ); 4195}; 4196 4197 4198/*! 4199 * jQuery UI Scroll Parent 1.12.1 4200 * http://jqueryui.com 4201 * 4202 * Copyright jQuery Foundation and other contributors 4203 * Released under the MIT license. 4204 * http://jquery.org/license 4205 */ 4206 4207//>>label: scrollParent 4208//>>group: Core 4209//>>description: Get the closest ancestor element that is scrollable. 4210//>>docs: http://api.jqueryui.com/scrollParent/ 4211 4212 4213 4214var scrollParent = $.fn.scrollParent = function( includeHidden ) { 4215 var position = this.css( "position" ), 4216 excludeStaticParent = position === "absolute", 4217 overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/, 4218 scrollParent = this.parents().filter( function() { 4219 var parent = $( this ); 4220 if ( excludeStaticParent && parent.css( "position" ) === "static" ) { 4221 return false; 4222 } 4223 return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + 4224 parent.css( "overflow-x" ) ); 4225 } ).eq( 0 ); 4226 4227 return position === "fixed" || !scrollParent.length ? 4228 $( this[ 0 ].ownerDocument || document ) : 4229 scrollParent; 4230}; 4231 4232 4233/*! 4234 * jQuery UI Tabbable 1.12.1 4235 * http://jqueryui.com 4236 * 4237 * Copyright jQuery Foundation and other contributors 4238 * Released under the MIT license. 4239 * http://jquery.org/license 4240 */ 4241 4242//>>label: :tabbable Selector 4243//>>group: Core 4244//>>description: Selects elements which can be tabbed to. 4245//>>docs: http://api.jqueryui.com/tabbable-selector/ 4246 4247 4248 4249var tabbable = $.extend( $.expr[ ":" ], { 4250 tabbable: function( element ) { 4251 var tabIndex = $.attr( element, "tabindex" ), 4252 hasTabindex = tabIndex != null; 4253 return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex ); 4254 } 4255} ); 4256 4257 4258/*! 4259 * jQuery UI Unique ID 1.12.1 4260 * http://jqueryui.com 4261 * 4262 * Copyright jQuery Foundation and other contributors 4263 * Released under the MIT license. 4264 * http://jquery.org/license 4265 */ 4266 4267//>>label: uniqueId 4268//>>group: Core 4269//>>description: Functions to generate and remove uniqueId's 4270//>>docs: http://api.jqueryui.com/uniqueId/ 4271 4272 4273 4274var uniqueId = $.fn.extend( { 4275 uniqueId: ( function() { 4276 var uuid = 0; 4277 4278 return function() { 4279 return this.each( function() { 4280 if ( !this.id ) { 4281 this.id = "ui-id-" + ( ++uuid ); 4282 } 4283 } ); 4284 }; 4285 } )(), 4286 4287 removeUniqueId: function() { 4288 return this.each( function() { 4289 if ( /^ui-id-\d+$/.test( this.id ) ) { 4290 $( this ).removeAttr( "id" ); 4291 } 4292 } ); 4293 } 4294} ); 4295 4296 4297/*! 4298 * jQuery UI Accordion 1.12.1 4299 * http://jqueryui.com 4300 * 4301 * Copyright jQuery Foundation and other contributors 4302 * Released under the MIT license. 4303 * http://jquery.org/license 4304 */ 4305 4306//>>label: Accordion 4307//>>group: Widgets 4308// jscs:disable maximumLineLength 4309//>>description: Displays collapsible content panels for presenting information in a limited amount of space. 4310// jscs:enable maximumLineLength 4311//>>docs: http://api.jqueryui.com/accordion/ 4312//>>demos: http://jqueryui.com/accordion/ 4313//>>css.structure: ../../themes/base/core.css 4314//>>css.structure: ../../themes/base/accordion.css 4315//>>css.theme: ../../themes/base/theme.css 4316 4317 4318 4319var widgetsAccordion = $.widget( "ui.accordion", { 4320 version: "1.12.1", 4321 options: { 4322 active: 0, 4323 animate: {}, 4324 classes: { 4325 "ui-accordion-header": "ui-corner-top", 4326 "ui-accordion-header-collapsed": "ui-corner-all", 4327 "ui-accordion-content": "ui-corner-bottom" 4328 }, 4329 collapsible: false, 4330 event: "click", 4331 header: "> li > :first-child, > :not(li):even", 4332 heightStyle: "auto", 4333 icons: { 4334 activeHeader: "ui-icon-triangle-1-s", 4335 header: "ui-icon-triangle-1-e" 4336 }, 4337 4338 // Callbacks 4339 activate: null, 4340 beforeActivate: null 4341 }, 4342 4343 hideProps: { 4344 borderTopWidth: "hide", 4345 borderBottomWidth: "hide", 4346 paddingTop: "hide", 4347 paddingBottom: "hide", 4348 height: "hide" 4349 }, 4350 4351 showProps: { 4352 borderTopWidth: "show", 4353 borderBottomWidth: "show", 4354 paddingTop: "show", 4355 paddingBottom: "show", 4356 height: "show" 4357 }, 4358 4359 _create: function() { 4360 var options = this.options; 4361 4362 this.prevShow = this.prevHide = $(); 4363 this._addClass( "ui-accordion", "ui-widget ui-helper-reset" ); 4364 this.element.attr( "role", "tablist" ); 4365 4366 // Don't allow collapsible: false and active: false / null 4367 if ( !options.collapsible && ( options.active === false || options.active == null ) ) { 4368 options.active = 0; 4369 } 4370 4371 this._processPanels(); 4372 4373 // handle negative values 4374 if ( options.active < 0 ) { 4375 options.active += this.headers.length; 4376 } 4377 this._refresh(); 4378 }, 4379 4380 _getCreateEventData: function() { 4381 return { 4382 header: this.active, 4383 panel: !this.active.length ? $() : this.active.next() 4384 }; 4385 }, 4386 4387 _createIcons: function() { 4388 var icon, children, 4389 icons = this.options.icons; 4390 4391 if ( icons ) { 4392 icon = $( "<span>" ); 4393 this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header ); 4394 icon.prependTo( this.headers ); 4395 children = this.active.children( ".ui-accordion-header-icon" ); 4396 this._removeClass( children, icons.header ) 4397 ._addClass( children, null, icons.activeHeader ) 4398 ._addClass( this.headers, "ui-accordion-icons" ); 4399 } 4400 }, 4401 4402 _destroyIcons: function() { 4403 this._removeClass( this.headers, "ui-accordion-icons" ); 4404 this.headers.children( ".ui-accordion-header-icon" ).remove(); 4405 }, 4406 4407 _destroy: function() { 4408 var contents; 4409 4410 // Clean up main element 4411 this.element.removeAttr( "role" ); 4412 4413 // Clean up headers 4414 this.headers 4415 .removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" ) 4416 .removeUniqueId(); 4417 4418 this._destroyIcons(); 4419 4420 // Clean up content panels 4421 contents = this.headers.next() 4422 .css( "display", "" ) 4423 .removeAttr( "role aria-hidden aria-labelledby" ) 4424 .removeUniqueId(); 4425 4426 if ( this.options.heightStyle !== "content" ) { 4427 contents.css( "height", "" ); 4428 } 4429 }, 4430 4431 _setOption: function( key, value ) { 4432 if ( key === "active" ) { 4433 4434 // _activate() will handle invalid values and update this.options 4435 this._activate( value ); 4436 return; 4437 } 4438 4439 if ( key === "event" ) { 4440 if ( this.options.event ) { 4441 this._off( this.headers, this.options.event ); 4442 } 4443 this._setupEvents( value ); 4444 } 4445 4446 this._super( key, value ); 4447 4448 // Setting collapsible: false while collapsed; open first panel 4449 if ( key === "collapsible" && !value && this.options.active === false ) { 4450 this._activate( 0 ); 4451 } 4452 4453 if ( key === "icons" ) { 4454 this._destroyIcons(); 4455 if ( value ) { 4456 this._createIcons(); 4457 } 4458 } 4459 }, 4460 4461 _setOptionDisabled: function( value ) { 4462 this._super( value ); 4463 4464 this.element.attr( "aria-disabled", value ); 4465 4466 // Support: IE8 Only 4467 // #5332 / #6059 - opacity doesn't cascade to positioned elements in IE 4468 // so we need to add the disabled class to the headers and panels 4469 this._toggleClass( null, "ui-state-disabled", !!value ); 4470 this._toggleClass( this.headers.add( this.headers.next() ), null, "ui-state-disabled", 4471 !!value ); 4472 }, 4473 4474 _keydown: function( event ) { 4475 if ( event.altKey || event.ctrlKey ) { 4476 return; 4477 } 4478 4479 var keyCode = $.ui.keyCode, 4480 length = this.headers.length, 4481 currentIndex = this.headers.index( event.target ), 4482 toFocus = false; 4483 4484 switch ( event.keyCode ) { 4485 case keyCode.RIGHT: 4486 case keyCode.DOWN: 4487 toFocus = this.headers[ ( currentIndex + 1 ) % length ]; 4488 break; 4489 case keyCode.LEFT: 4490 case keyCode.UP: 4491 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; 4492 break; 4493 case keyCode.SPACE: 4494 case keyCode.ENTER: 4495 this._eventHandler( event ); 4496 break; 4497 case keyCode.HOME: 4498 toFocus = this.headers[ 0 ]; 4499 break; 4500 case keyCode.END: 4501 toFocus = this.headers[ length - 1 ]; 4502 break; 4503 } 4504 4505 if ( toFocus ) { 4506 $( event.target ).attr( "tabIndex", -1 ); 4507 $( toFocus ).attr( "tabIndex", 0 ); 4508 $( toFocus ).trigger( "focus" ); 4509 event.preventDefault(); 4510 } 4511 }, 4512 4513 _panelKeyDown: function( event ) { 4514 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { 4515 $( event.currentTarget ).prev().trigger( "focus" ); 4516 } 4517 }, 4518 4519 refresh: function() { 4520 var options = this.options; 4521 this._processPanels(); 4522 4523 // Was collapsed or no panel 4524 if ( ( options.active === false && options.collapsible === true ) || 4525 !this.headers.length ) { 4526 options.active = false; 4527 this.active = $(); 4528 4529 // active false only when collapsible is true 4530 } else if ( options.active === false ) { 4531 this._activate( 0 ); 4532 4533 // was active, but active panel is gone 4534 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 4535 4536 // all remaining panel are disabled 4537 if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) { 4538 options.active = false; 4539 this.active = $(); 4540 4541 // activate previous panel 4542 } else { 4543 this._activate( Math.max( 0, options.active - 1 ) ); 4544 } 4545 4546 // was active, active panel still exists 4547 } else { 4548 4549 // make sure active index is correct 4550 options.active = this.headers.index( this.active ); 4551 } 4552 4553 this._destroyIcons(); 4554 4555 this._refresh(); 4556 }, 4557 4558 _processPanels: function() { 4559 var prevHeaders = this.headers, 4560 prevPanels = this.panels; 4561 4562 this.headers = this.element.find( this.options.header ); 4563 this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed", 4564 "ui-state-default" ); 4565 4566 this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide(); 4567 this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" ); 4568 4569 // Avoid memory leaks (#10056) 4570 if ( prevPanels ) { 4571 this._off( prevHeaders.not( this.headers ) ); 4572 this._off( prevPanels.not( this.panels ) ); 4573 } 4574 }, 4575 4576 _refresh: function() { 4577 var maxHeight, 4578 options = this.options, 4579 heightStyle = options.heightStyle, 4580 parent = this.element.parent(); 4581 4582 this.active = this._findActive( options.active ); 4583 this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" ) 4584 ._removeClass( this.active, "ui-accordion-header-collapsed" ); 4585 this._addClass( this.active.next(), "ui-accordion-content-active" ); 4586 this.active.next().show(); 4587 4588 this.headers 4589 .attr( "role", "tab" ) 4590 .each( function() { 4591 var header = $( this ), 4592 headerId = header.uniqueId().attr( "id" ), 4593 panel = header.next(), 4594 panelId = panel.uniqueId().attr( "id" ); 4595 header.attr( "aria-controls", panelId ); 4596 panel.attr( "aria-labelledby", headerId ); 4597 } ) 4598 .next() 4599 .attr( "role", "tabpanel" ); 4600 4601 this.headers 4602 .not( this.active ) 4603 .attr( { 4604 "aria-selected": "false", 4605 "aria-expanded": "false", 4606 tabIndex: -1 4607 } ) 4608 .next() 4609 .attr( { 4610 "aria-hidden": "true" 4611 } ) 4612 .hide(); 4613 4614 // Make sure at least one header is in the tab order 4615 if ( !this.active.length ) { 4616 this.headers.eq( 0 ).attr( "tabIndex", 0 ); 4617 } else { 4618 this.active.attr( { 4619 "aria-selected": "true", 4620 "aria-expanded": "true", 4621 tabIndex: 0 4622 } ) 4623 .next() 4624 .attr( { 4625 "aria-hidden": "false" 4626 } ); 4627 } 4628 4629 this._createIcons(); 4630 4631 this._setupEvents( options.event ); 4632 4633 if ( heightStyle === "fill" ) { 4634 maxHeight = parent.height(); 4635 this.element.siblings( ":visible" ).each( function() { 4636 var elem = $( this ), 4637 position = elem.css( "position" ); 4638 4639 if ( position === "absolute" || position === "fixed" ) { 4640 return; 4641 } 4642 maxHeight -= elem.outerHeight( true ); 4643 } ); 4644 4645 this.headers.each( function() { 4646 maxHeight -= $( this ).outerHeight( true ); 4647 } ); 4648 4649 this.headers.next() 4650 .each( function() { 4651 $( this ).height( Math.max( 0, maxHeight - 4652 $( this ).innerHeight() + $( this ).height() ) ); 4653 } ) 4654 .css( "overflow", "auto" ); 4655 } else if ( heightStyle === "auto" ) { 4656 maxHeight = 0; 4657 this.headers.next() 4658 .each( function() { 4659 var isVisible = $( this ).is( ":visible" ); 4660 if ( !isVisible ) { 4661 $( this ).show(); 4662 } 4663 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); 4664 if ( !isVisible ) { 4665 $( this ).hide(); 4666 } 4667 } ) 4668 .height( maxHeight ); 4669 } 4670 }, 4671 4672 _activate: function( index ) { 4673 var active = this._findActive( index )[ 0 ]; 4674 4675 // Trying to activate the already active panel 4676 if ( active === this.active[ 0 ] ) { 4677 return; 4678 } 4679 4680 // Trying to collapse, simulate a click on the currently active header 4681 active = active || this.active[ 0 ]; 4682 4683 this._eventHandler( { 4684 target: active, 4685 currentTarget: active, 4686 preventDefault: $.noop 4687 } ); 4688 }, 4689 4690 _findActive: function( selector ) { 4691 return typeof selector === "number" ? this.headers.eq( selector ) : $(); 4692 }, 4693 4694 _setupEvents: function( event ) { 4695 var events = { 4696 keydown: "_keydown" 4697 }; 4698 if ( event ) { 4699 $.each( event.split( " " ), function( index, eventName ) { 4700 events[ eventName ] = "_eventHandler"; 4701 } ); 4702 } 4703 4704 this._off( this.headers.add( this.headers.next() ) ); 4705 this._on( this.headers, events ); 4706 this._on( this.headers.next(), { keydown: "_panelKeyDown" } ); 4707 this._hoverable( this.headers ); 4708 this._focusable( this.headers ); 4709 }, 4710 4711 _eventHandler: function( event ) { 4712 var activeChildren, clickedChildren, 4713 options = this.options, 4714 active = this.active, 4715 clicked = $( event.currentTarget ), 4716 clickedIsActive = clicked[ 0 ] === active[ 0 ], 4717 collapsing = clickedIsActive && options.collapsible, 4718 toShow = collapsing ? $() : clicked.next(), 4719 toHide = active.next(), 4720 eventData = { 4721 oldHeader: active, 4722 oldPanel: toHide, 4723 newHeader: collapsing ? $() : clicked, 4724 newPanel: toShow 4725 }; 4726 4727 event.preventDefault(); 4728 4729 if ( 4730 4731 // click on active header, but not collapsible 4732 ( clickedIsActive && !options.collapsible ) || 4733 4734 // allow canceling activation 4735 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 4736 return; 4737 } 4738 4739 options.active = collapsing ? false : this.headers.index( clicked ); 4740 4741 // When the call to ._toggle() comes after the class changes 4742 // it causes a very odd bug in IE 8 (see #6720) 4743 this.active = clickedIsActive ? $() : clicked; 4744 this._toggle( eventData ); 4745 4746 // Switch classes 4747 // corner classes on the previously active header stay after the animation 4748 this._removeClass( active, "ui-accordion-header-active", "ui-state-active" ); 4749 if ( options.icons ) { 4750 activeChildren = active.children( ".ui-accordion-header-icon" ); 4751 this._removeClass( activeChildren, null, options.icons.activeHeader ) 4752 ._addClass( activeChildren, null, options.icons.header ); 4753 } 4754 4755 if ( !clickedIsActive ) { 4756 this._removeClass( clicked, "ui-accordion-header-collapsed" ) 4757 ._addClass( clicked, "ui-accordion-header-active", "ui-state-active" ); 4758 if ( options.icons ) { 4759 clickedChildren = clicked.children( ".ui-accordion-header-icon" ); 4760 this._removeClass( clickedChildren, null, options.icons.header ) 4761 ._addClass( clickedChildren, null, options.icons.activeHeader ); 4762 } 4763 4764 this._addClass( clicked.next(), "ui-accordion-content-active" ); 4765 } 4766 }, 4767 4768 _toggle: function( data ) { 4769 var toShow = data.newPanel, 4770 toHide = this.prevShow.length ? this.prevShow : data.oldPanel; 4771 4772 // Handle activating a panel during the animation for another activation 4773 this.prevShow.add( this.prevHide ).stop( true, true ); 4774 this.prevShow = toShow; 4775 this.prevHide = toHide; 4776 4777 if ( this.options.animate ) { 4778 this._animate( toShow, toHide, data ); 4779 } else { 4780 toHide.hide(); 4781 toShow.show(); 4782 this._toggleComplete( data ); 4783 } 4784 4785 toHide.attr( { 4786 "aria-hidden": "true" 4787 } ); 4788 toHide.prev().attr( { 4789 "aria-selected": "false", 4790 "aria-expanded": "false" 4791 } ); 4792 4793 // if we're switching panels, remove the old header from the tab order 4794 // if we're opening from collapsed state, remove the previous header from the tab order 4795 // if we're collapsing, then keep the collapsing header in the tab order 4796 if ( toShow.length && toHide.length ) { 4797 toHide.prev().attr( { 4798 "tabIndex": -1, 4799 "aria-expanded": "false" 4800 } ); 4801 } else if ( toShow.length ) { 4802 this.headers.filter( function() { 4803 return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0; 4804 } ) 4805 .attr( "tabIndex", -1 ); 4806 } 4807 4808 toShow 4809 .attr( "aria-hidden", "false" ) 4810 .prev() 4811 .attr( { 4812 "aria-selected": "true", 4813 "aria-expanded": "true", 4814 tabIndex: 0 4815 } ); 4816 }, 4817 4818 _animate: function( toShow, toHide, data ) { 4819 var total, easing, duration, 4820 that = this, 4821 adjust = 0, 4822 boxSizing = toShow.css( "box-sizing" ), 4823 down = toShow.length && 4824 ( !toHide.length || ( toShow.index() < toHide.index() ) ), 4825 animate = this.options.animate || {}, 4826 options = down && animate.down || animate, 4827 complete = function() { 4828 that._toggleComplete( data ); 4829 }; 4830 4831 if ( typeof options === "number" ) { 4832 duration = options; 4833 } 4834 if ( typeof options === "string" ) { 4835 easing = options; 4836 } 4837 4838 // fall back from options to animation in case of partial down settings 4839 easing = easing || options.easing || animate.easing; 4840 duration = duration || options.duration || animate.duration; 4841 4842 if ( !toHide.length ) { 4843 return toShow.animate( this.showProps, duration, easing, complete ); 4844 } 4845 if ( !toShow.length ) { 4846 return toHide.animate( this.hideProps, duration, easing, complete ); 4847 } 4848 4849 total = toShow.show().outerHeight(); 4850 toHide.animate( this.hideProps, { 4851 duration: duration, 4852 easing: easing, 4853 step: function( now, fx ) { 4854 fx.now = Math.round( now ); 4855 } 4856 } ); 4857 toShow 4858 .hide() 4859 .animate( this.showProps, { 4860 duration: duration, 4861 easing: easing, 4862 complete: complete, 4863 step: function( now, fx ) { 4864 fx.now = Math.round( now ); 4865 if ( fx.prop !== "height" ) { 4866 if ( boxSizing === "content-box" ) { 4867 adjust += fx.now; 4868 } 4869 } else if ( that.options.heightStyle !== "content" ) { 4870 fx.now = Math.round( total - toHide.outerHeight() - adjust ); 4871 adjust = 0; 4872 } 4873 } 4874 } ); 4875 }, 4876 4877 _toggleComplete: function( data ) { 4878 var toHide = data.oldPanel, 4879 prev = toHide.prev(); 4880 4881 this._removeClass( toHide, "ui-accordion-content-active" ); 4882 this._removeClass( prev, "ui-accordion-header-active" ) 4883 ._addClass( prev, "ui-accordion-header-collapsed" ); 4884 4885 // Work around for rendering bug in IE (#5421) 4886 if ( toHide.length ) { 4887 toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className; 4888 } 4889 this._trigger( "activate", null, data ); 4890 } 4891} ); 4892 4893 4894 4895var safeActiveElement = $.ui.safeActiveElement = function( document ) { 4896 var activeElement; 4897 4898 // Support: IE 9 only 4899 // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe> 4900 try { 4901 activeElement = document.activeElement; 4902 } catch ( error ) { 4903 activeElement = document.body; 4904 } 4905 4906 // Support: IE 9 - 11 only 4907 // IE may return null instead of an element 4908 // Interestingly, this only seems to occur when NOT in an iframe 4909 if ( !activeElement ) { 4910 activeElement = document.body; 4911 } 4912 4913 // Support: IE 11 only 4914 // IE11 returns a seemingly empty object in some cases when accessing 4915 // document.activeElement from an <iframe> 4916 if ( !activeElement.nodeName ) { 4917 activeElement = document.body; 4918 } 4919 4920 return activeElement; 4921}; 4922 4923 4924/*! 4925 * jQuery UI Menu 1.12.1 4926 * http://jqueryui.com 4927 * 4928 * Copyright jQuery Foundation and other contributors 4929 * Released under the MIT license. 4930 * http://jquery.org/license 4931 */ 4932 4933//>>label: Menu 4934//>>group: Widgets 4935//>>description: Creates nestable menus. 4936//>>docs: http://api.jqueryui.com/menu/ 4937//>>demos: http://jqueryui.com/menu/ 4938//>>css.structure: ../../themes/base/core.css 4939//>>css.structure: ../../themes/base/menu.css 4940//>>css.theme: ../../themes/base/theme.css 4941 4942 4943 4944var widgetsMenu = $.widget( "ui.menu", { 4945 version: "1.12.1", 4946 defaultElement: "<ul>", 4947 delay: 300, 4948 options: { 4949 icons: { 4950 submenu: "ui-icon-caret-1-e" 4951 }, 4952 items: "> *", 4953 menus: "ul", 4954 position: { 4955 my: "left top", 4956 at: "right top" 4957 }, 4958 role: "menu", 4959 4960 // Callbacks 4961 blur: null, 4962 focus: null, 4963 select: null 4964 }, 4965 4966 _create: function() { 4967 this.activeMenu = this.element; 4968 4969 // Flag used to prevent firing of the click handler 4970 // as the event bubbles up through nested menus 4971 this.mouseHandled = false; 4972 this.element 4973 .uniqueId() 4974 .attr( { 4975 role: this.options.role, 4976 tabIndex: 0 4977 } ); 4978 4979 this._addClass( "ui-menu", "ui-widget ui-widget-content" ); 4980 this._on( { 4981 4982 // Prevent focus from sticking to links inside menu after clicking 4983 // them (focus should always stay on UL during navigation). 4984 "mousedown .ui-menu-item": function( event ) { 4985 event.preventDefault(); 4986 }, 4987 "click .ui-menu-item": function( event ) { 4988 var target = $( event.target ); 4989 var active = $( $.ui.safeActiveElement( this.document[ 0 ] ) ); 4990 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) { 4991 this.select( event ); 4992 4993 // Only set the mouseHandled flag if the event will bubble, see #9469. 4994 if ( !event.isPropagationStopped() ) { 4995 this.mouseHandled = true; 4996 } 4997 4998 // Open submenu on click 4999 if ( target.has( ".ui-menu" ).length ) { 5000 this.expand( event ); 5001 } else if ( !this.element.is( ":focus" ) && 5002 active.closest( ".ui-menu" ).length ) { 5003 5004 // Redirect focus to the menu 5005 this.element.trigger( "focus", [ true ] ); 5006 5007 // If the active item is on the top level, let it stay active. 5008 // Otherwise, blur the active item since it is no longer visible. 5009 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) { 5010 clearTimeout( this.timer ); 5011 } 5012 } 5013 } 5014 }, 5015 "mouseenter .ui-menu-item": function( event ) { 5016 5017 // Ignore mouse events while typeahead is active, see #10458. 5018 // Prevents focusing the wrong item when typeahead causes a scroll while the mouse 5019 // is over an item in the menu 5020 if ( this.previousFilter ) { 5021 return; 5022 } 5023 5024 var actualTarget = $( event.target ).closest( ".ui-menu-item" ), 5025 target = $( event.currentTarget ); 5026 5027 // Ignore bubbled events on parent items, see #11641 5028 if ( actualTarget[ 0 ] !== target[ 0 ] ) { 5029 return; 5030 } 5031 5032 // Remove ui-state-active class from siblings of the newly focused menu item 5033 // to avoid a jump caused by adjacent elements both having a class with a border 5034 this._removeClass( target.siblings().children( ".ui-state-active" ), 5035 null, "ui-state-active" ); 5036 this.focus( event, target ); 5037 }, 5038 mouseleave: "collapseAll", 5039 "mouseleave .ui-menu": "collapseAll", 5040 focus: function( event, keepActiveItem ) { 5041 5042 // If there's already an active item, keep it active 5043 // If not, activate the first item 5044 var item = this.active || this.element.find( this.options.items ).eq( 0 ); 5045 5046 if ( !keepActiveItem ) { 5047 this.focus( event, item ); 5048 } 5049 }, 5050 blur: function( event ) { 5051 this._delay( function() { 5052 var notContained = !$.contains( 5053 this.element[ 0 ], 5054 $.ui.safeActiveElement( this.document[ 0 ] ) 5055 ); 5056 if ( notContained ) { 5057 this.collapseAll( event ); 5058 } 5059 } ); 5060 }, 5061 keydown: "_keydown" 5062 } ); 5063 5064 this.refresh(); 5065 5066 // Clicks outside of a menu collapse any open menus 5067 this._on( this.document, { 5068 click: function( event ) { 5069 if ( this._closeOnDocumentClick( event ) ) { 5070 this.collapseAll( event ); 5071 } 5072 5073 // Reset the mouseHandled flag 5074 this.mouseHandled = false; 5075 } 5076 } ); 5077 }, 5078 5079 _destroy: function() { 5080 var items = this.element.find( ".ui-menu-item" ) 5081 .removeAttr( "role aria-disabled" ), 5082 submenus = items.children( ".ui-menu-item-wrapper" ) 5083 .removeUniqueId() 5084 .removeAttr( "tabIndex role aria-haspopup" ); 5085 5086 // Destroy (sub)menus 5087 this.element 5088 .removeAttr( "aria-activedescendant" ) 5089 .find( ".ui-menu" ).addBack() 5090 .removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " + 5091 "tabIndex" ) 5092 .removeUniqueId() 5093 .show(); 5094 5095 submenus.children().each( function() { 5096 var elem = $( this ); 5097 if ( elem.data( "ui-menu-submenu-caret" ) ) { 5098 elem.remove(); 5099 } 5100 } ); 5101 }, 5102 5103 _keydown: function( event ) { 5104 var match, prev, character, skip, 5105 preventDefault = true; 5106 5107 switch ( event.keyCode ) { 5108 case $.ui.keyCode.PAGE_UP: 5109 this.previousPage( event ); 5110 break; 5111 case $.ui.keyCode.PAGE_DOWN: 5112 this.nextPage( event ); 5113 break; 5114 case $.ui.keyCode.HOME: 5115 this._move( "first", "first", event ); 5116 break; 5117 case $.ui.keyCode.END: 5118 this._move( "last", "last", event ); 5119 break; 5120 case $.ui.keyCode.UP: 5121 this.previous( event ); 5122 break; 5123 case $.ui.keyCode.DOWN: 5124 this.next( event ); 5125 break; 5126 case $.ui.keyCode.LEFT: 5127 this.collapse( event ); 5128 break; 5129 case $.ui.keyCode.RIGHT: 5130 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { 5131 this.expand( event ); 5132 } 5133 break; 5134 case $.ui.keyCode.ENTER: 5135 case $.ui.keyCode.SPACE: 5136 this._activate( event ); 5137 break; 5138 case $.ui.keyCode.ESCAPE: 5139 this.collapse( event ); 5140 break; 5141 default: 5142 preventDefault = false; 5143 prev = this.previousFilter || ""; 5144 skip = false; 5145 5146 // Support number pad values 5147 character = event.keyCode >= 96 && event.keyCode <= 105 ? 5148 ( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode ); 5149 5150 clearTimeout( this.filterTimer ); 5151 5152 if ( character === prev ) { 5153 skip = true; 5154 } else { 5155 character = prev + character; 5156 } 5157 5158 match = this._filterMenuItems( character ); 5159 match = skip && match.index( this.active.next() ) !== -1 ? 5160 this.active.nextAll( ".ui-menu-item" ) : 5161 match; 5162 5163 // If no matches on the current filter, reset to the last character pressed 5164 // to move down the menu to the first item that starts with that character 5165 if ( !match.length ) { 5166 character = String.fromCharCode( event.keyCode ); 5167 match = this._filterMenuItems( character ); 5168 } 5169 5170 if ( match.length ) { 5171 this.focus( event, match ); 5172 this.previousFilter = character; 5173 this.filterTimer = this._delay( function() { 5174 delete this.previousFilter; 5175 }, 1000 ); 5176 } else { 5177 delete this.previousFilter; 5178 } 5179 } 5180 5181 if ( preventDefault ) { 5182 event.preventDefault(); 5183 } 5184 }, 5185 5186 _activate: function( event ) { 5187 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { 5188 if ( this.active.children( "[aria-haspopup='true']" ).length ) { 5189 this.expand( event ); 5190 } else { 5191 this.select( event ); 5192 } 5193 } 5194 }, 5195 5196 refresh: function() { 5197 var menus, items, newSubmenus, newItems, newWrappers, 5198 that = this, 5199 icon = this.options.icons.submenu, 5200 submenus = this.element.find( this.options.menus ); 5201 5202 this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length ); 5203 5204 // Initialize nested menus 5205 newSubmenus = submenus.filter( ":not(.ui-menu)" ) 5206 .hide() 5207 .attr( { 5208 role: this.options.role, 5209 "aria-hidden": "true", 5210 "aria-expanded": "false" 5211 } ) 5212 .each( function() { 5213 var menu = $( this ), 5214 item = menu.prev(), 5215 submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true ); 5216 5217 that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon ); 5218 item 5219 .attr( "aria-haspopup", "true" ) 5220 .prepend( submenuCaret ); 5221 menu.attr( "aria-labelledby", item.attr( "id" ) ); 5222 } ); 5223 5224 this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" ); 5225 5226 menus = submenus.add( this.element ); 5227 items = menus.find( this.options.items ); 5228 5229 // Initialize menu-items containing spaces and/or dashes only as dividers 5230 items.not( ".ui-menu-item" ).each( function() { 5231 var item = $( this ); 5232 if ( that._isDivider( item ) ) { 5233 that._addClass( item, "ui-menu-divider", "ui-widget-content" ); 5234 } 5235 } ); 5236 5237 // Don't refresh list items that are already adapted 5238 newItems = items.not( ".ui-menu-item, .ui-menu-divider" ); 5239 newWrappers = newItems.children() 5240 .not( ".ui-menu" ) 5241 .uniqueId() 5242 .attr( { 5243 tabIndex: -1, 5244 role: this._itemRole() 5245 } ); 5246 this._addClass( newItems, "ui-menu-item" ) 5247 ._addClass( newWrappers, "ui-menu-item-wrapper" ); 5248 5249 // Add aria-disabled attribute to any disabled menu item 5250 items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); 5251 5252 // If the active item has been removed, blur the menu 5253 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 5254 this.blur(); 5255 } 5256 }, 5257 5258 _itemRole: function() { 5259 return { 5260 menu: "menuitem", 5261 listbox: "option" 5262 }[ this.options.role ]; 5263 }, 5264 5265 _setOption: function( key, value ) { 5266 if ( key === "icons" ) { 5267 var icons = this.element.find( ".ui-menu-icon" ); 5268 this._removeClass( icons, null, this.options.icons.submenu ) 5269 ._addClass( icons, null, value.submenu ); 5270 } 5271 this._super( key, value ); 5272 }, 5273 5274 _setOptionDisabled: function( value ) { 5275 this._super( value ); 5276 5277 this.element.attr( "aria-disabled", String( value ) ); 5278 this._toggleClass( null, "ui-state-disabled", !!value ); 5279 }, 5280 5281 focus: function( event, item ) { 5282 var nested, focused, activeParent; 5283 this.blur( event, event && event.type === "focus" ); 5284 5285 this._scrollIntoView( item ); 5286 5287 this.active = item.first(); 5288 5289 focused = this.active.children( ".ui-menu-item-wrapper" ); 5290 this._addClass( focused, null, "ui-state-active" ); 5291 5292 // Only update aria-activedescendant if there's a role 5293 // otherwise we assume focus is managed elsewhere 5294 if ( this.options.role ) { 5295 this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); 5296 } 5297 5298 // Highlight active parent menu item, if any 5299 activeParent = this.active 5300 .parent() 5301 .closest( ".ui-menu-item" ) 5302 .children( ".ui-menu-item-wrapper" ); 5303 this._addClass( activeParent, null, "ui-state-active" ); 5304 5305 if ( event && event.type === "keydown" ) { 5306 this._close(); 5307 } else { 5308 this.timer = this._delay( function() { 5309 this._close(); 5310 }, this.delay ); 5311 } 5312 5313 nested = item.children( ".ui-menu" ); 5314 if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) { 5315 this._startOpening( nested ); 5316 } 5317 this.activeMenu = item.parent(); 5318 5319 this._trigger( "focus", event, { item: item } ); 5320 }, 5321 5322 _scrollIntoView: function( item ) { 5323 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; 5324 if ( this._hasScroll() ) { 5325 borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0; 5326 paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0; 5327 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; 5328 scroll = this.activeMenu.scrollTop(); 5329 elementHeight = this.activeMenu.height(); 5330 itemHeight = item.outerHeight(); 5331 5332 if ( offset < 0 ) { 5333 this.activeMenu.scrollTop( scroll + offset ); 5334 } else if ( offset + itemHeight > elementHeight ) { 5335 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); 5336 } 5337 } 5338 }, 5339 5340 blur: function( event, fromFocus ) { 5341 if ( !fromFocus ) { 5342 clearTimeout( this.timer ); 5343 } 5344 5345 if ( !this.active ) { 5346 return; 5347 } 5348 5349 this._removeClass( this.active.children( ".ui-menu-item-wrapper" ), 5350 null, "ui-state-active" ); 5351 5352 this._trigger( "blur", event, { item: this.active } ); 5353 this.active = null; 5354 }, 5355 5356 _startOpening: function( submenu ) { 5357 clearTimeout( this.timer ); 5358 5359 // Don't open if already open fixes a Firefox bug that caused a .5 pixel 5360 // shift in the submenu position when mousing over the caret icon 5361 if ( submenu.attr( "aria-hidden" ) !== "true" ) { 5362 return; 5363 } 5364 5365 this.timer = this._delay( function() { 5366 this._close(); 5367 this._open( submenu ); 5368 }, this.delay ); 5369 }, 5370 5371 _open: function( submenu ) { 5372 var position = $.extend( { 5373 of: this.active 5374 }, this.options.position ); 5375 5376 clearTimeout( this.timer ); 5377 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) ) 5378 .hide() 5379 .attr( "aria-hidden", "true" ); 5380 5381 submenu 5382 .show() 5383 .removeAttr( "aria-hidden" ) 5384 .attr( "aria-expanded", "true" ) 5385 .position( position ); 5386 }, 5387 5388 collapseAll: function( event, all ) { 5389 clearTimeout( this.timer ); 5390 this.timer = this._delay( function() { 5391 5392 // If we were passed an event, look for the submenu that contains the event 5393 var currentMenu = all ? this.element : 5394 $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); 5395 5396 // If we found no valid submenu ancestor, use the main menu to close all 5397 // sub menus anyway 5398 if ( !currentMenu.length ) { 5399 currentMenu = this.element; 5400 } 5401 5402 this._close( currentMenu ); 5403 5404 this.blur( event ); 5405 5406 // Work around active item staying active after menu is blurred 5407 this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" ); 5408 5409 this.activeMenu = currentMenu; 5410 }, this.delay ); 5411 }, 5412 5413 // With no arguments, closes the currently active menu - if nothing is active 5414 // it closes all menus. If passed an argument, it will search for menus BELOW 5415 _close: function( startMenu ) { 5416 if ( !startMenu ) { 5417 startMenu = this.active ? this.active.parent() : this.element; 5418 } 5419 5420 startMenu.find( ".ui-menu" ) 5421 .hide() 5422 .attr( "aria-hidden", "true" ) 5423 .attr( "aria-expanded", "false" ); 5424 }, 5425 5426 _closeOnDocumentClick: function( event ) { 5427 return !$( event.target ).closest( ".ui-menu" ).length; 5428 }, 5429 5430 _isDivider: function( item ) { 5431 5432 // Match hyphen, em dash, en dash 5433 return !/[^\-\u2014\u2013\s]/.test( item.text() ); 5434 }, 5435 5436 collapse: function( event ) { 5437 var newItem = this.active && 5438 this.active.parent().closest( ".ui-menu-item", this.element ); 5439 if ( newItem && newItem.length ) { 5440 this._close(); 5441 this.focus( event, newItem ); 5442 } 5443 }, 5444 5445 expand: function( event ) { 5446 var newItem = this.active && 5447 this.active 5448 .children( ".ui-menu " ) 5449 .find( this.options.items ) 5450 .first(); 5451 5452 if ( newItem && newItem.length ) { 5453 this._open( newItem.parent() ); 5454 5455 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT 5456 this._delay( function() { 5457 this.focus( event, newItem ); 5458 } ); 5459 } 5460 }, 5461 5462 next: function( event ) { 5463 this._move( "next", "first", event ); 5464 }, 5465 5466 previous: function( event ) { 5467 this._move( "prev", "last", event ); 5468 }, 5469 5470 isFirstItem: function() { 5471 return this.active && !this.active.prevAll( ".ui-menu-item" ).length; 5472 }, 5473 5474 isLastItem: function() { 5475 return this.active && !this.active.nextAll( ".ui-menu-item" ).length; 5476 }, 5477 5478 _move: function( direction, filter, event ) { 5479 var next; 5480 if ( this.active ) { 5481 if ( direction === "first" || direction === "last" ) { 5482 next = this.active 5483 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) 5484 .eq( -1 ); 5485 } else { 5486 next = this.active 5487 [ direction + "All" ]( ".ui-menu-item" ) 5488 .eq( 0 ); 5489 } 5490 } 5491 if ( !next || !next.length || !this.active ) { 5492 next = this.activeMenu.find( this.options.items )[ filter ](); 5493 } 5494 5495 this.focus( event, next ); 5496 }, 5497 5498 nextPage: function( event ) { 5499 var item, base, height; 5500 5501 if ( !this.active ) { 5502 this.next( event ); 5503 return; 5504 } 5505 if ( this.isLastItem() ) { 5506 return; 5507 } 5508 if ( this._hasScroll() ) { 5509 base = this.active.offset().top; 5510 height = this.element.height(); 5511 this.active.nextAll( ".ui-menu-item" ).each( function() { 5512 item = $( this ); 5513 return item.offset().top - base - height < 0; 5514 } ); 5515 5516 this.focus( event, item ); 5517 } else { 5518 this.focus( event, this.activeMenu.find( this.options.items ) 5519 [ !this.active ? "first" : "last" ]() ); 5520 } 5521 }, 5522 5523 previousPage: function( event ) { 5524 var item, base, height; 5525 if ( !this.active ) { 5526 this.next( event ); 5527 return; 5528 } 5529 if ( this.isFirstItem() ) { 5530 return; 5531 } 5532 if ( this._hasScroll() ) { 5533 base = this.active.offset().top; 5534 height = this.element.height(); 5535 this.active.prevAll( ".ui-menu-item" ).each( function() { 5536 item = $( this ); 5537 return item.offset().top - base + height > 0; 5538 } ); 5539 5540 this.focus( event, item ); 5541 } else { 5542 this.focus( event, this.activeMenu.find( this.options.items ).first() ); 5543 } 5544 }, 5545 5546 _hasScroll: function() { 5547 return this.element.outerHeight() < this.element.prop( "scrollHeight" ); 5548 }, 5549 5550 select: function( event ) { 5551 5552 // TODO: It should never be possible to not have an active item at this 5553 // point, but the tests don't trigger mouseenter before click. 5554 this.active = this.active || $( event.target ).closest( ".ui-menu-item" ); 5555 var ui = { item: this.active }; 5556 if ( !this.active.has( ".ui-menu" ).length ) { 5557 this.collapseAll( event, true ); 5558 } 5559 this._trigger( "select", event, ui ); 5560 }, 5561 5562 _filterMenuItems: function( character ) { 5563 var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ), 5564 regex = new RegExp( "^" + escapedCharacter, "i" ); 5565 5566 return this.activeMenu 5567 .find( this.options.items ) 5568 5569 // Only match on items, not dividers or other content (#10571) 5570 .filter( ".ui-menu-item" ) 5571 .filter( function() { 5572 return regex.test( 5573 $.trim( $( this ).children( ".ui-menu-item-wrapper" ).text() ) ); 5574 } ); 5575 } 5576} ); 5577 5578 5579/*! 5580 * jQuery UI Autocomplete 1.12.1 5581 * http://jqueryui.com 5582 * 5583 * Copyright jQuery Foundation and other contributors 5584 * Released under the MIT license. 5585 * http://jquery.org/license 5586 */ 5587 5588//>>label: Autocomplete 5589//>>group: Widgets 5590//>>description: Lists suggested words as the user is typing. 5591//>>docs: http://api.jqueryui.com/autocomplete/ 5592//>>demos: http://jqueryui.com/autocomplete/ 5593//>>css.structure: ../../themes/base/core.css 5594//>>css.structure: ../../themes/base/autocomplete.css 5595//>>css.theme: ../../themes/base/theme.css 5596 5597 5598 5599$.widget( "ui.autocomplete", { 5600 version: "1.12.1", 5601 defaultElement: "<input>", 5602 options: { 5603 appendTo: null, 5604 autoFocus: false, 5605 delay: 300, 5606 minLength: 1, 5607 position: { 5608 my: "left top", 5609 at: "left bottom", 5610 collision: "none" 5611 }, 5612 source: null, 5613 5614 // Callbacks 5615 change: null, 5616 close: null, 5617 focus: null, 5618 open: null, 5619 response: null, 5620 search: null, 5621 select: null 5622 }, 5623 5624 requestIndex: 0, 5625 pending: 0, 5626 5627 _create: function() { 5628 5629 // Some browsers only repeat keydown events, not keypress events, 5630 // so we use the suppressKeyPress flag to determine if we've already 5631 // handled the keydown event. #7269 5632 // Unfortunately the code for & in keypress is the same as the up arrow, 5633 // so we use the suppressKeyPressRepeat flag to avoid handling keypress 5634 // events when we know the keydown event was used to modify the 5635 // search term. #7799 5636 var suppressKeyPress, suppressKeyPressRepeat, suppressInput, 5637 nodeName = this.element[ 0 ].nodeName.toLowerCase(), 5638 isTextarea = nodeName === "textarea", 5639 isInput = nodeName === "input"; 5640 5641 // Textareas are always multi-line 5642 // Inputs are always single-line, even if inside a contentEditable element 5643 // IE also treats inputs as contentEditable 5644 // All other element types are determined by whether or not they're contentEditable 5645 this.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element ); 5646 5647 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ]; 5648 this.isNewMenu = true; 5649 5650 this._addClass( "ui-autocomplete-input" ); 5651 this.element.attr( "autocomplete", "off" ); 5652 5653 this._on( this.element, { 5654 keydown: function( event ) { 5655 if ( this.element.prop( "readOnly" ) ) { 5656 suppressKeyPress = true; 5657 suppressInput = true; 5658 suppressKeyPressRepeat = true; 5659 return; 5660 } 5661 5662 suppressKeyPress = false; 5663 suppressInput = false; 5664 suppressKeyPressRepeat = false; 5665 var keyCode = $.ui.keyCode; 5666 switch ( event.keyCode ) { 5667 case keyCode.PAGE_UP: 5668 suppressKeyPress = true; 5669 this._move( "previousPage", event ); 5670 break; 5671 case keyCode.PAGE_DOWN: 5672 suppressKeyPress = true; 5673 this._move( "nextPage", event ); 5674 break; 5675 case keyCode.UP: 5676 suppressKeyPress = true; 5677 this._keyEvent( "previous", event ); 5678 break; 5679 case keyCode.DOWN: 5680 suppressKeyPress = true; 5681 this._keyEvent( "next", event ); 5682 break; 5683 case keyCode.ENTER: 5684 5685 // when menu is open and has focus 5686 if ( this.menu.active ) { 5687 5688 // #6055 - Opera still allows the keypress to occur 5689 // which causes forms to submit 5690 suppressKeyPress = true; 5691 event.preventDefault(); 5692 this.menu.select( event ); 5693 } 5694 break; 5695 case keyCode.TAB: 5696 if ( this.menu.active ) { 5697 this.menu.select( event ); 5698 } 5699 break; 5700 case keyCode.ESCAPE: 5701 if ( this.menu.element.is( ":visible" ) ) { 5702 if ( !this.isMultiLine ) { 5703 this._value( this.term ); 5704 } 5705 this.close( event ); 5706 5707 // Different browsers have different default behavior for escape 5708 // Single press can mean undo or clear 5709 // Double press in IE means clear the whole form 5710 event.preventDefault(); 5711 } 5712 break; 5713 default: 5714 suppressKeyPressRepeat = true; 5715 5716 // search timeout should be triggered before the input value is changed 5717 this._searchTimeout( event ); 5718 break; 5719 } 5720 }, 5721 keypress: function( event ) { 5722 if ( suppressKeyPress ) { 5723 suppressKeyPress = false; 5724 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 5725 event.preventDefault(); 5726 } 5727 return; 5728 } 5729 if ( suppressKeyPressRepeat ) { 5730 return; 5731 } 5732 5733 // Replicate some key handlers to allow them to repeat in Firefox and Opera 5734 var keyCode = $.ui.keyCode; 5735 switch ( event.keyCode ) { 5736 case keyCode.PAGE_UP: 5737 this._move( "previousPage", event ); 5738 break; 5739 case keyCode.PAGE_DOWN: 5740 this._move( "nextPage", event ); 5741 break; 5742 case keyCode.UP: 5743 this._keyEvent( "previous", event ); 5744 break; 5745 case keyCode.DOWN: 5746 this._keyEvent( "next", event ); 5747 break; 5748 } 5749 }, 5750 input: function( event ) { 5751 if ( suppressInput ) { 5752 suppressInput = false; 5753 event.preventDefault(); 5754 return; 5755 } 5756 this._searchTimeout( event ); 5757 }, 5758 focus: function() { 5759 this.selectedItem = null; 5760 this.previous = this._value(); 5761 }, 5762 blur: function( event ) { 5763 if ( this.cancelBlur ) { 5764 delete this.cancelBlur; 5765 return; 5766 } 5767 5768 clearTimeout( this.searching ); 5769 this.close( event ); 5770 this._change( event ); 5771 } 5772 } ); 5773 5774 this._initSource(); 5775 this.menu = $( "<ul>" ) 5776 .appendTo( this._appendTo() ) 5777 .menu( { 5778 5779 // disable ARIA support, the live region takes care of that 5780 role: null 5781 } ) 5782 .hide() 5783 .menu( "instance" ); 5784 5785 this._addClass( this.menu.element, "ui-autocomplete", "ui-front" ); 5786 this._on( this.menu.element, { 5787 mousedown: function( event ) { 5788 5789 // prevent moving focus out of the text field 5790 event.preventDefault(); 5791 5792 // IE doesn't prevent moving focus even with event.preventDefault() 5793 // so we set a flag to know when we should ignore the blur event 5794 this.cancelBlur = true; 5795 this._delay( function() { 5796 delete this.cancelBlur; 5797 5798 // Support: IE 8 only 5799 // Right clicking a menu item or selecting text from the menu items will 5800 // result in focus moving out of the input. However, we've already received 5801 // and ignored the blur event because of the cancelBlur flag set above. So 5802 // we restore focus to ensure that the menu closes properly based on the user's 5803 // next actions. 5804 if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) { 5805 this.element.trigger( "focus" ); 5806 } 5807 } ); 5808 }, 5809 menufocus: function( event, ui ) { 5810 var label, item; 5811 5812 // support: Firefox 5813 // Prevent accidental activation of menu items in Firefox (#7024 #9118) 5814 if ( this.isNewMenu ) { 5815 this.isNewMenu = false; 5816 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) { 5817 this.menu.blur(); 5818 5819 this.document.one( "mousemove", function() { 5820 $( event.target ).trigger( event.originalEvent ); 5821 } ); 5822 5823 return; 5824 } 5825 } 5826 5827 item = ui.item.data( "ui-autocomplete-item" ); 5828 if ( false !== this._trigger( "focus", event, { item: item } ) ) { 5829 5830 // use value to match what will end up in the input, if it was a key event 5831 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) { 5832 this._value( item.value ); 5833 } 5834 } 5835 5836 // Announce the value in the liveRegion 5837 label = ui.item.attr( "aria-label" ) || item.value; 5838 if ( label && $.trim( label ).length ) { 5839 this.liveRegion.children().hide(); 5840 $( "<div>" ).text( label ).appendTo( this.liveRegion ); 5841 } 5842 }, 5843 menuselect: function( event, ui ) { 5844 var item = ui.item.data( "ui-autocomplete-item" ), 5845 previous = this.previous; 5846 5847 // Only trigger when focus was lost (click on menu) 5848 if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) { 5849 this.element.trigger( "focus" ); 5850 this.previous = previous; 5851 5852 // #6109 - IE triggers two focus events and the second 5853 // is asynchronous, so we need to reset the previous 5854 // term synchronously and asynchronously :-( 5855 this._delay( function() { 5856 this.previous = previous; 5857 this.selectedItem = item; 5858 } ); 5859 } 5860 5861 if ( false !== this._trigger( "select", event, { item: item } ) ) { 5862 this._value( item.value ); 5863 } 5864 5865 // reset the term after the select event 5866 // this allows custom select handling to work properly 5867 this.term = this._value(); 5868 5869 this.close( event ); 5870 this.selectedItem = item; 5871 } 5872 } ); 5873 5874 this.liveRegion = $( "<div>", { 5875 role: "status", 5876 "aria-live": "assertive", 5877 "aria-relevant": "additions" 5878 } ) 5879 .appendTo( this.document[ 0 ].body ); 5880 5881 this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" ); 5882 5883 // Turning off autocomplete prevents the browser from remembering the 5884 // value when navigating through history, so we re-enable autocomplete 5885 // if the page is unloaded before the widget is destroyed. #7790 5886 this._on( this.window, { 5887 beforeunload: function() { 5888 this.element.removeAttr( "autocomplete" ); 5889 } 5890 } ); 5891 }, 5892 5893 _destroy: function() { 5894 clearTimeout( this.searching ); 5895 this.element.removeAttr( "autocomplete" ); 5896 this.menu.element.remove(); 5897 this.liveRegion.remove(); 5898 }, 5899 5900 _setOption: function( key, value ) { 5901 this._super( key, value ); 5902 if ( key === "source" ) { 5903 this._initSource(); 5904 } 5905 if ( key === "appendTo" ) { 5906 this.menu.element.appendTo( this._appendTo() ); 5907 } 5908 if ( key === "disabled" && value && this.xhr ) { 5909 this.xhr.abort(); 5910 } 5911 }, 5912 5913 _isEventTargetInWidget: function( event ) { 5914 var menuElement = this.menu.element[ 0 ]; 5915 5916 return event.target === this.element[ 0 ] || 5917 event.target === menuElement || 5918 $.contains( menuElement, event.target ); 5919 }, 5920 5921 _closeOnClickOutside: function( event ) { 5922 if ( !this._isEventTargetInWidget( event ) ) { 5923 this.close(); 5924 } 5925 }, 5926 5927 _appendTo: function() { 5928 var element = this.options.appendTo; 5929 5930 if ( element ) { 5931 element = element.jquery || element.nodeType ? 5932 $( element ) : 5933 this.document.find( element ).eq( 0 ); 5934 } 5935 5936 if ( !element || !element[ 0 ] ) { 5937 element = this.element.closest( ".ui-front, dialog" ); 5938 } 5939 5940 if ( !element.length ) { 5941 element = this.document[ 0 ].body; 5942 } 5943 5944 return element; 5945 }, 5946 5947 _initSource: function() { 5948 var array, url, 5949 that = this; 5950 if ( $.isArray( this.options.source ) ) { 5951 array = this.options.source; 5952 this.source = function( request, response ) { 5953 response( $.ui.autocomplete.filter( array, request.term ) ); 5954 }; 5955 } else if ( typeof this.options.source === "string" ) { 5956 url = this.options.source; 5957 this.source = function( request, response ) { 5958 if ( that.xhr ) { 5959 that.xhr.abort(); 5960 } 5961 that.xhr = $.ajax( { 5962 url: url, 5963 data: request, 5964 dataType: "json", 5965 success: function( data ) { 5966 response( data ); 5967 }, 5968 error: function() { 5969 response( [] ); 5970 } 5971 } ); 5972 }; 5973 } else { 5974 this.source = this.options.source; 5975 } 5976 }, 5977 5978 _searchTimeout: function( event ) { 5979 clearTimeout( this.searching ); 5980 this.searching = this._delay( function() { 5981 5982 // Search if the value has changed, or if the user retypes the same value (see #7434) 5983 var equalValues = this.term === this._value(), 5984 menuVisible = this.menu.element.is( ":visible" ), 5985 modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey; 5986 5987 if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) { 5988 this.selectedItem = null; 5989 this.search( null, event ); 5990 } 5991 }, this.options.delay ); 5992 }, 5993 5994 search: function( value, event ) { 5995 value = value != null ? value : this._value(); 5996 5997 // Always save the actual value, not the one passed as an argument 5998 this.term = this._value(); 5999 6000 if ( value.length < this.options.minLength ) { 6001 return this.close( event ); 6002 } 6003 6004 if ( this._trigger( "search", event ) === false ) { 6005 return; 6006 } 6007 6008 return this._search( value ); 6009 }, 6010 6011 _search: function( value ) { 6012 this.pending++; 6013 this._addClass( "ui-autocomplete-loading" ); 6014 this.cancelSearch = false; 6015 6016 this.source( { term: value }, this._response() ); 6017 }, 6018 6019 _response: function() { 6020 var index = ++this.requestIndex; 6021 6022 return $.proxy( function( content ) { 6023 if ( index === this.requestIndex ) { 6024 this.__response( content ); 6025 } 6026 6027 this.pending--; 6028 if ( !this.pending ) { 6029 this._removeClass( "ui-autocomplete-loading" ); 6030 } 6031 }, this ); 6032 }, 6033 6034 __response: function( content ) { 6035 if ( content ) { 6036 content = this._normalize( content ); 6037 } 6038 this._trigger( "response", null, { content: content } ); 6039 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) { 6040 this._suggest( content ); 6041 this._trigger( "open" ); 6042 } else { 6043 6044 // use ._close() instead of .close() so we don't cancel future searches 6045 this._close(); 6046 } 6047 }, 6048 6049 close: function( event ) { 6050 this.cancelSearch = true; 6051 this._close( event ); 6052 }, 6053 6054 _close: function( event ) { 6055 6056 // Remove the handler that closes the menu on outside clicks 6057 this._off( this.document, "mousedown" ); 6058 6059 if ( this.menu.element.is( ":visible" ) ) { 6060 this.menu.element.hide(); 6061 this.menu.blur(); 6062 this.isNewMenu = true; 6063 this._trigger( "close", event ); 6064 } 6065 }, 6066 6067 _change: function( event ) { 6068 if ( this.previous !== this._value() ) { 6069 this._trigger( "change", event, { item: this.selectedItem } ); 6070 } 6071 }, 6072 6073 _normalize: function( items ) { 6074 6075 // assume all items have the right format when the first item is complete 6076 if ( items.length && items[ 0 ].label && items[ 0 ].value ) { 6077 return items; 6078 } 6079 return $.map( items, function( item ) { 6080 if ( typeof item === "string" ) { 6081 return { 6082 label: item, 6083 value: item 6084 }; 6085 } 6086 return $.extend( {}, item, { 6087 label: item.label || item.value, 6088 value: item.value || item.label 6089 } ); 6090 } ); 6091 }, 6092 6093 _suggest: function( items ) { 6094 var ul = this.menu.element.empty(); 6095 this._renderMenu( ul, items ); 6096 this.isNewMenu = true; 6097 this.menu.refresh(); 6098 6099 // Size and position menu 6100 ul.show(); 6101 this._resizeMenu(); 6102 ul.position( $.extend( { 6103 of: this.element 6104 }, this.options.position ) ); 6105 6106 if ( this.options.autoFocus ) { 6107 this.menu.next(); 6108 } 6109 6110 // Listen for interactions outside of the widget (#6642) 6111 this._on( this.document, { 6112 mousedown: "_closeOnClickOutside" 6113 } ); 6114 }, 6115 6116 _resizeMenu: function() { 6117 var ul = this.menu.element; 6118 ul.outerWidth( Math.max( 6119 6120 // Firefox wraps long text (possibly a rounding bug) 6121 // so we add 1px to avoid the wrapping (#7513) 6122 ul.width( "" ).outerWidth() + 1, 6123 this.element.outerWidth() 6124 ) ); 6125 }, 6126 6127 _renderMenu: function( ul, items ) { 6128 var that = this; 6129 $.each( items, function( index, item ) { 6130 that._renderItemData( ul, item ); 6131 } ); 6132 }, 6133 6134 _renderItemData: function( ul, item ) { 6135 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item ); 6136 }, 6137 6138 _renderItem: function( ul, item ) { 6139 return $( "<li>" ) 6140 .append( $( "<div>" ).text( item.label ) ) 6141 .appendTo( ul ); 6142 }, 6143 6144 _move: function( direction, event ) { 6145 if ( !this.menu.element.is( ":visible" ) ) { 6146 this.search( null, event ); 6147 return; 6148 } 6149 if ( this.menu.isFirstItem() && /^previous/.test( direction ) || 6150 this.menu.isLastItem() && /^next/.test( direction ) ) { 6151 6152 if ( !this.isMultiLine ) { 6153 this._value( this.term ); 6154 } 6155 6156 this.menu.blur(); 6157 return; 6158 } 6159 this.menu[ direction ]( event ); 6160 }, 6161 6162 widget: function() { 6163 return this.menu.element; 6164 }, 6165 6166 _value: function() { 6167 return this.valueMethod.apply( this.element, arguments ); 6168 }, 6169 6170 _keyEvent: function( keyEvent, event ) { 6171 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 6172 this._move( keyEvent, event ); 6173 6174 // Prevents moving cursor to beginning/end of the text field in some browsers 6175 event.preventDefault(); 6176 } 6177 }, 6178 6179 // Support: Chrome <=50 6180 // We should be able to just use this.element.prop( "isContentEditable" ) 6181 // but hidden elements always report false in Chrome. 6182 // https://code.google.com/p/chromium/issues/detail?id=313082 6183 _isContentEditable: function( element ) { 6184 if ( !element.length ) { 6185 return false; 6186 } 6187 6188 var editable = element.prop( "contentEditable" ); 6189 6190 if ( editable === "inherit" ) { 6191 return this._isContentEditable( element.parent() ); 6192 } 6193 6194 return editable === "true"; 6195 } 6196} ); 6197 6198$.extend( $.ui.autocomplete, { 6199 escapeRegex: function( value ) { 6200 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ); 6201 }, 6202 filter: function( array, term ) { 6203 var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" ); 6204 return $.grep( array, function( value ) { 6205 return matcher.test( value.label || value.value || value ); 6206 } ); 6207 } 6208} ); 6209 6210// Live region extension, adding a `messages` option 6211// NOTE: This is an experimental API. We are still investigating 6212// a full solution for string manipulation and internationalization. 6213$.widget( "ui.autocomplete", $.ui.autocomplete, { 6214 options: { 6215 messages: { 6216 noResults: "No search results.", 6217 results: function( amount ) { 6218 return amount + ( amount > 1 ? " results are" : " result is" ) + 6219 " available, use up and down arrow keys to navigate."; 6220 } 6221 } 6222 }, 6223 6224 __response: function( content ) { 6225 var message; 6226 this._superApply( arguments ); 6227 if ( this.options.disabled || this.cancelSearch ) { 6228 return; 6229 } 6230 if ( content && content.length ) { 6231 message = this.options.messages.results( content.length ); 6232 } else { 6233 message = this.options.messages.noResults; 6234 } 6235 this.liveRegion.children().hide(); 6236 $( "<div>" ).text( message ).appendTo( this.liveRegion ); 6237 } 6238} ); 6239 6240var widgetsAutocomplete = $.ui.autocomplete; 6241 6242 6243/*! 6244 * jQuery UI Controlgroup 1.12.1 6245 * http://jqueryui.com 6246 * 6247 * Copyright jQuery Foundation and other contributors 6248 * Released under the MIT license. 6249 * http://jquery.org/license 6250 */ 6251 6252//>>label: Controlgroup 6253//>>group: Widgets 6254//>>description: Visually groups form control widgets 6255//>>docs: http://api.jqueryui.com/controlgroup/ 6256//>>demos: http://jqueryui.com/controlgroup/ 6257//>>css.structure: ../../themes/base/core.css 6258//>>css.structure: ../../themes/base/controlgroup.css 6259//>>css.theme: ../../themes/base/theme.css 6260 6261 6262var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g; 6263 6264var widgetsControlgroup = $.widget( "ui.controlgroup", { 6265 version: "1.12.1", 6266 defaultElement: "<div>", 6267 options: { 6268 direction: "horizontal", 6269 disabled: null, 6270 onlyVisible: true, 6271 items: { 6272 "button": "input[type=button], input[type=submit], input[type=reset], button, a", 6273 "controlgroupLabel": ".ui-controlgroup-label", 6274 "checkboxradio": "input[type='checkbox'], input[type='radio']", 6275 "selectmenu": "select", 6276 "spinner": ".ui-spinner-input" 6277 } 6278 }, 6279 6280 _create: function() { 6281 this._enhance(); 6282 }, 6283 6284 // To support the enhanced option in jQuery Mobile, we isolate DOM manipulation 6285 _enhance: function() { 6286 this.element.attr( "role", "toolbar" ); 6287 this.refresh(); 6288 }, 6289 6290 _destroy: function() { 6291 this._callChildMethod( "destroy" ); 6292 this.childWidgets.removeData( "ui-controlgroup-data" ); 6293 this.element.removeAttr( "role" ); 6294 if ( this.options.items.controlgroupLabel ) { 6295 this.element 6296 .find( this.options.items.controlgroupLabel ) 6297 .find( ".ui-controlgroup-label-contents" ) 6298 .contents().unwrap(); 6299 } 6300 }, 6301 6302 _initWidgets: function() { 6303 var that = this, 6304 childWidgets = []; 6305 6306 // First we iterate over each of the items options 6307 $.each( this.options.items, function( widget, selector ) { 6308 var labels; 6309 var options = {}; 6310 6311 // Make sure the widget has a selector set 6312 if ( !selector ) { 6313 return; 6314 } 6315 6316 if ( widget === "controlgroupLabel" ) { 6317 labels = that.element.find( selector ); 6318 labels.each( function() { 6319 var element = $( this ); 6320 6321 if ( element.children( ".ui-controlgroup-label-contents" ).length ) { 6322 return; 6323 } 6324 element.contents() 6325 .wrapAll( "<span class='ui-controlgroup-label-contents'></span>" ); 6326 } ); 6327 that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" ); 6328 childWidgets = childWidgets.concat( labels.get() ); 6329 return; 6330 } 6331 6332 // Make sure the widget actually exists 6333 if ( !$.fn[ widget ] ) { 6334 return; 6335 } 6336 6337 // We assume everything is in the middle to start because we can't determine 6338 // first / last elements until all enhancments are done. 6339 if ( that[ "_" + widget + "Options" ] ) { 6340 options = that[ "_" + widget + "Options" ]( "middle" ); 6341 } else { 6342 options = { classes: {} }; 6343 } 6344 6345 // Find instances of this widget inside controlgroup and init them 6346 that.element 6347 .find( selector ) 6348 .each( function() { 6349 var element = $( this ); 6350 var instance = element[ widget ]( "instance" ); 6351 6352 // We need to clone the default options for this type of widget to avoid 6353 // polluting the variable options which has a wider scope than a single widget. 6354 var instanceOptions = $.widget.extend( {}, options ); 6355 6356 // If the button is the child of a spinner ignore it 6357 // TODO: Find a more generic solution 6358 if ( widget === "button" && element.parent( ".ui-spinner" ).length ) { 6359 return; 6360 } 6361 6362 // Create the widget if it doesn't exist 6363 if ( !instance ) { 6364 instance = element[ widget ]()[ widget ]( "instance" ); 6365 } 6366 if ( instance ) { 6367 instanceOptions.classes = 6368 that._resolveClassesValues( instanceOptions.classes, instance ); 6369 } 6370 element[ widget ]( instanceOptions ); 6371 6372 // Store an instance of the controlgroup to be able to reference 6373 // from the outermost element for changing options and refresh 6374 var widgetElement = element[ widget ]( "widget" ); 6375 $.data( widgetElement[ 0 ], "ui-controlgroup-data", 6376 instance ? instance : element[ widget ]( "instance" ) ); 6377 6378 childWidgets.push( widgetElement[ 0 ] ); 6379 } ); 6380 } ); 6381 6382 this.childWidgets = $( $.unique( childWidgets ) ); 6383 this._addClass( this.childWidgets, "ui-controlgroup-item" ); 6384 }, 6385 6386 _callChildMethod: function( method ) { 6387 this.childWidgets.each( function() { 6388 var element = $( this ), 6389 data = element.data( "ui-controlgroup-data" ); 6390 if ( data && data[ method ] ) { 6391 data[ method ](); 6392 } 6393 } ); 6394 }, 6395 6396 _updateCornerClass: function( element, position ) { 6397 var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all"; 6398 var add = this._buildSimpleOptions( position, "label" ).classes.label; 6399 6400 this._removeClass( element, null, remove ); 6401 this._addClass( element, null, add ); 6402 }, 6403 6404 _buildSimpleOptions: function( position, key ) { 6405 var direction = this.options.direction === "vertical"; 6406 var result = { 6407 classes: {} 6408 }; 6409 result.classes[ key ] = { 6410 "middle": "", 6411 "first": "ui-corner-" + ( direction ? "top" : "left" ), 6412 "last": "ui-corner-" + ( direction ? "bottom" : "right" ), 6413 "only": "ui-corner-all" 6414 }[ position ]; 6415 6416 return result; 6417 }, 6418 6419 _spinnerOptions: function( position ) { 6420 var options = this._buildSimpleOptions( position, "ui-spinner" ); 6421 6422 options.classes[ "ui-spinner-up" ] = ""; 6423 options.classes[ "ui-spinner-down" ] = ""; 6424 6425 return options; 6426 }, 6427 6428 _buttonOptions: function( position ) { 6429 return this._buildSimpleOptions( position, "ui-button" ); 6430 }, 6431 6432 _checkboxradioOptions: function( position ) { 6433 return this._buildSimpleOptions( position, "ui-checkboxradio-label" ); 6434 }, 6435 6436 _selectmenuOptions: function( position ) { 6437 var direction = this.options.direction === "vertical"; 6438 return { 6439 width: direction ? "auto" : false, 6440 classes: { 6441 middle: { 6442 "ui-selectmenu-button-open": "", 6443 "ui-selectmenu-button-closed": "" 6444 }, 6445 first: { 6446 "ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ), 6447 "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" ) 6448 }, 6449 last: { 6450 "ui-selectmenu-button-open": direction ? "" : "ui-corner-tr", 6451 "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" ) 6452 }, 6453 only: { 6454 "ui-selectmenu-button-open": "ui-corner-top", 6455 "ui-selectmenu-button-closed": "ui-corner-all" 6456 } 6457 6458 }[ position ] 6459 }; 6460 }, 6461 6462 _resolveClassesValues: function( classes, instance ) { 6463 var result = {}; 6464 $.each( classes, function( key ) { 6465 var current = instance.options.classes[ key ] || ""; 6466 current = $.trim( current.replace( controlgroupCornerRegex, "" ) ); 6467 result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " ); 6468 } ); 6469 return result; 6470 }, 6471 6472 _setOption: function( key, value ) { 6473 if ( key === "direction" ) { 6474 this._removeClass( "ui-controlgroup-" + this.options.direction ); 6475 } 6476 6477 this._super( key, value ); 6478 if ( key === "disabled" ) { 6479 this._callChildMethod( value ? "disable" : "enable" ); 6480 return; 6481 } 6482 6483 this.refresh(); 6484 }, 6485 6486 refresh: function() { 6487 var children, 6488 that = this; 6489 6490 this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction ); 6491 6492 if ( this.options.direction === "horizontal" ) { 6493 this._addClass( null, "ui-helper-clearfix" ); 6494 } 6495 this._initWidgets(); 6496 6497 children = this.childWidgets; 6498 6499 // We filter here because we need to track all childWidgets not just the visible ones 6500 if ( this.options.onlyVisible ) { 6501 children = children.filter( ":visible" ); 6502 } 6503 6504 if ( children.length ) { 6505 6506 // We do this last because we need to make sure all enhancment is done 6507 // before determining first and last 6508 $.each( [ "first", "last" ], function( index, value ) { 6509 var instance = children[ value ]().data( "ui-controlgroup-data" ); 6510 6511 if ( instance && that[ "_" + instance.widgetName + "Options" ] ) { 6512 var options = that[ "_" + instance.widgetName + "Options" ]( 6513 children.length === 1 ? "only" : value 6514 ); 6515 options.classes = that._resolveClassesValues( options.classes, instance ); 6516 instance.element[ instance.widgetName ]( options ); 6517 } else { 6518 that._updateCornerClass( children[ value ](), value ); 6519 } 6520 } ); 6521 6522 // Finally call the refresh method on each of the child widgets. 6523 this._callChildMethod( "refresh" ); 6524 } 6525 } 6526} ); 6527 6528/*! 6529 * jQuery UI Checkboxradio 1.12.1 6530 * http://jqueryui.com 6531 * 6532 * Copyright jQuery Foundation and other contributors 6533 * Released under the MIT license. 6534 * http://jquery.org/license 6535 */ 6536 6537//>>label: Checkboxradio 6538//>>group: Widgets 6539//>>description: Enhances a form with multiple themeable checkboxes or radio buttons. 6540//>>docs: http://api.jqueryui.com/checkboxradio/ 6541//>>demos: http://jqueryui.com/checkboxradio/ 6542//>>css.structure: ../../themes/base/core.css 6543//>>css.structure: ../../themes/base/button.css 6544//>>css.structure: ../../themes/base/checkboxradio.css 6545//>>css.theme: ../../themes/base/theme.css 6546 6547 6548 6549$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, { 6550 version: "1.12.1", 6551 options: { 6552 disabled: null, 6553 label: null, 6554 icon: true, 6555 classes: { 6556 "ui-checkboxradio-label": "ui-corner-all", 6557 "ui-checkboxradio-icon": "ui-corner-all" 6558 } 6559 }, 6560 6561 _getCreateOptions: function() { 6562 var disabled, labels; 6563 var that = this; 6564 var options = this._super() || {}; 6565 6566 // We read the type here, because it makes more sense to throw a element type error first, 6567 // rather then the error for lack of a label. Often if its the wrong type, it 6568 // won't have a label (e.g. calling on a div, btn, etc) 6569 this._readType(); 6570 6571 labels = this.element.labels(); 6572 6573 // If there are multiple labels, use the last one 6574 this.label = $( labels[ labels.length - 1 ] ); 6575 if ( !this.label.length ) { 6576 $.error( "No label found for checkboxradio widget" ); 6577 } 6578 6579 this.originalLabel = ""; 6580 6581 // We need to get the label text but this may also need to make sure it does not contain the 6582 // input itself. 6583 this.label.contents().not( this.element[ 0 ] ).each( function() { 6584 6585 // The label contents could be text, html, or a mix. We concat each element to get a 6586 // string representation of the label, without the input as part of it. 6587 that.originalLabel += this.nodeType === 3 ? $( this ).text() : this.outerHTML; 6588 } ); 6589 6590 // Set the label option if we found label text 6591 if ( this.originalLabel ) { 6592 options.label = this.originalLabel; 6593 } 6594 6595 disabled = this.element[ 0 ].disabled; 6596 if ( disabled != null ) { 6597 options.disabled = disabled; 6598 } 6599 return options; 6600 }, 6601 6602 _create: function() { 6603 var checked = this.element[ 0 ].checked; 6604 6605 this._bindFormResetHandler(); 6606 6607 if ( this.options.disabled == null ) { 6608 this.options.disabled = this.element[ 0 ].disabled; 6609 } 6610 6611 this._setOption( "disabled", this.options.disabled ); 6612 this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" ); 6613 this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" ); 6614 6615 if ( this.type === "radio" ) { 6616 this._addClass( this.label, "ui-checkboxradio-radio-label" ); 6617 } 6618 6619 if ( this.options.label && this.options.label !== this.originalLabel ) { 6620 this._updateLabel(); 6621 } else if ( this.originalLabel ) { 6622 this.options.label = this.originalLabel; 6623 } 6624 6625 this._enhance(); 6626 6627 if ( checked ) { 6628 this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" ); 6629 if ( this.icon ) { 6630 this._addClass( this.icon, null, "ui-state-hover" ); 6631 } 6632 } 6633 6634 this._on( { 6635 change: "_toggleClasses", 6636 focus: function() { 6637 this._addClass( this.label, null, "ui-state-focus ui-visual-focus" ); 6638 }, 6639 blur: function() { 6640 this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" ); 6641 } 6642 } ); 6643 }, 6644 6645 _readType: function() { 6646 var nodeName = this.element[ 0 ].nodeName.toLowerCase(); 6647 this.type = this.element[ 0 ].type; 6648 if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) { 6649 $.error( "Can't create checkboxradio on element.nodeName=" + nodeName + 6650 " and element.type=" + this.type ); 6651 } 6652 }, 6653 6654 // Support jQuery Mobile enhanced option 6655 _enhance: function() { 6656 this._updateIcon( this.element[ 0 ].checked ); 6657 }, 6658 6659 widget: function() { 6660 return this.label; 6661 }, 6662 6663 _getRadioGroup: function() { 6664 var group; 6665 var name = this.element[ 0 ].name; 6666 var nameSelector = "input[name='" + $.ui.escapeSelector( name ) + "']"; 6667 6668 if ( !name ) { 6669 return $( [] ); 6670 } 6671 6672 if ( this.form.length ) { 6673 group = $( this.form[ 0 ].elements ).filter( nameSelector ); 6674 } else { 6675 6676 // Not inside a form, check all inputs that also are not inside a form 6677 group = $( nameSelector ).filter( function() { 6678 return $( this ).form().length === 0; 6679 } ); 6680 } 6681 6682 return group.not( this.element ); 6683 }, 6684 6685 _toggleClasses: function() { 6686 var checked = this.element[ 0 ].checked; 6687 this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked ); 6688 6689 if ( this.options.icon && this.type === "checkbox" ) { 6690 this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked ) 6691 ._toggleClass( this.icon, null, "ui-icon-blank", !checked ); 6692 } 6693 6694 if ( this.type === "radio" ) { 6695 this._getRadioGroup() 6696 .each( function() { 6697 var instance = $( this ).checkboxradio( "instance" ); 6698 6699 if ( instance ) { 6700 instance._removeClass( instance.label, 6701 "ui-checkboxradio-checked", "ui-state-active" ); 6702 } 6703 } ); 6704 } 6705 }, 6706 6707 _destroy: function() { 6708 this._unbindFormResetHandler(); 6709 6710 if ( this.icon ) { 6711 this.icon.remove(); 6712 this.iconSpace.remove(); 6713 } 6714 }, 6715 6716 _setOption: function( key, value ) { 6717 6718 // We don't allow the value to be set to nothing 6719 if ( key === "label" && !value ) { 6720 return; 6721 } 6722 6723 this._super( key, value ); 6724 6725 if ( key === "disabled" ) { 6726 this._toggleClass( this.label, null, "ui-state-disabled", value ); 6727 this.element[ 0 ].disabled = value; 6728 6729 // Don't refresh when setting disabled 6730 return; 6731 } 6732 this.refresh(); 6733 }, 6734 6735 _updateIcon: function( checked ) { 6736 var toAdd = "ui-icon ui-icon-background "; 6737 6738 if ( this.options.icon ) { 6739 if ( !this.icon ) { 6740 this.icon = $( "<span>" ); 6741 this.iconSpace = $( "<span> </span>" ); 6742 this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" ); 6743 } 6744 6745 if ( this.type === "checkbox" ) { 6746 toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank"; 6747 this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" ); 6748 } else { 6749 toAdd += "ui-icon-blank"; 6750 } 6751 this._addClass( this.icon, "ui-checkboxradio-icon", toAdd ); 6752 if ( !checked ) { 6753 this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" ); 6754 } 6755 this.icon.prependTo( this.label ).after( this.iconSpace ); 6756 } else if ( this.icon !== undefined ) { 6757 this.icon.remove(); 6758 this.iconSpace.remove(); 6759 delete this.icon; 6760 } 6761 }, 6762 6763 _updateLabel: function() { 6764 6765 // Remove the contents of the label ( minus the icon, icon space, and input ) 6766 var contents = this.label.contents().not( this.element[ 0 ] ); 6767 if ( this.icon ) { 6768 contents = contents.not( this.icon[ 0 ] ); 6769 } 6770 if ( this.iconSpace ) { 6771 contents = contents.not( this.iconSpace[ 0 ] ); 6772 } 6773 contents.remove(); 6774 6775 this.label.append( this.options.label ); 6776 }, 6777 6778 refresh: function() { 6779 var checked = this.element[ 0 ].checked, 6780 isDisabled = this.element[ 0 ].disabled; 6781 6782 this._updateIcon( checked ); 6783 this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked ); 6784 if ( this.options.label !== null ) { 6785 this._updateLabel(); 6786 } 6787 6788 if ( isDisabled !== this.options.disabled ) { 6789 this._setOptions( { "disabled": isDisabled } ); 6790 } 6791 } 6792 6793} ] ); 6794 6795var widgetsCheckboxradio = $.ui.checkboxradio; 6796 6797 6798/*! 6799 * jQuery UI Button 1.12.1 6800 * http://jqueryui.com 6801 * 6802 * Copyright jQuery Foundation and other contributors 6803 * Released under the MIT license. 6804 * http://jquery.org/license 6805 */ 6806 6807//>>label: Button 6808//>>group: Widgets 6809//>>description: Enhances a form with themeable buttons. 6810//>>docs: http://api.jqueryui.com/button/ 6811//>>demos: http://jqueryui.com/button/ 6812//>>css.structure: ../../themes/base/core.css 6813//>>css.structure: ../../themes/base/button.css 6814//>>css.theme: ../../themes/base/theme.css 6815 6816 6817 6818$.widget( "ui.button", { 6819 version: "1.12.1", 6820 defaultElement: "<button>", 6821 options: { 6822 classes: { 6823 "ui-button": "ui-corner-all" 6824 }, 6825 disabled: null, 6826 icon: null, 6827 iconPosition: "beginning", 6828 label: null, 6829 showLabel: true 6830 }, 6831 6832 _getCreateOptions: function() { 6833 var disabled, 6834 6835 // This is to support cases like in jQuery Mobile where the base widget does have 6836 // an implementation of _getCreateOptions 6837 options = this._super() || {}; 6838 6839 this.isInput = this.element.is( "input" ); 6840 6841 disabled = this.element[ 0 ].disabled; 6842 if ( disabled != null ) { 6843 options.disabled = disabled; 6844 } 6845 6846 this.originalLabel = this.isInput ? this.element.val() : this.element.html(); 6847 if ( this.originalLabel ) { 6848 options.label = this.originalLabel; 6849 } 6850 6851 return options; 6852 }, 6853 6854 _create: function() { 6855 if ( !this.option.showLabel & !this.options.icon ) { 6856 this.options.showLabel = true; 6857 } 6858 6859 // We have to check the option again here even though we did in _getCreateOptions, 6860 // because null may have been passed on init which would override what was set in 6861 // _getCreateOptions 6862 if ( this.options.disabled == null ) { 6863 this.options.disabled = this.element[ 0 ].disabled || false; 6864 } 6865 6866 this.hasTitle = !!this.element.attr( "title" ); 6867 6868 // Check to see if the label needs to be set or if its already correct 6869 if ( this.options.label && this.options.label !== this.originalLabel ) { 6870 if ( this.isInput ) { 6871 this.element.val( this.options.label ); 6872 } else { 6873 this.element.html( this.options.label ); 6874 } 6875 } 6876 this._addClass( "ui-button", "ui-widget" ); 6877 this._setOption( "disabled", this.options.disabled ); 6878 this._enhance(); 6879 6880 if ( this.element.is( "a" ) ) { 6881 this._on( { 6882 "keyup": function( event ) { 6883 if ( event.keyCode === $.ui.keyCode.SPACE ) { 6884 event.preventDefault(); 6885 6886 // Support: PhantomJS <= 1.9, IE 8 Only 6887 // If a native click is available use it so we actually cause navigation 6888 // otherwise just trigger a click event 6889 if ( this.element[ 0 ].click ) { 6890 this.element[ 0 ].click(); 6891 } else { 6892 this.element.trigger( "click" ); 6893 } 6894 } 6895 } 6896 } ); 6897 } 6898 }, 6899 6900 _enhance: function() { 6901 if ( !this.element.is( "button" ) ) { 6902 this.element.attr( "role", "button" ); 6903 } 6904 6905 if ( this.options.icon ) { 6906 this._updateIcon( "icon", this.options.icon ); 6907 this._updateTooltip(); 6908 } 6909 }, 6910 6911 _updateTooltip: function() { 6912 this.title = this.element.attr( "title" ); 6913 6914 if ( !this.options.showLabel && !this.title ) { 6915 this.element.attr( "title", this.options.label ); 6916 } 6917 }, 6918 6919 _updateIcon: function( option, value ) { 6920 var icon = option !== "iconPosition", 6921 position = icon ? this.options.iconPosition : value, 6922 displayBlock = position === "top" || position === "bottom"; 6923 6924 // Create icon 6925 if ( !this.icon ) { 6926 this.icon = $( "<span>" ); 6927 6928 this._addClass( this.icon, "ui-button-icon", "ui-icon" ); 6929 6930 if ( !this.options.showLabel ) { 6931 this._addClass( "ui-button-icon-only" ); 6932 } 6933 } else if ( icon ) { 6934 6935 // If we are updating the icon remove the old icon class 6936 this._removeClass( this.icon, null, this.options.icon ); 6937 } 6938 6939 // If we are updating the icon add the new icon class 6940 if ( icon ) { 6941 this._addClass( this.icon, null, value ); 6942 } 6943 6944 this._attachIcon( position ); 6945 6946 // If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove 6947 // the iconSpace if there is one. 6948 if ( displayBlock ) { 6949 this._addClass( this.icon, null, "ui-widget-icon-block" ); 6950 if ( this.iconSpace ) { 6951 this.iconSpace.remove(); 6952 } 6953 } else { 6954 6955 // Position is beginning or end so remove the ui-widget-icon-block class and add the 6956 // space if it does not exist 6957 if ( !this.iconSpace ) { 6958 this.iconSpace = $( "<span> </span>" ); 6959 this._addClass( this.iconSpace, "ui-button-icon-space" ); 6960 } 6961 this._removeClass( this.icon, null, "ui-wiget-icon-block" ); 6962 this._attachIconSpace( position ); 6963 } 6964 }, 6965 6966 _destroy: function() { 6967 this.element.removeAttr( "role" ); 6968 6969 if ( this.icon ) { 6970 this.icon.remove(); 6971 } 6972 if ( this.iconSpace ) { 6973 this.iconSpace.remove(); 6974 } 6975 if ( !this.hasTitle ) { 6976 this.element.removeAttr( "title" ); 6977 } 6978 }, 6979 6980 _attachIconSpace: function( iconPosition ) { 6981 this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace ); 6982 }, 6983 6984 _attachIcon: function( iconPosition ) { 6985 this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon ); 6986 }, 6987 6988 _setOptions: function( options ) { 6989 var newShowLabel = options.showLabel === undefined ? 6990 this.options.showLabel : 6991 options.showLabel, 6992 newIcon = options.icon === undefined ? this.options.icon : options.icon; 6993 6994 if ( !newShowLabel && !newIcon ) { 6995 options.showLabel = true; 6996 } 6997 this._super( options ); 6998 }, 6999 7000 _setOption: function( key, value ) { 7001 if ( key === "icon" ) { 7002 if ( value ) { 7003 this._updateIcon( key, value ); 7004 } else if ( this.icon ) { 7005 this.icon.remove(); 7006 if ( this.iconSpace ) { 7007 this.iconSpace.remove(); 7008 } 7009 } 7010 } 7011 7012 if ( key === "iconPosition" ) { 7013 this._updateIcon( key, value ); 7014 } 7015 7016 // Make sure we can't end up with a button that has neither text nor icon 7017 if ( key === "showLabel" ) { 7018 this._toggleClass( "ui-button-icon-only", null, !value ); 7019 this._updateTooltip(); 7020 } 7021 7022 if ( key === "label" ) { 7023 if ( this.isInput ) { 7024 this.element.val( value ); 7025 } else { 7026 7027 // If there is an icon, append it, else nothing then append the value 7028 // this avoids removal of the icon when setting label text 7029 this.element.html( value ); 7030 if ( this.icon ) { 7031 this._attachIcon( this.options.iconPosition ); 7032 this._attachIconSpace( this.options.iconPosition ); 7033 } 7034 } 7035 } 7036 7037 this._super( key, value ); 7038 7039 if ( key === "disabled" ) { 7040 this._toggleClass( null, "ui-state-disabled", value ); 7041 this.element[ 0 ].disabled = value; 7042 if ( value ) { 7043 this.element.blur(); 7044 } 7045 } 7046 }, 7047 7048 refresh: function() { 7049 7050 // Make sure to only check disabled if its an element that supports this otherwise 7051 // check for the disabled class to determine state 7052 var isDisabled = this.element.is( "input, button" ) ? 7053 this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" ); 7054 7055 if ( isDisabled !== this.options.disabled ) { 7056 this._setOptions( { disabled: isDisabled } ); 7057 } 7058 7059 this._updateTooltip(); 7060 } 7061} ); 7062 7063// DEPRECATED 7064if ( $.uiBackCompat !== false ) { 7065 7066 // Text and Icons options 7067 $.widget( "ui.button", $.ui.button, { 7068 options: { 7069 text: true, 7070 icons: { 7071 primary: null, 7072 secondary: null 7073 } 7074 }, 7075 7076 _create: function() { 7077 if ( this.options.showLabel && !this.options.text ) { 7078 this.options.showLabel = this.options.text; 7079 } 7080 if ( !this.options.showLabel && this.options.text ) { 7081 this.options.text = this.options.showLabel; 7082 } 7083 if ( !this.options.icon && ( this.options.icons.primary || 7084 this.options.icons.secondary ) ) { 7085 if ( this.options.icons.primary ) { 7086 this.options.icon = this.options.icons.primary; 7087 } else { 7088 this.options.icon = this.options.icons.secondary; 7089 this.options.iconPosition = "end"; 7090 } 7091 } else if ( this.options.icon ) { 7092 this.options.icons.primary = this.options.icon; 7093 } 7094 this._super(); 7095 }, 7096 7097 _setOption: function( key, value ) { 7098 if ( key === "text" ) { 7099 this._super( "showLabel", value ); 7100 return; 7101 } 7102 if ( key === "showLabel" ) { 7103 this.options.text = value; 7104 } 7105 if ( key === "icon" ) { 7106 this.options.icons.primary = value; 7107 } 7108 if ( key === "icons" ) { 7109 if ( value.primary ) { 7110 this._super( "icon", value.primary ); 7111 this._super( "iconPosition", "beginning" ); 7112 } else if ( value.secondary ) { 7113 this._super( "icon", value.secondary ); 7114 this._super( "iconPosition", "end" ); 7115 } 7116 } 7117 this._superApply( arguments ); 7118 } 7119 } ); 7120 7121 $.fn.button = ( function( orig ) { 7122 return function() { 7123 if ( !this.length || ( this.length && this[ 0 ].tagName !== "INPUT" ) || 7124 ( this.length && this[ 0 ].tagName === "INPUT" && ( 7125 this.attr( "type" ) !== "checkbox" && this.attr( "type" ) !== "radio" 7126 ) ) ) { 7127 return orig.apply( this, arguments ); 7128 } 7129 if ( !$.ui.checkboxradio ) { 7130 $.error( "Checkboxradio widget missing" ); 7131 } 7132 if ( arguments.length === 0 ) { 7133 return this.checkboxradio( { 7134 "icon": false 7135 } ); 7136 } 7137 return this.checkboxradio.apply( this, arguments ); 7138 }; 7139 } )( $.fn.button ); 7140 7141 $.fn.buttonset = function() { 7142 if ( !$.ui.controlgroup ) { 7143 $.error( "Controlgroup widget missing" ); 7144 } 7145 if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) { 7146 return this.controlgroup.apply( this, 7147 [ arguments[ 0 ], "items.button", arguments[ 2 ] ] ); 7148 } 7149 if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) { 7150 return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] ); 7151 } 7152 if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) { 7153 arguments[ 0 ].items = { 7154 button: arguments[ 0 ].items 7155 }; 7156 } 7157 return this.controlgroup.apply( this, arguments ); 7158 }; 7159} 7160 7161var widgetsButton = $.ui.button; 7162 7163 7164// jscs:disable maximumLineLength 7165/* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */ 7166/*! 7167 * jQuery UI Datepicker 1.12.1 7168 * http://jqueryui.com 7169 * 7170 * Copyright jQuery Foundation and other contributors 7171 7172 * Released under the MIT license. 7173 * http://jquery.org/license 7174 */ 7175 7176//>>label: Datepicker 7177//>>group: Widgets 7178//>>description: Displays a calendar from an input or inline for selecting dates. 7179//>>docs: http://api.jqueryui.com/datepicker/ 7180//>>demos: http://jqueryui.com/datepicker/ 7181//>>css.structure: ../../themes/base/core.css 7182//>>css.structure: ../../themes/base/datepicker.css 7183//>>css.theme: ../../themes/base/theme.css 7184 7185 7186 7187$.extend( $.ui, { datepicker: { version: "1.12.1" } } ); 7188 7189var datepicker_instActive; 7190 7191function datepicker_getZindex( elem ) { 7192 var position, value; 7193 while ( elem.length && elem[ 0 ] !== document ) { 7194 7195 // Ignore z-index if position is set to a value where z-index is ignored by the browser 7196 // This makes behavior of this function consistent across browsers 7197 // WebKit always returns auto if the element is positioned 7198 position = elem.css( "position" ); 7199 if ( position === "absolute" || position === "relative" || position === "fixed" ) { 7200 7201 // IE returns 0 when zIndex is not specified 7202 // other browsers return a string 7203 // we ignore the case of nested elements with an explicit value of 0 7204 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 7205 value = parseInt( elem.css( "zIndex" ), 10 ); 7206 if ( !isNaN( value ) && value !== 0 ) { 7207 return value; 7208 } 7209 } 7210 elem = elem.parent(); 7211 } 7212 7213 return 0; 7214} 7215/* Date picker manager. 7216 Use the singleton instance of this class, $.datepicker, to interact with the date picker. 7217 Settings for (groups of) date pickers are maintained in an instance object, 7218 allowing multiple different settings on the same page. */ 7219 7220function Datepicker() { 7221 this._curInst = null; // The current instance in use 7222 this._keyEvent = false; // If the last event was a key event 7223 this._disabledInputs = []; // List of date picker inputs that have been disabled 7224 this._datepickerShowing = false; // True if the popup picker is showing , false if not 7225 this._inDialog = false; // True if showing within a "dialog", false if not 7226 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division 7227 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class 7228 this._appendClass = "ui-datepicker-append"; // The name of the append marker class 7229 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class 7230 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class 7231 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class 7232 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class 7233 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class 7234 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class 7235 this.regional = []; // Available regional settings, indexed by language code 7236 this.regional[ "" ] = { // Default regional settings 7237 closeText: "Done", // Display text for close link 7238 prevText: "Prev", // Display text for previous month link 7239 nextText: "Next", // Display text for next month link 7240 currentText: "Today", // Display text for current month link 7241 monthNames: [ "January","February","March","April","May","June", 7242 "July","August","September","October","November","December" ], // Names of months for drop-down and formatting 7243 monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting 7244 dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting 7245 dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting 7246 dayNamesMin: [ "Su","Mo","Tu","We","Th","Fr","Sa" ], // Column headings for days starting at Sunday 7247 weekHeader: "Wk", // Column header for week of the year 7248 dateFormat: "mm/dd/yy", // See format options on parseDate 7249 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... 7250 isRTL: false, // True if right-to-left language, false if left-to-right 7251 showMonthAfterYear: false, // True if the year select precedes month, false for month then year 7252 yearSuffix: "" // Additional text to append to the year in the month headers 7253 }; 7254 this._defaults = { // Global defaults for all the date picker instances 7255 showOn: "focus", // "focus" for popup on focus, 7256 // "button" for trigger button, or "both" for either 7257 showAnim: "fadeIn", // Name of jQuery animation for popup 7258 showOptions: {}, // Options for enhanced animations 7259 defaultDate: null, // Used when field is blank: actual date, 7260 // +/-number for offset from today, null for today 7261 appendText: "", // Display text following the input box, e.g. showing the format 7262 buttonText: "...", // Text for trigger button 7263 buttonImage: "", // URL for trigger button image 7264 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button 7265 hideIfNoPrevNext: false, // True to hide next/previous month links 7266 // if not applicable, false to just disable them 7267 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links 7268 gotoCurrent: false, // True if today link goes back to current selection instead 7269 changeMonth: false, // True if month can be selected directly, false if only prev/next 7270 changeYear: false, // True if year can be selected directly, false if only prev/next 7271 yearRange: "c-10:c+10", // Range of years to display in drop-down, 7272 // either relative to today's year (-nn:+nn), relative to currently displayed year 7273 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) 7274 showOtherMonths: false, // True to show dates in other months, false to leave blank 7275 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable 7276 showWeek: false, // True to show week of the year, false to not show it 7277 calculateWeek: this.iso8601Week, // How to calculate the week of the year, 7278 // takes a Date and returns the number of the week for it 7279 shortYearCutoff: "+10", // Short year values < this are in the current century, 7280 // > this are in the previous century, 7281 // string value starting with "+" for current year + value 7282 minDate: null, // The earliest selectable date, or null for no limit 7283 maxDate: null, // The latest selectable date, or null for no limit 7284 duration: "fast", // Duration of display/closure 7285 beforeShowDay: null, // Function that takes a date and returns an array with 7286 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "", 7287 // [2] = cell title (optional), e.g. $.datepicker.noWeekends 7288 beforeShow: null, // Function that takes an input field and 7289 // returns a set of custom settings for the date picker 7290 onSelect: null, // Define a callback function when a date is selected 7291 onChangeMonthYear: null, // Define a callback function when the month or year is changed 7292 onClose: null, // Define a callback function when the datepicker is closed 7293 numberOfMonths: 1, // Number of months to show at a time 7294 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) 7295 stepMonths: 1, // Number of months to step back/forward 7296 stepBigMonths: 12, // Number of months to step back/forward for the big links 7297 altField: "", // Selector for an alternate field to store selected dates into 7298 altFormat: "", // The date format to use for the alternate field 7299 constrainInput: true, // The input is constrained by the current date format 7300 showButtonPanel: false, // True to show button panel, false to not show it 7301 autoSize: false, // True to size the input for the date format, false to leave as is 7302 disabled: false // The initial disabled state 7303 }; 7304 $.extend( this._defaults, this.regional[ "" ] ); 7305 this.regional.en = $.extend( true, {}, this.regional[ "" ] ); 7306 this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en ); 7307 this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ); 7308} 7309 7310$.extend( Datepicker.prototype, { 7311 /* Class name added to elements to indicate already configured with a date picker. */ 7312 markerClassName: "hasDatepicker", 7313 7314 //Keep track of the maximum number of rows displayed (see #7043) 7315 maxRows: 4, 7316 7317 // TODO rename to "widget" when switching to widget factory 7318 _widgetDatepicker: function() { 7319 return this.dpDiv; 7320 }, 7321 7322 /* Override the default settings for all instances of the date picker. 7323 * @param settings object - the new settings to use as defaults (anonymous object) 7324 * @return the manager object 7325 */ 7326 setDefaults: function( settings ) { 7327 datepicker_extendRemove( this._defaults, settings || {} ); 7328 return this; 7329 }, 7330 7331 /* Attach the date picker to a jQuery selection. 7332 * @param target element - the target input field or division or span 7333 * @param settings object - the new settings to use for this date picker instance (anonymous) 7334 */ 7335 _attachDatepicker: function( target, settings ) { 7336 var nodeName, inline, inst; 7337 nodeName = target.nodeName.toLowerCase(); 7338 inline = ( nodeName === "div" || nodeName === "span" ); 7339 if ( !target.id ) { 7340 this.uuid += 1; 7341 target.id = "dp" + this.uuid; 7342 } 7343 inst = this._newInst( $( target ), inline ); 7344 inst.settings = $.extend( {}, settings || {} ); 7345 if ( nodeName === "input" ) { 7346 this._connectDatepicker( target, inst ); 7347 } else if ( inline ) { 7348 this._inlineDatepicker( target, inst ); 7349 } 7350 }, 7351 7352 /* Create a new instance object. */ 7353 _newInst: function( target, inline ) { 7354 var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars 7355 return { id: id, input: target, // associated target 7356 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection 7357 drawMonth: 0, drawYear: 0, // month being drawn 7358 inline: inline, // is datepicker inline or not 7359 dpDiv: ( !inline ? this.dpDiv : // presentation div 7360 datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) }; 7361 }, 7362 7363 /* Attach the date picker to an input field. */ 7364 _connectDatepicker: function( target, inst ) { 7365 var input = $( target ); 7366 inst.append = $( [] ); 7367 inst.trigger = $( [] ); 7368 if ( input.hasClass( this.markerClassName ) ) { 7369 return; 7370 } 7371 this._attachments( input, inst ); 7372 input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ). 7373 on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp ); 7374 this._autoSize( inst ); 7375 $.data( target, "datepicker", inst ); 7376 7377 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) 7378 if ( inst.settings.disabled ) { 7379 this._disableDatepicker( target ); 7380 } 7381 }, 7382 7383 /* Make attachments based on settings. */ 7384 _attachments: function( input, inst ) { 7385 var showOn, buttonText, buttonImage, 7386 appendText = this._get( inst, "appendText" ), 7387 isRTL = this._get( inst, "isRTL" ); 7388 7389 if ( inst.append ) { 7390 inst.append.remove(); 7391 } 7392 if ( appendText ) { 7393 inst.append = $( "<span class='" + this._appendClass + "'>" + appendText + "</span>" ); 7394 input[ isRTL ? "before" : "after" ]( inst.append ); 7395 } 7396 7397 input.off( "focus", this._showDatepicker ); 7398 7399 if ( inst.trigger ) { 7400 inst.trigger.remove(); 7401 } 7402 7403 showOn = this._get( inst, "showOn" ); 7404 if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field 7405 input.on( "focus", this._showDatepicker ); 7406 } 7407 if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked 7408 buttonText = this._get( inst, "buttonText" ); 7409 buttonImage = this._get( inst, "buttonImage" ); 7410 inst.trigger = $( this._get( inst, "buttonImageOnly" ) ? 7411 $( "<img/>" ).addClass( this._triggerClass ). 7412 attr( { src: buttonImage, alt: buttonText, title: buttonText } ) : 7413 $( "<button type='button'></button>" ).addClass( this._triggerClass ). 7414 html( !buttonImage ? buttonText : $( "<img/>" ).attr( 7415 { src:buttonImage, alt:buttonText, title:buttonText } ) ) ); 7416 input[ isRTL ? "before" : "after" ]( inst.trigger ); 7417 inst.trigger.on( "click", function() { 7418 if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) { 7419 $.datepicker._hideDatepicker(); 7420 } else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) { 7421 $.datepicker._hideDatepicker(); 7422 $.datepicker._showDatepicker( input[ 0 ] ); 7423 } else { 7424 $.datepicker._showDatepicker( input[ 0 ] ); 7425 } 7426 return false; 7427 } ); 7428 } 7429 }, 7430 7431 /* Apply the maximum length for the date format. */ 7432 _autoSize: function( inst ) { 7433 if ( this._get( inst, "autoSize" ) && !inst.inline ) { 7434 var findMax, max, maxI, i, 7435 date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits 7436 dateFormat = this._get( inst, "dateFormat" ); 7437 7438 if ( dateFormat.match( /[DM]/ ) ) { 7439 findMax = function( names ) { 7440 max = 0; 7441 maxI = 0; 7442 for ( i = 0; i < names.length; i++ ) { 7443 if ( names[ i ].length > max ) { 7444 max = names[ i ].length; 7445 maxI = i; 7446 } 7447 } 7448 return maxI; 7449 }; 7450 date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ? 7451 "monthNames" : "monthNamesShort" ) ) ) ); 7452 date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ? 7453 "dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() ); 7454 } 7455 inst.input.attr( "size", this._formatDate( inst, date ).length ); 7456 } 7457 }, 7458 7459 /* Attach an inline date picker to a div. */ 7460 _inlineDatepicker: function( target, inst ) { 7461 var divSpan = $( target ); 7462 if ( divSpan.hasClass( this.markerClassName ) ) { 7463 return; 7464 } 7465 divSpan.addClass( this.markerClassName ).append( inst.dpDiv ); 7466 $.data( target, "datepicker", inst ); 7467 this._setDate( inst, this._getDefaultDate( inst ), true ); 7468 this._updateDatepicker( inst ); 7469 this._updateAlternate( inst ); 7470 7471 //If disabled option is true, disable the datepicker before showing it (see ticket #5665) 7472 if ( inst.settings.disabled ) { 7473 this._disableDatepicker( target ); 7474 } 7475 7476 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements 7477 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height 7478 inst.dpDiv.css( "display", "block" ); 7479 }, 7480 7481 /* Pop-up the date picker in a "dialog" box. 7482 * @param input element - ignored 7483 * @param date string or Date - the initial date to display 7484 * @param onSelect function - the function to call when a date is selected 7485 * @param settings object - update the dialog date picker instance's settings (anonymous object) 7486 * @param pos int[2] - coordinates for the dialog's position within the screen or 7487 * event - with x/y coordinates or 7488 * leave empty for default (screen centre) 7489 * @return the manager object 7490 */ 7491 _dialogDatepicker: function( input, date, onSelect, settings, pos ) { 7492 var id, browserWidth, browserHeight, scrollX, scrollY, 7493 inst = this._dialogInst; // internal instance 7494 7495 if ( !inst ) { 7496 this.uuid += 1; 7497 id = "dp" + this.uuid; 7498 this._dialogInput = $( "<input type='text' id='" + id + 7499 "' style='position: absolute; top: -100px; width: 0px;'/>" ); 7500 this._dialogInput.on( "keydown", this._doKeyDown ); 7501 $( "body" ).append( this._dialogInput ); 7502 inst = this._dialogInst = this._newInst( this._dialogInput, false ); 7503 inst.settings = {}; 7504 $.data( this._dialogInput[ 0 ], "datepicker", inst ); 7505 } 7506 datepicker_extendRemove( inst.settings, settings || {} ); 7507 date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date ); 7508 this._dialogInput.val( date ); 7509 7510 this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null ); 7511 if ( !this._pos ) { 7512 browserWidth = document.documentElement.clientWidth; 7513 browserHeight = document.documentElement.clientHeight; 7514 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; 7515 scrollY = document.documentElement.scrollTop || document.body.scrollTop; 7516 this._pos = // should use actual width/height below 7517 [ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ]; 7518 } 7519 7520 // Move input on screen for focus, but hidden behind dialog 7521 this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" ); 7522 inst.settings.onSelect = onSelect; 7523 this._inDialog = true; 7524 this.dpDiv.addClass( this._dialogClass ); 7525 this._showDatepicker( this._dialogInput[ 0 ] ); 7526 if ( $.blockUI ) { 7527 $.blockUI( this.dpDiv ); 7528 } 7529 $.data( this._dialogInput[ 0 ], "datepicker", inst ); 7530 return this; 7531 }, 7532 7533 /* Detach a datepicker from its control. 7534 * @param target element - the target input field or division or span 7535 */ 7536 _destroyDatepicker: function( target ) { 7537 var nodeName, 7538 $target = $( target ), 7539 inst = $.data( target, "datepicker" ); 7540 7541 if ( !$target.hasClass( this.markerClassName ) ) { 7542 return; 7543 } 7544 7545 nodeName = target.nodeName.toLowerCase(); 7546 $.removeData( target, "datepicker" ); 7547 if ( nodeName === "input" ) { 7548 inst.append.remove(); 7549 inst.trigger.remove(); 7550 $target.removeClass( this.markerClassName ). 7551 off( "focus", this._showDatepicker ). 7552 off( "keydown", this._doKeyDown ). 7553 off( "keypress", this._doKeyPress ). 7554 off( "keyup", this._doKeyUp ); 7555 } else if ( nodeName === "div" || nodeName === "span" ) { 7556 $target.removeClass( this.markerClassName ).empty(); 7557 } 7558 7559 if ( datepicker_instActive === inst ) { 7560 datepicker_instActive = null; 7561 } 7562 }, 7563 7564 /* Enable the date picker to a jQuery selection. 7565 * @param target element - the target input field or division or span 7566 */ 7567 _enableDatepicker: function( target ) { 7568 var nodeName, inline, 7569 $target = $( target ), 7570 inst = $.data( target, "datepicker" ); 7571 7572 if ( !$target.hasClass( this.markerClassName ) ) { 7573 return; 7574 } 7575 7576 nodeName = target.nodeName.toLowerCase(); 7577 if ( nodeName === "input" ) { 7578 target.disabled = false; 7579 inst.trigger.filter( "button" ). 7580 each( function() { this.disabled = false; } ).end(). 7581 filter( "img" ).css( { opacity: "1.0", cursor: "" } ); 7582 } else if ( nodeName === "div" || nodeName === "span" ) { 7583 inline = $target.children( "." + this._inlineClass ); 7584 inline.children().removeClass( "ui-state-disabled" ); 7585 inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ). 7586 prop( "disabled", false ); 7587 } 7588 this._disabledInputs = $.map( this._disabledInputs, 7589 function( value ) { return ( value === target ? null : value ); } ); // delete entry 7590 }, 7591 7592 /* Disable the date picker to a jQuery selection. 7593 * @param target element - the target input field or division or span 7594 */ 7595 _disableDatepicker: function( target ) { 7596 var nodeName, inline, 7597 $target = $( target ), 7598 inst = $.data( target, "datepicker" ); 7599 7600 if ( !$target.hasClass( this.markerClassName ) ) { 7601 return; 7602 } 7603 7604 nodeName = target.nodeName.toLowerCase(); 7605 if ( nodeName === "input" ) { 7606 target.disabled = true; 7607 inst.trigger.filter( "button" ). 7608 each( function() { this.disabled = true; } ).end(). 7609 filter( "img" ).css( { opacity: "0.5", cursor: "default" } ); 7610 } else if ( nodeName === "div" || nodeName === "span" ) { 7611 inline = $target.children( "." + this._inlineClass ); 7612 inline.children().addClass( "ui-state-disabled" ); 7613 inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ). 7614 prop( "disabled", true ); 7615 } 7616 this._disabledInputs = $.map( this._disabledInputs, 7617 function( value ) { return ( value === target ? null : value ); } ); // delete entry 7618 this._disabledInputs[ this._disabledInputs.length ] = target; 7619 }, 7620 7621 /* Is the first field in a jQuery collection disabled as a datepicker? 7622 * @param target element - the target input field or division or span 7623 * @return boolean - true if disabled, false if enabled 7624 */ 7625 _isDisabledDatepicker: function( target ) { 7626 if ( !target ) { 7627 return false; 7628 } 7629 for ( var i = 0; i < this._disabledInputs.length; i++ ) { 7630 if ( this._disabledInputs[ i ] === target ) { 7631 return true; 7632 } 7633 } 7634 return false; 7635 }, 7636 7637 /* Retrieve the instance data for the target control. 7638 * @param target element - the target input field or division or span 7639 * @return object - the associated instance data 7640 * @throws error if a jQuery problem getting data 7641 */ 7642 _getInst: function( target ) { 7643 try { 7644 return $.data( target, "datepicker" ); 7645 } 7646 catch ( err ) { 7647 throw "Missing instance data for this datepicker"; 7648 } 7649 }, 7650 7651 /* Update or retrieve the settings for a date picker attached to an input field or division. 7652 * @param target element - the target input field or division or span 7653 * @param name object - the new settings to update or 7654 * string - the name of the setting to change or retrieve, 7655 * when retrieving also "all" for all instance settings or 7656 * "defaults" for all global defaults 7657 * @param value any - the new value for the setting 7658 * (omit if above is an object or to retrieve a value) 7659 */ 7660 _optionDatepicker: function( target, name, value ) { 7661 var settings, date, minDate, maxDate, 7662 inst = this._getInst( target ); 7663 7664 if ( arguments.length === 2 && typeof name === "string" ) { 7665 return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) : 7666 ( inst ? ( name === "all" ? $.extend( {}, inst.settings ) : 7667 this._get( inst, name ) ) : null ) ); 7668 } 7669 7670 settings = name || {}; 7671 if ( typeof name === "string" ) { 7672 settings = {}; 7673 settings[ name ] = value; 7674 } 7675 7676 if ( inst ) { 7677 if ( this._curInst === inst ) { 7678 this._hideDatepicker(); 7679 } 7680 7681 date = this._getDateDatepicker( target, true ); 7682 minDate = this._getMinMaxDate( inst, "min" ); 7683 maxDate = this._getMinMaxDate( inst, "max" ); 7684 datepicker_extendRemove( inst.settings, settings ); 7685 7686 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided 7687 if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) { 7688 inst.settings.minDate = this._formatDate( inst, minDate ); 7689 } 7690 if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) { 7691 inst.settings.maxDate = this._formatDate( inst, maxDate ); 7692 } 7693 if ( "disabled" in settings ) { 7694 if ( settings.disabled ) { 7695 this._disableDatepicker( target ); 7696 } else { 7697 this._enableDatepicker( target ); 7698 } 7699 } 7700 this._attachments( $( target ), inst ); 7701 this._autoSize( inst ); 7702 this._setDate( inst, date ); 7703 this._updateAlternate( inst ); 7704 this._updateDatepicker( inst ); 7705 } 7706 }, 7707 7708 // Change method deprecated 7709 _changeDatepicker: function( target, name, value ) { 7710 this._optionDatepicker( target, name, value ); 7711 }, 7712 7713 /* Redraw the date picker attached to an input field or division. 7714 * @param target element - the target input field or division or span 7715 */ 7716 _refreshDatepicker: function( target ) { 7717 var inst = this._getInst( target ); 7718 if ( inst ) { 7719 this._updateDatepicker( inst ); 7720 } 7721 }, 7722 7723 /* Set the dates for a jQuery selection. 7724 * @param target element - the target input field or division or span 7725 * @param date Date - the new date 7726 */ 7727 _setDateDatepicker: function( target, date ) { 7728 var inst = this._getInst( target ); 7729 if ( inst ) { 7730 this._setDate( inst, date ); 7731 this._updateDatepicker( inst ); 7732 this._updateAlternate( inst ); 7733 } 7734 }, 7735 7736 /* Get the date(s) for the first entry in a jQuery selection. 7737 * @param target element - the target input field or division or span 7738 * @param noDefault boolean - true if no default date is to be used 7739 * @return Date - the current date 7740 */ 7741 _getDateDatepicker: function( target, noDefault ) { 7742 var inst = this._getInst( target ); 7743 if ( inst && !inst.inline ) { 7744 this._setDateFromField( inst, noDefault ); 7745 } 7746 return ( inst ? this._getDate( inst ) : null ); 7747 }, 7748 7749 /* Handle keystrokes. */ 7750 _doKeyDown: function( event ) { 7751 var onSelect, dateStr, sel, 7752 inst = $.datepicker._getInst( event.target ), 7753 handled = true, 7754 isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" ); 7755 7756 inst._keyEvent = true; 7757 if ( $.datepicker._datepickerShowing ) { 7758 switch ( event.keyCode ) { 7759 case 9: $.datepicker._hideDatepicker(); 7760 handled = false; 7761 break; // hide on tab out 7762 case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." + 7763 $.datepicker._currentClass + ")", inst.dpDiv ); 7764 if ( sel[ 0 ] ) { 7765 $.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] ); 7766 } 7767 7768 onSelect = $.datepicker._get( inst, "onSelect" ); 7769 if ( onSelect ) { 7770 dateStr = $.datepicker._formatDate( inst ); 7771 7772 // Trigger custom callback 7773 onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] ); 7774 } else { 7775 $.datepicker._hideDatepicker(); 7776 } 7777 7778 return false; // don't submit the form 7779 case 27: $.datepicker._hideDatepicker(); 7780 break; // hide on escape 7781 case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 7782 -$.datepicker._get( inst, "stepBigMonths" ) : 7783 -$.datepicker._get( inst, "stepMonths" ) ), "M" ); 7784 break; // previous month/year on page up/+ ctrl 7785 case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 7786 +$.datepicker._get( inst, "stepBigMonths" ) : 7787 +$.datepicker._get( inst, "stepMonths" ) ), "M" ); 7788 break; // next month/year on page down/+ ctrl 7789 case 35: if ( event.ctrlKey || event.metaKey ) { 7790 $.datepicker._clearDate( event.target ); 7791 } 7792 handled = event.ctrlKey || event.metaKey; 7793 break; // clear on ctrl or command +end 7794 case 36: if ( event.ctrlKey || event.metaKey ) { 7795 $.datepicker._gotoToday( event.target ); 7796 } 7797 handled = event.ctrlKey || event.metaKey; 7798 break; // current on ctrl or command +home 7799 case 37: if ( event.ctrlKey || event.metaKey ) { 7800 $.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" ); 7801 } 7802 handled = event.ctrlKey || event.metaKey; 7803 7804 // -1 day on ctrl or command +left 7805 if ( event.originalEvent.altKey ) { 7806 $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 7807 -$.datepicker._get( inst, "stepBigMonths" ) : 7808 -$.datepicker._get( inst, "stepMonths" ) ), "M" ); 7809 } 7810 7811 // next month/year on alt +left on Mac 7812 break; 7813 case 38: if ( event.ctrlKey || event.metaKey ) { 7814 $.datepicker._adjustDate( event.target, -7, "D" ); 7815 } 7816 handled = event.ctrlKey || event.metaKey; 7817 break; // -1 week on ctrl or command +up 7818 case 39: if ( event.ctrlKey || event.metaKey ) { 7819 $.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" ); 7820 } 7821 handled = event.ctrlKey || event.metaKey; 7822 7823 // +1 day on ctrl or command +right 7824 if ( event.originalEvent.altKey ) { 7825 $.datepicker._adjustDate( event.target, ( event.ctrlKey ? 7826 +$.datepicker._get( inst, "stepBigMonths" ) : 7827 +$.datepicker._get( inst, "stepMonths" ) ), "M" ); 7828 } 7829 7830 // next month/year on alt +right 7831 break; 7832 case 40: if ( event.ctrlKey || event.metaKey ) { 7833 $.datepicker._adjustDate( event.target, +7, "D" ); 7834 } 7835 handled = event.ctrlKey || event.metaKey; 7836 break; // +1 week on ctrl or command +down 7837 default: handled = false; 7838 } 7839 } else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home 7840 $.datepicker._showDatepicker( this ); 7841 } else { 7842 handled = false; 7843 } 7844 7845 if ( handled ) { 7846 event.preventDefault(); 7847 event.stopPropagation(); 7848 } 7849 }, 7850 7851 /* Filter entered characters - based on date format. */ 7852 _doKeyPress: function( event ) { 7853 var chars, chr, 7854 inst = $.datepicker._getInst( event.target ); 7855 7856 if ( $.datepicker._get( inst, "constrainInput" ) ) { 7857 chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) ); 7858 chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode ); 7859 return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 ); 7860 } 7861 }, 7862 7863 /* Synchronise manual entry and field/alternate field. */ 7864 _doKeyUp: function( event ) { 7865 var date, 7866 inst = $.datepicker._getInst( event.target ); 7867 7868 if ( inst.input.val() !== inst.lastVal ) { 7869 try { 7870 date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ), 7871 ( inst.input ? inst.input.val() : null ), 7872 $.datepicker._getFormatConfig( inst ) ); 7873 7874 if ( date ) { // only if valid 7875 $.datepicker._setDateFromField( inst ); 7876 $.datepicker._updateAlternate( inst ); 7877 $.datepicker._updateDatepicker( inst ); 7878 } 7879 } 7880 catch ( err ) { 7881 } 7882 } 7883 return true; 7884 }, 7885 7886 /* Pop-up the date picker for a given input field. 7887 * If false returned from beforeShow event handler do not show. 7888 * @param input element - the input field attached to the date picker or 7889 * event - if triggered by focus 7890 */ 7891 _showDatepicker: function( input ) { 7892 input = input.target || input; 7893 if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger 7894 input = $( "input", input.parentNode )[ 0 ]; 7895 } 7896 7897 if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here 7898 return; 7899 } 7900 7901 var inst, beforeShow, beforeShowSettings, isFixed, 7902 offset, showAnim, duration; 7903 7904 inst = $.datepicker._getInst( input ); 7905 if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) { 7906 $.datepicker._curInst.dpDiv.stop( true, true ); 7907 if ( inst && $.datepicker._datepickerShowing ) { 7908 $.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] ); 7909 } 7910 } 7911 7912 beforeShow = $.datepicker._get( inst, "beforeShow" ); 7913 beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {}; 7914 if ( beforeShowSettings === false ) { 7915 return; 7916 } 7917 datepicker_extendRemove( inst.settings, beforeShowSettings ); 7918 7919 inst.lastVal = null; 7920 $.datepicker._lastInput = input; 7921 $.datepicker._setDateFromField( inst ); 7922 7923 if ( $.datepicker._inDialog ) { // hide cursor 7924 input.value = ""; 7925 } 7926 if ( !$.datepicker._pos ) { // position below input 7927 $.datepicker._pos = $.datepicker._findPos( input ); 7928 $.datepicker._pos[ 1 ] += input.offsetHeight; // add the height 7929 } 7930 7931 isFixed = false; 7932 $( input ).parents().each( function() { 7933 isFixed |= $( this ).css( "position" ) === "fixed"; 7934 return !isFixed; 7935 } ); 7936 7937 offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] }; 7938 $.datepicker._pos = null; 7939 7940 //to avoid flashes on Firefox 7941 inst.dpDiv.empty(); 7942 7943 // determine sizing offscreen 7944 inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } ); 7945 $.datepicker._updateDatepicker( inst ); 7946 7947 // fix width for dynamic number of date pickers 7948 // and adjust position before showing 7949 offset = $.datepicker._checkOffset( inst, offset, isFixed ); 7950 inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ? 7951 "static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none", 7952 left: offset.left + "px", top: offset.top + "px" } ); 7953 7954 if ( !inst.inline ) { 7955 showAnim = $.datepicker._get( inst, "showAnim" ); 7956 duration = $.datepicker._get( inst, "duration" ); 7957 inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 ); 7958 $.datepicker._datepickerShowing = true; 7959 7960 if ( $.effects && $.effects.effect[ showAnim ] ) { 7961 inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration ); 7962 } else { 7963 inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null ); 7964 } 7965 7966 if ( $.datepicker._shouldFocusInput( inst ) ) { 7967 inst.input.trigger( "focus" ); 7968 } 7969 7970 $.datepicker._curInst = inst; 7971 } 7972 }, 7973 7974 /* Generate the date picker content. */ 7975 _updateDatepicker: function( inst ) { 7976 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) 7977 datepicker_instActive = inst; // for delegate hover events 7978 inst.dpDiv.empty().append( this._generateHTML( inst ) ); 7979 this._attachHandlers( inst ); 7980 7981 var origyearshtml, 7982 numMonths = this._getNumberOfMonths( inst ), 7983 cols = numMonths[ 1 ], 7984 width = 17, 7985 activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ); 7986 7987 if ( activeCell.length > 0 ) { 7988 datepicker_handleMouseover.apply( activeCell.get( 0 ) ); 7989 } 7990 7991 inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" ); 7992 if ( cols > 1 ) { 7993 inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" ); 7994 } 7995 inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) + 7996 "Class" ]( "ui-datepicker-multi" ); 7997 inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) + 7998 "Class" ]( "ui-datepicker-rtl" ); 7999 8000 if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) { 8001 inst.input.trigger( "focus" ); 8002 } 8003 8004 // Deffered render of the years select (to avoid flashes on Firefox) 8005 if ( inst.yearshtml ) { 8006 origyearshtml = inst.yearshtml; 8007 setTimeout( function() { 8008 8009 //assure that inst.yearshtml didn't change. 8010 if ( origyearshtml === inst.yearshtml && inst.yearshtml ) { 8011 inst.dpDiv.find( "select.ui-datepicker-year:first" ).replaceWith( inst.yearshtml ); 8012 } 8013 origyearshtml = inst.yearshtml = null; 8014 }, 0 ); 8015 } 8016 }, 8017 8018 // #6694 - don't focus the input if it's already focused 8019 // this breaks the change event in IE 8020 // Support: IE and jQuery <1.9 8021 _shouldFocusInput: function( inst ) { 8022 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" ); 8023 }, 8024 8025 /* Check positioning to remain on screen. */ 8026 _checkOffset: function( inst, offset, isFixed ) { 8027 var dpWidth = inst.dpDiv.outerWidth(), 8028 dpHeight = inst.dpDiv.outerHeight(), 8029 inputWidth = inst.input ? inst.input.outerWidth() : 0, 8030 inputHeight = inst.input ? inst.input.outerHeight() : 0, 8031 viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ), 8032 viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() ); 8033 8034 offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 ); 8035 offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0; 8036 offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0; 8037 8038 // Now check if datepicker is showing outside window viewport - move to a better place if so. 8039 offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ? 8040 Math.abs( offset.left + dpWidth - viewWidth ) : 0 ); 8041 offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ? 8042 Math.abs( dpHeight + inputHeight ) : 0 ); 8043 8044 return offset; 8045 }, 8046 8047 /* Find an object's position on the screen. */ 8048 _findPos: function( obj ) { 8049 var position, 8050 inst = this._getInst( obj ), 8051 isRTL = this._get( inst, "isRTL" ); 8052 8053 while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden( obj ) ) ) { 8054 obj = obj[ isRTL ? "previousSibling" : "nextSibling" ]; 8055 } 8056 8057 position = $( obj ).offset(); 8058 return [ position.left, position.top ]; 8059 }, 8060 8061 /* Hide the date picker from view. 8062 * @param input element - the input field attached to the date picker 8063 */ 8064 _hideDatepicker: function( input ) { 8065 var showAnim, duration, postProcess, onClose, 8066 inst = this._curInst; 8067 8068 if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) { 8069 return; 8070 } 8071 8072 if ( this._datepickerShowing ) { 8073 showAnim = this._get( inst, "showAnim" ); 8074 duration = this._get( inst, "duration" ); 8075 postProcess = function() { 8076 $.datepicker._tidyDialog( inst ); 8077 }; 8078 8079 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed 8080 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) { 8081 inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess ); 8082 } else { 8083 inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" : 8084 ( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess ); 8085 } 8086 8087 if ( !showAnim ) { 8088 postProcess(); 8089 } 8090 this._datepickerShowing = false; 8091 8092 onClose = this._get( inst, "onClose" ); 8093 if ( onClose ) { 8094 onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] ); 8095 } 8096 8097 this._lastInput = null; 8098 if ( this._inDialog ) { 8099 this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } ); 8100 if ( $.blockUI ) { 8101 $.unblockUI(); 8102 $( "body" ).append( this.dpDiv ); 8103 } 8104 } 8105 this._inDialog = false; 8106 } 8107 }, 8108 8109 /* Tidy up after a dialog display. */ 8110 _tidyDialog: function( inst ) { 8111 inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" ); 8112 }, 8113 8114 /* Close date picker if clicked elsewhere. */ 8115 _checkExternalClick: function( event ) { 8116 if ( !$.datepicker._curInst ) { 8117 return; 8118 } 8119 8120 var $target = $( event.target ), 8121 inst = $.datepicker._getInst( $target[ 0 ] ); 8122 8123 if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId && 8124 $target.parents( "#" + $.datepicker._mainDivId ).length === 0 && 8125 !$target.hasClass( $.datepicker.markerClassName ) && 8126 !$target.closest( "." + $.datepicker._triggerClass ).length && 8127 $.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) || 8128 ( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) { 8129 $.datepicker._hideDatepicker(); 8130 } 8131 }, 8132 8133 /* Adjust one of the date sub-fields. */ 8134 _adjustDate: function( id, offset, period ) { 8135 var target = $( id ), 8136 inst = this._getInst( target[ 0 ] ); 8137 8138 if ( this._isDisabledDatepicker( target[ 0 ] ) ) { 8139 return; 8140 } 8141 this._adjustInstDate( inst, offset + 8142 ( period === "M" ? this._get( inst, "showCurrentAtPos" ) : 0 ), // undo positioning 8143 period ); 8144 this._updateDatepicker( inst ); 8145 }, 8146 8147 /* Action for current link. */ 8148 _gotoToday: function( id ) { 8149 var date, 8150 target = $( id ), 8151 inst = this._getInst( target[ 0 ] ); 8152 8153 if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) { 8154 inst.selectedDay = inst.currentDay; 8155 inst.drawMonth = inst.selectedMonth = inst.currentMonth; 8156 inst.drawYear = inst.selectedYear = inst.currentYear; 8157 } else { 8158 date = new Date(); 8159 inst.selectedDay = date.getDate(); 8160 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8161 inst.drawYear = inst.selectedYear = date.getFullYear(); 8162 } 8163 this._notifyChange( inst ); 8164 this._adjustDate( target ); 8165 }, 8166 8167 /* Action for selecting a new month/year. */ 8168 _selectMonthYear: function( id, select, period ) { 8169 var target = $( id ), 8170 inst = this._getInst( target[ 0 ] ); 8171 8172 inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] = 8173 inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] = 8174 parseInt( select.options[ select.selectedIndex ].value, 10 ); 8175 8176 this._notifyChange( inst ); 8177 this._adjustDate( target ); 8178 }, 8179 8180 /* Action for selecting a day. */ 8181 _selectDay: function( id, month, year, td ) { 8182 var inst, 8183 target = $( id ); 8184 8185 if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) { 8186 return; 8187 } 8188 8189 inst = this._getInst( target[ 0 ] ); 8190 inst.selectedDay = inst.currentDay = $( "a", td ).html(); 8191 inst.selectedMonth = inst.currentMonth = month; 8192 inst.selectedYear = inst.currentYear = year; 8193 this._selectDate( id, this._formatDate( inst, 8194 inst.currentDay, inst.currentMonth, inst.currentYear ) ); 8195 }, 8196 8197 /* Erase the input field and hide the date picker. */ 8198 _clearDate: function( id ) { 8199 var target = $( id ); 8200 this._selectDate( target, "" ); 8201 }, 8202 8203 /* Update the input field with the selected date. */ 8204 _selectDate: function( id, dateStr ) { 8205 var onSelect, 8206 target = $( id ), 8207 inst = this._getInst( target[ 0 ] ); 8208 8209 dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) ); 8210 if ( inst.input ) { 8211 inst.input.val( dateStr ); 8212 } 8213 this._updateAlternate( inst ); 8214 8215 onSelect = this._get( inst, "onSelect" ); 8216 if ( onSelect ) { 8217 onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] ); // trigger custom callback 8218 } else if ( inst.input ) { 8219 inst.input.trigger( "change" ); // fire the change event 8220 } 8221 8222 if ( inst.inline ) { 8223 this._updateDatepicker( inst ); 8224 } else { 8225 this._hideDatepicker(); 8226 this._lastInput = inst.input[ 0 ]; 8227 if ( typeof( inst.input[ 0 ] ) !== "object" ) { 8228 inst.input.trigger( "focus" ); // restore focus 8229 } 8230 this._lastInput = null; 8231 } 8232 }, 8233 8234 /* Update any alternate field to synchronise with the main field. */ 8235 _updateAlternate: function( inst ) { 8236 var altFormat, date, dateStr, 8237 altField = this._get( inst, "altField" ); 8238 8239 if ( altField ) { // update alternate field too 8240 altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" ); 8241 date = this._getDate( inst ); 8242 dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) ); 8243 $( altField ).val( dateStr ); 8244 } 8245 }, 8246 8247 /* Set as beforeShowDay function to prevent selection of weekends. 8248 * @param date Date - the date to customise 8249 * @return [boolean, string] - is this date selectable?, what is its CSS class? 8250 */ 8251 noWeekends: function( date ) { 8252 var day = date.getDay(); 8253 return [ ( day > 0 && day < 6 ), "" ]; 8254 }, 8255 8256 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. 8257 * @param date Date - the date to get the week for 8258 * @return number - the number of the week within the year that contains this date 8259 */ 8260 iso8601Week: function( date ) { 8261 var time, 8262 checkDate = new Date( date.getTime() ); 8263 8264 // Find Thursday of this week starting on Monday 8265 checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) ); 8266 8267 time = checkDate.getTime(); 8268 checkDate.setMonth( 0 ); // Compare with Jan 1 8269 checkDate.setDate( 1 ); 8270 return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1; 8271 }, 8272 8273 /* Parse a string value into a date object. 8274 * See formatDate below for the possible formats. 8275 * 8276 * @param format string - the expected format of the date 8277 * @param value string - the date in the above format 8278 * @param settings Object - attributes include: 8279 * shortYearCutoff number - the cutoff year for determining the century (optional) 8280 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 8281 * dayNames string[7] - names of the days from Sunday (optional) 8282 * monthNamesShort string[12] - abbreviated names of the months (optional) 8283 * monthNames string[12] - names of the months (optional) 8284 * @return Date - the extracted date value or null if value is blank 8285 */ 8286 parseDate: function( format, value, settings ) { 8287 if ( format == null || value == null ) { 8288 throw "Invalid arguments"; 8289 } 8290 8291 value = ( typeof value === "object" ? value.toString() : value + "" ); 8292 if ( value === "" ) { 8293 return null; 8294 } 8295 8296 var iFormat, dim, extra, 8297 iValue = 0, 8298 shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff, 8299 shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp : 8300 new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ), 8301 dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort, 8302 dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames, 8303 monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort, 8304 monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames, 8305 year = -1, 8306 month = -1, 8307 day = -1, 8308 doy = -1, 8309 literal = false, 8310 date, 8311 8312 // Check whether a format character is doubled 8313 lookAhead = function( match ) { 8314 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match ); 8315 if ( matches ) { 8316 iFormat++; 8317 } 8318 return matches; 8319 }, 8320 8321 // Extract a number from the string value 8322 getNumber = function( match ) { 8323 var isDoubled = lookAhead( match ), 8324 size = ( match === "@" ? 14 : ( match === "!" ? 20 : 8325 ( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ), 8326 minSize = ( match === "y" ? size : 1 ), 8327 digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ), 8328 num = value.substring( iValue ).match( digits ); 8329 if ( !num ) { 8330 throw "Missing number at position " + iValue; 8331 } 8332 iValue += num[ 0 ].length; 8333 return parseInt( num[ 0 ], 10 ); 8334 }, 8335 8336 // Extract a name from the string value and convert to an index 8337 getName = function( match, shortNames, longNames ) { 8338 var index = -1, 8339 names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) { 8340 return [ [ k, v ] ]; 8341 } ).sort( function( a, b ) { 8342 return -( a[ 1 ].length - b[ 1 ].length ); 8343 } ); 8344 8345 $.each( names, function( i, pair ) { 8346 var name = pair[ 1 ]; 8347 if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) { 8348 index = pair[ 0 ]; 8349 iValue += name.length; 8350 return false; 8351 } 8352 } ); 8353 if ( index !== -1 ) { 8354 return index + 1; 8355 } else { 8356 throw "Unknown name at position " + iValue; 8357 } 8358 }, 8359 8360 // Confirm that a literal character matches the string value 8361 checkLiteral = function() { 8362 if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) { 8363 throw "Unexpected literal at position " + iValue; 8364 } 8365 iValue++; 8366 }; 8367 8368 for ( iFormat = 0; iFormat < format.length; iFormat++ ) { 8369 if ( literal ) { 8370 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) { 8371 literal = false; 8372 } else { 8373 checkLiteral(); 8374 } 8375 } else { 8376 switch ( format.charAt( iFormat ) ) { 8377 case "d": 8378 day = getNumber( "d" ); 8379 break; 8380 case "D": 8381 getName( "D", dayNamesShort, dayNames ); 8382 break; 8383 case "o": 8384 doy = getNumber( "o" ); 8385 break; 8386 case "m": 8387 month = getNumber( "m" ); 8388 break; 8389 case "M": 8390 month = getName( "M", monthNamesShort, monthNames ); 8391 break; 8392 case "y": 8393 year = getNumber( "y" ); 8394 break; 8395 case "@": 8396 date = new Date( getNumber( "@" ) ); 8397 year = date.getFullYear(); 8398 month = date.getMonth() + 1; 8399 day = date.getDate(); 8400 break; 8401 case "!": 8402 date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 ); 8403 year = date.getFullYear(); 8404 month = date.getMonth() + 1; 8405 day = date.getDate(); 8406 break; 8407 case "'": 8408 if ( lookAhead( "'" ) ) { 8409 checkLiteral(); 8410 } else { 8411 literal = true; 8412 } 8413 break; 8414 default: 8415 checkLiteral(); 8416 } 8417 } 8418 } 8419 8420 if ( iValue < value.length ) { 8421 extra = value.substr( iValue ); 8422 if ( !/^\s+/.test( extra ) ) { 8423 throw "Extra/unparsed characters found in date: " + extra; 8424 } 8425 } 8426 8427 if ( year === -1 ) { 8428 year = new Date().getFullYear(); 8429 } else if ( year < 100 ) { 8430 year += new Date().getFullYear() - new Date().getFullYear() % 100 + 8431 ( year <= shortYearCutoff ? 0 : -100 ); 8432 } 8433 8434 if ( doy > -1 ) { 8435 month = 1; 8436 day = doy; 8437 do { 8438 dim = this._getDaysInMonth( year, month - 1 ); 8439 if ( day <= dim ) { 8440 break; 8441 } 8442 month++; 8443 day -= dim; 8444 } while ( true ); 8445 } 8446 8447 date = this._daylightSavingAdjust( new Date( year, month - 1, day ) ); 8448 if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) { 8449 throw "Invalid date"; // E.g. 31/02/00 8450 } 8451 return date; 8452 }, 8453 8454 /* Standard date formats. */ 8455 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601) 8456 COOKIE: "D, dd M yy", 8457 ISO_8601: "yy-mm-dd", 8458 RFC_822: "D, d M y", 8459 RFC_850: "DD, dd-M-y", 8460 RFC_1036: "D, d M y", 8461 RFC_1123: "D, d M yy", 8462 RFC_2822: "D, d M yy", 8463 RSS: "D, d M y", // RFC 822 8464 TICKS: "!", 8465 TIMESTAMP: "@", 8466 W3C: "yy-mm-dd", // ISO 8601 8467 8468 _ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) + 8469 Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ), 8470 8471 /* Format a date object into a string value. 8472 * The format can be combinations of the following: 8473 * d - day of month (no leading zero) 8474 * dd - day of month (two digit) 8475 * o - day of year (no leading zeros) 8476 * oo - day of year (three digit) 8477 * D - day name short 8478 * DD - day name long 8479 * m - month of year (no leading zero) 8480 * mm - month of year (two digit) 8481 * M - month name short 8482 * MM - month name long 8483 * y - year (two digit) 8484 * yy - year (four digit) 8485 * @ - Unix timestamp (ms since 01/01/1970) 8486 * ! - Windows ticks (100ns since 01/01/0001) 8487 * "..." - literal text 8488 * '' - single quote 8489 * 8490 * @param format string - the desired format of the date 8491 * @param date Date - the date value to format 8492 * @param settings Object - attributes include: 8493 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 8494 * dayNames string[7] - names of the days from Sunday (optional) 8495 * monthNamesShort string[12] - abbreviated names of the months (optional) 8496 * monthNames string[12] - names of the months (optional) 8497 * @return string - the date in the above format 8498 */ 8499 formatDate: function( format, date, settings ) { 8500 if ( !date ) { 8501 return ""; 8502 } 8503 8504 var iFormat, 8505 dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort, 8506 dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames, 8507 monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort, 8508 monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames, 8509 8510 // Check whether a format character is doubled 8511 lookAhead = function( match ) { 8512 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match ); 8513 if ( matches ) { 8514 iFormat++; 8515 } 8516 return matches; 8517 }, 8518 8519 // Format a number, with leading zero if necessary 8520 formatNumber = function( match, value, len ) { 8521 var num = "" + value; 8522 if ( lookAhead( match ) ) { 8523 while ( num.length < len ) { 8524 num = "0" + num; 8525 } 8526 } 8527 return num; 8528 }, 8529 8530 // Format a name, short or long as requested 8531 formatName = function( match, value, shortNames, longNames ) { 8532 return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] ); 8533 }, 8534 output = "", 8535 literal = false; 8536 8537 if ( date ) { 8538 for ( iFormat = 0; iFormat < format.length; iFormat++ ) { 8539 if ( literal ) { 8540 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) { 8541 literal = false; 8542 } else { 8543 output += format.charAt( iFormat ); 8544 } 8545 } else { 8546 switch ( format.charAt( iFormat ) ) { 8547 case "d": 8548 output += formatNumber( "d", date.getDate(), 2 ); 8549 break; 8550 case "D": 8551 output += formatName( "D", date.getDay(), dayNamesShort, dayNames ); 8552 break; 8553 case "o": 8554 output += formatNumber( "o", 8555 Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 ); 8556 break; 8557 case "m": 8558 output += formatNumber( "m", date.getMonth() + 1, 2 ); 8559 break; 8560 case "M": 8561 output += formatName( "M", date.getMonth(), monthNamesShort, monthNames ); 8562 break; 8563 case "y": 8564 output += ( lookAhead( "y" ) ? date.getFullYear() : 8565 ( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 ); 8566 break; 8567 case "@": 8568 output += date.getTime(); 8569 break; 8570 case "!": 8571 output += date.getTime() * 10000 + this._ticksTo1970; 8572 break; 8573 case "'": 8574 if ( lookAhead( "'" ) ) { 8575 output += "'"; 8576 } else { 8577 literal = true; 8578 } 8579 break; 8580 default: 8581 output += format.charAt( iFormat ); 8582 } 8583 } 8584 } 8585 } 8586 return output; 8587 }, 8588 8589 /* Extract all possible characters from the date format. */ 8590 _possibleChars: function( format ) { 8591 var iFormat, 8592 chars = "", 8593 literal = false, 8594 8595 // Check whether a format character is doubled 8596 lookAhead = function( match ) { 8597 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match ); 8598 if ( matches ) { 8599 iFormat++; 8600 } 8601 return matches; 8602 }; 8603 8604 for ( iFormat = 0; iFormat < format.length; iFormat++ ) { 8605 if ( literal ) { 8606 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) { 8607 literal = false; 8608 } else { 8609 chars += format.charAt( iFormat ); 8610 } 8611 } else { 8612 switch ( format.charAt( iFormat ) ) { 8613 case "d": case "m": case "y": case "@": 8614 chars += "0123456789"; 8615 break; 8616 case "D": case "M": 8617 return null; // Accept anything 8618 case "'": 8619 if ( lookAhead( "'" ) ) { 8620 chars += "'"; 8621 } else { 8622 literal = true; 8623 } 8624 break; 8625 default: 8626 chars += format.charAt( iFormat ); 8627 } 8628 } 8629 } 8630 return chars; 8631 }, 8632 8633 /* Get a setting value, defaulting if necessary. */ 8634 _get: function( inst, name ) { 8635 return inst.settings[ name ] !== undefined ? 8636 inst.settings[ name ] : this._defaults[ name ]; 8637 }, 8638 8639 /* Parse existing date and initialise date picker. */ 8640 _setDateFromField: function( inst, noDefault ) { 8641 if ( inst.input.val() === inst.lastVal ) { 8642 return; 8643 } 8644 8645 var dateFormat = this._get( inst, "dateFormat" ), 8646 dates = inst.lastVal = inst.input ? inst.input.val() : null, 8647 defaultDate = this._getDefaultDate( inst ), 8648 date = defaultDate, 8649 settings = this._getFormatConfig( inst ); 8650 8651 try { 8652 date = this.parseDate( dateFormat, dates, settings ) || defaultDate; 8653 } catch ( event ) { 8654 dates = ( noDefault ? "" : dates ); 8655 } 8656 inst.selectedDay = date.getDate(); 8657 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8658 inst.drawYear = inst.selectedYear = date.getFullYear(); 8659 inst.currentDay = ( dates ? date.getDate() : 0 ); 8660 inst.currentMonth = ( dates ? date.getMonth() : 0 ); 8661 inst.currentYear = ( dates ? date.getFullYear() : 0 ); 8662 this._adjustInstDate( inst ); 8663 }, 8664 8665 /* Retrieve the default date shown on opening. */ 8666 _getDefaultDate: function( inst ) { 8667 return this._restrictMinMax( inst, 8668 this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) ); 8669 }, 8670 8671 /* A date may be specified as an exact value or a relative one. */ 8672 _determineDate: function( inst, date, defaultDate ) { 8673 var offsetNumeric = function( offset ) { 8674 var date = new Date(); 8675 date.setDate( date.getDate() + offset ); 8676 return date; 8677 }, 8678 offsetString = function( offset ) { 8679 try { 8680 return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ), 8681 offset, $.datepicker._getFormatConfig( inst ) ); 8682 } 8683 catch ( e ) { 8684 8685 // Ignore 8686 } 8687 8688 var date = ( offset.toLowerCase().match( /^c/ ) ? 8689 $.datepicker._getDate( inst ) : null ) || new Date(), 8690 year = date.getFullYear(), 8691 month = date.getMonth(), 8692 day = date.getDate(), 8693 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, 8694 matches = pattern.exec( offset ); 8695 8696 while ( matches ) { 8697 switch ( matches[ 2 ] || "d" ) { 8698 case "d" : case "D" : 8699 day += parseInt( matches[ 1 ], 10 ); break; 8700 case "w" : case "W" : 8701 day += parseInt( matches[ 1 ], 10 ) * 7; break; 8702 case "m" : case "M" : 8703 month += parseInt( matches[ 1 ], 10 ); 8704 day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) ); 8705 break; 8706 case "y": case "Y" : 8707 year += parseInt( matches[ 1 ], 10 ); 8708 day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) ); 8709 break; 8710 } 8711 matches = pattern.exec( offset ); 8712 } 8713 return new Date( year, month, day ); 8714 }, 8715 newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) : 8716 ( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) ); 8717 8718 newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate ); 8719 if ( newDate ) { 8720 newDate.setHours( 0 ); 8721 newDate.setMinutes( 0 ); 8722 newDate.setSeconds( 0 ); 8723 newDate.setMilliseconds( 0 ); 8724 } 8725 return this._daylightSavingAdjust( newDate ); 8726 }, 8727 8728 /* Handle switch to/from daylight saving. 8729 * Hours may be non-zero on daylight saving cut-over: 8730 * > 12 when midnight changeover, but then cannot generate 8731 * midnight datetime, so jump to 1AM, otherwise reset. 8732 * @param date (Date) the date to check 8733 * @return (Date) the corrected date 8734 */ 8735 _daylightSavingAdjust: function( date ) { 8736 if ( !date ) { 8737 return null; 8738 } 8739 date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 ); 8740 return date; 8741 }, 8742 8743 /* Set the date(s) directly. */ 8744 _setDate: function( inst, date, noChange ) { 8745 var clear = !date, 8746 origMonth = inst.selectedMonth, 8747 origYear = inst.selectedYear, 8748 newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) ); 8749 8750 inst.selectedDay = inst.currentDay = newDate.getDate(); 8751 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); 8752 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); 8753 if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) { 8754 this._notifyChange( inst ); 8755 } 8756 this._adjustInstDate( inst ); 8757 if ( inst.input ) { 8758 inst.input.val( clear ? "" : this._formatDate( inst ) ); 8759 } 8760 }, 8761 8762 /* Retrieve the date(s) directly. */ 8763 _getDate: function( inst ) { 8764 var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null : 8765 this._daylightSavingAdjust( new Date( 8766 inst.currentYear, inst.currentMonth, inst.currentDay ) ) ); 8767 return startDate; 8768 }, 8769 8770 /* Attach the onxxx handlers. These are declared statically so 8771 * they work with static code transformers like Caja. 8772 */ 8773 _attachHandlers: function( inst ) { 8774 var stepMonths = this._get( inst, "stepMonths" ), 8775 id = "#" + inst.id.replace( /\\\\/g, "\\" ); 8776 inst.dpDiv.find( "[data-handler]" ).map( function() { 8777 var handler = { 8778 prev: function() { 8779 $.datepicker._adjustDate( id, -stepMonths, "M" ); 8780 }, 8781 next: function() { 8782 $.datepicker._adjustDate( id, +stepMonths, "M" ); 8783 }, 8784 hide: function() { 8785 $.datepicker._hideDatepicker(); 8786 }, 8787 today: function() { 8788 $.datepicker._gotoToday( id ); 8789 }, 8790 selectDay: function() { 8791 $.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this ); 8792 return false; 8793 }, 8794 selectMonth: function() { 8795 $.datepicker._selectMonthYear( id, this, "M" ); 8796 return false; 8797 }, 8798 selectYear: function() { 8799 $.datepicker._selectMonthYear( id, this, "Y" ); 8800 return false; 8801 } 8802 }; 8803 $( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] ); 8804 } ); 8805 }, 8806 8807 /* Generate the HTML for the current state of the date picker. */ 8808 _generateHTML: function( inst ) { 8809 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate, 8810 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin, 8811 monthNames, monthNamesShort, beforeShowDay, showOtherMonths, 8812 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate, 8813 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows, 8814 printDate, dRow, tbody, daySettings, otherMonth, unselectable, 8815 tempDate = new Date(), 8816 today = this._daylightSavingAdjust( 8817 new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time 8818 isRTL = this._get( inst, "isRTL" ), 8819 showButtonPanel = this._get( inst, "showButtonPanel" ), 8820 hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ), 8821 navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ), 8822 numMonths = this._getNumberOfMonths( inst ), 8823 showCurrentAtPos = this._get( inst, "showCurrentAtPos" ), 8824 stepMonths = this._get( inst, "stepMonths" ), 8825 isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ), 8826 currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) : 8827 new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ), 8828 minDate = this._getMinMaxDate( inst, "min" ), 8829 maxDate = this._getMinMaxDate( inst, "max" ), 8830 drawMonth = inst.drawMonth - showCurrentAtPos, 8831 drawYear = inst.drawYear; 8832 8833 if ( drawMonth < 0 ) { 8834 drawMonth += 12; 8835 drawYear--; 8836 } 8837 if ( maxDate ) { 8838 maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(), 8839 maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) ); 8840 maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw ); 8841 while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) { 8842 drawMonth--; 8843 if ( drawMonth < 0 ) { 8844 drawMonth = 11; 8845 drawYear--; 8846 } 8847 } 8848 } 8849 inst.drawMonth = drawMonth; 8850 inst.drawYear = drawYear; 8851 8852 prevText = this._get( inst, "prevText" ); 8853 prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText, 8854 this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ), 8855 this._getFormatConfig( inst ) ) ); 8856 8857 prev = ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ? 8858 "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" + 8859 " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w" ) + "'>" + prevText + "</span></a>" : 8860 ( hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w" ) + "'>" + prevText + "</span></a>" ) ); 8861 8862 nextText = this._get( inst, "nextText" ); 8863 nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText, 8864 this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ), 8865 this._getFormatConfig( inst ) ) ); 8866 8867 next = ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ? 8868 "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" + 8869 " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e" ) + "'>" + nextText + "</span></a>" : 8870 ( hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e" ) + "'>" + nextText + "</span></a>" ) ); 8871 8872 currentText = this._get( inst, "currentText" ); 8873 gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today ); 8874 currentText = ( !navigationAsDateFormat ? currentText : 8875 this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) ); 8876 8877 controls = ( !inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" + 8878 this._get( inst, "closeText" ) + "</button>" : "" ); 8879 8880 buttonPanel = ( showButtonPanel ) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + ( isRTL ? controls : "" ) + 8881 ( this._isInRange( inst, gotoDate ) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" + 8882 ">" + currentText + "</button>" : "" ) + ( isRTL ? "" : controls ) + "</div>" : ""; 8883 8884 firstDay = parseInt( this._get( inst, "firstDay" ), 10 ); 8885 firstDay = ( isNaN( firstDay ) ? 0 : firstDay ); 8886 8887 showWeek = this._get( inst, "showWeek" ); 8888 dayNames = this._get( inst, "dayNames" ); 8889 dayNamesMin = this._get( inst, "dayNamesMin" ); 8890 monthNames = this._get( inst, "monthNames" ); 8891 monthNamesShort = this._get( inst, "monthNamesShort" ); 8892 beforeShowDay = this._get( inst, "beforeShowDay" ); 8893 showOtherMonths = this._get( inst, "showOtherMonths" ); 8894 selectOtherMonths = this._get( inst, "selectOtherMonths" ); 8895 defaultDate = this._getDefaultDate( inst ); 8896 html = ""; 8897 8898 for ( row = 0; row < numMonths[ 0 ]; row++ ) { 8899 group = ""; 8900 this.maxRows = 4; 8901 for ( col = 0; col < numMonths[ 1 ]; col++ ) { 8902 selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) ); 8903 cornerClass = " ui-corner-all"; 8904 calender = ""; 8905 if ( isMultiMonth ) { 8906 calender += "<div class='ui-datepicker-group"; 8907 if ( numMonths[ 1 ] > 1 ) { 8908 switch ( col ) { 8909 case 0: calender += " ui-datepicker-group-first"; 8910 cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break; 8911 case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last"; 8912 cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break; 8913 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break; 8914 } 8915 } 8916 calender += "'>"; 8917 } 8918 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" + 8919 ( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) + 8920 ( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) + 8921 this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate, 8922 row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers 8923 "</div><table class='ui-datepicker-calendar'><thead>" + 8924 "<tr>"; 8925 thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" ); 8926 for ( dow = 0; dow < 7; dow++ ) { // days of the week 8927 day = ( dow + firstDay ) % 7; 8928 thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" + 8929 "<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>"; 8930 } 8931 calender += thead + "</tr></thead><tbody>"; 8932 daysInMonth = this._getDaysInMonth( drawYear, drawMonth ); 8933 if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) { 8934 inst.selectedDay = Math.min( inst.selectedDay, daysInMonth ); 8935 } 8936 leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7; 8937 curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate 8938 numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043) 8939 this.maxRows = numRows; 8940 printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) ); 8941 for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows 8942 calender += "<tr>"; 8943 tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" + 8944 this._get( inst, "calculateWeek" )( printDate ) + "</td>" ); 8945 for ( dow = 0; dow < 7; dow++ ) { // create date picker days 8946 daySettings = ( beforeShowDay ? 8947 beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] ); 8948 otherMonth = ( printDate.getMonth() !== drawMonth ); 8949 unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] || 8950 ( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate ); 8951 tbody += "<td class='" + 8952 ( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends 8953 ( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months 8954 ( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key 8955 ( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ? 8956 8957 // or defaultDate is current printedDate and defaultDate is selectedDate 8958 " " + this._dayOverClass : "" ) + // highlight selected day 8959 ( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) + // highlight unselectable days 8960 ( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates 8961 ( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day 8962 ( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different) 8963 ( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "'" ) + "'" : "" ) + // cell title 8964 ( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions 8965 ( otherMonth && !showOtherMonths ? " " : // display for other months 8966 ( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" + 8967 ( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) + 8968 ( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day 8969 ( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months 8970 "' href='#'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date 8971 printDate.setDate( printDate.getDate() + 1 ); 8972 printDate = this._daylightSavingAdjust( printDate ); 8973 } 8974 calender += tbody + "</tr>"; 8975 } 8976 drawMonth++; 8977 if ( drawMonth > 11 ) { 8978 drawMonth = 0; 8979 drawYear++; 8980 } 8981 calender += "</tbody></table>" + ( isMultiMonth ? "</div>" + 8982 ( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" ); 8983 group += calender; 8984 } 8985 html += group; 8986 } 8987 html += buttonPanel; 8988 inst._keyEvent = false; 8989 return html; 8990 }, 8991 8992 /* Generate the month and year header. */ 8993 _generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate, 8994 secondary, monthNames, monthNamesShort ) { 8995 8996 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear, 8997 changeMonth = this._get( inst, "changeMonth" ), 8998 changeYear = this._get( inst, "changeYear" ), 8999 showMonthAfterYear = this._get( inst, "showMonthAfterYear" ), 9000 html = "<div class='ui-datepicker-title'>", 9001 monthHtml = ""; 9002 9003 // Month selection 9004 if ( secondary || !changeMonth ) { 9005 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>"; 9006 } else { 9007 inMinYear = ( minDate && minDate.getFullYear() === drawYear ); 9008 inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear ); 9009 monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>"; 9010 for ( month = 0; month < 12; month++ ) { 9011 if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) { 9012 monthHtml += "<option value='" + month + "'" + 9013 ( month === drawMonth ? " selected='selected'" : "" ) + 9014 ">" + monthNamesShort[ month ] + "</option>"; 9015 } 9016 } 9017 monthHtml += "</select>"; 9018 } 9019 9020 if ( !showMonthAfterYear ) { 9021 html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? " " : "" ); 9022 } 9023 9024 // Year selection 9025 if ( !inst.yearshtml ) { 9026 inst.yearshtml = ""; 9027 if ( secondary || !changeYear ) { 9028 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>"; 9029 } else { 9030 9031 // determine range of years to display 9032 years = this._get( inst, "yearRange" ).split( ":" ); 9033 thisYear = new Date().getFullYear(); 9034 determineYear = function( value ) { 9035 var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) : 9036 ( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) : 9037 parseInt( value, 10 ) ) ); 9038 return ( isNaN( year ) ? thisYear : year ); 9039 }; 9040 year = determineYear( years[ 0 ] ); 9041 endYear = Math.max( year, determineYear( years[ 1 ] || "" ) ); 9042 year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year ); 9043 endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear ); 9044 inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>"; 9045 for ( ; year <= endYear; year++ ) { 9046 inst.yearshtml += "<option value='" + year + "'" + 9047 ( year === drawYear ? " selected='selected'" : "" ) + 9048 ">" + year + "</option>"; 9049 } 9050 inst.yearshtml += "</select>"; 9051 9052 html += inst.yearshtml; 9053 inst.yearshtml = null; 9054 } 9055 } 9056 9057 html += this._get( inst, "yearSuffix" ); 9058 if ( showMonthAfterYear ) { 9059 html += ( secondary || !( changeMonth && changeYear ) ? " " : "" ) + monthHtml; 9060 } 9061 html += "</div>"; // Close datepicker_header 9062 return html; 9063 }, 9064 9065 /* Adjust one of the date sub-fields. */ 9066 _adjustInstDate: function( inst, offset, period ) { 9067 var year = inst.selectedYear + ( period === "Y" ? offset : 0 ), 9068 month = inst.selectedMonth + ( period === "M" ? offset : 0 ), 9069 day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ), 9070 date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) ); 9071 9072 inst.selectedDay = date.getDate(); 9073 inst.drawMonth = inst.selectedMonth = date.getMonth(); 9074 inst.drawYear = inst.selectedYear = date.getFullYear(); 9075 if ( period === "M" || period === "Y" ) { 9076 this._notifyChange( inst ); 9077 } 9078 }, 9079 9080 /* Ensure a date is within any min/max bounds. */ 9081 _restrictMinMax: function( inst, date ) { 9082 var minDate = this._getMinMaxDate( inst, "min" ), 9083 maxDate = this._getMinMaxDate( inst, "max" ), 9084 newDate = ( minDate && date < minDate ? minDate : date ); 9085 return ( maxDate && newDate > maxDate ? maxDate : newDate ); 9086 }, 9087 9088 /* Notify change of month/year. */ 9089 _notifyChange: function( inst ) { 9090 var onChange = this._get( inst, "onChangeMonthYear" ); 9091 if ( onChange ) { 9092 onChange.apply( ( inst.input ? inst.input[ 0 ] : null ), 9093 [ inst.selectedYear, inst.selectedMonth + 1, inst ] ); 9094 } 9095 }, 9096 9097 /* Determine the number of months to show. */ 9098 _getNumberOfMonths: function( inst ) { 9099 var numMonths = this._get( inst, "numberOfMonths" ); 9100 return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) ); 9101 }, 9102 9103 /* Determine the current maximum date - ensure no time components are set. */ 9104 _getMinMaxDate: function( inst, minMax ) { 9105 return this._determineDate( inst, this._get( inst, minMax + "Date" ), null ); 9106 }, 9107 9108 /* Find the number of days in a given month. */ 9109 _getDaysInMonth: function( year, month ) { 9110 return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate(); 9111 }, 9112 9113 /* Find the day of the week of the first of a month. */ 9114 _getFirstDayOfMonth: function( year, month ) { 9115 return new Date( year, month, 1 ).getDay(); 9116 }, 9117 9118 /* Determines if we should allow a "next/prev" month display change. */ 9119 _canAdjustMonth: function( inst, offset, curYear, curMonth ) { 9120 var numMonths = this._getNumberOfMonths( inst ), 9121 date = this._daylightSavingAdjust( new Date( curYear, 9122 curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) ); 9123 9124 if ( offset < 0 ) { 9125 date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) ); 9126 } 9127 return this._isInRange( inst, date ); 9128 }, 9129 9130 /* Is the given date in the accepted range? */ 9131 _isInRange: function( inst, date ) { 9132 var yearSplit, currentYear, 9133 minDate = this._getMinMaxDate( inst, "min" ), 9134 maxDate = this._getMinMaxDate( inst, "max" ), 9135 minYear = null, 9136 maxYear = null, 9137 years = this._get( inst, "yearRange" ); 9138 if ( years ) { 9139 yearSplit = years.split( ":" ); 9140 currentYear = new Date().getFullYear(); 9141 minYear = parseInt( yearSplit[ 0 ], 10 ); 9142 maxYear = parseInt( yearSplit[ 1 ], 10 ); 9143 if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) { 9144 minYear += currentYear; 9145 } 9146 if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) { 9147 maxYear += currentYear; 9148 } 9149 } 9150 9151 return ( ( !minDate || date.getTime() >= minDate.getTime() ) && 9152 ( !maxDate || date.getTime() <= maxDate.getTime() ) && 9153 ( !minYear || date.getFullYear() >= minYear ) && 9154 ( !maxYear || date.getFullYear() <= maxYear ) ); 9155 }, 9156 9157 /* Provide the configuration settings for formatting/parsing. */ 9158 _getFormatConfig: function( inst ) { 9159 var shortYearCutoff = this._get( inst, "shortYearCutoff" ); 9160 shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff : 9161 new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) ); 9162 return { shortYearCutoff: shortYearCutoff, 9163 dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ), 9164 monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) }; 9165 }, 9166 9167 /* Format the given date for display. */ 9168 _formatDate: function( inst, day, month, year ) { 9169 if ( !day ) { 9170 inst.currentDay = inst.selectedDay; 9171 inst.currentMonth = inst.selectedMonth; 9172 inst.currentYear = inst.selectedYear; 9173 } 9174 var date = ( day ? ( typeof day === "object" ? day : 9175 this._daylightSavingAdjust( new Date( year, month, day ) ) ) : 9176 this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ); 9177 return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) ); 9178 } 9179} ); 9180 9181/* 9182 * Bind hover events for datepicker elements. 9183 * Done via delegate so the binding only occurs once in the lifetime of the parent div. 9184 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. 9185 */ 9186function datepicker_bindHover( dpDiv ) { 9187 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a"; 9188 return dpDiv.on( "mouseout", selector, function() { 9189 $( this ).removeClass( "ui-state-hover" ); 9190 if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) { 9191 $( this ).removeClass( "ui-datepicker-prev-hover" ); 9192 } 9193 if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) { 9194 $( this ).removeClass( "ui-datepicker-next-hover" ); 9195 } 9196 } ) 9197 .on( "mouseover", selector, datepicker_handleMouseover ); 9198} 9199 9200function datepicker_handleMouseover() { 9201 if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) { 9202 $( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" ); 9203 $( this ).addClass( "ui-state-hover" ); 9204 if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) { 9205 $( this ).addClass( "ui-datepicker-prev-hover" ); 9206 } 9207 if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) { 9208 $( this ).addClass( "ui-datepicker-next-hover" ); 9209 } 9210 } 9211} 9212 9213/* jQuery extend now ignores nulls! */ 9214function datepicker_extendRemove( target, props ) { 9215 $.extend( target, props ); 9216 for ( var name in props ) { 9217 if ( props[ name ] == null ) { 9218 target[ name ] = props[ name ]; 9219 } 9220 } 9221 return target; 9222} 9223 9224/* Invoke the datepicker functionality. 9225 @param options string - a command, optionally followed by additional parameters or 9226 Object - settings for attaching new datepicker functionality 9227 @return jQuery object */ 9228$.fn.datepicker = function( options ) { 9229 9230 /* Verify an empty collection wasn't passed - Fixes #6976 */ 9231 if ( !this.length ) { 9232 return this; 9233 } 9234 9235 /* Initialise the date picker. */ 9236 if ( !$.datepicker.initialized ) { 9237 $( document ).on( "mousedown", $.datepicker._checkExternalClick ); 9238 $.datepicker.initialized = true; 9239 } 9240 9241 /* Append datepicker main container to body if not exist. */ 9242 if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) { 9243 $( "body" ).append( $.datepicker.dpDiv ); 9244 } 9245 9246 var otherArgs = Array.prototype.slice.call( arguments, 1 ); 9247 if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) { 9248 return $.datepicker[ "_" + options + "Datepicker" ]. 9249 apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) ); 9250 } 9251 if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) { 9252 return $.datepicker[ "_" + options + "Datepicker" ]. 9253 apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) ); 9254 } 9255 return this.each( function() { 9256 typeof options === "string" ? 9257 $.datepicker[ "_" + options + "Datepicker" ]. 9258 apply( $.datepicker, [ this ].concat( otherArgs ) ) : 9259 $.datepicker._attachDatepicker( this, options ); 9260 } ); 9261}; 9262 9263$.datepicker = new Datepicker(); // singleton instance 9264$.datepicker.initialized = false; 9265$.datepicker.uuid = new Date().getTime(); 9266$.datepicker.version = "1.12.1"; 9267 9268var widgetsDatepicker = $.datepicker; 9269 9270 9271 9272 9273// This file is deprecated 9274var ie = $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ); 9275 9276/*! 9277 * jQuery UI Mouse 1.12.1 9278 * http://jqueryui.com 9279 * 9280 * Copyright jQuery Foundation and other contributors 9281 * Released under the MIT license. 9282 * http://jquery.org/license 9283 */ 9284 9285//>>label: Mouse 9286//>>group: Widgets 9287//>>description: Abstracts mouse-based interactions to assist in creating certain widgets. 9288//>>docs: http://api.jqueryui.com/mouse/ 9289 9290 9291 9292var mouseHandled = false; 9293$( document ).on( "mouseup", function() { 9294 mouseHandled = false; 9295} ); 9296 9297var widgetsMouse = $.widget( "ui.mouse", { 9298 version: "1.12.1", 9299 options: { 9300 cancel: "input, textarea, button, select, option", 9301 distance: 1, 9302 delay: 0 9303 }, 9304 _mouseInit: function() { 9305 var that = this; 9306 9307 this.element 9308 .on( "mousedown." + this.widgetName, function( event ) { 9309 return that._mouseDown( event ); 9310 } ) 9311 .on( "click." + this.widgetName, function( event ) { 9312 if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) { 9313 $.removeData( event.target, that.widgetName + ".preventClickEvent" ); 9314 event.stopImmediatePropagation(); 9315 return false; 9316 } 9317 } ); 9318 9319 this.started = false; 9320 }, 9321 9322 // TODO: make sure destroying one instance of mouse doesn't mess with 9323 // other instances of mouse 9324 _mouseDestroy: function() { 9325 this.element.off( "." + this.widgetName ); 9326 if ( this._mouseMoveDelegate ) { 9327 this.document 9328 .off( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 9329 .off( "mouseup." + this.widgetName, this._mouseUpDelegate ); 9330 } 9331 }, 9332 9333 _mouseDown: function( event ) { 9334 9335 // don't let more than one widget handle mouseStart 9336 if ( mouseHandled ) { 9337 return; 9338 } 9339 9340 this._mouseMoved = false; 9341 9342 // We may have missed mouseup (out of window) 9343 ( this._mouseStarted && this._mouseUp( event ) ); 9344 9345 this._mouseDownEvent = event; 9346 9347 var that = this, 9348 btnIsLeft = ( event.which === 1 ), 9349 9350 // event.target.nodeName works around a bug in IE 8 with 9351 // disabled inputs (#7620) 9352 elIsCancel = ( typeof this.options.cancel === "string" && event.target.nodeName ? 9353 $( event.target ).closest( this.options.cancel ).length : false ); 9354 if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) { 9355 return true; 9356 } 9357 9358 this.mouseDelayMet = !this.options.delay; 9359 if ( !this.mouseDelayMet ) { 9360 this._mouseDelayTimer = setTimeout( function() { 9361 that.mouseDelayMet = true; 9362 }, this.options.delay ); 9363 } 9364 9365 if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) { 9366 this._mouseStarted = ( this._mouseStart( event ) !== false ); 9367 if ( !this._mouseStarted ) { 9368 event.preventDefault(); 9369 return true; 9370 } 9371 } 9372 9373 // Click event may never have fired (Gecko & Opera) 9374 if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) { 9375 $.removeData( event.target, this.widgetName + ".preventClickEvent" ); 9376 } 9377 9378 // These delegates are required to keep context 9379 this._mouseMoveDelegate = function( event ) { 9380 return that._mouseMove( event ); 9381 }; 9382 this._mouseUpDelegate = function( event ) { 9383 return that._mouseUp( event ); 9384 }; 9385 9386 this.document 9387 .on( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 9388 .on( "mouseup." + this.widgetName, this._mouseUpDelegate ); 9389 9390 event.preventDefault(); 9391 9392 mouseHandled = true; 9393 return true; 9394 }, 9395 9396 _mouseMove: function( event ) { 9397 9398 // Only check for mouseups outside the document if you've moved inside the document 9399 // at least once. This prevents the firing of mouseup in the case of IE<9, which will 9400 // fire a mousemove event if content is placed under the cursor. See #7778 9401 // Support: IE <9 9402 if ( this._mouseMoved ) { 9403 9404 // IE mouseup check - mouseup happened when mouse was out of window 9405 if ( $.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && 9406 !event.button ) { 9407 return this._mouseUp( event ); 9408 9409 // Iframe mouseup check - mouseup occurred in another document 9410 } else if ( !event.which ) { 9411 9412 // Support: Safari <=8 - 9 9413 // Safari sets which to 0 if you press any of the following keys 9414 // during a drag (#14461) 9415 if ( event.originalEvent.altKey || event.originalEvent.ctrlKey || 9416 event.originalEvent.metaKey || event.originalEvent.shiftKey ) { 9417 this.ignoreMissingWhich = true; 9418 } else if ( !this.ignoreMissingWhich ) { 9419 return this._mouseUp( event ); 9420 } 9421 } 9422 } 9423 9424 if ( event.which || event.button ) { 9425 this._mouseMoved = true; 9426 } 9427 9428 if ( this._mouseStarted ) { 9429 this._mouseDrag( event ); 9430 return event.preventDefault(); 9431 } 9432 9433 if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) { 9434 this._mouseStarted = 9435 ( this._mouseStart( this._mouseDownEvent, event ) !== false ); 9436 ( this._mouseStarted ? this._mouseDrag( event ) : this._mouseUp( event ) ); 9437 } 9438 9439 return !this._mouseStarted; 9440 }, 9441 9442 _mouseUp: function( event ) { 9443 this.document 9444 .off( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 9445 .off( "mouseup." + this.widgetName, this._mouseUpDelegate ); 9446 9447 if ( this._mouseStarted ) { 9448 this._mouseStarted = false; 9449 9450 if ( event.target === this._mouseDownEvent.target ) { 9451 $.data( event.target, this.widgetName + ".preventClickEvent", true ); 9452 } 9453 9454 this._mouseStop( event ); 9455 } 9456 9457 if ( this._mouseDelayTimer ) { 9458 clearTimeout( this._mouseDelayTimer ); 9459 delete this._mouseDelayTimer; 9460 } 9461 9462 this.ignoreMissingWhich = false; 9463 mouseHandled = false; 9464 event.preventDefault(); 9465 }, 9466 9467 _mouseDistanceMet: function( event ) { 9468 return ( Math.max( 9469 Math.abs( this._mouseDownEvent.pageX - event.pageX ), 9470 Math.abs( this._mouseDownEvent.pageY - event.pageY ) 9471 ) >= this.options.distance 9472 ); 9473 }, 9474 9475 _mouseDelayMet: function( /* event */ ) { 9476 return this.mouseDelayMet; 9477 }, 9478 9479 // These are placeholder methods, to be overriden by extending plugin 9480 _mouseStart: function( /* event */ ) {}, 9481 _mouseDrag: function( /* event */ ) {}, 9482 _mouseStop: function( /* event */ ) {}, 9483 _mouseCapture: function( /* event */ ) { return true; } 9484} ); 9485 9486 9487 9488 9489// $.ui.plugin is deprecated. Use $.widget() extensions instead. 9490var plugin = $.ui.plugin = { 9491 add: function( module, option, set ) { 9492 var i, 9493 proto = $.ui[ module ].prototype; 9494 for ( i in set ) { 9495 proto.plugins[ i ] = proto.plugins[ i ] || []; 9496 proto.plugins[ i ].push( [ option, set[ i ] ] ); 9497 } 9498 }, 9499 call: function( instance, name, args, allowDisconnected ) { 9500 var i, 9501 set = instance.plugins[ name ]; 9502 9503 if ( !set ) { 9504 return; 9505 } 9506 9507 if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || 9508 instance.element[ 0 ].parentNode.nodeType === 11 ) ) { 9509 return; 9510 } 9511 9512 for ( i = 0; i < set.length; i++ ) { 9513 if ( instance.options[ set[ i ][ 0 ] ] ) { 9514 set[ i ][ 1 ].apply( instance.element, args ); 9515 } 9516 } 9517 } 9518}; 9519 9520 9521 9522var safeBlur = $.ui.safeBlur = function( element ) { 9523 9524 // Support: IE9 - 10 only 9525 // If the <body> is blurred, IE will switch windows, see #9420 9526 if ( element && element.nodeName.toLowerCase() !== "body" ) { 9527 $( element ).trigger( "blur" ); 9528 } 9529}; 9530 9531 9532 9533/*! 9534 * jQuery UI Selectmenu 1.12.1 9535 * http://jqueryui.com 9536 * 9537 * Copyright jQuery Foundation and other contributors 9538 * Released under the MIT license. 9539 * http://jquery.org/license 9540 */ 9541 9542//>>label: Selectmenu 9543//>>group: Widgets 9544// jscs:disable maximumLineLength 9545//>>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. 9546// jscs:enable maximumLineLength 9547//>>docs: http://api.jqueryui.com/selectmenu/ 9548//>>demos: http://jqueryui.com/selectmenu/ 9549//>>css.structure: ../../themes/base/core.css 9550//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css 9551//>>css.theme: ../../themes/base/theme.css 9552 9553 9554 9555var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, { 9556 version: "1.12.1", 9557 defaultElement: "<select>", 9558 options: { 9559 appendTo: null, 9560 classes: { 9561 "ui-selectmenu-button-open": "ui-corner-top", 9562 "ui-selectmenu-button-closed": "ui-corner-all" 9563 }, 9564 disabled: null, 9565 icons: { 9566 button: "ui-icon-triangle-1-s" 9567 }, 9568 position: { 9569 my: "left top", 9570 at: "left bottom", 9571 collision: "none" 9572 }, 9573 width: false, 9574 9575 // Callbacks 9576 change: null, 9577 close: null, 9578 focus: null, 9579 open: null, 9580 select: null 9581 }, 9582 9583 _create: function() { 9584 var selectmenuId = this.element.uniqueId().attr( "id" ); 9585 this.ids = { 9586 element: selectmenuId, 9587 button: selectmenuId + "-button", 9588 menu: selectmenuId + "-menu" 9589 }; 9590 9591 this._drawButton(); 9592 this._drawMenu(); 9593 this._bindFormResetHandler(); 9594 9595 this._rendered = false; 9596 this.menuItems = $(); 9597 }, 9598 9599 _drawButton: function() { 9600 var icon, 9601 that = this, 9602 item = this._parseOption( 9603 this.element.find( "option:selected" ), 9604 this.element[ 0 ].selectedIndex 9605 ); 9606 9607 // Associate existing label with the new button 9608 this.labels = this.element.labels().attr( "for", this.ids.button ); 9609 this._on( this.labels, { 9610 click: function( event ) { 9611 this.button.focus(); 9612 event.preventDefault(); 9613 } 9614 } ); 9615 9616 // Hide original select element 9617 this.element.hide(); 9618 9619 // Create button 9620 this.button = $( "<span>", { 9621 tabindex: this.options.disabled ? -1 : 0, 9622 id: this.ids.button, 9623 role: "combobox", 9624 "aria-expanded": "false", 9625 "aria-autocomplete": "list", 9626 "aria-owns": this.ids.menu, 9627 "aria-haspopup": "true", 9628 title: this.element.attr( "title" ) 9629 } ) 9630 .insertAfter( this.element ); 9631 9632 this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed", 9633 "ui-button ui-widget" ); 9634 9635 icon = $( "<span>" ).appendTo( this.button ); 9636 this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button ); 9637 this.buttonItem = this._renderButtonItem( item ) 9638 .appendTo( this.button ); 9639 9640 if ( this.options.width !== false ) { 9641 this._resizeButton(); 9642 } 9643 9644 this._on( this.button, this._buttonEvents ); 9645 this.button.one( "focusin", function() { 9646 9647 // Delay rendering the menu items until the button receives focus. 9648 // The menu may have already been rendered via a programmatic open. 9649 if ( !that._rendered ) { 9650 that._refreshMenu(); 9651 } 9652 } ); 9653 }, 9654 9655 _drawMenu: function() { 9656 var that = this; 9657 9658 // Create menu 9659 this.menu = $( "<ul>", { 9660 "aria-hidden": "true", 9661 "aria-labelledby": this.ids.button, 9662 id: this.ids.menu 9663 } ); 9664 9665 // Wrap menu 9666 this.menuWrap = $( "<div>" ).append( this.menu ); 9667 this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" ); 9668 this.menuWrap.appendTo( this._appendTo() ); 9669 9670 // Initialize menu widget 9671 this.menuInstance = this.menu 9672 .menu( { 9673 classes: { 9674 "ui-menu": "ui-corner-bottom" 9675 }, 9676 role: "listbox", 9677 select: function( event, ui ) { 9678 event.preventDefault(); 9679 9680 // Support: IE8 9681 // If the item was selected via a click, the text selection 9682 // will be destroyed in IE 9683 that._setSelection(); 9684 9685 that._select( ui.item.data( "ui-selectmenu-item" ), event ); 9686 }, 9687 focus: function( event, ui ) { 9688 var item = ui.item.data( "ui-selectmenu-item" ); 9689 9690 // Prevent inital focus from firing and check if its a newly focused item 9691 if ( that.focusIndex != null && item.index !== that.focusIndex ) { 9692 that._trigger( "focus", event, { item: item } ); 9693 if ( !that.isOpen ) { 9694 that._select( item, event ); 9695 } 9696 } 9697 that.focusIndex = item.index; 9698 9699 that.button.attr( "aria-activedescendant", 9700 that.menuItems.eq( item.index ).attr( "id" ) ); 9701 } 9702 } ) 9703 .menu( "instance" ); 9704 9705 // Don't close the menu on mouseleave 9706 this.menuInstance._off( this.menu, "mouseleave" ); 9707 9708 // Cancel the menu's collapseAll on document click 9709 this.menuInstance._closeOnDocumentClick = function() { 9710 return false; 9711 }; 9712 9713 // Selects often contain empty items, but never contain dividers 9714 this.menuInstance._isDivider = function() { 9715 return false; 9716 }; 9717 }, 9718 9719 refresh: function() { 9720 this._refreshMenu(); 9721 this.buttonItem.replaceWith( 9722 this.buttonItem = this._renderButtonItem( 9723 9724 // Fall back to an empty object in case there are no options 9725 this._getSelectedItem().data( "ui-selectmenu-item" ) || {} 9726 ) 9727 ); 9728 if ( this.options.width === null ) { 9729 this._resizeButton(); 9730 } 9731 }, 9732 9733 _refreshMenu: function() { 9734 var item, 9735 options = this.element.find( "option" ); 9736 9737 this.menu.empty(); 9738 9739 this._parseOptions( options ); 9740 this._renderMenu( this.menu, this.items ); 9741 9742 this.menuInstance.refresh(); 9743 this.menuItems = this.menu.find( "li" ) 9744 .not( ".ui-selectmenu-optgroup" ) 9745 .find( ".ui-menu-item-wrapper" ); 9746 9747 this._rendered = true; 9748 9749 if ( !options.length ) { 9750 return; 9751 } 9752 9753 item = this._getSelectedItem(); 9754 9755 // Update the menu to have the correct item focused 9756 this.menuInstance.focus( null, item ); 9757 this._setAria( item.data( "ui-selectmenu-item" ) ); 9758 9759 // Set disabled state 9760 this._setOption( "disabled", this.element.prop( "disabled" ) ); 9761 }, 9762 9763 open: function( event ) { 9764 if ( this.options.disabled ) { 9765 return; 9766 } 9767 9768 // If this is the first time the menu is being opened, render the items 9769 if ( !this._rendered ) { 9770 this._refreshMenu(); 9771 } else { 9772 9773 // Menu clears focus on close, reset focus to selected item 9774 this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" ); 9775 this.menuInstance.focus( null, this._getSelectedItem() ); 9776 } 9777 9778 // If there are no options, don't open the menu 9779 if ( !this.menuItems.length ) { 9780 return; 9781 } 9782 9783 this.isOpen = true; 9784 this._toggleAttr(); 9785 this._resizeMenu(); 9786 this._position(); 9787 9788 this._on( this.document, this._documentClick ); 9789 9790 this._trigger( "open", event ); 9791 }, 9792 9793 _position: function() { 9794 this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) ); 9795 }, 9796 9797 close: function( event ) { 9798 if ( !this.isOpen ) { 9799 return; 9800 } 9801 9802 this.isOpen = false; 9803 this._toggleAttr(); 9804 9805 this.range = null; 9806 this._off( this.document ); 9807 9808 this._trigger( "close", event ); 9809 }, 9810 9811 widget: function() { 9812 return this.button; 9813 }, 9814 9815 menuWidget: function() { 9816 return this.menu; 9817 }, 9818 9819 _renderButtonItem: function( item ) { 9820 var buttonItem = $( "<span>" ); 9821 9822 this._setText( buttonItem, item.label ); 9823 this._addClass( buttonItem, "ui-selectmenu-text" ); 9824 9825 return buttonItem; 9826 }, 9827 9828 _renderMenu: function( ul, items ) { 9829 var that = this, 9830 currentOptgroup = ""; 9831 9832 $.each( items, function( index, item ) { 9833 var li; 9834 9835 if ( item.optgroup !== currentOptgroup ) { 9836 li = $( "<li>", { 9837 text: item.optgroup 9838 } ); 9839 that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" + 9840 ( item.element.parent( "optgroup" ).prop( "disabled" ) ? 9841 " ui-state-disabled" : 9842 "" ) ); 9843 9844 li.appendTo( ul ); 9845 9846 currentOptgroup = item.optgroup; 9847 } 9848 9849 that._renderItemData( ul, item ); 9850 } ); 9851 }, 9852 9853 _renderItemData: function( ul, item ) { 9854 return this._renderItem( ul, item ).data( "ui-selectmenu-item", item ); 9855 }, 9856 9857 _renderItem: function( ul, item ) { 9858 var li = $( "<li>" ), 9859 wrapper = $( "<div>", { 9860 title: item.element.attr( "title" ) 9861 } ); 9862 9863 if ( item.disabled ) { 9864 this._addClass( li, null, "ui-state-disabled" ); 9865 } 9866 this._setText( wrapper, item.label ); 9867 9868 return li.append( wrapper ).appendTo( ul ); 9869 }, 9870 9871 _setText: function( element, value ) { 9872 if ( value ) { 9873 element.text( value ); 9874 } else { 9875 element.html( " " ); 9876 } 9877 }, 9878 9879 _move: function( direction, event ) { 9880 var item, next, 9881 filter = ".ui-menu-item"; 9882 9883 if ( this.isOpen ) { 9884 item = this.menuItems.eq( this.focusIndex ).parent( "li" ); 9885 } else { 9886 item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" ); 9887 filter += ":not(.ui-state-disabled)"; 9888 } 9889 9890 if ( direction === "first" || direction === "last" ) { 9891 next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 ); 9892 } else { 9893 next = item[ direction + "All" ]( filter ).eq( 0 ); 9894 } 9895 9896 if ( next.length ) { 9897 this.menuInstance.focus( event, next ); 9898 } 9899 }, 9900 9901 _getSelectedItem: function() { 9902 return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" ); 9903 }, 9904 9905 _toggle: function( event ) { 9906 this[ this.isOpen ? "close" : "open" ]( event ); 9907 }, 9908 9909 _setSelection: function() { 9910 var selection; 9911 9912 if ( !this.range ) { 9913 return; 9914 } 9915 9916 if ( window.getSelection ) { 9917 selection = window.getSelection(); 9918 selection.removeAllRanges(); 9919 selection.addRange( this.range ); 9920 9921 // Support: IE8 9922 } else { 9923 this.range.select(); 9924 } 9925 9926 // Support: IE 9927 // Setting the text selection kills the button focus in IE, but 9928 // restoring the focus doesn't kill the selection. 9929 this.button.focus(); 9930 }, 9931 9932 _documentClick: { 9933 mousedown: function( event ) { 9934 if ( !this.isOpen ) { 9935 return; 9936 } 9937 9938 if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" + 9939 $.ui.escapeSelector( this.ids.button ) ).length ) { 9940 this.close( event ); 9941 } 9942 } 9943 }, 9944 9945 _buttonEvents: { 9946 9947 // Prevent text selection from being reset when interacting with the selectmenu (#10144) 9948 mousedown: function() { 9949 var selection; 9950 9951 if ( window.getSelection ) { 9952 selection = window.getSelection(); 9953 if ( selection.rangeCount ) { 9954 this.range = selection.getRangeAt( 0 ); 9955 } 9956 9957 // Support: IE8 9958 } else { 9959 this.range = document.selection.createRange(); 9960 } 9961 }, 9962 9963 click: function( event ) { 9964 this._setSelection(); 9965 this._toggle( event ); 9966 }, 9967 9968 keydown: function( event ) { 9969 var preventDefault = true; 9970 switch ( event.keyCode ) { 9971 case $.ui.keyCode.TAB: 9972 case $.ui.keyCode.ESCAPE: 9973 this.close( event ); 9974 preventDefault = false; 9975 break; 9976 case $.ui.keyCode.ENTER: 9977 if ( this.isOpen ) { 9978 this._selectFocusedItem( event ); 9979 } 9980 break; 9981 case $.ui.keyCode.UP: 9982 if ( event.altKey ) { 9983 this._toggle( event ); 9984 } else { 9985 this._move( "prev", event ); 9986 } 9987 break; 9988 case $.ui.keyCode.DOWN: 9989 if ( event.altKey ) { 9990 this._toggle( event ); 9991 } else { 9992 this._move( "next", event ); 9993 } 9994 break; 9995 case $.ui.keyCode.SPACE: 9996 if ( this.isOpen ) { 9997 this._selectFocusedItem( event ); 9998 } else { 9999 this._toggle( event ); 10000 } 10001 break; 10002 case $.ui.keyCode.LEFT: 10003 this._move( "prev", event ); 10004 break; 10005 case $.ui.keyCode.RIGHT: 10006 this._move( "next", event ); 10007 break; 10008 case $.ui.keyCode.HOME: 10009 case $.ui.keyCode.PAGE_UP: 10010 this._move( "first", event ); 10011 break; 10012 case $.ui.keyCode.END: 10013 case $.ui.keyCode.PAGE_DOWN: 10014 this._move( "last", event ); 10015 break; 10016 default: 10017 this.menu.trigger( event ); 10018 preventDefault = false; 10019 } 10020 10021 if ( preventDefault ) { 10022 event.preventDefault(); 10023 } 10024 } 10025 }, 10026 10027 _selectFocusedItem: function( event ) { 10028 var item = this.menuItems.eq( this.focusIndex ).parent( "li" ); 10029 if ( !item.hasClass( "ui-state-disabled" ) ) { 10030 this._select( item.data( "ui-selectmenu-item" ), event ); 10031 } 10032 }, 10033 10034 _select: function( item, event ) { 10035 var oldIndex = this.element[ 0 ].selectedIndex; 10036 10037 // Change native select element 10038 this.element[ 0 ].selectedIndex = item.index; 10039 this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) ); 10040 this._setAria( item ); 10041 this._trigger( "select", event, { item: item } ); 10042 10043 if ( item.index !== oldIndex ) { 10044 this._trigger( "change", event, { item: item } ); 10045 } 10046 10047 this.close( event ); 10048 }, 10049 10050 _setAria: function( item ) { 10051 var id = this.menuItems.eq( item.index ).attr( "id" ); 10052 10053 this.button.attr( { 10054 "aria-labelledby": id, 10055 "aria-activedescendant": id 10056 } ); 10057 this.menu.attr( "aria-activedescendant", id ); 10058 }, 10059 10060 _setOption: function( key, value ) { 10061 if ( key === "icons" ) { 10062 var icon = this.button.find( "span.ui-icon" ); 10063 this._removeClass( icon, null, this.options.icons.button ) 10064 ._addClass( icon, null, value.button ); 10065 } 10066 10067 this._super( key, value ); 10068 10069 if ( key === "appendTo" ) { 10070 this.menuWrap.appendTo( this._appendTo() ); 10071 } 10072 10073 if ( key === "width" ) { 10074 this._resizeButton(); 10075 } 10076 }, 10077 10078 _setOptionDisabled: function( value ) { 10079 this._super( value ); 10080 10081 this.menuInstance.option( "disabled", value ); 10082 this.button.attr( "aria-disabled", value ); 10083 this._toggleClass( this.button, null, "ui-state-disabled", value ); 10084 10085 this.element.prop( "disabled", value ); 10086 if ( value ) { 10087 this.button.attr( "tabindex", -1 ); 10088 this.close(); 10089 } else { 10090 this.button.attr( "tabindex", 0 ); 10091 } 10092 }, 10093 10094 _appendTo: function() { 10095 var element = this.options.appendTo; 10096 10097 if ( element ) { 10098 element = element.jquery || element.nodeType ? 10099 $( element ) : 10100 this.document.find( element ).eq( 0 ); 10101 } 10102 10103 if ( !element || !element[ 0 ] ) { 10104 element = this.element.closest( ".ui-front, dialog" ); 10105 } 10106 10107 if ( !element.length ) { 10108 element = this.document[ 0 ].body; 10109 } 10110 10111 return element; 10112 }, 10113 10114 _toggleAttr: function() { 10115 this.button.attr( "aria-expanded", this.isOpen ); 10116 10117 // We can't use two _toggleClass() calls here, because we need to make sure 10118 // we always remove classes first and add them second, otherwise if both classes have the 10119 // same theme class, it will be removed after we add it. 10120 this._removeClass( this.button, "ui-selectmenu-button-" + 10121 ( this.isOpen ? "closed" : "open" ) ) 10122 ._addClass( this.button, "ui-selectmenu-button-" + 10123 ( this.isOpen ? "open" : "closed" ) ) 10124 ._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen ); 10125 10126 this.menu.attr( "aria-hidden", !this.isOpen ); 10127 }, 10128 10129 _resizeButton: function() { 10130 var width = this.options.width; 10131 10132 // For `width: false`, just remove inline style and stop 10133 if ( width === false ) { 10134 this.button.css( "width", "" ); 10135 return; 10136 } 10137 10138 // For `width: null`, match the width of the original element 10139 if ( width === null ) { 10140 width = this.element.show().outerWidth(); 10141 this.element.hide(); 10142 } 10143 10144 this.button.outerWidth( width ); 10145 }, 10146 10147 _resizeMenu: function() { 10148 this.menu.outerWidth( Math.max( 10149 this.button.outerWidth(), 10150 10151 // Support: IE10 10152 // IE10 wraps long text (possibly a rounding bug) 10153 // so we add 1px to avoid the wrapping 10154 this.menu.width( "" ).outerWidth() + 1 10155 ) ); 10156 }, 10157 10158 _getCreateOptions: function() { 10159 var options = this._super(); 10160 10161 options.disabled = this.element.prop( "disabled" ); 10162 10163 return options; 10164 }, 10165 10166 _parseOptions: function( options ) { 10167 var that = this, 10168 data = []; 10169 options.each( function( index, item ) { 10170 data.push( that._parseOption( $( item ), index ) ); 10171 } ); 10172 this.items = data; 10173 }, 10174 10175 _parseOption: function( option, index ) { 10176 var optgroup = option.parent( "optgroup" ); 10177 10178 return { 10179 element: option, 10180 index: index, 10181 value: option.val(), 10182 label: option.text(), 10183 optgroup: optgroup.attr( "label" ) || "", 10184 disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" ) 10185 }; 10186 }, 10187 10188 _destroy: function() { 10189 this._unbindFormResetHandler(); 10190 this.menuWrap.remove(); 10191 this.button.remove(); 10192 this.element.show(); 10193 this.element.removeUniqueId(); 10194 this.labels.attr( "for", this.ids.element ); 10195 } 10196} ] ); 10197 10198 10199/*! 10200 * jQuery UI Slider 1.12.1 10201 * http://jqueryui.com 10202 * 10203 * Copyright jQuery Foundation and other contributors 10204 * Released under the MIT license. 10205 * http://jquery.org/license 10206 */ 10207 10208//>>label: Slider 10209//>>group: Widgets 10210//>>description: Displays a flexible slider with ranges and accessibility via keyboard. 10211//>>docs: http://api.jqueryui.com/slider/ 10212//>>demos: http://jqueryui.com/slider/ 10213//>>css.structure: ../../themes/base/core.css 10214//>>css.structure: ../../themes/base/slider.css 10215//>>css.theme: ../../themes/base/theme.css 10216 10217 10218 10219var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, { 10220 version: "1.12.1", 10221 widgetEventPrefix: "slide", 10222 10223 options: { 10224 animate: false, 10225 classes: { 10226 "ui-slider": "ui-corner-all", 10227 "ui-slider-handle": "ui-corner-all", 10228 10229 // Note: ui-widget-header isn't the most fittingly semantic framework class for this 10230 // element, but worked best visually with a variety of themes 10231 "ui-slider-range": "ui-corner-all ui-widget-header" 10232 }, 10233 distance: 0, 10234 max: 100, 10235 min: 0, 10236 orientation: "horizontal", 10237 range: false, 10238 step: 1, 10239 value: 0, 10240 values: null, 10241 10242 // Callbacks 10243 change: null, 10244 slide: null, 10245 start: null, 10246 stop: null 10247 }, 10248 10249 // Number of pages in a slider 10250 // (how many times can you page up/down to go through the whole range) 10251 numPages: 5, 10252 10253 _create: function() { 10254 this._keySliding = false; 10255 this._mouseSliding = false; 10256 this._animateOff = true; 10257 this._handleIndex = null; 10258 this._detectOrientation(); 10259 this._mouseInit(); 10260 this._calculateNewMax(); 10261 10262 this._addClass( "ui-slider ui-slider-" + this.orientation, 10263 "ui-widget ui-widget-content" ); 10264 10265 this._refresh(); 10266 10267 this._animateOff = false; 10268 }, 10269 10270 _refresh: function() { 10271 this._createRange(); 10272 this._createHandles(); 10273 this._setupEvents(); 10274 this._refreshValue(); 10275 }, 10276 10277 _createHandles: function() { 10278 var i, handleCount, 10279 options = this.options, 10280 existingHandles = this.element.find( ".ui-slider-handle" ), 10281 handle = "<span tabindex='0'></span>", 10282 handles = []; 10283 10284 handleCount = ( options.values && options.values.length ) || 1; 10285 10286 if ( existingHandles.length > handleCount ) { 10287 existingHandles.slice( handleCount ).remove(); 10288 existingHandles = existingHandles.slice( 0, handleCount ); 10289 } 10290 10291 for ( i = existingHandles.length; i < handleCount; i++ ) { 10292 handles.push( handle ); 10293 } 10294 10295 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) ); 10296 10297 this._addClass( this.handles, "ui-slider-handle", "ui-state-default" ); 10298 10299 this.handle = this.handles.eq( 0 ); 10300 10301 this.handles.each( function( i ) { 10302 $( this ) 10303 .data( "ui-slider-handle-index", i ) 10304 .attr( "tabIndex", 0 ); 10305 } ); 10306 }, 10307 10308 _createRange: function() { 10309 var options = this.options; 10310 10311 if ( options.range ) { 10312 if ( options.range === true ) { 10313 if ( !options.values ) { 10314 options.values = [ this._valueMin(), this._valueMin() ]; 10315 } else if ( options.values.length && options.values.length !== 2 ) { 10316 options.values = [ options.values[ 0 ], options.values[ 0 ] ]; 10317 } else if ( $.isArray( options.values ) ) { 10318 options.values = options.values.slice( 0 ); 10319 } 10320 } 10321 10322 if ( !this.range || !this.range.length ) { 10323 this.range = $( "<div>" ) 10324 .appendTo( this.element ); 10325 10326 this._addClass( this.range, "ui-slider-range" ); 10327 } else { 10328 this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" ); 10329 10330 // Handle range switching from true to min/max 10331 this.range.css( { 10332 "left": "", 10333 "bottom": "" 10334 } ); 10335 } 10336 if ( options.range === "min" || options.range === "max" ) { 10337 this._addClass( this.range, "ui-slider-range-" + options.range ); 10338 } 10339 } else { 10340 if ( this.range ) { 10341 this.range.remove(); 10342 } 10343 this.range = null; 10344 } 10345 }, 10346 10347 _setupEvents: function() { 10348 this._off( this.handles ); 10349 this._on( this.handles, this._handleEvents ); 10350 this._hoverable( this.handles ); 10351 this._focusable( this.handles ); 10352 }, 10353 10354 _destroy: function() { 10355 this.handles.remove(); 10356 if ( this.range ) { 10357 this.range.remove(); 10358 } 10359 10360 this._mouseDestroy(); 10361 }, 10362 10363 _mouseCapture: function( event ) { 10364 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, 10365 that = this, 10366 o = this.options; 10367 10368 if ( o.disabled ) { 10369 return false; 10370 } 10371 10372 this.elementSize = { 10373 width: this.element.outerWidth(), 10374 height: this.element.outerHeight() 10375 }; 10376 this.elementOffset = this.element.offset(); 10377 10378 position = { x: event.pageX, y: event.pageY }; 10379 normValue = this._normValueFromMouse( position ); 10380 distance = this._valueMax() - this._valueMin() + 1; 10381 this.handles.each( function( i ) { 10382 var thisDistance = Math.abs( normValue - that.values( i ) ); 10383 if ( ( distance > thisDistance ) || 10384 ( distance === thisDistance && 10385 ( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) { 10386 distance = thisDistance; 10387 closestHandle = $( this ); 10388 index = i; 10389 } 10390 } ); 10391 10392 allowed = this._start( event, index ); 10393 if ( allowed === false ) { 10394 return false; 10395 } 10396 this._mouseSliding = true; 10397 10398 this._handleIndex = index; 10399 10400 this._addClass( closestHandle, null, "ui-state-active" ); 10401 closestHandle.trigger( "focus" ); 10402 10403 offset = closestHandle.offset(); 10404 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" ); 10405 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { 10406 left: event.pageX - offset.left - ( closestHandle.width() / 2 ), 10407 top: event.pageY - offset.top - 10408 ( closestHandle.height() / 2 ) - 10409 ( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) - 10410 ( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) + 10411 ( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 ) 10412 }; 10413 10414 if ( !this.handles.hasClass( "ui-state-hover" ) ) { 10415 this._slide( event, index, normValue ); 10416 } 10417 this._animateOff = true; 10418 return true; 10419 }, 10420 10421 _mouseStart: function() { 10422 return true; 10423 }, 10424 10425 _mouseDrag: function( event ) { 10426 var position = { x: event.pageX, y: event.pageY }, 10427 normValue = this._normValueFromMouse( position ); 10428 10429 this._slide( event, this._handleIndex, normValue ); 10430 10431 return false; 10432 }, 10433 10434 _mouseStop: function( event ) { 10435 this._removeClass( this.handles, null, "ui-state-active" ); 10436 this._mouseSliding = false; 10437 10438 this._stop( event, this._handleIndex ); 10439 this._change( event, this._handleIndex ); 10440 10441 this._handleIndex = null; 10442 this._clickOffset = null; 10443 this._animateOff = false; 10444 10445 return false; 10446 }, 10447 10448 _detectOrientation: function() { 10449 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; 10450 }, 10451 10452 _normValueFromMouse: function( position ) { 10453 var pixelTotal, 10454 pixelMouse, 10455 percentMouse, 10456 valueTotal, 10457 valueMouse; 10458 10459 if ( this.orientation === "horizontal" ) { 10460 pixelTotal = this.elementSize.width; 10461 pixelMouse = position.x - this.elementOffset.left - 10462 ( this._clickOffset ? this._clickOffset.left : 0 ); 10463 } else { 10464 pixelTotal = this.elementSize.height; 10465 pixelMouse = position.y - this.elementOffset.top - 10466 ( this._clickOffset ? this._clickOffset.top : 0 ); 10467 } 10468 10469 percentMouse = ( pixelMouse / pixelTotal ); 10470 if ( percentMouse > 1 ) { 10471 percentMouse = 1; 10472 } 10473 if ( percentMouse < 0 ) { 10474 percentMouse = 0; 10475 } 10476 if ( this.orientation === "vertical" ) { 10477 percentMouse = 1 - percentMouse; 10478 } 10479 10480 valueTotal = this._valueMax() - this._valueMin(); 10481 valueMouse = this._valueMin() + percentMouse * valueTotal; 10482 10483 return this._trimAlignValue( valueMouse ); 10484 }, 10485 10486 _uiHash: function( index, value, values ) { 10487 var uiHash = { 10488 handle: this.handles[ index ], 10489 handleIndex: index, 10490 value: value !== undefined ? value : this.value() 10491 }; 10492 10493 if ( this._hasMultipleValues() ) { 10494 uiHash.value = value !== undefined ? value : this.values( index ); 10495 uiHash.values = values || this.values(); 10496 } 10497 10498 return uiHash; 10499 }, 10500 10501 _hasMultipleValues: function() { 10502 return this.options.values && this.options.values.length; 10503 }, 10504 10505 _start: function( event, index ) { 10506 return this._trigger( "start", event, this._uiHash( index ) ); 10507 }, 10508 10509 _slide: function( event, index, newVal ) { 10510 var allowed, otherVal, 10511 currentValue = this.value(), 10512 newValues = this.values(); 10513 10514 if ( this._hasMultipleValues() ) { 10515 otherVal = this.values( index ? 0 : 1 ); 10516 currentValue = this.values( index ); 10517 10518 if ( this.options.values.length === 2 && this.options.range === true ) { 10519 newVal = index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal ); 10520 } 10521 10522 newValues[ index ] = newVal; 10523 } 10524 10525 if ( newVal === currentValue ) { 10526 return; 10527 } 10528 10529 allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) ); 10530 10531 // A slide can be canceled by returning false from the slide callback 10532 if ( allowed === false ) { 10533 return; 10534 } 10535 10536 if ( this._hasMultipleValues() ) { 10537 this.values( index, newVal ); 10538 } else { 10539 this.value( newVal ); 10540 } 10541 }, 10542 10543 _stop: function( event, index ) { 10544 this._trigger( "stop", event, this._uiHash( index ) ); 10545 }, 10546 10547 _change: function( event, index ) { 10548 if ( !this._keySliding && !this._mouseSliding ) { 10549 10550 //store the last changed value index for reference when handles overlap 10551 this._lastChangedValue = index; 10552 this._trigger( "change", event, this._uiHash( index ) ); 10553 } 10554 }, 10555 10556 value: function( newValue ) { 10557 if ( arguments.length ) { 10558 this.options.value = this._trimAlignValue( newValue ); 10559 this._refreshValue(); 10560 this._change( null, 0 ); 10561 return; 10562 } 10563 10564 return this._value(); 10565 }, 10566 10567 values: function( index, newValue ) { 10568 var vals, 10569 newValues, 10570 i; 10571 10572 if ( arguments.length > 1 ) { 10573 this.options.values[ index ] = this._trimAlignValue( newValue ); 10574 this._refreshValue(); 10575 this._change( null, index ); 10576 return; 10577 } 10578 10579 if ( arguments.length ) { 10580 if ( $.isArray( arguments[ 0 ] ) ) { 10581 vals = this.options.values; 10582 newValues = arguments[ 0 ]; 10583 for ( i = 0; i < vals.length; i += 1 ) { 10584 vals[ i ] = this._trimAlignValue( newValues[ i ] ); 10585 this._change( null, i ); 10586 } 10587 this._refreshValue(); 10588 } else { 10589 if ( this._hasMultipleValues() ) { 10590 return this._values( index ); 10591 } else { 10592 return this.value(); 10593 } 10594 } 10595 } else { 10596 return this._values(); 10597 } 10598 }, 10599 10600 _setOption: function( key, value ) { 10601 var i, 10602 valsLength = 0; 10603 10604 if ( key === "range" && this.options.range === true ) { 10605 if ( value === "min" ) { 10606 this.options.value = this._values( 0 ); 10607 this.options.values = null; 10608 } else if ( value === "max" ) { 10609 this.options.value = this._values( this.options.values.length - 1 ); 10610 this.options.values = null; 10611 } 10612 } 10613 10614 if ( $.isArray( this.options.values ) ) { 10615 valsLength = this.options.values.length; 10616 } 10617 10618 this._super( key, value ); 10619 10620 switch ( key ) { 10621 case "orientation": 10622 this._detectOrientation(); 10623 this._removeClass( "ui-slider-horizontal ui-slider-vertical" ) 10624 ._addClass( "ui-slider-" + this.orientation ); 10625 this._refreshValue(); 10626 if ( this.options.range ) { 10627 this._refreshRange( value ); 10628 } 10629 10630 // Reset positioning from previous orientation 10631 this.handles.css( value === "horizontal" ? "bottom" : "left", "" ); 10632 break; 10633 case "value": 10634 this._animateOff = true; 10635 this._refreshValue(); 10636 this._change( null, 0 ); 10637 this._animateOff = false; 10638 break; 10639 case "values": 10640 this._animateOff = true; 10641 this._refreshValue(); 10642 10643 // Start from the last handle to prevent unreachable handles (#9046) 10644 for ( i = valsLength - 1; i >= 0; i-- ) { 10645 this._change( null, i ); 10646 } 10647 this._animateOff = false; 10648 break; 10649 case "step": 10650 case "min": 10651 case "max": 10652 this._animateOff = true; 10653 this._calculateNewMax(); 10654 this._refreshValue(); 10655 this._animateOff = false; 10656 break; 10657 case "range": 10658 this._animateOff = true; 10659 this._refresh(); 10660 this._animateOff = false; 10661 break; 10662 } 10663 }, 10664 10665 _setOptionDisabled: function( value ) { 10666 this._super( value ); 10667 10668 this._toggleClass( null, "ui-state-disabled", !!value ); 10669 }, 10670 10671 //internal value getter 10672 // _value() returns value trimmed by min and max, aligned by step 10673 _value: function() { 10674 var val = this.options.value; 10675 val = this._trimAlignValue( val ); 10676 10677 return val; 10678 }, 10679 10680 //internal values getter 10681 // _values() returns array of values trimmed by min and max, aligned by step 10682 // _values( index ) returns single value trimmed by min and max, aligned by step 10683 _values: function( index ) { 10684 var val, 10685 vals, 10686 i; 10687 10688 if ( arguments.length ) { 10689 val = this.options.values[ index ]; 10690 val = this._trimAlignValue( val ); 10691 10692 return val; 10693 } else if ( this._hasMultipleValues() ) { 10694 10695 // .slice() creates a copy of the array 10696 // this copy gets trimmed by min and max and then returned 10697 vals = this.options.values.slice(); 10698 for ( i = 0; i < vals.length; i += 1 ) { 10699 vals[ i ] = this._trimAlignValue( vals[ i ] ); 10700 } 10701 10702 return vals; 10703 } else { 10704 return []; 10705 } 10706 }, 10707 10708 // Returns the step-aligned value that val is closest to, between (inclusive) min and max 10709 _trimAlignValue: function( val ) { 10710 if ( val <= this._valueMin() ) { 10711 return this._valueMin(); 10712 } 10713 if ( val >= this._valueMax() ) { 10714 return this._valueMax(); 10715 } 10716 var step = ( this.options.step > 0 ) ? this.options.step : 1, 10717 valModStep = ( val - this._valueMin() ) % step, 10718 alignValue = val - valModStep; 10719 10720 if ( Math.abs( valModStep ) * 2 >= step ) { 10721 alignValue += ( valModStep > 0 ) ? step : ( -step ); 10722 } 10723 10724 // Since JavaScript has problems with large floats, round 10725 // the final value to 5 digits after the decimal point (see #4124) 10726 return parseFloat( alignValue.toFixed( 5 ) ); 10727 }, 10728 10729 _calculateNewMax: function() { 10730 var max = this.options.max, 10731 min = this._valueMin(), 10732 step = this.options.step, 10733 aboveMin = Math.round( ( max - min ) / step ) * step; 10734 max = aboveMin + min; 10735 if ( max > this.options.max ) { 10736 10737 //If max is not divisible by step, rounding off may increase its value 10738 max -= step; 10739 } 10740 this.max = parseFloat( max.toFixed( this._precision() ) ); 10741 }, 10742 10743 _precision: function() { 10744 var precision = this._precisionOf( this.options.step ); 10745 if ( this.options.min !== null ) { 10746 precision = Math.max( precision, this._precisionOf( this.options.min ) ); 10747 } 10748 return precision; 10749 }, 10750 10751 _precisionOf: function( num ) { 10752 var str = num.toString(), 10753 decimal = str.indexOf( "." ); 10754 return decimal === -1 ? 0 : str.length - decimal - 1; 10755 }, 10756 10757 _valueMin: function() { 10758 return this.options.min; 10759 }, 10760 10761 _valueMax: function() { 10762 return this.max; 10763 }, 10764 10765 _refreshRange: function( orientation ) { 10766 if ( orientation === "vertical" ) { 10767 this.range.css( { "width": "", "left": "" } ); 10768 } 10769 if ( orientation === "horizontal" ) { 10770 this.range.css( { "height": "", "bottom": "" } ); 10771 } 10772 }, 10773 10774 _refreshValue: function() { 10775 var lastValPercent, valPercent, value, valueMin, valueMax, 10776 oRange = this.options.range, 10777 o = this.options, 10778 that = this, 10779 animate = ( !this._animateOff ) ? o.animate : false, 10780 _set = {}; 10781 10782 if ( this._hasMultipleValues() ) { 10783 this.handles.each( function( i ) { 10784 valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() - 10785 that._valueMin() ) * 100; 10786 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 10787 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 10788 if ( that.options.range === true ) { 10789 if ( that.orientation === "horizontal" ) { 10790 if ( i === 0 ) { 10791 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 10792 left: valPercent + "%" 10793 }, o.animate ); 10794 } 10795 if ( i === 1 ) { 10796 that.range[ animate ? "animate" : "css" ]( { 10797 width: ( valPercent - lastValPercent ) + "%" 10798 }, { 10799 queue: false, 10800 duration: o.animate 10801 } ); 10802 } 10803 } else { 10804 if ( i === 0 ) { 10805 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 10806 bottom: ( valPercent ) + "%" 10807 }, o.animate ); 10808 } 10809 if ( i === 1 ) { 10810 that.range[ animate ? "animate" : "css" ]( { 10811 height: ( valPercent - lastValPercent ) + "%" 10812 }, { 10813 queue: false, 10814 duration: o.animate 10815 } ); 10816 } 10817 } 10818 } 10819 lastValPercent = valPercent; 10820 } ); 10821 } else { 10822 value = this.value(); 10823 valueMin = this._valueMin(); 10824 valueMax = this._valueMax(); 10825 valPercent = ( valueMax !== valueMin ) ? 10826 ( value - valueMin ) / ( valueMax - valueMin ) * 100 : 10827 0; 10828 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 10829 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 10830 10831 if ( oRange === "min" && this.orientation === "horizontal" ) { 10832 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 10833 width: valPercent + "%" 10834 }, o.animate ); 10835 } 10836 if ( oRange === "max" && this.orientation === "horizontal" ) { 10837 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 10838 width: ( 100 - valPercent ) + "%" 10839 }, o.animate ); 10840 } 10841 if ( oRange === "min" && this.orientation === "vertical" ) { 10842 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 10843 height: valPercent + "%" 10844 }, o.animate ); 10845 } 10846 if ( oRange === "max" && this.orientation === "vertical" ) { 10847 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { 10848 height: ( 100 - valPercent ) + "%" 10849 }, o.animate ); 10850 } 10851 } 10852 }, 10853 10854 _handleEvents: { 10855 keydown: function( event ) { 10856 var allowed, curVal, newVal, step, 10857 index = $( event.target ).data( "ui-slider-handle-index" ); 10858 10859 switch ( event.keyCode ) { 10860 case $.ui.keyCode.HOME: 10861 case $.ui.keyCode.END: 10862 case $.ui.keyCode.PAGE_UP: 10863 case $.ui.keyCode.PAGE_DOWN: 10864 case $.ui.keyCode.UP: 10865 case $.ui.keyCode.RIGHT: 10866 case $.ui.keyCode.DOWN: 10867 case $.ui.keyCode.LEFT: 10868 event.preventDefault(); 10869 if ( !this._keySliding ) { 10870 this._keySliding = true; 10871 this._addClass( $( event.target ), null, "ui-state-active" ); 10872 allowed = this._start( event, index ); 10873 if ( allowed === false ) { 10874 return; 10875 } 10876 } 10877 break; 10878 } 10879 10880 step = this.options.step; 10881 if ( this._hasMultipleValues() ) { 10882 curVal = newVal = this.values( index ); 10883 } else { 10884 curVal = newVal = this.value(); 10885 } 10886 10887 switch ( event.keyCode ) { 10888 case $.ui.keyCode.HOME: 10889 newVal = this._valueMin(); 10890 break; 10891 case $.ui.keyCode.END: 10892 newVal = this._valueMax(); 10893 break; 10894 case $.ui.keyCode.PAGE_UP: 10895 newVal = this._trimAlignValue( 10896 curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages ) 10897 ); 10898 break; 10899 case $.ui.keyCode.PAGE_DOWN: 10900 newVal = this._trimAlignValue( 10901 curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) ); 10902 break; 10903 case $.ui.keyCode.UP: 10904 case $.ui.keyCode.RIGHT: 10905 if ( curVal === this._valueMax() ) { 10906 return; 10907 } 10908 newVal = this._trimAlignValue( curVal + step ); 10909 break; 10910 case $.ui.keyCode.DOWN: 10911 case $.ui.keyCode.LEFT: 10912 if ( curVal === this._valueMin() ) { 10913 return; 10914 } 10915 newVal = this._trimAlignValue( curVal - step ); 10916 break; 10917 } 10918 10919 this._slide( event, index, newVal ); 10920 }, 10921 keyup: function( event ) { 10922 var index = $( event.target ).data( "ui-slider-handle-index" ); 10923 10924 if ( this._keySliding ) { 10925 this._keySliding = false; 10926 this._stop( event, index ); 10927 this._change( event, index ); 10928 this._removeClass( $( event.target ), null, "ui-state-active" ); 10929 } 10930 } 10931 } 10932} ); 10933 10934 10935/*! 10936 * jQuery UI Sortable 1.12.1 10937 * http://jqueryui.com 10938 * 10939 * Copyright jQuery Foundation and other contributors 10940 * Released under the MIT license. 10941 * http://jquery.org/license 10942 */ 10943 10944//>>label: Sortable 10945//>>group: Interactions 10946//>>description: Enables items in a list to be sorted using the mouse. 10947//>>docs: http://api.jqueryui.com/sortable/ 10948//>>demos: http://jqueryui.com/sortable/ 10949//>>css.structure: ../../themes/base/sortable.css 10950 10951 10952 10953var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, { 10954 version: "1.12.1", 10955 widgetEventPrefix: "sort", 10956 ready: false, 10957 options: { 10958 appendTo: "parent", 10959 axis: false, 10960 connectWith: false, 10961 containment: false, 10962 cursor: "auto", 10963 cursorAt: false, 10964 dropOnEmpty: true, 10965 forcePlaceholderSize: false, 10966 forceHelperSize: false, 10967 grid: false, 10968 handle: false, 10969 helper: "original", 10970 items: "> *", 10971 opacity: false, 10972 placeholder: false, 10973 revert: false, 10974 scroll: true, 10975 scrollSensitivity: 20, 10976 scrollSpeed: 20, 10977 scope: "default", 10978 tolerance: "intersect", 10979 zIndex: 1000, 10980 10981 // Callbacks 10982 activate: null, 10983 beforeStop: null, 10984 change: null, 10985 deactivate: null, 10986 out: null, 10987 over: null, 10988 receive: null, 10989 remove: null, 10990 sort: null, 10991 start: null, 10992 stop: null, 10993 update: null 10994 }, 10995 10996 _isOverAxis: function( x, reference, size ) { 10997 return ( x >= reference ) && ( x < ( reference + size ) ); 10998 }, 10999 11000 _isFloating: function( item ) { 11001 return ( /left|right/ ).test( item.css( "float" ) ) || 11002 ( /inline|table-cell/ ).test( item.css( "display" ) ); 11003 }, 11004 11005 _create: function() { 11006 this.containerCache = {}; 11007 this._addClass( "ui-sortable" ); 11008 11009 //Get the items 11010 this.refresh(); 11011 11012 //Let's determine the parent's offset 11013 this.offset = this.element.offset(); 11014 11015 //Initialize mouse events for interaction 11016 this._mouseInit(); 11017 11018 this._setHandleClassName(); 11019 11020 //We're ready to go 11021 this.ready = true; 11022 11023 }, 11024 11025 _setOption: function( key, value ) { 11026 this._super( key, value ); 11027 11028 if ( key === "handle" ) { 11029 this._setHandleClassName(); 11030 } 11031 }, 11032 11033 _setHandleClassName: function() { 11034 var that = this; 11035 this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" ); 11036 $.each( this.items, function() { 11037 that._addClass( 11038 this.instance.options.handle ? 11039 this.item.find( this.instance.options.handle ) : 11040 this.item, 11041 "ui-sortable-handle" 11042 ); 11043 } ); 11044 }, 11045 11046 _destroy: function() { 11047 this._mouseDestroy(); 11048 11049 for ( var i = this.items.length - 1; i >= 0; i-- ) { 11050 this.items[ i ].item.removeData( this.widgetName + "-item" ); 11051 } 11052 11053 return this; 11054 }, 11055 11056 _mouseCapture: function( event, overrideHandle ) { 11057 var currentItem = null, 11058 validHandle = false, 11059 that = this; 11060 11061 if ( this.reverting ) { 11062 return false; 11063 } 11064 11065 if ( this.options.disabled || this.options.type === "static" ) { 11066 return false; 11067 } 11068 11069 //We have to refresh the items data once first 11070 this._refreshItems( event ); 11071 11072 //Find out if the clicked node (or one of its parents) is a actual item in this.items 11073 $( event.target ).parents().each( function() { 11074 if ( $.data( this, that.widgetName + "-item" ) === that ) { 11075 currentItem = $( this ); 11076 return false; 11077 } 11078 } ); 11079 if ( $.data( event.target, that.widgetName + "-item" ) === that ) { 11080 currentItem = $( event.target ); 11081 } 11082 11083 if ( !currentItem ) { 11084 return false; 11085 } 11086 if ( this.options.handle && !overrideHandle ) { 11087 $( this.options.handle, currentItem ).find( "*" ).addBack().each( function() { 11088 if ( this === event.target ) { 11089 validHandle = true; 11090 } 11091 } ); 11092 if ( !validHandle ) { 11093 return false; 11094 } 11095 } 11096 11097 this.currentItem = currentItem; 11098 this._removeCurrentsFromItems(); 11099 return true; 11100 11101 }, 11102 11103 _mouseStart: function( event, overrideHandle, noActivation ) { 11104 11105 var i, body, 11106 o = this.options; 11107 11108 this.currentContainer = this; 11109 11110 //We only need to call refreshPositions, because the refreshItems call has been moved to 11111 // mouseCapture 11112 this.refreshPositions(); 11113 11114 //Create and append the visible helper 11115 this.helper = this._createHelper( event ); 11116 11117 //Cache the helper size 11118 this._cacheHelperProportions(); 11119 11120 /* 11121 * - Position generation - 11122 * This block generates everything position related - it's the core of draggables. 11123 */ 11124 11125 //Cache the margins of the original element 11126 this._cacheMargins(); 11127 11128 //Get the next scrolling parent 11129 this.scrollParent = this.helper.scrollParent(); 11130 11131 //The element's absolute position on the page minus margins 11132 this.offset = this.currentItem.offset(); 11133 this.offset = { 11134 top: this.offset.top - this.margins.top, 11135 left: this.offset.left - this.margins.left 11136 }; 11137 11138 $.extend( this.offset, { 11139 click: { //Where the click happened, relative to the element 11140 left: event.pageX - this.offset.left, 11141 top: event.pageY - this.offset.top 11142 }, 11143 parent: this._getParentOffset(), 11144 11145 // This is a relative to absolute position minus the actual position calculation - 11146 // only used for relative positioned helper 11147 relative: this._getRelativeOffset() 11148 } ); 11149 11150 // Only after we got the offset, we can change the helper's position to absolute 11151 // TODO: Still need to figure out a way to make relative sorting possible 11152 this.helper.css( "position", "absolute" ); 11153 this.cssPosition = this.helper.css( "position" ); 11154 11155 //Generate the original position 11156 this.originalPosition = this._generatePosition( event ); 11157 this.originalPageX = event.pageX; 11158 this.originalPageY = event.pageY; 11159 11160 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 11161 ( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) ); 11162 11163 //Cache the former DOM position 11164 this.domPosition = { 11165 prev: this.currentItem.prev()[ 0 ], 11166 parent: this.currentItem.parent()[ 0 ] 11167 }; 11168 11169 // If the helper is not the original, hide the original so it's not playing any role during 11170 // the drag, won't cause anything bad this way 11171 if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) { 11172 this.currentItem.hide(); 11173 } 11174 11175 //Create the placeholder 11176 this._createPlaceholder(); 11177 11178 //Set a containment if given in the options 11179 if ( o.containment ) { 11180 this._setContainment(); 11181 } 11182 11183 if ( o.cursor && o.cursor !== "auto" ) { // cursor option 11184 body = this.document.find( "body" ); 11185 11186 // Support: IE 11187 this.storedCursor = body.css( "cursor" ); 11188 body.css( "cursor", o.cursor ); 11189 11190 this.storedStylesheet = 11191 $( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body ); 11192 } 11193 11194 if ( o.opacity ) { // opacity option 11195 if ( this.helper.css( "opacity" ) ) { 11196 this._storedOpacity = this.helper.css( "opacity" ); 11197 } 11198 this.helper.css( "opacity", o.opacity ); 11199 } 11200 11201 if ( o.zIndex ) { // zIndex option 11202 if ( this.helper.css( "zIndex" ) ) { 11203 this._storedZIndex = this.helper.css( "zIndex" ); 11204 } 11205 this.helper.css( "zIndex", o.zIndex ); 11206 } 11207 11208 //Prepare scrolling 11209 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && 11210 this.scrollParent[ 0 ].tagName !== "HTML" ) { 11211 this.overflowOffset = this.scrollParent.offset(); 11212 } 11213 11214 //Call callbacks 11215 this._trigger( "start", event, this._uiHash() ); 11216 11217 //Recache the helper size 11218 if ( !this._preserveHelperProportions ) { 11219 this._cacheHelperProportions(); 11220 } 11221 11222 //Post "activate" events to possible containers 11223 if ( !noActivation ) { 11224 for ( i = this.containers.length - 1; i >= 0; i-- ) { 11225 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); 11226 } 11227 } 11228 11229 //Prepare possible droppables 11230 if ( $.ui.ddmanager ) { 11231 $.ui.ddmanager.current = this; 11232 } 11233 11234 if ( $.ui.ddmanager && !o.dropBehaviour ) { 11235 $.ui.ddmanager.prepareOffsets( this, event ); 11236 } 11237 11238 this.dragging = true; 11239 11240 this._addClass( this.helper, "ui-sortable-helper" ); 11241 11242 // Execute the drag once - this causes the helper not to be visiblebefore getting its 11243 // correct position 11244 this._mouseDrag( event ); 11245 return true; 11246 11247 }, 11248 11249 _mouseDrag: function( event ) { 11250 var i, item, itemElement, intersection, 11251 o = this.options, 11252 scrolled = false; 11253 11254 //Compute the helpers position 11255 this.position = this._generatePosition( event ); 11256 this.positionAbs = this._convertPositionTo( "absolute" ); 11257 11258 if ( !this.lastPositionAbs ) { 11259 this.lastPositionAbs = this.positionAbs; 11260 } 11261 11262 //Do scrolling 11263 if ( this.options.scroll ) { 11264 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] && 11265 this.scrollParent[ 0 ].tagName !== "HTML" ) { 11266 11267 if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) - 11268 event.pageY < o.scrollSensitivity ) { 11269 this.scrollParent[ 0 ].scrollTop = 11270 scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed; 11271 } else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) { 11272 this.scrollParent[ 0 ].scrollTop = 11273 scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed; 11274 } 11275 11276 if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) - 11277 event.pageX < o.scrollSensitivity ) { 11278 this.scrollParent[ 0 ].scrollLeft = scrolled = 11279 this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed; 11280 } else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) { 11281 this.scrollParent[ 0 ].scrollLeft = scrolled = 11282 this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed; 11283 } 11284 11285 } else { 11286 11287 if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) { 11288 scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed ); 11289 } else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) < 11290 o.scrollSensitivity ) { 11291 scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed ); 11292 } 11293 11294 if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) { 11295 scrolled = this.document.scrollLeft( 11296 this.document.scrollLeft() - o.scrollSpeed 11297 ); 11298 } else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) < 11299 o.scrollSensitivity ) { 11300 scrolled = this.document.scrollLeft( 11301 this.document.scrollLeft() + o.scrollSpeed 11302 ); 11303 } 11304 11305 } 11306 11307 if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) { 11308 $.ui.ddmanager.prepareOffsets( this, event ); 11309 } 11310 } 11311 11312 //Regenerate the absolute position used for position checks 11313 this.positionAbs = this._convertPositionTo( "absolute" ); 11314 11315 //Set the helper position 11316 if ( !this.options.axis || this.options.axis !== "y" ) { 11317 this.helper[ 0 ].style.left = this.position.left + "px"; 11318 } 11319 if ( !this.options.axis || this.options.axis !== "x" ) { 11320 this.helper[ 0 ].style.top = this.position.top + "px"; 11321 } 11322 11323 //Rearrange 11324 for ( i = this.items.length - 1; i >= 0; i-- ) { 11325 11326 //Cache variables and intersection, continue if no intersection 11327 item = this.items[ i ]; 11328 itemElement = item.item[ 0 ]; 11329 intersection = this._intersectsWithPointer( item ); 11330 if ( !intersection ) { 11331 continue; 11332 } 11333 11334 // Only put the placeholder inside the current Container, skip all 11335 // items from other containers. This works because when moving 11336 // an item from one container to another the 11337 // currentContainer is switched before the placeholder is moved. 11338 // 11339 // Without this, moving items in "sub-sortables" can cause 11340 // the placeholder to jitter between the outer and inner container. 11341 if ( item.instance !== this.currentContainer ) { 11342 continue; 11343 } 11344 11345 // Cannot intersect with itself 11346 // no useless actions that have been done before 11347 // no action if the item moved is the parent of the item checked 11348 if ( itemElement !== this.currentItem[ 0 ] && 11349 this.placeholder[ intersection === 1 ? "next" : "prev" ]()[ 0 ] !== itemElement && 11350 !$.contains( this.placeholder[ 0 ], itemElement ) && 11351 ( this.options.type === "semi-dynamic" ? 11352 !$.contains( this.element[ 0 ], itemElement ) : 11353 true 11354 ) 11355 ) { 11356 11357 this.direction = intersection === 1 ? "down" : "up"; 11358 11359 if ( this.options.tolerance === "pointer" || this._intersectsWithSides( item ) ) { 11360 this._rearrange( event, item ); 11361 } else { 11362 break; 11363 } 11364 11365 this._trigger( "change", event, this._uiHash() ); 11366 break; 11367 } 11368 } 11369 11370 //Post events to containers 11371 this._contactContainers( event ); 11372 11373 //Interconnect with droppables 11374 if ( $.ui.ddmanager ) { 11375 $.ui.ddmanager.drag( this, event ); 11376 } 11377 11378 //Call callbacks 11379 this._trigger( "sort", event, this._uiHash() ); 11380 11381 this.lastPositionAbs = this.positionAbs; 11382 return false; 11383 11384 }, 11385 11386 _mouseStop: function( event, noPropagation ) { 11387 11388 if ( !event ) { 11389 return; 11390 } 11391 11392 //If we are using droppables, inform the manager about the drop 11393 if ( $.ui.ddmanager && !this.options.dropBehaviour ) { 11394 $.ui.ddmanager.drop( this, event ); 11395 } 11396 11397 if ( this.options.revert ) { 11398 var that = this, 11399 cur = this.placeholder.offset(), 11400 axis = this.options.axis, 11401 animation = {}; 11402 11403 if ( !axis || axis === "x" ) { 11404 animation.left = cur.left - this.offset.parent.left - this.margins.left + 11405 ( this.offsetParent[ 0 ] === this.document[ 0 ].body ? 11406 0 : 11407 this.offsetParent[ 0 ].scrollLeft 11408 ); 11409 } 11410 if ( !axis || axis === "y" ) { 11411 animation.top = cur.top - this.offset.parent.top - this.margins.top + 11412 ( this.offsetParent[ 0 ] === this.document[ 0 ].body ? 11413 0 : 11414 this.offsetParent[ 0 ].scrollTop 11415 ); 11416 } 11417 this.reverting = true; 11418 $( this.helper ).animate( 11419 animation, 11420 parseInt( this.options.revert, 10 ) || 500, 11421 function() { 11422 that._clear( event ); 11423 } 11424 ); 11425 } else { 11426 this._clear( event, noPropagation ); 11427 } 11428 11429 return false; 11430 11431 }, 11432 11433 cancel: function() { 11434 11435 if ( this.dragging ) { 11436 11437 this._mouseUp( new $.Event( "mouseup", { target: null } ) ); 11438 11439 if ( this.options.helper === "original" ) { 11440 this.currentItem.css( this._storedCSS ); 11441 this._removeClass( this.currentItem, "ui-sortable-helper" ); 11442 } else { 11443 this.currentItem.show(); 11444 } 11445 11446 //Post deactivating events to containers 11447 for ( var i = this.containers.length - 1; i >= 0; i-- ) { 11448 this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) ); 11449 if ( this.containers[ i ].containerCache.over ) { 11450 this.containers[ i ]._trigger( "out", null, this._uiHash( this ) ); 11451 this.containers[ i ].containerCache.over = 0; 11452 } 11453 } 11454 11455 } 11456 11457 if ( this.placeholder ) { 11458 11459 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, 11460 // it unbinds ALL events from the original node! 11461 if ( this.placeholder[ 0 ].parentNode ) { 11462 this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] ); 11463 } 11464 if ( this.options.helper !== "original" && this.helper && 11465 this.helper[ 0 ].parentNode ) { 11466 this.helper.remove(); 11467 } 11468 11469 $.extend( this, { 11470 helper: null, 11471 dragging: false, 11472 reverting: false, 11473 _noFinalSort: null 11474 } ); 11475 11476 if ( this.domPosition.prev ) { 11477 $( this.domPosition.prev ).after( this.currentItem ); 11478 } else { 11479 $( this.domPosition.parent ).prepend( this.currentItem ); 11480 } 11481 } 11482 11483 return this; 11484 11485 }, 11486 11487 serialize: function( o ) { 11488 11489 var items = this._getItemsAsjQuery( o && o.connected ), 11490 str = []; 11491 o = o || {}; 11492 11493 $( items ).each( function() { 11494 var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" ) 11495 .match( o.expression || ( /(.+)[\-=_](.+)/ ) ); 11496 if ( res ) { 11497 str.push( 11498 ( o.key || res[ 1 ] + "[]" ) + 11499 "=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) ); 11500 } 11501 } ); 11502 11503 if ( !str.length && o.key ) { 11504 str.push( o.key + "=" ); 11505 } 11506 11507 return str.join( "&" ); 11508 11509 }, 11510 11511 toArray: function( o ) { 11512 11513 var items = this._getItemsAsjQuery( o && o.connected ), 11514 ret = []; 11515 11516 o = o || {}; 11517 11518 items.each( function() { 11519 ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" ); 11520 } ); 11521 return ret; 11522 11523 }, 11524 11525 /* Be careful with the following core functions */ 11526 _intersectsWith: function( item ) { 11527 11528 var x1 = this.positionAbs.left, 11529 x2 = x1 + this.helperProportions.width, 11530 y1 = this.positionAbs.top, 11531 y2 = y1 + this.helperProportions.height, 11532 l = item.left, 11533 r = l + item.width, 11534 t = item.top, 11535 b = t + item.height, 11536 dyClick = this.offset.click.top, 11537 dxClick = this.offset.click.left, 11538 isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && 11539 ( y1 + dyClick ) < b ), 11540 isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && 11541 ( x1 + dxClick ) < r ), 11542 isOverElement = isOverElementHeight && isOverElementWidth; 11543 11544 if ( this.options.tolerance === "pointer" || 11545 this.options.forcePointerForContainers || 11546 ( this.options.tolerance !== "pointer" && 11547 this.helperProportions[ this.floating ? "width" : "height" ] > 11548 item[ this.floating ? "width" : "height" ] ) 11549 ) { 11550 return isOverElement; 11551 } else { 11552 11553 return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half 11554 x2 - ( this.helperProportions.width / 2 ) < r && // Left Half 11555 t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half 11556 y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half 11557 11558 } 11559 }, 11560 11561 _intersectsWithPointer: function( item ) { 11562 var verticalDirection, horizontalDirection, 11563 isOverElementHeight = ( this.options.axis === "x" ) || 11564 this._isOverAxis( 11565 this.positionAbs.top + this.offset.click.top, item.top, item.height ), 11566 isOverElementWidth = ( this.options.axis === "y" ) || 11567 this._isOverAxis( 11568 this.positionAbs.left + this.offset.click.left, item.left, item.width ), 11569 isOverElement = isOverElementHeight && isOverElementWidth; 11570 11571 if ( !isOverElement ) { 11572 return false; 11573 } 11574 11575 verticalDirection = this._getDragVerticalDirection(); 11576 horizontalDirection = this._getDragHorizontalDirection(); 11577 11578 return this.floating ? 11579 ( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) 11580 : ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) ); 11581 11582 }, 11583 11584 _intersectsWithSides: function( item ) { 11585 11586 var isOverBottomHalf = this._isOverAxis( this.positionAbs.top + 11587 this.offset.click.top, item.top + ( item.height / 2 ), item.height ), 11588 isOverRightHalf = this._isOverAxis( this.positionAbs.left + 11589 this.offset.click.left, item.left + ( item.width / 2 ), item.width ), 11590 verticalDirection = this._getDragVerticalDirection(), 11591 horizontalDirection = this._getDragHorizontalDirection(); 11592 11593 if ( this.floating && horizontalDirection ) { 11594 return ( ( horizontalDirection === "right" && isOverRightHalf ) || 11595 ( horizontalDirection === "left" && !isOverRightHalf ) ); 11596 } else { 11597 return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) || 11598 ( verticalDirection === "up" && !isOverBottomHalf ) ); 11599 } 11600 11601 }, 11602 11603 _getDragVerticalDirection: function() { 11604 var delta = this.positionAbs.top - this.lastPositionAbs.top; 11605 return delta !== 0 && ( delta > 0 ? "down" : "up" ); 11606 }, 11607 11608 _getDragHorizontalDirection: function() { 11609 var delta = this.positionAbs.left - this.lastPositionAbs.left; 11610 return delta !== 0 && ( delta > 0 ? "right" : "left" ); 11611 }, 11612 11613 refresh: function( event ) { 11614 this._refreshItems( event ); 11615 this._setHandleClassName(); 11616 this.refreshPositions(); 11617 return this; 11618 }, 11619 11620 _connectWith: function() { 11621 var options = this.options; 11622 return options.connectWith.constructor === String ? 11623 [ options.connectWith ] : 11624 options.connectWith; 11625 }, 11626 11627 _getItemsAsjQuery: function( connected ) { 11628 11629 var i, j, cur, inst, 11630 items = [], 11631 queries = [], 11632 connectWith = this._connectWith(); 11633 11634 if ( connectWith && connected ) { 11635 for ( i = connectWith.length - 1; i >= 0; i-- ) { 11636 cur = $( connectWith[ i ], this.document[ 0 ] ); 11637 for ( j = cur.length - 1; j >= 0; j-- ) { 11638 inst = $.data( cur[ j ], this.widgetFullName ); 11639 if ( inst && inst !== this && !inst.options.disabled ) { 11640 queries.push( [ $.isFunction( inst.options.items ) ? 11641 inst.options.items.call( inst.element ) : 11642 $( inst.options.items, inst.element ) 11643 .not( ".ui-sortable-helper" ) 11644 .not( ".ui-sortable-placeholder" ), inst ] ); 11645 } 11646 } 11647 } 11648 } 11649 11650 queries.push( [ $.isFunction( this.options.items ) ? 11651 this.options.items 11652 .call( this.element, null, { options: this.options, item: this.currentItem } ) : 11653 $( this.options.items, this.element ) 11654 .not( ".ui-sortable-helper" ) 11655 .not( ".ui-sortable-placeholder" ), this ] ); 11656 11657 function addItems() { 11658 items.push( this ); 11659 } 11660 for ( i = queries.length - 1; i >= 0; i-- ) { 11661 queries[ i ][ 0 ].each( addItems ); 11662 } 11663 11664 return $( items ); 11665 11666 }, 11667 11668 _removeCurrentsFromItems: function() { 11669 11670 var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" ); 11671 11672 this.items = $.grep( this.items, function( item ) { 11673 for ( var j = 0; j < list.length; j++ ) { 11674 if ( list[ j ] === item.item[ 0 ] ) { 11675 return false; 11676 } 11677 } 11678 return true; 11679 } ); 11680 11681 }, 11682 11683 _refreshItems: function( event ) { 11684 11685 this.items = []; 11686 this.containers = [ this ]; 11687 11688 var i, j, cur, inst, targetData, _queries, item, queriesLength, 11689 items = this.items, 11690 queries = [ [ $.isFunction( this.options.items ) ? 11691 this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) : 11692 $( this.options.items, this.element ), this ] ], 11693 connectWith = this._connectWith(); 11694 11695 //Shouldn't be run the first time through due to massive slow-down 11696 if ( connectWith && this.ready ) { 11697 for ( i = connectWith.length - 1; i >= 0; i-- ) { 11698 cur = $( connectWith[ i ], this.document[ 0 ] ); 11699 for ( j = cur.length - 1; j >= 0; j-- ) { 11700 inst = $.data( cur[ j ], this.widgetFullName ); 11701 if ( inst && inst !== this && !inst.options.disabled ) { 11702 queries.push( [ $.isFunction( inst.options.items ) ? 11703 inst.options.items 11704 .call( inst.element[ 0 ], event, { item: this.currentItem } ) : 11705 $( inst.options.items, inst.element ), inst ] ); 11706 this.containers.push( inst ); 11707 } 11708 } 11709 } 11710 } 11711 11712 for ( i = queries.length - 1; i >= 0; i-- ) { 11713 targetData = queries[ i ][ 1 ]; 11714 _queries = queries[ i ][ 0 ]; 11715 11716 for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) { 11717 item = $( _queries[ j ] ); 11718 11719 // Data for target checking (mouse manager) 11720 item.data( this.widgetName + "-item", targetData ); 11721 11722 items.push( { 11723 item: item, 11724 instance: targetData, 11725 width: 0, height: 0, 11726 left: 0, top: 0 11727 } ); 11728 } 11729 } 11730 11731 }, 11732 11733 refreshPositions: function( fast ) { 11734 11735 // Determine whether items are being displayed horizontally 11736 this.floating = this.items.length ? 11737 this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) : 11738 false; 11739 11740 //This has to be redone because due to the item being moved out/into the offsetParent, 11741 // the offsetParent's position will change 11742 if ( this.offsetParent && this.helper ) { 11743 this.offset.parent = this._getParentOffset(); 11744 } 11745 11746 var i, item, t, p; 11747 11748 for ( i = this.items.length - 1; i >= 0; i-- ) { 11749 item = this.items[ i ]; 11750 11751 //We ignore calculating positions of all connected containers when we're not over them 11752 if ( item.instance !== this.currentContainer && this.currentContainer && 11753 item.item[ 0 ] !== this.currentItem[ 0 ] ) { 11754 continue; 11755 } 11756 11757 t = this.options.toleranceElement ? 11758 $( this.options.toleranceElement, item.item ) : 11759 item.item; 11760 11761 if ( !fast ) { 11762 item.width = t.outerWidth(); 11763 item.height = t.outerHeight(); 11764 } 11765 11766 p = t.offset(); 11767 item.left = p.left; 11768 item.top = p.top; 11769 } 11770 11771 if ( this.options.custom && this.options.custom.refreshContainers ) { 11772 this.options.custom.refreshContainers.call( this ); 11773 } else { 11774 for ( i = this.containers.length - 1; i >= 0; i-- ) { 11775 p = this.containers[ i ].element.offset(); 11776 this.containers[ i ].containerCache.left = p.left; 11777 this.containers[ i ].containerCache.top = p.top; 11778 this.containers[ i ].containerCache.width = 11779 this.containers[ i ].element.outerWidth(); 11780 this.containers[ i ].containerCache.height = 11781 this.containers[ i ].element.outerHeight(); 11782 } 11783 } 11784 11785 return this; 11786 }, 11787 11788 _createPlaceholder: function( that ) { 11789 that = that || this; 11790 var className, 11791 o = that.options; 11792 11793 if ( !o.placeholder || o.placeholder.constructor === String ) { 11794 className = o.placeholder; 11795 o.placeholder = { 11796 element: function() { 11797 11798 var nodeName = that.currentItem[ 0 ].nodeName.toLowerCase(), 11799 element = $( "<" + nodeName + ">", that.document[ 0 ] ); 11800 11801 that._addClass( element, "ui-sortable-placeholder", 11802 className || that.currentItem[ 0 ].className ) 11803 ._removeClass( element, "ui-sortable-helper" ); 11804 11805 if ( nodeName === "tbody" ) { 11806 that._createTrPlaceholder( 11807 that.currentItem.find( "tr" ).eq( 0 ), 11808 $( "<tr>", that.document[ 0 ] ).appendTo( element ) 11809 ); 11810 } else if ( nodeName === "tr" ) { 11811 that._createTrPlaceholder( that.currentItem, element ); 11812 } else if ( nodeName === "img" ) { 11813 element.attr( "src", that.currentItem.attr( "src" ) ); 11814 } 11815 11816 if ( !className ) { 11817 element.css( "visibility", "hidden" ); 11818 } 11819 11820 return element; 11821 }, 11822 update: function( container, p ) { 11823 11824 // 1. If a className is set as 'placeholder option, we don't force sizes - 11825 // the class is responsible for that 11826 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a 11827 // class name is specified 11828 if ( className && !o.forcePlaceholderSize ) { 11829 return; 11830 } 11831 11832 //If the element doesn't have a actual height by itself (without styles coming 11833 // from a stylesheet), it receives the inline height from the dragged item 11834 if ( !p.height() ) { 11835 p.height( 11836 that.currentItem.innerHeight() - 11837 parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) - 11838 parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) ); 11839 } 11840 if ( !p.width() ) { 11841 p.width( 11842 that.currentItem.innerWidth() - 11843 parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) - 11844 parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) ); 11845 } 11846 } 11847 }; 11848 } 11849 11850 //Create the placeholder 11851 that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) ); 11852 11853 //Append it after the actual current item 11854 that.currentItem.after( that.placeholder ); 11855 11856 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) 11857 o.placeholder.update( that, that.placeholder ); 11858 11859 }, 11860 11861 _createTrPlaceholder: function( sourceTr, targetTr ) { 11862 var that = this; 11863 11864 sourceTr.children().each( function() { 11865 $( "<td> </td>", that.document[ 0 ] ) 11866 .attr( "colspan", $( this ).attr( "colspan" ) || 1 ) 11867 .appendTo( targetTr ); 11868 } ); 11869 }, 11870 11871 _contactContainers: function( event ) { 11872 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, 11873 floating, axis, 11874 innermostContainer = null, 11875 innermostIndex = null; 11876 11877 // Get innermost container that intersects with item 11878 for ( i = this.containers.length - 1; i >= 0; i-- ) { 11879 11880 // Never consider a container that's located within the item itself 11881 if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) { 11882 continue; 11883 } 11884 11885 if ( this._intersectsWith( this.containers[ i ].containerCache ) ) { 11886 11887 // If we've already found a container and it's more "inner" than this, then continue 11888 if ( innermostContainer && 11889 $.contains( 11890 this.containers[ i ].element[ 0 ], 11891 innermostContainer.element[ 0 ] ) ) { 11892 continue; 11893 } 11894 11895 innermostContainer = this.containers[ i ]; 11896 innermostIndex = i; 11897 11898 } else { 11899 11900 // container doesn't intersect. trigger "out" event if necessary 11901 if ( this.containers[ i ].containerCache.over ) { 11902 this.containers[ i ]._trigger( "out", event, this._uiHash( this ) ); 11903 this.containers[ i ].containerCache.over = 0; 11904 } 11905 } 11906 11907 } 11908 11909 // If no intersecting containers found, return 11910 if ( !innermostContainer ) { 11911 return; 11912 } 11913 11914 // Move the item into the container if it's not there already 11915 if ( this.containers.length === 1 ) { 11916 if ( !this.containers[ innermostIndex ].containerCache.over ) { 11917 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) ); 11918 this.containers[ innermostIndex ].containerCache.over = 1; 11919 } 11920 } else { 11921 11922 // When entering a new container, we will find the item with the least distance and 11923 // append our item near it 11924 dist = 10000; 11925 itemWithLeastDistance = null; 11926 floating = innermostContainer.floating || this._isFloating( this.currentItem ); 11927 posProperty = floating ? "left" : "top"; 11928 sizeProperty = floating ? "width" : "height"; 11929 axis = floating ? "pageX" : "pageY"; 11930 11931 for ( j = this.items.length - 1; j >= 0; j-- ) { 11932 if ( !$.contains( 11933 this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] ) 11934 ) { 11935 continue; 11936 } 11937 if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) { 11938 continue; 11939 } 11940 11941 cur = this.items[ j ].item.offset()[ posProperty ]; 11942 nearBottom = false; 11943 if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) { 11944 nearBottom = true; 11945 } 11946 11947 if ( Math.abs( event[ axis ] - cur ) < dist ) { 11948 dist = Math.abs( event[ axis ] - cur ); 11949 itemWithLeastDistance = this.items[ j ]; 11950 this.direction = nearBottom ? "up" : "down"; 11951 } 11952 } 11953 11954 //Check if dropOnEmpty is enabled 11955 if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) { 11956 return; 11957 } 11958 11959 if ( this.currentContainer === this.containers[ innermostIndex ] ) { 11960 if ( !this.currentContainer.containerCache.over ) { 11961 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() ); 11962 this.currentContainer.containerCache.over = 1; 11963 } 11964 return; 11965 } 11966 11967 itemWithLeastDistance ? 11968 this._rearrange( event, itemWithLeastDistance, null, true ) : 11969 this._rearrange( event, null, this.containers[ innermostIndex ].element, true ); 11970 this._trigger( "change", event, this._uiHash() ); 11971 this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) ); 11972 this.currentContainer = this.containers[ innermostIndex ]; 11973 11974 //Update the placeholder 11975 this.options.placeholder.update( this.currentContainer, this.placeholder ); 11976 11977 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) ); 11978 this.containers[ innermostIndex ].containerCache.over = 1; 11979 } 11980 11981 }, 11982 11983 _createHelper: function( event ) { 11984 11985 var o = this.options, 11986 helper = $.isFunction( o.helper ) ? 11987 $( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) : 11988 ( o.helper === "clone" ? this.currentItem.clone() : this.currentItem ); 11989 11990 //Add the helper to the DOM if that didn't happen already 11991 if ( !helper.parents( "body" ).length ) { 11992 $( o.appendTo !== "parent" ? 11993 o.appendTo : 11994 this.currentItem[ 0 ].parentNode )[ 0 ].appendChild( helper[ 0 ] ); 11995 } 11996 11997 if ( helper[ 0 ] === this.currentItem[ 0 ] ) { 11998 this._storedCSS = { 11999 width: this.currentItem[ 0 ].style.width, 12000 height: this.currentItem[ 0 ].style.height, 12001 position: this.currentItem.css( "position" ), 12002 top: this.currentItem.css( "top" ), 12003 left: this.currentItem.css( "left" ) 12004 }; 12005 } 12006 12007 if ( !helper[ 0 ].style.width || o.forceHelperSize ) { 12008 helper.width( this.currentItem.width() ); 12009 } 12010 if ( !helper[ 0 ].style.height || o.forceHelperSize ) { 12011 helper.height( this.currentItem.height() ); 12012 } 12013 12014 return helper; 12015 12016 }, 12017 12018 _adjustOffsetFromHelper: function( obj ) { 12019 if ( typeof obj === "string" ) { 12020 obj = obj.split( " " ); 12021 } 12022 if ( $.isArray( obj ) ) { 12023 obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 }; 12024 } 12025 if ( "left" in obj ) { 12026 this.offset.click.left = obj.left + this.margins.left; 12027 } 12028 if ( "right" in obj ) { 12029 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 12030 } 12031 if ( "top" in obj ) { 12032 this.offset.click.top = obj.top + this.margins.top; 12033 } 12034 if ( "bottom" in obj ) { 12035 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 12036 } 12037 }, 12038 12039 _getParentOffset: function() { 12040 12041 //Get the offsetParent and cache its position 12042 this.offsetParent = this.helper.offsetParent(); 12043 var po = this.offsetParent.offset(); 12044 12045 // This is a special case where we need to modify a offset calculated on start, since the 12046 // following happened: 12047 // 1. The position of the helper is absolute, so it's position is calculated based on the 12048 // next positioned parent 12049 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't 12050 // the document, which means that the scroll is included in the initial calculation of the 12051 // offset of the parent, and never recalculated upon drag 12052 if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] && 12053 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) { 12054 po.left += this.scrollParent.scrollLeft(); 12055 po.top += this.scrollParent.scrollTop(); 12056 } 12057 12058 // This needs to be actually done for all browsers, since pageX/pageY includes this 12059 // information with an ugly IE fix 12060 if ( this.offsetParent[ 0 ] === this.document[ 0 ].body || 12061 ( this.offsetParent[ 0 ].tagName && 12062 this.offsetParent[ 0 ].tagName.toLowerCase() === "html" && $.ui.ie ) ) { 12063 po = { top: 0, left: 0 }; 12064 } 12065 12066 return { 12067 top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ), 12068 left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 ) 12069 }; 12070 12071 }, 12072 12073 _getRelativeOffset: function() { 12074 12075 if ( this.cssPosition === "relative" ) { 12076 var p = this.currentItem.position(); 12077 return { 12078 top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) + 12079 this.scrollParent.scrollTop(), 12080 left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) + 12081 this.scrollParent.scrollLeft() 12082 }; 12083 } else { 12084 return { top: 0, left: 0 }; 12085 } 12086 12087 }, 12088 12089 _cacheMargins: function() { 12090 this.margins = { 12091 left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ), 12092 top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 ) 12093 }; 12094 }, 12095 12096 _cacheHelperProportions: function() { 12097 this.helperProportions = { 12098 width: this.helper.outerWidth(), 12099 height: this.helper.outerHeight() 12100 }; 12101 }, 12102 12103 _setContainment: function() { 12104 12105 var ce, co, over, 12106 o = this.options; 12107 if ( o.containment === "parent" ) { 12108 o.containment = this.helper[ 0 ].parentNode; 12109 } 12110 if ( o.containment === "document" || o.containment === "window" ) { 12111 this.containment = [ 12112 0 - this.offset.relative.left - this.offset.parent.left, 12113 0 - this.offset.relative.top - this.offset.parent.top, 12114 o.containment === "document" ? 12115 this.document.width() : 12116 this.window.width() - this.helperProportions.width - this.margins.left, 12117 ( o.containment === "document" ? 12118 ( this.document.height() || document.body.parentNode.scrollHeight ) : 12119 this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight 12120 ) - this.helperProportions.height - this.margins.top 12121 ]; 12122 } 12123 12124 if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) { 12125 ce = $( o.containment )[ 0 ]; 12126 co = $( o.containment ).offset(); 12127 over = ( $( ce ).css( "overflow" ) !== "hidden" ); 12128 12129 this.containment = [ 12130 co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) + 12131 ( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left, 12132 co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) + 12133 ( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top, 12134 co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - 12135 ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) - 12136 ( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) - 12137 this.helperProportions.width - this.margins.left, 12138 co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - 12139 ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) - 12140 ( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) - 12141 this.helperProportions.height - this.margins.top 12142 ]; 12143 } 12144 12145 }, 12146 12147 _convertPositionTo: function( d, pos ) { 12148 12149 if ( !pos ) { 12150 pos = this.position; 12151 } 12152 var mod = d === "absolute" ? 1 : -1, 12153 scroll = this.cssPosition === "absolute" && 12154 !( this.scrollParent[ 0 ] !== this.document[ 0 ] && 12155 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? 12156 this.offsetParent : 12157 this.scrollParent, 12158 scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName ); 12159 12160 return { 12161 top: ( 12162 12163 // The absolute mouse position 12164 pos.top + 12165 12166 // Only for relative positioned nodes: Relative offset from element to offset parent 12167 this.offset.relative.top * mod + 12168 12169 // The offsetParent's offset without borders (offset + border) 12170 this.offset.parent.top * mod - 12171 ( ( this.cssPosition === "fixed" ? 12172 -this.scrollParent.scrollTop() : 12173 ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod ) 12174 ), 12175 left: ( 12176 12177 // The absolute mouse position 12178 pos.left + 12179 12180 // Only for relative positioned nodes: Relative offset from element to offset parent 12181 this.offset.relative.left * mod + 12182 12183 // The offsetParent's offset without borders (offset + border) 12184 this.offset.parent.left * mod - 12185 ( ( this.cssPosition === "fixed" ? 12186 -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : 12187 scroll.scrollLeft() ) * mod ) 12188 ) 12189 }; 12190 12191 }, 12192 12193 _generatePosition: function( event ) { 12194 12195 var top, left, 12196 o = this.options, 12197 pageX = event.pageX, 12198 pageY = event.pageY, 12199 scroll = this.cssPosition === "absolute" && 12200 !( this.scrollParent[ 0 ] !== this.document[ 0 ] && 12201 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? 12202 this.offsetParent : 12203 this.scrollParent, 12204 scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName ); 12205 12206 // This is another very weird special case that only happens for relative elements: 12207 // 1. If the css position is relative 12208 // 2. and the scroll parent is the document or similar to the offset parent 12209 // we have to refresh the relative offset during the scroll so there are no jumps 12210 if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] && 12211 this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) { 12212 this.offset.relative = this._getRelativeOffset(); 12213 } 12214 12215 /* 12216 * - Position constraining - 12217 * Constrain the position to a mix of grid, containment. 12218 */ 12219 12220 if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options 12221 12222 if ( this.containment ) { 12223 if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) { 12224 pageX = this.containment[ 0 ] + this.offset.click.left; 12225 } 12226 if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) { 12227 pageY = this.containment[ 1 ] + this.offset.click.top; 12228 } 12229 if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) { 12230 pageX = this.containment[ 2 ] + this.offset.click.left; 12231 } 12232 if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) { 12233 pageY = this.containment[ 3 ] + this.offset.click.top; 12234 } 12235 } 12236 12237 if ( o.grid ) { 12238 top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) / 12239 o.grid[ 1 ] ) * o.grid[ 1 ]; 12240 pageY = this.containment ? 12241 ( ( top - this.offset.click.top >= this.containment[ 1 ] && 12242 top - this.offset.click.top <= this.containment[ 3 ] ) ? 12243 top : 12244 ( ( top - this.offset.click.top >= this.containment[ 1 ] ) ? 12245 top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : 12246 top; 12247 12248 left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) / 12249 o.grid[ 0 ] ) * o.grid[ 0 ]; 12250 pageX = this.containment ? 12251 ( ( left - this.offset.click.left >= this.containment[ 0 ] && 12252 left - this.offset.click.left <= this.containment[ 2 ] ) ? 12253 left : 12254 ( ( left - this.offset.click.left >= this.containment[ 0 ] ) ? 12255 left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : 12256 left; 12257 } 12258 12259 } 12260 12261 return { 12262 top: ( 12263 12264 // The absolute mouse position 12265 pageY - 12266 12267 // Click offset (relative to the element) 12268 this.offset.click.top - 12269 12270 // Only for relative positioned nodes: Relative offset from element to offset parent 12271 this.offset.relative.top - 12272 12273 // The offsetParent's offset without borders (offset + border) 12274 this.offset.parent.top + 12275 ( ( this.cssPosition === "fixed" ? 12276 -this.scrollParent.scrollTop() : 12277 ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) ) 12278 ), 12279 left: ( 12280 12281 // The absolute mouse position 12282 pageX - 12283 12284 // Click offset (relative to the element) 12285 this.offset.click.left - 12286 12287 // Only for relative positioned nodes: Relative offset from element to offset parent 12288 this.offset.relative.left - 12289 12290 // The offsetParent's offset without borders (offset + border) 12291 this.offset.parent.left + 12292 ( ( this.cssPosition === "fixed" ? 12293 -this.scrollParent.scrollLeft() : 12294 scrollIsRootNode ? 0 : scroll.scrollLeft() ) ) 12295 ) 12296 }; 12297 12298 }, 12299 12300 _rearrange: function( event, i, a, hardRefresh ) { 12301 12302 a ? a[ 0 ].appendChild( this.placeholder[ 0 ] ) : 12303 i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ], 12304 ( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) ); 12305 12306 //Various things done here to improve the performance: 12307 // 1. we create a setTimeout, that calls refreshPositions 12308 // 2. on the instance, we have a counter variable, that get's higher after every append 12309 // 3. on the local scope, we copy the counter variable, and check in the timeout, 12310 // if it's still the same 12311 // 4. this lets only the last addition to the timeout stack through 12312 this.counter = this.counter ? ++this.counter : 1; 12313 var counter = this.counter; 12314 12315 this._delay( function() { 12316 if ( counter === this.counter ) { 12317 12318 //Precompute after each DOM insertion, NOT on mousemove 12319 this.refreshPositions( !hardRefresh ); 12320 } 12321 } ); 12322 12323 }, 12324 12325 _clear: function( event, noPropagation ) { 12326 12327 this.reverting = false; 12328 12329 // We delay all events that have to be triggered to after the point where the placeholder 12330 // has been removed and everything else normalized again 12331 var i, 12332 delayedTriggers = []; 12333 12334 // We first have to update the dom position of the actual currentItem 12335 // Note: don't do it if the current item is already removed (by a user), or it gets 12336 // reappended (see #4088) 12337 if ( !this._noFinalSort && this.currentItem.parent().length ) { 12338 this.placeholder.before( this.currentItem ); 12339 } 12340 this._noFinalSort = null; 12341 12342 if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) { 12343 for ( i in this._storedCSS ) { 12344 if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) { 12345 this._storedCSS[ i ] = ""; 12346 } 12347 } 12348 this.currentItem.css( this._storedCSS ); 12349 this._removeClass( this.currentItem, "ui-sortable-helper" ); 12350 } else { 12351 this.currentItem.show(); 12352 } 12353 12354 if ( this.fromOutside && !noPropagation ) { 12355 delayedTriggers.push( function( event ) { 12356 this._trigger( "receive", event, this._uiHash( this.fromOutside ) ); 12357 } ); 12358 } 12359 if ( ( this.fromOutside || 12360 this.domPosition.prev !== 12361 this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] || 12362 this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) { 12363 12364 // Trigger update callback if the DOM position has changed 12365 delayedTriggers.push( function( event ) { 12366 this._trigger( "update", event, this._uiHash() ); 12367 } ); 12368 } 12369 12370 // Check if the items Container has Changed and trigger appropriate 12371 // events. 12372 if ( this !== this.currentContainer ) { 12373 if ( !noPropagation ) { 12374 delayedTriggers.push( function( event ) { 12375 this._trigger( "remove", event, this._uiHash() ); 12376 } ); 12377 delayedTriggers.push( ( function( c ) { 12378 return function( event ) { 12379 c._trigger( "receive", event, this._uiHash( this ) ); 12380 }; 12381 } ).call( this, this.currentContainer ) ); 12382 delayedTriggers.push( ( function( c ) { 12383 return function( event ) { 12384 c._trigger( "update", event, this._uiHash( this ) ); 12385 }; 12386 } ).call( this, this.currentContainer ) ); 12387 } 12388 } 12389 12390 //Post events to containers 12391 function delayEvent( type, instance, container ) { 12392 return function( event ) { 12393 container._trigger( type, event, instance._uiHash( instance ) ); 12394 }; 12395 } 12396 for ( i = this.containers.length - 1; i >= 0; i-- ) { 12397 if ( !noPropagation ) { 12398 delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) ); 12399 } 12400 if ( this.containers[ i ].containerCache.over ) { 12401 delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) ); 12402 this.containers[ i ].containerCache.over = 0; 12403 } 12404 } 12405 12406 //Do what was originally in plugins 12407 if ( this.storedCursor ) { 12408 this.document.find( "body" ).css( "cursor", this.storedCursor ); 12409 this.storedStylesheet.remove(); 12410 } 12411 if ( this._storedOpacity ) { 12412 this.helper.css( "opacity", this._storedOpacity ); 12413 } 12414 if ( this._storedZIndex ) { 12415 this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex ); 12416 } 12417 12418 this.dragging = false; 12419 12420 if ( !noPropagation ) { 12421 this._trigger( "beforeStop", event, this._uiHash() ); 12422 } 12423 12424 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, 12425 // it unbinds ALL events from the original node! 12426 this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] ); 12427 12428 if ( !this.cancelHelperRemoval ) { 12429 if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) { 12430 this.helper.remove(); 12431 } 12432 this.helper = null; 12433 } 12434 12435 if ( !noPropagation ) { 12436 for ( i = 0; i < delayedTriggers.length; i++ ) { 12437 12438 // Trigger all delayed events 12439 delayedTriggers[ i ].call( this, event ); 12440 } 12441 this._trigger( "stop", event, this._uiHash() ); 12442 } 12443 12444 this.fromOutside = false; 12445 return !this.cancelHelperRemoval; 12446 12447 }, 12448 12449 _trigger: function() { 12450 if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) { 12451 this.cancel(); 12452 } 12453 }, 12454 12455 _uiHash: function( _inst ) { 12456 var inst = _inst || this; 12457 return { 12458 helper: inst.helper, 12459 placeholder: inst.placeholder || $( [] ), 12460 position: inst.position, 12461 originalPosition: inst.originalPosition, 12462 offset: inst.positionAbs, 12463 item: inst.currentItem, 12464 sender: _inst ? _inst.element : null 12465 }; 12466 } 12467 12468} ); 12469 12470 12471/*! 12472 * jQuery UI Spinner 1.12.1 12473 * http://jqueryui.com 12474 * 12475 * Copyright jQuery Foundation and other contributors 12476 * Released under the MIT license. 12477 * http://jquery.org/license 12478 */ 12479 12480//>>label: Spinner 12481//>>group: Widgets 12482//>>description: Displays buttons to easily input numbers via the keyboard or mouse. 12483//>>docs: http://api.jqueryui.com/spinner/ 12484//>>demos: http://jqueryui.com/spinner/ 12485//>>css.structure: ../../themes/base/core.css 12486//>>css.structure: ../../themes/base/spinner.css 12487//>>css.theme: ../../themes/base/theme.css 12488 12489 12490 12491function spinnerModifer( fn ) { 12492 return function() { 12493 var previous = this.element.val(); 12494 fn.apply( this, arguments ); 12495 this._refresh(); 12496 if ( previous !== this.element.val() ) { 12497 this._trigger( "change" ); 12498 } 12499 }; 12500} 12501 12502$.widget( "ui.spinner", { 12503 version: "1.12.1", 12504 defaultElement: "<input>", 12505 widgetEventPrefix: "spin", 12506 options: { 12507 classes: { 12508 "ui-spinner": "ui-corner-all", 12509 "ui-spinner-down": "ui-corner-br", 12510 "ui-spinner-up": "ui-corner-tr" 12511 }, 12512 culture: null, 12513 icons: { 12514 down: "ui-icon-triangle-1-s", 12515 up: "ui-icon-triangle-1-n" 12516 }, 12517 incremental: true, 12518 max: null, 12519 min: null, 12520 numberFormat: null, 12521 page: 10, 12522 step: 1, 12523 12524 change: null, 12525 spin: null, 12526 start: null, 12527 stop: null 12528 }, 12529 12530 _create: function() { 12531 12532 // handle string values that need to be parsed 12533 this._setOption( "max", this.options.max ); 12534 this._setOption( "min", this.options.min ); 12535 this._setOption( "step", this.options.step ); 12536 12537 // Only format if there is a value, prevents the field from being marked 12538 // as invalid in Firefox, see #9573. 12539 if ( this.value() !== "" ) { 12540 12541 // Format the value, but don't constrain. 12542 this._value( this.element.val(), true ); 12543 } 12544 12545 this._draw(); 12546 this._on( this._events ); 12547 this._refresh(); 12548 12549 // Turning off autocomplete prevents the browser from remembering the 12550 // value when navigating through history, so we re-enable autocomplete 12551 // if the page is unloaded before the widget is destroyed. #7790 12552 this._on( this.window, { 12553 beforeunload: function() { 12554 this.element.removeAttr( "autocomplete" ); 12555 } 12556 } ); 12557 }, 12558 12559 _getCreateOptions: function() { 12560 var options = this._super(); 12561 var element = this.element; 12562 12563 $.each( [ "min", "max", "step" ], function( i, option ) { 12564 var value = element.attr( option ); 12565 if ( value != null && value.length ) { 12566 options[ option ] = value; 12567 } 12568 } ); 12569 12570 return options; 12571 }, 12572 12573 _events: { 12574 keydown: function( event ) { 12575 if ( this._start( event ) && this._keydown( event ) ) { 12576 event.preventDefault(); 12577 } 12578 }, 12579 keyup: "_stop", 12580 focus: function() { 12581 this.previous = this.element.val(); 12582 }, 12583 blur: function( event ) { 12584 if ( this.cancelBlur ) { 12585 delete this.cancelBlur; 12586 return; 12587 } 12588 12589 this._stop(); 12590 this._refresh(); 12591 if ( this.previous !== this.element.val() ) { 12592 this._trigger( "change", event ); 12593 } 12594 }, 12595 mousewheel: function( event, delta ) { 12596 if ( !delta ) { 12597 return; 12598 } 12599 if ( !this.spinning && !this._start( event ) ) { 12600 return false; 12601 } 12602 12603 this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event ); 12604 clearTimeout( this.mousewheelTimer ); 12605 this.mousewheelTimer = this._delay( function() { 12606 if ( this.spinning ) { 12607 this._stop( event ); 12608 } 12609 }, 100 ); 12610 event.preventDefault(); 12611 }, 12612 "mousedown .ui-spinner-button": function( event ) { 12613 var previous; 12614 12615 // We never want the buttons to have focus; whenever the user is 12616 // interacting with the spinner, the focus should be on the input. 12617 // If the input is focused then this.previous is properly set from 12618 // when the input first received focus. If the input is not focused 12619 // then we need to set this.previous based on the value before spinning. 12620 previous = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] ) ? 12621 this.previous : this.element.val(); 12622 function checkFocus() { 12623 var isActive = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] ); 12624 if ( !isActive ) { 12625 this.element.trigger( "focus" ); 12626 this.previous = previous; 12627 12628 // support: IE 12629 // IE sets focus asynchronously, so we need to check if focus 12630 // moved off of the input because the user clicked on the button. 12631 this._delay( function() { 12632 this.previous = previous; 12633 } ); 12634 } 12635 } 12636 12637 // Ensure focus is on (or stays on) the text field 12638 event.preventDefault(); 12639 checkFocus.call( this ); 12640 12641 // Support: IE 12642 // IE doesn't prevent moving focus even with event.preventDefault() 12643 // so we set a flag to know when we should ignore the blur event 12644 // and check (again) if focus moved off of the input. 12645 this.cancelBlur = true; 12646 this._delay( function() { 12647 delete this.cancelBlur; 12648 checkFocus.call( this ); 12649 } ); 12650 12651 if ( this._start( event ) === false ) { 12652 return; 12653 } 12654 12655 this._repeat( null, $( event.currentTarget ) 12656 .hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 12657 }, 12658 "mouseup .ui-spinner-button": "_stop", 12659 "mouseenter .ui-spinner-button": function( event ) { 12660 12661 // button will add ui-state-active if mouse was down while mouseleave and kept down 12662 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) { 12663 return; 12664 } 12665 12666 if ( this._start( event ) === false ) { 12667 return false; 12668 } 12669 this._repeat( null, $( event.currentTarget ) 12670 .hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 12671 }, 12672 12673 // TODO: do we really want to consider this a stop? 12674 // shouldn't we just stop the repeater and wait until mouseup before 12675 // we trigger the stop event? 12676 "mouseleave .ui-spinner-button": "_stop" 12677 }, 12678 12679 // Support mobile enhanced option and make backcompat more sane 12680 _enhance: function() { 12681 this.uiSpinner = this.element 12682 .attr( "autocomplete", "off" ) 12683 .wrap( "<span>" ) 12684 .parent() 12685 12686 // Add buttons 12687 .append( 12688 "<a></a><a></a>" 12689 ); 12690 }, 12691 12692 _draw: function() { 12693 this._enhance(); 12694 12695 this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" ); 12696 this._addClass( "ui-spinner-input" ); 12697 12698 this.element.attr( "role", "spinbutton" ); 12699 12700 // Button bindings 12701 this.buttons = this.uiSpinner.children( "a" ) 12702 .attr( "tabIndex", -1 ) 12703 .attr( "aria-hidden", true ) 12704 .button( { 12705 classes: { 12706 "ui-button": "" 12707 } 12708 } ); 12709 12710 // TODO: Right now button does not support classes this is already updated in button PR 12711 this._removeClass( this.buttons, "ui-corner-all" ); 12712 12713 this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" ); 12714 this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" ); 12715 this.buttons.first().button( { 12716 "icon": this.options.icons.up, 12717 "showLabel": false 12718 } ); 12719 this.buttons.last().button( { 12720 "icon": this.options.icons.down, 12721 "showLabel": false 12722 } ); 12723 12724 // IE 6 doesn't understand height: 50% for the buttons 12725 // unless the wrapper has an explicit height 12726 if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) && 12727 this.uiSpinner.height() > 0 ) { 12728 this.uiSpinner.height( this.uiSpinner.height() ); 12729 } 12730 }, 12731 12732 _keydown: function( event ) { 12733 var options = this.options, 12734 keyCode = $.ui.keyCode; 12735 12736 switch ( event.keyCode ) { 12737 case keyCode.UP: 12738 this._repeat( null, 1, event ); 12739 return true; 12740 case keyCode.DOWN: 12741 this._repeat( null, -1, event ); 12742 return true; 12743 case keyCode.PAGE_UP: 12744 this._repeat( null, options.page, event ); 12745 return true; 12746 case keyCode.PAGE_DOWN: 12747 this._repeat( null, -options.page, event ); 12748 return true; 12749 } 12750 12751 return false; 12752 }, 12753 12754 _start: function( event ) { 12755 if ( !this.spinning && this._trigger( "start", event ) === false ) { 12756 return false; 12757 } 12758 12759 if ( !this.counter ) { 12760 this.counter = 1; 12761 } 12762 this.spinning = true; 12763 return true; 12764 }, 12765 12766 _repeat: function( i, steps, event ) { 12767 i = i || 500; 12768 12769 clearTimeout( this.timer ); 12770 this.timer = this._delay( function() { 12771 this._repeat( 40, steps, event ); 12772 }, i ); 12773 12774 this._spin( steps * this.options.step, event ); 12775 }, 12776 12777 _spin: function( step, event ) { 12778 var value = this.value() || 0; 12779 12780 if ( !this.counter ) { 12781 this.counter = 1; 12782 } 12783 12784 value = this._adjustValue( value + step * this._increment( this.counter ) ); 12785 12786 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) { 12787 this._value( value ); 12788 this.counter++; 12789 } 12790 }, 12791 12792 _increment: function( i ) { 12793 var incremental = this.options.incremental; 12794 12795 if ( incremental ) { 12796 return $.isFunction( incremental ) ? 12797 incremental( i ) : 12798 Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 ); 12799 } 12800 12801 return 1; 12802 }, 12803 12804 _precision: function() { 12805 var precision = this._precisionOf( this.options.step ); 12806 if ( this.options.min !== null ) { 12807 precision = Math.max( precision, this._precisionOf( this.options.min ) ); 12808 } 12809 return precision; 12810 }, 12811 12812 _precisionOf: function( num ) { 12813 var str = num.toString(), 12814 decimal = str.indexOf( "." ); 12815 return decimal === -1 ? 0 : str.length - decimal - 1; 12816 }, 12817 12818 _adjustValue: function( value ) { 12819 var base, aboveMin, 12820 options = this.options; 12821 12822 // Make sure we're at a valid step 12823 // - find out where we are relative to the base (min or 0) 12824 base = options.min !== null ? options.min : 0; 12825 aboveMin = value - base; 12826 12827 // - round to the nearest step 12828 aboveMin = Math.round( aboveMin / options.step ) * options.step; 12829 12830 // - rounding is based on 0, so adjust back to our base 12831 value = base + aboveMin; 12832 12833 // Fix precision from bad JS floating point math 12834 value = parseFloat( value.toFixed( this._precision() ) ); 12835 12836 // Clamp the value 12837 if ( options.max !== null && value > options.max ) { 12838 return options.max; 12839 } 12840 if ( options.min !== null && value < options.min ) { 12841 return options.min; 12842 } 12843 12844 return value; 12845 }, 12846 12847 _stop: function( event ) { 12848 if ( !this.spinning ) { 12849 return; 12850 } 12851 12852 clearTimeout( this.timer ); 12853 clearTimeout( this.mousewheelTimer ); 12854 this.counter = 0; 12855 this.spinning = false; 12856 this._trigger( "stop", event ); 12857 }, 12858 12859 _setOption: function( key, value ) { 12860 var prevValue, first, last; 12861 12862 if ( key === "culture" || key === "numberFormat" ) { 12863 prevValue = this._parse( this.element.val() ); 12864 this.options[ key ] = value; 12865 this.element.val( this._format( prevValue ) ); 12866 return; 12867 } 12868 12869 if ( key === "max" || key === "min" || key === "step" ) { 12870 if ( typeof value === "string" ) { 12871 value = this._parse( value ); 12872 } 12873 } 12874 if ( key === "icons" ) { 12875 first = this.buttons.first().find( ".ui-icon" ); 12876 this._removeClass( first, null, this.options.icons.up ); 12877 this._addClass( first, null, value.up ); 12878 last = this.buttons.last().find( ".ui-icon" ); 12879 this._removeClass( last, null, this.options.icons.down ); 12880 this._addClass( last, null, value.down ); 12881 } 12882 12883 this._super( key, value ); 12884 }, 12885 12886 _setOptionDisabled: function( value ) { 12887 this._super( value ); 12888 12889 this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value ); 12890 this.element.prop( "disabled", !!value ); 12891 this.buttons.button( value ? "disable" : "enable" ); 12892 }, 12893 12894 _setOptions: spinnerModifer( function( options ) { 12895 this._super( options ); 12896 } ), 12897 12898 _parse: function( val ) { 12899 if ( typeof val === "string" && val !== "" ) { 12900 val = window.Globalize && this.options.numberFormat ? 12901 Globalize.parseFloat( val, 10, this.options.culture ) : +val; 12902 } 12903 return val === "" || isNaN( val ) ? null : val; 12904 }, 12905 12906 _format: function( value ) { 12907 if ( value === "" ) { 12908 return ""; 12909 } 12910 return window.Globalize && this.options.numberFormat ? 12911 Globalize.format( value, this.options.numberFormat, this.options.culture ) : 12912 value; 12913 }, 12914 12915 _refresh: function() { 12916 this.element.attr( { 12917 "aria-valuemin": this.options.min, 12918 "aria-valuemax": this.options.max, 12919 12920 // TODO: what should we do with values that can't be parsed? 12921 "aria-valuenow": this._parse( this.element.val() ) 12922 } ); 12923 }, 12924 12925 isValid: function() { 12926 var value = this.value(); 12927 12928 // Null is invalid 12929 if ( value === null ) { 12930 return false; 12931 } 12932 12933 // If value gets adjusted, it's invalid 12934 return value === this._adjustValue( value ); 12935 }, 12936 12937 // Update the value without triggering change 12938 _value: function( value, allowAny ) { 12939 var parsed; 12940 if ( value !== "" ) { 12941 parsed = this._parse( value ); 12942 if ( parsed !== null ) { 12943 if ( !allowAny ) { 12944 parsed = this._adjustValue( parsed ); 12945 } 12946 value = this._format( parsed ); 12947 } 12948 } 12949 this.element.val( value ); 12950 this._refresh(); 12951 }, 12952 12953 _destroy: function() { 12954 this.element 12955 .prop( "disabled", false ) 12956 .removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" ); 12957 12958 this.uiSpinner.replaceWith( this.element ); 12959 }, 12960 12961 stepUp: spinnerModifer( function( steps ) { 12962 this._stepUp( steps ); 12963 } ), 12964 _stepUp: function( steps ) { 12965 if ( this._start() ) { 12966 this._spin( ( steps || 1 ) * this.options.step ); 12967 this._stop(); 12968 } 12969 }, 12970 12971 stepDown: spinnerModifer( function( steps ) { 12972 this._stepDown( steps ); 12973 } ), 12974 _stepDown: function( steps ) { 12975 if ( this._start() ) { 12976 this._spin( ( steps || 1 ) * -this.options.step ); 12977 this._stop(); 12978 } 12979 }, 12980 12981 pageUp: spinnerModifer( function( pages ) { 12982 this._stepUp( ( pages || 1 ) * this.options.page ); 12983 } ), 12984 12985 pageDown: spinnerModifer( function( pages ) { 12986 this._stepDown( ( pages || 1 ) * this.options.page ); 12987 } ), 12988 12989 value: function( newVal ) { 12990 if ( !arguments.length ) { 12991 return this._parse( this.element.val() ); 12992 } 12993 spinnerModifer( this._value ).call( this, newVal ); 12994 }, 12995 12996 widget: function() { 12997 return this.uiSpinner; 12998 } 12999} ); 13000 13001// DEPRECATED 13002// TODO: switch return back to widget declaration at top of file when this is removed 13003if ( $.uiBackCompat !== false ) { 13004 13005 // Backcompat for spinner html extension points 13006 $.widget( "ui.spinner", $.ui.spinner, { 13007 _enhance: function() { 13008 this.uiSpinner = this.element 13009 .attr( "autocomplete", "off" ) 13010 .wrap( this._uiSpinnerHtml() ) 13011 .parent() 13012 13013 // Add buttons 13014 .append( this._buttonHtml() ); 13015 }, 13016 _uiSpinnerHtml: function() { 13017 return "<span>"; 13018 }, 13019 13020 _buttonHtml: function() { 13021 return "<a></a><a></a>"; 13022 } 13023 } ); 13024} 13025 13026var widgetsSpinner = $.ui.spinner; 13027 13028 13029/*! 13030 * jQuery UI Tabs 1.12.1 13031 * http://jqueryui.com 13032 * 13033 * Copyright jQuery Foundation and other contributors 13034 * Released under the MIT license. 13035 * http://jquery.org/license 13036 */ 13037 13038//>>label: Tabs 13039//>>group: Widgets 13040//>>description: Transforms a set of container elements into a tab structure. 13041//>>docs: http://api.jqueryui.com/tabs/ 13042//>>demos: http://jqueryui.com/tabs/ 13043//>>css.structure: ../../themes/base/core.css 13044//>>css.structure: ../../themes/base/tabs.css 13045//>>css.theme: ../../themes/base/theme.css 13046 13047 13048 13049$.widget( "ui.tabs", { 13050 version: "1.12.1", 13051 delay: 300, 13052 options: { 13053 active: null, 13054 classes: { 13055 "ui-tabs": "ui-corner-all", 13056 "ui-tabs-nav": "ui-corner-all", 13057 "ui-tabs-panel": "ui-corner-bottom", 13058 "ui-tabs-tab": "ui-corner-top" 13059 }, 13060 collapsible: false, 13061 event: "click", 13062 heightStyle: "content", 13063 hide: null, 13064 show: null, 13065 13066 // Callbacks 13067 activate: null, 13068 beforeActivate: null, 13069 beforeLoad: null, 13070 load: null 13071 }, 13072 13073 _isLocal: ( function() { 13074 var rhash = /#.*$/; 13075 13076 return function( anchor ) { 13077 var anchorUrl, locationUrl; 13078 13079 anchorUrl = anchor.href.replace( rhash, "" ); 13080 locationUrl = location.href.replace( rhash, "" ); 13081 13082 // Decoding may throw an error if the URL isn't UTF-8 (#9518) 13083 try { 13084 anchorUrl = decodeURIComponent( anchorUrl ); 13085 } catch ( error ) {} 13086 try { 13087 locationUrl = decodeURIComponent( locationUrl ); 13088 } catch ( error ) {} 13089 13090 return anchor.hash.length > 1 && anchorUrl === locationUrl; 13091 }; 13092 } )(), 13093 13094 _create: function() { 13095 var that = this, 13096 options = this.options; 13097 13098 this.running = false; 13099 13100 this._addClass( "ui-tabs", "ui-widget ui-widget-content" ); 13101 this._toggleClass( "ui-tabs-collapsible", null, options.collapsible ); 13102 13103 this._processTabs(); 13104 options.active = this._initialActive(); 13105 13106 // Take disabling tabs via class attribute from HTML 13107 // into account and update option properly. 13108 if ( $.isArray( options.disabled ) ) { 13109 options.disabled = $.unique( options.disabled.concat( 13110 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { 13111 return that.tabs.index( li ); 13112 } ) 13113 ) ).sort(); 13114 } 13115 13116 // Check for length avoids error when initializing empty list 13117 if ( this.options.active !== false && this.anchors.length ) { 13118 this.active = this._findActive( options.active ); 13119 } else { 13120 this.active = $(); 13121 } 13122 13123 this._refresh(); 13124 13125 if ( this.active.length ) { 13126 this.load( options.active ); 13127 } 13128 }, 13129 13130 _initialActive: function() { 13131 var active = this.options.active, 13132 collapsible = this.options.collapsible, 13133 locationHash = location.hash.substring( 1 ); 13134 13135 if ( active === null ) { 13136 13137 // check the fragment identifier in the URL 13138 if ( locationHash ) { 13139 this.tabs.each( function( i, tab ) { 13140 if ( $( tab ).attr( "aria-controls" ) === locationHash ) { 13141 active = i; 13142 return false; 13143 } 13144 } ); 13145 } 13146 13147 // Check for a tab marked active via a class 13148 if ( active === null ) { 13149 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); 13150 } 13151 13152 // No active tab, set to false 13153 if ( active === null || active === -1 ) { 13154 active = this.tabs.length ? 0 : false; 13155 } 13156 } 13157 13158 // Handle numbers: negative, out of range 13159 if ( active !== false ) { 13160 active = this.tabs.index( this.tabs.eq( active ) ); 13161 if ( active === -1 ) { 13162 active = collapsible ? false : 0; 13163 } 13164 } 13165 13166 // Don't allow collapsible: false and active: false 13167 if ( !collapsible && active === false && this.anchors.length ) { 13168 active = 0; 13169 } 13170 13171 return active; 13172 }, 13173 13174 _getCreateEventData: function() { 13175 return { 13176 tab: this.active, 13177 panel: !this.active.length ? $() : this._getPanelForTab( this.active ) 13178 }; 13179 }, 13180 13181 _tabKeydown: function( event ) { 13182 var focusedTab = $( $.ui.safeActiveElement( this.document[ 0 ] ) ).closest( "li" ), 13183 selectedIndex = this.tabs.index( focusedTab ), 13184 goingForward = true; 13185 13186 if ( this._handlePageNav( event ) ) { 13187 return; 13188 } 13189 13190 switch ( event.keyCode ) { 13191 case $.ui.keyCode.RIGHT: 13192 case $.ui.keyCode.DOWN: 13193 selectedIndex++; 13194 break; 13195 case $.ui.keyCode.UP: 13196 case $.ui.keyCode.LEFT: 13197 goingForward = false; 13198 selectedIndex--; 13199 break; 13200 case $.ui.keyCode.END: 13201 selectedIndex = this.anchors.length - 1; 13202 break; 13203 case $.ui.keyCode.HOME: 13204 selectedIndex = 0; 13205 break; 13206 case $.ui.keyCode.SPACE: 13207 13208 // Activate only, no collapsing 13209 event.preventDefault(); 13210 clearTimeout( this.activating ); 13211 this._activate( selectedIndex ); 13212 return; 13213 case $.ui.keyCode.ENTER: 13214 13215 // Toggle (cancel delayed activation, allow collapsing) 13216 event.preventDefault(); 13217 clearTimeout( this.activating ); 13218 13219 // Determine if we should collapse or activate 13220 this._activate( selectedIndex === this.options.active ? false : selectedIndex ); 13221 return; 13222 default: 13223 return; 13224 } 13225 13226 // Focus the appropriate tab, based on which key was pressed 13227 event.preventDefault(); 13228 clearTimeout( this.activating ); 13229 selectedIndex = this._focusNextTab( selectedIndex, goingForward ); 13230 13231 // Navigating with control/command key will prevent automatic activation 13232 if ( !event.ctrlKey && !event.metaKey ) { 13233 13234 // Update aria-selected immediately so that AT think the tab is already selected. 13235 // Otherwise AT may confuse the user by stating that they need to activate the tab, 13236 // but the tab will already be activated by the time the announcement finishes. 13237 focusedTab.attr( "aria-selected", "false" ); 13238 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); 13239 13240 this.activating = this._delay( function() { 13241 this.option( "active", selectedIndex ); 13242 }, this.delay ); 13243 } 13244 }, 13245 13246 _panelKeydown: function( event ) { 13247 if ( this._handlePageNav( event ) ) { 13248 return; 13249 } 13250 13251 // Ctrl+up moves focus to the current tab 13252 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { 13253 event.preventDefault(); 13254 this.active.trigger( "focus" ); 13255 } 13256 }, 13257 13258 // Alt+page up/down moves focus to the previous/next tab (and activates) 13259 _handlePageNav: function( event ) { 13260 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { 13261 this._activate( this._focusNextTab( this.options.active - 1, false ) ); 13262 return true; 13263 } 13264 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { 13265 this._activate( this._focusNextTab( this.options.active + 1, true ) ); 13266 return true; 13267 } 13268 }, 13269 13270 _findNextTab: function( index, goingForward ) { 13271 var lastTabIndex = this.tabs.length - 1; 13272 13273 function constrain() { 13274 if ( index > lastTabIndex ) { 13275 index = 0; 13276 } 13277 if ( index < 0 ) { 13278 index = lastTabIndex; 13279 } 13280 return index; 13281 } 13282 13283 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { 13284 index = goingForward ? index + 1 : index - 1; 13285 } 13286 13287 return index; 13288 }, 13289 13290 _focusNextTab: function( index, goingForward ) { 13291 index = this._findNextTab( index, goingForward ); 13292 this.tabs.eq( index ).trigger( "focus" ); 13293 return index; 13294 }, 13295 13296 _setOption: function( key, value ) { 13297 if ( key === "active" ) { 13298 13299 // _activate() will handle invalid values and update this.options 13300 this._activate( value ); 13301 return; 13302 } 13303 13304 this._super( key, value ); 13305 13306 if ( key === "collapsible" ) { 13307 this._toggleClass( "ui-tabs-collapsible", null, value ); 13308 13309 // Setting collapsible: false while collapsed; open first panel 13310 if ( !value && this.options.active === false ) { 13311 this._activate( 0 ); 13312 } 13313 } 13314 13315 if ( key === "event" ) { 13316 this._setupEvents( value ); 13317 } 13318 13319 if ( key === "heightStyle" ) { 13320 this._setupHeightStyle( value ); 13321 } 13322 }, 13323 13324 _sanitizeSelector: function( hash ) { 13325 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : ""; 13326 }, 13327 13328 refresh: function() { 13329 var options = this.options, 13330 lis = this.tablist.children( ":has(a[href])" ); 13331 13332 // Get disabled tabs from class attribute from HTML 13333 // this will get converted to a boolean if needed in _refresh() 13334 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { 13335 return lis.index( tab ); 13336 } ); 13337 13338 this._processTabs(); 13339 13340 // Was collapsed or no tabs 13341 if ( options.active === false || !this.anchors.length ) { 13342 options.active = false; 13343 this.active = $(); 13344 13345 // was active, but active tab is gone 13346 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { 13347 13348 // all remaining tabs are disabled 13349 if ( this.tabs.length === options.disabled.length ) { 13350 options.active = false; 13351 this.active = $(); 13352 13353 // activate previous tab 13354 } else { 13355 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); 13356 } 13357 13358 // was active, active tab still exists 13359 } else { 13360 13361 // make sure active index is correct 13362 options.active = this.tabs.index( this.active ); 13363 } 13364 13365 this._refresh(); 13366 }, 13367 13368 _refresh: function() { 13369 this._setOptionDisabled( this.options.disabled ); 13370 this._setupEvents( this.options.event ); 13371 this._setupHeightStyle( this.options.heightStyle ); 13372 13373 this.tabs.not( this.active ).attr( { 13374 "aria-selected": "false", 13375 "aria-expanded": "false", 13376 tabIndex: -1 13377 } ); 13378 this.panels.not( this._getPanelForTab( this.active ) ) 13379 .hide() 13380 .attr( { 13381 "aria-hidden": "true" 13382 } ); 13383 13384 // Make sure one tab is in the tab order 13385 if ( !this.active.length ) { 13386 this.tabs.eq( 0 ).attr( "tabIndex", 0 ); 13387 } else { 13388 this.active 13389 .attr( { 13390 "aria-selected": "true", 13391 "aria-expanded": "true", 13392 tabIndex: 0 13393 } ); 13394 this._addClass( this.active, "ui-tabs-active", "ui-state-active" ); 13395 this._getPanelForTab( this.active ) 13396 .show() 13397 .attr( { 13398 "aria-hidden": "false" 13399 } ); 13400 } 13401 }, 13402 13403 _processTabs: function() { 13404 var that = this, 13405 prevTabs = this.tabs, 13406 prevAnchors = this.anchors, 13407 prevPanels = this.panels; 13408 13409 this.tablist = this._getList().attr( "role", "tablist" ); 13410 this._addClass( this.tablist, "ui-tabs-nav", 13411 "ui-helper-reset ui-helper-clearfix ui-widget-header" ); 13412 13413 // Prevent users from focusing disabled tabs via click 13414 this.tablist 13415 .on( "mousedown" + this.eventNamespace, "> li", function( event ) { 13416 if ( $( this ).is( ".ui-state-disabled" ) ) { 13417 event.preventDefault(); 13418 } 13419 } ) 13420 13421 // Support: IE <9 13422 // Preventing the default action in mousedown doesn't prevent IE 13423 // from focusing the element, so if the anchor gets focused, blur. 13424 // We don't have to worry about focusing the previously focused 13425 // element since clicking on a non-focusable element should focus 13426 // the body anyway. 13427 .on( "focus" + this.eventNamespace, ".ui-tabs-anchor", function() { 13428 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) { 13429 this.blur(); 13430 } 13431 } ); 13432 13433 this.tabs = this.tablist.find( "> li:has(a[href])" ) 13434 .attr( { 13435 role: "tab", 13436 tabIndex: -1 13437 } ); 13438 this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" ); 13439 13440 this.anchors = this.tabs.map( function() { 13441 return $( "a", this )[ 0 ]; 13442 } ) 13443 .attr( { 13444 role: "presentation", 13445 tabIndex: -1 13446 } ); 13447 this._addClass( this.anchors, "ui-tabs-anchor" ); 13448 13449 this.panels = $(); 13450 13451 this.anchors.each( function( i, anchor ) { 13452 var selector, panel, panelId, 13453 anchorId = $( anchor ).uniqueId().attr( "id" ), 13454 tab = $( anchor ).closest( "li" ), 13455 originalAriaControls = tab.attr( "aria-controls" ); 13456 13457 // Inline tab 13458 if ( that._isLocal( anchor ) ) { 13459 selector = anchor.hash; 13460 panelId = selector.substring( 1 ); 13461 panel = that.element.find( that._sanitizeSelector( selector ) ); 13462 13463 // remote tab 13464 } else { 13465 13466 // If the tab doesn't already have aria-controls, 13467 // generate an id by using a throw-away element 13468 panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id; 13469 selector = "#" + panelId; 13470 panel = that.element.find( selector ); 13471 if ( !panel.length ) { 13472 panel = that._createPanel( panelId ); 13473 panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); 13474 } 13475 panel.attr( "aria-live", "polite" ); 13476 } 13477 13478 if ( panel.length ) { 13479 that.panels = that.panels.add( panel ); 13480 } 13481 if ( originalAriaControls ) { 13482 tab.data( "ui-tabs-aria-controls", originalAriaControls ); 13483 } 13484 tab.attr( { 13485 "aria-controls": panelId, 13486 "aria-labelledby": anchorId 13487 } ); 13488 panel.attr( "aria-labelledby", anchorId ); 13489 } ); 13490 13491 this.panels.attr( "role", "tabpanel" ); 13492 this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" ); 13493 13494 // Avoid memory leaks (#10056) 13495 if ( prevTabs ) { 13496 this._off( prevTabs.not( this.tabs ) ); 13497 this._off( prevAnchors.not( this.anchors ) ); 13498 this._off( prevPanels.not( this.panels ) ); 13499 } 13500 }, 13501 13502 // Allow overriding how to find the list for rare usage scenarios (#7715) 13503 _getList: function() { 13504 return this.tablist || this.element.find( "ol, ul" ).eq( 0 ); 13505 }, 13506 13507 _createPanel: function( id ) { 13508 return $( "<div>" ) 13509 .attr( "id", id ) 13510 .data( "ui-tabs-destroy", true ); 13511 }, 13512 13513 _setOptionDisabled: function( disabled ) { 13514 var currentItem, li, i; 13515 13516 if ( $.isArray( disabled ) ) { 13517 if ( !disabled.length ) { 13518 disabled = false; 13519 } else if ( disabled.length === this.anchors.length ) { 13520 disabled = true; 13521 } 13522 } 13523 13524 // Disable tabs 13525 for ( i = 0; ( li = this.tabs[ i ] ); i++ ) { 13526 currentItem = $( li ); 13527 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { 13528 currentItem.attr( "aria-disabled", "true" ); 13529 this._addClass( currentItem, null, "ui-state-disabled" ); 13530 } else { 13531 currentItem.removeAttr( "aria-disabled" ); 13532 this._removeClass( currentItem, null, "ui-state-disabled" ); 13533 } 13534 } 13535 13536 this.options.disabled = disabled; 13537 13538 this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, 13539 disabled === true ); 13540 }, 13541 13542 _setupEvents: function( event ) { 13543 var events = {}; 13544 if ( event ) { 13545 $.each( event.split( " " ), function( index, eventName ) { 13546 events[ eventName ] = "_eventHandler"; 13547 } ); 13548 } 13549 13550 this._off( this.anchors.add( this.tabs ).add( this.panels ) ); 13551 13552 // Always prevent the default action, even when disabled 13553 this._on( true, this.anchors, { 13554 click: function( event ) { 13555 event.preventDefault(); 13556 } 13557 } ); 13558 this._on( this.anchors, events ); 13559 this._on( this.tabs, { keydown: "_tabKeydown" } ); 13560 this._on( this.panels, { keydown: "_panelKeydown" } ); 13561 13562 this._focusable( this.tabs ); 13563 this._hoverable( this.tabs ); 13564 }, 13565 13566 _setupHeightStyle: function( heightStyle ) { 13567 var maxHeight, 13568 parent = this.element.parent(); 13569 13570 if ( heightStyle === "fill" ) { 13571 maxHeight = parent.height(); 13572 maxHeight -= this.element.outerHeight() - this.element.height(); 13573 13574 this.element.siblings( ":visible" ).each( function() { 13575 var elem = $( this ), 13576 position = elem.css( "position" ); 13577 13578 if ( position === "absolute" || position === "fixed" ) { 13579 return; 13580 } 13581 maxHeight -= elem.outerHeight( true ); 13582 } ); 13583 13584 this.element.children().not( this.panels ).each( function() { 13585 maxHeight -= $( this ).outerHeight( true ); 13586 } ); 13587 13588 this.panels.each( function() { 13589 $( this ).height( Math.max( 0, maxHeight - 13590 $( this ).innerHeight() + $( this ).height() ) ); 13591 } ) 13592 .css( "overflow", "auto" ); 13593 } else if ( heightStyle === "auto" ) { 13594 maxHeight = 0; 13595 this.panels.each( function() { 13596 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); 13597 } ).height( maxHeight ); 13598 } 13599 }, 13600 13601 _eventHandler: function( event ) { 13602 var options = this.options, 13603 active = this.active, 13604 anchor = $( event.currentTarget ), 13605 tab = anchor.closest( "li" ), 13606 clickedIsActive = tab[ 0 ] === active[ 0 ], 13607 collapsing = clickedIsActive && options.collapsible, 13608 toShow = collapsing ? $() : this._getPanelForTab( tab ), 13609 toHide = !active.length ? $() : this._getPanelForTab( active ), 13610 eventData = { 13611 oldTab: active, 13612 oldPanel: toHide, 13613 newTab: collapsing ? $() : tab, 13614 newPanel: toShow 13615 }; 13616 13617 event.preventDefault(); 13618 13619 if ( tab.hasClass( "ui-state-disabled" ) || 13620 13621 // tab is already loading 13622 tab.hasClass( "ui-tabs-loading" ) || 13623 13624 // can't switch durning an animation 13625 this.running || 13626 13627 // click on active header, but not collapsible 13628 ( clickedIsActive && !options.collapsible ) || 13629 13630 // allow canceling activation 13631 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 13632 return; 13633 } 13634 13635 options.active = collapsing ? false : this.tabs.index( tab ); 13636 13637 this.active = clickedIsActive ? $() : tab; 13638 if ( this.xhr ) { 13639 this.xhr.abort(); 13640 } 13641 13642 if ( !toHide.length && !toShow.length ) { 13643 $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); 13644 } 13645 13646 if ( toShow.length ) { 13647 this.load( this.tabs.index( tab ), event ); 13648 } 13649 this._toggle( event, eventData ); 13650 }, 13651 13652 // Handles show/hide for selecting tabs 13653 _toggle: function( event, eventData ) { 13654 var that = this, 13655 toShow = eventData.newPanel, 13656 toHide = eventData.oldPanel; 13657 13658 this.running = true; 13659 13660 function complete() { 13661 that.running = false; 13662 that._trigger( "activate", event, eventData ); 13663 } 13664 13665 function show() { 13666 that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" ); 13667 13668 if ( toShow.length && that.options.show ) { 13669 that._show( toShow, that.options.show, complete ); 13670 } else { 13671 toShow.show(); 13672 complete(); 13673 } 13674 } 13675 13676 // Start out by hiding, then showing, then completing 13677 if ( toHide.length && this.options.hide ) { 13678 this._hide( toHide, this.options.hide, function() { 13679 that._removeClass( eventData.oldTab.closest( "li" ), 13680 "ui-tabs-active", "ui-state-active" ); 13681 show(); 13682 } ); 13683 } else { 13684 this._removeClass( eventData.oldTab.closest( "li" ), 13685 "ui-tabs-active", "ui-state-active" ); 13686 toHide.hide(); 13687 show(); 13688 } 13689 13690 toHide.attr( "aria-hidden", "true" ); 13691 eventData.oldTab.attr( { 13692 "aria-selected": "false", 13693 "aria-expanded": "false" 13694 } ); 13695 13696 // If we're switching tabs, remove the old tab from the tab order. 13697 // If we're opening from collapsed state, remove the previous tab from the tab order. 13698 // If we're collapsing, then keep the collapsing tab in the tab order. 13699 if ( toShow.length && toHide.length ) { 13700 eventData.oldTab.attr( "tabIndex", -1 ); 13701 } else if ( toShow.length ) { 13702 this.tabs.filter( function() { 13703 return $( this ).attr( "tabIndex" ) === 0; 13704 } ) 13705 .attr( "tabIndex", -1 ); 13706 } 13707 13708 toShow.attr( "aria-hidden", "false" ); 13709 eventData.newTab.attr( { 13710 "aria-selected": "true", 13711 "aria-expanded": "true", 13712 tabIndex: 0 13713 } ); 13714 }, 13715 13716 _activate: function( index ) { 13717 var anchor, 13718 active = this._findActive( index ); 13719 13720 // Trying to activate the already active panel 13721 if ( active[ 0 ] === this.active[ 0 ] ) { 13722 return; 13723 } 13724 13725 // Trying to collapse, simulate a click on the current active header 13726 if ( !active.length ) { 13727 active = this.active; 13728 } 13729 13730 anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; 13731 this._eventHandler( { 13732 target: anchor, 13733 currentTarget: anchor, 13734 preventDefault: $.noop 13735 } ); 13736 }, 13737 13738 _findActive: function( index ) { 13739 return index === false ? $() : this.tabs.eq( index ); 13740 }, 13741 13742 _getIndex: function( index ) { 13743 13744 // meta-function to give users option to provide a href string instead of a numerical index. 13745 if ( typeof index === "string" ) { 13746 index = this.anchors.index( this.anchors.filter( "[href$='" + 13747 $.ui.escapeSelector( index ) + "']" ) ); 13748 } 13749 13750 return index; 13751 }, 13752 13753 _destroy: function() { 13754 if ( this.xhr ) { 13755 this.xhr.abort(); 13756 } 13757 13758 this.tablist 13759 .removeAttr( "role" ) 13760 .off( this.eventNamespace ); 13761 13762 this.anchors 13763 .removeAttr( "role tabIndex" ) 13764 .removeUniqueId(); 13765 13766 this.tabs.add( this.panels ).each( function() { 13767 if ( $.data( this, "ui-tabs-destroy" ) ) { 13768 $( this ).remove(); 13769 } else { 13770 $( this ).removeAttr( "role tabIndex " + 13771 "aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" ); 13772 } 13773 } ); 13774 13775 this.tabs.each( function() { 13776 var li = $( this ), 13777 prev = li.data( "ui-tabs-aria-controls" ); 13778 if ( prev ) { 13779 li 13780 .attr( "aria-controls", prev ) 13781 .removeData( "ui-tabs-aria-controls" ); 13782 } else { 13783 li.removeAttr( "aria-controls" ); 13784 } 13785 } ); 13786 13787 this.panels.show(); 13788 13789 if ( this.options.heightStyle !== "content" ) { 13790 this.panels.css( "height", "" ); 13791 } 13792 }, 13793 13794 enable: function( index ) { 13795 var disabled = this.options.disabled; 13796 if ( disabled === false ) { 13797 return; 13798 } 13799 13800 if ( index === undefined ) { 13801 disabled = false; 13802 } else { 13803 index = this._getIndex( index ); 13804 if ( $.isArray( disabled ) ) { 13805 disabled = $.map( disabled, function( num ) { 13806 return num !== index ? num : null; 13807 } ); 13808 } else { 13809 disabled = $.map( this.tabs, function( li, num ) { 13810 return num !== index ? num : null; 13811 } ); 13812 } 13813 } 13814 this._setOptionDisabled( disabled ); 13815 }, 13816 13817 disable: function( index ) { 13818 var disabled = this.options.disabled; 13819 if ( disabled === true ) { 13820 return; 13821 } 13822 13823 if ( index === undefined ) { 13824 disabled = true; 13825 } else { 13826 index = this._getIndex( index ); 13827 if ( $.inArray( index, disabled ) !== -1 ) { 13828 return; 13829 } 13830 if ( $.isArray( disabled ) ) { 13831 disabled = $.merge( [ index ], disabled ).sort(); 13832 } else { 13833 disabled = [ index ]; 13834 } 13835 } 13836 this._setOptionDisabled( disabled ); 13837 }, 13838 13839 load: function( index, event ) { 13840 index = this._getIndex( index ); 13841 var that = this, 13842 tab = this.tabs.eq( index ), 13843 anchor = tab.find( ".ui-tabs-anchor" ), 13844 panel = this._getPanelForTab( tab ), 13845 eventData = { 13846 tab: tab, 13847 panel: panel 13848 }, 13849 complete = function( jqXHR, status ) { 13850 if ( status === "abort" ) { 13851 that.panels.stop( false, true ); 13852 } 13853 13854 that._removeClass( tab, "ui-tabs-loading" ); 13855 panel.removeAttr( "aria-busy" ); 13856 13857 if ( jqXHR === that.xhr ) { 13858 delete that.xhr; 13859 } 13860 }; 13861 13862 // Not remote 13863 if ( this._isLocal( anchor[ 0 ] ) ) { 13864 return; 13865 } 13866 13867 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); 13868 13869 // Support: jQuery <1.8 13870 // jQuery <1.8 returns false if the request is canceled in beforeSend, 13871 // but as of 1.8, $.ajax() always returns a jqXHR object. 13872 if ( this.xhr && this.xhr.statusText !== "canceled" ) { 13873 this._addClass( tab, "ui-tabs-loading" ); 13874 panel.attr( "aria-busy", "true" ); 13875 13876 this.xhr 13877 .done( function( response, status, jqXHR ) { 13878 13879 // support: jQuery <1.8 13880 // http://bugs.jquery.com/ticket/11778 13881 setTimeout( function() { 13882 panel.html( response ); 13883 that._trigger( "load", event, eventData ); 13884 13885 complete( jqXHR, status ); 13886 }, 1 ); 13887 } ) 13888 .fail( function( jqXHR, status ) { 13889 13890 // support: jQuery <1.8 13891 // http://bugs.jquery.com/ticket/11778 13892 setTimeout( function() { 13893 complete( jqXHR, status ); 13894 }, 1 ); 13895 } ); 13896 } 13897 }, 13898 13899 _ajaxSettings: function( anchor, event, eventData ) { 13900 var that = this; 13901 return { 13902 13903 // Support: IE <11 only 13904 // Strip any hash that exists to prevent errors with the Ajax request 13905 url: anchor.attr( "href" ).replace( /#.*$/, "" ), 13906 beforeSend: function( jqXHR, settings ) { 13907 return that._trigger( "beforeLoad", event, 13908 $.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) ); 13909 } 13910 }; 13911 }, 13912 13913 _getPanelForTab: function( tab ) { 13914 var id = $( tab ).attr( "aria-controls" ); 13915 return this.element.find( this._sanitizeSelector( "#" + id ) ); 13916 } 13917} ); 13918 13919// DEPRECATED 13920// TODO: Switch return back to widget declaration at top of file when this is removed 13921if ( $.uiBackCompat !== false ) { 13922 13923 // Backcompat for ui-tab class (now ui-tabs-tab) 13924 $.widget( "ui.tabs", $.ui.tabs, { 13925 _processTabs: function() { 13926 this._superApply( arguments ); 13927 this._addClass( this.tabs, "ui-tab" ); 13928 } 13929 } ); 13930} 13931 13932var widgetsTabs = $.ui.tabs; 13933 13934
13935 13936 13937}));
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.