[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 /*! jQuery UI - v1.11.4 - 2015-03-15 2 * http://jqueryui.com 3 * Includes: core.js, widget.js, mouse.js, position.js, draggable.js, droppable.js, resizable.js, selectable.js, sortable.js, accordion.js, autocomplete.js, button.js, datepicker.js, dialog.js, menu.js, progressbar.js, selectmenu.js, slider.js, spinner.js, tabs.js, tooltip.js, effect.js, effect-blind.js, effect-bounce.js, effect-clip.js, effect-drop.js, effect-explode.js, effect-fade.js, effect-fold.js, effect-highlight.js, effect-puff.js, effect-pulsate.js, effect-scale.js, effect-shake.js, effect-size.js, effect-slide.js, effect-transfer.js 4 * Copyright 2015 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 * jQuery UI Core 1.11.4 19 * http://jqueryui.com 20 * 21 * Copyright jQuery Foundation and other contributors 22 * Released under the MIT license. 23 * http://jquery.org/license 24 * 25 * http://api.jqueryui.com/category/ui-core/ 26 */ 27 28 29 // $.ui might exist from components with no dependencies, e.g., $.ui.position 30 $.ui = $.ui || {}; 31 32 $.extend( $.ui, { 33 version: "1.11.4", 34 35 keyCode: { 36 BACKSPACE: 8, 37 COMMA: 188, 38 DELETE: 46, 39 DOWN: 40, 40 END: 35, 41 ENTER: 13, 42 ESCAPE: 27, 43 HOME: 36, 44 LEFT: 37, 45 PAGE_DOWN: 34, 46 PAGE_UP: 33, 47 PERIOD: 190, 48 RIGHT: 39, 49 SPACE: 32, 50 TAB: 9, 51 UP: 38 52 } 53 }); 54 55 // plugins 56 $.fn.extend({ 57 scrollParent: function( includeHidden ) { 58 var position = this.css( "position" ), 59 excludeStaticParent = position === "absolute", 60 overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/, 61 scrollParent = this.parents().filter( function() { 62 var parent = $( this ); 63 if ( excludeStaticParent && parent.css( "position" ) === "static" ) { 64 return false; 65 } 66 return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + parent.css( "overflow-x" ) ); 67 }).eq( 0 ); 68 69 return position === "fixed" || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent; 70 }, 71 72 uniqueId: (function() { 73 var uuid = 0; 74 75 return function() { 76 return this.each(function() { 77 if ( !this.id ) { 78 this.id = "ui-id-" + ( ++uuid ); 79 } 80 }); 81 }; 82 })(), 83 84 removeUniqueId: function() { 85 return this.each(function() { 86 if ( /^ui-id-\d+$/.test( this.id ) ) { 87 $( this ).removeAttr( "id" ); 88 } 89 }); 90 } 91 }); 92 93 // selectors 94 function focusable( element, isTabIndexNotNaN ) { 95 var map, mapName, img, 96 nodeName = element.nodeName.toLowerCase(); 97 if ( "area" === nodeName ) { 98 map = element.parentNode; 99 mapName = map.name; 100 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { 101 return false; 102 } 103 img = $( "img[usemap='#" + mapName + "']" )[ 0 ]; 104 return !!img && visible( img ); 105 } 106 return ( /^(input|select|textarea|button|object)$/.test( nodeName ) ? 107 !element.disabled : 108 "a" === nodeName ? 109 element.href || isTabIndexNotNaN : 110 isTabIndexNotNaN) && 111 // the element and all of its ancestors must be visible 112 visible( element ); 113 } 114 115 function visible( element ) { 116 return $.expr.filters.visible( element ) && 117 !$( element ).parents().addBack().filter(function() { 118 return $.css( this, "visibility" ) === "hidden"; 119 }).length; 120 } 121 122 $.extend( $.expr[ ":" ], { 123 data: $.expr.createPseudo ? 124 $.expr.createPseudo(function( dataName ) { 125 return function( elem ) { 126 return !!$.data( elem, dataName ); 127 }; 128 }) : 129 // support: jQuery <1.8 130 function( elem, i, match ) { 131 return !!$.data( elem, match[ 3 ] ); 132 }, 133 134 focusable: function( element ) { 135 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); 136 }, 137 138 tabbable: function( element ) { 139 var tabIndex = $.attr( element, "tabindex" ), 140 isTabIndexNaN = isNaN( tabIndex ); 141 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); 142 } 143 }); 144 145 // support: jQuery <1.8 146 if ( !$( "<a>" ).outerWidth( 1 ).jquery ) { 147 $.each( [ "Width", "Height" ], function( i, name ) { 148 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], 149 type = name.toLowerCase(), 150 orig = { 151 innerWidth: $.fn.innerWidth, 152 innerHeight: $.fn.innerHeight, 153 outerWidth: $.fn.outerWidth, 154 outerHeight: $.fn.outerHeight 155 }; 156 157 function reduce( elem, size, border, margin ) { 158 $.each( side, function() { 159 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; 160 if ( border ) { 161 size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; 162 } 163 if ( margin ) { 164 size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; 165 } 166 }); 167 return size; 168 } 169 170 $.fn[ "inner" + name ] = function( size ) { 171 if ( size === undefined ) { 172 return orig[ "inner" + name ].call( this ); 173 } 174 175 return this.each(function() { 176 $( this ).css( type, reduce( this, size ) + "px" ); 177 }); 178 }; 179 180 $.fn[ "outer" + name] = function( size, margin ) { 181 if ( typeof size !== "number" ) { 182 return orig[ "outer" + name ].call( this, size ); 183 } 184 185 return this.each(function() { 186 $( this).css( type, reduce( this, size, true, margin ) + "px" ); 187 }); 188 }; 189 }); 190 } 191 192 // support: jQuery <1.8 193 if ( !$.fn.addBack ) { 194 $.fn.addBack = function( selector ) { 195 return this.add( selector == null ? 196 this.prevObject : this.prevObject.filter( selector ) 197 ); 198 }; 199 } 200 201 // support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413) 202 if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) { 203 $.fn.removeData = (function( removeData ) { 204 return function( key ) { 205 if ( arguments.length ) { 206 return removeData.call( this, $.camelCase( key ) ); 207 } else { 208 return removeData.call( this ); 209 } 210 }; 211 })( $.fn.removeData ); 212 } 213 214 // deprecated 215 $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ); 216 217 $.fn.extend({ 218 focus: (function( orig ) { 219 return function( delay, fn ) { 220 return typeof delay === "number" ? 221 this.each(function() { 222 var elem = this; 223 setTimeout(function() { 224 $( elem ).focus(); 225 if ( fn ) { 226 fn.call( elem ); 227 } 228 }, delay ); 229 }) : 230 orig.apply( this, arguments ); 231 }; 232 })( $.fn.focus ), 233 234 disableSelection: (function() { 235 var eventType = "onselectstart" in document.createElement( "div" ) ? 236 "selectstart" : 237 "mousedown"; 238 239 return function() { 240 return this.bind( eventType + ".ui-disableSelection", function( event ) { 241 event.preventDefault(); 242 }); 243 }; 244 })(), 245 246 enableSelection: function() { 247 return this.unbind( ".ui-disableSelection" ); 248 }, 249 250 zIndex: function( zIndex ) { 251 if ( zIndex !== undefined ) { 252 return this.css( "zIndex", zIndex ); 253 } 254 255 if ( this.length ) { 256 var elem = $( this[ 0 ] ), position, value; 257 while ( elem.length && elem[ 0 ] !== document ) { 258 // Ignore z-index if position is set to a value where z-index is ignored by the browser 259 // This makes behavior of this function consistent across browsers 260 // WebKit always returns auto if the element is positioned 261 position = elem.css( "position" ); 262 if ( position === "absolute" || position === "relative" || position === "fixed" ) { 263 // IE returns 0 when zIndex is not specified 264 // other browsers return a string 265 // we ignore the case of nested elements with an explicit value of 0 266 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 267 value = parseInt( elem.css( "zIndex" ), 10 ); 268 if ( !isNaN( value ) && value !== 0 ) { 269 return value; 270 } 271 } 272 elem = elem.parent(); 273 } 274 } 275 276 return 0; 277 } 278 }); 279 280 // $.ui.plugin is deprecated. Use $.widget() extensions instead. 281 $.ui.plugin = { 282 add: function( module, option, set ) { 283 var i, 284 proto = $.ui[ module ].prototype; 285 for ( i in set ) { 286 proto.plugins[ i ] = proto.plugins[ i ] || []; 287 proto.plugins[ i ].push( [ option, set[ i ] ] ); 288 } 289 }, 290 call: function( instance, name, args, allowDisconnected ) { 291 var i, 292 set = instance.plugins[ name ]; 293 294 if ( !set ) { 295 return; 296 } 297 298 if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) { 299 return; 300 } 301 302 for ( i = 0; i < set.length; i++ ) { 303 if ( instance.options[ set[ i ][ 0 ] ] ) { 304 set[ i ][ 1 ].apply( instance.element, args ); 305 } 306 } 307 } 308 }; 309 310 311 /*! 312 * jQuery UI Widget 1.11.4 313 * http://jqueryui.com 314 * 315 * Copyright jQuery Foundation and other contributors 316 * Released under the MIT license. 317 * http://jquery.org/license 318 * 319 * http://api.jqueryui.com/jQuery.widget/ 320 */ 321 322 323 var widget_uuid = 0, 324 widget_slice = Array.prototype.slice; 325 326 $.cleanData = (function( orig ) { 327 return function( elems ) { 328 var events, elem, i; 329 for ( i = 0; (elem = elems[i]) != null; i++ ) { 330 try { 331 332 // Only trigger remove when necessary to save time 333 events = $._data( elem, "events" ); 334 if ( events && events.remove ) { 335 $( elem ).triggerHandler( "remove" ); 336 } 337 338 // http://bugs.jquery.com/ticket/8235 339 } catch ( e ) {} 340 } 341 orig( elems ); 342 }; 343 })( $.cleanData ); 344 345 $.widget = function( name, base, prototype ) { 346 var fullName, existingConstructor, constructor, basePrototype, 347 // proxiedPrototype allows the provided prototype to remain unmodified 348 // so that it can be used as a mixin for multiple widgets (#8876) 349 proxiedPrototype = {}, 350 namespace = name.split( "." )[ 0 ]; 351 352 name = name.split( "." )[ 1 ]; 353 fullName = namespace + "-" + name; 354 355 if ( !prototype ) { 356 prototype = base; 357 base = $.Widget; 358 } 359 360 // create selector for plugin 361 $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { 362 return !!$.data( elem, fullName ); 363 }; 364 365 $[ namespace ] = $[ namespace ] || {}; 366 existingConstructor = $[ namespace ][ name ]; 367 constructor = $[ namespace ][ name ] = function( options, element ) { 368 // allow instantiation without "new" keyword 369 if ( !this._createWidget ) { 370 return new constructor( options, element ); 371 } 372 373 // allow instantiation without initializing for simple inheritance 374 // must use "new" keyword (the code above always passes args) 375 if ( arguments.length ) { 376 this._createWidget( options, element ); 377 } 378 }; 379 // extend with the existing constructor to carry over any static properties 380 $.extend( constructor, existingConstructor, { 381 version: prototype.version, 382 // copy the object used to create the prototype in case we need to 383 // redefine the widget later 384 _proto: $.extend( {}, prototype ), 385 // track widgets that inherit from this widget in case this widget is 386 // redefined after a widget inherits from it 387 _childConstructors: [] 388 }); 389 390 basePrototype = new base(); 391 // we need to make the options hash a property directly on the new instance 392 // otherwise we'll modify the options hash on the prototype that we're 393 // inheriting from 394 basePrototype.options = $.widget.extend( {}, basePrototype.options ); 395 $.each( prototype, function( prop, value ) { 396 if ( !$.isFunction( value ) ) { 397 proxiedPrototype[ prop ] = value; 398 return; 399 } 400 proxiedPrototype[ prop ] = (function() { 401 var _super = function() { 402 return base.prototype[ prop ].apply( this, arguments ); 403 }, 404 _superApply = function( args ) { 405 return base.prototype[ prop ].apply( this, args ); 406 }; 407 return function() { 408 var __super = this._super, 409 __superApply = this._superApply, 410 returnValue; 411 412 this._super = _super; 413 this._superApply = _superApply; 414 415 returnValue = value.apply( this, arguments ); 416 417 this._super = __super; 418 this._superApply = __superApply; 419 420 return returnValue; 421 }; 422 })(); 423 }); 424 constructor.prototype = $.widget.extend( basePrototype, { 425 // TODO: remove support for widgetEventPrefix 426 // always use the name + a colon as the prefix, e.g., draggable:start 427 // don't prefix for widgets that aren't DOM-based 428 widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name 429 }, proxiedPrototype, { 430 constructor: constructor, 431 namespace: namespace, 432 widgetName: name, 433 widgetFullName: fullName 434 }); 435 436 // If this widget is being redefined then we need to find all widgets that 437 // are inheriting from it and redefine all of them so that they inherit from 438 // the new version of this widget. We're essentially trying to replace one 439 // level in the prototype chain. 440 if ( existingConstructor ) { 441 $.each( existingConstructor._childConstructors, function( i, child ) { 442 var childPrototype = child.prototype; 443 444 // redefine the child widget using the same prototype that was 445 // originally used, but inherit from the new version of the base 446 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); 447 }); 448 // remove the list of existing child constructors from the old constructor 449 // so the old child constructors can be garbage collected 450 delete existingConstructor._childConstructors; 451 } else { 452 base._childConstructors.push( constructor ); 453 } 454 455 $.widget.bridge( name, constructor ); 456 457 return constructor; 458 }; 459 460 $.widget.extend = function( target ) { 461 var input = widget_slice.call( arguments, 1 ), 462 inputIndex = 0, 463 inputLength = input.length, 464 key, 465 value; 466 for ( ; inputIndex < inputLength; inputIndex++ ) { 467 for ( key in input[ inputIndex ] ) { 468 value = input[ inputIndex ][ key ]; 469 if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { 470 // Clone objects 471 if ( $.isPlainObject( value ) ) { 472 target[ key ] = $.isPlainObject( target[ key ] ) ? 473 $.widget.extend( {}, target[ key ], value ) : 474 // Don't extend strings, arrays, etc. with objects 475 $.widget.extend( {}, value ); 476 // Copy everything else by reference 477 } else { 478 target[ key ] = value; 479 } 480 } 481 } 482 } 483 return target; 484 }; 485 486 $.widget.bridge = function( name, object ) { 487 var fullName = object.prototype.widgetFullName || name; 488 $.fn[ name ] = function( options ) { 489 var isMethodCall = typeof options === "string", 490 args = widget_slice.call( arguments, 1 ), 491 returnValue = this; 492 493 if ( isMethodCall ) { 494 this.each(function() { 495 var methodValue, 496 instance = $.data( this, fullName ); 497 if ( options === "instance" ) { 498 returnValue = instance; 499 return false; 500 } 501 if ( !instance ) { 502 return $.error( "cannot call methods on " + name + " prior to initialization; " + 503 "attempted to call method '" + options + "'" ); 504 } 505 if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { 506 return $.error( "no such method '" + options + "' for " + name + " widget instance" ); 507 } 508 methodValue = instance[ options ].apply( instance, args ); 509 if ( methodValue !== instance && methodValue !== undefined ) { 510 returnValue = methodValue && methodValue.jquery ? 511 returnValue.pushStack( methodValue.get() ) : 512 methodValue; 513 return false; 514 } 515 }); 516 } else { 517 518 // Allow multiple hashes to be passed on init 519 if ( args.length ) { 520 options = $.widget.extend.apply( null, [ options ].concat(args) ); 521 } 522 523 this.each(function() { 524 var instance = $.data( this, fullName ); 525 if ( instance ) { 526 instance.option( options || {} ); 527 if ( instance._init ) { 528 instance._init(); 529 } 530 } else { 531 $.data( this, fullName, new object( options, this ) ); 532 } 533 }); 534 } 535 536 return returnValue; 537 }; 538 }; 539 540 $.Widget = function( /* options, element */ ) {}; 541 $.Widget._childConstructors = []; 542 543 $.Widget.prototype = { 544 widgetName: "widget", 545 widgetEventPrefix: "", 546 defaultElement: "<div>", 547 options: { 548 disabled: false, 549 550 // callbacks 551 create: null 552 }, 553 _createWidget: function( options, element ) { 554 element = $( element || this.defaultElement || this )[ 0 ]; 555 this.element = $( element ); 556 this.uuid = widget_uuid++; 557 this.eventNamespace = "." + this.widgetName + this.uuid; 558 559 this.bindings = $(); 560 this.hoverable = $(); 561 this.focusable = $(); 562 563 if ( element !== this ) { 564 $.data( element, this.widgetFullName, this ); 565 this._on( true, this.element, { 566 remove: function( event ) { 567 if ( event.target === element ) { 568 this.destroy(); 569 } 570 } 571 }); 572 this.document = $( element.style ? 573 // element within the document 574 element.ownerDocument : 575 // element is window or document 576 element.document || element ); 577 this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); 578 } 579 580 this.options = $.widget.extend( {}, 581 this.options, 582 this._getCreateOptions(), 583 options ); 584 585 this._create(); 586 this._trigger( "create", null, this._getCreateEventData() ); 587 this._init(); 588 }, 589 _getCreateOptions: $.noop, 590 _getCreateEventData: $.noop, 591 _create: $.noop, 592 _init: $.noop, 593 594 destroy: function() { 595 this._destroy(); 596 // we can probably remove the unbind calls in 2.0 597 // all event bindings should go through this._on() 598 this.element 599 .unbind( this.eventNamespace ) 600 .removeData( this.widgetFullName ) 601 // support: jquery <1.6.3 602 // http://bugs.jquery.com/ticket/9413 603 .removeData( $.camelCase( this.widgetFullName ) ); 604 this.widget() 605 .unbind( this.eventNamespace ) 606 .removeAttr( "aria-disabled" ) 607 .removeClass( 608 this.widgetFullName + "-disabled " + 609 "ui-state-disabled" ); 610 611 // clean up events and states 612 this.bindings.unbind( this.eventNamespace ); 613 this.hoverable.removeClass( "ui-state-hover" ); 614 this.focusable.removeClass( "ui-state-focus" ); 615 }, 616 _destroy: $.noop, 617 618 widget: function() { 619 return this.element; 620 }, 621 622 option: function( key, value ) { 623 var options = key, 624 parts, 625 curOption, 626 i; 627 628 if ( arguments.length === 0 ) { 629 // don't return a reference to the internal hash 630 return $.widget.extend( {}, this.options ); 631 } 632 633 if ( typeof key === "string" ) { 634 // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } 635 options = {}; 636 parts = key.split( "." ); 637 key = parts.shift(); 638 if ( parts.length ) { 639 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); 640 for ( i = 0; i < parts.length - 1; i++ ) { 641 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; 642 curOption = curOption[ parts[ i ] ]; 643 } 644 key = parts.pop(); 645 if ( arguments.length === 1 ) { 646 return curOption[ key ] === undefined ? null : curOption[ key ]; 647 } 648 curOption[ key ] = value; 649 } else { 650 if ( arguments.length === 1 ) { 651 return this.options[ key ] === undefined ? null : this.options[ key ]; 652 } 653 options[ key ] = value; 654 } 655 } 656 657 this._setOptions( options ); 658 659 return this; 660 }, 661 _setOptions: function( options ) { 662 var key; 663 664 for ( key in options ) { 665 this._setOption( key, options[ key ] ); 666 } 667 668 return this; 669 }, 670 _setOption: function( key, value ) { 671 this.options[ key ] = value; 672 673 if ( key === "disabled" ) { 674 this.widget() 675 .toggleClass( this.widgetFullName + "-disabled", !!value ); 676 677 // If the widget is becoming disabled, then nothing is interactive 678 if ( value ) { 679 this.hoverable.removeClass( "ui-state-hover" ); 680 this.focusable.removeClass( "ui-state-focus" ); 681 } 682 } 683 684 return this; 685 }, 686 687 enable: function() { 688 return this._setOptions({ disabled: false }); 689 }, 690 disable: function() { 691 return this._setOptions({ disabled: true }); 692 }, 693 694 _on: function( suppressDisabledCheck, element, handlers ) { 695 var delegateElement, 696 instance = this; 697 698 // no suppressDisabledCheck flag, shuffle arguments 699 if ( typeof suppressDisabledCheck !== "boolean" ) { 700 handlers = element; 701 element = suppressDisabledCheck; 702 suppressDisabledCheck = false; 703 } 704 705 // no element argument, shuffle and use this.element 706 if ( !handlers ) { 707 handlers = element; 708 element = this.element; 709 delegateElement = this.widget(); 710 } else { 711 element = delegateElement = $( element ); 712 this.bindings = this.bindings.add( element ); 713 } 714 715 $.each( handlers, function( event, handler ) { 716 function handlerProxy() { 717 // allow widgets to customize the disabled handling 718 // - disabled as an array instead of boolean 719 // - disabled class as method for disabling individual parts 720 if ( !suppressDisabledCheck && 721 ( instance.options.disabled === true || 722 $( this ).hasClass( "ui-state-disabled" ) ) ) { 723 return; 724 } 725 return ( typeof handler === "string" ? instance[ handler ] : handler ) 726 .apply( instance, arguments ); 727 } 728 729 // copy the guid so direct unbinding works 730 if ( typeof handler !== "string" ) { 731 handlerProxy.guid = handler.guid = 732 handler.guid || handlerProxy.guid || $.guid++; 733 } 734 735 var match = event.match( /^([\w:-]*)\s*(.*)$/ ), 736 eventName = match[1] + instance.eventNamespace, 737 selector = match[2]; 738 if ( selector ) { 739 delegateElement.delegate( selector, eventName, handlerProxy ); 740 } else { 741 element.bind( eventName, handlerProxy ); 742 } 743 }); 744 }, 745 746 _off: function( element, eventName ) { 747 eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + 748 this.eventNamespace; 749 element.unbind( eventName ).undelegate( eventName ); 750 751 // Clear the stack to avoid memory leaks (#10056) 752 this.bindings = $( this.bindings.not( element ).get() ); 753 this.focusable = $( this.focusable.not( element ).get() ); 754 this.hoverable = $( this.hoverable.not( element ).get() ); 755 }, 756 757 _delay: function( handler, delay ) { 758 function handlerProxy() { 759 return ( typeof handler === "string" ? instance[ handler ] : handler ) 760 .apply( instance, arguments ); 761 } 762 var instance = this; 763 return setTimeout( handlerProxy, delay || 0 ); 764 }, 765 766 _hoverable: function( element ) { 767 this.hoverable = this.hoverable.add( element ); 768 this._on( element, { 769 mouseenter: function( event ) { 770 $( event.currentTarget ).addClass( "ui-state-hover" ); 771 }, 772 mouseleave: function( event ) { 773 $( event.currentTarget ).removeClass( "ui-state-hover" ); 774 } 775 }); 776 }, 777 778 _focusable: function( element ) { 779 this.focusable = this.focusable.add( element ); 780 this._on( element, { 781 focusin: function( event ) { 782 $( event.currentTarget ).addClass( "ui-state-focus" ); 783 }, 784 focusout: function( event ) { 785 $( event.currentTarget ).removeClass( "ui-state-focus" ); 786 } 787 }); 788 }, 789 790 _trigger: function( type, event, data ) { 791 var prop, orig, 792 callback = this.options[ type ]; 793 794 data = data || {}; 795 event = $.Event( event ); 796 event.type = ( type === this.widgetEventPrefix ? 797 type : 798 this.widgetEventPrefix + type ).toLowerCase(); 799 // the original event may come from any element 800 // so we need to reset the target on the new event 801 event.target = this.element[ 0 ]; 802 803 // copy original event properties over to the new event 804 orig = event.originalEvent; 805 if ( orig ) { 806 for ( prop in orig ) { 807 if ( !( prop in event ) ) { 808 event[ prop ] = orig[ prop ]; 809 } 810 } 811 } 812 813 this.element.trigger( event, data ); 814 return !( $.isFunction( callback ) && 815 callback.apply( this.element[0], [ event ].concat( data ) ) === false || 816 event.isDefaultPrevented() ); 817 } 818 }; 819 820 $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { 821 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { 822 if ( typeof options === "string" ) { 823 options = { effect: options }; 824 } 825 var hasOptions, 826 effectName = !options ? 827 method : 828 options === true || typeof options === "number" ? 829 defaultEffect : 830 options.effect || defaultEffect; 831 options = options || {}; 832 if ( typeof options === "number" ) { 833 options = { duration: options }; 834 } 835 hasOptions = !$.isEmptyObject( options ); 836 options.complete = callback; 837 if ( options.delay ) { 838 element.delay( options.delay ); 839 } 840 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { 841 element[ method ]( options ); 842 } else if ( effectName !== method && element[ effectName ] ) { 843 element[ effectName ]( options.duration, options.easing, callback ); 844 } else { 845 element.queue(function( next ) { 846 $( this )[ method ](); 847 if ( callback ) { 848 callback.call( element[ 0 ] ); 849 } 850 next(); 851 }); 852 } 853 }; 854 }); 855 856 var widget = $.widget; 857 858 859 /*! 860 * jQuery UI Mouse 1.11.4 861 * http://jqueryui.com 862 * 863 * Copyright jQuery Foundation and other contributors 864 * Released under the MIT license. 865 * http://jquery.org/license 866 * 867 * http://api.jqueryui.com/mouse/ 868 */ 869 870 871 var mouseHandled = false; 872 $( document ).mouseup( function() { 873 mouseHandled = false; 874 }); 875 876 var mouse = $.widget("ui.mouse", { 877 version: "1.11.4", 878 options: { 879 cancel: "input,textarea,button,select,option", 880 distance: 1, 881 delay: 0 882 }, 883 _mouseInit: function() { 884 var that = this; 885 886 this.element 887 .bind("mousedown." + this.widgetName, function(event) { 888 return that._mouseDown(event); 889 }) 890 .bind("click." + this.widgetName, function(event) { 891 if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) { 892 $.removeData(event.target, that.widgetName + ".preventClickEvent"); 893 event.stopImmediatePropagation(); 894 return false; 895 } 896 }); 897 898 this.started = false; 899 }, 900 901 // TODO: make sure destroying one instance of mouse doesn't mess with 902 // other instances of mouse 903 _mouseDestroy: function() { 904 this.element.unbind("." + this.widgetName); 905 if ( this._mouseMoveDelegate ) { 906 this.document 907 .unbind("mousemove." + this.widgetName, this._mouseMoveDelegate) 908 .unbind("mouseup." + this.widgetName, this._mouseUpDelegate); 909 } 910 }, 911 912 _mouseDown: function(event) { 913 // don't let more than one widget handle mouseStart 914 if ( mouseHandled ) { 915 return; 916 } 917 918 this._mouseMoved = false; 919 920 // we may have missed mouseup (out of window) 921 (this._mouseStarted && this._mouseUp(event)); 922 923 this._mouseDownEvent = event; 924 925 var that = this, 926 btnIsLeft = (event.which === 1), 927 // event.target.nodeName works around a bug in IE 8 with 928 // disabled inputs (#7620) 929 elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); 930 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { 931 return true; 932 } 933 934 this.mouseDelayMet = !this.options.delay; 935 if (!this.mouseDelayMet) { 936 this._mouseDelayTimer = setTimeout(function() { 937 that.mouseDelayMet = true; 938 }, this.options.delay); 939 } 940 941 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 942 this._mouseStarted = (this._mouseStart(event) !== false); 943 if (!this._mouseStarted) { 944 event.preventDefault(); 945 return true; 946 } 947 } 948 949 // Click event may never have fired (Gecko & Opera) 950 if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) { 951 $.removeData(event.target, this.widgetName + ".preventClickEvent"); 952 } 953 954 // these delegates are required to keep context 955 this._mouseMoveDelegate = function(event) { 956 return that._mouseMove(event); 957 }; 958 this._mouseUpDelegate = function(event) { 959 return that._mouseUp(event); 960 }; 961 962 this.document 963 .bind( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 964 .bind( "mouseup." + this.widgetName, this._mouseUpDelegate ); 965 966 event.preventDefault(); 967 968 mouseHandled = true; 969 return true; 970 }, 971 972 _mouseMove: function(event) { 973 // Only check for mouseups outside the document if you've moved inside the document 974 // at least once. This prevents the firing of mouseup in the case of IE<9, which will 975 // fire a mousemove event if content is placed under the cursor. See #7778 976 // Support: IE <9 977 if ( this._mouseMoved ) { 978 // IE mouseup check - mouseup happened when mouse was out of window 979 if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) { 980 return this._mouseUp(event); 981 982 // Iframe mouseup check - mouseup occurred in another document 983 } else if ( !event.which ) { 984 return this._mouseUp( event ); 985 } 986 } 987 988 if ( event.which || event.button ) { 989 this._mouseMoved = true; 990 } 991 992 if (this._mouseStarted) { 993 this._mouseDrag(event); 994 return event.preventDefault(); 995 } 996 997 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 998 this._mouseStarted = 999 (this._mouseStart(this._mouseDownEvent, event) !== false); 1000 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); 1001 } 1002 1003 return !this._mouseStarted; 1004 }, 1005 1006 _mouseUp: function(event) { 1007 this.document 1008 .unbind( "mousemove." + this.widgetName, this._mouseMoveDelegate ) 1009 .unbind( "mouseup." + this.widgetName, this._mouseUpDelegate ); 1010 1011 if (this._mouseStarted) { 1012 this._mouseStarted = false; 1013 1014 if (event.target === this._mouseDownEvent.target) { 1015 $.data(event.target, this.widgetName + ".preventClickEvent", true); 1016 } 1017 1018 this._mouseStop(event); 1019 } 1020 1021 mouseHandled = false; 1022 return false; 1023 }, 1024 1025 _mouseDistanceMet: function(event) { 1026 return (Math.max( 1027 Math.abs(this._mouseDownEvent.pageX - event.pageX), 1028 Math.abs(this._mouseDownEvent.pageY - event.pageY) 1029 ) >= this.options.distance 1030 ); 1031 }, 1032 1033 _mouseDelayMet: function(/* event */) { 1034 return this.mouseDelayMet; 1035 }, 1036 1037 // These are placeholder methods, to be overriden by extending plugin 1038 _mouseStart: function(/* event */) {}, 1039 _mouseDrag: function(/* event */) {}, 1040 _mouseStop: function(/* event */) {}, 1041 _mouseCapture: function(/* event */) { return true; } 1042 }); 1043 1044 1045 /*! 1046 * jQuery UI Position 1.11.4 1047 * http://jqueryui.com 1048 * 1049 * Copyright jQuery Foundation and other contributors 1050 * Released under the MIT license. 1051 * http://jquery.org/license 1052 * 1053 * http://api.jqueryui.com/position/ 1054 */ 1055 1056 (function() { 1057 1058 $.ui = $.ui || {}; 1059 1060 var cachedScrollbarWidth, supportsOffsetFractions, 1061 max = Math.max, 1062 abs = Math.abs, 1063 round = Math.round, 1064 rhorizontal = /left|center|right/, 1065 rvertical = /top|center|bottom/, 1066 roffset = /[\+\-]\d+(\.[\d]+)?%?/, 1067 rposition = /^\w+/, 1068 rpercent = /%$/, 1069 _position = $.fn.position; 1070 1071 function getOffsets( offsets, width, height ) { 1072 return [ 1073 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), 1074 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) 1075 ]; 1076 } 1077 1078 function parseCss( element, property ) { 1079 return parseInt( $.css( element, property ), 10 ) || 0; 1080 } 1081 1082 function getDimensions( elem ) { 1083 var raw = elem[0]; 1084 if ( raw.nodeType === 9 ) { 1085 return { 1086 width: elem.width(), 1087 height: elem.height(), 1088 offset: { top: 0, left: 0 } 1089 }; 1090 } 1091 if ( $.isWindow( raw ) ) { 1092 return { 1093 width: elem.width(), 1094 height: elem.height(), 1095 offset: { top: elem.scrollTop(), left: elem.scrollLeft() } 1096 }; 1097 } 1098 if ( raw.preventDefault ) { 1099 return { 1100 width: 0, 1101 height: 0, 1102 offset: { top: raw.pageY, left: raw.pageX } 1103 }; 1104 } 1105 return { 1106 width: elem.outerWidth(), 1107 height: elem.outerHeight(), 1108 offset: elem.offset() 1109 }; 1110 } 1111 1112 $.position = { 1113 scrollbarWidth: function() { 1114 if ( cachedScrollbarWidth !== undefined ) { 1115 return cachedScrollbarWidth; 1116 } 1117 var w1, w2, 1118 div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ), 1119 innerDiv = div.children()[0]; 1120 1121 $( "body" ).append( div ); 1122 w1 = innerDiv.offsetWidth; 1123 div.css( "overflow", "scroll" ); 1124 1125 w2 = innerDiv.offsetWidth; 1126 1127 if ( w1 === w2 ) { 1128 w2 = div[0].clientWidth; 1129 } 1130 1131 div.remove(); 1132 1133 return (cachedScrollbarWidth = w1 - w2); 1134 }, 1135 getScrollInfo: function( within ) { 1136 var overflowX = within.isWindow || within.isDocument ? "" : 1137 within.element.css( "overflow-x" ), 1138 overflowY = within.isWindow || within.isDocument ? "" : 1139 within.element.css( "overflow-y" ), 1140 hasOverflowX = overflowX === "scroll" || 1141 ( overflowX === "auto" && within.width < within.element[0].scrollWidth ), 1142 hasOverflowY = overflowY === "scroll" || 1143 ( overflowY === "auto" && within.height < within.element[0].scrollHeight ); 1144 return { 1145 width: hasOverflowY ? $.position.scrollbarWidth() : 0, 1146 height: hasOverflowX ? $.position.scrollbarWidth() : 0 1147 }; 1148 }, 1149 getWithinInfo: function( element ) { 1150 var withinElement = $( element || window ), 1151 isWindow = $.isWindow( withinElement[0] ), 1152 isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9; 1153 return { 1154 element: withinElement, 1155 isWindow: isWindow, 1156 isDocument: isDocument, 1157 offset: withinElement.offset() || { left: 0, top: 0 }, 1158 scrollLeft: withinElement.scrollLeft(), 1159 scrollTop: withinElement.scrollTop(), 1160 1161 // support: jQuery 1.6.x 1162 // jQuery 1.6 doesn't support .outerWidth/Height() on documents or windows 1163 width: isWindow || isDocument ? withinElement.width() : withinElement.outerWidth(), 1164 height: isWindow || isDocument ? withinElement.height() : withinElement.outerHeight() 1165 }; 1166 } 1167 }; 1168 1169 $.fn.position = function( options ) { 1170 if ( !options || !options.of ) { 1171 return _position.apply( this, arguments ); 1172 } 1173 1174 // make a copy, we don't want to modify arguments 1175 options = $.extend( {}, options ); 1176 1177 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, 1178 target = $( options.of ), 1179 within = $.position.getWithinInfo( options.within ), 1180 scrollInfo = $.position.getScrollInfo( within ), 1181 collision = ( options.collision || "flip" ).split( " " ), 1182 offsets = {}; 1183 1184 dimensions = getDimensions( target ); 1185 if ( target[0].preventDefault ) { 1186 // force left top to allow flipping 1187 options.at = "left top"; 1188 } 1189 targetWidth = dimensions.width; 1190 targetHeight = dimensions.height; 1191 targetOffset = dimensions.offset; 1192 // clone to reuse original targetOffset later 1193 basePosition = $.extend( {}, targetOffset ); 1194 1195 // force my and at to have valid horizontal and vertical positions 1196 // if a value is missing or invalid, it will be converted to center 1197 $.each( [ "my", "at" ], function() { 1198 var pos = ( options[ this ] || "" ).split( " " ), 1199 horizontalOffset, 1200 verticalOffset; 1201 1202 if ( pos.length === 1) { 1203 pos = rhorizontal.test( pos[ 0 ] ) ? 1204 pos.concat( [ "center" ] ) : 1205 rvertical.test( pos[ 0 ] ) ? 1206 [ "center" ].concat( pos ) : 1207 [ "center", "center" ]; 1208 } 1209 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; 1210 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; 1211 1212 // calculate offsets 1213 horizontalOffset = roffset.exec( pos[ 0 ] ); 1214 verticalOffset = roffset.exec( pos[ 1 ] ); 1215 offsets[ this ] = [ 1216 horizontalOffset ? horizontalOffset[ 0 ] : 0, 1217 verticalOffset ? verticalOffset[ 0 ] : 0 1218 ]; 1219 1220 // reduce to just the positions without the offsets 1221 options[ this ] = [ 1222 rposition.exec( pos[ 0 ] )[ 0 ], 1223 rposition.exec( pos[ 1 ] )[ 0 ] 1224 ]; 1225 }); 1226 1227 // normalize collision option 1228 if ( collision.length === 1 ) { 1229 collision[ 1 ] = collision[ 0 ]; 1230 } 1231 1232 if ( options.at[ 0 ] === "right" ) { 1233 basePosition.left += targetWidth; 1234 } else if ( options.at[ 0 ] === "center" ) { 1235 basePosition.left += targetWidth / 2; 1236 } 1237 1238 if ( options.at[ 1 ] === "bottom" ) { 1239 basePosition.top += targetHeight; 1240 } else if ( options.at[ 1 ] === "center" ) { 1241 basePosition.top += targetHeight / 2; 1242 } 1243 1244 atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); 1245 basePosition.left += atOffset[ 0 ]; 1246 basePosition.top += atOffset[ 1 ]; 1247 1248 return this.each(function() { 1249 var collisionPosition, using, 1250 elem = $( this ), 1251 elemWidth = elem.outerWidth(), 1252 elemHeight = elem.outerHeight(), 1253 marginLeft = parseCss( this, "marginLeft" ), 1254 marginTop = parseCss( this, "marginTop" ), 1255 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width, 1256 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height, 1257 position = $.extend( {}, basePosition ), 1258 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); 1259 1260 if ( options.my[ 0 ] === "right" ) { 1261 position.left -= elemWidth; 1262 } else if ( options.my[ 0 ] === "center" ) { 1263 position.left -= elemWidth / 2; 1264 } 1265 1266 if ( options.my[ 1 ] === "bottom" ) { 1267 position.top -= elemHeight; 1268 } else if ( options.my[ 1 ] === "center" ) { 1269 position.top -= elemHeight / 2; 1270 } 1271 1272 position.left += myOffset[ 0 ]; 1273 position.top += myOffset[ 1 ]; 1274 1275 // if the browser doesn't support fractions, then round for consistent results 1276 if ( !supportsOffsetFractions ) { 1277 position.left = round( position.left ); 1278 position.top = round( position.top ); 1279 } 1280 1281 collisionPosition = { 1282 marginLeft: marginLeft, 1283 marginTop: marginTop 1284 }; 1285 1286 $.each( [ "left", "top" ], function( i, dir ) { 1287 if ( $.ui.position[ collision[ i ] ] ) { 1288 $.ui.position[ collision[ i ] ][ dir ]( position, { 1289 targetWidth: targetWidth, 1290 targetHeight: targetHeight, 1291 elemWidth: elemWidth, 1292 elemHeight: elemHeight, 1293 collisionPosition: collisionPosition, 1294 collisionWidth: collisionWidth, 1295 collisionHeight: collisionHeight, 1296 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], 1297 my: options.my, 1298 at: options.at, 1299 within: within, 1300 elem: elem 1301 }); 1302 } 1303 }); 1304 1305 if ( options.using ) { 1306 // adds feedback as second argument to using callback, if present 1307 using = function( props ) { 1308 var left = targetOffset.left - position.left, 1309 right = left + targetWidth - elemWidth, 1310 top = targetOffset.top - position.top, 1311 bottom = top + targetHeight - elemHeight, 1312 feedback = { 1313 target: { 1314 element: target, 1315 left: targetOffset.left, 1316 top: targetOffset.top, 1317 width: targetWidth, 1318 height: targetHeight 1319 }, 1320 element: { 1321 element: elem, 1322 left: position.left, 1323 top: position.top, 1324 width: elemWidth, 1325 height: elemHeight 1326 }, 1327 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", 1328 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" 1329 }; 1330 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { 1331 feedback.horizontal = "center"; 1332 } 1333 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { 1334 feedback.vertical = "middle"; 1335 } 1336 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { 1337 feedback.important = "horizontal"; 1338 } else { 1339 feedback.important = "vertical"; 1340 } 1341 options.using.call( this, props, feedback ); 1342 }; 1343 } 1344 1345 elem.offset( $.extend( position, { using: using } ) ); 1346 }); 1347 }; 1348 1349 $.ui.position = { 1350 fit: { 1351 left: function( position, data ) { 1352 var within = data.within, 1353 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, 1354 outerWidth = within.width, 1355 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 1356 overLeft = withinOffset - collisionPosLeft, 1357 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, 1358 newOverRight; 1359 1360 // element is wider than within 1361 if ( data.collisionWidth > outerWidth ) { 1362 // element is initially over the left side of within 1363 if ( overLeft > 0 && overRight <= 0 ) { 1364 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset; 1365 position.left += overLeft - newOverRight; 1366 // element is initially over right side of within 1367 } else if ( overRight > 0 && overLeft <= 0 ) { 1368 position.left = withinOffset; 1369 // element is initially over both left and right sides of within 1370 } else { 1371 if ( overLeft > overRight ) { 1372 position.left = withinOffset + outerWidth - data.collisionWidth; 1373 } else { 1374 position.left = withinOffset; 1375 } 1376 } 1377 // too far left -> align with left edge 1378 } else if ( overLeft > 0 ) { 1379 position.left += overLeft; 1380 // too far right -> align with right edge 1381 } else if ( overRight > 0 ) { 1382 position.left -= overRight; 1383 // adjust based on position and margin 1384 } else { 1385 position.left = max( position.left - collisionPosLeft, position.left ); 1386 } 1387 }, 1388 top: function( position, data ) { 1389 var within = data.within, 1390 withinOffset = within.isWindow ? within.scrollTop : within.offset.top, 1391 outerHeight = data.within.height, 1392 collisionPosTop = position.top - data.collisionPosition.marginTop, 1393 overTop = withinOffset - collisionPosTop, 1394 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, 1395 newOverBottom; 1396 1397 // element is taller than within 1398 if ( data.collisionHeight > outerHeight ) { 1399 // element is initially over the top of within 1400 if ( overTop > 0 && overBottom <= 0 ) { 1401 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset; 1402 position.top += overTop - newOverBottom; 1403 // element is initially over bottom of within 1404 } else if ( overBottom > 0 && overTop <= 0 ) { 1405 position.top = withinOffset; 1406 // element is initially over both top and bottom of within 1407 } else { 1408 if ( overTop > overBottom ) { 1409 position.top = withinOffset + outerHeight - data.collisionHeight; 1410 } else { 1411 position.top = withinOffset; 1412 } 1413 } 1414 // too far up -> align with top 1415 } else if ( overTop > 0 ) { 1416 position.top += overTop; 1417 // too far down -> align with bottom edge 1418 } else if ( overBottom > 0 ) { 1419 position.top -= overBottom; 1420 // adjust based on position and margin 1421 } else { 1422 position.top = max( position.top - collisionPosTop, position.top ); 1423 } 1424 } 1425 }, 1426 flip: { 1427 left: function( position, data ) { 1428 var within = data.within, 1429 withinOffset = within.offset.left + within.scrollLeft, 1430 outerWidth = within.width, 1431 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, 1432 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 1433 overLeft = collisionPosLeft - offsetLeft, 1434 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, 1435 myOffset = data.my[ 0 ] === "left" ? 1436 -data.elemWidth : 1437 data.my[ 0 ] === "right" ? 1438 data.elemWidth : 1439 0, 1440 atOffset = data.at[ 0 ] === "left" ? 1441 data.targetWidth : 1442 data.at[ 0 ] === "right" ? 1443 -data.targetWidth : 1444 0, 1445 offset = -2 * data.offset[ 0 ], 1446 newOverRight, 1447 newOverLeft; 1448 1449 if ( overLeft < 0 ) { 1450 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset; 1451 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { 1452 position.left += myOffset + atOffset + offset; 1453 } 1454 } else if ( overRight > 0 ) { 1455 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft; 1456 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { 1457 position.left += myOffset + atOffset + offset; 1458 } 1459 } 1460 }, 1461 top: function( position, data ) { 1462 var within = data.within, 1463 withinOffset = within.offset.top + within.scrollTop, 1464 outerHeight = within.height, 1465 offsetTop = within.isWindow ? within.scrollTop : within.offset.top, 1466 collisionPosTop = position.top - data.collisionPosition.marginTop, 1467 overTop = collisionPosTop - offsetTop, 1468 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, 1469 top = data.my[ 1 ] === "top", 1470 myOffset = top ? 1471 -data.elemHeight : 1472 data.my[ 1 ] === "bottom" ? 1473 data.elemHeight : 1474 0, 1475 atOffset = data.at[ 1 ] === "top" ? 1476 data.targetHeight : 1477 data.at[ 1 ] === "bottom" ? 1478 -data.targetHeight : 1479 0, 1480 offset = -2 * data.offset[ 1 ], 1481 newOverTop, 1482 newOverBottom; 1483 if ( overTop < 0 ) { 1484 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset; 1485 if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) { 1486 position.top += myOffset + atOffset + offset; 1487 } 1488 } else if ( overBottom > 0 ) { 1489 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop; 1490 if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) { 1491 position.top += myOffset + atOffset + offset; 1492 } 1493 } 1494 } 1495 }, 1496 flipfit: { 1497 left: function() { 1498 $.ui.position.flip.left.apply( this, arguments ); 1499 $.ui.position.fit.left.apply( this, arguments ); 1500 }, 1501 top: function() { 1502 $.ui.position.flip.top.apply( this, arguments ); 1503 $.ui.position.fit.top.apply( this, arguments ); 1504 } 1505 } 1506 }; 1507 1508 // fraction support test 1509 (function() { 1510 var testElement, testElementParent, testElementStyle, offsetLeft, i, 1511 body = document.getElementsByTagName( "body" )[ 0 ], 1512 div = document.createElement( "div" ); 1513 1514 //Create a "fake body" for testing based on method used in jQuery.support 1515 testElement = document.createElement( body ? "div" : "body" ); 1516 testElementStyle = { 1517 visibility: "hidden", 1518 width: 0, 1519 height: 0, 1520 border: 0, 1521 margin: 0, 1522 background: "none" 1523 }; 1524 if ( body ) { 1525 $.extend( testElementStyle, { 1526 position: "absolute", 1527 left: "-1000px", 1528 top: "-1000px" 1529 }); 1530 } 1531 for ( i in testElementStyle ) { 1532 testElement.style[ i ] = testElementStyle[ i ]; 1533 } 1534 testElement.appendChild( div ); 1535 testElementParent = body || document.documentElement; 1536 testElementParent.insertBefore( testElement, testElementParent.firstChild ); 1537 1538 div.style.cssText = "position: absolute; left: 10.7432222px;"; 1539 1540 offsetLeft = $( div ).offset().left; 1541 supportsOffsetFractions = offsetLeft > 10 && offsetLeft < 11; 1542 1543 testElement.innerHTML = ""; 1544 testElementParent.removeChild( testElement ); 1545 })(); 1546 1547 })(); 1548 1549 var position = $.ui.position; 1550 1551 1552 /*! 1553 * jQuery UI Draggable 1.11.4 1554 * http://jqueryui.com 1555 * 1556 * Copyright jQuery Foundation and other contributors 1557 * Released under the MIT license. 1558 * http://jquery.org/license 1559 * 1560 * http://api.jqueryui.com/draggable/ 1561 */ 1562 1563 1564 $.widget("ui.draggable", $.ui.mouse, { 1565 version: "1.11.4", 1566 widgetEventPrefix: "drag", 1567 options: { 1568 addClasses: true, 1569 appendTo: "parent", 1570 axis: false, 1571 connectToSortable: false, 1572 containment: false, 1573 cursor: "auto", 1574 cursorAt: false, 1575 grid: false, 1576 handle: false, 1577 helper: "original", 1578 iframeFix: false, 1579 opacity: false, 1580 refreshPositions: false, 1581 revert: false, 1582 revertDuration: 500, 1583 scope: "default", 1584 scroll: true, 1585 scrollSensitivity: 20, 1586 scrollSpeed: 20, 1587 snap: false, 1588 snapMode: "both", 1589 snapTolerance: 20, 1590 stack: false, 1591 zIndex: false, 1592 1593 // callbacks 1594 drag: null, 1595 start: null, 1596 stop: null 1597 }, 1598 _create: function() { 1599 1600 if ( this.options.helper === "original" ) { 1601 this._setPositionRelative(); 1602 } 1603 if (this.options.addClasses){ 1604 this.element.addClass("ui-draggable"); 1605 } 1606 if (this.options.disabled){ 1607 this.element.addClass("ui-draggable-disabled"); 1608 } 1609 this._setHandleClassName(); 1610 1611 this._mouseInit(); 1612 }, 1613 1614 _setOption: function( key, value ) { 1615 this._super( key, value ); 1616 if ( key === "handle" ) { 1617 this._removeHandleClassName(); 1618 this._setHandleClassName(); 1619 } 1620 }, 1621 1622 _destroy: function() { 1623 if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) { 1624 this.destroyOnClear = true; 1625 return; 1626 } 1627 this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" ); 1628 this._removeHandleClassName(); 1629 this._mouseDestroy(); 1630 }, 1631 1632 _mouseCapture: function(event) { 1633 var o = this.options; 1634 1635 this._blurActiveElement( event ); 1636 1637 // among others, prevent a drag on a resizable-handle 1638 if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) { 1639 return false; 1640 } 1641 1642 //Quit if we're not on a valid handle 1643 this.handle = this._getHandle(event); 1644 if (!this.handle) { 1645 return false; 1646 } 1647 1648 this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix ); 1649 1650 return true; 1651 1652 }, 1653 1654 _blockFrames: function( selector ) { 1655 this.iframeBlocks = this.document.find( selector ).map(function() { 1656 var iframe = $( this ); 1657 1658 return $( "<div>" ) 1659 .css( "position", "absolute" ) 1660 .appendTo( iframe.parent() ) 1661 .outerWidth( iframe.outerWidth() ) 1662 .outerHeight( iframe.outerHeight() ) 1663 .offset( iframe.offset() )[ 0 ]; 1664 }); 1665 }, 1666 1667 _unblockFrames: function() { 1668 if ( this.iframeBlocks ) { 1669 this.iframeBlocks.remove(); 1670 delete this.iframeBlocks; 1671 } 1672 }, 1673 1674 _blurActiveElement: function( event ) { 1675 var document = this.document[ 0 ]; 1676 1677 // Only need to blur if the event occurred on the draggable itself, see #10527 1678 if ( !this.handleElement.is( event.target ) ) { 1679 return; 1680 } 1681 1682 // support: IE9 1683 // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe> 1684 try { 1685 1686 // Support: IE9, IE10 1687 // If the <body> is blurred, IE will switch windows, see #9520 1688 if ( document.activeElement && document.activeElement.nodeName.toLowerCase() !== "body" ) { 1689 1690 // Blur any element that currently has focus, see #4261 1691 $( document.activeElement ).blur(); 1692 } 1693 } catch ( error ) {} 1694 }, 1695 1696 _mouseStart: function(event) { 1697 1698 var o = this.options; 1699 1700 //Create and append the visible helper 1701 this.helper = this._createHelper(event); 1702 1703 this.helper.addClass("ui-draggable-dragging"); 1704 1705 //Cache the helper size 1706 this._cacheHelperProportions(); 1707 1708 //If ddmanager is used for droppables, set the global draggable 1709 if ($.ui.ddmanager) { 1710 $.ui.ddmanager.current = this; 1711 } 1712 1713 /* 1714 * - Position generation - 1715 * This block generates everything position related - it's the core of draggables. 1716 */ 1717 1718 //Cache the margins of the original element 1719 this._cacheMargins(); 1720 1721 //Store the helper's css position 1722 this.cssPosition = this.helper.css( "position" ); 1723 this.scrollParent = this.helper.scrollParent( true ); 1724 this.offsetParent = this.helper.offsetParent(); 1725 this.hasFixedAncestor = this.helper.parents().filter(function() { 1726 return $( this ).css( "position" ) === "fixed"; 1727 }).length > 0; 1728 1729 //The element's absolute position on the page minus margins 1730 this.positionAbs = this.element.offset(); 1731 this._refreshOffsets( event ); 1732 1733 //Generate the original position 1734 this.originalPosition = this.position = this._generatePosition( event, false ); 1735 this.originalPageX = event.pageX; 1736 this.originalPageY = event.pageY; 1737 1738 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 1739 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); 1740 1741 //Set a containment if given in the options 1742 this._setContainment(); 1743 1744 //Trigger event + callbacks 1745 if (this._trigger("start", event) === false) { 1746 this._clear(); 1747 return false; 1748 } 1749 1750 //Recache the helper size 1751 this._cacheHelperProportions(); 1752 1753 //Prepare the droppable offsets 1754 if ($.ui.ddmanager && !o.dropBehaviour) { 1755 $.ui.ddmanager.prepareOffsets(this, event); 1756 } 1757 1758 // Reset helper's right/bottom css if they're set and set explicit width/height instead 1759 // as this prevents resizing of elements with right/bottom set (see #7772) 1760 this._normalizeRightBottom(); 1761 1762 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position 1763 1764 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) 1765 if ( $.ui.ddmanager ) { 1766 $.ui.ddmanager.dragStart(this, event); 1767 } 1768 1769 return true; 1770 }, 1771 1772 _refreshOffsets: function( event ) { 1773 this.offset = { 1774 top: this.positionAbs.top - this.margins.top, 1775 left: this.positionAbs.left - this.margins.left, 1776 scroll: false, 1777 parent: this._getParentOffset(), 1778 relative: this._getRelativeOffset() 1779 }; 1780 1781 this.offset.click = { 1782 left: event.pageX - this.offset.left, 1783 top: event.pageY - this.offset.top 1784 }; 1785 }, 1786 1787 _mouseDrag: function(event, noPropagation) { 1788 // reset any necessary cached properties (see #5009) 1789 if ( this.hasFixedAncestor ) { 1790 this.offset.parent = this._getParentOffset(); 1791 } 1792 1793 //Compute the helpers position 1794 this.position = this._generatePosition( event, true ); 1795 this.positionAbs = this._convertPositionTo("absolute"); 1796 1797 //Call plugins and callbacks and use the resulting position if something is returned 1798 if (!noPropagation) { 1799 var ui = this._uiHash(); 1800 if (this._trigger("drag", event, ui) === false) { 1801 this._mouseUp({}); 1802 return false; 1803 } 1804 this.position = ui.position; 1805 } 1806 1807 this.helper[ 0 ].style.left = this.position.left + "px"; 1808 this.helper[ 0 ].style.top = this.position.top + "px"; 1809 1810 if ($.ui.ddmanager) { 1811 $.ui.ddmanager.drag(this, event); 1812 } 1813 1814 return false; 1815 }, 1816 1817 _mouseStop: function(event) { 1818 1819 //If we are using droppables, inform the manager about the drop 1820 var that = this, 1821 dropped = false; 1822 if ($.ui.ddmanager && !this.options.dropBehaviour) { 1823 dropped = $.ui.ddmanager.drop(this, event); 1824 } 1825 1826 //if a drop comes from outside (a sortable) 1827 if (this.dropped) { 1828 dropped = this.dropped; 1829 this.dropped = false; 1830 } 1831 1832 if ((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) { 1833 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { 1834 if (that._trigger("stop", event) !== false) { 1835 that._clear(); 1836 } 1837 }); 1838 } else { 1839 if (this._trigger("stop", event) !== false) { 1840 this._clear(); 1841 } 1842 } 1843 1844 return false; 1845 }, 1846 1847 _mouseUp: function( event ) { 1848 this._unblockFrames(); 1849 1850 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) 1851 if ( $.ui.ddmanager ) { 1852 $.ui.ddmanager.dragStop(this, event); 1853 } 1854 1855 // Only need to focus if the event occurred on the draggable itself, see #10527 1856 if ( this.handleElement.is( event.target ) ) { 1857 // The interaction is over; whether or not the click resulted in a drag, focus the element 1858 this.element.focus(); 1859 } 1860 1861 return $.ui.mouse.prototype._mouseUp.call(this, event); 1862 }, 1863 1864 cancel: function() { 1865 1866 if (this.helper.is(".ui-draggable-dragging")) { 1867 this._mouseUp({}); 1868 } else { 1869 this._clear(); 1870 } 1871 1872 return this; 1873 1874 }, 1875 1876 _getHandle: function(event) { 1877 return this.options.handle ? 1878 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length : 1879 true; 1880 }, 1881 1882 _setHandleClassName: function() { 1883 this.handleElement = this.options.handle ? 1884 this.element.find( this.options.handle ) : this.element; 1885 this.handleElement.addClass( "ui-draggable-handle" ); 1886 }, 1887 1888 _removeHandleClassName: function() { 1889 this.handleElement.removeClass( "ui-draggable-handle" ); 1890 }, 1891 1892 _createHelper: function(event) { 1893 1894 var o = this.options, 1895 helperIsFunction = $.isFunction( o.helper ), 1896 helper = helperIsFunction ? 1897 $( o.helper.apply( this.element[ 0 ], [ event ] ) ) : 1898 ( o.helper === "clone" ? 1899 this.element.clone().removeAttr( "id" ) : 1900 this.element ); 1901 1902 if (!helper.parents("body").length) { 1903 helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo)); 1904 } 1905 1906 // http://bugs.jqueryui.com/ticket/9446 1907 // a helper function can return the original element 1908 // which wouldn't have been set to relative in _create 1909 if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) { 1910 this._setPositionRelative(); 1911 } 1912 1913 if (helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) { 1914 helper.css("position", "absolute"); 1915 } 1916 1917 return helper; 1918 1919 }, 1920 1921 _setPositionRelative: function() { 1922 if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) { 1923 this.element[ 0 ].style.position = "relative"; 1924 } 1925 }, 1926 1927 _adjustOffsetFromHelper: function(obj) { 1928 if (typeof obj === "string") { 1929 obj = obj.split(" "); 1930 } 1931 if ($.isArray(obj)) { 1932 obj = { left: +obj[0], top: +obj[1] || 0 }; 1933 } 1934 if ("left" in obj) { 1935 this.offset.click.left = obj.left + this.margins.left; 1936 } 1937 if ("right" in obj) { 1938 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 1939 } 1940 if ("top" in obj) { 1941 this.offset.click.top = obj.top + this.margins.top; 1942 } 1943 if ("bottom" in obj) { 1944 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 1945 } 1946 }, 1947 1948 _isRootNode: function( element ) { 1949 return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ]; 1950 }, 1951 1952 _getParentOffset: function() { 1953 1954 //Get the offsetParent and cache its position 1955 var po = this.offsetParent.offset(), 1956 document = this.document[ 0 ]; 1957 1958 // This is a special case where we need to modify a offset calculated on start, since the following happened: 1959 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent 1960 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that 1961 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag 1962 if (this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { 1963 po.left += this.scrollParent.scrollLeft(); 1964 po.top += this.scrollParent.scrollTop(); 1965 } 1966 1967 if ( this._isRootNode( this.offsetParent[ 0 ] ) ) { 1968 po = { top: 0, left: 0 }; 1969 } 1970 1971 return { 1972 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0), 1973 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0) 1974 }; 1975 1976 }, 1977 1978 _getRelativeOffset: function() { 1979 if ( this.cssPosition !== "relative" ) { 1980 return { top: 0, left: 0 }; 1981 } 1982 1983 var p = this.element.position(), 1984 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ); 1985 1986 return { 1987 top: p.top - ( parseInt(this.helper.css( "top" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ), 1988 left: p.left - ( parseInt(this.helper.css( "left" ), 10) || 0 ) + ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 ) 1989 }; 1990 1991 }, 1992 1993 _cacheMargins: function() { 1994 this.margins = { 1995 left: (parseInt(this.element.css("marginLeft"), 10) || 0), 1996 top: (parseInt(this.element.css("marginTop"), 10) || 0), 1997 right: (parseInt(this.element.css("marginRight"), 10) || 0), 1998 bottom: (parseInt(this.element.css("marginBottom"), 10) || 0) 1999 }; 2000 }, 2001 2002 _cacheHelperProportions: function() { 2003 this.helperProportions = { 2004 width: this.helper.outerWidth(), 2005 height: this.helper.outerHeight() 2006 }; 2007 }, 2008 2009 _setContainment: function() { 2010 2011 var isUserScrollable, c, ce, 2012 o = this.options, 2013 document = this.document[ 0 ]; 2014 2015 this.relativeContainer = null; 2016 2017 if ( !o.containment ) { 2018 this.containment = null; 2019 return; 2020 } 2021 2022 if ( o.containment === "window" ) { 2023 this.containment = [ 2024 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left, 2025 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top, 2026 $( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left, 2027 $( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top 2028 ]; 2029 return; 2030 } 2031 2032 if ( o.containment === "document") { 2033 this.containment = [ 2034 0, 2035 0, 2036 $( document ).width() - this.helperProportions.width - this.margins.left, 2037 ( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top 2038 ]; 2039 return; 2040 } 2041 2042 if ( o.containment.constructor === Array ) { 2043 this.containment = o.containment; 2044 return; 2045 } 2046 2047 if ( o.containment === "parent" ) { 2048 o.containment = this.helper[ 0 ].parentNode; 2049 } 2050 2051 c = $( o.containment ); 2052 ce = c[ 0 ]; 2053 2054 if ( !ce ) { 2055 return; 2056 } 2057 2058 isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) ); 2059 2060 this.containment = [ 2061 ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ), 2062 ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ), 2063 ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - 2064 ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - 2065 ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - 2066 this.helperProportions.width - 2067 this.margins.left - 2068 this.margins.right, 2069 ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - 2070 ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - 2071 ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - 2072 this.helperProportions.height - 2073 this.margins.top - 2074 this.margins.bottom 2075 ]; 2076 this.relativeContainer = c; 2077 }, 2078 2079 _convertPositionTo: function(d, pos) { 2080 2081 if (!pos) { 2082 pos = this.position; 2083 } 2084 2085 var mod = d === "absolute" ? 1 : -1, 2086 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ); 2087 2088 return { 2089 top: ( 2090 pos.top + // The absolute mouse position 2091 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 2092 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) 2093 ( ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod) 2094 ), 2095 left: ( 2096 pos.left + // The absolute mouse position 2097 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 2098 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) 2099 ( ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod) 2100 ) 2101 }; 2102 2103 }, 2104 2105 _generatePosition: function( event, constrainPosition ) { 2106 2107 var containment, co, top, left, 2108 o = this.options, 2109 scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ), 2110 pageX = event.pageX, 2111 pageY = event.pageY; 2112 2113 // Cache the scroll 2114 if ( !scrollIsRootNode || !this.offset.scroll ) { 2115 this.offset.scroll = { 2116 top: this.scrollParent.scrollTop(), 2117 left: this.scrollParent.scrollLeft() 2118 }; 2119 } 2120 2121 /* 2122 * - Position constraining - 2123 * Constrain the position to a mix of grid, containment. 2124 */ 2125 2126 // If we are not dragging yet, we won't check for options 2127 if ( constrainPosition ) { 2128 if ( this.containment ) { 2129 if ( this.relativeContainer ){ 2130 co = this.relativeContainer.offset(); 2131 containment = [ 2132 this.containment[ 0 ] + co.left, 2133 this.containment[ 1 ] + co.top, 2134 this.containment[ 2 ] + co.left, 2135 this.containment[ 3 ] + co.top 2136 ]; 2137 } else { 2138 containment = this.containment; 2139 } 2140 2141 if (event.pageX - this.offset.click.left < containment[0]) { 2142 pageX = containment[0] + this.offset.click.left; 2143 } 2144 if (event.pageY - this.offset.click.top < containment[1]) { 2145 pageY = containment[1] + this.offset.click.top; 2146 } 2147 if (event.pageX - this.offset.click.left > containment[2]) { 2148 pageX = containment[2] + this.offset.click.left; 2149 } 2150 if (event.pageY - this.offset.click.top > containment[3]) { 2151 pageY = containment[3] + this.offset.click.top; 2152 } 2153 } 2154 2155 if (o.grid) { 2156 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) 2157 top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; 2158 pageY = containment ? ((top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3]) ? top : ((top - this.offset.click.top >= containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; 2159 2160 left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; 2161 pageX = containment ? ((left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2]) ? left : ((left - this.offset.click.left >= containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; 2162 } 2163 2164 if ( o.axis === "y" ) { 2165 pageX = this.originalPageX; 2166 } 2167 2168 if ( o.axis === "x" ) { 2169 pageY = this.originalPageY; 2170 } 2171 } 2172 2173 return { 2174 top: ( 2175 pageY - // The absolute mouse position 2176 this.offset.click.top - // Click offset (relative to the element) 2177 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent 2178 this.offset.parent.top + // The offsetParent's offset without borders (offset + border) 2179 ( this.cssPosition === "fixed" ? -this.offset.scroll.top : ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) 2180 ), 2181 left: ( 2182 pageX - // The absolute mouse position 2183 this.offset.click.left - // Click offset (relative to the element) 2184 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent 2185 this.offset.parent.left + // The offsetParent's offset without borders (offset + border) 2186 ( this.cssPosition === "fixed" ? -this.offset.scroll.left : ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) 2187 ) 2188 }; 2189 2190 }, 2191 2192 _clear: function() { 2193 this.helper.removeClass("ui-draggable-dragging"); 2194 if (this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) { 2195 this.helper.remove(); 2196 } 2197 this.helper = null; 2198 this.cancelHelperRemoval = false; 2199 if ( this.destroyOnClear ) { 2200 this.destroy(); 2201 } 2202 }, 2203 2204 _normalizeRightBottom: function() { 2205 if ( this.options.axis !== "y" && this.helper.css( "right" ) !== "auto" ) { 2206 this.helper.width( this.helper.width() ); 2207 this.helper.css( "right", "auto" ); 2208 } 2209 if ( this.options.axis !== "x" && this.helper.css( "bottom" ) !== "auto" ) { 2210 this.helper.height( this.helper.height() ); 2211 this.helper.css( "bottom", "auto" ); 2212 } 2213 }, 2214 2215 // From now on bulk stuff - mainly helpers 2216 2217 _trigger: function( type, event, ui ) { 2218 ui = ui || this._uiHash(); 2219 $.ui.plugin.call( this, type, [ event, ui, this ], true ); 2220 2221 // Absolute position and offset (see #6884 ) have to be recalculated after plugins 2222 if ( /^(drag|start|stop)/.test( type ) ) { 2223 this.positionAbs = this._convertPositionTo( "absolute" ); 2224 ui.offset = this.positionAbs; 2225 } 2226 return $.Widget.prototype._trigger.call( this, type, event, ui ); 2227 }, 2228 2229 plugins: {}, 2230 2231 _uiHash: function() { 2232 return { 2233 helper: this.helper, 2234 position: this.position, 2235 originalPosition: this.originalPosition, 2236 offset: this.positionAbs 2237 }; 2238 } 2239 2240 }); 2241 2242 $.ui.plugin.add( "draggable", "connectToSortable", { 2243 start: function( event, ui, draggable ) { 2244 var uiSortable = $.extend( {}, ui, { 2245 item: draggable.element 2246 }); 2247 2248 draggable.sortables = []; 2249 $( draggable.options.connectToSortable ).each(function() { 2250 var sortable = $( this ).sortable( "instance" ); 2251 2252 if ( sortable && !sortable.options.disabled ) { 2253 draggable.sortables.push( sortable ); 2254 2255 // refreshPositions is called at drag start to refresh the containerCache 2256 // which is used in drag. This ensures it's initialized and synchronized 2257 // with any changes that might have happened on the page since initialization. 2258 sortable.refreshPositions(); 2259 sortable._trigger("activate", event, uiSortable); 2260 } 2261 }); 2262 }, 2263 stop: function( event, ui, draggable ) { 2264 var uiSortable = $.extend( {}, ui, { 2265 item: draggable.element 2266 }); 2267 2268 draggable.cancelHelperRemoval = false; 2269 2270 $.each( draggable.sortables, function() { 2271 var sortable = this; 2272 2273 if ( sortable.isOver ) { 2274 sortable.isOver = 0; 2275 2276 // Allow this sortable to handle removing the helper 2277 draggable.cancelHelperRemoval = true; 2278 sortable.cancelHelperRemoval = false; 2279 2280 // Use _storedCSS To restore properties in the sortable, 2281 // as this also handles revert (#9675) since the draggable 2282 // may have modified them in unexpected ways (#8809) 2283 sortable._storedCSS = { 2284 position: sortable.placeholder.css( "position" ), 2285 top: sortable.placeholder.css( "top" ), 2286 left: sortable.placeholder.css( "left" ) 2287 }; 2288 2289 sortable._mouseStop(event); 2290 2291 // Once drag has ended, the sortable should return to using 2292 // its original helper, not the shared helper from draggable 2293 sortable.options.helper = sortable.options._helper; 2294 } else { 2295 // Prevent this Sortable from removing the helper. 2296 // However, don't set the draggable to remove the helper 2297 // either as another connected Sortable may yet handle the removal. 2298 sortable.cancelHelperRemoval = true; 2299 2300 sortable._trigger( "deactivate", event, uiSortable ); 2301 } 2302 }); 2303 }, 2304 drag: function( event, ui, draggable ) { 2305 $.each( draggable.sortables, function() { 2306 var innermostIntersecting = false, 2307 sortable = this; 2308 2309 // Copy over variables that sortable's _intersectsWith uses 2310 sortable.positionAbs = draggable.positionAbs; 2311 sortable.helperProportions = draggable.helperProportions; 2312 sortable.offset.click = draggable.offset.click; 2313 2314 if ( sortable._intersectsWith( sortable.containerCache ) ) { 2315 innermostIntersecting = true; 2316 2317 $.each( draggable.sortables, function() { 2318 // Copy over variables that sortable's _intersectsWith uses 2319 this.positionAbs = draggable.positionAbs; 2320 this.helperProportions = draggable.helperProportions; 2321 this.offset.click = draggable.offset.click; 2322 2323 if ( this !== sortable && 2324 this._intersectsWith( this.containerCache ) && 2325 $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) { 2326 innermostIntersecting = false; 2327 } 2328 2329 return innermostIntersecting; 2330 }); 2331 } 2332 2333 if ( innermostIntersecting ) { 2334 // If it intersects, we use a little isOver variable and set it once, 2335 // so that the move-in stuff gets fired only once. 2336 if ( !sortable.isOver ) { 2337 sortable.isOver = 1; 2338 2339 // Store draggable's parent in case we need to reappend to it later. 2340 draggable._parent = ui.helper.parent(); 2341 2342 sortable.currentItem = ui.helper 2343 .appendTo( sortable.element ) 2344 .data( "ui-sortable-item", true ); 2345 2346 // Store helper option to later restore it 2347 sortable.options._helper = sortable.options.helper; 2348 2349 sortable.options.helper = function() { 2350 return ui.helper[ 0 ]; 2351 }; 2352 2353 // Fire the start events of the sortable with our passed browser event, 2354 // and our own helper (so it doesn't create a new one) 2355 event.target = sortable.currentItem[ 0 ]; 2356 sortable._mouseCapture( event, true ); 2357 sortable._mouseStart( event, true, true ); 2358 2359 // Because the browser event is way off the new appended portlet, 2360 // modify necessary variables to reflect the changes 2361 sortable.offset.click.top = draggable.offset.click.top; 2362 sortable.offset.click.left = draggable.offset.click.left; 2363 sortable.offset.parent.left -= draggable.offset.parent.left - 2364 sortable.offset.parent.left; 2365 sortable.offset.parent.top -= draggable.offset.parent.top - 2366 sortable.offset.parent.top; 2367 2368 draggable._trigger( "toSortable", event ); 2369 2370 // Inform draggable that the helper is in a valid drop zone, 2371 // used solely in the revert option to handle "valid/invalid". 2372 draggable.dropped = sortable.element; 2373 2374 // Need to refreshPositions of all sortables in the case that 2375 // adding to one sortable changes the location of the other sortables (#9675) 2376 $.each( draggable.sortables, function() { 2377 this.refreshPositions(); 2378 }); 2379 2380 // hack so receive/update callbacks work (mostly) 2381 draggable.currentItem = draggable.element; 2382 sortable.fromOutside = draggable; 2383 } 2384 2385 if ( sortable.currentItem ) { 2386 sortable._mouseDrag( event ); 2387 // Copy the sortable's position because the draggable's can potentially reflect 2388 // a relative position, while sortable is always absolute, which the dragged 2389 // element has now become. (#8809) 2390 ui.position = sortable.position; 2391 } 2392 } else { 2393 // If it doesn't intersect with the sortable, and it intersected before, 2394 // we fake the drag stop of the sortable, but make sure it doesn't remove 2395 // the helper by using cancelHelperRemoval. 2396 if ( sortable.isOver ) { 2397 2398 sortable.isOver = 0; 2399 sortable.cancelHelperRemoval = true; 2400 2401 // Calling sortable's mouseStop would trigger a revert, 2402 // so revert must be temporarily false until after mouseStop is called. 2403 sortable.options._revert = sortable.options.revert; 2404 sortable.options.revert = false; 2405 2406 sortable._trigger( "out", event, sortable._uiHash( sortable ) ); 2407 sortable._mouseStop( event, true ); 2408 2409 // restore sortable behaviors that were modfied 2410 // when the draggable entered the sortable area (#9481) 2411 sortable.options.revert = sortable.options._revert; 2412 sortable.options.helper = sortable.options._helper; 2413 2414 if ( sortable.placeholder ) { 2415 sortable.placeholder.remove(); 2416 } 2417 2418 // Restore and recalculate the draggable's offset considering the sortable 2419 // may have modified them in unexpected ways. (#8809, #10669) 2420 ui.helper.appendTo( draggable._parent ); 2421 draggable._refreshOffsets( event ); 2422 ui.position = draggable._generatePosition( event, true ); 2423 2424 draggable._trigger( "fromSortable", event ); 2425 2426 // Inform draggable that the helper is no longer in a valid drop zone 2427 draggable.dropped = false; 2428 2429 // Need to refreshPositions of all sortables just in case removing 2430 // from one sortable changes the location of other sortables (#9675) 2431 $.each( draggable.sortables, function() { 2432 this.refreshPositions(); 2433 }); 2434 } 2435 } 2436 }); 2437 } 2438 }); 2439 2440 $.ui.plugin.add("draggable", "cursor", { 2441 start: function( event, ui, instance ) { 2442 var t = $( "body" ), 2443 o = instance.options; 2444 2445 if (t.css("cursor")) { 2446 o._cursor = t.css("cursor"); 2447 } 2448 t.css("cursor", o.cursor); 2449 }, 2450 stop: function( event, ui, instance ) { 2451 var o = instance.options; 2452 if (o._cursor) { 2453 $("body").css("cursor", o._cursor); 2454 } 2455 } 2456 }); 2457 2458 $.ui.plugin.add("draggable", "opacity", { 2459 start: function( event, ui, instance ) { 2460 var t = $( ui.helper ), 2461 o = instance.options; 2462 if (t.css("opacity")) { 2463 o._opacity = t.css("opacity"); 2464 } 2465 t.css("opacity", o.opacity); 2466 }, 2467 stop: function( event, ui, instance ) { 2468 var o = instance.options; 2469 if (o._opacity) { 2470 $(ui.helper).css("opacity", o._opacity); 2471 } 2472 } 2473 }); 2474 2475 $.ui.plugin.add("draggable", "scroll", { 2476 start: function( event, ui, i ) { 2477 if ( !i.scrollParentNotHidden ) { 2478 i.scrollParentNotHidden = i.helper.scrollParent( false ); 2479 } 2480 2481 if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] && i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) { 2482 i.overflowOffset = i.scrollParentNotHidden.offset(); 2483 } 2484 }, 2485 drag: function( event, ui, i ) { 2486 2487 var o = i.options, 2488 scrolled = false, 2489 scrollParent = i.scrollParentNotHidden[ 0 ], 2490 document = i.document[ 0 ]; 2491 2492 if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) { 2493 if ( !o.axis || o.axis !== "x" ) { 2494 if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY < o.scrollSensitivity ) { 2495 scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed; 2496 } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) { 2497 scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed; 2498 } 2499 } 2500 2501 if ( !o.axis || o.axis !== "y" ) { 2502 if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX < o.scrollSensitivity ) { 2503 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed; 2504 } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) { 2505 scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed; 2506 } 2507 } 2508 2509 } else { 2510 2511 if (!o.axis || o.axis !== "x") { 2512 if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) { 2513 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); 2514 } else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { 2515 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); 2516 } 2517 } 2518 2519 if (!o.axis || o.axis !== "y") { 2520 if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { 2521 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); 2522 } else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { 2523 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); 2524 } 2525 } 2526 2527 } 2528 2529 if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { 2530 $.ui.ddmanager.prepareOffsets(i, event); 2531 } 2532 2533 } 2534 }); 2535 2536 $.ui.plugin.add("draggable", "snap", { 2537 start: function( event, ui, i ) { 2538 2539 var o = i.options; 2540 2541 i.snapElements = []; 2542 2543 $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() { 2544 var $t = $(this), 2545 $o = $t.offset(); 2546 if (this !== i.element[0]) { 2547 i.snapElements.push({ 2548 item: this, 2549 width: $t.outerWidth(), height: $t.outerHeight(), 2550 top: $o.top, left: $o.left 2551 }); 2552 } 2553 }); 2554 2555 }, 2556 drag: function( event, ui, inst ) { 2557 2558 var ts, bs, ls, rs, l, r, t, b, i, first, 2559 o = inst.options, 2560 d = o.snapTolerance, 2561 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, 2562 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; 2563 2564 for (i = inst.snapElements.length - 1; i >= 0; i--){ 2565 2566 l = inst.snapElements[i].left - inst.margins.left; 2567 r = l + inst.snapElements[i].width; 2568 t = inst.snapElements[i].top - inst.margins.top; 2569 b = t + inst.snapElements[i].height; 2570 2571 if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) { 2572 if (inst.snapElements[i].snapping) { 2573 (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); 2574 } 2575 inst.snapElements[i].snapping = false; 2576 continue; 2577 } 2578 2579 if (o.snapMode !== "inner") { 2580 ts = Math.abs(t - y2) <= d; 2581 bs = Math.abs(b - y1) <= d; 2582 ls = Math.abs(l - x2) <= d; 2583 rs = Math.abs(r - x1) <= d; 2584 if (ts) { 2585 ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top; 2586 } 2587 if (bs) { 2588 ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top; 2589 } 2590 if (ls) { 2591 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left; 2592 } 2593 if (rs) { 2594 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left; 2595 } 2596 } 2597 2598 first = (ts || bs || ls || rs); 2599 2600 if (o.snapMode !== "outer") { 2601 ts = Math.abs(t - y1) <= d; 2602 bs = Math.abs(b - y2) <= d; 2603 ls = Math.abs(l - x1) <= d; 2604 rs = Math.abs(r - x2) <= d; 2605 if (ts) { 2606 ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top; 2607 } 2608 if (bs) { 2609 ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top; 2610 } 2611 if (ls) { 2612 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left; 2613 } 2614 if (rs) { 2615 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left; 2616 } 2617 } 2618 2619 if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) { 2620 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); 2621 } 2622 inst.snapElements[i].snapping = (ts || bs || ls || rs || first); 2623 2624 } 2625 2626 } 2627 }); 2628 2629 $.ui.plugin.add("draggable", "stack", { 2630 start: function( event, ui, instance ) { 2631 var min, 2632 o = instance.options, 2633 group = $.makeArray($(o.stack)).sort(function(a, b) { 2634 return (parseInt($(a).css("zIndex"), 10) || 0) - (parseInt($(b).css("zIndex"), 10) || 0); 2635 }); 2636 2637 if (!group.length) { return; } 2638 2639 min = parseInt($(group[0]).css("zIndex"), 10) || 0; 2640 $(group).each(function(i) { 2641 $(this).css("zIndex", min + i); 2642 }); 2643 this.css("zIndex", (min + group.length)); 2644 } 2645 }); 2646 2647 $.ui.plugin.add("draggable", "zIndex", { 2648 start: function( event, ui, instance ) { 2649 var t = $( ui.helper ), 2650 o = instance.options; 2651 2652 if (t.css("zIndex")) { 2653 o._zIndex = t.css("zIndex"); 2654 } 2655 t.css("zIndex", o.zIndex); 2656 }, 2657 stop: function( event, ui, instance ) { 2658 var o = instance.options; 2659 2660 if (o._zIndex) { 2661 $(ui.helper).css("zIndex", o._zIndex); 2662 } 2663 } 2664 }); 2665 2666 var draggable = $.ui.draggable; 2667 2668 2669 /*! 2670 * jQuery UI Droppable 1.11.4 2671 * http://jqueryui.com 2672 * 2673 * Copyright jQuery Foundation and other contributors 2674 * Released under the MIT license. 2675 * http://jquery.org/license 2676 * 2677 * http://api.jqueryui.com/droppable/ 2678 */ 2679 2680 2681 $.widget( "ui.droppable", { 2682 version: "1.11.4", 2683 widgetEventPrefix: "drop", 2684 options: { 2685 accept: "*", 2686 activeClass: false, 2687 addClasses: true, 2688 greedy: false, 2689 hoverClass: false, 2690 scope: "default", 2691 tolerance: "intersect", 2692 2693 // callbacks 2694 activate: null, 2695 deactivate: null, 2696 drop: null, 2697 out: null, 2698 over: null 2699 }, 2700 _create: function() { 2701 2702 var proportions, 2703 o = this.options, 2704 accept = o.accept; 2705 2706 this.isover = false; 2707 this.isout = true; 2708 2709 this.accept = $.isFunction( accept ) ? accept : function( d ) { 2710 return d.is( accept ); 2711 }; 2712 2713 this.proportions = function( /* valueToWrite */ ) { 2714 if ( arguments.length ) { 2715 // Store the droppable's proportions 2716 proportions = arguments[ 0 ]; 2717 } else { 2718 // Retrieve or derive the droppable's proportions 2719 return proportions ? 2720 proportions : 2721 proportions = { 2722 width: this.element[ 0 ].offsetWidth, 2723 height: this.element[ 0 ].offsetHeight 2724 }; 2725 } 2726 }; 2727 2728 this._addToManager( o.scope ); 2729 2730 o.addClasses && this.element.addClass( "ui-droppable" ); 2731 2732 }, 2733 2734 _addToManager: function( scope ) { 2735 // Add the reference and positions to the manager 2736 $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || []; 2737 $.ui.ddmanager.droppables[ scope ].push( this ); 2738 }, 2739 2740 _splice: function( drop ) { 2741 var i = 0; 2742 for ( ; i < drop.length; i++ ) { 2743 if ( drop[ i ] === this ) { 2744 drop.splice( i, 1 ); 2745 } 2746 } 2747 }, 2748 2749 _destroy: function() { 2750 var drop = $.ui.ddmanager.droppables[ this.options.scope ]; 2751 2752 this._splice( drop ); 2753 2754 this.element.removeClass( "ui-droppable ui-droppable-disabled" ); 2755 }, 2756 2757 _setOption: function( key, value ) { 2758 2759 if ( key === "accept" ) { 2760 this.accept = $.isFunction( value ) ? value : function( d ) { 2761 return d.is( value ); 2762 }; 2763 } else if ( key === "scope" ) { 2764 var drop = $.ui.ddmanager.droppables[ this.options.scope ]; 2765 2766 this._splice( drop ); 2767 this._addToManager( value ); 2768 } 2769 2770 this._super( key, value ); 2771 }, 2772 2773 _activate: function( event ) { 2774 var draggable = $.ui.ddmanager.current; 2775 if ( this.options.activeClass ) { 2776 this.element.addClass( this.options.activeClass ); 2777 } 2778 if ( draggable ){ 2779 this._trigger( "activate", event, this.ui( draggable ) ); 2780 } 2781 }, 2782 2783 _deactivate: function( event ) { 2784 var draggable = $.ui.ddmanager.current; 2785 if ( this.options.activeClass ) { 2786 this.element.removeClass( this.options.activeClass ); 2787 } 2788 if ( draggable ){ 2789 this._trigger( "deactivate", event, this.ui( draggable ) ); 2790 } 2791 }, 2792 2793 _over: function( event ) { 2794 2795 var draggable = $.ui.ddmanager.current; 2796 2797 // Bail if draggable and droppable are same element 2798 if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) { 2799 return; 2800 } 2801 2802 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) { 2803 if ( this.options.hoverClass ) { 2804 this.element.addClass( this.options.hoverClass ); 2805 } 2806 this._trigger( "over", event, this.ui( draggable ) ); 2807 } 2808 2809 }, 2810 2811 _out: function( event ) { 2812 2813 var draggable = $.ui.ddmanager.current; 2814 2815 // Bail if draggable and droppable are same element 2816 if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) { 2817 return; 2818 } 2819 2820 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) { 2821 if ( this.options.hoverClass ) { 2822 this.element.removeClass( this.options.hoverClass ); 2823 } 2824 this._trigger( "out", event, this.ui( draggable ) ); 2825 } 2826 2827 }, 2828 2829 _drop: function( event, custom ) { 2830 2831 var draggable = custom || $.ui.ddmanager.current, 2832 childrenIntersection = false; 2833 2834 // Bail if draggable and droppable are same element 2835 if ( !draggable || ( draggable.currentItem || draggable.element )[ 0 ] === this.element[ 0 ] ) { 2836 return false; 2837 } 2838 2839 this.element.find( ":data(ui-droppable)" ).not( ".ui-draggable-dragging" ).each(function() { 2840 var inst = $( this ).droppable( "instance" ); 2841 if ( 2842 inst.options.greedy && 2843 !inst.options.disabled && 2844 inst.options.scope === draggable.options.scope && 2845 inst.accept.call( inst.element[ 0 ], ( draggable.currentItem || draggable.element ) ) && 2846 $.ui.intersect( draggable, $.extend( inst, { offset: inst.element.offset() } ), inst.options.tolerance, event ) 2847 ) { childrenIntersection = true; return false; } 2848 }); 2849 if ( childrenIntersection ) { 2850 return false; 2851 } 2852 2853 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) { 2854 if ( this.options.activeClass ) { 2855 this.element.removeClass( this.options.activeClass ); 2856 } 2857 if ( this.options.hoverClass ) { 2858 this.element.removeClass( this.options.hoverClass ); 2859 } 2860 this._trigger( "drop", event, this.ui( draggable ) ); 2861 return this.element; 2862 } 2863 2864 return false; 2865 2866 }, 2867 2868 ui: function( c ) { 2869 return { 2870 draggable: ( c.currentItem || c.element ), 2871 helper: c.helper, 2872 position: c.position, 2873 offset: c.positionAbs 2874 }; 2875 } 2876 2877 }); 2878 2879 $.ui.intersect = (function() { 2880 function isOverAxis( x, reference, size ) { 2881 return ( x >= reference ) && ( x < ( reference + size ) ); 2882 } 2883 2884 return function( draggable, droppable, toleranceMode, event ) { 2885 2886 if ( !droppable.offset ) { 2887 return false; 2888 } 2889 2890 var x1 = ( draggable.positionAbs || draggable.position.absolute ).left + draggable.margins.left, 2891 y1 = ( draggable.positionAbs || draggable.position.absolute ).top + draggable.margins.top, 2892 x2 = x1 + draggable.helperProportions.width, 2893 y2 = y1 + draggable.helperProportions.height, 2894 l = droppable.offset.left, 2895 t = droppable.offset.top, 2896 r = l + droppable.proportions().width, 2897 b = t + droppable.proportions().height; 2898 2899 switch ( toleranceMode ) { 2900 case "fit": 2901 return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b ); 2902 case "intersect": 2903 return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half 2904 x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half 2905 t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half 2906 y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half 2907 case "pointer": 2908 return isOverAxis( event.pageY, t, droppable.proportions().height ) && isOverAxis( event.pageX, l, droppable.proportions().width ); 2909 case "touch": 2910 return ( 2911 ( y1 >= t && y1 <= b ) || // Top edge touching 2912 ( y2 >= t && y2 <= b ) || // Bottom edge touching 2913 ( y1 < t && y2 > b ) // Surrounded vertically 2914 ) && ( 2915 ( x1 >= l && x1 <= r ) || // Left edge touching 2916 ( x2 >= l && x2 <= r ) || // Right edge touching 2917 ( x1 < l && x2 > r ) // Surrounded horizontally 2918 ); 2919 default: 2920 return false; 2921 } 2922 }; 2923 })(); 2924 2925 /* 2926 This manager tracks offsets of draggables and droppables 2927 */ 2928 $.ui.ddmanager = { 2929 current: null, 2930 droppables: { "default": [] }, 2931 prepareOffsets: function( t, event ) { 2932 2933 var i, j, 2934 m = $.ui.ddmanager.droppables[ t.options.scope ] || [], 2935 type = event ? event.type : null, // workaround for #2317 2936 list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack(); 2937 2938 droppablesLoop: for ( i = 0; i < m.length; i++ ) { 2939 2940 // No disabled and non-accepted 2941 if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ], ( t.currentItem || t.element ) ) ) ) { 2942 continue; 2943 } 2944 2945 // Filter out elements in the current dragged item 2946 for ( j = 0; j < list.length; j++ ) { 2947 if ( list[ j ] === m[ i ].element[ 0 ] ) { 2948 m[ i ].proportions().height = 0; 2949 continue droppablesLoop; 2950 } 2951 } 2952 2953 m[ i ].visible = m[ i ].element.css( "display" ) !== "none"; 2954 if ( !m[ i ].visible ) { 2955 continue; 2956 } 2957 2958 // Activate the droppable if used directly from draggables 2959 if ( type === "mousedown" ) { 2960 m[ i ]._activate.call( m[ i ], event ); 2961 } 2962 2963 m[ i ].offset = m[ i ].element.offset(); 2964 m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth, height: m[ i ].element[ 0 ].offsetHeight }); 2965 2966 } 2967 2968 }, 2969 drop: function( draggable, event ) { 2970 2971 var dropped = false; 2972 // Create a copy of the droppables in case the list changes during the drop (#9116) 2973 $.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() { 2974 2975 if ( !this.options ) { 2976 return; 2977 } 2978 if ( !this.options.disabled && this.visible && $.ui.intersect( draggable, this, this.options.tolerance, event ) ) { 2979 dropped = this._drop.call( this, event ) || dropped; 2980 } 2981 2982 if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ], ( draggable.currentItem || draggable.element ) ) ) { 2983 this.isout = true; 2984 this.isover = false; 2985 this._deactivate.call( this, event ); 2986 } 2987 2988 }); 2989 return dropped; 2990 2991 }, 2992 dragStart: function( draggable, event ) { 2993 // Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) 2994 draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() { 2995 if ( !draggable.options.refreshPositions ) { 2996 $.ui.ddmanager.prepareOffsets( draggable, event ); 2997 } 2998 }); 2999 }, 3000 drag: function( draggable, event ) { 3001 3002 // If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. 3003 if ( draggable.options.refreshPositions ) { 3004 $.ui.ddmanager.prepareOffsets( draggable, event ); 3005 } 3006 3007 // Run through all droppables and check their positions based on specific tolerance options 3008 $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() { 3009 3010 if ( this.options.disabled || this.greedyChild || !this.visible ) { 3011 return; 3012 } 3013 3014 var parentInstance, scope, parent, 3015 intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ), 3016 c = !intersects && this.isover ? "isout" : ( intersects && !this.isover ? "isover" : null ); 3017 if ( !c ) { 3018 return; 3019 } 3020 3021 if ( this.options.greedy ) { 3022 // find droppable parents with same scope 3023 scope = this.options.scope; 3024 parent = this.element.parents( ":data(ui-droppable)" ).filter(function() { 3025 return $( this ).droppable( "instance" ).options.scope === scope; 3026 }); 3027 3028 if ( parent.length ) { 3029 parentInstance = $( parent[ 0 ] ).droppable( "instance" ); 3030 parentInstance.greedyChild = ( c === "isover" ); 3031 } 3032 } 3033 3034 // we just moved into a greedy child 3035 if ( parentInstance && c === "isover" ) { 3036 parentInstance.isover = false; 3037 parentInstance.isout = true; 3038 parentInstance._out.call( parentInstance, event ); 3039 } 3040 3041 this[ c ] = true; 3042 this[c === "isout" ? "isover" : "isout"] = false; 3043 this[c === "isover" ? "_over" : "_out"].call( this, event ); 3044 3045 // we just moved out of a greedy child 3046 if ( parentInstance && c === "isout" ) { 3047 parentInstance.isout = false; 3048 parentInstance.isover = true; 3049 parentInstance._over.call( parentInstance, event ); 3050 } 3051 }); 3052 3053 }, 3054 dragStop: function( draggable, event ) { 3055 draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" ); 3056 // Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) 3057 if ( !draggable.options.refreshPositions ) { 3058 $.ui.ddmanager.prepareOffsets( draggable, event ); 3059 } 3060 } 3061 }; 3062 3063 var droppable = $.ui.droppable; 3064 3065 3066 /*! 3067 * jQuery UI Resizable 1.11.4 3068 * http://jqueryui.com 3069 * 3070 * Copyright jQuery Foundation and other contributors 3071 * Released under the MIT license. 3072 * http://jquery.org/license 3073 * 3074 * http://api.jqueryui.com/resizable/ 3075 */ 3076 3077 3078 $.widget("ui.resizable", $.ui.mouse, { 3079 version: "1.11.4", 3080 widgetEventPrefix: "resize", 3081 options: { 3082 alsoResize: false, 3083 animate: false, 3084 animateDuration: "slow", 3085 animateEasing: "swing", 3086 aspectRatio: false, 3087 autoHide: false, 3088 containment: false, 3089 ghost: false, 3090 grid: false, 3091 handles: "e,s,se", 3092 helper: false, 3093 maxHeight: null, 3094 maxWidth: null, 3095 minHeight: 10, 3096 minWidth: 10, 3097 // See #7960 3098 zIndex: 90, 3099 3100 // callbacks 3101 resize: null, 3102 start: null, 3103 stop: null 3104 }, 3105 3106 _num: function( value ) { 3107 return parseInt( value, 10 ) || 0; 3108 }, 3109 3110 _isNumber: function( value ) { 3111 return !isNaN( parseInt( value, 10 ) ); 3112 }, 3113 3114 _hasScroll: function( el, a ) { 3115 3116 if ( $( el ).css( "overflow" ) === "hidden") { 3117 return false; 3118 } 3119 3120 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", 3121 has = false; 3122 3123 if ( el[ scroll ] > 0 ) { 3124 return true; 3125 } 3126 3127 // TODO: determine which cases actually cause this to happen 3128 // if the element doesn't have the scroll set, see if it's possible to 3129 // set the scroll 3130 el[ scroll ] = 1; 3131 has = ( el[ scroll ] > 0 ); 3132 el[ scroll ] = 0; 3133 return has; 3134 }, 3135 3136 _create: function() { 3137 3138 var n, i, handle, axis, hname, 3139 that = this, 3140 o = this.options; 3141 this.element.addClass("ui-resizable"); 3142 3143 $.extend(this, { 3144 _aspectRatio: !!(o.aspectRatio), 3145 aspectRatio: o.aspectRatio, 3146 originalElement: this.element, 3147 _proportionallyResizeElements: [], 3148 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null 3149 }); 3150 3151 // Wrap the element if it cannot hold child nodes 3152 if (this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)) { 3153 3154 this.element.wrap( 3155 $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({ 3156 position: this.element.css("position"), 3157 width: this.element.outerWidth(), 3158 height: this.element.outerHeight(), 3159 top: this.element.css("top"), 3160 left: this.element.css("left") 3161 }) 3162 ); 3163 3164 this.element = this.element.parent().data( 3165 "ui-resizable", this.element.resizable( "instance" ) 3166 ); 3167 3168 this.elementIsWrapper = true; 3169 3170 this.element.css({ 3171 marginLeft: this.originalElement.css("marginLeft"), 3172 marginTop: this.originalElement.css("marginTop"), 3173 marginRight: this.originalElement.css("marginRight"), 3174 marginBottom: this.originalElement.css("marginBottom") 3175 }); 3176 this.originalElement.css({ 3177 marginLeft: 0, 3178 marginTop: 0, 3179 marginRight: 0, 3180 marginBottom: 0 3181 }); 3182 // support: Safari 3183 // Prevent Safari textarea resize 3184 this.originalResizeStyle = this.originalElement.css("resize"); 3185 this.originalElement.css("resize", "none"); 3186 3187 this._proportionallyResizeElements.push( this.originalElement.css({ 3188 position: "static", 3189 zoom: 1, 3190 display: "block" 3191 }) ); 3192 3193 // support: IE9 3194 // avoid IE jump (hard set the margin) 3195 this.originalElement.css({ margin: this.originalElement.css("margin") }); 3196 3197 this._proportionallyResize(); 3198 } 3199 3200 this.handles = o.handles || 3201 ( !$(".ui-resizable-handle", this.element).length ? 3202 "e,s,se" : { 3203 n: ".ui-resizable-n", 3204 e: ".ui-resizable-e", 3205 s: ".ui-resizable-s", 3206 w: ".ui-resizable-w", 3207 se: ".ui-resizable-se", 3208 sw: ".ui-resizable-sw", 3209 ne: ".ui-resizable-ne", 3210 nw: ".ui-resizable-nw" 3211 } ); 3212 3213 this._handles = $(); 3214 if ( this.handles.constructor === String ) { 3215 3216 if ( this.handles === "all") { 3217 this.handles = "n,e,s,w,se,sw,ne,nw"; 3218 } 3219 3220 n = this.handles.split(","); 3221 this.handles = {}; 3222 3223 for (i = 0; i < n.length; i++) { 3224 3225 handle = $.trim(n[i]); 3226 hname = "ui-resizable-" + handle; 3227 axis = $("<div class='ui-resizable-handle " + hname + "'></div>"); 3228 3229 axis.css({ zIndex: o.zIndex }); 3230 3231 // TODO : What's going on here? 3232 if ("se" === handle) { 3233 axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se"); 3234 } 3235 3236 this.handles[handle] = ".ui-resizable-" + handle; 3237 this.element.append(axis); 3238 } 3239 3240 } 3241 3242 this._renderAxis = function(target) { 3243 3244 var i, axis, padPos, padWrapper; 3245 3246 target = target || this.element; 3247 3248 for (i in this.handles) { 3249 3250 if (this.handles[i].constructor === String) { 3251 this.handles[i] = this.element.children( this.handles[ i ] ).first().show(); 3252 } else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) { 3253 this.handles[ i ] = $( this.handles[ i ] ); 3254 this._on( this.handles[ i ], { "mousedown": that._mouseDown }); 3255 } 3256 3257 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)) { 3258 3259 axis = $(this.handles[i], this.element); 3260 3261 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); 3262 3263 padPos = [ "padding", 3264 /ne|nw|n/.test(i) ? "Top" : 3265 /se|sw|s/.test(i) ? "Bottom" : 3266 /^e$/.test(i) ? "Right" : "Left" ].join(""); 3267 3268 target.css(padPos, padWrapper); 3269 3270 this._proportionallyResize(); 3271 } 3272 3273 this._handles = this._handles.add( this.handles[ i ] ); 3274 } 3275 }; 3276 3277 // TODO: make renderAxis a prototype function 3278 this._renderAxis(this.element); 3279 3280 this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) ); 3281 this._handles.disableSelection(); 3282 3283 this._handles.mouseover(function() { 3284 if (!that.resizing) { 3285 if (this.className) { 3286 axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); 3287 } 3288 that.axis = axis && axis[1] ? axis[1] : "se"; 3289 } 3290 }); 3291 3292 if (o.autoHide) { 3293 this._handles.hide(); 3294 $(this.element) 3295 .addClass("ui-resizable-autohide") 3296 .mouseenter(function() { 3297 if (o.disabled) { 3298 return; 3299 } 3300 $(this).removeClass("ui-resizable-autohide"); 3301 that._handles.show(); 3302 }) 3303 .mouseleave(function() { 3304 if (o.disabled) { 3305 return; 3306 } 3307 if (!that.resizing) { 3308 $(this).addClass("ui-resizable-autohide"); 3309 that._handles.hide(); 3310 } 3311 }); 3312 } 3313 3314 this._mouseInit(); 3315 }, 3316 3317 _destroy: function() { 3318 3319 this._mouseDestroy(); 3320 3321 var wrapper, 3322 _destroy = function(exp) { 3323 $(exp) 3324 .removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") 3325 .removeData("resizable") 3326 .removeData("ui-resizable") 3327 .unbind(".resizable") 3328 .find(".ui-resizable-handle") 3329 .remove(); 3330 }; 3331 3332 // TODO: Unwrap at same DOM position 3333 if (this.elementIsWrapper) { 3334 _destroy(this.element); 3335 wrapper = this.element; 3336 this.originalElement.css({ 3337 position: wrapper.css("position"), 3338 width: wrapper.outerWidth(), 3339 height: wrapper.outerHeight(), 3340 top: wrapper.css("top"), 3341 left: wrapper.css("left") 3342 }).insertAfter( wrapper ); 3343 wrapper.remove(); 3344 } 3345 3346 this.originalElement.css("resize", this.originalResizeStyle); 3347 _destroy(this.originalElement); 3348 3349 return this; 3350 }, 3351 3352 _mouseCapture: function(event) { 3353 var i, handle, 3354 capture = false; 3355 3356 for (i in this.handles) { 3357 handle = $(this.handles[i])[0]; 3358 if (handle === event.target || $.contains(handle, event.target)) { 3359 capture = true; 3360 } 3361 } 3362 3363 return !this.options.disabled && capture; 3364 }, 3365 3366 _mouseStart: function(event) { 3367 3368 var curleft, curtop, cursor, 3369 o = this.options, 3370 el = this.element; 3371 3372 this.resizing = true; 3373 3374 this._renderProxy(); 3375 3376 curleft = this._num(this.helper.css("left")); 3377 curtop = this._num(this.helper.css("top")); 3378 3379 if (o.containment) { 3380 curleft += $(o.containment).scrollLeft() || 0; 3381 curtop += $(o.containment).scrollTop() || 0; 3382 } 3383 3384 this.offset = this.helper.offset(); 3385 this.position = { left: curleft, top: curtop }; 3386 3387 this.size = this._helper ? { 3388 width: this.helper.width(), 3389 height: this.helper.height() 3390 } : { 3391 width: el.width(), 3392 height: el.height() 3393 }; 3394 3395 this.originalSize = this._helper ? { 3396 width: el.outerWidth(), 3397 height: el.outerHeight() 3398 } : { 3399 width: el.width(), 3400 height: el.height() 3401 }; 3402 3403 this.sizeDiff = { 3404 width: el.outerWidth() - el.width(), 3405 height: el.outerHeight() - el.height() 3406 }; 3407 3408 this.originalPosition = { left: curleft, top: curtop }; 3409 this.originalMousePosition = { left: event.pageX, top: event.pageY }; 3410 3411 this.aspectRatio = (typeof o.aspectRatio === "number") ? 3412 o.aspectRatio : 3413 ((this.originalSize.width / this.originalSize.height) || 1); 3414 3415 cursor = $(".ui-resizable-" + this.axis).css("cursor"); 3416 $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor); 3417 3418 el.addClass("ui-resizable-resizing"); 3419 this._propagate("start", event); 3420 return true; 3421 }, 3422 3423 _mouseDrag: function(event) { 3424 3425 var data, props, 3426 smp = this.originalMousePosition, 3427 a = this.axis, 3428 dx = (event.pageX - smp.left) || 0, 3429 dy = (event.pageY - smp.top) || 0, 3430 trigger = this._change[a]; 3431 3432 this._updatePrevProperties(); 3433 3434 if (!trigger) { 3435 return false; 3436 } 3437 3438 data = trigger.apply(this, [ event, dx, dy ]); 3439 3440 this._updateVirtualBoundaries(event.shiftKey); 3441 if (this._aspectRatio || event.shiftKey) { 3442 data = this._updateRatio(data, event); 3443 } 3444 3445 data = this._respectSize(data, event); 3446 3447 this._updateCache(data); 3448 3449 this._propagate("resize", event); 3450 3451 props = this._applyChanges(); 3452 3453 if ( !this._helper && this._proportionallyResizeElements.length ) { 3454 this._proportionallyResize(); 3455 } 3456 3457 if ( !$.isEmptyObject( props ) ) { 3458 this._updatePrevProperties(); 3459 this._trigger( "resize", event, this.ui() ); 3460 this._applyChanges(); 3461 } 3462 3463 return false; 3464 }, 3465 3466 _mouseStop: function(event) { 3467 3468 this.resizing = false; 3469 var pr, ista, soffseth, soffsetw, s, left, top, 3470 o = this.options, that = this; 3471 3472 if (this._helper) { 3473 3474 pr = this._proportionallyResizeElements; 3475 ista = pr.length && (/textarea/i).test(pr[0].nodeName); 3476 soffseth = ista && this._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height; 3477 soffsetw = ista ? 0 : that.sizeDiff.width; 3478 3479 s = { 3480 width: (that.helper.width() - soffsetw), 3481 height: (that.helper.height() - soffseth) 3482 }; 3483 left = (parseInt(that.element.css("left"), 10) + 3484 (that.position.left - that.originalPosition.left)) || null; 3485 top = (parseInt(that.element.css("top"), 10) + 3486 (that.position.top - that.originalPosition.top)) || null; 3487 3488 if (!o.animate) { 3489 this.element.css($.extend(s, { top: top, left: left })); 3490 } 3491 3492 that.helper.height(that.size.height); 3493 that.helper.width(that.size.width); 3494 3495 if (this._helper && !o.animate) { 3496 this._proportionallyResize(); 3497 } 3498 } 3499 3500 $("body").css("cursor", "auto"); 3501 3502 this.element.removeClass("ui-resizable-resizing"); 3503 3504 this._propagate("stop", event); 3505 3506 if (this._helper) { 3507 this.helper.remove(); 3508 } 3509 3510 return false; 3511 3512 }, 3513 3514 _updatePrevProperties: function() { 3515 this.prevPosition = { 3516 top: this.position.top, 3517 left: this.position.left 3518 }; 3519 this.prevSize = { 3520 width: this.size.width, 3521 height: this.size.height 3522 }; 3523 }, 3524 3525 _applyChanges: function() { 3526 var props = {}; 3527 3528 if ( this.position.top !== this.prevPosition.top ) { 3529 props.top = this.position.top + "px"; 3530 } 3531 if ( this.position.left !== this.prevPosition.left ) { 3532 props.left = this.position.left + "px"; 3533 } 3534 if ( this.size.width !== this.prevSize.width ) { 3535 props.width = this.size.width + "px"; 3536 } 3537 if ( this.size.height !== this.prevSize.height ) { 3538 props.height = this.size.height + "px"; 3539 } 3540 3541 this.helper.css( props ); 3542 3543 return props; 3544 }, 3545 3546 _updateVirtualBoundaries: function(forceAspectRatio) { 3547 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b, 3548 o = this.options; 3549 3550 b = { 3551 minWidth: this._isNumber(o.minWidth) ? o.minWidth : 0, 3552 maxWidth: this._isNumber(o.maxWidth) ? o.maxWidth : Infinity, 3553 minHeight: this._isNumber(o.minHeight) ? o.minHeight : 0, 3554 maxHeight: this._isNumber(o.maxHeight) ? o.maxHeight : Infinity 3555 }; 3556 3557 if (this._aspectRatio || forceAspectRatio) { 3558 pMinWidth = b.minHeight * this.aspectRatio; 3559 pMinHeight = b.minWidth / this.aspectRatio; 3560 pMaxWidth = b.maxHeight * this.aspectRatio; 3561 pMaxHeight = b.maxWidth / this.aspectRatio; 3562 3563 if (pMinWidth > b.minWidth) { 3564 b.minWidth = pMinWidth; 3565 } 3566 if (pMinHeight > b.minHeight) { 3567 b.minHeight = pMinHeight; 3568 } 3569 if (pMaxWidth < b.maxWidth) { 3570 b.maxWidth = pMaxWidth; 3571 } 3572 if (pMaxHeight < b.maxHeight) { 3573 b.maxHeight = pMaxHeight; 3574 } 3575 } 3576 this._vBoundaries = b; 3577 }, 3578 3579 _updateCache: function(data) { 3580 this.offset = this.helper.offset(); 3581 if (this._isNumber(data.left)) { 3582 this.position.left = data.left; 3583 } 3584 if (this._isNumber(data.top)) { 3585 this.position.top = data.top; 3586 } 3587 if (this._isNumber(data.height)) { 3588 this.size.height = data.height; 3589 } 3590 if (this._isNumber(data.width)) { 3591 this.size.width = data.width; 3592 } 3593 }, 3594 3595 _updateRatio: function( data ) { 3596 3597 var cpos = this.position, 3598 csize = this.size, 3599 a = this.axis; 3600 3601 if (this._isNumber(data.height)) { 3602 data.width = (data.height * this.aspectRatio); 3603 } else if (this._isNumber(data.width)) { 3604 data.height = (data.width / this.aspectRatio); 3605 } 3606 3607 if (a === "sw") { 3608 data.left = cpos.left + (csize.width - data.width); 3609 data.top = null; 3610 } 3611 if (a === "nw") { 3612 data.top = cpos.top + (csize.height - data.height); 3613 data.left = cpos.left + (csize.width - data.width); 3614 } 3615 3616 return data; 3617 }, 3618 3619 _respectSize: function( data ) { 3620 3621 var o = this._vBoundaries, 3622 a = this.axis, 3623 ismaxw = this._isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), 3624 ismaxh = this._isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), 3625 isminw = this._isNumber(data.width) && o.minWidth && (o.minWidth > data.width), 3626 isminh = this._isNumber(data.height) && o.minHeight && (o.minHeight > data.height), 3627 dw = this.originalPosition.left + this.originalSize.width, 3628 dh = this.position.top + this.size.height, 3629 cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); 3630 if (isminw) { 3631 data.width = o.minWidth; 3632 } 3633 if (isminh) { 3634 data.height = o.minHeight; 3635 } 3636 if (ismaxw) { 3637 data.width = o.maxWidth; 3638 } 3639 if (ismaxh) { 3640 data.height = o.maxHeight; 3641 } 3642 3643 if (isminw && cw) { 3644 data.left = dw - o.minWidth; 3645 } 3646 if (ismaxw && cw) { 3647 data.left = dw - o.maxWidth; 3648 } 3649 if (isminh && ch) { 3650 data.top = dh - o.minHeight; 3651 } 3652 if (ismaxh && ch) { 3653 data.top = dh - o.maxHeight; 3654 } 3655 3656 // Fixing jump error on top/left - bug #2330 3657 if (!data.width && !data.height && !data.left && data.top) { 3658 data.top = null; 3659 } else if (!data.width && !data.height && !data.top && data.left) { 3660 data.left = null; 3661 } 3662 3663 return data; 3664 }, 3665 3666 _getPaddingPlusBorderDimensions: function( element ) { 3667 var i = 0, 3668 widths = [], 3669 borders = [ 3670 element.css( "borderTopWidth" ), 3671 element.css( "borderRightWidth" ), 3672 element.css( "borderBottomWidth" ), 3673 element.css( "borderLeftWidth" ) 3674 ], 3675 paddings = [ 3676 element.css( "paddingTop" ), 3677 element.css( "paddingRight" ), 3678 element.css( "paddingBottom" ), 3679 element.css( "paddingLeft" ) 3680 ]; 3681 3682 for ( ; i < 4; i++ ) { 3683 widths[ i ] = ( parseInt( borders[ i ], 10 ) || 0 ); 3684 widths[ i ] += ( parseInt( paddings[ i ], 10 ) || 0 ); 3685 } 3686 3687 return { 3688 height: widths[ 0 ] + widths[ 2 ], 3689 width: widths[ 1 ] + widths[ 3 ] 3690 }; 3691 }, 3692 3693 _proportionallyResize: function() { 3694 3695 if (!this._proportionallyResizeElements.length) { 3696 return; 3697 } 3698 3699 var prel, 3700 i = 0, 3701 element = this.helper || this.element; 3702 3703 for ( ; i < this._proportionallyResizeElements.length; i++) { 3704 3705 prel = this._proportionallyResizeElements[i]; 3706 3707 // TODO: Seems like a bug to cache this.outerDimensions 3708 // considering that we are in a loop. 3709 if (!this.outerDimensions) { 3710 this.outerDimensions = this._getPaddingPlusBorderDimensions( prel ); 3711 } 3712 3713 prel.css({ 3714 height: (element.height() - this.outerDimensions.height) || 0, 3715 width: (element.width() - this.outerDimensions.width) || 0 3716 }); 3717 3718 } 3719 3720 }, 3721 3722 _renderProxy: function() { 3723 3724 var el = this.element, o = this.options; 3725 this.elementOffset = el.offset(); 3726 3727 if (this._helper) { 3728 3729 this.helper = this.helper || $("<div style='overflow:hidden;'></div>"); 3730 3731 this.helper.addClass(this._helper).css({ 3732 width: this.element.outerWidth() - 1, 3733 height: this.element.outerHeight() - 1, 3734 position: "absolute", 3735 left: this.elementOffset.left + "px", 3736 top: this.elementOffset.top + "px", 3737 zIndex: ++o.zIndex //TODO: Don't modify option 3738 }); 3739 3740 this.helper 3741 .appendTo("body") 3742 .disableSelection(); 3743 3744 } else { 3745 this.helper = this.element; 3746 } 3747 3748 }, 3749 3750 _change: { 3751 e: function(event, dx) { 3752 return { width: this.originalSize.width + dx }; 3753 }, 3754 w: function(event, dx) { 3755 var cs = this.originalSize, sp = this.originalPosition; 3756 return { left: sp.left + dx, width: cs.width - dx }; 3757 }, 3758 n: function(event, dx, dy) { 3759 var cs = this.originalSize, sp = this.originalPosition; 3760 return { top: sp.top + dy, height: cs.height - dy }; 3761 }, 3762 s: function(event, dx, dy) { 3763 return { height: this.originalSize.height + dy }; 3764 }, 3765 se: function(event, dx, dy) { 3766 return $.extend(this._change.s.apply(this, arguments), 3767 this._change.e.apply(this, [ event, dx, dy ])); 3768 }, 3769 sw: function(event, dx, dy) { 3770 return $.extend(this._change.s.apply(this, arguments), 3771 this._change.w.apply(this, [ event, dx, dy ])); 3772 }, 3773 ne: function(event, dx, dy) { 3774 return $.extend(this._change.n.apply(this, arguments), 3775 this._change.e.apply(this, [ event, dx, dy ])); 3776 }, 3777 nw: function(event, dx, dy) { 3778 return $.extend(this._change.n.apply(this, arguments), 3779 this._change.w.apply(this, [ event, dx, dy ])); 3780 } 3781 }, 3782 3783 _propagate: function(n, event) { 3784 $.ui.plugin.call(this, n, [ event, this.ui() ]); 3785 (n !== "resize" && this._trigger(n, event, this.ui())); 3786 }, 3787 3788 plugins: {}, 3789 3790 ui: function() { 3791 return { 3792 originalElement: this.originalElement, 3793 element: this.element, 3794 helper: this.helper, 3795 position: this.position, 3796 size: this.size, 3797 originalSize: this.originalSize, 3798 originalPosition: this.originalPosition 3799 }; 3800 } 3801 3802 }); 3803 3804 /* 3805 * Resizable Extensions 3806 */ 3807 3808 $.ui.plugin.add("resizable", "animate", { 3809 3810 stop: function( event ) { 3811 var that = $(this).resizable( "instance" ), 3812 o = that.options, 3813 pr = that._proportionallyResizeElements, 3814 ista = pr.length && (/textarea/i).test(pr[0].nodeName), 3815 soffseth = ista && that._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height, 3816 soffsetw = ista ? 0 : that.sizeDiff.width, 3817 style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) }, 3818 left = (parseInt(that.element.css("left"), 10) + 3819 (that.position.left - that.originalPosition.left)) || null, 3820 top = (parseInt(that.element.css("top"), 10) + 3821 (that.position.top - that.originalPosition.top)) || null; 3822 3823 that.element.animate( 3824 $.extend(style, top && left ? { top: top, left: left } : {}), { 3825 duration: o.animateDuration, 3826 easing: o.animateEasing, 3827 step: function() { 3828 3829 var data = { 3830 width: parseInt(that.element.css("width"), 10), 3831 height: parseInt(that.element.css("height"), 10), 3832 top: parseInt(that.element.css("top"), 10), 3833 left: parseInt(that.element.css("left"), 10) 3834 }; 3835 3836 if (pr && pr.length) { 3837 $(pr[0]).css({ width: data.width, height: data.height }); 3838 } 3839 3840 // propagating resize, and updating values for each animation step 3841 that._updateCache(data); 3842 that._propagate("resize", event); 3843 3844 } 3845 } 3846 ); 3847 } 3848 3849 }); 3850 3851 $.ui.plugin.add( "resizable", "containment", { 3852 3853 start: function() { 3854 var element, p, co, ch, cw, width, height, 3855 that = $( this ).resizable( "instance" ), 3856 o = that.options, 3857 el = that.element, 3858 oc = o.containment, 3859 ce = ( oc instanceof $ ) ? oc.get( 0 ) : ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc; 3860 3861 if ( !ce ) { 3862 return; 3863 } 3864 3865 that.containerElement = $( ce ); 3866 3867 if ( /document/.test( oc ) || oc === document ) { 3868 that.containerOffset = { 3869 left: 0, 3870 top: 0 3871 }; 3872 that.containerPosition = { 3873 left: 0, 3874 top: 0 3875 }; 3876 3877 that.parentData = { 3878 element: $( document ), 3879 left: 0, 3880 top: 0, 3881 width: $( document ).width(), 3882 height: $( document ).height() || document.body.parentNode.scrollHeight 3883 }; 3884 } else { 3885 element = $( ce ); 3886 p = []; 3887 $([ "Top", "Right", "Left", "Bottom" ]).each(function( i, name ) { 3888 p[ i ] = that._num( element.css( "padding" + name ) ); 3889 }); 3890 3891 that.containerOffset = element.offset(); 3892 that.containerPosition = element.position(); 3893 that.containerSize = { 3894 height: ( element.innerHeight() - p[ 3 ] ), 3895 width: ( element.innerWidth() - p[ 1 ] ) 3896 }; 3897 3898 co = that.containerOffset; 3899 ch = that.containerSize.height; 3900 cw = that.containerSize.width; 3901 width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw ); 3902 height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ; 3903 3904 that.parentData = { 3905 element: ce, 3906 left: co.left, 3907 top: co.top, 3908 width: width, 3909 height: height 3910 }; 3911 } 3912 }, 3913 3914 resize: function( event ) { 3915 var woset, hoset, isParent, isOffsetRelative, 3916 that = $( this ).resizable( "instance" ), 3917 o = that.options, 3918 co = that.containerOffset, 3919 cp = that.position, 3920 pRatio = that._aspectRatio || event.shiftKey, 3921 cop = { 3922 top: 0, 3923 left: 0 3924 }, 3925 ce = that.containerElement, 3926 continueResize = true; 3927 3928 if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) { 3929 cop = co; 3930 } 3931 3932 if ( cp.left < ( that._helper ? co.left : 0 ) ) { 3933 that.size.width = that.size.width + 3934 ( that._helper ? 3935 ( that.position.left - co.left ) : 3936 ( that.position.left - cop.left ) ); 3937 3938 if ( pRatio ) { 3939 that.size.height = that.size.width / that.aspectRatio; 3940 continueResize = false; 3941 } 3942 that.position.left = o.helper ? co.left : 0; 3943 } 3944 3945 if ( cp.top < ( that._helper ? co.top : 0 ) ) { 3946 that.size.height = that.size.height + 3947 ( that._helper ? 3948 ( that.position.top - co.top ) : 3949 that.position.top ); 3950 3951 if ( pRatio ) { 3952 that.size.width = that.size.height * that.aspectRatio; 3953 continueResize = false; 3954 } 3955 that.position.top = that._helper ? co.top : 0; 3956 } 3957 3958 isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 ); 3959 isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) ); 3960 3961 if ( isParent && isOffsetRelative ) { 3962 that.offset.left = that.parentData.left + that.position.left; 3963 that.offset.top = that.parentData.top + that.position.top; 3964 } else { 3965 that.offset.left = that.element.offset().left; 3966 that.offset.top = that.element.offset().top; 3967 } 3968 3969 woset = Math.abs( that.sizeDiff.width + 3970 (that._helper ? 3971 that.offset.left - cop.left : 3972 (that.offset.left - co.left)) ); 3973 3974 hoset = Math.abs( that.sizeDiff.height + 3975 (that._helper ? 3976 that.offset.top - cop.top : 3977 (that.offset.top - co.top)) ); 3978 3979 if ( woset + that.size.width >= that.parentData.width ) { 3980 that.size.width = that.parentData.width - woset; 3981 if ( pRatio ) { 3982 that.size.height = that.size.width / that.aspectRatio; 3983 continueResize = false; 3984 } 3985 } 3986 3987 if ( hoset + that.size.height >= that.parentData.height ) { 3988 that.size.height = that.parentData.height - hoset; 3989 if ( pRatio ) { 3990 that.size.width = that.size.height * that.aspectRatio; 3991 continueResize = false; 3992 } 3993 } 3994 3995 if ( !continueResize ) { 3996 that.position.left = that.prevPosition.left; 3997 that.position.top = that.prevPosition.top; 3998 that.size.width = that.prevSize.width; 3999 that.size.height = that.prevSize.height; 4000 } 4001 }, 4002 4003 stop: function() { 4004 var that = $( this ).resizable( "instance" ), 4005 o = that.options, 4006 co = that.containerOffset, 4007 cop = that.containerPosition, 4008 ce = that.containerElement, 4009 helper = $( that.helper ), 4010 ho = helper.offset(), 4011 w = helper.outerWidth() - that.sizeDiff.width, 4012 h = helper.outerHeight() - that.sizeDiff.height; 4013 4014 if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) { 4015 $( this ).css({ 4016 left: ho.left - cop.left - co.left, 4017 width: w, 4018 height: h 4019 }); 4020 } 4021 4022 if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) { 4023 $( this ).css({ 4024 left: ho.left - cop.left - co.left, 4025 width: w, 4026 height: h 4027 }); 4028 } 4029 } 4030 }); 4031 4032 $.ui.plugin.add("resizable", "alsoResize", { 4033 4034 start: function() { 4035 var that = $(this).resizable( "instance" ), 4036 o = that.options; 4037 4038 $(o.alsoResize).each(function() { 4039 var el = $(this); 4040 el.data("ui-resizable-alsoresize", { 4041 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), 4042 left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10) 4043 }); 4044 }); 4045 }, 4046 4047 resize: function(event, ui) { 4048 var that = $(this).resizable( "instance" ), 4049 o = that.options, 4050 os = that.originalSize, 4051 op = that.originalPosition, 4052 delta = { 4053 height: (that.size.height - os.height) || 0, 4054 width: (that.size.width - os.width) || 0, 4055 top: (that.position.top - op.top) || 0, 4056 left: (that.position.left - op.left) || 0 4057 }; 4058 4059 $(o.alsoResize).each(function() { 4060 var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {}, 4061 css = el.parents(ui.originalElement[0]).length ? 4062 [ "width", "height" ] : 4063 [ "width", "height", "top", "left" ]; 4064 4065 $.each(css, function(i, prop) { 4066 var sum = (start[prop] || 0) + (delta[prop] || 0); 4067 if (sum && sum >= 0) { 4068 style[prop] = sum || null; 4069 } 4070 }); 4071 4072 el.css(style); 4073 }); 4074 }, 4075 4076 stop: function() { 4077 $(this).removeData("resizable-alsoresize"); 4078 } 4079 }); 4080 4081 $.ui.plugin.add("resizable", "ghost", { 4082 4083 start: function() { 4084 4085 var that = $(this).resizable( "instance" ), o = that.options, cs = that.size; 4086 4087 that.ghost = that.originalElement.clone(); 4088 that.ghost 4089 .css({ 4090 opacity: 0.25, 4091 display: "block", 4092 position: "relative", 4093 height: cs.height, 4094 width: cs.width, 4095 margin: 0, 4096 left: 0, 4097 top: 0 4098 }) 4099 .addClass("ui-resizable-ghost") 4100 .addClass(typeof o.ghost === "string" ? o.ghost : ""); 4101 4102 that.ghost.appendTo(that.helper); 4103 4104 }, 4105 4106 resize: function() { 4107 var that = $(this).resizable( "instance" ); 4108 if (that.ghost) { 4109 that.ghost.css({ 4110 position: "relative", 4111 height: that.size.height, 4112 width: that.size.width 4113 }); 4114 } 4115 }, 4116 4117 stop: function() { 4118 var that = $(this).resizable( "instance" ); 4119 if (that.ghost && that.helper) { 4120 that.helper.get(0).removeChild(that.ghost.get(0)); 4121 } 4122 } 4123 4124 }); 4125 4126 $.ui.plugin.add("resizable", "grid", { 4127 4128 resize: function() { 4129 var outerDimensions, 4130 that = $(this).resizable( "instance" ), 4131 o = that.options, 4132 cs = that.size, 4133 os = that.originalSize, 4134 op = that.originalPosition, 4135 a = that.axis, 4136 grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid, 4137 gridX = (grid[0] || 1), 4138 gridY = (grid[1] || 1), 4139 ox = Math.round((cs.width - os.width) / gridX) * gridX, 4140 oy = Math.round((cs.height - os.height) / gridY) * gridY, 4141 newWidth = os.width + ox, 4142 newHeight = os.height + oy, 4143 isMaxWidth = o.maxWidth && (o.maxWidth < newWidth), 4144 isMaxHeight = o.maxHeight && (o.maxHeight < newHeight), 4145 isMinWidth = o.minWidth && (o.minWidth > newWidth), 4146 isMinHeight = o.minHeight && (o.minHeight > newHeight); 4147 4148 o.grid = grid; 4149 4150 if (isMinWidth) { 4151 newWidth += gridX; 4152 } 4153 if (isMinHeight) { 4154 newHeight += gridY; 4155 } 4156 if (isMaxWidth) { 4157 newWidth -= gridX; 4158 } 4159 if (isMaxHeight) { 4160 newHeight -= gridY; 4161 } 4162 4163 if (/^(se|s|e)$/.test(a)) { 4164 that.size.width = newWidth; 4165 that.size.height = newHeight; 4166 } else if (/^(ne)$/.test(a)) { 4167 that.size.width = newWidth; 4168 that.size.height = newHeight; 4169 that.position.top = op.top - oy; 4170 } else if (/^(sw)$/.test(a)) { 4171 that.size.width = newWidth; 4172 that.size.height = newHeight; 4173 that.position.left = op.left - ox; 4174 } else { 4175 if ( newHeight - gridY <= 0 || newWidth - gridX <= 0) { 4176 outerDimensions = that._getPaddingPlusBorderDimensions( this ); 4177 } 4178 4179 if ( newHeight - gridY > 0 ) { 4180 that.size.height = newHeight; 4181 that.position.top = op.top - oy; 4182 } else { 4183 newHeight = gridY - outerDimensions.height; 4184 that.size.height = newHeight; 4185 that.position.top = op.top + os.height - newHeight; 4186 } 4187 if ( newWidth - gridX > 0 ) { 4188 that.size.width = newWidth; 4189 that.position.left = op.left - ox; 4190 } else { 4191 newWidth = gridX - outerDimensions.width; 4192 that.size.width = newWidth; 4193 that.position.left = op.left + os.width - newWidth; 4194 } 4195 } 4196 } 4197 4198 }); 4199 4200 var resizable = $.ui.resizable; 4201 4202 4203 /*! 4204 * jQuery UI Selectable 1.11.4 4205 * http://jqueryui.com 4206 * 4207 * Copyright jQuery Foundation and other contributors 4208 * Released under the MIT license. 4209 * http://jquery.org/license 4210 * 4211 * http://api.jqueryui.com/selectable/ 4212 */ 4213 4214 4215 var selectable = $.widget("ui.selectable", $.ui.mouse, { 4216 version: "1.11.4", 4217 options: { 4218 appendTo: "body", 4219 autoRefresh: true, 4220 distance: 0, 4221 filter: "*", 4222 tolerance: "touch", 4223 4224 // callbacks 4225 selected: null, 4226 selecting: null, 4227 start: null, 4228 stop: null, 4229 unselected: null, 4230 unselecting: null 4231 }, 4232 _create: function() { 4233 var selectees, 4234 that = this; 4235 4236 this.element.addClass("ui-selectable"); 4237 4238 this.dragged = false; 4239 4240 // cache selectee children based on filter 4241 this.refresh = function() { 4242 selectees = $(that.options.filter, that.element[0]); 4243 selectees.addClass("ui-selectee"); 4244 selectees.each(function() { 4245 var $this = $(this), 4246 pos = $this.offset(); 4247 $.data(this, "selectable-item", { 4248 element: this, 4249 $element: $this, 4250 left: pos.left, 4251 top: pos.top, 4252 right: pos.left + $this.outerWidth(), 4253 bottom: pos.top + $this.outerHeight(), 4254 startselected: false, 4255 selected: $this.hasClass("ui-selected"), 4256 selecting: $this.hasClass("ui-selecting"), 4257 unselecting: $this.hasClass("ui-unselecting") 4258 }); 4259 }); 4260 }; 4261 this.refresh(); 4262 4263 this.selectees = selectees.addClass("ui-selectee"); 4264 4265 this._mouseInit(); 4266 4267 this.helper = $("<div class='ui-selectable-helper'></div>"); 4268 }, 4269 4270 _destroy: function() { 4271 this.selectees 4272 .removeClass("ui-selectee") 4273 .removeData("selectable-item"); 4274 this.element 4275 .removeClass("ui-selectable ui-selectable-disabled"); 4276 this._mouseDestroy(); 4277 }, 4278 4279 _mouseStart: function(event) { 4280 var that = this, 4281 options = this.options; 4282 4283 this.opos = [ event.pageX, event.pageY ]; 4284 4285 if (this.options.disabled) { 4286 return; 4287 } 4288 4289 this.selectees = $(options.filter, this.element[0]); 4290 4291 this._trigger("start", event); 4292 4293 $(options.appendTo).append(this.helper); 4294 // position helper (lasso) 4295 this.helper.css({ 4296 "left": event.pageX, 4297 "top": event.pageY, 4298 "width": 0, 4299 "height": 0 4300 }); 4301 4302 if (options.autoRefresh) { 4303 this.refresh(); 4304 } 4305 4306 this.selectees.filter(".ui-selected").each(function() { 4307 var selectee = $.data(this, "selectable-item"); 4308 selectee.startselected = true; 4309 if (!event.metaKey && !event.ctrlKey) { 4310 selectee.$element.removeClass("ui-selected"); 4311 selectee.selected = false; 4312 selectee.$element.addClass("ui-unselecting"); 4313 selectee.unselecting = true; 4314 // selectable UNSELECTING callback 4315 that._trigger("unselecting", event, { 4316 unselecting: selectee.element 4317 }); 4318 } 4319 }); 4320 4321 $(event.target).parents().addBack().each(function() { 4322 var doSelect, 4323 selectee = $.data(this, "selectable-item"); 4324 if (selectee) { 4325 doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected"); 4326 selectee.$element 4327 .removeClass(doSelect ? "ui-unselecting" : "ui-selected") 4328 .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); 4329 selectee.unselecting = !doSelect; 4330 selectee.selecting = doSelect; 4331 selectee.selected = doSelect; 4332 // selectable (UN)SELECTING callback 4333 if (doSelect) { 4334 that._trigger("selecting", event, { 4335 selecting: selectee.element 4336 }); 4337 } else { 4338 that._trigger("unselecting", event, { 4339 unselecting: selectee.element 4340 }); 4341 } 4342 return false; 4343 } 4344 }); 4345 4346 }, 4347 4348 _mouseDrag: function(event) { 4349 4350 this.dragged = true; 4351 4352 if (this.options.disabled) { 4353 return; 4354 } 4355 4356 var tmp, 4357 that = this, 4358 options = this.options, 4359 x1 = this.opos[0], 4360 y1 = this.opos[1], 4361 x2 = event.pageX, 4362 y2 = event.pageY; 4363 4364 if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; } 4365 if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; } 4366 this.helper.css({ left: x1, top: y1, width: x2 - x1, height: y2 - y1 }); 4367 4368 this.selectees.each(function() { 4369 var selectee = $.data(this, "selectable-item"), 4370 hit = false; 4371 4372 //prevent helper from being selected if appendTo: selectable 4373 if (!selectee || selectee.element === that.element[0]) { 4374 return; 4375 } 4376 4377 if (options.tolerance === "touch") { 4378 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); 4379 } else if (options.tolerance === "fit") { 4380 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); 4381 } 4382 4383 if (hit) { 4384 // SELECT 4385 if (selectee.selected) { 4386 selectee.$element.removeClass("ui-selected"); 4387 selectee.selected = false; 4388 } 4389 if (selectee.unselecting) { 4390 selectee.$element.removeClass("ui-unselecting"); 4391 selectee.unselecting = false; 4392 } 4393 if (!selectee.selecting) { 4394 selectee.$element.addClass("ui-selecting"); 4395 selectee.selecting = true; 4396 // selectable SELECTING callback 4397 that._trigger("selecting", event, { 4398 selecting: selectee.element 4399 }); 4400 } 4401 } else { 4402 // UNSELECT 4403 if (selectee.selecting) { 4404 if ((event.metaKey || event.ctrlKey) && selectee.startselected) { 4405 selectee.$element.removeClass("ui-selecting"); 4406 selectee.selecting = false; 4407 selectee.$element.addClass("ui-selected"); 4408 selectee.selected = true; 4409 } else { 4410 selectee.$element.removeClass("ui-selecting"); 4411 selectee.selecting = false; 4412 if (selectee.startselected) { 4413 selectee.$element.addClass("ui-unselecting"); 4414 selectee.unselecting = true; 4415 } 4416 // selectable UNSELECTING callback 4417 that._trigger("unselecting", event, { 4418 unselecting: selectee.element 4419 }); 4420 } 4421 } 4422 if (selectee.selected) { 4423 if (!event.metaKey && !event.ctrlKey && !selectee.startselected) { 4424 selectee.$element.removeClass("ui-selected"); 4425 selectee.selected = false; 4426 4427 selectee.$element.addClass("ui-unselecting"); 4428 selectee.unselecting = true; 4429 // selectable UNSELECTING callback 4430 that._trigger("unselecting", event, { 4431 unselecting: selectee.element 4432 }); 4433 } 4434 } 4435 } 4436 }); 4437 4438 return false; 4439 }, 4440 4441 _mouseStop: function(event) { 4442 var that = this; 4443 4444 this.dragged = false; 4445 4446 $(".ui-unselecting", this.element[0]).each(function() { 4447 var selectee = $.data(this, "selectable-item"); 4448 selectee.$element.removeClass("ui-unselecting"); 4449 selectee.unselecting = false; 4450 selectee.startselected = false; 4451 that._trigger("unselected", event, { 4452 unselected: selectee.element 4453 }); 4454 }); 4455 $(".ui-selecting", this.element[0]).each(function() { 4456 var selectee = $.data(this, "selectable-item"); 4457 selectee.$element.removeClass("ui-selecting").addClass("ui-selected"); 4458 selectee.selecting = false; 4459 selectee.selected = true; 4460 selectee.startselected = true; 4461 that._trigger("selected", event, { 4462 selected: selectee.element 4463 }); 4464 }); 4465 this._trigger("stop", event); 4466 4467 this.helper.remove(); 4468 4469 return false; 4470 } 4471 4472 }); 4473 4474 4475 /*! 4476 * jQuery UI Sortable 1.11.4 4477 * http://jqueryui.com 4478 * 4479 * Copyright jQuery Foundation and other contributors 4480 * Released under the MIT license. 4481 * http://jquery.org/license 4482 * 4483 * http://api.jqueryui.com/sortable/ 4484 */ 4485 4486 4487 var sortable = $.widget("ui.sortable", $.ui.mouse, { 4488 version: "1.11.4", 4489 widgetEventPrefix: "sort", 4490 ready: false, 4491 options: { 4492 appendTo: "parent", 4493 axis: false, 4494 connectWith: false, 4495 containment: false, 4496 cursor: "auto", 4497 cursorAt: false, 4498 dropOnEmpty: true, 4499 forcePlaceholderSize: false, 4500 forceHelperSize: false, 4501 grid: false, 4502 handle: false, 4503 helper: "original", 4504 items: "> *", 4505 opacity: false, 4506 placeholder: false, 4507 revert: false, 4508 scroll: true, 4509 scrollSensitivity: 20, 4510 scrollSpeed: 20, 4511 scope: "default", 4512 tolerance: "intersect", 4513 zIndex: 1000, 4514 4515 // callbacks 4516 activate: null, 4517 beforeStop: null, 4518 change: null, 4519 deactivate: null, 4520 out: null, 4521 over: null, 4522 receive: null, 4523 remove: null, 4524 sort: null, 4525 start: null, 4526 stop: null, 4527 update: null 4528 }, 4529 4530 _isOverAxis: function( x, reference, size ) { 4531 return ( x >= reference ) && ( x < ( reference + size ) ); 4532 }, 4533 4534 _isFloating: function( item ) { 4535 return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display")); 4536 }, 4537 4538 _create: function() { 4539 this.containerCache = {}; 4540 this.element.addClass("ui-sortable"); 4541 4542 //Get the items 4543 this.refresh(); 4544 4545 //Let's determine the parent's offset 4546 this.offset = this.element.offset(); 4547 4548 //Initialize mouse events for interaction 4549 this._mouseInit(); 4550 4551 this._setHandleClassName(); 4552 4553 //We're ready to go 4554 this.ready = true; 4555 4556 }, 4557 4558 _setOption: function( key, value ) { 4559 this._super( key, value ); 4560 4561 if ( key === "handle" ) { 4562 this._setHandleClassName(); 4563 } 4564 }, 4565 4566 _setHandleClassName: function() { 4567 this.element.find( ".ui-sortable-handle" ).removeClass( "ui-sortable-handle" ); 4568 $.each( this.items, function() { 4569 ( this.instance.options.handle ? 4570 this.item.find( this.instance.options.handle ) : this.item ) 4571 .addClass( "ui-sortable-handle" ); 4572 }); 4573 }, 4574 4575 _destroy: function() { 4576 this.element 4577 .removeClass( "ui-sortable ui-sortable-disabled" ) 4578 .find( ".ui-sortable-handle" ) 4579 .removeClass( "ui-sortable-handle" ); 4580 this._mouseDestroy(); 4581 4582 for ( var i = this.items.length - 1; i >= 0; i-- ) { 4583 this.items[i].item.removeData(this.widgetName + "-item"); 4584 } 4585 4586 return this; 4587 }, 4588 4589 _mouseCapture: function(event, overrideHandle) { 4590 var currentItem = null, 4591 validHandle = false, 4592 that = this; 4593 4594 if (this.reverting) { 4595 return false; 4596 } 4597 4598 if(this.options.disabled || this.options.type === "static") { 4599 return false; 4600 } 4601 4602 //We have to refresh the items data once first 4603 this._refreshItems(event); 4604 4605 //Find out if the clicked node (or one of its parents) is a actual item in this.items 4606 $(event.target).parents().each(function() { 4607 if($.data(this, that.widgetName + "-item") === that) { 4608 currentItem = $(this); 4609 return false; 4610 } 4611 }); 4612 if($.data(event.target, that.widgetName + "-item") === that) { 4613 currentItem = $(event.target); 4614 } 4615 4616 if(!currentItem) { 4617 return false; 4618 } 4619 if(this.options.handle && !overrideHandle) { 4620 $(this.options.handle, currentItem).find("*").addBack().each(function() { 4621 if(this === event.target) { 4622 validHandle = true; 4623 } 4624 }); 4625 if(!validHandle) { 4626 return false; 4627 } 4628 } 4629 4630 this.currentItem = currentItem; 4631 this._removeCurrentsFromItems(); 4632 return true; 4633 4634 }, 4635 4636 _mouseStart: function(event, overrideHandle, noActivation) { 4637 4638 var i, body, 4639 o = this.options; 4640 4641 this.currentContainer = this; 4642 4643 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture 4644 this.refreshPositions(); 4645 4646 //Create and append the visible helper 4647 this.helper = this._createHelper(event); 4648 4649 //Cache the helper size 4650 this._cacheHelperProportions(); 4651 4652 /* 4653 * - Position generation - 4654 * This block generates everything position related - it's the core of draggables. 4655 */ 4656 4657 //Cache the margins of the original element 4658 this._cacheMargins(); 4659 4660 //Get the next scrolling parent 4661 this.scrollParent = this.helper.scrollParent(); 4662 4663 //The element's absolute position on the page minus margins 4664 this.offset = this.currentItem.offset(); 4665 this.offset = { 4666 top: this.offset.top - this.margins.top, 4667 left: this.offset.left - this.margins.left 4668 }; 4669 4670 $.extend(this.offset, { 4671 click: { //Where the click happened, relative to the element 4672 left: event.pageX - this.offset.left, 4673 top: event.pageY - this.offset.top 4674 }, 4675 parent: this._getParentOffset(), 4676 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper 4677 }); 4678 4679 // Only after we got the offset, we can change the helper's position to absolute 4680 // TODO: Still need to figure out a way to make relative sorting possible 4681 this.helper.css("position", "absolute"); 4682 this.cssPosition = this.helper.css("position"); 4683 4684 //Generate the original position 4685 this.originalPosition = this._generatePosition(event); 4686 this.originalPageX = event.pageX; 4687 this.originalPageY = event.pageY; 4688 4689 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 4690 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); 4691 4692 //Cache the former DOM position 4693 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; 4694 4695 //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way 4696 if(this.helper[0] !== this.currentItem[0]) { 4697 this.currentItem.hide(); 4698 } 4699 4700 //Create the placeholder 4701 this._createPlaceholder(); 4702 4703 //Set a containment if given in the options 4704 if(o.containment) { 4705 this._setContainment(); 4706 } 4707 4708 if( o.cursor && o.cursor !== "auto" ) { // cursor option 4709 body = this.document.find( "body" ); 4710 4711 // support: IE 4712 this.storedCursor = body.css( "cursor" ); 4713 body.css( "cursor", o.cursor ); 4714 4715 this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body ); 4716 } 4717 4718 if(o.opacity) { // opacity option 4719 if (this.helper.css("opacity")) { 4720 this._storedOpacity = this.helper.css("opacity"); 4721 } 4722 this.helper.css("opacity", o.opacity); 4723 } 4724 4725 if(o.zIndex) { // zIndex option 4726 if (this.helper.css("zIndex")) { 4727 this._storedZIndex = this.helper.css("zIndex"); 4728 } 4729 this.helper.css("zIndex", o.zIndex); 4730 } 4731 4732 //Prepare scrolling 4733 if(this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") { 4734 this.overflowOffset = this.scrollParent.offset(); 4735 } 4736 4737 //Call callbacks 4738 this._trigger("start", event, this._uiHash()); 4739 4740 //Recache the helper size 4741 if(!this._preserveHelperProportions) { 4742 this._cacheHelperProportions(); 4743 } 4744 4745 4746 //Post "activate" events to possible containers 4747 if( !noActivation ) { 4748 for ( i = this.containers.length - 1; i >= 0; i-- ) { 4749 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); 4750 } 4751 } 4752 4753 //Prepare possible droppables 4754 if($.ui.ddmanager) { 4755 $.ui.ddmanager.current = this; 4756 } 4757 4758 if ($.ui.ddmanager && !o.dropBehaviour) { 4759 $.ui.ddmanager.prepareOffsets(this, event); 4760 } 4761 4762 this.dragging = true; 4763 4764 this.helper.addClass("ui-sortable-helper"); 4765 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position 4766 return true; 4767 4768 }, 4769 4770 _mouseDrag: function(event) { 4771 var i, item, itemElement, intersection, 4772 o = this.options, 4773 scrolled = false; 4774 4775 //Compute the helpers position 4776 this.position = this._generatePosition(event); 4777 this.positionAbs = this._convertPositionTo("absolute"); 4778 4779 if (!this.lastPositionAbs) { 4780 this.lastPositionAbs = this.positionAbs; 4781 } 4782 4783 //Do scrolling 4784 if(this.options.scroll) { 4785 if(this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") { 4786 4787 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { 4788 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; 4789 } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) { 4790 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; 4791 } 4792 4793 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { 4794 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; 4795 } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) { 4796 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; 4797 } 4798 4799 } else { 4800 4801 if(event.pageY - this.document.scrollTop() < o.scrollSensitivity) { 4802 scrolled = this.document.scrollTop(this.document.scrollTop() - o.scrollSpeed); 4803 } else if(this.window.height() - (event.pageY - this.document.scrollTop()) < o.scrollSensitivity) { 4804 scrolled = this.document.scrollTop(this.document.scrollTop() + o.scrollSpeed); 4805 } 4806 4807 if(event.pageX - this.document.scrollLeft() < o.scrollSensitivity) { 4808 scrolled = this.document.scrollLeft(this.document.scrollLeft() - o.scrollSpeed); 4809 } else if(this.window.width() - (event.pageX - this.document.scrollLeft()) < o.scrollSensitivity) { 4810 scrolled = this.document.scrollLeft(this.document.scrollLeft() + o.scrollSpeed); 4811 } 4812 4813 } 4814 4815 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { 4816 $.ui.ddmanager.prepareOffsets(this, event); 4817 } 4818 } 4819 4820 //Regenerate the absolute position used for position checks 4821 this.positionAbs = this._convertPositionTo("absolute"); 4822 4823 //Set the helper position 4824 if(!this.options.axis || this.options.axis !== "y") { 4825 this.helper[0].style.left = this.position.left+"px"; 4826 } 4827 if(!this.options.axis || this.options.axis !== "x") { 4828 this.helper[0].style.top = this.position.top+"px"; 4829 } 4830 4831 //Rearrange 4832 for (i = this.items.length - 1; i >= 0; i--) { 4833 4834 //Cache variables and intersection, continue if no intersection 4835 item = this.items[i]; 4836 itemElement = item.item[0]; 4837 intersection = this._intersectsWithPointer(item); 4838 if (!intersection) { 4839 continue; 4840 } 4841 4842 // Only put the placeholder inside the current Container, skip all 4843 // items from other containers. This works because when moving 4844 // an item from one container to another the 4845 // currentContainer is switched before the placeholder is moved. 4846 // 4847 // Without this, moving items in "sub-sortables" can cause 4848 // the placeholder to jitter between the outer and inner container. 4849 if (item.instance !== this.currentContainer) { 4850 continue; 4851 } 4852 4853 // cannot intersect with itself 4854 // no useless actions that have been done before 4855 // no action if the item moved is the parent of the item checked 4856 if (itemElement !== this.currentItem[0] && 4857 this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement && 4858 !$.contains(this.placeholder[0], itemElement) && 4859 (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true) 4860 ) { 4861 4862 this.direction = intersection === 1 ? "down" : "up"; 4863 4864 if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) { 4865 this._rearrange(event, item); 4866 } else { 4867 break; 4868 } 4869 4870 this._trigger("change", event, this._uiHash()); 4871 break; 4872 } 4873 } 4874 4875 //Post events to containers 4876 this._contactContainers(event); 4877 4878 //Interconnect with droppables 4879 if($.ui.ddmanager) { 4880 $.ui.ddmanager.drag(this, event); 4881 } 4882 4883 //Call callbacks 4884 this._trigger("sort", event, this._uiHash()); 4885 4886 this.lastPositionAbs = this.positionAbs; 4887 return false; 4888 4889 }, 4890 4891 _mouseStop: function(event, noPropagation) { 4892 4893 if(!event) { 4894 return; 4895 } 4896 4897 //If we are using droppables, inform the manager about the drop 4898 if ($.ui.ddmanager && !this.options.dropBehaviour) { 4899 $.ui.ddmanager.drop(this, event); 4900 } 4901 4902 if(this.options.revert) { 4903 var that = this, 4904 cur = this.placeholder.offset(), 4905 axis = this.options.axis, 4906 animation = {}; 4907 4908 if ( !axis || axis === "x" ) { 4909 animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollLeft); 4910 } 4911 if ( !axis || axis === "y" ) { 4912 animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollTop); 4913 } 4914 this.reverting = true; 4915 $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() { 4916 that._clear(event); 4917 }); 4918 } else { 4919 this._clear(event, noPropagation); 4920 } 4921 4922 return false; 4923 4924 }, 4925 4926 cancel: function() { 4927 4928 if(this.dragging) { 4929 4930 this._mouseUp({ target: null }); 4931 4932 if(this.options.helper === "original") { 4933 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); 4934 } else { 4935 this.currentItem.show(); 4936 } 4937 4938 //Post deactivating events to containers 4939 for (var i = this.containers.length - 1; i >= 0; i--){ 4940 this.containers[i]._trigger("deactivate", null, this._uiHash(this)); 4941 if(this.containers[i].containerCache.over) { 4942 this.containers[i]._trigger("out", null, this._uiHash(this)); 4943 this.containers[i].containerCache.over = 0; 4944 } 4945 } 4946 4947 } 4948 4949 if (this.placeholder) { 4950 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! 4951 if(this.placeholder[0].parentNode) { 4952 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 4953 } 4954 if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) { 4955 this.helper.remove(); 4956 } 4957 4958 $.extend(this, { 4959 helper: null, 4960 dragging: false, 4961 reverting: false, 4962 _noFinalSort: null 4963 }); 4964 4965 if(this.domPosition.prev) { 4966 $(this.domPosition.prev).after(this.currentItem); 4967 } else { 4968 $(this.domPosition.parent).prepend(this.currentItem); 4969 } 4970 } 4971 4972 return this; 4973 4974 }, 4975 4976 serialize: function(o) { 4977 4978 var items = this._getItemsAsjQuery(o && o.connected), 4979 str = []; 4980 o = o || {}; 4981 4982 $(items).each(function() { 4983 var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/)); 4984 if (res) { 4985 str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2])); 4986 } 4987 }); 4988 4989 if(!str.length && o.key) { 4990 str.push(o.key + "="); 4991 } 4992 4993 return str.join("&"); 4994 4995 }, 4996 4997 toArray: function(o) { 4998 4999 var items = this._getItemsAsjQuery(o && o.connected), 5000 ret = []; 5001 5002 o = o || {}; 5003 5004 items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); }); 5005 return ret; 5006 5007 }, 5008 5009 /* Be careful with the following core functions */ 5010 _intersectsWith: function(item) { 5011 5012 var x1 = this.positionAbs.left, 5013 x2 = x1 + this.helperProportions.width, 5014 y1 = this.positionAbs.top, 5015 y2 = y1 + this.helperProportions.height, 5016 l = item.left, 5017 r = l + item.width, 5018 t = item.top, 5019 b = t + item.height, 5020 dyClick = this.offset.click.top, 5021 dxClick = this.offset.click.left, 5022 isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ), 5023 isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ), 5024 isOverElement = isOverElementHeight && isOverElementWidth; 5025 5026 if ( this.options.tolerance === "pointer" || 5027 this.options.forcePointerForContainers || 5028 (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"]) 5029 ) { 5030 return isOverElement; 5031 } else { 5032 5033 return (l < x1 + (this.helperProportions.width / 2) && // Right Half 5034 x2 - (this.helperProportions.width / 2) < r && // Left Half 5035 t < y1 + (this.helperProportions.height / 2) && // Bottom Half 5036 y2 - (this.helperProportions.height / 2) < b ); // Top Half 5037 5038 } 5039 }, 5040 5041 _intersectsWithPointer: function(item) { 5042 5043 var isOverElementHeight = (this.options.axis === "x") || this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), 5044 isOverElementWidth = (this.options.axis === "y") || this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), 5045 isOverElement = isOverElementHeight && isOverElementWidth, 5046 verticalDirection = this._getDragVerticalDirection(), 5047 horizontalDirection = this._getDragHorizontalDirection(); 5048 5049 if (!isOverElement) { 5050 return false; 5051 } 5052 5053 return this.floating ? 5054 ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 ) 5055 : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) ); 5056 5057 }, 5058 5059 _intersectsWithSides: function(item) { 5060 5061 var isOverBottomHalf = this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), 5062 isOverRightHalf = this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), 5063 verticalDirection = this._getDragVerticalDirection(), 5064 horizontalDirection = this._getDragHorizontalDirection(); 5065 5066 if (this.floating && horizontalDirection) { 5067 return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf)); 5068 } else { 5069 return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf)); 5070 } 5071 5072 }, 5073 5074 _getDragVerticalDirection: function() { 5075 var delta = this.positionAbs.top - this.lastPositionAbs.top; 5076 return delta !== 0 && (delta > 0 ? "down" : "up"); 5077 }, 5078 5079 _getDragHorizontalDirection: function() { 5080 var delta = this.positionAbs.left - this.lastPositionAbs.left; 5081 return delta !== 0 && (delta > 0 ? "right" : "left"); 5082 }, 5083 5084 refresh: function(event) { 5085 this._refreshItems(event); 5086 this._setHandleClassName(); 5087 this.refreshPositions(); 5088 return this; 5089 }, 5090 5091 _connectWith: function() { 5092 var options = this.options; 5093 return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith; 5094 }, 5095 5096 _getItemsAsjQuery: function(connected) { 5097 5098 var i, j, cur, inst, 5099 items = [], 5100 queries = [], 5101 connectWith = this._connectWith(); 5102 5103 if(connectWith && connected) { 5104 for (i = connectWith.length - 1; i >= 0; i--){ 5105 cur = $(connectWith[i], this.document[0]); 5106 for ( j = cur.length - 1; j >= 0; j--){ 5107 inst = $.data(cur[j], this.widgetFullName); 5108 if(inst && inst !== this && !inst.options.disabled) { 5109 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), inst]); 5110 } 5111 } 5112 } 5113 } 5114 5115 queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]); 5116 5117 function addItems() { 5118 items.push( this ); 5119 } 5120 for (i = queries.length - 1; i >= 0; i--){ 5121 queries[i][0].each( addItems ); 5122 } 5123 5124 return $(items); 5125 5126 }, 5127 5128 _removeCurrentsFromItems: function() { 5129 5130 var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); 5131 5132 this.items = $.grep(this.items, function (item) { 5133 for (var j=0; j < list.length; j++) { 5134 if(list[j] === item.item[0]) { 5135 return false; 5136 } 5137 } 5138 return true; 5139 }); 5140 5141 }, 5142 5143 _refreshItems: function(event) { 5144 5145 this.items = []; 5146 this.containers = [this]; 5147 5148 var i, j, cur, inst, targetData, _queries, item, queriesLength, 5149 items = this.items, 5150 queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]], 5151 connectWith = this._connectWith(); 5152 5153 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down 5154 for (i = connectWith.length - 1; i >= 0; i--){ 5155 cur = $(connectWith[i], this.document[0]); 5156 for (j = cur.length - 1; j >= 0; j--){ 5157 inst = $.data(cur[j], this.widgetFullName); 5158 if(inst && inst !== this && !inst.options.disabled) { 5159 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); 5160 this.containers.push(inst); 5161 } 5162 } 5163 } 5164 } 5165 5166 for (i = queries.length - 1; i >= 0; i--) { 5167 targetData = queries[i][1]; 5168 _queries = queries[i][0]; 5169 5170 for (j=0, queriesLength = _queries.length; j < queriesLength; j++) { 5171 item = $(_queries[j]); 5172 5173 item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager) 5174 5175 items.push({ 5176 item: item, 5177 instance: targetData, 5178 width: 0, height: 0, 5179 left: 0, top: 0 5180 }); 5181 } 5182 } 5183 5184 }, 5185 5186 refreshPositions: function(fast) { 5187 5188 // Determine whether items are being displayed horizontally 5189 this.floating = this.items.length ? 5190 this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) : 5191 false; 5192 5193 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change 5194 if(this.offsetParent && this.helper) { 5195 this.offset.parent = this._getParentOffset(); 5196 } 5197 5198 var i, item, t, p; 5199 5200 for (i = this.items.length - 1; i >= 0; i--){ 5201 item = this.items[i]; 5202 5203 //We ignore calculating positions of all connected containers when we're not over them 5204 if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) { 5205 continue; 5206 } 5207 5208 t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; 5209 5210 if (!fast) { 5211 item.width = t.outerWidth(); 5212 item.height = t.outerHeight(); 5213 } 5214 5215 p = t.offset(); 5216 item.left = p.left; 5217 item.top = p.top; 5218 } 5219 5220 if(this.options.custom && this.options.custom.refreshContainers) { 5221 this.options.custom.refreshContainers.call(this); 5222 } else { 5223 for (i = this.containers.length - 1; i >= 0; i--){ 5224 p = this.containers[i].element.offset(); 5225 this.containers[i].containerCache.left = p.left; 5226 this.containers[i].containerCache.top = p.top; 5227 this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); 5228 this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); 5229 } 5230 } 5231 5232 return this; 5233 }, 5234 5235 _createPlaceholder: function(that) { 5236 that = that || this; 5237 var className, 5238 o = that.options; 5239 5240 if(!o.placeholder || o.placeholder.constructor === String) { 5241 className = o.placeholder; 5242 o.placeholder = { 5243 element: function() { 5244 5245 var nodeName = that.currentItem[0].nodeName.toLowerCase(), 5246 element = $( "<" + nodeName + ">", that.document[0] ) 5247 .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder") 5248 .removeClass("ui-sortable-helper"); 5249 5250 if ( nodeName === "tbody" ) { 5251 that._createTrPlaceholder( 5252 that.currentItem.find( "tr" ).eq( 0 ), 5253 $( "<tr>", that.document[ 0 ] ).appendTo( element ) 5254 ); 5255 } else if ( nodeName === "tr" ) { 5256 that._createTrPlaceholder( that.currentItem, element ); 5257 } else if ( nodeName === "img" ) { 5258 element.attr( "src", that.currentItem.attr( "src" ) ); 5259 } 5260 5261 if ( !className ) { 5262 element.css( "visibility", "hidden" ); 5263 } 5264 5265 return element; 5266 }, 5267 update: function(container, p) { 5268 5269 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that 5270 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified 5271 if(className && !o.forcePlaceholderSize) { 5272 return; 5273 } 5274 5275 //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item 5276 if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); } 5277 if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); } 5278 } 5279 }; 5280 } 5281 5282 //Create the placeholder 5283 that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem)); 5284 5285 //Append it after the actual current item 5286 that.currentItem.after(that.placeholder); 5287 5288 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) 5289 o.placeholder.update(that, that.placeholder); 5290 5291 }, 5292 5293 _createTrPlaceholder: function( sourceTr, targetTr ) { 5294 var that = this; 5295 5296 sourceTr.children().each(function() { 5297 $( "<td> </td>", that.document[ 0 ] ) 5298 .attr( "colspan", $( this ).attr( "colspan" ) || 1 ) 5299 .appendTo( targetTr ); 5300 }); 5301 }, 5302 5303 _contactContainers: function(event) { 5304 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, floating, axis, 5305 innermostContainer = null, 5306 innermostIndex = null; 5307 5308 // get innermost container that intersects with item 5309 for (i = this.containers.length - 1; i >= 0; i--) { 5310 5311 // never consider a container that's located within the item itself 5312 if($.contains(this.currentItem[0], this.containers[i].element[0])) { 5313 continue; 5314 } 5315 5316 if(this._intersectsWith(this.containers[i].containerCache)) { 5317 5318 // if we've already found a container and it's more "inner" than this, then continue 5319 if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) { 5320 continue; 5321 } 5322 5323 innermostContainer = this.containers[i]; 5324 innermostIndex = i; 5325 5326 } else { 5327 // container doesn't intersect. trigger "out" event if necessary 5328 if(this.containers[i].containerCache.over) { 5329 this.containers[i]._trigger("out", event, this._uiHash(this)); 5330 this.containers[i].containerCache.over = 0; 5331 } 5332 } 5333 5334 } 5335 5336 // if no intersecting containers found, return 5337 if(!innermostContainer) { 5338 return; 5339 } 5340 5341 // move the item into the container if it's not there already 5342 if(this.containers.length === 1) { 5343 if (!this.containers[innermostIndex].containerCache.over) { 5344 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 5345 this.containers[innermostIndex].containerCache.over = 1; 5346 } 5347 } else { 5348 5349 //When entering a new container, we will find the item with the least distance and append our item near it 5350 dist = 10000; 5351 itemWithLeastDistance = null; 5352 floating = innermostContainer.floating || this._isFloating(this.currentItem); 5353 posProperty = floating ? "left" : "top"; 5354 sizeProperty = floating ? "width" : "height"; 5355 axis = floating ? "clientX" : "clientY"; 5356 5357 for (j = this.items.length - 1; j >= 0; j--) { 5358 if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) { 5359 continue; 5360 } 5361 if(this.items[j].item[0] === this.currentItem[0]) { 5362 continue; 5363 } 5364 5365 cur = this.items[j].item.offset()[posProperty]; 5366 nearBottom = false; 5367 if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) { 5368 nearBottom = true; 5369 } 5370 5371 if ( Math.abs( event[ axis ] - cur ) < dist ) { 5372 dist = Math.abs( event[ axis ] - cur ); 5373 itemWithLeastDistance = this.items[ j ]; 5374 this.direction = nearBottom ? "up": "down"; 5375 } 5376 } 5377 5378 //Check if dropOnEmpty is enabled 5379 if(!itemWithLeastDistance && !this.options.dropOnEmpty) { 5380 return; 5381 } 5382 5383 if(this.currentContainer === this.containers[innermostIndex]) { 5384 if ( !this.currentContainer.containerCache.over ) { 5385 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() ); 5386 this.currentContainer.containerCache.over = 1; 5387 } 5388 return; 5389 } 5390 5391 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 5392 this._trigger("change", event, this._uiHash()); 5393 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 5394 this.currentContainer = this.containers[innermostIndex]; 5395 5396 //Update the placeholder 5397 this.options.placeholder.update(this.currentContainer, this.placeholder); 5398 5399 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 5400 this.containers[innermostIndex].containerCache.over = 1; 5401 } 5402 5403 5404 }, 5405 5406 _createHelper: function(event) { 5407 5408 var o = this.options, 5409 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem); 5410 5411 //Add the helper to the DOM if that didn't happen already 5412 if(!helper.parents("body").length) { 5413 $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); 5414 } 5415 5416 if(helper[0] === this.currentItem[0]) { 5417 this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") }; 5418 } 5419 5420 if(!helper[0].style.width || o.forceHelperSize) { 5421 helper.width(this.currentItem.width()); 5422 } 5423 if(!helper[0].style.height || o.forceHelperSize) { 5424 helper.height(this.currentItem.height()); 5425 } 5426 5427 return helper; 5428 5429 }, 5430 5431 _adjustOffsetFromHelper: function(obj) { 5432 if (typeof obj === "string") { 5433 obj = obj.split(" "); 5434 } 5435 if ($.isArray(obj)) { 5436 obj = {left: +obj[0], top: +obj[1] || 0}; 5437 } 5438 if ("left" in obj) { 5439 this.offset.click.left = obj.left + this.margins.left; 5440 } 5441 if ("right" in obj) { 5442 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 5443 } 5444 if ("top" in obj) { 5445 this.offset.click.top = obj.top + this.margins.top; 5446 } 5447 if ("bottom" in obj) { 5448 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 5449 } 5450 }, 5451 5452 _getParentOffset: function() { 5453 5454 5455 //Get the offsetParent and cache its position 5456 this.offsetParent = this.helper.offsetParent(); 5457 var po = this.offsetParent.offset(); 5458 5459 // This is a special case where we need to modify a offset calculated on start, since the following happened: 5460 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent 5461 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that 5462 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag 5463 if(this.cssPosition === "absolute" && this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) { 5464 po.left += this.scrollParent.scrollLeft(); 5465 po.top += this.scrollParent.scrollTop(); 5466 } 5467 5468 // This needs to be actually done for all browsers, since pageX/pageY includes this information 5469 // with an ugly IE fix 5470 if( this.offsetParent[0] === this.document[0].body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { 5471 po = { top: 0, left: 0 }; 5472 } 5473 5474 return { 5475 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), 5476 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) 5477 }; 5478 5479 }, 5480 5481 _getRelativeOffset: function() { 5482 5483 if(this.cssPosition === "relative") { 5484 var p = this.currentItem.position(); 5485 return { 5486 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), 5487 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() 5488 }; 5489 } else { 5490 return { top: 0, left: 0 }; 5491 } 5492 5493 }, 5494 5495 _cacheMargins: function() { 5496 this.margins = { 5497 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), 5498 top: (parseInt(this.currentItem.css("marginTop"),10) || 0) 5499 }; 5500 }, 5501 5502 _cacheHelperProportions: function() { 5503 this.helperProportions = { 5504 width: this.helper.outerWidth(), 5505 height: this.helper.outerHeight() 5506 }; 5507 }, 5508 5509 _setContainment: function() { 5510 5511 var ce, co, over, 5512 o = this.options; 5513 if(o.containment === "parent") { 5514 o.containment = this.helper[0].parentNode; 5515 } 5516 if(o.containment === "document" || o.containment === "window") { 5517 this.containment = [ 5518 0 - this.offset.relative.left - this.offset.parent.left, 5519 0 - this.offset.relative.top - this.offset.parent.top, 5520 o.containment === "document" ? this.document.width() : this.window.width() - this.helperProportions.width - this.margins.left, 5521 (o.containment === "document" ? this.document.width() : this.window.height() || this.document[0].body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top 5522 ]; 5523 } 5524 5525 if(!(/^(document|window|parent)$/).test(o.containment)) { 5526 ce = $(o.containment)[0]; 5527 co = $(o.containment).offset(); 5528 over = ($(ce).css("overflow") !== "hidden"); 5529 5530 this.containment = [ 5531 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, 5532 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, 5533 co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left, 5534 co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top 5535 ]; 5536 } 5537 5538 }, 5539 5540 _convertPositionTo: function(d, pos) { 5541 5542 if(!pos) { 5543 pos = this.position; 5544 } 5545 var mod = d === "absolute" ? 1 : -1, 5546 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, 5547 scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 5548 5549 return { 5550 top: ( 5551 pos.top + // The absolute mouse position 5552 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 5553 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) 5554 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) 5555 ), 5556 left: ( 5557 pos.left + // The absolute mouse position 5558 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 5559 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) 5560 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) 5561 ) 5562 }; 5563 5564 }, 5565 5566 _generatePosition: function(event) { 5567 5568 var top, left, 5569 o = this.options, 5570 pageX = event.pageX, 5571 pageY = event.pageY, 5572 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 5573 5574 // This is another very weird special case that only happens for relative elements: 5575 // 1. If the css position is relative 5576 // 2. and the scroll parent is the document or similar to the offset parent 5577 // we have to refresh the relative offset during the scroll so there are no jumps 5578 if(this.cssPosition === "relative" && !(this.scrollParent[0] !== this.document[0] && this.scrollParent[0] !== this.offsetParent[0])) { 5579 this.offset.relative = this._getRelativeOffset(); 5580 } 5581 5582 /* 5583 * - Position constraining - 5584 * Constrain the position to a mix of grid, containment. 5585 */ 5586 5587 if(this.originalPosition) { //If we are not dragging yet, we won't check for options 5588 5589 if(this.containment) { 5590 if(event.pageX - this.offset.click.left < this.containment[0]) { 5591 pageX = this.containment[0] + this.offset.click.left; 5592 } 5593 if(event.pageY - this.offset.click.top < this.containment[1]) { 5594 pageY = this.containment[1] + this.offset.click.top; 5595 } 5596 if(event.pageX - this.offset.click.left > this.containment[2]) { 5597 pageX = this.containment[2] + this.offset.click.left; 5598 } 5599 if(event.pageY - this.offset.click.top > this.containment[3]) { 5600 pageY = this.containment[3] + this.offset.click.top; 5601 } 5602 } 5603 5604 if(o.grid) { 5605 top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; 5606 pageY = this.containment ? ( (top - this.offset.click.top >= this.containment[1] && top - this.offset.click.top <= this.containment[3]) ? top : ((top - this.offset.click.top >= this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; 5607 5608 left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; 5609 pageX = this.containment ? ( (left - this.offset.click.left >= this.containment[0] && left - this.offset.click.left <= this.containment[2]) ? left : ((left - this.offset.click.left >= this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; 5610 } 5611 5612 } 5613 5614 return { 5615 top: ( 5616 pageY - // The absolute mouse position 5617 this.offset.click.top - // Click offset (relative to the element) 5618 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent 5619 this.offset.parent.top + // The offsetParent's offset without borders (offset + border) 5620 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) 5621 ), 5622 left: ( 5623 pageX - // The absolute mouse position 5624 this.offset.click.left - // Click offset (relative to the element) 5625 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent 5626 this.offset.parent.left + // The offsetParent's offset without borders (offset + border) 5627 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) 5628 ) 5629 }; 5630 5631 }, 5632 5633 _rearrange: function(event, i, a, hardRefresh) { 5634 5635 a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" ? i.item[0] : i.item[0].nextSibling)); 5636 5637 //Various things done here to improve the performance: 5638 // 1. we create a setTimeout, that calls refreshPositions 5639 // 2. on the instance, we have a counter variable, that get's higher after every append 5640 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same 5641 // 4. this lets only the last addition to the timeout stack through 5642 this.counter = this.counter ? ++this.counter : 1; 5643 var counter = this.counter; 5644 5645 this._delay(function() { 5646 if(counter === this.counter) { 5647 this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove 5648 } 5649 }); 5650 5651 }, 5652 5653 _clear: function(event, noPropagation) { 5654 5655 this.reverting = false; 5656 // We delay all events that have to be triggered to after the point where the placeholder has been removed and 5657 // everything else normalized again 5658 var i, 5659 delayedTriggers = []; 5660 5661 // We first have to update the dom position of the actual currentItem 5662 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) 5663 if(!this._noFinalSort && this.currentItem.parent().length) { 5664 this.placeholder.before(this.currentItem); 5665 } 5666 this._noFinalSort = null; 5667 5668 if(this.helper[0] === this.currentItem[0]) { 5669 for(i in this._storedCSS) { 5670 if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") { 5671 this._storedCSS[i] = ""; 5672 } 5673 } 5674 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); 5675 } else { 5676 this.currentItem.show(); 5677 } 5678 5679 if(this.fromOutside && !noPropagation) { 5680 delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); 5681 } 5682 if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) { 5683 delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed 5684 } 5685 5686 // Check if the items Container has Changed and trigger appropriate 5687 // events. 5688 if (this !== this.currentContainer) { 5689 if(!noPropagation) { 5690 delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); 5691 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); 5692 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); 5693 } 5694 } 5695 5696 5697 //Post events to containers 5698 function delayEvent( type, instance, container ) { 5699 return function( event ) { 5700 container._trigger( type, event, instance._uiHash( instance ) ); 5701 }; 5702 } 5703 for (i = this.containers.length - 1; i >= 0; i--){ 5704 if (!noPropagation) { 5705 delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) ); 5706 } 5707 if(this.containers[i].containerCache.over) { 5708 delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) ); 5709 this.containers[i].containerCache.over = 0; 5710 } 5711 } 5712 5713 //Do what was originally in plugins 5714 if ( this.storedCursor ) { 5715 this.document.find( "body" ).css( "cursor", this.storedCursor ); 5716 this.storedStylesheet.remove(); 5717 } 5718 if(this._storedOpacity) { 5719 this.helper.css("opacity", this._storedOpacity); 5720 } 5721 if(this._storedZIndex) { 5722 this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex); 5723 } 5724 5725 this.dragging = false; 5726 5727 if(!noPropagation) { 5728 this._trigger("beforeStop", event, this._uiHash()); 5729 } 5730 5731 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! 5732 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 5733 5734 if ( !this.cancelHelperRemoval ) { 5735 if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) { 5736 this.helper.remove(); 5737 } 5738 this.helper = null; 5739 } 5740 5741 if(!noPropagation) { 5742 for (i=0; i < delayedTriggers.length; i++) { 5743 delayedTriggers[i].call(this, event); 5744 } //Trigger all delayed events 5745 this._trigger("stop", event, this._uiHash()); 5746 } 5747 5748 this.fromOutside = false; 5749 return !this.cancelHelperRemoval; 5750 5751 }, 5752 5753 _trigger: function() { 5754 if ($.Widget.prototype._trigger.apply(this, arguments) === false) { 5755 this.cancel(); 5756 } 5757 }, 5758 5759 _uiHash: function(_inst) { 5760 var inst = _inst || this; 5761 return { 5762 helper: inst.helper, 5763 placeholder: inst.placeholder || $([]), 5764 position: inst.position, 5765 originalPosition: inst.originalPosition, 5766 offset: inst.positionAbs, 5767 item: inst.currentItem, 5768 sender: _inst ? _inst.element : null 5769 }; 5770 } 5771 5772 }); 5773 5774 5775 /*! 5776 * jQuery UI Accordion 1.11.4 5777 * http://jqueryui.com 5778 * 5779 * Copyright jQuery Foundation and other contributors 5780 * Released under the MIT license. 5781 * http://jquery.org/license 5782 * 5783 * http://api.jqueryui.com/accordion/ 5784 */ 5785 5786 5787 var accordion = $.widget( "ui.accordion", { 5788 version: "1.11.4", 5789 options: { 5790 active: 0, 5791 animate: {}, 5792 collapsible: false, 5793 event: "click", 5794 header: "> li > :first-child,> :not(li):even", 5795 heightStyle: "auto", 5796 icons: { 5797 activeHeader: "ui-icon-triangle-1-s", 5798 header: "ui-icon-triangle-1-e" 5799 }, 5800 5801 // callbacks 5802 activate: null, 5803 beforeActivate: null 5804 }, 5805 5806 hideProps: { 5807 borderTopWidth: "hide", 5808 borderBottomWidth: "hide", 5809 paddingTop: "hide", 5810 paddingBottom: "hide", 5811 height: "hide" 5812 }, 5813 5814 showProps: { 5815 borderTopWidth: "show", 5816 borderBottomWidth: "show", 5817 paddingTop: "show", 5818 paddingBottom: "show", 5819 height: "show" 5820 }, 5821 5822 _create: function() { 5823 var options = this.options; 5824 this.prevShow = this.prevHide = $(); 5825 this.element.addClass( "ui-accordion ui-widget ui-helper-reset" ) 5826 // ARIA 5827 .attr( "role", "tablist" ); 5828 5829 // don't allow collapsible: false and active: false / null 5830 if ( !options.collapsible && (options.active === false || options.active == null) ) { 5831 options.active = 0; 5832 } 5833 5834 this._processPanels(); 5835 // handle negative values 5836 if ( options.active < 0 ) { 5837 options.active += this.headers.length; 5838 } 5839 this._refresh(); 5840 }, 5841 5842 _getCreateEventData: function() { 5843 return { 5844 header: this.active, 5845 panel: !this.active.length ? $() : this.active.next() 5846 }; 5847 }, 5848 5849 _createIcons: function() { 5850 var icons = this.options.icons; 5851 if ( icons ) { 5852 $( "<span>" ) 5853 .addClass( "ui-accordion-header-icon ui-icon " + icons.header ) 5854 .prependTo( this.headers ); 5855 this.active.children( ".ui-accordion-header-icon" ) 5856 .removeClass( icons.header ) 5857 .addClass( icons.activeHeader ); 5858 this.headers.addClass( "ui-accordion-icons" ); 5859 } 5860 }, 5861 5862 _destroyIcons: function() { 5863 this.headers 5864 .removeClass( "ui-accordion-icons" ) 5865 .children( ".ui-accordion-header-icon" ) 5866 .remove(); 5867 }, 5868 5869 _destroy: function() { 5870 var contents; 5871 5872 // clean up main element 5873 this.element 5874 .removeClass( "ui-accordion ui-widget ui-helper-reset" ) 5875 .removeAttr( "role" ); 5876 5877 // clean up headers 5878 this.headers 5879 .removeClass( "ui-accordion-header ui-accordion-header-active ui-state-default " + 5880 "ui-corner-all ui-state-active ui-state-disabled ui-corner-top" ) 5881 .removeAttr( "role" ) 5882 .removeAttr( "aria-expanded" ) 5883 .removeAttr( "aria-selected" ) 5884 .removeAttr( "aria-controls" ) 5885 .removeAttr( "tabIndex" ) 5886 .removeUniqueId(); 5887 5888 this._destroyIcons(); 5889 5890 // clean up content panels 5891 contents = this.headers.next() 5892 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom " + 5893 "ui-accordion-content ui-accordion-content-active ui-state-disabled" ) 5894 .css( "display", "" ) 5895 .removeAttr( "role" ) 5896 .removeAttr( "aria-hidden" ) 5897 .removeAttr( "aria-labelledby" ) 5898 .removeUniqueId(); 5899 5900 if ( this.options.heightStyle !== "content" ) { 5901 contents.css( "height", "" ); 5902 } 5903 }, 5904 5905 _setOption: function( key, value ) { 5906 if ( key === "active" ) { 5907 // _activate() will handle invalid values and update this.options 5908 this._activate( value ); 5909 return; 5910 } 5911 5912 if ( key === "event" ) { 5913 if ( this.options.event ) { 5914 this._off( this.headers, this.options.event ); 5915 } 5916 this._setupEvents( value ); 5917 } 5918 5919 this._super( key, value ); 5920 5921 // setting collapsible: false while collapsed; open first panel 5922 if ( key === "collapsible" && !value && this.options.active === false ) { 5923 this._activate( 0 ); 5924 } 5925 5926 if ( key === "icons" ) { 5927 this._destroyIcons(); 5928 if ( value ) { 5929 this._createIcons(); 5930 } 5931 } 5932 5933 // #5332 - opacity doesn't cascade to positioned elements in IE 5934 // so we need to add the disabled class to the headers and panels 5935 if ( key === "disabled" ) { 5936 this.element 5937 .toggleClass( "ui-state-disabled", !!value ) 5938 .attr( "aria-disabled", value ); 5939 this.headers.add( this.headers.next() ) 5940 .toggleClass( "ui-state-disabled", !!value ); 5941 } 5942 }, 5943 5944 _keydown: function( event ) { 5945 if ( event.altKey || event.ctrlKey ) { 5946 return; 5947 } 5948 5949 var keyCode = $.ui.keyCode, 5950 length = this.headers.length, 5951 currentIndex = this.headers.index( event.target ), 5952 toFocus = false; 5953 5954 switch ( event.keyCode ) { 5955 case keyCode.RIGHT: 5956 case keyCode.DOWN: 5957 toFocus = this.headers[ ( currentIndex + 1 ) % length ]; 5958 break; 5959 case keyCode.LEFT: 5960 case keyCode.UP: 5961 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; 5962 break; 5963 case keyCode.SPACE: 5964 case keyCode.ENTER: 5965 this._eventHandler( event ); 5966 break; 5967 case keyCode.HOME: 5968 toFocus = this.headers[ 0 ]; 5969 break; 5970 case keyCode.END: 5971 toFocus = this.headers[ length - 1 ]; 5972 break; 5973 } 5974 5975 if ( toFocus ) { 5976 $( event.target ).attr( "tabIndex", -1 ); 5977 $( toFocus ).attr( "tabIndex", 0 ); 5978 toFocus.focus(); 5979 event.preventDefault(); 5980 } 5981 }, 5982 5983 _panelKeyDown: function( event ) { 5984 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { 5985 $( event.currentTarget ).prev().focus(); 5986 } 5987 }, 5988 5989 refresh: function() { 5990 var options = this.options; 5991 this._processPanels(); 5992 5993 // was collapsed or no panel 5994 if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) { 5995 options.active = false; 5996 this.active = $(); 5997 // active false only when collapsible is true 5998 } else if ( options.active === false ) { 5999 this._activate( 0 ); 6000 // was active, but active panel is gone 6001 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 6002 // all remaining panel are disabled 6003 if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) { 6004 options.active = false; 6005 this.active = $(); 6006 // activate previous panel 6007 } else { 6008 this._activate( Math.max( 0, options.active - 1 ) ); 6009 } 6010 // was active, active panel still exists 6011 } else { 6012 // make sure active index is correct 6013 options.active = this.headers.index( this.active ); 6014 } 6015 6016 this._destroyIcons(); 6017 6018 this._refresh(); 6019 }, 6020 6021 _processPanels: function() { 6022 var prevHeaders = this.headers, 6023 prevPanels = this.panels; 6024 6025 this.headers = this.element.find( this.options.header ) 6026 .addClass( "ui-accordion-header ui-state-default ui-corner-all" ); 6027 6028 this.panels = this.headers.next() 6029 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ) 6030 .filter( ":not(.ui-accordion-content-active)" ) 6031 .hide(); 6032 6033 // Avoid memory leaks (#10056) 6034 if ( prevPanels ) { 6035 this._off( prevHeaders.not( this.headers ) ); 6036 this._off( prevPanels.not( this.panels ) ); 6037 } 6038 }, 6039 6040 _refresh: function() { 6041 var maxHeight, 6042 options = this.options, 6043 heightStyle = options.heightStyle, 6044 parent = this.element.parent(); 6045 6046 this.active = this._findActive( options.active ) 6047 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ) 6048 .removeClass( "ui-corner-all" ); 6049 this.active.next() 6050 .addClass( "ui-accordion-content-active" ) 6051 .show(); 6052 6053 this.headers 6054 .attr( "role", "tab" ) 6055 .each(function() { 6056 var header = $( this ), 6057 headerId = header.uniqueId().attr( "id" ), 6058 panel = header.next(), 6059 panelId = panel.uniqueId().attr( "id" ); 6060 header.attr( "aria-controls", panelId ); 6061 panel.attr( "aria-labelledby", headerId ); 6062 }) 6063 .next() 6064 .attr( "role", "tabpanel" ); 6065 6066 this.headers 6067 .not( this.active ) 6068 .attr({ 6069 "aria-selected": "false", 6070 "aria-expanded": "false", 6071 tabIndex: -1 6072 }) 6073 .next() 6074 .attr({ 6075 "aria-hidden": "true" 6076 }) 6077 .hide(); 6078 6079 // make sure at least one header is in the tab order 6080 if ( !this.active.length ) { 6081 this.headers.eq( 0 ).attr( "tabIndex", 0 ); 6082 } else { 6083 this.active.attr({ 6084 "aria-selected": "true", 6085 "aria-expanded": "true", 6086 tabIndex: 0 6087 }) 6088 .next() 6089 .attr({ 6090 "aria-hidden": "false" 6091 }); 6092 } 6093 6094 this._createIcons(); 6095 6096 this._setupEvents( options.event ); 6097 6098 if ( heightStyle === "fill" ) { 6099 maxHeight = parent.height(); 6100 this.element.siblings( ":visible" ).each(function() { 6101 var elem = $( this ), 6102 position = elem.css( "position" ); 6103 6104 if ( position === "absolute" || position === "fixed" ) { 6105 return; 6106 } 6107 maxHeight -= elem.outerHeight( true ); 6108 }); 6109 6110 this.headers.each(function() { 6111 maxHeight -= $( this ).outerHeight( true ); 6112 }); 6113 6114 this.headers.next() 6115 .each(function() { 6116 $( this ).height( Math.max( 0, maxHeight - 6117 $( this ).innerHeight() + $( this ).height() ) ); 6118 }) 6119 .css( "overflow", "auto" ); 6120 } else if ( heightStyle === "auto" ) { 6121 maxHeight = 0; 6122 this.headers.next() 6123 .each(function() { 6124 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); 6125 }) 6126 .height( maxHeight ); 6127 } 6128 }, 6129 6130 _activate: function( index ) { 6131 var active = this._findActive( index )[ 0 ]; 6132 6133 // trying to activate the already active panel 6134 if ( active === this.active[ 0 ] ) { 6135 return; 6136 } 6137 6138 // trying to collapse, simulate a click on the currently active header 6139 active = active || this.active[ 0 ]; 6140 6141 this._eventHandler({ 6142 target: active, 6143 currentTarget: active, 6144 preventDefault: $.noop 6145 }); 6146 }, 6147 6148 _findActive: function( selector ) { 6149 return typeof selector === "number" ? this.headers.eq( selector ) : $(); 6150 }, 6151 6152 _setupEvents: function( event ) { 6153 var events = { 6154 keydown: "_keydown" 6155 }; 6156 if ( event ) { 6157 $.each( event.split( " " ), function( index, eventName ) { 6158 events[ eventName ] = "_eventHandler"; 6159 }); 6160 } 6161 6162 this._off( this.headers.add( this.headers.next() ) ); 6163 this._on( this.headers, events ); 6164 this._on( this.headers.next(), { keydown: "_panelKeyDown" }); 6165 this._hoverable( this.headers ); 6166 this._focusable( this.headers ); 6167 }, 6168 6169 _eventHandler: function( event ) { 6170 var options = this.options, 6171 active = this.active, 6172 clicked = $( event.currentTarget ), 6173 clickedIsActive = clicked[ 0 ] === active[ 0 ], 6174 collapsing = clickedIsActive && options.collapsible, 6175 toShow = collapsing ? $() : clicked.next(), 6176 toHide = active.next(), 6177 eventData = { 6178 oldHeader: active, 6179 oldPanel: toHide, 6180 newHeader: collapsing ? $() : clicked, 6181 newPanel: toShow 6182 }; 6183 6184 event.preventDefault(); 6185 6186 if ( 6187 // click on active header, but not collapsible 6188 ( clickedIsActive && !options.collapsible ) || 6189 // allow canceling activation 6190 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 6191 return; 6192 } 6193 6194 options.active = collapsing ? false : this.headers.index( clicked ); 6195 6196 // when the call to ._toggle() comes after the class changes 6197 // it causes a very odd bug in IE 8 (see #6720) 6198 this.active = clickedIsActive ? $() : clicked; 6199 this._toggle( eventData ); 6200 6201 // switch classes 6202 // corner classes on the previously active header stay after the animation 6203 active.removeClass( "ui-accordion-header-active ui-state-active" ); 6204 if ( options.icons ) { 6205 active.children( ".ui-accordion-header-icon" ) 6206 .removeClass( options.icons.activeHeader ) 6207 .addClass( options.icons.header ); 6208 } 6209 6210 if ( !clickedIsActive ) { 6211 clicked 6212 .removeClass( "ui-corner-all" ) 6213 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ); 6214 if ( options.icons ) { 6215 clicked.children( ".ui-accordion-header-icon" ) 6216 .removeClass( options.icons.header ) 6217 .addClass( options.icons.activeHeader ); 6218 } 6219 6220 clicked 6221 .next() 6222 .addClass( "ui-accordion-content-active" ); 6223 } 6224 }, 6225 6226 _toggle: function( data ) { 6227 var toShow = data.newPanel, 6228 toHide = this.prevShow.length ? this.prevShow : data.oldPanel; 6229 6230 // handle activating a panel during the animation for another activation 6231 this.prevShow.add( this.prevHide ).stop( true, true ); 6232 this.prevShow = toShow; 6233 this.prevHide = toHide; 6234 6235 if ( this.options.animate ) { 6236 this._animate( toShow, toHide, data ); 6237 } else { 6238 toHide.hide(); 6239 toShow.show(); 6240 this._toggleComplete( data ); 6241 } 6242 6243 toHide.attr({ 6244 "aria-hidden": "true" 6245 }); 6246 toHide.prev().attr({ 6247 "aria-selected": "false", 6248 "aria-expanded": "false" 6249 }); 6250 // if we're switching panels, remove the old header from the tab order 6251 // if we're opening from collapsed state, remove the previous header from the tab order 6252 // if we're collapsing, then keep the collapsing header in the tab order 6253 if ( toShow.length && toHide.length ) { 6254 toHide.prev().attr({ 6255 "tabIndex": -1, 6256 "aria-expanded": "false" 6257 }); 6258 } else if ( toShow.length ) { 6259 this.headers.filter(function() { 6260 return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0; 6261 }) 6262 .attr( "tabIndex", -1 ); 6263 } 6264 6265 toShow 6266 .attr( "aria-hidden", "false" ) 6267 .prev() 6268 .attr({ 6269 "aria-selected": "true", 6270 "aria-expanded": "true", 6271 tabIndex: 0 6272 }); 6273 }, 6274 6275 _animate: function( toShow, toHide, data ) { 6276 var total, easing, duration, 6277 that = this, 6278 adjust = 0, 6279 boxSizing = toShow.css( "box-sizing" ), 6280 down = toShow.length && 6281 ( !toHide.length || ( toShow.index() < toHide.index() ) ), 6282 animate = this.options.animate || {}, 6283 options = down && animate.down || animate, 6284 complete = function() { 6285 that._toggleComplete( data ); 6286 }; 6287 6288 if ( typeof options === "number" ) { 6289 duration = options; 6290 } 6291 if ( typeof options === "string" ) { 6292 easing = options; 6293 } 6294 // fall back from options to animation in case of partial down settings 6295 easing = easing || options.easing || animate.easing; 6296 duration = duration || options.duration || animate.duration; 6297 6298 if ( !toHide.length ) { 6299 return toShow.animate( this.showProps, duration, easing, complete ); 6300 } 6301 if ( !toShow.length ) { 6302 return toHide.animate( this.hideProps, duration, easing, complete ); 6303 } 6304 6305 total = toShow.show().outerHeight(); 6306 toHide.animate( this.hideProps, { 6307 duration: duration, 6308 easing: easing, 6309 step: function( now, fx ) { 6310 fx.now = Math.round( now ); 6311 } 6312 }); 6313 toShow 6314 .hide() 6315 .animate( this.showProps, { 6316 duration: duration, 6317 easing: easing, 6318 complete: complete, 6319 step: function( now, fx ) { 6320 fx.now = Math.round( now ); 6321 if ( fx.prop !== "height" ) { 6322 if ( boxSizing === "content-box" ) { 6323 adjust += fx.now; 6324 } 6325 } else if ( that.options.heightStyle !== "content" ) { 6326 fx.now = Math.round( total - toHide.outerHeight() - adjust ); 6327 adjust = 0; 6328 } 6329 } 6330 }); 6331 }, 6332 6333 _toggleComplete: function( data ) { 6334 var toHide = data.oldPanel; 6335 6336 toHide 6337 .removeClass( "ui-accordion-content-active" ) 6338 .prev() 6339 .removeClass( "ui-corner-top" ) 6340 .addClass( "ui-corner-all" ); 6341 6342 // Work around for rendering bug in IE (#5421) 6343 if ( toHide.length ) { 6344 toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className; 6345 } 6346 this._trigger( "activate", null, data ); 6347 } 6348 }); 6349 6350 6351 /*! 6352 * jQuery UI Menu 1.11.4 6353 * http://jqueryui.com 6354 * 6355 * Copyright jQuery Foundation and other contributors 6356 * Released under the MIT license. 6357 * http://jquery.org/license 6358 * 6359 * http://api.jqueryui.com/menu/ 6360 */ 6361 6362 6363 var menu = $.widget( "ui.menu", { 6364 version: "1.11.4", 6365 defaultElement: "<ul>", 6366 delay: 300, 6367 options: { 6368 icons: { 6369 submenu: "ui-icon-carat-1-e" 6370 }, 6371 items: "> *", 6372 menus: "ul", 6373 position: { 6374 my: "left-1 top", 6375 at: "right top" 6376 }, 6377 role: "menu", 6378 6379 // callbacks 6380 blur: null, 6381 focus: null, 6382 select: null 6383 }, 6384 6385 _create: function() { 6386 this.activeMenu = this.element; 6387 6388 // Flag used to prevent firing of the click handler 6389 // as the event bubbles up through nested menus 6390 this.mouseHandled = false; 6391 this.element 6392 .uniqueId() 6393 .addClass( "ui-menu ui-widget ui-widget-content" ) 6394 .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ) 6395 .attr({ 6396 role: this.options.role, 6397 tabIndex: 0 6398 }); 6399 6400 if ( this.options.disabled ) { 6401 this.element 6402 .addClass( "ui-state-disabled" ) 6403 .attr( "aria-disabled", "true" ); 6404 } 6405 6406 this._on({ 6407 // Prevent focus from sticking to links inside menu after clicking 6408 // them (focus should always stay on UL during navigation). 6409 "mousedown .ui-menu-item": function( event ) { 6410 event.preventDefault(); 6411 }, 6412 "click .ui-menu-item": function( event ) { 6413 var target = $( event.target ); 6414 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) { 6415 this.select( event ); 6416 6417 // Only set the mouseHandled flag if the event will bubble, see #9469. 6418 if ( !event.isPropagationStopped() ) { 6419 this.mouseHandled = true; 6420 } 6421 6422 // Open submenu on click 6423 if ( target.has( ".ui-menu" ).length ) { 6424 this.expand( event ); 6425 } else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) { 6426 6427 // Redirect focus to the menu 6428 this.element.trigger( "focus", [ true ] ); 6429 6430 // If the active item is on the top level, let it stay active. 6431 // Otherwise, blur the active item since it is no longer visible. 6432 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) { 6433 clearTimeout( this.timer ); 6434 } 6435 } 6436 } 6437 }, 6438 "mouseenter .ui-menu-item": function( event ) { 6439 // Ignore mouse events while typeahead is active, see #10458. 6440 // Prevents focusing the wrong item when typeahead causes a scroll while the mouse 6441 // is over an item in the menu 6442 if ( this.previousFilter ) { 6443 return; 6444 } 6445 var target = $( event.currentTarget ); 6446 // Remove ui-state-active class from siblings of the newly focused menu item 6447 // to avoid a jump caused by adjacent elements both having a class with a border 6448 target.siblings( ".ui-state-active" ).removeClass( "ui-state-active" ); 6449 this.focus( event, target ); 6450 }, 6451 mouseleave: "collapseAll", 6452 "mouseleave .ui-menu": "collapseAll", 6453 focus: function( event, keepActiveItem ) { 6454 // If there's already an active item, keep it active 6455 // If not, activate the first item 6456 var item = this.active || this.element.find( this.options.items ).eq( 0 ); 6457 6458 if ( !keepActiveItem ) { 6459 this.focus( event, item ); 6460 } 6461 }, 6462 blur: function( event ) { 6463 this._delay(function() { 6464 if ( !$.contains( this.element[0], this.document[0].activeElement ) ) { 6465 this.collapseAll( event ); 6466 } 6467 }); 6468 }, 6469 keydown: "_keydown" 6470 }); 6471 6472 this.refresh(); 6473 6474 // Clicks outside of a menu collapse any open menus 6475 this._on( this.document, { 6476 click: function( event ) { 6477 if ( this._closeOnDocumentClick( event ) ) { 6478 this.collapseAll( event ); 6479 } 6480 6481 // Reset the mouseHandled flag 6482 this.mouseHandled = false; 6483 } 6484 }); 6485 }, 6486 6487 _destroy: function() { 6488 // Destroy (sub)menus 6489 this.element 6490 .removeAttr( "aria-activedescendant" ) 6491 .find( ".ui-menu" ).addBack() 6492 .removeClass( "ui-menu ui-widget ui-widget-content ui-menu-icons ui-front" ) 6493 .removeAttr( "role" ) 6494 .removeAttr( "tabIndex" ) 6495 .removeAttr( "aria-labelledby" ) 6496 .removeAttr( "aria-expanded" ) 6497 .removeAttr( "aria-hidden" ) 6498 .removeAttr( "aria-disabled" ) 6499 .removeUniqueId() 6500 .show(); 6501 6502 // Destroy menu items 6503 this.element.find( ".ui-menu-item" ) 6504 .removeClass( "ui-menu-item" ) 6505 .removeAttr( "role" ) 6506 .removeAttr( "aria-disabled" ) 6507 .removeUniqueId() 6508 .removeClass( "ui-state-hover" ) 6509 .removeAttr( "tabIndex" ) 6510 .removeAttr( "role" ) 6511 .removeAttr( "aria-haspopup" ) 6512 .children().each( function() { 6513 var elem = $( this ); 6514 if ( elem.data( "ui-menu-submenu-carat" ) ) { 6515 elem.remove(); 6516 } 6517 }); 6518 6519 // Destroy menu dividers 6520 this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" ); 6521 }, 6522 6523 _keydown: function( event ) { 6524 var match, prev, character, skip, 6525 preventDefault = true; 6526 6527 switch ( event.keyCode ) { 6528 case $.ui.keyCode.PAGE_UP: 6529 this.previousPage( event ); 6530 break; 6531 case $.ui.keyCode.PAGE_DOWN: 6532 this.nextPage( event ); 6533 break; 6534 case $.ui.keyCode.HOME: 6535 this._move( "first", "first", event ); 6536 break; 6537 case $.ui.keyCode.END: 6538 this._move( "last", "last", event ); 6539 break; 6540 case $.ui.keyCode.UP: 6541 this.previous( event ); 6542 break; 6543 case $.ui.keyCode.DOWN: 6544 this.next( event ); 6545 break; 6546 case $.ui.keyCode.LEFT: 6547 this.collapse( event ); 6548 break; 6549 case $.ui.keyCode.RIGHT: 6550 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { 6551 this.expand( event ); 6552 } 6553 break; 6554 case $.ui.keyCode.ENTER: 6555 case $.ui.keyCode.SPACE: 6556 this._activate( event ); 6557 break; 6558 case $.ui.keyCode.ESCAPE: 6559 this.collapse( event ); 6560 break; 6561 default: 6562 preventDefault = false; 6563 prev = this.previousFilter || ""; 6564 character = String.fromCharCode( event.keyCode ); 6565 skip = false; 6566 6567 clearTimeout( this.filterTimer ); 6568 6569 if ( character === prev ) { 6570 skip = true; 6571 } else { 6572 character = prev + character; 6573 } 6574 6575 match = this._filterMenuItems( character ); 6576 match = skip && match.index( this.active.next() ) !== -1 ? 6577 this.active.nextAll( ".ui-menu-item" ) : 6578 match; 6579 6580 // If no matches on the current filter, reset to the last character pressed 6581 // to move down the menu to the first item that starts with that character 6582 if ( !match.length ) { 6583 character = String.fromCharCode( event.keyCode ); 6584 match = this._filterMenuItems( character ); 6585 } 6586 6587 if ( match.length ) { 6588 this.focus( event, match ); 6589 this.previousFilter = character; 6590 this.filterTimer = this._delay(function() { 6591 delete this.previousFilter; 6592 }, 1000 ); 6593 } else { 6594 delete this.previousFilter; 6595 } 6596 } 6597 6598 if ( preventDefault ) { 6599 event.preventDefault(); 6600 } 6601 }, 6602 6603 _activate: function( event ) { 6604 if ( !this.active.is( ".ui-state-disabled" ) ) { 6605 if ( this.active.is( "[aria-haspopup='true']" ) ) { 6606 this.expand( event ); 6607 } else { 6608 this.select( event ); 6609 } 6610 } 6611 }, 6612 6613 refresh: function() { 6614 var menus, items, 6615 that = this, 6616 icon = this.options.icons.submenu, 6617 submenus = this.element.find( this.options.menus ); 6618 6619 this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ); 6620 6621 // Initialize nested menus 6622 submenus.filter( ":not(.ui-menu)" ) 6623 .addClass( "ui-menu ui-widget ui-widget-content ui-front" ) 6624 .hide() 6625 .attr({ 6626 role: this.options.role, 6627 "aria-hidden": "true", 6628 "aria-expanded": "false" 6629 }) 6630 .each(function() { 6631 var menu = $( this ), 6632 item = menu.parent(), 6633 submenuCarat = $( "<span>" ) 6634 .addClass( "ui-menu-icon ui-icon " + icon ) 6635 .data( "ui-menu-submenu-carat", true ); 6636 6637 item 6638 .attr( "aria-haspopup", "true" ) 6639 .prepend( submenuCarat ); 6640 menu.attr( "aria-labelledby", item.attr( "id" ) ); 6641 }); 6642 6643 menus = submenus.add( this.element ); 6644 items = menus.find( this.options.items ); 6645 6646 // Initialize menu-items containing spaces and/or dashes only as dividers 6647 items.not( ".ui-menu-item" ).each(function() { 6648 var item = $( this ); 6649 if ( that._isDivider( item ) ) { 6650 item.addClass( "ui-widget-content ui-menu-divider" ); 6651 } 6652 }); 6653 6654 // Don't refresh list items that are already adapted 6655 items.not( ".ui-menu-item, .ui-menu-divider" ) 6656 .addClass( "ui-menu-item" ) 6657 .uniqueId() 6658 .attr({ 6659 tabIndex: -1, 6660 role: this._itemRole() 6661 }); 6662 6663 // Add aria-disabled attribute to any disabled menu item 6664 items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); 6665 6666 // If the active item has been removed, blur the menu 6667 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 6668 this.blur(); 6669 } 6670 }, 6671 6672 _itemRole: function() { 6673 return { 6674 menu: "menuitem", 6675 listbox: "option" 6676 }[ this.options.role ]; 6677 }, 6678 6679 _setOption: function( key, value ) { 6680 if ( key === "icons" ) { 6681 this.element.find( ".ui-menu-icon" ) 6682 .removeClass( this.options.icons.submenu ) 6683 .addClass( value.submenu ); 6684 } 6685 if ( key === "disabled" ) { 6686 this.element 6687 .toggleClass( "ui-state-disabled", !!value ) 6688 .attr( "aria-disabled", value ); 6689 } 6690 this._super( key, value ); 6691 }, 6692 6693 focus: function( event, item ) { 6694 var nested, focused; 6695 this.blur( event, event && event.type === "focus" ); 6696 6697 this._scrollIntoView( item ); 6698 6699 this.active = item.first(); 6700 focused = this.active.addClass( "ui-state-focus" ).removeClass( "ui-state-active" ); 6701 // Only update aria-activedescendant if there's a role 6702 // otherwise we assume focus is managed elsewhere 6703 if ( this.options.role ) { 6704 this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); 6705 } 6706 6707 // Highlight active parent menu item, if any 6708 this.active 6709 .parent() 6710 .closest( ".ui-menu-item" ) 6711 .addClass( "ui-state-active" ); 6712 6713 if ( event && event.type === "keydown" ) { 6714 this._close(); 6715 } else { 6716 this.timer = this._delay(function() { 6717 this._close(); 6718 }, this.delay ); 6719 } 6720 6721 nested = item.children( ".ui-menu" ); 6722 if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) { 6723 this._startOpening(nested); 6724 } 6725 this.activeMenu = item.parent(); 6726 6727 this._trigger( "focus", event, { item: item } ); 6728 }, 6729 6730 _scrollIntoView: function( item ) { 6731 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; 6732 if ( this._hasScroll() ) { 6733 borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0; 6734 paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0; 6735 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; 6736 scroll = this.activeMenu.scrollTop(); 6737 elementHeight = this.activeMenu.height(); 6738 itemHeight = item.outerHeight(); 6739 6740 if ( offset < 0 ) { 6741 this.activeMenu.scrollTop( scroll + offset ); 6742 } else if ( offset + itemHeight > elementHeight ) { 6743 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); 6744 } 6745 } 6746 }, 6747 6748 blur: function( event, fromFocus ) { 6749 if ( !fromFocus ) { 6750 clearTimeout( this.timer ); 6751 } 6752 6753 if ( !this.active ) { 6754 return; 6755 } 6756 6757 this.active.removeClass( "ui-state-focus" ); 6758 this.active = null; 6759 6760 this._trigger( "blur", event, { item: this.active } ); 6761 }, 6762 6763 _startOpening: function( submenu ) { 6764 clearTimeout( this.timer ); 6765 6766 // Don't open if already open fixes a Firefox bug that caused a .5 pixel 6767 // shift in the submenu position when mousing over the carat icon 6768 if ( submenu.attr( "aria-hidden" ) !== "true" ) { 6769 return; 6770 } 6771 6772 this.timer = this._delay(function() { 6773 this._close(); 6774 this._open( submenu ); 6775 }, this.delay ); 6776 }, 6777 6778 _open: function( submenu ) { 6779 var position = $.extend({ 6780 of: this.active 6781 }, this.options.position ); 6782 6783 clearTimeout( this.timer ); 6784 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) ) 6785 .hide() 6786 .attr( "aria-hidden", "true" ); 6787 6788 submenu 6789 .show() 6790 .removeAttr( "aria-hidden" ) 6791 .attr( "aria-expanded", "true" ) 6792 .position( position ); 6793 }, 6794 6795 collapseAll: function( event, all ) { 6796 clearTimeout( this.timer ); 6797 this.timer = this._delay(function() { 6798 // If we were passed an event, look for the submenu that contains the event 6799 var currentMenu = all ? this.element : 6800 $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); 6801 6802 // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway 6803 if ( !currentMenu.length ) { 6804 currentMenu = this.element; 6805 } 6806 6807 this._close( currentMenu ); 6808 6809 this.blur( event ); 6810 this.activeMenu = currentMenu; 6811 }, this.delay ); 6812 }, 6813 6814 // With no arguments, closes the currently active menu - if nothing is active 6815 // it closes all menus. If passed an argument, it will search for menus BELOW 6816 _close: function( startMenu ) { 6817 if ( !startMenu ) { 6818 startMenu = this.active ? this.active.parent() : this.element; 6819 } 6820 6821 startMenu 6822 .find( ".ui-menu" ) 6823 .hide() 6824 .attr( "aria-hidden", "true" ) 6825 .attr( "aria-expanded", "false" ) 6826 .end() 6827 .find( ".ui-state-active" ).not( ".ui-state-focus" ) 6828 .removeClass( "ui-state-active" ); 6829 }, 6830 6831 _closeOnDocumentClick: function( event ) { 6832 return !$( event.target ).closest( ".ui-menu" ).length; 6833 }, 6834 6835 _isDivider: function( item ) { 6836 6837 // Match hyphen, em dash, en dash 6838 return !/[^\-\u2014\u2013\s]/.test( item.text() ); 6839 }, 6840 6841 collapse: function( event ) { 6842 var newItem = this.active && 6843 this.active.parent().closest( ".ui-menu-item", this.element ); 6844 if ( newItem && newItem.length ) { 6845 this._close(); 6846 this.focus( event, newItem ); 6847 } 6848 }, 6849 6850 expand: function( event ) { 6851 var newItem = this.active && 6852 this.active 6853 .children( ".ui-menu " ) 6854 .find( this.options.items ) 6855 .first(); 6856 6857 if ( newItem && newItem.length ) { 6858 this._open( newItem.parent() ); 6859 6860 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT 6861 this._delay(function() { 6862 this.focus( event, newItem ); 6863 }); 6864 } 6865 }, 6866 6867 next: function( event ) { 6868 this._move( "next", "first", event ); 6869 }, 6870 6871 previous: function( event ) { 6872 this._move( "prev", "last", event ); 6873 }, 6874 6875 isFirstItem: function() { 6876 return this.active && !this.active.prevAll( ".ui-menu-item" ).length; 6877 }, 6878 6879 isLastItem: function() { 6880 return this.active && !this.active.nextAll( ".ui-menu-item" ).length; 6881 }, 6882 6883 _move: function( direction, filter, event ) { 6884 var next; 6885 if ( this.active ) { 6886 if ( direction === "first" || direction === "last" ) { 6887 next = this.active 6888 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) 6889 .eq( -1 ); 6890 } else { 6891 next = this.active 6892 [ direction + "All" ]( ".ui-menu-item" ) 6893 .eq( 0 ); 6894 } 6895 } 6896 if ( !next || !next.length || !this.active ) { 6897 next = this.activeMenu.find( this.options.items )[ filter ](); 6898 } 6899 6900 this.focus( event, next ); 6901 }, 6902 6903 nextPage: function( event ) { 6904 var item, base, height; 6905 6906 if ( !this.active ) { 6907 this.next( event ); 6908 return; 6909 } 6910 if ( this.isLastItem() ) { 6911 return; 6912 } 6913 if ( this._hasScroll() ) { 6914 base = this.active.offset().top; 6915 height = this.element.height(); 6916 this.active.nextAll( ".ui-menu-item" ).each(function() { 6917 item = $( this ); 6918 return item.offset().top - base - height < 0; 6919 }); 6920 6921 this.focus( event, item ); 6922 } else { 6923 this.focus( event, this.activeMenu.find( this.options.items ) 6924 [ !this.active ? "first" : "last" ]() ); 6925 } 6926 }, 6927 6928 previousPage: function( event ) { 6929 var item, base, height; 6930 if ( !this.active ) { 6931 this.next( event ); 6932 return; 6933 } 6934 if ( this.isFirstItem() ) { 6935 return; 6936 } 6937 if ( this._hasScroll() ) { 6938 base = this.active.offset().top; 6939 height = this.element.height(); 6940 this.active.prevAll( ".ui-menu-item" ).each(function() { 6941 item = $( this ); 6942 return item.offset().top - base + height > 0; 6943 }); 6944 6945 this.focus( event, item ); 6946 } else { 6947 this.focus( event, this.activeMenu.find( this.options.items ).first() ); 6948 } 6949 }, 6950 6951 _hasScroll: function() { 6952 return this.element.outerHeight() < this.element.prop( "scrollHeight" ); 6953 }, 6954 6955 select: function( event ) { 6956 // TODO: It should never be possible to not have an active item at this 6957 // point, but the tests don't trigger mouseenter before click. 6958 this.active = this.active || $( event.target ).closest( ".ui-menu-item" ); 6959 var ui = { item: this.active }; 6960 if ( !this.active.has( ".ui-menu" ).length ) { 6961 this.collapseAll( event, true ); 6962 } 6963 this._trigger( "select", event, ui ); 6964 }, 6965 6966 _filterMenuItems: function(character) { 6967 var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ), 6968 regex = new RegExp( "^" + escapedCharacter, "i" ); 6969 6970 return this.activeMenu 6971 .find( this.options.items ) 6972 6973 // Only match on items, not dividers or other content (#10571) 6974 .filter( ".ui-menu-item" ) 6975 .filter(function() { 6976 return regex.test( $.trim( $( this ).text() ) ); 6977 }); 6978 } 6979 }); 6980 6981 6982 /*! 6983 * jQuery UI Autocomplete 1.11.4 6984 * http://jqueryui.com 6985 * 6986 * Copyright jQuery Foundation and other contributors 6987 * Released under the MIT license. 6988 * http://jquery.org/license 6989 * 6990 * http://api.jqueryui.com/autocomplete/ 6991 */ 6992 6993 6994 $.widget( "ui.autocomplete", { 6995 version: "1.11.4", 6996 defaultElement: "<input>", 6997 options: { 6998 appendTo: null, 6999 autoFocus: false, 7000 delay: 300, 7001 minLength: 1, 7002 position: { 7003 my: "left top", 7004 at: "left bottom", 7005 collision: "none" 7006 }, 7007 source: null, 7008 7009 // callbacks 7010 change: null, 7011 close: null, 7012 focus: null, 7013 open: null, 7014 response: null, 7015 search: null, 7016 select: null 7017 }, 7018 7019 requestIndex: 0, 7020 pending: 0, 7021 7022 _create: function() { 7023 // Some browsers only repeat keydown events, not keypress events, 7024 // so we use the suppressKeyPress flag to determine if we've already 7025 // handled the keydown event. #7269 7026 // Unfortunately the code for & in keypress is the same as the up arrow, 7027 // so we use the suppressKeyPressRepeat flag to avoid handling keypress 7028 // events when we know the keydown event was used to modify the 7029 // search term. #7799 7030 var suppressKeyPress, suppressKeyPressRepeat, suppressInput, 7031 nodeName = this.element[ 0 ].nodeName.toLowerCase(), 7032 isTextarea = nodeName === "textarea", 7033 isInput = nodeName === "input"; 7034 7035 this.isMultiLine = 7036 // Textareas are always multi-line 7037 isTextarea ? true : 7038 // Inputs are always single-line, even if inside a contentEditable element 7039 // IE also treats inputs as contentEditable 7040 isInput ? false : 7041 // All other element types are determined by whether or not they're contentEditable 7042 this.element.prop( "isContentEditable" ); 7043 7044 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ]; 7045 this.isNewMenu = true; 7046 7047 this.element 7048 .addClass( "ui-autocomplete-input" ) 7049 .attr( "autocomplete", "off" ); 7050 7051 this._on( this.element, { 7052 keydown: function( event ) { 7053 if ( this.element.prop( "readOnly" ) ) { 7054 suppressKeyPress = true; 7055 suppressInput = true; 7056 suppressKeyPressRepeat = true; 7057 return; 7058 } 7059 7060 suppressKeyPress = false; 7061 suppressInput = false; 7062 suppressKeyPressRepeat = false; 7063 var keyCode = $.ui.keyCode; 7064 switch ( event.keyCode ) { 7065 case keyCode.PAGE_UP: 7066 suppressKeyPress = true; 7067 this._move( "previousPage", event ); 7068 break; 7069 case keyCode.PAGE_DOWN: 7070 suppressKeyPress = true; 7071 this._move( "nextPage", event ); 7072 break; 7073 case keyCode.UP: 7074 suppressKeyPress = true; 7075 this._keyEvent( "previous", event ); 7076 break; 7077 case keyCode.DOWN: 7078 suppressKeyPress = true; 7079 this._keyEvent( "next", event ); 7080 break; 7081 case keyCode.ENTER: 7082 // when menu is open and has focus 7083 if ( this.menu.active ) { 7084 // #6055 - Opera still allows the keypress to occur 7085 // which causes forms to submit 7086 suppressKeyPress = true; 7087 event.preventDefault(); 7088 this.menu.select( event ); 7089 } 7090 break; 7091 case keyCode.TAB: 7092 if ( this.menu.active ) { 7093 this.menu.select( event ); 7094 } 7095 break; 7096 case keyCode.ESCAPE: 7097 if ( this.menu.element.is( ":visible" ) ) { 7098 if ( !this.isMultiLine ) { 7099 this._value( this.term ); 7100 } 7101 this.close( event ); 7102 // Different browsers have different default behavior for escape 7103 // Single press can mean undo or clear 7104 // Double press in IE means clear the whole form 7105 event.preventDefault(); 7106 } 7107 break; 7108 default: 7109 suppressKeyPressRepeat = true; 7110 // search timeout should be triggered before the input value is changed 7111 this._searchTimeout( event ); 7112 break; 7113 } 7114 }, 7115 keypress: function( event ) { 7116 if ( suppressKeyPress ) { 7117 suppressKeyPress = false; 7118 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 7119 event.preventDefault(); 7120 } 7121 return; 7122 } 7123 if ( suppressKeyPressRepeat ) { 7124 return; 7125 } 7126 7127 // replicate some key handlers to allow them to repeat in Firefox and Opera 7128 var keyCode = $.ui.keyCode; 7129 switch ( event.keyCode ) { 7130 case keyCode.PAGE_UP: 7131 this._move( "previousPage", event ); 7132 break; 7133 case keyCode.PAGE_DOWN: 7134 this._move( "nextPage", event ); 7135 break; 7136 case keyCode.UP: 7137 this._keyEvent( "previous", event ); 7138 break; 7139 case keyCode.DOWN: 7140 this._keyEvent( "next", event ); 7141 break; 7142 } 7143 }, 7144 input: function( event ) { 7145 if ( suppressInput ) { 7146 suppressInput = false; 7147 event.preventDefault(); 7148 return; 7149 } 7150 this._searchTimeout( event ); 7151 }, 7152 focus: function() { 7153 this.selectedItem = null; 7154 this.previous = this._value(); 7155 }, 7156 blur: function( event ) { 7157 if ( this.cancelBlur ) { 7158 delete this.cancelBlur; 7159 return; 7160 } 7161 7162 clearTimeout( this.searching ); 7163 this.close( event ); 7164 this._change( event ); 7165 } 7166 }); 7167 7168 this._initSource(); 7169 this.menu = $( "<ul>" ) 7170 .addClass( "ui-autocomplete ui-front" ) 7171 .appendTo( this._appendTo() ) 7172 .menu({ 7173 // disable ARIA support, the live region takes care of that 7174 role: null 7175 }) 7176 .hide() 7177 .menu( "instance" ); 7178 7179 this._on( this.menu.element, { 7180 mousedown: function( event ) { 7181 // prevent moving focus out of the text field 7182 event.preventDefault(); 7183 7184 // IE doesn't prevent moving focus even with event.preventDefault() 7185 // so we set a flag to know when we should ignore the blur event 7186 this.cancelBlur = true; 7187 this._delay(function() { 7188 delete this.cancelBlur; 7189 }); 7190 7191 // clicking on the scrollbar causes focus to shift to the body 7192 // but we can't detect a mouseup or a click immediately afterward 7193 // so we have to track the next mousedown and close the menu if 7194 // the user clicks somewhere outside of the autocomplete 7195 var menuElement = this.menu.element[ 0 ]; 7196 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { 7197 this._delay(function() { 7198 var that = this; 7199 this.document.one( "mousedown", function( event ) { 7200 if ( event.target !== that.element[ 0 ] && 7201 event.target !== menuElement && 7202 !$.contains( menuElement, event.target ) ) { 7203 that.close(); 7204 } 7205 }); 7206 }); 7207 } 7208 }, 7209 menufocus: function( event, ui ) { 7210 var label, item; 7211 // support: Firefox 7212 // Prevent accidental activation of menu items in Firefox (#7024 #9118) 7213 if ( this.isNewMenu ) { 7214 this.isNewMenu = false; 7215 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) { 7216 this.menu.blur(); 7217 7218 this.document.one( "mousemove", function() { 7219 $( event.target ).trigger( event.originalEvent ); 7220 }); 7221 7222 return; 7223 } 7224 } 7225 7226 item = ui.item.data( "ui-autocomplete-item" ); 7227 if ( false !== this._trigger( "focus", event, { item: item } ) ) { 7228 // use value to match what will end up in the input, if it was a key event 7229 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) { 7230 this._value( item.value ); 7231 } 7232 } 7233 7234 // Announce the value in the liveRegion 7235 label = ui.item.attr( "aria-label" ) || item.value; 7236 if ( label && $.trim( label ).length ) { 7237 this.liveRegion.children().hide(); 7238 $( "<div>" ).text( label ).appendTo( this.liveRegion ); 7239 } 7240 }, 7241 menuselect: function( event, ui ) { 7242 var item = ui.item.data( "ui-autocomplete-item" ), 7243 previous = this.previous; 7244 7245 // only trigger when focus was lost (click on menu) 7246 if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) { 7247 this.element.focus(); 7248 this.previous = previous; 7249 // #6109 - IE triggers two focus events and the second 7250 // is asynchronous, so we need to reset the previous 7251 // term synchronously and asynchronously :-( 7252 this._delay(function() { 7253 this.previous = previous; 7254 this.selectedItem = item; 7255 }); 7256 } 7257 7258 if ( false !== this._trigger( "select", event, { item: item } ) ) { 7259 this._value( item.value ); 7260 } 7261 // reset the term after the select event 7262 // this allows custom select handling to work properly 7263 this.term = this._value(); 7264 7265 this.close( event ); 7266 this.selectedItem = item; 7267 } 7268 }); 7269 7270 this.liveRegion = $( "<span>", { 7271 role: "status", 7272 "aria-live": "assertive", 7273 "aria-relevant": "additions" 7274 }) 7275 .addClass( "ui-helper-hidden-accessible" ) 7276 .appendTo( this.document[ 0 ].body ); 7277 7278 // turning off autocomplete prevents the browser from remembering the 7279 // value when navigating through history, so we re-enable autocomplete 7280 // if the page is unloaded before the widget is destroyed. #7790 7281 this._on( this.window, { 7282 beforeunload: function() { 7283 this.element.removeAttr( "autocomplete" ); 7284 } 7285 }); 7286 }, 7287 7288 _destroy: function() { 7289 clearTimeout( this.searching ); 7290 this.element 7291 .removeClass( "ui-autocomplete-input" ) 7292 .removeAttr( "autocomplete" ); 7293 this.menu.element.remove(); 7294 this.liveRegion.remove(); 7295 }, 7296 7297 _setOption: function( key, value ) { 7298 this._super( key, value ); 7299 if ( key === "source" ) { 7300 this._initSource(); 7301 } 7302 if ( key === "appendTo" ) { 7303 this.menu.element.appendTo( this._appendTo() ); 7304 } 7305 if ( key === "disabled" && value && this.xhr ) { 7306 this.xhr.abort(); 7307 } 7308 }, 7309 7310 _appendTo: function() { 7311 var element = this.options.appendTo; 7312 7313 if ( element ) { 7314 element = element.jquery || element.nodeType ? 7315 $( element ) : 7316 this.document.find( element ).eq( 0 ); 7317 } 7318 7319 if ( !element || !element[ 0 ] ) { 7320 element = this.element.closest( ".ui-front" ); 7321 } 7322 7323 if ( !element.length ) { 7324 element = this.document[ 0 ].body; 7325 } 7326 7327 return element; 7328 }, 7329 7330 _initSource: function() { 7331 var array, url, 7332 that = this; 7333 if ( $.isArray( this.options.source ) ) { 7334 array = this.options.source; 7335 this.source = function( request, response ) { 7336 response( $.ui.autocomplete.filter( array, request.term ) ); 7337 }; 7338 } else if ( typeof this.options.source === "string" ) { 7339 url = this.options.source; 7340 this.source = function( request, response ) { 7341 if ( that.xhr ) { 7342 that.xhr.abort(); 7343 } 7344 that.xhr = $.ajax({ 7345 url: url, 7346 data: request, 7347 dataType: "json", 7348 success: function( data ) { 7349 response( data ); 7350 }, 7351 error: function() { 7352 response([]); 7353 } 7354 }); 7355 }; 7356 } else { 7357 this.source = this.options.source; 7358 } 7359 }, 7360 7361 _searchTimeout: function( event ) { 7362 clearTimeout( this.searching ); 7363 this.searching = this._delay(function() { 7364 7365 // Search if the value has changed, or if the user retypes the same value (see #7434) 7366 var equalValues = this.term === this._value(), 7367 menuVisible = this.menu.element.is( ":visible" ), 7368 modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey; 7369 7370 if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) { 7371 this.selectedItem = null; 7372 this.search( null, event ); 7373 } 7374 }, this.options.delay ); 7375 }, 7376 7377 search: function( value, event ) { 7378 value = value != null ? value : this._value(); 7379 7380 // always save the actual value, not the one passed as an argument 7381 this.term = this._value(); 7382 7383 if ( value.length < this.options.minLength ) { 7384 return this.close( event ); 7385 } 7386 7387 if ( this._trigger( "search", event ) === false ) { 7388 return; 7389 } 7390 7391 return this._search( value ); 7392 }, 7393 7394 _search: function( value ) { 7395 this.pending++; 7396 this.element.addClass( "ui-autocomplete-loading" ); 7397 this.cancelSearch = false; 7398 7399 this.source( { term: value }, this._response() ); 7400 }, 7401 7402 _response: function() { 7403 var index = ++this.requestIndex; 7404 7405 return $.proxy(function( content ) { 7406 if ( index === this.requestIndex ) { 7407 this.__response( content ); 7408 } 7409 7410 this.pending--; 7411 if ( !this.pending ) { 7412 this.element.removeClass( "ui-autocomplete-loading" ); 7413 } 7414 }, this ); 7415 }, 7416 7417 __response: function( content ) { 7418 if ( content ) { 7419 content = this._normalize( content ); 7420 } 7421 this._trigger( "response", null, { content: content } ); 7422 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) { 7423 this._suggest( content ); 7424 this._trigger( "open" ); 7425 } else { 7426 // use ._close() instead of .close() so we don't cancel future searches 7427 this._close(); 7428 } 7429 }, 7430 7431 close: function( event ) { 7432 this.cancelSearch = true; 7433 this._close( event ); 7434 }, 7435 7436 _close: function( event ) { 7437 if ( this.menu.element.is( ":visible" ) ) { 7438 this.menu.element.hide(); 7439 this.menu.blur(); 7440 this.isNewMenu = true; 7441 this._trigger( "close", event ); 7442 } 7443 }, 7444 7445 _change: function( event ) { 7446 if ( this.previous !== this._value() ) { 7447 this._trigger( "change", event, { item: this.selectedItem } ); 7448 } 7449 }, 7450 7451 _normalize: function( items ) { 7452 // assume all items have the right format when the first item is complete 7453 if ( items.length && items[ 0 ].label && items[ 0 ].value ) { 7454 return items; 7455 } 7456 return $.map( items, function( item ) { 7457 if ( typeof item === "string" ) { 7458 return { 7459 label: item, 7460 value: item 7461 }; 7462 } 7463 return $.extend( {}, item, { 7464 label: item.label || item.value, 7465 value: item.value || item.label 7466 }); 7467 }); 7468 }, 7469 7470 _suggest: function( items ) { 7471 var ul = this.menu.element.empty(); 7472 this._renderMenu( ul, items ); 7473 this.isNewMenu = true; 7474 this.menu.refresh(); 7475 7476 // size and position menu 7477 ul.show(); 7478 this._resizeMenu(); 7479 ul.position( $.extend({ 7480 of: this.element 7481 }, this.options.position ) ); 7482 7483 if ( this.options.autoFocus ) { 7484 this.menu.next(); 7485 } 7486 }, 7487 7488 _resizeMenu: function() { 7489 var ul = this.menu.element; 7490 ul.outerWidth( Math.max( 7491 // Firefox wraps long text (possibly a rounding bug) 7492 // so we add 1px to avoid the wrapping (#7513) 7493 ul.width( "" ).outerWidth() + 1, 7494 this.element.outerWidth() 7495 ) ); 7496 }, 7497 7498 _renderMenu: function( ul, items ) { 7499 var that = this; 7500 $.each( items, function( index, item ) { 7501 that._renderItemData( ul, item ); 7502 }); 7503 }, 7504 7505 _renderItemData: function( ul, item ) { 7506 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item ); 7507 }, 7508 7509 _renderItem: function( ul, item ) { 7510 return $( "<li>" ).text( item.label ).appendTo( ul ); 7511 }, 7512 7513 _move: function( direction, event ) { 7514 if ( !this.menu.element.is( ":visible" ) ) { 7515 this.search( null, event ); 7516 return; 7517 } 7518 if ( this.menu.isFirstItem() && /^previous/.test( direction ) || 7519 this.menu.isLastItem() && /^next/.test( direction ) ) { 7520 7521 if ( !this.isMultiLine ) { 7522 this._value( this.term ); 7523 } 7524 7525 this.menu.blur(); 7526 return; 7527 } 7528 this.menu[ direction ]( event ); 7529 }, 7530 7531 widget: function() { 7532 return this.menu.element; 7533 }, 7534 7535 _value: function() { 7536 return this.valueMethod.apply( this.element, arguments ); 7537 }, 7538 7539 _keyEvent: function( keyEvent, event ) { 7540 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 7541 this._move( keyEvent, event ); 7542 7543 // prevents moving cursor to beginning/end of the text field in some browsers 7544 event.preventDefault(); 7545 } 7546 } 7547 }); 7548 7549 $.extend( $.ui.autocomplete, { 7550 escapeRegex: function( value ) { 7551 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ); 7552 }, 7553 filter: function( array, term ) { 7554 var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" ); 7555 return $.grep( array, function( value ) { 7556 return matcher.test( value.label || value.value || value ); 7557 }); 7558 } 7559 }); 7560 7561 // live region extension, adding a `messages` option 7562 // NOTE: This is an experimental API. We are still investigating 7563 // a full solution for string manipulation and internationalization. 7564 $.widget( "ui.autocomplete", $.ui.autocomplete, { 7565 options: { 7566 messages: { 7567 noResults: "No search results.", 7568 results: function( amount ) { 7569 return amount + ( amount > 1 ? " results are" : " result is" ) + 7570 " available, use up and down arrow keys to navigate."; 7571 } 7572 } 7573 }, 7574 7575 __response: function( content ) { 7576 var message; 7577 this._superApply( arguments ); 7578 if ( this.options.disabled || this.cancelSearch ) { 7579 return; 7580 } 7581 if ( content && content.length ) { 7582 message = this.options.messages.results( content.length ); 7583 } else { 7584 message = this.options.messages.noResults; 7585 } 7586 this.liveRegion.children().hide(); 7587 $( "<div>" ).text( message ).appendTo( this.liveRegion ); 7588 } 7589 }); 7590 7591 var autocomplete = $.ui.autocomplete; 7592 7593 7594 /*! 7595 * jQuery UI Button 1.11.4 7596 * http://jqueryui.com 7597 * 7598 * Copyright jQuery Foundation and other contributors 7599 * Released under the MIT license. 7600 * http://jquery.org/license 7601 * 7602 * http://api.jqueryui.com/button/ 7603 */ 7604 7605 7606 var lastActive, 7607 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", 7608 typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only", 7609 formResetHandler = function() { 7610 var form = $( this ); 7611 setTimeout(function() { 7612 form.find( ":ui-button" ).button( "refresh" ); 7613 }, 1 ); 7614 }, 7615 radioGroup = function( radio ) { 7616 var name = radio.name, 7617 form = radio.form, 7618 radios = $( [] ); 7619 if ( name ) { 7620 name = name.replace( /'/g, "\\'" ); 7621 if ( form ) { 7622 radios = $( form ).find( "[name='" + name + "'][type=radio]" ); 7623 } else { 7624 radios = $( "[name='" + name + "'][type=radio]", radio.ownerDocument ) 7625 .filter(function() { 7626 return !this.form; 7627 }); 7628 } 7629 } 7630 return radios; 7631 }; 7632 7633 $.widget( "ui.button", { 7634 version: "1.11.4", 7635 defaultElement: "<button>", 7636 options: { 7637 disabled: null, 7638 text: true, 7639 label: null, 7640 icons: { 7641 primary: null, 7642 secondary: null 7643 } 7644 }, 7645 _create: function() { 7646 this.element.closest( "form" ) 7647 .unbind( "reset" + this.eventNamespace ) 7648 .bind( "reset" + this.eventNamespace, formResetHandler ); 7649 7650 if ( typeof this.options.disabled !== "boolean" ) { 7651 this.options.disabled = !!this.element.prop( "disabled" ); 7652 } else { 7653 this.element.prop( "disabled", this.options.disabled ); 7654 } 7655 7656 this._determineButtonType(); 7657 this.hasTitle = !!this.buttonElement.attr( "title" ); 7658 7659 var that = this, 7660 options = this.options, 7661 toggleButton = this.type === "checkbox" || this.type === "radio", 7662 activeClass = !toggleButton ? "ui-state-active" : ""; 7663 7664 if ( options.label === null ) { 7665 options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html()); 7666 } 7667 7668 this._hoverable( this.buttonElement ); 7669 7670 this.buttonElement 7671 .addClass( baseClasses ) 7672 .attr( "role", "button" ) 7673 .bind( "mouseenter" + this.eventNamespace, function() { 7674 if ( options.disabled ) { 7675 return; 7676 } 7677 if ( this === lastActive ) { 7678 $( this ).addClass( "ui-state-active" ); 7679 } 7680 }) 7681 .bind( "mouseleave" + this.eventNamespace, function() { 7682 if ( options.disabled ) { 7683 return; 7684 } 7685 $( this ).removeClass( activeClass ); 7686 }) 7687 .bind( "click" + this.eventNamespace, function( event ) { 7688 if ( options.disabled ) { 7689 event.preventDefault(); 7690 event.stopImmediatePropagation(); 7691 } 7692 }); 7693 7694 // Can't use _focusable() because the element that receives focus 7695 // and the element that gets the ui-state-focus class are different 7696 this._on({ 7697 focus: function() { 7698 this.buttonElement.addClass( "ui-state-focus" ); 7699 }, 7700 blur: function() { 7701 this.buttonElement.removeClass( "ui-state-focus" ); 7702 } 7703 }); 7704 7705 if ( toggleButton ) { 7706 this.element.bind( "change" + this.eventNamespace, function() { 7707 that.refresh(); 7708 }); 7709 } 7710 7711 if ( this.type === "checkbox" ) { 7712 this.buttonElement.bind( "click" + this.eventNamespace, function() { 7713 if ( options.disabled ) { 7714 return false; 7715 } 7716 }); 7717 } else if ( this.type === "radio" ) { 7718 this.buttonElement.bind( "click" + this.eventNamespace, function() { 7719 if ( options.disabled ) { 7720 return false; 7721 } 7722 $( this ).addClass( "ui-state-active" ); 7723 that.buttonElement.attr( "aria-pressed", "true" ); 7724 7725 var radio = that.element[ 0 ]; 7726 radioGroup( radio ) 7727 .not( radio ) 7728 .map(function() { 7729 return $( this ).button( "widget" )[ 0 ]; 7730 }) 7731 .removeClass( "ui-state-active" ) 7732 .attr( "aria-pressed", "false" ); 7733 }); 7734 } else { 7735 this.buttonElement 7736 .bind( "mousedown" + this.eventNamespace, function() { 7737 if ( options.disabled ) { 7738 return false; 7739 } 7740 $( this ).addClass( "ui-state-active" ); 7741 lastActive = this; 7742 that.document.one( "mouseup", function() { 7743 lastActive = null; 7744 }); 7745 }) 7746 .bind( "mouseup" + this.eventNamespace, function() { 7747 if ( options.disabled ) { 7748 return false; 7749 } 7750 $( this ).removeClass( "ui-state-active" ); 7751 }) 7752 .bind( "keydown" + this.eventNamespace, function(event) { 7753 if ( options.disabled ) { 7754 return false; 7755 } 7756 if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) { 7757 $( this ).addClass( "ui-state-active" ); 7758 } 7759 }) 7760 // see #8559, we bind to blur here in case the button element loses 7761 // focus between keydown and keyup, it would be left in an "active" state 7762 .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() { 7763 $( this ).removeClass( "ui-state-active" ); 7764 }); 7765 7766 if ( this.buttonElement.is("a") ) { 7767 this.buttonElement.keyup(function(event) { 7768 if ( event.keyCode === $.ui.keyCode.SPACE ) { 7769 // TODO pass through original event correctly (just as 2nd argument doesn't work) 7770 $( this ).click(); 7771 } 7772 }); 7773 } 7774 } 7775 7776 this._setOption( "disabled", options.disabled ); 7777 this._resetButton(); 7778 }, 7779 7780 _determineButtonType: function() { 7781 var ancestor, labelSelector, checked; 7782 7783 if ( this.element.is("[type=checkbox]") ) { 7784 this.type = "checkbox"; 7785 } else if ( this.element.is("[type=radio]") ) { 7786 this.type = "radio"; 7787 } else if ( this.element.is("input") ) { 7788 this.type = "input"; 7789 } else { 7790 this.type = "button"; 7791 } 7792 7793 if ( this.type === "checkbox" || this.type === "radio" ) { 7794 // we don't search against the document in case the element 7795 // is disconnected from the DOM 7796 ancestor = this.element.parents().last(); 7797 labelSelector = "label[for='" + this.element.attr("id") + "']"; 7798 this.buttonElement = ancestor.find( labelSelector ); 7799 if ( !this.buttonElement.length ) { 7800 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); 7801 this.buttonElement = ancestor.filter( labelSelector ); 7802 if ( !this.buttonElement.length ) { 7803 this.buttonElement = ancestor.find( labelSelector ); 7804 } 7805 } 7806 this.element.addClass( "ui-helper-hidden-accessible" ); 7807 7808 checked = this.element.is( ":checked" ); 7809 if ( checked ) { 7810 this.buttonElement.addClass( "ui-state-active" ); 7811 } 7812 this.buttonElement.prop( "aria-pressed", checked ); 7813 } else { 7814 this.buttonElement = this.element; 7815 } 7816 }, 7817 7818 widget: function() { 7819 return this.buttonElement; 7820 }, 7821 7822 _destroy: function() { 7823 this.element 7824 .removeClass( "ui-helper-hidden-accessible" ); 7825 this.buttonElement 7826 .removeClass( baseClasses + " ui-state-active " + typeClasses ) 7827 .removeAttr( "role" ) 7828 .removeAttr( "aria-pressed" ) 7829 .html( this.buttonElement.find(".ui-button-text").html() ); 7830 7831 if ( !this.hasTitle ) { 7832 this.buttonElement.removeAttr( "title" ); 7833 } 7834 }, 7835 7836 _setOption: function( key, value ) { 7837 this._super( key, value ); 7838 if ( key === "disabled" ) { 7839 this.widget().toggleClass( "ui-state-disabled", !!value ); 7840 this.element.prop( "disabled", !!value ); 7841 if ( value ) { 7842 if ( this.type === "checkbox" || this.type === "radio" ) { 7843 this.buttonElement.removeClass( "ui-state-focus" ); 7844 } else { 7845 this.buttonElement.removeClass( "ui-state-focus ui-state-active" ); 7846 } 7847 } 7848 return; 7849 } 7850 this._resetButton(); 7851 }, 7852 7853 refresh: function() { 7854 //See #8237 & #8828 7855 var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" ); 7856 7857 if ( isDisabled !== this.options.disabled ) { 7858 this._setOption( "disabled", isDisabled ); 7859 } 7860 if ( this.type === "radio" ) { 7861 radioGroup( this.element[0] ).each(function() { 7862 if ( $( this ).is( ":checked" ) ) { 7863 $( this ).button( "widget" ) 7864 .addClass( "ui-state-active" ) 7865 .attr( "aria-pressed", "true" ); 7866 } else { 7867 $( this ).button( "widget" ) 7868 .removeClass( "ui-state-active" ) 7869 .attr( "aria-pressed", "false" ); 7870 } 7871 }); 7872 } else if ( this.type === "checkbox" ) { 7873 if ( this.element.is( ":checked" ) ) { 7874 this.buttonElement 7875 .addClass( "ui-state-active" ) 7876 .attr( "aria-pressed", "true" ); 7877 } else { 7878 this.buttonElement 7879 .removeClass( "ui-state-active" ) 7880 .attr( "aria-pressed", "false" ); 7881 } 7882 } 7883 }, 7884 7885 _resetButton: function() { 7886 if ( this.type === "input" ) { 7887 if ( this.options.label ) { 7888 this.element.val( this.options.label ); 7889 } 7890 return; 7891 } 7892 var buttonElement = this.buttonElement.removeClass( typeClasses ), 7893 buttonText = $( "<span></span>", this.document[0] ) 7894 .addClass( "ui-button-text" ) 7895 .html( this.options.label ) 7896 .appendTo( buttonElement.empty() ) 7897 .text(), 7898 icons = this.options.icons, 7899 multipleIcons = icons.primary && icons.secondary, 7900 buttonClasses = []; 7901 7902 if ( icons.primary || icons.secondary ) { 7903 if ( this.options.text ) { 7904 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) ); 7905 } 7906 7907 if ( icons.primary ) { 7908 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" ); 7909 } 7910 7911 if ( icons.secondary ) { 7912 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" ); 7913 } 7914 7915 if ( !this.options.text ) { 7916 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" ); 7917 7918 if ( !this.hasTitle ) { 7919 buttonElement.attr( "title", $.trim( buttonText ) ); 7920 } 7921 } 7922 } else { 7923 buttonClasses.push( "ui-button-text-only" ); 7924 } 7925 buttonElement.addClass( buttonClasses.join( " " ) ); 7926 } 7927 }); 7928 7929 $.widget( "ui.buttonset", { 7930 version: "1.11.4", 7931 options: { 7932 items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)" 7933 }, 7934 7935 _create: function() { 7936 this.element.addClass( "ui-buttonset" ); 7937 }, 7938 7939 _init: function() { 7940 this.refresh(); 7941 }, 7942 7943 _setOption: function( key, value ) { 7944 if ( key === "disabled" ) { 7945 this.buttons.button( "option", key, value ); 7946 } 7947 7948 this._super( key, value ); 7949 }, 7950 7951 refresh: function() { 7952 var rtl = this.element.css( "direction" ) === "rtl", 7953 allButtons = this.element.find( this.options.items ), 7954 existingButtons = allButtons.filter( ":ui-button" ); 7955 7956 // Initialize new buttons 7957 allButtons.not( ":ui-button" ).button(); 7958 7959 // Refresh existing buttons 7960 existingButtons.button( "refresh" ); 7961 7962 this.buttons = allButtons 7963 .map(function() { 7964 return $( this ).button( "widget" )[ 0 ]; 7965 }) 7966 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" ) 7967 .filter( ":first" ) 7968 .addClass( rtl ? "ui-corner-right" : "ui-corner-left" ) 7969 .end() 7970 .filter( ":last" ) 7971 .addClass( rtl ? "ui-corner-left" : "ui-corner-right" ) 7972 .end() 7973 .end(); 7974 }, 7975 7976 _destroy: function() { 7977 this.element.removeClass( "ui-buttonset" ); 7978 this.buttons 7979 .map(function() { 7980 return $( this ).button( "widget" )[ 0 ]; 7981 }) 7982 .removeClass( "ui-corner-left ui-corner-right" ) 7983 .end() 7984 .button( "destroy" ); 7985 } 7986 }); 7987 7988 var button = $.ui.button; 7989 7990 7991 /*! 7992 * jQuery UI Datepicker 1.11.4 7993 * http://jqueryui.com 7994 * 7995 * Copyright jQuery Foundation and other contributors 7996 * Released under the MIT license. 7997 * http://jquery.org/license 7998 * 7999 * http://api.jqueryui.com/datepicker/ 8000 */ 8001 8002 8003 $.extend($.ui, { datepicker: { version: "1.11.4" } }); 8004 8005 var datepicker_instActive; 8006 8007 function datepicker_getZindex( elem ) { 8008 var position, value; 8009 while ( elem.length && elem[ 0 ] !== document ) { 8010 // Ignore z-index if position is set to a value where z-index is ignored by the browser 8011 // This makes behavior of this function consistent across browsers 8012 // WebKit always returns auto if the element is positioned 8013 position = elem.css( "position" ); 8014 if ( position === "absolute" || position === "relative" || position === "fixed" ) { 8015 // IE returns 0 when zIndex is not specified 8016 // other browsers return a string 8017 // we ignore the case of nested elements with an explicit value of 0 8018 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 8019 value = parseInt( elem.css( "zIndex" ), 10 ); 8020 if ( !isNaN( value ) && value !== 0 ) { 8021 return value; 8022 } 8023 } 8024 elem = elem.parent(); 8025 } 8026 8027 return 0; 8028 } 8029 /* Date picker manager. 8030 Use the singleton instance of this class, $.datepicker, to interact with the date picker. 8031 Settings for (groups of) date pickers are maintained in an instance object, 8032 allowing multiple different settings on the same page. */ 8033 8034 function Datepicker() { 8035 this._curInst = null; // The current instance in use 8036 this._keyEvent = false; // If the last event was a key event 8037 this._disabledInputs = []; // List of date picker inputs that have been disabled 8038 this._datepickerShowing = false; // True if the popup picker is showing , false if not 8039 this._inDialog = false; // True if showing within a "dialog", false if not 8040 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division 8041 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class 8042 this._appendClass = "ui-datepicker-append"; // The name of the append marker class 8043 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class 8044 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class 8045 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class 8046 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class 8047 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class 8048 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class 8049 this.regional = []; // Available regional settings, indexed by language code 8050 this.regional[""] = { // Default regional settings 8051 closeText: "Done", // Display text for close link 8052 prevText: "Prev", // Display text for previous month link 8053 nextText: "Next", // Display text for next month link 8054 currentText: "Today", // Display text for current month link 8055 monthNames: ["January","February","March","April","May","June", 8056 "July","August","September","October","November","December"], // Names of months for drop-down and formatting 8057 monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting 8058 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting 8059 dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting 8060 dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday 8061 weekHeader: "Wk", // Column header for week of the year 8062 dateFormat: "mm/dd/yy", // See format options on parseDate 8063 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... 8064 isRTL: false, // True if right-to-left language, false if left-to-right 8065 showMonthAfterYear: false, // True if the year select precedes month, false for month then year 8066 yearSuffix: "" // Additional text to append to the year in the month headers 8067 }; 8068 this._defaults = { // Global defaults for all the date picker instances 8069 showOn: "focus", // "focus" for popup on focus, 8070 // "button" for trigger button, or "both" for either 8071 showAnim: "fadeIn", // Name of jQuery animation for popup 8072 showOptions: {}, // Options for enhanced animations 8073 defaultDate: null, // Used when field is blank: actual date, 8074 // +/-number for offset from today, null for today 8075 appendText: "", // Display text following the input box, e.g. showing the format 8076 buttonText: "...", // Text for trigger button 8077 buttonImage: "", // URL for trigger button image 8078 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button 8079 hideIfNoPrevNext: false, // True to hide next/previous month links 8080 // if not applicable, false to just disable them 8081 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links 8082 gotoCurrent: false, // True if today link goes back to current selection instead 8083 changeMonth: false, // True if month can be selected directly, false if only prev/next 8084 changeYear: false, // True if year can be selected directly, false if only prev/next 8085 yearRange: "c-10:c+10", // Range of years to display in drop-down, 8086 // either relative to today's year (-nn:+nn), relative to currently displayed year 8087 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) 8088 showOtherMonths: false, // True to show dates in other months, false to leave blank 8089 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable 8090 showWeek: false, // True to show week of the year, false to not show it 8091 calculateWeek: this.iso8601Week, // How to calculate the week of the year, 8092 // takes a Date and returns the number of the week for it 8093 shortYearCutoff: "+10", // Short year values < this are in the current century, 8094 // > this are in the previous century, 8095 // string value starting with "+" for current year + value 8096 minDate: null, // The earliest selectable date, or null for no limit 8097 maxDate: null, // The latest selectable date, or null for no limit 8098 duration: "fast", // Duration of display/closure 8099 beforeShowDay: null, // Function that takes a date and returns an array with 8100 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "", 8101 // [2] = cell title (optional), e.g. $.datepicker.noWeekends 8102 beforeShow: null, // Function that takes an input field and 8103 // returns a set of custom settings for the date picker 8104 onSelect: null, // Define a callback function when a date is selected 8105 onChangeMonthYear: null, // Define a callback function when the month or year is changed 8106 onClose: null, // Define a callback function when the datepicker is closed 8107 numberOfMonths: 1, // Number of months to show at a time 8108 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) 8109 stepMonths: 1, // Number of months to step back/forward 8110 stepBigMonths: 12, // Number of months to step back/forward for the big links 8111 altField: "", // Selector for an alternate field to store selected dates into 8112 altFormat: "", // The date format to use for the alternate field 8113 constrainInput: true, // The input is constrained by the current date format 8114 showButtonPanel: false, // True to show button panel, false to not show it 8115 autoSize: false, // True to size the input for the date format, false to leave as is 8116 disabled: false // The initial disabled state 8117 }; 8118 $.extend(this._defaults, this.regional[""]); 8119 this.regional.en = $.extend( true, {}, this.regional[ "" ]); 8120 this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en ); 8121 this.dpDiv = datepicker_bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")); 8122 } 8123 8124 $.extend(Datepicker.prototype, { 8125 /* Class name added to elements to indicate already configured with a date picker. */ 8126 markerClassName: "hasDatepicker", 8127 8128 //Keep track of the maximum number of rows displayed (see #7043) 8129 maxRows: 4, 8130 8131 // TODO rename to "widget" when switching to widget factory 8132 _widgetDatepicker: function() { 8133 return this.dpDiv; 8134 }, 8135 8136 /* Override the default settings for all instances of the date picker. 8137 * @param settings object - the new settings to use as defaults (anonymous object) 8138 * @return the manager object 8139 */ 8140 setDefaults: function(settings) { 8141 datepicker_extendRemove(this._defaults, settings || {}); 8142 return this; 8143 }, 8144 8145 /* Attach the date picker to a jQuery selection. 8146 * @param target element - the target input field or division or span 8147 * @param settings object - the new settings to use for this date picker instance (anonymous) 8148 */ 8149 _attachDatepicker: function(target, settings) { 8150 var nodeName, inline, inst; 8151 nodeName = target.nodeName.toLowerCase(); 8152 inline = (nodeName === "div" || nodeName === "span"); 8153 if (!target.id) { 8154 this.uuid += 1; 8155 target.id = "dp" + this.uuid; 8156 } 8157 inst = this._newInst($(target), inline); 8158 inst.settings = $.extend({}, settings || {}); 8159 if (nodeName === "input") { 8160 this._connectDatepicker(target, inst); 8161 } else if (inline) { 8162 this._inlineDatepicker(target, inst); 8163 } 8164 }, 8165 8166 /* Create a new instance object. */ 8167 _newInst: function(target, inline) { 8168 var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars 8169 return {id: id, input: target, // associated target 8170 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection 8171 drawMonth: 0, drawYear: 0, // month being drawn 8172 inline: inline, // is datepicker inline or not 8173 dpDiv: (!inline ? this.dpDiv : // presentation div 8174 datepicker_bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))}; 8175 }, 8176 8177 /* Attach the date picker to an input field. */ 8178 _connectDatepicker: function(target, inst) { 8179 var input = $(target); 8180 inst.append = $([]); 8181 inst.trigger = $([]); 8182 if (input.hasClass(this.markerClassName)) { 8183 return; 8184 } 8185 this._attachments(input, inst); 8186 input.addClass(this.markerClassName).keydown(this._doKeyDown). 8187 keypress(this._doKeyPress).keyup(this._doKeyUp); 8188 this._autoSize(inst); 8189 $.data(target, "datepicker", inst); 8190 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) 8191 if( inst.settings.disabled ) { 8192 this._disableDatepicker( target ); 8193 } 8194 }, 8195 8196 /* Make attachments based on settings. */ 8197 _attachments: function(input, inst) { 8198 var showOn, buttonText, buttonImage, 8199 appendText = this._get(inst, "appendText"), 8200 isRTL = this._get(inst, "isRTL"); 8201 8202 if (inst.append) { 8203 inst.append.remove(); 8204 } 8205 if (appendText) { 8206 inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>"); 8207 input[isRTL ? "before" : "after"](inst.append); 8208 } 8209 8210 input.unbind("focus", this._showDatepicker); 8211 8212 if (inst.trigger) { 8213 inst.trigger.remove(); 8214 } 8215 8216 showOn = this._get(inst, "showOn"); 8217 if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field 8218 input.focus(this._showDatepicker); 8219 } 8220 if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked 8221 buttonText = this._get(inst, "buttonText"); 8222 buttonImage = this._get(inst, "buttonImage"); 8223 inst.trigger = $(this._get(inst, "buttonImageOnly") ? 8224 $("<img/>").addClass(this._triggerClass). 8225 attr({ src: buttonImage, alt: buttonText, title: buttonText }) : 8226 $("<button type='button'></button>").addClass(this._triggerClass). 8227 html(!buttonImage ? buttonText : $("<img/>").attr( 8228 { src:buttonImage, alt:buttonText, title:buttonText }))); 8229 input[isRTL ? "before" : "after"](inst.trigger); 8230 inst.trigger.click(function() { 8231 if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) { 8232 $.datepicker._hideDatepicker(); 8233 } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) { 8234 $.datepicker._hideDatepicker(); 8235 $.datepicker._showDatepicker(input[0]); 8236 } else { 8237 $.datepicker._showDatepicker(input[0]); 8238 } 8239 return false; 8240 }); 8241 } 8242 }, 8243 8244 /* Apply the maximum length for the date format. */ 8245 _autoSize: function(inst) { 8246 if (this._get(inst, "autoSize") && !inst.inline) { 8247 var findMax, max, maxI, i, 8248 date = new Date(2009, 12 - 1, 20), // Ensure double digits 8249 dateFormat = this._get(inst, "dateFormat"); 8250 8251 if (dateFormat.match(/[DM]/)) { 8252 findMax = function(names) { 8253 max = 0; 8254 maxI = 0; 8255 for (i = 0; i < names.length; i++) { 8256 if (names[i].length > max) { 8257 max = names[i].length; 8258 maxI = i; 8259 } 8260 } 8261 return maxI; 8262 }; 8263 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? 8264 "monthNames" : "monthNamesShort")))); 8265 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? 8266 "dayNames" : "dayNamesShort"))) + 20 - date.getDay()); 8267 } 8268 inst.input.attr("size", this._formatDate(inst, date).length); 8269 } 8270 }, 8271 8272 /* Attach an inline date picker to a div. */ 8273 _inlineDatepicker: function(target, inst) { 8274 var divSpan = $(target); 8275 if (divSpan.hasClass(this.markerClassName)) { 8276 return; 8277 } 8278 divSpan.addClass(this.markerClassName).append(inst.dpDiv); 8279 $.data(target, "datepicker", inst); 8280 this._setDate(inst, this._getDefaultDate(inst), true); 8281 this._updateDatepicker(inst); 8282 this._updateAlternate(inst); 8283 //If disabled option is true, disable the datepicker before showing it (see ticket #5665) 8284 if( inst.settings.disabled ) { 8285 this._disableDatepicker( target ); 8286 } 8287 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements 8288 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height 8289 inst.dpDiv.css( "display", "block" ); 8290 }, 8291 8292 /* Pop-up the date picker in a "dialog" box. 8293 * @param input element - ignored 8294 * @param date string or Date - the initial date to display 8295 * @param onSelect function - the function to call when a date is selected 8296 * @param settings object - update the dialog date picker instance's settings (anonymous object) 8297 * @param pos int[2] - coordinates for the dialog's position within the screen or 8298 * event - with x/y coordinates or 8299 * leave empty for default (screen centre) 8300 * @return the manager object 8301 */ 8302 _dialogDatepicker: function(input, date, onSelect, settings, pos) { 8303 var id, browserWidth, browserHeight, scrollX, scrollY, 8304 inst = this._dialogInst; // internal instance 8305 8306 if (!inst) { 8307 this.uuid += 1; 8308 id = "dp" + this.uuid; 8309 this._dialogInput = $("<input type='text' id='" + id + 8310 "' style='position: absolute; top: -100px; width: 0px;'/>"); 8311 this._dialogInput.keydown(this._doKeyDown); 8312 $("body").append(this._dialogInput); 8313 inst = this._dialogInst = this._newInst(this._dialogInput, false); 8314 inst.settings = {}; 8315 $.data(this._dialogInput[0], "datepicker", inst); 8316 } 8317 datepicker_extendRemove(inst.settings, settings || {}); 8318 date = (date && date.constructor === Date ? this._formatDate(inst, date) : date); 8319 this._dialogInput.val(date); 8320 8321 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); 8322 if (!this._pos) { 8323 browserWidth = document.documentElement.clientWidth; 8324 browserHeight = document.documentElement.clientHeight; 8325 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; 8326 scrollY = document.documentElement.scrollTop || document.body.scrollTop; 8327 this._pos = // should use actual width/height below 8328 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; 8329 } 8330 8331 // move input on screen for focus, but hidden behind dialog 8332 this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px"); 8333 inst.settings.onSelect = onSelect; 8334 this._inDialog = true; 8335 this.dpDiv.addClass(this._dialogClass); 8336 this._showDatepicker(this._dialogInput[0]); 8337 if ($.blockUI) { 8338 $.blockUI(this.dpDiv); 8339 } 8340 $.data(this._dialogInput[0], "datepicker", inst); 8341 return this; 8342 }, 8343 8344 /* Detach a datepicker from its control. 8345 * @param target element - the target input field or division or span 8346 */ 8347 _destroyDatepicker: function(target) { 8348 var nodeName, 8349 $target = $(target), 8350 inst = $.data(target, "datepicker"); 8351 8352 if (!$target.hasClass(this.markerClassName)) { 8353 return; 8354 } 8355 8356 nodeName = target.nodeName.toLowerCase(); 8357 $.removeData(target, "datepicker"); 8358 if (nodeName === "input") { 8359 inst.append.remove(); 8360 inst.trigger.remove(); 8361 $target.removeClass(this.markerClassName). 8362 unbind("focus", this._showDatepicker). 8363 unbind("keydown", this._doKeyDown). 8364 unbind("keypress", this._doKeyPress). 8365 unbind("keyup", this._doKeyUp); 8366 } else if (nodeName === "div" || nodeName === "span") { 8367 $target.removeClass(this.markerClassName).empty(); 8368 } 8369 8370 if ( datepicker_instActive === inst ) { 8371 datepicker_instActive = null; 8372 } 8373 }, 8374 8375 /* Enable the date picker to a jQuery selection. 8376 * @param target element - the target input field or division or span 8377 */ 8378 _enableDatepicker: function(target) { 8379 var nodeName, inline, 8380 $target = $(target), 8381 inst = $.data(target, "datepicker"); 8382 8383 if (!$target.hasClass(this.markerClassName)) { 8384 return; 8385 } 8386 8387 nodeName = target.nodeName.toLowerCase(); 8388 if (nodeName === "input") { 8389 target.disabled = false; 8390 inst.trigger.filter("button"). 8391 each(function() { this.disabled = false; }).end(). 8392 filter("img").css({opacity: "1.0", cursor: ""}); 8393 } else if (nodeName === "div" || nodeName === "span") { 8394 inline = $target.children("." + this._inlineClass); 8395 inline.children().removeClass("ui-state-disabled"); 8396 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 8397 prop("disabled", false); 8398 } 8399 this._disabledInputs = $.map(this._disabledInputs, 8400 function(value) { return (value === target ? null : value); }); // delete entry 8401 }, 8402 8403 /* Disable the date picker to a jQuery selection. 8404 * @param target element - the target input field or division or span 8405 */ 8406 _disableDatepicker: function(target) { 8407 var nodeName, inline, 8408 $target = $(target), 8409 inst = $.data(target, "datepicker"); 8410 8411 if (!$target.hasClass(this.markerClassName)) { 8412 return; 8413 } 8414 8415 nodeName = target.nodeName.toLowerCase(); 8416 if (nodeName === "input") { 8417 target.disabled = true; 8418 inst.trigger.filter("button"). 8419 each(function() { this.disabled = true; }).end(). 8420 filter("img").css({opacity: "0.5", cursor: "default"}); 8421 } else if (nodeName === "div" || nodeName === "span") { 8422 inline = $target.children("." + this._inlineClass); 8423 inline.children().addClass("ui-state-disabled"); 8424 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 8425 prop("disabled", true); 8426 } 8427 this._disabledInputs = $.map(this._disabledInputs, 8428 function(value) { return (value === target ? null : value); }); // delete entry 8429 this._disabledInputs[this._disabledInputs.length] = target; 8430 }, 8431 8432 /* Is the first field in a jQuery collection disabled as a datepicker? 8433 * @param target element - the target input field or division or span 8434 * @return boolean - true if disabled, false if enabled 8435 */ 8436 _isDisabledDatepicker: function(target) { 8437 if (!target) { 8438 return false; 8439 } 8440 for (var i = 0; i < this._disabledInputs.length; i++) { 8441 if (this._disabledInputs[i] === target) { 8442 return true; 8443 } 8444 } 8445 return false; 8446 }, 8447 8448 /* Retrieve the instance data for the target control. 8449 * @param target element - the target input field or division or span 8450 * @return object - the associated instance data 8451 * @throws error if a jQuery problem getting data 8452 */ 8453 _getInst: function(target) { 8454 try { 8455 return $.data(target, "datepicker"); 8456 } 8457 catch (err) { 8458 throw "Missing instance data for this datepicker"; 8459 } 8460 }, 8461 8462 /* Update or retrieve the settings for a date picker attached to an input field or division. 8463 * @param target element - the target input field or division or span 8464 * @param name object - the new settings to update or 8465 * string - the name of the setting to change or retrieve, 8466 * when retrieving also "all" for all instance settings or 8467 * "defaults" for all global defaults 8468 * @param value any - the new value for the setting 8469 * (omit if above is an object or to retrieve a value) 8470 */ 8471 _optionDatepicker: function(target, name, value) { 8472 var settings, date, minDate, maxDate, 8473 inst = this._getInst(target); 8474 8475 if (arguments.length === 2 && typeof name === "string") { 8476 return (name === "defaults" ? $.extend({}, $.datepicker._defaults) : 8477 (inst ? (name === "all" ? $.extend({}, inst.settings) : 8478 this._get(inst, name)) : null)); 8479 } 8480 8481 settings = name || {}; 8482 if (typeof name === "string") { 8483 settings = {}; 8484 settings[name] = value; 8485 } 8486 8487 if (inst) { 8488 if (this._curInst === inst) { 8489 this._hideDatepicker(); 8490 } 8491 8492 date = this._getDateDatepicker(target, true); 8493 minDate = this._getMinMaxDate(inst, "min"); 8494 maxDate = this._getMinMaxDate(inst, "max"); 8495 datepicker_extendRemove(inst.settings, settings); 8496 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided 8497 if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) { 8498 inst.settings.minDate = this._formatDate(inst, minDate); 8499 } 8500 if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) { 8501 inst.settings.maxDate = this._formatDate(inst, maxDate); 8502 } 8503 if ( "disabled" in settings ) { 8504 if ( settings.disabled ) { 8505 this._disableDatepicker(target); 8506 } else { 8507 this._enableDatepicker(target); 8508 } 8509 } 8510 this._attachments($(target), inst); 8511 this._autoSize(inst); 8512 this._setDate(inst, date); 8513 this._updateAlternate(inst); 8514 this._updateDatepicker(inst); 8515 } 8516 }, 8517 8518 // change method deprecated 8519 _changeDatepicker: function(target, name, value) { 8520 this._optionDatepicker(target, name, value); 8521 }, 8522 8523 /* Redraw the date picker attached to an input field or division. 8524 * @param target element - the target input field or division or span 8525 */ 8526 _refreshDatepicker: function(target) { 8527 var inst = this._getInst(target); 8528 if (inst) { 8529 this._updateDatepicker(inst); 8530 } 8531 }, 8532 8533 /* Set the dates for a jQuery selection. 8534 * @param target element - the target input field or division or span 8535 * @param date Date - the new date 8536 */ 8537 _setDateDatepicker: function(target, date) { 8538 var inst = this._getInst(target); 8539 if (inst) { 8540 this._setDate(inst, date); 8541 this._updateDatepicker(inst); 8542 this._updateAlternate(inst); 8543 } 8544 }, 8545 8546 /* Get the date(s) for the first entry in a jQuery selection. 8547 * @param target element - the target input field or division or span 8548 * @param noDefault boolean - true if no default date is to be used 8549 * @return Date - the current date 8550 */ 8551 _getDateDatepicker: function(target, noDefault) { 8552 var inst = this._getInst(target); 8553 if (inst && !inst.inline) { 8554 this._setDateFromField(inst, noDefault); 8555 } 8556 return (inst ? this._getDate(inst) : null); 8557 }, 8558 8559 /* Handle keystrokes. */ 8560 _doKeyDown: function(event) { 8561 var onSelect, dateStr, sel, 8562 inst = $.datepicker._getInst(event.target), 8563 handled = true, 8564 isRTL = inst.dpDiv.is(".ui-datepicker-rtl"); 8565 8566 inst._keyEvent = true; 8567 if ($.datepicker._datepickerShowing) { 8568 switch (event.keyCode) { 8569 case 9: $.datepicker._hideDatepicker(); 8570 handled = false; 8571 break; // hide on tab out 8572 case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." + 8573 $.datepicker._currentClass + ")", inst.dpDiv); 8574 if (sel[0]) { 8575 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); 8576 } 8577 8578 onSelect = $.datepicker._get(inst, "onSelect"); 8579 if (onSelect) { 8580 dateStr = $.datepicker._formatDate(inst); 8581 8582 // trigger custom callback 8583 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); 8584 } else { 8585 $.datepicker._hideDatepicker(); 8586 } 8587 8588 return false; // don't submit the form 8589 case 27: $.datepicker._hideDatepicker(); 8590 break; // hide on escape 8591 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 8592 -$.datepicker._get(inst, "stepBigMonths") : 8593 -$.datepicker._get(inst, "stepMonths")), "M"); 8594 break; // previous month/year on page up/+ ctrl 8595 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 8596 +$.datepicker._get(inst, "stepBigMonths") : 8597 +$.datepicker._get(inst, "stepMonths")), "M"); 8598 break; // next month/year on page down/+ ctrl 8599 case 35: if (event.ctrlKey || event.metaKey) { 8600 $.datepicker._clearDate(event.target); 8601 } 8602 handled = event.ctrlKey || event.metaKey; 8603 break; // clear on ctrl or command +end 8604 case 36: if (event.ctrlKey || event.metaKey) { 8605 $.datepicker._gotoToday(event.target); 8606 } 8607 handled = event.ctrlKey || event.metaKey; 8608 break; // current on ctrl or command +home 8609 case 37: if (event.ctrlKey || event.metaKey) { 8610 $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D"); 8611 } 8612 handled = event.ctrlKey || event.metaKey; 8613 // -1 day on ctrl or command +left 8614 if (event.originalEvent.altKey) { 8615 $.datepicker._adjustDate(event.target, (event.ctrlKey ? 8616 -$.datepicker._get(inst, "stepBigMonths") : 8617 -$.datepicker._get(inst, "stepMonths")), "M"); 8618 } 8619 // next month/year on alt +left on Mac 8620 break; 8621 case 38: if (event.ctrlKey || event.metaKey) { 8622 $.datepicker._adjustDate(event.target, -7, "D"); 8623 } 8624 handled = event.ctrlKey || event.metaKey; 8625 break; // -1 week on ctrl or command +up 8626 case 39: if (event.ctrlKey || event.metaKey) { 8627 $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D"); 8628 } 8629 handled = event.ctrlKey || event.metaKey; 8630 // +1 day on ctrl or command +right 8631 if (event.originalEvent.altKey) { 8632 $.datepicker._adjustDate(event.target, (event.ctrlKey ? 8633 +$.datepicker._get(inst, "stepBigMonths") : 8634 +$.datepicker._get(inst, "stepMonths")), "M"); 8635 } 8636 // next month/year on alt +right 8637 break; 8638 case 40: if (event.ctrlKey || event.metaKey) { 8639 $.datepicker._adjustDate(event.target, +7, "D"); 8640 } 8641 handled = event.ctrlKey || event.metaKey; 8642 break; // +1 week on ctrl or command +down 8643 default: handled = false; 8644 } 8645 } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home 8646 $.datepicker._showDatepicker(this); 8647 } else { 8648 handled = false; 8649 } 8650 8651 if (handled) { 8652 event.preventDefault(); 8653 event.stopPropagation(); 8654 } 8655 }, 8656 8657 /* Filter entered characters - based on date format. */ 8658 _doKeyPress: function(event) { 8659 var chars, chr, 8660 inst = $.datepicker._getInst(event.target); 8661 8662 if ($.datepicker._get(inst, "constrainInput")) { 8663 chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat")); 8664 chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode); 8665 return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1); 8666 } 8667 }, 8668 8669 /* Synchronise manual entry and field/alternate field. */ 8670 _doKeyUp: function(event) { 8671 var date, 8672 inst = $.datepicker._getInst(event.target); 8673 8674 if (inst.input.val() !== inst.lastVal) { 8675 try { 8676 date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), 8677 (inst.input ? inst.input.val() : null), 8678 $.datepicker._getFormatConfig(inst)); 8679 8680 if (date) { // only if valid 8681 $.datepicker._setDateFromField(inst); 8682 $.datepicker._updateAlternate(inst); 8683 $.datepicker._updateDatepicker(inst); 8684 } 8685 } 8686 catch (err) { 8687 } 8688 } 8689 return true; 8690 }, 8691 8692 /* Pop-up the date picker for a given input field. 8693 * If false returned from beforeShow event handler do not show. 8694 * @param input element - the input field attached to the date picker or 8695 * event - if triggered by focus 8696 */ 8697 _showDatepicker: function(input) { 8698 input = input.target || input; 8699 if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger 8700 input = $("input", input.parentNode)[0]; 8701 } 8702 8703 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here 8704 return; 8705 } 8706 8707 var inst, beforeShow, beforeShowSettings, isFixed, 8708 offset, showAnim, duration; 8709 8710 inst = $.datepicker._getInst(input); 8711 if ($.datepicker._curInst && $.datepicker._curInst !== inst) { 8712 $.datepicker._curInst.dpDiv.stop(true, true); 8713 if ( inst && $.datepicker._datepickerShowing ) { 8714 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] ); 8715 } 8716 } 8717 8718 beforeShow = $.datepicker._get(inst, "beforeShow"); 8719 beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; 8720 if(beforeShowSettings === false){ 8721 return; 8722 } 8723 datepicker_extendRemove(inst.settings, beforeShowSettings); 8724 8725 inst.lastVal = null; 8726 $.datepicker._lastInput = input; 8727 $.datepicker._setDateFromField(inst); 8728 8729 if ($.datepicker._inDialog) { // hide cursor 8730 input.value = ""; 8731 } 8732 if (!$.datepicker._pos) { // position below input 8733 $.datepicker._pos = $.datepicker._findPos(input); 8734 $.datepicker._pos[1] += input.offsetHeight; // add the height 8735 } 8736 8737 isFixed = false; 8738 $(input).parents().each(function() { 8739 isFixed |= $(this).css("position") === "fixed"; 8740 return !isFixed; 8741 }); 8742 8743 offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; 8744 $.datepicker._pos = null; 8745 //to avoid flashes on Firefox 8746 inst.dpDiv.empty(); 8747 // determine sizing offscreen 8748 inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"}); 8749 $.datepicker._updateDatepicker(inst); 8750 // fix width for dynamic number of date pickers 8751 // and adjust position before showing 8752 offset = $.datepicker._checkOffset(inst, offset, isFixed); 8753 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? 8754 "static" : (isFixed ? "fixed" : "absolute")), display: "none", 8755 left: offset.left + "px", top: offset.top + "px"}); 8756 8757 if (!inst.inline) { 8758 showAnim = $.datepicker._get(inst, "showAnim"); 8759 duration = $.datepicker._get(inst, "duration"); 8760 inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 ); 8761 $.datepicker._datepickerShowing = true; 8762 8763 if ( $.effects && $.effects.effect[ showAnim ] ) { 8764 inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration); 8765 } else { 8766 inst.dpDiv[showAnim || "show"](showAnim ? duration : null); 8767 } 8768 8769 if ( $.datepicker._shouldFocusInput( inst ) ) { 8770 inst.input.focus(); 8771 } 8772 8773 $.datepicker._curInst = inst; 8774 } 8775 }, 8776 8777 /* Generate the date picker content. */ 8778 _updateDatepicker: function(inst) { 8779 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) 8780 datepicker_instActive = inst; // for delegate hover events 8781 inst.dpDiv.empty().append(this._generateHTML(inst)); 8782 this._attachHandlers(inst); 8783 8784 var origyearshtml, 8785 numMonths = this._getNumberOfMonths(inst), 8786 cols = numMonths[1], 8787 width = 17, 8788 activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ); 8789 8790 if ( activeCell.length > 0 ) { 8791 datepicker_handleMouseover.apply( activeCell.get( 0 ) ); 8792 } 8793 8794 inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""); 8795 if (cols > 1) { 8796 inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em"); 8797 } 8798 inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") + 8799 "Class"]("ui-datepicker-multi"); 8800 inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") + 8801 "Class"]("ui-datepicker-rtl"); 8802 8803 if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) { 8804 inst.input.focus(); 8805 } 8806 8807 // deffered render of the years select (to avoid flashes on Firefox) 8808 if( inst.yearshtml ){ 8809 origyearshtml = inst.yearshtml; 8810 setTimeout(function(){ 8811 //assure that inst.yearshtml didn't change. 8812 if( origyearshtml === inst.yearshtml && inst.yearshtml ){ 8813 inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml); 8814 } 8815 origyearshtml = inst.yearshtml = null; 8816 }, 0); 8817 } 8818 }, 8819 8820 // #6694 - don't focus the input if it's already focused 8821 // this breaks the change event in IE 8822 // Support: IE and jQuery <1.9 8823 _shouldFocusInput: function( inst ) { 8824 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" ); 8825 }, 8826 8827 /* Check positioning to remain on screen. */ 8828 _checkOffset: function(inst, offset, isFixed) { 8829 var dpWidth = inst.dpDiv.outerWidth(), 8830 dpHeight = inst.dpDiv.outerHeight(), 8831 inputWidth = inst.input ? inst.input.outerWidth() : 0, 8832 inputHeight = inst.input ? inst.input.outerHeight() : 0, 8833 viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()), 8834 viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop()); 8835 8836 offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0); 8837 offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0; 8838 offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; 8839 8840 // now check if datepicker is showing outside window viewport - move to a better place if so. 8841 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? 8842 Math.abs(offset.left + dpWidth - viewWidth) : 0); 8843 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? 8844 Math.abs(dpHeight + inputHeight) : 0); 8845 8846 return offset; 8847 }, 8848 8849 /* Find an object's position on the screen. */ 8850 _findPos: function(obj) { 8851 var position, 8852 inst = this._getInst(obj), 8853 isRTL = this._get(inst, "isRTL"); 8854 8855 while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) { 8856 obj = obj[isRTL ? "previousSibling" : "nextSibling"]; 8857 } 8858 8859 position = $(obj).offset(); 8860 return [position.left, position.top]; 8861 }, 8862 8863 /* Hide the date picker from view. 8864 * @param input element - the input field attached to the date picker 8865 */ 8866 _hideDatepicker: function(input) { 8867 var showAnim, duration, postProcess, onClose, 8868 inst = this._curInst; 8869 8870 if (!inst || (input && inst !== $.data(input, "datepicker"))) { 8871 return; 8872 } 8873 8874 if (this._datepickerShowing) { 8875 showAnim = this._get(inst, "showAnim"); 8876 duration = this._get(inst, "duration"); 8877 postProcess = function() { 8878 $.datepicker._tidyDialog(inst); 8879 }; 8880 8881 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed 8882 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) { 8883 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess); 8884 } else { 8885 inst.dpDiv[(showAnim === "slideDown" ? "slideUp" : 8886 (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess); 8887 } 8888 8889 if (!showAnim) { 8890 postProcess(); 8891 } 8892 this._datepickerShowing = false; 8893 8894 onClose = this._get(inst, "onClose"); 8895 if (onClose) { 8896 onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]); 8897 } 8898 8899 this._lastInput = null; 8900 if (this._inDialog) { 8901 this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" }); 8902 if ($.blockUI) { 8903 $.unblockUI(); 8904 $("body").append(this.dpDiv); 8905 } 8906 } 8907 this._inDialog = false; 8908 } 8909 }, 8910 8911 /* Tidy up after a dialog display. */ 8912 _tidyDialog: function(inst) { 8913 inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar"); 8914 }, 8915 8916 /* Close date picker if clicked elsewhere. */ 8917 _checkExternalClick: function(event) { 8918 if (!$.datepicker._curInst) { 8919 return; 8920 } 8921 8922 var $target = $(event.target), 8923 inst = $.datepicker._getInst($target[0]); 8924 8925 if ( ( ( $target[0].id !== $.datepicker._mainDivId && 8926 $target.parents("#" + $.datepicker._mainDivId).length === 0 && 8927 !$target.hasClass($.datepicker.markerClassName) && 8928 !$target.closest("." + $.datepicker._triggerClass).length && 8929 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) || 8930 ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) { 8931 $.datepicker._hideDatepicker(); 8932 } 8933 }, 8934 8935 /* Adjust one of the date sub-fields. */ 8936 _adjustDate: function(id, offset, period) { 8937 var target = $(id), 8938 inst = this._getInst(target[0]); 8939 8940 if (this._isDisabledDatepicker(target[0])) { 8941 return; 8942 } 8943 this._adjustInstDate(inst, offset + 8944 (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning 8945 period); 8946 this._updateDatepicker(inst); 8947 }, 8948 8949 /* Action for current link. */ 8950 _gotoToday: function(id) { 8951 var date, 8952 target = $(id), 8953 inst = this._getInst(target[0]); 8954 8955 if (this._get(inst, "gotoCurrent") && inst.currentDay) { 8956 inst.selectedDay = inst.currentDay; 8957 inst.drawMonth = inst.selectedMonth = inst.currentMonth; 8958 inst.drawYear = inst.selectedYear = inst.currentYear; 8959 } else { 8960 date = new Date(); 8961 inst.selectedDay = date.getDate(); 8962 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8963 inst.drawYear = inst.selectedYear = date.getFullYear(); 8964 } 8965 this._notifyChange(inst); 8966 this._adjustDate(target); 8967 }, 8968 8969 /* Action for selecting a new month/year. */ 8970 _selectMonthYear: function(id, select, period) { 8971 var target = $(id), 8972 inst = this._getInst(target[0]); 8973 8974 inst["selected" + (period === "M" ? "Month" : "Year")] = 8975 inst["draw" + (period === "M" ? "Month" : "Year")] = 8976 parseInt(select.options[select.selectedIndex].value,10); 8977 8978 this._notifyChange(inst); 8979 this._adjustDate(target); 8980 }, 8981 8982 /* Action for selecting a day. */ 8983 _selectDay: function(id, month, year, td) { 8984 var inst, 8985 target = $(id); 8986 8987 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { 8988 return; 8989 } 8990 8991 inst = this._getInst(target[0]); 8992 inst.selectedDay = inst.currentDay = $("a", td).html(); 8993 inst.selectedMonth = inst.currentMonth = month; 8994 inst.selectedYear = inst.currentYear = year; 8995 this._selectDate(id, this._formatDate(inst, 8996 inst.currentDay, inst.currentMonth, inst.currentYear)); 8997 }, 8998 8999 /* Erase the input field and hide the date picker. */ 9000 _clearDate: function(id) { 9001 var target = $(id); 9002 this._selectDate(target, ""); 9003 }, 9004 9005 /* Update the input field with the selected date. */ 9006 _selectDate: function(id, dateStr) { 9007 var onSelect, 9008 target = $(id), 9009 inst = this._getInst(target[0]); 9010 9011 dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); 9012 if (inst.input) { 9013 inst.input.val(dateStr); 9014 } 9015 this._updateAlternate(inst); 9016 9017 onSelect = this._get(inst, "onSelect"); 9018 if (onSelect) { 9019 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback 9020 } else if (inst.input) { 9021 inst.input.trigger("change"); // fire the change event 9022 } 9023 9024 if (inst.inline){ 9025 this._updateDatepicker(inst); 9026 } else { 9027 this._hideDatepicker(); 9028 this._lastInput = inst.input[0]; 9029 if (typeof(inst.input[0]) !== "object") { 9030 inst.input.focus(); // restore focus 9031 } 9032 this._lastInput = null; 9033 } 9034 }, 9035 9036 /* Update any alternate field to synchronise with the main field. */ 9037 _updateAlternate: function(inst) { 9038 var altFormat, date, dateStr, 9039 altField = this._get(inst, "altField"); 9040 9041 if (altField) { // update alternate field too 9042 altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat"); 9043 date = this._getDate(inst); 9044 dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); 9045 $(altField).each(function() { $(this).val(dateStr); }); 9046 } 9047 }, 9048 9049 /* Set as beforeShowDay function to prevent selection of weekends. 9050 * @param date Date - the date to customise 9051 * @return [boolean, string] - is this date selectable?, what is its CSS class? 9052 */ 9053 noWeekends: function(date) { 9054 var day = date.getDay(); 9055 return [(day > 0 && day < 6), ""]; 9056 }, 9057 9058 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. 9059 * @param date Date - the date to get the week for 9060 * @return number - the number of the week within the year that contains this date 9061 */ 9062 iso8601Week: function(date) { 9063 var time, 9064 checkDate = new Date(date.getTime()); 9065 9066 // Find Thursday of this week starting on Monday 9067 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); 9068 9069 time = checkDate.getTime(); 9070 checkDate.setMonth(0); // Compare with Jan 1 9071 checkDate.setDate(1); 9072 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; 9073 }, 9074 9075 /* Parse a string value into a date object. 9076 * See formatDate below for the possible formats. 9077 * 9078 * @param format string - the expected format of the date 9079 * @param value string - the date in the above format 9080 * @param settings Object - attributes include: 9081 * shortYearCutoff number - the cutoff year for determining the century (optional) 9082 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 9083 * dayNames string[7] - names of the days from Sunday (optional) 9084 * monthNamesShort string[12] - abbreviated names of the months (optional) 9085 * monthNames string[12] - names of the months (optional) 9086 * @return Date - the extracted date value or null if value is blank 9087 */ 9088 parseDate: function (format, value, settings) { 9089 if (format == null || value == null) { 9090 throw "Invalid arguments"; 9091 } 9092 9093 value = (typeof value === "object" ? value.toString() : value + ""); 9094 if (value === "") { 9095 return null; 9096 } 9097 9098 var iFormat, dim, extra, 9099 iValue = 0, 9100 shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff, 9101 shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp : 9102 new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)), 9103 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, 9104 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, 9105 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, 9106 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, 9107 year = -1, 9108 month = -1, 9109 day = -1, 9110 doy = -1, 9111 literal = false, 9112 date, 9113 // Check whether a format character is doubled 9114 lookAhead = function(match) { 9115 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 9116 if (matches) { 9117 iFormat++; 9118 } 9119 return matches; 9120 }, 9121 // Extract a number from the string value 9122 getNumber = function(match) { 9123 var isDoubled = lookAhead(match), 9124 size = (match === "@" ? 14 : (match === "!" ? 20 : 9125 (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))), 9126 minSize = (match === "y" ? size : 1), 9127 digits = new RegExp("^\\d{" + minSize + "," + size + "}"), 9128 num = value.substring(iValue).match(digits); 9129 if (!num) { 9130 throw "Missing number at position " + iValue; 9131 } 9132 iValue += num[0].length; 9133 return parseInt(num[0], 10); 9134 }, 9135 // Extract a name from the string value and convert to an index 9136 getName = function(match, shortNames, longNames) { 9137 var index = -1, 9138 names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { 9139 return [ [k, v] ]; 9140 }).sort(function (a, b) { 9141 return -(a[1].length - b[1].length); 9142 }); 9143 9144 $.each(names, function (i, pair) { 9145 var name = pair[1]; 9146 if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) { 9147 index = pair[0]; 9148 iValue += name.length; 9149 return false; 9150 } 9151 }); 9152 if (index !== -1) { 9153 return index + 1; 9154 } else { 9155 throw "Unknown name at position " + iValue; 9156 } 9157 }, 9158 // Confirm that a literal character matches the string value 9159 checkLiteral = function() { 9160 if (value.charAt(iValue) !== format.charAt(iFormat)) { 9161 throw "Unexpected literal at position " + iValue; 9162 } 9163 iValue++; 9164 }; 9165 9166 for (iFormat = 0; iFormat < format.length; iFormat++) { 9167 if (literal) { 9168 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 9169 literal = false; 9170 } else { 9171 checkLiteral(); 9172 } 9173 } else { 9174 switch (format.charAt(iFormat)) { 9175 case "d": 9176 day = getNumber("d"); 9177 break; 9178 case "D": 9179 getName("D", dayNamesShort, dayNames); 9180 break; 9181 case "o": 9182 doy = getNumber("o"); 9183 break; 9184 case "m": 9185 month = getNumber("m"); 9186 break; 9187 case "M": 9188 month = getName("M", monthNamesShort, monthNames); 9189 break; 9190 case "y": 9191 year = getNumber("y"); 9192 break; 9193 case "@": 9194 date = new Date(getNumber("@")); 9195 year = date.getFullYear(); 9196 month = date.getMonth() + 1; 9197 day = date.getDate(); 9198 break; 9199 case "!": 9200 date = new Date((getNumber("!") - this._ticksTo1970) / 10000); 9201 year = date.getFullYear(); 9202 month = date.getMonth() + 1; 9203 day = date.getDate(); 9204 break; 9205 case "'": 9206 if (lookAhead("'")){ 9207 checkLiteral(); 9208 } else { 9209 literal = true; 9210 } 9211 break; 9212 default: 9213 checkLiteral(); 9214 } 9215 } 9216 } 9217 9218 if (iValue < value.length){ 9219 extra = value.substr(iValue); 9220 if (!/^\s+/.test(extra)) { 9221 throw "Extra/unparsed characters found in date: " + extra; 9222 } 9223 } 9224 9225 if (year === -1) { 9226 year = new Date().getFullYear(); 9227 } else if (year < 100) { 9228 year += new Date().getFullYear() - new Date().getFullYear() % 100 + 9229 (year <= shortYearCutoff ? 0 : -100); 9230 } 9231 9232 if (doy > -1) { 9233 month = 1; 9234 day = doy; 9235 do { 9236 dim = this._getDaysInMonth(year, month - 1); 9237 if (day <= dim) { 9238 break; 9239 } 9240 month++; 9241 day -= dim; 9242 } while (true); 9243 } 9244 9245 date = this._daylightSavingAdjust(new Date(year, month - 1, day)); 9246 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) { 9247 throw "Invalid date"; // E.g. 31/02/00 9248 } 9249 return date; 9250 }, 9251 9252 /* Standard date formats. */ 9253 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601) 9254 COOKIE: "D, dd M yy", 9255 ISO_8601: "yy-mm-dd", 9256 RFC_822: "D, d M y", 9257 RFC_850: "DD, dd-M-y", 9258 RFC_1036: "D, d M y", 9259 RFC_1123: "D, d M yy", 9260 RFC_2822: "D, d M yy", 9261 RSS: "D, d M y", // RFC 822 9262 TICKS: "!", 9263 TIMESTAMP: "@", 9264 W3C: "yy-mm-dd", // ISO 8601 9265 9266 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + 9267 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), 9268 9269 /* Format a date object into a string value. 9270 * The format can be combinations of the following: 9271 * d - day of month (no leading zero) 9272 * dd - day of month (two digit) 9273 * o - day of year (no leading zeros) 9274 * oo - day of year (three digit) 9275 * D - day name short 9276 * DD - day name long 9277 * m - month of year (no leading zero) 9278 * mm - month of year (two digit) 9279 * M - month name short 9280 * MM - month name long 9281 * y - year (two digit) 9282 * yy - year (four digit) 9283 * @ - Unix timestamp (ms since 01/01/1970) 9284 * ! - Windows ticks (100ns since 01/01/0001) 9285 * "..." - literal text 9286 * '' - single quote 9287 * 9288 * @param format string - the desired format of the date 9289 * @param date Date - the date value to format 9290 * @param settings Object - attributes include: 9291 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 9292 * dayNames string[7] - names of the days from Sunday (optional) 9293 * monthNamesShort string[12] - abbreviated names of the months (optional) 9294 * monthNames string[12] - names of the months (optional) 9295 * @return string - the date in the above format 9296 */ 9297 formatDate: function (format, date, settings) { 9298 if (!date) { 9299 return ""; 9300 } 9301 9302 var iFormat, 9303 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, 9304 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, 9305 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, 9306 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, 9307 // Check whether a format character is doubled 9308 lookAhead = function(match) { 9309 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 9310 if (matches) { 9311 iFormat++; 9312 } 9313 return matches; 9314 }, 9315 // Format a number, with leading zero if necessary 9316 formatNumber = function(match, value, len) { 9317 var num = "" + value; 9318 if (lookAhead(match)) { 9319 while (num.length < len) { 9320 num = "0" + num; 9321 } 9322 } 9323 return num; 9324 }, 9325 // Format a name, short or long as requested 9326 formatName = function(match, value, shortNames, longNames) { 9327 return (lookAhead(match) ? longNames[value] : shortNames[value]); 9328 }, 9329 output = "", 9330 literal = false; 9331 9332 if (date) { 9333 for (iFormat = 0; iFormat < format.length; iFormat++) { 9334 if (literal) { 9335 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 9336 literal = false; 9337 } else { 9338 output += format.charAt(iFormat); 9339 } 9340 } else { 9341 switch (format.charAt(iFormat)) { 9342 case "d": 9343 output += formatNumber("d", date.getDate(), 2); 9344 break; 9345 case "D": 9346 output += formatName("D", date.getDay(), dayNamesShort, dayNames); 9347 break; 9348 case "o": 9349 output += formatNumber("o", 9350 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); 9351 break; 9352 case "m": 9353 output += formatNumber("m", date.getMonth() + 1, 2); 9354 break; 9355 case "M": 9356 output += formatName("M", date.getMonth(), monthNamesShort, monthNames); 9357 break; 9358 case "y": 9359 output += (lookAhead("y") ? date.getFullYear() : 9360 (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100); 9361 break; 9362 case "@": 9363 output += date.getTime(); 9364 break; 9365 case "!": 9366 output += date.getTime() * 10000 + this._ticksTo1970; 9367 break; 9368 case "'": 9369 if (lookAhead("'")) { 9370 output += "'"; 9371 } else { 9372 literal = true; 9373 } 9374 break; 9375 default: 9376 output += format.charAt(iFormat); 9377 } 9378 } 9379 } 9380 } 9381 return output; 9382 }, 9383 9384 /* Extract all possible characters from the date format. */ 9385 _possibleChars: function (format) { 9386 var iFormat, 9387 chars = "", 9388 literal = false, 9389 // Check whether a format character is doubled 9390 lookAhead = function(match) { 9391 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 9392 if (matches) { 9393 iFormat++; 9394 } 9395 return matches; 9396 }; 9397 9398 for (iFormat = 0; iFormat < format.length; iFormat++) { 9399 if (literal) { 9400 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 9401 literal = false; 9402 } else { 9403 chars += format.charAt(iFormat); 9404 } 9405 } else { 9406 switch (format.charAt(iFormat)) { 9407 case "d": case "m": case "y": case "@": 9408 chars += "0123456789"; 9409 break; 9410 case "D": case "M": 9411 return null; // Accept anything 9412 case "'": 9413 if (lookAhead("'")) { 9414 chars += "'"; 9415 } else { 9416 literal = true; 9417 } 9418 break; 9419 default: 9420 chars += format.charAt(iFormat); 9421 } 9422 } 9423 } 9424 return chars; 9425 }, 9426 9427 /* Get a setting value, defaulting if necessary. */ 9428 _get: function(inst, name) { 9429 return inst.settings[name] !== undefined ? 9430 inst.settings[name] : this._defaults[name]; 9431 }, 9432 9433 /* Parse existing date and initialise date picker. */ 9434 _setDateFromField: function(inst, noDefault) { 9435 if (inst.input.val() === inst.lastVal) { 9436 return; 9437 } 9438 9439 var dateFormat = this._get(inst, "dateFormat"), 9440 dates = inst.lastVal = inst.input ? inst.input.val() : null, 9441 defaultDate = this._getDefaultDate(inst), 9442 date = defaultDate, 9443 settings = this._getFormatConfig(inst); 9444 9445 try { 9446 date = this.parseDate(dateFormat, dates, settings) || defaultDate; 9447 } catch (event) { 9448 dates = (noDefault ? "" : dates); 9449 } 9450 inst.selectedDay = date.getDate(); 9451 inst.drawMonth = inst.selectedMonth = date.getMonth(); 9452 inst.drawYear = inst.selectedYear = date.getFullYear(); 9453 inst.currentDay = (dates ? date.getDate() : 0); 9454 inst.currentMonth = (dates ? date.getMonth() : 0); 9455 inst.currentYear = (dates ? date.getFullYear() : 0); 9456 this._adjustInstDate(inst); 9457 }, 9458 9459 /* Retrieve the default date shown on opening. */ 9460 _getDefaultDate: function(inst) { 9461 return this._restrictMinMax(inst, 9462 this._determineDate(inst, this._get(inst, "defaultDate"), new Date())); 9463 }, 9464 9465 /* A date may be specified as an exact value or a relative one. */ 9466 _determineDate: function(inst, date, defaultDate) { 9467 var offsetNumeric = function(offset) { 9468 var date = new Date(); 9469 date.setDate(date.getDate() + offset); 9470 return date; 9471 }, 9472 offsetString = function(offset) { 9473 try { 9474 return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), 9475 offset, $.datepicker._getFormatConfig(inst)); 9476 } 9477 catch (e) { 9478 // Ignore 9479 } 9480 9481 var date = (offset.toLowerCase().match(/^c/) ? 9482 $.datepicker._getDate(inst) : null) || new Date(), 9483 year = date.getFullYear(), 9484 month = date.getMonth(), 9485 day = date.getDate(), 9486 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, 9487 matches = pattern.exec(offset); 9488 9489 while (matches) { 9490 switch (matches[2] || "d") { 9491 case "d" : case "D" : 9492 day += parseInt(matches[1],10); break; 9493 case "w" : case "W" : 9494 day += parseInt(matches[1],10) * 7; break; 9495 case "m" : case "M" : 9496 month += parseInt(matches[1],10); 9497 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 9498 break; 9499 case "y": case "Y" : 9500 year += parseInt(matches[1],10); 9501 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 9502 break; 9503 } 9504 matches = pattern.exec(offset); 9505 } 9506 return new Date(year, month, day); 9507 }, 9508 newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) : 9509 (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); 9510 9511 newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate); 9512 if (newDate) { 9513 newDate.setHours(0); 9514 newDate.setMinutes(0); 9515 newDate.setSeconds(0); 9516 newDate.setMilliseconds(0); 9517 } 9518 return this._daylightSavingAdjust(newDate); 9519 }, 9520 9521 /* Handle switch to/from daylight saving. 9522 * Hours may be non-zero on daylight saving cut-over: 9523 * > 12 when midnight changeover, but then cannot generate 9524 * midnight datetime, so jump to 1AM, otherwise reset. 9525 * @param date (Date) the date to check 9526 * @return (Date) the corrected date 9527 */ 9528 _daylightSavingAdjust: function(date) { 9529 if (!date) { 9530 return null; 9531 } 9532 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); 9533 return date; 9534 }, 9535 9536 /* Set the date(s) directly. */ 9537 _setDate: function(inst, date, noChange) { 9538 var clear = !date, 9539 origMonth = inst.selectedMonth, 9540 origYear = inst.selectedYear, 9541 newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); 9542 9543 inst.selectedDay = inst.currentDay = newDate.getDate(); 9544 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); 9545 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); 9546 if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) { 9547 this._notifyChange(inst); 9548 } 9549 this._adjustInstDate(inst); 9550 if (inst.input) { 9551 inst.input.val(clear ? "" : this._formatDate(inst)); 9552 } 9553 }, 9554 9555 /* Retrieve the date(s) directly. */ 9556 _getDate: function(inst) { 9557 var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null : 9558 this._daylightSavingAdjust(new Date( 9559 inst.currentYear, inst.currentMonth, inst.currentDay))); 9560 return startDate; 9561 }, 9562 9563 /* Attach the onxxx handlers. These are declared statically so 9564 * they work with static code transformers like Caja. 9565 */ 9566 _attachHandlers: function(inst) { 9567 var stepMonths = this._get(inst, "stepMonths"), 9568 id = "#" + inst.id.replace( /\\\\/g, "\\" ); 9569 inst.dpDiv.find("[data-handler]").map(function () { 9570 var handler = { 9571 prev: function () { 9572 $.datepicker._adjustDate(id, -stepMonths, "M"); 9573 }, 9574 next: function () { 9575 $.datepicker._adjustDate(id, +stepMonths, "M"); 9576 }, 9577 hide: function () { 9578 $.datepicker._hideDatepicker(); 9579 }, 9580 today: function () { 9581 $.datepicker._gotoToday(id); 9582 }, 9583 selectDay: function () { 9584 $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this); 9585 return false; 9586 }, 9587 selectMonth: function () { 9588 $.datepicker._selectMonthYear(id, this, "M"); 9589 return false; 9590 }, 9591 selectYear: function () { 9592 $.datepicker._selectMonthYear(id, this, "Y"); 9593 return false; 9594 } 9595 }; 9596 $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]); 9597 }); 9598 }, 9599 9600 /* Generate the HTML for the current state of the date picker. */ 9601 _generateHTML: function(inst) { 9602 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate, 9603 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin, 9604 monthNames, monthNamesShort, beforeShowDay, showOtherMonths, 9605 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate, 9606 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows, 9607 printDate, dRow, tbody, daySettings, otherMonth, unselectable, 9608 tempDate = new Date(), 9609 today = this._daylightSavingAdjust( 9610 new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time 9611 isRTL = this._get(inst, "isRTL"), 9612 showButtonPanel = this._get(inst, "showButtonPanel"), 9613 hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"), 9614 navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"), 9615 numMonths = this._getNumberOfMonths(inst), 9616 showCurrentAtPos = this._get(inst, "showCurrentAtPos"), 9617 stepMonths = this._get(inst, "stepMonths"), 9618 isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1), 9619 currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : 9620 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))), 9621 minDate = this._getMinMaxDate(inst, "min"), 9622 maxDate = this._getMinMaxDate(inst, "max"), 9623 drawMonth = inst.drawMonth - showCurrentAtPos, 9624 drawYear = inst.drawYear; 9625 9626 if (drawMonth < 0) { 9627 drawMonth += 12; 9628 drawYear--; 9629 } 9630 if (maxDate) { 9631 maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), 9632 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); 9633 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); 9634 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { 9635 drawMonth--; 9636 if (drawMonth < 0) { 9637 drawMonth = 11; 9638 drawYear--; 9639 } 9640 } 9641 } 9642 inst.drawMonth = drawMonth; 9643 inst.drawYear = drawYear; 9644 9645 prevText = this._get(inst, "prevText"); 9646 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, 9647 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), 9648 this._getFormatConfig(inst))); 9649 9650 prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? 9651 "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" + 9652 " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" : 9653 (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>")); 9654 9655 nextText = this._get(inst, "nextText"); 9656 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, 9657 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), 9658 this._getFormatConfig(inst))); 9659 9660 next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? 9661 "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" + 9662 " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" : 9663 (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>")); 9664 9665 currentText = this._get(inst, "currentText"); 9666 gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today); 9667 currentText = (!navigationAsDateFormat ? currentText : 9668 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); 9669 9670 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'>" + 9671 this._get(inst, "closeText") + "</button>" : ""); 9672 9673 buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") + 9674 (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'" + 9675 ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : ""; 9676 9677 firstDay = parseInt(this._get(inst, "firstDay"),10); 9678 firstDay = (isNaN(firstDay) ? 0 : firstDay); 9679 9680 showWeek = this._get(inst, "showWeek"); 9681 dayNames = this._get(inst, "dayNames"); 9682 dayNamesMin = this._get(inst, "dayNamesMin"); 9683 monthNames = this._get(inst, "monthNames"); 9684 monthNamesShort = this._get(inst, "monthNamesShort"); 9685 beforeShowDay = this._get(inst, "beforeShowDay"); 9686 showOtherMonths = this._get(inst, "showOtherMonths"); 9687 selectOtherMonths = this._get(inst, "selectOtherMonths"); 9688 defaultDate = this._getDefaultDate(inst); 9689 html = ""; 9690 dow; 9691 for (row = 0; row < numMonths[0]; row++) { 9692 group = ""; 9693 this.maxRows = 4; 9694 for (col = 0; col < numMonths[1]; col++) { 9695 selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); 9696 cornerClass = " ui-corner-all"; 9697 calender = ""; 9698 if (isMultiMonth) { 9699 calender += "<div class='ui-datepicker-group"; 9700 if (numMonths[1] > 1) { 9701 switch (col) { 9702 case 0: calender += " ui-datepicker-group-first"; 9703 cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break; 9704 case numMonths[1]-1: calender += " ui-datepicker-group-last"; 9705 cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break; 9706 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break; 9707 } 9708 } 9709 calender += "'>"; 9710 } 9711 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" + 9712 (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") + 9713 (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") + 9714 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, 9715 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers 9716 "</div><table class='ui-datepicker-calendar'><thead>" + 9717 "<tr>"; 9718 thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : ""); 9719 for (dow = 0; dow < 7; dow++) { // days of the week 9720 day = (dow + firstDay) % 7; 9721 thead += "<th scope='col'" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" + 9722 "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>"; 9723 } 9724 calender += thead + "</tr></thead><tbody>"; 9725 daysInMonth = this._getDaysInMonth(drawYear, drawMonth); 9726 if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) { 9727 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); 9728 } 9729 leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; 9730 curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate 9731 numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) 9732 this.maxRows = numRows; 9733 printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); 9734 for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows 9735 calender += "<tr>"; 9736 tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" + 9737 this._get(inst, "calculateWeek")(printDate) + "</td>"); 9738 for (dow = 0; dow < 7; dow++) { // create date picker days 9739 daySettings = (beforeShowDay ? 9740 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]); 9741 otherMonth = (printDate.getMonth() !== drawMonth); 9742 unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || 9743 (minDate && printDate < minDate) || (maxDate && printDate > maxDate); 9744 tbody += "<td class='" + 9745 ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends 9746 (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months 9747 ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key 9748 (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ? 9749 // or defaultDate is current printedDate and defaultDate is selectedDate 9750 " " + this._dayOverClass : "") + // highlight selected day 9751 (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days 9752 (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates 9753 (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day 9754 (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different) 9755 ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "'") + "'" : "") + // cell title 9756 (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions 9757 (otherMonth && !showOtherMonths ? " " : // display for other months 9758 (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" + 9759 (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") + 9760 (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day 9761 (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months 9762 "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date 9763 printDate.setDate(printDate.getDate() + 1); 9764 printDate = this._daylightSavingAdjust(printDate); 9765 } 9766 calender += tbody + "</tr>"; 9767 } 9768 drawMonth++; 9769 if (drawMonth > 11) { 9770 drawMonth = 0; 9771 drawYear++; 9772 } 9773 calender += "</tbody></table>" + (isMultiMonth ? "</div>" + 9774 ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : ""); 9775 group += calender; 9776 } 9777 html += group; 9778 } 9779 html += buttonPanel; 9780 inst._keyEvent = false; 9781 return html; 9782 }, 9783 9784 /* Generate the month and year header. */ 9785 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, 9786 secondary, monthNames, monthNamesShort) { 9787 9788 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear, 9789 changeMonth = this._get(inst, "changeMonth"), 9790 changeYear = this._get(inst, "changeYear"), 9791 showMonthAfterYear = this._get(inst, "showMonthAfterYear"), 9792 html = "<div class='ui-datepicker-title'>", 9793 monthHtml = ""; 9794 9795 // month selection 9796 if (secondary || !changeMonth) { 9797 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>"; 9798 } else { 9799 inMinYear = (minDate && minDate.getFullYear() === drawYear); 9800 inMaxYear = (maxDate && maxDate.getFullYear() === drawYear); 9801 monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>"; 9802 for ( month = 0; month < 12; month++) { 9803 if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) { 9804 monthHtml += "<option value='" + month + "'" + 9805 (month === drawMonth ? " selected='selected'" : "") + 9806 ">" + monthNamesShort[month] + "</option>"; 9807 } 9808 } 9809 monthHtml += "</select>"; 9810 } 9811 9812 if (!showMonthAfterYear) { 9813 html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : ""); 9814 } 9815 9816 // year selection 9817 if ( !inst.yearshtml ) { 9818 inst.yearshtml = ""; 9819 if (secondary || !changeYear) { 9820 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>"; 9821 } else { 9822 // determine range of years to display 9823 years = this._get(inst, "yearRange").split(":"); 9824 thisYear = new Date().getFullYear(); 9825 determineYear = function(value) { 9826 var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) : 9827 (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) : 9828 parseInt(value, 10))); 9829 return (isNaN(year) ? thisYear : year); 9830 }; 9831 year = determineYear(years[0]); 9832 endYear = Math.max(year, determineYear(years[1] || "")); 9833 year = (minDate ? Math.max(year, minDate.getFullYear()) : year); 9834 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); 9835 inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>"; 9836 for (; year <= endYear; year++) { 9837 inst.yearshtml += "<option value='" + year + "'" + 9838 (year === drawYear ? " selected='selected'" : "") + 9839 ">" + year + "</option>"; 9840 } 9841 inst.yearshtml += "</select>"; 9842 9843 html += inst.yearshtml; 9844 inst.yearshtml = null; 9845 } 9846 } 9847 9848 html += this._get(inst, "yearSuffix"); 9849 if (showMonthAfterYear) { 9850 html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml; 9851 } 9852 html += "</div>"; // Close datepicker_header 9853 return html; 9854 }, 9855 9856 /* Adjust one of the date sub-fields. */ 9857 _adjustInstDate: function(inst, offset, period) { 9858 var year = inst.drawYear + (period === "Y" ? offset : 0), 9859 month = inst.drawMonth + (period === "M" ? offset : 0), 9860 day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0), 9861 date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day))); 9862 9863 inst.selectedDay = date.getDate(); 9864 inst.drawMonth = inst.selectedMonth = date.getMonth(); 9865 inst.drawYear = inst.selectedYear = date.getFullYear(); 9866 if (period === "M" || period === "Y") { 9867 this._notifyChange(inst); 9868 } 9869 }, 9870 9871 /* Ensure a date is within any min/max bounds. */ 9872 _restrictMinMax: function(inst, date) { 9873 var minDate = this._getMinMaxDate(inst, "min"), 9874 maxDate = this._getMinMaxDate(inst, "max"), 9875 newDate = (minDate && date < minDate ? minDate : date); 9876 return (maxDate && newDate > maxDate ? maxDate : newDate); 9877 }, 9878 9879 /* Notify change of month/year. */ 9880 _notifyChange: function(inst) { 9881 var onChange = this._get(inst, "onChangeMonthYear"); 9882 if (onChange) { 9883 onChange.apply((inst.input ? inst.input[0] : null), 9884 [inst.selectedYear, inst.selectedMonth + 1, inst]); 9885 } 9886 }, 9887 9888 /* Determine the number of months to show. */ 9889 _getNumberOfMonths: function(inst) { 9890 var numMonths = this._get(inst, "numberOfMonths"); 9891 return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths)); 9892 }, 9893 9894 /* Determine the current maximum date - ensure no time components are set. */ 9895 _getMinMaxDate: function(inst, minMax) { 9896 return this._determineDate(inst, this._get(inst, minMax + "Date"), null); 9897 }, 9898 9899 /* Find the number of days in a given month. */ 9900 _getDaysInMonth: function(year, month) { 9901 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); 9902 }, 9903 9904 /* Find the day of the week of the first of a month. */ 9905 _getFirstDayOfMonth: function(year, month) { 9906 return new Date(year, month, 1).getDay(); 9907 }, 9908 9909 /* Determines if we should allow a "next/prev" month display change. */ 9910 _canAdjustMonth: function(inst, offset, curYear, curMonth) { 9911 var numMonths = this._getNumberOfMonths(inst), 9912 date = this._daylightSavingAdjust(new Date(curYear, 9913 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); 9914 9915 if (offset < 0) { 9916 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); 9917 } 9918 return this._isInRange(inst, date); 9919 }, 9920 9921 /* Is the given date in the accepted range? */ 9922 _isInRange: function(inst, date) { 9923 var yearSplit, currentYear, 9924 minDate = this._getMinMaxDate(inst, "min"), 9925 maxDate = this._getMinMaxDate(inst, "max"), 9926 minYear = null, 9927 maxYear = null, 9928 years = this._get(inst, "yearRange"); 9929 if (years){ 9930 yearSplit = years.split(":"); 9931 currentYear = new Date().getFullYear(); 9932 minYear = parseInt(yearSplit[0], 10); 9933 maxYear = parseInt(yearSplit[1], 10); 9934 if ( yearSplit[0].match(/[+\-].*/) ) { 9935 minYear += currentYear; 9936 } 9937 if ( yearSplit[1].match(/[+\-].*/) ) { 9938 maxYear += currentYear; 9939 } 9940 } 9941 9942 return ((!minDate || date.getTime() >= minDate.getTime()) && 9943 (!maxDate || date.getTime() <= maxDate.getTime()) && 9944 (!minYear || date.getFullYear() >= minYear) && 9945 (!maxYear || date.getFullYear() <= maxYear)); 9946 }, 9947 9948 /* Provide the configuration settings for formatting/parsing. */ 9949 _getFormatConfig: function(inst) { 9950 var shortYearCutoff = this._get(inst, "shortYearCutoff"); 9951 shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff : 9952 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); 9953 return {shortYearCutoff: shortYearCutoff, 9954 dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"), 9955 monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")}; 9956 }, 9957 9958 /* Format the given date for display. */ 9959 _formatDate: function(inst, day, month, year) { 9960 if (!day) { 9961 inst.currentDay = inst.selectedDay; 9962 inst.currentMonth = inst.selectedMonth; 9963 inst.currentYear = inst.selectedYear; 9964 } 9965 var date = (day ? (typeof day === "object" ? day : 9966 this._daylightSavingAdjust(new Date(year, month, day))) : 9967 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); 9968 return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst)); 9969 } 9970 }); 9971 9972 /* 9973 * Bind hover events for datepicker elements. 9974 * Done via delegate so the binding only occurs once in the lifetime of the parent div. 9975 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. 9976 */ 9977 function datepicker_bindHover(dpDiv) { 9978 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a"; 9979 return dpDiv.delegate(selector, "mouseout", function() { 9980 $(this).removeClass("ui-state-hover"); 9981 if (this.className.indexOf("ui-datepicker-prev") !== -1) { 9982 $(this).removeClass("ui-datepicker-prev-hover"); 9983 } 9984 if (this.className.indexOf("ui-datepicker-next") !== -1) { 9985 $(this).removeClass("ui-datepicker-next-hover"); 9986 } 9987 }) 9988 .delegate( selector, "mouseover", datepicker_handleMouseover ); 9989 } 9990 9991 function datepicker_handleMouseover() { 9992 if (!$.datepicker._isDisabledDatepicker( datepicker_instActive.inline? datepicker_instActive.dpDiv.parent()[0] : datepicker_instActive.input[0])) { 9993 $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); 9994 $(this).addClass("ui-state-hover"); 9995 if (this.className.indexOf("ui-datepicker-prev") !== -1) { 9996 $(this).addClass("ui-datepicker-prev-hover"); 9997 } 9998 if (this.className.indexOf("ui-datepicker-next") !== -1) { 9999 $(this).addClass("ui-datepicker-next-hover"); 10000 } 10001 } 10002 } 10003 10004 /* jQuery extend now ignores nulls! */ 10005 function datepicker_extendRemove(target, props) { 10006 $.extend(target, props); 10007 for (var name in props) { 10008 if (props[name] == null) { 10009 target[name] = props[name]; 10010 } 10011 } 10012 return target; 10013 } 10014 10015 /* Invoke the datepicker functionality. 10016 @param options string - a command, optionally followed by additional parameters or 10017 Object - settings for attaching new datepicker functionality 10018 @return jQuery object */ 10019 $.fn.datepicker = function(options){ 10020 10021 /* Verify an empty collection wasn't passed - Fixes #6976 */ 10022 if ( !this.length ) { 10023 return this; 10024 } 10025 10026 /* Initialise the date picker. */ 10027 if (!$.datepicker.initialized) { 10028 $(document).mousedown($.datepicker._checkExternalClick); 10029 $.datepicker.initialized = true; 10030 } 10031 10032 /* Append datepicker main container to body if not exist. */ 10033 if ($("#"+$.datepicker._mainDivId).length === 0) { 10034 $("body").append($.datepicker.dpDiv); 10035 } 10036 10037 var otherArgs = Array.prototype.slice.call(arguments, 1); 10038 if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) { 10039 return $.datepicker["_" + options + "Datepicker"]. 10040 apply($.datepicker, [this[0]].concat(otherArgs)); 10041 } 10042 if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") { 10043 return $.datepicker["_" + options + "Datepicker"]. 10044 apply($.datepicker, [this[0]].concat(otherArgs)); 10045 } 10046 return this.each(function() { 10047 typeof options === "string" ? 10048 $.datepicker["_" + options + "Datepicker"]. 10049 apply($.datepicker, [this].concat(otherArgs)) : 10050 $.datepicker._attachDatepicker(this, options); 10051 }); 10052 }; 10053 10054 $.datepicker = new Datepicker(); // singleton instance 10055 $.datepicker.initialized = false; 10056 $.datepicker.uuid = new Date().getTime(); 10057 $.datepicker.version = "1.11.4"; 10058 10059 var datepicker = $.datepicker; 10060 10061 10062 /*! 10063 * jQuery UI Dialog 1.11.4 10064 * http://jqueryui.com 10065 * 10066 * Copyright jQuery Foundation and other contributors 10067 * Released under the MIT license. 10068 * http://jquery.org/license 10069 * 10070 * http://api.jqueryui.com/dialog/ 10071 */ 10072 10073 10074 var dialog = $.widget( "ui.dialog", { 10075 version: "1.11.4", 10076 options: { 10077 appendTo: "body", 10078 autoOpen: true, 10079 buttons: [], 10080 closeOnEscape: true, 10081 closeText: "Close", 10082 dialogClass: "", 10083 draggable: true, 10084 hide: null, 10085 height: "auto", 10086 maxHeight: null, 10087 maxWidth: null, 10088 minHeight: 150, 10089 minWidth: 150, 10090 modal: false, 10091 position: { 10092 my: "center", 10093 at: "center", 10094 of: window, 10095 collision: "fit", 10096 // Ensure the titlebar is always visible 10097 using: function( pos ) { 10098 var topOffset = $( this ).css( pos ).offset().top; 10099 if ( topOffset < 0 ) { 10100 $( this ).css( "top", pos.top - topOffset ); 10101 } 10102 } 10103 }, 10104 resizable: true, 10105 show: null, 10106 title: null, 10107 width: 300, 10108 10109 // callbacks 10110 beforeClose: null, 10111 close: null, 10112 drag: null, 10113 dragStart: null, 10114 dragStop: null, 10115 focus: null, 10116 open: null, 10117 resize: null, 10118 resizeStart: null, 10119 resizeStop: null 10120 }, 10121 10122 sizeRelatedOptions: { 10123 buttons: true, 10124 height: true, 10125 maxHeight: true, 10126 maxWidth: true, 10127 minHeight: true, 10128 minWidth: true, 10129 width: true 10130 }, 10131 10132 resizableRelatedOptions: { 10133 maxHeight: true, 10134 maxWidth: true, 10135 minHeight: true, 10136 minWidth: true 10137 }, 10138 10139 _create: function() { 10140 this.originalCss = { 10141 display: this.element[ 0 ].style.display, 10142 width: this.element[ 0 ].style.width, 10143 minHeight: this.element[ 0 ].style.minHeight, 10144 maxHeight: this.element[ 0 ].style.maxHeight, 10145 height: this.element[ 0 ].style.height 10146 }; 10147 this.originalPosition = { 10148 parent: this.element.parent(), 10149 index: this.element.parent().children().index( this.element ) 10150 }; 10151 this.originalTitle = this.element.attr( "title" ); 10152 this.options.title = this.options.title || this.originalTitle; 10153 10154 this._createWrapper(); 10155 10156 this.element 10157 .show() 10158 .removeAttr( "title" ) 10159 .addClass( "ui-dialog-content ui-widget-content" ) 10160 .appendTo( this.uiDialog ); 10161 10162 this._createTitlebar(); 10163 this._createButtonPane(); 10164 10165 if ( this.options.draggable && $.fn.draggable ) { 10166 this._makeDraggable(); 10167 } 10168 if ( this.options.resizable && $.fn.resizable ) { 10169 this._makeResizable(); 10170 } 10171 10172 this._isOpen = false; 10173 10174 this._trackFocus(); 10175 }, 10176 10177 _init: function() { 10178 if ( this.options.autoOpen ) { 10179 this.open(); 10180 } 10181 }, 10182 10183 _appendTo: function() { 10184 var element = this.options.appendTo; 10185 if ( element && (element.jquery || element.nodeType) ) { 10186 return $( element ); 10187 } 10188 return this.document.find( element || "body" ).eq( 0 ); 10189 }, 10190 10191 _destroy: function() { 10192 var next, 10193 originalPosition = this.originalPosition; 10194 10195 this._untrackInstance(); 10196 this._destroyOverlay(); 10197 10198 this.element 10199 .removeUniqueId() 10200 .removeClass( "ui-dialog-content ui-widget-content" ) 10201 .css( this.originalCss ) 10202 // Without detaching first, the following becomes really slow 10203 .detach(); 10204 10205 this.uiDialog.stop( true, true ).remove(); 10206 10207 if ( this.originalTitle ) { 10208 this.element.attr( "title", this.originalTitle ); 10209 } 10210 10211 next = originalPosition.parent.children().eq( originalPosition.index ); 10212 // Don't try to place the dialog next to itself (#8613) 10213 if ( next.length && next[ 0 ] !== this.element[ 0 ] ) { 10214 next.before( this.element ); 10215 } else { 10216 originalPosition.parent.append( this.element ); 10217 } 10218 }, 10219 10220 widget: function() { 10221 return this.uiDialog; 10222 }, 10223 10224 disable: $.noop, 10225 enable: $.noop, 10226 10227 close: function( event ) { 10228 var activeElement, 10229 that = this; 10230 10231 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) { 10232 return; 10233 } 10234 10235 this._isOpen = false; 10236 this._focusedElement = null; 10237 this._destroyOverlay(); 10238 this._untrackInstance(); 10239 10240 if ( !this.opener.filter( ":focusable" ).focus().length ) { 10241 10242 // support: IE9 10243 // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe> 10244 try { 10245 activeElement = this.document[ 0 ].activeElement; 10246 10247 // Support: IE9, IE10 10248 // If the <body> is blurred, IE will switch windows, see #4520 10249 if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) { 10250 10251 // Hiding a focused element doesn't trigger blur in WebKit 10252 // so in case we have nothing to focus on, explicitly blur the active element 10253 // https://bugs.webkit.org/show_bug.cgi?id=47182 10254 $( activeElement ).blur(); 10255 } 10256 } catch ( error ) {} 10257 } 10258 10259 this._hide( this.uiDialog, this.options.hide, function() { 10260 that._trigger( "close", event ); 10261 }); 10262 }, 10263 10264 isOpen: function() { 10265 return this._isOpen; 10266 }, 10267 10268 moveToTop: function() { 10269 this._moveToTop(); 10270 }, 10271 10272 _moveToTop: function( event, silent ) { 10273 var moved = false, 10274 zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map(function() { 10275 return +$( this ).css( "z-index" ); 10276 }).get(), 10277 zIndexMax = Math.max.apply( null, zIndices ); 10278 10279 if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) { 10280 this.uiDialog.css( "z-index", zIndexMax + 1 ); 10281 moved = true; 10282 } 10283 10284 if ( moved && !silent ) { 10285 this._trigger( "focus", event ); 10286 } 10287 return moved; 10288 }, 10289 10290 open: function() { 10291 var that = this; 10292 if ( this._isOpen ) { 10293 if ( this._moveToTop() ) { 10294 this._focusTabbable(); 10295 } 10296 return; 10297 } 10298 10299 this._isOpen = true; 10300 this.opener = $( this.document[ 0 ].activeElement ); 10301 10302 this._size(); 10303 this._position(); 10304 this._createOverlay(); 10305 this._moveToTop( null, true ); 10306 10307 // Ensure the overlay is moved to the top with the dialog, but only when 10308 // opening. The overlay shouldn't move after the dialog is open so that 10309 // modeless dialogs opened after the modal dialog stack properly. 10310 if ( this.overlay ) { 10311 this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 ); 10312 } 10313 10314 this._show( this.uiDialog, this.options.show, function() { 10315 that._focusTabbable(); 10316 that._trigger( "focus" ); 10317 }); 10318 10319 // Track the dialog immediately upon openening in case a focus event 10320 // somehow occurs outside of the dialog before an element inside the 10321 // dialog is focused (#10152) 10322 this._makeFocusTarget(); 10323 10324 this._trigger( "open" ); 10325 }, 10326 10327 _focusTabbable: function() { 10328 // Set focus to the first match: 10329 // 1. An element that was focused previously 10330 // 2. First element inside the dialog matching [autofocus] 10331 // 3. Tabbable element inside the content element 10332 // 4. Tabbable element inside the buttonpane 10333 // 5. The close button 10334 // 6. The dialog itself 10335 var hasFocus = this._focusedElement; 10336 if ( !hasFocus ) { 10337 hasFocus = this.element.find( "[autofocus]" ); 10338 } 10339 if ( !hasFocus.length ) { 10340 hasFocus = this.element.find( ":tabbable" ); 10341 } 10342 if ( !hasFocus.length ) { 10343 hasFocus = this.uiDialogButtonPane.find( ":tabbable" ); 10344 } 10345 if ( !hasFocus.length ) { 10346 hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" ); 10347 } 10348 if ( !hasFocus.length ) { 10349 hasFocus = this.uiDialog; 10350 } 10351 hasFocus.eq( 0 ).focus(); 10352 }, 10353 10354 _keepFocus: function( event ) { 10355 function checkFocus() { 10356 var activeElement = this.document[0].activeElement, 10357 isActive = this.uiDialog[0] === activeElement || 10358 $.contains( this.uiDialog[0], activeElement ); 10359 if ( !isActive ) { 10360 this._focusTabbable(); 10361 } 10362 } 10363 event.preventDefault(); 10364 checkFocus.call( this ); 10365 // support: IE 10366 // IE <= 8 doesn't prevent moving focus even with event.preventDefault() 10367 // so we check again later 10368 this._delay( checkFocus ); 10369 }, 10370 10371 _createWrapper: function() { 10372 this.uiDialog = $("<div>") 10373 .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " + 10374 this.options.dialogClass ) 10375 .hide() 10376 .attr({ 10377 // Setting tabIndex makes the div focusable 10378 tabIndex: -1, 10379 role: "dialog" 10380 }) 10381 .appendTo( this._appendTo() ); 10382 10383 this._on( this.uiDialog, { 10384 keydown: function( event ) { 10385 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && 10386 event.keyCode === $.ui.keyCode.ESCAPE ) { 10387 event.preventDefault(); 10388 this.close( event ); 10389 return; 10390 } 10391 10392 // prevent tabbing out of dialogs 10393 if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) { 10394 return; 10395 } 10396 var tabbables = this.uiDialog.find( ":tabbable" ), 10397 first = tabbables.filter( ":first" ), 10398 last = tabbables.filter( ":last" ); 10399 10400 if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) { 10401 this._delay(function() { 10402 first.focus(); 10403 }); 10404 event.preventDefault(); 10405 } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) { 10406 this._delay(function() { 10407 last.focus(); 10408 }); 10409 event.preventDefault(); 10410 } 10411 }, 10412 mousedown: function( event ) { 10413 if ( this._moveToTop( event ) ) { 10414 this._focusTabbable(); 10415 } 10416 } 10417 }); 10418 10419 // We assume that any existing aria-describedby attribute means 10420 // that the dialog content is marked up properly 10421 // otherwise we brute force the content as the description 10422 if ( !this.element.find( "[aria-describedby]" ).length ) { 10423 this.uiDialog.attr({ 10424 "aria-describedby": this.element.uniqueId().attr( "id" ) 10425 }); 10426 } 10427 }, 10428 10429 _createTitlebar: function() { 10430 var uiDialogTitle; 10431 10432 this.uiDialogTitlebar = $( "<div>" ) 10433 .addClass( "ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix" ) 10434 .prependTo( this.uiDialog ); 10435 this._on( this.uiDialogTitlebar, { 10436 mousedown: function( event ) { 10437 // Don't prevent click on close button (#8838) 10438 // Focusing a dialog that is partially scrolled out of view 10439 // causes the browser to scroll it into view, preventing the click event 10440 if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) { 10441 // Dialog isn't getting focus when dragging (#8063) 10442 this.uiDialog.focus(); 10443 } 10444 } 10445 }); 10446 10447 // support: IE 10448 // Use type="button" to prevent enter keypresses in textboxes from closing the 10449 // dialog in IE (#9312) 10450 this.uiDialogTitlebarClose = $( "<button type='button'></button>" ) 10451 .button({ 10452 label: this.options.closeText, 10453 icons: { 10454 primary: "ui-icon-closethick" 10455 }, 10456 text: false 10457 }) 10458 .addClass( "ui-dialog-titlebar-close" ) 10459 .appendTo( this.uiDialogTitlebar ); 10460 this._on( this.uiDialogTitlebarClose, { 10461 click: function( event ) { 10462 event.preventDefault(); 10463 this.close( event ); 10464 } 10465 }); 10466 10467 uiDialogTitle = $( "<span>" ) 10468 .uniqueId() 10469 .addClass( "ui-dialog-title" ) 10470 .prependTo( this.uiDialogTitlebar ); 10471 this._title( uiDialogTitle ); 10472 10473 this.uiDialog.attr({ 10474 "aria-labelledby": uiDialogTitle.attr( "id" ) 10475 }); 10476 }, 10477 10478 _title: function( title ) { 10479 if ( !this.options.title ) { 10480 title.html( " " ); 10481 } 10482 title.text( this.options.title ); 10483 }, 10484 10485 _createButtonPane: function() { 10486 this.uiDialogButtonPane = $( "<div>" ) 10487 .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" ); 10488 10489 this.uiButtonSet = $( "<div>" ) 10490 .addClass( "ui-dialog-buttonset" ) 10491 .appendTo( this.uiDialogButtonPane ); 10492 10493 this._createButtons(); 10494 }, 10495 10496 _createButtons: function() { 10497 var that = this, 10498 buttons = this.options.buttons; 10499 10500 // if we already have a button pane, remove it 10501 this.uiDialogButtonPane.remove(); 10502 this.uiButtonSet.empty(); 10503 10504 if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) { 10505 this.uiDialog.removeClass( "ui-dialog-buttons" ); 10506 return; 10507 } 10508 10509 $.each( buttons, function( name, props ) { 10510 var click, buttonOptions; 10511 props = $.isFunction( props ) ? 10512 { click: props, text: name } : 10513 props; 10514 // Default to a non-submitting button 10515 props = $.extend( { type: "button" }, props ); 10516 // Change the context for the click callback to be the main element 10517 click = props.click; 10518 props.click = function() { 10519 click.apply( that.element[ 0 ], arguments ); 10520 }; 10521 buttonOptions = { 10522 icons: props.icons, 10523 text: props.showText 10524 }; 10525 delete props.icons; 10526 delete props.showText; 10527 $( "<button></button>", props ) 10528 .button( buttonOptions ) 10529 .appendTo( that.uiButtonSet ); 10530 }); 10531 this.uiDialog.addClass( "ui-dialog-buttons" ); 10532 this.uiDialogButtonPane.appendTo( this.uiDialog ); 10533 }, 10534 10535 _makeDraggable: function() { 10536 var that = this, 10537 options = this.options; 10538 10539 function filteredUi( ui ) { 10540 return { 10541 position: ui.position, 10542 offset: ui.offset 10543 }; 10544 } 10545 10546 this.uiDialog.draggable({ 10547 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", 10548 handle: ".ui-dialog-titlebar", 10549 containment: "document", 10550 start: function( event, ui ) { 10551 $( this ).addClass( "ui-dialog-dragging" ); 10552 that._blockFrames(); 10553 that._trigger( "dragStart", event, filteredUi( ui ) ); 10554 }, 10555 drag: function( event, ui ) { 10556 that._trigger( "drag", event, filteredUi( ui ) ); 10557 }, 10558 stop: function( event, ui ) { 10559 var left = ui.offset.left - that.document.scrollLeft(), 10560 top = ui.offset.top - that.document.scrollTop(); 10561 10562 options.position = { 10563 my: "left top", 10564 at: "left" + (left >= 0 ? "+" : "") + left + " " + 10565 "top" + (top >= 0 ? "+" : "") + top, 10566 of: that.window 10567 }; 10568 $( this ).removeClass( "ui-dialog-dragging" ); 10569 that._unblockFrames(); 10570 that._trigger( "dragStop", event, filteredUi( ui ) ); 10571 } 10572 }); 10573 }, 10574 10575 _makeResizable: function() { 10576 var that = this, 10577 options = this.options, 10578 handles = options.resizable, 10579 // .ui-resizable has position: relative defined in the stylesheet 10580 // but dialogs have to use absolute or fixed positioning 10581 position = this.uiDialog.css("position"), 10582 resizeHandles = typeof handles === "string" ? 10583 handles : 10584 "n,e,s,w,se,sw,ne,nw"; 10585 10586 function filteredUi( ui ) { 10587 return { 10588 originalPosition: ui.originalPosition, 10589 originalSize: ui.originalSize, 10590 position: ui.position, 10591 size: ui.size 10592 }; 10593 } 10594 10595 this.uiDialog.resizable({ 10596 cancel: ".ui-dialog-content", 10597 containment: "document", 10598 alsoResize: this.element, 10599 maxWidth: options.maxWidth, 10600 maxHeight: options.maxHeight, 10601 minWidth: options.minWidth, 10602 minHeight: this._minHeight(), 10603 handles: resizeHandles, 10604 start: function( event, ui ) { 10605 $( this ).addClass( "ui-dialog-resizing" ); 10606 that._blockFrames(); 10607 that._trigger( "resizeStart", event, filteredUi( ui ) ); 10608 }, 10609 resize: function( event, ui ) { 10610 that._trigger( "resize", event, filteredUi( ui ) ); 10611 }, 10612 stop: function( event, ui ) { 10613 var offset = that.uiDialog.offset(), 10614 left = offset.left - that.document.scrollLeft(), 10615 top = offset.top - that.document.scrollTop(); 10616 10617 options.height = that.uiDialog.height(); 10618 options.width = that.uiDialog.width(); 10619 options.position = { 10620 my: "left top", 10621 at: "left" + (left >= 0 ? "+" : "") + left + " " + 10622 "top" + (top >= 0 ? "+" : "") + top, 10623 of: that.window 10624 }; 10625 $( this ).removeClass( "ui-dialog-resizing" ); 10626 that._unblockFrames(); 10627 that._trigger( "resizeStop", event, filteredUi( ui ) ); 10628 } 10629 }) 10630 .css( "position", position ); 10631 }, 10632 10633 _trackFocus: function() { 10634 this._on( this.widget(), { 10635 focusin: function( event ) { 10636 this._makeFocusTarget(); 10637 this._focusedElement = $( event.target ); 10638 } 10639 }); 10640 }, 10641 10642 _makeFocusTarget: function() { 10643 this._untrackInstance(); 10644 this._trackingInstances().unshift( this ); 10645 }, 10646 10647 _untrackInstance: function() { 10648 var instances = this._trackingInstances(), 10649 exists = $.inArray( this, instances ); 10650 if ( exists !== -1 ) { 10651 instances.splice( exists, 1 ); 10652 } 10653 }, 10654 10655 _trackingInstances: function() { 10656 var instances = this.document.data( "ui-dialog-instances" ); 10657 if ( !instances ) { 10658 instances = []; 10659 this.document.data( "ui-dialog-instances", instances ); 10660 } 10661 return instances; 10662 }, 10663 10664 _minHeight: function() { 10665 var options = this.options; 10666 10667 return options.height === "auto" ? 10668 options.minHeight : 10669 Math.min( options.minHeight, options.height ); 10670 }, 10671 10672 _position: function() { 10673 // Need to show the dialog to get the actual offset in the position plugin 10674 var isVisible = this.uiDialog.is( ":visible" ); 10675 if ( !isVisible ) { 10676 this.uiDialog.show(); 10677 } 10678 this.uiDialog.position( this.options.position ); 10679 if ( !isVisible ) { 10680 this.uiDialog.hide(); 10681 } 10682 }, 10683 10684 _setOptions: function( options ) { 10685 var that = this, 10686 resize = false, 10687 resizableOptions = {}; 10688 10689 $.each( options, function( key, value ) { 10690 that._setOption( key, value ); 10691 10692 if ( key in that.sizeRelatedOptions ) { 10693 resize = true; 10694 } 10695 if ( key in that.resizableRelatedOptions ) { 10696 resizableOptions[ key ] = value; 10697 } 10698 }); 10699 10700 if ( resize ) { 10701 this._size(); 10702 this._position(); 10703 } 10704 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) { 10705 this.uiDialog.resizable( "option", resizableOptions ); 10706 } 10707 }, 10708 10709 _setOption: function( key, value ) { 10710 var isDraggable, isResizable, 10711 uiDialog = this.uiDialog; 10712 10713 if ( key === "dialogClass" ) { 10714 uiDialog 10715 .removeClass( this.options.dialogClass ) 10716 .addClass( value ); 10717 } 10718 10719 if ( key === "disabled" ) { 10720 return; 10721 } 10722 10723 this._super( key, value ); 10724 10725 if ( key === "appendTo" ) { 10726 this.uiDialog.appendTo( this._appendTo() ); 10727 } 10728 10729 if ( key === "buttons" ) { 10730 this._createButtons(); 10731 } 10732 10733 if ( key === "closeText" ) { 10734 this.uiDialogTitlebarClose.button({ 10735 // Ensure that we always pass a string 10736 label: "" + value 10737 }); 10738 } 10739 10740 if ( key === "draggable" ) { 10741 isDraggable = uiDialog.is( ":data(ui-draggable)" ); 10742 if ( isDraggable && !value ) { 10743 uiDialog.draggable( "destroy" ); 10744 } 10745 10746 if ( !isDraggable && value ) { 10747 this._makeDraggable(); 10748 } 10749 } 10750 10751 if ( key === "position" ) { 10752 this._position(); 10753 } 10754 10755 if ( key === "resizable" ) { 10756 // currently resizable, becoming non-resizable 10757 isResizable = uiDialog.is( ":data(ui-resizable)" ); 10758 if ( isResizable && !value ) { 10759 uiDialog.resizable( "destroy" ); 10760 } 10761 10762 // currently resizable, changing handles 10763 if ( isResizable && typeof value === "string" ) { 10764 uiDialog.resizable( "option", "handles", value ); 10765 } 10766 10767 // currently non-resizable, becoming resizable 10768 if ( !isResizable && value !== false ) { 10769 this._makeResizable(); 10770 } 10771 } 10772 10773 if ( key === "title" ) { 10774 this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) ); 10775 } 10776 }, 10777 10778 _size: function() { 10779 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content 10780 // divs will both have width and height set, so we need to reset them 10781 var nonContentHeight, minContentHeight, maxContentHeight, 10782 options = this.options; 10783 10784 // Reset content sizing 10785 this.element.show().css({ 10786 width: "auto", 10787 minHeight: 0, 10788 maxHeight: "none", 10789 height: 0 10790 }); 10791 10792 if ( options.minWidth > options.width ) { 10793 options.width = options.minWidth; 10794 } 10795 10796 // reset wrapper sizing 10797 // determine the height of all the non-content elements 10798 nonContentHeight = this.uiDialog.css({ 10799 height: "auto", 10800 width: options.width 10801 }) 10802 .outerHeight(); 10803 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); 10804 maxContentHeight = typeof options.maxHeight === "number" ? 10805 Math.max( 0, options.maxHeight - nonContentHeight ) : 10806 "none"; 10807 10808 if ( options.height === "auto" ) { 10809 this.element.css({ 10810 minHeight: minContentHeight, 10811 maxHeight: maxContentHeight, 10812 height: "auto" 10813 }); 10814 } else { 10815 this.element.height( Math.max( 0, options.height - nonContentHeight ) ); 10816 } 10817 10818 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) { 10819 this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); 10820 } 10821 }, 10822 10823 _blockFrames: function() { 10824 this.iframeBlocks = this.document.find( "iframe" ).map(function() { 10825 var iframe = $( this ); 10826 10827 return $( "<div>" ) 10828 .css({ 10829 position: "absolute", 10830 width: iframe.outerWidth(), 10831 height: iframe.outerHeight() 10832 }) 10833 .appendTo( iframe.parent() ) 10834 .offset( iframe.offset() )[0]; 10835 }); 10836 }, 10837 10838 _unblockFrames: function() { 10839 if ( this.iframeBlocks ) { 10840 this.iframeBlocks.remove(); 10841 delete this.iframeBlocks; 10842 } 10843 }, 10844 10845 _allowInteraction: function( event ) { 10846 if ( $( event.target ).closest( ".ui-dialog" ).length ) { 10847 return true; 10848 } 10849 10850 // TODO: Remove hack when datepicker implements 10851 // the .ui-front logic (#8989) 10852 return !!$( event.target ).closest( ".ui-datepicker" ).length; 10853 }, 10854 10855 _createOverlay: function() { 10856 if ( !this.options.modal ) { 10857 return; 10858 } 10859 10860 // We use a delay in case the overlay is created from an 10861 // event that we're going to be cancelling (#2804) 10862 var isOpening = true; 10863 this._delay(function() { 10864 isOpening = false; 10865 }); 10866 10867 if ( !this.document.data( "ui-dialog-overlays" ) ) { 10868 10869 // Prevent use of anchors and inputs 10870 // Using _on() for an event handler shared across many instances is 10871 // safe because the dialogs stack and must be closed in reverse order 10872 this._on( this.document, { 10873 focusin: function( event ) { 10874 if ( isOpening ) { 10875 return; 10876 } 10877 10878 if ( !this._allowInteraction( event ) ) { 10879 event.preventDefault(); 10880 this._trackingInstances()[ 0 ]._focusTabbable(); 10881 } 10882 } 10883 }); 10884 } 10885 10886 this.overlay = $( "<div>" ) 10887 .addClass( "ui-widget-overlay ui-front" ) 10888 .appendTo( this._appendTo() ); 10889 this._on( this.overlay, { 10890 mousedown: "_keepFocus" 10891 }); 10892 this.document.data( "ui-dialog-overlays", 10893 (this.document.data( "ui-dialog-overlays" ) || 0) + 1 ); 10894 }, 10895 10896 _destroyOverlay: function() { 10897 if ( !this.options.modal ) { 10898 return; 10899 } 10900 10901 if ( this.overlay ) { 10902 var overlays = this.document.data( "ui-dialog-overlays" ) - 1; 10903 10904 if ( !overlays ) { 10905 this.document 10906 .unbind( "focusin" ) 10907 .removeData( "ui-dialog-overlays" ); 10908 } else { 10909 this.document.data( "ui-dialog-overlays", overlays ); 10910 } 10911 10912 this.overlay.remove(); 10913 this.overlay = null; 10914 } 10915 } 10916 }); 10917 10918 10919 /*! 10920 * jQuery UI Progressbar 1.11.4 10921 * http://jqueryui.com 10922 * 10923 * Copyright jQuery Foundation and other contributors 10924 * Released under the MIT license. 10925 * http://jquery.org/license 10926 * 10927 * http://api.jqueryui.com/progressbar/ 10928 */ 10929 10930 10931 var progressbar = $.widget( "ui.progressbar", { 10932 version: "1.11.4", 10933 options: { 10934 max: 100, 10935 value: 0, 10936 10937 change: null, 10938 complete: null 10939 }, 10940 10941 min: 0, 10942 10943 _create: function() { 10944 // Constrain initial value 10945 this.oldValue = this.options.value = this._constrainedValue(); 10946 10947 this.element 10948 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) 10949 .attr({ 10950 // Only set static values, aria-valuenow and aria-valuemax are 10951 // set inside _refreshValue() 10952 role: "progressbar", 10953 "aria-valuemin": this.min 10954 }); 10955 10956 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" ) 10957 .appendTo( this.element ); 10958 10959 this._refreshValue(); 10960 }, 10961 10962 _destroy: function() { 10963 this.element 10964 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) 10965 .removeAttr( "role" ) 10966 .removeAttr( "aria-valuemin" ) 10967 .removeAttr( "aria-valuemax" ) 10968 .removeAttr( "aria-valuenow" ); 10969 10970 this.valueDiv.remove(); 10971 }, 10972 10973 value: function( newValue ) { 10974 if ( newValue === undefined ) { 10975 return this.options.value; 10976 } 10977 10978 this.options.value = this._constrainedValue( newValue ); 10979 this._refreshValue(); 10980 }, 10981 10982 _constrainedValue: function( newValue ) { 10983 if ( newValue === undefined ) { 10984 newValue = this.options.value; 10985 } 10986 10987 this.indeterminate = newValue === false; 10988 10989 // sanitize value 10990 if ( typeof newValue !== "number" ) { 10991 newValue = 0; 10992 } 10993 10994 return this.indeterminate ? false : 10995 Math.min( this.options.max, Math.max( this.min, newValue ) ); 10996 }, 10997 10998 _setOptions: function( options ) { 10999 // Ensure "value" option is set after other values (like max) 11000 var value = options.value; 11001 delete options.value; 11002 11003 this._super( options ); 11004 11005 this.options.value = this._constrainedValue( value ); 11006 this._refreshValue(); 11007 }, 11008 11009 _setOption: function( key, value ) { 11010 if ( key === "max" ) { 11011 // Don't allow a max less than min 11012 value = Math.max( this.min, value ); 11013 } 11014 if ( key === "disabled" ) { 11015 this.element 11016 .toggleClass( "ui-state-disabled", !!value ) 11017 .attr( "aria-disabled", value ); 11018 } 11019 this._super( key, value ); 11020 }, 11021 11022 _percentage: function() { 11023 return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min ); 11024 }, 11025 11026 _refreshValue: function() { 11027 var value = this.options.value, 11028 percentage = this._percentage(); 11029 11030 this.valueDiv 11031 .toggle( this.indeterminate || value > this.min ) 11032 .toggleClass( "ui-corner-right", value === this.options.max ) 11033 .width( percentage.toFixed(0) + "%" ); 11034 11035 this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate ); 11036 11037 if ( this.indeterminate ) { 11038 this.element.removeAttr( "aria-valuenow" ); 11039 if ( !this.overlayDiv ) { 11040 this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv ); 11041 } 11042 } else { 11043 this.element.attr({ 11044 "aria-valuemax": this.options.max, 11045 "aria-valuenow": value 11046 }); 11047 if ( this.overlayDiv ) { 11048 this.overlayDiv.remove(); 11049 this.overlayDiv = null; 11050 } 11051 } 11052 11053 if ( this.oldValue !== value ) { 11054 this.oldValue = value; 11055 this._trigger( "change" ); 11056 } 11057 if ( value === this.options.max ) { 11058 this._trigger( "complete" ); 11059 } 11060 } 11061 }); 11062 11063 11064 /*! 11065 * jQuery UI Selectmenu 1.11.4 11066 * http://jqueryui.com 11067 * 11068 * Copyright jQuery Foundation and other contributors 11069 * Released under the MIT license. 11070 * http://jquery.org/license 11071 * 11072 * http://api.jqueryui.com/selectmenu 11073 */ 11074 11075 11076 var selectmenu = $.widget( "ui.selectmenu", { 11077 version: "1.11.4", 11078 defaultElement: "<select>", 11079 options: { 11080 appendTo: null, 11081 disabled: null, 11082 icons: { 11083 button: "ui-icon-triangle-1-s" 11084 }, 11085 position: { 11086 my: "left top", 11087 at: "left bottom", 11088 collision: "none" 11089 }, 11090 width: null, 11091 11092 // callbacks 11093 change: null, 11094 close: null, 11095 focus: null, 11096 open: null, 11097 select: null 11098 }, 11099 11100 _create: function() { 11101 var selectmenuId = this.element.uniqueId().attr( "id" ); 11102 this.ids = { 11103 element: selectmenuId, 11104 button: selectmenuId + "-button", 11105 menu: selectmenuId + "-menu" 11106 }; 11107 11108 this._drawButton(); 11109 this._drawMenu(); 11110 11111 if ( this.options.disabled ) { 11112 this.disable(); 11113 } 11114 }, 11115 11116 _drawButton: function() { 11117 var that = this; 11118 11119 // Associate existing label with the new button 11120 this.label = $( "label[for='" + this.ids.element + "']" ).attr( "for", this.ids.button ); 11121 this._on( this.label, { 11122 click: function( event ) { 11123 this.button.focus(); 11124 event.preventDefault(); 11125 } 11126 }); 11127 11128 // Hide original select element 11129 this.element.hide(); 11130 11131 // Create button 11132 this.button = $( "<span>", { 11133 "class": "ui-selectmenu-button ui-widget ui-state-default ui-corner-all", 11134 tabindex: this.options.disabled ? -1 : 0, 11135 id: this.ids.button, 11136 role: "combobox", 11137 "aria-expanded": "false", 11138 "aria-autocomplete": "list", 11139 "aria-owns": this.ids.menu, 11140 "aria-haspopup": "true" 11141 }) 11142 .insertAfter( this.element ); 11143 11144 $( "<span>", { 11145 "class": "ui-icon " + this.options.icons.button 11146 }) 11147 .prependTo( this.button ); 11148 11149 this.buttonText = $( "<span>", { 11150 "class": "ui-selectmenu-text" 11151 }) 11152 .appendTo( this.button ); 11153 11154 this._setText( this.buttonText, this.element.find( "option:selected" ).text() ); 11155 this._resizeButton(); 11156 11157 this._on( this.button, this._buttonEvents ); 11158 this.button.one( "focusin", function() { 11159 11160 // Delay rendering the menu items until the button receives focus. 11161 // The menu may have already been rendered via a programmatic open. 11162 if ( !that.menuItems ) { 11163 that._refreshMenu(); 11164 } 11165 }); 11166 this._hoverable( this.button ); 11167 this._focusable( this.button ); 11168 }, 11169 11170 _drawMenu: function() { 11171 var that = this; 11172 11173 // Create menu 11174 this.menu = $( "<ul>", { 11175 "aria-hidden": "true", 11176 "aria-labelledby": this.ids.button, 11177 id: this.ids.menu 11178 }); 11179 11180 // Wrap menu 11181 this.menuWrap = $( "<div>", { 11182 "class": "ui-selectmenu-menu ui-front" 11183 }) 11184 .append( this.menu ) 11185 .appendTo( this._appendTo() ); 11186 11187 // Initialize menu widget 11188 this.menuInstance = this.menu 11189 .menu({ 11190 role: "listbox", 11191 select: function( event, ui ) { 11192 event.preventDefault(); 11193 11194 // support: IE8 11195 // If the item was selected via a click, the text selection 11196 // will be destroyed in IE 11197 that._setSelection(); 11198 11199 that._select( ui.item.data( "ui-selectmenu-item" ), event ); 11200 }, 11201 focus: function( event, ui ) { 11202 var item = ui.item.data( "ui-selectmenu-item" ); 11203 11204 // Prevent inital focus from firing and check if its a newly focused item 11205 if ( that.focusIndex != null && item.index !== that.focusIndex ) { 11206 that._trigger( "focus", event, { item: item } ); 11207 if ( !that.isOpen ) { 11208 that._select( item, event ); 11209 } 11210 } 11211 that.focusIndex = item.index; 11212 11213 that.button.attr( "aria-activedescendant", 11214 that.menuItems.eq( item.index ).attr( "id" ) ); 11215 } 11216 }) 11217 .menu( "instance" ); 11218 11219 // Adjust menu styles to dropdown 11220 this.menu 11221 .addClass( "ui-corner-bottom" ) 11222 .removeClass( "ui-corner-all" ); 11223 11224 // Don't close the menu on mouseleave 11225 this.menuInstance._off( this.menu, "mouseleave" ); 11226 11227 // Cancel the menu's collapseAll on document click 11228 this.menuInstance._closeOnDocumentClick = function() { 11229 return false; 11230 }; 11231 11232 // Selects often contain empty items, but never contain dividers 11233 this.menuInstance._isDivider = function() { 11234 return false; 11235 }; 11236 }, 11237 11238 refresh: function() { 11239 this._refreshMenu(); 11240 this._setText( this.buttonText, this._getSelectedItem().text() ); 11241 if ( !this.options.width ) { 11242 this._resizeButton(); 11243 } 11244 }, 11245 11246 _refreshMenu: function() { 11247 this.menu.empty(); 11248 11249 var item, 11250 options = this.element.find( "option" ); 11251 11252 if ( !options.length ) { 11253 return; 11254 } 11255 11256 this._parseOptions( options ); 11257 this._renderMenu( this.menu, this.items ); 11258 11259 this.menuInstance.refresh(); 11260 this.menuItems = this.menu.find( "li" ).not( ".ui-selectmenu-optgroup" ); 11261 11262 item = this._getSelectedItem(); 11263 11264 // Update the menu to have the correct item focused 11265 this.menuInstance.focus( null, item ); 11266 this._setAria( item.data( "ui-selectmenu-item" ) ); 11267 11268 // Set disabled state 11269 this._setOption( "disabled", this.element.prop( "disabled" ) ); 11270 }, 11271 11272 open: function( event ) { 11273 if ( this.options.disabled ) { 11274 return; 11275 } 11276 11277 // If this is the first time the menu is being opened, render the items 11278 if ( !this.menuItems ) { 11279 this._refreshMenu(); 11280 } else { 11281 11282 // Menu clears focus on close, reset focus to selected item 11283 this.menu.find( ".ui-state-focus" ).removeClass( "ui-state-focus" ); 11284 this.menuInstance.focus( null, this._getSelectedItem() ); 11285 } 11286 11287 this.isOpen = true; 11288 this._toggleAttr(); 11289 this._resizeMenu(); 11290 this._position(); 11291 11292 this._on( this.document, this._documentClick ); 11293 11294 this._trigger( "open", event ); 11295 }, 11296 11297 _position: function() { 11298 this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) ); 11299 }, 11300 11301 close: function( event ) { 11302 if ( !this.isOpen ) { 11303 return; 11304 } 11305 11306 this.isOpen = false; 11307 this._toggleAttr(); 11308 11309 this.range = null; 11310 this._off( this.document ); 11311 11312 this._trigger( "close", event ); 11313 }, 11314 11315 widget: function() { 11316 return this.button; 11317 }, 11318 11319 menuWidget: function() { 11320 return this.menu; 11321 }, 11322 11323 _renderMenu: function( ul, items ) { 11324 var that = this, 11325 currentOptgroup = ""; 11326 11327 $.each( items, function( index, item ) { 11328 if ( item.optgroup !== currentOptgroup ) { 11329 $( "<li>", { 11330 "class": "ui-selectmenu-optgroup ui-menu-divider" + 11331 ( item.element.parent( "optgroup" ).prop( "disabled" ) ? 11332 " ui-state-disabled" : 11333 "" ), 11334 text: item.optgroup 11335 }) 11336 .appendTo( ul ); 11337 11338 currentOptgroup = item.optgroup; 11339 } 11340 11341 that._renderItemData( ul, item ); 11342 }); 11343 }, 11344 11345 _renderItemData: function( ul, item ) { 11346 return this._renderItem( ul, item ).data( "ui-selectmenu-item", item ); 11347 }, 11348 11349 _renderItem: function( ul, item ) { 11350 var li = $( "<li>" ); 11351 11352 if ( item.disabled ) { 11353 li.addClass( "ui-state-disabled" ); 11354 } 11355 this._setText( li, item.label ); 11356 11357 return li.appendTo( ul ); 11358 }, 11359 11360 _setText: function( element, value ) { 11361 if ( value ) { 11362 element.text( value ); 11363 } else { 11364 element.html( " " ); 11365 } 11366 }, 11367 11368 _move: function( direction, event ) { 11369 var item, next, 11370 filter = ".ui-menu-item"; 11371 11372 if ( this.isOpen ) { 11373 item = this.menuItems.eq( this.focusIndex ); 11374 } else { 11375 item = this.menuItems.eq( this.element[ 0 ].selectedIndex ); 11376 filter += ":not(.ui-state-disabled)"; 11377 } 11378 11379 if ( direction === "first" || direction === "last" ) { 11380 next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 ); 11381 } else { 11382 next = item[ direction + "All" ]( filter ).eq( 0 ); 11383 } 11384 11385 if ( next.length ) { 11386 this.menuInstance.focus( event, next ); 11387 } 11388 }, 11389 11390 _getSelectedItem: function() { 11391 return this.menuItems.eq( this.element[ 0 ].selectedIndex ); 11392 }, 11393 11394 _toggle: function( event ) { 11395 this[ this.isOpen ? "close" : "open" ]( event ); 11396 }, 11397 11398 _setSelection: function() { 11399 var selection; 11400 11401 if ( !this.range ) { 11402 return; 11403 } 11404 11405 if ( window.getSelection ) { 11406 selection = window.getSelection(); 11407 selection.removeAllRanges(); 11408 selection.addRange( this.range ); 11409 11410 // support: IE8 11411 } else { 11412 this.range.select(); 11413 } 11414 11415 // support: IE 11416 // Setting the text selection kills the button focus in IE, but 11417 // restoring the focus doesn't kill the selection. 11418 this.button.focus(); 11419 }, 11420 11421 _documentClick: { 11422 mousedown: function( event ) { 11423 if ( !this.isOpen ) { 11424 return; 11425 } 11426 11427 if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" + this.ids.button ).length ) { 11428 this.close( event ); 11429 } 11430 } 11431 }, 11432 11433 _buttonEvents: { 11434 11435 // Prevent text selection from being reset when interacting with the selectmenu (#10144) 11436 mousedown: function() { 11437 var selection; 11438 11439 if ( window.getSelection ) { 11440 selection = window.getSelection(); 11441 if ( selection.rangeCount ) { 11442 this.range = selection.getRangeAt( 0 ); 11443 } 11444 11445 // support: IE8 11446 } else { 11447 this.range = document.selection.createRange(); 11448 } 11449 }, 11450 11451 click: function( event ) { 11452 this._setSelection(); 11453 this._toggle( event ); 11454 }, 11455 11456 keydown: function( event ) { 11457 var preventDefault = true; 11458 switch ( event.keyCode ) { 11459 case $.ui.keyCode.TAB: 11460 case $.ui.keyCode.ESCAPE: 11461 this.close( event ); 11462 preventDefault = false; 11463 break; 11464 case $.ui.keyCode.ENTER: 11465 if ( this.isOpen ) { 11466 this._selectFocusedItem( event ); 11467 } 11468 break; 11469 case $.ui.keyCode.UP: 11470 if ( event.altKey ) { 11471 this._toggle( event ); 11472 } else { 11473 this._move( "prev", event ); 11474 } 11475 break; 11476 case $.ui.keyCode.DOWN: 11477 if ( event.altKey ) { 11478 this._toggle( event ); 11479 } else { 11480 this._move( "next", event ); 11481 } 11482 break; 11483 case $.ui.keyCode.SPACE: 11484 if ( this.isOpen ) { 11485 this._selectFocusedItem( event ); 11486 } else { 11487 this._toggle( event ); 11488 } 11489 break; 11490 case $.ui.keyCode.LEFT: 11491 this._move( "prev", event ); 11492 break; 11493 case $.ui.keyCode.RIGHT: 11494 this._move( "next", event ); 11495 break; 11496 case $.ui.keyCode.HOME: 11497 case $.ui.keyCode.PAGE_UP: 11498 this._move( "first", event ); 11499 break; 11500 case $.ui.keyCode.END: 11501 case $.ui.keyCode.PAGE_DOWN: 11502 this._move( "last", event ); 11503 break; 11504 default: 11505 this.menu.trigger( event ); 11506 preventDefault = false; 11507 } 11508 11509 if ( preventDefault ) { 11510 event.preventDefault(); 11511 } 11512 } 11513 }, 11514 11515 _selectFocusedItem: function( event ) { 11516 var item = this.menuItems.eq( this.focusIndex ); 11517 if ( !item.hasClass( "ui-state-disabled" ) ) { 11518 this._select( item.data( "ui-selectmenu-item" ), event ); 11519 } 11520 }, 11521 11522 _select: function( item, event ) { 11523 var oldIndex = this.element[ 0 ].selectedIndex; 11524 11525 // Change native select element 11526 this.element[ 0 ].selectedIndex = item.index; 11527 this._setText( this.buttonText, item.label ); 11528 this._setAria( item ); 11529 this._trigger( "select", event, { item: item } ); 11530 11531 if ( item.index !== oldIndex ) { 11532 this._trigger( "change", event, { item: item } ); 11533 } 11534 11535 this.close( event ); 11536 }, 11537 11538 _setAria: function( item ) { 11539 var id = this.menuItems.eq( item.index ).attr( "id" ); 11540 11541 this.button.attr({ 11542 "aria-labelledby": id, 11543 "aria-activedescendant": id 11544 }); 11545 this.menu.attr( "aria-activedescendant", id ); 11546 }, 11547 11548 _setOption: function( key, value ) { 11549 if ( key === "icons" ) { 11550 this.button.find( "span.ui-icon" ) 11551 .removeClass( this.options.icons.button ) 11552 .addClass( value.button ); 11553 } 11554 11555 this._super( key, value ); 11556 11557 if ( key === "appendTo" ) { 11558 this.menuWrap.appendTo( this._appendTo() ); 11559 } 11560 11561 if ( key === "disabled" ) { 11562 this.menuInstance.option( "disabled", value ); 11563 this.button 11564 .toggleClass( "ui-state-disabled", value ) 11565 .attr( "aria-disabled", value ); 11566 11567 this.element.prop( "disabled", value ); 11568 if ( value ) { 11569 this.button.attr( "tabindex", -1 ); 11570 this.close(); 11571 } else { 11572 this.button.attr( "tabindex", 0 ); 11573 } 11574 } 11575 11576 if ( key === "width" ) { 11577 this._resizeButton(); 11578 } 11579 }, 11580 11581 _appendTo: function() { 11582 var element = this.options.appendTo; 11583 11584 if ( element ) { 11585 element = element.jquery || element.nodeType ? 11586 $( element ) : 11587 this.document.find( element ).eq( 0 ); 11588 } 11589 11590 if ( !element || !element[ 0 ] ) { 11591 element = this.element.closest( ".ui-front" ); 11592 } 11593 11594 if ( !element.length ) { 11595 element = this.document[ 0 ].body; 11596 } 11597 11598 return element; 11599 }, 11600 11601 _toggleAttr: function() { 11602 this.button 11603 .toggleClass( "ui-corner-top", this.isOpen ) 11604 .toggleClass( "ui-corner-all", !this.isOpen ) 11605 .attr( "aria-expanded", this.isOpen ); 11606 this.menuWrap.toggleClass( "ui-selectmenu-open", this.isOpen ); 11607 this.menu.attr( "aria-hidden", !this.isOpen ); 11608 }, 11609 11610 _resizeButton: function() { 11611 var width = this.options.width; 11612 11613 if ( !width ) { 11614 width = this.element.show().outerWidth(); 11615 this.element.hide(); 11616 } 11617 11618 this.button.outerWidth( width ); 11619 }, 11620 11621 _resizeMenu: function() { 11622 this.menu.outerWidth( Math.max( 11623 this.button.outerWidth(), 11624 11625 // support: IE10 11626 // IE10 wraps long text (possibly a rounding bug) 11627 // so we add 1px to avoid the wrapping 11628 this.menu.width( "" ).outerWidth() + 1 11629 ) ); 11630 }, 11631 11632 _getCreateOptions: function() { 11633 return { disabled: this.element.prop( "disabled" ) }; 11634 }, 11635 11636 _parseOptions: function( options ) { 11637 var data = []; 11638 options.each(function( index, item ) { 11639 var option = $( item ), 11640 optgroup = option.parent( "optgroup" ); 11641 data.push({ 11642 element: option, 11643 index: index, 11644 value: option.val(), 11645 label: option.text(), 11646 optgroup: optgroup.attr( "label" ) || "", 11647 disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" ) 11648 }); 11649 }); 11650 this.items = data; 11651 }, 11652 11653 _destroy: function() { 11654 this.menuWrap.remove(); 11655 this.button.remove(); 11656 this.element.show(); 11657 this.element.removeUniqueId(); 11658 this.label.attr( "for", this.ids.element ); 11659 } 11660 }); 11661 11662 11663 /*! 11664 * jQuery UI Slider 1.11.4 11665 * http://jqueryui.com 11666 * 11667 * Copyright jQuery Foundation and other contributors 11668 * Released under the MIT license. 11669 * http://jquery.org/license 11670 * 11671 * http://api.jqueryui.com/slider/ 11672 */ 11673 11674 11675 var slider = $.widget( "ui.slider", $.ui.mouse, { 11676 version: "1.11.4", 11677 widgetEventPrefix: "slide", 11678 11679 options: { 11680 animate: false, 11681 distance: 0, 11682 max: 100, 11683 min: 0, 11684 orientation: "horizontal", 11685 range: false, 11686 step: 1, 11687 value: 0, 11688 values: null, 11689 11690 // callbacks 11691 change: null, 11692 slide: null, 11693 start: null, 11694 stop: null 11695 }, 11696 11697 // number of pages in a slider 11698 // (how many times can you page up/down to go through the whole range) 11699 numPages: 5, 11700 11701 _create: function() { 11702 this._keySliding = false; 11703 this._mouseSliding = false; 11704 this._animateOff = true; 11705 this._handleIndex = null; 11706 this._detectOrientation(); 11707 this._mouseInit(); 11708 this._calculateNewMax(); 11709 11710 this.element 11711 .addClass( "ui-slider" + 11712 " ui-slider-" + this.orientation + 11713 " ui-widget" + 11714 " ui-widget-content" + 11715 " ui-corner-all"); 11716 11717 this._refresh(); 11718 this._setOption( "disabled", this.options.disabled ); 11719 11720 this._animateOff = false; 11721 }, 11722 11723 _refresh: function() { 11724 this._createRange(); 11725 this._createHandles(); 11726 this._setupEvents(); 11727 this._refreshValue(); 11728 }, 11729 11730 _createHandles: function() { 11731 var i, handleCount, 11732 options = this.options, 11733 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), 11734 handle = "<span class='ui-slider-handle ui-state-default ui-corner-all' tabindex='0'></span>", 11735 handles = []; 11736 11737 handleCount = ( options.values && options.values.length ) || 1; 11738 11739 if ( existingHandles.length > handleCount ) { 11740 existingHandles.slice( handleCount ).remove(); 11741 existingHandles = existingHandles.slice( 0, handleCount ); 11742 } 11743 11744 for ( i = existingHandles.length; i < handleCount; i++ ) { 11745 handles.push( handle ); 11746 } 11747 11748 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) ); 11749 11750 this.handle = this.handles.eq( 0 ); 11751 11752 this.handles.each(function( i ) { 11753 $( this ).data( "ui-slider-handle-index", i ); 11754 }); 11755 }, 11756 11757 _createRange: function() { 11758 var options = this.options, 11759 classes = ""; 11760 11761 if ( options.range ) { 11762 if ( options.range === true ) { 11763 if ( !options.values ) { 11764 options.values = [ this._valueMin(), this._valueMin() ]; 11765 } else if ( options.values.length && options.values.length !== 2 ) { 11766 options.values = [ options.values[0], options.values[0] ]; 11767 } else if ( $.isArray( options.values ) ) { 11768 options.values = options.values.slice(0); 11769 } 11770 } 11771 11772 if ( !this.range || !this.range.length ) { 11773 this.range = $( "<div></div>" ) 11774 .appendTo( this.element ); 11775 11776 classes = "ui-slider-range" + 11777 // note: this isn't the most fittingly semantic framework class for this element, 11778 // but worked best visually with a variety of themes 11779 " ui-widget-header ui-corner-all"; 11780 } else { 11781 this.range.removeClass( "ui-slider-range-min ui-slider-range-max" ) 11782 // Handle range switching from true to min/max 11783 .css({ 11784 "left": "", 11785 "bottom": "" 11786 }); 11787 } 11788 11789 this.range.addClass( classes + 11790 ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) ); 11791 } else { 11792 if ( this.range ) { 11793 this.range.remove(); 11794 } 11795 this.range = null; 11796 } 11797 }, 11798 11799 _setupEvents: function() { 11800 this._off( this.handles ); 11801 this._on( this.handles, this._handleEvents ); 11802 this._hoverable( this.handles ); 11803 this._focusable( this.handles ); 11804 }, 11805 11806 _destroy: function() { 11807 this.handles.remove(); 11808 if ( this.range ) { 11809 this.range.remove(); 11810 } 11811 11812 this.element 11813 .removeClass( "ui-slider" + 11814 " ui-slider-horizontal" + 11815 " ui-slider-vertical" + 11816 " ui-widget" + 11817 " ui-widget-content" + 11818 " ui-corner-all" ); 11819 11820 this._mouseDestroy(); 11821 }, 11822 11823 _mouseCapture: function( event ) { 11824 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, 11825 that = this, 11826 o = this.options; 11827 11828 if ( o.disabled ) { 11829 return false; 11830 } 11831 11832 this.elementSize = { 11833 width: this.element.outerWidth(), 11834 height: this.element.outerHeight() 11835 }; 11836 this.elementOffset = this.element.offset(); 11837 11838 position = { x: event.pageX, y: event.pageY }; 11839 normValue = this._normValueFromMouse( position ); 11840 distance = this._valueMax() - this._valueMin() + 1; 11841 this.handles.each(function( i ) { 11842 var thisDistance = Math.abs( normValue - that.values(i) ); 11843 if (( distance > thisDistance ) || 11844 ( distance === thisDistance && 11845 (i === that._lastChangedValue || that.values(i) === o.min ))) { 11846 distance = thisDistance; 11847 closestHandle = $( this ); 11848 index = i; 11849 } 11850 }); 11851 11852 allowed = this._start( event, index ); 11853 if ( allowed === false ) { 11854 return false; 11855 } 11856 this._mouseSliding = true; 11857 11858 this._handleIndex = index; 11859 11860 closestHandle 11861 .addClass( "ui-state-active" ) 11862 .focus(); 11863 11864 offset = closestHandle.offset(); 11865 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" ); 11866 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { 11867 left: event.pageX - offset.left - ( closestHandle.width() / 2 ), 11868 top: event.pageY - offset.top - 11869 ( closestHandle.height() / 2 ) - 11870 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - 11871 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + 11872 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) 11873 }; 11874 11875 if ( !this.handles.hasClass( "ui-state-hover" ) ) { 11876 this._slide( event, index, normValue ); 11877 } 11878 this._animateOff = true; 11879 return true; 11880 }, 11881 11882 _mouseStart: function() { 11883 return true; 11884 }, 11885 11886 _mouseDrag: function( event ) { 11887 var position = { x: event.pageX, y: event.pageY }, 11888 normValue = this._normValueFromMouse( position ); 11889 11890 this._slide( event, this._handleIndex, normValue ); 11891 11892 return false; 11893 }, 11894 11895 _mouseStop: function( event ) { 11896 this.handles.removeClass( "ui-state-active" ); 11897 this._mouseSliding = false; 11898 11899 this._stop( event, this._handleIndex ); 11900 this._change( event, this._handleIndex ); 11901 11902 this._handleIndex = null; 11903 this._clickOffset = null; 11904 this._animateOff = false; 11905 11906 return false; 11907 }, 11908 11909 _detectOrientation: function() { 11910 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; 11911 }, 11912 11913 _normValueFromMouse: function( position ) { 11914 var pixelTotal, 11915 pixelMouse, 11916 percentMouse, 11917 valueTotal, 11918 valueMouse; 11919 11920 if ( this.orientation === "horizontal" ) { 11921 pixelTotal = this.elementSize.width; 11922 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); 11923 } else { 11924 pixelTotal = this.elementSize.height; 11925 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); 11926 } 11927 11928 percentMouse = ( pixelMouse / pixelTotal ); 11929 if ( percentMouse > 1 ) { 11930 percentMouse = 1; 11931 } 11932 if ( percentMouse < 0 ) { 11933 percentMouse = 0; 11934 } 11935 if ( this.orientation === "vertical" ) { 11936 percentMouse = 1 - percentMouse; 11937 } 11938 11939 valueTotal = this._valueMax() - this._valueMin(); 11940 valueMouse = this._valueMin() + percentMouse * valueTotal; 11941 11942 return this._trimAlignValue( valueMouse ); 11943 }, 11944 11945 _start: function( event, index ) { 11946 var uiHash = { 11947 handle: this.handles[ index ], 11948 value: this.value() 11949 }; 11950 if ( this.options.values && this.options.values.length ) { 11951 uiHash.value = this.values( index ); 11952 uiHash.values = this.values(); 11953 } 11954 return this._trigger( "start", event, uiHash ); 11955 }, 11956 11957 _slide: function( event, index, newVal ) { 11958 var otherVal, 11959 newValues, 11960 allowed; 11961 11962 if ( this.options.values && this.options.values.length ) { 11963 otherVal = this.values( index ? 0 : 1 ); 11964 11965 if ( ( this.options.values.length === 2 && this.options.range === true ) && 11966 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) 11967 ) { 11968 newVal = otherVal; 11969 } 11970 11971 if ( newVal !== this.values( index ) ) { 11972 newValues = this.values(); 11973 newValues[ index ] = newVal; 11974 // A slide can be canceled by returning false from the slide callback 11975 allowed = this._trigger( "slide", event, { 11976 handle: this.handles[ index ], 11977 value: newVal, 11978 values: newValues 11979 } ); 11980 otherVal = this.values( index ? 0 : 1 ); 11981 if ( allowed !== false ) { 11982 this.values( index, newVal ); 11983 } 11984 } 11985 } else { 11986 if ( newVal !== this.value() ) { 11987 // A slide can be canceled by returning false from the slide callback 11988 allowed = this._trigger( "slide", event, { 11989 handle: this.handles[ index ], 11990 value: newVal 11991 } ); 11992 if ( allowed !== false ) { 11993 this.value( newVal ); 11994 } 11995 } 11996 } 11997 }, 11998 11999 _stop: function( event, index ) { 12000 var uiHash = { 12001 handle: this.handles[ index ], 12002 value: this.value() 12003 }; 12004 if ( this.options.values && this.options.values.length ) { 12005 uiHash.value = this.values( index ); 12006 uiHash.values = this.values(); 12007 } 12008 12009 this._trigger( "stop", event, uiHash ); 12010 }, 12011 12012 _change: function( event, index ) { 12013 if ( !this._keySliding && !this._mouseSliding ) { 12014 var uiHash = { 12015 handle: this.handles[ index ], 12016 value: this.value() 12017 }; 12018 if ( this.options.values && this.options.values.length ) { 12019 uiHash.value = this.values( index ); 12020 uiHash.values = this.values(); 12021 } 12022 12023 //store the last changed value index for reference when handles overlap 12024 this._lastChangedValue = index; 12025 12026 this._trigger( "change", event, uiHash ); 12027 } 12028 }, 12029 12030 value: function( newValue ) { 12031 if ( arguments.length ) { 12032 this.options.value = this._trimAlignValue( newValue ); 12033 this._refreshValue(); 12034 this._change( null, 0 ); 12035 return; 12036 } 12037 12038 return this._value(); 12039 }, 12040 12041 values: function( index, newValue ) { 12042 var vals, 12043 newValues, 12044 i; 12045 12046 if ( arguments.length > 1 ) { 12047 this.options.values[ index ] = this._trimAlignValue( newValue ); 12048 this._refreshValue(); 12049 this._change( null, index ); 12050 return; 12051 } 12052 12053 if ( arguments.length ) { 12054 if ( $.isArray( arguments[ 0 ] ) ) { 12055 vals = this.options.values; 12056 newValues = arguments[ 0 ]; 12057 for ( i = 0; i < vals.length; i += 1 ) { 12058 vals[ i ] = this._trimAlignValue( newValues[ i ] ); 12059 this._change( null, i ); 12060 } 12061 this._refreshValue(); 12062 } else { 12063 if ( this.options.values && this.options.values.length ) { 12064 return this._values( index ); 12065 } else { 12066 return this.value(); 12067 } 12068 } 12069 } else { 12070 return this._values(); 12071 } 12072 }, 12073 12074 _setOption: function( key, value ) { 12075 var i, 12076 valsLength = 0; 12077 12078 if ( key === "range" && this.options.range === true ) { 12079 if ( value === "min" ) { 12080 this.options.value = this._values( 0 ); 12081 this.options.values = null; 12082 } else if ( value === "max" ) { 12083 this.options.value = this._values( this.options.values.length - 1 ); 12084 this.options.values = null; 12085 } 12086 } 12087 12088 if ( $.isArray( this.options.values ) ) { 12089 valsLength = this.options.values.length; 12090 } 12091 12092 if ( key === "disabled" ) { 12093 this.element.toggleClass( "ui-state-disabled", !!value ); 12094 } 12095 12096 this._super( key, value ); 12097 12098 switch ( key ) { 12099 case "orientation": 12100 this._detectOrientation(); 12101 this.element 12102 .removeClass( "ui-slider-horizontal ui-slider-vertical" ) 12103 .addClass( "ui-slider-" + this.orientation ); 12104 this._refreshValue(); 12105 12106 // Reset positioning from previous orientation 12107 this.handles.css( value === "horizontal" ? "bottom" : "left", "" ); 12108 break; 12109 case "value": 12110 this._animateOff = true; 12111 this._refreshValue(); 12112 this._change( null, 0 ); 12113 this._animateOff = false; 12114 break; 12115 case "values": 12116 this._animateOff = true; 12117 this._refreshValue(); 12118 for ( i = 0; i < valsLength; i += 1 ) { 12119 this._change( null, i ); 12120 } 12121 this._animateOff = false; 12122 break; 12123 case "step": 12124 case "min": 12125 case "max": 12126 this._animateOff = true; 12127 this._calculateNewMax(); 12128 this._refreshValue(); 12129 this._animateOff = false; 12130 break; 12131 case "range": 12132 this._animateOff = true; 12133 this._refresh(); 12134 this._animateOff = false; 12135 break; 12136 } 12137 }, 12138 12139 //internal value getter 12140 // _value() returns value trimmed by min and max, aligned by step 12141 _value: function() { 12142 var val = this.options.value; 12143 val = this._trimAlignValue( val ); 12144 12145 return val; 12146 }, 12147 12148 //internal values getter 12149 // _values() returns array of values trimmed by min and max, aligned by step 12150 // _values( index ) returns single value trimmed by min and max, aligned by step 12151 _values: function( index ) { 12152 var val, 12153 vals, 12154 i; 12155 12156 if ( arguments.length ) { 12157 val = this.options.values[ index ]; 12158 val = this._trimAlignValue( val ); 12159 12160 return val; 12161 } else if ( this.options.values && this.options.values.length ) { 12162 // .slice() creates a copy of the array 12163 // this copy gets trimmed by min and max and then returned 12164 vals = this.options.values.slice(); 12165 for ( i = 0; i < vals.length; i += 1) { 12166 vals[ i ] = this._trimAlignValue( vals[ i ] ); 12167 } 12168 12169 return vals; 12170 } else { 12171 return []; 12172 } 12173 }, 12174 12175 // returns the step-aligned value that val is closest to, between (inclusive) min and max 12176 _trimAlignValue: function( val ) { 12177 if ( val <= this._valueMin() ) { 12178 return this._valueMin(); 12179 } 12180 if ( val >= this._valueMax() ) { 12181 return this._valueMax(); 12182 } 12183 var step = ( this.options.step > 0 ) ? this.options.step : 1, 12184 valModStep = (val - this._valueMin()) % step, 12185 alignValue = val - valModStep; 12186 12187 if ( Math.abs(valModStep) * 2 >= step ) { 12188 alignValue += ( valModStep > 0 ) ? step : ( -step ); 12189 } 12190 12191 // Since JavaScript has problems with large floats, round 12192 // the final value to 5 digits after the decimal point (see #4124) 12193 return parseFloat( alignValue.toFixed(5) ); 12194 }, 12195 12196 _calculateNewMax: function() { 12197 var max = this.options.max, 12198 min = this._valueMin(), 12199 step = this.options.step, 12200 aboveMin = Math.floor( ( +( max - min ).toFixed( this._precision() ) ) / step ) * step; 12201 max = aboveMin + min; 12202 this.max = parseFloat( max.toFixed( this._precision() ) ); 12203 }, 12204 12205 _precision: function() { 12206 var precision = this._precisionOf( this.options.step ); 12207 if ( this.options.min !== null ) { 12208 precision = Math.max( precision, this._precisionOf( this.options.min ) ); 12209 } 12210 return precision; 12211 }, 12212 12213 _precisionOf: function( num ) { 12214 var str = num.toString(), 12215 decimal = str.indexOf( "." ); 12216 return decimal === -1 ? 0 : str.length - decimal - 1; 12217 }, 12218 12219 _valueMin: function() { 12220 return this.options.min; 12221 }, 12222 12223 _valueMax: function() { 12224 return this.max; 12225 }, 12226 12227 _refreshValue: function() { 12228 var lastValPercent, valPercent, value, valueMin, valueMax, 12229 oRange = this.options.range, 12230 o = this.options, 12231 that = this, 12232 animate = ( !this._animateOff ) ? o.animate : false, 12233 _set = {}; 12234 12235 if ( this.options.values && this.options.values.length ) { 12236 this.handles.each(function( i ) { 12237 valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100; 12238 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 12239 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 12240 if ( that.options.range === true ) { 12241 if ( that.orientation === "horizontal" ) { 12242 if ( i === 0 ) { 12243 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); 12244 } 12245 if ( i === 1 ) { 12246 that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); 12247 } 12248 } else { 12249 if ( i === 0 ) { 12250 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); 12251 } 12252 if ( i === 1 ) { 12253 that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); 12254 } 12255 } 12256 } 12257 lastValPercent = valPercent; 12258 }); 12259 } else { 12260 value = this.value(); 12261 valueMin = this._valueMin(); 12262 valueMax = this._valueMax(); 12263 valPercent = ( valueMax !== valueMin ) ? 12264 ( value - valueMin ) / ( valueMax - valueMin ) * 100 : 12265 0; 12266 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 12267 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 12268 12269 if ( oRange === "min" && this.orientation === "horizontal" ) { 12270 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); 12271 } 12272 if ( oRange === "max" && this.orientation === "horizontal" ) { 12273 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); 12274 } 12275 if ( oRange === "min" && this.orientation === "vertical" ) { 12276 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); 12277 } 12278 if ( oRange === "max" && this.orientation === "vertical" ) { 12279 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); 12280 } 12281 } 12282 }, 12283 12284 _handleEvents: { 12285 keydown: function( event ) { 12286 var allowed, curVal, newVal, step, 12287 index = $( event.target ).data( "ui-slider-handle-index" ); 12288 12289 switch ( event.keyCode ) { 12290 case $.ui.keyCode.HOME: 12291 case $.ui.keyCode.END: 12292 case $.ui.keyCode.PAGE_UP: 12293 case $.ui.keyCode.PAGE_DOWN: 12294 case $.ui.keyCode.UP: 12295 case $.ui.keyCode.RIGHT: 12296 case $.ui.keyCode.DOWN: 12297 case $.ui.keyCode.LEFT: 12298 event.preventDefault(); 12299 if ( !this._keySliding ) { 12300 this._keySliding = true; 12301 $( event.target ).addClass( "ui-state-active" ); 12302 allowed = this._start( event, index ); 12303 if ( allowed === false ) { 12304 return; 12305 } 12306 } 12307 break; 12308 } 12309 12310 step = this.options.step; 12311 if ( this.options.values && this.options.values.length ) { 12312 curVal = newVal = this.values( index ); 12313 } else { 12314 curVal = newVal = this.value(); 12315 } 12316 12317 switch ( event.keyCode ) { 12318 case $.ui.keyCode.HOME: 12319 newVal = this._valueMin(); 12320 break; 12321 case $.ui.keyCode.END: 12322 newVal = this._valueMax(); 12323 break; 12324 case $.ui.keyCode.PAGE_UP: 12325 newVal = this._trimAlignValue( 12326 curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages ) 12327 ); 12328 break; 12329 case $.ui.keyCode.PAGE_DOWN: 12330 newVal = this._trimAlignValue( 12331 curVal - ( (this._valueMax() - this._valueMin()) / this.numPages ) ); 12332 break; 12333 case $.ui.keyCode.UP: 12334 case $.ui.keyCode.RIGHT: 12335 if ( curVal === this._valueMax() ) { 12336 return; 12337 } 12338 newVal = this._trimAlignValue( curVal + step ); 12339 break; 12340 case $.ui.keyCode.DOWN: 12341 case $.ui.keyCode.LEFT: 12342 if ( curVal === this._valueMin() ) { 12343 return; 12344 } 12345 newVal = this._trimAlignValue( curVal - step ); 12346 break; 12347 } 12348 12349 this._slide( event, index, newVal ); 12350 }, 12351 keyup: function( event ) { 12352 var index = $( event.target ).data( "ui-slider-handle-index" ); 12353 12354 if ( this._keySliding ) { 12355 this._keySliding = false; 12356 this._stop( event, index ); 12357 this._change( event, index ); 12358 $( event.target ).removeClass( "ui-state-active" ); 12359 } 12360 } 12361 } 12362 }); 12363 12364 12365 /*! 12366 * jQuery UI Spinner 1.11.4 12367 * http://jqueryui.com 12368 * 12369 * Copyright jQuery Foundation and other contributors 12370 * Released under the MIT license. 12371 * http://jquery.org/license 12372 * 12373 * http://api.jqueryui.com/spinner/ 12374 */ 12375 12376 12377 function spinner_modifier( fn ) { 12378 return function() { 12379 var previous = this.element.val(); 12380 fn.apply( this, arguments ); 12381 this._refresh(); 12382 if ( previous !== this.element.val() ) { 12383 this._trigger( "change" ); 12384 } 12385 }; 12386 } 12387 12388 var spinner = $.widget( "ui.spinner", { 12389 version: "1.11.4", 12390 defaultElement: "<input>", 12391 widgetEventPrefix: "spin", 12392 options: { 12393 culture: null, 12394 icons: { 12395 down: "ui-icon-triangle-1-s", 12396 up: "ui-icon-triangle-1-n" 12397 }, 12398 incremental: true, 12399 max: null, 12400 min: null, 12401 numberFormat: null, 12402 page: 10, 12403 step: 1, 12404 12405 change: null, 12406 spin: null, 12407 start: null, 12408 stop: null 12409 }, 12410 12411 _create: function() { 12412 // handle string values that need to be parsed 12413 this._setOption( "max", this.options.max ); 12414 this._setOption( "min", this.options.min ); 12415 this._setOption( "step", this.options.step ); 12416 12417 // Only format if there is a value, prevents the field from being marked 12418 // as invalid in Firefox, see #9573. 12419 if ( this.value() !== "" ) { 12420 // Format the value, but don't constrain. 12421 this._value( this.element.val(), true ); 12422 } 12423 12424 this._draw(); 12425 this._on( this._events ); 12426 this._refresh(); 12427 12428 // turning off autocomplete prevents the browser from remembering the 12429 // value when navigating through history, so we re-enable autocomplete 12430 // if the page is unloaded before the widget is destroyed. #7790 12431 this._on( this.window, { 12432 beforeunload: function() { 12433 this.element.removeAttr( "autocomplete" ); 12434 } 12435 }); 12436 }, 12437 12438 _getCreateOptions: function() { 12439 var options = {}, 12440 element = this.element; 12441 12442 $.each( [ "min", "max", "step" ], function( i, option ) { 12443 var value = element.attr( option ); 12444 if ( value !== undefined && value.length ) { 12445 options[ option ] = value; 12446 } 12447 }); 12448 12449 return options; 12450 }, 12451 12452 _events: { 12453 keydown: function( event ) { 12454 if ( this._start( event ) && this._keydown( event ) ) { 12455 event.preventDefault(); 12456 } 12457 }, 12458 keyup: "_stop", 12459 focus: function() { 12460 this.previous = this.element.val(); 12461 }, 12462 blur: function( event ) { 12463 if ( this.cancelBlur ) { 12464 delete this.cancelBlur; 12465 return; 12466 } 12467 12468 this._stop(); 12469 this._refresh(); 12470 if ( this.previous !== this.element.val() ) { 12471 this._trigger( "change", event ); 12472 } 12473 }, 12474 mousewheel: function( event, delta ) { 12475 if ( !delta ) { 12476 return; 12477 } 12478 if ( !this.spinning && !this._start( event ) ) { 12479 return false; 12480 } 12481 12482 this._spin( (delta > 0 ? 1 : -1) * this.options.step, event ); 12483 clearTimeout( this.mousewheelTimer ); 12484 this.mousewheelTimer = this._delay(function() { 12485 if ( this.spinning ) { 12486 this._stop( event ); 12487 } 12488 }, 100 ); 12489 event.preventDefault(); 12490 }, 12491 "mousedown .ui-spinner-button": function( event ) { 12492 var previous; 12493 12494 // We never want the buttons to have focus; whenever the user is 12495 // interacting with the spinner, the focus should be on the input. 12496 // If the input is focused then this.previous is properly set from 12497 // when the input first received focus. If the input is not focused 12498 // then we need to set this.previous based on the value before spinning. 12499 previous = this.element[0] === this.document[0].activeElement ? 12500 this.previous : this.element.val(); 12501 function checkFocus() { 12502 var isActive = this.element[0] === this.document[0].activeElement; 12503 if ( !isActive ) { 12504 this.element.focus(); 12505 this.previous = previous; 12506 // support: IE 12507 // IE sets focus asynchronously, so we need to check if focus 12508 // moved off of the input because the user clicked on the button. 12509 this._delay(function() { 12510 this.previous = previous; 12511 }); 12512 } 12513 } 12514 12515 // ensure focus is on (or stays on) the text field 12516 event.preventDefault(); 12517 checkFocus.call( this ); 12518 12519 // support: IE 12520 // IE doesn't prevent moving focus even with event.preventDefault() 12521 // so we set a flag to know when we should ignore the blur event 12522 // and check (again) if focus moved off of the input. 12523 this.cancelBlur = true; 12524 this._delay(function() { 12525 delete this.cancelBlur; 12526 checkFocus.call( this ); 12527 }); 12528 12529 if ( this._start( event ) === false ) { 12530 return; 12531 } 12532 12533 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 12534 }, 12535 "mouseup .ui-spinner-button": "_stop", 12536 "mouseenter .ui-spinner-button": function( event ) { 12537 // button will add ui-state-active if mouse was down while mouseleave and kept down 12538 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) { 12539 return; 12540 } 12541 12542 if ( this._start( event ) === false ) { 12543 return false; 12544 } 12545 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 12546 }, 12547 // TODO: do we really want to consider this a stop? 12548 // shouldn't we just stop the repeater and wait until mouseup before 12549 // we trigger the stop event? 12550 "mouseleave .ui-spinner-button": "_stop" 12551 }, 12552 12553 _draw: function() { 12554 var uiSpinner = this.uiSpinner = this.element 12555 .addClass( "ui-spinner-input" ) 12556 .attr( "autocomplete", "off" ) 12557 .wrap( this._uiSpinnerHtml() ) 12558 .parent() 12559 // add buttons 12560 .append( this._buttonHtml() ); 12561 12562 this.element.attr( "role", "spinbutton" ); 12563 12564 // button bindings 12565 this.buttons = uiSpinner.find( ".ui-spinner-button" ) 12566 .attr( "tabIndex", -1 ) 12567 .button() 12568 .removeClass( "ui-corner-all" ); 12569 12570 // IE 6 doesn't understand height: 50% for the buttons 12571 // unless the wrapper has an explicit height 12572 if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) && 12573 uiSpinner.height() > 0 ) { 12574 uiSpinner.height( uiSpinner.height() ); 12575 } 12576 12577 // disable spinner if element was already disabled 12578 if ( this.options.disabled ) { 12579 this.disable(); 12580 } 12581 }, 12582 12583 _keydown: function( event ) { 12584 var options = this.options, 12585 keyCode = $.ui.keyCode; 12586 12587 switch ( event.keyCode ) { 12588 case keyCode.UP: 12589 this._repeat( null, 1, event ); 12590 return true; 12591 case keyCode.DOWN: 12592 this._repeat( null, -1, event ); 12593 return true; 12594 case keyCode.PAGE_UP: 12595 this._repeat( null, options.page, event ); 12596 return true; 12597 case keyCode.PAGE_DOWN: 12598 this._repeat( null, -options.page, event ); 12599 return true; 12600 } 12601 12602 return false; 12603 }, 12604 12605 _uiSpinnerHtml: function() { 12606 return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"; 12607 }, 12608 12609 _buttonHtml: function() { 12610 return "" + 12611 "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" + 12612 "<span class='ui-icon " + this.options.icons.up + "'>▲</span>" + 12613 "</a>" + 12614 "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" + 12615 "<span class='ui-icon " + this.options.icons.down + "'>▼</span>" + 12616 "</a>"; 12617 }, 12618 12619 _start: function( event ) { 12620 if ( !this.spinning && this._trigger( "start", event ) === false ) { 12621 return false; 12622 } 12623 12624 if ( !this.counter ) { 12625 this.counter = 1; 12626 } 12627 this.spinning = true; 12628 return true; 12629 }, 12630 12631 _repeat: function( i, steps, event ) { 12632 i = i || 500; 12633 12634 clearTimeout( this.timer ); 12635 this.timer = this._delay(function() { 12636 this._repeat( 40, steps, event ); 12637 }, i ); 12638 12639 this._spin( steps * this.options.step, event ); 12640 }, 12641 12642 _spin: function( step, event ) { 12643 var value = this.value() || 0; 12644 12645 if ( !this.counter ) { 12646 this.counter = 1; 12647 } 12648 12649 value = this._adjustValue( value + step * this._increment( this.counter ) ); 12650 12651 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) { 12652 this._value( value ); 12653 this.counter++; 12654 } 12655 }, 12656 12657 _increment: function( i ) { 12658 var incremental = this.options.incremental; 12659 12660 if ( incremental ) { 12661 return $.isFunction( incremental ) ? 12662 incremental( i ) : 12663 Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 ); 12664 } 12665 12666 return 1; 12667 }, 12668 12669 _precision: function() { 12670 var precision = this._precisionOf( this.options.step ); 12671 if ( this.options.min !== null ) { 12672 precision = Math.max( precision, this._precisionOf( this.options.min ) ); 12673 } 12674 return precision; 12675 }, 12676 12677 _precisionOf: function( num ) { 12678 var str = num.toString(), 12679 decimal = str.indexOf( "." ); 12680 return decimal === -1 ? 0 : str.length - decimal - 1; 12681 }, 12682 12683 _adjustValue: function( value ) { 12684 var base, aboveMin, 12685 options = this.options; 12686 12687 // make sure we're at a valid step 12688 // - find out where we are relative to the base (min or 0) 12689 base = options.min !== null ? options.min : 0; 12690 aboveMin = value - base; 12691 // - round to the nearest step 12692 aboveMin = Math.round(aboveMin / options.step) * options.step; 12693 // - rounding is based on 0, so adjust back to our base 12694 value = base + aboveMin; 12695 12696 // fix precision from bad JS floating point math 12697 value = parseFloat( value.toFixed( this._precision() ) ); 12698 12699 // clamp the value 12700 if ( options.max !== null && value > options.max) { 12701 return options.max; 12702 } 12703 if ( options.min !== null && value < options.min ) { 12704 return options.min; 12705 } 12706 12707 return value; 12708 }, 12709 12710 _stop: function( event ) { 12711 if ( !this.spinning ) { 12712 return; 12713 } 12714 12715 clearTimeout( this.timer ); 12716 clearTimeout( this.mousewheelTimer ); 12717 this.counter = 0; 12718 this.spinning = false; 12719 this._trigger( "stop", event ); 12720 }, 12721 12722 _setOption: function( key, value ) { 12723 if ( key === "culture" || key === "numberFormat" ) { 12724 var prevValue = this._parse( this.element.val() ); 12725 this.options[ key ] = value; 12726 this.element.val( this._format( prevValue ) ); 12727 return; 12728 } 12729 12730 if ( key === "max" || key === "min" || key === "step" ) { 12731 if ( typeof value === "string" ) { 12732 value = this._parse( value ); 12733 } 12734 } 12735 if ( key === "icons" ) { 12736 this.buttons.first().find( ".ui-icon" ) 12737 .removeClass( this.options.icons.up ) 12738 .addClass( value.up ); 12739 this.buttons.last().find( ".ui-icon" ) 12740 .removeClass( this.options.icons.down ) 12741 .addClass( value.down ); 12742 } 12743 12744 this._super( key, value ); 12745 12746 if ( key === "disabled" ) { 12747 this.widget().toggleClass( "ui-state-disabled", !!value ); 12748 this.element.prop( "disabled", !!value ); 12749 this.buttons.button( value ? "disable" : "enable" ); 12750 } 12751 }, 12752 12753 _setOptions: spinner_modifier(function( options ) { 12754 this._super( options ); 12755 }), 12756 12757 _parse: function( val ) { 12758 if ( typeof val === "string" && val !== "" ) { 12759 val = window.Globalize && this.options.numberFormat ? 12760 Globalize.parseFloat( val, 10, this.options.culture ) : +val; 12761 } 12762 return val === "" || isNaN( val ) ? null : val; 12763 }, 12764 12765 _format: function( value ) { 12766 if ( value === "" ) { 12767 return ""; 12768 } 12769 return window.Globalize && this.options.numberFormat ? 12770 Globalize.format( value, this.options.numberFormat, this.options.culture ) : 12771 value; 12772 }, 12773 12774 _refresh: function() { 12775 this.element.attr({ 12776 "aria-valuemin": this.options.min, 12777 "aria-valuemax": this.options.max, 12778 // TODO: what should we do with values that can't be parsed? 12779 "aria-valuenow": this._parse( this.element.val() ) 12780 }); 12781 }, 12782 12783 isValid: function() { 12784 var value = this.value(); 12785 12786 // null is invalid 12787 if ( value === null ) { 12788 return false; 12789 } 12790 12791 // if value gets adjusted, it's invalid 12792 return value === this._adjustValue( value ); 12793 }, 12794 12795 // update the value without triggering change 12796 _value: function( value, allowAny ) { 12797 var parsed; 12798 if ( value !== "" ) { 12799 parsed = this._parse( value ); 12800 if ( parsed !== null ) { 12801 if ( !allowAny ) { 12802 parsed = this._adjustValue( parsed ); 12803 } 12804 value = this._format( parsed ); 12805 } 12806 } 12807 this.element.val( value ); 12808 this._refresh(); 12809 }, 12810 12811 _destroy: function() { 12812 this.element 12813 .removeClass( "ui-spinner-input" ) 12814 .prop( "disabled", false ) 12815 .removeAttr( "autocomplete" ) 12816 .removeAttr( "role" ) 12817 .removeAttr( "aria-valuemin" ) 12818 .removeAttr( "aria-valuemax" ) 12819 .removeAttr( "aria-valuenow" ); 12820 this.uiSpinner.replaceWith( this.element ); 12821 }, 12822 12823 stepUp: spinner_modifier(function( steps ) { 12824 this._stepUp( steps ); 12825 }), 12826 _stepUp: function( steps ) { 12827 if ( this._start() ) { 12828 this._spin( (steps || 1) * this.options.step ); 12829 this._stop(); 12830 } 12831 }, 12832 12833 stepDown: spinner_modifier(function( steps ) { 12834 this._stepDown( steps ); 12835 }), 12836 _stepDown: function( steps ) { 12837 if ( this._start() ) { 12838 this._spin( (steps || 1) * -this.options.step ); 12839 this._stop(); 12840 } 12841 }, 12842 12843 pageUp: spinner_modifier(function( pages ) { 12844 this._stepUp( (pages || 1) * this.options.page ); 12845 }), 12846 12847 pageDown: spinner_modifier(function( pages ) { 12848 this._stepDown( (pages || 1) * this.options.page ); 12849 }), 12850 12851 value: function( newVal ) { 12852 if ( !arguments.length ) { 12853 return this._parse( this.element.val() ); 12854 } 12855 spinner_modifier( this._value ).call( this, newVal ); 12856 }, 12857 12858 widget: function() { 12859 return this.uiSpinner; 12860 } 12861 }); 12862 12863 12864 /*! 12865 * jQuery UI Tabs 1.11.4 12866 * http://jqueryui.com 12867 * 12868 * Copyright jQuery Foundation and other contributors 12869 * Released under the MIT license. 12870 * http://jquery.org/license 12871 * 12872 * http://api.jqueryui.com/tabs/ 12873 */ 12874 12875 12876 var tabs = $.widget( "ui.tabs", { 12877 version: "1.11.4", 12878 delay: 300, 12879 options: { 12880 active: null, 12881 collapsible: false, 12882 event: "click", 12883 heightStyle: "content", 12884 hide: null, 12885 show: null, 12886 12887 // callbacks 12888 activate: null, 12889 beforeActivate: null, 12890 beforeLoad: null, 12891 load: null 12892 }, 12893 12894 _isLocal: (function() { 12895 var rhash = /#.*$/; 12896 12897 return function( anchor ) { 12898 var anchorUrl, locationUrl; 12899 12900 // support: IE7 12901 // IE7 doesn't normalize the href property when set via script (#9317) 12902 anchor = anchor.cloneNode( false ); 12903 12904 anchorUrl = anchor.href.replace( rhash, "" ); 12905 locationUrl = location.href.replace( rhash, "" ); 12906 12907 // decoding may throw an error if the URL isn't UTF-8 (#9518) 12908 try { 12909 anchorUrl = decodeURIComponent( anchorUrl ); 12910 } catch ( error ) {} 12911 try { 12912 locationUrl = decodeURIComponent( locationUrl ); 12913 } catch ( error ) {} 12914 12915 return anchor.hash.length > 1 && anchorUrl === locationUrl; 12916 }; 12917 })(), 12918 12919 _create: function() { 12920 var that = this, 12921 options = this.options; 12922 12923 this.running = false; 12924 12925 this.element 12926 .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ) 12927 .toggleClass( "ui-tabs-collapsible", options.collapsible ); 12928 12929 this._processTabs(); 12930 options.active = this._initialActive(); 12931 12932 // Take disabling tabs via class attribute from HTML 12933 // into account and update option properly. 12934 if ( $.isArray( options.disabled ) ) { 12935 options.disabled = $.unique( options.disabled.concat( 12936 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { 12937 return that.tabs.index( li ); 12938 }) 12939 ) ).sort(); 12940 } 12941 12942 // check for length avoids error when initializing empty list 12943 if ( this.options.active !== false && this.anchors.length ) { 12944 this.active = this._findActive( options.active ); 12945 } else { 12946 this.active = $(); 12947 } 12948 12949 this._refresh(); 12950 12951 if ( this.active.length ) { 12952 this.load( options.active ); 12953 } 12954 }, 12955 12956 _initialActive: function() { 12957 var active = this.options.active, 12958 collapsible = this.options.collapsible, 12959 locationHash = location.hash.substring( 1 ); 12960 12961 if ( active === null ) { 12962 // check the fragment identifier in the URL 12963 if ( locationHash ) { 12964 this.tabs.each(function( i, tab ) { 12965 if ( $( tab ).attr( "aria-controls" ) === locationHash ) { 12966 active = i; 12967 return false; 12968 } 12969 }); 12970 } 12971 12972 // check for a tab marked active via a class 12973 if ( active === null ) { 12974 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); 12975 } 12976 12977 // no active tab, set to false 12978 if ( active === null || active === -1 ) { 12979 active = this.tabs.length ? 0 : false; 12980 } 12981 } 12982 12983 // handle numbers: negative, out of range 12984 if ( active !== false ) { 12985 active = this.tabs.index( this.tabs.eq( active ) ); 12986 if ( active === -1 ) { 12987 active = collapsible ? false : 0; 12988 } 12989 } 12990 12991 // don't allow collapsible: false and active: false 12992 if ( !collapsible && active === false && this.anchors.length ) { 12993 active = 0; 12994 } 12995 12996 return active; 12997 }, 12998 12999 _getCreateEventData: function() { 13000 return { 13001 tab: this.active, 13002 panel: !this.active.length ? $() : this._getPanelForTab( this.active ) 13003 }; 13004 }, 13005 13006 _tabKeydown: function( event ) { 13007 var focusedTab = $( this.document[0].activeElement ).closest( "li" ), 13008 selectedIndex = this.tabs.index( focusedTab ), 13009 goingForward = true; 13010 13011 if ( this._handlePageNav( event ) ) { 13012 return; 13013 } 13014 13015 switch ( event.keyCode ) { 13016 case $.ui.keyCode.RIGHT: 13017 case $.ui.keyCode.DOWN: 13018 selectedIndex++; 13019 break; 13020 case $.ui.keyCode.UP: 13021 case $.ui.keyCode.LEFT: 13022 goingForward = false; 13023 selectedIndex--; 13024 break; 13025 case $.ui.keyCode.END: 13026 selectedIndex = this.anchors.length - 1; 13027 break; 13028 case $.ui.keyCode.HOME: 13029 selectedIndex = 0; 13030 break; 13031 case $.ui.keyCode.SPACE: 13032 // Activate only, no collapsing 13033 event.preventDefault(); 13034 clearTimeout( this.activating ); 13035 this._activate( selectedIndex ); 13036 return; 13037 case $.ui.keyCode.ENTER: 13038 // Toggle (cancel delayed activation, allow collapsing) 13039 event.preventDefault(); 13040 clearTimeout( this.activating ); 13041 // Determine if we should collapse or activate 13042 this._activate( selectedIndex === this.options.active ? false : selectedIndex ); 13043 return; 13044 default: 13045 return; 13046 } 13047 13048 // Focus the appropriate tab, based on which key was pressed 13049 event.preventDefault(); 13050 clearTimeout( this.activating ); 13051 selectedIndex = this._focusNextTab( selectedIndex, goingForward ); 13052 13053 // Navigating with control/command key will prevent automatic activation 13054 if ( !event.ctrlKey && !event.metaKey ) { 13055 13056 // Update aria-selected immediately so that AT think the tab is already selected. 13057 // Otherwise AT may confuse the user by stating that they need to activate the tab, 13058 // but the tab will already be activated by the time the announcement finishes. 13059 focusedTab.attr( "aria-selected", "false" ); 13060 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); 13061 13062 this.activating = this._delay(function() { 13063 this.option( "active", selectedIndex ); 13064 }, this.delay ); 13065 } 13066 }, 13067 13068 _panelKeydown: function( event ) { 13069 if ( this._handlePageNav( event ) ) { 13070 return; 13071 } 13072 13073 // Ctrl+up moves focus to the current tab 13074 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { 13075 event.preventDefault(); 13076 this.active.focus(); 13077 } 13078 }, 13079 13080 // Alt+page up/down moves focus to the previous/next tab (and activates) 13081 _handlePageNav: function( event ) { 13082 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { 13083 this._activate( this._focusNextTab( this.options.active - 1, false ) ); 13084 return true; 13085 } 13086 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { 13087 this._activate( this._focusNextTab( this.options.active + 1, true ) ); 13088 return true; 13089 } 13090 }, 13091 13092 _findNextTab: function( index, goingForward ) { 13093 var lastTabIndex = this.tabs.length - 1; 13094 13095 function constrain() { 13096 if ( index > lastTabIndex ) { 13097 index = 0; 13098 } 13099 if ( index < 0 ) { 13100 index = lastTabIndex; 13101 } 13102 return index; 13103 } 13104 13105 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { 13106 index = goingForward ? index + 1 : index - 1; 13107 } 13108 13109 return index; 13110 }, 13111 13112 _focusNextTab: function( index, goingForward ) { 13113 index = this._findNextTab( index, goingForward ); 13114 this.tabs.eq( index ).focus(); 13115 return index; 13116 }, 13117 13118 _setOption: function( key, value ) { 13119 if ( key === "active" ) { 13120 // _activate() will handle invalid values and update this.options 13121 this._activate( value ); 13122 return; 13123 } 13124 13125 if ( key === "disabled" ) { 13126 // don't use the widget factory's disabled handling 13127 this._setupDisabled( value ); 13128 return; 13129 } 13130 13131 this._super( key, value); 13132 13133 if ( key === "collapsible" ) { 13134 this.element.toggleClass( "ui-tabs-collapsible", value ); 13135 // Setting collapsible: false while collapsed; open first panel 13136 if ( !value && this.options.active === false ) { 13137 this._activate( 0 ); 13138 } 13139 } 13140 13141 if ( key === "event" ) { 13142 this._setupEvents( value ); 13143 } 13144 13145 if ( key === "heightStyle" ) { 13146 this._setupHeightStyle( value ); 13147 } 13148 }, 13149 13150 _sanitizeSelector: function( hash ) { 13151 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : ""; 13152 }, 13153 13154 refresh: function() { 13155 var options = this.options, 13156 lis = this.tablist.children( ":has(a[href])" ); 13157 13158 // get disabled tabs from class attribute from HTML 13159 // this will get converted to a boolean if needed in _refresh() 13160 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { 13161 return lis.index( tab ); 13162 }); 13163 13164 this._processTabs(); 13165 13166 // was collapsed or no tabs 13167 if ( options.active === false || !this.anchors.length ) { 13168 options.active = false; 13169 this.active = $(); 13170 // was active, but active tab is gone 13171 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { 13172 // all remaining tabs are disabled 13173 if ( this.tabs.length === options.disabled.length ) { 13174 options.active = false; 13175 this.active = $(); 13176 // activate previous tab 13177 } else { 13178 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); 13179 } 13180 // was active, active tab still exists 13181 } else { 13182 // make sure active index is correct 13183 options.active = this.tabs.index( this.active ); 13184 } 13185 13186 this._refresh(); 13187 }, 13188 13189 _refresh: function() { 13190 this._setupDisabled( this.options.disabled ); 13191 this._setupEvents( this.options.event ); 13192 this._setupHeightStyle( this.options.heightStyle ); 13193 13194 this.tabs.not( this.active ).attr({ 13195 "aria-selected": "false", 13196 "aria-expanded": "false", 13197 tabIndex: -1 13198 }); 13199 this.panels.not( this._getPanelForTab( this.active ) ) 13200 .hide() 13201 .attr({ 13202 "aria-hidden": "true" 13203 }); 13204 13205 // Make sure one tab is in the tab order 13206 if ( !this.active.length ) { 13207 this.tabs.eq( 0 ).attr( "tabIndex", 0 ); 13208 } else { 13209 this.active 13210 .addClass( "ui-tabs-active ui-state-active" ) 13211 .attr({ 13212 "aria-selected": "true", 13213 "aria-expanded": "true", 13214 tabIndex: 0 13215 }); 13216 this._getPanelForTab( this.active ) 13217 .show() 13218 .attr({ 13219 "aria-hidden": "false" 13220 }); 13221 } 13222 }, 13223 13224 _processTabs: function() { 13225 var that = this, 13226 prevTabs = this.tabs, 13227 prevAnchors = this.anchors, 13228 prevPanels = this.panels; 13229 13230 this.tablist = this._getList() 13231 .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) 13232 .attr( "role", "tablist" ) 13233 13234 // Prevent users from focusing disabled tabs via click 13235 .delegate( "> li", "mousedown" + this.eventNamespace, function( event ) { 13236 if ( $( this ).is( ".ui-state-disabled" ) ) { 13237 event.preventDefault(); 13238 } 13239 }) 13240 13241 // support: IE <9 13242 // Preventing the default action in mousedown doesn't prevent IE 13243 // from focusing the element, so if the anchor gets focused, blur. 13244 // We don't have to worry about focusing the previously focused 13245 // element since clicking on a non-focusable element should focus 13246 // the body anyway. 13247 .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() { 13248 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) { 13249 this.blur(); 13250 } 13251 }); 13252 13253 this.tabs = this.tablist.find( "> li:has(a[href])" ) 13254 .addClass( "ui-state-default ui-corner-top" ) 13255 .attr({ 13256 role: "tab", 13257 tabIndex: -1 13258 }); 13259 13260 this.anchors = this.tabs.map(function() { 13261 return $( "a", this )[ 0 ]; 13262 }) 13263 .addClass( "ui-tabs-anchor" ) 13264 .attr({ 13265 role: "presentation", 13266 tabIndex: -1 13267 }); 13268 13269 this.panels = $(); 13270 13271 this.anchors.each(function( i, anchor ) { 13272 var selector, panel, panelId, 13273 anchorId = $( anchor ).uniqueId().attr( "id" ), 13274 tab = $( anchor ).closest( "li" ), 13275 originalAriaControls = tab.attr( "aria-controls" ); 13276 13277 // inline tab 13278 if ( that._isLocal( anchor ) ) { 13279 selector = anchor.hash; 13280 panelId = selector.substring( 1 ); 13281 panel = that.element.find( that._sanitizeSelector( selector ) ); 13282 // remote tab 13283 } else { 13284 // If the tab doesn't already have aria-controls, 13285 // generate an id by using a throw-away element 13286 panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id; 13287 selector = "#" + panelId; 13288 panel = that.element.find( selector ); 13289 if ( !panel.length ) { 13290 panel = that._createPanel( panelId ); 13291 panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); 13292 } 13293 panel.attr( "aria-live", "polite" ); 13294 } 13295 13296 if ( panel.length) { 13297 that.panels = that.panels.add( panel ); 13298 } 13299 if ( originalAriaControls ) { 13300 tab.data( "ui-tabs-aria-controls", originalAriaControls ); 13301 } 13302 tab.attr({ 13303 "aria-controls": panelId, 13304 "aria-labelledby": anchorId 13305 }); 13306 panel.attr( "aria-labelledby", anchorId ); 13307 }); 13308 13309 this.panels 13310 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) 13311 .attr( "role", "tabpanel" ); 13312 13313 // Avoid memory leaks (#10056) 13314 if ( prevTabs ) { 13315 this._off( prevTabs.not( this.tabs ) ); 13316 this._off( prevAnchors.not( this.anchors ) ); 13317 this._off( prevPanels.not( this.panels ) ); 13318 } 13319 }, 13320 13321 // allow overriding how to find the list for rare usage scenarios (#7715) 13322 _getList: function() { 13323 return this.tablist || this.element.find( "ol,ul" ).eq( 0 ); 13324 }, 13325 13326 _createPanel: function( id ) { 13327 return $( "<div>" ) 13328 .attr( "id", id ) 13329 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) 13330 .data( "ui-tabs-destroy", true ); 13331 }, 13332 13333 _setupDisabled: function( disabled ) { 13334 if ( $.isArray( disabled ) ) { 13335 if ( !disabled.length ) { 13336 disabled = false; 13337 } else if ( disabled.length === this.anchors.length ) { 13338 disabled = true; 13339 } 13340 } 13341 13342 // disable tabs 13343 for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) { 13344 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { 13345 $( li ) 13346 .addClass( "ui-state-disabled" ) 13347 .attr( "aria-disabled", "true" ); 13348 } else { 13349 $( li ) 13350 .removeClass( "ui-state-disabled" ) 13351 .removeAttr( "aria-disabled" ); 13352 } 13353 } 13354 13355 this.options.disabled = disabled; 13356 }, 13357 13358 _setupEvents: function( event ) { 13359 var events = {}; 13360 if ( event ) { 13361 $.each( event.split(" "), function( index, eventName ) { 13362 events[ eventName ] = "_eventHandler"; 13363 }); 13364 } 13365 13366 this._off( this.anchors.add( this.tabs ).add( this.panels ) ); 13367 // Always prevent the default action, even when disabled 13368 this._on( true, this.anchors, { 13369 click: function( event ) { 13370 event.preventDefault(); 13371 } 13372 }); 13373 this._on( this.anchors, events ); 13374 this._on( this.tabs, { keydown: "_tabKeydown" } ); 13375 this._on( this.panels, { keydown: "_panelKeydown" } ); 13376 13377 this._focusable( this.tabs ); 13378 this._hoverable( this.tabs ); 13379 }, 13380 13381 _setupHeightStyle: function( heightStyle ) { 13382 var maxHeight, 13383 parent = this.element.parent(); 13384 13385 if ( heightStyle === "fill" ) { 13386 maxHeight = parent.height(); 13387 maxHeight -= this.element.outerHeight() - this.element.height(); 13388 13389 this.element.siblings( ":visible" ).each(function() { 13390 var elem = $( this ), 13391 position = elem.css( "position" ); 13392 13393 if ( position === "absolute" || position === "fixed" ) { 13394 return; 13395 } 13396 maxHeight -= elem.outerHeight( true ); 13397 }); 13398 13399 this.element.children().not( this.panels ).each(function() { 13400 maxHeight -= $( this ).outerHeight( true ); 13401 }); 13402 13403 this.panels.each(function() { 13404 $( this ).height( Math.max( 0, maxHeight - 13405 $( this ).innerHeight() + $( this ).height() ) ); 13406 }) 13407 .css( "overflow", "auto" ); 13408 } else if ( heightStyle === "auto" ) { 13409 maxHeight = 0; 13410 this.panels.each(function() { 13411 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); 13412 }).height( maxHeight ); 13413 } 13414 }, 13415 13416 _eventHandler: function( event ) { 13417 var options = this.options, 13418 active = this.active, 13419 anchor = $( event.currentTarget ), 13420 tab = anchor.closest( "li" ), 13421 clickedIsActive = tab[ 0 ] === active[ 0 ], 13422 collapsing = clickedIsActive && options.collapsible, 13423 toShow = collapsing ? $() : this._getPanelForTab( tab ), 13424 toHide = !active.length ? $() : this._getPanelForTab( active ), 13425 eventData = { 13426 oldTab: active, 13427 oldPanel: toHide, 13428 newTab: collapsing ? $() : tab, 13429 newPanel: toShow 13430 }; 13431 13432 event.preventDefault(); 13433 13434 if ( tab.hasClass( "ui-state-disabled" ) || 13435 // tab is already loading 13436 tab.hasClass( "ui-tabs-loading" ) || 13437 // can't switch durning an animation 13438 this.running || 13439 // click on active header, but not collapsible 13440 ( clickedIsActive && !options.collapsible ) || 13441 // allow canceling activation 13442 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 13443 return; 13444 } 13445 13446 options.active = collapsing ? false : this.tabs.index( tab ); 13447 13448 this.active = clickedIsActive ? $() : tab; 13449 if ( this.xhr ) { 13450 this.xhr.abort(); 13451 } 13452 13453 if ( !toHide.length && !toShow.length ) { 13454 $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); 13455 } 13456 13457 if ( toShow.length ) { 13458 this.load( this.tabs.index( tab ), event ); 13459 } 13460 this._toggle( event, eventData ); 13461 }, 13462 13463 // handles show/hide for selecting tabs 13464 _toggle: function( event, eventData ) { 13465 var that = this, 13466 toShow = eventData.newPanel, 13467 toHide = eventData.oldPanel; 13468 13469 this.running = true; 13470 13471 function complete() { 13472 that.running = false; 13473 that._trigger( "activate", event, eventData ); 13474 } 13475 13476 function show() { 13477 eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); 13478 13479 if ( toShow.length && that.options.show ) { 13480 that._show( toShow, that.options.show, complete ); 13481 } else { 13482 toShow.show(); 13483 complete(); 13484 } 13485 } 13486 13487 // start out by hiding, then showing, then completing 13488 if ( toHide.length && this.options.hide ) { 13489 this._hide( toHide, this.options.hide, function() { 13490 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); 13491 show(); 13492 }); 13493 } else { 13494 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); 13495 toHide.hide(); 13496 show(); 13497 } 13498 13499 toHide.attr( "aria-hidden", "true" ); 13500 eventData.oldTab.attr({ 13501 "aria-selected": "false", 13502 "aria-expanded": "false" 13503 }); 13504 // If we're switching tabs, remove the old tab from the tab order. 13505 // If we're opening from collapsed state, remove the previous tab from the tab order. 13506 // If we're collapsing, then keep the collapsing tab in the tab order. 13507 if ( toShow.length && toHide.length ) { 13508 eventData.oldTab.attr( "tabIndex", -1 ); 13509 } else if ( toShow.length ) { 13510 this.tabs.filter(function() { 13511 return $( this ).attr( "tabIndex" ) === 0; 13512 }) 13513 .attr( "tabIndex", -1 ); 13514 } 13515 13516 toShow.attr( "aria-hidden", "false" ); 13517 eventData.newTab.attr({ 13518 "aria-selected": "true", 13519 "aria-expanded": "true", 13520 tabIndex: 0 13521 }); 13522 }, 13523 13524 _activate: function( index ) { 13525 var anchor, 13526 active = this._findActive( index ); 13527 13528 // trying to activate the already active panel 13529 if ( active[ 0 ] === this.active[ 0 ] ) { 13530 return; 13531 } 13532 13533 // trying to collapse, simulate a click on the current active header 13534 if ( !active.length ) { 13535 active = this.active; 13536 } 13537 13538 anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; 13539 this._eventHandler({ 13540 target: anchor, 13541 currentTarget: anchor, 13542 preventDefault: $.noop 13543 }); 13544 }, 13545 13546 _findActive: function( index ) { 13547 return index === false ? $() : this.tabs.eq( index ); 13548 }, 13549 13550 _getIndex: function( index ) { 13551 // meta-function to give users option to provide a href string instead of a numerical index. 13552 if ( typeof index === "string" ) { 13553 index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) ); 13554 } 13555 13556 return index; 13557 }, 13558 13559 _destroy: function() { 13560 if ( this.xhr ) { 13561 this.xhr.abort(); 13562 } 13563 13564 this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ); 13565 13566 this.tablist 13567 .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) 13568 .removeAttr( "role" ); 13569 13570 this.anchors 13571 .removeClass( "ui-tabs-anchor" ) 13572 .removeAttr( "role" ) 13573 .removeAttr( "tabIndex" ) 13574 .removeUniqueId(); 13575 13576 this.tablist.unbind( this.eventNamespace ); 13577 13578 this.tabs.add( this.panels ).each(function() { 13579 if ( $.data( this, "ui-tabs-destroy" ) ) { 13580 $( this ).remove(); 13581 } else { 13582 $( this ) 13583 .removeClass( "ui-state-default ui-state-active ui-state-disabled " + 13584 "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" ) 13585 .removeAttr( "tabIndex" ) 13586 .removeAttr( "aria-live" ) 13587 .removeAttr( "aria-busy" ) 13588 .removeAttr( "aria-selected" ) 13589 .removeAttr( "aria-labelledby" ) 13590 .removeAttr( "aria-hidden" ) 13591 .removeAttr( "aria-expanded" ) 13592 .removeAttr( "role" ); 13593 } 13594 }); 13595 13596 this.tabs.each(function() { 13597 var li = $( this ), 13598 prev = li.data( "ui-tabs-aria-controls" ); 13599 if ( prev ) { 13600 li 13601 .attr( "aria-controls", prev ) 13602 .removeData( "ui-tabs-aria-controls" ); 13603 } else { 13604 li.removeAttr( "aria-controls" ); 13605 } 13606 }); 13607 13608 this.panels.show(); 13609 13610 if ( this.options.heightStyle !== "content" ) { 13611 this.panels.css( "height", "" ); 13612 } 13613 }, 13614 13615 enable: function( index ) { 13616 var disabled = this.options.disabled; 13617 if ( disabled === false ) { 13618 return; 13619 } 13620 13621 if ( index === undefined ) { 13622 disabled = false; 13623 } else { 13624 index = this._getIndex( index ); 13625 if ( $.isArray( disabled ) ) { 13626 disabled = $.map( disabled, function( num ) { 13627 return num !== index ? num : null; 13628 }); 13629 } else { 13630 disabled = $.map( this.tabs, function( li, num ) { 13631 return num !== index ? num : null; 13632 }); 13633 } 13634 } 13635 this._setupDisabled( disabled ); 13636 }, 13637 13638 disable: function( index ) { 13639 var disabled = this.options.disabled; 13640 if ( disabled === true ) { 13641 return; 13642 } 13643 13644 if ( index === undefined ) { 13645 disabled = true; 13646 } else { 13647 index = this._getIndex( index ); 13648 if ( $.inArray( index, disabled ) !== -1 ) { 13649 return; 13650 } 13651 if ( $.isArray( disabled ) ) { 13652 disabled = $.merge( [ index ], disabled ).sort(); 13653 } else { 13654 disabled = [ index ]; 13655 } 13656 } 13657 this._setupDisabled( disabled ); 13658 }, 13659 13660 load: function( index, event ) { 13661 index = this._getIndex( index ); 13662 var that = this, 13663 tab = this.tabs.eq( index ), 13664 anchor = tab.find( ".ui-tabs-anchor" ), 13665 panel = this._getPanelForTab( tab ), 13666 eventData = { 13667 tab: tab, 13668 panel: panel 13669 }, 13670 complete = function( jqXHR, status ) { 13671 if ( status === "abort" ) { 13672 that.panels.stop( false, true ); 13673 } 13674 13675 tab.removeClass( "ui-tabs-loading" ); 13676 panel.removeAttr( "aria-busy" ); 13677 13678 if ( jqXHR === that.xhr ) { 13679 delete that.xhr; 13680 } 13681 }; 13682 13683 // not remote 13684 if ( this._isLocal( anchor[ 0 ] ) ) { 13685 return; 13686 } 13687 13688 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); 13689 13690 // support: jQuery <1.8 13691 // jQuery <1.8 returns false if the request is canceled in beforeSend, 13692 // but as of 1.8, $.ajax() always returns a jqXHR object. 13693 if ( this.xhr && this.xhr.statusText !== "canceled" ) { 13694 tab.addClass( "ui-tabs-loading" ); 13695 panel.attr( "aria-busy", "true" ); 13696 13697 this.xhr 13698 .done(function( response, status, jqXHR ) { 13699 // support: jQuery <1.8 13700 // http://bugs.jquery.com/ticket/11778 13701 setTimeout(function() { 13702 panel.html( response ); 13703 that._trigger( "load", event, eventData ); 13704 13705 complete( jqXHR, status ); 13706 }, 1 ); 13707 }) 13708 .fail(function( jqXHR, status ) { 13709 // support: jQuery <1.8 13710 // http://bugs.jquery.com/ticket/11778 13711 setTimeout(function() { 13712 complete( jqXHR, status ); 13713 }, 1 ); 13714 }); 13715 } 13716 }, 13717 13718 _ajaxSettings: function( anchor, event, eventData ) { 13719 var that = this; 13720 return { 13721 url: anchor.attr( "href" ), 13722 beforeSend: function( jqXHR, settings ) { 13723 return that._trigger( "beforeLoad", event, 13724 $.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) ); 13725 } 13726 }; 13727 }, 13728 13729 _getPanelForTab: function( tab ) { 13730 var id = $( tab ).attr( "aria-controls" ); 13731 return this.element.find( this._sanitizeSelector( "#" + id ) ); 13732 } 13733 }); 13734 13735 13736 /*! 13737 * jQuery UI Tooltip 1.11.4 13738 * http://jqueryui.com 13739 * 13740 * Copyright jQuery Foundation and other contributors 13741 * Released under the MIT license. 13742 * http://jquery.org/license 13743 * 13744 * http://api.jqueryui.com/tooltip/ 13745 */ 13746 13747 13748 var tooltip = $.widget( "ui.tooltip", { 13749 version: "1.11.4", 13750 options: { 13751 content: function() { 13752 // support: IE<9, Opera in jQuery <1.7 13753 // .text() can't accept undefined, so coerce to a string 13754 var title = $( this ).attr( "title" ) || ""; 13755 // Escape title, since we're going from an attribute to raw HTML 13756 return $( "<a>" ).text( title ).html(); 13757 }, 13758 hide: true, 13759 // Disabled elements have inconsistent behavior across browsers (#8661) 13760 items: "[title]:not([disabled])", 13761 position: { 13762 my: "left top+15", 13763 at: "left bottom", 13764 collision: "flipfit flip" 13765 }, 13766 show: true, 13767 tooltipClass: null, 13768 track: false, 13769 13770 // callbacks 13771 close: null, 13772 open: null 13773 }, 13774 13775 _addDescribedBy: function( elem, id ) { 13776 var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ); 13777 describedby.push( id ); 13778 elem 13779 .data( "ui-tooltip-id", id ) 13780 .attr( "aria-describedby", $.trim( describedby.join( " " ) ) ); 13781 }, 13782 13783 _removeDescribedBy: function( elem ) { 13784 var id = elem.data( "ui-tooltip-id" ), 13785 describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ), 13786 index = $.inArray( id, describedby ); 13787 13788 if ( index !== -1 ) { 13789 describedby.splice( index, 1 ); 13790 } 13791 13792 elem.removeData( "ui-tooltip-id" ); 13793 describedby = $.trim( describedby.join( " " ) ); 13794 if ( describedby ) { 13795 elem.attr( "aria-describedby", describedby ); 13796 } else { 13797 elem.removeAttr( "aria-describedby" ); 13798 } 13799 }, 13800 13801 _create: function() { 13802 this._on({ 13803 mouseover: "open", 13804 focusin: "open" 13805 }); 13806 13807 // IDs of generated tooltips, needed for destroy 13808 this.tooltips = {}; 13809 13810 // IDs of parent tooltips where we removed the title attribute 13811 this.parents = {}; 13812 13813 if ( this.options.disabled ) { 13814 this._disable(); 13815 } 13816 13817 // Append the aria-live region so tooltips announce correctly 13818 this.liveRegion = $( "<div>" ) 13819 .attr({ 13820 role: "log", 13821 "aria-live": "assertive", 13822 "aria-relevant": "additions" 13823 }) 13824 .addClass( "ui-helper-hidden-accessible" ) 13825 .appendTo( this.document[ 0 ].body ); 13826 }, 13827 13828 _setOption: function( key, value ) { 13829 var that = this; 13830 13831 if ( key === "disabled" ) { 13832 this[ value ? "_disable" : "_enable" ](); 13833 this.options[ key ] = value; 13834 // disable element style changes 13835 return; 13836 } 13837 13838 this._super( key, value ); 13839 13840 if ( key === "content" ) { 13841 $.each( this.tooltips, function( id, tooltipData ) { 13842 that._updateContent( tooltipData.element ); 13843 }); 13844 } 13845 }, 13846 13847 _disable: function() { 13848 var that = this; 13849 13850 // close open tooltips 13851 $.each( this.tooltips, function( id, tooltipData ) { 13852 var event = $.Event( "blur" ); 13853 event.target = event.currentTarget = tooltipData.element[ 0 ]; 13854 that.close( event, true ); 13855 }); 13856 13857 // remove title attributes to prevent native tooltips 13858 this.element.find( this.options.items ).addBack().each(function() { 13859 var element = $( this ); 13860 if ( element.is( "[title]" ) ) { 13861 element 13862 .data( "ui-tooltip-title", element.attr( "title" ) ) 13863 .removeAttr( "title" ); 13864 } 13865 }); 13866 }, 13867 13868 _enable: function() { 13869 // restore title attributes 13870 this.element.find( this.options.items ).addBack().each(function() { 13871 var element = $( this ); 13872 if ( element.data( "ui-tooltip-title" ) ) { 13873 element.attr( "title", element.data( "ui-tooltip-title" ) ); 13874 } 13875 }); 13876 }, 13877 13878 open: function( event ) { 13879 var that = this, 13880 target = $( event ? event.target : this.element ) 13881 // we need closest here due to mouseover bubbling, 13882 // but always pointing at the same event target 13883 .closest( this.options.items ); 13884 13885 // No element to show a tooltip for or the tooltip is already open 13886 if ( !target.length || target.data( "ui-tooltip-id" ) ) { 13887 return; 13888 } 13889 13890 if ( target.attr( "title" ) ) { 13891 target.data( "ui-tooltip-title", target.attr( "title" ) ); 13892 } 13893 13894 target.data( "ui-tooltip-open", true ); 13895 13896 // kill parent tooltips, custom or native, for hover 13897 if ( event && event.type === "mouseover" ) { 13898 target.parents().each(function() { 13899 var parent = $( this ), 13900 blurEvent; 13901 if ( parent.data( "ui-tooltip-open" ) ) { 13902 blurEvent = $.Event( "blur" ); 13903 blurEvent.target = blurEvent.currentTarget = this; 13904 that.close( blurEvent, true ); 13905 } 13906 if ( parent.attr( "title" ) ) { 13907 parent.uniqueId(); 13908 that.parents[ this.id ] = { 13909 element: this, 13910 title: parent.attr( "title" ) 13911 }; 13912 parent.attr( "title", "" ); 13913 } 13914 }); 13915 } 13916 13917 this._registerCloseHandlers( event, target ); 13918 this._updateContent( target, event ); 13919 }, 13920 13921 _updateContent: function( target, event ) { 13922 var content, 13923 contentOption = this.options.content, 13924 that = this, 13925 eventType = event ? event.type : null; 13926 13927 if ( typeof contentOption === "string" ) { 13928 return this._open( event, target, contentOption ); 13929 } 13930 13931 content = contentOption.call( target[0], function( response ) { 13932 13933 // IE may instantly serve a cached response for ajax requests 13934 // delay this call to _open so the other call to _open runs first 13935 that._delay(function() { 13936 13937 // Ignore async response if tooltip was closed already 13938 if ( !target.data( "ui-tooltip-open" ) ) { 13939 return; 13940 } 13941 13942 // jQuery creates a special event for focusin when it doesn't 13943 // exist natively. To improve performance, the native event 13944 // object is reused and the type is changed. Therefore, we can't 13945 // rely on the type being correct after the event finished 13946 // bubbling, so we set it back to the previous value. (#8740) 13947 if ( event ) { 13948 event.type = eventType; 13949 } 13950 this._open( event, target, response ); 13951 }); 13952 }); 13953 if ( content ) { 13954 this._open( event, target, content ); 13955 } 13956 }, 13957 13958 _open: function( event, target, content ) { 13959 var tooltipData, tooltip, delayedShow, a11yContent, 13960 positionOption = $.extend( {}, this.options.position ); 13961 13962 if ( !content ) { 13963 return; 13964 } 13965 13966 // Content can be updated multiple times. If the tooltip already 13967 // exists, then just update the content and bail. 13968 tooltipData = this._find( target ); 13969 if ( tooltipData ) { 13970 tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content ); 13971 return; 13972 } 13973 13974 // if we have a title, clear it to prevent the native tooltip 13975 // we have to check first to avoid defining a title if none exists 13976 // (we don't want to cause an element to start matching [title]) 13977 // 13978 // We use removeAttr only for key events, to allow IE to export the correct 13979 // accessible attributes. For mouse events, set to empty string to avoid 13980 // native tooltip showing up (happens only when removing inside mouseover). 13981 if ( target.is( "[title]" ) ) { 13982 if ( event && event.type === "mouseover" ) { 13983 target.attr( "title", "" ); 13984 } else { 13985 target.removeAttr( "title" ); 13986 } 13987 } 13988 13989 tooltipData = this._tooltip( target ); 13990 tooltip = tooltipData.tooltip; 13991 this._addDescribedBy( target, tooltip.attr( "id" ) ); 13992 tooltip.find( ".ui-tooltip-content" ).html( content ); 13993 13994 // Support: Voiceover on OS X, JAWS on IE <= 9 13995 // JAWS announces deletions even when aria-relevant="additions" 13996 // Voiceover will sometimes re-read the entire log region's contents from the beginning 13997 this.liveRegion.children().hide(); 13998 if ( content.clone ) { 13999 a11yContent = content.clone(); 14000 a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" ); 14001 } else { 14002 a11yContent = content; 14003 } 14004 $( "<div>" ).html( a11yContent ).appendTo( this.liveRegion ); 14005 14006 function position( event ) { 14007 positionOption.of = event; 14008 if ( tooltip.is( ":hidden" ) ) { 14009 return; 14010 } 14011 tooltip.position( positionOption ); 14012 } 14013 if ( this.options.track && event && /^mouse/.test( event.type ) ) { 14014 this._on( this.document, { 14015 mousemove: position 14016 }); 14017 // trigger once to override element-relative positioning 14018 position( event ); 14019 } else { 14020 tooltip.position( $.extend({ 14021 of: target 14022 }, this.options.position ) ); 14023 } 14024 14025 tooltip.hide(); 14026 14027 this._show( tooltip, this.options.show ); 14028 // Handle tracking tooltips that are shown with a delay (#8644). As soon 14029 // as the tooltip is visible, position the tooltip using the most recent 14030 // event. 14031 if ( this.options.show && this.options.show.delay ) { 14032 delayedShow = this.delayedShow = setInterval(function() { 14033 if ( tooltip.is( ":visible" ) ) { 14034 position( positionOption.of ); 14035 clearInterval( delayedShow ); 14036 } 14037 }, $.fx.interval ); 14038 } 14039 14040 this._trigger( "open", event, { tooltip: tooltip } ); 14041 }, 14042 14043 _registerCloseHandlers: function( event, target ) { 14044 var events = { 14045 keyup: function( event ) { 14046 if ( event.keyCode === $.ui.keyCode.ESCAPE ) { 14047 var fakeEvent = $.Event(event); 14048 fakeEvent.currentTarget = target[0]; 14049 this.close( fakeEvent, true ); 14050 } 14051 } 14052 }; 14053 14054 // Only bind remove handler for delegated targets. Non-delegated 14055 // tooltips will handle this in destroy. 14056 if ( target[ 0 ] !== this.element[ 0 ] ) { 14057 events.remove = function() { 14058 this._removeTooltip( this._find( target ).tooltip ); 14059 }; 14060 } 14061 14062 if ( !event || event.type === "mouseover" ) { 14063 events.mouseleave = "close"; 14064 } 14065 if ( !event || event.type === "focusin" ) { 14066 events.focusout = "close"; 14067 } 14068 this._on( true, target, events ); 14069 }, 14070 14071 close: function( event ) { 14072 var tooltip, 14073 that = this, 14074 target = $( event ? event.currentTarget : this.element ), 14075 tooltipData = this._find( target ); 14076 14077 // The tooltip may already be closed 14078 if ( !tooltipData ) { 14079 14080 // We set ui-tooltip-open immediately upon open (in open()), but only set the 14081 // additional data once there's actually content to show (in _open()). So even if the 14082 // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in 14083 // the period between open() and _open(). 14084 target.removeData( "ui-tooltip-open" ); 14085 return; 14086 } 14087 14088 tooltip = tooltipData.tooltip; 14089 14090 // disabling closes the tooltip, so we need to track when we're closing 14091 // to avoid an infinite loop in case the tooltip becomes disabled on close 14092 if ( tooltipData.closing ) { 14093 return; 14094 } 14095 14096 // Clear the interval for delayed tracking tooltips 14097 clearInterval( this.delayedShow ); 14098 14099 // only set title if we had one before (see comment in _open()) 14100 // If the title attribute has changed since open(), don't restore 14101 if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) { 14102 target.attr( "title", target.data( "ui-tooltip-title" ) ); 14103 } 14104 14105 this._removeDescribedBy( target ); 14106 14107 tooltipData.hiding = true; 14108 tooltip.stop( true ); 14109 this._hide( tooltip, this.options.hide, function() { 14110 that._removeTooltip( $( this ) ); 14111 }); 14112 14113 target.removeData( "ui-tooltip-open" ); 14114 this._off( target, "mouseleave focusout keyup" ); 14115 14116 // Remove 'remove' binding only on delegated targets 14117 if ( target[ 0 ] !== this.element[ 0 ] ) { 14118 this._off( target, "remove" ); 14119 } 14120 this._off( this.document, "mousemove" ); 14121 14122 if ( event && event.type === "mouseleave" ) { 14123 $.each( this.parents, function( id, parent ) { 14124 $( parent.element ).attr( "title", parent.title ); 14125 delete that.parents[ id ]; 14126 }); 14127 } 14128 14129 tooltipData.closing = true; 14130 this._trigger( "close", event, { tooltip: tooltip } ); 14131 if ( !tooltipData.hiding ) { 14132 tooltipData.closing = false; 14133 } 14134 }, 14135 14136 _tooltip: function( element ) { 14137 var tooltip = $( "<div>" ) 14138 .attr( "role", "tooltip" ) 14139 .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " + 14140 ( this.options.tooltipClass || "" ) ), 14141 id = tooltip.uniqueId().attr( "id" ); 14142 14143 $( "<div>" ) 14144 .addClass( "ui-tooltip-content" ) 14145 .appendTo( tooltip ); 14146 14147 tooltip.appendTo( this.document[0].body ); 14148 14149 return this.tooltips[ id ] = { 14150 element: element, 14151 tooltip: tooltip 14152 }; 14153 }, 14154 14155 _find: function( target ) { 14156 var id = target.data( "ui-tooltip-id" ); 14157 return id ? this.tooltips[ id ] : null; 14158 }, 14159 14160 _removeTooltip: function( tooltip ) { 14161 tooltip.remove(); 14162 delete this.tooltips[ tooltip.attr( "id" ) ]; 14163 }, 14164 14165 _destroy: function() { 14166 var that = this; 14167 14168 // close open tooltips 14169 $.each( this.tooltips, function( id, tooltipData ) { 14170 // Delegate to close method to handle common cleanup 14171 var event = $.Event( "blur" ), 14172 element = tooltipData.element; 14173 event.target = event.currentTarget = element[ 0 ]; 14174 that.close( event, true ); 14175 14176 // Remove immediately; destroying an open tooltip doesn't use the 14177 // hide animation 14178 $( "#" + id ).remove(); 14179 14180 // Restore the title 14181 if ( element.data( "ui-tooltip-title" ) ) { 14182 // If the title attribute has changed since open(), don't restore 14183 if ( !element.attr( "title" ) ) { 14184 element.attr( "title", element.data( "ui-tooltip-title" ) ); 14185 } 14186 element.removeData( "ui-tooltip-title" ); 14187 } 14188 }); 14189 this.liveRegion.remove(); 14190 } 14191 }); 14192 14193 14194 /*! 14195 * jQuery UI Effects 1.11.4 14196 * http://jqueryui.com 14197 * 14198 * Copyright jQuery Foundation and other contributors 14199 * Released under the MIT license. 14200 * http://jquery.org/license 14201 * 14202 * http://api.jqueryui.com/category/effects-core/ 14203 */ 14204 14205 14206 var dataSpace = "ui-effects-", 14207 14208 // Create a local jQuery because jQuery Color relies on it and the 14209 // global may not exist with AMD and a custom build (#10199) 14210 jQuery = $; 14211 14212 $.effects = { 14213 effect: {} 14214 }; 14215 14216 /*! 14217 * jQuery Color Animations v2.1.2 14218 * https://github.com/jquery/jquery-color 14219 * 14220 * Copyright 2014 jQuery Foundation and other contributors 14221 * Released under the MIT license. 14222 * http://jquery.org/license 14223 * 14224 * Date: Wed Jan 16 08:47:09 2013 -0600 14225 */ 14226 (function( jQuery, undefined ) { 14227 14228 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", 14229 14230 // plusequals test for += 100 -= 100 14231 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, 14232 // a set of RE's that can match strings and generate color tuples. 14233 stringParsers = [ { 14234 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 14235 parse: function( execResult ) { 14236 return [ 14237 execResult[ 1 ], 14238 execResult[ 2 ], 14239 execResult[ 3 ], 14240 execResult[ 4 ] 14241 ]; 14242 } 14243 }, { 14244 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 14245 parse: function( execResult ) { 14246 return [ 14247 execResult[ 1 ] * 2.55, 14248 execResult[ 2 ] * 2.55, 14249 execResult[ 3 ] * 2.55, 14250 execResult[ 4 ] 14251 ]; 14252 } 14253 }, { 14254 // this regex ignores A-F because it's compared against an already lowercased string 14255 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/, 14256 parse: function( execResult ) { 14257 return [ 14258 parseInt( execResult[ 1 ], 16 ), 14259 parseInt( execResult[ 2 ], 16 ), 14260 parseInt( execResult[ 3 ], 16 ) 14261 ]; 14262 } 14263 }, { 14264 // this regex ignores A-F because it's compared against an already lowercased string 14265 re: /#([a-f0-9])([a-f0-9])([a-f0-9])/, 14266 parse: function( execResult ) { 14267 return [ 14268 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), 14269 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), 14270 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ) 14271 ]; 14272 } 14273 }, { 14274 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 14275 space: "hsla", 14276 parse: function( execResult ) { 14277 return [ 14278 execResult[ 1 ], 14279 execResult[ 2 ] / 100, 14280 execResult[ 3 ] / 100, 14281 execResult[ 4 ] 14282 ]; 14283 } 14284 } ], 14285 14286 // jQuery.Color( ) 14287 color = jQuery.Color = function( color, green, blue, alpha ) { 14288 return new jQuery.Color.fn.parse( color, green, blue, alpha ); 14289 }, 14290 spaces = { 14291 rgba: { 14292 props: { 14293 red: { 14294 idx: 0, 14295 type: "byte" 14296 }, 14297 green: { 14298 idx: 1, 14299 type: "byte" 14300 }, 14301 blue: { 14302 idx: 2, 14303 type: "byte" 14304 } 14305 } 14306 }, 14307 14308 hsla: { 14309 props: { 14310 hue: { 14311 idx: 0, 14312 type: "degrees" 14313 }, 14314 saturation: { 14315 idx: 1, 14316 type: "percent" 14317 }, 14318 lightness: { 14319 idx: 2, 14320 type: "percent" 14321 } 14322 } 14323 } 14324 }, 14325 propTypes = { 14326 "byte": { 14327 floor: true, 14328 max: 255 14329 }, 14330 "percent": { 14331 max: 1 14332 }, 14333 "degrees": { 14334 mod: 360, 14335 floor: true 14336 } 14337 }, 14338 support = color.support = {}, 14339 14340 // element for support tests 14341 supportElem = jQuery( "<p>" )[ 0 ], 14342 14343 // colors = jQuery.Color.names 14344 colors, 14345 14346 // local aliases of functions called often 14347 each = jQuery.each; 14348 14349 // determine rgba support immediately 14350 supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; 14351 support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; 14352 14353 // define cache name and alpha properties 14354 // for rgba and hsla spaces 14355 each( spaces, function( spaceName, space ) { 14356 space.cache = "_" + spaceName; 14357 space.props.alpha = { 14358 idx: 3, 14359 type: "percent", 14360 def: 1 14361 }; 14362 }); 14363 14364 function clamp( value, prop, allowEmpty ) { 14365 var type = propTypes[ prop.type ] || {}; 14366 14367 if ( value == null ) { 14368 return (allowEmpty || !prop.def) ? null : prop.def; 14369 } 14370 14371 // ~~ is an short way of doing floor for positive numbers 14372 value = type.floor ? ~~value : parseFloat( value ); 14373 14374 // IE will pass in empty strings as value for alpha, 14375 // which will hit this case 14376 if ( isNaN( value ) ) { 14377 return prop.def; 14378 } 14379 14380 if ( type.mod ) { 14381 // we add mod before modding to make sure that negatives values 14382 // get converted properly: -10 -> 350 14383 return (value + type.mod) % type.mod; 14384 } 14385 14386 // for now all property types without mod have min and max 14387 return 0 > value ? 0 : type.max < value ? type.max : value; 14388 } 14389 14390 function stringParse( string ) { 14391 var inst = color(), 14392 rgba = inst._rgba = []; 14393 14394 string = string.toLowerCase(); 14395 14396 each( stringParsers, function( i, parser ) { 14397 var parsed, 14398 match = parser.re.exec( string ), 14399 values = match && parser.parse( match ), 14400 spaceName = parser.space || "rgba"; 14401 14402 if ( values ) { 14403 parsed = inst[ spaceName ]( values ); 14404 14405 // if this was an rgba parse the assignment might happen twice 14406 // oh well.... 14407 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; 14408 rgba = inst._rgba = parsed._rgba; 14409 14410 // exit each( stringParsers ) here because we matched 14411 return false; 14412 } 14413 }); 14414 14415 // Found a stringParser that handled it 14416 if ( rgba.length ) { 14417 14418 // if this came from a parsed string, force "transparent" when alpha is 0 14419 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) 14420 if ( rgba.join() === "0,0,0,0" ) { 14421 jQuery.extend( rgba, colors.transparent ); 14422 } 14423 return inst; 14424 } 14425 14426 // named colors 14427 return colors[ string ]; 14428 } 14429 14430 color.fn = jQuery.extend( color.prototype, { 14431 parse: function( red, green, blue, alpha ) { 14432 if ( red === undefined ) { 14433 this._rgba = [ null, null, null, null ]; 14434 return this; 14435 } 14436 if ( red.jquery || red.nodeType ) { 14437 red = jQuery( red ).css( green ); 14438 green = undefined; 14439 } 14440 14441 var inst = this, 14442 type = jQuery.type( red ), 14443 rgba = this._rgba = []; 14444 14445 // more than 1 argument specified - assume ( red, green, blue, alpha ) 14446 if ( green !== undefined ) { 14447 red = [ red, green, blue, alpha ]; 14448 type = "array"; 14449 } 14450 14451 if ( type === "string" ) { 14452 return this.parse( stringParse( red ) || colors._default ); 14453 } 14454 14455 if ( type === "array" ) { 14456 each( spaces.rgba.props, function( key, prop ) { 14457 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); 14458 }); 14459 return this; 14460 } 14461 14462 if ( type === "object" ) { 14463 if ( red instanceof color ) { 14464 each( spaces, function( spaceName, space ) { 14465 if ( red[ space.cache ] ) { 14466 inst[ space.cache ] = red[ space.cache ].slice(); 14467 } 14468 }); 14469 } else { 14470 each( spaces, function( spaceName, space ) { 14471 var cache = space.cache; 14472 each( space.props, function( key, prop ) { 14473 14474 // if the cache doesn't exist, and we know how to convert 14475 if ( !inst[ cache ] && space.to ) { 14476 14477 // if the value was null, we don't need to copy it 14478 // if the key was alpha, we don't need to copy it either 14479 if ( key === "alpha" || red[ key ] == null ) { 14480 return; 14481 } 14482 inst[ cache ] = space.to( inst._rgba ); 14483 } 14484 14485 // this is the only case where we allow nulls for ALL properties. 14486 // call clamp with alwaysAllowEmpty 14487 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); 14488 }); 14489 14490 // everything defined but alpha? 14491 if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { 14492 // use the default of 1 14493 inst[ cache ][ 3 ] = 1; 14494 if ( space.from ) { 14495 inst._rgba = space.from( inst[ cache ] ); 14496 } 14497 } 14498 }); 14499 } 14500 return this; 14501 } 14502 }, 14503 is: function( compare ) { 14504 var is = color( compare ), 14505 same = true, 14506 inst = this; 14507 14508 each( spaces, function( _, space ) { 14509 var localCache, 14510 isCache = is[ space.cache ]; 14511 if (isCache) { 14512 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; 14513 each( space.props, function( _, prop ) { 14514 if ( isCache[ prop.idx ] != null ) { 14515 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); 14516 return same; 14517 } 14518 }); 14519 } 14520 return same; 14521 }); 14522 return same; 14523 }, 14524 _space: function() { 14525 var used = [], 14526 inst = this; 14527 each( spaces, function( spaceName, space ) { 14528 if ( inst[ space.cache ] ) { 14529 used.push( spaceName ); 14530 } 14531 }); 14532 return used.pop(); 14533 }, 14534 transition: function( other, distance ) { 14535 var end = color( other ), 14536 spaceName = end._space(), 14537 space = spaces[ spaceName ], 14538 startColor = this.alpha() === 0 ? color( "transparent" ) : this, 14539 start = startColor[ space.cache ] || space.to( startColor._rgba ), 14540 result = start.slice(); 14541 14542 end = end[ space.cache ]; 14543 each( space.props, function( key, prop ) { 14544 var index = prop.idx, 14545 startValue = start[ index ], 14546 endValue = end[ index ], 14547 type = propTypes[ prop.type ] || {}; 14548 14549 // if null, don't override start value 14550 if ( endValue === null ) { 14551 return; 14552 } 14553 // if null - use end 14554 if ( startValue === null ) { 14555 result[ index ] = endValue; 14556 } else { 14557 if ( type.mod ) { 14558 if ( endValue - startValue > type.mod / 2 ) { 14559 startValue += type.mod; 14560 } else if ( startValue - endValue > type.mod / 2 ) { 14561 startValue -= type.mod; 14562 } 14563 } 14564 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); 14565 } 14566 }); 14567 return this[ spaceName ]( result ); 14568 }, 14569 blend: function( opaque ) { 14570 // if we are already opaque - return ourself 14571 if ( this._rgba[ 3 ] === 1 ) { 14572 return this; 14573 } 14574 14575 var rgb = this._rgba.slice(), 14576 a = rgb.pop(), 14577 blend = color( opaque )._rgba; 14578 14579 return color( jQuery.map( rgb, function( v, i ) { 14580 return ( 1 - a ) * blend[ i ] + a * v; 14581 })); 14582 }, 14583 toRgbaString: function() { 14584 var prefix = "rgba(", 14585 rgba = jQuery.map( this._rgba, function( v, i ) { 14586 return v == null ? ( i > 2 ? 1 : 0 ) : v; 14587 }); 14588 14589 if ( rgba[ 3 ] === 1 ) { 14590 rgba.pop(); 14591 prefix = "rgb("; 14592 } 14593 14594 return prefix + rgba.join() + ")"; 14595 }, 14596 toHslaString: function() { 14597 var prefix = "hsla(", 14598 hsla = jQuery.map( this.hsla(), function( v, i ) { 14599 if ( v == null ) { 14600 v = i > 2 ? 1 : 0; 14601 } 14602 14603 // catch 1 and 2 14604 if ( i && i < 3 ) { 14605 v = Math.round( v * 100 ) + "%"; 14606 } 14607 return v; 14608 }); 14609 14610 if ( hsla[ 3 ] === 1 ) { 14611 hsla.pop(); 14612 prefix = "hsl("; 14613 } 14614 return prefix + hsla.join() + ")"; 14615 }, 14616 toHexString: function( includeAlpha ) { 14617 var rgba = this._rgba.slice(), 14618 alpha = rgba.pop(); 14619 14620 if ( includeAlpha ) { 14621 rgba.push( ~~( alpha * 255 ) ); 14622 } 14623 14624 return "#" + jQuery.map( rgba, function( v ) { 14625 14626 // default to 0 when nulls exist 14627 v = ( v || 0 ).toString( 16 ); 14628 return v.length === 1 ? "0" + v : v; 14629 }).join(""); 14630 }, 14631 toString: function() { 14632 return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); 14633 } 14634 }); 14635 color.fn.parse.prototype = color.fn; 14636 14637 // hsla conversions adapted from: 14638 // https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 14639 14640 function hue2rgb( p, q, h ) { 14641 h = ( h + 1 ) % 1; 14642 if ( h * 6 < 1 ) { 14643 return p + ( q - p ) * h * 6; 14644 } 14645 if ( h * 2 < 1) { 14646 return q; 14647 } 14648 if ( h * 3 < 2 ) { 14649 return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6; 14650 } 14651 return p; 14652 } 14653 14654 spaces.hsla.to = function( rgba ) { 14655 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { 14656 return [ null, null, null, rgba[ 3 ] ]; 14657 } 14658 var r = rgba[ 0 ] / 255, 14659 g = rgba[ 1 ] / 255, 14660 b = rgba[ 2 ] / 255, 14661 a = rgba[ 3 ], 14662 max = Math.max( r, g, b ), 14663 min = Math.min( r, g, b ), 14664 diff = max - min, 14665 add = max + min, 14666 l = add * 0.5, 14667 h, s; 14668 14669 if ( min === max ) { 14670 h = 0; 14671 } else if ( r === max ) { 14672 h = ( 60 * ( g - b ) / diff ) + 360; 14673 } else if ( g === max ) { 14674 h = ( 60 * ( b - r ) / diff ) + 120; 14675 } else { 14676 h = ( 60 * ( r - g ) / diff ) + 240; 14677 } 14678 14679 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0% 14680 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) 14681 if ( diff === 0 ) { 14682 s = 0; 14683 } else if ( l <= 0.5 ) { 14684 s = diff / add; 14685 } else { 14686 s = diff / ( 2 - add ); 14687 } 14688 return [ Math.round(h) % 360, s, l, a == null ? 1 : a ]; 14689 }; 14690 14691 spaces.hsla.from = function( hsla ) { 14692 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { 14693 return [ null, null, null, hsla[ 3 ] ]; 14694 } 14695 var h = hsla[ 0 ] / 360, 14696 s = hsla[ 1 ], 14697 l = hsla[ 2 ], 14698 a = hsla[ 3 ], 14699 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, 14700 p = 2 * l - q; 14701 14702 return [ 14703 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), 14704 Math.round( hue2rgb( p, q, h ) * 255 ), 14705 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), 14706 a 14707 ]; 14708 }; 14709 14710 each( spaces, function( spaceName, space ) { 14711 var props = space.props, 14712 cache = space.cache, 14713 to = space.to, 14714 from = space.from; 14715 14716 // makes rgba() and hsla() 14717 color.fn[ spaceName ] = function( value ) { 14718 14719 // generate a cache for this space if it doesn't exist 14720 if ( to && !this[ cache ] ) { 14721 this[ cache ] = to( this._rgba ); 14722 } 14723 if ( value === undefined ) { 14724 return this[ cache ].slice(); 14725 } 14726 14727 var ret, 14728 type = jQuery.type( value ), 14729 arr = ( type === "array" || type === "object" ) ? value : arguments, 14730 local = this[ cache ].slice(); 14731 14732 each( props, function( key, prop ) { 14733 var val = arr[ type === "object" ? key : prop.idx ]; 14734 if ( val == null ) { 14735 val = local[ prop.idx ]; 14736 } 14737 local[ prop.idx ] = clamp( val, prop ); 14738 }); 14739 14740 if ( from ) { 14741 ret = color( from( local ) ); 14742 ret[ cache ] = local; 14743 return ret; 14744 } else { 14745 return color( local ); 14746 } 14747 }; 14748 14749 // makes red() green() blue() alpha() hue() saturation() lightness() 14750 each( props, function( key, prop ) { 14751 // alpha is included in more than one space 14752 if ( color.fn[ key ] ) { 14753 return; 14754 } 14755 color.fn[ key ] = function( value ) { 14756 var vtype = jQuery.type( value ), 14757 fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ), 14758 local = this[ fn ](), 14759 cur = local[ prop.idx ], 14760 match; 14761 14762 if ( vtype === "undefined" ) { 14763 return cur; 14764 } 14765 14766 if ( vtype === "function" ) { 14767 value = value.call( this, cur ); 14768 vtype = jQuery.type( value ); 14769 } 14770 if ( value == null && prop.empty ) { 14771 return this; 14772 } 14773 if ( vtype === "string" ) { 14774 match = rplusequals.exec( value ); 14775 if ( match ) { 14776 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); 14777 } 14778 } 14779 local[ prop.idx ] = value; 14780 return this[ fn ]( local ); 14781 }; 14782 }); 14783 }); 14784 14785 // add cssHook and .fx.step function for each named hook. 14786 // accept a space separated string of properties 14787 color.hook = function( hook ) { 14788 var hooks = hook.split( " " ); 14789 each( hooks, function( i, hook ) { 14790 jQuery.cssHooks[ hook ] = { 14791 set: function( elem, value ) { 14792 var parsed, curElem, 14793 backgroundColor = ""; 14794 14795 if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) { 14796 value = color( parsed || value ); 14797 if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { 14798 curElem = hook === "backgroundColor" ? elem.parentNode : elem; 14799 while ( 14800 (backgroundColor === "" || backgroundColor === "transparent") && 14801 curElem && curElem.style 14802 ) { 14803 try { 14804 backgroundColor = jQuery.css( curElem, "backgroundColor" ); 14805 curElem = curElem.parentNode; 14806 } catch ( e ) { 14807 } 14808 } 14809 14810 value = value.blend( backgroundColor && backgroundColor !== "transparent" ? 14811 backgroundColor : 14812 "_default" ); 14813 } 14814 14815 value = value.toRgbaString(); 14816 } 14817 try { 14818 elem.style[ hook ] = value; 14819 } catch ( e ) { 14820 // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' 14821 } 14822 } 14823 }; 14824 jQuery.fx.step[ hook ] = function( fx ) { 14825 if ( !fx.colorInit ) { 14826 fx.start = color( fx.elem, hook ); 14827 fx.end = color( fx.end ); 14828 fx.colorInit = true; 14829 } 14830 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); 14831 }; 14832 }); 14833 14834 }; 14835 14836 color.hook( stepHooks ); 14837 14838 jQuery.cssHooks.borderColor = { 14839 expand: function( value ) { 14840 var expanded = {}; 14841 14842 each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) { 14843 expanded[ "border" + part + "Color" ] = value; 14844 }); 14845 return expanded; 14846 } 14847 }; 14848 14849 // Basic color names only. 14850 // Usage of any of the other color names requires adding yourself or including 14851 // jquery.color.svg-names.js. 14852 colors = jQuery.Color.names = { 14853 // 4.1. Basic color keywords 14854 aqua: "#00ffff", 14855 black: "#000000", 14856 blue: "#0000ff", 14857 fuchsia: "#ff00ff", 14858 gray: "#808080", 14859 green: "#008000", 14860 lime: "#00ff00", 14861 maroon: "#800000", 14862 navy: "#000080", 14863 olive: "#808000", 14864 purple: "#800080", 14865 red: "#ff0000", 14866 silver: "#c0c0c0", 14867 teal: "#008080", 14868 white: "#ffffff", 14869 yellow: "#ffff00", 14870 14871 // 4.2.3. "transparent" color keyword 14872 transparent: [ null, null, null, 0 ], 14873 14874 _default: "#ffffff" 14875 }; 14876 14877 })( jQuery ); 14878 14879 /******************************************************************************/ 14880 /****************************** CLASS ANIMATIONS ******************************/ 14881 /******************************************************************************/ 14882 (function() { 14883 14884 var classAnimationActions = [ "add", "remove", "toggle" ], 14885 shorthandStyles = { 14886 border: 1, 14887 borderBottom: 1, 14888 borderColor: 1, 14889 borderLeft: 1, 14890 borderRight: 1, 14891 borderTop: 1, 14892 borderWidth: 1, 14893 margin: 1, 14894 padding: 1 14895 }; 14896 14897 $.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) { 14898 $.fx.step[ prop ] = function( fx ) { 14899 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { 14900 jQuery.style( fx.elem, prop, fx.end ); 14901 fx.setAttr = true; 14902 } 14903 }; 14904 }); 14905 14906 function getElementStyles( elem ) { 14907 var key, len, 14908 style = elem.ownerDocument.defaultView ? 14909 elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : 14910 elem.currentStyle, 14911 styles = {}; 14912 14913 if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { 14914 len = style.length; 14915 while ( len-- ) { 14916 key = style[ len ]; 14917 if ( typeof style[ key ] === "string" ) { 14918 styles[ $.camelCase( key ) ] = style[ key ]; 14919 } 14920 } 14921 // support: Opera, IE <9 14922 } else { 14923 for ( key in style ) { 14924 if ( typeof style[ key ] === "string" ) { 14925 styles[ key ] = style[ key ]; 14926 } 14927 } 14928 } 14929 14930 return styles; 14931 } 14932 14933 function styleDifference( oldStyle, newStyle ) { 14934 var diff = {}, 14935 name, value; 14936 14937 for ( name in newStyle ) { 14938 value = newStyle[ name ]; 14939 if ( oldStyle[ name ] !== value ) { 14940 if ( !shorthandStyles[ name ] ) { 14941 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { 14942 diff[ name ] = value; 14943 } 14944 } 14945 } 14946 } 14947 14948 return diff; 14949 } 14950 14951 // support: jQuery <1.8 14952 if ( !$.fn.addBack ) { 14953 $.fn.addBack = function( selector ) { 14954 return this.add( selector == null ? 14955 this.prevObject : this.prevObject.filter( selector ) 14956 ); 14957 }; 14958 } 14959 14960 $.effects.animateClass = function( value, duration, easing, callback ) { 14961 var o = $.speed( duration, easing, callback ); 14962 14963 return this.queue( function() { 14964 var animated = $( this ), 14965 baseClass = animated.attr( "class" ) || "", 14966 applyClassChange, 14967 allAnimations = o.children ? animated.find( "*" ).addBack() : animated; 14968 14969 // map the animated objects to store the original styles. 14970 allAnimations = allAnimations.map(function() { 14971 var el = $( this ); 14972 return { 14973 el: el, 14974 start: getElementStyles( this ) 14975 }; 14976 }); 14977 14978 // apply class change 14979 applyClassChange = function() { 14980 $.each( classAnimationActions, function(i, action) { 14981 if ( value[ action ] ) { 14982 animated[ action + "Class" ]( value[ action ] ); 14983 } 14984 }); 14985 }; 14986 applyClassChange(); 14987 14988 // map all animated objects again - calculate new styles and diff 14989 allAnimations = allAnimations.map(function() { 14990 this.end = getElementStyles( this.el[ 0 ] ); 14991 this.diff = styleDifference( this.start, this.end ); 14992 return this; 14993 }); 14994 14995 // apply original class 14996 animated.attr( "class", baseClass ); 14997 14998 // map all animated objects again - this time collecting a promise 14999 allAnimations = allAnimations.map(function() { 15000 var styleInfo = this, 15001 dfd = $.Deferred(), 15002 opts = $.extend({}, o, { 15003 queue: false, 15004 complete: function() { 15005 dfd.resolve( styleInfo ); 15006 } 15007 }); 15008 15009 this.el.animate( this.diff, opts ); 15010 return dfd.promise(); 15011 }); 15012 15013 // once all animations have completed: 15014 $.when.apply( $, allAnimations.get() ).done(function() { 15015 15016 // set the final class 15017 applyClassChange(); 15018 15019 // for each animated element, 15020 // clear all css properties that were animated 15021 $.each( arguments, function() { 15022 var el = this.el; 15023 $.each( this.diff, function(key) { 15024 el.css( key, "" ); 15025 }); 15026 }); 15027 15028 // this is guarnteed to be there if you use jQuery.speed() 15029 // it also handles dequeuing the next anim... 15030 o.complete.call( animated[ 0 ] ); 15031 }); 15032 }); 15033 }; 15034 15035 $.fn.extend({ 15036 addClass: (function( orig ) { 15037 return function( classNames, speed, easing, callback ) { 15038 return speed ? 15039 $.effects.animateClass.call( this, 15040 { add: classNames }, speed, easing, callback ) : 15041 orig.apply( this, arguments ); 15042 }; 15043 })( $.fn.addClass ), 15044 15045 removeClass: (function( orig ) { 15046 return function( classNames, speed, easing, callback ) { 15047 return arguments.length > 1 ? 15048 $.effects.animateClass.call( this, 15049 { remove: classNames }, speed, easing, callback ) : 15050 orig.apply( this, arguments ); 15051 }; 15052 })( $.fn.removeClass ), 15053 15054 toggleClass: (function( orig ) { 15055 return function( classNames, force, speed, easing, callback ) { 15056 if ( typeof force === "boolean" || force === undefined ) { 15057 if ( !speed ) { 15058 // without speed parameter 15059 return orig.apply( this, arguments ); 15060 } else { 15061 return $.effects.animateClass.call( this, 15062 (force ? { add: classNames } : { remove: classNames }), 15063 speed, easing, callback ); 15064 } 15065 } else { 15066 // without force parameter 15067 return $.effects.animateClass.call( this, 15068 { toggle: classNames }, force, speed, easing ); 15069 } 15070 }; 15071 })( $.fn.toggleClass ), 15072 15073 switchClass: function( remove, add, speed, easing, callback) { 15074 return $.effects.animateClass.call( this, { 15075 add: add, 15076 remove: remove 15077 }, speed, easing, callback ); 15078 } 15079 }); 15080 15081 })(); 15082 15083 /******************************************************************************/ 15084 /*********************************** EFFECTS **********************************/ 15085 /******************************************************************************/ 15086 15087 (function() { 15088 15089 $.extend( $.effects, { 15090 version: "1.11.4", 15091 15092 // Saves a set of properties in a data storage 15093 save: function( element, set ) { 15094 for ( var i = 0; i < set.length; i++ ) { 15095 if ( set[ i ] !== null ) { 15096 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); 15097 } 15098 } 15099 }, 15100 15101 // Restores a set of previously saved properties from a data storage 15102 restore: function( element, set ) { 15103 var val, i; 15104 for ( i = 0; i < set.length; i++ ) { 15105 if ( set[ i ] !== null ) { 15106 val = element.data( dataSpace + set[ i ] ); 15107 // support: jQuery 1.6.2 15108 // http://bugs.jquery.com/ticket/9917 15109 // jQuery 1.6.2 incorrectly returns undefined for any falsy value. 15110 // We can't differentiate between "" and 0 here, so we just assume 15111 // empty string since it's likely to be a more common value... 15112 if ( val === undefined ) { 15113 val = ""; 15114 } 15115 element.css( set[ i ], val ); 15116 } 15117 } 15118 }, 15119 15120 setMode: function( el, mode ) { 15121 if (mode === "toggle") { 15122 mode = el.is( ":hidden" ) ? "show" : "hide"; 15123 } 15124 return mode; 15125 }, 15126 15127 // Translates a [top,left] array into a baseline value 15128 // this should be a little more flexible in the future to handle a string & hash 15129 getBaseline: function( origin, original ) { 15130 var y, x; 15131 switch ( origin[ 0 ] ) { 15132 case "top": y = 0; break; 15133 case "middle": y = 0.5; break; 15134 case "bottom": y = 1; break; 15135 default: y = origin[ 0 ] / original.height; 15136 } 15137 switch ( origin[ 1 ] ) { 15138 case "left": x = 0; break; 15139 case "center": x = 0.5; break; 15140 case "right": x = 1; break; 15141 default: x = origin[ 1 ] / original.width; 15142 } 15143 return { 15144 x: x, 15145 y: y 15146 }; 15147 }, 15148 15149 // Wraps the element around a wrapper that copies position properties 15150 createWrapper: function( element ) { 15151 15152 // if the element is already wrapped, return it 15153 if ( element.parent().is( ".ui-effects-wrapper" )) { 15154 return element.parent(); 15155 } 15156 15157 // wrap the element 15158 var props = { 15159 width: element.outerWidth(true), 15160 height: element.outerHeight(true), 15161 "float": element.css( "float" ) 15162 }, 15163 wrapper = $( "<div></div>" ) 15164 .addClass( "ui-effects-wrapper" ) 15165 .css({ 15166 fontSize: "100%", 15167 background: "transparent", 15168 border: "none", 15169 margin: 0, 15170 padding: 0 15171 }), 15172 // Store the size in case width/height are defined in % - Fixes #5245 15173 size = { 15174 width: element.width(), 15175 height: element.height() 15176 }, 15177 active = document.activeElement; 15178 15179 // support: Firefox 15180 // Firefox incorrectly exposes anonymous content 15181 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 15182 try { 15183 active.id; 15184 } catch ( e ) { 15185 active = document.body; 15186 } 15187 15188 element.wrap( wrapper ); 15189 15190 // Fixes #7595 - Elements lose focus when wrapped. 15191 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 15192 $( active ).focus(); 15193 } 15194 15195 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element 15196 15197 // transfer positioning properties to the wrapper 15198 if ( element.css( "position" ) === "static" ) { 15199 wrapper.css({ position: "relative" }); 15200 element.css({ position: "relative" }); 15201 } else { 15202 $.extend( props, { 15203 position: element.css( "position" ), 15204 zIndex: element.css( "z-index" ) 15205 }); 15206 $.each([ "top", "left", "bottom", "right" ], function(i, pos) { 15207 props[ pos ] = element.css( pos ); 15208 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { 15209 props[ pos ] = "auto"; 15210 } 15211 }); 15212 element.css({ 15213 position: "relative", 15214 top: 0, 15215 left: 0, 15216 right: "auto", 15217 bottom: "auto" 15218 }); 15219 } 15220 element.css(size); 15221 15222 return wrapper.css( props ).show(); 15223 }, 15224 15225 removeWrapper: function( element ) { 15226 var active = document.activeElement; 15227 15228 if ( element.parent().is( ".ui-effects-wrapper" ) ) { 15229 element.parent().replaceWith( element ); 15230 15231 // Fixes #7595 - Elements lose focus when wrapped. 15232 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 15233 $( active ).focus(); 15234 } 15235 } 15236 15237 return element; 15238 }, 15239 15240 setTransition: function( element, list, factor, value ) { 15241 value = value || {}; 15242 $.each( list, function( i, x ) { 15243 var unit = element.cssUnit( x ); 15244 if ( unit[ 0 ] > 0 ) { 15245 value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; 15246 } 15247 }); 15248 return value; 15249 } 15250 }); 15251 15252 // return an effect options object for the given parameters: 15253 function _normalizeArguments( effect, options, speed, callback ) { 15254 15255 // allow passing all options as the first parameter 15256 if ( $.isPlainObject( effect ) ) { 15257 options = effect; 15258 effect = effect.effect; 15259 } 15260 15261 // convert to an object 15262 effect = { effect: effect }; 15263 15264 // catch (effect, null, ...) 15265 if ( options == null ) { 15266 options = {}; 15267 } 15268 15269 // catch (effect, callback) 15270 if ( $.isFunction( options ) ) { 15271 callback = options; 15272 speed = null; 15273 options = {}; 15274 } 15275 15276 // catch (effect, speed, ?) 15277 if ( typeof options === "number" || $.fx.speeds[ options ] ) { 15278 callback = speed; 15279 speed = options; 15280 options = {}; 15281 } 15282 15283 // catch (effect, options, callback) 15284 if ( $.isFunction( speed ) ) { 15285 callback = speed; 15286 speed = null; 15287 } 15288 15289 // add options to effect 15290 if ( options ) { 15291 $.extend( effect, options ); 15292 } 15293 15294 speed = speed || options.duration; 15295 effect.duration = $.fx.off ? 0 : 15296 typeof speed === "number" ? speed : 15297 speed in $.fx.speeds ? $.fx.speeds[ speed ] : 15298 $.fx.speeds._default; 15299 15300 effect.complete = callback || options.complete; 15301 15302 return effect; 15303 } 15304 15305 function standardAnimationOption( option ) { 15306 // Valid standard speeds (nothing, number, named speed) 15307 if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) { 15308 return true; 15309 } 15310 15311 // Invalid strings - treat as "normal" speed 15312 if ( typeof option === "string" && !$.effects.effect[ option ] ) { 15313 return true; 15314 } 15315 15316 // Complete callback 15317 if ( $.isFunction( option ) ) { 15318 return true; 15319 } 15320 15321 // Options hash (but not naming an effect) 15322 if ( typeof option === "object" && !option.effect ) { 15323 return true; 15324 } 15325 15326 // Didn't match any standard API 15327 return false; 15328 } 15329 15330 $.fn.extend({ 15331 effect: function( /* effect, options, speed, callback */ ) { 15332 var args = _normalizeArguments.apply( this, arguments ), 15333 mode = args.mode, 15334 queue = args.queue, 15335 effectMethod = $.effects.effect[ args.effect ]; 15336 15337 if ( $.fx.off || !effectMethod ) { 15338 // delegate to the original method (e.g., .show()) if possible 15339 if ( mode ) { 15340 return this[ mode ]( args.duration, args.complete ); 15341 } else { 15342 return this.each( function() { 15343 if ( args.complete ) { 15344 args.complete.call( this ); 15345 } 15346 }); 15347 } 15348 } 15349 15350 function run( next ) { 15351 var elem = $( this ), 15352 complete = args.complete, 15353 mode = args.mode; 15354 15355 function done() { 15356 if ( $.isFunction( complete ) ) { 15357 complete.call( elem[0] ); 15358 } 15359 if ( $.isFunction( next ) ) { 15360 next(); 15361 } 15362 } 15363 15364 // If the element already has the correct final state, delegate to 15365 // the core methods so the internal tracking of "olddisplay" works. 15366 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { 15367 elem[ mode ](); 15368 done(); 15369 } else { 15370 effectMethod.call( elem[0], args, done ); 15371 } 15372 } 15373 15374 return queue === false ? this.each( run ) : this.queue( queue || "fx", run ); 15375 }, 15376 15377 show: (function( orig ) { 15378 return function( option ) { 15379 if ( standardAnimationOption( option ) ) { 15380 return orig.apply( this, arguments ); 15381 } else { 15382 var args = _normalizeArguments.apply( this, arguments ); 15383 args.mode = "show"; 15384 return this.effect.call( this, args ); 15385 } 15386 }; 15387 })( $.fn.show ), 15388 15389 hide: (function( orig ) { 15390 return function( option ) { 15391 if ( standardAnimationOption( option ) ) { 15392 return orig.apply( this, arguments ); 15393 } else { 15394 var args = _normalizeArguments.apply( this, arguments ); 15395 args.mode = "hide"; 15396 return this.effect.call( this, args ); 15397 } 15398 }; 15399 })( $.fn.hide ), 15400 15401 toggle: (function( orig ) { 15402 return function( option ) { 15403 if ( standardAnimationOption( option ) || typeof option === "boolean" ) { 15404 return orig.apply( this, arguments ); 15405 } else { 15406 var args = _normalizeArguments.apply( this, arguments ); 15407 args.mode = "toggle"; 15408 return this.effect.call( this, args ); 15409 } 15410 }; 15411 })( $.fn.toggle ), 15412 15413 // helper functions 15414 cssUnit: function(key) { 15415 var style = this.css( key ), 15416 val = []; 15417 15418 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { 15419 if ( style.indexOf( unit ) > 0 ) { 15420 val = [ parseFloat( style ), unit ]; 15421 } 15422 }); 15423 return val; 15424 } 15425 }); 15426 15427 })(); 15428 15429 /******************************************************************************/ 15430 /*********************************** EASING ***********************************/ 15431 /******************************************************************************/ 15432 15433 (function() { 15434 15435 // based on easing equations from Robert Penner (http://www.robertpenner.com/easing) 15436 15437 var baseEasings = {}; 15438 15439 $.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { 15440 baseEasings[ name ] = function( p ) { 15441 return Math.pow( p, i + 2 ); 15442 }; 15443 }); 15444 15445 $.extend( baseEasings, { 15446 Sine: function( p ) { 15447 return 1 - Math.cos( p * Math.PI / 2 ); 15448 }, 15449 Circ: function( p ) { 15450 return 1 - Math.sqrt( 1 - p * p ); 15451 }, 15452 Elastic: function( p ) { 15453 return p === 0 || p === 1 ? p : 15454 -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 ); 15455 }, 15456 Back: function( p ) { 15457 return p * p * ( 3 * p - 2 ); 15458 }, 15459 Bounce: function( p ) { 15460 var pow2, 15461 bounce = 4; 15462 15463 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} 15464 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); 15465 } 15466 }); 15467 15468 $.each( baseEasings, function( name, easeIn ) { 15469 $.easing[ "easeIn" + name ] = easeIn; 15470 $.easing[ "easeOut" + name ] = function( p ) { 15471 return 1 - easeIn( 1 - p ); 15472 }; 15473 $.easing[ "easeInOut" + name ] = function( p ) { 15474 return p < 0.5 ? 15475 easeIn( p * 2 ) / 2 : 15476 1 - easeIn( p * -2 + 2 ) / 2; 15477 }; 15478 }); 15479 15480 })(); 15481 15482 var effect = $.effects; 15483 15484 15485 /*! 15486 * jQuery UI Effects Blind 1.11.4 15487 * http://jqueryui.com 15488 * 15489 * Copyright jQuery Foundation and other contributors 15490 * Released under the MIT license. 15491 * http://jquery.org/license 15492 * 15493 * http://api.jqueryui.com/blind-effect/ 15494 */ 15495 15496 15497 var effectBlind = $.effects.effect.blind = function( o, done ) { 15498 // Create element 15499 var el = $( this ), 15500 rvertical = /up|down|vertical/, 15501 rpositivemotion = /up|left|vertical|horizontal/, 15502 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 15503 mode = $.effects.setMode( el, o.mode || "hide" ), 15504 direction = o.direction || "up", 15505 vertical = rvertical.test( direction ), 15506 ref = vertical ? "height" : "width", 15507 ref2 = vertical ? "top" : "left", 15508 motion = rpositivemotion.test( direction ), 15509 animation = {}, 15510 show = mode === "show", 15511 wrapper, distance, margin; 15512 15513 // if already wrapped, the wrapper's properties are my property. #6245 15514 if ( el.parent().is( ".ui-effects-wrapper" ) ) { 15515 $.effects.save( el.parent(), props ); 15516 } else { 15517 $.effects.save( el, props ); 15518 } 15519 el.show(); 15520 wrapper = $.effects.createWrapper( el ).css({ 15521 overflow: "hidden" 15522 }); 15523 15524 distance = wrapper[ ref ](); 15525 margin = parseFloat( wrapper.css( ref2 ) ) || 0; 15526 15527 animation[ ref ] = show ? distance : 0; 15528 if ( !motion ) { 15529 el 15530 .css( vertical ? "bottom" : "right", 0 ) 15531 .css( vertical ? "top" : "left", "auto" ) 15532 .css({ position: "absolute" }); 15533 15534 animation[ ref2 ] = show ? margin : distance + margin; 15535 } 15536 15537 // start at 0 if we are showing 15538 if ( show ) { 15539 wrapper.css( ref, 0 ); 15540 if ( !motion ) { 15541 wrapper.css( ref2, margin + distance ); 15542 } 15543 } 15544 15545 // Animate 15546 wrapper.animate( animation, { 15547 duration: o.duration, 15548 easing: o.easing, 15549 queue: false, 15550 complete: function() { 15551 if ( mode === "hide" ) { 15552 el.hide(); 15553 } 15554 $.effects.restore( el, props ); 15555 $.effects.removeWrapper( el ); 15556 done(); 15557 } 15558 }); 15559 }; 15560 15561 15562 /*! 15563 * jQuery UI Effects Bounce 1.11.4 15564 * http://jqueryui.com 15565 * 15566 * Copyright jQuery Foundation and other contributors 15567 * Released under the MIT license. 15568 * http://jquery.org/license 15569 * 15570 * http://api.jqueryui.com/bounce-effect/ 15571 */ 15572 15573 15574 var effectBounce = $.effects.effect.bounce = function( o, done ) { 15575 var el = $( this ), 15576 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 15577 15578 // defaults: 15579 mode = $.effects.setMode( el, o.mode || "effect" ), 15580 hide = mode === "hide", 15581 show = mode === "show", 15582 direction = o.direction || "up", 15583 distance = o.distance, 15584 times = o.times || 5, 15585 15586 // number of internal animations 15587 anims = times * 2 + ( show || hide ? 1 : 0 ), 15588 speed = o.duration / anims, 15589 easing = o.easing, 15590 15591 // utility: 15592 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 15593 motion = ( direction === "up" || direction === "left" ), 15594 i, 15595 upAnim, 15596 downAnim, 15597 15598 // we will need to re-assemble the queue to stack our animations in place 15599 queue = el.queue(), 15600 queuelen = queue.length; 15601 15602 // Avoid touching opacity to prevent clearType and PNG issues in IE 15603 if ( show || hide ) { 15604 props.push( "opacity" ); 15605 } 15606 15607 $.effects.save( el, props ); 15608 el.show(); 15609 $.effects.createWrapper( el ); // Create Wrapper 15610 15611 // default distance for the BIGGEST bounce is the outer Distance / 3 15612 if ( !distance ) { 15613 distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; 15614 } 15615 15616 if ( show ) { 15617 downAnim = { opacity: 1 }; 15618 downAnim[ ref ] = 0; 15619 15620 // if we are showing, force opacity 0 and set the initial position 15621 // then do the "first" animation 15622 el.css( "opacity", 0 ) 15623 .css( ref, motion ? -distance * 2 : distance * 2 ) 15624 .animate( downAnim, speed, easing ); 15625 } 15626 15627 // start at the smallest distance if we are hiding 15628 if ( hide ) { 15629 distance = distance / Math.pow( 2, times - 1 ); 15630 } 15631 15632 downAnim = {}; 15633 downAnim[ ref ] = 0; 15634 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here 15635 for ( i = 0; i < times; i++ ) { 15636 upAnim = {}; 15637 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 15638 15639 el.animate( upAnim, speed, easing ) 15640 .animate( downAnim, speed, easing ); 15641 15642 distance = hide ? distance * 2 : distance / 2; 15643 } 15644 15645 // Last Bounce when Hiding 15646 if ( hide ) { 15647 upAnim = { opacity: 0 }; 15648 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 15649 15650 el.animate( upAnim, speed, easing ); 15651 } 15652 15653 el.queue(function() { 15654 if ( hide ) { 15655 el.hide(); 15656 } 15657 $.effects.restore( el, props ); 15658 $.effects.removeWrapper( el ); 15659 done(); 15660 }); 15661 15662 // inject all the animations we just queued to be first in line (after "inprogress") 15663 if ( queuelen > 1) { 15664 queue.splice.apply( queue, 15665 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); 15666 } 15667 el.dequeue(); 15668 15669 }; 15670 15671 15672 /*! 15673 * jQuery UI Effects Clip 1.11.4 15674 * http://jqueryui.com 15675 * 15676 * Copyright jQuery Foundation and other contributors 15677 * Released under the MIT license. 15678 * http://jquery.org/license 15679 * 15680 * http://api.jqueryui.com/clip-effect/ 15681 */ 15682 15683 15684 var effectClip = $.effects.effect.clip = function( o, done ) { 15685 // Create element 15686 var el = $( this ), 15687 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 15688 mode = $.effects.setMode( el, o.mode || "hide" ), 15689 show = mode === "show", 15690 direction = o.direction || "vertical", 15691 vert = direction === "vertical", 15692 size = vert ? "height" : "width", 15693 position = vert ? "top" : "left", 15694 animation = {}, 15695 wrapper, animate, distance; 15696 15697 // Save & Show 15698 $.effects.save( el, props ); 15699 el.show(); 15700 15701 // Create Wrapper 15702 wrapper = $.effects.createWrapper( el ).css({ 15703 overflow: "hidden" 15704 }); 15705 animate = ( el[0].tagName === "IMG" ) ? wrapper : el; 15706 distance = animate[ size ](); 15707 15708 // Shift 15709 if ( show ) { 15710 animate.css( size, 0 ); 15711 animate.css( position, distance / 2 ); 15712 } 15713 15714 // Create Animation Object: 15715 animation[ size ] = show ? distance : 0; 15716 animation[ position ] = show ? 0 : distance / 2; 15717 15718 // Animate 15719 animate.animate( animation, { 15720 queue: false, 15721 duration: o.duration, 15722 easing: o.easing, 15723 complete: function() { 15724 if ( !show ) { 15725 el.hide(); 15726 } 15727 $.effects.restore( el, props ); 15728 $.effects.removeWrapper( el ); 15729 done(); 15730 } 15731 }); 15732 15733 }; 15734 15735 15736 /*! 15737 * jQuery UI Effects Drop 1.11.4 15738 * http://jqueryui.com 15739 * 15740 * Copyright jQuery Foundation and other contributors 15741 * Released under the MIT license. 15742 * http://jquery.org/license 15743 * 15744 * http://api.jqueryui.com/drop-effect/ 15745 */ 15746 15747 15748 var effectDrop = $.effects.effect.drop = function( o, done ) { 15749 15750 var el = $( this ), 15751 props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ], 15752 mode = $.effects.setMode( el, o.mode || "hide" ), 15753 show = mode === "show", 15754 direction = o.direction || "left", 15755 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 15756 motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg", 15757 animation = { 15758 opacity: show ? 1 : 0 15759 }, 15760 distance; 15761 15762 // Adjust 15763 $.effects.save( el, props ); 15764 el.show(); 15765 $.effects.createWrapper( el ); 15766 15767 distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2; 15768 15769 if ( show ) { 15770 el 15771 .css( "opacity", 0 ) 15772 .css( ref, motion === "pos" ? -distance : distance ); 15773 } 15774 15775 // Animation 15776 animation[ ref ] = ( show ? 15777 ( motion === "pos" ? "+=" : "-=" ) : 15778 ( motion === "pos" ? "-=" : "+=" ) ) + 15779 distance; 15780 15781 // Animate 15782 el.animate( animation, { 15783 queue: false, 15784 duration: o.duration, 15785 easing: o.easing, 15786 complete: function() { 15787 if ( mode === "hide" ) { 15788 el.hide(); 15789 } 15790 $.effects.restore( el, props ); 15791 $.effects.removeWrapper( el ); 15792 done(); 15793 } 15794 }); 15795 }; 15796 15797 15798 /*! 15799 * jQuery UI Effects Explode 1.11.4 15800 * http://jqueryui.com 15801 * 15802 * Copyright jQuery Foundation and other contributors 15803 * Released under the MIT license. 15804 * http://jquery.org/license 15805 * 15806 * http://api.jqueryui.com/explode-effect/ 15807 */ 15808 15809 15810 var effectExplode = $.effects.effect.explode = function( o, done ) { 15811 15812 var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3, 15813 cells = rows, 15814 el = $( this ), 15815 mode = $.effects.setMode( el, o.mode || "hide" ), 15816 show = mode === "show", 15817 15818 // show and then visibility:hidden the element before calculating offset 15819 offset = el.show().css( "visibility", "hidden" ).offset(), 15820 15821 // width and height of a piece 15822 width = Math.ceil( el.outerWidth() / cells ), 15823 height = Math.ceil( el.outerHeight() / rows ), 15824 pieces = [], 15825 15826 // loop 15827 i, j, left, top, mx, my; 15828 15829 // children animate complete: 15830 function childComplete() { 15831 pieces.push( this ); 15832 if ( pieces.length === rows * cells ) { 15833 animComplete(); 15834 } 15835 } 15836 15837 // clone the element for each row and cell. 15838 for ( i = 0; i < rows ; i++ ) { // ===> 15839 top = offset.top + i * height; 15840 my = i - ( rows - 1 ) / 2 ; 15841 15842 for ( j = 0; j < cells ; j++ ) { // ||| 15843 left = offset.left + j * width; 15844 mx = j - ( cells - 1 ) / 2 ; 15845 15846 // Create a clone of the now hidden main element that will be absolute positioned 15847 // within a wrapper div off the -left and -top equal to size of our pieces 15848 el 15849 .clone() 15850 .appendTo( "body" ) 15851 .wrap( "<div></div>" ) 15852 .css({ 15853 position: "absolute", 15854 visibility: "visible", 15855 left: -j * width, 15856 top: -i * height 15857 }) 15858 15859 // select the wrapper - make it overflow: hidden and absolute positioned based on 15860 // where the original was located +left and +top equal to the size of pieces 15861 .parent() 15862 .addClass( "ui-effects-explode" ) 15863 .css({ 15864 position: "absolute", 15865 overflow: "hidden", 15866 width: width, 15867 height: height, 15868 left: left + ( show ? mx * width : 0 ), 15869 top: top + ( show ? my * height : 0 ), 15870 opacity: show ? 0 : 1 15871 }).animate({ 15872 left: left + ( show ? 0 : mx * width ), 15873 top: top + ( show ? 0 : my * height ), 15874 opacity: show ? 1 : 0 15875 }, o.duration || 500, o.easing, childComplete ); 15876 } 15877 } 15878 15879 function animComplete() { 15880 el.css({ 15881 visibility: "visible" 15882 }); 15883 $( pieces ).remove(); 15884 if ( !show ) { 15885 el.hide(); 15886 } 15887 done(); 15888 } 15889 }; 15890 15891 15892 /*! 15893 * jQuery UI Effects Fade 1.11.4 15894 * http://jqueryui.com 15895 * 15896 * Copyright jQuery Foundation and other contributors 15897 * Released under the MIT license. 15898 * http://jquery.org/license 15899 * 15900 * http://api.jqueryui.com/fade-effect/ 15901 */ 15902 15903 15904 var effectFade = $.effects.effect.fade = function( o, done ) { 15905 var el = $( this ), 15906 mode = $.effects.setMode( el, o.mode || "toggle" ); 15907 15908 el.animate({ 15909 opacity: mode 15910 }, { 15911 queue: false, 15912 duration: o.duration, 15913 easing: o.easing, 15914 complete: done 15915 }); 15916 }; 15917 15918 15919 /*! 15920 * jQuery UI Effects Fold 1.11.4 15921 * http://jqueryui.com 15922 * 15923 * Copyright jQuery Foundation and other contributors 15924 * Released under the MIT license. 15925 * http://jquery.org/license 15926 * 15927 * http://api.jqueryui.com/fold-effect/ 15928 */ 15929 15930 15931 var effectFold = $.effects.effect.fold = function( o, done ) { 15932 15933 // Create element 15934 var el = $( this ), 15935 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 15936 mode = $.effects.setMode( el, o.mode || "hide" ), 15937 show = mode === "show", 15938 hide = mode === "hide", 15939 size = o.size || 15, 15940 percent = /([0-9]+)%/.exec( size ), 15941 horizFirst = !!o.horizFirst, 15942 widthFirst = show !== horizFirst, 15943 ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ], 15944 duration = o.duration / 2, 15945 wrapper, distance, 15946 animation1 = {}, 15947 animation2 = {}; 15948 15949 $.effects.save( el, props ); 15950 el.show(); 15951 15952 // Create Wrapper 15953 wrapper = $.effects.createWrapper( el ).css({ 15954 overflow: "hidden" 15955 }); 15956 distance = widthFirst ? 15957 [ wrapper.width(), wrapper.height() ] : 15958 [ wrapper.height(), wrapper.width() ]; 15959 15960 if ( percent ) { 15961 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; 15962 } 15963 if ( show ) { 15964 wrapper.css( horizFirst ? { 15965 height: 0, 15966 width: size 15967 } : { 15968 height: size, 15969 width: 0 15970 }); 15971 } 15972 15973 // Animation 15974 animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size; 15975 animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0; 15976 15977 // Animate 15978 wrapper 15979 .animate( animation1, duration, o.easing ) 15980 .animate( animation2, duration, o.easing, function() { 15981 if ( hide ) { 15982 el.hide(); 15983 } 15984 $.effects.restore( el, props ); 15985 $.effects.removeWrapper( el ); 15986 done(); 15987 }); 15988 15989 }; 15990 15991 15992 /*! 15993 * jQuery UI Effects Highlight 1.11.4 15994 * http://jqueryui.com 15995 * 15996 * Copyright jQuery Foundation and other contributors 15997 * Released under the MIT license. 15998 * http://jquery.org/license 15999 * 16000 * http://api.jqueryui.com/highlight-effect/ 16001 */ 16002 16003 16004 var effectHighlight = $.effects.effect.highlight = function( o, done ) { 16005 var elem = $( this ), 16006 props = [ "backgroundImage", "backgroundColor", "opacity" ], 16007 mode = $.effects.setMode( elem, o.mode || "show" ), 16008 animation = { 16009 backgroundColor: elem.css( "backgroundColor" ) 16010 }; 16011 16012 if (mode === "hide") { 16013 animation.opacity = 0; 16014 } 16015 16016 $.effects.save( elem, props ); 16017 16018 elem 16019 .show() 16020 .css({ 16021 backgroundImage: "none", 16022 backgroundColor: o.color || "#ffff99" 16023 }) 16024 .animate( animation, { 16025 queue: false, 16026 duration: o.duration, 16027 easing: o.easing, 16028 complete: function() { 16029 if ( mode === "hide" ) { 16030 elem.hide(); 16031 } 16032 $.effects.restore( elem, props ); 16033 done(); 16034 } 16035 }); 16036 }; 16037 16038 16039 /*! 16040 * jQuery UI Effects Size 1.11.4 16041 * http://jqueryui.com 16042 * 16043 * Copyright jQuery Foundation and other contributors 16044 * Released under the MIT license. 16045 * http://jquery.org/license 16046 * 16047 * http://api.jqueryui.com/size-effect/ 16048 */ 16049 16050 16051 var effectSize = $.effects.effect.size = function( o, done ) { 16052 16053 // Create element 16054 var original, baseline, factor, 16055 el = $( this ), 16056 props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ], 16057 16058 // Always restore 16059 props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ], 16060 16061 // Copy for children 16062 props2 = [ "width", "height", "overflow" ], 16063 cProps = [ "fontSize" ], 16064 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], 16065 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], 16066 16067 // Set options 16068 mode = $.effects.setMode( el, o.mode || "effect" ), 16069 restore = o.restore || mode !== "effect", 16070 scale = o.scale || "both", 16071 origin = o.origin || [ "middle", "center" ], 16072 position = el.css( "position" ), 16073 props = restore ? props0 : props1, 16074 zero = { 16075 height: 0, 16076 width: 0, 16077 outerHeight: 0, 16078 outerWidth: 0 16079 }; 16080 16081 if ( mode === "show" ) { 16082 el.show(); 16083 } 16084 original = { 16085 height: el.height(), 16086 width: el.width(), 16087 outerHeight: el.outerHeight(), 16088 outerWidth: el.outerWidth() 16089 }; 16090 16091 if ( o.mode === "toggle" && mode === "show" ) { 16092 el.from = o.to || zero; 16093 el.to = o.from || original; 16094 } else { 16095 el.from = o.from || ( mode === "show" ? zero : original ); 16096 el.to = o.to || ( mode === "hide" ? zero : original ); 16097 } 16098 16099 // Set scaling factor 16100 factor = { 16101 from: { 16102 y: el.from.height / original.height, 16103 x: el.from.width / original.width 16104 }, 16105 to: { 16106 y: el.to.height / original.height, 16107 x: el.to.width / original.width 16108 } 16109 }; 16110 16111 // Scale the css box 16112 if ( scale === "box" || scale === "both" ) { 16113 16114 // Vertical props scaling 16115 if ( factor.from.y !== factor.to.y ) { 16116 props = props.concat( vProps ); 16117 el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from ); 16118 el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to ); 16119 } 16120 16121 // Horizontal props scaling 16122 if ( factor.from.x !== factor.to.x ) { 16123 props = props.concat( hProps ); 16124 el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from ); 16125 el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to ); 16126 } 16127 } 16128 16129 // Scale the content 16130 if ( scale === "content" || scale === "both" ) { 16131 16132 // Vertical props scaling 16133 if ( factor.from.y !== factor.to.y ) { 16134 props = props.concat( cProps ).concat( props2 ); 16135 el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from ); 16136 el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to ); 16137 } 16138 } 16139 16140 $.effects.save( el, props ); 16141 el.show(); 16142 $.effects.createWrapper( el ); 16143 el.css( "overflow", "hidden" ).css( el.from ); 16144 16145 // Adjust 16146 if (origin) { // Calculate baseline shifts 16147 baseline = $.effects.getBaseline( origin, original ); 16148 el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y; 16149 el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x; 16150 el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y; 16151 el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x; 16152 } 16153 el.css( el.from ); // set top & left 16154 16155 // Animate 16156 if ( scale === "content" || scale === "both" ) { // Scale the children 16157 16158 // Add margins/font-size 16159 vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps); 16160 hProps = hProps.concat([ "marginLeft", "marginRight" ]); 16161 props2 = props0.concat(vProps).concat(hProps); 16162 16163 el.find( "*[width]" ).each( function() { 16164 var child = $( this ), 16165 c_original = { 16166 height: child.height(), 16167 width: child.width(), 16168 outerHeight: child.outerHeight(), 16169 outerWidth: child.outerWidth() 16170 }; 16171 if (restore) { 16172 $.effects.save(child, props2); 16173 } 16174 16175 child.from = { 16176 height: c_original.height * factor.from.y, 16177 width: c_original.width * factor.from.x, 16178 outerHeight: c_original.outerHeight * factor.from.y, 16179 outerWidth: c_original.outerWidth * factor.from.x 16180 }; 16181 child.to = { 16182 height: c_original.height * factor.to.y, 16183 width: c_original.width * factor.to.x, 16184 outerHeight: c_original.height * factor.to.y, 16185 outerWidth: c_original.width * factor.to.x 16186 }; 16187 16188 // Vertical props scaling 16189 if ( factor.from.y !== factor.to.y ) { 16190 child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from ); 16191 child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to ); 16192 } 16193 16194 // Horizontal props scaling 16195 if ( factor.from.x !== factor.to.x ) { 16196 child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from ); 16197 child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to ); 16198 } 16199 16200 // Animate children 16201 child.css( child.from ); 16202 child.animate( child.to, o.duration, o.easing, function() { 16203 16204 // Restore children 16205 if ( restore ) { 16206 $.effects.restore( child, props2 ); 16207 } 16208 }); 16209 }); 16210 } 16211 16212 // Animate 16213 el.animate( el.to, { 16214 queue: false, 16215 duration: o.duration, 16216 easing: o.easing, 16217 complete: function() { 16218 if ( el.to.opacity === 0 ) { 16219 el.css( "opacity", el.from.opacity ); 16220 } 16221 if ( mode === "hide" ) { 16222 el.hide(); 16223 } 16224 $.effects.restore( el, props ); 16225 if ( !restore ) { 16226 16227 // we need to calculate our new positioning based on the scaling 16228 if ( position === "static" ) { 16229 el.css({ 16230 position: "relative", 16231 top: el.to.top, 16232 left: el.to.left 16233 }); 16234 } else { 16235 $.each([ "top", "left" ], function( idx, pos ) { 16236 el.css( pos, function( _, str ) { 16237 var val = parseInt( str, 10 ), 16238 toRef = idx ? el.to.left : el.to.top; 16239 16240 // if original was "auto", recalculate the new value from wrapper 16241 if ( str === "auto" ) { 16242 return toRef + "px"; 16243 } 16244 16245 return val + toRef + "px"; 16246 }); 16247 }); 16248 } 16249 } 16250 16251 $.effects.removeWrapper( el ); 16252 done(); 16253 } 16254 }); 16255 16256 }; 16257 16258 16259 /*! 16260 * jQuery UI Effects Scale 1.11.4 16261 * http://jqueryui.com 16262 * 16263 * Copyright jQuery Foundation and other contributors 16264 * Released under the MIT license. 16265 * http://jquery.org/license 16266 * 16267 * http://api.jqueryui.com/scale-effect/ 16268 */ 16269 16270 16271 var effectScale = $.effects.effect.scale = function( o, done ) { 16272 16273 // Create element 16274 var el = $( this ), 16275 options = $.extend( true, {}, o ), 16276 mode = $.effects.setMode( el, o.mode || "effect" ), 16277 percent = parseInt( o.percent, 10 ) || 16278 ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ), 16279 direction = o.direction || "both", 16280 origin = o.origin, 16281 original = { 16282 height: el.height(), 16283 width: el.width(), 16284 outerHeight: el.outerHeight(), 16285 outerWidth: el.outerWidth() 16286 }, 16287 factor = { 16288 y: direction !== "horizontal" ? (percent / 100) : 1, 16289 x: direction !== "vertical" ? (percent / 100) : 1 16290 }; 16291 16292 // We are going to pass this effect to the size effect: 16293 options.effect = "size"; 16294 options.queue = false; 16295 options.complete = done; 16296 16297 // Set default origin and restore for show/hide 16298 if ( mode !== "effect" ) { 16299 options.origin = origin || [ "middle", "center" ]; 16300 options.restore = true; 16301 } 16302 16303 options.from = o.from || ( mode === "show" ? { 16304 height: 0, 16305 width: 0, 16306 outerHeight: 0, 16307 outerWidth: 0 16308 } : original ); 16309 options.to = { 16310 height: original.height * factor.y, 16311 width: original.width * factor.x, 16312 outerHeight: original.outerHeight * factor.y, 16313 outerWidth: original.outerWidth * factor.x 16314 }; 16315 16316 // Fade option to support puff 16317 if ( options.fade ) { 16318 if ( mode === "show" ) { 16319 options.from.opacity = 0; 16320 options.to.opacity = 1; 16321 } 16322 if ( mode === "hide" ) { 16323 options.from.opacity = 1; 16324 options.to.opacity = 0; 16325 } 16326 } 16327 16328 // Animate 16329 el.effect( options ); 16330 16331 }; 16332 16333 16334 /*! 16335 * jQuery UI Effects Puff 1.11.4 16336 * http://jqueryui.com 16337 * 16338 * Copyright jQuery Foundation and other contributors 16339 * Released under the MIT license. 16340 * http://jquery.org/license 16341 * 16342 * http://api.jqueryui.com/puff-effect/ 16343 */ 16344 16345 16346 var effectPuff = $.effects.effect.puff = function( o, done ) { 16347 var elem = $( this ), 16348 mode = $.effects.setMode( elem, o.mode || "hide" ), 16349 hide = mode === "hide", 16350 percent = parseInt( o.percent, 10 ) || 150, 16351 factor = percent / 100, 16352 original = { 16353 height: elem.height(), 16354 width: elem.width(), 16355 outerHeight: elem.outerHeight(), 16356 outerWidth: elem.outerWidth() 16357 }; 16358 16359 $.extend( o, { 16360 effect: "scale", 16361 queue: false, 16362 fade: true, 16363 mode: mode, 16364 complete: done, 16365 percent: hide ? percent : 100, 16366 from: hide ? 16367 original : 16368 { 16369 height: original.height * factor, 16370 width: original.width * factor, 16371 outerHeight: original.outerHeight * factor, 16372 outerWidth: original.outerWidth * factor 16373 } 16374 }); 16375 16376 elem.effect( o ); 16377 }; 16378 16379 16380 /*! 16381 * jQuery UI Effects Pulsate 1.11.4 16382 * http://jqueryui.com 16383 * 16384 * Copyright jQuery Foundation and other contributors 16385 * Released under the MIT license. 16386 * http://jquery.org/license 16387 * 16388 * http://api.jqueryui.com/pulsate-effect/ 16389 */ 16390 16391 16392 var effectPulsate = $.effects.effect.pulsate = function( o, done ) { 16393 var elem = $( this ), 16394 mode = $.effects.setMode( elem, o.mode || "show" ), 16395 show = mode === "show", 16396 hide = mode === "hide", 16397 showhide = ( show || mode === "hide" ), 16398 16399 // showing or hiding leaves of the "last" animation 16400 anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), 16401 duration = o.duration / anims, 16402 animateTo = 0, 16403 queue = elem.queue(), 16404 queuelen = queue.length, 16405 i; 16406 16407 if ( show || !elem.is(":visible")) { 16408 elem.css( "opacity", 0 ).show(); 16409 animateTo = 1; 16410 } 16411 16412 // anims - 1 opacity "toggles" 16413 for ( i = 1; i < anims; i++ ) { 16414 elem.animate({ 16415 opacity: animateTo 16416 }, duration, o.easing ); 16417 animateTo = 1 - animateTo; 16418 } 16419 16420 elem.animate({ 16421 opacity: animateTo 16422 }, duration, o.easing); 16423 16424 elem.queue(function() { 16425 if ( hide ) { 16426 elem.hide(); 16427 } 16428 done(); 16429 }); 16430 16431 // We just queued up "anims" animations, we need to put them next in the queue 16432 if ( queuelen > 1 ) { 16433 queue.splice.apply( queue, 16434 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); 16435 } 16436 elem.dequeue(); 16437 }; 16438 16439 16440 /*! 16441 * jQuery UI Effects Shake 1.11.4 16442 * http://jqueryui.com 16443 * 16444 * Copyright jQuery Foundation and other contributors 16445 * Released under the MIT license. 16446 * http://jquery.org/license 16447 * 16448 * http://api.jqueryui.com/shake-effect/ 16449 */ 16450 16451 16452 var effectShake = $.effects.effect.shake = function( o, done ) { 16453 16454 var el = $( this ), 16455 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 16456 mode = $.effects.setMode( el, o.mode || "effect" ), 16457 direction = o.direction || "left", 16458 distance = o.distance || 20, 16459 times = o.times || 3, 16460 anims = times * 2 + 1, 16461 speed = Math.round( o.duration / anims ), 16462 ref = (direction === "up" || direction === "down") ? "top" : "left", 16463 positiveMotion = (direction === "up" || direction === "left"), 16464 animation = {}, 16465 animation1 = {}, 16466 animation2 = {}, 16467 i, 16468 16469 // we will need to re-assemble the queue to stack our animations in place 16470 queue = el.queue(), 16471 queuelen = queue.length; 16472 16473 $.effects.save( el, props ); 16474 el.show(); 16475 $.effects.createWrapper( el ); 16476 16477 // Animation 16478 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; 16479 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; 16480 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; 16481 16482 // Animate 16483 el.animate( animation, speed, o.easing ); 16484 16485 // Shakes 16486 for ( i = 1; i < times; i++ ) { 16487 el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing ); 16488 } 16489 el 16490 .animate( animation1, speed, o.easing ) 16491 .animate( animation, speed / 2, o.easing ) 16492 .queue(function() { 16493 if ( mode === "hide" ) { 16494 el.hide(); 16495 } 16496 $.effects.restore( el, props ); 16497 $.effects.removeWrapper( el ); 16498 done(); 16499 }); 16500 16501 // inject all the animations we just queued to be first in line (after "inprogress") 16502 if ( queuelen > 1) { 16503 queue.splice.apply( queue, 16504 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); 16505 } 16506 el.dequeue(); 16507 16508 }; 16509 16510 16511 /*! 16512 * jQuery UI Effects Slide 1.11.4 16513 * http://jqueryui.com 16514 * 16515 * Copyright jQuery Foundation and other contributors 16516 * Released under the MIT license. 16517 * http://jquery.org/license 16518 * 16519 * http://api.jqueryui.com/slide-effect/ 16520 */ 16521 16522 16523 var effectSlide = $.effects.effect.slide = function( o, done ) { 16524 16525 // Create element 16526 var el = $( this ), 16527 props = [ "position", "top", "bottom", "left", "right", "width", "height" ], 16528 mode = $.effects.setMode( el, o.mode || "show" ), 16529 show = mode === "show", 16530 direction = o.direction || "left", 16531 ref = (direction === "up" || direction === "down") ? "top" : "left", 16532 positiveMotion = (direction === "up" || direction === "left"), 16533 distance, 16534 animation = {}; 16535 16536 // Adjust 16537 $.effects.save( el, props ); 16538 el.show(); 16539 distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ); 16540 16541 $.effects.createWrapper( el ).css({ 16542 overflow: "hidden" 16543 }); 16544 16545 if ( show ) { 16546 el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance ); 16547 } 16548 16549 // Animation 16550 animation[ ref ] = ( show ? 16551 ( positiveMotion ? "+=" : "-=") : 16552 ( positiveMotion ? "-=" : "+=")) + 16553 distance; 16554 16555 // Animate 16556 el.animate( animation, { 16557 queue: false, 16558 duration: o.duration, 16559 easing: o.easing, 16560 complete: function() { 16561 if ( mode === "hide" ) { 16562 el.hide(); 16563 } 16564 $.effects.restore( el, props ); 16565 $.effects.removeWrapper( el ); 16566 done(); 16567 } 16568 }); 16569 }; 16570 16571 16572 /*! 16573 * jQuery UI Effects Transfer 1.11.4 16574 * http://jqueryui.com 16575 * 16576 * Copyright jQuery Foundation and other contributors 16577 * Released under the MIT license. 16578 * http://jquery.org/license 16579 * 16580 * http://api.jqueryui.com/transfer-effect/ 16581 */ 16582 16583 16584 var effectTransfer = $.effects.effect.transfer = function( o, done ) { 16585 var elem = $( this ), 16586 target = $( o.to ), 16587 targetFixed = target.css( "position" ) === "fixed", 16588 body = $("body"), 16589 fixTop = targetFixed ? body.scrollTop() : 0, 16590 fixLeft = targetFixed ? body.scrollLeft() : 0, 16591 endPosition = target.offset(), 16592 animation = { 16593 top: endPosition.top - fixTop, 16594 left: endPosition.left - fixLeft, 16595 height: target.innerHeight(), 16596 width: target.innerWidth() 16597 }, 16598 startPosition = elem.offset(), 16599 transfer = $( "<div class='ui-effects-transfer'></div>" ) 16600 .appendTo( document.body ) 16601 .addClass( o.className ) 16602 .css({ 16603 top: startPosition.top - fixTop, 16604 left: startPosition.left - fixLeft, 16605 height: elem.innerHeight(), 16606 width: elem.innerWidth(), 16607 position: targetFixed ? "fixed" : "absolute" 16608 }) 16609 .animate( animation, o.duration, o.easing, function() { 16610 transfer.remove(); 16611 done(); 16612 }); 16613 }; 16614 16615 16616 16617 }));
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |