1/*! jQuery UI - v1.10.0 - 2013-01-18 2* http://jqueryui.com 3* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js 4* Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */ 5 6(function( $, undefined ) { 7 8var uuid = 0, 9 runiqueId = /^ui-id-\d+$/; 10 11// prevent duplicate loading 12// this is only a problem because we proxy existing functions 13// and we don't want to double proxy them 14$.ui = $.ui || {}; 15if ( $.ui.version ) { 16 return; 17} 18 19$.extend( $.ui, { 20 version: "1.10.0", 21 22 keyCode: { 23 BACKSPACE: 8, 24 COMMA: 188, 25 DELETE: 46, 26 DOWN: 40, 27 END: 35, 28 ENTER: 13, 29 ESCAPE: 27, 30 HOME: 36, 31 LEFT: 37, 32 NUMPAD_ADD: 107, 33 NUMPAD_DECIMAL: 110, 34 NUMPAD_DIVIDE: 111, 35 NUMPAD_ENTER: 108, 36 NUMPAD_MULTIPLY: 106, 37 NUMPAD_SUBTRACT: 109, 38 PAGE_DOWN: 34, 39 PAGE_UP: 33, 40 PERIOD: 190, 41 RIGHT: 39, 42 SPACE: 32, 43 TAB: 9, 44 UP: 38 45 } 46}); 47 48// plugins 49$.fn.extend({ 50 _focus: $.fn.focus, 51 focus: function( delay, fn ) { 52 return typeof delay === "number" ? 53 this.each(function() { 54 var elem = this; 55 setTimeout(function() { 56 $( elem ).focus(); 57 if ( fn ) { 58 fn.call( elem ); 59 } 60 }, delay ); 61 }) : 62 this._focus.apply( this, arguments ); 63 }, 64 65 scrollParent: function() { 66 var scrollParent; 67 if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) { 68 scrollParent = this.parents().filter(function() { 69 return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); 70 }).eq(0); 71 } else { 72 scrollParent = this.parents().filter(function() { 73 return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); 74 }).eq(0); 75 } 76 77 return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent; 78 }, 79 80 zIndex: function( zIndex ) { 81 if ( zIndex !== undefined ) { 82 return this.css( "zIndex", zIndex ); 83 } 84 85 if ( this.length ) { 86 var elem = $( this[ 0 ] ), position, value; 87 while ( elem.length && elem[ 0 ] !== document ) { 88 // Ignore z-index if position is set to a value where z-index is ignored by the browser 89 // This makes behavior of this function consistent across browsers 90 // WebKit always returns auto if the element is positioned 91 position = elem.css( "position" ); 92 if ( position === "absolute" || position === "relative" || position === "fixed" ) { 93 // IE returns 0 when zIndex is not specified 94 // other browsers return a string 95 // we ignore the case of nested elements with an explicit value of 0 96 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 97 value = parseInt( elem.css( "zIndex" ), 10 ); 98 if ( !isNaN( value ) && value !== 0 ) { 99 return value; 100 } 101 } 102 elem = elem.parent(); 103 } 104 } 105 106 return 0; 107 }, 108 109 uniqueId: function() { 110 return this.each(function() { 111 if ( !this.id ) { 112 this.id = "ui-id-" + (++uuid); 113 } 114 }); 115 }, 116 117 removeUniqueId: function() { 118 return this.each(function() { 119 if ( runiqueId.test( this.id ) ) { 120 $( this ).removeAttr( "id" ); 121 } 122 }); 123 } 124}); 125 126// selectors 127function focusable( element, isTabIndexNotNaN ) { 128 var map, mapName, img, 129 nodeName = element.nodeName.toLowerCase(); 130 if ( "area" === nodeName ) { 131 map = element.parentNode; 132 mapName = map.name; 133 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { 134 return false;
vendor: 48,845 bytes, lines 135-1818
135 } 136 img = $( "img[usemap=#" + mapName + "]" )[0]; 137 return !!img && visible( img ); 138 } 139 return ( /input|select|textarea|button|object/.test( nodeName ) ? 140 !element.disabled : 141 "a" === nodeName ? 142 element.href || isTabIndexNotNaN : 143 isTabIndexNotNaN) && 144 // the element and all of its ancestors must be visible 145 visible( element ); 146} 147 148function visible( element ) { 149 return $.expr.filters.visible( element ) && 150 !$( element ).parents().addBack().filter(function() { 151 return $.css( this, "visibility" ) === "hidden"; 152 }).length; 153} 154 155$.extend( $.expr[ ":" ], { 156 data: $.expr.createPseudo ? 157 $.expr.createPseudo(function( dataName ) { 158 return function( elem ) { 159 return !!$.data( elem, dataName ); 160 }; 161 }) : 162 // support: jQuery <1.8 163 function( elem, i, match ) { 164 return !!$.data( elem, match[ 3 ] ); 165 }, 166 167 focusable: function( element ) { 168 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); 169 }, 170 171 tabbable: function( element ) { 172 var tabIndex = $.attr( element, "tabindex" ), 173 isTabIndexNaN = isNaN( tabIndex ); 174 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); 175 } 176}); 177 178// support: jQuery <1.8 179if ( !$( "<a>" ).outerWidth( 1 ).jquery ) { 180 $.each( [ "Width", "Height" ], function( i, name ) { 181 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], 182 type = name.toLowerCase(), 183 orig = { 184 innerWidth: $.fn.innerWidth, 185 innerHeight: $.fn.innerHeight, 186 outerWidth: $.fn.outerWidth, 187 outerHeight: $.fn.outerHeight 188 }; 189 190 function reduce( elem, size, border, margin ) { 191 $.each( side, function() { 192 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; 193 if ( border ) { 194 size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; 195 } 196 if ( margin ) { 197 size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; 198 } 199 }); 200 return size; 201 } 202 203 $.fn[ "inner" + name ] = function( size ) { 204 if ( size === undefined ) { 205 return orig[ "inner" + name ].call( this ); 206 } 207 208 return this.each(function() { 209 $( this ).css( type, reduce( this, size ) + "px" ); 210 }); 211 }; 212 213 $.fn[ "outer" + name] = function( size, margin ) { 214 if ( typeof size !== "number" ) { 215 return orig[ "outer" + name ].call( this, size ); 216 } 217 218 return this.each(function() { 219 $( this).css( type, reduce( this, size, true, margin ) + "px" ); 220 }); 221 }; 222 }); 223} 224 225// support: jQuery <1.8 226if ( !$.fn.addBack ) { 227 $.fn.addBack = function( selector ) { 228 return this.add( selector == null ? 229 this.prevObject : this.prevObject.filter( selector ) 230 ); 231 }; 232} 233 234// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413) 235if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) { 236 $.fn.removeData = (function( removeData ) { 237 return function( key ) { 238 if ( arguments.length ) { 239 return removeData.call( this, $.camelCase( key ) ); 240 } else { 241 return removeData.call( this ); 242 } 243 }; 244 })( $.fn.removeData ); 245} 246 247 248 249 250 251// deprecated 252$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ); 253 254$.support.selectstart = "onselectstart" in document.createElement( "div" ); 255$.fn.extend({ 256 disableSelection: function() { 257 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + 258 ".ui-disableSelection", function( event ) { 259 event.preventDefault(); 260 }); 261 }, 262 263 enableSelection: function() { 264 return this.unbind( ".ui-disableSelection" ); 265 } 266}); 267 268$.extend( $.ui, { 269 // $.ui.plugin is deprecated. Use the proxy pattern instead. 270 plugin: { 271 add: function( module, option, set ) { 272 var i, 273 proto = $.ui[ module ].prototype; 274 for ( i in set ) { 275 proto.plugins[ i ] = proto.plugins[ i ] || []; 276 proto.plugins[ i ].push( [ option, set[ i ] ] ); 277 } 278 }, 279 call: function( instance, name, args ) { 280 var i, 281 set = instance.plugins[ name ]; 282 if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) { 283 return; 284 } 285 286 for ( i = 0; i < set.length; i++ ) { 287 if ( instance.options[ set[ i ][ 0 ] ] ) { 288 set[ i ][ 1 ].apply( instance.element, args ); 289 } 290 } 291 } 292 }, 293 294 // only used by resizable 295 hasScroll: function( el, a ) { 296 297 //If overflow is hidden, the element might have extra content, but the user wants to hide it 298 if ( $( el ).css( "overflow" ) === "hidden") { 299 return false; 300 } 301 302 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", 303 has = false; 304 305 if ( el[ scroll ] > 0 ) { 306 return true; 307 } 308 309 // TODO: determine which cases actually cause this to happen 310 // if the element doesn't have the scroll set, see if it's possible to 311 // set the scroll 312 el[ scroll ] = 1; 313 has = ( el[ scroll ] > 0 ); 314 el[ scroll ] = 0; 315 return has; 316 } 317}); 318 319})( jQuery ); 320(function( $, undefined ) { 321 322var uuid = 0, 323 slice = Array.prototype.slice, 324 _cleanData = $.cleanData; 325$.cleanData = function( elems ) { 326 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { 327 try { 328 $( elem ).triggerHandler( "remove" ); 329 // http://bugs.jquery.com/ticket/8235 330 } catch( e ) {} 331 } 332 _cleanData( elems ); 333}; 334 335$.widget = function( name, base, prototype ) { 336 var fullName, existingConstructor, constructor, basePrototype, 337 // proxiedPrototype allows the provided prototype to remain unmodified 338 // so that it can be used as a mixin for multiple widgets (#8876) 339 proxiedPrototype = {}, 340 namespace = name.split( "." )[ 0 ]; 341 342 name = name.split( "." )[ 1 ]; 343 fullName = namespace + "-" + name; 344 345 if ( !prototype ) { 346 prototype = base; 347 base = $.Widget; 348 } 349 350 // create selector for plugin 351 $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { 352 return !!$.data( elem, fullName ); 353 }; 354 355 $[ namespace ] = $[ namespace ] || {}; 356 existingConstructor = $[ namespace ][ name ]; 357 constructor = $[ namespace ][ name ] = function( options, element ) { 358 // allow instantiation without "new" keyword 359 if ( !this._createWidget ) { 360 return new constructor( options, element ); 361 } 362 363 // allow instantiation without initializing for simple inheritance 364 // must use "new" keyword (the code above always passes args) 365 if ( arguments.length ) { 366 this._createWidget( options, element ); 367 } 368 }; 369 // extend with the existing constructor to carry over any static properties 370 $.extend( constructor, existingConstructor, { 371 version: prototype.version, 372 // copy the object used to create the prototype in case we need to 373 // redefine the widget later 374 _proto: $.extend( {}, prototype ), 375 // track widgets that inherit from this widget in case this widget is 376 // redefined after a widget inherits from it 377 _childConstructors: [] 378 }); 379 380 basePrototype = new base(); 381 // we need to make the options hash a property directly on the new instance 382 // otherwise we'll modify the options hash on the prototype that we're 383 // inheriting from 384 basePrototype.options = $.widget.extend( {}, basePrototype.options ); 385 $.each( prototype, function( prop, value ) { 386 if ( !$.isFunction( value ) ) { 387 proxiedPrototype[ prop ] = value; 388 return; 389 } 390 proxiedPrototype[ prop ] = (function() { 391 var _super = function() { 392 return base.prototype[ prop ].apply( this, arguments ); 393 }, 394 _superApply = function( args ) { 395 return base.prototype[ prop ].apply( this, args ); 396 }; 397 return function() { 398 var __super = this._super, 399 __superApply = this._superApply, 400 returnValue; 401 402 this._super = _super; 403 this._superApply = _superApply; 404 405 returnValue = value.apply( this, arguments ); 406 407 this._super = __super; 408 this._superApply = __superApply; 409 410 return returnValue; 411 }; 412 })(); 413 }); 414 constructor.prototype = $.widget.extend( basePrototype, { 415 // TODO: remove support for widgetEventPrefix 416 // always use the name + a colon as the prefix, e.g., draggable:start 417 // don't prefix for widgets that aren't DOM-based 418 widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name 419 }, proxiedPrototype, { 420 constructor: constructor, 421 namespace: namespace, 422 widgetName: name, 423 widgetFullName: fullName 424 }); 425 426 // If this widget is being redefined then we need to find all widgets that 427 // are inheriting from it and redefine all of them so that they inherit from 428 // the new version of this widget. We're essentially trying to replace one 429 // level in the prototype chain. 430 if ( existingConstructor ) { 431 $.each( existingConstructor._childConstructors, function( i, child ) { 432 var childPrototype = child.prototype; 433 434 // redefine the child widget using the same prototype that was 435 // originally used, but inherit from the new version of the base 436 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); 437 }); 438 // remove the list of existing child constructors from the old constructor 439 // so the old child constructors can be garbage collected 440 delete existingConstructor._childConstructors; 441 } else { 442 base._childConstructors.push( constructor ); 443 } 444 445 $.widget.bridge( name, constructor ); 446}; 447 448$.widget.extend = function( target ) { 449 var input = slice.call( arguments, 1 ), 450 inputIndex = 0, 451 inputLength = input.length, 452 key, 453 value; 454 for ( ; inputIndex < inputLength; inputIndex++ ) { 455 for ( key in input[ inputIndex ] ) { 456 value = input[ inputIndex ][ key ]; 457 if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { 458 // Clone objects 459 if ( $.isPlainObject( value ) ) { 460 target[ key ] = $.isPlainObject( target[ key ] ) ? 461 $.widget.extend( {}, target[ key ], value ) : 462 // Don't extend strings, arrays, etc. with objects 463 $.widget.extend( {}, value ); 464 // Copy everything else by reference 465 } else { 466 target[ key ] = value; 467 } 468 } 469 } 470 } 471 return target; 472}; 473 474$.widget.bridge = function( name, object ) { 475 var fullName = object.prototype.widgetFullName || name; 476 $.fn[ name ] = function( options ) { 477 var isMethodCall = typeof options === "string", 478 args = slice.call( arguments, 1 ), 479 returnValue = this; 480 481 // allow multiple hashes to be passed on init 482 options = !isMethodCall && args.length ? 483 $.widget.extend.apply( null, [ options ].concat(args) ) : 484 options; 485 486 if ( isMethodCall ) { 487 this.each(function() { 488 var methodValue, 489 instance = $.data( this, fullName ); 490 if ( !instance ) { 491 return $.error( "cannot call methods on " + name + " prior to initialization; " + 492 "attempted to call method '" + options + "'" ); 493 } 494 if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { 495 return $.error( "no such method '" + options + "' for " + name + " widget instance" ); 496 } 497 methodValue = instance[ options ].apply( instance, args ); 498 if ( methodValue !== instance && methodValue !== undefined ) { 499 returnValue = methodValue && methodValue.jquery ? 500 returnValue.pushStack( methodValue.get() ) : 501 methodValue; 502 return false; 503 } 504 }); 505 } else { 506 this.each(function() { 507 var instance = $.data( this, fullName ); 508 if ( instance ) { 509 instance.option( options || {} )._init(); 510 } else { 511 $.data( this, fullName, new object( options, this ) ); 512 } 513 }); 514 } 515 516 return returnValue; 517 }; 518}; 519 520$.Widget = function( /* options, element */ ) {}; 521$.Widget._childConstructors = []; 522 523$.Widget.prototype = { 524 widgetName: "widget", 525 widgetEventPrefix: "", 526 defaultElement: "<div>", 527 options: { 528 disabled: false, 529 530 // callbacks 531 create: null 532 }, 533 _createWidget: function( options, element ) { 534 element = $( element || this.defaultElement || this )[ 0 ]; 535 this.element = $( element ); 536 this.uuid = uuid++; 537 this.eventNamespace = "." + this.widgetName + this.uuid; 538 this.options = $.widget.extend( {}, 539 this.options, 540 this._getCreateOptions(), 541 options ); 542 543 this.bindings = $(); 544 this.hoverable = $(); 545 this.focusable = $(); 546 547 if ( element !== this ) { 548 $.data( element, this.widgetFullName, this ); 549 this._on( true, this.element, { 550 remove: function( event ) { 551 if ( event.target === element ) { 552 this.destroy(); 553 } 554 } 555 }); 556 this.document = $( element.style ? 557 // element within the document 558 element.ownerDocument : 559 // element is window or document 560 element.document || element ); 561 this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); 562 } 563 564 this._create(); 565 this._trigger( "create", null, this._getCreateEventData() ); 566 this._init(); 567 }, 568 _getCreateOptions: $.noop, 569 _getCreateEventData: $.noop, 570 _create: $.noop, 571 _init: $.noop, 572 573 destroy: function() { 574 this._destroy(); 575 // we can probably remove the unbind calls in 2.0 576 // all event bindings should go through this._on() 577 this.element 578 .unbind( this.eventNamespace ) 579 // 1.9 BC for #7810 580 // TODO remove dual storage 581 .removeData( this.widgetName ) 582 .removeData( this.widgetFullName ) 583 // support: jquery <1.6.3 584 // http://bugs.jquery.com/ticket/9413 585 .removeData( $.camelCase( this.widgetFullName ) ); 586 this.widget() 587 .unbind( this.eventNamespace ) 588 .removeAttr( "aria-disabled" ) 589 .removeClass( 590 this.widgetFullName + "-disabled " + 591 "ui-state-disabled" ); 592 593 // clean up events and states 594 this.bindings.unbind( this.eventNamespace ); 595 this.hoverable.removeClass( "ui-state-hover" ); 596 this.focusable.removeClass( "ui-state-focus" ); 597 }, 598 _destroy: $.noop, 599 600 widget: function() { 601 return this.element; 602 }, 603 604 option: function( key, value ) { 605 var options = key, 606 parts, 607 curOption, 608 i; 609 610 if ( arguments.length === 0 ) { 611 // don't return a reference to the internal hash 612 return $.widget.extend( {}, this.options ); 613 } 614 615 if ( typeof key === "string" ) { 616 // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } 617 options = {}; 618 parts = key.split( "." ); 619 key = parts.shift(); 620 if ( parts.length ) { 621 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); 622 for ( i = 0; i < parts.length - 1; i++ ) { 623 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; 624 curOption = curOption[ parts[ i ] ]; 625 } 626 key = parts.pop(); 627 if ( value === undefined ) { 628 return curOption[ key ] === undefined ? null : curOption[ key ]; 629 } 630 curOption[ key ] = value; 631 } else { 632 if ( value === undefined ) { 633 return this.options[ key ] === undefined ? null : this.options[ key ]; 634 } 635 options[ key ] = value; 636 } 637 } 638 639 this._setOptions( options ); 640 641 return this; 642 }, 643 _setOptions: function( options ) { 644 var key; 645 646 for ( key in options ) { 647 this._setOption( key, options[ key ] ); 648 } 649 650 return this; 651 }, 652 _setOption: function( key, value ) { 653 this.options[ key ] = value; 654 655 if ( key === "disabled" ) { 656 this.widget() 657 .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value ) 658 .attr( "aria-disabled", value ); 659 this.hoverable.removeClass( "ui-state-hover" ); 660 this.focusable.removeClass( "ui-state-focus" ); 661 } 662 663 return this; 664 }, 665 666 enable: function() { 667 return this._setOption( "disabled", false ); 668 }, 669 disable: function() { 670 return this._setOption( "disabled", true ); 671 }, 672 673 _on: function( suppressDisabledCheck, element, handlers ) { 674 var delegateElement, 675 instance = this; 676 677 // no suppressDisabledCheck flag, shuffle arguments 678 if ( typeof suppressDisabledCheck !== "boolean" ) { 679 handlers = element; 680 element = suppressDisabledCheck; 681 suppressDisabledCheck = false; 682 } 683 684 // no element argument, shuffle and use this.element 685 if ( !handlers ) { 686 handlers = element; 687 element = this.element; 688 delegateElement = this.widget(); 689 } else { 690 // accept selectors, DOM elements 691 element = delegateElement = $( element ); 692 this.bindings = this.bindings.add( element ); 693 } 694 695 $.each( handlers, function( event, handler ) { 696 function handlerProxy() { 697 // allow widgets to customize the disabled handling 698 // - disabled as an array instead of boolean 699 // - disabled class as method for disabling individual parts 700 if ( !suppressDisabledCheck && 701 ( instance.options.disabled === true || 702 $( this ).hasClass( "ui-state-disabled" ) ) ) { 703 return; 704 } 705 return ( typeof handler === "string" ? instance[ handler ] : handler ) 706 .apply( instance, arguments ); 707 } 708 709 // copy the guid so direct unbinding works 710 if ( typeof handler !== "string" ) { 711 handlerProxy.guid = handler.guid = 712 handler.guid || handlerProxy.guid || $.guid++; 713 } 714 715 var match = event.match( /^(\w+)\s*(.*)$/ ), 716 eventName = match[1] + instance.eventNamespace, 717 selector = match[2]; 718 if ( selector ) { 719 delegateElement.delegate( selector, eventName, handlerProxy ); 720 } else { 721 element.bind( eventName, handlerProxy ); 722 } 723 }); 724 }, 725 726 _off: function( element, eventName ) { 727 eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace; 728 element.unbind( eventName ).undelegate( eventName ); 729 }, 730 731 _delay: function( handler, delay ) { 732 function handlerProxy() { 733 return ( typeof handler === "string" ? instance[ handler ] : handler ) 734 .apply( instance, arguments ); 735 } 736 var instance = this; 737 return setTimeout( handlerProxy, delay || 0 ); 738 }, 739 740 _hoverable: function( element ) { 741 this.hoverable = this.hoverable.add( element ); 742 this._on( element, { 743 mouseenter: function( event ) { 744 $( event.currentTarget ).addClass( "ui-state-hover" ); 745 }, 746 mouseleave: function( event ) { 747 $( event.currentTarget ).removeClass( "ui-state-hover" ); 748 } 749 }); 750 }, 751 752 _focusable: function( element ) { 753 this.focusable = this.focusable.add( element ); 754 this._on( element, { 755 focusin: function( event ) { 756 $( event.currentTarget ).addClass( "ui-state-focus" ); 757 }, 758 focusout: function( event ) { 759 $( event.currentTarget ).removeClass( "ui-state-focus" ); 760 } 761 }); 762 }, 763 764 _trigger: function( type, event, data ) { 765 var prop, orig, 766 callback = this.options[ type ]; 767 768 data = data || {}; 769 event = $.Event( event ); 770 event.type = ( type === this.widgetEventPrefix ? 771 type : 772 this.widgetEventPrefix + type ).toLowerCase(); 773 // the original event may come from any element 774 // so we need to reset the target on the new event 775 event.target = this.element[ 0 ]; 776 777 // copy original event properties over to the new event 778 orig = event.originalEvent; 779 if ( orig ) { 780 for ( prop in orig ) { 781 if ( !( prop in event ) ) { 782 event[ prop ] = orig[ prop ]; 783 } 784 } 785 } 786 787 this.element.trigger( event, data ); 788 return !( $.isFunction( callback ) && 789 callback.apply( this.element[0], [ event ].concat( data ) ) === false || 790 event.isDefaultPrevented() ); 791 } 792}; 793 794$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { 795 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { 796 if ( typeof options === "string" ) { 797 options = { effect: options }; 798 } 799 var hasOptions, 800 effectName = !options ? 801 method : 802 options === true || typeof options === "number" ? 803 defaultEffect : 804 options.effect || defaultEffect; 805 options = options || {}; 806 if ( typeof options === "number" ) { 807 options = { duration: options }; 808 } 809 hasOptions = !$.isEmptyObject( options ); 810 options.complete = callback; 811 if ( options.delay ) { 812 element.delay( options.delay ); 813 } 814 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { 815 element[ method ]( options ); 816 } else if ( effectName !== method && element[ effectName ] ) { 817 element[ effectName ]( options.duration, options.easing, callback ); 818 } else { 819 element.queue(function( next ) { 820 $( this )[ method ](); 821 if ( callback ) { 822 callback.call( element[ 0 ] ); 823 } 824 next(); 825 }); 826 } 827 }; 828}); 829 830})( jQuery ); 831(function( $, undefined ) { 832 833var mouseHandled = false; 834$( document ).mouseup( function() { 835 mouseHandled = false; 836}); 837 838$.widget("ui.mouse", { 839 version: "1.10.0", 840 options: { 841 cancel: "input,textarea,button,select,option", 842 distance: 1, 843 delay: 0 844 }, 845 _mouseInit: function() { 846 var that = this; 847 848 this.element 849 .bind("mousedown."+this.widgetName, function(event) { 850 return that._mouseDown(event); 851 }) 852 .bind("click."+this.widgetName, function(event) { 853 if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) { 854 $.removeData(event.target, that.widgetName + ".preventClickEvent"); 855 event.stopImmediatePropagation(); 856 return false; 857 } 858 }); 859 860 this.started = false; 861 }, 862 863 // TODO: make sure destroying one instance of mouse doesn't mess with 864 // other instances of mouse 865 _mouseDestroy: function() { 866 this.element.unbind("."+this.widgetName); 867 if ( this._mouseMoveDelegate ) { 868 $(document) 869 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate) 870 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate); 871 } 872 }, 873 874 _mouseDown: function(event) { 875 // don't let more than one widget handle mouseStart 876 if( mouseHandled ) { return; } 877 878 // we may have missed mouseup (out of window) 879 (this._mouseStarted && this._mouseUp(event)); 880 881 this._mouseDownEvent = event; 882 883 var that = this, 884 btnIsLeft = (event.which === 1), 885 // event.target.nodeName works around a bug in IE 8 with 886 // disabled inputs (#7620) 887 elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); 888 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { 889 return true; 890 } 891 892 this.mouseDelayMet = !this.options.delay; 893 if (!this.mouseDelayMet) { 894 this._mouseDelayTimer = setTimeout(function() { 895 that.mouseDelayMet = true; 896 }, this.options.delay); 897 } 898 899 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 900 this._mouseStarted = (this._mouseStart(event) !== false); 901 if (!this._mouseStarted) { 902 event.preventDefault(); 903 return true; 904 } 905 } 906 907 // Click event may never have fired (Gecko & Opera) 908 if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) { 909 $.removeData(event.target, this.widgetName + ".preventClickEvent"); 910 } 911 912 // these delegates are required to keep context 913 this._mouseMoveDelegate = function(event) { 914 return that._mouseMove(event); 915 }; 916 this._mouseUpDelegate = function(event) { 917 return that._mouseUp(event); 918 }; 919 $(document) 920 .bind("mousemove."+this.widgetName, this._mouseMoveDelegate) 921 .bind("mouseup."+this.widgetName, this._mouseUpDelegate); 922 923 event.preventDefault(); 924 925 mouseHandled = true; 926 return true; 927 }, 928 929 _mouseMove: function(event) { 930 // IE mouseup check - mouseup happened when mouse was out of window 931 if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) { 932 return this._mouseUp(event); 933 } 934 935 if (this._mouseStarted) { 936 this._mouseDrag(event); 937 return event.preventDefault(); 938 } 939 940 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 941 this._mouseStarted = 942 (this._mouseStart(this._mouseDownEvent, event) !== false); 943 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); 944 } 945 946 return !this._mouseStarted; 947 }, 948 949 _mouseUp: function(event) { 950 $(document) 951 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate) 952 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate); 953 954 if (this._mouseStarted) { 955 this._mouseStarted = false; 956 957 if (event.target === this._mouseDownEvent.target) { 958 $.data(event.target, this.widgetName + ".preventClickEvent", true); 959 } 960 961 this._mouseStop(event); 962 } 963 964 return false; 965 }, 966 967 _mouseDistanceMet: function(event) { 968 return (Math.max( 969 Math.abs(this._mouseDownEvent.pageX - event.pageX), 970 Math.abs(this._mouseDownEvent.pageY - event.pageY) 971 ) >= this.options.distance 972 ); 973 }, 974 975 _mouseDelayMet: function(/* event */) { 976 return this.mouseDelayMet; 977 }, 978 979 // These are placeholder methods, to be overriden by extending plugin 980 _mouseStart: function(/* event */) {}, 981 _mouseDrag: function(/* event */) {}, 982 _mouseStop: function(/* event */) {}, 983 _mouseCapture: function(/* event */) { return true; } 984}); 985 986})(jQuery); 987(function( $, undefined ) { 988 989$.ui = $.ui || {}; 990 991var cachedScrollbarWidth, 992 max = Math.max, 993 abs = Math.abs, 994 round = Math.round, 995 rhorizontal = /left|center|right/, 996 rvertical = /top|center|bottom/, 997 roffset = /[\+\-]\d+%?/, 998 rposition = /^\w+/, 999 rpercent = /%$/, 1000 _position = $.fn.position; 1001 1002function getOffsets( offsets, width, height ) { 1003 return [ 1004 parseInt( offsets[ 0 ], 10 ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), 1005 parseInt( offsets[ 1 ], 10 ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) 1006 ]; 1007} 1008 1009function parseCss( element, property ) { 1010 return parseInt( $.css( element, property ), 10 ) || 0; 1011} 1012 1013function getDimensions( elem ) { 1014 var raw = elem[0]; 1015 if ( raw.nodeType === 9 ) { 1016 return { 1017 width: elem.width(), 1018 height: elem.height(), 1019 offset: { top: 0, left: 0 } 1020 }; 1021 } 1022 if ( $.isWindow( raw ) ) { 1023 return { 1024 width: elem.width(), 1025 height: elem.height(), 1026 offset: { top: elem.scrollTop(), left: elem.scrollLeft() } 1027 }; 1028 } 1029 if ( raw.preventDefault ) { 1030 return { 1031 width: 0, 1032 height: 0, 1033 offset: { top: raw.pageY, left: raw.pageX } 1034 }; 1035 } 1036 return { 1037 width: elem.outerWidth(), 1038 height: elem.outerHeight(), 1039 offset: elem.offset() 1040 }; 1041} 1042 1043$.position = { 1044 scrollbarWidth: function() { 1045 if ( cachedScrollbarWidth !== undefined ) { 1046 return cachedScrollbarWidth; 1047 } 1048 var w1, w2, 1049 div = $( "<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ), 1050 innerDiv = div.children()[0]; 1051 1052 $( "body" ).append( div ); 1053 w1 = innerDiv.offsetWidth; 1054 div.css( "overflow", "scroll" ); 1055 1056 w2 = innerDiv.offsetWidth; 1057 1058 if ( w1 === w2 ) { 1059 w2 = div[0].clientWidth; 1060 } 1061 1062 div.remove(); 1063 1064 return (cachedScrollbarWidth = w1 - w2); 1065 }, 1066 getScrollInfo: function( within ) { 1067 var overflowX = within.isWindow ? "" : within.element.css( "overflow-x" ), 1068 overflowY = within.isWindow ? "" : within.element.css( "overflow-y" ), 1069 hasOverflowX = overflowX === "scroll" || 1070 ( overflowX === "auto" && within.width < within.element[0].scrollWidth ), 1071 hasOverflowY = overflowY === "scroll" || 1072 ( overflowY === "auto" && within.height < within.element[0].scrollHeight ); 1073 return { 1074 width: hasOverflowX ? $.position.scrollbarWidth() : 0, 1075 height: hasOverflowY ? $.position.scrollbarWidth() : 0 1076 }; 1077 }, 1078 getWithinInfo: function( element ) { 1079 var withinElement = $( element || window ), 1080 isWindow = $.isWindow( withinElement[0] ); 1081 return { 1082 element: withinElement, 1083 isWindow: isWindow, 1084 offset: withinElement.offset() || { left: 0, top: 0 }, 1085 scrollLeft: withinElement.scrollLeft(), 1086 scrollTop: withinElement.scrollTop(), 1087 width: isWindow ? withinElement.width() : withinElement.outerWidth(), 1088 height: isWindow ? withinElement.height() : withinElement.outerHeight() 1089 }; 1090 } 1091}; 1092 1093$.fn.position = function( options ) { 1094 if ( !options || !options.of ) { 1095 return _position.apply( this, arguments ); 1096 } 1097 1098 // make a copy, we don't want to modify arguments 1099 options = $.extend( {}, options ); 1100 1101 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, 1102 target = $( options.of ), 1103 within = $.position.getWithinInfo( options.within ), 1104 scrollInfo = $.position.getScrollInfo( within ), 1105 collision = ( options.collision || "flip" ).split( " " ), 1106 offsets = {}; 1107 1108 dimensions = getDimensions( target ); 1109 if ( target[0].preventDefault ) { 1110 // force left top to allow flipping 1111 options.at = "left top"; 1112 } 1113 targetWidth = dimensions.width; 1114 targetHeight = dimensions.height; 1115 targetOffset = dimensions.offset; 1116 // clone to reuse original targetOffset later 1117 basePosition = $.extend( {}, targetOffset ); 1118 1119 // force my and at to have valid horizontal and vertical positions 1120 // if a value is missing or invalid, it will be converted to center 1121 $.each( [ "my", "at" ], function() { 1122 var pos = ( options[ this ] || "" ).split( " " ), 1123 horizontalOffset, 1124 verticalOffset; 1125 1126 if ( pos.length === 1) { 1127 pos = rhorizontal.test( pos[ 0 ] ) ? 1128 pos.concat( [ "center" ] ) : 1129 rvertical.test( pos[ 0 ] ) ? 1130 [ "center" ].concat( pos ) : 1131 [ "center", "center" ]; 1132 } 1133 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; 1134 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; 1135 1136 // calculate offsets 1137 horizontalOffset = roffset.exec( pos[ 0 ] ); 1138 verticalOffset = roffset.exec( pos[ 1 ] ); 1139 offsets[ this ] = [ 1140 horizontalOffset ? horizontalOffset[ 0 ] : 0, 1141 verticalOffset ? verticalOffset[ 0 ] : 0 1142 ]; 1143 1144 // reduce to just the positions without the offsets 1145 options[ this ] = [ 1146 rposition.exec( pos[ 0 ] )[ 0 ], 1147 rposition.exec( pos[ 1 ] )[ 0 ] 1148 ]; 1149 }); 1150 1151 // normalize collision option 1152 if ( collision.length === 1 ) { 1153 collision[ 1 ] = collision[ 0 ]; 1154 } 1155 1156 if ( options.at[ 0 ] === "right" ) { 1157 basePosition.left += targetWidth; 1158 } else if ( options.at[ 0 ] === "center" ) { 1159 basePosition.left += targetWidth / 2; 1160 } 1161 1162 if ( options.at[ 1 ] === "bottom" ) { 1163 basePosition.top += targetHeight; 1164 } else if ( options.at[ 1 ] === "center" ) { 1165 basePosition.top += targetHeight / 2; 1166 } 1167 1168 atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); 1169 basePosition.left += atOffset[ 0 ]; 1170 basePosition.top += atOffset[ 1 ]; 1171 1172 return this.each(function() { 1173 var collisionPosition, using, 1174 elem = $( this ), 1175 elemWidth = elem.outerWidth(), 1176 elemHeight = elem.outerHeight(), 1177 marginLeft = parseCss( this, "marginLeft" ), 1178 marginTop = parseCss( this, "marginTop" ), 1179 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width, 1180 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height, 1181 position = $.extend( {}, basePosition ), 1182 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); 1183 1184 if ( options.my[ 0 ] === "right" ) { 1185 position.left -= elemWidth; 1186 } else if ( options.my[ 0 ] === "center" ) { 1187 position.left -= elemWidth / 2; 1188 } 1189 1190 if ( options.my[ 1 ] === "bottom" ) { 1191 position.top -= elemHeight; 1192 } else if ( options.my[ 1 ] === "center" ) { 1193 position.top -= elemHeight / 2; 1194 } 1195 1196 position.left += myOffset[ 0 ]; 1197 position.top += myOffset[ 1 ]; 1198 1199 // if the browser doesn't support fractions, then round for consistent results 1200 if ( !$.support.offsetFractions ) { 1201 position.left = round( position.left ); 1202 position.top = round( position.top ); 1203 } 1204 1205 collisionPosition = { 1206 marginLeft: marginLeft, 1207 marginTop: marginTop 1208 }; 1209 1210 $.each( [ "left", "top" ], function( i, dir ) { 1211 if ( $.ui.position[ collision[ i ] ] ) { 1212 $.ui.position[ collision[ i ] ][ dir ]( position, { 1213 targetWidth: targetWidth, 1214 targetHeight: targetHeight, 1215 elemWidth: elemWidth, 1216 elemHeight: elemHeight, 1217 collisionPosition: collisionPosition, 1218 collisionWidth: collisionWidth, 1219 collisionHeight: collisionHeight, 1220 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], 1221 my: options.my, 1222 at: options.at, 1223 within: within, 1224 elem : elem 1225 }); 1226 } 1227 }); 1228 1229 if ( options.using ) { 1230 // adds feedback as second argument to using callback, if present 1231 using = function( props ) { 1232 var left = targetOffset.left - position.left, 1233 right = left + targetWidth - elemWidth, 1234 top = targetOffset.top - position.top, 1235 bottom = top + targetHeight - elemHeight, 1236 feedback = { 1237 target: { 1238 element: target, 1239 left: targetOffset.left, 1240 top: targetOffset.top, 1241 width: targetWidth, 1242 height: targetHeight 1243 }, 1244 element: { 1245 element: elem, 1246 left: position.left, 1247 top: position.top, 1248 width: elemWidth, 1249 height: elemHeight 1250 }, 1251 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", 1252 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" 1253 }; 1254 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { 1255 feedback.horizontal = "center"; 1256 } 1257 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { 1258 feedback.vertical = "middle"; 1259 } 1260 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { 1261 feedback.important = "horizontal"; 1262 } else { 1263 feedback.important = "vertical"; 1264 } 1265 options.using.call( this, props, feedback ); 1266 }; 1267 } 1268 1269 elem.offset( $.extend( position, { using: using } ) ); 1270 }); 1271}; 1272 1273$.ui.position = { 1274 fit: { 1275 left: function( position, data ) { 1276 var within = data.within, 1277 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, 1278 outerWidth = within.width, 1279 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 1280 overLeft = withinOffset - collisionPosLeft, 1281 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, 1282 newOverRight; 1283 1284 // element is wider than within 1285 if ( data.collisionWidth > outerWidth ) { 1286 // element is initially over the left side of within 1287 if ( overLeft > 0 && overRight <= 0 ) { 1288 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset; 1289 position.left += overLeft - newOverRight; 1290 // element is initially over right side of within 1291 } else if ( overRight > 0 && overLeft <= 0 ) { 1292 position.left = withinOffset; 1293 // element is initially over both left and right sides of within 1294 } else { 1295 if ( overLeft > overRight ) { 1296 position.left = withinOffset + outerWidth - data.collisionWidth; 1297 } else { 1298 position.left = withinOffset; 1299 } 1300 } 1301 // too far left -> align with left edge 1302 } else if ( overLeft > 0 ) { 1303 position.left += overLeft; 1304 // too far right -> align with right edge 1305 } else if ( overRight > 0 ) { 1306 position.left -= overRight; 1307 // adjust based on position and margin 1308 } else { 1309 position.left = max( position.left - collisionPosLeft, position.left ); 1310 } 1311 }, 1312 top: function( position, data ) { 1313 var within = data.within, 1314 withinOffset = within.isWindow ? within.scrollTop : within.offset.top, 1315 outerHeight = data.within.height, 1316 collisionPosTop = position.top - data.collisionPosition.marginTop, 1317 overTop = withinOffset - collisionPosTop, 1318 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, 1319 newOverBottom; 1320 1321 // element is taller than within 1322 if ( data.collisionHeight > outerHeight ) { 1323 // element is initially over the top of within 1324 if ( overTop > 0 && overBottom <= 0 ) { 1325 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset; 1326 position.top += overTop - newOverBottom; 1327 // element is initially over bottom of within 1328 } else if ( overBottom > 0 && overTop <= 0 ) { 1329 position.top = withinOffset; 1330 // element is initially over both top and bottom of within 1331 } else { 1332 if ( overTop > overBottom ) { 1333 position.top = withinOffset + outerHeight - data.collisionHeight; 1334 } else { 1335 position.top = withinOffset; 1336 } 1337 } 1338 // too far up -> align with top 1339 } else if ( overTop > 0 ) { 1340 position.top += overTop; 1341 // too far down -> align with bottom edge 1342 } else if ( overBottom > 0 ) { 1343 position.top -= overBottom; 1344 // adjust based on position and margin 1345 } else { 1346 position.top = max( position.top - collisionPosTop, position.top ); 1347 } 1348 } 1349 }, 1350 flip: { 1351 left: function( position, data ) { 1352 var within = data.within, 1353 withinOffset = within.offset.left + within.scrollLeft, 1354 outerWidth = within.width, 1355 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, 1356 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 1357 overLeft = collisionPosLeft - offsetLeft, 1358 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, 1359 myOffset = data.my[ 0 ] === "left" ? 1360 -data.elemWidth : 1361 data.my[ 0 ] === "right" ? 1362 data.elemWidth : 1363 0, 1364 atOffset = data.at[ 0 ] === "left" ? 1365 data.targetWidth : 1366 data.at[ 0 ] === "right" ? 1367 -data.targetWidth : 1368 0, 1369 offset = -2 * data.offset[ 0 ], 1370 newOverRight, 1371 newOverLeft; 1372 1373 if ( overLeft < 0 ) { 1374 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset; 1375 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { 1376 position.left += myOffset + atOffset + offset; 1377 } 1378 } 1379 else if ( overRight > 0 ) { 1380 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft; 1381 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { 1382 position.left += myOffset + atOffset + offset; 1383 } 1384 } 1385 }, 1386 top: function( position, data ) { 1387 var within = data.within, 1388 withinOffset = within.offset.top + within.scrollTop, 1389 outerHeight = within.height, 1390 offsetTop = within.isWindow ? within.scrollTop : within.offset.top, 1391 collisionPosTop = position.top - data.collisionPosition.marginTop, 1392 overTop = collisionPosTop - offsetTop, 1393 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, 1394 top = data.my[ 1 ] === "top", 1395 myOffset = top ? 1396 -data.elemHeight : 1397 data.my[ 1 ] === "bottom" ? 1398 data.elemHeight : 1399 0, 1400 atOffset = data.at[ 1 ] === "top" ? 1401 data.targetHeight : 1402 data.at[ 1 ] === "bottom" ? 1403 -data.targetHeight : 1404 0, 1405 offset = -2 * data.offset[ 1 ], 1406 newOverTop, 1407 newOverBottom; 1408 if ( overTop < 0 ) { 1409 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset; 1410 if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) { 1411 position.top += myOffset + atOffset + offset; 1412 } 1413 } 1414 else if ( overBottom > 0 ) { 1415 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop; 1416 if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) { 1417 position.top += myOffset + atOffset + offset; 1418 } 1419 } 1420 } 1421 }, 1422 flipfit: { 1423 left: function() { 1424 $.ui.position.flip.left.apply( this, arguments ); 1425 $.ui.position.fit.left.apply( this, arguments ); 1426 }, 1427 top: function() { 1428 $.ui.position.flip.top.apply( this, arguments ); 1429 $.ui.position.fit.top.apply( this, arguments ); 1430 } 1431 } 1432}; 1433 1434// fraction support test 1435(function () { 1436 var testElement, testElementParent, testElementStyle, offsetLeft, i, 1437 body = document.getElementsByTagName( "body" )[ 0 ], 1438 div = document.createElement( "div" ); 1439 1440 //Create a "fake body" for testing based on method used in jQuery.support 1441 testElement = document.createElement( body ? "div" : "body" ); 1442 testElementStyle = { 1443 visibility: "hidden", 1444 width: 0, 1445 height: 0, 1446 border: 0, 1447 margin: 0, 1448 background: "none" 1449 }; 1450 if ( body ) { 1451 $.extend( testElementStyle, { 1452 position: "absolute", 1453 left: "-1000px", 1454 top: "-1000px" 1455 }); 1456 } 1457 for ( i in testElementStyle ) { 1458 testElement.style[ i ] = testElementStyle[ i ]; 1459 } 1460 testElement.appendChild( div ); 1461 testElementParent = body || document.documentElement; 1462 testElementParent.insertBefore( testElement, testElementParent.firstChild ); 1463 1464 div.style.cssText = "position: absolute; left: 10.7432222px;"; 1465 1466 offsetLeft = $( div ).offset().left; 1467 $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11; 1468 1469 testElement.innerHTML = ""; 1470 testElementParent.removeChild( testElement ); 1471})(); 1472 1473}( jQuery ) ); 1474(function( $, undefined ) { 1475 1476$.widget("ui.draggable", $.ui.mouse, { 1477 version: "1.10.0", 1478 widgetEventPrefix: "drag", 1479 options: { 1480 addClasses: true, 1481 appendTo: "parent", 1482 axis: false, 1483 connectToSortable: false, 1484 containment: false, 1485 cursor: "auto", 1486 cursorAt: false, 1487 grid: false, 1488 handle: false, 1489 helper: "original", 1490 iframeFix: false, 1491 opacity: false, 1492 refreshPositions: false, 1493 revert: false, 1494 revertDuration: 500, 1495 scope: "default", 1496 scroll: true, 1497 scrollSensitivity: 20, 1498 scrollSpeed: 20, 1499 snap: false, 1500 snapMode: "both", 1501 snapTolerance: 20, 1502 stack: false, 1503 zIndex: false, 1504 1505 // callbacks 1506 drag: null, 1507 start: null, 1508 stop: null 1509 }, 1510 _create: function() { 1511 1512 if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) { 1513 this.element[0].style.position = "relative"; 1514 } 1515 if (this.options.addClasses){ 1516 this.element.addClass("ui-draggable"); 1517 } 1518 if (this.options.disabled){ 1519 this.element.addClass("ui-draggable-disabled"); 1520 } 1521 1522 this._mouseInit(); 1523 1524 }, 1525 1526 _destroy: function() { 1527 this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" ); 1528 this._mouseDestroy(); 1529 }, 1530 1531 _mouseCapture: function(event) { 1532 1533 var o = this.options; 1534 1535 // among others, prevent a drag on a resizable-handle 1536 if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) { 1537 return false; 1538 } 1539 1540 //Quit if we're not on a valid handle 1541 this.handle = this._getHandle(event); 1542 if (!this.handle) { 1543 return false; 1544 } 1545 1546 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { 1547 $("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>") 1548 .css({ 1549 width: this.offsetWidth+"px", height: this.offsetHeight+"px", 1550 position: "absolute", opacity: "0.001", zIndex: 1000 1551 }) 1552 .css($(this).offset()) 1553 .appendTo("body"); 1554 }); 1555 1556 return true; 1557 1558 }, 1559 1560 _mouseStart: function(event) { 1561 1562 var o = this.options; 1563 1564 //Create and append the visible helper 1565 this.helper = this._createHelper(event); 1566 1567 this.helper.addClass("ui-draggable-dragging"); 1568 1569 //Cache the helper size 1570 this._cacheHelperProportions(); 1571 1572 //If ddmanager is used for droppables, set the global draggable 1573 if($.ui.ddmanager) { 1574 $.ui.ddmanager.current = this; 1575 } 1576 1577 /* 1578 * - Position generation - 1579 * This block generates everything position related - it's the core of draggables. 1580 */ 1581 1582 //Cache the margins of the original element 1583 this._cacheMargins(); 1584 1585 //Store the helper's css position 1586 this.cssPosition = this.helper.css("position"); 1587 this.scrollParent = this.helper.scrollParent(); 1588 1589 //The element's absolute position on the page minus margins 1590 this.offset = this.positionAbs = this.element.offset(); 1591 this.offset = { 1592 top: this.offset.top - this.margins.top, 1593 left: this.offset.left - this.margins.left 1594 }; 1595 1596 $.extend(this.offset, { 1597 click: { //Where the click happened, relative to the element 1598 left: event.pageX - this.offset.left, 1599 top: event.pageY - this.offset.top 1600 }, 1601 parent: this._getParentOffset(), 1602 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper 1603 }); 1604 1605 //Generate the original position 1606 this.originalPosition = this.position = this._generatePosition(event); 1607 this.originalPageX = event.pageX; 1608 this.originalPageY = event.pageY; 1609 1610 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 1611 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); 1612 1613 //Set a containment if given in the options 1614 if(o.containment) { 1615 this._setContainment(); 1616 } 1617 1618 //Trigger event + callbacks 1619 if(this._trigger("start", event) === false) { 1620 this._clear(); 1621 return false; 1622 } 1623 1624 //Recache the helper size 1625 this._cacheHelperProportions(); 1626 1627 //Prepare the droppable offsets 1628 if ($.ui.ddmanager && !o.dropBehaviour) { 1629 $.ui.ddmanager.prepareOffsets(this, event); 1630 } 1631 1632 1633 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position 1634 1635 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) 1636 if ( $.ui.ddmanager ) { 1637 $.ui.ddmanager.dragStart(this, event); 1638 } 1639 1640 return true; 1641 }, 1642 1643 _mouseDrag: function(event, noPropagation) { 1644 1645 //Compute the helpers position 1646 this.position = this._generatePosition(event); 1647 this.positionAbs = this._convertPositionTo("absolute"); 1648 1649 //Call plugins and callbacks and use the resulting position if something is returned 1650 if (!noPropagation) { 1651 var ui = this._uiHash(); 1652 if(this._trigger("drag", event, ui) === false) { 1653 this._mouseUp({}); 1654 return false; 1655 } 1656 this.position = ui.position; 1657 } 1658 1659 if(!this.options.axis || this.options.axis !== "y") { 1660 this.helper[0].style.left = this.position.left+"px"; 1661 } 1662 if(!this.options.axis || this.options.axis !== "x") { 1663 this.helper[0].style.top = this.position.top+"px"; 1664 } 1665 if($.ui.ddmanager) { 1666 $.ui.ddmanager.drag(this, event); 1667 } 1668 1669 return false; 1670 }, 1671 1672 _mouseStop: function(event) { 1673 1674 //If we are using droppables, inform the manager about the drop 1675 var element, 1676 that = this, 1677 elementInDom = false, 1678 dropped = false; 1679 if ($.ui.ddmanager && !this.options.dropBehaviour) { 1680 dropped = $.ui.ddmanager.drop(this, event); 1681 } 1682 1683 //if a drop comes from outside (a sortable) 1684 if(this.dropped) { 1685 dropped = this.dropped; 1686 this.dropped = false; 1687 } 1688 1689 //if the original element is no longer in the DOM don't bother to continue (see #8269) 1690 element = this.element[0]; 1691 while ( element && (element = element.parentNode) ) { 1692 if (element === document ) { 1693 elementInDom = true; 1694 } 1695 } 1696 if ( !elementInDom && this.options.helper === "original" ) { 1697 return false; 1698 } 1699 1700 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))) { 1701 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { 1702 if(that._trigger("stop", event) !== false) { 1703 that._clear(); 1704 } 1705 }); 1706 } else { 1707 if(this._trigger("stop", event) !== false) { 1708 this._clear(); 1709 } 1710 } 1711 1712 return false; 1713 }, 1714 1715 _mouseUp: function(event) { 1716 //Remove frame helpers 1717 $("div.ui-draggable-iframeFix").each(function() { 1718 this.parentNode.removeChild(this); 1719 }); 1720 1721 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) 1722 if( $.ui.ddmanager ) { 1723 $.ui.ddmanager.dragStop(this, event); 1724 } 1725 1726 return $.ui.mouse.prototype._mouseUp.call(this, event); 1727 }, 1728 1729 cancel: function() { 1730 1731 if(this.helper.is(".ui-draggable-dragging")) { 1732 this._mouseUp({}); 1733 } else { 1734 this._clear(); 1735 } 1736 1737 return this; 1738 1739 }, 1740 1741 _getHandle: function(event) { 1742 1743 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false; 1744 $(this.options.handle, this.element) 1745 .find("*") 1746 .addBack() 1747 .each(function() { 1748 if(this === event.target) { 1749 handle = true; 1750 } 1751 }); 1752 1753 return handle; 1754 1755 }, 1756 1757 _createHelper: function(event) { 1758 1759 var o = this.options, 1760 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element); 1761 1762 if(!helper.parents("body").length) { 1763 helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo)); 1764 } 1765 1766 if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) { 1767 helper.css("position", "absolute"); 1768 } 1769 1770 return helper; 1771 1772 }, 1773 1774 _adjustOffsetFromHelper: function(obj) { 1775 if (typeof obj === "string") { 1776 obj = obj.split(" "); 1777 } 1778 if ($.isArray(obj)) { 1779 obj = {left: +obj[0], top: +obj[1] || 0}; 1780 } 1781 if ("left" in obj) { 1782 this.offset.click.left = obj.left + this.margins.left; 1783 } 1784 if ("right" in obj) { 1785 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 1786 } 1787 if ("top" in obj) { 1788 this.offset.click.top = obj.top + this.margins.top; 1789 } 1790 if ("bottom" in obj) { 1791 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 1792 } 1793 }, 1794 1795 _getParentOffset: function() { 1796 1797 //Get the offsetParent and cache its position 1798 this.offsetParent = this.helper.offsetParent(); 1799 var po = this.offsetParent.offset(); 1800 1801 // This is a special case where we need to modify a offset calculated on start, since the following happened: 1802 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent 1803 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that 1804 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag 1805 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { 1806 po.left += this.scrollParent.scrollLeft(); 1807 po.top += this.scrollParent.scrollTop(); 1808 } 1809 1810 //This needs to be actually done for all browsers, since pageX/pageY includes this information 1811 //Ugly IE fix 1812 if((this.offsetParent[0] === document.body) || 1813 (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { 1814 po = { top: 0, left: 0 }; 1815 } 1816 1817 return { 1818 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),
vendor: 1,408 bytes, lines 1818-1865
181810) || 0), 1819 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) 1820 }; 1821 1822 }, 1823 1824 _getRelativeOffset: function() { 1825 1826 if(this.cssPosition === "relative") { 1827 var p = this.element.position(); 1828 return { 1829 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), 1830 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() 1831 }; 1832 } else { 1833 return { top: 0, left: 0 }; 1834 } 1835 1836 }, 1837 1838 _cacheMargins: function() { 1839 this.margins = { 1840 left: (parseInt(this.element.css("marginLeft"),10) || 0), 1841 top: (parseInt(this.element.css("marginTop"),10) || 0), 1842 right: (parseInt(this.element.css("marginRight"),10) || 0), 1843 bottom: (parseInt(this.element.css("marginBottom"),10) || 0) 1844 }; 1845 }, 1846 1847 _cacheHelperProportions: function() { 1848 this.helperProportions = { 1849 width: this.helper.outerWidth(), 1850 height: this.helper.outerHeight() 1851 }; 1852 }, 1853 1854 _setContainment: function() { 1855 1856 var over, c, ce, 1857 o = this.options; 1858 1859 if(o.containment === "parent") { 1860 o.containment = this.helper[0].parentNode; 1861 } 1862 if(o.containment === "document" || o.containment === "window") { 1863 this.containment = [ 1864 o.containment === "document" ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left, 1865 o.containment === "document" ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
vendor: 6,288 bytes, lines 1866-1998
1866 (o.containment === "document" ? 0 : $(window).scrollLeft()) + $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left, 1867 (o.containment === "document" ? 0 : $(window).scrollTop()) + ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top 1868 ]; 1869 } 1870 1871 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor !== Array) { 1872 c = $(o.containment); 1873 ce = c[0]; 1874 1875 if(!ce) { 1876 return; 1877 } 1878 1879 over = ($(ce).css("overflow") !== "hidden"); 1880 1881 this.containment = [ 1882 (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0), 1883 (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0), 1884 (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 - this.margins.right, 1885 (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 - this.margins.bottom 1886 ]; 1887 this.relative_container = c; 1888 1889 } else if(o.containment.constructor === Array) { 1890 this.containment = o.containment; 1891 } 1892 1893 }, 1894 1895 _convertPositionTo: function(d, pos) { 1896 1897 if(!pos) { 1898 pos = this.position; 1899 } 1900 1901 var mod = d === "absolute" ? 1 : -1, 1902 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 1903 1904 return { 1905 top: ( 1906 pos.top + // The absolute mouse position 1907 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 1908 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) 1909 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) 1910 ), 1911 left: ( 1912 pos.left + // The absolute mouse position 1913 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 1914 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) 1915 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) 1916 ) 1917 }; 1918 1919 }, 1920 1921 _generatePosition: function(event) { 1922 1923 var containment, co, top, left, 1924 o = this.options, 1925 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, 1926 scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName), 1927 pageX = event.pageX, 1928 pageY = event.pageY; 1929 1930 /* 1931 * - Position constraining - 1932 * Constrain the position to a mix of grid, containment. 1933 */ 1934 1935 if(this.originalPosition) { //If we are not dragging yet, we won't check for options 1936 if(this.containment) { 1937 if (this.relative_container){ 1938 co = this.relative_container.offset(); 1939 containment = [ this.containment[0] + co.left, 1940 this.containment[1] + co.top, 1941 this.containment[2] + co.left, 1942 this.containment[3] + co.top ]; 1943 } 1944 else { 1945 containment = this.containment; 1946 } 1947 1948 if(event.pageX - this.offset.click.left < containment[0]) { 1949 pageX = containment[0] + this.offset.click.left; 1950 } 1951 if(event.pageY - this.offset.click.top < containment[1]) { 1952 pageY = containment[1] + this.offset.click.top; 1953 } 1954 if(event.pageX - this.offset.click.left > containment[2]) { 1955 pageX = containment[2] + this.offset.click.left; 1956 } 1957 if(event.pageY - this.offset.click.top > containment[3]) { 1958 pageY = containment[3] + this.offset.click.top; 1959 } 1960 } 1961 1962 if(o.grid) { 1963 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) 1964 top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; 1965 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; 1966 1967 left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; 1968 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; 1969 } 1970 1971 } 1972 1973 return { 1974 top: ( 1975 pageY - // The absolute mouse position 1976 this.offset.click.top - // Click offset (relative to the element) 1977 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent 1978 this.offset.parent.top + // The offsetParent's offset without borders (offset + border) 1979 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) 1980 ), 1981 left: ( 1982 pageX - // The absolute mouse position 1983 this.offset.click.left - // Click offset (relative to the element) 1984 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent 1985 this.offset.parent.left + // The offsetParent's offset without borders (offset + border) 1986 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) 1987 ) 1988 }; 1989 1990 }, 1991 1992 _clear: function() { 1993 this.helper.removeClass("ui-draggable-dragging"); 1994 if(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) { 1995 this.helper.remove(); 1996 } 1997 this.helper = null; 1998 this.cancelHelperRemoval = false;
1999 }, 2000 2001 // From now on bulk stuff - mainly helpers 2002 2003 _trigger: function(type, event, ui) { 2004 ui = ui || this._uiHash(); 2005 $.ui.plugin.call(this, type, [event, ui]); 2006 //The absolute position has to be recalculated after plugins 2007 if(type === "drag") { 2008 this.positionAbs = this._convertPositionTo("absolute"); 2009 } 2010 return $.Widget.prototype._trigger.call(this, type, event, ui); 2011 }, 2012 2013 plugins: {}, 2014 2015 _uiHash: function() { 2016 return { 2017 helper: this.helper, 2018 position: this.position, 2019 originalPosition: this.originalPosition, 2020 offset: this.positionAbs 2021 }; 2022 } 2023 2024}); 2025 2026$.ui.plugin.add("draggable", "connectToSortable", { 2027 start: function(event, ui) { 2028 2029 var inst = $(this).data("ui-draggable"), o = inst.options, 2030 uiSortable = $.extend({}, ui, { item: inst.element }); 2031 inst.sortables = []; 2032 $(o.connectToSortable).each(function() { 2033 var sortable = $.data(this, "ui-sortable"); 2034 if (sortable && !sortable.options.disabled) { 2035 inst.sortables.push({ 2036 instance: sortable, 2037 shouldRevert: sortable.options.revert 2038 }); 2039 sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page). 2040 sortable._trigger("activate", event, uiSortable); 2041 } 2042 }); 2043 2044 }, 2045 stop: function(event, ui) { 2046 2047 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper 2048 var inst = $(this).data("ui-draggable"), 2049 uiSortable = $.extend({}, ui, { item: inst.element }); 2050 2051 $.each(inst.sortables, function() { 2052 if(this.instance.isOver) { 2053 2054 this.instance.isOver = 0; 2055 2056 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance 2057 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) 2058 2059 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid" 2060 if(this.shouldRevert) { 2061 this.instance.options.revert = true; 2062 } 2063 2064 //Trigger the stop of the sortable 2065 this.instance._mouseStop(event); 2066 2067 this.instance.options.helper = this.instance.options._helper; 2068 2069 //If the helper has been the original item, restore properties in the sortable 2070 if(inst.options.helper === "original") { 2071 this.instance.currentItem.css({ top: "auto", left: "auto" }); 2072 } 2073 2074 } else { 2075 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance 2076 this.instance._trigger("deactivate", event, uiSortable); 2077 } 2078 2079 }); 2080 2081 }, 2082 drag: function(event, ui) { 2083 2084 var inst = $(this).data("ui-draggable"), that = this; 2085 2086 $.each(inst.sortables, function() { 2087 2088 var innermostIntersecting = false, 2089 thisSortable = this; 2090 2091 //Copy over some variables to allow calling the sortable's native _intersectsWith 2092 this.instance.positionAbs = inst.positionAbs; 2093 this.instance.helperProportions = inst.helperProportions; 2094 this.instance.offset.click = inst.offset.click; 2095 2096 if(this.instance._intersectsWith(this.instance.containerCache)) { 2097 innermostIntersecting = true; 2098 $.each(inst.sortables, function () { 2099 this.instance.positionAbs = inst.positionAbs; 2100 this.instance.helperProportions = inst.helperProportions; 2101 this.instance.offset.click = inst.offset.click; 2102 if (this !== thisSortable && 2103 this.instance._intersectsWith(this.instance.containerCache) && 2104 $.ui.contains(thisSortable.instance.element[0], this.instance.element[0]) 2105 ) { 2106 innermostIntersecting = false; 2107 } 2108 return innermostIntersecting; 2109 }); 2110 } 2111 2112 2113 if(innermostIntersecting) { 2114 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once 2115 if(!this.instance.isOver) { 2116 2117 this.instance.isOver = 1; 2118 //Now we fake the start of dragging for the sortable instance, 2119 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem 2120 //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one) 2121 this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true); 2122 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it 2123 this.instance.options.helper = function() { return ui.helper[0]; }; 2124 2125 event.target = this.instance.currentItem[0]; 2126 this.instance._mouseCapture(event, true); 2127 this.instance._mouseStart(event, true, true); 2128
2129 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes 2130 this.instance.offset.click.top = inst.offset.click.top; 2131 this.instance.offset.click.left = inst.offset.click.left; 2132 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; 2133 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; 2134 2135 inst._trigger("toSortable", event); 2136 inst.dropped = this.instance.element; //draggable revert needs that 2137 //hack so receive/update callbacks work (mostly) 2138 inst.currentItem = inst.element; 2139 this.instance.fromOutside = inst; 2140 2141 } 2142 2143 //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable 2144 if(this.instance.currentItem) { 2145 this.instance._mouseDrag(event); 2146 } 2147 2148 } else { 2149 2150 //If it doesn't intersect with the sortable, and it intersected before, 2151 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval 2152 if(this.instance.isOver) { 2153 2154 this.instance.isOver = 0; 2155 this.instance.cancelHelperRemoval = true; 2156 2157 //Prevent reverting on this forced stop 2158 this.instance.options.revert = false; 2159 2160 // The out event needs to be triggered independently 2161 this.instance._trigger("out", event, this.instance._uiHash(this.instance)); 2162 2163 this.instance._mouseStop(event, true); 2164 this.instance.options.helper = this.instance.options._helper; 2165 2166 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size 2167 this.instance.currentItem.remove(); 2168 if(this.instance.placeholder) { 2169 this.instance.placeholder.remove(); 2170 } 2171 2172 inst._trigger("fromSortable", event); 2173 inst.dropped = false; //draggable revert needs that 2174 } 2175 2176 } 2177 2178 }); 2179 2180 } 2181}); 2182 2183$.ui.plugin.add("draggable", "cursor", { 2184 start: function() { 2185 var t = $("body"), o = $(this).data("ui-draggable").options; 2186 if (t.css("cursor")) { 2187 o._cursor = t.css("cursor"); 2188 } 2189 t.css("cursor", o.cursor); 2190 }, 2191 stop: function() { 2192 var o = $(this).data("ui-draggable").options; 2193 if (o._cursor) { 2194 $("body").css("cursor", o._cursor); 2195 } 2196 } 2197}); 2198 2199$.ui.plugin.add("draggable", "opacity", { 2200 start: function(event, ui) { 2201 var t = $(ui.helper), o = $(this).data("ui-draggable").options; 2202 if(t.css("opacity")) { 2203 o._opacity = t.css("opacity"); 2204 } 2205 t.css("opacity", o.opacity); 2206 }, 2207 stop: function(event, ui) { 2208 var o = $(this).data("ui-draggable").options; 2209 if(o._opacity) { 2210 $(ui.helper).css("opacity", o._opacity); 2211 } 2212 } 2213}); 2214 2215$.ui.plugin.add("draggable", "scroll", { 2216 start: function() { 2217 var i = $(this).data("ui-draggable"); 2218 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") { 2219 i.overflowOffset = i.scrollParent.offset(); 2220 } 2221 }, 2222 drag: function( event ) { 2223 2224 var i = $(this).data("ui-draggable"), o = i.options, scrolled = false; 2225 2226 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") { 2227 2228 if(!o.axis || o.axis !== "x") { 2229 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { 2230 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; 2231 } else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) { 2232 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; 2233 } 2234 } 2235 2236 if(!o.axis || o.axis !== "y") { 2237 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { 2238 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; 2239 } else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) { 2240 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; 2241 } 2242 } 2243 2244 } else { 2245 2246 if(!o.axis || o.axis !== "x") { 2247 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { 2248 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); 2249 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { 2250 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); 2251 } 2252 } 2253 2254 if(!o.axis || o.axis !== "y") { 2255 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { 2256 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); 2257 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { 2258 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); 2259 } 2260 } 2261 2262 } 2263 2264 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { 2265 $.ui.ddmanager.prepareOffsets(i, event); 2266 } 2267 2268 } 2269}); 2270 2271$.ui.plugin.add("draggable", "snap", { 2272 start: function() { 2273 2274 var i = $(this).data("ui-draggable"), 2275 o = i.options; 2276 2277 i.snapElements = []; 2278 2279 $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() { 2280 var $t = $(this), 2281 $o = $t.offset(); 2282 if(this !== i.element[0]) { 2283 i.snapElements.push({ 2284 item: this, 2285 width: $t.outerWidth(), height: $t.outerHeight(), 2286 top: $o.top, left: $o.left 2287 }); 2288 } 2289 }); 2290 2291 }, 2292 drag: function(event, ui) { 2293 2294 var ts, bs, ls, rs, l, r, t, b, i, first, 2295 inst = $(this).data("ui-draggable"), 2296 o = inst.options, 2297 d = o.snapTolerance, 2298 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, 2299 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; 2300 2301 for (i = inst.snapElements.length - 1; i >= 0; i--){ 2302 2303 l = inst.snapElements[i].left; 2304 r = l + inst.snapElements[i].width; 2305 t = inst.snapElements[i].top; 2306 b = t + inst.snapElements[i].height; 2307 2308 //Yes, I know, this is insane ;) 2309 if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) { 2310 if(inst.snapElements[i].snapping) { 2311 (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); 2312 } 2313 inst.snapElements[i].snapping = false;
vendor: 32,426 bytes, lines 2314-3456
2314 continue; 2315 } 2316 2317 if(o.snapMode !== "inner") { 2318 ts = Math.abs(t - y2) <= d; 2319 bs = Math.abs(b - y1) <= d; 2320 ls = Math.abs(l - x2) <= d; 2321 rs = Math.abs(r - x1) <= d; 2322 if(ts) { 2323 ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; 2324 } 2325 if(bs) { 2326 ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; 2327 } 2328 if(ls) { 2329 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; 2330 } 2331 if(rs) { 2332 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; 2333 } 2334 } 2335 2336 first = (ts || bs || ls || rs); 2337 2338 if(o.snapMode !== "outer") { 2339 ts = Math.abs(t - y1) <= d; 2340 bs = Math.abs(b - y2) <= d; 2341 ls = Math.abs(l - x1) <= d; 2342 rs = Math.abs(r - x2) <= d; 2343 if(ts) { 2344 ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; 2345 } 2346 if(bs) { 2347 ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; 2348 } 2349 if(ls) { 2350 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; 2351 } 2352 if(rs) { 2353 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; 2354 } 2355 } 2356 2357 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) { 2358 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); 2359 } 2360 inst.snapElements[i].snapping = (ts || bs || ls || rs || first); 2361 2362 } 2363 2364 } 2365}); 2366 2367$.ui.plugin.add("draggable", "stack", { 2368 start: function() { 2369 2370 var min, 2371 o = $(this).data("ui-draggable").options, 2372 group = $.makeArray($(o.stack)).sort(function(a,b) { 2373 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); 2374 }); 2375 2376 if (!group.length) { return; } 2377 2378 min = parseInt(group[0].style.zIndex, 10) || 0; 2379 $(group).each(function(i) { 2380 this.style.zIndex = min + i; 2381 }); 2382 2383 this[0].style.zIndex = min + group.length; 2384 2385 } 2386}); 2387 2388$.ui.plugin.add("draggable", "zIndex", { 2389 start: function(event, ui) { 2390 var t = $(ui.helper), o = $(this).data("ui-draggable").options; 2391 if(t.css("zIndex")) { 2392 o._zIndex = t.css("zIndex"); 2393 } 2394 t.css("zIndex", o.zIndex); 2395 }, 2396 stop: function(event, ui) { 2397 var o = $(this).data("ui-draggable").options; 2398 if(o._zIndex) { 2399 $(ui.helper).css("zIndex", o._zIndex); 2400 } 2401 } 2402}); 2403 2404})(jQuery); 2405(function( $, undefined ) { 2406 2407function isOverAxis( x, reference, size ) { 2408 return ( x > reference ) && ( x < ( reference + size ) ); 2409} 2410 2411$.widget("ui.droppable", { 2412 version: "1.10.0", 2413 widgetEventPrefix: "drop", 2414 options: { 2415 accept: "*", 2416 activeClass: false, 2417 addClasses: true, 2418 greedy: false, 2419 hoverClass: false, 2420 scope: "default", 2421 tolerance: "intersect", 2422 2423 // callbacks 2424 activate: null, 2425 deactivate: null, 2426 drop: null, 2427 out: null, 2428 over: null 2429 }, 2430 _create: function() { 2431 2432 var o = this.options, 2433 accept = o.accept; 2434 2435 this.isover = false; 2436 this.isout = true; 2437 2438 this.accept = $.isFunction(accept) ? accept : function(d) { 2439 return d.is(accept); 2440 }; 2441 2442 //Store the droppable's proportions 2443 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight }; 2444 2445 // Add the reference and positions to the manager 2446 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; 2447 $.ui.ddmanager.droppables[o.scope].push(this); 2448 2449 (o.addClasses && this.element.addClass("ui-droppable")); 2450 2451 }, 2452 2453 _destroy: function() { 2454 var i = 0, 2455 drop = $.ui.ddmanager.droppables[this.options.scope]; 2456 2457 for ( ; i < drop.length; i++ ) { 2458 if ( drop[i] === this ) { 2459 drop.splice(i, 1); 2460 } 2461 } 2462 2463 this.element.removeClass("ui-droppable ui-droppable-disabled"); 2464 }, 2465 2466 _setOption: function(key, value) { 2467 2468 if(key === "accept") { 2469 this.accept = $.isFunction(value) ? value : function(d) { 2470 return d.is(value); 2471 }; 2472 } 2473 $.Widget.prototype._setOption.apply(this, arguments); 2474 }, 2475 2476 _activate: function(event) { 2477 var draggable = $.ui.ddmanager.current; 2478 if(this.options.activeClass) { 2479 this.element.addClass(this.options.activeClass); 2480 } 2481 if(draggable){ 2482 this._trigger("activate", event, this.ui(draggable)); 2483 } 2484 }, 2485 2486 _deactivate: function(event) { 2487 var draggable = $.ui.ddmanager.current; 2488 if(this.options.activeClass) { 2489 this.element.removeClass(this.options.activeClass); 2490 } 2491 if(draggable){ 2492 this._trigger("deactivate", event, this.ui(draggable)); 2493 } 2494 }, 2495 2496 _over: function(event) { 2497 2498 var draggable = $.ui.ddmanager.current; 2499 2500 // Bail if draggable and droppable are same element 2501 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { 2502 return; 2503 } 2504 2505 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 2506 if(this.options.hoverClass) { 2507 this.element.addClass(this.options.hoverClass); 2508 } 2509 this._trigger("over", event, this.ui(draggable)); 2510 } 2511 2512 }, 2513 2514 _out: function(event) { 2515 2516 var draggable = $.ui.ddmanager.current; 2517 2518 // Bail if draggable and droppable are same element 2519 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { 2520 return; 2521 } 2522 2523 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 2524 if(this.options.hoverClass) { 2525 this.element.removeClass(this.options.hoverClass); 2526 } 2527 this._trigger("out", event, this.ui(draggable)); 2528 } 2529 2530 }, 2531 2532 _drop: function(event,custom) { 2533 2534 var draggable = custom || $.ui.ddmanager.current, 2535 childrenIntersection = false; 2536 2537 // Bail if draggable and droppable are same element 2538 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { 2539 return false; 2540 } 2541 2542 this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() { 2543 var inst = $.data(this, "ui-droppable"); 2544 if( 2545 inst.options.greedy && 2546 !inst.options.disabled && 2547 inst.options.scope === draggable.options.scope && 2548 inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) && 2549 $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) 2550 ) { childrenIntersection = true; return false; } 2551 }); 2552 if(childrenIntersection) { 2553 return false; 2554 } 2555 2556 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 2557 if(this.options.activeClass) { 2558 this.element.removeClass(this.options.activeClass); 2559 } 2560 if(this.options.hoverClass) { 2561 this.element.removeClass(this.options.hoverClass); 2562 } 2563 this._trigger("drop", event, this.ui(draggable)); 2564 return this.element; 2565 } 2566 2567 return false; 2568 2569 }, 2570 2571 ui: function(c) { 2572 return { 2573 draggable: (c.currentItem || c.element), 2574 helper: c.helper, 2575 position: c.position, 2576 offset: c.positionAbs 2577 }; 2578 } 2579 2580}); 2581 2582$.ui.intersect = function(draggable, droppable, toleranceMode) { 2583 2584 if (!droppable.offset) { 2585 return false; 2586 } 2587 2588 var draggableLeft, draggableTop, 2589 x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, 2590 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height, 2591 l = droppable.offset.left, r = l + droppable.proportions.width, 2592 t = droppable.offset.top, b = t + droppable.proportions.height; 2593 2594 switch (toleranceMode) { 2595 case "fit": 2596 return (l <= x1 && x2 <= r && t <= y1 && y2 <= b); 2597 case "intersect": 2598 return (l < x1 + (draggable.helperProportions.width / 2) && // Right Half 2599 x2 - (draggable.helperProportions.width / 2) < r && // Left Half 2600 t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half 2601 y2 - (draggable.helperProportions.height / 2) < b ); // Top Half 2602 case "pointer": 2603 draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left); 2604 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top); 2605 return isOverAxis( draggableTop, t, droppable.proportions.height ) && isOverAxis( draggableLeft, l, droppable.proportions.width ); 2606 case "touch": 2607 return ( 2608 (y1 >= t && y1 <= b) || // Top edge touching 2609 (y2 >= t && y2 <= b) || // Bottom edge touching 2610 (y1 < t && y2 > b) // Surrounded vertically 2611 ) && ( 2612 (x1 >= l && x1 <= r) || // Left edge touching 2613 (x2 >= l && x2 <= r) || // Right edge touching 2614 (x1 < l && x2 > r) // Surrounded horizontally 2615 ); 2616 default: 2617 return false; 2618 } 2619 2620}; 2621 2622/* 2623 This manager tracks offsets of draggables and droppables 2624*/ 2625$.ui.ddmanager = { 2626 current: null, 2627 droppables: { "default": [] }, 2628 prepareOffsets: function(t, event) { 2629 2630 var i, j, 2631 m = $.ui.ddmanager.droppables[t.options.scope] || [], 2632 type = event ? event.type : null, // workaround for #2317 2633 list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack(); 2634 2635 droppablesLoop: for (i = 0; i < m.length; i++) { 2636 2637 //No disabled and non-accepted 2638 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) { 2639 continue; 2640 } 2641 2642 // Filter out elements in the current dragged item 2643 for (j=0; j < list.length; j++) { 2644 if(list[j] === m[i].element[0]) { 2645 m[i].proportions.height = 0; 2646 continue droppablesLoop; 2647 } 2648 } 2649 2650 m[i].visible = m[i].element.css("display") !== "none"; 2651 if(!m[i].visible) { 2652 continue; 2653 } 2654 2655 //Activate the droppable if used directly from draggables 2656 if(type === "mousedown") { 2657 m[i]._activate.call(m[i], event); 2658 } 2659 2660 m[i].offset = m[i].element.offset(); 2661 m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight }; 2662 2663 } 2664 2665 }, 2666 drop: function(draggable, event) { 2667 2668 var dropped = false; 2669 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { 2670 2671 if(!this.options) { 2672 return; 2673 } 2674 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) { 2675 dropped = this._drop.call(this, event) || dropped; 2676 } 2677 2678 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 2679 this.isout = true; 2680 this.isover = false; 2681 this._deactivate.call(this, event); 2682 } 2683 2684 }); 2685 return dropped; 2686 2687 }, 2688 dragStart: function( draggable, event ) { 2689 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) 2690 draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() { 2691 if( !draggable.options.refreshPositions ) { 2692 $.ui.ddmanager.prepareOffsets( draggable, event ); 2693 } 2694 }); 2695 }, 2696 drag: function(draggable, event) { 2697 2698 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. 2699 if(draggable.options.refreshPositions) { 2700 $.ui.ddmanager.prepareOffsets(draggable, event); 2701 } 2702 2703 //Run through all droppables and check their positions based on specific tolerance options 2704 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { 2705 2706 if(this.options.disabled || this.greedyChild || !this.visible) { 2707 return; 2708 } 2709 2710 var parentInstance, scope, parent, 2711 intersects = $.ui.intersect(draggable, this, this.options.tolerance), 2712 c = !intersects && this.isover ? "isout" : (intersects && !this.isover ? "isover" : null); 2713 if(!c) { 2714 return; 2715 } 2716 2717 if (this.options.greedy) { 2718 // find droppable parents with same scope 2719 scope = this.options.scope; 2720 parent = this.element.parents(":data(ui-droppable)").filter(function () { 2721 return $.data(this, "ui-droppable").options.scope === scope; 2722 }); 2723 2724 if (parent.length) { 2725 parentInstance = $.data(parent[0], "ui-droppable"); 2726 parentInstance.greedyChild = (c === "isover"); 2727 } 2728 } 2729 2730 // we just moved into a greedy child 2731 if (parentInstance && c === "isover") { 2732 parentInstance.isover = false; 2733 parentInstance.isout = true; 2734 parentInstance._out.call(parentInstance, event); 2735 } 2736 2737 this[c] = true; 2738 this[c === "isout" ? "isover" : "isout"] = false; 2739 this[c === "isover" ? "_over" : "_out"].call(this, event); 2740 2741 // we just moved out of a greedy child 2742 if (parentInstance && c === "isout") { 2743 parentInstance.isout = false; 2744 parentInstance.isover = true; 2745 parentInstance._over.call(parentInstance, event); 2746 } 2747 }); 2748 2749 }, 2750 dragStop: function( draggable, event ) { 2751 draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" ); 2752 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) 2753 if( !draggable.options.refreshPositions ) { 2754 $.ui.ddmanager.prepareOffsets( draggable, event ); 2755 } 2756 } 2757}; 2758 2759})(jQuery); 2760(function( $, undefined ) { 2761 2762function num(v) { 2763 return parseInt(v, 10) || 0; 2764} 2765 2766function isNumber(value) { 2767 return !isNaN(parseInt(value, 10)); 2768} 2769 2770$.widget("ui.resizable", $.ui.mouse, { 2771 version: "1.10.0", 2772 widgetEventPrefix: "resize", 2773 options: { 2774 alsoResize: false, 2775 animate: false, 2776 animateDuration: "slow", 2777 animateEasing: "swing", 2778 aspectRatio: false, 2779 autoHide: false, 2780 containment: false, 2781 ghost: false, 2782 grid: false, 2783 handles: "e,s,se", 2784 helper: false, 2785 maxHeight: null, 2786 maxWidth: null, 2787 minHeight: 10, 2788 minWidth: 10, 2789 // See #7960 2790 zIndex: 90, 2791 2792 // callbacks 2793 resize: null, 2794 start: null, 2795 stop: null 2796 }, 2797 _create: function() { 2798 2799 var n, i, handle, axis, hname, 2800 that = this, 2801 o = this.options; 2802 this.element.addClass("ui-resizable"); 2803 2804 $.extend(this, { 2805 _aspectRatio: !!(o.aspectRatio), 2806 aspectRatio: o.aspectRatio, 2807 originalElement: this.element, 2808 _proportionallyResizeElements: [], 2809 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null 2810 }); 2811 2812 //Wrap the element if it cannot hold child nodes 2813 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { 2814 2815 //Create a wrapper element and set the wrapper to the new current internal element 2816 this.element.wrap( 2817 $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({ 2818 position: this.element.css("position"), 2819 width: this.element.outerWidth(), 2820 height: this.element.outerHeight(), 2821 top: this.element.css("top"), 2822 left: this.element.css("left") 2823 }) 2824 ); 2825 2826 //Overwrite the original this.element 2827 this.element = this.element.parent().data( 2828 "ui-resizable", this.element.data("ui-resizable") 2829 ); 2830 2831 this.elementIsWrapper = true; 2832 2833 //Move margins to the wrapper 2834 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); 2835 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); 2836 2837 //Prevent Safari textarea resize 2838 this.originalResizeStyle = this.originalElement.css("resize"); 2839 this.originalElement.css("resize", "none"); 2840 2841 //Push the actual element to our proportionallyResize internal array 2842 this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" })); 2843 2844 // avoid IE jump (hard set the margin) 2845 this.originalElement.css({ margin: this.originalElement.css("margin") }); 2846 2847 // fix handlers offset 2848 this._proportionallyResize(); 2849 2850 } 2851 2852 this.handles = o.handles || (!$(".ui-resizable-handle", this.element).length ? "e,s,se" : { n: ".ui-resizable-n", e: ".ui-resizable-e", s: ".ui-resizable-s", w: ".ui-resizable-w", se: ".ui-resizable-se", sw: ".ui-resizable-sw", ne: ".ui-resizable-ne", nw: ".ui-resizable-nw" }); 2853 if(this.handles.constructor === String) { 2854 2855 if ( this.handles === "all") { 2856 this.handles = "n,e,s,w,se,sw,ne,nw"; 2857 } 2858 2859 n = this.handles.split(","); 2860 this.handles = {}; 2861 2862 for(i = 0; i < n.length; i++) { 2863 2864 handle = $.trim(n[i]); 2865 hname = "ui-resizable-"+handle; 2866 axis = $("<div class='ui-resizable-handle " + hname + "'></div>"); 2867 2868 // Apply zIndex to all handles - see #7960 2869 axis.css({ zIndex: o.zIndex }); 2870 2871 //TODO : What's going on here? 2872 if ("se" === handle) { 2873 axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se"); 2874 } 2875 2876 //Insert into internal handles object and append to element 2877 this.handles[handle] = ".ui-resizable-"+handle; 2878 this.element.append(axis); 2879 } 2880 2881 } 2882 2883 this._renderAxis = function(target) { 2884 2885 var i, axis, padPos, padWrapper; 2886 2887 target = target || this.element; 2888 2889 for(i in this.handles) { 2890 2891 if(this.handles[i].constructor === String) { 2892 this.handles[i] = $(this.handles[i], this.element).show(); 2893 } 2894 2895 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) 2896 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { 2897 2898 axis = $(this.handles[i], this.element); 2899 2900 //Checking the correct pad and border 2901 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); 2902 2903 //The padding type i have to apply... 2904 padPos = [ "padding", 2905 /ne|nw|n/.test(i) ? "Top" : 2906 /se|sw|s/.test(i) ? "Bottom" : 2907 /^e$/.test(i) ? "Right" : "Left" ].join(""); 2908 2909 target.css(padPos, padWrapper); 2910 2911 this._proportionallyResize(); 2912 2913 } 2914 2915 //TODO: What's that good for? There's not anything to be executed left 2916 if(!$(this.handles[i]).length) { 2917 continue; 2918 } 2919 } 2920 }; 2921 2922 //TODO: make renderAxis a prototype function 2923 this._renderAxis(this.element); 2924 2925 this._handles = $(".ui-resizable-handle", this.element) 2926 .disableSelection(); 2927 2928 //Matching axis name 2929 this._handles.mouseover(function() { 2930 if (!that.resizing) { 2931 if (this.className) { 2932 axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); 2933 } 2934 //Axis, default = se 2935 that.axis = axis && axis[1] ? axis[1] : "se"; 2936 } 2937 }); 2938 2939 //If we want to auto hide the elements 2940 if (o.autoHide) { 2941 this._handles.hide(); 2942 $(this.element) 2943 .addClass("ui-resizable-autohide") 2944 .mouseenter(function() { 2945 if (o.disabled) { 2946 return; 2947 } 2948 $(this).removeClass("ui-resizable-autohide"); 2949 that._handles.show(); 2950 }) 2951 .mouseleave(function(){ 2952 if (o.disabled) { 2953 return; 2954 } 2955 if (!that.resizing) { 2956 $(this).addClass("ui-resizable-autohide"); 2957 that._handles.hide(); 2958 } 2959 }); 2960 } 2961 2962 //Initialize the mouse interaction 2963 this._mouseInit(); 2964 2965 }, 2966 2967 _destroy: function() { 2968 2969 this._mouseDestroy(); 2970 2971 var wrapper, 2972 _destroy = function(exp) { 2973 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") 2974 .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove(); 2975 }; 2976 2977 //TODO: Unwrap at same DOM position 2978 if (this.elementIsWrapper) { 2979 _destroy(this.element); 2980 wrapper = this.element; 2981 this.originalElement.css({ 2982 position: wrapper.css("position"), 2983 width: wrapper.outerWidth(), 2984 height: wrapper.outerHeight(), 2985 top: wrapper.css("top"), 2986 left: wrapper.css("left") 2987 }).insertAfter( wrapper ); 2988 wrapper.remove(); 2989 } 2990 2991 this.originalElement.css("resize", this.originalResizeStyle); 2992 _destroy(this.originalElement); 2993 2994 return this; 2995 }, 2996 2997 _mouseCapture: function(event) { 2998 var i, handle, 2999 capture = false; 3000 3001 for (i in this.handles) { 3002 handle = $(this.handles[i])[0]; 3003 if (handle === event.target || $.contains(handle, event.target)) { 3004 capture = true; 3005 } 3006 } 3007 3008 return !this.options.disabled && capture; 3009 }, 3010 3011 _mouseStart: function(event) { 3012 3013 var curleft, curtop, cursor, 3014 o = this.options, 3015 iniPos = this.element.position(), 3016 el = this.element; 3017 3018 this.resizing = true; 3019 3020 // bugfix for http://dev.jquery.com/ticket/1749 3021 if ( (/absolute/).test( el.css("position") ) ) { 3022 el.css({ position: "absolute", top: el.css("top"), left: el.css("left") }); 3023 } else if (el.is(".ui-draggable")) { 3024 el.css({ position: "absolute", top: iniPos.top, left: iniPos.left }); 3025 } 3026 3027 this._renderProxy(); 3028 3029 curleft = num(this.helper.css("left")); 3030 curtop = num(this.helper.css("top")); 3031 3032 if (o.containment) { 3033 curleft += $(o.containment).scrollLeft() || 0; 3034 curtop += $(o.containment).scrollTop() || 0; 3035 } 3036 3037 //Store needed variables 3038 this.offset = this.helper.offset(); 3039 this.position = { left: curleft, top: curtop }; 3040 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; 3041 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; 3042 this.originalPosition = { left: curleft, top: curtop }; 3043 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; 3044 this.originalMousePosition = { left: event.pageX, top: event.pageY }; 3045 3046 //Aspect Ratio 3047 this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); 3048 3049 cursor = $(".ui-resizable-" + this.axis).css("cursor"); 3050 $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor); 3051 3052 el.addClass("ui-resizable-resizing"); 3053 this._propagate("start", event); 3054 return true; 3055 }, 3056 3057 _mouseDrag: function(event) { 3058 3059 //Increase performance, avoid regex 3060 var data, 3061 el = this.helper, props = {}, 3062 smp = this.originalMousePosition, 3063 a = this.axis, 3064 prevTop = this.position.top, 3065 prevLeft = this.position.left, 3066 prevWidth = this.size.width, 3067 prevHeight = this.size.height, 3068 dx = (event.pageX-smp.left)||0, 3069 dy = (event.pageY-smp.top)||0, 3070 trigger = this._change[a]; 3071 3072 if (!trigger) { 3073 return false; 3074 } 3075 3076 // Calculate the attrs that will be change 3077 data = trigger.apply(this, [event, dx, dy]); 3078 3079 // Put this in the mouseDrag handler since the user can start pressing shift while resizing 3080 this._updateVirtualBoundaries(event.shiftKey); 3081 if (this._aspectRatio || event.shiftKey) { 3082 data = this._updateRatio(data, event); 3083 } 3084 3085 data = this._respectSize(data, event); 3086 3087 this._updateCache(data); 3088 3089 // plugins callbacks need to be called first 3090 this._propagate("resize", event); 3091 3092 if (this.position.top !== prevTop) { 3093 props.top = this.position.top + "px"; 3094 } 3095 if (this.position.left !== prevLeft) { 3096 props.left = this.position.left + "px"; 3097 } 3098 if (this.size.width !== prevWidth) { 3099 props.width = this.size.width + "px"; 3100 } 3101 if (this.size.height !== prevHeight) { 3102 props.height = this.size.height + "px"; 3103 } 3104 el.css(props); 3105 3106 if (!this._helper && this._proportionallyResizeElements.length) { 3107 this._proportionallyResize(); 3108 } 3109 3110 // Call the user callback if the element was resized 3111 if ( ! $.isEmptyObject(props) ) { 3112 this._trigger("resize", event, this.ui()); 3113 } 3114 3115 return false; 3116 }, 3117 3118 _mouseStop: function(event) { 3119 3120 this.resizing = false; 3121 var pr, ista, soffseth, soffsetw, s, left, top, 3122 o = this.options, that = this; 3123 3124 if(this._helper) { 3125 3126 pr = this._proportionallyResizeElements; 3127 ista = pr.length && (/textarea/i).test(pr[0].nodeName); 3128 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height; 3129 soffsetw = ista ? 0 : that.sizeDiff.width; 3130 3131 s = { width: (that.helper.width() - soffsetw), height: (that.helper.height() - soffseth) }; 3132 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null; 3133 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null; 3134 3135 if (!o.animate) { 3136 this.element.css($.extend(s, { top: top, left: left })); 3137 } 3138 3139 that.helper.height(that.size.height); 3140 that.helper.width(that.size.width); 3141 3142 if (this._helper && !o.animate) { 3143 this._proportionallyResize(); 3144 } 3145 } 3146 3147 $("body").css("cursor", "auto"); 3148 3149 this.element.removeClass("ui-resizable-resizing"); 3150 3151 this._propagate("stop", event); 3152 3153 if (this._helper) { 3154 this.helper.remove(); 3155 } 3156 3157 return false; 3158 3159 }, 3160 3161 _updateVirtualBoundaries: function(forceAspectRatio) { 3162 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b, 3163 o = this.options; 3164 3165 b = { 3166 minWidth: isNumber(o.minWidth) ? o.minWidth : 0, 3167 maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity, 3168 minHeight: isNumber(o.minHeight) ? o.minHeight : 0, 3169 maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity 3170 }; 3171 3172 if(this._aspectRatio || forceAspectRatio) { 3173 // We want to create an enclosing box whose aspect ration is the requested one 3174 // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension 3175 pMinWidth = b.minHeight * this.aspectRatio; 3176 pMinHeight = b.minWidth / this.aspectRatio; 3177 pMaxWidth = b.maxHeight * this.aspectRatio; 3178 pMaxHeight = b.maxWidth / this.aspectRatio; 3179 3180 if(pMinWidth > b.minWidth) { 3181 b.minWidth = pMinWidth; 3182 } 3183 if(pMinHeight > b.minHeight) { 3184 b.minHeight = pMinHeight; 3185 } 3186 if(pMaxWidth < b.maxWidth) { 3187 b.maxWidth = pMaxWidth; 3188 } 3189 if(pMaxHeight < b.maxHeight) { 3190 b.maxHeight = pMaxHeight; 3191 } 3192 } 3193 this._vBoundaries = b; 3194 }, 3195 3196 _updateCache: function(data) { 3197 this.offset = this.helper.offset(); 3198 if (isNumber(data.left)) { 3199 this.position.left = data.left; 3200 } 3201 if (isNumber(data.top)) { 3202 this.position.top = data.top; 3203 } 3204 if (isNumber(data.height)) { 3205 this.size.height = data.height; 3206 } 3207 if (isNumber(data.width)) { 3208 this.size.width = data.width; 3209 } 3210 }, 3211 3212 _updateRatio: function( data ) { 3213 3214 var cpos = this.position, 3215 csize = this.size, 3216 a = this.axis; 3217 3218 if (isNumber(data.height)) { 3219 data.width = (data.height * this.aspectRatio); 3220 } else if (isNumber(data.width)) { 3221 data.height = (data.width / this.aspectRatio); 3222 } 3223 3224 if (a === "sw") { 3225 data.left = cpos.left + (csize.width - data.width); 3226 data.top = null; 3227 } 3228 if (a === "nw") { 3229 data.top = cpos.top + (csize.height - data.height); 3230 data.left = cpos.left + (csize.width - data.width); 3231 } 3232 3233 return data; 3234 }, 3235 3236 _respectSize: function( data ) { 3237 3238 var o = this._vBoundaries, 3239 a = this.axis, 3240 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), 3241 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height), 3242 dw = this.originalPosition.left + this.originalSize.width, 3243 dh = this.position.top + this.size.height, 3244 cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); 3245 if (isminw) { 3246 data.width = o.minWidth; 3247 } 3248 if (isminh) { 3249 data.height = o.minHeight; 3250 } 3251 if (ismaxw) { 3252 data.width = o.maxWidth; 3253 } 3254 if (ismaxh) { 3255 data.height = o.maxHeight; 3256 } 3257 3258 if (isminw && cw) { 3259 data.left = dw - o.minWidth; 3260 } 3261 if (ismaxw && cw) { 3262 data.left = dw - o.maxWidth; 3263 } 3264 if (isminh && ch) { 3265 data.top = dh - o.minHeight; 3266 } 3267 if (ismaxh && ch) { 3268 data.top = dh - o.maxHeight; 3269 } 3270 3271 // fixing jump error on top/left - bug #2330 3272 if (!data.width && !data.height && !data.left && data.top) { 3273 data.top = null; 3274 } else if (!data.width && !data.height && !data.top && data.left) { 3275 data.left = null; 3276 } 3277 3278 return data; 3279 }, 3280 3281 _proportionallyResize: function() { 3282 3283 if (!this._proportionallyResizeElements.length) { 3284 return; 3285 } 3286 3287 var i, j, borders, paddings, prel, 3288 element = this.helper || this.element; 3289 3290 for ( i=0; i < this._proportionallyResizeElements.length; i++) { 3291 3292 prel = this._proportionallyResizeElements[i]; 3293 3294 if (!this.borderDif) { 3295 this.borderDif = []; 3296 borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")]; 3297 paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")]; 3298 3299 for ( j = 0; j < borders.length; j++ ) { 3300 this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 ); 3301 } 3302 } 3303 3304 prel.css({ 3305 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, 3306 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 3307 }); 3308 3309 } 3310 3311 }, 3312 3313 _renderProxy: function() { 3314 3315 var el = this.element, o = this.options; 3316 this.elementOffset = el.offset(); 3317 3318 if(this._helper) { 3319 3320 this.helper = this.helper || $("<div style='overflow:hidden;'></div>"); 3321 3322 this.helper.addClass(this._helper).css({ 3323 width: this.element.outerWidth() - 1, 3324 height: this.element.outerHeight() - 1, 3325 position: "absolute", 3326 left: this.elementOffset.left +"px", 3327 top: this.elementOffset.top +"px", 3328 zIndex: ++o.zIndex //TODO: Don't modify option 3329 }); 3330 3331 this.helper 3332 .appendTo("body") 3333 .disableSelection(); 3334 3335 } else { 3336 this.helper = this.element; 3337 } 3338 3339 }, 3340 3341 _change: { 3342 e: function(event, dx) { 3343 return { width: this.originalSize.width + dx }; 3344 }, 3345 w: function(event, dx) { 3346 var cs = this.originalSize, sp = this.originalPosition; 3347 return { left: sp.left + dx, width: cs.width - dx }; 3348 }, 3349 n: function(event, dx, dy) { 3350 var cs = this.originalSize, sp = this.originalPosition; 3351 return { top: sp.top + dy, height: cs.height - dy }; 3352 }, 3353 s: function(event, dx, dy) { 3354 return { height: this.originalSize.height + dy }; 3355 }, 3356 se: function(event, dx, dy) { 3357 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); 3358 }, 3359 sw: function(event, dx, dy) { 3360 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); 3361 }, 3362 ne: function(event, dx, dy) { 3363 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); 3364 }, 3365 nw: function(event, dx, dy) { 3366 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); 3367 } 3368 }, 3369 3370 _propagate: function(n, event) { 3371 $.ui.plugin.call(this, n, [event, this.ui()]); 3372 (n !== "resize" && this._trigger(n, event, this.ui())); 3373 }, 3374 3375 plugins: {}, 3376 3377 ui: function() { 3378 return { 3379 originalElement: this.originalElement, 3380 element: this.element, 3381 helper: this.helper, 3382 position: this.position, 3383 size: this.size, 3384 originalSize: this.originalSize, 3385 originalPosition: this.originalPosition 3386 }; 3387 } 3388 3389}); 3390 3391/* 3392 * Resizable Extensions 3393 */ 3394 3395$.ui.plugin.add("resizable", "animate", { 3396 3397 stop: function( event ) { 3398 var that = $(this).data("ui-resizable"), 3399 o = that.options, 3400 pr = that._proportionallyResizeElements, 3401 ista = pr.length && (/textarea/i).test(pr[0].nodeName), 3402 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height, 3403 soffsetw = ista ? 0 : that.sizeDiff.width, 3404 style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) }, 3405 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null, 3406 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null; 3407 3408 that.element.animate( 3409 $.extend(style, top && left ? { top: top, left: left } : {}), { 3410 duration: o.animateDuration, 3411 easing: o.animateEasing, 3412 step: function() { 3413 3414 var data = { 3415 width: parseInt(that.element.css("width"), 10), 3416 height: parseInt(that.element.css("height"), 10), 3417 top: parseInt(that.element.css("top"), 10), 3418 left: parseInt(that.element.css("left"), 10) 3419 }; 3420 3421 if (pr && pr.length) { 3422 $(pr[0]).css({ width: data.width, height: data.height }); 3423 } 3424 3425 // propagating resize, and updating values for each animation step 3426 that._updateCache(data); 3427 that._propagate("resize", event); 3428 3429 } 3430 } 3431 ); 3432 } 3433 3434}); 3435 3436$.ui.plugin.add("resizable", "containment", { 3437 3438 start: function() { 3439 var element, p, co, ch, cw, width, height, 3440 that = $(this).data("ui-resizable"), 3441 o = that.options, 3442 el = that.element, 3443 oc = o.containment, 3444 ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; 3445 3446 if (!ce) { 3447 return; 3448 } 3449 3450 that.containerElement = $(ce); 3451 3452 if (/document/.test(oc) || oc === document) { 3453 that.containerOffset = { left: 0, top: 0 }; 3454 that.containerPosition = { left: 0, top: 0 }; 3455 3456 that.parentData = {
3457 element: $(document), left: 0, top: 0, 3458 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight 3459 }; 3460 } 3461 3462 // i'm a node, so compute top, left, right, bottom 3463 else { 3464 element = $(ce); 3465 p = []; 3466 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); }); 3467 3468 that.containerOffset = element.offset(); 3469 that.containerPosition = element.position(); 3470 that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; 3471 3472 co = that.containerOffset; 3473 ch = that.containerSize.height; 3474 cw = that.containerSize.width; 3475 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ); 3476 height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); 3477 3478 that.parentData = { 3479 element: ce, left: co.left, top: co.top, width: width, height: height 3480 }; 3481 } 3482 }, 3483 3484 resize: function( event ) { 3485 var woset, hoset, isParent, isOffsetRelative, 3486 that = $(this).data("ui-resizable"), 3487 o = that.options, 3488 co = that.containerOffset, cp = that.position, 3489 pRatio = that._aspectRatio || event.shiftKey, 3490 cop = { top:0, left:0 }, ce = that.containerElement; 3491 3492 if (ce[0] !== document && (/static/).test(ce.css("position"))) { 3493 cop = co; 3494 } 3495 3496 if (cp.left < (that._helper ? co.left : 0)) { 3497 that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left)); 3498 if (pRatio) { 3499 that.size.height = that.size.width / that.aspectRatio; 3500 } 3501 that.position.left = o.helper ? co.left : 0; 3502 } 3503 3504 if (cp.top < (that._helper ? co.top : 0)) { 3505 that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top); 3506 if (pRatio) { 3507 that.size.width = that.size.height * that.aspectRatio; 3508 } 3509 that.position.top = that._helper ? co.top : 0; 3510 } 3511 3512 that.offset.left = that.parentData.left+that.position.left; 3513 that.offset.top = that.parentData.top+that.position.top; 3514 3515 woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width ); 3516 hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height ); 3517 3518 isParent = that.containerElement.get(0) === that.element.parent().get(0); 3519 isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position")); 3520 3521 if(isParent && isOffsetRelative) { 3522 woset -= that.parentData.left; 3523 } 3524 3525 if (woset + that.size.width >= that.parentData.width) { 3526 that.size.width = that.parentData.width - woset; 3527 if (pRatio) { 3528 that.size.height = that.size.width / that.aspectRatio; 3529 } 3530 } 3531 3532 if (hoset + that.size.height >= that.parentData.height) { 3533 that.size.height = that.parentData.height - hoset; 3534 if (pRatio) { 3535 that.size.width = that.size.height * that.aspectRatio; 3536 } 3537 } 3538 }, 3539 3540 stop: function(){ 3541 var that = $(this).data("ui-resizable"), 3542 o = that.options, 3543 co = that.containerOffset, 3544 cop = that.containerPosition, 3545 ce = that.containerElement, 3546 helper = $(that.helper), 3547 ho = helper.offset(), 3548 w = helper.outerWidth() - that.sizeDiff.width, 3549 h = helper.outerHeight() - that.sizeDiff.height; 3550 3551 if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) { 3552 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); 3553 } 3554 3555 if (that._helper && !o.animate && (/static/).test(ce.css("position"))) { 3556 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); 3557 } 3558 3559 } 3560}); 3561 3562$.ui.plugin.add("resizable", "alsoResize", { 3563 3564 start: function () { 3565 var that = $(this).data("ui-resizable"), 3566 o = that.options, 3567 _store = function (exp) { 3568 $(exp).each(function() { 3569 var el = $(this); 3570 el.data("ui-resizable-alsoresize", { 3571 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), 3572 left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10) 3573 }); 3574 }); 3575 }; 3576 3577 if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) { 3578 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); } 3579 else { $.each(o.alsoResize, function (exp) { _store(exp); }); } 3580 }else{ 3581 _store(o.alsoResize); 3582 } 3583 }, 3584 3585 resize: function (event, ui) { 3586 var that = $(this).data("ui-resizable"), 3587 o = that.options, 3588 os = that.originalSize, 3589 op = that.originalPosition, 3590 delta = { 3591 height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0, 3592 top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0 3593 }, 3594 3595 _alsoResize = function (exp, c) { 3596 $(exp).each(function() { 3597 var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {}, 3598 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"]; 3599
vendor: 36,304 bytes, lines 3600-4848
3600 $.each(css, function (i, prop) { 3601 var sum = (start[prop]||0) + (delta[prop]||0); 3602 if (sum && sum >= 0) { 3603 style[prop] = sum || null; 3604 } 3605 }); 3606 3607 el.css(style); 3608 }); 3609 }; 3610 3611 if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) { 3612 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); }); 3613 }else{ 3614 _alsoResize(o.alsoResize); 3615 } 3616 }, 3617 3618 stop: function () { 3619 $(this).removeData("resizable-alsoresize"); 3620 } 3621}); 3622 3623$.ui.plugin.add("resizable", "ghost", { 3624 3625 start: function() { 3626 3627 var that = $(this).data("ui-resizable"), o = that.options, cs = that.size; 3628 3629 that.ghost = that.originalElement.clone(); 3630 that.ghost 3631 .css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) 3632 .addClass("ui-resizable-ghost") 3633 .addClass(typeof o.ghost === "string" ? o.ghost : ""); 3634 3635 that.ghost.appendTo(that.helper); 3636 3637 }, 3638 3639 resize: function(){ 3640 var that = $(this).data("ui-resizable"); 3641 if (that.ghost) { 3642 that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width }); 3643 } 3644 }, 3645 3646 stop: function() { 3647 var that = $(this).data("ui-resizable"); 3648 if (that.ghost && that.helper) { 3649 that.helper.get(0).removeChild(that.ghost.get(0)); 3650 } 3651 } 3652 3653}); 3654 3655$.ui.plugin.add("resizable", "grid", { 3656 3657 resize: function() { 3658 var that = $(this).data("ui-resizable"), 3659 o = that.options, 3660 cs = that.size, 3661 os = that.originalSize, 3662 op = that.originalPosition, 3663 a = that.axis, 3664 grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid, 3665 gridX = (grid[0]||1), 3666 gridY = (grid[1]||1), 3667 ox = Math.round((cs.width - os.width) / gridX) * gridX, 3668 oy = Math.round((cs.height - os.height) / gridY) * gridY, 3669 newWidth = os.width + ox, 3670 newHeight = os.height + oy, 3671 isMaxWidth = o.maxWidth && (o.maxWidth < newWidth), 3672 isMaxHeight = o.maxHeight && (o.maxHeight < newHeight), 3673 isMinWidth = o.minWidth && (o.minWidth > newWidth), 3674 isMinHeight = o.minHeight && (o.minHeight > newHeight); 3675 3676 o.grid = grid; 3677 3678 if (isMinWidth) { 3679 newWidth = newWidth + gridX; 3680 } 3681 if (isMinHeight) { 3682 newHeight = newHeight + gridY; 3683 } 3684 if (isMaxWidth) { 3685 newWidth = newWidth - gridX; 3686 } 3687 if (isMaxHeight) { 3688 newHeight = newHeight - gridY; 3689 } 3690 3691 if (/^(se|s|e)$/.test(a)) { 3692 that.size.width = newWidth; 3693 that.size.height = newHeight; 3694 } else if (/^(ne)$/.test(a)) { 3695 that.size.width = newWidth; 3696 that.size.height = newHeight; 3697 that.position.top = op.top - oy; 3698 } else if (/^(sw)$/.test(a)) { 3699 that.size.width = newWidth; 3700 that.size.height = newHeight; 3701 that.position.left = op.left - ox; 3702 } else { 3703 that.size.width = newWidth; 3704 that.size.height = newHeight; 3705 that.position.top = op.top - oy; 3706 that.position.left = op.left - ox; 3707 } 3708 } 3709 3710}); 3711 3712})(jQuery); 3713(function( $, undefined ) { 3714 3715$.widget("ui.selectable", $.ui.mouse, { 3716 version: "1.10.0", 3717 options: { 3718 appendTo: "body", 3719 autoRefresh: true, 3720 distance: 0, 3721 filter: "*", 3722 tolerance: "touch", 3723 3724 // callbacks 3725 selected: null, 3726 selecting: null, 3727 start: null, 3728 stop: null, 3729 unselected: null, 3730 unselecting: null 3731 }, 3732 _create: function() { 3733 var selectees, 3734 that = this; 3735 3736 this.element.addClass("ui-selectable"); 3737 3738 this.dragged = false; 3739 3740 // cache selectee children based on filter 3741 this.refresh = function() { 3742 selectees = $(that.options.filter, that.element[0]); 3743 selectees.addClass("ui-selectee"); 3744 selectees.each(function() { 3745 var $this = $(this), 3746 pos = $this.offset(); 3747 $.data(this, "selectable-item", { 3748 element: this, 3749 $element: $this, 3750 left: pos.left, 3751 top: pos.top, 3752 right: pos.left + $this.outerWidth(), 3753 bottom: pos.top + $this.outerHeight(), 3754 startselected: false, 3755 selected: $this.hasClass("ui-selected"), 3756 selecting: $this.hasClass("ui-selecting"), 3757 unselecting: $this.hasClass("ui-unselecting") 3758 }); 3759 }); 3760 }; 3761 this.refresh(); 3762 3763 this.selectees = selectees.addClass("ui-selectee"); 3764 3765 this._mouseInit(); 3766 3767 this.helper = $("<div class='ui-selectable-helper'></div>"); 3768 }, 3769 3770 _destroy: function() { 3771 this.selectees 3772 .removeClass("ui-selectee") 3773 .removeData("selectable-item"); 3774 this.element 3775 .removeClass("ui-selectable ui-selectable-disabled"); 3776 this._mouseDestroy(); 3777 }, 3778 3779 _mouseStart: function(event) { 3780 var that = this, 3781 options = this.options; 3782 3783 this.opos = [event.pageX, event.pageY]; 3784 3785 if (this.options.disabled) { 3786 return; 3787 } 3788 3789 this.selectees = $(options.filter, this.element[0]); 3790 3791 this._trigger("start", event); 3792 3793 $(options.appendTo).append(this.helper); 3794 // position helper (lasso) 3795 this.helper.css({ 3796 "left": event.pageX, 3797 "top": event.pageY, 3798 "width": 0, 3799 "height": 0 3800 }); 3801 3802 if (options.autoRefresh) { 3803 this.refresh(); 3804 } 3805 3806 this.selectees.filter(".ui-selected").each(function() { 3807 var selectee = $.data(this, "selectable-item"); 3808 selectee.startselected = true; 3809 if (!event.metaKey && !event.ctrlKey) { 3810 selectee.$element.removeClass("ui-selected"); 3811 selectee.selected = false; 3812 selectee.$element.addClass("ui-unselecting"); 3813 selectee.unselecting = true; 3814 // selectable UNSELECTING callback 3815 that._trigger("unselecting", event, { 3816 unselecting: selectee.element 3817 }); 3818 } 3819 }); 3820 3821 $(event.target).parents().addBack().each(function() { 3822 var doSelect, 3823 selectee = $.data(this, "selectable-item"); 3824 if (selectee) { 3825 doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected"); 3826 selectee.$element 3827 .removeClass(doSelect ? "ui-unselecting" : "ui-selected") 3828 .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); 3829 selectee.unselecting = !doSelect; 3830 selectee.selecting = doSelect; 3831 selectee.selected = doSelect; 3832 // selectable (UN)SELECTING callback 3833 if (doSelect) { 3834 that._trigger("selecting", event, { 3835 selecting: selectee.element 3836 }); 3837 } else { 3838 that._trigger("unselecting", event, { 3839 unselecting: selectee.element 3840 }); 3841 } 3842 return false; 3843 } 3844 }); 3845 3846 }, 3847 3848 _mouseDrag: function(event) { 3849 3850 this.dragged = true; 3851 3852 if (this.options.disabled) { 3853 return; 3854 } 3855 3856 var tmp, 3857 that = this, 3858 options = this.options, 3859 x1 = this.opos[0], 3860 y1 = this.opos[1], 3861 x2 = event.pageX, 3862 y2 = event.pageY; 3863 3864 if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; } 3865 if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; } 3866 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); 3867 3868 this.selectees.each(function() { 3869 var selectee = $.data(this, "selectable-item"), 3870 hit = false; 3871 3872 //prevent helper from being selected if appendTo: selectable 3873 if (!selectee || selectee.element === that.element[0]) { 3874 return; 3875 } 3876 3877 if (options.tolerance === "touch") { 3878 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); 3879 } else if (options.tolerance === "fit") { 3880 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); 3881 } 3882 3883 if (hit) { 3884 // SELECT 3885 if (selectee.selected) { 3886 selectee.$element.removeClass("ui-selected"); 3887 selectee.selected = false; 3888 } 3889 if (selectee.unselecting) { 3890 selectee.$element.removeClass("ui-unselecting"); 3891 selectee.unselecting = false; 3892 } 3893 if (!selectee.selecting) { 3894 selectee.$element.addClass("ui-selecting"); 3895 selectee.selecting = true; 3896 // selectable SELECTING callback 3897 that._trigger("selecting", event, { 3898 selecting: selectee.element 3899 }); 3900 } 3901 } else { 3902 // UNSELECT 3903 if (selectee.selecting) { 3904 if ((event.metaKey || event.ctrlKey) && selectee.startselected) { 3905 selectee.$element.removeClass("ui-selecting"); 3906 selectee.selecting = false; 3907 selectee.$element.addClass("ui-selected"); 3908 selectee.selected = true; 3909 } else { 3910 selectee.$element.removeClass("ui-selecting"); 3911 selectee.selecting = false; 3912 if (selectee.startselected) { 3913 selectee.$element.addClass("ui-unselecting"); 3914 selectee.unselecting = true; 3915 } 3916 // selectable UNSELECTING callback 3917 that._trigger("unselecting", event, { 3918 unselecting: selectee.element 3919 }); 3920 } 3921 } 3922 if (selectee.selected) { 3923 if (!event.metaKey && !event.ctrlKey && !selectee.startselected) { 3924 selectee.$element.removeClass("ui-selected"); 3925 selectee.selected = false; 3926 3927 selectee.$element.addClass("ui-unselecting"); 3928 selectee.unselecting = true; 3929 // selectable UNSELECTING callback 3930 that._trigger("unselecting", event, { 3931 unselecting: selectee.element 3932 }); 3933 } 3934 } 3935 } 3936 }); 3937 3938 return false; 3939 }, 3940 3941 _mouseStop: function(event) { 3942 var that = this; 3943 3944 this.dragged = false; 3945 3946 $(".ui-unselecting", this.element[0]).each(function() { 3947 var selectee = $.data(this, "selectable-item"); 3948 selectee.$element.removeClass("ui-unselecting"); 3949 selectee.unselecting = false; 3950 selectee.startselected = false; 3951 that._trigger("unselected", event, { 3952 unselected: selectee.element 3953 }); 3954 }); 3955 $(".ui-selecting", this.element[0]).each(function() { 3956 var selectee = $.data(this, "selectable-item"); 3957 selectee.$element.removeClass("ui-selecting").addClass("ui-selected"); 3958 selectee.selecting = false; 3959 selectee.selected = true; 3960 selectee.startselected = true; 3961 that._trigger("selected", event, { 3962 selected: selectee.element 3963 }); 3964 }); 3965 this._trigger("stop", event); 3966 3967 this.helper.remove(); 3968 3969 return false; 3970 } 3971 3972}); 3973 3974})(jQuery); 3975(function( $, undefined ) { 3976 3977/*jshint loopfunc: true */ 3978 3979function isOverAxis( x, reference, size ) { 3980 return ( x > reference ) && ( x < ( reference + size ) ); 3981} 3982 3983$.widget("ui.sortable", $.ui.mouse, { 3984 version: "1.10.0", 3985 widgetEventPrefix: "sort", 3986 ready: false, 3987 options: { 3988 appendTo: "parent", 3989 axis: false, 3990 connectWith: false, 3991 containment: false, 3992 cursor: "auto", 3993 cursorAt: false, 3994 dropOnEmpty: true, 3995 forcePlaceholderSize: false, 3996 forceHelperSize: false, 3997 grid: false, 3998 handle: false, 3999 helper: "original", 4000 items: "> *", 4001 opacity: false, 4002 placeholder: false, 4003 revert: false, 4004 scroll: true, 4005 scrollSensitivity: 20, 4006 scrollSpeed: 20, 4007 scope: "default", 4008 tolerance: "intersect", 4009 zIndex: 1000, 4010 4011 // callbacks 4012 activate: null, 4013 beforeStop: null, 4014 change: null, 4015 deactivate: null, 4016 out: null, 4017 over: null, 4018 receive: null, 4019 remove: null, 4020 sort: null, 4021 start: null, 4022 stop: null, 4023 update: null 4024 }, 4025 _create: function() { 4026 4027 var o = this.options; 4028 this.containerCache = {}; 4029 this.element.addClass("ui-sortable"); 4030 4031 //Get the items 4032 this.refresh(); 4033 4034 //Let's determine if the items are being displayed horizontally 4035 this.floating = this.items.length ? o.axis === "x" || (/left|right/).test(this.items[0].item.css("float")) || (/inline|table-cell/).test(this.items[0].item.css("display")) : false; 4036 4037 //Let's determine the parent's offset 4038 this.offset = this.element.offset(); 4039 4040 //Initialize mouse events for interaction 4041 this._mouseInit(); 4042 4043 //We're ready to go 4044 this.ready = true; 4045 4046 }, 4047 4048 _destroy: function() { 4049 this.element 4050 .removeClass("ui-sortable ui-sortable-disabled"); 4051 this._mouseDestroy(); 4052 4053 for ( var i = this.items.length - 1; i >= 0; i-- ) { 4054 this.items[i].item.removeData(this.widgetName + "-item"); 4055 } 4056 4057 return this; 4058 }, 4059 4060 _setOption: function(key, value){ 4061 if ( key === "disabled" ) { 4062 this.options[ key ] = value; 4063 4064 this.widget().toggleClass( "ui-sortable-disabled", !!value ); 4065 } else { 4066 // Don't call widget base _setOption for disable as it adds ui-state-disabled class 4067 $.Widget.prototype._setOption.apply(this, arguments); 4068 } 4069 }, 4070 4071 _mouseCapture: function(event, overrideHandle) { 4072 var currentItem = null, 4073 validHandle = false, 4074 that = this; 4075 4076 if (this.reverting) { 4077 return false; 4078 } 4079 4080 if(this.options.disabled || this.options.type === "static") { 4081 return false; 4082 } 4083 4084 //We have to refresh the items data once first 4085 this._refreshItems(event); 4086 4087 //Find out if the clicked node (or one of its parents) is a actual item in this.items 4088 $(event.target).parents().each(function() { 4089 if($.data(this, that.widgetName + "-item") === that) { 4090 currentItem = $(this); 4091 return false; 4092 } 4093 }); 4094 if($.data(event.target, that.widgetName + "-item") === that) { 4095 currentItem = $(event.target); 4096 } 4097 4098 if(!currentItem) { 4099 return false; 4100 } 4101 if(this.options.handle && !overrideHandle) { 4102 $(this.options.handle, currentItem).find("*").addBack().each(function() { 4103 if(this === event.target) { 4104 validHandle = true; 4105 } 4106 }); 4107 if(!validHandle) { 4108 return false; 4109 } 4110 } 4111 4112 this.currentItem = currentItem; 4113 this._removeCurrentsFromItems(); 4114 return true; 4115 4116 }, 4117 4118 _mouseStart: function(event, overrideHandle, noActivation) { 4119 4120 var i, 4121 o = this.options; 4122 4123 this.currentContainer = this; 4124 4125 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture 4126 this.refreshPositions(); 4127 4128 //Create and append the visible helper 4129 this.helper = this._createHelper(event); 4130 4131 //Cache the helper size 4132 this._cacheHelperProportions(); 4133 4134 /* 4135 * - Position generation - 4136 * This block generates everything position related - it's the core of draggables. 4137 */ 4138 4139 //Cache the margins of the original element 4140 this._cacheMargins(); 4141 4142 //Get the next scrolling parent 4143 this.scrollParent = this.helper.scrollParent(); 4144 4145 //The element's absolute position on the page minus margins 4146 this.offset = this.currentItem.offset(); 4147 this.offset = { 4148 top: this.offset.top - this.margins.top, 4149 left: this.offset.left - this.margins.left 4150 }; 4151 4152 $.extend(this.offset, { 4153 click: { //Where the click happened, relative to the element 4154 left: event.pageX - this.offset.left, 4155 top: event.pageY - this.offset.top 4156 }, 4157 parent: this._getParentOffset(), 4158 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper 4159 }); 4160 4161 // Only after we got the offset, we can change the helper's position to absolute 4162 // TODO: Still need to figure out a way to make relative sorting possible 4163 this.helper.css("position", "absolute"); 4164 this.cssPosition = this.helper.css("position"); 4165 4166 //Generate the original position 4167 this.originalPosition = this._generatePosition(event); 4168 this.originalPageX = event.pageX; 4169 this.originalPageY = event.pageY; 4170 4171 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 4172 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); 4173 4174 //Cache the former DOM position 4175 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; 4176 4177 //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 4178 if(this.helper[0] !== this.currentItem[0]) { 4179 this.currentItem.hide(); 4180 } 4181 4182 //Create the placeholder 4183 this._createPlaceholder(); 4184 4185 //Set a containment if given in the options 4186 if(o.containment) { 4187 this._setContainment(); 4188 } 4189 4190 if(o.cursor) { // cursor option 4191 if ($("body").css("cursor")) { 4192 this._storedCursor = $("body").css("cursor"); 4193 } 4194 $("body").css("cursor", o.cursor); 4195 } 4196 4197 if(o.opacity) { // opacity option 4198 if (this.helper.css("opacity")) { 4199 this._storedOpacity = this.helper.css("opacity"); 4200 } 4201 this.helper.css("opacity", o.opacity); 4202 } 4203 4204 if(o.zIndex) { // zIndex option 4205 if (this.helper.css("zIndex")) { 4206 this._storedZIndex = this.helper.css("zIndex"); 4207 } 4208 this.helper.css("zIndex", o.zIndex); 4209 } 4210 4211 //Prepare scrolling 4212 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { 4213 this.overflowOffset = this.scrollParent.offset(); 4214 } 4215 4216 //Call callbacks 4217 this._trigger("start", event, this._uiHash()); 4218 4219 //Recache the helper size 4220 if(!this._preserveHelperProportions) { 4221 this._cacheHelperProportions(); 4222 } 4223 4224 4225 //Post "activate" events to possible containers 4226 if( !noActivation ) { 4227 for ( i = this.containers.length - 1; i >= 0; i-- ) { 4228 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); 4229 } 4230 } 4231 4232 //Prepare possible droppables 4233 if($.ui.ddmanager) { 4234 $.ui.ddmanager.current = this; 4235 } 4236 4237 if ($.ui.ddmanager && !o.dropBehaviour) { 4238 $.ui.ddmanager.prepareOffsets(this, event); 4239 } 4240 4241 this.dragging = true; 4242 4243 this.helper.addClass("ui-sortable-helper"); 4244 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position 4245 return true; 4246 4247 }, 4248 4249 _mouseDrag: function(event) { 4250 var i, item, itemElement, intersection, 4251 o = this.options, 4252 scrolled = false; 4253 4254 //Compute the helpers position 4255 this.position = this._generatePosition(event); 4256 this.positionAbs = this._convertPositionTo("absolute"); 4257 4258 if (!this.lastPositionAbs) { 4259 this.lastPositionAbs = this.positionAbs; 4260 } 4261 4262 //Do scrolling 4263 if(this.options.scroll) { 4264 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { 4265 4266 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { 4267 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; 4268 } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) { 4269 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; 4270 } 4271 4272 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { 4273 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; 4274 } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) { 4275 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; 4276 } 4277 4278 } else { 4279 4280 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { 4281 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); 4282 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { 4283 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); 4284 } 4285 4286 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { 4287 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); 4288 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { 4289 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); 4290 } 4291 4292 } 4293 4294 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { 4295 $.ui.ddmanager.prepareOffsets(this, event); 4296 } 4297 } 4298 4299 //Regenerate the absolute position used for position checks 4300 this.positionAbs = this._convertPositionTo("absolute"); 4301 4302 //Set the helper position 4303 if(!this.options.axis || this.options.axis !== "y") { 4304 this.helper[0].style.left = this.position.left+"px"; 4305 } 4306 if(!this.options.axis || this.options.axis !== "x") { 4307 this.helper[0].style.top = this.position.top+"px"; 4308 } 4309 4310 //Rearrange 4311 for (i = this.items.length - 1; i >= 0; i--) { 4312 4313 //Cache variables and intersection, continue if no intersection 4314 item = this.items[i]; 4315 itemElement = item.item[0]; 4316 intersection = this._intersectsWithPointer(item); 4317 if (!intersection) { 4318 continue; 4319 } 4320 4321 // Only put the placeholder inside the current Container, skip all 4322 // items form other containers. This works because when moving 4323 // an item from one container to another the 4324 // currentContainer is switched before the placeholder is moved. 4325 // 4326 // Without this moving items in "sub-sortables" can cause the placeholder to jitter 4327 // beetween the outer and inner container. 4328 if (item.instance !== this.currentContainer) { 4329 continue; 4330 } 4331 4332 // cannot intersect with itself 4333 // no useless actions that have been done before 4334 // no action if the item moved is the parent of the item checked 4335 if (itemElement !== this.currentItem[0] && 4336 this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement && 4337 !$.contains(this.placeholder[0], itemElement) && 4338 (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true) 4339 ) { 4340 4341 this.direction = intersection === 1 ? "down" : "up"; 4342 4343 if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) { 4344 this._rearrange(event, item); 4345 } else { 4346 break; 4347 } 4348 4349 this._trigger("change", event, this._uiHash()); 4350 break; 4351 } 4352 } 4353 4354 //Post events to containers 4355 this._contactContainers(event); 4356 4357 //Interconnect with droppables 4358 if($.ui.ddmanager) { 4359 $.ui.ddmanager.drag(this, event); 4360 } 4361 4362 //Call callbacks 4363 this._trigger("sort", event, this._uiHash()); 4364 4365 this.lastPositionAbs = this.positionAbs; 4366 return false; 4367 4368 }, 4369 4370 _mouseStop: function(event, noPropagation) { 4371 4372 if(!event) { 4373 return; 4374 } 4375 4376 //If we are using droppables, inform the manager about the drop 4377 if ($.ui.ddmanager && !this.options.dropBehaviour) { 4378 $.ui.ddmanager.drop(this, event); 4379 } 4380 4381 if(this.options.revert) { 4382 var that = this, 4383 cur = this.placeholder.offset(); 4384 4385 this.reverting = true; 4386 4387 $(this.helper).animate({ 4388 left: cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft), 4389 top: cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop) 4390 }, parseInt(this.options.revert, 10) || 500, function() { 4391 that._clear(event); 4392 }); 4393 } else { 4394 this._clear(event, noPropagation); 4395 } 4396 4397 return false; 4398 4399 }, 4400 4401 cancel: function() { 4402 4403 if(this.dragging) { 4404 4405 this._mouseUp({ target: null }); 4406 4407 if(this.options.helper === "original") { 4408 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); 4409 } else { 4410 this.currentItem.show(); 4411 } 4412 4413 //Post deactivating events to containers 4414 for (var i = this.containers.length - 1; i >= 0; i--){ 4415 this.containers[i]._trigger("deactivate", null, this._uiHash(this)); 4416 if(this.containers[i].containerCache.over) { 4417 this.containers[i]._trigger("out", null, this._uiHash(this)); 4418 this.containers[i].containerCache.over = 0; 4419 } 4420 } 4421 4422 } 4423 4424 if (this.placeholder) { 4425 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! 4426 if(this.placeholder[0].parentNode) { 4427 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 4428 } 4429 if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) { 4430 this.helper.remove(); 4431 } 4432 4433 $.extend(this, { 4434 helper: null, 4435 dragging: false, 4436 reverting: false, 4437 _noFinalSort: null 4438 }); 4439 4440 if(this.domPosition.prev) { 4441 $(this.domPosition.prev).after(this.currentItem); 4442 } else { 4443 $(this.domPosition.parent).prepend(this.currentItem); 4444 } 4445 } 4446 4447 return this; 4448 4449 }, 4450 4451 serialize: function(o) { 4452 4453 var items = this._getItemsAsjQuery(o && o.connected), 4454 str = []; 4455 o = o || {}; 4456 4457 $(items).each(function() { 4458 var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/)); 4459 if (res) { 4460 str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2])); 4461 } 4462 }); 4463 4464 if(!str.length && o.key) { 4465 str.push(o.key + "="); 4466 } 4467 4468 return str.join("&"); 4469 4470 }, 4471 4472 toArray: function(o) { 4473 4474 var items = this._getItemsAsjQuery(o && o.connected), 4475 ret = []; 4476 4477 o = o || {}; 4478 4479 items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); }); 4480 return ret; 4481 4482 }, 4483 4484 /* Be careful with the following core functions */ 4485 _intersectsWith: function(item) { 4486 4487 var x1 = this.positionAbs.left, 4488 x2 = x1 + this.helperProportions.width, 4489 y1 = this.positionAbs.top, 4490 y2 = y1 + this.helperProportions.height, 4491 l = item.left, 4492 r = l + item.width, 4493 t = item.top, 4494 b = t + item.height, 4495 dyClick = this.offset.click.top, 4496 dxClick = this.offset.click.left, 4497 isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r; 4498 4499 if ( this.options.tolerance === "pointer" || 4500 this.options.forcePointerForContainers || 4501 (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"]) 4502 ) { 4503 return isOverElement; 4504 } else { 4505 4506 return (l < x1 + (this.helperProportions.width / 2) && // Right Half 4507 x2 - (this.helperProportions.width / 2) < r && // Left Half 4508 t < y1 + (this.helperProportions.height / 2) && // Bottom Half 4509 y2 - (this.helperProportions.height / 2) < b ); // Top Half 4510 4511 } 4512 }, 4513 4514 _intersectsWithPointer: function(item) { 4515 4516 var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), 4517 isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), 4518 isOverElement = isOverElementHeight && isOverElementWidth, 4519 verticalDirection = this._getDragVerticalDirection(), 4520 horizontalDirection = this._getDragHorizontalDirection(); 4521 4522 if (!isOverElement) { 4523 return false; 4524 } 4525 4526 return this.floating ? 4527 ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 ) 4528 : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) ); 4529 4530 }, 4531 4532 _intersectsWithSides: function(item) { 4533 4534 var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), 4535 isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), 4536 verticalDirection = this._getDragVerticalDirection(), 4537 horizontalDirection = this._getDragHorizontalDirection(); 4538 4539 if (this.floating && horizontalDirection) { 4540 return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf)); 4541 } else { 4542 return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf)); 4543 } 4544 4545 }, 4546 4547 _getDragVerticalDirection: function() { 4548 var delta = this.positionAbs.top - this.lastPositionAbs.top; 4549 return delta !== 0 && (delta > 0 ? "down" : "up"); 4550 }, 4551 4552 _getDragHorizontalDirection: function() { 4553 var delta = this.positionAbs.left - this.lastPositionAbs.left; 4554 return delta !== 0 && (delta > 0 ? "right" : "left"); 4555 }, 4556 4557 refresh: function(event) { 4558 this._refreshItems(event); 4559 this.refreshPositions(); 4560 return this; 4561 }, 4562 4563 _connectWith: function() { 4564 var options = this.options; 4565 return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith; 4566 }, 4567 4568 _getItemsAsjQuery: function(connected) { 4569 4570 var i, j, cur, inst, 4571 items = [], 4572 queries = [], 4573 connectWith = this._connectWith(); 4574 4575 if(connectWith && connected) { 4576 for (i = connectWith.length - 1; i >= 0; i--){ 4577 cur = $(connectWith[i]); 4578 for ( j = cur.length - 1; j >= 0; j--){ 4579 inst = $.data(cur[j], this.widgetFullName); 4580 if(inst && inst !== this && !inst.options.disabled) { 4581 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]); 4582 } 4583 } 4584 } 4585 } 4586 4587 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]); 4588 4589 for (i = queries.length - 1; i >= 0; i--){ 4590 queries[i][0].each(function() { 4591 items.push(this); 4592 }); 4593 } 4594 4595 return $(items); 4596 4597 }, 4598 4599 _removeCurrentsFromItems: function() { 4600 4601 var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); 4602 4603 this.items = $.grep(this.items, function (item) { 4604 for (var j=0; j < list.length; j++) { 4605 if(list[j] === item.item[0]) { 4606 return false; 4607 } 4608 } 4609 return true; 4610 }); 4611 4612 }, 4613 4614 _refreshItems: function(event) { 4615 4616 this.items = []; 4617 this.containers = [this]; 4618 4619 var i, j, cur, inst, targetData, _queries, item, queriesLength, 4620 items = this.items, 4621 queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]], 4622 connectWith = this._connectWith(); 4623 4624 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down 4625 for (i = connectWith.length - 1; i >= 0; i--){ 4626 cur = $(connectWith[i]); 4627 for (j = cur.length - 1; j >= 0; j--){ 4628 inst = $.data(cur[j], this.widgetFullName); 4629 if(inst && inst !== this && !inst.options.disabled) { 4630 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); 4631 this.containers.push(inst); 4632 } 4633 } 4634 } 4635 } 4636 4637 for (i = queries.length - 1; i >= 0; i--) { 4638 targetData = queries[i][1]; 4639 _queries = queries[i][0]; 4640 4641 for (j=0, queriesLength = _queries.length; j < queriesLength; j++) { 4642 item = $(_queries[j]); 4643 4644 item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager) 4645 4646 items.push({ 4647 item: item, 4648 instance: targetData, 4649 width: 0, height: 0, 4650 left: 0, top: 0 4651 }); 4652 } 4653 } 4654 4655 }, 4656 4657 refreshPositions: function(fast) { 4658 4659 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change 4660 if(this.offsetParent && this.helper) { 4661 this.offset.parent = this._getParentOffset(); 4662 } 4663 4664 var i, item, t, p; 4665 4666 for (i = this.items.length - 1; i >= 0; i--){ 4667 item = this.items[i]; 4668 4669 //We ignore calculating positions of all connected containers when we're not over them 4670 if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) { 4671 continue; 4672 } 4673 4674 t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; 4675 4676 if (!fast) { 4677 item.width = t.outerWidth(); 4678 item.height = t.outerHeight(); 4679 } 4680 4681 p = t.offset(); 4682 item.left = p.left; 4683 item.top = p.top; 4684 } 4685 4686 if(this.options.custom && this.options.custom.refreshContainers) { 4687 this.options.custom.refreshContainers.call(this); 4688 } else { 4689 for (i = this.containers.length - 1; i >= 0; i--){ 4690 p = this.containers[i].element.offset(); 4691 this.containers[i].containerCache.left = p.left; 4692 this.containers[i].containerCache.top = p.top; 4693 this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); 4694 this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); 4695 } 4696 } 4697 4698 return this; 4699 }, 4700 4701 _createPlaceholder: function(that) { 4702 that = that || this; 4703 var className, 4704 o = that.options; 4705 4706 if(!o.placeholder || o.placeholder.constructor === String) { 4707 className = o.placeholder; 4708 o.placeholder = { 4709 element: function() { 4710 4711 var el = $(document.createElement(that.currentItem[0].nodeName)) 4712 .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder") 4713 .removeClass("ui-sortable-helper")[0]; 4714 4715 if(!className) { 4716 el.style.visibility = "hidden"; 4717 } 4718 4719 return el; 4720 }, 4721 update: function(container, p) { 4722 4723 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that 4724 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified 4725 if(className && !o.forcePlaceholderSize) { 4726 return; 4727 } 4728 4729 //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 4730 if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); } 4731 if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); } 4732 } 4733 }; 4734 } 4735 4736 //Create the placeholder 4737 that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem)); 4738 4739 //Append it after the actual current item 4740 that.currentItem.after(that.placeholder); 4741 4742 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) 4743 o.placeholder.update(that, that.placeholder); 4744 4745 }, 4746 4747 _contactContainers: function(event) { 4748 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, 4749 innermostContainer = null, 4750 innermostIndex = null; 4751 4752 // get innermost container that intersects with item 4753 for (i = this.containers.length - 1; i >= 0; i--) { 4754 4755 // never consider a container that's located within the item itself 4756 if($.contains(this.currentItem[0], this.containers[i].element[0])) { 4757 continue; 4758 } 4759 4760 if(this._intersectsWith(this.containers[i].containerCache)) { 4761 4762 // if we've already found a container and it's more "inner" than this, then continue 4763 if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) { 4764 continue; 4765 } 4766 4767 innermostContainer = this.containers[i]; 4768 innermostIndex = i; 4769 4770 } else { 4771 // container doesn't intersect. trigger "out" event if necessary 4772 if(this.containers[i].containerCache.over) { 4773 this.containers[i]._trigger("out", event, this._uiHash(this)); 4774 this.containers[i].containerCache.over = 0; 4775 } 4776 } 4777 4778 } 4779 4780 // if no intersecting containers found, return 4781 if(!innermostContainer) { 4782 return; 4783 } 4784 4785 // move the item into the container if it's not there already 4786 if(this.containers.length === 1) { 4787 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 4788 this.containers[innermostIndex].containerCache.over = 1; 4789 } else { 4790 4791 //When entering a new container, we will find the item with the least distance and append our item near it 4792 dist = 10000; 4793 itemWithLeastDistance = null; 4794 posProperty = this.containers[innermostIndex].floating ? "left" : "top"; 4795 sizeProperty = this.containers[innermostIndex].floating ? "width" : "height"; 4796 base = this.positionAbs[posProperty] + this.offset.click[posProperty]; 4797 for (j = this.items.length - 1; j >= 0; j--) { 4798 if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) { 4799 continue; 4800 } 4801 if(this.items[j].item[0] === this.currentItem[0]) { 4802 continue; 4803 } 4804 cur = this.items[j].item.offset()[posProperty]; 4805 nearBottom = false; 4806 if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){ 4807 nearBottom = true; 4808 cur += this.items[j][sizeProperty]; 4809 } 4810 4811 if(Math.abs(cur - base) < dist) { 4812 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 4813 this.direction = nearBottom ? "up": "down"; 4814 } 4815 } 4816 4817 //Check if dropOnEmpty is enabled 4818 if(!itemWithLeastDistance && !this.options.dropOnEmpty) { 4819 return; 4820 } 4821 4822 this.currentContainer = this.containers[innermostIndex]; 4823 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 4824 this._trigger("change", event, this._uiHash()); 4825 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 4826 4827 //Update the placeholder 4828 this.options.placeholder.update(this.currentContainer, this.placeholder); 4829 4830 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 4831 this.containers[innermostIndex].containerCache.over = 1; 4832 } 4833 4834 4835 }, 4836 4837 _createHelper: function(event) { 4838 4839 var o = this.options, 4840 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem); 4841 4842 //Add the helper to the DOM if that didn't happen already 4843 if(!helper.parents("body").length) { 4844 $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); 4845 } 4846 4847 if(helper[0] === this.currentItem[0]) { 4848 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
vendor: 4,379 bytes, lines 4848-4965
4848: this.currentItem.css("left") }; 4849 } 4850 4851 if(!helper[0].style.width || o.forceHelperSize) { 4852 helper.width(this.currentItem.width()); 4853 } 4854 if(!helper[0].style.height || o.forceHelperSize) { 4855 helper.height(this.currentItem.height()); 4856 } 4857 4858 return helper; 4859 4860 }, 4861 4862 _adjustOffsetFromHelper: function(obj) { 4863 if (typeof obj === "string") { 4864 obj = obj.split(" "); 4865 } 4866 if ($.isArray(obj)) { 4867 obj = {left: +obj[0], top: +obj[1] || 0}; 4868 } 4869 if ("left" in obj) { 4870 this.offset.click.left = obj.left + this.margins.left; 4871 } 4872 if ("right" in obj) { 4873 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 4874 } 4875 if ("top" in obj) { 4876 this.offset.click.top = obj.top + this.margins.top; 4877 } 4878 if ("bottom" in obj) { 4879 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 4880 } 4881 }, 4882 4883 _getParentOffset: function() { 4884 4885 4886 //Get the offsetParent and cache its position 4887 this.offsetParent = this.helper.offsetParent(); 4888 var po = this.offsetParent.offset(); 4889 4890 // This is a special case where we need to modify a offset calculated on start, since the following happened: 4891 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent 4892 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that 4893 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag 4894 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { 4895 po.left += this.scrollParent.scrollLeft(); 4896 po.top += this.scrollParent.scrollTop(); 4897 } 4898 4899 // This needs to be actually done for all browsers, since pageX/pageY includes this information 4900 // with an ugly IE fix 4901 if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { 4902 po = { top: 0, left: 0 }; 4903 } 4904 4905 return { 4906 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), 4907 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) 4908 }; 4909 4910 }, 4911 4912 _getRelativeOffset: function() { 4913 4914 if(this.cssPosition === "relative") { 4915 var p = this.currentItem.position(); 4916 return { 4917 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), 4918 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() 4919 }; 4920 } else { 4921 return { top: 0, left: 0 }; 4922 } 4923 4924 }, 4925 4926 _cacheMargins: function() { 4927 this.margins = { 4928 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), 4929 top: (parseInt(this.currentItem.css("marginTop"),10) || 0) 4930 }; 4931 }, 4932 4933 _cacheHelperProportions: function() { 4934 this.helperProportions = { 4935 width: this.helper.outerWidth(), 4936 height: this.helper.outerHeight() 4937 }; 4938 }, 4939 4940 _setContainment: function() { 4941 4942 var ce, co, over, 4943 o = this.options; 4944 if(o.containment === "parent") { 4945 o.containment = this.helper[0].parentNode; 4946 } 4947 if(o.containment === "document" || o.containment === "window") { 4948 this.containment = [ 4949 0 - this.offset.relative.left - this.offset.parent.left, 4950 0 - this.offset.relative.top - this.offset.parent.top, 4951 $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left, 4952 ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top 4953 ]; 4954 } 4955 4956 if(!(/^(document|window|parent)$/).test(o.containment)) { 4957 ce = $(o.containment)[0]; 4958 co = $(o.containment).offset(); 4959 over = ($(ce).css("overflow") !== "hidden"); 4960 4961 this.containment = [ 4962 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, 4963 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, 4964 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, 4965 co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),
vendor: 5,508 bytes, lines 4965-5077
496510) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top 4966 ]; 4967 } 4968 4969 }, 4970 4971 _convertPositionTo: function(d, pos) { 4972 4973 if(!pos) { 4974 pos = this.position; 4975 } 4976 var mod = d === "absolute" ? 1 : -1, 4977 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, 4978 scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 4979 4980 return { 4981 top: ( 4982 pos.top + // The absolute mouse position 4983 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 4984 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) 4985 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) 4986 ), 4987 left: ( 4988 pos.left + // The absolute mouse position 4989 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 4990 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) 4991 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) 4992 ) 4993 }; 4994 4995 }, 4996 4997 _generatePosition: function(event) { 4998 4999 var top, left, 5000 o = this.options, 5001 pageX = event.pageX, 5002 pageY = event.pageY, 5003 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 5004 5005 // This is another very weird special case that only happens for relative elements: 5006 // 1. If the css position is relative 5007 // 2. and the scroll parent is the document or similar to the offset parent 5008 // we have to refresh the relative offset during the scroll so there are no jumps 5009 if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) { 5010 this.offset.relative = this._getRelativeOffset(); 5011 } 5012 5013 /* 5014 * - Position constraining - 5015 * Constrain the position to a mix of grid, containment. 5016 */ 5017 5018 if(this.originalPosition) { //If we are not dragging yet, we won't check for options 5019 5020 if(this.containment) { 5021 if(event.pageX - this.offset.click.left < this.containment[0]) { 5022 pageX = this.containment[0] + this.offset.click.left; 5023 } 5024 if(event.pageY - this.offset.click.top < this.containment[1]) { 5025 pageY = this.containment[1] + this.offset.click.top; 5026 } 5027 if(event.pageX - this.offset.click.left > this.containment[2]) { 5028 pageX = this.containment[2] + this.offset.click.left; 5029 } 5030 if(event.pageY - this.offset.click.top > this.containment[3]) { 5031 pageY = this.containment[3] + this.offset.click.top; 5032 } 5033 } 5034 5035 if(o.grid) { 5036 top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; 5037 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; 5038 5039 left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; 5040 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; 5041 } 5042 5043 } 5044 5045 return { 5046 top: ( 5047 pageY - // The absolute mouse position 5048 this.offset.click.top - // Click offset (relative to the element) 5049 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent 5050 this.offset.parent.top + // The offsetParent's offset without borders (offset + border) 5051 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) 5052 ), 5053 left: ( 5054 pageX - // The absolute mouse position 5055 this.offset.click.left - // Click offset (relative to the element) 5056 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent 5057 this.offset.parent.left + // The offsetParent's offset without borders (offset + border) 5058 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) 5059 ) 5060 }; 5061 5062 }, 5063 5064 _rearrange: function(event, i, a, hardRefresh) { 5065 5066 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)); 5067 5068 //Various things done here to improve the performance: 5069 // 1. we create a setTimeout, that calls refreshPositions 5070 // 2. on the instance, we have a counter variable, that get's higher after every append 5071 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same 5072 // 4. this lets only the last addition to the timeout stack through 5073 this.counter = this.counter ? ++this.counter : 1; 5074 var counter = this.counter; 5075 5076 this._delay(function() { 5077 if(counter === this.counter) {
vendor: 3,274 bytes, lines 5078-5160
5078 this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove 5079 } 5080 }); 5081 5082 }, 5083 5084 _clear: function(event, noPropagation) { 5085 5086 this.reverting = false; 5087 // We delay all events that have to be triggered to after the point where the placeholder has been removed and 5088 // everything else normalized again 5089 var i, 5090 delayedTriggers = []; 5091 5092 // We first have to update the dom position of the actual currentItem 5093 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) 5094 if(!this._noFinalSort && this.currentItem.parent().length) { 5095 this.placeholder.before(this.currentItem); 5096 } 5097 this._noFinalSort = null; 5098 5099 if(this.helper[0] === this.currentItem[0]) { 5100 for(i in this._storedCSS) { 5101 if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") { 5102 this._storedCSS[i] = ""; 5103 } 5104 } 5105 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); 5106 } else { 5107 this.currentItem.show(); 5108 } 5109 5110 if(this.fromOutside && !noPropagation) { 5111 delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); 5112 } 5113 if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) { 5114 delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed 5115 } 5116 5117 // Check if the items Container has Changed and trigger appropriate 5118 // events. 5119 if (this !== this.currentContainer) { 5120 if(!noPropagation) { 5121 delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); 5122 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); 5123 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); 5124 } 5125 } 5126 5127 5128 //Post events to containers 5129 for (i = this.containers.length - 1; i >= 0; i--){ 5130 if(!noPropagation) { 5131 delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i])); 5132 } 5133 if(this.containers[i].containerCache.over) { 5134 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i])); 5135 this.containers[i].containerCache.over = 0; 5136 } 5137 } 5138 5139 //Do what was originally in plugins 5140 if(this._storedCursor) { 5141 $("body").css("cursor", this._storedCursor); 5142 } 5143 if(this._storedOpacity) { 5144 this.helper.css("opacity", this._storedOpacity); 5145 } 5146 if(this._storedZIndex) { 5147 this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex); 5148 } 5149 5150 this.dragging = false; 5151 if(this.cancelHelperRemoval) { 5152 if(!noPropagation) { 5153 this._trigger("beforeStop", event, this._uiHash()); 5154 for (i=0; i < delayedTriggers.length; i++) { 5155 delayedTriggers[i].call(this, event); 5156 } //Trigger all delayed events 5157 this._trigger("stop", event, this._uiHash()); 5158 } 5159 5160 this.fromOutside = false;
vendor: 46,112 bytes, lines 5161-6819
5161 return false; 5162 } 5163 5164 if(!noPropagation) { 5165 this._trigger("beforeStop", event, this._uiHash()); 5166 } 5167 5168 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! 5169 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 5170 5171 if(this.helper[0] !== this.currentItem[0]) { 5172 this.helper.remove(); 5173 } 5174 this.helper = null; 5175 5176 if(!noPropagation) { 5177 for (i=0; i < delayedTriggers.length; i++) { 5178 delayedTriggers[i].call(this, event); 5179 } //Trigger all delayed events 5180 this._trigger("stop", event, this._uiHash()); 5181 } 5182 5183 this.fromOutside = false; 5184 return true; 5185 5186 }, 5187 5188 _trigger: function() { 5189 if ($.Widget.prototype._trigger.apply(this, arguments) === false) { 5190 this.cancel(); 5191 } 5192 }, 5193 5194 _uiHash: function(_inst) { 5195 var inst = _inst || this; 5196 return { 5197 helper: inst.helper, 5198 placeholder: inst.placeholder || $([]), 5199 position: inst.position, 5200 originalPosition: inst.originalPosition, 5201 offset: inst.positionAbs, 5202 item: inst.currentItem, 5203 sender: _inst ? _inst.element : null 5204 }; 5205 } 5206 5207}); 5208 5209})(jQuery); 5210(function( $, undefined ) { 5211 5212var uid = 0, 5213 hideProps = {}, 5214 showProps = {}; 5215 5216hideProps.height = hideProps.paddingTop = hideProps.paddingBottom = 5217 hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide"; 5218showProps.height = showProps.paddingTop = showProps.paddingBottom = 5219 showProps.borderTopWidth = showProps.borderBottomWidth = "show"; 5220 5221$.widget( "ui.accordion", { 5222 version: "1.10.0", 5223 options: { 5224 active: 0, 5225 animate: {}, 5226 collapsible: false, 5227 event: "click", 5228 header: "> li > :first-child,> :not(li):even", 5229 heightStyle: "auto", 5230 icons: { 5231 activeHeader: "ui-icon-triangle-1-s", 5232 header: "ui-icon-triangle-1-e" 5233 }, 5234 5235 // callbacks 5236 activate: null, 5237 beforeActivate: null 5238 }, 5239 5240 _create: function() { 5241 var options = this.options; 5242 this.prevShow = this.prevHide = $(); 5243 this.element.addClass( "ui-accordion ui-widget ui-helper-reset" ) 5244 // ARIA 5245 .attr( "role", "tablist" ); 5246 5247 // don't allow collapsible: false and active: false / null 5248 if ( !options.collapsible && (options.active === false || options.active == null) ) { 5249 options.active = 0; 5250 } 5251 5252 this._processPanels(); 5253 // handle negative values 5254 if ( options.active < 0 ) { 5255 options.active += this.headers.length; 5256 } 5257 this._refresh(); 5258 }, 5259 5260 _getCreateEventData: function() { 5261 return { 5262 header: this.active, 5263 content: !this.active.length ? $() : this.active.next() 5264 }; 5265 }, 5266 5267 _createIcons: function() { 5268 var icons = this.options.icons; 5269 if ( icons ) { 5270 $( "<span>" ) 5271 .addClass( "ui-accordion-header-icon ui-icon " + icons.header ) 5272 .prependTo( this.headers ); 5273 this.active.children( ".ui-accordion-header-icon" ) 5274 .removeClass( icons.header ) 5275 .addClass( icons.activeHeader ); 5276 this.headers.addClass( "ui-accordion-icons" ); 5277 } 5278 }, 5279 5280 _destroyIcons: function() { 5281 this.headers 5282 .removeClass( "ui-accordion-icons" ) 5283 .children( ".ui-accordion-header-icon" ) 5284 .remove(); 5285 }, 5286 5287 _destroy: function() { 5288 var contents; 5289 5290 // clean up main element 5291 this.element 5292 .removeClass( "ui-accordion ui-widget ui-helper-reset" ) 5293 .removeAttr( "role" ); 5294 5295 // clean up headers 5296 this.headers 5297 .removeClass( "ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" ) 5298 .removeAttr( "role" ) 5299 .removeAttr( "aria-selected" ) 5300 .removeAttr( "aria-controls" ) 5301 .removeAttr( "tabIndex" ) 5302 .each(function() { 5303 if ( /^ui-accordion/.test( this.id ) ) { 5304 this.removeAttribute( "id" ); 5305 } 5306 }); 5307 this._destroyIcons(); 5308 5309 // clean up content panels 5310 contents = this.headers.next() 5311 .css( "display", "" ) 5312 .removeAttr( "role" ) 5313 .removeAttr( "aria-expanded" ) 5314 .removeAttr( "aria-hidden" ) 5315 .removeAttr( "aria-labelledby" ) 5316 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" ) 5317 .each(function() { 5318 if ( /^ui-accordion/.test( this.id ) ) { 5319 this.removeAttribute( "id" ); 5320 } 5321 }); 5322 if ( this.options.heightStyle !== "content" ) { 5323 contents.css( "height", "" ); 5324 } 5325 }, 5326 5327 _setOption: function( key, value ) { 5328 if ( key === "active" ) { 5329 // _activate() will handle invalid values and update this.options 5330 this._activate( value ); 5331 return; 5332 } 5333 5334 if ( key === "event" ) { 5335 if ( this.options.event ) { 5336 this._off( this.headers, this.options.event ); 5337 } 5338 this._setupEvents( value ); 5339 } 5340 5341 this._super( key, value ); 5342 5343 // setting collapsible: false while collapsed; open first panel 5344 if ( key === "collapsible" && !value && this.options.active === false ) { 5345 this._activate( 0 ); 5346 } 5347 5348 if ( key === "icons" ) { 5349 this._destroyIcons(); 5350 if ( value ) { 5351 this._createIcons(); 5352 } 5353 } 5354 5355 // #5332 - opacity doesn't cascade to positioned elements in IE 5356 // so we need to add the disabled class to the headers and panels 5357 if ( key === "disabled" ) { 5358 this.headers.add( this.headers.next() ) 5359 .toggleClass( "ui-state-disabled", !!value ); 5360 } 5361 }, 5362 5363 _keydown: function( event ) { 5364 /*jshint maxcomplexity:15*/ 5365 if ( event.altKey || event.ctrlKey ) { 5366 return; 5367 } 5368 5369 var keyCode = $.ui.keyCode, 5370 length = this.headers.length, 5371 currentIndex = this.headers.index( event.target ), 5372 toFocus = false; 5373 5374 switch ( event.keyCode ) { 5375 case keyCode.RIGHT: 5376 case keyCode.DOWN: 5377 toFocus = this.headers[ ( currentIndex + 1 ) % length ]; 5378 break; 5379 case keyCode.LEFT: 5380 case keyCode.UP: 5381 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; 5382 break; 5383 case keyCode.SPACE: 5384 case keyCode.ENTER: 5385 this._eventHandler( event ); 5386 break; 5387 case keyCode.HOME: 5388 toFocus = this.headers[ 0 ]; 5389 break; 5390 case keyCode.END: 5391 toFocus = this.headers[ length - 1 ]; 5392 break; 5393 } 5394 5395 if ( toFocus ) { 5396 $( event.target ).attr( "tabIndex", -1 ); 5397 $( toFocus ).attr( "tabIndex", 0 ); 5398 toFocus.focus(); 5399 event.preventDefault(); 5400 } 5401 }, 5402 5403 _panelKeyDown : function( event ) { 5404 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { 5405 $( event.currentTarget ).prev().focus(); 5406 } 5407 }, 5408 5409 refresh: function() { 5410 var options = this.options; 5411 this._processPanels(); 5412 5413 // was collapsed or no panel 5414 if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) { 5415 options.active = false; 5416 this.active = $(); 5417 // active false only when collapsible is true 5418 } if ( options.active === false ) { 5419 this._activate( 0 ); 5420 // was active, but active panel is gone 5421 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 5422 // all remaining panel are disabled 5423 if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) { 5424 options.active = false; 5425 this.active = $(); 5426 // activate previous panel 5427 } else { 5428 this._activate( Math.max( 0, options.active - 1 ) ); 5429 } 5430 // was active, active panel still exists 5431 } else { 5432 // make sure active index is correct 5433 options.active = this.headers.index( this.active ); 5434 } 5435 5436 this._destroyIcons(); 5437 5438 this._refresh(); 5439 }, 5440 5441 _processPanels: function() { 5442 this.headers = this.element.find( this.options.header ) 5443 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ); 5444 5445 this.headers.next() 5446 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ) 5447 .filter(":not(.ui-accordion-content-active)") 5448 .hide(); 5449 }, 5450 5451 _refresh: function() { 5452 var maxHeight, 5453 options = this.options, 5454 heightStyle = options.heightStyle, 5455 parent = this.element.parent(), 5456 accordionId = this.accordionId = "ui-accordion-" + 5457 (this.element.attr( "id" ) || ++uid); 5458 5459 this.active = this._findActive( options.active ) 5460 .addClass( "ui-accordion-header-active ui-state-active" ) 5461 .toggleClass( "ui-corner-all ui-corner-top" ); 5462 this.active.next() 5463 .addClass( "ui-accordion-content-active" ) 5464 .show(); 5465 5466 this.headers 5467 .attr( "role", "tab" ) 5468 .each(function( i ) { 5469 var header = $( this ), 5470 headerId = header.attr( "id" ), 5471 panel = header.next(), 5472 panelId = panel.attr( "id" ); 5473 if ( !headerId ) { 5474 headerId = accordionId + "-header-" + i; 5475 header.attr( "id", headerId ); 5476 } 5477 if ( !panelId ) { 5478 panelId = accordionId + "-panel-" + i; 5479 panel.attr( "id", panelId ); 5480 } 5481 header.attr( "aria-controls", panelId ); 5482 panel.attr( "aria-labelledby", headerId ); 5483 }) 5484 .next() 5485 .attr( "role", "tabpanel" ); 5486 5487 this.headers 5488 .not( this.active ) 5489 .attr({ 5490 "aria-selected": "false", 5491 tabIndex: -1 5492 }) 5493 .next() 5494 .attr({ 5495 "aria-expanded": "false", 5496 "aria-hidden": "true" 5497 }) 5498 .hide(); 5499 5500 // make sure at least one header is in the tab order 5501 if ( !this.active.length ) { 5502 this.headers.eq( 0 ).attr( "tabIndex", 0 ); 5503 } else { 5504 this.active.attr({ 5505 "aria-selected": "true", 5506 tabIndex: 0 5507 }) 5508 .next() 5509 .attr({ 5510 "aria-expanded": "true", 5511 "aria-hidden": "false" 5512 }); 5513 } 5514 5515 this._createIcons(); 5516 5517 this._setupEvents( options.event ); 5518 5519 if ( heightStyle === "fill" ) { 5520 maxHeight = parent.height(); 5521 this.element.siblings( ":visible" ).each(function() { 5522 var elem = $( this ), 5523 position = elem.css( "position" ); 5524 5525 if ( position === "absolute" || position === "fixed" ) { 5526 return; 5527 } 5528 maxHeight -= elem.outerHeight( true ); 5529 }); 5530 5531 this.headers.each(function() { 5532 maxHeight -= $( this ).outerHeight( true ); 5533 }); 5534 5535 this.headers.next() 5536 .each(function() { 5537 $( this ).height( Math.max( 0, maxHeight - 5538 $( this ).innerHeight() + $( this ).height() ) ); 5539 }) 5540 .css( "overflow", "auto" ); 5541 } else if ( heightStyle === "auto" ) { 5542 maxHeight = 0; 5543 this.headers.next() 5544 .each(function() { 5545 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); 5546 }) 5547 .height( maxHeight ); 5548 } 5549 }, 5550 5551 _activate: function( index ) { 5552 var active = this._findActive( index )[ 0 ]; 5553 5554 // trying to activate the already active panel 5555 if ( active === this.active[ 0 ] ) { 5556 return; 5557 } 5558 5559 // trying to collapse, simulate a click on the currently active header 5560 active = active || this.active[ 0 ]; 5561 5562 this._eventHandler({ 5563 target: active, 5564 currentTarget: active, 5565 preventDefault: $.noop 5566 }); 5567 }, 5568 5569 _findActive: function( selector ) { 5570 return typeof selector === "number" ? this.headers.eq( selector ) : $(); 5571 }, 5572 5573 _setupEvents: function( event ) { 5574 var events = { 5575 keydown: "_keydown" 5576 }; 5577 if ( event ) { 5578 $.each( event.split(" "), function( index, eventName ) { 5579 events[ eventName ] = "_eventHandler"; 5580 }); 5581 } 5582 5583 this._off( this.headers.add( this.headers.next() ) ); 5584 this._on( this.headers, events ); 5585 this._on( this.headers.next(), { keydown: "_panelKeyDown" }); 5586 this._hoverable( this.headers ); 5587 this._focusable( this.headers ); 5588 }, 5589 5590 _eventHandler: function( event ) { 5591 var options = this.options, 5592 active = this.active, 5593 clicked = $( event.currentTarget ), 5594 clickedIsActive = clicked[ 0 ] === active[ 0 ], 5595 collapsing = clickedIsActive && options.collapsible, 5596 toShow = collapsing ? $() : clicked.next(), 5597 toHide = active.next(), 5598 eventData = { 5599 oldHeader: active, 5600 oldPanel: toHide, 5601 newHeader: collapsing ? $() : clicked, 5602 newPanel: toShow 5603 }; 5604 5605 event.preventDefault(); 5606 5607 if ( 5608 // click on active header, but not collapsible 5609 ( clickedIsActive && !options.collapsible ) || 5610 // allow canceling activation 5611 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 5612 return; 5613 } 5614 5615 options.active = collapsing ? false : this.headers.index( clicked ); 5616 5617 // when the call to ._toggle() comes after the class changes 5618 // it causes a very odd bug in IE 8 (see #6720) 5619 this.active = clickedIsActive ? $() : clicked; 5620 this._toggle( eventData ); 5621 5622 // switch classes 5623 // corner classes on the previously active header stay after the animation 5624 active.removeClass( "ui-accordion-header-active ui-state-active" ); 5625 if ( options.icons ) { 5626 active.children( ".ui-accordion-header-icon" ) 5627 .removeClass( options.icons.activeHeader ) 5628 .addClass( options.icons.header ); 5629 } 5630 5631 if ( !clickedIsActive ) { 5632 clicked 5633 .removeClass( "ui-corner-all" ) 5634 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ); 5635 if ( options.icons ) { 5636 clicked.children( ".ui-accordion-header-icon" ) 5637 .removeClass( options.icons.header ) 5638 .addClass( options.icons.activeHeader ); 5639 } 5640 5641 clicked 5642 .next() 5643 .addClass( "ui-accordion-content-active" ); 5644 } 5645 }, 5646 5647 _toggle: function( data ) { 5648 var toShow = data.newPanel, 5649 toHide = this.prevShow.length ? this.prevShow : data.oldPanel; 5650 5651 // handle activating a panel during the animation for another activation 5652 this.prevShow.add( this.prevHide ).stop( true, true ); 5653 this.prevShow = toShow; 5654 this.prevHide = toHide; 5655 5656 if ( this.options.animate ) { 5657 this._animate( toShow, toHide, data ); 5658 } else { 5659 toHide.hide(); 5660 toShow.show(); 5661 this._toggleComplete( data ); 5662 } 5663 5664 toHide.attr({ 5665 "aria-expanded": "false", 5666 "aria-hidden": "true" 5667 }); 5668 toHide.prev().attr( "aria-selected", "false" ); 5669 // if we're switching panels, remove the old header from the tab order 5670 // if we're opening from collapsed state, remove the previous header from the tab order 5671 // if we're collapsing, then keep the collapsing header in the tab order 5672 if ( toShow.length && toHide.length ) { 5673 toHide.prev().attr( "tabIndex", -1 ); 5674 } else if ( toShow.length ) { 5675 this.headers.filter(function() { 5676 return $( this ).attr( "tabIndex" ) === 0; 5677 }) 5678 .attr( "tabIndex", -1 ); 5679 } 5680 5681 toShow 5682 .attr({ 5683 "aria-expanded": "true", 5684 "aria-hidden": "false" 5685 }) 5686 .prev() 5687 .attr({ 5688 "aria-selected": "true", 5689 tabIndex: 0 5690 }); 5691 }, 5692 5693 _animate: function( toShow, toHide, data ) { 5694 var total, easing, duration, 5695 that = this, 5696 adjust = 0, 5697 down = toShow.length && 5698 ( !toHide.length || ( toShow.index() < toHide.index() ) ), 5699 animate = this.options.animate || {}, 5700 options = down && animate.down || animate, 5701 complete = function() { 5702 that._toggleComplete( data ); 5703 }; 5704 5705 if ( typeof options === "number" ) { 5706 duration = options; 5707 } 5708 if ( typeof options === "string" ) { 5709 easing = options; 5710 } 5711 // fall back from options to animation in case of partial down settings 5712 easing = easing || options.easing || animate.easing; 5713 duration = duration || options.duration || animate.duration; 5714 5715 if ( !toHide.length ) { 5716 return toShow.animate( showProps, duration, easing, complete ); 5717 } 5718 if ( !toShow.length ) { 5719 return toHide.animate( hideProps, duration, easing, complete ); 5720 } 5721 5722 total = toShow.show().outerHeight(); 5723 toHide.animate( hideProps, { 5724 duration: duration, 5725 easing: easing, 5726 step: function( now, fx ) { 5727 fx.now = Math.round( now ); 5728 } 5729 }); 5730 toShow 5731 .hide() 5732 .animate( showProps, { 5733 duration: duration, 5734 easing: easing, 5735 complete: complete, 5736 step: function( now, fx ) { 5737 fx.now = Math.round( now ); 5738 if ( fx.prop !== "height" ) { 5739 adjust += fx.now; 5740 } else if ( that.options.heightStyle !== "content" ) { 5741 fx.now = Math.round( total - toHide.outerHeight() - adjust ); 5742 adjust = 0; 5743 } 5744 } 5745 }); 5746 }, 5747 5748 _toggleComplete: function( data ) { 5749 var toHide = data.oldPanel; 5750 5751 toHide 5752 .removeClass( "ui-accordion-content-active" ) 5753 .prev() 5754 .removeClass( "ui-corner-top" ) 5755 .addClass( "ui-corner-all" ); 5756 5757 // Work around for rendering bug in IE (#5421) 5758 if ( toHide.length ) { 5759 toHide.parent()[0].className = toHide.parent()[0].className; 5760 } 5761 5762 this._trigger( "activate", null, data ); 5763 } 5764}); 5765 5766})( jQuery ); 5767(function( $, undefined ) { 5768 5769// used to prevent race conditions with remote data sources 5770var requestIndex = 0; 5771 5772$.widget( "ui.autocomplete", { 5773 version: "1.10.0", 5774 defaultElement: "<input>", 5775 options: { 5776 appendTo: null, 5777 autoFocus: false, 5778 delay: 300, 5779 minLength: 1, 5780 position: { 5781 my: "left top", 5782 at: "left bottom", 5783 collision: "none" 5784 }, 5785 source: null, 5786 5787 // callbacks 5788 change: null, 5789 close: null, 5790 focus: null, 5791 open: null, 5792 response: null, 5793 search: null, 5794 select: null 5795 }, 5796 5797 pending: 0, 5798 5799 _create: function() { 5800 // Some browsers only repeat keydown events, not keypress events, 5801 // so we use the suppressKeyPress flag to determine if we've already 5802 // handled the keydown event. #7269 5803 // Unfortunately the code for & in keypress is the same as the up arrow, 5804 // so we use the suppressKeyPressRepeat flag to avoid handling keypress 5805 // events when we know the keydown event was used to modify the 5806 // search term. #7799 5807 var suppressKeyPress, suppressKeyPressRepeat, suppressInput; 5808 5809 this.isMultiLine = this._isMultiLine(); 5810 this.valueMethod = this.element[ this.element.is( "input,textarea" ) ? "val" : "text" ]; 5811 this.isNewMenu = true; 5812 5813 this.element 5814 .addClass( "ui-autocomplete-input" ) 5815 .attr( "autocomplete", "off" ); 5816 5817 this._on( this.element, { 5818 keydown: function( event ) { 5819 /*jshint maxcomplexity:15*/ 5820 if ( this.element.prop( "readOnly" ) ) { 5821 suppressKeyPress = true; 5822 suppressInput = true; 5823 suppressKeyPressRepeat = true; 5824 return; 5825 } 5826 5827 suppressKeyPress = false; 5828 suppressInput = false; 5829 suppressKeyPressRepeat = false; 5830 var keyCode = $.ui.keyCode; 5831 switch( event.keyCode ) { 5832 case keyCode.PAGE_UP: 5833 suppressKeyPress = true; 5834 this._move( "previousPage", event ); 5835 break; 5836 case keyCode.PAGE_DOWN: 5837 suppressKeyPress = true; 5838 this._move( "nextPage", event ); 5839 break; 5840 case keyCode.UP: 5841 suppressKeyPress = true; 5842 this._keyEvent( "previous", event ); 5843 break; 5844 case keyCode.DOWN: 5845 suppressKeyPress = true; 5846 this._keyEvent( "next", event ); 5847 break; 5848 case keyCode.ENTER: 5849 case keyCode.NUMPAD_ENTER: 5850 // when menu is open and has focus 5851 if ( this.menu.active ) { 5852 // #6055 - Opera still allows the keypress to occur 5853 // which causes forms to submit 5854 suppressKeyPress = true; 5855 event.preventDefault(); 5856 this.menu.select( event ); 5857 } 5858 break; 5859 case keyCode.TAB: 5860 if ( this.menu.active ) { 5861 this.menu.select( event ); 5862 } 5863 break; 5864 case keyCode.ESCAPE: 5865 if ( this.menu.element.is( ":visible" ) ) { 5866 this._value( this.term ); 5867 this.close( event ); 5868 // Different browsers have different default behavior for escape 5869 // Single press can mean undo or clear 5870 // Double press in IE means clear the whole form 5871 event.preventDefault(); 5872 } 5873 break; 5874 default: 5875 suppressKeyPressRepeat = true; 5876 // search timeout should be triggered before the input value is changed 5877 this._searchTimeout( event ); 5878 break; 5879 } 5880 }, 5881 keypress: function( event ) { 5882 if ( suppressKeyPress ) { 5883 suppressKeyPress = false; 5884 event.preventDefault(); 5885 return; 5886 } 5887 if ( suppressKeyPressRepeat ) { 5888 return; 5889 } 5890 5891 // replicate some key handlers to allow them to repeat in Firefox and Opera 5892 var keyCode = $.ui.keyCode; 5893 switch( event.keyCode ) { 5894 case keyCode.PAGE_UP: 5895 this._move( "previousPage", event ); 5896 break; 5897 case keyCode.PAGE_DOWN: 5898 this._move( "nextPage", event ); 5899 break; 5900 case keyCode.UP: 5901 this._keyEvent( "previous", event ); 5902 break; 5903 case keyCode.DOWN: 5904 this._keyEvent( "next", event ); 5905 break; 5906 } 5907 }, 5908 input: function( event ) { 5909 if ( suppressInput ) { 5910 suppressInput = false; 5911 event.preventDefault(); 5912 return; 5913 } 5914 this._searchTimeout( event ); 5915 }, 5916 focus: function() { 5917 this.selectedItem = null; 5918 this.previous = this._value(); 5919 }, 5920 blur: function( event ) { 5921 if ( this.cancelBlur ) { 5922 delete this.cancelBlur; 5923 return; 5924 } 5925 5926 clearTimeout( this.searching ); 5927 this.close( event ); 5928 this._change( event ); 5929 } 5930 }); 5931 5932 this._initSource(); 5933 this.menu = $( "<ul>" ) 5934 .addClass( "ui-autocomplete" ) 5935 .appendTo( this._appendTo() ) 5936 .menu({ 5937 // custom key handling for now 5938 input: $(), 5939 // disable ARIA support, the live region takes care of that 5940 role: null 5941 }) 5942 .zIndex( this.element.zIndex() + 1 ) 5943 .hide() 5944 .data( "ui-menu" ); 5945 5946 this._on( this.menu.element, { 5947 mousedown: function( event ) { 5948 // prevent moving focus out of the text field 5949 event.preventDefault(); 5950 5951 // IE doesn't prevent moving focus even with event.preventDefault() 5952 // so we set a flag to know when we should ignore the blur event 5953 this.cancelBlur = true; 5954 this._delay(function() { 5955 delete this.cancelBlur; 5956 }); 5957 5958 // clicking on the scrollbar causes focus to shift to the body 5959 // but we can't detect a mouseup or a click immediately afterward 5960 // so we have to track the next mousedown and close the menu if 5961 // the user clicks somewhere outside of the autocomplete 5962 var menuElement = this.menu.element[ 0 ]; 5963 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { 5964 this._delay(function() { 5965 var that = this; 5966 this.document.one( "mousedown", function( event ) { 5967 if ( event.target !== that.element[ 0 ] && 5968 event.target !== menuElement && 5969 !$.contains( menuElement, event.target ) ) { 5970 that.close(); 5971 } 5972 }); 5973 }); 5974 } 5975 }, 5976 menufocus: function( event, ui ) { 5977 // #7024 - Prevent accidental activation of menu items in Firefox 5978 if ( this.isNewMenu ) { 5979 this.isNewMenu = false; 5980 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) { 5981 this.menu.blur(); 5982 5983 this.document.one( "mousemove", function() { 5984 $( event.target ).trigger( event.originalEvent ); 5985 }); 5986 5987 return; 5988 } 5989 } 5990 5991 var item = ui.item.data( "ui-autocomplete-item" ); 5992 if ( false !== this._trigger( "focus", event, { item: item } ) ) { 5993 // use value to match what will end up in the input, if it was a key event 5994 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) { 5995 this._value( item.value ); 5996 } 5997 } else { 5998 // Normally the input is populated with the item's value as the 5999 // menu is navigated, causing screen readers to notice a change and 6000 // announce the item. Since the focus event was canceled, this doesn't 6001 // happen, so we update the live region so that screen readers can 6002 // still notice the change and announce it. 6003 this.liveRegion.text( item.value ); 6004 } 6005 }, 6006 menuselect: function( event, ui ) { 6007 var item = ui.item.data( "ui-autocomplete-item" ), 6008 previous = this.previous; 6009 6010 // only trigger when focus was lost (click on menu) 6011 if ( this.element[0] !== this.document[0].activeElement ) { 6012 this.element.focus(); 6013 this.previous = previous; 6014 // #6109 - IE triggers two focus events and the second 6015 // is asynchronous, so we need to reset the previous 6016 // term synchronously and asynchronously :-( 6017 this._delay(function() { 6018 this.previous = previous; 6019 this.selectedItem = item; 6020 }); 6021 } 6022 6023 if ( false !== this._trigger( "select", event, { item: item } ) ) { 6024 this._value( item.value ); 6025 } 6026 // reset the term after the select event 6027 // this allows custom select handling to work properly 6028 this.term = this._value(); 6029 6030 this.close( event ); 6031 this.selectedItem = item; 6032 } 6033 }); 6034 6035 this.liveRegion = $( "<span>", { 6036 role: "status", 6037 "aria-live": "polite" 6038 }) 6039 .addClass( "ui-helper-hidden-accessible" ) 6040 .insertAfter( this.element ); 6041 6042 // turning off autocomplete prevents the browser from remembering the 6043 // value when navigating through history, so we re-enable autocomplete 6044 // if the page is unloaded before the widget is destroyed. #7790 6045 this._on( this.window, { 6046 beforeunload: function() { 6047 this.element.removeAttr( "autocomplete" ); 6048 } 6049 }); 6050 }, 6051 6052 _destroy: function() { 6053 clearTimeout( this.searching ); 6054 this.element 6055 .removeClass( "ui-autocomplete-input" ) 6056 .removeAttr( "autocomplete" ); 6057 this.menu.element.remove(); 6058 this.liveRegion.remove(); 6059 }, 6060 6061 _setOption: function( key, value ) { 6062 this._super( key, value ); 6063 if ( key === "source" ) { 6064 this._initSource(); 6065 } 6066 if ( key === "appendTo" ) { 6067 this.menu.element.appendTo( this._appendTo() ); 6068 } 6069 if ( key === "disabled" && value && this.xhr ) { 6070 this.xhr.abort(); 6071 } 6072 }, 6073 6074 _appendTo: function() { 6075 var element = this.options.appendTo; 6076 6077 if ( element ) { 6078 element = element.jquery || element.nodeType ? 6079 $( element ) : 6080 this.document.find( element ).eq( 0 ); 6081 } 6082 6083 if ( !element ) { 6084 element = this.element.closest( ".ui-front" ); 6085 } 6086 6087 if ( !element.length ) { 6088 element = this.document[0].body; 6089 } 6090 6091 return element; 6092 }, 6093 6094 _isMultiLine: function() { 6095 // Textareas are always multi-line 6096 if ( this.element.is( "textarea" ) ) { 6097 return true; 6098 } 6099 // Inputs are always single-line, even if inside a contentEditable element 6100 // IE also treats inputs as contentEditable 6101 if ( this.element.is( "input" ) ) { 6102 return false; 6103 } 6104 // All other element types are determined by whether or not they're contentEditable 6105 return this.element.prop( "isContentEditable" ); 6106 }, 6107 6108 _initSource: function() { 6109 var array, url, 6110 that = this; 6111 if ( $.isArray(this.options.source) ) { 6112 array = this.options.source; 6113 this.source = function( request, response ) { 6114 response( $.ui.autocomplete.filter( array, request.term ) ); 6115 }; 6116 } else if ( typeof this.options.source === "string" ) { 6117 url = this.options.source; 6118 this.source = function( request, response ) { 6119 if ( that.xhr ) { 6120 that.xhr.abort(); 6121 } 6122 that.xhr = $.ajax({ 6123 url: url, 6124 data: request, 6125 dataType: "json", 6126 success: function( data ) { 6127 response( data ); 6128 }, 6129 error: function() { 6130 response( [] ); 6131 } 6132 }); 6133 }; 6134 } else { 6135 this.source = this.options.source; 6136 } 6137 }, 6138 6139 _searchTimeout: function( event ) { 6140 clearTimeout( this.searching ); 6141 this.searching = this._delay(function() { 6142 // only search if the value has changed 6143 if ( this.term !== this._value() ) { 6144 this.selectedItem = null; 6145 this.search( null, event ); 6146 } 6147 }, this.options.delay ); 6148 }, 6149 6150 search: function( value, event ) { 6151 value = value != null ? value : this._value(); 6152 6153 // always save the actual value, not the one passed as an argument 6154 this.term = this._value(); 6155 6156 if ( value.length < this.options.minLength ) { 6157 return this.close( event ); 6158 } 6159 6160 if ( this._trigger( "search", event ) === false ) { 6161 return; 6162 } 6163 6164 return this._search( value ); 6165 }, 6166 6167 _search: function( value ) { 6168 this.pending++; 6169 this.element.addClass( "ui-autocomplete-loading" ); 6170 this.cancelSearch = false; 6171 6172 this.source( { term: value }, this._response() ); 6173 }, 6174 6175 _response: function() { 6176 var that = this, 6177 index = ++requestIndex; 6178 6179 return function( content ) { 6180 if ( index === requestIndex ) { 6181 that.__response( content ); 6182 } 6183 6184 that.pending--; 6185 if ( !that.pending ) { 6186 that.element.removeClass( "ui-autocomplete-loading" ); 6187 } 6188 }; 6189 }, 6190 6191 __response: function( content ) { 6192 if ( content ) { 6193 content = this._normalize( content ); 6194 } 6195 this._trigger( "response", null, { content: content } ); 6196 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) { 6197 this._suggest( content ); 6198 this._trigger( "open" ); 6199 } else { 6200 // use ._close() instead of .close() so we don't cancel future searches 6201 this._close(); 6202 } 6203 }, 6204 6205 close: function( event ) { 6206 this.cancelSearch = true; 6207 this._close( event ); 6208 }, 6209 6210 _close: function( event ) { 6211 if ( this.menu.element.is( ":visible" ) ) { 6212 this.menu.element.hide(); 6213 this.menu.blur(); 6214 this.isNewMenu = true; 6215 this._trigger( "close", event ); 6216 } 6217 }, 6218 6219 _change: function( event ) { 6220 if ( this.previous !== this._value() ) { 6221 this._trigger( "change", event, { item: this.selectedItem } ); 6222 } 6223 }, 6224 6225 _normalize: function( items ) { 6226 // assume all items have the right format when the first item is complete 6227 if ( items.length && items[0].label && items[0].value ) { 6228 return items; 6229 } 6230 return $.map( items, function( item ) { 6231 if ( typeof item === "string" ) { 6232 return { 6233 label: item, 6234 value: item 6235 }; 6236 } 6237 return $.extend({ 6238 label: item.label || item.value, 6239 value: item.value || item.label 6240 }, item ); 6241 }); 6242 }, 6243 6244 _suggest: function( items ) { 6245 var ul = this.menu.element 6246 .empty() 6247 .zIndex( this.element.zIndex() + 1 ); 6248 this._renderMenu( ul, items ); 6249 this.menu.refresh(); 6250 6251 // size and position menu 6252 ul.show(); 6253 this._resizeMenu(); 6254 ul.position( $.extend({ 6255 of: this.element 6256 }, this.options.position )); 6257 6258 if ( this.options.autoFocus ) { 6259 this.menu.next(); 6260 } 6261 }, 6262 6263 _resizeMenu: function() { 6264 var ul = this.menu.element; 6265 ul.outerWidth( Math.max( 6266 // Firefox wraps long text (possibly a rounding bug) 6267 // so we add 1px to avoid the wrapping (#7513) 6268 ul.width( "" ).outerWidth() + 1, 6269 this.element.outerWidth() 6270 ) ); 6271 }, 6272 6273 _renderMenu: function( ul, items ) { 6274 var that = this; 6275 $.each( items, function( index, item ) { 6276 that._renderItemData( ul, item ); 6277 }); 6278 }, 6279 6280 _renderItemData: function( ul, item ) { 6281 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item ); 6282 }, 6283 6284 _renderItem: function( ul, item ) { 6285 return $( "<li>" ) 6286 .append( $( "<a>" ).text( item.label ) ) 6287 .appendTo( ul ); 6288 }, 6289 6290 _move: function( direction, event ) { 6291 if ( !this.menu.element.is( ":visible" ) ) { 6292 this.search( null, event ); 6293 return; 6294 } 6295 if ( this.menu.isFirstItem() && /^previous/.test( direction ) || 6296 this.menu.isLastItem() && /^next/.test( direction ) ) { 6297 this._value( this.term ); 6298 this.menu.blur(); 6299 return; 6300 } 6301 this.menu[ direction ]( event ); 6302 }, 6303 6304 widget: function() { 6305 return this.menu.element; 6306 }, 6307 6308 _value: function() { 6309 return this.valueMethod.apply( this.element, arguments ); 6310 }, 6311 6312 _keyEvent: function( keyEvent, event ) { 6313 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 6314 this._move( keyEvent, event ); 6315 6316 // prevents moving cursor to beginning/end of the text field in some browsers 6317 event.preventDefault(); 6318 } 6319 } 6320}); 6321 6322$.extend( $.ui.autocomplete, { 6323 escapeRegex: function( value ) { 6324 return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); 6325 }, 6326 filter: function(array, term) { 6327 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); 6328 return $.grep( array, function(value) { 6329 return matcher.test( value.label || value.value || value ); 6330 }); 6331 } 6332}); 6333 6334 6335// live region extension, adding a `messages` option 6336// NOTE: This is an experimental API. We are still investigating 6337// a full solution for string manipulation and internationalization. 6338$.widget( "ui.autocomplete", $.ui.autocomplete, { 6339 options: { 6340 messages: { 6341 noResults: "No search results.", 6342 results: function( amount ) { 6343 return amount + ( amount > 1 ? " results are" : " result is" ) + 6344 " available, use up and down arrow keys to navigate."; 6345 } 6346 } 6347 }, 6348 6349 __response: function( content ) { 6350 var message; 6351 this._superApply( arguments ); 6352 if ( this.options.disabled || this.cancelSearch ) { 6353 return; 6354 } 6355 if ( content && content.length ) { 6356 message = this.options.messages.results( content.length ); 6357 } else { 6358 message = this.options.messages.noResults; 6359 } 6360 this.liveRegion.text( message ); 6361 } 6362}); 6363 6364}( jQuery )); 6365(function( $, undefined ) { 6366 6367var lastActive, startXPos, startYPos, clickDragged, 6368 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", 6369 stateClasses = "ui-state-hover ui-state-active ", 6370 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", 6371 formResetHandler = function() { 6372 var buttons = $( this ).find( ":ui-button" ); 6373 setTimeout(function() { 6374 buttons.button( "refresh" ); 6375 }, 1 ); 6376 }, 6377 radioGroup = function( radio ) { 6378 var name = radio.name, 6379 form = radio.form, 6380 radios = $( [] ); 6381 if ( name ) { 6382 name = name.replace( /'/g, "\\'" ); 6383 if ( form ) { 6384 radios = $( form ).find( "[name='" + name + "']" ); 6385 } else { 6386 radios = $( "[name='" + name + "']", radio.ownerDocument ) 6387 .filter(function() { 6388 return !this.form; 6389 }); 6390 } 6391 } 6392 return radios; 6393 }; 6394 6395$.widget( "ui.button", { 6396 version: "1.10.0", 6397 defaultElement: "<button>", 6398 options: { 6399 disabled: null, 6400 text: true, 6401 label: null, 6402 icons: { 6403 primary: null, 6404 secondary: null 6405 } 6406 }, 6407 _create: function() { 6408 this.element.closest( "form" ) 6409 .unbind( "reset" + this.eventNamespace ) 6410 .bind( "reset" + this.eventNamespace, formResetHandler ); 6411 6412 if ( typeof this.options.disabled !== "boolean" ) { 6413 this.options.disabled = !!this.element.prop( "disabled" ); 6414 } else { 6415 this.element.prop( "disabled", this.options.disabled ); 6416 } 6417 6418 this._determineButtonType(); 6419 this.hasTitle = !!this.buttonElement.attr( "title" ); 6420 6421 var that = this, 6422 options = this.options, 6423 toggleButton = this.type === "checkbox" || this.type === "radio", 6424 activeClass = !toggleButton ? "ui-state-active" : "", 6425 focusClass = "ui-state-focus"; 6426 6427 if ( options.label === null ) { 6428 options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html()); 6429 } 6430 6431 this._hoverable( this.buttonElement ); 6432 6433 this.buttonElement 6434 .addClass( baseClasses ) 6435 .attr( "role", "button" ) 6436 .bind( "mouseenter" + this.eventNamespace, function() { 6437 if ( options.disabled ) { 6438 return; 6439 } 6440 if ( this === lastActive ) { 6441 $( this ).addClass( "ui-state-active" ); 6442 } 6443 }) 6444 .bind( "mouseleave" + this.eventNamespace, function() { 6445 if ( options.disabled ) { 6446 return; 6447 } 6448 $( this ).removeClass( activeClass ); 6449 }) 6450 .bind( "click" + this.eventNamespace, function( event ) { 6451 if ( options.disabled ) { 6452 event.preventDefault(); 6453 event.stopImmediatePropagation(); 6454 } 6455 }); 6456 6457 this.element 6458 .bind( "focus" + this.eventNamespace, function() { 6459 // no need to check disabled, focus won't be triggered anyway 6460 that.buttonElement.addClass( focusClass ); 6461 }) 6462 .bind( "blur" + this.eventNamespace, function() { 6463 that.buttonElement.removeClass( focusClass ); 6464 }); 6465 6466 if ( toggleButton ) { 6467 this.element.bind( "change" + this.eventNamespace, function() { 6468 if ( clickDragged ) { 6469 return; 6470 } 6471 that.refresh(); 6472 }); 6473 // if mouse moves between mousedown and mouseup (drag) set clickDragged flag 6474 // prevents issue where button state changes but checkbox/radio checked state 6475 // does not in Firefox (see ticket #6970) 6476 this.buttonElement 6477 .bind( "mousedown" + this.eventNamespace, function( event ) { 6478 if ( options.disabled ) { 6479 return; 6480 } 6481 clickDragged = false; 6482 startXPos = event.pageX; 6483 startYPos = event.pageY; 6484 }) 6485 .bind( "mouseup" + this.eventNamespace, function( event ) { 6486 if ( options.disabled ) { 6487 return; 6488 } 6489 if ( startXPos !== event.pageX || startYPos !== event.pageY ) { 6490 clickDragged = true; 6491 } 6492 }); 6493 } 6494 6495 if ( this.type === "checkbox" ) { 6496 this.buttonElement.bind( "click" + this.eventNamespace, function() { 6497 if ( options.disabled || clickDragged ) { 6498 return false; 6499 } 6500 }); 6501 } else if ( this.type === "radio" ) { 6502 this.buttonElement.bind( "click" + this.eventNamespace, function() { 6503 if ( options.disabled || clickDragged ) { 6504 return false; 6505 } 6506 $( this ).addClass( "ui-state-active" ); 6507 that.buttonElement.attr( "aria-pressed", "true" ); 6508 6509 var radio = that.element[ 0 ]; 6510 radioGroup( radio ) 6511 .not( radio ) 6512 .map(function() { 6513 return $( this ).button( "widget" )[ 0 ]; 6514 }) 6515 .removeClass( "ui-state-active" ) 6516 .attr( "aria-pressed", "false" ); 6517 }); 6518 } else { 6519 this.buttonElement 6520 .bind( "mousedown" + this.eventNamespace, function() { 6521 if ( options.disabled ) { 6522 return false; 6523 } 6524 $( this ).addClass( "ui-state-active" ); 6525 lastActive = this; 6526 that.document.one( "mouseup", function() { 6527 lastActive = null; 6528 }); 6529 }) 6530 .bind( "mouseup" + this.eventNamespace, function() { 6531 if ( options.disabled ) { 6532 return false; 6533 } 6534 $( this ).removeClass( "ui-state-active" ); 6535 }) 6536 .bind( "keydown" + this.eventNamespace, function(event) { 6537 if ( options.disabled ) { 6538 return false; 6539 } 6540 if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) { 6541 $( this ).addClass( "ui-state-active" ); 6542 } 6543 }) 6544 // see #8559, we bind to blur here in case the button element loses 6545 // focus between keydown and keyup, it would be left in an "active" state 6546 .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() { 6547 $( this ).removeClass( "ui-state-active" ); 6548 }); 6549 6550 if ( this.buttonElement.is("a") ) { 6551 this.buttonElement.keyup(function(event) { 6552 if ( event.keyCode === $.ui.keyCode.SPACE ) { 6553 // TODO pass through original event correctly (just as 2nd argument doesn't work) 6554 $( this ).click(); 6555 } 6556 }); 6557 } 6558 } 6559 6560 // TODO: pull out $.Widget's handling for the disabled option into 6561 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can 6562 // be overridden by individual plugins 6563 this._setOption( "disabled", options.disabled ); 6564 this._resetButton(); 6565 }, 6566 6567 _determineButtonType: function() { 6568 var ancestor, labelSelector, checked; 6569 6570 if ( this.element.is("[type=checkbox]") ) { 6571 this.type = "checkbox"; 6572 } else if ( this.element.is("[type=radio]") ) { 6573 this.type = "radio"; 6574 } else if ( this.element.is("input") ) { 6575 this.type = "input"; 6576 } else { 6577 this.type = "button"; 6578 } 6579 6580 if ( this.type === "checkbox" || this.type === "radio" ) { 6581 // we don't search against the document in case the element 6582 // is disconnected from the DOM 6583 ancestor = this.element.parents().last(); 6584 labelSelector = "label[for='" + this.element.attr("id") + "']"; 6585 this.buttonElement = ancestor.find( labelSelector ); 6586 if ( !this.buttonElement.length ) { 6587 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); 6588 this.buttonElement = ancestor.filter( labelSelector ); 6589 if ( !this.buttonElement.length ) { 6590 this.buttonElement = ancestor.find( labelSelector ); 6591 } 6592 } 6593 this.element.addClass( "ui-helper-hidden-accessible" ); 6594 6595 checked = this.element.is( ":checked" ); 6596 if ( checked ) { 6597 this.buttonElement.addClass( "ui-state-active" ); 6598 } 6599 this.buttonElement.prop( "aria-pressed", checked ); 6600 } else { 6601 this.buttonElement = this.element; 6602 } 6603 }, 6604 6605 widget: function() { 6606 return this.buttonElement; 6607 }, 6608 6609 _destroy: function() { 6610 this.element 6611 .removeClass( "ui-helper-hidden-accessible" ); 6612 this.buttonElement 6613 .removeClass( baseClasses + " " + stateClasses + " " + typeClasses ) 6614 .removeAttr( "role" ) 6615 .removeAttr( "aria-pressed" ) 6616 .html( this.buttonElement.find(".ui-button-text").html() ); 6617 6618 if ( !this.hasTitle ) { 6619 this.buttonElement.removeAttr( "title" ); 6620 } 6621 }, 6622 6623 _setOption: function( key, value ) { 6624 this._super( key, value ); 6625 if ( key === "disabled" ) { 6626 if ( value ) { 6627 this.element.prop( "disabled", true ); 6628 } else { 6629 this.element.prop( "disabled", false ); 6630 } 6631 return; 6632 } 6633 this._resetButton(); 6634 }, 6635 6636 refresh: function() { 6637 //See #8237 & #8828 6638 var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" ); 6639 6640 if ( isDisabled !== this.options.disabled ) { 6641 this._setOption( "disabled", isDisabled ); 6642 } 6643 if ( this.type === "radio" ) { 6644 radioGroup( this.element[0] ).each(function() { 6645 if ( $( this ).is( ":checked" ) ) { 6646 $( this ).button( "widget" ) 6647 .addClass( "ui-state-active" ) 6648 .attr( "aria-pressed", "true" ); 6649 } else { 6650 $( this ).button( "widget" ) 6651 .removeClass( "ui-state-active" ) 6652 .attr( "aria-pressed", "false" ); 6653 } 6654 }); 6655 } else if ( this.type === "checkbox" ) { 6656 if ( this.element.is( ":checked" ) ) { 6657 this.buttonElement 6658 .addClass( "ui-state-active" ) 6659 .attr( "aria-pressed", "true" ); 6660 } else { 6661 this.buttonElement 6662 .removeClass( "ui-state-active" ) 6663 .attr( "aria-pressed", "false" ); 6664 } 6665 } 6666 }, 6667 6668 _resetButton: function() { 6669 if ( this.type === "input" ) { 6670 if ( this.options.label ) { 6671 this.element.val( this.options.label ); 6672 } 6673 return; 6674 } 6675 var buttonElement = this.buttonElement.removeClass( typeClasses ), 6676 buttonText = $( "<span></span>", this.document[0] ) 6677 .addClass( "ui-button-text" ) 6678 .html( this.options.label ) 6679 .appendTo( buttonElement.empty() ) 6680 .text(), 6681 icons = this.options.icons, 6682 multipleIcons = icons.primary && icons.secondary, 6683 buttonClasses = []; 6684 6685 if ( icons.primary || icons.secondary ) { 6686 if ( this.options.text ) { 6687 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) ); 6688 } 6689 6690 if ( icons.primary ) { 6691 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" ); 6692 } 6693 6694 if ( icons.secondary ) { 6695 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" ); 6696 } 6697 6698 if ( !this.options.text ) { 6699 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" ); 6700 6701 if ( !this.hasTitle ) { 6702 buttonElement.attr( "title", $.trim( buttonText ) ); 6703 } 6704 } 6705 } else { 6706 buttonClasses.push( "ui-button-text-only" ); 6707 } 6708 buttonElement.addClass( buttonClasses.join( " " ) ); 6709 } 6710}); 6711 6712$.widget( "ui.buttonset", { 6713 version: "1.10.0", 6714 options: { 6715 items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)" 6716 }, 6717 6718 _create: function() { 6719 this.element.addClass( "ui-buttonset" ); 6720 }, 6721 6722 _init: function() { 6723 this.refresh(); 6724 }, 6725 6726 _setOption: function( key, value ) { 6727 if ( key === "disabled" ) { 6728 this.buttons.button( "option", key, value ); 6729 } 6730 6731 this._super( key, value ); 6732 }, 6733 6734 refresh: function() { 6735 var rtl = this.element.css( "direction" ) === "rtl"; 6736 6737 this.buttons = this.element.find( this.options.items ) 6738 .filter( ":ui-button" ) 6739 .button( "refresh" ) 6740 .end() 6741 .not( ":ui-button" ) 6742 .button() 6743 .end() 6744 .map(function() { 6745 return $( this ).button( "widget" )[ 0 ]; 6746 }) 6747 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" ) 6748 .filter( ":first" ) 6749 .addClass( rtl ? "ui-corner-right" : "ui-corner-left" ) 6750 .end() 6751 .filter( ":last" ) 6752 .addClass( rtl ? "ui-corner-left" : "ui-corner-right" ) 6753 .end() 6754 .end(); 6755 }, 6756 6757 _destroy: function() { 6758 this.element.removeClass( "ui-buttonset" ); 6759 this.buttons 6760 .map(function() { 6761 return $( this ).button( "widget" )[ 0 ]; 6762 }) 6763 .removeClass( "ui-corner-left ui-corner-right" ) 6764 .end() 6765 .button( "destroy" ); 6766 } 6767}); 6768 6769}( jQuery ) ); 6770(function( $, undefined ) { 6771 6772$.extend($.ui, { datepicker: { version: "1.10.0" } }); 6773 6774var PROP_NAME = "datepicker", 6775 dpuuid = new Date().getTime(), 6776 instActive; 6777 6778/* Date picker manager. 6779 Use the singleton instance of this class, $.datepicker, to interact with the date picker. 6780 Settings for (groups of) date pickers are maintained in an instance object, 6781 allowing multiple different settings on the same page. */ 6782 6783function Datepicker() { 6784 this._curInst = null; // The current instance in use 6785 this._keyEvent = false; // If the last event was a key event 6786 this._disabledInputs = []; // List of date picker inputs that have been disabled 6787 this._datepickerShowing = false; // True if the popup picker is showing , false if not 6788 this._inDialog = false; // True if showing within a "dialog", false if not 6789 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division 6790 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class 6791 this._appendClass = "ui-datepicker-append"; // The name of the append marker class 6792 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class 6793 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class 6794 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class 6795 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class 6796 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class 6797 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class 6798 this.regional = []; // Available regional settings, indexed by language code 6799 this.regional[""] = { // Default regional settings 6800 closeText: "Done", // Display text for close link 6801 prevText: "Prev", // Display text for previous month link 6802 nextText: "Next", // Display text for next month link 6803 currentText: "Today", // Display text for current month link 6804 monthNames: ["January","February","March","April","May","June", 6805 "July","August","September","October","November","December"], // Names of months for drop-down and formatting 6806 monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting 6807 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting 6808 dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting 6809 dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday 6810 weekHeader: "Wk", // Column header for week of the year 6811 dateFormat: "mm/dd/yy", // See format options on parseDate 6812 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... 6813 isRTL: false, // True if right-to-left language, false if left-to-right 6814 showMonthAfterYear: false, // True if the year select precedes month, false for month then year 6815 yearSuffix: "" // Additional text to append to the year in the month headers 6816 }; 6817 this._defaults = { // Global defaults for all the date picker instances 6818 showOn: "focus", // "focus" for popup on focus, 6819 // "button" for trigger button, or "both" for either
vendor: 6,360 bytes, lines 6820-6949
6820 showAnim: "fadeIn", // Name of jQuery animation for popup 6821 showOptions: {}, // Options for enhanced animations 6822 defaultDate: null, // Used when field is blank: actual date, 6823 // +/-number for offset from today, null for today 6824 appendText: "", // Display text following the input box, e.g. showing the format 6825 buttonText: "...", // Text for trigger button 6826 buttonImage: "", // URL for trigger button image 6827 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button 6828 hideIfNoPrevNext: false, // True to hide next/previous month links 6829 // if not applicable, false to just disable them 6830 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links 6831 gotoCurrent: false, // True if today link goes back to current selection instead 6832 changeMonth: false, // True if month can be selected directly, false if only prev/next 6833 changeYear: false, // True if year can be selected directly, false if only prev/next 6834 yearRange: "c-10:c+10", // Range of years to display in drop-down, 6835 // either relative to today's year (-nn:+nn), relative to currently displayed year 6836 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) 6837 showOtherMonths: false, // True to show dates in other months, false to leave blank 6838 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable 6839 showWeek: false, // True to show week of the year, false to not show it 6840 calculateWeek: this.iso8601Week, // How to calculate the week of the year, 6841 // takes a Date and returns the number of the week for it 6842 shortYearCutoff: "+10", // Short year values < this are in the current century, 6843 // > this are in the previous century, 6844 // string value starting with "+" for current year + value 6845 minDate: null, // The earliest selectable date, or null for no limit 6846 maxDate: null, // The latest selectable date, or null for no limit 6847 duration: "fast", // Duration of display/closure 6848 beforeShowDay: null, // Function that takes a date and returns an array with 6849 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "", 6850 // [2] = cell title (optional), e.g. $.datepicker.noWeekends 6851 beforeShow: null, // Function that takes an input field and 6852 // returns a set of custom settings for the date picker 6853 onSelect: null, // Define a callback function when a date is selected 6854 onChangeMonthYear: null, // Define a callback function when the month or year is changed 6855 onClose: null, // Define a callback function when the datepicker is closed 6856 numberOfMonths: 1, // Number of months to show at a time 6857 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) 6858 stepMonths: 1, // Number of months to step back/forward 6859 stepBigMonths: 12, // Number of months to step back/forward for the big links 6860 altField: "", // Selector for an alternate field to store selected dates into 6861 altFormat: "", // The date format to use for the alternate field 6862 constrainInput: true, // The input is constrained by the current date format 6863 showButtonPanel: false, // True to show button panel, false to not show it 6864 autoSize: false, // True to size the input for the date format, false to leave as is 6865 disabled: false // The initial disabled state 6866 }; 6867 $.extend(this._defaults, this.regional[""]); 6868 this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")); 6869} 6870 6871$.extend(Datepicker.prototype, { 6872 /* Class name added to elements to indicate already configured with a date picker. */ 6873 markerClassName: "hasDatepicker", 6874 6875 //Keep track of the maximum number of rows displayed (see #7043) 6876 maxRows: 4, 6877 6878 // TODO rename to "widget" when switching to widget factory 6879 _widgetDatepicker: function() { 6880 return this.dpDiv; 6881 }, 6882 6883 /* Override the default settings for all instances of the date picker. 6884 * @param settings object - the new settings to use as defaults (anonymous object) 6885 * @return the manager object 6886 */ 6887 setDefaults: function(settings) { 6888 extendRemove(this._defaults, settings || {}); 6889 return this; 6890 }, 6891 6892 /* Attach the date picker to a jQuery selection. 6893 * @param target element - the target input field or division or span 6894 * @param settings object - the new settings to use for this date picker instance (anonymous) 6895 */ 6896 _attachDatepicker: function(target, settings) { 6897 var nodeName, inline, inst; 6898 nodeName = target.nodeName.toLowerCase(); 6899 inline = (nodeName === "div" || nodeName === "span"); 6900 if (!target.id) { 6901 this.uuid += 1; 6902 target.id = "dp" + this.uuid; 6903 } 6904 inst = this._newInst($(target), inline); 6905 inst.settings = $.extend({}, settings || {}); 6906 if (nodeName === "input") { 6907 this._connectDatepicker(target, inst); 6908 } else if (inline) { 6909 this._inlineDatepicker(target, inst); 6910 } 6911 }, 6912 6913 /* Create a new instance object. */ 6914 _newInst: function(target, inline) { 6915 var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars 6916 return {id: id, input: target, // associated target 6917 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection 6918 drawMonth: 0, drawYear: 0, // month being drawn 6919 inline: inline, // is datepicker inline or not 6920 dpDiv: (!inline ? this.dpDiv : // presentation div 6921 bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))}; 6922 }, 6923 6924 /* Attach the date picker to an input field. */ 6925 _connectDatepicker: function(target, inst) { 6926 var input = $(target); 6927 inst.append = $([]); 6928 inst.trigger = $([]); 6929 if (input.hasClass(this.markerClassName)) { 6930 return; 6931 } 6932 this._attachments(input, inst); 6933 input.addClass(this.markerClassName).keydown(this._doKeyDown). 6934 keypress(this._doKeyPress).keyup(this._doKeyUp); 6935 this._autoSize(inst); 6936 $.data(target, PROP_NAME, inst); 6937 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) 6938 if( inst.settings.disabled ) { 6939 this._disableDatepicker( target ); 6940 } 6941 }, 6942 6943 /* Make attachments based on settings. */ 6944 _attachments: function(input, inst) { 6945 var showOn, buttonText, buttonImage, 6946 appendText = this._get(inst, "appendText"), 6947 isRTL = this._get(inst, "isRTL"); 6948 6949 if (inst.append) {
vendor: 5,777 bytes, lines 6950-7105
6950 inst.append.remove(); 6951 } 6952 if (appendText) { 6953 inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>"); 6954 input[isRTL ? "before" : "after"](inst.append); 6955 } 6956 6957 input.unbind("focus", this._showDatepicker); 6958 6959 if (inst.trigger) { 6960 inst.trigger.remove(); 6961 } 6962 6963 showOn = this._get(inst, "showOn"); 6964 if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field 6965 input.focus(this._showDatepicker); 6966 } 6967 if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked 6968 buttonText = this._get(inst, "buttonText"); 6969 buttonImage = this._get(inst, "buttonImage"); 6970 inst.trigger = $(this._get(inst, "buttonImageOnly") ? 6971 $("<img/>").addClass(this._triggerClass). 6972 attr({ src: buttonImage, alt: buttonText, title: buttonText }) : 6973 $("<button type='button'></button>").addClass(this._triggerClass). 6974 html(!buttonImage ? buttonText : $("<img/>").attr( 6975 { src:buttonImage, alt:buttonText, title:buttonText }))); 6976 input[isRTL ? "before" : "after"](inst.trigger); 6977 inst.trigger.click(function() { 6978 if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) { 6979 $.datepicker._hideDatepicker(); 6980 } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) { 6981 $.datepicker._hideDatepicker(); 6982 $.datepicker._showDatepicker(input[0]); 6983 } else { 6984 $.datepicker._showDatepicker(input[0]); 6985 } 6986 return false; 6987 }); 6988 } 6989 }, 6990 6991 /* Apply the maximum length for the date format. */ 6992 _autoSize: function(inst) { 6993 if (this._get(inst, "autoSize") && !inst.inline) { 6994 var findMax, max, maxI, i, 6995 date = new Date(2009, 12 - 1, 20), // Ensure double digits 6996 dateFormat = this._get(inst, "dateFormat"); 6997 6998 if (dateFormat.match(/[DM]/)) { 6999 findMax = function(names) { 7000 max = 0; 7001 maxI = 0; 7002 for (i = 0; i < names.length; i++) { 7003 if (names[i].length > max) { 7004 max = names[i].length; 7005 maxI = i; 7006 } 7007 } 7008 return maxI; 7009 }; 7010 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? 7011 "monthNames" : "monthNamesShort")))); 7012 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? 7013 "dayNames" : "dayNamesShort"))) + 20 - date.getDay()); 7014 } 7015 inst.input.attr("size", this._formatDate(inst, date).length); 7016 } 7017 }, 7018 7019 /* Attach an inline date picker to a div. */ 7020 _inlineDatepicker: function(target, inst) { 7021 var divSpan = $(target); 7022 if (divSpan.hasClass(this.markerClassName)) { 7023 return; 7024 } 7025 divSpan.addClass(this.markerClassName).append(inst.dpDiv); 7026 $.data(target, PROP_NAME, inst); 7027 this._setDate(inst, this._getDefaultDate(inst), true); 7028 this._updateDatepicker(inst); 7029 this._updateAlternate(inst); 7030 //If disabled option is true, disable the datepicker before showing it (see ticket #5665) 7031 if( inst.settings.disabled ) { 7032 this._disableDatepicker( target ); 7033 } 7034 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements 7035 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height 7036 inst.dpDiv.css( "display", "block" ); 7037 }, 7038 7039 /* Pop-up the date picker in a "dialog" box. 7040 * @param input element - ignored 7041 * @param date string or Date - the initial date to display 7042 * @param onSelect function - the function to call when a date is selected 7043 * @param settings object - update the dialog date picker instance's settings (anonymous object) 7044 * @param pos int[2] - coordinates for the dialog's position within the screen or 7045 * event - with x/y coordinates or 7046 * leave empty for default (screen centre) 7047 * @return the manager object 7048 */ 7049 _dialogDatepicker: function(input, date, onSelect, settings, pos) { 7050 var id, browserWidth, browserHeight, scrollX, scrollY, 7051 inst = this._dialogInst; // internal instance 7052 7053 if (!inst) { 7054 this.uuid += 1; 7055 id = "dp" + this.uuid; 7056 this._dialogInput = $("<input type='text' id='" + id + 7057 "' style='position: absolute; top: -100px; width: 0px;'/>"); 7058 this._dialogInput.keydown(this._doKeyDown); 7059 $("body").append(this._dialogInput); 7060 inst = this._dialogInst = this._newInst(this._dialogInput, false); 7061 inst.settings = {}; 7062 $.data(this._dialogInput[0], PROP_NAME, inst); 7063 } 7064 extendRemove(inst.settings, settings || {}); 7065 date = (date && date.constructor === Date ? this._formatDate(inst, date) : date); 7066 this._dialogInput.val(date); 7067 7068 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); 7069 if (!this._pos) { 7070 browserWidth = document.documentElement.clientWidth; 7071 browserHeight = document.documentElement.clientHeight; 7072 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; 7073 scrollY = document.documentElement.scrollTop || document.body.scrollTop; 7074 this._pos = // should use actual width/height below 7075 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; 7076 } 7077 7078 // move input on screen for focus, but hidden behind dialog 7079 this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px"); 7080 inst.settings.onSelect = onSelect; 7081 this._inDialog = true; 7082 this.dpDiv.addClass(this._dialogClass); 7083 this._showDatepicker(this._dialogInput[0]); 7084 if ($.blockUI) { 7085 $.blockUI(this.dpDiv); 7086 } 7087 $.data(this._dialogInput[0], PROP_NAME, inst); 7088 return this; 7089 }, 7090 7091 /* Detach a datepicker from its control. 7092 * @param target element - the target input field or division or span 7093 */ 7094 _destroyDatepicker: function(target) { 7095 var nodeName, 7096 $target = $(target), 7097 inst = $.data(target, PROP_NAME); 7098 7099 if (!$target.hasClass(this.markerClassName)) { 7100 return; 7101 } 7102 7103 nodeName = target.nodeName.toLowerCase(); 7104 $.removeData(target, PROP_NAME); 7105 if (nodeName === "input") {
vendor: 4,434 bytes, lines 7106-7238
7106 inst.append.remove(); 7107 inst.trigger.remove(); 7108 $target.removeClass(this.markerClassName). 7109 unbind("focus", this._showDatepicker). 7110 unbind("keydown", this._doKeyDown). 7111 unbind("keypress", this._doKeyPress). 7112 unbind("keyup", this._doKeyUp); 7113 } else if (nodeName === "div" || nodeName === "span") { 7114 $target.removeClass(this.markerClassName).empty(); 7115 } 7116 }, 7117 7118 /* Enable the date picker to a jQuery selection. 7119 * @param target element - the target input field or division or span 7120 */ 7121 _enableDatepicker: function(target) { 7122 var nodeName, inline, 7123 $target = $(target), 7124 inst = $.data(target, PROP_NAME); 7125 7126 if (!$target.hasClass(this.markerClassName)) { 7127 return; 7128 } 7129 7130 nodeName = target.nodeName.toLowerCase(); 7131 if (nodeName === "input") { 7132 target.disabled = false; 7133 inst.trigger.filter("button"). 7134 each(function() { this.disabled = false; }).end(). 7135 filter("img").css({opacity: "1.0", cursor: ""}); 7136 } else if (nodeName === "div" || nodeName === "span") { 7137 inline = $target.children("." + this._inlineClass); 7138 inline.children().removeClass("ui-state-disabled"); 7139 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 7140 prop("disabled", false); 7141 } 7142 this._disabledInputs = $.map(this._disabledInputs, 7143 function(value) { return (value === target ? null : value); }); // delete entry 7144 }, 7145 7146 /* Disable the date picker to a jQuery selection. 7147 * @param target element - the target input field or division or span 7148 */ 7149 _disableDatepicker: function(target) { 7150 var nodeName, inline, 7151 $target = $(target), 7152 inst = $.data(target, PROP_NAME); 7153 7154 if (!$target.hasClass(this.markerClassName)) { 7155 return; 7156 } 7157 7158 nodeName = target.nodeName.toLowerCase(); 7159 if (nodeName === "input") { 7160 target.disabled = true; 7161 inst.trigger.filter("button"). 7162 each(function() { this.disabled = true; }).end(). 7163 filter("img").css({opacity: "0.5", cursor: "default"}); 7164 } else if (nodeName === "div" || nodeName === "span") { 7165 inline = $target.children("." + this._inlineClass); 7166 inline.children().addClass("ui-state-disabled"); 7167 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 7168 prop("disabled", true); 7169 } 7170 this._disabledInputs = $.map(this._disabledInputs, 7171 function(value) { return (value === target ? null : value); }); // delete entry 7172 this._disabledInputs[this._disabledInputs.length] = target; 7173 }, 7174 7175 /* Is the first field in a jQuery collection disabled as a datepicker? 7176 * @param target element - the target input field or division or span 7177 * @return boolean - true if disabled, false if enabled 7178 */ 7179 _isDisabledDatepicker: function(target) { 7180 if (!target) { 7181 return false; 7182 } 7183 for (var i = 0; i < this._disabledInputs.length; i++) { 7184 if (this._disabledInputs[i] === target) { 7185 return true; 7186 } 7187 } 7188 return false; 7189 }, 7190 7191 /* Retrieve the instance data for the target control. 7192 * @param target element - the target input field or division or span 7193 * @return object - the associated instance data 7194 * @throws error if a jQuery problem getting data 7195 */ 7196 _getInst: function(target) { 7197 try { 7198 return $.data(target, PROP_NAME); 7199 } 7200 catch (err) { 7201 throw "Missing instance data for this datepicker"; 7202 } 7203 }, 7204 7205 /* Update or retrieve the settings for a date picker attached to an input field or division. 7206 * @param target element - the target input field or division or span 7207 * @param name object - the new settings to update or 7208 * string - the name of the setting to change or retrieve, 7209 * when retrieving also "all" for all instance settings or 7210 * "defaults" for all global defaults 7211 * @param value any - the new value for the setting 7212 * (omit if above is an object or to retrieve a value) 7213 */ 7214 _optionDatepicker: function(target, name, value) { 7215 var settings, date, minDate, maxDate, 7216 inst = this._getInst(target); 7217 7218 if (arguments.length === 2 && typeof name === "string") { 7219 return (name === "defaults" ? $.extend({}, $.datepicker._defaults) : 7220 (inst ? (name === "all" ? $.extend({}, inst.settings) : 7221 this._get(inst, name)) : null)); 7222 } 7223 7224 settings = name || {}; 7225 if (typeof name === "string") { 7226 settings = {}; 7227 settings[name] = value; 7228 } 7229 7230 if (inst) { 7231 if (this._curInst === inst) { 7232 this._hideDatepicker(); 7233 } 7234 7235 date = this._getDateDatepicker(target, true); 7236 minDate = this._getMinMaxDate(inst, "min"); 7237 maxDate = this._getMinMaxDate(inst, "max"); 7238
vendor: 7,816 bytes, lines 7238-7466
7238extendRemove(inst.settings, settings); 7239 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided 7240 if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) { 7241 inst.settings.minDate = this._formatDate(inst, minDate); 7242 } 7243 if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) { 7244 inst.settings.maxDate = this._formatDate(inst, maxDate); 7245 } 7246 if ( "disabled" in settings ) { 7247 if ( settings.disabled ) { 7248 this._disableDatepicker(target); 7249 } else { 7250 this._enableDatepicker(target); 7251 } 7252 } 7253 this._attachments($(target), inst); 7254 this._autoSize(inst); 7255 this._setDate(inst, date); 7256 this._updateAlternate(inst); 7257 this._updateDatepicker(inst); 7258 } 7259 }, 7260 7261 // change method deprecated 7262 _changeDatepicker: function(target, name, value) { 7263 this._optionDatepicker(target, name, value); 7264 }, 7265 7266 /* Redraw the date picker attached to an input field or division. 7267 * @param target element - the target input field or division or span 7268 */ 7269 _refreshDatepicker: function(target) { 7270 var inst = this._getInst(target); 7271 if (inst) { 7272 this._updateDatepicker(inst); 7273 } 7274 }, 7275 7276 /* Set the dates for a jQuery selection. 7277 * @param target element - the target input field or division or span 7278 * @param date Date - the new date 7279 */ 7280 _setDateDatepicker: function(target, date) { 7281 var inst = this._getInst(target); 7282 if (inst) { 7283 this._setDate(inst, date); 7284 this._updateDatepicker(inst); 7285 this._updateAlternate(inst); 7286 } 7287 }, 7288 7289 /* Get the date(s) for the first entry in a jQuery selection. 7290 * @param target element - the target input field or division or span 7291 * @param noDefault boolean - true if no default date is to be used 7292 * @return Date - the current date 7293 */ 7294 _getDateDatepicker: function(target, noDefault) { 7295 var inst = this._getInst(target); 7296 if (inst && !inst.inline) { 7297 this._setDateFromField(inst, noDefault); 7298 } 7299 return (inst ? this._getDate(inst) : null); 7300 }, 7301 7302 /* Handle keystrokes. */ 7303 _doKeyDown: function(event) { 7304 var onSelect, dateStr, sel, 7305 inst = $.datepicker._getInst(event.target), 7306 handled = true, 7307 isRTL = inst.dpDiv.is(".ui-datepicker-rtl"); 7308 7309 inst._keyEvent = true; 7310 if ($.datepicker._datepickerShowing) { 7311 switch (event.keyCode) { 7312 case 9: $.datepicker._hideDatepicker(); 7313 handled = false; 7314 break; // hide on tab out 7315 case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." + 7316 $.datepicker._currentClass + ")", inst.dpDiv); 7317 if (sel[0]) { 7318 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); 7319 } 7320 7321 onSelect = $.datepicker._get(inst, "onSelect"); 7322 if (onSelect) { 7323 dateStr = $.datepicker._formatDate(inst); 7324 7325 // trigger custom callback 7326 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); 7327 } else { 7328 $.datepicker._hideDatepicker(); 7329 } 7330 7331 return false; // don't submit the form 7332 case 27: $.datepicker._hideDatepicker(); 7333 break; // hide on escape 7334 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7335 -$.datepicker._get(inst, "stepBigMonths") : 7336 -$.datepicker._get(inst, "stepMonths")), "M"); 7337 break; // previous month/year on page up/+ ctrl 7338 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7339 +$.datepicker._get(inst, "stepBigMonths") : 7340 +$.datepicker._get(inst, "stepMonths")), "M"); 7341 break; // next month/year on page down/+ ctrl 7342 case 35: if (event.ctrlKey || event.metaKey) { 7343 $.datepicker._clearDate(event.target); 7344 } 7345 handled = event.ctrlKey || event.metaKey; 7346 break; // clear on ctrl or command +end 7347 case 36: if (event.ctrlKey || event.metaKey) { 7348 $.datepicker._gotoToday(event.target); 7349 } 7350 handled = event.ctrlKey || event.metaKey; 7351 break; // current on ctrl or command +home 7352 case 37: if (event.ctrlKey || event.metaKey) { 7353 $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D"); 7354 } 7355 handled = event.ctrlKey || event.metaKey; 7356 // -1 day on ctrl or command +left 7357 if (event.originalEvent.altKey) { 7358 $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7359 -$.datepicker._get(inst, "stepBigMonths") : 7360 -$.datepicker._get(inst, "stepMonths")), "M"); 7361 } 7362 // next month/year on alt +left on Mac 7363 break; 7364 case 38: if (event.ctrlKey || event.metaKey) { 7365 $.datepicker._adjustDate(event.target, -7, "D"); 7366 } 7367 handled = event.ctrlKey || event.metaKey; 7368 break; // -1 week on ctrl or command +up 7369 case 39: if (event.ctrlKey || event.metaKey) { 7370 $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D"); 7371 } 7372 handled = event.ctrlKey || event.metaKey; 7373 // +1 day on ctrl or command +right 7374 if (event.originalEvent.altKey) { 7375 $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7376 +$.datepicker._get(inst, "stepBigMonths") : 7377 +$.datepicker._get(inst, "stepMonths")), "M"); 7378 } 7379 // next month/year on alt +right 7380 break; 7381 case 40: if (event.ctrlKey || event.metaKey) { 7382 $.datepicker._adjustDate(event.target, +7, "D"); 7383 } 7384 handled = event.ctrlKey || event.metaKey; 7385 break; // +1 week on ctrl or command +down 7386 default: handled = false; 7387 } 7388 } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home 7389 $.datepicker._showDatepicker(this); 7390 } else { 7391 handled = false; 7392 } 7393 7394 if (handled) { 7395 event.preventDefault(); 7396 event.stopPropagation(); 7397 } 7398 }, 7399 7400 /* Filter entered characters - based on date format. */ 7401 _doKeyPress: function(event) { 7402 var chars, chr, 7403 inst = $.datepicker._getInst(event.target); 7404 7405 if ($.datepicker._get(inst, "constrainInput")) { 7406 chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat")); 7407 chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode); 7408 return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1); 7409 } 7410 }, 7411 7412 /* Synchronise manual entry and field/alternate field. */ 7413 _doKeyUp: function(event) { 7414 var date, 7415 inst = $.datepicker._getInst(event.target); 7416 7417 if (inst.input.val() !== inst.lastVal) { 7418 try { 7419 date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), 7420 (inst.input ? inst.input.val() : null), 7421 $.datepicker._getFormatConfig(inst)); 7422 7423 if (date) { // only if valid 7424 $.datepicker._setDateFromField(inst); 7425 $.datepicker._updateAlternate(inst); 7426 $.datepicker._updateDatepicker(inst); 7427 } 7428 } 7429 catch (err) { 7430 } 7431 } 7432 return true; 7433 }, 7434 7435 /* Pop-up the date picker for a given input field. 7436 * If false returned from beforeShow event handler do not show. 7437 * @param input element - the input field attached to the date picker or 7438 * event - if triggered by focus 7439 */ 7440 _showDatepicker: function(input) { 7441 input = input.target || input; 7442 if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger 7443 input = $("input", input.parentNode)[0]; 7444 } 7445 7446 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here 7447 return; 7448 } 7449 7450 var inst, beforeShow, beforeShowSettings, isFixed, 7451 offset, showAnim, duration; 7452 7453 inst = $.datepicker._getInst(input); 7454 if ($.datepicker._curInst && $.datepicker._curInst !== inst) { 7455 $.datepicker._curInst.dpDiv.stop(true, true); 7456 if ( inst && $.datepicker._datepickerShowing ) { 7457 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] ); 7458 } 7459 } 7460 7461 beforeShow = $.datepicker._get(inst, "beforeShow"); 7462 beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; 7463 if(beforeShowSettings === false){ 7464 return; 7465 } 7466
vendor: 5,662 bytes, lines 7466-7616
7466extendRemove(inst.settings, beforeShowSettings); 7467 7468 inst.lastVal = null; 7469 $.datepicker._lastInput = input; 7470 $.datepicker._setDateFromField(inst); 7471 7472 if ($.datepicker._inDialog) { // hide cursor 7473 input.value = ""; 7474 } 7475 if (!$.datepicker._pos) { // position below input 7476 $.datepicker._pos = $.datepicker._findPos(input); 7477 $.datepicker._pos[1] += input.offsetHeight; // add the height 7478 } 7479 7480 isFixed = false; 7481 $(input).parents().each(function() { 7482 isFixed |= $(this).css("position") === "fixed"; 7483 return !isFixed; 7484 }); 7485 7486 offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; 7487 $.datepicker._pos = null; 7488 //to avoid flashes on Firefox 7489 inst.dpDiv.empty(); 7490 // determine sizing offscreen 7491 inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"}); 7492 $.datepicker._updateDatepicker(inst); 7493 // fix width for dynamic number of date pickers 7494 // and adjust position before showing 7495 offset = $.datepicker._checkOffset(inst, offset, isFixed); 7496 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? 7497 "static" : (isFixed ? "fixed" : "absolute")), display: "none", 7498 left: offset.left + "px", top: offset.top + "px"}); 7499 7500 if (!inst.inline) { 7501 showAnim = $.datepicker._get(inst, "showAnim"); 7502 duration = $.datepicker._get(inst, "duration"); 7503 inst.dpDiv.zIndex($(input).zIndex()+1); 7504 $.datepicker._datepickerShowing = true; 7505 7506 if ( $.effects && $.effects.effect[ showAnim ] ) { 7507 inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration); 7508 } else { 7509 inst.dpDiv[showAnim || "show"](showAnim ? duration : null); 7510 } 7511 7512 if (inst.input.is(":visible") && !inst.input.is(":disabled")) { 7513 inst.input.focus(); 7514 } 7515 $.datepicker._curInst = inst; 7516 } 7517 }, 7518 7519 /* Generate the date picker content. */ 7520 _updateDatepicker: function(inst) { 7521 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) 7522 instActive = inst; // for delegate hover events 7523 inst.dpDiv.empty().append(this._generateHTML(inst)); 7524 this._attachHandlers(inst); 7525 inst.dpDiv.find("." + this._dayOverClass + " a").mouseover(); 7526 7527 var origyearshtml, 7528 numMonths = this._getNumberOfMonths(inst), 7529 cols = numMonths[1], 7530 width = 17; 7531 7532 inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""); 7533 if (cols > 1) { 7534 inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em"); 7535 } 7536 inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") + 7537 "Class"]("ui-datepicker-multi"); 7538 inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") + 7539 "Class"]("ui-datepicker-rtl"); 7540 7541 // #6694 - don't focus the input if it's already focused 7542 // this breaks the change event in IE 7543 if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input && 7544 inst.input.is(":visible") && !inst.input.is(":disabled") && inst.input[0] !== document.activeElement) { 7545 inst.input.focus(); 7546 } 7547 7548 // deffered render of the years select (to avoid flashes on Firefox) 7549 if( inst.yearshtml ){ 7550 origyearshtml = inst.yearshtml; 7551 setTimeout(function(){ 7552 //assure that inst.yearshtml didn't change. 7553 if( origyearshtml === inst.yearshtml && inst.yearshtml ){ 7554 inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml); 7555 } 7556 origyearshtml = inst.yearshtml = null; 7557 }, 0); 7558 } 7559 }, 7560 7561 /* Retrieve the size of left and top borders for an element. 7562 * @param elem (jQuery object) the element of interest 7563 * @return (number[2]) the left and top borders 7564 */ 7565 _getBorders: function(elem) { 7566 var convert = function(value) { 7567 return {thin: 1, medium: 2, thick: 3}[value] || value; 7568 }; 7569 return [parseFloat(convert(elem.css("border-left-width"))), 7570 parseFloat(convert(elem.css("border-top-width")))]; 7571 }, 7572 7573 /* Check positioning to remain on screen. */ 7574 _checkOffset: function(inst, offset, isFixed) { 7575 var dpWidth = inst.dpDiv.outerWidth(), 7576 dpHeight = inst.dpDiv.outerHeight(), 7577 inputWidth = inst.input ? inst.input.outerWidth() : 0, 7578 inputHeight = inst.input ? inst.input.outerHeight() : 0, 7579 viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()), 7580 viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop()); 7581 7582 offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0); 7583 offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0; 7584 offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; 7585 7586 // now check if datepicker is showing outside window viewport - move to a better place if so. 7587 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? 7588 Math.abs(offset.left + dpWidth - viewWidth) : 0); 7589 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? 7590 Math.abs(dpHeight + inputHeight) : 0); 7591 7592 return offset; 7593 }, 7594 7595 /* Find an object's position on the screen. */ 7596 _findPos: function(obj) { 7597 var position, 7598 inst = this._getInst(obj), 7599 isRTL = this._get(inst, "isRTL"); 7600 7601 while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) { 7602 obj = obj[isRTL ? "previousSibling" : "nextSibling"]; 7603 } 7604 7605 position = $(obj).offset(); 7606 return [position.left, position.top]; 7607 }, 7608 7609 /* Hide the date picker from view. 7610 * @param input element - the input field attached to the date picker 7611 */ 7612 _hideDatepicker: function(input) { 7613 var showAnim, duration, postProcess, onClose, 7614 inst = this._curInst; 7615 7616 if (!inst || (input && inst !== $.data(input, PROP_NAME
vendor: 8,428 bytes, lines 7616-7872
7616))) { 7617 return; 7618 } 7619 7620 if (this._datepickerShowing) { 7621 showAnim = this._get(inst, "showAnim"); 7622 duration = this._get(inst, "duration"); 7623 postProcess = function() { 7624 $.datepicker._tidyDialog(inst); 7625 }; 7626 7627 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed 7628 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) { 7629 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess); 7630 } else { 7631 inst.dpDiv[(showAnim === "slideDown" ? "slideUp" : 7632 (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess); 7633 } 7634 7635 if (!showAnim) { 7636 postProcess(); 7637 } 7638 this._datepickerShowing = false; 7639 7640 onClose = this._get(inst, "onClose"); 7641 if (onClose) { 7642 onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]); 7643 } 7644 7645 this._lastInput = null; 7646 if (this._inDialog) { 7647 this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" }); 7648 if ($.blockUI) { 7649 $.unblockUI(); 7650 $("body").append(this.dpDiv); 7651 } 7652 } 7653 this._inDialog = false; 7654 } 7655 }, 7656 7657 /* Tidy up after a dialog display. */ 7658 _tidyDialog: function(inst) { 7659 inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar"); 7660 }, 7661 7662 /* Close date picker if clicked elsewhere. */ 7663 _checkExternalClick: function(event) { 7664 if (!$.datepicker._curInst) { 7665 return; 7666 } 7667 7668 var $target = $(event.target), 7669 inst = $.datepicker._getInst($target[0]); 7670 7671 if ( ( ( $target[0].id !== $.datepicker._mainDivId && 7672 $target.parents("#" + $.datepicker._mainDivId).length === 0 && 7673 !$target.hasClass($.datepicker.markerClassName) && 7674 !$target.closest("." + $.datepicker._triggerClass).length && 7675 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) || 7676 ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) { 7677 $.datepicker._hideDatepicker(); 7678 } 7679 }, 7680 7681 /* Adjust one of the date sub-fields. */ 7682 _adjustDate: function(id, offset, period) { 7683 var target = $(id), 7684 inst = this._getInst(target[0]); 7685 7686 if (this._isDisabledDatepicker(target[0])) { 7687 return; 7688 } 7689 this._adjustInstDate(inst, offset + 7690 (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning 7691 period); 7692 this._updateDatepicker(inst); 7693 }, 7694 7695 /* Action for current link. */ 7696 _gotoToday: function(id) { 7697 var date, 7698 target = $(id), 7699 inst = this._getInst(target[0]); 7700 7701 if (this._get(inst, "gotoCurrent") && inst.currentDay) { 7702 inst.selectedDay = inst.currentDay; 7703 inst.drawMonth = inst.selectedMonth = inst.currentMonth; 7704 inst.drawYear = inst.selectedYear = inst.currentYear; 7705 } else { 7706 date = new Date(); 7707 inst.selectedDay = date.getDate(); 7708 inst.drawMonth = inst.selectedMonth = date.getMonth(); 7709 inst.drawYear = inst.selectedYear = date.getFullYear(); 7710 } 7711 this._notifyChange(inst); 7712 this._adjustDate(target); 7713 }, 7714 7715 /* Action for selecting a new month/year. */ 7716 _selectMonthYear: function(id, select, period) { 7717 var target = $(id), 7718 inst = this._getInst(target[0]); 7719 7720 inst["selected" + (period === "M" ? "Month" : "Year")] = 7721 inst["draw" + (period === "M" ? "Month" : "Year")] = 7722 parseInt(select.options[select.selectedIndex].value,10); 7723 7724 this._notifyChange(inst); 7725 this._adjustDate(target); 7726 }, 7727 7728 /* Action for selecting a day. */ 7729 _selectDay: function(id, month, year, td) { 7730 var inst, 7731 target = $(id); 7732 7733 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { 7734 return; 7735 } 7736 7737 inst = this._getInst(target[0]); 7738 inst.selectedDay = inst.currentDay = $("a", td).html(); 7739 inst.selectedMonth = inst.currentMonth = month; 7740 inst.selectedYear = inst.currentYear = year; 7741 this._selectDate(id, this._formatDate(inst, 7742 inst.currentDay, inst.currentMonth, inst.currentYear)); 7743 }, 7744 7745 /* Erase the input field and hide the date picker. */ 7746 _clearDate: function(id) { 7747 var target = $(id); 7748 this._selectDate(target, ""); 7749 }, 7750 7751 /* Update the input field with the selected date. */ 7752 _selectDate: function(id, dateStr) { 7753 var onSelect, 7754 target = $(id), 7755 inst = this._getInst(target[0]); 7756 7757 dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); 7758 if (inst.input) { 7759 inst.input.val(dateStr); 7760 } 7761 this._updateAlternate(inst); 7762 7763 onSelect = this._get(inst, "onSelect"); 7764 if (onSelect) { 7765 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback 7766 } else if (inst.input) { 7767 inst.input.trigger("change"); // fire the change event 7768 } 7769 7770 if (inst.inline){ 7771 this._updateDatepicker(inst); 7772 } else { 7773 this._hideDatepicker(); 7774 this._lastInput = inst.input[0]; 7775 if (typeof(inst.input[0]) !== "object") { 7776 inst.input.focus(); // restore focus 7777 } 7778 this._lastInput = null; 7779 } 7780 }, 7781 7782 /* Update any alternate field to synchronise with the main field. */ 7783 _updateAlternate: function(inst) { 7784 var altFormat, date, dateStr, 7785 altField = this._get(inst, "altField"); 7786 7787 if (altField) { // update alternate field too 7788 altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat"); 7789 date = this._getDate(inst); 7790 dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); 7791 $(altField).each(function() { $(this).val(dateStr); }); 7792 } 7793 }, 7794 7795 /* Set as beforeShowDay function to prevent selection of weekends. 7796 * @param date Date - the date to customise 7797 * @return [boolean, string] - is this date selectable?, what is its CSS class? 7798 */ 7799 noWeekends: function(date) { 7800 var day = date.getDay(); 7801 return [(day > 0 && day < 6), ""]; 7802 }, 7803 7804 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. 7805 * @param date Date - the date to get the week for 7806 * @return number - the number of the week within the year that contains this date 7807 */ 7808 iso8601Week: function(date) { 7809 var time, 7810 checkDate = new Date(date.getTime()); 7811 7812 // Find Thursday of this week starting on Monday 7813 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); 7814 7815 time = checkDate.getTime(); 7816 checkDate.setMonth(0); // Compare with Jan 1 7817 checkDate.setDate(1); 7818 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; 7819 }, 7820 7821 /* Parse a string value into a date object. 7822 * See formatDate below for the possible formats. 7823 * 7824 * @param format string - the expected format of the date 7825 * @param value string - the date in the above format 7826 * @param settings Object - attributes include: 7827 * shortYearCutoff number - the cutoff year for determining the century (optional) 7828 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 7829 * dayNames string[7] - names of the days from Sunday (optional) 7830 * monthNamesShort string[12] - abbreviated names of the months (optional) 7831 * monthNames string[12] - names of the months (optional) 7832 * @return Date - the extracted date value or null if value is blank 7833 */ 7834 parseDate: function (format, value, settings) { 7835 if (format == null || value == null) { 7836 throw "Invalid arguments"; 7837 } 7838 7839 value = (typeof value === "object" ? value.toString() : value + ""); 7840 if (value === "") { 7841 return null; 7842 } 7843 7844 var iFormat, dim, extra, 7845 iValue = 0, 7846 shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff, 7847 shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp : 7848 new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)), 7849 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, 7850 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, 7851 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, 7852 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, 7853 year = -1, 7854 month = -1, 7855 day = -1, 7856 doy = -1, 7857 literal = false, 7858 date, 7859 // Check whether a format character is doubled 7860 lookAhead = function(match) { 7861 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 7862 if (matches) { 7863 iFormat++; 7864 } 7865 return matches; 7866 }, 7867 // Extract a number from the string value 7868 getNumber = function(match) { 7869 var isDoubled = lookAhead(match), 7870 size = (match === "@" ? 14 : (match === "!" ? 20 : 7871 (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))), 7872
7872digits = new RegExp("^\\d{1
vendor: 13,244 bytes, lines 7872-8317
7872," + size + "}"), 7873 num = value.substring(iValue).match(digits); 7874 if (!num) { 7875 throw "Missing number at position " + iValue; 7876 } 7877 iValue += num[0].length; 7878 return parseInt(num[0], 10); 7879 }, 7880 // Extract a name from the string value and convert to an index 7881 getName = function(match, shortNames, longNames) { 7882 var index = -1, 7883 names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { 7884 return [ [k, v] ]; 7885 }).sort(function (a, b) { 7886 return -(a[1].length - b[1].length); 7887 }); 7888 7889 $.each(names, function (i, pair) { 7890 var name = pair[1]; 7891 if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) { 7892 index = pair[0]; 7893 iValue += name.length; 7894 return false; 7895 } 7896 }); 7897 if (index !== -1) { 7898 return index + 1; 7899 } else { 7900 throw "Unknown name at position " + iValue; 7901 } 7902 }, 7903 // Confirm that a literal character matches the string value 7904 checkLiteral = function() { 7905 if (value.charAt(iValue) !== format.charAt(iFormat)) { 7906 throw "Unexpected literal at position " + iValue; 7907 } 7908 iValue++; 7909 }; 7910 7911 for (iFormat = 0; iFormat < format.length; iFormat++) { 7912 if (literal) { 7913 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 7914 literal = false; 7915 } else { 7916 checkLiteral(); 7917 } 7918 } else { 7919 switch (format.charAt(iFormat)) { 7920 case "d": 7921 day = getNumber("d"); 7922 break; 7923 case "D": 7924 getName("D", dayNamesShort, dayNames); 7925 break; 7926 case "o": 7927 doy = getNumber("o"); 7928 break; 7929 case "m": 7930 month = getNumber("m"); 7931 break; 7932 case "M": 7933 month = getName("M", monthNamesShort, monthNames); 7934 break; 7935 case "y": 7936 year = getNumber("y"); 7937 break; 7938 case "@": 7939 date = new Date(getNumber("@")); 7940 year = date.getFullYear(); 7941 month = date.getMonth() + 1; 7942 day = date.getDate(); 7943 break; 7944 case "!": 7945 date = new Date((getNumber("!") - this._ticksTo1970) / 10000); 7946 year = date.getFullYear(); 7947 month = date.getMonth() + 1; 7948 day = date.getDate(); 7949 break; 7950 case "'": 7951 if (lookAhead("'")){ 7952 checkLiteral(); 7953 } else { 7954 literal = true; 7955 } 7956 break; 7957 default: 7958 checkLiteral(); 7959 } 7960 } 7961 } 7962 7963 if (iValue < value.length){ 7964 extra = value.substr(iValue); 7965 if (!/^\s+/.test(extra)) { 7966 throw "Extra/unparsed characters found in date: " + extra; 7967 } 7968 } 7969 7970 if (year === -1) { 7971 year = new Date().getFullYear(); 7972 } else if (year < 100) { 7973 year += new Date().getFullYear() - new Date().getFullYear() % 100 + 7974 (year <= shortYearCutoff ? 0 : -100); 7975 } 7976 7977 if (doy > -1) { 7978 month = 1; 7979 day = doy; 7980 do { 7981 dim = this._getDaysInMonth(year, month - 1); 7982 if (day <= dim) { 7983 break; 7984 } 7985 month++; 7986 day -= dim; 7987 } while (true); 7988 } 7989 7990 date = this._daylightSavingAdjust(new Date(year, month - 1, day)); 7991 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) { 7992 throw "Invalid date"; // E.g. 31/02/00 7993 } 7994 return date; 7995 }, 7996 7997 /* Standard date formats. */ 7998 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601) 7999 COOKIE: "D, dd M yy", 8000 ISO_8601: "yy-mm-dd", 8001 RFC_822: "D, d M y", 8002 RFC_850: "DD, dd-M-y", 8003 RFC_1036: "D, d M y", 8004 RFC_1123: "D, d M yy", 8005 RFC_2822: "D, d M yy", 8006 RSS: "D, d M y", // RFC 822 8007 TICKS: "!", 8008 TIMESTAMP: "@", 8009 W3C: "yy-mm-dd", // ISO 8601 8010 8011 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + 8012 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), 8013 8014 /* Format a date object into a string value. 8015 * The format can be combinations of the following: 8016 * d - day of month (no leading zero) 8017 * dd - day of month (two digit) 8018 * o - day of year (no leading zeros) 8019 * oo - day of year (three digit) 8020 * D - day name short 8021 * DD - day name long 8022 * m - month of year (no leading zero) 8023 * mm - month of year (two digit) 8024 * M - month name short 8025 * MM - month name long 8026 * y - year (two digit) 8027 * yy - year (four digit) 8028 * @ - Unix timestamp (ms since 01/01/1970) 8029 * ! - Windows ticks (100ns since 01/01/0001) 8030 * "..." - literal text 8031 * '' - single quote 8032 * 8033 * @param format string - the desired format of the date 8034 * @param date Date - the date value to format 8035 * @param settings Object - attributes include: 8036 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 8037 * dayNames string[7] - names of the days from Sunday (optional) 8038 * monthNamesShort string[12] - abbreviated names of the months (optional) 8039 * monthNames string[12] - names of the months (optional) 8040 * @return string - the date in the above format 8041 */ 8042 formatDate: function (format, date, settings) { 8043 if (!date) { 8044 return ""; 8045 } 8046 8047 var iFormat, 8048 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, 8049 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, 8050 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, 8051 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, 8052 // Check whether a format character is doubled 8053 lookAhead = function(match) { 8054 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 8055 if (matches) { 8056 iFormat++; 8057 } 8058 return matches; 8059 }, 8060 // Format a number, with leading zero if necessary 8061 formatNumber = function(match, value, len) { 8062 var num = "" + value; 8063 if (lookAhead(match)) { 8064 while (num.length < len) { 8065 num = "0" + num; 8066 } 8067 } 8068 return num; 8069 }, 8070 // Format a name, short or long as requested 8071 formatName = function(match, value, shortNames, longNames) { 8072 return (lookAhead(match) ? longNames[value] : shortNames[value]); 8073 }, 8074 output = "", 8075 literal = false; 8076 8077 if (date) { 8078 for (iFormat = 0; iFormat < format.length; iFormat++) { 8079 if (literal) { 8080 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 8081 literal = false; 8082 } else { 8083 output += format.charAt(iFormat); 8084 } 8085 } else { 8086 switch (format.charAt(iFormat)) { 8087 case "d": 8088 output += formatNumber("d", date.getDate(), 2); 8089 break; 8090 case "D": 8091 output += formatName("D", date.getDay(), dayNamesShort, dayNames); 8092 break; 8093 case "o": 8094 output += formatNumber("o", 8095 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); 8096 break; 8097 case "m": 8098 output += formatNumber("m", date.getMonth() + 1, 2); 8099 break; 8100 case "M": 8101 output += formatName("M", date.getMonth(), monthNamesShort, monthNames); 8102 break; 8103 case "y": 8104 output += (lookAhead("y") ? date.getFullYear() : 8105 (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100); 8106 break; 8107 case "@": 8108 output += date.getTime(); 8109 break; 8110 case "!": 8111 output += date.getTime() * 10000 + this._ticksTo1970; 8112 break; 8113 case "'": 8114 if (lookAhead("'")) { 8115 output += "'"; 8116 } else { 8117 literal = true; 8118 } 8119 break; 8120 default: 8121 output += format.charAt(iFormat); 8122 } 8123 } 8124 } 8125 } 8126 return output; 8127 }, 8128 8129 /* Extract all possible characters from the date format. */ 8130 _possibleChars: function (format) { 8131 var iFormat, 8132 chars = "", 8133 literal = false, 8134 // Check whether a format character is doubled 8135 lookAhead = function(match) { 8136 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 8137 if (matches) { 8138 iFormat++; 8139 } 8140 return matches; 8141 }; 8142 8143 for (iFormat = 0; iFormat < format.length; iFormat++) { 8144 if (literal) { 8145 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 8146 literal = false; 8147 } else { 8148 chars += format.charAt(iFormat); 8149 } 8150 } else { 8151 switch (format.charAt(iFormat)) { 8152 case "d": case "m": case "y": case "@": 8153 chars += "0123456789"; 8154 break; 8155 case "D": case "M": 8156 return null; // Accept anything 8157 case "'": 8158 if (lookAhead("'")) { 8159 chars += "'"; 8160 } else { 8161 literal = true; 8162 } 8163 break; 8164 default: 8165 chars += format.charAt(iFormat); 8166 } 8167 } 8168 } 8169 return chars; 8170 }, 8171 8172 /* Get a setting value, defaulting if necessary. */ 8173 _get: function(inst, name) { 8174 return inst.settings[name] !== undefined ? 8175 inst.settings[name] : this._defaults[name]; 8176 }, 8177 8178 /* Parse existing date and initialise date picker. */ 8179 _setDateFromField: function(inst, noDefault) { 8180 if (inst.input.val() === inst.lastVal) { 8181 return; 8182 } 8183 8184 var dateFormat = this._get(inst, "dateFormat"), 8185 dates = inst.lastVal = inst.input ? inst.input.val() : null, 8186 defaultDate = this._getDefaultDate(inst), 8187 date = defaultDate, 8188 settings = this._getFormatConfig(inst); 8189 8190 try { 8191 date = this.parseDate(dateFormat, dates, settings) || defaultDate; 8192 } catch (event) { 8193 dates = (noDefault ? "" : dates); 8194 } 8195 inst.selectedDay = date.getDate(); 8196 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8197 inst.drawYear = inst.selectedYear = date.getFullYear(); 8198 inst.currentDay = (dates ? date.getDate() : 0); 8199 inst.currentMonth = (dates ? date.getMonth() : 0); 8200 inst.currentYear = (dates ? date.getFullYear() : 0); 8201 this._adjustInstDate(inst); 8202 }, 8203 8204 /* Retrieve the default date shown on opening. */ 8205 _getDefaultDate: function(inst) { 8206 return this._restrictMinMax(inst, 8207 this._determineDate(inst, this._get(inst, "defaultDate"), new Date())); 8208 }, 8209 8210 /* A date may be specified as an exact value or a relative one. */ 8211 _determineDate: function(inst, date, defaultDate) { 8212 var offsetNumeric = function(offset) { 8213 var date = new Date(); 8214 date.setDate(date.getDate() + offset); 8215 return date; 8216 }, 8217 offsetString = function(offset) { 8218 try { 8219 return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), 8220 offset, $.datepicker._getFormatConfig(inst)); 8221 } 8222 catch (e) { 8223 // Ignore 8224 } 8225 8226 var date = (offset.toLowerCase().match(/^c/) ? 8227 $.datepicker._getDate(inst) : null) || new Date(), 8228 year = date.getFullYear(), 8229 month = date.getMonth(), 8230 day = date.getDate(), 8231 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, 8232 matches = pattern.exec(offset); 8233 8234 while (matches) { 8235 switch (matches[2] || "d") { 8236 case "d" : case "D" : 8237 day += parseInt(matches[1],10); break; 8238 case "w" : case "W" : 8239 day += parseInt(matches[1],10) * 7; break; 8240 case "m" : case "M" : 8241 month += parseInt(matches[1],10); 8242 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 8243 break; 8244 case "y": case "Y" : 8245 year += parseInt(matches[1],10); 8246 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 8247 break; 8248 } 8249 matches = pattern.exec(offset); 8250 } 8251 return new Date(year, month, day); 8252 }, 8253 newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) : 8254 (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); 8255 8256 newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate); 8257 if (newDate) { 8258 newDate.setHours(0); 8259 newDate.setMinutes(0); 8260 newDate.setSeconds(0); 8261 newDate.setMilliseconds(0); 8262 } 8263 return this._daylightSavingAdjust(newDate); 8264 }, 8265 8266 /* Handle switch to/from daylight saving. 8267 * Hours may be non-zero on daylight saving cut-over: 8268 * > 12 when midnight changeover, but then cannot generate 8269 * midnight datetime, so jump to 1AM, otherwise reset. 8270 * @param date (Date) the date to check 8271 * @return (Date) the corrected date 8272 */ 8273 _daylightSavingAdjust: function(date) { 8274 if (!date) { 8275 return null; 8276 } 8277 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); 8278 return date; 8279 }, 8280 8281 /* Set the date(s) directly. */ 8282 _setDate: function(inst, date, noChange) { 8283 var clear = !date, 8284 origMonth = inst.selectedMonth, 8285 origYear = inst.selectedYear, 8286 newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); 8287 8288 inst.selectedDay = inst.currentDay = newDate.getDate(); 8289 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); 8290 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); 8291 if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) { 8292 this._notifyChange(inst); 8293 } 8294 this._adjustInstDate(inst); 8295 if (inst.input) { 8296 inst.input.val(clear ? "" : this._formatDate(inst)); 8297 } 8298 }, 8299 8300 /* Retrieve the date(s) directly. */ 8301 _getDate: function(inst) { 8302 var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null : 8303 this._daylightSavingAdjust(new Date( 8304 inst.currentYear, inst.currentMonth, inst.currentDay))); 8305 return startDate; 8306 }, 8307 8308 /* Attach the onxxx handlers. These are declared statically so 8309 * they work with static code transformers like Caja. 8310 */ 8311 _attachHandlers: function(inst) { 8312 var stepMonths = this._get(inst, "stepMonths"), 8313 id = "#" + inst.id.replace( /\\\\/g, "\\" ); 8314 inst.dpDiv.find("[data-handler]").map(function () { 8315 var handler = { 8316 prev: function () { 8317
vendor: 2,282 bytes, lines 8317-8366
8317window["DP_jQuery_" + dpuuid].datepicker._adjustDate(id, -stepMonths, "M"); 8318 }, 8319 next: function () { 8320 window["DP_jQuery_" + dpuuid].datepicker._adjustDate(id, +stepMonths, "M"); 8321 }, 8322 hide: function () { 8323 window["DP_jQuery_" + dpuuid].datepicker._hideDatepicker(); 8324 }, 8325 today: function () { 8326 window["DP_jQuery_" + dpuuid].datepicker._gotoToday(id); 8327 }, 8328 selectDay: function () { 8329 window["DP_jQuery_" + dpuuid].datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this); 8330 return false; 8331 }, 8332 selectMonth: function () { 8333 window["DP_jQuery_" + dpuuid].datepicker._selectMonthYear(id, this, "M"); 8334 return false; 8335 }, 8336 selectYear: function () { 8337 window["DP_jQuery_" + dpuuid].datepicker._selectMonthYear(id, this, "Y"); 8338 return false; 8339 } 8340 }; 8341 $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]); 8342 }); 8343 }, 8344 8345 /* Generate the HTML for the current state of the date picker. */ 8346 _generateHTML: function(inst) { 8347 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate, 8348 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin, 8349 monthNames, monthNamesShort, beforeShowDay, showOtherMonths, 8350 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate, 8351 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows, 8352 printDate, dRow, tbody, daySettings, otherMonth, unselectable, 8353 tempDate = new Date(), 8354 today = this._daylightSavingAdjust( 8355 new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time 8356 isRTL = this._get(inst, "isRTL"), 8357 showButtonPanel = this._get(inst, "showButtonPanel"), 8358 hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"), 8359 navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"), 8360 numMonths = this._getNumberOfMonths(inst), 8361 showCurrentAtPos = this._get(inst, "showCurrentAtPos"), 8362 stepMonths = this._get(inst, "stepMonths"), 8363 isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1), 8364 currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : 8365 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))), 8366 minDate = this._getMinMaxDate(inst, "min"),
vendor: 7,799 bytes, lines 8367-8500
8367 maxDate = this._getMinMaxDate(inst, "max"), 8368 drawMonth = inst.drawMonth - showCurrentAtPos, 8369 drawYear = inst.drawYear; 8370 8371 if (drawMonth < 0) { 8372 drawMonth += 12; 8373 drawYear--; 8374 } 8375 if (maxDate) { 8376 maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), 8377 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); 8378 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); 8379 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { 8380 drawMonth--; 8381 if (drawMonth < 0) { 8382 drawMonth = 11; 8383 drawYear--; 8384 } 8385 } 8386 } 8387 inst.drawMonth = drawMonth; 8388 inst.drawYear = drawYear; 8389 8390 prevText = this._get(inst, "prevText"); 8391 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, 8392 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), 8393 this._getFormatConfig(inst))); 8394 8395 prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? 8396 "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" + 8397 " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" : 8398 (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>")); 8399 8400 nextText = this._get(inst, "nextText"); 8401 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, 8402 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), 8403 this._getFormatConfig(inst))); 8404 8405 next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? 8406 "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" + 8407 " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" : 8408 (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>")); 8409 8410 currentText = this._get(inst, "currentText"); 8411 gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today); 8412 currentText = (!navigationAsDateFormat ? currentText : 8413 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); 8414 8415 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'>" + 8416 this._get(inst, "closeText") + "</button>" : ""); 8417 8418 buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") + 8419 (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'" + 8420 ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : ""; 8421 8422 firstDay = parseInt(this._get(inst, "firstDay"),10); 8423 firstDay = (isNaN(firstDay) ? 0 : firstDay); 8424 8425 showWeek = this._get(inst, "showWeek"); 8426 dayNames = this._get(inst, "dayNames"); 8427 dayNamesMin = this._get(inst, "dayNamesMin"); 8428 monthNames = this._get(inst, "monthNames"); 8429 monthNamesShort = this._get(inst, "monthNamesShort"); 8430 beforeShowDay = this._get(inst, "beforeShowDay"); 8431 showOtherMonths = this._get(inst, "showOtherMonths"); 8432 selectOtherMonths = this._get(inst, "selectOtherMonths"); 8433 defaultDate = this._getDefaultDate(inst); 8434 html = ""; 8435 dow; 8436 for (row = 0; row < numMonths[0]; row++) { 8437 group = ""; 8438 this.maxRows = 4; 8439 for (col = 0; col < numMonths[1]; col++) { 8440 selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); 8441 cornerClass = " ui-corner-all"; 8442 calender = ""; 8443 if (isMultiMonth) { 8444 calender += "<div class='ui-datepicker-group"; 8445 if (numMonths[1] > 1) { 8446 switch (col) { 8447 case 0: calender += " ui-datepicker-group-first"; 8448 cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break; 8449 case numMonths[1]-1: calender += " ui-datepicker-group-last"; 8450 cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break; 8451 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break; 8452 } 8453 } 8454 calender += "'>"; 8455 } 8456 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" + 8457 (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") + 8458 (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") + 8459 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, 8460 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers 8461 "</div><table class='ui-datepicker-calendar'><thead>" + 8462 "<tr>"; 8463 thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : ""); 8464 for (dow = 0; dow < 7; dow++) { // days of the week 8465 day = (dow + firstDay) % 7; 8466 thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" + 8467 "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>"; 8468 } 8469 calender += thead + "</tr></thead><tbody>"; 8470 daysInMonth = this._getDaysInMonth(drawYear, drawMonth); 8471 if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) { 8472 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); 8473 } 8474 leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; 8475 curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate 8476 numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) 8477 this.maxRows = numRows; 8478 printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); 8479 for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows 8480 calender += "<tr>"; 8481 tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" + 8482 this._get(inst, "calculateWeek")(printDate) + "</td>"); 8483 for (dow = 0; dow < 7; dow++) { // create date picker days 8484 daySettings = (beforeShowDay ? 8485 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]); 8486 otherMonth = (printDate.getMonth() !== drawMonth); 8487 unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || 8488 (minDate && printDate < minDate) || (maxDate && printDate > maxDate); 8489 tbody += "<td class='" + 8490 ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends 8491 (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months 8492 ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key 8493 (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ? 8494 // or defaultDate is current printedDate and defaultDate is selectedDate 8495 " " + this._dayOverClass : "") + // highlight selected day 8496 (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days 8497 (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates 8498 (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day 8499 (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different) 8500 ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2]
vendor: 6,995 bytes, lines 8500-8677
8500 + "'" : "") + // cell title 8501 (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions 8502 (otherMonth && !showOtherMonths ? " " : // display for other months 8503 (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" + 8504 (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") + 8505 (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day 8506 (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months 8507 "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date 8508 printDate.setDate(printDate.getDate() + 1); 8509 printDate = this._daylightSavingAdjust(printDate); 8510 } 8511 calender += tbody + "</tr>"; 8512 } 8513 drawMonth++; 8514 if (drawMonth > 11) { 8515 drawMonth = 0; 8516 drawYear++; 8517 } 8518 calender += "</tbody></table>" + (isMultiMonth ? "</div>" + 8519 ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : ""); 8520 group += calender; 8521 } 8522 html += group; 8523 } 8524 html += buttonPanel; 8525 inst._keyEvent = false; 8526 return html; 8527 }, 8528 8529 /* Generate the month and year header. */ 8530 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, 8531 secondary, monthNames, monthNamesShort) { 8532 8533 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear, 8534 changeMonth = this._get(inst, "changeMonth"), 8535 changeYear = this._get(inst, "changeYear"), 8536 showMonthAfterYear = this._get(inst, "showMonthAfterYear"), 8537 html = "<div class='ui-datepicker-title'>", 8538 monthHtml = ""; 8539 8540 // month selection 8541 if (secondary || !changeMonth) { 8542 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>"; 8543 } else { 8544 inMinYear = (minDate && minDate.getFullYear() === drawYear); 8545 inMaxYear = (maxDate && maxDate.getFullYear() === drawYear); 8546 monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>"; 8547 for ( month = 0; month < 12; month++) { 8548 if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) { 8549 monthHtml += "<option value='" + month + "'" + 8550 (month === drawMonth ? " selected='selected'" : "") + 8551 ">" + monthNamesShort[month] + "</option>"; 8552 } 8553 } 8554 monthHtml += "</select>"; 8555 } 8556 8557 if (!showMonthAfterYear) { 8558 html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : ""); 8559 } 8560 8561 // year selection 8562 if ( !inst.yearshtml ) { 8563 inst.yearshtml = ""; 8564 if (secondary || !changeYear) { 8565 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>"; 8566 } else { 8567 // determine range of years to display 8568 years = this._get(inst, "yearRange").split(":"); 8569 thisYear = new Date().getFullYear(); 8570 determineYear = function(value) { 8571 var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) : 8572 (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) : 8573 parseInt(value, 10))); 8574 return (isNaN(year) ? thisYear : year); 8575 }; 8576 year = determineYear(years[0]); 8577 endYear = Math.max(year, determineYear(years[1] || "")); 8578 year = (minDate ? Math.max(year, minDate.getFullYear()) : year); 8579 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); 8580 inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>"; 8581 for (; year <= endYear; year++) { 8582 inst.yearshtml += "<option value='" + year + "'" + 8583 (year === drawYear ? " selected='selected'" : "") + 8584 ">" + year + "</option>"; 8585 } 8586 inst.yearshtml += "</select>"; 8587 8588 html += inst.yearshtml; 8589 inst.yearshtml = null; 8590 } 8591 } 8592 8593 html += this._get(inst, "yearSuffix"); 8594 if (showMonthAfterYear) { 8595 html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml; 8596 } 8597 html += "</div>"; // Close datepicker_header 8598 return html; 8599 }, 8600 8601 /* Adjust one of the date sub-fields. */ 8602 _adjustInstDate: function(inst, offset, period) { 8603 var year = inst.drawYear + (period === "Y" ? offset : 0), 8604 month = inst.drawMonth + (period === "M" ? offset : 0), 8605 day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0), 8606 date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day))); 8607 8608 inst.selectedDay = date.getDate(); 8609 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8610 inst.drawYear = inst.selectedYear = date.getFullYear(); 8611 if (period === "M" || period === "Y") { 8612 this._notifyChange(inst); 8613 } 8614 }, 8615 8616 /* Ensure a date is within any min/max bounds. */ 8617 _restrictMinMax: function(inst, date) { 8618 var minDate = this._getMinMaxDate(inst, "min"), 8619 maxDate = this._getMinMaxDate(inst, "max"), 8620 newDate = (minDate && date < minDate ? minDate : date); 8621 return (maxDate && newDate > maxDate ? maxDate : newDate); 8622 }, 8623 8624 /* Notify change of month/year. */ 8625 _notifyChange: function(inst) { 8626 var onChange = this._get(inst, "onChangeMonthYear"); 8627 if (onChange) { 8628 onChange.apply((inst.input ? inst.input[0] : null), 8629 [inst.selectedYear, inst.selectedMonth + 1, inst]); 8630 } 8631 }, 8632 8633 /* Determine the number of months to show. */ 8634 _getNumberOfMonths: function(inst) { 8635 var numMonths = this._get(inst, "numberOfMonths"); 8636 return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths)); 8637 }, 8638 8639 /* Determine the current maximum date - ensure no time components are set. */ 8640 _getMinMaxDate: function(inst, minMax) { 8641 return this._determineDate(inst, this._get(inst, minMax + "Date"), null); 8642 }, 8643 8644 /* Find the number of days in a given month. */ 8645 _getDaysInMonth: function(year, month) { 8646 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); 8647 }, 8648 8649 /* Find the day of the week of the first of a month. */ 8650 _getFirstDayOfMonth: function(year, month) { 8651 return new Date(year, month, 1).getDay(); 8652 }, 8653 8654 /* Determines if we should allow a "next/prev" month display change. */ 8655 _canAdjustMonth: function(inst, offset, curYear, curMonth) { 8656 var numMonths = this._getNumberOfMonths(inst), 8657 date = this._daylightSavingAdjust(new Date(curYear, 8658 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); 8659 8660 if (offset < 0) { 8661 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); 8662 } 8663 return this._isInRange(inst, date); 8664 }, 8665 8666 /* Is the given date in the accepted range? */ 8667 _isInRange: function(inst, date) { 8668 var yearSplit, currentYear, 8669 minDate = this._getMinMaxDate(inst, "min"), 8670 maxDate = this._getMinMaxDate(inst, "max"), 8671 minYear = null, 8672 maxYear = null, 8673 years = this._get(inst, "yearRange"); 8674 if (years){ 8675 yearSplit = years.split(":"); 8676 currentYear = new Date().getFullYear(); 8677 minYear = parseInt(yearSplit[0], 10)
vendor: 21,273 bytes, lines 8677-9473
8677 + currentYear; 8678 maxYear = parseInt(yearSplit[1], 10) + currentYear; 8679 } 8680 8681 return ((!minDate || date.getTime() >= minDate.getTime()) && 8682 (!maxDate || date.getTime() <= maxDate.getTime()) && 8683 (!minYear || date.getFullYear() >= minYear) && 8684 (!maxYear || date.getFullYear() <= maxYear)); 8685 }, 8686 8687 /* Provide the configuration settings for formatting/parsing. */ 8688 _getFormatConfig: function(inst) { 8689 var shortYearCutoff = this._get(inst, "shortYearCutoff"); 8690 shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff : 8691 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); 8692 return {shortYearCutoff: shortYearCutoff, 8693 dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"), 8694 monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")}; 8695 }, 8696 8697 /* Format the given date for display. */ 8698 _formatDate: function(inst, day, month, year) { 8699 if (!day) { 8700 inst.currentDay = inst.selectedDay; 8701 inst.currentMonth = inst.selectedMonth; 8702 inst.currentYear = inst.selectedYear; 8703 } 8704 var date = (day ? (typeof day === "object" ? day : 8705 this._daylightSavingAdjust(new Date(year, month, day))) : 8706 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); 8707 return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst)); 8708 } 8709}); 8710 8711/* 8712 * Bind hover events for datepicker elements. 8713 * Done via delegate so the binding only occurs once in the lifetime of the parent div. 8714 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. 8715 */ 8716function bindHover(dpDiv) { 8717 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a"; 8718 return dpDiv.delegate(selector, "mouseout", function() { 8719 $(this).removeClass("ui-state-hover"); 8720 if (this.className.indexOf("ui-datepicker-prev") !== -1) { 8721 $(this).removeClass("ui-datepicker-prev-hover"); 8722 } 8723 if (this.className.indexOf("ui-datepicker-next") !== -1) { 8724 $(this).removeClass("ui-datepicker-next-hover"); 8725 } 8726 }) 8727 .delegate(selector, "mouseover", function(){ 8728 if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) { 8729 $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); 8730 $(this).addClass("ui-state-hover"); 8731 if (this.className.indexOf("ui-datepicker-prev") !== -1) { 8732 $(this).addClass("ui-datepicker-prev-hover"); 8733 } 8734 if (this.className.indexOf("ui-datepicker-next") !== -1) { 8735 $(this).addClass("ui-datepicker-next-hover"); 8736 } 8737 } 8738 }); 8739} 8740 8741/* jQuery extend now ignores nulls! */ 8742function extendRemove(target, props) { 8743 $.extend(target, props); 8744 for (var name in props) { 8745 if (props[name] == null) { 8746 target[name] = props[name]; 8747 } 8748 } 8749 return target; 8750} 8751 8752/* Invoke the datepicker functionality. 8753 @param options string - a command, optionally followed by additional parameters or 8754 Object - settings for attaching new datepicker functionality 8755 @return jQuery object */ 8756$.fn.datepicker = function(options){ 8757 8758 /* Verify an empty collection wasn't passed - Fixes #6976 */ 8759 if ( !this.length ) { 8760 return this; 8761 } 8762 8763 /* Initialise the date picker. */ 8764 if (!$.datepicker.initialized) { 8765 $(document).mousedown($.datepicker._checkExternalClick); 8766 $.datepicker.initialized = true; 8767 } 8768 8769 /* Append datepicker main container to body if not exist. */ 8770 if ($("#"+$.datepicker._mainDivId).length === 0) { 8771 $("body").append($.datepicker.dpDiv); 8772 } 8773 8774 var otherArgs = Array.prototype.slice.call(arguments, 1); 8775 if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) { 8776 return $.datepicker["_" + options + "Datepicker"]. 8777 apply($.datepicker, [this[0]].concat(otherArgs)); 8778 } 8779 if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") { 8780 return $.datepicker["_" + options + "Datepicker"]. 8781 apply($.datepicker, [this[0]].concat(otherArgs)); 8782 } 8783 return this.each(function() { 8784 typeof options === "string" ? 8785 $.datepicker["_" + options + "Datepicker"]. 8786 apply($.datepicker, [this].concat(otherArgs)) : 8787 $.datepicker._attachDatepicker(this, options); 8788 }); 8789}; 8790 8791$.datepicker = new Datepicker(); // singleton instance 8792$.datepicker.initialized = false; 8793$.datepicker.uuid = new Date().getTime(); 8794$.datepicker.version = "1.10.0"; 8795 8796// Workaround for #4055 8797// Add another global to avoid noConflict issues with inline event handlers 8798window["DP_jQuery_" + dpuuid] = $; 8799 8800})(jQuery); 8801(function( $, undefined ) { 8802 8803var sizeRelatedOptions = { 8804 buttons: true, 8805 height: true, 8806 maxHeight: true, 8807 maxWidth: true, 8808 minHeight: true, 8809 minWidth: true, 8810 width: true 8811 }, 8812 resizableRelatedOptions = { 8813 maxHeight: true, 8814 maxWidth: true, 8815 minHeight: true, 8816 minWidth: true 8817 }; 8818 8819$.widget( "ui.dialog", { 8820 version: "1.10.0", 8821 options: { 8822 appendTo: "body", 8823 autoOpen: true, 8824 buttons: [], 8825 closeOnEscape: true, 8826 closeText: "close", 8827 dialogClass: "", 8828 draggable: true, 8829 hide: null, 8830 height: "auto", 8831 maxHeight: null, 8832 maxWidth: null, 8833 minHeight: 150, 8834 minWidth: 150, 8835 modal: false, 8836 position: { 8837 my: "center", 8838 at: "center", 8839 of: window, 8840 collision: "fit", 8841 // Ensure the titlebar is always visible 8842 using: function( pos ) { 8843 var topOffset = $( this ).css( pos ).offset().top; 8844 if ( topOffset < 0 ) { 8845 $( this ).css( "top", pos.top - topOffset ); 8846 } 8847 } 8848 }, 8849 resizable: true, 8850 show: null, 8851 title: null, 8852 width: 300, 8853 8854 // callbacks 8855 beforeClose: null, 8856 close: null, 8857 drag: null, 8858 dragStart: null, 8859 dragStop: null, 8860 focus: null, 8861 open: null, 8862 resize: null, 8863 resizeStart: null, 8864 resizeStop: null 8865 }, 8866 8867 _create: function() { 8868 this.originalCss = { 8869 display: this.element[0].style.display, 8870 width: this.element[0].style.width, 8871 minHeight: this.element[0].style.minHeight, 8872 maxHeight: this.element[0].style.maxHeight, 8873 height: this.element[0].style.height 8874 }; 8875 this.originalPosition = { 8876 parent: this.element.parent(), 8877 index: this.element.parent().children().index( this.element ) 8878 }; 8879 this.originalTitle = this.element.attr("title"); 8880 this.options.title = this.options.title || this.originalTitle; 8881 8882 this._createWrapper(); 8883 8884 this.element 8885 .show() 8886 .removeAttr("title") 8887 .addClass("ui-dialog-content ui-widget-content") 8888 .appendTo( this.uiDialog ); 8889 8890 this._createTitlebar(); 8891 this._createButtonPane(); 8892 8893 if ( this.options.draggable && $.fn.draggable ) { 8894 this._makeDraggable(); 8895 } 8896 if ( this.options.resizable && $.fn.resizable ) { 8897 this._makeResizable(); 8898 } 8899 8900 this._isOpen = false; 8901 }, 8902 8903 _init: function() { 8904 if ( this.options.autoOpen ) { 8905 this.open(); 8906 } 8907 }, 8908 8909 _appendTo: function() { 8910 var element = this.options.appendTo; 8911 if ( element && (element.jquery || element.nodeType) ) { 8912 return $( element ); 8913 } 8914 return this.document.find( element || "body" ).eq( 0 ); 8915 }, 8916 8917 _destroy: function() { 8918 var next, 8919 originalPosition = this.originalPosition; 8920 8921 this._destroyOverlay(); 8922 8923 this.element 8924 .removeUniqueId() 8925 .removeClass("ui-dialog-content ui-widget-content") 8926 .css( this.originalCss ) 8927 // Without detaching first, the following becomes really slow 8928 .detach(); 8929 8930 this.uiDialog.stop( true, true ).remove(); 8931 8932 if ( this.originalTitle ) { 8933 this.element.attr( "title", this.originalTitle ); 8934 } 8935 8936 next = originalPosition.parent.children().eq( originalPosition.index ); 8937 // Don't try to place the dialog next to itself (#8613) 8938 if ( next.length && next[0] !== this.element[0] ) { 8939 next.before( this.element ); 8940 } else { 8941 originalPosition.parent.append( this.element ); 8942 } 8943 }, 8944 8945 widget: function() { 8946 return this.uiDialog; 8947 }, 8948 8949 disable: $.noop, 8950 enable: $.noop, 8951 8952 close: function( event ) { 8953 var that = this; 8954 8955 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) { 8956 return; 8957 } 8958 8959 this._isOpen = false; 8960 this._destroyOverlay(); 8961 8962 if ( !this.opener.filter(":focusable").focus().length ) { 8963 // Hiding a focused element doesn't trigger blur in WebKit 8964 // so in case we have nothing to focus on, explicitly blur the active element 8965 // https://bugs.webkit.org/show_bug.cgi?id=47182 8966 $( this.document[0].activeElement ).blur(); 8967 } 8968 8969 this._hide( this.uiDialog, this.options.hide, function() { 8970 that._trigger( "close", event ); 8971 }); 8972 }, 8973 8974 isOpen: function() { 8975 return this._isOpen; 8976 }, 8977 8978 moveToTop: function() { 8979 this._moveToTop(); 8980 }, 8981 8982 _moveToTop: function( event, silent ) { 8983 var moved = !!this.uiDialog.nextAll(":visible").insertBefore( this.uiDialog ).length; 8984 if ( moved && !silent ) { 8985 this._trigger( "focus", event ); 8986 } 8987 return moved; 8988 }, 8989 8990 open: function() { 8991 if ( this._isOpen ) { 8992 if ( this._moveToTop() ) { 8993 this._focusTabbable(); 8994 } 8995 return; 8996 } 8997 8998 this.opener = $( this.document[0].activeElement ); 8999 9000 this._size(); 9001 this._position(); 9002 this._createOverlay(); 9003 this._moveToTop( null, true ); 9004 this._show( this.uiDialog, this.options.show ); 9005 9006 this._focusTabbable(); 9007 9008 this._isOpen = true; 9009 this._trigger("open"); 9010 this._trigger("focus"); 9011 }, 9012 9013 _focusTabbable: function() { 9014 // Set focus to the first match: 9015 // 1. First element inside the dialog matching [autofocus] 9016 // 2. Tabbable element inside the content element 9017 // 3. Tabbable element inside the buttonpane 9018 // 4. The close button 9019 // 5. The dialog itself 9020 var hasFocus = this.element.find("[autofocus]"); 9021 if ( !hasFocus.length ) { 9022 hasFocus = this.element.find(":tabbable"); 9023 } 9024 if ( !hasFocus.length ) { 9025 hasFocus = this.uiDialogButtonPane.find(":tabbable"); 9026 } 9027 if ( !hasFocus.length ) { 9028 hasFocus = this.uiDialogTitlebarClose.filter(":tabbable"); 9029 } 9030 if ( !hasFocus.length ) { 9031 hasFocus = this.uiDialog; 9032 } 9033 hasFocus.eq( 0 ).focus(); 9034 }, 9035 9036 _keepFocus: function( event ) { 9037 function checkFocus() { 9038 var activeElement = this.document[0].activeElement, 9039 isActive = this.uiDialog[0] === activeElement || 9040 $.contains( this.uiDialog[0], activeElement ); 9041 if ( !isActive ) { 9042 this._focusTabbable(); 9043 } 9044 } 9045 event.preventDefault(); 9046 checkFocus.call( this ); 9047 // support: IE 9048 // IE <= 8 doesn't prevent moving focus even with event.preventDefault() 9049 // so we check again later 9050 this._delay( checkFocus ); 9051 }, 9052 9053 _createWrapper: function() { 9054 this.uiDialog = $("<div>") 9055 .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " + 9056 this.options.dialogClass ) 9057 .hide() 9058 .attr({ 9059 // Setting tabIndex makes the div focusable 9060 tabIndex: -1, 9061 role: "dialog" 9062 }) 9063 .appendTo( this._appendTo() ); 9064 9065 this._on( this.uiDialog, { 9066 keydown: function( event ) { 9067 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && 9068 event.keyCode === $.ui.keyCode.ESCAPE ) { 9069 event.preventDefault(); 9070 this.close( event ); 9071 return; 9072 } 9073 9074 // prevent tabbing out of dialogs 9075 if ( event.keyCode !== $.ui.keyCode.TAB ) { 9076 return; 9077 } 9078 var tabbables = this.uiDialog.find(":tabbable"), 9079 first = tabbables.filter(":first"), 9080 last = tabbables.filter(":last"); 9081 9082 if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) { 9083 first.focus( 1 ); 9084 event.preventDefault(); 9085 } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) { 9086 last.focus( 1 ); 9087 event.preventDefault(); 9088 } 9089 }, 9090 mousedown: function( event ) { 9091 if ( this._moveToTop( event ) ) { 9092 this._focusTabbable(); 9093 } 9094 } 9095 }); 9096 9097 // We assume that any existing aria-describedby attribute means 9098 // that the dialog content is marked up properly 9099 // otherwise we brute force the content as the description 9100 if ( !this.element.find("[aria-describedby]").length ) { 9101 this.uiDialog.attr({ 9102 "aria-describedby": this.element.uniqueId().attr("id") 9103 }); 9104 } 9105 }, 9106 9107 _createTitlebar: function() { 9108 var uiDialogTitle; 9109 9110 this.uiDialogTitlebar = $("<div>") 9111 .addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix") 9112 .prependTo( this.uiDialog ); 9113 this._on( this.uiDialogTitlebar, { 9114 mousedown: function( event ) { 9115 // Don't prevent click on close button (#8838) 9116 // Focusing a dialog that is partially scrolled out of view 9117 // causes the browser to scroll it into view, preventing the click event 9118 if ( !$( event.target ).closest(".ui-dialog-titlebar-close") ) { 9119 // Dialog isn't getting focus when dragging (#8063) 9120 this.uiDialog.focus(); 9121 } 9122 } 9123 }); 9124 9125 this.uiDialogTitlebarClose = $("<button></button>") 9126 .button({ 9127 label: this.options.closeText, 9128 icons: { 9129 primary: "ui-icon-closethick" 9130 }, 9131 text: false 9132 }) 9133 .addClass("ui-dialog-titlebar-close") 9134 .appendTo( this.uiDialogTitlebar ); 9135 this._on( this.uiDialogTitlebarClose, { 9136 click: function( event ) { 9137 event.preventDefault(); 9138 this.close( event ); 9139 } 9140 }); 9141 9142 uiDialogTitle = $("<span>") 9143 .uniqueId() 9144 .addClass("ui-dialog-title") 9145 .prependTo( this.uiDialogTitlebar ); 9146 this._title( uiDialogTitle ); 9147 9148 this.uiDialog.attr({ 9149 "aria-labelledby": uiDialogTitle.attr("id") 9150 }); 9151 }, 9152 9153 _title: function( title ) { 9154 if ( !this.options.title ) { 9155 title.html(" "); 9156 } 9157 title.text( this.options.title ); 9158 }, 9159 9160 _createButtonPane: function() { 9161 this.uiDialogButtonPane = $("<div>") 9162 .addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"); 9163 9164 this.uiButtonSet = $("<div>") 9165 .addClass("ui-dialog-buttonset") 9166 .appendTo( this.uiDialogButtonPane ); 9167 9168 this._createButtons(); 9169 }, 9170 9171 _createButtons: function() { 9172 var that = this, 9173 buttons = this.options.buttons; 9174 9175 // if we already have a button pane, remove it 9176 this.uiDialogButtonPane.remove(); 9177 this.uiButtonSet.empty(); 9178 9179 if ( $.isEmptyObject( buttons ) ) { 9180 this.uiDialog.removeClass("ui-dialog-buttons"); 9181 return; 9182 } 9183 9184 $.each( buttons, function( name, props ) { 9185 var click, buttonOptions; 9186 props = $.isFunction( props ) ? 9187 { click: props, text: name } : 9188 props; 9189 // Default to a non-submitting button 9190 props = $.extend( { type: "button" }, props ); 9191 // Change the context for the click callback to be the main element 9192 click = props.click; 9193 props.click = function() { 9194 click.apply( that.element[0], arguments ); 9195 }; 9196 buttonOptions = { 9197 icons: props.icons, 9198 text: props.showText 9199 }; 9200 delete props.icons; 9201 delete props.showText; 9202 $( "<button></button>", props ) 9203 .button( buttonOptions ) 9204 .appendTo( that.uiButtonSet ); 9205 }); 9206 this.uiDialog.addClass("ui-dialog-buttons"); 9207 this.uiDialogButtonPane.appendTo( this.uiDialog ); 9208 }, 9209 9210 _makeDraggable: function() { 9211 var that = this, 9212 options = this.options; 9213 9214 function filteredUi( ui ) { 9215 return { 9216 position: ui.position, 9217 offset: ui.offset 9218 }; 9219 } 9220 9221 this.uiDialog.draggable({ 9222 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", 9223 handle: ".ui-dialog-titlebar", 9224 containment: "document", 9225 start: function( event, ui ) { 9226 $( this ).addClass("ui-dialog-dragging"); 9227 that._trigger( "dragStart", event, filteredUi( ui ) ); 9228 }, 9229 drag: function( event, ui ) { 9230 that._trigger( "drag", event, filteredUi( ui ) ); 9231 }, 9232 stop: function( event, ui ) { 9233 options.position = [ 9234 ui.position.left - that.document.scrollLeft(), 9235 ui.position.top - that.document.scrollTop() 9236 ]; 9237 $( this ).removeClass("ui-dialog-dragging"); 9238 that._trigger( "dragStop", event, filteredUi( ui ) ); 9239 } 9240 }); 9241 }, 9242 9243 _makeResizable: function() { 9244 var that = this, 9245 options = this.options, 9246 handles = options.resizable, 9247 // .ui-resizable has position: relative defined in the stylesheet 9248 // but dialogs have to use absolute or fixed positioning 9249 position = this.uiDialog.css("position"), 9250 resizeHandles = typeof handles === "string" ? 9251 handles : 9252 "n,e,s,w,se,sw,ne,nw"; 9253 9254 function filteredUi( ui ) { 9255 return { 9256 originalPosition: ui.originalPosition, 9257 originalSize: ui.originalSize, 9258 position: ui.position, 9259 size: ui.size 9260 }; 9261 } 9262 9263 this.uiDialog.resizable({ 9264 cancel: ".ui-dialog-content", 9265 containment: "document", 9266 alsoResize: this.element, 9267 maxWidth: options.maxWidth, 9268 maxHeight: options.maxHeight, 9269 minWidth: options.minWidth, 9270 minHeight: this._minHeight(), 9271 handles: resizeHandles, 9272 start: function( event, ui ) { 9273 $( this ).addClass("ui-dialog-resizing"); 9274 that._trigger( "resizeStart", event, filteredUi( ui ) ); 9275 }, 9276 resize: function( event, ui ) { 9277 that._trigger( "resize", event, filteredUi( ui ) ); 9278 }, 9279 stop: function( event, ui ) { 9280 options.height = $( this ).height(); 9281 options.width = $( this ).width(); 9282 $( this ).removeClass("ui-dialog-resizing"); 9283 that._trigger( "resizeStop", event, filteredUi( ui ) ); 9284 } 9285 }) 9286 .css( "position", position ); 9287 }, 9288 9289 _minHeight: function() { 9290 var options = this.options; 9291 9292 return options.height === "auto" ? 9293 options.minHeight : 9294 Math.min( options.minHeight, options.height ); 9295 }, 9296 9297 _position: function() { 9298 // Need to show the dialog to get the actual offset in the position plugin 9299 var isVisible = this.uiDialog.is(":visible"); 9300 if ( !isVisible ) { 9301 this.uiDialog.show(); 9302 } 9303 this.uiDialog.position( this.options.position ); 9304 if ( !isVisible ) { 9305 this.uiDialog.hide(); 9306 } 9307 }, 9308 9309 _setOptions: function( options ) { 9310 var that = this, 9311 resize = false, 9312 resizableOptions = {}; 9313 9314 $.each( options, function( key, value ) { 9315 that._setOption( key, value ); 9316 9317 if ( key in sizeRelatedOptions ) { 9318 resize = true; 9319 } 9320 if ( key in resizableRelatedOptions ) { 9321 resizableOptions[ key ] = value; 9322 } 9323 }); 9324 9325 if ( resize ) { 9326 this._size(); 9327 this._position(); 9328 } 9329 if ( this.uiDialog.is(":data(ui-resizable)") ) { 9330 this.uiDialog.resizable( "option", resizableOptions ); 9331 } 9332 }, 9333 9334 _setOption: function( key, value ) { 9335 /*jshint maxcomplexity:15*/ 9336 var isDraggable, isResizable, 9337 uiDialog = this.uiDialog; 9338 9339 if ( key === "dialogClass" ) { 9340 uiDialog 9341 .removeClass( this.options.dialogClass ) 9342 .addClass( value ); 9343 } 9344 9345 if ( key === "disabled" ) { 9346 return; 9347 } 9348 9349 this._super( key, value ); 9350 9351 if ( key === "appendTo" ) { 9352 this.uiDialog.appendTo( this._appendTo() ); 9353 } 9354 9355 if ( key === "buttons" ) { 9356 this._createButtons(); 9357 } 9358 9359 if ( key === "closeText" ) { 9360 this.uiDialogTitlebarClose.button({ 9361 // Ensure that we always pass a string 9362 label: "" + value 9363 }); 9364 } 9365 9366 if ( key === "draggable" ) { 9367 isDraggable = uiDialog.is(":data(ui-draggable)"); 9368 if ( isDraggable && !value ) { 9369 uiDialog.draggable("destroy"); 9370 } 9371 9372 if ( !isDraggable && value ) { 9373 this._makeDraggable(); 9374 } 9375 } 9376 9377 if ( key === "position" ) { 9378 this._position(); 9379 } 9380 9381 if ( key === "resizable" ) { 9382 // currently resizable, becoming non-resizable 9383 isResizable = uiDialog.is(":data(ui-resizable)"); 9384 if ( isResizable && !value ) { 9385 uiDialog.resizable("destroy"); 9386 } 9387 9388 // currently resizable, changing handles 9389 if ( isResizable && typeof value === "string" ) { 9390 uiDialog.resizable( "option", "handles", value ); 9391 } 9392 9393 // currently non-resizable, becoming resizable 9394 if ( !isResizable && value !== false ) { 9395 this._makeResizable(); 9396 } 9397 } 9398 9399 if ( key === "title" ) { 9400 this._title( this.uiDialogTitlebar.find(".ui-dialog-title") ); 9401 } 9402 }, 9403 9404 _size: function() { 9405 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content 9406 // divs will both have width and height set, so we need to reset them 9407 var nonContentHeight, minContentHeight, maxContentHeight, 9408 options = this.options; 9409 9410 // Reset content sizing 9411 this.element.show().css({ 9412 width: "auto", 9413 minHeight: 0, 9414 maxHeight: "none", 9415 height: 0 9416 }); 9417 9418 if ( options.minWidth > options.width ) { 9419 options.width = options.minWidth; 9420 } 9421 9422 // reset wrapper sizing 9423 // determine the height of all the non-content elements 9424 nonContentHeight = this.uiDialog.css({ 9425 height: "auto", 9426 width: options.width 9427 }) 9428 .outerHeight(); 9429 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); 9430 maxContentHeight = typeof options.maxHeight === "number" ? 9431 Math.max( 0, options.maxHeight - nonContentHeight ) : 9432 "none"; 9433 9434 if ( options.height === "auto" ) { 9435 this.element.css({ 9436 minHeight: minContentHeight, 9437 maxHeight: maxContentHeight, 9438 height: "auto" 9439 }); 9440 } else { 9441 this.element.height( Math.max( 0, options.height - nonContentHeight ) ); 9442 } 9443 9444 if (this.uiDialog.is(":data(ui-resizable)") ) { 9445 this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); 9446 } 9447 }, 9448 9449 _createOverlay: function() { 9450 if ( !this.options.modal ) { 9451 return; 9452 } 9453 9454 if ( !$.ui.dialog.overlayInstances ) { 9455 // Prevent use of anchors and inputs. 9456 // We use a delay in case the overlay is created from an 9457 // event that we're going to be cancelling. (#2804) 9458 this._delay(function() { 9459 // Handle .dialog().dialog("close") (#4065) 9460 if ( $.ui.dialog.overlayInstances ) { 9461 this._on( this.document, { 9462 focusin: function( event ) { 9463 if ( !$( event.target ).closest(".ui-dialog").length ) { 9464 event.preventDefault(); 9465 $(".ui-dialog:visible:last .ui-dialog-content") 9466 .data("ui-dialog")._focusTabbable(); 9467 } 9468 } 9469 }); 9470 } 9471 }); 9472 } 9473
9474 this.overlay = $("<div>") 9475 .addClass("ui-widget-overlay ui-front") 9476 .appendTo( this.document[0].body ); 9477 this._on( this.overlay, { 9478 mousedown: "_keepFocus" 9479 }); 9480 $.ui.dialog.overlayInstances++; 9481 }, 9482 9483 _destroyOverlay: function() { 9484 if ( !this.options.modal ) { 9485 return; 9486 } 9487 9488 $.ui.dialog.overlayInstances--; 9489 if ( !$.ui.dialog.overlayInstances ) { 9490 this._off( this.document, "focusin" ); 9491 } 9492 this.overlay.remove(); 9493 } 9494}); 9495 9496$.ui.dialog.overlayInstances = 0; 9497 9498// DEPRECATED 9499if ( $.uiBackCompat !== false ) { 9500 // position option with array notation 9501 // just override with old implementation 9502 $.widget( "ui.dialog", $.ui.dialog, { 9503 _position: function() { 9504 var position = this.options.position, 9505 myAt = [], 9506 offset = [ 0, 0 ], 9507 isVisible; 9508 9509 if ( position ) { 9510 if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) { 9511 myAt = position.split ? position.split(" ") : [ position[0], position[1] ]; 9512 if ( myAt.length === 1 ) { 9513 myAt[1] = myAt[0]; 9514 } 9515 9516 $.each( [ "left", "top" ], function( i, offsetPosition ) { 9517 if ( +myAt[ i ] === myAt[ i ] ) { 9518 offset[ i ] = myAt[ i ]; 9519 myAt[ i ] = offsetPosition; 9520 } 9521 }); 9522 9523 position = { 9524 my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " + 9525 myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]), 9526 at: myAt.join(" ") 9527 }; 9528 } 9529 9530 position = $.extend( {}, $.ui.dialog.prototype.options.position, position ); 9531 } else { 9532 position = $.ui.dialog.prototype.options.position; 9533 } 9534 9535 // need to show the dialog to get the actual offset in the position plugin 9536 isVisible = this.uiDialog.is(":visible"); 9537 if ( !isVisible ) { 9538 this.uiDialog.show(); 9539 } 9540 this.uiDialog.position( position ); 9541 if ( !isVisible ) { 9542 this.uiDialog.hide(); 9543 } 9544 } 9545 }); 9546} 9547 9548}( jQuery ) ); 9549(function( $, undefined ) { 9550 9551$.widget( "ui.menu", { 9552 version: "1.10.0", 9553 defaultElement: "<ul>", 9554 delay: 300, 9555 options: { 9556 icons: { 9557 submenu: "ui-icon-carat-1-e" 9558 }, 9559 menus: "ul", 9560 position: { 9561 my: "left top", 9562 at: "right top" 9563 }, 9564 role: "menu", 9565 9566 // callbacks 9567 blur: null, 9568 focus: null, 9569 select: null 9570 }, 9571 9572 _create: function() { 9573 this.activeMenu = this.element; 9574 // flag used to prevent firing of the click handler 9575 // as the event bubbles up through nested menus 9576 this.mouseHandled = false; 9577 this.element 9578 .uniqueId() 9579 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) 9580 .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ) 9581 .attr({ 9582 role: this.options.role, 9583 tabIndex: 0 9584 }) 9585 // need to catch all clicks on disabled menu 9586 // not possible through _on 9587 .bind( "click" + this.eventNamespace, $.proxy(function( event ) { 9588 if ( this.options.disabled ) { 9589 event.preventDefault(); 9590 } 9591 }, this )); 9592 9593 if ( this.options.disabled ) { 9594 this.element 9595 .addClass( "ui-state-disabled" ) 9596 .attr( "aria-disabled", "true" ); 9597 } 9598 9599 this._on({ 9600 // Prevent focus from sticking to links inside menu after clicking 9601 // them (focus should always stay on UL during navigation). 9602 "mousedown .ui-menu-item > a": function( event ) { 9603 event.preventDefault(); 9604 }, 9605 "click .ui-state-disabled > a": function( event ) { 9606 event.preventDefault(); 9607 }, 9608 "click .ui-menu-item:has(a)": function( event ) { 9609 var target = $( event.target ).closest( ".ui-menu-item" ); 9610 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) { 9611 this.mouseHandled = true; 9612 9613 this.select( event ); 9614 // Open submenu on click 9615 if ( target.has( ".ui-menu" ).length ) { 9616 this.expand( event ); 9617 } else if ( !this.element.is( ":focus" ) ) { 9618 // Redirect focus to the menu 9619 this.element.trigger( "focus", [ true ] ); 9620 9621 // If the active item is on the top level, let it stay active. 9622 // Otherwise, blur the active item since it is no longer visible. 9623 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) { 9624 clearTimeout( this.timer ); 9625 } 9626 } 9627 } 9628 }, 9629 "mouseenter .ui-menu-item": function( event ) { 9630 var target = $( event.currentTarget ); 9631 // Remove ui-state-active class from siblings of the newly focused menu item 9632 // to avoid a jump caused by adjacent elements both having a class with a border 9633 target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" ); 9634 this.focus( event, target ); 9635 }, 9636 mouseleave: "collapseAll", 9637 "mouseleave .ui-menu": "collapseAll", 9638 focus: function( event, keepActiveItem ) { 9639 // If there's already an active item, keep it active 9640 // If not, activate the first item 9641 var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 ); 9642 9643 if ( !keepActiveItem ) { 9644 this.focus( event, item ); 9645 } 9646 }, 9647 blur: function( event ) { 9648 this._delay(function() { 9649 if ( !$.contains( this.element[0], this.document[0].activeElement ) ) { 9650 this.collapseAll( event ); 9651 } 9652 }); 9653 }, 9654 keydown: "_keydown" 9655 }); 9656 9657 this.refresh(); 9658
vendor: 132,758 bytes, lines 9659-14850
9659 // Clicks outside of a menu collapse any open menus 9660 this._on( this.document, { 9661 click: function( event ) { 9662 if ( !$( event.target ).closest( ".ui-menu" ).length ) { 9663 this.collapseAll( event ); 9664 } 9665 9666 // Reset the mouseHandled flag 9667 this.mouseHandled = false; 9668 } 9669 }); 9670 }, 9671 9672 _destroy: function() { 9673 // Destroy (sub)menus 9674 this.element 9675 .removeAttr( "aria-activedescendant" ) 9676 .find( ".ui-menu" ).addBack() 9677 .removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" ) 9678 .removeAttr( "role" ) 9679 .removeAttr( "tabIndex" ) 9680 .removeAttr( "aria-labelledby" ) 9681 .removeAttr( "aria-expanded" ) 9682 .removeAttr( "aria-hidden" ) 9683 .removeAttr( "aria-disabled" ) 9684 .removeUniqueId() 9685 .show(); 9686 9687 // Destroy menu items 9688 this.element.find( ".ui-menu-item" ) 9689 .removeClass( "ui-menu-item" ) 9690 .removeAttr( "role" ) 9691 .removeAttr( "aria-disabled" ) 9692 .children( "a" ) 9693 .removeUniqueId() 9694 .removeClass( "ui-corner-all ui-state-hover" ) 9695 .removeAttr( "tabIndex" ) 9696 .removeAttr( "role" ) 9697 .removeAttr( "aria-haspopup" ) 9698 .children().each( function() { 9699 var elem = $( this ); 9700 if ( elem.data( "ui-menu-submenu-carat" ) ) { 9701 elem.remove(); 9702 } 9703 }); 9704 9705 // Destroy menu dividers 9706 this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" ); 9707 }, 9708 9709 _keydown: function( event ) { 9710 /*jshint maxcomplexity:20*/ 9711 var match, prev, character, skip, regex, 9712 preventDefault = true; 9713 9714 function escape( value ) { 9715 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ); 9716 } 9717 9718 switch ( event.keyCode ) { 9719 case $.ui.keyCode.PAGE_UP: 9720 this.previousPage( event ); 9721 break; 9722 case $.ui.keyCode.PAGE_DOWN: 9723 this.nextPage( event ); 9724 break; 9725 case $.ui.keyCode.HOME: 9726 this._move( "first", "first", event ); 9727 break; 9728 case $.ui.keyCode.END: 9729 this._move( "last", "last", event ); 9730 break; 9731 case $.ui.keyCode.UP: 9732 this.previous( event ); 9733 break; 9734 case $.ui.keyCode.DOWN: 9735 this.next( event ); 9736 break; 9737 case $.ui.keyCode.LEFT: 9738 this.collapse( event ); 9739 break; 9740 case $.ui.keyCode.RIGHT: 9741 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { 9742 this.expand( event ); 9743 } 9744 break; 9745 case $.ui.keyCode.ENTER: 9746 case $.ui.keyCode.SPACE: 9747 this._activate( event ); 9748 break; 9749 case $.ui.keyCode.ESCAPE: 9750 this.collapse( event ); 9751 break; 9752 default: 9753 preventDefault = false; 9754 prev = this.previousFilter || ""; 9755 character = String.fromCharCode( event.keyCode ); 9756 skip = false; 9757 9758 clearTimeout( this.filterTimer ); 9759 9760 if ( character === prev ) { 9761 skip = true; 9762 } else { 9763 character = prev + character; 9764 } 9765 9766 regex = new RegExp( "^" + escape( character ), "i" ); 9767 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { 9768 return regex.test( $( this ).children( "a" ).text() ); 9769 }); 9770 match = skip && match.index( this.active.next() ) !== -1 ? 9771 this.active.nextAll( ".ui-menu-item" ) : 9772 match; 9773 9774 // If no matches on the current filter, reset to the last character pressed 9775 // to move down the menu to the first item that starts with that character 9776 if ( !match.length ) { 9777 character = String.fromCharCode( event.keyCode ); 9778 regex = new RegExp( "^" + escape( character ), "i" ); 9779 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { 9780 return regex.test( $( this ).children( "a" ).text() ); 9781 }); 9782 } 9783 9784 if ( match.length ) { 9785 this.focus( event, match ); 9786 if ( match.length > 1 ) { 9787 this.previousFilter = character; 9788 this.filterTimer = this._delay(function() { 9789 delete this.previousFilter; 9790 }, 1000 ); 9791 } else { 9792 delete this.previousFilter; 9793 } 9794 } else { 9795 delete this.previousFilter; 9796 } 9797 } 9798 9799 if ( preventDefault ) { 9800 event.preventDefault(); 9801 } 9802 }, 9803 9804 _activate: function( event ) { 9805 if ( !this.active.is( ".ui-state-disabled" ) ) { 9806 if ( this.active.children( "a[aria-haspopup='true']" ).length ) { 9807 this.expand( event ); 9808 } else { 9809 this.select( event ); 9810 } 9811 } 9812 }, 9813 9814 refresh: function() { 9815 var menus, 9816 icon = this.options.icons.submenu, 9817 submenus = this.element.find( this.options.menus ); 9818 9819 // Initialize nested menus 9820 submenus.filter( ":not(.ui-menu)" ) 9821 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) 9822 .hide() 9823 .attr({ 9824 role: this.options.role, 9825 "aria-hidden": "true", 9826 "aria-expanded": "false" 9827 }) 9828 .each(function() { 9829 var menu = $( this ), 9830 item = menu.prev( "a" ), 9831 submenuCarat = $( "<span>" ) 9832 .addClass( "ui-menu-icon ui-icon " + icon ) 9833 .data( "ui-menu-submenu-carat", true ); 9834 9835 item 9836 .attr( "aria-haspopup", "true" ) 9837 .prepend( submenuCarat ); 9838 menu.attr( "aria-labelledby", item.attr( "id" ) ); 9839 }); 9840 9841 menus = submenus.add( this.element ); 9842 9843 // Don't refresh list items that are already adapted 9844 menus.children( ":not(.ui-menu-item):has(a)" ) 9845 .addClass( "ui-menu-item" ) 9846 .attr( "role", "presentation" ) 9847 .children( "a" ) 9848 .uniqueId() 9849 .addClass( "ui-corner-all" ) 9850 .attr({ 9851 tabIndex: -1, 9852 role: this._itemRole() 9853 }); 9854 9855 // Initialize unlinked menu-items containing spaces and/or dashes only as dividers 9856 menus.children( ":not(.ui-menu-item)" ).each(function() { 9857 var item = $( this ); 9858 // hyphen, em dash, en dash 9859 if ( !/[^\-—–\s]/.test( item.text() ) ) { 9860 item.addClass( "ui-widget-content ui-menu-divider" ); 9861 } 9862 }); 9863 9864 // Add aria-disabled attribute to any disabled menu item 9865 menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); 9866 9867 // If the active item has been removed, blur the menu 9868 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 9869 this.blur(); 9870 } 9871 }, 9872 9873 _itemRole: function() { 9874 return { 9875 menu: "menuitem", 9876 listbox: "option" 9877 }[ this.options.role ]; 9878 }, 9879 9880 _setOption: function( key, value ) { 9881 if ( key === "icons" ) { 9882 this.element.find( ".ui-menu-icon" ) 9883 .removeClass( this.options.icons.submenu ) 9884 .addClass( value.submenu ); 9885 } 9886 this._super( key, value ); 9887 }, 9888 9889 focus: function( event, item ) { 9890 var nested, focused; 9891 this.blur( event, event && event.type === "focus" ); 9892 9893 this._scrollIntoView( item ); 9894 9895 this.active = item.first(); 9896 focused = this.active.children( "a" ).addClass( "ui-state-focus" ); 9897 // Only update aria-activedescendant if there's a role 9898 // otherwise we assume focus is managed elsewhere 9899 if ( this.options.role ) { 9900 this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); 9901 } 9902 9903 // Highlight active parent menu item, if any 9904 this.active 9905 .parent() 9906 .closest( ".ui-menu-item" ) 9907 .children( "a:first" ) 9908 .addClass( "ui-state-active" ); 9909 9910 if ( event && event.type === "keydown" ) { 9911 this._close(); 9912 } else { 9913 this.timer = this._delay(function() { 9914 this._close(); 9915 }, this.delay ); 9916 } 9917 9918 nested = item.children( ".ui-menu" ); 9919 if ( nested.length && ( /^mouse/.test( event.type ) ) ) { 9920 this._startOpening(nested); 9921 } 9922 this.activeMenu = item.parent(); 9923 9924 this._trigger( "focus", event, { item: item } ); 9925 }, 9926 9927 _scrollIntoView: function( item ) { 9928 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; 9929 if ( this._hasScroll() ) { 9930 borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0; 9931 paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0; 9932 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; 9933 scroll = this.activeMenu.scrollTop(); 9934 elementHeight = this.activeMenu.height(); 9935 itemHeight = item.height(); 9936 9937 if ( offset < 0 ) { 9938 this.activeMenu.scrollTop( scroll + offset ); 9939 } else if ( offset + itemHeight > elementHeight ) { 9940 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); 9941 } 9942 } 9943 }, 9944 9945 blur: function( event, fromFocus ) { 9946 if ( !fromFocus ) { 9947 clearTimeout( this.timer ); 9948 } 9949 9950 if ( !this.active ) { 9951 return; 9952 } 9953 9954 this.active.children( "a" ).removeClass( "ui-state-focus" ); 9955 this.active = null; 9956 9957 this._trigger( "blur", event, { item: this.active } ); 9958 }, 9959 9960 _startOpening: function( submenu ) { 9961 clearTimeout( this.timer ); 9962 9963 // Don't open if already open fixes a Firefox bug that caused a .5 pixel 9964 // shift in the submenu position when mousing over the carat icon 9965 if ( submenu.attr( "aria-hidden" ) !== "true" ) { 9966 return; 9967 } 9968 9969 this.timer = this._delay(function() { 9970 this._close(); 9971 this._open( submenu ); 9972 }, this.delay ); 9973 }, 9974 9975 _open: function( submenu ) { 9976 var position = $.extend({ 9977 of: this.active 9978 }, this.options.position ); 9979 9980 clearTimeout( this.timer ); 9981 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) ) 9982 .hide() 9983 .attr( "aria-hidden", "true" ); 9984 9985 submenu 9986 .show() 9987 .removeAttr( "aria-hidden" ) 9988 .attr( "aria-expanded", "true" ) 9989 .position( position ); 9990 }, 9991 9992 collapseAll: function( event, all ) { 9993 clearTimeout( this.timer ); 9994 this.timer = this._delay(function() { 9995 // If we were passed an event, look for the submenu that contains the event 9996 var currentMenu = all ? this.element : 9997 $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); 9998 9999 // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway 10000 if ( !currentMenu.length ) { 10001 currentMenu = this.element; 10002 } 10003 10004 this._close( currentMenu ); 10005 10006 this.blur( event ); 10007 this.activeMenu = currentMenu; 10008 }, this.delay ); 10009 }, 10010 10011 // With no arguments, closes the currently active menu - if nothing is active 10012 // it closes all menus. If passed an argument, it will search for menus BELOW 10013 _close: function( startMenu ) { 10014 if ( !startMenu ) { 10015 startMenu = this.active ? this.active.parent() : this.element; 10016 } 10017 10018 startMenu 10019 .find( ".ui-menu" ) 10020 .hide() 10021 .attr( "aria-hidden", "true" ) 10022 .attr( "aria-expanded", "false" ) 10023 .end() 10024 .find( "a.ui-state-active" ) 10025 .removeClass( "ui-state-active" ); 10026 }, 10027 10028 collapse: function( event ) { 10029 var newItem = this.active && 10030 this.active.parent().closest( ".ui-menu-item", this.element ); 10031 if ( newItem && newItem.length ) { 10032 this._close(); 10033 this.focus( event, newItem ); 10034 } 10035 }, 10036 10037 expand: function( event ) { 10038 var newItem = this.active && 10039 this.active 10040 .children( ".ui-menu " ) 10041 .children( ".ui-menu-item" ) 10042 .first(); 10043 10044 if ( newItem && newItem.length ) { 10045 this._open( newItem.parent() ); 10046 10047 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT 10048 this._delay(function() { 10049 this.focus( event, newItem ); 10050 }); 10051 } 10052 }, 10053 10054 next: function( event ) { 10055 this._move( "next", "first", event ); 10056 }, 10057 10058 previous: function( event ) { 10059 this._move( "prev", "last", event ); 10060 }, 10061 10062 isFirstItem: function() { 10063 return this.active && !this.active.prevAll( ".ui-menu-item" ).length; 10064 }, 10065 10066 isLastItem: function() { 10067 return this.active && !this.active.nextAll( ".ui-menu-item" ).length; 10068 }, 10069 10070 _move: function( direction, filter, event ) { 10071 var next; 10072 if ( this.active ) { 10073 if ( direction === "first" || direction === "last" ) { 10074 next = this.active 10075 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) 10076 .eq( -1 ); 10077 } else { 10078 next = this.active 10079 [ direction + "All" ]( ".ui-menu-item" ) 10080 .eq( 0 ); 10081 } 10082 } 10083 if ( !next || !next.length || !this.active ) { 10084 next = this.activeMenu.children( ".ui-menu-item" )[ filter ](); 10085 } 10086 10087 this.focus( event, next ); 10088 }, 10089 10090 nextPage: function( event ) { 10091 var item, base, height; 10092 10093 if ( !this.active ) { 10094 this.next( event ); 10095 return; 10096 } 10097 if ( this.isLastItem() ) { 10098 return; 10099 } 10100 if ( this._hasScroll() ) { 10101 base = this.active.offset().top; 10102 height = this.element.height(); 10103 this.active.nextAll( ".ui-menu-item" ).each(function() { 10104 item = $( this ); 10105 return item.offset().top - base - height < 0; 10106 }); 10107 10108 this.focus( event, item ); 10109 } else { 10110 this.focus( event, this.activeMenu.children( ".ui-menu-item" ) 10111 [ !this.active ? "first" : "last" ]() ); 10112 } 10113 }, 10114 10115 previousPage: function( event ) { 10116 var item, base, height; 10117 if ( !this.active ) { 10118 this.next( event ); 10119 return; 10120 } 10121 if ( this.isFirstItem() ) { 10122 return; 10123 } 10124 if ( this._hasScroll() ) { 10125 base = this.active.offset().top; 10126 height = this.element.height(); 10127 this.active.prevAll( ".ui-menu-item" ).each(function() { 10128 item = $( this ); 10129 return item.offset().top - base + height > 0; 10130 }); 10131 10132 this.focus( event, item ); 10133 } else { 10134 this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() ); 10135 } 10136 }, 10137 10138 _hasScroll: function() { 10139 return this.element.outerHeight() < this.element.prop( "scrollHeight" ); 10140 }, 10141 10142 select: function( event ) { 10143 // TODO: It should never be possible to not have an active item at this 10144 // point, but the tests don't trigger mouseenter before click. 10145 this.active = this.active || $( event.target ).closest( ".ui-menu-item" ); 10146 var ui = { item: this.active }; 10147 if ( !this.active.has( ".ui-menu" ).length ) { 10148 this.collapseAll( event, true ); 10149 } 10150 this._trigger( "select", event, ui ); 10151 } 10152}); 10153 10154}( jQuery )); 10155(function( $, undefined ) { 10156 10157$.widget( "ui.progressbar", { 10158 version: "1.10.0", 10159 options: { 10160 max: 100, 10161 value: 0, 10162 10163 change: null, 10164 complete: null 10165 }, 10166 10167 min: 0, 10168 10169 _create: function() { 10170 // Constrain initial value 10171 this.oldValue = this.options.value = this._constrainedValue(); 10172 10173 this.element 10174 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) 10175 .attr({ 10176 // Only set static values, aria-valuenow and aria-valuemax are 10177 // set inside _refreshValue() 10178 role: "progressbar", 10179 "aria-valuemin": this.min 10180 }); 10181 10182 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" ) 10183 .appendTo( this.element ); 10184 10185 this._refreshValue(); 10186 }, 10187 10188 _destroy: function() { 10189 this.element 10190 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) 10191 .removeAttr( "role" ) 10192 .removeAttr( "aria-valuemin" ) 10193 .removeAttr( "aria-valuemax" ) 10194 .removeAttr( "aria-valuenow" ); 10195 10196 this.valueDiv.remove(); 10197 }, 10198 10199 value: function( newValue ) { 10200 if ( newValue === undefined ) { 10201 return this.options.value; 10202 } 10203 10204 this.options.value = this._constrainedValue( newValue ); 10205 this._refreshValue(); 10206 }, 10207 10208 _constrainedValue: function( newValue ) { 10209 if ( newValue === undefined ) { 10210 newValue = this.options.value; 10211 } 10212 10213 this.indeterminate = newValue === false; 10214 10215 // sanitize value 10216 if ( typeof newValue !== "number" ) { 10217 newValue = 0; 10218 } 10219 10220 return this.indeterminate ? false : 10221 Math.min( this.options.max, Math.max( this.min, newValue ) ); 10222 }, 10223 10224 _setOptions: function( options ) { 10225 // Ensure "value" option is set after other values (like max) 10226 var value = options.value; 10227 delete options.value; 10228 10229 this._super( options ); 10230 10231 this.options.value = this._constrainedValue( value ); 10232 this._refreshValue(); 10233 }, 10234 10235 _setOption: function( key, value ) { 10236 if ( key === "max" ) { 10237 // Don't allow a max less than min 10238 value = Math.max( this.min, value ); 10239 } 10240 10241 this._super( key, value ); 10242 }, 10243 10244 _percentage: function() { 10245 return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min ); 10246 }, 10247 10248 _refreshValue: function() { 10249 var value = this.options.value, 10250 percentage = this._percentage(); 10251 10252 this.valueDiv 10253 .toggle( this.indeterminate || value > this.min ) 10254 .toggleClass( "ui-corner-right", value === this.options.max ) 10255 .width( percentage.toFixed(0) + "%" ); 10256 10257 this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate ); 10258 10259 if ( this.indeterminate ) { 10260 this.element.removeAttr( "aria-valuenow" ); 10261 if ( !this.overlayDiv ) { 10262 this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv ); 10263 } 10264 } else { 10265 this.element.attr({ 10266 "aria-valuemax": this.options.max, 10267 "aria-valuenow": value 10268 }); 10269 if ( this.overlayDiv ) { 10270 this.overlayDiv.remove(); 10271 this.overlayDiv = null; 10272 } 10273 } 10274 10275 if ( this.oldValue !== value ) { 10276 this.oldValue = value; 10277 this._trigger( "change" ); 10278 } 10279 if ( value === this.options.max ) { 10280 this._trigger( "complete" ); 10281 } 10282 } 10283}); 10284 10285})( jQuery ); 10286(function( $, undefined ) { 10287 10288// number of pages in a slider 10289// (how many times can you page up/down to go through the whole range) 10290var numPages = 5; 10291 10292$.widget( "ui.slider", $.ui.mouse, { 10293 version: "1.10.0", 10294 widgetEventPrefix: "slide", 10295 10296 options: { 10297 animate: false, 10298 distance: 0, 10299 max: 100, 10300 min: 0, 10301 orientation: "horizontal", 10302 range: false, 10303 step: 1, 10304 value: 0, 10305 values: null, 10306 10307 // callbacks 10308 change: null, 10309 slide: null, 10310 start: null, 10311 stop: null 10312 }, 10313 10314 _create: function() { 10315 var i, handleCount, 10316 o = this.options, 10317 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), 10318 handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>", 10319 handles = []; 10320 10321 this._keySliding = false; 10322 this._mouseSliding = false; 10323 this._animateOff = true; 10324 this._handleIndex = null; 10325 this._detectOrientation(); 10326 this._mouseInit(); 10327 10328 this.element 10329 .addClass( "ui-slider" + 10330 " ui-slider-" + this.orientation + 10331 " ui-widget" + 10332 " ui-widget-content" + 10333 " ui-corner-all"); 10334 10335 this.range = $([]); 10336 10337 if ( o.range ) { 10338 if ( o.range === true ) { 10339 if ( !o.values ) { 10340 o.values = [ this._valueMin(), this._valueMin() ]; 10341 } else if ( o.values.length && o.values.length !== 2 ) { 10342 o.values = [ o.values[0], o.values[0] ]; 10343 } else if ( $.isArray( o.values ) ) { 10344 o.values = o.values.slice(0); 10345 } 10346 } 10347 10348 this.range = $( "<div></div>" ) 10349 .appendTo( this.element ) 10350 .addClass( "ui-slider-range" + 10351 // note: this isn't the most fittingly semantic framework class for this element, 10352 // but worked best visually with a variety of themes 10353 " ui-widget-header" + 10354 ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) ); 10355 } 10356 10357 handleCount = ( o.values && o.values.length ) || 1; 10358 10359 for ( i = existingHandles.length; i < handleCount; i++ ) { 10360 handles.push( handle ); 10361 } 10362 10363 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) ); 10364 10365 this.handle = this.handles.eq( 0 ); 10366 10367 this.handles.add( this.range ).filter( "a" ) 10368 .click(function( event ) { 10369 event.preventDefault(); 10370 }) 10371 .mouseenter(function() { 10372 if ( !o.disabled ) { 10373 $( this ).addClass( "ui-state-hover" ); 10374 } 10375 }) 10376 .mouseleave(function() { 10377 $( this ).removeClass( "ui-state-hover" ); 10378 }) 10379 .focus(function() { 10380 if ( !o.disabled ) { 10381 $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" ); 10382 $( this ).addClass( "ui-state-focus" ); 10383 } else { 10384 $( this ).blur(); 10385 } 10386 }) 10387 .blur(function() { 10388 $( this ).removeClass( "ui-state-focus" ); 10389 }); 10390 10391 this.handles.each(function( i ) { 10392 $( this ).data( "ui-slider-handle-index", i ); 10393 }); 10394 10395 this._setOption( "disabled", o.disabled ); 10396 10397 this._on( this.handles, this._handleEvents ); 10398 10399 this._refreshValue(); 10400 10401 this._animateOff = false; 10402 }, 10403 10404 _destroy: function() { 10405 this.handles.remove(); 10406 this.range.remove(); 10407 10408 this.element 10409 .removeClass( "ui-slider" + 10410 " ui-slider-horizontal" + 10411 " ui-slider-vertical" + 10412 " ui-widget" + 10413 " ui-widget-content" + 10414 " ui-corner-all" ); 10415 10416 this._mouseDestroy(); 10417 }, 10418 10419 _mouseCapture: function( event ) { 10420 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, 10421 that = this, 10422 o = this.options; 10423 10424 if ( o.disabled ) { 10425 return false; 10426 } 10427 10428 this.elementSize = { 10429 width: this.element.outerWidth(), 10430 height: this.element.outerHeight() 10431 }; 10432 this.elementOffset = this.element.offset(); 10433 10434 position = { x: event.pageX, y: event.pageY }; 10435 normValue = this._normValueFromMouse( position ); 10436 distance = this._valueMax() - this._valueMin() + 1; 10437 this.handles.each(function( i ) { 10438 var thisDistance = Math.abs( normValue - that.values(i) ); 10439 if (( distance > thisDistance ) || 10440 ( distance === thisDistance && 10441 (i === that._lastChangedValue || that.values(i) === o.min ))) { 10442 distance = thisDistance; 10443 closestHandle = $( this ); 10444 index = i; 10445 } 10446 }); 10447 10448 allowed = this._start( event, index ); 10449 if ( allowed === false ) { 10450 return false; 10451 } 10452 this._mouseSliding = true; 10453 10454 this._handleIndex = index; 10455 10456 closestHandle 10457 .addClass( "ui-state-active" ) 10458 .focus(); 10459 10460 offset = closestHandle.offset(); 10461 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" ); 10462 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { 10463 left: event.pageX - offset.left - ( closestHandle.width() / 2 ), 10464 top: event.pageY - offset.top - 10465 ( closestHandle.height() / 2 ) - 10466 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - 10467 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + 10468 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) 10469 }; 10470 10471 if ( !this.handles.hasClass( "ui-state-hover" ) ) { 10472 this._slide( event, index, normValue ); 10473 } 10474 this._animateOff = true; 10475 return true; 10476 }, 10477 10478 _mouseStart: function() { 10479 return true; 10480 }, 10481 10482 _mouseDrag: function( event ) { 10483 var position = { x: event.pageX, y: event.pageY }, 10484 normValue = this._normValueFromMouse( position ); 10485 10486 this._slide( event, this._handleIndex, normValue ); 10487 10488 return false; 10489 }, 10490 10491 _mouseStop: function( event ) { 10492 this.handles.removeClass( "ui-state-active" ); 10493 this._mouseSliding = false; 10494 10495 this._stop( event, this._handleIndex ); 10496 this._change( event, this._handleIndex ); 10497 10498 this._handleIndex = null; 10499 this._clickOffset = null; 10500 this._animateOff = false; 10501 10502 return false; 10503 }, 10504 10505 _detectOrientation: function() { 10506 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; 10507 }, 10508 10509 _normValueFromMouse: function( position ) { 10510 var pixelTotal, 10511 pixelMouse, 10512 percentMouse, 10513 valueTotal, 10514 valueMouse; 10515 10516 if ( this.orientation === "horizontal" ) { 10517 pixelTotal = this.elementSize.width; 10518 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); 10519 } else { 10520 pixelTotal = this.elementSize.height; 10521 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); 10522 } 10523 10524 percentMouse = ( pixelMouse / pixelTotal ); 10525 if ( percentMouse > 1 ) { 10526 percentMouse = 1; 10527 } 10528 if ( percentMouse < 0 ) { 10529 percentMouse = 0; 10530 } 10531 if ( this.orientation === "vertical" ) { 10532 percentMouse = 1 - percentMouse; 10533 } 10534 10535 valueTotal = this._valueMax() - this._valueMin(); 10536 valueMouse = this._valueMin() + percentMouse * valueTotal; 10537 10538 return this._trimAlignValue( valueMouse ); 10539 }, 10540 10541 _start: function( event, index ) { 10542 var uiHash = { 10543 handle: this.handles[ index ], 10544 value: this.value() 10545 }; 10546 if ( this.options.values && this.options.values.length ) { 10547 uiHash.value = this.values( index ); 10548 uiHash.values = this.values(); 10549 } 10550 return this._trigger( "start", event, uiHash ); 10551 }, 10552 10553 _slide: function( event, index, newVal ) { 10554 var otherVal, 10555 newValues, 10556 allowed; 10557 10558 if ( this.options.values && this.options.values.length ) { 10559 otherVal = this.values( index ? 0 : 1 ); 10560 10561 if ( ( this.options.values.length === 2 && this.options.range === true ) && 10562 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) 10563 ) { 10564 newVal = otherVal; 10565 } 10566 10567 if ( newVal !== this.values( index ) ) { 10568 newValues = this.values(); 10569 newValues[ index ] = newVal; 10570 // A slide can be canceled by returning false from the slide callback 10571 allowed = this._trigger( "slide", event, { 10572 handle: this.handles[ index ], 10573 value: newVal, 10574 values: newValues 10575 } ); 10576 otherVal = this.values( index ? 0 : 1 ); 10577 if ( allowed !== false ) { 10578 this.values( index, newVal, true ); 10579 } 10580 } 10581 } else { 10582 if ( newVal !== this.value() ) { 10583 // A slide can be canceled by returning false from the slide callback 10584 allowed = this._trigger( "slide", event, { 10585 handle: this.handles[ index ], 10586 value: newVal 10587 } ); 10588 if ( allowed !== false ) { 10589 this.value( newVal ); 10590 } 10591 } 10592 } 10593 }, 10594 10595 _stop: function( event, index ) { 10596 var uiHash = { 10597 handle: this.handles[ index ], 10598 value: this.value() 10599 }; 10600 if ( this.options.values && this.options.values.length ) { 10601 uiHash.value = this.values( index ); 10602 uiHash.values = this.values(); 10603 } 10604 10605 this._trigger( "stop", event, uiHash ); 10606 }, 10607 10608 _change: function( event, index ) { 10609 if ( !this._keySliding && !this._mouseSliding ) { 10610 var uiHash = { 10611 handle: this.handles[ index ], 10612 value: this.value() 10613 }; 10614 if ( this.options.values && this.options.values.length ) { 10615 uiHash.value = this.values( index ); 10616 uiHash.values = this.values(); 10617 } 10618 10619 //store the last changed value index for reference when handles overlap 10620 this._lastChangedValue = index; 10621 10622 this._trigger( "change", event, uiHash ); 10623 } 10624 }, 10625 10626 value: function( newValue ) { 10627 if ( arguments.length ) { 10628 this.options.value = this._trimAlignValue( newValue ); 10629 this._refreshValue(); 10630 this._change( null, 0 ); 10631 return; 10632 } 10633 10634 return this._value(); 10635 }, 10636 10637 values: function( index, newValue ) { 10638 var vals, 10639 newValues, 10640 i; 10641 10642 if ( arguments.length > 1 ) { 10643 this.options.values[ index ] = this._trimAlignValue( newValue ); 10644 this._refreshValue(); 10645 this._change( null, index ); 10646 return; 10647 } 10648 10649 if ( arguments.length ) { 10650 if ( $.isArray( arguments[ 0 ] ) ) { 10651 vals = this.options.values; 10652 newValues = arguments[ 0 ]; 10653 for ( i = 0; i < vals.length; i += 1 ) { 10654 vals[ i ] = this._trimAlignValue( newValues[ i ] ); 10655 this._change( null, i ); 10656 } 10657 this._refreshValue(); 10658 } else { 10659 if ( this.options.values && this.options.values.length ) { 10660 return this._values( index ); 10661 } else { 10662 return this.value(); 10663 } 10664 } 10665 } else { 10666 return this._values(); 10667 } 10668 }, 10669 10670 _setOption: function( key, value ) { 10671 var i, 10672 valsLength = 0; 10673 10674 if ( $.isArray( this.options.values ) ) { 10675 valsLength = this.options.values.length; 10676 } 10677 10678 $.Widget.prototype._setOption.apply( this, arguments ); 10679 10680 switch ( key ) { 10681 case "disabled": 10682 if ( value ) { 10683 this.handles.filter( ".ui-state-focus" ).blur(); 10684 this.handles.removeClass( "ui-state-hover" ); 10685 this.handles.prop( "disabled", true ); 10686 } else { 10687 this.handles.prop( "disabled", false ); 10688 } 10689 break; 10690 case "orientation": 10691 this._detectOrientation(); 10692 this.element 10693 .removeClass( "ui-slider-horizontal ui-slider-vertical" ) 10694 .addClass( "ui-slider-" + this.orientation ); 10695 this._refreshValue(); 10696 break; 10697 case "value": 10698 this._animateOff = true; 10699 this._refreshValue(); 10700 this._change( null, 0 ); 10701 this._animateOff = false; 10702 break; 10703 case "values": 10704 this._animateOff = true; 10705 this._refreshValue(); 10706 for ( i = 0; i < valsLength; i += 1 ) { 10707 this._change( null, i ); 10708 } 10709 this._animateOff = false; 10710 break; 10711 case "min": 10712 case "max": 10713 this._animateOff = true; 10714 this._refreshValue(); 10715 this._animateOff = false; 10716 break; 10717 } 10718 }, 10719 10720 //internal value getter 10721 // _value() returns value trimmed by min and max, aligned by step 10722 _value: function() { 10723 var val = this.options.value; 10724 val = this._trimAlignValue( val ); 10725 10726 return val; 10727 }, 10728 10729 //internal values getter 10730 // _values() returns array of values trimmed by min and max, aligned by step 10731 // _values( index ) returns single value trimmed by min and max, aligned by step 10732 _values: function( index ) { 10733 var val, 10734 vals, 10735 i; 10736 10737 if ( arguments.length ) { 10738 val = this.options.values[ index ]; 10739 val = this._trimAlignValue( val ); 10740 10741 return val; 10742 } else { 10743 // .slice() creates a copy of the array 10744 // this copy gets trimmed by min and max and then returned 10745 vals = this.options.values.slice(); 10746 for ( i = 0; i < vals.length; i+= 1) { 10747 vals[ i ] = this._trimAlignValue( vals[ i ] ); 10748 } 10749 10750 return vals; 10751 } 10752 }, 10753 10754 // returns the step-aligned value that val is closest to, between (inclusive) min and max 10755 _trimAlignValue: function( val ) { 10756 if ( val <= this._valueMin() ) { 10757 return this._valueMin(); 10758 } 10759 if ( val >= this._valueMax() ) { 10760 return this._valueMax(); 10761 } 10762 var step = ( this.options.step > 0 ) ? this.options.step : 1, 10763 valModStep = (val - this._valueMin()) % step, 10764 alignValue = val - valModStep; 10765 10766 if ( Math.abs(valModStep) * 2 >= step ) { 10767 alignValue += ( valModStep > 0 ) ? step : ( -step ); 10768 } 10769 10770 // Since JavaScript has problems with large floats, round 10771 // the final value to 5 digits after the decimal point (see #4124) 10772 return parseFloat( alignValue.toFixed(5) ); 10773 }, 10774 10775 _valueMin: function() { 10776 return this.options.min; 10777 }, 10778 10779 _valueMax: function() { 10780 return this.options.max; 10781 }, 10782 10783 _refreshValue: function() { 10784 var lastValPercent, valPercent, value, valueMin, valueMax, 10785 oRange = this.options.range, 10786 o = this.options, 10787 that = this, 10788 animate = ( !this._animateOff ) ? o.animate : false, 10789 _set = {}; 10790 10791 if ( this.options.values && this.options.values.length ) { 10792 this.handles.each(function( i ) { 10793 valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100; 10794 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 10795 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 10796 if ( that.options.range === true ) { 10797 if ( that.orientation === "horizontal" ) { 10798 if ( i === 0 ) { 10799 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); 10800 } 10801 if ( i === 1 ) { 10802 that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); 10803 } 10804 } else { 10805 if ( i === 0 ) { 10806 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); 10807 } 10808 if ( i === 1 ) { 10809 that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); 10810 } 10811 } 10812 } 10813 lastValPercent = valPercent; 10814 }); 10815 } else { 10816 value = this.value(); 10817 valueMin = this._valueMin(); 10818 valueMax = this._valueMax(); 10819 valPercent = ( valueMax !== valueMin ) ? 10820 ( value - valueMin ) / ( valueMax - valueMin ) * 100 : 10821 0; 10822 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 10823 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 10824 10825 if ( oRange === "min" && this.orientation === "horizontal" ) { 10826 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); 10827 } 10828 if ( oRange === "max" && this.orientation === "horizontal" ) { 10829 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); 10830 } 10831 if ( oRange === "min" && this.orientation === "vertical" ) { 10832 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); 10833 } 10834 if ( oRange === "max" && this.orientation === "vertical" ) { 10835 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); 10836 } 10837 } 10838 }, 10839 10840 _handleEvents: { 10841 keydown: function( event ) { 10842 /*jshint maxcomplexity:25*/ 10843 var allowed, curVal, newVal, step, 10844 index = $( event.target ).data( "ui-slider-handle-index" ); 10845 10846 switch ( event.keyCode ) { 10847 case $.ui.keyCode.HOME: 10848 case $.ui.keyCode.END: 10849 case $.ui.keyCode.PAGE_UP: 10850 case $.ui.keyCode.PAGE_DOWN: 10851 case $.ui.keyCode.UP: 10852 case $.ui.keyCode.RIGHT: 10853 case $.ui.keyCode.DOWN: 10854 case $.ui.keyCode.LEFT: 10855 event.preventDefault(); 10856 if ( !this._keySliding ) { 10857 this._keySliding = true; 10858 $( event.target ).addClass( "ui-state-active" ); 10859 allowed = this._start( event, index ); 10860 if ( allowed === false ) { 10861 return; 10862 } 10863 } 10864 break; 10865 } 10866 10867 step = this.options.step; 10868 if ( this.options.values && this.options.values.length ) { 10869 curVal = newVal = this.values( index ); 10870 } else { 10871 curVal = newVal = this.value(); 10872 } 10873 10874 switch ( event.keyCode ) { 10875 case $.ui.keyCode.HOME: 10876 newVal = this._valueMin(); 10877 break; 10878 case $.ui.keyCode.END: 10879 newVal = this._valueMax(); 10880 break; 10881 case $.ui.keyCode.PAGE_UP: 10882 newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) ); 10883 break; 10884 case $.ui.keyCode.PAGE_DOWN: 10885 newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) ); 10886 break; 10887 case $.ui.keyCode.UP: 10888 case $.ui.keyCode.RIGHT: 10889 if ( curVal === this._valueMax() ) { 10890 return; 10891 } 10892 newVal = this._trimAlignValue( curVal + step ); 10893 break; 10894 case $.ui.keyCode.DOWN: 10895 case $.ui.keyCode.LEFT: 10896 if ( curVal === this._valueMin() ) { 10897 return; 10898 } 10899 newVal = this._trimAlignValue( curVal - step ); 10900 break; 10901 } 10902 10903 this._slide( event, index, newVal ); 10904 }, 10905 keyup: function( event ) { 10906 var index = $( event.target ).data( "ui-slider-handle-index" ); 10907 10908 if ( this._keySliding ) { 10909 this._keySliding = false; 10910 this._stop( event, index ); 10911 this._change( event, index ); 10912 $( event.target ).removeClass( "ui-state-active" ); 10913 } 10914 } 10915 } 10916 10917}); 10918 10919}(jQuery)); 10920(function( $ ) { 10921 10922function modifier( fn ) { 10923 return function() { 10924 var previous = this.element.val(); 10925 fn.apply( this, arguments ); 10926 this._refresh(); 10927 if ( previous !== this.element.val() ) { 10928 this._trigger( "change" ); 10929 } 10930 }; 10931} 10932 10933$.widget( "ui.spinner", { 10934 version: "1.10.0", 10935 defaultElement: "<input>", 10936 widgetEventPrefix: "spin", 10937 options: { 10938 culture: null, 10939 icons: { 10940 down: "ui-icon-triangle-1-s", 10941 up: "ui-icon-triangle-1-n" 10942 }, 10943 incremental: true, 10944 max: null, 10945 min: null, 10946 numberFormat: null, 10947 page: 10, 10948 step: 1, 10949 10950 change: null, 10951 spin: null, 10952 start: null, 10953 stop: null 10954 }, 10955 10956 _create: function() { 10957 // handle string values that need to be parsed 10958 this._setOption( "max", this.options.max ); 10959 this._setOption( "min", this.options.min ); 10960 this._setOption( "step", this.options.step ); 10961 10962 // format the value, but don't constrain 10963 this._value( this.element.val(), true ); 10964 10965 this._draw(); 10966 this._on( this._events ); 10967 this._refresh(); 10968 10969 // turning off autocomplete prevents the browser from remembering the 10970 // value when navigating through history, so we re-enable autocomplete 10971 // if the page is unloaded before the widget is destroyed. #7790 10972 this._on( this.window, { 10973 beforeunload: function() { 10974 this.element.removeAttr( "autocomplete" ); 10975 } 10976 }); 10977 }, 10978 10979 _getCreateOptions: function() { 10980 var options = {}, 10981 element = this.element; 10982 10983 $.each( [ "min", "max", "step" ], function( i, option ) { 10984 var value = element.attr( option ); 10985 if ( value !== undefined && value.length ) { 10986 options[ option ] = value; 10987 } 10988 }); 10989 10990 return options; 10991 }, 10992 10993 _events: { 10994 keydown: function( event ) { 10995 if ( this._start( event ) && this._keydown( event ) ) { 10996 event.preventDefault(); 10997 } 10998 }, 10999 keyup: "_stop", 11000 focus: function() { 11001 this.previous = this.element.val(); 11002 }, 11003 blur: function( event ) { 11004 if ( this.cancelBlur ) { 11005 delete this.cancelBlur; 11006 return; 11007 } 11008 11009 this._refresh(); 11010 if ( this.previous !== this.element.val() ) { 11011 this._trigger( "change", event ); 11012 } 11013 }, 11014 mousewheel: function( event, delta ) { 11015 if ( !delta ) { 11016 return; 11017 } 11018 if ( !this.spinning && !this._start( event ) ) { 11019 return false; 11020 } 11021 11022 this._spin( (delta > 0 ? 1 : -1) * this.options.step, event ); 11023 clearTimeout( this.mousewheelTimer ); 11024 this.mousewheelTimer = this._delay(function() { 11025 if ( this.spinning ) { 11026 this._stop( event ); 11027 } 11028 }, 100 ); 11029 event.preventDefault(); 11030 }, 11031 "mousedown .ui-spinner-button": function( event ) { 11032 var previous; 11033 11034 // We never want the buttons to have focus; whenever the user is 11035 // interacting with the spinner, the focus should be on the input. 11036 // If the input is focused then this.previous is properly set from 11037 // when the input first received focus. If the input is not focused 11038 // then we need to set this.previous based on the value before spinning. 11039 previous = this.element[0] === this.document[0].activeElement ? 11040 this.previous : this.element.val(); 11041 function checkFocus() { 11042 var isActive = this.element[0] === this.document[0].activeElement; 11043 if ( !isActive ) { 11044 this.element.focus(); 11045 this.previous = previous; 11046 // support: IE 11047 // IE sets focus asynchronously, so we need to check if focus 11048 // moved off of the input because the user clicked on the button. 11049 this._delay(function() { 11050 this.previous = previous; 11051 }); 11052 } 11053 } 11054 11055 // ensure focus is on (or stays on) the text field 11056 event.preventDefault(); 11057 checkFocus.call( this ); 11058 11059 // support: IE 11060 // IE doesn't prevent moving focus even with event.preventDefault() 11061 // so we set a flag to know when we should ignore the blur event 11062 // and check (again) if focus moved off of the input. 11063 this.cancelBlur = true; 11064 this._delay(function() { 11065 delete this.cancelBlur; 11066 checkFocus.call( this ); 11067 }); 11068 11069 if ( this._start( event ) === false ) { 11070 return; 11071 } 11072 11073 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 11074 }, 11075 "mouseup .ui-spinner-button": "_stop", 11076 "mouseenter .ui-spinner-button": function( event ) { 11077 // button will add ui-state-active if mouse was down while mouseleave and kept down 11078 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) { 11079 return; 11080 } 11081 11082 if ( this._start( event ) === false ) { 11083 return false; 11084 } 11085 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 11086 }, 11087 // TODO: do we really want to consider this a stop? 11088 // shouldn't we just stop the repeater and wait until mouseup before 11089 // we trigger the stop event? 11090 "mouseleave .ui-spinner-button": "_stop" 11091 }, 11092 11093 _draw: function() { 11094 var uiSpinner = this.uiSpinner = this.element 11095 .addClass( "ui-spinner-input" ) 11096 .attr( "autocomplete", "off" ) 11097 .wrap( this._uiSpinnerHtml() ) 11098 .parent() 11099 // add buttons 11100 .append( this._buttonHtml() ); 11101 11102 this.element.attr( "role", "spinbutton" ); 11103 11104 // button bindings 11105 this.buttons = uiSpinner.find( ".ui-spinner-button" ) 11106 .attr( "tabIndex", -1 ) 11107 .button() 11108 .removeClass( "ui-corner-all" ); 11109 11110 // IE 6 doesn't understand height: 50% for the buttons 11111 // unless the wrapper has an explicit height 11112 if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) && 11113 uiSpinner.height() > 0 ) { 11114 uiSpinner.height( uiSpinner.height() ); 11115 } 11116 11117 // disable spinner if element was already disabled 11118 if ( this.options.disabled ) { 11119 this.disable(); 11120 } 11121 }, 11122 11123 _keydown: function( event ) { 11124 var options = this.options, 11125 keyCode = $.ui.keyCode; 11126 11127 switch ( event.keyCode ) { 11128 case keyCode.UP: 11129 this._repeat( null, 1, event ); 11130 return true; 11131 case keyCode.DOWN: 11132 this._repeat( null, -1, event ); 11133 return true; 11134 case keyCode.PAGE_UP: 11135 this._repeat( null, options.page, event ); 11136 return true; 11137 case keyCode.PAGE_DOWN: 11138 this._repeat( null, -options.page, event ); 11139 return true; 11140 } 11141 11142 return false; 11143 }, 11144 11145 _uiSpinnerHtml: function() { 11146 return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"; 11147 }, 11148 11149 _buttonHtml: function() { 11150 return "" + 11151 "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" + 11152 "<span class='ui-icon " + this.options.icons.up + "'>▲</span>" + 11153 "</a>" + 11154 "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" + 11155 "<span class='ui-icon " + this.options.icons.down + "'>▼</span>" + 11156 "</a>"; 11157 }, 11158 11159 _start: function( event ) { 11160 if ( !this.spinning && this._trigger( "start", event ) === false ) { 11161 return false; 11162 } 11163 11164 if ( !this.counter ) { 11165 this.counter = 1; 11166 } 11167 this.spinning = true; 11168 return true; 11169 }, 11170 11171 _repeat: function( i, steps, event ) { 11172 i = i || 500; 11173 11174 clearTimeout( this.timer ); 11175 this.timer = this._delay(function() { 11176 this._repeat( 40, steps, event ); 11177 }, i ); 11178 11179 this._spin( steps * this.options.step, event ); 11180 }, 11181 11182 _spin: function( step, event ) { 11183 var value = this.value() || 0; 11184 11185 if ( !this.counter ) { 11186 this.counter = 1; 11187 } 11188 11189 value = this._adjustValue( value + step * this._increment( this.counter ) ); 11190 11191 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) { 11192 this._value( value ); 11193 this.counter++; 11194 } 11195 }, 11196 11197 _increment: function( i ) { 11198 var incremental = this.options.incremental; 11199 11200 if ( incremental ) { 11201 return $.isFunction( incremental ) ? 11202 incremental( i ) : 11203 Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 ); 11204 } 11205 11206 return 1; 11207 }, 11208 11209 _precision: function() { 11210 var precision = this._precisionOf( this.options.step ); 11211 if ( this.options.min !== null ) { 11212 precision = Math.max( precision, this._precisionOf( this.options.min ) ); 11213 } 11214 return precision; 11215 }, 11216 11217 _precisionOf: function( num ) { 11218 var str = num.toString(), 11219 decimal = str.indexOf( "." ); 11220 return decimal === -1 ? 0 : str.length - decimal - 1; 11221 }, 11222 11223 _adjustValue: function( value ) { 11224 var base, aboveMin, 11225 options = this.options; 11226 11227 // make sure we're at a valid step 11228 // - find out where we are relative to the base (min or 0) 11229 base = options.min !== null ? options.min : 0; 11230 aboveMin = value - base; 11231 // - round to the nearest step 11232 aboveMin = Math.round(aboveMin / options.step) * options.step; 11233 // - rounding is based on 0, so adjust back to our base 11234 value = base + aboveMin; 11235 11236 // fix precision from bad JS floating point math 11237 value = parseFloat( value.toFixed( this._precision() ) ); 11238 11239 // clamp the value 11240 if ( options.max !== null && value > options.max) { 11241 return options.max; 11242 } 11243 if ( options.min !== null && value < options.min ) { 11244 return options.min; 11245 } 11246 11247 return value; 11248 }, 11249 11250 _stop: function( event ) { 11251 if ( !this.spinning ) { 11252 return; 11253 } 11254 11255 clearTimeout( this.timer ); 11256 clearTimeout( this.mousewheelTimer ); 11257 this.counter = 0; 11258 this.spinning = false; 11259 this._trigger( "stop", event ); 11260 }, 11261 11262 _setOption: function( key, value ) { 11263 if ( key === "culture" || key === "numberFormat" ) { 11264 var prevValue = this._parse( this.element.val() ); 11265 this.options[ key ] = value; 11266 this.element.val( this._format( prevValue ) ); 11267 return; 11268 } 11269 11270 if ( key === "max" || key === "min" || key === "step" ) { 11271 if ( typeof value === "string" ) { 11272 value = this._parse( value ); 11273 } 11274 } 11275 if ( key === "icons" ) { 11276 this.buttons.first().find( ".ui-icon" ) 11277 .removeClass( this.options.icons.up ) 11278 .addClass( value.up ); 11279 this.buttons.last().find( ".ui-icon" ) 11280 .removeClass( this.options.icons.down ) 11281 .addClass( value.down ); 11282 } 11283 11284 this._super( key, value ); 11285 11286 if ( key === "disabled" ) { 11287 if ( value ) { 11288 this.element.prop( "disabled", true ); 11289 this.buttons.button( "disable" ); 11290 } else { 11291 this.element.prop( "disabled", false ); 11292 this.buttons.button( "enable" ); 11293 } 11294 } 11295 }, 11296 11297 _setOptions: modifier(function( options ) { 11298 this._super( options ); 11299 this._value( this.element.val() ); 11300 }), 11301 11302 _parse: function( val ) { 11303 if ( typeof val === "string" && val !== "" ) { 11304 val = window.Globalize && this.options.numberFormat ? 11305 Globalize.parseFloat( val, 10, this.options.culture ) : +val; 11306 } 11307 return val === "" || isNaN( val ) ? null : val; 11308 }, 11309 11310 _format: function( value ) { 11311 if ( value === "" ) { 11312 return ""; 11313 } 11314 return window.Globalize && this.options.numberFormat ? 11315 Globalize.format( value, this.options.numberFormat, this.options.culture ) : 11316 value; 11317 }, 11318 11319 _refresh: function() { 11320 this.element.attr({ 11321 "aria-valuemin": this.options.min, 11322 "aria-valuemax": this.options.max, 11323 // TODO: what should we do with values that can't be parsed? 11324 "aria-valuenow": this._parse( this.element.val() ) 11325 }); 11326 }, 11327 11328 // update the value without triggering change 11329 _value: function( value, allowAny ) { 11330 var parsed; 11331 if ( value !== "" ) { 11332 parsed = this._parse( value ); 11333 if ( parsed !== null ) { 11334 if ( !allowAny ) { 11335 parsed = this._adjustValue( parsed ); 11336 } 11337 value = this._format( parsed ); 11338 } 11339 } 11340 this.element.val( value ); 11341 this._refresh(); 11342 }, 11343 11344 _destroy: function() { 11345 this.element 11346 .removeClass( "ui-spinner-input" ) 11347 .prop( "disabled", false ) 11348 .removeAttr( "autocomplete" ) 11349 .removeAttr( "role" ) 11350 .removeAttr( "aria-valuemin" ) 11351 .removeAttr( "aria-valuemax" ) 11352 .removeAttr( "aria-valuenow" ); 11353 this.uiSpinner.replaceWith( this.element ); 11354 }, 11355 11356 stepUp: modifier(function( steps ) { 11357 this._stepUp( steps ); 11358 }), 11359 _stepUp: function( steps ) { 11360 if ( this._start() ) { 11361 this._spin( (steps || 1) * this.options.step ); 11362 this._stop(); 11363 } 11364 }, 11365 11366 stepDown: modifier(function( steps ) { 11367 this._stepDown( steps ); 11368 }), 11369 _stepDown: function( steps ) { 11370 if ( this._start() ) { 11371 this._spin( (steps || 1) * -this.options.step ); 11372 this._stop(); 11373 } 11374 }, 11375 11376 pageUp: modifier(function( pages ) { 11377 this._stepUp( (pages || 1) * this.options.page ); 11378 }), 11379 11380 pageDown: modifier(function( pages ) { 11381 this._stepDown( (pages || 1) * this.options.page ); 11382 }), 11383 11384 value: function( newVal ) { 11385 if ( !arguments.length ) { 11386 return this._parse( this.element.val() ); 11387 } 11388 modifier( this._value ).call( this, newVal ); 11389 }, 11390 11391 widget: function() { 11392 return this.uiSpinner; 11393 } 11394}); 11395 11396}( jQuery ) ); 11397(function( $, undefined ) { 11398 11399var tabId = 0, 11400 rhash = /#.*$/; 11401 11402function getNextTabId() { 11403 return ++tabId; 11404} 11405 11406function isLocal( anchor ) { 11407 return anchor.hash.length > 1 && 11408 decodeURIComponent( anchor.href.replace( rhash, "" ) ) === 11409 decodeURIComponent( location.href.replace( rhash, "" ) ); 11410} 11411 11412$.widget( "ui.tabs", { 11413 version: "1.10.0", 11414 delay: 300, 11415 options: { 11416 active: null, 11417 collapsible: false, 11418 event: "click", 11419 heightStyle: "content", 11420 hide: null, 11421 show: null, 11422 11423 // callbacks 11424 activate: null, 11425 beforeActivate: null, 11426 beforeLoad: null, 11427 load: null 11428 }, 11429 11430 _create: function() { 11431 var that = this, 11432 options = this.options; 11433 11434 this.running = false; 11435 11436 this.element 11437 .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ) 11438 .toggleClass( "ui-tabs-collapsible", options.collapsible ) 11439 // Prevent users from focusing disabled tabs via click 11440 .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) { 11441 if ( $( this ).is( ".ui-state-disabled" ) ) { 11442 event.preventDefault(); 11443 } 11444 }) 11445 // support: IE <9 11446 // Preventing the default action in mousedown doesn't prevent IE 11447 // from focusing the element, so if the anchor gets focused, blur. 11448 // We don't have to worry about focusing the previously focused 11449 // element since clicking on a non-focusable element should focus 11450 // the body anyway. 11451 .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() { 11452 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) { 11453 this.blur(); 11454 } 11455 }); 11456 11457 this._processTabs(); 11458 options.active = this._initialActive(); 11459 11460 // Take disabling tabs via class attribute from HTML 11461 // into account and update option properly. 11462 if ( $.isArray( options.disabled ) ) { 11463 options.disabled = $.unique( options.disabled.concat( 11464 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { 11465 return that.tabs.index( li ); 11466 }) 11467 ) ).sort(); 11468 } 11469 11470 // check for length avoids error when initializing empty list 11471 if ( this.options.active !== false && this.anchors.length ) { 11472 this.active = this._findActive( options.active ); 11473 } else { 11474 this.active = $(); 11475 } 11476 11477 this._refresh(); 11478 11479 if ( this.active.length ) { 11480 this.load( options.active ); 11481 } 11482 }, 11483 11484 _initialActive: function() { 11485 var active = this.options.active, 11486 collapsible = this.options.collapsible, 11487 locationHash = location.hash.substring( 1 ); 11488 11489 if ( active === null ) { 11490 // check the fragment identifier in the URL 11491 if ( locationHash ) { 11492 this.tabs.each(function( i, tab ) { 11493 if ( $( tab ).attr( "aria-controls" ) === locationHash ) { 11494 active = i; 11495 return false; 11496 } 11497 }); 11498 } 11499 11500 // check for a tab marked active via a class 11501 if ( active === null ) { 11502 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); 11503 } 11504 11505 // no active tab, set to false 11506 if ( active === null || active === -1 ) { 11507 active = this.tabs.length ? 0 : false; 11508 } 11509 } 11510 11511 // handle numbers: negative, out of range 11512 if ( active !== false ) { 11513 active = this.tabs.index( this.tabs.eq( active ) ); 11514 if ( active === -1 ) { 11515 active = collapsible ? false : 0; 11516 } 11517 } 11518 11519 // don't allow collapsible: false and active: false 11520 if ( !collapsible && active === false && this.anchors.length ) { 11521 active = 0; 11522 } 11523 11524 return active; 11525 }, 11526 11527 _getCreateEventData: function() { 11528 return { 11529 tab: this.active, 11530 panel: !this.active.length ? $() : this._getPanelForTab( this.active ) 11531 }; 11532 }, 11533 11534 _tabKeydown: function( event ) { 11535 /*jshint maxcomplexity:15*/ 11536 var focusedTab = $( this.document[0].activeElement ).closest( "li" ), 11537 selectedIndex = this.tabs.index( focusedTab ), 11538 goingForward = true; 11539 11540 if ( this._handlePageNav( event ) ) { 11541 return; 11542 } 11543 11544 switch ( event.keyCode ) { 11545 case $.ui.keyCode.RIGHT: 11546 case $.ui.keyCode.DOWN: 11547 selectedIndex++; 11548 break; 11549 case $.ui.keyCode.UP: 11550 case $.ui.keyCode.LEFT: 11551 goingForward = false; 11552 selectedIndex--; 11553 break; 11554 case $.ui.keyCode.END: 11555 selectedIndex = this.anchors.length - 1; 11556 break; 11557 case $.ui.keyCode.HOME: 11558 selectedIndex = 0; 11559 break; 11560 case $.ui.keyCode.SPACE: 11561 // Activate only, no collapsing 11562 event.preventDefault(); 11563 clearTimeout( this.activating ); 11564 this._activate( selectedIndex ); 11565 return; 11566 case $.ui.keyCode.ENTER: 11567 // Toggle (cancel delayed activation, allow collapsing) 11568 event.preventDefault(); 11569 clearTimeout( this.activating ); 11570 // Determine if we should collapse or activate 11571 this._activate( selectedIndex === this.options.active ? false : selectedIndex ); 11572 return; 11573 default: 11574 return; 11575 } 11576 11577 // Focus the appropriate tab, based on which key was pressed 11578 event.preventDefault(); 11579 clearTimeout( this.activating ); 11580 selectedIndex = this._focusNextTab( selectedIndex, goingForward ); 11581 11582 // Navigating with control key will prevent automatic activation 11583 if ( !event.ctrlKey ) { 11584 // Update aria-selected immediately so that AT think the tab is already selected. 11585 // Otherwise AT may confuse the user by stating that they need to activate the tab, 11586 // but the tab will already be activated by the time the announcement finishes. 11587 focusedTab.attr( "aria-selected", "false" ); 11588 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); 11589 11590 this.activating = this._delay(function() { 11591 this.option( "active", selectedIndex ); 11592 }, this.delay ); 11593 } 11594 }, 11595 11596 _panelKeydown: function( event ) { 11597 if ( this._handlePageNav( event ) ) { 11598 return; 11599 } 11600 11601 // Ctrl+up moves focus to the current tab 11602 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { 11603 event.preventDefault(); 11604 this.active.focus(); 11605 } 11606 }, 11607 11608 // Alt+page up/down moves focus to the previous/next tab (and activates) 11609 _handlePageNav: function( event ) { 11610 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { 11611 this._activate( this._focusNextTab( this.options.active - 1, false ) ); 11612 return true; 11613 } 11614 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { 11615 this._activate( this._focusNextTab( this.options.active + 1, true ) ); 11616 return true; 11617 } 11618 }, 11619 11620 _findNextTab: function( index, goingForward ) { 11621 var lastTabIndex = this.tabs.length - 1; 11622 11623 function constrain() { 11624 if ( index > lastTabIndex ) { 11625 index = 0; 11626 } 11627 if ( index < 0 ) { 11628 index = lastTabIndex; 11629 } 11630 return index; 11631 } 11632 11633 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { 11634 index = goingForward ? index + 1 : index - 1; 11635 } 11636 11637 return index; 11638 }, 11639 11640 _focusNextTab: function( index, goingForward ) { 11641 index = this._findNextTab( index, goingForward ); 11642 this.tabs.eq( index ).focus(); 11643 return index; 11644 }, 11645 11646 _setOption: function( key, value ) { 11647 if ( key === "active" ) { 11648 // _activate() will handle invalid values and update this.options 11649 this._activate( value ); 11650 return; 11651 } 11652 11653 if ( key === "disabled" ) { 11654 // don't use the widget factory's disabled handling 11655 this._setupDisabled( value ); 11656 return; 11657 } 11658 11659 this._super( key, value); 11660 11661 if ( key === "collapsible" ) { 11662 this.element.toggleClass( "ui-tabs-collapsible", value ); 11663 // Setting collapsible: false while collapsed; open first panel 11664 if ( !value && this.options.active === false ) { 11665 this._activate( 0 ); 11666 } 11667 } 11668 11669 if ( key === "event" ) { 11670 this._setupEvents( value ); 11671 } 11672 11673 if ( key === "heightStyle" ) { 11674 this._setupHeightStyle( value ); 11675 } 11676 }, 11677 11678 _tabId: function( tab ) { 11679 return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId(); 11680 }, 11681 11682 _sanitizeSelector: function( hash ) { 11683 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : ""; 11684 }, 11685 11686 refresh: function() { 11687 var options = this.options, 11688 lis = this.tablist.children( ":has(a[href])" ); 11689 11690 // get disabled tabs from class attribute from HTML 11691 // this will get converted to a boolean if needed in _refresh() 11692 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { 11693 return lis.index( tab ); 11694 }); 11695 11696 this._processTabs(); 11697 11698 // was collapsed or no tabs 11699 if ( options.active === false || !this.anchors.length ) { 11700 options.active = false; 11701 this.active = $(); 11702 // was active, but active tab is gone 11703 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { 11704 // all remaining tabs are disabled 11705 if ( this.tabs.length === options.disabled.length ) { 11706 options.active = false; 11707 this.active = $(); 11708 // activate previous tab 11709 } else { 11710 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); 11711 } 11712 // was active, active tab still exists 11713 } else { 11714 // make sure active index is correct 11715 options.active = this.tabs.index( this.active ); 11716 } 11717 11718 this._refresh(); 11719 }, 11720 11721 _refresh: function() { 11722 this._setupDisabled( this.options.disabled ); 11723 this._setupEvents( this.options.event ); 11724 this._setupHeightStyle( this.options.heightStyle ); 11725 11726 this.tabs.not( this.active ).attr({ 11727 "aria-selected": "false", 11728 tabIndex: -1 11729 }); 11730 this.panels.not( this._getPanelForTab( this.active ) ) 11731 .hide() 11732 .attr({ 11733 "aria-expanded": "false", 11734 "aria-hidden": "true" 11735 }); 11736 11737 // Make sure one tab is in the tab order 11738 if ( !this.active.length ) { 11739 this.tabs.eq( 0 ).attr( "tabIndex", 0 ); 11740 } else { 11741 this.active 11742 .addClass( "ui-tabs-active ui-state-active" ) 11743 .attr({ 11744 "aria-selected": "true", 11745 tabIndex: 0 11746 }); 11747 this._getPanelForTab( this.active ) 11748 .show() 11749 .attr({ 11750 "aria-expanded": "true", 11751 "aria-hidden": "false" 11752 }); 11753 } 11754 }, 11755 11756 _processTabs: function() { 11757 var that = this; 11758 11759 this.tablist = this._getList() 11760 .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) 11761 .attr( "role", "tablist" ); 11762 11763 this.tabs = this.tablist.find( "> li:has(a[href])" ) 11764 .addClass( "ui-state-default ui-corner-top" ) 11765 .attr({ 11766 role: "tab", 11767 tabIndex: -1 11768 }); 11769 11770 this.anchors = this.tabs.map(function() { 11771 return $( "a", this )[ 0 ]; 11772 }) 11773 .addClass( "ui-tabs-anchor" ) 11774 .attr({ 11775 role: "presentation", 11776 tabIndex: -1 11777 }); 11778 11779 this.panels = $(); 11780 11781 this.anchors.each(function( i, anchor ) { 11782 var selector, panel, panelId, 11783 anchorId = $( anchor ).uniqueId().attr( "id" ), 11784 tab = $( anchor ).closest( "li" ), 11785 originalAriaControls = tab.attr( "aria-controls" ); 11786 11787 // inline tab 11788 if ( isLocal( anchor ) ) { 11789 selector = anchor.hash; 11790 panel = that.element.find( that._sanitizeSelector( selector ) ); 11791 // remote tab 11792 } else { 11793 panelId = that._tabId( tab ); 11794 selector = "#" + panelId; 11795 panel = that.element.find( selector ); 11796 if ( !panel.length ) { 11797 panel = that._createPanel( panelId ); 11798 panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); 11799 } 11800 panel.attr( "aria-live", "polite" ); 11801 } 11802 11803 if ( panel.length) { 11804 that.panels = that.panels.add( panel ); 11805 } 11806 if ( originalAriaControls ) { 11807 tab.data( "ui-tabs-aria-controls", originalAriaControls ); 11808 } 11809 tab.attr({ 11810 "aria-controls": selector.substring( 1 ), 11811 "aria-labelledby": anchorId 11812 }); 11813 panel.attr( "aria-labelledby", anchorId ); 11814 }); 11815 11816 this.panels 11817 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) 11818 .attr( "role", "tabpanel" ); 11819 }, 11820 11821 // allow overriding how to find the list for rare usage scenarios (#7715) 11822 _getList: function() { 11823 return this.element.find( "ol,ul" ).eq( 0 ); 11824 }, 11825 11826 _createPanel: function( id ) { 11827 return $( "<div>" ) 11828 .attr( "id", id ) 11829 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) 11830 .data( "ui-tabs-destroy", true ); 11831 }, 11832 11833 _setupDisabled: function( disabled ) { 11834 if ( $.isArray( disabled ) ) { 11835 if ( !disabled.length ) { 11836 disabled = false; 11837 } else if ( disabled.length === this.anchors.length ) { 11838 disabled = true; 11839 } 11840 } 11841 11842 // disable tabs 11843 for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) { 11844 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { 11845 $( li ) 11846 .addClass( "ui-state-disabled" ) 11847 .attr( "aria-disabled", "true" ); 11848 } else { 11849 $( li ) 11850 .removeClass( "ui-state-disabled" ) 11851 .removeAttr( "aria-disabled" ); 11852 } 11853 } 11854 11855 this.options.disabled = disabled; 11856 }, 11857 11858 _setupEvents: function( event ) { 11859 var events = { 11860 click: function( event ) { 11861 event.preventDefault(); 11862 } 11863 }; 11864 if ( event ) { 11865 $.each( event.split(" "), function( index, eventName ) { 11866 events[ eventName ] = "_eventHandler"; 11867 }); 11868 } 11869 11870 this._off( this.anchors.add( this.tabs ).add( this.panels ) ); 11871 this._on( this.anchors, events ); 11872 this._on( this.tabs, { keydown: "_tabKeydown" } ); 11873 this._on( this.panels, { keydown: "_panelKeydown" } ); 11874 11875 this._focusable( this.tabs ); 11876 this._hoverable( this.tabs ); 11877 }, 11878 11879 _setupHeightStyle: function( heightStyle ) { 11880 var maxHeight, 11881 parent = this.element.parent(); 11882 11883 if ( heightStyle === "fill" ) { 11884 maxHeight = parent.height(); 11885 maxHeight -= this.element.outerHeight() - this.element.height(); 11886 11887 this.element.siblings( ":visible" ).each(function() { 11888 var elem = $( this ), 11889 position = elem.css( "position" ); 11890 11891 if ( position === "absolute" || position === "fixed" ) { 11892 return; 11893 } 11894 maxHeight -= elem.outerHeight( true ); 11895 }); 11896 11897 this.element.children().not( this.panels ).each(function() { 11898 maxHeight -= $( this ).outerHeight( true ); 11899 }); 11900 11901 this.panels.each(function() { 11902 $( this ).height( Math.max( 0, maxHeight - 11903 $( this ).innerHeight() + $( this ).height() ) ); 11904 }) 11905 .css( "overflow", "auto" ); 11906 } else if ( heightStyle === "auto" ) { 11907 maxHeight = 0; 11908 this.panels.each(function() { 11909 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); 11910 }).height( maxHeight ); 11911 } 11912 }, 11913 11914 _eventHandler: function( event ) { 11915 var options = this.options, 11916 active = this.active, 11917 anchor = $( event.currentTarget ), 11918 tab = anchor.closest( "li" ), 11919 clickedIsActive = tab[ 0 ] === active[ 0 ], 11920 collapsing = clickedIsActive && options.collapsible, 11921 toShow = collapsing ? $() : this._getPanelForTab( tab ), 11922 toHide = !active.length ? $() : this._getPanelForTab( active ), 11923 eventData = { 11924 oldTab: active, 11925 oldPanel: toHide, 11926 newTab: collapsing ? $() : tab, 11927 newPanel: toShow 11928 }; 11929 11930 event.preventDefault(); 11931 11932 if ( tab.hasClass( "ui-state-disabled" ) || 11933 // tab is already loading 11934 tab.hasClass( "ui-tabs-loading" ) || 11935 // can't switch durning an animation 11936 this.running || 11937 // click on active header, but not collapsible 11938 ( clickedIsActive && !options.collapsible ) || 11939 // allow canceling activation 11940 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 11941 return; 11942 } 11943 11944 options.active = collapsing ? false : this.tabs.index( tab ); 11945 11946 this.active = clickedIsActive ? $() : tab; 11947 if ( this.xhr ) { 11948 this.xhr.abort(); 11949 } 11950 11951 if ( !toHide.length && !toShow.length ) { 11952 $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); 11953 } 11954 11955 if ( toShow.length ) { 11956 this.load( this.tabs.index( tab ), event ); 11957 } 11958 this._toggle( event, eventData ); 11959 }, 11960 11961 // handles show/hide for selecting tabs 11962 _toggle: function( event, eventData ) { 11963 var that = this, 11964 toShow = eventData.newPanel, 11965 toHide = eventData.oldPanel; 11966 11967 this.running = true; 11968 11969 function complete() { 11970 that.running = false; 11971 that._trigger( "activate", event, eventData ); 11972 } 11973 11974 function show() { 11975 eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); 11976 11977 if ( toShow.length && that.options.show ) { 11978 that._show( toShow, that.options.show, complete ); 11979 } else { 11980 toShow.show(); 11981 complete(); 11982 } 11983 } 11984 11985 // start out by hiding, then showing, then completing 11986 if ( toHide.length && this.options.hide ) { 11987 this._hide( toHide, this.options.hide, function() { 11988 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); 11989 show(); 11990 }); 11991 } else { 11992 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); 11993 toHide.hide(); 11994 show(); 11995 } 11996 11997 toHide.attr({ 11998 "aria-expanded": "false", 11999 "aria-hidden": "true" 12000 }); 12001 eventData.oldTab.attr( "aria-selected", "false" ); 12002 // If we're switching tabs, remove the old tab from the tab order. 12003 // If we're opening from collapsed state, remove the previous tab from the tab order. 12004 // If we're collapsing, then keep the collapsing tab in the tab order. 12005 if ( toShow.length && toHide.length ) { 12006 eventData.oldTab.attr( "tabIndex", -1 ); 12007 } else if ( toShow.length ) { 12008 this.tabs.filter(function() { 12009 return $( this ).attr( "tabIndex" ) === 0; 12010 }) 12011 .attr( "tabIndex", -1 ); 12012 } 12013 12014 toShow.attr({ 12015 "aria-expanded": "true", 12016 "aria-hidden": "false" 12017 }); 12018 eventData.newTab.attr({ 12019 "aria-selected": "true", 12020 tabIndex: 0 12021 }); 12022 }, 12023 12024 _activate: function( index ) { 12025 var anchor, 12026 active = this._findActive( index ); 12027 12028 // trying to activate the already active panel 12029 if ( active[ 0 ] === this.active[ 0 ] ) { 12030 return; 12031 } 12032 12033 // trying to collapse, simulate a click on the current active header 12034 if ( !active.length ) { 12035 active = this.active; 12036 } 12037 12038 anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; 12039 this._eventHandler({ 12040 target: anchor, 12041 currentTarget: anchor, 12042 preventDefault: $.noop 12043 }); 12044 }, 12045 12046 _findActive: function( index ) { 12047 return index === false ? $() : this.tabs.eq( index ); 12048 }, 12049 12050 _getIndex: function( index ) { 12051 // meta-function to give users option to provide a href string instead of a numerical index. 12052 if ( typeof index === "string" ) { 12053 index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) ); 12054 } 12055 12056 return index; 12057 }, 12058 12059 _destroy: function() { 12060 if ( this.xhr ) { 12061 this.xhr.abort(); 12062 } 12063 12064 this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ); 12065 12066 this.tablist 12067 .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) 12068 .removeAttr( "role" ); 12069 12070 this.anchors 12071 .removeClass( "ui-tabs-anchor" ) 12072 .removeAttr( "role" ) 12073 .removeAttr( "tabIndex" ) 12074 .removeUniqueId(); 12075 12076 this.tabs.add( this.panels ).each(function() { 12077 if ( $.data( this, "ui-tabs-destroy" ) ) { 12078 $( this ).remove(); 12079 } else { 12080 $( this ) 12081 .removeClass( "ui-state-default ui-state-active ui-state-disabled " + 12082 "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" ) 12083 .removeAttr( "tabIndex" ) 12084 .removeAttr( "aria-live" ) 12085 .removeAttr( "aria-busy" ) 12086 .removeAttr( "aria-selected" ) 12087 .removeAttr( "aria-labelledby" ) 12088 .removeAttr( "aria-hidden" ) 12089 .removeAttr( "aria-expanded" ) 12090 .removeAttr( "role" ); 12091 } 12092 }); 12093 12094 this.tabs.each(function() { 12095 var li = $( this ), 12096 prev = li.data( "ui-tabs-aria-controls" ); 12097 if ( prev ) { 12098 li 12099 .attr( "aria-controls", prev ) 12100 .removeData( "ui-tabs-aria-controls" ); 12101 } else { 12102 li.removeAttr( "aria-controls" ); 12103 } 12104 }); 12105 12106 this.panels.show(); 12107 12108 if ( this.options.heightStyle !== "content" ) { 12109 this.panels.css( "height", "" ); 12110 } 12111 }, 12112 12113 enable: function( index ) { 12114 var disabled = this.options.disabled; 12115 if ( disabled === false ) { 12116 return; 12117 } 12118 12119 if ( index === undefined ) { 12120 disabled = false; 12121 } else { 12122 index = this._getIndex( index ); 12123 if ( $.isArray( disabled ) ) { 12124 disabled = $.map( disabled, function( num ) { 12125 return num !== index ? num : null; 12126 }); 12127 } else { 12128 disabled = $.map( this.tabs, function( li, num ) { 12129 return num !== index ? num : null; 12130 }); 12131 } 12132 } 12133 this._setupDisabled( disabled ); 12134 }, 12135 12136 disable: function( index ) { 12137 var disabled = this.options.disabled; 12138 if ( disabled === true ) { 12139 return; 12140 } 12141 12142 if ( index === undefined ) { 12143 disabled = true; 12144 } else { 12145 index = this._getIndex( index ); 12146 if ( $.inArray( index, disabled ) !== -1 ) { 12147 return; 12148 } 12149 if ( $.isArray( disabled ) ) { 12150 disabled = $.merge( [ index ], disabled ).sort(); 12151 } else { 12152 disabled = [ index ]; 12153 } 12154 } 12155 this._setupDisabled( disabled ); 12156 }, 12157 12158 load: function( index, event ) { 12159 index = this._getIndex( index ); 12160 var that = this, 12161 tab = this.tabs.eq( index ), 12162 anchor = tab.find( ".ui-tabs-anchor" ), 12163 panel = this._getPanelForTab( tab ), 12164 eventData = { 12165 tab: tab, 12166 panel: panel 12167 }; 12168 12169 // not remote 12170 if ( isLocal( anchor[ 0 ] ) ) { 12171 return; 12172 } 12173 12174 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); 12175 12176 // support: jQuery <1.8 12177 // jQuery <1.8 returns false if the request is canceled in beforeSend, 12178 // but as of 1.8, $.ajax() always returns a jqXHR object. 12179 if ( this.xhr && this.xhr.statusText !== "canceled" ) { 12180 tab.addClass( "ui-tabs-loading" ); 12181 panel.attr( "aria-busy", "true" ); 12182 12183 this.xhr 12184 .success(function( response ) { 12185 // support: jQuery <1.8 12186 // http://bugs.jquery.com/ticket/11778 12187 setTimeout(function() { 12188 panel.html( response ); 12189 that._trigger( "load", event, eventData ); 12190 }, 1 ); 12191 }) 12192 .complete(function( jqXHR, status ) { 12193 // support: jQuery <1.8 12194 // http://bugs.jquery.com/ticket/11778 12195 setTimeout(function() { 12196 if ( status === "abort" ) { 12197 that.panels.stop( false, true ); 12198 } 12199 12200 tab.removeClass( "ui-tabs-loading" ); 12201 panel.removeAttr( "aria-busy" ); 12202 12203 if ( jqXHR === that.xhr ) { 12204 delete that.xhr; 12205 } 12206 }, 1 ); 12207 }); 12208 } 12209 }, 12210 12211 _ajaxSettings: function( anchor, event, eventData ) { 12212 var that = this; 12213 return { 12214 url: anchor.attr( "href" ), 12215 beforeSend: function( jqXHR, settings ) { 12216 return that._trigger( "beforeLoad", event, 12217 $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) ); 12218 } 12219 }; 12220 }, 12221 12222 _getPanelForTab: function( tab ) { 12223 var id = $( tab ).attr( "aria-controls" ); 12224 return this.element.find( this._sanitizeSelector( "#" + id ) ); 12225 } 12226}); 12227 12228})( jQuery ); 12229(function( $ ) { 12230 12231var increments = 0; 12232 12233function addDescribedBy( elem, id ) { 12234 var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ); 12235 describedby.push( id ); 12236 elem 12237 .data( "ui-tooltip-id", id ) 12238 .attr( "aria-describedby", $.trim( describedby.join( " " ) ) ); 12239} 12240 12241function removeDescribedBy( elem ) { 12242 var id = elem.data( "ui-tooltip-id" ), 12243 describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ), 12244 index = $.inArray( id, describedby ); 12245 if ( index !== -1 ) { 12246 describedby.splice( index, 1 ); 12247 } 12248 12249 elem.removeData( "ui-tooltip-id" ); 12250 describedby = $.trim( describedby.join( " " ) ); 12251 if ( describedby ) { 12252 elem.attr( "aria-describedby", describedby ); 12253 } else { 12254 elem.removeAttr( "aria-describedby" ); 12255 } 12256} 12257 12258$.widget( "ui.tooltip", { 12259 version: "1.10.0", 12260 options: { 12261 content: function() { 12262 // support: IE<9, Opera in jQuery <1.7 12263 // .text() can't accept undefined, so coerce to a string 12264 var title = $( this ).attr( "title" ) || ""; 12265 // Escape title, since we're going from an attribute to raw HTML 12266 return $( "<a>" ).text( title ).html(); 12267 }, 12268 hide: true, 12269 // Disabled elements have inconsistent behavior across browsers (#8661) 12270 items: "[title]:not([disabled])", 12271 position: { 12272 my: "left top+15", 12273 at: "left bottom", 12274 collision: "flipfit flip" 12275 }, 12276 show: true, 12277 tooltipClass: null, 12278 track: false, 12279 12280 // callbacks 12281 close: null, 12282 open: null 12283 }, 12284 12285 _create: function() { 12286 this._on({ 12287 mouseover: "open", 12288 focusin: "open" 12289 }); 12290 12291 // IDs of generated tooltips, needed for destroy 12292 this.tooltips = {}; 12293 // IDs of parent tooltips where we removed the title attribute 12294 this.parents = {}; 12295 12296 if ( this.options.disabled ) { 12297 this._disable(); 12298 } 12299 }, 12300 12301 _setOption: function( key, value ) { 12302 var that = this; 12303 12304 if ( key === "disabled" ) { 12305 this[ value ? "_disable" : "_enable" ](); 12306 this.options[ key ] = value; 12307 // disable element style changes 12308 return; 12309 } 12310 12311 this._super( key, value ); 12312 12313 if ( key === "content" ) { 12314 $.each( this.tooltips, function( id, element ) { 12315 that._updateContent( element ); 12316 }); 12317 } 12318 }, 12319 12320 _disable: function() { 12321 var that = this; 12322 12323 // close open tooltips 12324 $.each( this.tooltips, function( id, element ) { 12325 var event = $.Event( "blur" ); 12326 event.target = event.currentTarget = element[0]; 12327 that.close( event, true ); 12328 }); 12329 12330 // remove title attributes to prevent native tooltips 12331 this.element.find( this.options.items ).addBack().each(function() { 12332 var element = $( this ); 12333 if ( element.is( "[title]" ) ) { 12334 element 12335 .data( "ui-tooltip-title", element.attr( "title" ) ) 12336 .attr( "title", "" ); 12337 } 12338 }); 12339 }, 12340 12341 _enable: function() { 12342 // restore title attributes 12343 this.element.find( this.options.items ).addBack().each(function() { 12344 var element = $( this ); 12345 if ( element.data( "ui-tooltip-title" ) ) { 12346 element.attr( "title", element.data( "ui-tooltip-title" ) ); 12347 } 12348 }); 12349 }, 12350 12351 open: function( event ) { 12352 var that = this, 12353 target = $( event ? event.target : this.element ) 12354 // we need closest here due to mouseover bubbling, 12355 // but always pointing at the same event target 12356 .closest( this.options.items ); 12357 12358 // No element to show a tooltip for or the tooltip is already open 12359 if ( !target.length || target.data( "ui-tooltip-id" ) ) { 12360 return; 12361 } 12362 12363 if ( target.attr( "title" ) ) { 12364 target.data( "ui-tooltip-title", target.attr( "title" ) ); 12365 } 12366 12367 target.data( "ui-tooltip-open", true ); 12368 12369 // kill parent tooltips, custom or native, for hover 12370 if ( event && event.type === "mouseover" ) { 12371 target.parents().each(function() { 12372 var parent = $( this ), 12373 blurEvent; 12374 if ( parent.data( "ui-tooltip-open" ) ) { 12375 blurEvent = $.Event( "blur" ); 12376 blurEvent.target = blurEvent.currentTarget = this; 12377 that.close( blurEvent, true ); 12378 } 12379 if ( parent.attr( "title" ) ) { 12380 parent.uniqueId(); 12381 that.parents[ this.id ] = { 12382 element: this, 12383 title: parent.attr( "title" ) 12384 }; 12385 parent.attr( "title", "" ); 12386 } 12387 }); 12388 } 12389 12390 this._updateContent( target, event ); 12391 }, 12392 12393 _updateContent: function( target, event ) { 12394 var content, 12395 contentOption = this.options.content, 12396 that = this, 12397 eventType = event ? event.type : null; 12398 12399 if ( typeof contentOption === "string" ) { 12400 return this._open( event, target, contentOption ); 12401 } 12402 12403 content = contentOption.call( target[0], function( response ) { 12404 // ignore async response if tooltip was closed already 12405 if ( !target.data( "ui-tooltip-open" ) ) { 12406 return; 12407 } 12408 // IE may instantly serve a cached response for ajax requests 12409 // delay this call to _open so the other call to _open runs first 12410 that._delay(function() { 12411 // jQuery creates a special event for focusin when it doesn't 12412 // exist natively. To improve performance, the native event 12413 // object is reused and the type is changed. Therefore, we can't 12414 // rely on the type being correct after the event finished 12415 // bubbling, so we set it back to the previous value. (#8740) 12416 if ( event ) { 12417 event.type = eventType; 12418 } 12419 this._open( event, target, response ); 12420 }); 12421 }); 12422 if ( content ) { 12423 this._open( event, target, content ); 12424 } 12425 }, 12426 12427 _open: function( event, target, content ) { 12428 var tooltip, events, delayedShow, 12429 positionOption = $.extend( {}, this.options.position ); 12430 12431 if ( !content ) { 12432 return; 12433 } 12434 12435 // Content can be updated multiple times. If the tooltip already 12436 // exists, then just update the content and bail. 12437 tooltip = this._find( target ); 12438 if ( tooltip.length ) { 12439 tooltip.find( ".ui-tooltip-content" ).html( content ); 12440 return; 12441 } 12442 12443 // if we have a title, clear it to prevent the native tooltip 12444 // we have to check first to avoid defining a title if none exists 12445 // (we don't want to cause an element to start matching [title]) 12446 // 12447 // We use removeAttr only for key events, to allow IE to export the correct 12448 // accessible attributes. For mouse events, set to empty string to avoid 12449 // native tooltip showing up (happens only when removing inside mouseover). 12450 if ( target.is( "[title]" ) ) { 12451 if ( event && event.type === "mouseover" ) { 12452 target.attr( "title", "" ); 12453 } else { 12454 target.removeAttr( "title" ); 12455 } 12456 } 12457 12458 tooltip = this._tooltip( target ); 12459 addDescribedBy( target, tooltip.attr( "id" ) ); 12460 tooltip.find( ".ui-tooltip-content" ).html( content ); 12461 12462 function position( event ) { 12463 positionOption.of = event; 12464 if ( tooltip.is( ":hidden" ) ) { 12465 return; 12466 } 12467 tooltip.position( positionOption ); 12468 } 12469 if ( this.options.track && event && /^mouse/.test( event.type ) ) { 12470 this._on( this.document, { 12471 mousemove: position 12472 }); 12473 // trigger once to override element-relative positioning 12474 position( event ); 12475 } else { 12476 tooltip.position( $.extend({ 12477 of: target 12478 }, this.options.position ) ); 12479 } 12480 12481 tooltip.hide(); 12482 12483 this._show( tooltip, this.options.show ); 12484 // Handle tracking tooltips that are shown with a delay (#8644). As soon 12485 // as the tooltip is visible, position the tooltip using the most recent 12486 // event. 12487 if ( this.options.show && this.options.show.delay ) { 12488 delayedShow = this.delayedShow = setInterval(function() { 12489 if ( tooltip.is( ":visible" ) ) { 12490 position( positionOption.of ); 12491 clearInterval( delayedShow ); 12492 } 12493 }, $.fx.interval ); 12494 } 12495 12496 this._trigger( "open", event, { tooltip: tooltip } ); 12497 12498 events = { 12499 keyup: function( event ) { 12500 if ( event.keyCode === $.ui.keyCode.ESCAPE ) { 12501 var fakeEvent = $.Event(event); 12502 fakeEvent.currentTarget = target[0]; 12503 this.close( fakeEvent, true ); 12504 } 12505 }, 12506 remove: function() { 12507 this._removeTooltip( tooltip ); 12508 } 12509 }; 12510 if ( !event || event.type === "mouseover" ) { 12511 events.mouseleave = "close"; 12512 } 12513 if ( !event || event.type === "focusin" ) { 12514 events.focusout = "close"; 12515 } 12516 this._on( true, target, events ); 12517 }, 12518 12519 close: function( event ) { 12520 var that = this, 12521 target = $( event ? event.currentTarget : this.element ), 12522 tooltip = this._find( target ); 12523 12524 // disabling closes the tooltip, so we need to track when we're closing 12525 // to avoid an infinite loop in case the tooltip becomes disabled on close 12526 if ( this.closing ) { 12527 return; 12528 } 12529 12530 // Clear the interval for delayed tracking tooltips 12531 clearInterval( this.delayedShow ); 12532 12533 // only set title if we had one before (see comment in _open()) 12534 if ( target.data( "ui-tooltip-title" ) ) { 12535 target.attr( "title", target.data( "ui-tooltip-title" ) ); 12536 } 12537 12538 removeDescribedBy( target ); 12539 12540 tooltip.stop( true ); 12541 this._hide( tooltip, this.options.hide, function() { 12542 that._removeTooltip( $( this ) ); 12543 }); 12544 12545 target.removeData( "ui-tooltip-open" ); 12546 this._off( target, "mouseleave focusout keyup" ); 12547 // Remove 'remove' binding only on delegated targets 12548 if ( target[0] !== this.element[0] ) { 12549 this._off( target, "remove" ); 12550 } 12551 this._off( this.document, "mousemove" ); 12552 12553 if ( event && event.type === "mouseleave" ) { 12554 $.each( this.parents, function( id, parent ) { 12555 $( parent.element ).attr( "title", parent.title ); 12556 delete that.parents[ id ]; 12557 }); 12558 } 12559 12560 this.closing = true; 12561 this._trigger( "close", event, { tooltip: tooltip } ); 12562 this.closing = false; 12563 }, 12564 12565 _tooltip: function( element ) { 12566 var id = "ui-tooltip-" + increments++, 12567 tooltip = $( "<div>" ) 12568 .attr({ 12569 id: id, 12570 role: "tooltip" 12571 }) 12572 .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " + 12573 ( this.options.tooltipClass || "" ) ); 12574 $( "<div>" ) 12575 .addClass( "ui-tooltip-content" ) 12576 .appendTo( tooltip ); 12577 tooltip.appendTo( this.document[0].body ); 12578 this.tooltips[ id ] = element; 12579 return tooltip; 12580 }, 12581 12582 _find: function( target ) { 12583 var id = target.data( "ui-tooltip-id" ); 12584 return id ? $( "#" + id ) : $(); 12585 }, 12586 12587 _removeTooltip: function( tooltip ) { 12588 tooltip.remove(); 12589 delete this.tooltips[ tooltip.attr( "id" ) ]; 12590 }, 12591 12592 _destroy: function() { 12593 var that = this; 12594 12595 // close open tooltips 12596 $.each( this.tooltips, function( id, element ) { 12597 // Delegate to close method to handle common cleanup 12598 var event = $.Event( "blur" ); 12599 event.target = event.currentTarget = element[0]; 12600 that.close( event, true ); 12601 12602 // Remove immediately; destroying an open tooltip doesn't use the 12603 // hide animation 12604 $( "#" + id ).remove(); 12605 12606 // Restore the title 12607 if ( element.data( "ui-tooltip-title" ) ) { 12608 element.attr( "title", element.data( "ui-tooltip-title" ) ); 12609 element.removeData( "ui-tooltip-title" ); 12610 } 12611 }); 12612 } 12613}); 12614 12615}( jQuery ) ); 12616;(jQuery.effects || (function($, undefined) { 12617 12618var dataSpace = "ui-effects-"; 12619 12620$.effects = { 12621 effect: {} 12622}; 12623 12624/*! 12625 * jQuery Color Animations v2.1.2 12626 * https://github.com/jquery/jquery-color 12627 * 12628 * Copyright 2013 jQuery Foundation and other contributors 12629 * Released under the MIT license. 12630 * http://jquery.org/license 12631 * 12632 * Date: Wed Jan 16 08:47:09 2013 -0600 12633 */ 12634(function( jQuery, undefined ) { 12635 12636 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", 12637 12638 // plusequals test for += 100 -= 100 12639 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, 12640 // a set of RE's that can match strings and generate color tuples. 12641 stringParsers = [{ 12642 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 12643 parse: function( execResult ) { 12644 return [ 12645 execResult[ 1 ], 12646 execResult[ 2 ], 12647 execResult[ 3 ], 12648 execResult[ 4 ] 12649 ]; 12650 } 12651 }, { 12652 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 12653 parse: function( execResult ) { 12654 return [ 12655 execResult[ 1 ] * 2.55, 12656 execResult[ 2 ] * 2.55, 12657 execResult[ 3 ] * 2.55, 12658 execResult[ 4 ] 12659 ]; 12660 } 12661 }, { 12662 // this regex ignores A-F because it's compared against an already lowercased string 12663 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/, 12664 parse: function( execResult ) { 12665 return [ 12666 parseInt( execResult[ 1 ], 16 ), 12667 parseInt( execResult[ 2 ], 16 ), 12668 parseInt( execResult[ 3 ], 16 ) 12669 ]; 12670 } 12671 }, { 12672 // this regex ignores A-F because it's compared against an already lowercased string 12673 re: /#([a-f0-9])([a-f0-9])([a-f0-9])/, 12674 parse: function( execResult ) { 12675 return [ 12676 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), 12677 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), 12678 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ) 12679 ]; 12680 } 12681 }, { 12682 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 12683 space: "hsla", 12684 parse: function( execResult ) { 12685 return [ 12686 execResult[ 1 ], 12687 execResult[ 2 ] / 100, 12688 execResult[ 3 ] / 100, 12689 execResult[ 4 ] 12690 ]; 12691 } 12692 }], 12693 12694 // jQuery.Color( ) 12695 color = jQuery.Color = function( color, green, blue, alpha ) { 12696 return new jQuery.Color.fn.parse( color, green, blue, alpha ); 12697 }, 12698 spaces = { 12699 rgba: { 12700 props: { 12701 red: { 12702 idx: 0, 12703 type: "byte" 12704 }, 12705 green: { 12706 idx: 1, 12707 type: "byte" 12708 }, 12709 blue: { 12710 idx: 2, 12711 type: "byte" 12712 } 12713 } 12714 }, 12715 12716 hsla: { 12717 props: { 12718 hue: { 12719 idx: 0, 12720 type: "degrees" 12721 }, 12722 saturation: { 12723 idx: 1, 12724 type: "percent" 12725 }, 12726 lightness: { 12727 idx: 2, 12728 type: "percent" 12729 } 12730 } 12731 } 12732 }, 12733 propTypes = { 12734 "byte": { 12735 floor: true, 12736 max: 255 12737 }, 12738 "percent": { 12739 max: 1 12740 }, 12741 "degrees": { 12742 mod: 360, 12743 floor: true 12744 } 12745 }, 12746 support = color.support = {}, 12747 12748 // element for support tests 12749 supportElem = jQuery( "<p>" )[ 0 ], 12750 12751 // colors = jQuery.Color.names 12752 colors, 12753 12754 // local aliases of functions called often 12755 each = jQuery.each; 12756 12757// determine rgba support immediately 12758supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; 12759support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; 12760 12761// define cache name and alpha properties 12762// for rgba and hsla spaces 12763each( spaces, function( spaceName, space ) { 12764 space.cache = "_" + spaceName; 12765 space.props.alpha = { 12766 idx: 3, 12767 type: "percent", 12768 def: 1 12769 }; 12770}); 12771 12772function clamp( value, prop, allowEmpty ) { 12773 var type = propTypes[ prop.type ] || {}; 12774 12775 if ( value == null ) { 12776 return (allowEmpty || !prop.def) ? null : prop.def; 12777 } 12778 12779 // ~~ is an short way of doing floor for positive numbers 12780 value = type.floor ? ~~value : parseFloat( value ); 12781 12782 // IE will pass in empty strings as value for alpha, 12783 // which will hit this case 12784 if ( isNaN( value ) ) { 12785 return prop.def; 12786 } 12787 12788 if ( type.mod ) { 12789 // we add mod before modding to make sure that negatives values 12790 // get converted properly: -10 -> 350 12791 return (value + type.mod) % type.mod; 12792 } 12793 12794 // for now all property types without mod have min and max 12795 return 0 > value ? 0 : type.max < value ? type.max : value; 12796} 12797 12798function stringParse( string ) { 12799 var inst = color(), 12800 rgba = inst._rgba = []; 12801 12802 string = string.toLowerCase(); 12803 12804 each( stringParsers, function( i, parser ) { 12805 var parsed, 12806 match = parser.re.exec( string ), 12807 values = match && parser.parse( match ), 12808 spaceName = parser.space || "rgba"; 12809 12810 if ( values ) { 12811 parsed = inst[ spaceName ]( values ); 12812 12813 // if this was an rgba parse the assignment might happen twice 12814 // oh well.... 12815 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; 12816 rgba = inst._rgba = parsed._rgba; 12817 12818 // exit each( stringParsers ) here because we matched 12819 return false; 12820 } 12821 }); 12822 12823 // Found a stringParser that handled it 12824 if ( rgba.length ) { 12825 12826 // if this came from a parsed string, force "transparent" when alpha is 0 12827 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) 12828 if ( rgba.join() === "0,0,0,0" ) { 12829 jQuery.extend( rgba, colors.transparent ); 12830 } 12831 return inst; 12832 } 12833 12834 // named colors 12835 return colors[ string ]; 12836} 12837 12838color.fn = jQuery.extend( color.prototype, { 12839 parse: function( red, green, blue, alpha ) { 12840 if ( red === undefined ) { 12841 this._rgba = [ null, null, null, null ]; 12842 return this; 12843 } 12844 if ( red.jquery || red.nodeType ) { 12845 red = jQuery( red ).css( green ); 12846 green = undefined; 12847 } 12848 12849 var inst = this, 12850 type = jQuery.type( red ), 12851 rgba = this._rgba = []; 12852 12853 // more than 1 argument specified - assume ( red, green, blue, alpha ) 12854 if ( green !== undefined ) { 12855 red = [ red, green, blue, alpha ]; 12856 type = "array"; 12857 } 12858 12859 if ( type === "string" ) { 12860 return this.parse( stringParse( red ) || colors._default ); 12861 } 12862 12863 if ( type === "array" ) { 12864 each( spaces.rgba.props, function( key, prop ) { 12865 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); 12866 }); 12867 return this; 12868 } 12869 12870 if ( type === "object" ) { 12871 if ( red instanceof color ) { 12872 each( spaces, function( spaceName, space ) { 12873 if ( red[ space.cache ] ) { 12874 inst[ space.cache ] = red[ space.cache ].slice(); 12875 } 12876 }); 12877 } else { 12878 each( spaces, function( spaceName, space ) { 12879 var cache = space.cache; 12880 each( space.props, function( key, prop ) { 12881 12882 // if the cache doesn't exist, and we know how to convert 12883 if ( !inst[ cache ] && space.to ) { 12884 12885 // if the value was null, we don't need to copy it 12886 // if the key was alpha, we don't need to copy it either 12887 if ( key === "alpha" || red[ key ] == null ) { 12888 return; 12889 } 12890 inst[ cache ] = space.to( inst._rgba ); 12891 } 12892 12893 // this is the only case where we allow nulls for ALL properties. 12894 // call clamp with alwaysAllowEmpty 12895 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); 12896 }); 12897 12898 // everything defined but alpha? 12899 if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { 12900 // use the default of 1 12901 inst[ cache ][ 3 ] = 1; 12902 if ( space.from ) { 12903 inst._rgba = space.from( inst[ cache ] ); 12904 } 12905 } 12906 }); 12907 } 12908 return this; 12909 } 12910 }, 12911 is: function( compare ) { 12912 var is = color( compare ), 12913 same = true, 12914 inst = this; 12915 12916 each( spaces, function( _, space ) { 12917 var localCache, 12918 isCache = is[ space.cache ]; 12919 if (isCache) { 12920 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; 12921 each( space.props, function( _, prop ) { 12922 if ( isCache[ prop.idx ] != null ) { 12923 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); 12924 return same; 12925 } 12926 }); 12927 } 12928 return same; 12929 }); 12930 return same; 12931 }, 12932 _space: function() { 12933 var used = [], 12934 inst = this; 12935 each( spaces, function( spaceName, space ) { 12936 if ( inst[ space.cache ] ) { 12937 used.push( spaceName ); 12938 } 12939 }); 12940 return used.pop(); 12941 }, 12942 transition: function( other, distance ) { 12943 var end = color( other ), 12944 spaceName = end._space(), 12945 space = spaces[ spaceName ], 12946 startColor = this.alpha() === 0 ? color( "transparent" ) : this, 12947 start = startColor[ space.cache ] || space.to( startColor._rgba ), 12948 result = start.slice(); 12949 12950 end = end[ space.cache ]; 12951 each( space.props, function( key, prop ) { 12952 var index = prop.idx, 12953 startValue = start[ index ], 12954 endValue = end[ index ], 12955 type = propTypes[ prop.type ] || {}; 12956 12957 // if null, don't override start value 12958 if ( endValue === null ) { 12959 return; 12960 } 12961 // if null - use end 12962 if ( startValue === null ) { 12963 result[ index ] = endValue; 12964 } else { 12965 if ( type.mod ) { 12966 if ( endValue - startValue > type.mod / 2 ) { 12967 startValue += type.mod; 12968 } else if ( startValue - endValue > type.mod / 2 ) { 12969 startValue -= type.mod; 12970 } 12971 } 12972 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); 12973 } 12974 }); 12975 return this[ spaceName ]( result ); 12976 }, 12977 blend: function( opaque ) { 12978 // if we are already opaque - return ourself 12979 if ( this._rgba[ 3 ] === 1 ) { 12980 return this; 12981 } 12982 12983 var rgb = this._rgba.slice(), 12984 a = rgb.pop(), 12985 blend = color( opaque )._rgba; 12986 12987 return color( jQuery.map( rgb, function( v, i ) { 12988 return ( 1 - a ) * blend[ i ] + a * v; 12989 })); 12990 }, 12991 toRgbaString: function() { 12992 var prefix = "rgba(", 12993 rgba = jQuery.map( this._rgba, function( v, i ) { 12994 return v == null ? ( i > 2 ? 1 : 0 ) : v; 12995 }); 12996 12997 if ( rgba[ 3 ] === 1 ) { 12998 rgba.pop(); 12999 prefix = "rgb("; 13000 } 13001 13002 return prefix + rgba.join() + ")"; 13003 }, 13004 toHslaString: function() { 13005 var prefix = "hsla(", 13006 hsla = jQuery.map( this.hsla(), function( v, i ) { 13007 if ( v == null ) { 13008 v = i > 2 ? 1 : 0; 13009 } 13010 13011 // catch 1 and 2 13012 if ( i && i < 3 ) { 13013 v = Math.round( v * 100 ) + "%"; 13014 } 13015 return v; 13016 }); 13017 13018 if ( hsla[ 3 ] === 1 ) { 13019 hsla.pop(); 13020 prefix = "hsl("; 13021 } 13022 return prefix + hsla.join() + ")"; 13023 }, 13024 toHexString: function( includeAlpha ) { 13025 var rgba = this._rgba.slice(), 13026 alpha = rgba.pop(); 13027 13028 if ( includeAlpha ) { 13029 rgba.push( ~~( alpha * 255 ) ); 13030 } 13031 13032 return "#" + jQuery.map( rgba, function( v ) { 13033 13034 // default to 0 when nulls exist 13035 v = ( v || 0 ).toString( 16 ); 13036 return v.length === 1 ? "0" + v : v; 13037 }).join(""); 13038 }, 13039 toString: function() { 13040 return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); 13041 } 13042}); 13043color.fn.parse.prototype = color.fn; 13044 13045// hsla conversions adapted from: 13046// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 13047 13048function hue2rgb( p, q, h ) { 13049 h = ( h + 1 ) % 1; 13050 if ( h * 6 < 1 ) { 13051 return p + (q - p) * h * 6; 13052 } 13053 if ( h * 2 < 1) { 13054 return q; 13055 } 13056 if ( h * 3 < 2 ) { 13057 return p + (q - p) * ((2/3) - h) * 6; 13058 } 13059 return p; 13060} 13061 13062spaces.hsla.to = function ( rgba ) { 13063 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { 13064 return [ null, null, null, rgba[ 3 ] ]; 13065 } 13066 var r = rgba[ 0 ] / 255, 13067 g = rgba[ 1 ] / 255, 13068 b = rgba[ 2 ] / 255, 13069 a = rgba[ 3 ], 13070 max = Math.max( r, g, b ), 13071 min = Math.min( r, g, b ), 13072 diff = max - min, 13073 add = max + min, 13074 l = add * 0.5, 13075 h, s; 13076 13077 if ( min === max ) { 13078 h = 0; 13079 } else if ( r === max ) { 13080 h = ( 60 * ( g - b ) / diff ) + 360; 13081 } else if ( g === max ) { 13082 h = ( 60 * ( b - r ) / diff ) + 120; 13083 } else { 13084 h = ( 60 * ( r - g ) / diff ) + 240; 13085 } 13086 13087 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0% 13088 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) 13089 if ( diff === 0 ) { 13090 s = 0; 13091 } else if ( l <= 0.5 ) { 13092 s = diff / add; 13093 } else { 13094 s = diff / ( 2 - add ); 13095 } 13096 return [ Math.round(h) % 360, s, l, a == null ? 1 : a ]; 13097}; 13098 13099spaces.hsla.from = function ( hsla ) { 13100 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { 13101 return [ null, null, null, hsla[ 3 ] ]; 13102 } 13103 var h = hsla[ 0 ] / 360, 13104 s = hsla[ 1 ], 13105 l = hsla[ 2 ], 13106 a = hsla[ 3 ], 13107 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, 13108 p = 2 * l - q; 13109 13110 return [ 13111 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), 13112 Math.round( hue2rgb( p, q, h ) * 255 ), 13113 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), 13114 a 13115 ]; 13116}; 13117 13118 13119each( spaces, function( spaceName, space ) { 13120 var props = space.props, 13121 cache = space.cache, 13122 to = space.to, 13123 from = space.from; 13124 13125 // makes rgba() and hsla() 13126 color.fn[ spaceName ] = function( value ) { 13127 13128 // generate a cache for this space if it doesn't exist 13129 if ( to && !this[ cache ] ) { 13130 this[ cache ] = to( this._rgba ); 13131 } 13132 if ( value === undefined ) { 13133 return this[ cache ].slice(); 13134 } 13135 13136 var ret, 13137 type = jQuery.type( value ), 13138 arr = ( type === "array" || type === "object" ) ? value : arguments, 13139 local = this[ cache ].slice(); 13140 13141 each( props, function( key, prop ) { 13142 var val = arr[ type === "object" ? key : prop.idx ]; 13143 if ( val == null ) { 13144 val = local[ prop.idx ]; 13145 } 13146 local[ prop.idx ] = clamp( val, prop ); 13147 }); 13148 13149 if ( from ) { 13150 ret = color( from( local ) ); 13151 ret[ cache ] = local; 13152 return ret; 13153 } else { 13154 return color( local ); 13155 } 13156 }; 13157 13158 // makes red() green() blue() alpha() hue() saturation() lightness() 13159 each( props, function( key, prop ) { 13160 // alpha is included in more than one space 13161 if ( color.fn[ key ] ) { 13162 return; 13163 } 13164 color.fn[ key ] = function( value ) { 13165 var vtype = jQuery.type( value ), 13166 fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ), 13167 local = this[ fn ](), 13168 cur = local[ prop.idx ], 13169 match; 13170 13171 if ( vtype === "undefined" ) { 13172 return cur; 13173 } 13174 13175 if ( vtype === "function" ) { 13176 value = value.call( this, cur ); 13177 vtype = jQuery.type( value ); 13178 } 13179 if ( value == null && prop.empty ) { 13180 return this; 13181 } 13182 if ( vtype === "string" ) { 13183 match = rplusequals.exec( value ); 13184 if ( match ) { 13185 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); 13186 } 13187 } 13188 local[ prop.idx ] = value; 13189 return this[ fn ]( local ); 13190 }; 13191 }); 13192}); 13193 13194// add cssHook and .fx.step function for each named hook. 13195// accept a space separated string of properties 13196color.hook = function( hook ) { 13197 var hooks = hook.split( " " ); 13198 each( hooks, function( i, hook ) { 13199 jQuery.cssHooks[ hook ] = { 13200 set: function( elem, value ) { 13201 var parsed, curElem, 13202 backgroundColor = ""; 13203 13204 if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) { 13205 value = color( parsed || value ); 13206 if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { 13207 curElem = hook === "backgroundColor" ? elem.parentNode : elem; 13208 while ( 13209 (backgroundColor === "" || backgroundColor === "transparent") && 13210 curElem && curElem.style 13211 ) { 13212 try { 13213 backgroundColor = jQuery.css( curElem, "backgroundColor" ); 13214 curElem = curElem.parentNode; 13215 } catch ( e ) { 13216 } 13217 } 13218 13219 value = value.blend( backgroundColor && backgroundColor !== "transparent" ? 13220 backgroundColor : 13221 "_default" ); 13222 } 13223 13224 value = value.toRgbaString(); 13225 } 13226 try { 13227 elem.style[ hook ] = value; 13228 } catch( e ) { 13229 // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' 13230 } 13231 } 13232 }; 13233 jQuery.fx.step[ hook ] = function( fx ) { 13234 if ( !fx.colorInit ) { 13235 fx.start = color( fx.elem, hook ); 13236 fx.end = color( fx.end ); 13237 fx.colorInit = true; 13238 } 13239 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); 13240 }; 13241 }); 13242 13243}; 13244 13245color.hook( stepHooks ); 13246 13247jQuery.cssHooks.borderColor = { 13248 expand: function( value ) { 13249 var expanded = {}; 13250 13251 each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) { 13252 expanded[ "border" + part + "Color" ] = value; 13253 }); 13254 return expanded; 13255 } 13256}; 13257 13258// Basic color names only. 13259// Usage of any of the other color names requires adding yourself or including 13260// jquery.color.svg-names.js. 13261colors = jQuery.Color.names = { 13262 // 4.1. Basic color keywords 13263 aqua: "#00ffff", 13264 black: "#000000", 13265 blue: "#0000ff", 13266 fuchsia: "#ff00ff", 13267 gray: "#808080", 13268 green: "#008000", 13269 lime: "#00ff00", 13270 maroon: "#800000", 13271 navy: "#000080", 13272 olive: "#808000", 13273 purple: "#800080", 13274 red: "#ff0000", 13275 silver: "#c0c0c0", 13276 teal: "#008080", 13277 white: "#ffffff", 13278 yellow: "#ffff00", 13279 13280 // 4.2.3. "transparent" color keyword 13281 transparent: [ null, null, null, 0 ], 13282 13283 _default: "#ffffff" 13284}; 13285 13286})( jQuery ); 13287 13288 13289/******************************************************************************/ 13290/****************************** CLASS ANIMATIONS ******************************/ 13291/******************************************************************************/ 13292(function() { 13293 13294var classAnimationActions = [ "add", "remove", "toggle" ], 13295 shorthandStyles = { 13296 border: 1, 13297 borderBottom: 1, 13298 borderColor: 1, 13299 borderLeft: 1, 13300 borderRight: 1, 13301 borderTop: 1, 13302 borderWidth: 1, 13303 margin: 1, 13304 padding: 1 13305 }; 13306 13307$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) { 13308 $.fx.step[ prop ] = function( fx ) { 13309 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { 13310 jQuery.style( fx.elem, prop, fx.end ); 13311 fx.setAttr = true; 13312 } 13313 }; 13314}); 13315 13316function getElementStyles( elem ) { 13317 var key, len, 13318 style = elem.ownerDocument.defaultView ? 13319 elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : 13320 elem.currentStyle, 13321 styles = {}; 13322 13323 if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { 13324 len = style.length; 13325 while ( len-- ) { 13326 key = style[ len ]; 13327 if ( typeof style[ key ] === "string" ) { 13328 styles[ $.camelCase( key ) ] = style[ key ]; 13329 } 13330 } 13331 // support: Opera, IE <9 13332 } else { 13333 for ( key in style ) { 13334 if ( typeof style[ key ] === "string" ) { 13335 styles[ key ] = style[ key ]; 13336 } 13337 } 13338 } 13339 13340 return styles; 13341} 13342 13343 13344function styleDifference( oldStyle, newStyle ) { 13345 var diff = {}, 13346 name, value; 13347 13348 for ( name in newStyle ) { 13349 value = newStyle[ name ]; 13350 if ( oldStyle[ name ] !== value ) { 13351 if ( !shorthandStyles[ name ] ) { 13352 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { 13353 diff[ name ] = value; 13354 } 13355 } 13356 } 13357 } 13358 13359 return diff; 13360} 13361 13362// support: jQuery <1.8 13363if ( !$.fn.addBack ) { 13364 $.fn.addBack = function( selector ) { 13365 return this.add( selector == null ? 13366 this.prevObject : this.prevObject.filter( selector ) 13367 ); 13368 }; 13369} 13370 13371$.effects.animateClass = function( value, duration, easing, callback ) { 13372 var o = $.speed( duration, easing, callback ); 13373 13374 return this.queue( function() { 13375 var animated = $( this ), 13376 baseClass = animated.attr( "class" ) || "", 13377 applyClassChange, 13378 allAnimations = o.children ? animated.find( "*" ).addBack() : animated; 13379 13380 // map the animated objects to store the original styles. 13381 allAnimations = allAnimations.map(function() { 13382 var el = $( this ); 13383 return { 13384 el: el, 13385 start: getElementStyles( this ) 13386 }; 13387 }); 13388 13389 // apply class change 13390 applyClassChange = function() { 13391 $.each( classAnimationActions, function(i, action) { 13392 if ( value[ action ] ) { 13393 animated[ action + "Class" ]( value[ action ] ); 13394 } 13395 }); 13396 }; 13397 applyClassChange(); 13398 13399 // map all animated objects again - calculate new styles and diff 13400 allAnimations = allAnimations.map(function() { 13401 this.end = getElementStyles( this.el[ 0 ] ); 13402 this.diff = styleDifference( this.start, this.end ); 13403 return this; 13404 }); 13405 13406 // apply original class 13407 animated.attr( "class", baseClass ); 13408 13409 // map all animated objects again - this time collecting a promise 13410 allAnimations = allAnimations.map(function() { 13411 var styleInfo = this, 13412 dfd = $.Deferred(), 13413 opts = $.extend({}, o, { 13414 queue: false, 13415 complete: function() { 13416 dfd.resolve( styleInfo ); 13417 } 13418 }); 13419 13420 this.el.animate( this.diff, opts ); 13421 return dfd.promise(); 13422 }); 13423 13424 // once all animations have completed: 13425 $.when.apply( $, allAnimations.get() ).done(function() { 13426 13427 // set the final class 13428 applyClassChange(); 13429 13430 // for each animated element, 13431 // clear all css properties that were animated 13432 $.each( arguments, function() { 13433 var el = this.el; 13434 $.each( this.diff, function(key) { 13435 el.css( key, "" ); 13436 }); 13437 }); 13438 13439 // this is guarnteed to be there if you use jQuery.speed() 13440 // it also handles dequeuing the next anim... 13441 o.complete.call( animated[ 0 ] ); 13442 }); 13443 }); 13444}; 13445 13446$.fn.extend({ 13447 _addClass: $.fn.addClass, 13448 addClass: function( classNames, speed, easing, callback ) { 13449 return speed ? 13450 $.effects.animateClass.call( this, 13451 { add: classNames }, speed, easing, callback ) : 13452 this._addClass( classNames ); 13453 }, 13454 13455 _removeClass: $.fn.removeClass, 13456 removeClass: function( classNames, speed, easing, callback ) { 13457 return speed ? 13458 $.effects.animateClass.call( this, 13459 { remove: classNames }, speed, easing, callback ) : 13460 this._removeClass( classNames ); 13461 }, 13462 13463 _toggleClass: $.fn.toggleClass, 13464 toggleClass: function( classNames, force, speed, easing, callback ) { 13465 if ( typeof force === "boolean" || force === undefined ) { 13466 if ( !speed ) { 13467 // without speed parameter 13468 return this._toggleClass( classNames, force ); 13469 } else { 13470 return $.effects.animateClass.call( this, 13471 (force ? { add: classNames } : { remove: classNames }), 13472 speed, easing, callback ); 13473 } 13474 } else { 13475 // without force parameter 13476 return $.effects.animateClass.call( this, 13477 { toggle: classNames }, force, speed, easing ); 13478 } 13479 }, 13480 13481 switchClass: function( remove, add, speed, easing, callback) { 13482 return $.effects.animateClass.call( this, { 13483 add: add, 13484 remove: remove 13485 }, speed, easing, callback ); 13486 } 13487}); 13488 13489})(); 13490 13491/******************************************************************************/ 13492/*********************************** EFFECTS **********************************/ 13493/******************************************************************************/ 13494 13495(function() { 13496 13497$.extend( $.effects, { 13498 version: "1.10.0", 13499 13500 // Saves a set of properties in a data storage 13501 save: function( element, set ) { 13502 for( var i=0; i < set.length; i++ ) { 13503 if ( set[ i ] !== null ) { 13504 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); 13505 } 13506 } 13507 }, 13508 13509 // Restores a set of previously saved properties from a data storage 13510 restore: function( element, set ) { 13511 var val, i; 13512 for( i=0; i < set.length; i++ ) { 13513 if ( set[ i ] !== null ) { 13514 val = element.data( dataSpace + set[ i ] ); 13515 // support: jQuery 1.6.2 13516 // http://bugs.jquery.com/ticket/9917 13517 // jQuery 1.6.2 incorrectly returns undefined for any falsy value. 13518 // We can't differentiate between "" and 0 here, so we just assume 13519 // empty string since it's likely to be a more common value... 13520 if ( val === undefined ) { 13521 val = ""; 13522 } 13523 element.css( set[ i ], val ); 13524 } 13525 } 13526 }, 13527 13528 setMode: function( el, mode ) { 13529 if (mode === "toggle") { 13530 mode = el.is( ":hidden" ) ? "show" : "hide"; 13531 } 13532 return mode; 13533 }, 13534 13535 // Translates a [top,left] array into a baseline value 13536 // this should be a little more flexible in the future to handle a string & hash 13537 getBaseline: function( origin, original ) { 13538 var y, x; 13539 switch ( origin[ 0 ] ) { 13540 case "top": y = 0; break; 13541 case "middle": y = 0.5; break; 13542 case "bottom": y = 1; break; 13543 default: y = origin[ 0 ] / original.height; 13544 } 13545 switch ( origin[ 1 ] ) { 13546 case "left": x = 0; break; 13547 case "center": x = 0.5; break; 13548 case "right": x = 1; break; 13549 default: x = origin[ 1 ] / original.width; 13550 } 13551 return { 13552 x: x, 13553 y: y 13554 }; 13555 }, 13556 13557 // Wraps the element around a wrapper that copies position properties 13558 createWrapper: function( element ) { 13559 13560 // if the element is already wrapped, return it 13561 if ( element.parent().is( ".ui-effects-wrapper" )) { 13562 return element.parent(); 13563 } 13564 13565 // wrap the element 13566 var props = { 13567 width: element.outerWidth(true), 13568 height: element.outerHeight(true), 13569 "float": element.css( "float" ) 13570 }, 13571 wrapper = $( "<div></div>" ) 13572 .addClass( "ui-effects-wrapper" ) 13573 .css({ 13574 fontSize: "100%", 13575 background: "transparent", 13576 border: "none", 13577 margin: 0, 13578 padding: 0 13579 }), 13580 // Store the size in case width/height are defined in % - Fixes #5245 13581 size = { 13582 width: element.width(), 13583 height: element.height() 13584 }, 13585 active = document.activeElement; 13586 13587 // support: Firefox 13588 // Firefox incorrectly exposes anonymous content 13589 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 13590 try { 13591 active.id; 13592 } catch( e ) { 13593 active = document.body; 13594 } 13595 13596 element.wrap( wrapper ); 13597 13598 // Fixes #7595 - Elements lose focus when wrapped. 13599 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 13600 $( active ).focus(); 13601 } 13602 13603 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element 13604 13605 // transfer positioning properties to the wrapper 13606 if ( element.css( "position" ) === "static" ) { 13607 wrapper.css({ position: "relative" }); 13608 element.css({ position: "relative" }); 13609 } else { 13610 $.extend( props, { 13611 position: element.css( "position" ), 13612 zIndex: element.css( "z-index" ) 13613 }); 13614 $.each([ "top", "left", "bottom", "right" ], function(i, pos) { 13615 props[ pos ] = element.css( pos ); 13616 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { 13617 props[ pos ] = "auto"; 13618 } 13619 }); 13620 element.css({ 13621 position: "relative", 13622 top: 0, 13623 left: 0, 13624 right: "auto", 13625 bottom: "auto" 13626 }); 13627 } 13628 element.css(size); 13629 13630 return wrapper.css( props ).show(); 13631 }, 13632 13633 removeWrapper: function( element ) { 13634 var active = document.activeElement; 13635 13636 if ( element.parent().is( ".ui-effects-wrapper" ) ) { 13637 element.parent().replaceWith( element ); 13638 13639 // Fixes #7595 - Elements lose focus when wrapped. 13640 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 13641 $( active ).focus(); 13642 } 13643 } 13644 13645 13646 return element; 13647 }, 13648 13649 setTransition: function( element, list, factor, value ) { 13650 value = value || {}; 13651 $.each( list, function( i, x ) { 13652 var unit = element.cssUnit( x ); 13653 if ( unit[ 0 ] > 0 ) { 13654 value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; 13655 } 13656 }); 13657 return value; 13658 } 13659}); 13660 13661// return an effect options object for the given parameters: 13662function _normalizeArguments( effect, options, speed, callback ) { 13663 13664 // allow passing all options as the first parameter 13665 if ( $.isPlainObject( effect ) ) { 13666 options = effect; 13667 effect = effect.effect; 13668 } 13669 13670 // convert to an object 13671 effect = { effect: effect }; 13672 13673 // catch (effect, null, ...) 13674 if ( options == null ) { 13675 options = {}; 13676 } 13677 13678 // catch (effect, callback) 13679 if ( $.isFunction( options ) ) { 13680 callback = options; 13681 speed = null; 13682 options = {}; 13683 } 13684 13685 // catch (effect, speed, ?) 13686 if ( typeof options === "number" || $.fx.speeds[ options ] ) { 13687 callback = speed; 13688 speed = options; 13689 options = {}; 13690 } 13691 13692 // catch (effect, options, callback) 13693 if ( $.isFunction( speed ) ) { 13694 callback = speed; 13695 speed = null; 13696 } 13697 13698 // add options to effect 13699 if ( options ) { 13700 $.extend( effect, options ); 13701 } 13702 13703 speed = speed || options.duration; 13704 effect.duration = $.fx.off ? 0 : 13705 typeof speed === "number" ? speed : 13706 speed in $.fx.speeds ? $.fx.speeds[ speed ] : 13707 $.fx.speeds._default; 13708 13709 effect.complete = callback || options.complete; 13710 13711 return effect; 13712} 13713 13714function standardSpeed( speed ) { 13715 // valid standard speeds 13716 if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) { 13717 return true; 13718 } 13719 13720 // invalid strings - treat as "normal" speed 13721 return typeof speed === "string" && !$.effects.effect[ speed ]; 13722} 13723 13724$.fn.extend({ 13725 effect: function( /* effect, options, speed, callback */ ) { 13726 var args = _normalizeArguments.apply( this, arguments ), 13727 mode = args.mode, 13728 queue = args.queue, 13729 effectMethod = $.effects.effect[ args.effect ]; 13730 13731 if ( $.fx.off || !effectMethod ) { 13732 // delegate to the original method (e.g., .show()) if possible 13733 if ( mode ) { 13734 return this[ mode ]( args.duration, args.complete ); 13735 } else { 13736 return this.each( function() { 13737 if ( args.complete ) { 13738 args.complete.call( this ); 13739 } 13740 }); 13741 } 13742 } 13743 13744 function run( next ) { 13745 var elem = $( this ), 13746 complete = args.complete, 13747 mode = args.mode; 13748 13749 function done() { 13750 if ( $.isFunction( complete ) ) { 13751 complete.call( elem[0] ); 13752 } 13753 if ( $.isFunction( next ) ) { 13754 next(); 13755 } 13756 } 13757 13758 // if the element is hiddden and mode is hide, 13759 // or element is visible and mode is show 13760 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { 13761 done(); 13762 } else { 13763 effectMethod.call( elem[0], args, done ); 13764 } 13765 } 13766 13767 return queue === false ? this.each( run ) : this.queue( queue || "fx", run ); 13768 }, 13769 13770 _show: $.fn.show, 13771 show: function( speed ) { 13772 if ( standardSpeed( speed ) ) { 13773 return this._show.apply( this, arguments ); 13774 } else { 13775 var args = _normalizeArguments.apply( this, arguments ); 13776 args.mode = "show"; 13777 return this.effect.call( this, args ); 13778 } 13779 }, 13780 13781 _hide: $.fn.hide, 13782 hide: function( speed ) { 13783 if ( standardSpeed( speed ) ) { 13784 return this._hide.apply( this, arguments ); 13785 } else { 13786 var args = _normalizeArguments.apply( this, arguments ); 13787 args.mode = "hide"; 13788 return this.effect.call( this, args ); 13789 } 13790 }, 13791 13792 // jQuery core overloads toggle and creates _toggle 13793 __toggle: $.fn.toggle, 13794 toggle: function( speed ) { 13795 if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) { 13796 return this.__toggle.apply( this, arguments ); 13797 } else { 13798 var args = _normalizeArguments.apply( this, arguments ); 13799 args.mode = "toggle"; 13800 return this.effect.call( this, args ); 13801 } 13802 }, 13803 13804 // helper functions 13805 cssUnit: function(key) { 13806 var style = this.css( key ), 13807 val = []; 13808 13809 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { 13810 if ( style.indexOf( unit ) > 0 ) { 13811 val = [ parseFloat( style ), unit ]; 13812 } 13813 }); 13814 return val; 13815 } 13816}); 13817 13818})(); 13819 13820/******************************************************************************/ 13821/*********************************** EASING ***********************************/ 13822/******************************************************************************/ 13823 13824(function() { 13825 13826// based on easing equations from Robert Penner (http://www.robertpenner.com/easing) 13827 13828var baseEasings = {}; 13829 13830$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { 13831 baseEasings[ name ] = function( p ) { 13832 return Math.pow( p, i + 2 ); 13833 }; 13834}); 13835 13836$.extend( baseEasings, { 13837 Sine: function ( p ) { 13838 return 1 - Math.cos( p * Math.PI / 2 ); 13839 }, 13840 Circ: function ( p ) { 13841 return 1 - Math.sqrt( 1 - p * p ); 13842 }, 13843 Elastic: function( p ) { 13844 return p === 0 || p === 1 ? p : 13845 -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 ); 13846 }, 13847 Back: function( p ) { 13848 return p * p * ( 3 * p - 2 ); 13849 }, 13850 Bounce: function ( p ) { 13851 var pow2, 13852 bounce = 4; 13853 13854 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} 13855 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); 13856 } 13857}); 13858 13859$.each( baseEasings, function( name, easeIn ) { 13860 $.easing[ "easeIn" + name ] = easeIn; 13861 $.easing[ "easeOut" + name ] = function( p ) { 13862 return 1 - easeIn( 1 - p ); 13863 }; 13864 $.easing[ "easeInOut" + name ] = function( p ) { 13865 return p < 0.5 ? 13866 easeIn( p * 2 ) / 2 : 13867 1 - easeIn( p * -2 + 2 ) / 2; 13868 }; 13869}); 13870 13871})(); 13872 13873})(jQuery)); 13874(function( $, undefined ) { 13875 13876var rvertical = /up|down|vertical/, 13877 rpositivemotion = /up|left|vertical|horizontal/; 13878 13879$.effects.effect.blind = function( o, done ) { 13880 // Create element 13881 var el = $( this ), 13882 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 13883 mode = $.effects.setMode( el, o.mode || "hide" ), 13884 direction = o.direction || "up", 13885 vertical = rvertical.test( direction ), 13886 ref = vertical ? "height" : "width", 13887 ref2 = vertical ? "top" : "left", 13888 motion = rpositivemotion.test( direction ), 13889 animation = {}, 13890 show = mode === "show", 13891 wrapper, distance, margin; 13892 13893 // if already wrapped, the wrapper's properties are my property. #6245 13894 if ( el.parent().is( ".ui-effects-wrapper" ) ) { 13895 $.effects.save( el.parent(), props ); 13896 } else { 13897 $.effects.save( el, props ); 13898 } 13899 el.show(); 13900 wrapper = $.effects.createWrapper( el ).css({ 13901 overflow: "hidden" 13902 }); 13903 13904 distance = wrapper[ ref ](); 13905 margin = parseFloat( wrapper.css( ref2 ) ) || 0; 13906 13907 animation[ ref ] = show ? distance : 0; 13908 if ( !motion ) { 13909 el 13910 .css( vertical ? "bottom" : "right", 0 ) 13911 .css( vertical ? "top" : "left", "auto" ) 13912 .css({ position: "absolute" }); 13913 13914 animation[ ref2 ] = show ? margin : distance + margin; 13915 } 13916 13917 // start at 0 if we are showing 13918 if ( show ) { 13919 wrapper.css( ref, 0 ); 13920 if ( ! motion ) { 13921 wrapper.css( ref2, margin + distance ); 13922 } 13923 } 13924 13925 // Animate 13926 wrapper.animate( animation, { 13927 duration: o.duration, 13928 easing: o.easing, 13929 queue: false, 13930 complete: function() { 13931 if ( mode === "hide" ) { 13932 el.hide(); 13933 } 13934 $.effects.restore( el, props ); 13935 $.effects.removeWrapper( el ); 13936 done(); 13937 } 13938 }); 13939 13940}; 13941 13942})(jQuery); 13943(function( $, undefined ) { 13944 13945$.effects.effect.bounce = function( o, done ) { 13946 var el = $( this ), 13947 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 13948 13949 // defaults: 13950 mode = $.effects.setMode( el, o.mode || "effect" ), 13951 hide = mode === "hide", 13952 show = mode === "show", 13953 direction = o.direction || "up", 13954 distance = o.distance, 13955 times = o.times || 5, 13956 13957 // number of internal animations 13958 anims = times * 2 + ( show || hide ? 1 : 0 ), 13959 speed = o.duration / anims, 13960 easing = o.easing, 13961 13962 // utility: 13963 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 13964 motion = ( direction === "up" || direction === "left" ), 13965 i, 13966 upAnim, 13967 downAnim, 13968 13969 // we will need to re-assemble the queue to stack our animations in place 13970 queue = el.queue(), 13971 queuelen = queue.length; 13972 13973 // Avoid touching opacity to prevent clearType and PNG issues in IE 13974 if ( show || hide ) { 13975 props.push( "opacity" ); 13976 } 13977 13978 $.effects.save( el, props ); 13979 el.show(); 13980 $.effects.createWrapper( el ); // Create Wrapper 13981 13982 // default distance for the BIGGEST bounce is the outer Distance / 3 13983 if ( !distance ) { 13984 distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; 13985 } 13986 13987 if ( show ) { 13988 downAnim = { opacity: 1 }; 13989 downAnim[ ref ] = 0; 13990 13991 // if we are showing, force opacity 0 and set the initial position 13992 // then do the "first" animation 13993 el.css( "opacity", 0 ) 13994 .css( ref, motion ? -distance * 2 : distance * 2 ) 13995 .animate( downAnim, speed, easing ); 13996 } 13997 13998 // start at the smallest distance if we are hiding 13999 if ( hide ) { 14000 distance = distance / Math.pow( 2, times - 1 ); 14001 } 14002 14003 downAnim = {}; 14004 downAnim[ ref ] = 0; 14005 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here 14006 for ( i = 0; i < times; i++ ) { 14007 upAnim = {}; 14008 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 14009 14010 el.animate( upAnim, speed, easing ) 14011 .animate( downAnim, speed, easing ); 14012 14013 distance = hide ? distance * 2 : distance / 2; 14014 } 14015 14016 // Last Bounce when Hiding 14017 if ( hide ) { 14018 upAnim = { opacity: 0 }; 14019 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 14020 14021 el.animate( upAnim, speed, easing ); 14022 } 14023 14024 el.queue(function() { 14025 if ( hide ) { 14026 el.hide(); 14027 } 14028 $.effects.restore( el, props ); 14029 $.effects.removeWrapper( el ); 14030 done(); 14031 }); 14032 14033 // inject all the animations we just queued to be first in line (after "inprogress") 14034 if ( queuelen > 1) { 14035 queue.splice.apply( queue, 14036 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); 14037 } 14038 el.dequeue(); 14039 14040}; 14041 14042})(jQuery); 14043(function( $, undefined ) { 14044 14045$.effects.effect.clip = function( o, done ) { 14046 // Create element 14047 var el = $( this ), 14048 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 14049 mode = $.effects.setMode( el, o.mode || "hide" ), 14050 show = mode === "show", 14051 direction = o.direction || "vertical", 14052 vert = direction === "vertical", 14053 size = vert ? "height" : "width", 14054 position = vert ? "top" : "left", 14055 animation = {}, 14056 wrapper, animate, distance; 14057 14058 // Save & Show 14059 $.effects.save( el, props ); 14060 el.show(); 14061 14062 // Create Wrapper 14063 wrapper = $.effects.createWrapper( el ).css({ 14064 overflow: "hidden" 14065 }); 14066 animate = ( el[0].tagName === "IMG" ) ? wrapper : el; 14067 distance = animate[ size ](); 14068 14069 // Shift 14070 if ( show ) { 14071 animate.css( size, 0 ); 14072 animate.css( position, distance / 2 ); 14073 } 14074 14075 // Create Animation Object: 14076 animation[ size ] = show ? distance : 0; 14077 animation[ position ] = show ? 0 : distance / 2; 14078 14079 // Animate 14080 animate.animate( animation, { 14081 queue: false, 14082 duration: o.duration, 14083 easing: o.easing, 14084 complete: function() { 14085 if ( !show ) { 14086 el.hide(); 14087 } 14088 $.effects.restore( el, props ); 14089 $.effects.removeWrapper( el ); 14090 done(); 14091 } 14092 }); 14093 14094}; 14095 14096})(jQuery); 14097(function( $, undefined ) { 14098 14099$.effects.effect.drop = function( o, done ) { 14100 14101 var el = $( this ), 14102 props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ], 14103 mode = $.effects.setMode( el, o.mode || "hide" ), 14104 show = mode === "show", 14105 direction = o.direction || "left", 14106 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 14107 motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg", 14108 animation = { 14109 opacity: show ? 1 : 0 14110 }, 14111 distance; 14112 14113 // Adjust 14114 $.effects.save( el, props ); 14115 el.show(); 14116 $.effects.createWrapper( el ); 14117 14118 distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2; 14119 14120 if ( show ) { 14121 el 14122 .css( "opacity", 0 ) 14123 .css( ref, motion === "pos" ? -distance : distance ); 14124 } 14125 14126 // Animation 14127 animation[ ref ] = ( show ? 14128 ( motion === "pos" ? "+=" : "-=" ) : 14129 ( motion === "pos" ? "-=" : "+=" ) ) + 14130 distance; 14131 14132 // Animate 14133 el.animate( animation, { 14134 queue: false, 14135 duration: o.duration, 14136 easing: o.easing, 14137 complete: function() { 14138 if ( mode === "hide" ) { 14139 el.hide(); 14140 } 14141 $.effects.restore( el, props ); 14142 $.effects.removeWrapper( el ); 14143 done(); 14144 } 14145 }); 14146}; 14147 14148})(jQuery); 14149(function( $, undefined ) { 14150 14151$.effects.effect.explode = function( o, done ) { 14152 14153 var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3, 14154 cells = rows, 14155 el = $( this ), 14156 mode = $.effects.setMode( el, o.mode || "hide" ), 14157 show = mode === "show", 14158 14159 // show and then visibility:hidden the element before calculating offset 14160 offset = el.show().css( "visibility", "hidden" ).offset(), 14161 14162 // width and height of a piece 14163 width = Math.ceil( el.outerWidth() / cells ), 14164 height = Math.ceil( el.outerHeight() / rows ), 14165 pieces = [], 14166 14167 // loop 14168 i, j, left, top, mx, my; 14169 14170 // children animate complete: 14171 function childComplete() { 14172 pieces.push( this ); 14173 if ( pieces.length === rows * cells ) { 14174 animComplete(); 14175 } 14176 } 14177 14178 // clone the element for each row and cell. 14179 for( i = 0; i < rows ; i++ ) { // ===> 14180 top = offset.top + i * height; 14181 my = i - ( rows - 1 ) / 2 ; 14182 14183 for( j = 0; j < cells ; j++ ) { // ||| 14184 left = offset.left + j * width; 14185 mx = j - ( cells - 1 ) / 2 ; 14186 14187 // Create a clone of the now hidden main element that will be absolute positioned 14188 // within a wrapper div off the -left and -top equal to size of our pieces 14189 el 14190 .clone() 14191 .appendTo( "body" ) 14192 .wrap( "<div></div>" ) 14193 .css({ 14194 position: "absolute", 14195 visibility: "visible", 14196 left: -j * width, 14197 top: -i * height 14198 }) 14199 14200 // select the wrapper - make it overflow: hidden and absolute positioned based on 14201 // where the original was located +left and +top equal to the size of pieces 14202 .parent() 14203 .addClass( "ui-effects-explode" ) 14204 .css({ 14205 position: "absolute", 14206 overflow: "hidden", 14207 width: width, 14208 height: height, 14209 left: left + ( show ? mx * width : 0 ), 14210 top: top + ( show ? my * height : 0 ), 14211 opacity: show ? 0 : 1 14212 }).animate({ 14213 left: left + ( show ? 0 : mx * width ), 14214 top: top + ( show ? 0 : my * height ), 14215 opacity: show ? 1 : 0 14216 }, o.duration || 500, o.easing, childComplete ); 14217 } 14218 } 14219 14220 function animComplete() { 14221 el.css({ 14222 visibility: "visible" 14223 }); 14224 $( pieces ).remove(); 14225 if ( !show ) { 14226 el.hide(); 14227 } 14228 done(); 14229 } 14230}; 14231 14232})(jQuery); 14233(function( $, undefined ) { 14234 14235$.effects.effect.fade = function( o, done ) { 14236 var el = $( this ), 14237 mode = $.effects.setMode( el, o.mode || "toggle" ); 14238 14239 el.animate({ 14240 opacity: mode 14241 }, { 14242 queue: false, 14243 duration: o.duration, 14244 easing: o.easing, 14245 complete: done 14246 }); 14247}; 14248 14249})( jQuery ); 14250(function( $, undefined ) { 14251 14252$.effects.effect.fold = function( o, done ) { 14253 14254 // Create element 14255 var el = $( this ), 14256 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 14257 mode = $.effects.setMode( el, o.mode || "hide" ), 14258 show = mode === "show", 14259 hide = mode === "hide", 14260 size = o.size || 15, 14261 percent = /([0-9]+)%/.exec( size ), 14262 horizFirst = !!o.horizFirst, 14263 widthFirst = show !== horizFirst, 14264 ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ], 14265 duration = o.duration / 2, 14266 wrapper, distance, 14267 animation1 = {}, 14268 animation2 = {}; 14269 14270 $.effects.save( el, props ); 14271 el.show(); 14272 14273 // Create Wrapper 14274 wrapper = $.effects.createWrapper( el ).css({ 14275 overflow: "hidden" 14276 }); 14277 distance = widthFirst ? 14278 [ wrapper.width(), wrapper.height() ] : 14279 [ wrapper.height(), wrapper.width() ]; 14280 14281 if ( percent ) { 14282 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; 14283 } 14284 if ( show ) { 14285 wrapper.css( horizFirst ? { 14286 height: 0, 14287 width: size 14288 } : { 14289 height: size, 14290 width: 0 14291 }); 14292 } 14293 14294 // Animation 14295 animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size; 14296 animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0; 14297 14298 // Animate 14299 wrapper 14300 .animate( animation1, duration, o.easing ) 14301 .animate( animation2, duration, o.easing, function() { 14302 if ( hide ) { 14303 el.hide(); 14304 } 14305 $.effects.restore( el, props ); 14306 $.effects.removeWrapper( el ); 14307 done(); 14308 }); 14309 14310}; 14311 14312})(jQuery); 14313(function( $, undefined ) { 14314 14315$.effects.effect.highlight = function( o, done ) { 14316 var elem = $( this ), 14317 props = [ "backgroundImage", "backgroundColor", "opacity" ], 14318 mode = $.effects.setMode( elem, o.mode || "show" ), 14319 animation = { 14320 backgroundColor: elem.css( "backgroundColor" ) 14321 }; 14322 14323 if (mode === "hide") { 14324 animation.opacity = 0; 14325 } 14326 14327 $.effects.save( elem, props ); 14328 14329 elem 14330 .show() 14331 .css({ 14332 backgroundImage: "none", 14333 backgroundColor: o.color || "#ffff99" 14334 }) 14335 .animate( animation, { 14336 queue: false, 14337 duration: o.duration, 14338 easing: o.easing, 14339 complete: function() { 14340 if ( mode === "hide" ) { 14341 elem.hide(); 14342 } 14343 $.effects.restore( elem, props ); 14344 done(); 14345 } 14346 }); 14347}; 14348 14349})(jQuery); 14350(function( $, undefined ) { 14351 14352$.effects.effect.pulsate = function( o, done ) { 14353 var elem = $( this ), 14354 mode = $.effects.setMode( elem, o.mode || "show" ), 14355 show = mode === "show", 14356 hide = mode === "hide", 14357 showhide = ( show || mode === "hide" ), 14358 14359 // showing or hiding leaves of the "last" animation 14360 anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), 14361 duration = o.duration / anims, 14362 animateTo = 0, 14363 queue = elem.queue(), 14364 queuelen = queue.length, 14365 i; 14366 14367 if ( show || !elem.is(":visible")) { 14368 elem.css( "opacity", 0 ).show(); 14369 animateTo = 1; 14370 } 14371 14372 // anims - 1 opacity "toggles" 14373 for ( i = 1; i < anims; i++ ) { 14374 elem.animate({ 14375 opacity: animateTo 14376 }, duration, o.easing ); 14377 animateTo = 1 - animateTo; 14378 } 14379 14380 elem.animate({ 14381 opacity: animateTo 14382 }, duration, o.easing); 14383 14384 elem.queue(function() { 14385 if ( hide ) { 14386 elem.hide(); 14387 } 14388 done(); 14389 }); 14390 14391 // We just queued up "anims" animations, we need to put them next in the queue 14392 if ( queuelen > 1 ) { 14393 queue.splice.apply( queue, 14394 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); 14395 } 14396 elem.dequeue(); 14397}; 14398 14399})(jQuery); 14400(function( $, undefined ) { 14401 14402$.effects.effect.puff = function( o, done ) { 14403 var elem = $( this ), 14404 mode = $.effects.setMode( elem, o.mode || "hide" ), 14405 hide = mode === "hide", 14406 percent = parseInt( o.percent, 10 ) || 150, 14407 factor = percent / 100, 14408 original = { 14409 height: elem.height(), 14410 width: elem.width(), 14411 outerHeight: elem.outerHeight(), 14412 outerWidth: elem.outerWidth() 14413 }; 14414 14415 $.extend( o, { 14416 effect: "scale", 14417 queue: false, 14418 fade: true, 14419 mode: mode, 14420 complete: done, 14421 percent: hide ? percent : 100, 14422 from: hide ? 14423 original : 14424 { 14425 height: original.height * factor, 14426 width: original.width * factor, 14427 outerHeight: original.outerHeight * factor, 14428 outerWidth: original.outerWidth * factor 14429 } 14430 }); 14431 14432 elem.effect( o ); 14433}; 14434 14435$.effects.effect.scale = function( o, done ) { 14436 14437 // Create element 14438 var el = $( this ), 14439 options = $.extend( true, {}, o ), 14440 mode = $.effects.setMode( el, o.mode || "effect" ), 14441 percent = parseInt( o.percent, 10 ) || 14442 ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ), 14443 direction = o.direction || "both", 14444 origin = o.origin, 14445 original = { 14446 height: el.height(), 14447 width: el.width(), 14448 outerHeight: el.outerHeight(), 14449 outerWidth: el.outerWidth() 14450 }, 14451 factor = { 14452 y: direction !== "horizontal" ? (percent / 100) : 1, 14453 x: direction !== "vertical" ? (percent / 100) : 1 14454 }; 14455 14456 // We are going to pass this effect to the size effect: 14457 options.effect = "size"; 14458 options.queue = false; 14459 options.complete = done; 14460 14461 // Set default origin and restore for show/hide 14462 if ( mode !== "effect" ) { 14463 options.origin = origin || ["middle","center"]; 14464 options.restore = true; 14465 } 14466 14467 options.from = o.from || ( mode === "show" ? { 14468 height: 0, 14469 width: 0, 14470 outerHeight: 0, 14471 outerWidth: 0 14472 } : original ); 14473 options.to = { 14474 height: original.height * factor.y, 14475 width: original.width * factor.x, 14476 outerHeight: original.outerHeight * factor.y, 14477 outerWidth: original.outerWidth * factor.x 14478 }; 14479 14480 // Fade option to support puff 14481 if ( options.fade ) { 14482 if ( mode === "show" ) { 14483 options.from.opacity = 0; 14484 options.to.opacity = 1; 14485 } 14486 if ( mode === "hide" ) { 14487 options.from.opacity = 1; 14488 options.to.opacity = 0; 14489 } 14490 } 14491 14492 // Animate 14493 el.effect( options ); 14494 14495}; 14496 14497$.effects.effect.size = function( o, done ) { 14498 14499 // Create element 14500 var original, baseline, factor, 14501 el = $( this ), 14502 props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ], 14503 14504 // Always restore 14505 props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ], 14506 14507 // Copy for children 14508 props2 = [ "width", "height", "overflow" ], 14509 cProps = [ "fontSize" ], 14510 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], 14511 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], 14512 14513 // Set options 14514 mode = $.effects.setMode( el, o.mode || "effect" ), 14515 restore = o.restore || mode !== "effect", 14516 scale = o.scale || "both", 14517 origin = o.origin || [ "middle", "center" ], 14518 position = el.css( "position" ), 14519 props = restore ? props0 : props1, 14520 zero = { 14521 height: 0, 14522 width: 0, 14523 outerHeight: 0, 14524 outerWidth: 0 14525 }; 14526 14527 if ( mode === "show" ) { 14528 el.show(); 14529 } 14530 original = { 14531 height: el.height(), 14532 width: el.width(), 14533 outerHeight: el.outerHeight(), 14534 outerWidth: el.outerWidth() 14535 }; 14536 14537 if ( o.mode === "toggle" && mode === "show" ) { 14538 el.from = o.to || zero; 14539 el.to = o.from || original; 14540 } else { 14541 el.from = o.from || ( mode === "show" ? zero : original ); 14542 el.to = o.to || ( mode === "hide" ? zero : original ); 14543 } 14544 14545 // Set scaling factor 14546 factor = { 14547 from: { 14548 y: el.from.height / original.height, 14549 x: el.from.width / original.width 14550 }, 14551 to: { 14552 y: el.to.height / original.height, 14553 x: el.to.width / original.width 14554 } 14555 }; 14556 14557 // Scale the css box 14558 if ( scale === "box" || scale === "both" ) { 14559 14560 // Vertical props scaling 14561 if ( factor.from.y !== factor.to.y ) { 14562 props = props.concat( vProps ); 14563 el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from ); 14564 el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to ); 14565 } 14566 14567 // Horizontal props scaling 14568 if ( factor.from.x !== factor.to.x ) { 14569 props = props.concat( hProps ); 14570 el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from ); 14571 el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to ); 14572 } 14573 } 14574 14575 // Scale the content 14576 if ( scale === "content" || scale === "both" ) { 14577 14578 // Vertical props scaling 14579 if ( factor.from.y !== factor.to.y ) { 14580 props = props.concat( cProps ).concat( props2 ); 14581 el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from ); 14582 el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to ); 14583 } 14584 } 14585 14586 $.effects.save( el, props ); 14587 el.show(); 14588 $.effects.createWrapper( el ); 14589 el.css( "overflow", "hidden" ).css( el.from ); 14590 14591 // Adjust 14592 if (origin) { // Calculate baseline shifts 14593 baseline = $.effects.getBaseline( origin, original ); 14594 el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y; 14595 el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x; 14596 el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y; 14597 el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x; 14598 } 14599 el.css( el.from ); // set top & left 14600 14601 // Animate 14602 if ( scale === "content" || scale === "both" ) { // Scale the children 14603 14604 // Add margins/font-size 14605 vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps); 14606 hProps = hProps.concat([ "marginLeft", "marginRight" ]); 14607 props2 = props0.concat(vProps).concat(hProps); 14608 14609 el.find( "*[width]" ).each( function(){ 14610 var child = $( this ), 14611 c_original = { 14612 height: child.height(), 14613 width: child.width(), 14614 outerHeight: child.outerHeight(), 14615 outerWidth: child.outerWidth() 14616 }; 14617 if (restore) { 14618 $.effects.save(child, props2); 14619 } 14620 14621 child.from = { 14622 height: c_original.height * factor.from.y, 14623 width: c_original.width * factor.from.x, 14624 outerHeight: c_original.outerHeight * factor.from.y, 14625 outerWidth: c_original.outerWidth * factor.from.x 14626 }; 14627 child.to = { 14628 height: c_original.height * factor.to.y, 14629 width: c_original.width * factor.to.x, 14630 outerHeight: c_original.height * factor.to.y, 14631 outerWidth: c_original.width * factor.to.x 14632 }; 14633 14634 // Vertical props scaling 14635 if ( factor.from.y !== factor.to.y ) { 14636 child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from ); 14637 child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to ); 14638 } 14639 14640 // Horizontal props scaling 14641 if ( factor.from.x !== factor.to.x ) { 14642 child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from ); 14643 child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to ); 14644 } 14645 14646 // Animate children 14647 child.css( child.from ); 14648 child.animate( child.to, o.duration, o.easing, function() { 14649 14650 // Restore children 14651 if ( restore ) { 14652 $.effects.restore( child, props2 ); 14653 } 14654 }); 14655 }); 14656 } 14657 14658 // Animate 14659 el.animate( el.to, { 14660 queue: false, 14661 duration: o.duration, 14662 easing: o.easing, 14663 complete: function() { 14664 if ( el.to.opacity === 0 ) { 14665 el.css( "opacity", el.from.opacity ); 14666 } 14667 if( mode === "hide" ) { 14668 el.hide(); 14669 } 14670 $.effects.restore( el, props ); 14671 if ( !restore ) { 14672 14673 // we need to calculate our new positioning based on the scaling 14674 if ( position === "static" ) { 14675 el.css({ 14676 position: "relative", 14677 top: el.to.top, 14678 left: el.to.left 14679 }); 14680 } else { 14681 $.each([ "top", "left" ], function( idx, pos ) { 14682 el.css( pos, function( _, str ) { 14683 var val = parseInt( str, 10 ), 14684 toRef = idx ? el.to.left : el.to.top; 14685 14686 // if original was "auto", recalculate the new value from wrapper 14687 if ( str === "auto" ) { 14688 return toRef + "px"; 14689 } 14690 14691 return val + toRef + "px"; 14692 }); 14693 }); 14694 } 14695 } 14696 14697 $.effects.removeWrapper( el ); 14698 done(); 14699 } 14700 }); 14701 14702}; 14703 14704})(jQuery); 14705(function( $, undefined ) { 14706 14707$.effects.effect.shake = function( o, done ) { 14708 14709 var el = $( this ), 14710 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 14711 mode = $.effects.setMode( el, o.mode || "effect" ), 14712 direction = o.direction || "left", 14713 distance = o.distance || 20, 14714 times = o.times || 3, 14715 anims = times * 2 + 1, 14716 speed = Math.round(o.duration/anims), 14717 ref = (direction === "up" || direction === "down") ? "top" : "left", 14718 positiveMotion = (direction === "up" || direction === "left"), 14719 animation = {}, 14720 animation1 = {}, 14721 animation2 = {}, 14722 i, 14723 14724 // we will need to re-assemble the queue to stack our animations in place 14725 queue = el.queue(), 14726 queuelen = queue.length; 14727 14728 $.effects.save( el, props ); 14729 el.show(); 14730 $.effects.createWrapper( el ); 14731 14732 // Animation 14733 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; 14734 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; 14735 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; 14736 14737 // Animate 14738 el.animate( animation, speed, o.easing ); 14739 14740 // Shakes 14741 for ( i = 1; i < times; i++ ) { 14742 el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing ); 14743 } 14744 el 14745 .animate( animation1, speed, o.easing ) 14746 .animate( animation, speed / 2, o.easing ) 14747 .queue(function() { 14748 if ( mode === "hide" ) { 14749 el.hide(); 14750 } 14751 $.effects.restore( el, props ); 14752 $.effects.removeWrapper( el ); 14753 done(); 14754 }); 14755 14756 // inject all the animations we just queued to be first in line (after "inprogress") 14757 if ( queuelen > 1) { 14758 queue.splice.apply( queue, 14759 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); 14760 } 14761 el.dequeue(); 14762 14763}; 14764 14765})(jQuery); 14766(function( $, undefined ) { 14767 14768$.effects.effect.slide = function( o, done ) { 14769 14770 // Create element 14771 var el = $( this ), 14772 props = [ "position", "top", "bottom", "left", "right", "width", "height" ], 14773 mode = $.effects.setMode( el, o.mode || "show" ), 14774 show = mode === "show", 14775 direction = o.direction || "left", 14776 ref = (direction === "up" || direction === "down") ? "top" : "left", 14777 positiveMotion = (direction === "up" || direction === "left"), 14778 distance, 14779 animation = {}; 14780 14781 // Adjust 14782 $.effects.save( el, props ); 14783 el.show(); 14784 distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ); 14785 14786 $.effects.createWrapper( el ).css({ 14787 overflow: "hidden" 14788 }); 14789 14790 if ( show ) { 14791 el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance ); 14792 } 14793 14794 // Animation 14795 animation[ ref ] = ( show ? 14796 ( positiveMotion ? "+=" : "-=") : 14797 ( positiveMotion ? "-=" : "+=")) + 14798 distance; 14799 14800 // Animate 14801 el.animate( animation, { 14802 queue: false, 14803 duration: o.duration, 14804 easing: o.easing, 14805 complete: function() { 14806 if ( mode === "hide" ) { 14807 el.hide(); 14808 } 14809 $.effects.restore( el, props ); 14810 $.effects.removeWrapper( el ); 14811 done(); 14812 } 14813 }); 14814}; 14815 14816})(jQuery); 14817(function( $, undefined ) { 14818 14819$.effects.effect.transfer = function( o, done ) { 14820 var elem = $( this ), 14821 target = $( o.to ), 14822 targetFixed = target.css( "position" ) === "fixed", 14823 body = $("body"), 14824 fixTop = targetFixed ? body.scrollTop() : 0, 14825 fixLeft = targetFixed ? body.scrollLeft() : 0, 14826 endPosition = target.offset(), 14827 animation = { 14828 top: endPosition.top - fixTop , 14829 left: endPosition.left - fixLeft , 14830 height: target.innerHeight(), 14831 width: target.innerWidth() 14832 }, 14833 startPosition = elem.offset(), 14834 transfer = $( "<div class='ui-effects-transfer'></div>" ) 14835 .appendTo( document.body ) 14836 .addClass( o.className ) 14837 .css({ 14838 top: startPosition.top - fixTop , 14839 left: startPosition.left - fixLeft , 14840 height: elem.innerHeight(), 14841 width: elem.innerWidth(), 14842 position: targetFixed ? "fixed" : "absolute" 14843 }) 14844 .animate( animation, o.duration, o.easing, function() { 14845 transfer.remove(); 14846 done(); 14847 }); 14848}; 14849 14850})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.