vendor: 8,540 bytes, lines 1-295
1/*! jQuery UI - v1.10.2 - 2013-04-17 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 2013 jQuery Foundation and other contributors Licensed MIT */ 5 6(function( $, undefined ) { 7 8var uuid = 0, 9 runiqueId = /^ui-id-\d+$/; 10 11// $.ui might exist from components with no dependencies, e.g., $.ui.position 12$.ui = $.ui || {}; 13 14$.extend( $.ui, { 15 version: "1.10.2", 16 17 keyCode: { 18 BACKSPACE: 8, 19 COMMA: 188, 20 DELETE: 46, 21 DOWN: 40, 22 END: 35, 23 ENTER: 13, 24 ESCAPE: 27, 25 HOME: 36, 26 LEFT: 37, 27 NUMPAD_ADD: 107, 28 NUMPAD_DECIMAL: 110, 29 NUMPAD_DIVIDE: 111, 30 NUMPAD_ENTER: 108, 31 NUMPAD_MULTIPLY: 106, 32 NUMPAD_SUBTRACT: 109, 33 PAGE_DOWN: 34, 34 PAGE_UP: 33, 35 PERIOD: 190, 36 RIGHT: 39, 37 SPACE: 32, 38 TAB: 9, 39 UP: 38 40 } 41}); 42 43// plugins 44$.fn.extend({ 45 focus: (function( orig ) { 46 return function( delay, fn ) { 47 return typeof delay === "number" ? 48 this.each(function() { 49 var elem = this; 50 setTimeout(function() { 51 $( elem ).focus(); 52 if ( fn ) { 53 fn.call( elem ); 54 } 55 }, delay ); 56 }) : 57 orig.apply( this, arguments ); 58 }; 59 })( $.fn.focus ), 60 61 scrollParent: function() { 62 var scrollParent; 63 if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) { 64 scrollParent = this.parents().filter(function() { 65 return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); 66 }).eq(0); 67 } else { 68 scrollParent = this.parents().filter(function() { 69 return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); 70 }).eq(0); 71 } 72 73 return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent; 74 }, 75 76 zIndex: function( zIndex ) { 77 if ( zIndex !== undefined ) { 78 return this.css( "zIndex", zIndex ); 79 } 80 81 if ( this.length ) { 82 var elem = $( this[ 0 ] ), position, value; 83 while ( elem.length && elem[ 0 ] !== document ) { 84 // Ignore z-index if position is set to a value where z-index is ignored by the browser 85 // This makes behavior of this function consistent across browsers 86 // WebKit always returns auto if the element is positioned 87 position = elem.css( "position" ); 88 if ( position === "absolute" || position === "relative" || position === "fixed" ) { 89 // IE returns 0 when zIndex is not specified 90 // other browsers return a string 91 // we ignore the case of nested elements with an explicit value of 0 92 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 93 value = parseInt( elem.css( "zIndex" ), 10 ); 94 if ( !isNaN( value ) && value !== 0 ) { 95 return value; 96 } 97 } 98 elem = elem.parent(); 99 } 100 } 101 102 return 0; 103 }, 104 105 uniqueId: function() { 106 return this.each(function() { 107 if ( !this.id ) { 108 this.id = "ui-id-" + (++uuid); 109 } 110 }); 111 }, 112 113 removeUniqueId: function() { 114 return this.each(function() { 115 if ( runiqueId.test( this.id ) ) { 116 $( this ).removeAttr( "id" ); 117 } 118 }); 119 } 120}); 121 122// selectors 123function focusable( element, isTabIndexNotNaN ) { 124 var map, mapName, img, 125 nodeName = element.nodeName.toLowerCase(); 126 if ( "area" === nodeName ) { 127 map = element.parentNode; 128 mapName = map.name; 129 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { 130 return false; 131 } 132 img = $( "img[usemap=#" + mapName + "]" )[0]; 133 return !!img && visible( img ); 134 } 135 return ( /input|select|textarea|button|object/.test( nodeName ) ? 136 !element.disabled : 137 "a" === nodeName ? 138 element.href || isTabIndexNotNaN : 139 isTabIndexNotNaN) && 140 // the element and all of its ancestors must be visible 141 visible( element ); 142} 143 144function visible( element ) { 145 return $.expr.filters.visible( element ) && 146 !$( element ).parents().addBack().filter(function() { 147 return $.css( this, "visibility" ) === "hidden"; 148 }).length; 149} 150 151$.extend( $.expr[ ":" ], { 152 data: $.expr.createPseudo ? 153 $.expr.createPseudo(function( dataName ) { 154 return function( elem ) { 155 return !!$.data( elem, dataName ); 156 }; 157 }) : 158 // support: jQuery <1.8 159 function( elem, i, match ) { 160 return !!$.data( elem, match[ 3 ] ); 161 }, 162 163 focusable: function( element ) { 164 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); 165 }, 166 167 tabbable: function( element ) { 168 var tabIndex = $.attr( element, "tabindex" ), 169 isTabIndexNaN = isNaN( tabIndex ); 170 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); 171 } 172}); 173 174// support: jQuery <1.8 175if ( !$( "<a>" ).outerWidth( 1 ).jquery ) { 176 $.each( [ "Width", "Height" ], function( i, name ) { 177 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], 178 type = name.toLowerCase(), 179 orig = { 180 innerWidth: $.fn.innerWidth, 181 innerHeight: $.fn.innerHeight, 182 outerWidth: $.fn.outerWidth, 183 outerHeight: $.fn.outerHeight 184 }; 185 186 function reduce( elem, size, border, margin ) { 187 $.each( side, function() { 188 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; 189 if ( border ) { 190 size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; 191 } 192 if ( margin ) { 193 size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; 194 } 195 }); 196 return size; 197 } 198 199 $.fn[ "inner" + name ] = function( size ) { 200 if ( size === undefined ) { 201 return orig[ "inner" + name ].call( this ); 202 } 203 204 return this.each(function() { 205 $( this ).css( type, reduce( this, size ) + "px" ); 206 }); 207 }; 208 209 $.fn[ "outer" + name] = function( size, margin ) { 210 if ( typeof size !== "number" ) { 211 return orig[ "outer" + name ].call( this, size ); 212 } 213 214 return this.each(function() { 215 $( this).css( type, reduce( this, size, true, margin ) + "px" ); 216 }); 217 }; 218 }); 219} 220 221// support: jQuery <1.8 222if ( !$.fn.addBack ) { 223 $.fn.addBack = function( selector ) { 224 return this.add( selector == null ? 225 this.prevObject : this.prevObject.filter( selector ) 226 ); 227 }; 228} 229 230// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413) 231if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) { 232 $.fn.removeData = (function( removeData ) { 233 return function( key ) { 234 if ( arguments.length ) { 235 return removeData.call( this, $.camelCase( key ) ); 236 } else { 237 return removeData.call( this ); 238 } 239 }; 240 })( $.fn.removeData ); 241} 242 243 244 245 246 247// deprecated 248$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ); 249 250$.support.selectstart = "onselectstart" in document.createElement( "div" ); 251$.fn.extend({ 252 disableSelection: function() { 253 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + 254 ".ui-disableSelection", function( event ) { 255 event.preventDefault(); 256 }); 257 }, 258 259 enableSelection: function() { 260 return this.unbind( ".ui-disableSelection" ); 261 } 262}); 263 264$.extend( $.ui, { 265 // $.ui.plugin is deprecated. Use the proxy pattern instead. 266 plugin: { 267 add: function( module, option, set ) { 268 var i, 269 proto = $.ui[ module ].prototype; 270 for ( i in set ) { 271 proto.plugins[ i ] = proto.plugins[ i ] || []; 272 proto.plugins[ i ].push( [ option, set[ i ] ] ); 273 } 274 }, 275 call: function( instance, name, args ) { 276 var i, 277 set = instance.plugins[ name ]; 278 if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) { 279 return; 280 } 281 282 for ( i = 0; i < set.length; i++ ) { 283 if ( instance.options[ set[ i ][ 0 ] ] ) { 284 set[ i ][ 1 ].apply( instance.element, args ); 285 } 286 } 287 } 288 }, 289 290 // only used by resizable 291 hasScroll: function( el, a ) { 292 293 //If overflow is hidden, the element might have extra content, but the user wants to hide it 294 if ( $( el ).css( "overflow" ) === "hidden") { 295 return false;
296 } 297 298 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", 299 has = false; 300 301 if ( el[ scroll ] > 0 ) { 302 return true; 303 } 304 305 // TODO: determine which cases actually cause this to happen 306 // if the element doesn't have the scroll set, see if it's possible to 307 // set the scroll 308 el[ scroll ] = 1; 309 has = ( el[ scroll ] > 0 ); 310 el[ scroll ] = 0; 311 return has; 312 } 313}); 314 315})( jQuery );
vendor: 14,841 bytes, lines 315-826
315 316(function( $, undefined ) { 317 318var uuid = 0, 319 slice = Array.prototype.slice, 320 _cleanData = $.cleanData; 321$.cleanData = function( elems ) { 322 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { 323 try { 324 $( elem ).triggerHandler( "remove" ); 325 // http://bugs.jquery.com/ticket/8235 326 } catch( e ) {} 327 } 328 _cleanData( elems ); 329}; 330 331$.widget = function( name, base, prototype ) { 332 var fullName, existingConstructor, constructor, basePrototype, 333 // proxiedPrototype allows the provided prototype to remain unmodified 334 // so that it can be used as a mixin for multiple widgets (#8876) 335 proxiedPrototype = {}, 336 namespace = name.split( "." )[ 0 ]; 337 338 name = name.split( "." )[ 1 ]; 339 fullName = namespace + "-" + name; 340 341 if ( !prototype ) { 342 prototype = base; 343 base = $.Widget; 344 } 345 346 // create selector for plugin 347 $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { 348 return !!$.data( elem, fullName ); 349 }; 350 351 $[ namespace ] = $[ namespace ] || {}; 352 existingConstructor = $[ namespace ][ name ]; 353 constructor = $[ namespace ][ name ] = function( options, element ) { 354 // allow instantiation without "new" keyword 355 if ( !this._createWidget ) { 356 return new constructor( options, element ); 357 } 358 359 // allow instantiation without initializing for simple inheritance 360 // must use "new" keyword (the code above always passes args) 361 if ( arguments.length ) { 362 this._createWidget( options, element ); 363 } 364 }; 365 // extend with the existing constructor to carry over any static properties 366 $.extend( constructor, existingConstructor, { 367 version: prototype.version, 368 // copy the object used to create the prototype in case we need to 369 // redefine the widget later 370 _proto: $.extend( {}, prototype ), 371 // track widgets that inherit from this widget in case this widget is 372 // redefined after a widget inherits from it 373 _childConstructors: [] 374 }); 375 376 basePrototype = new base(); 377 // we need to make the options hash a property directly on the new instance 378 // otherwise we'll modify the options hash on the prototype that we're 379 // inheriting from 380 basePrototype.options = $.widget.extend( {}, basePrototype.options ); 381 $.each( prototype, function( prop, value ) { 382 if ( !$.isFunction( value ) ) { 383 proxiedPrototype[ prop ] = value; 384 return; 385 } 386 proxiedPrototype[ prop ] = (function() { 387 var _super = function() { 388 return base.prototype[ prop ].apply( this, arguments ); 389 }, 390 _superApply = function( args ) { 391 return base.prototype[ prop ].apply( this, args ); 392 }; 393 return function() { 394 var __super = this._super, 395 __superApply = this._superApply, 396 returnValue; 397 398 this._super = _super; 399 this._superApply = _superApply; 400 401 returnValue = value.apply( this, arguments ); 402 403 this._super = __super; 404 this._superApply = __superApply; 405 406 return returnValue; 407 }; 408 })(); 409 }); 410 constructor.prototype = $.widget.extend( basePrototype, { 411 // TODO: remove support for widgetEventPrefix 412 // always use the name + a colon as the prefix, e.g., draggable:start 413 // don't prefix for widgets that aren't DOM-based 414 widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name 415 }, proxiedPrototype, { 416 constructor: constructor, 417 namespace: namespace, 418 widgetName: name, 419 widgetFullName: fullName 420 }); 421 422 // If this widget is being redefined then we need to find all widgets that 423 // are inheriting from it and redefine all of them so that they inherit from 424 // the new version of this widget. We're essentially trying to replace one 425 // level in the prototype chain. 426 if ( existingConstructor ) { 427 $.each( existingConstructor._childConstructors, function( i, child ) { 428 var childPrototype = child.prototype; 429 430 // redefine the child widget using the same prototype that was 431 // originally used, but inherit from the new version of the base 432 $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); 433 }); 434 // remove the list of existing child constructors from the old constructor 435 // so the old child constructors can be garbage collected 436 delete existingConstructor._childConstructors; 437 } else { 438 base._childConstructors.push( constructor ); 439 } 440 441 $.widget.bridge( name, constructor ); 442}; 443 444$.widget.extend = function( target ) { 445 var input = slice.call( arguments, 1 ), 446 inputIndex = 0, 447 inputLength = input.length, 448 key, 449 value; 450 for ( ; inputIndex < inputLength; inputIndex++ ) { 451 for ( key in input[ inputIndex ] ) { 452 value = input[ inputIndex ][ key ]; 453 if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { 454 // Clone objects 455 if ( $.isPlainObject( value ) ) { 456 target[ key ] = $.isPlainObject( target[ key ] ) ? 457 $.widget.extend( {}, target[ key ], value ) : 458 // Don't extend strings, arrays, etc. with objects 459 $.widget.extend( {}, value ); 460 // Copy everything else by reference 461 } else { 462 target[ key ] = value; 463 } 464 } 465 } 466 } 467 return target; 468}; 469 470$.widget.bridge = function( name, object ) { 471 var fullName = object.prototype.widgetFullName || name; 472 $.fn[ name ] = function( options ) { 473 var isMethodCall = typeof options === "string", 474 args = slice.call( arguments, 1 ), 475 returnValue = this; 476 477 // allow multiple hashes to be passed on init 478 options = !isMethodCall && args.length ? 479 $.widget.extend.apply( null, [ options ].concat(args) ) : 480 options; 481 482 if ( isMethodCall ) { 483 this.each(function() { 484 var methodValue, 485 instance = $.data( this, fullName ); 486 if ( !instance ) { 487 return $.error( "cannot call methods on " + name + " prior to initialization; " + 488 "attempted to call method '" + options + "'" ); 489 } 490 if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { 491 return $.error( "no such method '" + options + "' for " + name + " widget instance" ); 492 } 493 methodValue = instance[ options ].apply( instance, args ); 494 if ( methodValue !== instance && methodValue !== undefined ) { 495 returnValue = methodValue && methodValue.jquery ? 496 returnValue.pushStack( methodValue.get() ) : 497 methodValue; 498 return false; 499 } 500 }); 501 } else { 502 this.each(function() { 503 var instance = $.data( this, fullName ); 504 if ( instance ) { 505 instance.option( options || {} )._init(); 506 } else { 507 $.data( this, fullName, new object( options, this ) ); 508 } 509 }); 510 } 511 512 return returnValue; 513 }; 514}; 515 516$.Widget = function( /* options, element */ ) {}; 517$.Widget._childConstructors = []; 518 519$.Widget.prototype = { 520 widgetName: "widget", 521 widgetEventPrefix: "", 522 defaultElement: "<div>", 523 options: { 524 disabled: false, 525 526 // callbacks 527 create: null 528 }, 529 _createWidget: function( options, element ) { 530 element = $( element || this.defaultElement || this )[ 0 ]; 531 this.element = $( element ); 532 this.uuid = uuid++; 533 this.eventNamespace = "." + this.widgetName + this.uuid; 534 this.options = $.widget.extend( {}, 535 this.options, 536 this._getCreateOptions(), 537 options ); 538 539 this.bindings = $(); 540 this.hoverable = $(); 541 this.focusable = $(); 542 543 if ( element !== this ) { 544 $.data( element, this.widgetFullName, this ); 545 this._on( true, this.element, { 546 remove: function( event ) { 547 if ( event.target === element ) { 548 this.destroy(); 549 } 550 } 551 }); 552 this.document = $( element.style ? 553 // element within the document 554 element.ownerDocument : 555 // element is window or document 556 element.document || element ); 557 this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); 558 } 559 560 this._create(); 561 this._trigger( "create", null, this._getCreateEventData() ); 562 this._init(); 563 }, 564 _getCreateOptions: $.noop, 565 _getCreateEventData: $.noop, 566 _create: $.noop, 567 _init: $.noop, 568 569 destroy: function() { 570 this._destroy(); 571 // we can probably remove the unbind calls in 2.0 572 // all event bindings should go through this._on() 573 this.element 574 .unbind( this.eventNamespace ) 575 // 1.9 BC for #7810 576 // TODO remove dual storage 577 .removeData( this.widgetName ) 578 .removeData( this.widgetFullName ) 579 // support: jquery <1.6.3 580 // http://bugs.jquery.com/ticket/9413 581 .removeData( $.camelCase( this.widgetFullName ) ); 582 this.widget() 583 .unbind( this.eventNamespace ) 584 .removeAttr( "aria-disabled" ) 585 .removeClass( 586 this.widgetFullName + "-disabled " + 587 "ui-state-disabled" ); 588 589 // clean up events and states 590 this.bindings.unbind( this.eventNamespace ); 591 this.hoverable.removeClass( "ui-state-hover" ); 592 this.focusable.removeClass( "ui-state-focus" ); 593 }, 594 _destroy: $.noop, 595 596 widget: function() { 597 return this.element; 598 }, 599 600 option: function( key, value ) { 601 var options = key, 602 parts, 603 curOption, 604 i; 605 606 if ( arguments.length === 0 ) { 607 // don't return a reference to the internal hash 608 return $.widget.extend( {}, this.options ); 609 } 610 611 if ( typeof key === "string" ) { 612 // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } 613 options = {}; 614 parts = key.split( "." ); 615 key = parts.shift(); 616 if ( parts.length ) { 617 curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); 618 for ( i = 0; i < parts.length - 1; i++ ) { 619 curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; 620 curOption = curOption[ parts[ i ] ]; 621 } 622 key = parts.pop(); 623 if ( value === undefined ) { 624 return curOption[ key ] === undefined ? null : curOption[ key ]; 625 } 626 curOption[ key ] = value; 627 } else { 628 if ( value === undefined ) { 629 return this.options[ key ] === undefined ? null : this.options[ key ]; 630 } 631 options[ key ] = value; 632 } 633 } 634 635 this._setOptions( options ); 636 637 return this; 638 }, 639 _setOptions: function( options ) { 640 var key; 641 642 for ( key in options ) { 643 this._setOption( key, options[ key ] ); 644 } 645 646 return this; 647 }, 648 _setOption: function( key, value ) { 649 this.options[ key ] = value; 650 651 if ( key === "disabled" ) { 652 this.widget() 653 .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value ) 654 .attr( "aria-disabled", value ); 655 this.hoverable.removeClass( "ui-state-hover" ); 656 this.focusable.removeClass( "ui-state-focus" ); 657 } 658 659 return this; 660 }, 661 662 enable: function() { 663 return this._setOption( "disabled", false ); 664 }, 665 disable: function() { 666 return this._setOption( "disabled", true ); 667 }, 668 669 _on: function( suppressDisabledCheck, element, handlers ) { 670 var delegateElement, 671 instance = this; 672 673 // no suppressDisabledCheck flag, shuffle arguments 674 if ( typeof suppressDisabledCheck !== "boolean" ) { 675 handlers = element; 676 element = suppressDisabledCheck; 677 suppressDisabledCheck = false; 678 } 679 680 // no element argument, shuffle and use this.element 681 if ( !handlers ) { 682 handlers = element; 683 element = this.element; 684 delegateElement = this.widget(); 685 } else { 686 // accept selectors, DOM elements 687 element = delegateElement = $( element ); 688 this.bindings = this.bindings.add( element ); 689 } 690 691 $.each( handlers, function( event, handler ) { 692 function handlerProxy() { 693 // allow widgets to customize the disabled handling 694 // - disabled as an array instead of boolean 695 // - disabled class as method for disabling individual parts 696 if ( !suppressDisabledCheck && 697 ( instance.options.disabled === true || 698 $( this ).hasClass( "ui-state-disabled" ) ) ) { 699 return; 700 } 701 return ( typeof handler === "string" ? instance[ handler ] : handler ) 702 .apply( instance, arguments ); 703 } 704 705 // copy the guid so direct unbinding works 706 if ( typeof handler !== "string" ) { 707 handlerProxy.guid = handler.guid = 708 handler.guid || handlerProxy.guid || $.guid++; 709 } 710 711 var match = event.match( /^(\w+)\s*(.*)$/ ), 712 eventName = match[1] + instance.eventNamespace, 713 selector = match[2]; 714 if ( selector ) { 715 delegateElement.delegate( selector, eventName, handlerProxy ); 716 } else { 717 element.bind( eventName, handlerProxy ); 718 } 719 }); 720 }, 721 722 _off: function( element, eventName ) { 723 eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace; 724 element.unbind( eventName ).undelegate( eventName ); 725 }, 726 727 _delay: function( handler, delay ) { 728 function handlerProxy() { 729 return ( typeof handler === "string" ? instance[ handler ] : handler ) 730 .apply( instance, arguments ); 731 } 732 var instance = this; 733 return setTimeout( handlerProxy, delay || 0 ); 734 }, 735 736 _hoverable: function( element ) { 737 this.hoverable = this.hoverable.add( element ); 738 this._on( element, { 739 mouseenter: function( event ) { 740 $( event.currentTarget ).addClass( "ui-state-hover" ); 741 }, 742 mouseleave: function( event ) { 743 $( event.currentTarget ).removeClass( "ui-state-hover" ); 744 } 745 }); 746 }, 747 748 _focusable: function( element ) { 749 this.focusable = this.focusable.add( element ); 750 this._on( element, { 751 focusin: function( event ) { 752 $( event.currentTarget ).addClass( "ui-state-focus" ); 753 }, 754 focusout: function( event ) { 755 $( event.currentTarget ).removeClass( "ui-state-focus" ); 756 } 757 }); 758 }, 759 760 _trigger: function( type, event, data ) { 761 var prop, orig, 762 callback = this.options[ type ]; 763 764 data = data || {}; 765 event = $.Event( event ); 766 event.type = ( type === this.widgetEventPrefix ? 767 type : 768 this.widgetEventPrefix + type ).toLowerCase(); 769 // the original event may come from any element 770 // so we need to reset the target on the new event 771 event.target = this.element[ 0 ]; 772 773 // copy original event properties over to the new event 774 orig = event.originalEvent; 775 if ( orig ) { 776 for ( prop in orig ) { 777 if ( !( prop in event ) ) { 778 event[ prop ] = orig[ prop ]; 779 } 780 } 781 } 782 783 this.element.trigger( event, data ); 784 return !( $.isFunction( callback ) && 785 callback.apply( this.element[0], [ event ].concat( data ) ) === false || 786 event.isDefaultPrevented() ); 787 } 788}; 789 790$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { 791 $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { 792 if ( typeof options === "string" ) { 793 options = { effect: options }; 794 } 795 var hasOptions, 796 effectName = !options ? 797 method : 798 options === true || typeof options === "number" ? 799 defaultEffect : 800 options.effect || defaultEffect; 801 options = options || {}; 802 if ( typeof options === "number" ) { 803 options = { duration: options }; 804 } 805 hasOptions = !$.isEmptyObject( options ); 806 options.complete = callback; 807 if ( options.delay ) { 808 element.delay( options.delay ); 809 } 810 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { 811 element[ method ]( options ); 812 } else if ( effectName !== method && element[ effectName ] ) { 813 element[ effectName ]( options.duration, options.easing, callback ); 814 } else { 815 element.queue(function( next ) { 816 $( this )[ method ](); 817 if ( callback ) { 818 callback.call( element[ 0 ] ); 819 } 820 next(); 821 }); 822 } 823 }; 824}); 825 826})( jQuery );
827(function( $, undefined ) { 828 829var mouseHandled = false;
vendor: 29,059 bytes, lines 830-1804
830$( document ).mouseup( function() { 831 mouseHandled = false; 832}); 833 834$.widget("ui.mouse", { 835 version: "1.10.2", 836 options: { 837 cancel: "input,textarea,button,select,option", 838 distance: 1, 839 delay: 0 840 }, 841 _mouseInit: function() { 842 var that = this; 843 844 this.element 845 .bind("mousedown."+this.widgetName, function(event) { 846 return that._mouseDown(event); 847 }) 848 .bind("click."+this.widgetName, function(event) { 849 if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) { 850 $.removeData(event.target, that.widgetName + ".preventClickEvent"); 851 event.stopImmediatePropagation(); 852 return false; 853 } 854 }); 855 856 this.started = false; 857 }, 858 859 // TODO: make sure destroying one instance of mouse doesn't mess with 860 // other instances of mouse 861 _mouseDestroy: function() { 862 this.element.unbind("."+this.widgetName); 863 if ( this._mouseMoveDelegate ) { 864 $(document) 865 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate) 866 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate); 867 } 868 }, 869 870 _mouseDown: function(event) { 871 // don't let more than one widget handle mouseStart 872 if( mouseHandled ) { return; } 873 874 // we may have missed mouseup (out of window) 875 (this._mouseStarted && this._mouseUp(event)); 876 877 this._mouseDownEvent = event; 878 879 var that = this, 880 btnIsLeft = (event.which === 1), 881 // event.target.nodeName works around a bug in IE 8 with 882 // disabled inputs (#7620) 883 elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); 884 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { 885 return true; 886 } 887 888 this.mouseDelayMet = !this.options.delay; 889 if (!this.mouseDelayMet) { 890 this._mouseDelayTimer = setTimeout(function() { 891 that.mouseDelayMet = true; 892 }, this.options.delay); 893 } 894 895 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 896 this._mouseStarted = (this._mouseStart(event) !== false); 897 if (!this._mouseStarted) { 898 event.preventDefault(); 899 return true; 900 } 901 } 902 903 // Click event may never have fired (Gecko & Opera) 904 if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) { 905 $.removeData(event.target, this.widgetName + ".preventClickEvent"); 906 } 907 908 // these delegates are required to keep context 909 this._mouseMoveDelegate = function(event) { 910 return that._mouseMove(event); 911 }; 912 this._mouseUpDelegate = function(event) { 913 return that._mouseUp(event); 914 }; 915 $(document) 916 .bind("mousemove."+this.widgetName, this._mouseMoveDelegate) 917 .bind("mouseup."+this.widgetName, this._mouseUpDelegate); 918 919 event.preventDefault(); 920 921 mouseHandled = true; 922 return true; 923 }, 924 925 _mouseMove: function(event) { 926 // IE mouseup check - mouseup happened when mouse was out of window 927 if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) { 928 return this._mouseUp(event); 929 } 930 931 if (this._mouseStarted) { 932 this._mouseDrag(event); 933 return event.preventDefault(); 934 } 935 936 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 937 this._mouseStarted = 938 (this._mouseStart(this._mouseDownEvent, event) !== false); 939 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); 940 } 941 942 return !this._mouseStarted; 943 }, 944 945 _mouseUp: function(event) { 946 $(document) 947 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate) 948 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate); 949 950 if (this._mouseStarted) { 951 this._mouseStarted = false; 952 953 if (event.target === this._mouseDownEvent.target) { 954 $.data(event.target, this.widgetName + ".preventClickEvent", true); 955 } 956 957 this._mouseStop(event); 958 } 959 960 return false; 961 }, 962 963 _mouseDistanceMet: function(event) { 964 return (Math.max( 965 Math.abs(this._mouseDownEvent.pageX - event.pageX), 966 Math.abs(this._mouseDownEvent.pageY - event.pageY) 967 ) >= this.options.distance 968 ); 969 }, 970 971 _mouseDelayMet: function(/* event */) { 972 return this.mouseDelayMet; 973 }, 974 975 // These are placeholder methods, to be overriden by extending plugin 976 _mouseStart: function(/* event */) {}, 977 _mouseDrag: function(/* event */) {}, 978 _mouseStop: function(/* event */) {}, 979 _mouseCapture: function(/* event */) { return true; } 980}); 981 982})(jQuery); 983(function( $, undefined ) { 984 985$.ui = $.ui || {}; 986 987var cachedScrollbarWidth, 988 max = Math.max, 989 abs = Math.abs, 990 round = Math.round, 991 rhorizontal = /left|center|right/, 992 rvertical = /top|center|bottom/, 993 roffset = /[\+\-]\d+(\.[\d]+)?%?/, 994 rposition = /^\w+/, 995 rpercent = /%$/, 996 _position = $.fn.position; 997 998function getOffsets( offsets, width, height ) { 999 return [ 1000 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), 1001 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) 1002 ]; 1003} 1004 1005function parseCss( element, property ) { 1006 return parseInt( $.css( element, property ), 10 ) || 0; 1007} 1008 1009function getDimensions( elem ) { 1010 var raw = elem[0]; 1011 if ( raw.nodeType === 9 ) { 1012 return { 1013 width: elem.width(), 1014 height: elem.height(), 1015 offset: { top: 0, left: 0 } 1016 }; 1017 } 1018 if ( $.isWindow( raw ) ) { 1019 return { 1020 width: elem.width(), 1021 height: elem.height(), 1022 offset: { top: elem.scrollTop(), left: elem.scrollLeft() } 1023 }; 1024 } 1025 if ( raw.preventDefault ) { 1026 return { 1027 width: 0, 1028 height: 0, 1029 offset: { top: raw.pageY, left: raw.pageX } 1030 }; 1031 } 1032 return { 1033 width: elem.outerWidth(), 1034 height: elem.outerHeight(), 1035 offset: elem.offset() 1036 }; 1037} 1038 1039$.position = { 1040 scrollbarWidth: function() { 1041 if ( cachedScrollbarWidth !== undefined ) { 1042 return cachedScrollbarWidth; 1043 } 1044 var w1, w2, 1045 div = $( "<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ), 1046 innerDiv = div.children()[0]; 1047 1048 $( "body" ).append( div ); 1049 w1 = innerDiv.offsetWidth; 1050 div.css( "overflow", "scroll" ); 1051 1052 w2 = innerDiv.offsetWidth; 1053 1054 if ( w1 === w2 ) { 1055 w2 = div[0].clientWidth; 1056 } 1057 1058 div.remove(); 1059 1060 return (cachedScrollbarWidth = w1 - w2); 1061 }, 1062 getScrollInfo: function( within ) { 1063 var overflowX = within.isWindow ? "" : within.element.css( "overflow-x" ), 1064 overflowY = within.isWindow ? "" : within.element.css( "overflow-y" ), 1065 hasOverflowX = overflowX === "scroll" || 1066 ( overflowX === "auto" && within.width < within.element[0].scrollWidth ), 1067 hasOverflowY = overflowY === "scroll" || 1068 ( overflowY === "auto" && within.height < within.element[0].scrollHeight ); 1069 return { 1070 width: hasOverflowY ? $.position.scrollbarWidth() : 0, 1071 height: hasOverflowX ? $.position.scrollbarWidth() : 0 1072 }; 1073 }, 1074 getWithinInfo: function( element ) { 1075 var withinElement = $( element || window ), 1076 isWindow = $.isWindow( withinElement[0] ); 1077 return { 1078 element: withinElement, 1079 isWindow: isWindow, 1080 offset: withinElement.offset() || { left: 0, top: 0 }, 1081 scrollLeft: withinElement.scrollLeft(), 1082 scrollTop: withinElement.scrollTop(), 1083 width: isWindow ? withinElement.width() : withinElement.outerWidth(), 1084 height: isWindow ? withinElement.height() : withinElement.outerHeight() 1085 }; 1086 } 1087}; 1088 1089$.fn.position = function( options ) { 1090 if ( !options || !options.of ) { 1091 return _position.apply( this, arguments ); 1092 } 1093 1094 // make a copy, we don't want to modify arguments 1095 options = $.extend( {}, options ); 1096 1097 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, 1098 target = $( options.of ), 1099 within = $.position.getWithinInfo( options.within ), 1100 scrollInfo = $.position.getScrollInfo( within ), 1101 collision = ( options.collision || "flip" ).split( " " ), 1102 offsets = {}; 1103 1104 dimensions = getDimensions( target ); 1105 if ( target[0].preventDefault ) { 1106 // force left top to allow flipping 1107 options.at = "left top"; 1108 } 1109 targetWidth = dimensions.width; 1110 targetHeight = dimensions.height; 1111 targetOffset = dimensions.offset; 1112 // clone to reuse original targetOffset later 1113 basePosition = $.extend( {}, targetOffset ); 1114 1115 // force my and at to have valid horizontal and vertical positions 1116 // if a value is missing or invalid, it will be converted to center 1117 $.each( [ "my", "at" ], function() { 1118 var pos = ( options[ this ] || "" ).split( " " ), 1119 horizontalOffset, 1120 verticalOffset; 1121 1122 if ( pos.length === 1) { 1123 pos = rhorizontal.test( pos[ 0 ] ) ? 1124 pos.concat( [ "center" ] ) : 1125 rvertical.test( pos[ 0 ] ) ? 1126 [ "center" ].concat( pos ) : 1127 [ "center", "center" ]; 1128 } 1129 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; 1130 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; 1131 1132 // calculate offsets 1133 horizontalOffset = roffset.exec( pos[ 0 ] ); 1134 verticalOffset = roffset.exec( pos[ 1 ] ); 1135 offsets[ this ] = [ 1136 horizontalOffset ? horizontalOffset[ 0 ] : 0, 1137 verticalOffset ? verticalOffset[ 0 ] : 0 1138 ]; 1139 1140 // reduce to just the positions without the offsets 1141 options[ this ] = [ 1142 rposition.exec( pos[ 0 ] )[ 0 ], 1143 rposition.exec( pos[ 1 ] )[ 0 ] 1144 ]; 1145 }); 1146 1147 // normalize collision option 1148 if ( collision.length === 1 ) { 1149 collision[ 1 ] = collision[ 0 ]; 1150 } 1151 1152 if ( options.at[ 0 ] === "right" ) { 1153 basePosition.left += targetWidth; 1154 } else if ( options.at[ 0 ] === "center" ) { 1155 basePosition.left += targetWidth / 2; 1156 } 1157 1158 if ( options.at[ 1 ] === "bottom" ) { 1159 basePosition.top += targetHeight; 1160 } else if ( options.at[ 1 ] === "center" ) { 1161 basePosition.top += targetHeight / 2; 1162 } 1163 1164 atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); 1165 basePosition.left += atOffset[ 0 ]; 1166 basePosition.top += atOffset[ 1 ]; 1167 1168 return this.each(function() { 1169 var collisionPosition, using, 1170 elem = $( this ), 1171 elemWidth = elem.outerWidth(), 1172 elemHeight = elem.outerHeight(), 1173 marginLeft = parseCss( this, "marginLeft" ), 1174 marginTop = parseCss( this, "marginTop" ), 1175 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width, 1176 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height, 1177 position = $.extend( {}, basePosition ), 1178 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); 1179 1180 if ( options.my[ 0 ] === "right" ) { 1181 position.left -= elemWidth; 1182 } else if ( options.my[ 0 ] === "center" ) { 1183 position.left -= elemWidth / 2; 1184 } 1185 1186 if ( options.my[ 1 ] === "bottom" ) { 1187 position.top -= elemHeight; 1188 } else if ( options.my[ 1 ] === "center" ) { 1189 position.top -= elemHeight / 2; 1190 } 1191 1192 position.left += myOffset[ 0 ]; 1193 position.top += myOffset[ 1 ]; 1194 1195 // if the browser doesn't support fractions, then round for consistent results 1196 if ( !$.support.offsetFractions ) { 1197 position.left = round( position.left ); 1198 position.top = round( position.top ); 1199 } 1200 1201 collisionPosition = { 1202 marginLeft: marginLeft, 1203 marginTop: marginTop 1204 }; 1205 1206 $.each( [ "left", "top" ], function( i, dir ) { 1207 if ( $.ui.position[ collision[ i ] ] ) { 1208 $.ui.position[ collision[ i ] ][ dir ]( position, { 1209 targetWidth: targetWidth, 1210 targetHeight: targetHeight, 1211 elemWidth: elemWidth, 1212 elemHeight: elemHeight, 1213 collisionPosition: collisionPosition, 1214 collisionWidth: collisionWidth, 1215 collisionHeight: collisionHeight, 1216 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], 1217 my: options.my, 1218 at: options.at, 1219 within: within, 1220 elem : elem 1221 }); 1222 } 1223 }); 1224 1225 if ( options.using ) { 1226 // adds feedback as second argument to using callback, if present 1227 using = function( props ) { 1228 var left = targetOffset.left - position.left, 1229 right = left + targetWidth - elemWidth, 1230 top = targetOffset.top - position.top, 1231 bottom = top + targetHeight - elemHeight, 1232 feedback = { 1233 target: { 1234 element: target, 1235 left: targetOffset.left, 1236 top: targetOffset.top, 1237 width: targetWidth, 1238 height: targetHeight 1239 }, 1240 element: { 1241 element: elem, 1242 left: position.left, 1243 top: position.top, 1244 width: elemWidth, 1245 height: elemHeight 1246 }, 1247 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", 1248 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" 1249 }; 1250 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { 1251 feedback.horizontal = "center"; 1252 } 1253 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { 1254 feedback.vertical = "middle"; 1255 } 1256 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { 1257 feedback.important = "horizontal"; 1258 } else { 1259 feedback.important = "vertical"; 1260 } 1261 options.using.call( this, props, feedback ); 1262 }; 1263 } 1264 1265 elem.offset( $.extend( position, { using: using } ) ); 1266 }); 1267}; 1268 1269$.ui.position = { 1270 fit: { 1271 left: function( position, data ) { 1272 var within = data.within, 1273 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, 1274 outerWidth = within.width, 1275 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 1276 overLeft = withinOffset - collisionPosLeft, 1277 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, 1278 newOverRight; 1279 1280 // element is wider than within 1281 if ( data.collisionWidth > outerWidth ) { 1282 // element is initially over the left side of within 1283 if ( overLeft > 0 && overRight <= 0 ) { 1284 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset; 1285 position.left += overLeft - newOverRight; 1286 // element is initially over right side of within 1287 } else if ( overRight > 0 && overLeft <= 0 ) { 1288 position.left = withinOffset; 1289 // element is initially over both left and right sides of within 1290 } else { 1291 if ( overLeft > overRight ) { 1292 position.left = withinOffset + outerWidth - data.collisionWidth; 1293 } else { 1294 position.left = withinOffset; 1295 } 1296 } 1297 // too far left -> align with left edge 1298 } else if ( overLeft > 0 ) { 1299 position.left += overLeft; 1300 // too far right -> align with right edge 1301 } else if ( overRight > 0 ) { 1302 position.left -= overRight; 1303 // adjust based on position and margin 1304 } else { 1305 position.left = max( position.left - collisionPosLeft, position.left ); 1306 } 1307 }, 1308 top: function( position, data ) { 1309 var within = data.within, 1310 withinOffset = within.isWindow ? within.scrollTop : within.offset.top, 1311 outerHeight = data.within.height, 1312 collisionPosTop = position.top - data.collisionPosition.marginTop, 1313 overTop = withinOffset - collisionPosTop, 1314 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, 1315 newOverBottom; 1316 1317 // element is taller than within 1318 if ( data.collisionHeight > outerHeight ) { 1319 // element is initially over the top of within 1320 if ( overTop > 0 && overBottom <= 0 ) { 1321 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset; 1322 position.top += overTop - newOverBottom; 1323 // element is initially over bottom of within 1324 } else if ( overBottom > 0 && overTop <= 0 ) { 1325 position.top = withinOffset; 1326 // element is initially over both top and bottom of within 1327 } else { 1328 if ( overTop > overBottom ) { 1329 position.top = withinOffset + outerHeight - data.collisionHeight; 1330 } else { 1331 position.top = withinOffset; 1332 } 1333 } 1334 // too far up -> align with top 1335 } else if ( overTop > 0 ) { 1336 position.top += overTop; 1337 // too far down -> align with bottom edge 1338 } else if ( overBottom > 0 ) { 1339 position.top -= overBottom; 1340 // adjust based on position and margin 1341 } else { 1342 position.top = max( position.top - collisionPosTop, position.top ); 1343 } 1344 } 1345 }, 1346 flip: { 1347 left: function( position, data ) { 1348 var within = data.within, 1349 withinOffset = within.offset.left + within.scrollLeft, 1350 outerWidth = within.width, 1351 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, 1352 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 1353 overLeft = collisionPosLeft - offsetLeft, 1354 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, 1355 myOffset = data.my[ 0 ] === "left" ? 1356 -data.elemWidth : 1357 data.my[ 0 ] === "right" ? 1358 data.elemWidth : 1359 0, 1360 atOffset = data.at[ 0 ] === "left" ? 1361 data.targetWidth : 1362 data.at[ 0 ] === "right" ? 1363 -data.targetWidth : 1364 0, 1365 offset = -2 * data.offset[ 0 ], 1366 newOverRight, 1367 newOverLeft; 1368 1369 if ( overLeft < 0 ) { 1370 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset; 1371 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { 1372 position.left += myOffset + atOffset + offset; 1373 } 1374 } 1375 else if ( overRight > 0 ) { 1376 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft; 1377 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { 1378 position.left += myOffset + atOffset + offset; 1379 } 1380 } 1381 }, 1382 top: function( position, data ) { 1383 var within = data.within, 1384 withinOffset = within.offset.top + within.scrollTop, 1385 outerHeight = within.height, 1386 offsetTop = within.isWindow ? within.scrollTop : within.offset.top, 1387 collisionPosTop = position.top - data.collisionPosition.marginTop, 1388 overTop = collisionPosTop - offsetTop, 1389 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, 1390 top = data.my[ 1 ] === "top", 1391 myOffset = top ? 1392 -data.elemHeight : 1393 data.my[ 1 ] === "bottom" ? 1394 data.elemHeight : 1395 0, 1396 atOffset = data.at[ 1 ] === "top" ? 1397 data.targetHeight : 1398 data.at[ 1 ] === "bottom" ? 1399 -data.targetHeight : 1400 0, 1401 offset = -2 * data.offset[ 1 ], 1402 newOverTop, 1403 newOverBottom; 1404 if ( overTop < 0 ) { 1405 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset; 1406 if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) { 1407 position.top += myOffset + atOffset + offset; 1408 } 1409 } 1410 else if ( overBottom > 0 ) { 1411 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop; 1412 if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) { 1413 position.top += myOffset + atOffset + offset; 1414 } 1415 } 1416 } 1417 }, 1418 flipfit: { 1419 left: function() { 1420 $.ui.position.flip.left.apply( this, arguments ); 1421 $.ui.position.fit.left.apply( this, arguments ); 1422 }, 1423 top: function() { 1424 $.ui.position.flip.top.apply( this, arguments ); 1425 $.ui.position.fit.top.apply( this, arguments ); 1426 } 1427 } 1428}; 1429 1430// fraction support test 1431(function () { 1432 var testElement, testElementParent, testElementStyle, offsetLeft, i, 1433 body = document.getElementsByTagName( "body" )[ 0 ], 1434 div = document.createElement( "div" ); 1435 1436 //Create a "fake body" for testing based on method used in jQuery.support 1437 testElement = document.createElement( body ? "div" : "body" ); 1438 testElementStyle = { 1439 visibility: "hidden", 1440 width: 0, 1441 height: 0, 1442 border: 0, 1443 margin: 0, 1444 background: "none" 1445 }; 1446 if ( body ) { 1447 $.extend( testElementStyle, { 1448 position: "absolute", 1449 left: "-1000px", 1450 top: "-1000px" 1451 }); 1452 } 1453 for ( i in testElementStyle ) { 1454 testElement.style[ i ] = testElementStyle[ i ]; 1455 } 1456 testElement.appendChild( div ); 1457 testElementParent = body || document.documentElement; 1458 testElementParent.insertBefore( testElement, testElementParent.firstChild ); 1459 1460 div.style.cssText = "position: absolute; left: 10.7432222px;"; 1461 1462 offsetLeft = $( div ).offset().left; 1463 $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11; 1464 1465 testElement.innerHTML = ""; 1466 testElementParent.removeChild( testElement ); 1467})(); 1468 1469}( jQuery ) ); 1470(function( $, undefined ) { 1471 1472$.widget("ui.draggable", $.ui.mouse, { 1473 version: "1.10.2", 1474 widgetEventPrefix: "drag", 1475 options: { 1476 addClasses: true, 1477 appendTo: "parent", 1478 axis: false, 1479 connectToSortable: false, 1480 containment: false, 1481 cursor: "auto", 1482 cursorAt: false, 1483 grid: false, 1484 handle: false, 1485 helper: "original", 1486 iframeFix: false, 1487 opacity: false, 1488 refreshPositions: false, 1489 revert: false, 1490 revertDuration: 500, 1491 scope: "default", 1492 scroll: true, 1493 scrollSensitivity: 20, 1494 scrollSpeed: 20, 1495 snap: false, 1496 snapMode: "both", 1497 snapTolerance: 20, 1498 stack: false, 1499 zIndex: false, 1500 1501 // callbacks 1502 drag: null, 1503 start: null, 1504 stop: null 1505 }, 1506 _create: function() { 1507 1508 if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) { 1509 this.element[0].style.position = "relative"; 1510 } 1511 if (this.options.addClasses){ 1512 this.element.addClass("ui-draggable"); 1513 } 1514 if (this.options.disabled){ 1515 this.element.addClass("ui-draggable-disabled"); 1516 } 1517 1518 this._mouseInit(); 1519 1520 }, 1521 1522 _destroy: function() { 1523 this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" ); 1524 this._mouseDestroy(); 1525 }, 1526 1527 _mouseCapture: function(event) { 1528 1529 var o = this.options; 1530 1531 // among others, prevent a drag on a resizable-handle 1532 if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) { 1533 return false; 1534 } 1535 1536 //Quit if we're not on a valid handle 1537 this.handle = this._getHandle(event); 1538 if (!this.handle) { 1539 return false; 1540 } 1541 1542 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { 1543 $("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>") 1544 .css({ 1545 width: this.offsetWidth+"px", height: this.offsetHeight+"px", 1546 position: "absolute", opacity: "0.001", zIndex: 1000 1547 }) 1548 .css($(this).offset()) 1549 .appendTo("body"); 1550 }); 1551 1552 return true; 1553 1554 }, 1555 1556 _mouseStart: function(event) { 1557 1558 var o = this.options; 1559 1560 //Create and append the visible helper 1561 this.helper = this._createHelper(event); 1562 1563 this.helper.addClass("ui-draggable-dragging"); 1564 1565 //Cache the helper size 1566 this._cacheHelperProportions(); 1567 1568 //If ddmanager is used for droppables, set the global draggable 1569 if($.ui.ddmanager) { 1570 $.ui.ddmanager.current = this; 1571 } 1572 1573 /* 1574 * - Position generation - 1575 * This block generates everything position related - it's the core of draggables. 1576 */ 1577 1578 //Cache the margins of the original element 1579 this._cacheMargins(); 1580 1581 //Store the helper's css position 1582 this.cssPosition = this.helper.css("position"); 1583 this.scrollParent = this.helper.scrollParent(); 1584 1585 //The element's absolute position on the page minus margins 1586 this.offset = this.positionAbs = this.element.offset(); 1587 this.offset = { 1588 top: this.offset.top - this.margins.top, 1589 left: this.offset.left - this.margins.left 1590 }; 1591 1592 $.extend(this.offset, { 1593 click: { //Where the click happened, relative to the element 1594 left: event.pageX - this.offset.left, 1595 top: event.pageY - this.offset.top 1596 }, 1597 parent: this._getParentOffset(), 1598 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper 1599 }); 1600 1601 //Generate the original position 1602 this.originalPosition = this.position = this._generatePosition(event); 1603 this.originalPageX = event.pageX; 1604 this.originalPageY = event.pageY; 1605 1606 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 1607 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); 1608 1609 //Set a containment if given in the options 1610 if(o.containment) { 1611 this._setContainment(); 1612 } 1613 1614 //Trigger event + callbacks 1615 if(this._trigger("start", event) === false) { 1616 this._clear(); 1617 return false; 1618 } 1619 1620 //Recache the helper size 1621 this._cacheHelperProportions(); 1622 1623 //Prepare the droppable offsets 1624 if ($.ui.ddmanager && !o.dropBehaviour) { 1625 $.ui.ddmanager.prepareOffsets(this, event); 1626 } 1627 1628 1629 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position 1630 1631 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) 1632 if ( $.ui.ddmanager ) { 1633 $.ui.ddmanager.dragStart(this, event); 1634 } 1635 1636 return true; 1637 }, 1638 1639 _mouseDrag: function(event, noPropagation) { 1640 1641 //Compute the helpers position 1642 this.position = this._generatePosition(event); 1643 this.positionAbs = this._convertPositionTo("absolute"); 1644 1645 //Call plugins and callbacks and use the resulting position if something is returned 1646 if (!noPropagation) { 1647 var ui = this._uiHash(); 1648 if(this._trigger("drag", event, ui) === false) { 1649 this._mouseUp({}); 1650 return false; 1651 } 1652 this.position = ui.position; 1653 } 1654 1655 if(!this.options.axis || this.options.axis !== "y") { 1656 this.helper[0].style.left = this.position.left+"px"; 1657 } 1658 if(!this.options.axis || this.options.axis !== "x") { 1659 this.helper[0].style.top = this.position.top+"px"; 1660 } 1661 if($.ui.ddmanager) { 1662 $.ui.ddmanager.drag(this, event); 1663 } 1664 1665 return false; 1666 }, 1667 1668 _mouseStop: function(event) { 1669 1670 //If we are using droppables, inform the manager about the drop 1671 var element, 1672 that = this, 1673 elementInDom = false, 1674 dropped = false; 1675 if ($.ui.ddmanager && !this.options.dropBehaviour) { 1676 dropped = $.ui.ddmanager.drop(this, event); 1677 } 1678 1679 //if a drop comes from outside (a sortable) 1680 if(this.dropped) { 1681 dropped = this.dropped; 1682 this.dropped = false; 1683 } 1684 1685 //if the original element is no longer in the DOM don't bother to continue (see #8269) 1686 element = this.element[0]; 1687 while ( element && (element = element.parentNode) ) { 1688 if (element === document ) { 1689 elementInDom = true; 1690 } 1691 } 1692 if ( !elementInDom && this.options.helper === "original" ) { 1693 return false; 1694 } 1695 1696 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))) { 1697 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { 1698 if(that._trigger("stop", event) !== false) { 1699 that._clear(); 1700 } 1701 }); 1702 } else { 1703 if(this._trigger("stop", event) !== false) { 1704 this._clear(); 1705 } 1706 } 1707 1708 return false; 1709 }, 1710 1711 _mouseUp: function(event) { 1712 //Remove frame helpers 1713 $("div.ui-draggable-iframeFix").each(function() { 1714 this.parentNode.removeChild(this); 1715 }); 1716 1717 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) 1718 if( $.ui.ddmanager ) { 1719 $.ui.ddmanager.dragStop(this, event); 1720 } 1721 1722 return $.ui.mouse.prototype._mouseUp.call(this, event); 1723 }, 1724 1725 cancel: function() { 1726 1727 if(this.helper.is(".ui-draggable-dragging")) { 1728 this._mouseUp({}); 1729 } else { 1730 this._clear(); 1731 } 1732 1733 return this; 1734 1735 }, 1736 1737 _getHandle: function(event) { 1738 return this.options.handle ? 1739 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length : 1740 true; 1741 }, 1742 1743 _createHelper: function(event) { 1744 1745 var o = this.options, 1746 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element); 1747 1748 if(!helper.parents("body").length) { 1749 helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo)); 1750 } 1751 1752 if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) { 1753 helper.css("position", "absolute"); 1754 } 1755 1756 return helper; 1757 1758 }, 1759 1760 _adjustOffsetFromHelper: function(obj) { 1761 if (typeof obj === "string") { 1762 obj = obj.split(" "); 1763 } 1764 if ($.isArray(obj)) { 1765 obj = {left: +obj[0], top: +obj[1] || 0}; 1766 } 1767 if ("left" in obj) { 1768 this.offset.click.left = obj.left + this.margins.left; 1769 } 1770 if ("right" in obj) { 1771 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 1772 } 1773 if ("top" in obj) { 1774 this.offset.click.top = obj.top + this.margins.top; 1775 } 1776 if ("bottom" in obj) { 1777 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 1778 } 1779 }, 1780 1781 _getParentOffset: function() { 1782 1783 //Get the offsetParent and cache its position 1784 this.offsetParent = this.helper.offsetParent(); 1785 var po = this.offsetParent.offset(); 1786 1787 // This is a special case where we need to modify a offset calculated on start, since the following happened: 1788 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent 1789 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that 1790 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag 1791 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { 1792 po.left += this.scrollParent.scrollLeft(); 1793 po.top += this.scrollParent.scrollTop(); 1794 } 1795 1796 //This needs to be actually done for all browsers, since pageX/pageY includes this information 1797 //Ugly IE fix 1798 if((this.offsetParent[0] === document.body) || 1799 (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { 1800 po = { top: 0, left: 0 }; 1801 } 1802 1803 return { 1804 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),
vendor: 1,408 bytes, lines 1804-1851
180410) || 0), 1805 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) 1806 }; 1807 1808 }, 1809 1810 _getRelativeOffset: function() { 1811 1812 if(this.cssPosition === "relative") { 1813 var p = this.element.position(); 1814 return { 1815 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), 1816 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() 1817 }; 1818 } else { 1819 return { top: 0, left: 0 }; 1820 } 1821 1822 }, 1823 1824 _cacheMargins: function() { 1825 this.margins = { 1826 left: (parseInt(this.element.css("marginLeft"),10) || 0), 1827 top: (parseInt(this.element.css("marginTop"),10) || 0), 1828 right: (parseInt(this.element.css("marginRight"),10) || 0), 1829 bottom: (parseInt(this.element.css("marginBottom"),10) || 0) 1830 }; 1831 }, 1832 1833 _cacheHelperProportions: function() { 1834 this.helperProportions = { 1835 width: this.helper.outerWidth(), 1836 height: this.helper.outerHeight() 1837 }; 1838 }, 1839 1840 _setContainment: function() { 1841 1842 var over, c, ce, 1843 o = this.options; 1844 1845 if(o.containment === "parent") { 1846 o.containment = this.helper[0].parentNode; 1847 } 1848 if(o.containment === "document" || o.containment === "window") { 1849 this.containment = [ 1850 o.containment === "document" ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left, 1851 o.containment === "document" ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
vendor: 87,253 bytes, lines 1852-4734
1852 (o.containment === "document" ? 0 : $(window).scrollLeft()) + $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left, 1853 (o.containment === "document" ? 0 : $(window).scrollTop()) + ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top 1854 ]; 1855 } 1856 1857 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor !== Array) { 1858 c = $(o.containment); 1859 ce = c[0]; 1860 1861 if(!ce) { 1862 return; 1863 } 1864 1865 over = ($(ce).css("overflow") !== "hidden"); 1866 1867 this.containment = [ 1868 (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0), 1869 (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0), 1870 (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderRightWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right, 1871 (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderBottomWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom 1872 ]; 1873 this.relative_container = c; 1874 1875 } else if(o.containment.constructor === Array) { 1876 this.containment = o.containment; 1877 } 1878 1879 }, 1880 1881 _convertPositionTo: function(d, pos) { 1882 1883 if(!pos) { 1884 pos = this.position; 1885 } 1886 1887 var mod = d === "absolute" ? 1 : -1, 1888 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); 1889 1890 return { 1891 top: ( 1892 pos.top + // The absolute mouse position 1893 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 1894 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) 1895 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) 1896 ), 1897 left: ( 1898 pos.left + // The absolute mouse position 1899 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 1900 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) 1901 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) 1902 ) 1903 }; 1904 1905 }, 1906 1907 _generatePosition: function(event) { 1908 1909 var containment, co, top, left, 1910 o = this.options, 1911 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, 1912 scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName), 1913 pageX = event.pageX, 1914 pageY = event.pageY; 1915 1916 /* 1917 * - Position constraining - 1918 * Constrain the position to a mix of grid, containment. 1919 */ 1920 1921 if(this.originalPosition) { //If we are not dragging yet, we won't check for options 1922 if(this.containment) { 1923 if (this.relative_container){ 1924 co = this.relative_container.offset(); 1925 containment = [ this.containment[0] + co.left, 1926 this.containment[1] + co.top, 1927 this.containment[2] + co.left, 1928 this.containment[3] + co.top ]; 1929 } 1930 else { 1931 containment = this.containment; 1932 } 1933 1934 if(event.pageX - this.offset.click.left < containment[0]) { 1935 pageX = containment[0] + this.offset.click.left; 1936 } 1937 if(event.pageY - this.offset.click.top < containment[1]) { 1938 pageY = containment[1] + this.offset.click.top; 1939 } 1940 if(event.pageX - this.offset.click.left > containment[2]) { 1941 pageX = containment[2] + this.offset.click.left; 1942 } 1943 if(event.pageY - this.offset.click.top > containment[3]) { 1944 pageY = containment[3] + this.offset.click.top; 1945 } 1946 } 1947 1948 if(o.grid) { 1949 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) 1950 top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; 1951 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; 1952 1953 left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; 1954 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; 1955 } 1956 1957 } 1958 1959 return { 1960 top: ( 1961 pageY - // The absolute mouse position 1962 this.offset.click.top - // Click offset (relative to the element) 1963 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent 1964 this.offset.parent.top + // The offsetParent's offset without borders (offset + border) 1965 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) 1966 ), 1967 left: ( 1968 pageX - // The absolute mouse position 1969 this.offset.click.left - // Click offset (relative to the element) 1970 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent 1971 this.offset.parent.left + // The offsetParent's offset without borders (offset + border) 1972 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) 1973 ) 1974 }; 1975 1976 }, 1977 1978 _clear: function() { 1979 this.helper.removeClass("ui-draggable-dragging"); 1980 if(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) { 1981 this.helper.remove(); 1982 } 1983 this.helper = null; 1984 this.cancelHelperRemoval = false; 1985 }, 1986 1987 // From now on bulk stuff - mainly helpers 1988 1989 _trigger: function(type, event, ui) { 1990 ui = ui || this._uiHash(); 1991 $.ui.plugin.call(this, type, [event, ui]); 1992 //The absolute position has to be recalculated after plugins 1993 if(type === "drag") { 1994 this.positionAbs = this._convertPositionTo("absolute"); 1995 } 1996 return $.Widget.prototype._trigger.call(this, type, event, ui); 1997 }, 1998 1999 plugins: {}, 2000 2001 _uiHash: function() { 2002 return { 2003 helper: this.helper, 2004 position: this.position, 2005 originalPosition: this.originalPosition, 2006 offset: this.positionAbs 2007 }; 2008 } 2009 2010}); 2011 2012$.ui.plugin.add("draggable", "connectToSortable", { 2013 start: function(event, ui) { 2014 2015 var inst = $(this).data("ui-draggable"), o = inst.options, 2016 uiSortable = $.extend({}, ui, { item: inst.element }); 2017 inst.sortables = []; 2018 $(o.connectToSortable).each(function() { 2019 var sortable = $.data(this, "ui-sortable"); 2020 if (sortable && !sortable.options.disabled) { 2021 inst.sortables.push({ 2022 instance: sortable, 2023 shouldRevert: sortable.options.revert 2024 }); 2025 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). 2026 sortable._trigger("activate", event, uiSortable); 2027 } 2028 }); 2029 2030 }, 2031 stop: function(event, ui) { 2032 2033 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper 2034 var inst = $(this).data("ui-draggable"), 2035 uiSortable = $.extend({}, ui, { item: inst.element }); 2036 2037 $.each(inst.sortables, function() { 2038 if(this.instance.isOver) { 2039 2040 this.instance.isOver = 0; 2041 2042 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance 2043 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) 2044 2045 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid" 2046 if(this.shouldRevert) { 2047 this.instance.options.revert = this.shouldRevert; 2048 } 2049 2050 //Trigger the stop of the sortable 2051 this.instance._mouseStop(event); 2052 2053 this.instance.options.helper = this.instance.options._helper; 2054 2055 //If the helper has been the original item, restore properties in the sortable 2056 if(inst.options.helper === "original") { 2057 this.instance.currentItem.css({ top: "auto", left: "auto" }); 2058 } 2059 2060 } else { 2061 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance 2062 this.instance._trigger("deactivate", event, uiSortable); 2063 } 2064 2065 }); 2066 2067 }, 2068 drag: function(event, ui) { 2069 2070 var inst = $(this).data("ui-draggable"), that = this; 2071 2072 $.each(inst.sortables, function() { 2073 2074 var innermostIntersecting = false, 2075 thisSortable = this; 2076 2077 //Copy over some variables to allow calling the sortable's native _intersectsWith 2078 this.instance.positionAbs = inst.positionAbs; 2079 this.instance.helperProportions = inst.helperProportions; 2080 this.instance.offset.click = inst.offset.click; 2081 2082 if(this.instance._intersectsWith(this.instance.containerCache)) { 2083 innermostIntersecting = true; 2084 $.each(inst.sortables, function () { 2085 this.instance.positionAbs = inst.positionAbs; 2086 this.instance.helperProportions = inst.helperProportions; 2087 this.instance.offset.click = inst.offset.click; 2088 if (this !== thisSortable && 2089 this.instance._intersectsWith(this.instance.containerCache) && 2090 $.contains(thisSortable.instance.element[0], this.instance.element[0]) 2091 ) { 2092 innermostIntersecting = false; 2093 } 2094 return innermostIntersecting; 2095 }); 2096 } 2097 2098 2099 if(innermostIntersecting) { 2100 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once 2101 if(!this.instance.isOver) { 2102 2103 this.instance.isOver = 1; 2104 //Now we fake the start of dragging for the sortable instance, 2105 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem 2106 //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) 2107 this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true); 2108 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it 2109 this.instance.options.helper = function() { return ui.helper[0]; }; 2110 2111 event.target = this.instance.currentItem[0]; 2112 this.instance._mouseCapture(event, true); 2113 this.instance._mouseStart(event, true, true); 2114 2115 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes 2116 this.instance.offset.click.top = inst.offset.click.top; 2117 this.instance.offset.click.left = inst.offset.click.left; 2118 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; 2119 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; 2120 2121 inst._trigger("toSortable", event); 2122 inst.dropped = this.instance.element; //draggable revert needs that 2123 //hack so receive/update callbacks work (mostly) 2124 inst.currentItem = inst.element; 2125 this.instance.fromOutside = inst; 2126 2127 } 2128 2129 //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 2130 if(this.instance.currentItem) { 2131 this.instance._mouseDrag(event); 2132 } 2133 2134 } else { 2135 2136 //If it doesn't intersect with the sortable, and it intersected before, 2137 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval 2138 if(this.instance.isOver) { 2139 2140 this.instance.isOver = 0; 2141 this.instance.cancelHelperRemoval = true; 2142 2143 //Prevent reverting on this forced stop 2144 this.instance.options.revert = false; 2145 2146 // The out event needs to be triggered independently 2147 this.instance._trigger("out", event, this.instance._uiHash(this.instance)); 2148 2149 this.instance._mouseStop(event, true); 2150 this.instance.options.helper = this.instance.options._helper; 2151 2152 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size 2153 this.instance.currentItem.remove(); 2154 if(this.instance.placeholder) { 2155 this.instance.placeholder.remove(); 2156 } 2157 2158 inst._trigger("fromSortable", event); 2159 inst.dropped = false; //draggable revert needs that 2160 } 2161 2162 } 2163 2164 }); 2165 2166 } 2167}); 2168 2169$.ui.plugin.add("draggable", "cursor", { 2170 start: function() { 2171 var t = $("body"), o = $(this).data("ui-draggable").options; 2172 if (t.css("cursor")) { 2173 o._cursor = t.css("cursor"); 2174 } 2175 t.css("cursor", o.cursor); 2176 }, 2177 stop: function() { 2178 var o = $(this).data("ui-draggable").options; 2179 if (o._cursor) { 2180 $("body").css("cursor", o._cursor); 2181 } 2182 } 2183}); 2184 2185$.ui.plugin.add("draggable", "opacity", { 2186 start: function(event, ui) { 2187 var t = $(ui.helper), o = $(this).data("ui-draggable").options; 2188 if(t.css("opacity")) { 2189 o._opacity = t.css("opacity"); 2190 } 2191 t.css("opacity", o.opacity); 2192 }, 2193 stop: function(event, ui) { 2194 var o = $(this).data("ui-draggable").options; 2195 if(o._opacity) { 2196 $(ui.helper).css("opacity", o._opacity); 2197 } 2198 } 2199}); 2200 2201$.ui.plugin.add("draggable", "scroll", { 2202 start: function() { 2203 var i = $(this).data("ui-draggable"); 2204 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") { 2205 i.overflowOffset = i.scrollParent.offset(); 2206 } 2207 }, 2208 drag: function( event ) { 2209 2210 var i = $(this).data("ui-draggable"), o = i.options, scrolled = false; 2211 2212 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") { 2213 2214 if(!o.axis || o.axis !== "x") { 2215 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { 2216 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; 2217 } else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) { 2218 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; 2219 } 2220 } 2221 2222 if(!o.axis || o.axis !== "y") { 2223 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { 2224 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; 2225 } else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) { 2226 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; 2227 } 2228 } 2229 2230 } else { 2231 2232 if(!o.axis || o.axis !== "x") { 2233 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { 2234 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); 2235 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { 2236 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); 2237 } 2238 } 2239 2240 if(!o.axis || o.axis !== "y") { 2241 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { 2242 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); 2243 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { 2244 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); 2245 } 2246 } 2247 2248 } 2249 2250 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { 2251 $.ui.ddmanager.prepareOffsets(i, event); 2252 } 2253 2254 } 2255}); 2256 2257$.ui.plugin.add("draggable", "snap", { 2258 start: function() { 2259 2260 var i = $(this).data("ui-draggable"), 2261 o = i.options; 2262 2263 i.snapElements = []; 2264 2265 $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() { 2266 var $t = $(this), 2267 $o = $t.offset(); 2268 if(this !== i.element[0]) { 2269 i.snapElements.push({ 2270 item: this, 2271 width: $t.outerWidth(), height: $t.outerHeight(), 2272 top: $o.top, left: $o.left 2273 }); 2274 } 2275 }); 2276 2277 }, 2278 drag: function(event, ui) { 2279 2280 var ts, bs, ls, rs, l, r, t, b, i, first, 2281 inst = $(this).data("ui-draggable"), 2282 o = inst.options, 2283 d = o.snapTolerance, 2284 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, 2285 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; 2286 2287 for (i = inst.snapElements.length - 1; i >= 0; i--){ 2288 2289 l = inst.snapElements[i].left; 2290 r = l + inst.snapElements[i].width; 2291 t = inst.snapElements[i].top; 2292 b = t + inst.snapElements[i].height; 2293 2294 //Yes, I know, this is insane ;) 2295 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))) { 2296 if(inst.snapElements[i].snapping) { 2297 (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); 2298 } 2299 inst.snapElements[i].snapping = false; 2300 continue; 2301 } 2302 2303 if(o.snapMode !== "inner") { 2304 ts = Math.abs(t - y2) <= d; 2305 bs = Math.abs(b - y1) <= d; 2306 ls = Math.abs(l - x2) <= d; 2307 rs = Math.abs(r - x1) <= d; 2308 if(ts) { 2309 ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; 2310 } 2311 if(bs) { 2312 ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; 2313 } 2314 if(ls) { 2315 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; 2316 } 2317 if(rs) { 2318 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; 2319 } 2320 } 2321 2322 first = (ts || bs || ls || rs); 2323 2324 if(o.snapMode !== "outer") { 2325 ts = Math.abs(t - y1) <= d; 2326 bs = Math.abs(b - y2) <= d; 2327 ls = Math.abs(l - x1) <= d; 2328 rs = Math.abs(r - x2) <= d; 2329 if(ts) { 2330 ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; 2331 } 2332 if(bs) { 2333 ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; 2334 } 2335 if(ls) { 2336 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; 2337 } 2338 if(rs) { 2339 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; 2340 } 2341 } 2342 2343 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) { 2344 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); 2345 } 2346 inst.snapElements[i].snapping = (ts || bs || ls || rs || first); 2347 2348 } 2349 2350 } 2351}); 2352 2353$.ui.plugin.add("draggable", "stack", { 2354 start: function() { 2355 var min, 2356 o = this.data("ui-draggable").options, 2357 group = $.makeArray($(o.stack)).sort(function(a,b) { 2358 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); 2359 }); 2360 2361 if (!group.length) { return; } 2362 2363 min = parseInt($(group[0]).css("zIndex"), 10) || 0; 2364 $(group).each(function(i) { 2365 $(this).css("zIndex", min + i); 2366 }); 2367 this.css("zIndex", (min + group.length)); 2368 } 2369}); 2370 2371$.ui.plugin.add("draggable", "zIndex", { 2372 start: function(event, ui) { 2373 var t = $(ui.helper), o = $(this).data("ui-draggable").options; 2374 if(t.css("zIndex")) { 2375 o._zIndex = t.css("zIndex"); 2376 } 2377 t.css("zIndex", o.zIndex); 2378 }, 2379 stop: function(event, ui) { 2380 var o = $(this).data("ui-draggable").options; 2381 if(o._zIndex) { 2382 $(ui.helper).css("zIndex", o._zIndex); 2383 } 2384 } 2385}); 2386 2387})(jQuery); 2388(function( $, undefined ) { 2389 2390function isOverAxis( x, reference, size ) { 2391 return ( x > reference ) && ( x < ( reference + size ) ); 2392} 2393 2394$.widget("ui.droppable", { 2395 version: "1.10.2", 2396 widgetEventPrefix: "drop", 2397 options: { 2398 accept: "*", 2399 activeClass: false, 2400 addClasses: true, 2401 greedy: false, 2402 hoverClass: false, 2403 scope: "default", 2404 tolerance: "intersect", 2405 2406 // callbacks 2407 activate: null, 2408 deactivate: null, 2409 drop: null, 2410 out: null, 2411 over: null 2412 }, 2413 _create: function() { 2414 2415 var o = this.options, 2416 accept = o.accept; 2417 2418 this.isover = false; 2419 this.isout = true; 2420 2421 this.accept = $.isFunction(accept) ? accept : function(d) { 2422 return d.is(accept); 2423 }; 2424 2425 //Store the droppable's proportions 2426 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight }; 2427 2428 // Add the reference and positions to the manager 2429 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; 2430 $.ui.ddmanager.droppables[o.scope].push(this); 2431 2432 (o.addClasses && this.element.addClass("ui-droppable")); 2433 2434 }, 2435 2436 _destroy: function() { 2437 var i = 0, 2438 drop = $.ui.ddmanager.droppables[this.options.scope]; 2439 2440 for ( ; i < drop.length; i++ ) { 2441 if ( drop[i] === this ) { 2442 drop.splice(i, 1); 2443 } 2444 } 2445 2446 this.element.removeClass("ui-droppable ui-droppable-disabled"); 2447 }, 2448 2449 _setOption: function(key, value) { 2450 2451 if(key === "accept") { 2452 this.accept = $.isFunction(value) ? value : function(d) { 2453 return d.is(value); 2454 }; 2455 } 2456 $.Widget.prototype._setOption.apply(this, arguments); 2457 }, 2458 2459 _activate: function(event) { 2460 var draggable = $.ui.ddmanager.current; 2461 if(this.options.activeClass) { 2462 this.element.addClass(this.options.activeClass); 2463 } 2464 if(draggable){ 2465 this._trigger("activate", event, this.ui(draggable)); 2466 } 2467 }, 2468 2469 _deactivate: function(event) { 2470 var draggable = $.ui.ddmanager.current; 2471 if(this.options.activeClass) { 2472 this.element.removeClass(this.options.activeClass); 2473 } 2474 if(draggable){ 2475 this._trigger("deactivate", event, this.ui(draggable)); 2476 } 2477 }, 2478 2479 _over: function(event) { 2480 2481 var draggable = $.ui.ddmanager.current; 2482 2483 // Bail if draggable and droppable are same element 2484 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { 2485 return; 2486 } 2487 2488 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 2489 if(this.options.hoverClass) { 2490 this.element.addClass(this.options.hoverClass); 2491 } 2492 this._trigger("over", event, this.ui(draggable)); 2493 } 2494 2495 }, 2496 2497 _out: function(event) { 2498 2499 var draggable = $.ui.ddmanager.current; 2500 2501 // Bail if draggable and droppable are same element 2502 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { 2503 return; 2504 } 2505 2506 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 2507 if(this.options.hoverClass) { 2508 this.element.removeClass(this.options.hoverClass); 2509 } 2510 this._trigger("out", event, this.ui(draggable)); 2511 } 2512 2513 }, 2514 2515 _drop: function(event,custom) { 2516 2517 var draggable = custom || $.ui.ddmanager.current, 2518 childrenIntersection = false; 2519 2520 // Bail if draggable and droppable are same element 2521 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { 2522 return false; 2523 } 2524 2525 this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() { 2526 var inst = $.data(this, "ui-droppable"); 2527 if( 2528 inst.options.greedy && 2529 !inst.options.disabled && 2530 inst.options.scope === draggable.options.scope && 2531 inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) && 2532 $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) 2533 ) { childrenIntersection = true; return false; } 2534 }); 2535 if(childrenIntersection) { 2536 return false; 2537 } 2538 2539 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 2540 if(this.options.activeClass) { 2541 this.element.removeClass(this.options.activeClass); 2542 } 2543 if(this.options.hoverClass) { 2544 this.element.removeClass(this.options.hoverClass); 2545 } 2546 this._trigger("drop", event, this.ui(draggable)); 2547 return this.element; 2548 } 2549 2550 return false; 2551 2552 }, 2553 2554 ui: function(c) { 2555 return { 2556 draggable: (c.currentItem || c.element), 2557 helper: c.helper, 2558 position: c.position, 2559 offset: c.positionAbs 2560 }; 2561 } 2562 2563}); 2564 2565$.ui.intersect = function(draggable, droppable, toleranceMode) { 2566 2567 if (!droppable.offset) { 2568 return false; 2569 } 2570 2571 var draggableLeft, draggableTop, 2572 x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, 2573 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height, 2574 l = droppable.offset.left, r = l + droppable.proportions.width, 2575 t = droppable.offset.top, b = t + droppable.proportions.height; 2576 2577 switch (toleranceMode) { 2578 case "fit": 2579 return (l <= x1 && x2 <= r && t <= y1 && y2 <= b); 2580 case "intersect": 2581 return (l < x1 + (draggable.helperProportions.width / 2) && // Right Half 2582 x2 - (draggable.helperProportions.width / 2) < r && // Left Half 2583 t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half 2584 y2 - (draggable.helperProportions.height / 2) < b ); // Top Half 2585 case "pointer": 2586 draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left); 2587 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top); 2588 return isOverAxis( draggableTop, t, droppable.proportions.height ) && isOverAxis( draggableLeft, l, droppable.proportions.width ); 2589 case "touch": 2590 return ( 2591 (y1 >= t && y1 <= b) || // Top edge touching 2592 (y2 >= t && y2 <= b) || // Bottom edge touching 2593 (y1 < t && y2 > b) // Surrounded vertically 2594 ) && ( 2595 (x1 >= l && x1 <= r) || // Left edge touching 2596 (x2 >= l && x2 <= r) || // Right edge touching 2597 (x1 < l && x2 > r) // Surrounded horizontally 2598 ); 2599 default: 2600 return false; 2601 } 2602 2603}; 2604 2605/* 2606 This manager tracks offsets of draggables and droppables 2607*/ 2608$.ui.ddmanager = { 2609 current: null, 2610 droppables: { "default": [] }, 2611 prepareOffsets: function(t, event) { 2612 2613 var i, j, 2614 m = $.ui.ddmanager.droppables[t.options.scope] || [], 2615 type = event ? event.type : null, // workaround for #2317 2616 list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack(); 2617 2618 droppablesLoop: for (i = 0; i < m.length; i++) { 2619 2620 //No disabled and non-accepted 2621 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) { 2622 continue; 2623 } 2624 2625 // Filter out elements in the current dragged item 2626 for (j=0; j < list.length; j++) { 2627 if(list[j] === m[i].element[0]) { 2628 m[i].proportions.height = 0; 2629 continue droppablesLoop; 2630 } 2631 } 2632 2633 m[i].visible = m[i].element.css("display") !== "none"; 2634 if(!m[i].visible) { 2635 continue; 2636 } 2637 2638 //Activate the droppable if used directly from draggables 2639 if(type === "mousedown") { 2640 m[i]._activate.call(m[i], event); 2641 } 2642 2643 m[i].offset = m[i].element.offset(); 2644 m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight }; 2645 2646 } 2647 2648 }, 2649 drop: function(draggable, event) { 2650 2651 var dropped = false; 2652 // Create a copy of the droppables in case the list changes during the drop (#9116) 2653 $.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function() { 2654 2655 if(!this.options) { 2656 return; 2657 } 2658 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) { 2659 dropped = this._drop.call(this, event) || dropped; 2660 } 2661 2662 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 2663 this.isout = true; 2664 this.isover = false; 2665 this._deactivate.call(this, event); 2666 } 2667 2668 }); 2669 return dropped; 2670 2671 }, 2672 dragStart: function( draggable, event ) { 2673 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) 2674 draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() { 2675 if( !draggable.options.refreshPositions ) { 2676 $.ui.ddmanager.prepareOffsets( draggable, event ); 2677 } 2678 }); 2679 }, 2680 drag: function(draggable, event) { 2681 2682 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. 2683 if(draggable.options.refreshPositions) { 2684 $.ui.ddmanager.prepareOffsets(draggable, event); 2685 } 2686 2687 //Run through all droppables and check their positions based on specific tolerance options 2688 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { 2689 2690 if(this.options.disabled || this.greedyChild || !this.visible) { 2691 return; 2692 } 2693 2694 var parentInstance, scope, parent, 2695 intersects = $.ui.intersect(draggable, this, this.options.tolerance), 2696 c = !intersects && this.isover ? "isout" : (intersects && !this.isover ? "isover" : null); 2697 if(!c) { 2698 return; 2699 } 2700 2701 if (this.options.greedy) { 2702 // find droppable parents with same scope 2703 scope = this.options.scope; 2704 parent = this.element.parents(":data(ui-droppable)").filter(function () { 2705 return $.data(this, "ui-droppable").options.scope === scope; 2706 }); 2707 2708 if (parent.length) { 2709 parentInstance = $.data(parent[0], "ui-droppable"); 2710 parentInstance.greedyChild = (c === "isover"); 2711 } 2712 } 2713 2714 // we just moved into a greedy child 2715 if (parentInstance && c === "isover") { 2716 parentInstance.isover = false; 2717 parentInstance.isout = true; 2718 parentInstance._out.call(parentInstance, event); 2719 } 2720 2721 this[c] = true; 2722 this[c === "isout" ? "isover" : "isout"] = false; 2723 this[c === "isover" ? "_over" : "_out"].call(this, event); 2724 2725 // we just moved out of a greedy child 2726 if (parentInstance && c === "isout") { 2727 parentInstance.isout = false; 2728 parentInstance.isover = true; 2729 parentInstance._over.call(parentInstance, event); 2730 } 2731 }); 2732 2733 }, 2734 dragStop: function( draggable, event ) { 2735 draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" ); 2736 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) 2737 if( !draggable.options.refreshPositions ) { 2738 $.ui.ddmanager.prepareOffsets( draggable, event ); 2739 } 2740 } 2741}; 2742 2743})(jQuery); 2744(function( $, undefined ) { 2745 2746function num(v) { 2747 return parseInt(v, 10) || 0; 2748} 2749 2750function isNumber(value) { 2751 return !isNaN(parseInt(value, 10)); 2752} 2753 2754$.widget("ui.resizable", $.ui.mouse, { 2755 version: "1.10.2", 2756 widgetEventPrefix: "resize", 2757 options: { 2758 alsoResize: false, 2759 animate: false, 2760 animateDuration: "slow", 2761 animateEasing: "swing", 2762 aspectRatio: false, 2763 autoHide: false, 2764 containment: false, 2765 ghost: false, 2766 grid: false, 2767 handles: "e,s,se", 2768 helper: false, 2769 maxHeight: null, 2770 maxWidth: null, 2771 minHeight: 10, 2772 minWidth: 10, 2773 // See #7960 2774 zIndex: 90, 2775 2776 // callbacks 2777 resize: null, 2778 start: null, 2779 stop: null 2780 }, 2781 _create: function() { 2782 2783 var n, i, handle, axis, hname, 2784 that = this, 2785 o = this.options; 2786 this.element.addClass("ui-resizable"); 2787 2788 $.extend(this, { 2789 _aspectRatio: !!(o.aspectRatio), 2790 aspectRatio: o.aspectRatio, 2791 originalElement: this.element, 2792 _proportionallyResizeElements: [], 2793 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null 2794 }); 2795 2796 //Wrap the element if it cannot hold child nodes 2797 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { 2798 2799 //Create a wrapper element and set the wrapper to the new current internal element 2800 this.element.wrap( 2801 $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({ 2802 position: this.element.css("position"), 2803 width: this.element.outerWidth(), 2804 height: this.element.outerHeight(), 2805 top: this.element.css("top"), 2806 left: this.element.css("left") 2807 }) 2808 ); 2809 2810 //Overwrite the original this.element 2811 this.element = this.element.parent().data( 2812 "ui-resizable", this.element.data("ui-resizable") 2813 ); 2814 2815 this.elementIsWrapper = true; 2816 2817 //Move margins to the wrapper 2818 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); 2819 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); 2820 2821 //Prevent Safari textarea resize 2822 this.originalResizeStyle = this.originalElement.css("resize"); 2823 this.originalElement.css("resize", "none"); 2824 2825 //Push the actual element to our proportionallyResize internal array 2826 this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" })); 2827 2828 // avoid IE jump (hard set the margin) 2829 this.originalElement.css({ margin: this.originalElement.css("margin") }); 2830 2831 // fix handlers offset 2832 this._proportionallyResize(); 2833 2834 } 2835 2836 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" }); 2837 if(this.handles.constructor === String) { 2838 2839 if ( this.handles === "all") { 2840 this.handles = "n,e,s,w,se,sw,ne,nw"; 2841 } 2842 2843 n = this.handles.split(","); 2844 this.handles = {}; 2845 2846 for(i = 0; i < n.length; i++) { 2847 2848 handle = $.trim(n[i]); 2849 hname = "ui-resizable-"+handle; 2850 axis = $("<div class='ui-resizable-handle " + hname + "'></div>"); 2851 2852 // Apply zIndex to all handles - see #7960 2853 axis.css({ zIndex: o.zIndex }); 2854 2855 //TODO : What's going on here? 2856 if ("se" === handle) { 2857 axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se"); 2858 } 2859 2860 //Insert into internal handles object and append to element 2861 this.handles[handle] = ".ui-resizable-"+handle; 2862 this.element.append(axis); 2863 } 2864 2865 } 2866 2867 this._renderAxis = function(target) { 2868 2869 var i, axis, padPos, padWrapper; 2870 2871 target = target || this.element; 2872 2873 for(i in this.handles) { 2874 2875 if(this.handles[i].constructor === String) { 2876 this.handles[i] = $(this.handles[i], this.element).show(); 2877 } 2878 2879 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) 2880 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { 2881 2882 axis = $(this.handles[i], this.element); 2883 2884 //Checking the correct pad and border 2885 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); 2886 2887 //The padding type i have to apply... 2888 padPos = [ "padding", 2889 /ne|nw|n/.test(i) ? "Top" : 2890 /se|sw|s/.test(i) ? "Bottom" : 2891 /^e$/.test(i) ? "Right" : "Left" ].join(""); 2892 2893 target.css(padPos, padWrapper); 2894 2895 this._proportionallyResize(); 2896 2897 } 2898 2899 //TODO: What's that good for? There's not anything to be executed left 2900 if(!$(this.handles[i]).length) { 2901 continue; 2902 } 2903 } 2904 }; 2905 2906 //TODO: make renderAxis a prototype function 2907 this._renderAxis(this.element); 2908 2909 this._handles = $(".ui-resizable-handle", this.element) 2910 .disableSelection(); 2911 2912 //Matching axis name 2913 this._handles.mouseover(function() { 2914 if (!that.resizing) { 2915 if (this.className) { 2916 axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); 2917 } 2918 //Axis, default = se 2919 that.axis = axis && axis[1] ? axis[1] : "se"; 2920 } 2921 }); 2922 2923 //If we want to auto hide the elements 2924 if (o.autoHide) { 2925 this._handles.hide(); 2926 $(this.element) 2927 .addClass("ui-resizable-autohide") 2928 .mouseenter(function() { 2929 if (o.disabled) { 2930 return; 2931 } 2932 $(this).removeClass("ui-resizable-autohide"); 2933 that._handles.show(); 2934 }) 2935 .mouseleave(function(){ 2936 if (o.disabled) { 2937 return; 2938 } 2939 if (!that.resizing) { 2940 $(this).addClass("ui-resizable-autohide"); 2941 that._handles.hide(); 2942 } 2943 }); 2944 } 2945 2946 //Initialize the mouse interaction 2947 this._mouseInit(); 2948 2949 }, 2950 2951 _destroy: function() { 2952 2953 this._mouseDestroy(); 2954 2955 var wrapper, 2956 _destroy = function(exp) { 2957 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") 2958 .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove(); 2959 }; 2960 2961 //TODO: Unwrap at same DOM position 2962 if (this.elementIsWrapper) { 2963 _destroy(this.element); 2964 wrapper = this.element; 2965 this.originalElement.css({ 2966 position: wrapper.css("position"), 2967 width: wrapper.outerWidth(), 2968 height: wrapper.outerHeight(), 2969 top: wrapper.css("top"), 2970 left: wrapper.css("left") 2971 }).insertAfter( wrapper ); 2972 wrapper.remove(); 2973 } 2974 2975 this.originalElement.css("resize", this.originalResizeStyle); 2976 _destroy(this.originalElement); 2977 2978 return this; 2979 }, 2980 2981 _mouseCapture: function(event) { 2982 var i, handle, 2983 capture = false; 2984 2985 for (i in this.handles) { 2986 handle = $(this.handles[i])[0]; 2987 if (handle === event.target || $.contains(handle, event.target)) { 2988 capture = true; 2989 } 2990 } 2991 2992 return !this.options.disabled && capture; 2993 }, 2994 2995 _mouseStart: function(event) { 2996 2997 var curleft, curtop, cursor, 2998 o = this.options, 2999 iniPos = this.element.position(), 3000 el = this.element; 3001 3002 this.resizing = true; 3003 3004 // bugfix for http://dev.jquery.com/ticket/1749 3005 if ( (/absolute/).test( el.css("position") ) ) { 3006 el.css({ position: "absolute", top: el.css("top"), left: el.css("left") }); 3007 } else if (el.is(".ui-draggable")) { 3008 el.css({ position: "absolute", top: iniPos.top, left: iniPos.left }); 3009 } 3010 3011 this._renderProxy(); 3012 3013 curleft = num(this.helper.css("left")); 3014 curtop = num(this.helper.css("top")); 3015 3016 if (o.containment) { 3017 curleft += $(o.containment).scrollLeft() || 0; 3018 curtop += $(o.containment).scrollTop() || 0; 3019 } 3020 3021 //Store needed variables 3022 this.offset = this.helper.offset(); 3023 this.position = { left: curleft, top: curtop }; 3024 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; 3025 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; 3026 this.originalPosition = { left: curleft, top: curtop }; 3027 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; 3028 this.originalMousePosition = { left: event.pageX, top: event.pageY }; 3029 3030 //Aspect Ratio 3031 this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); 3032 3033 cursor = $(".ui-resizable-" + this.axis).css("cursor"); 3034 $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor); 3035 3036 el.addClass("ui-resizable-resizing"); 3037 this._propagate("start", event); 3038 return true; 3039 }, 3040 3041 _mouseDrag: function(event) { 3042 3043 //Increase performance, avoid regex 3044 var data, 3045 el = this.helper, props = {}, 3046 smp = this.originalMousePosition, 3047 a = this.axis, 3048 prevTop = this.position.top, 3049 prevLeft = this.position.left, 3050 prevWidth = this.size.width, 3051 prevHeight = this.size.height, 3052 dx = (event.pageX-smp.left)||0, 3053 dy = (event.pageY-smp.top)||0, 3054 trigger = this._change[a]; 3055 3056 if (!trigger) { 3057 return false; 3058 } 3059 3060 // Calculate the attrs that will be change 3061 data = trigger.apply(this, [event, dx, dy]); 3062 3063 // Put this in the mouseDrag handler since the user can start pressing shift while resizing 3064 this._updateVirtualBoundaries(event.shiftKey); 3065 if (this._aspectRatio || event.shiftKey) { 3066 data = this._updateRatio(data, event); 3067 } 3068 3069 data = this._respectSize(data, event); 3070 3071 this._updateCache(data); 3072 3073 // plugins callbacks need to be called first 3074 this._propagate("resize", event); 3075 3076 if (this.position.top !== prevTop) { 3077 props.top = this.position.top + "px"; 3078 } 3079 if (this.position.left !== prevLeft) { 3080 props.left = this.position.left + "px"; 3081 } 3082 if (this.size.width !== prevWidth) { 3083 props.width = this.size.width + "px"; 3084 } 3085 if (this.size.height !== prevHeight) { 3086 props.height = this.size.height + "px"; 3087 } 3088 el.css(props); 3089 3090 if (!this._helper && this._proportionallyResizeElements.length) { 3091 this._proportionallyResize(); 3092 } 3093 3094 // Call the user callback if the element was resized 3095 if ( ! $.isEmptyObject(props) ) { 3096 this._trigger("resize", event, this.ui()); 3097 } 3098 3099 return false; 3100 }, 3101 3102 _mouseStop: function(event) { 3103 3104 this.resizing = false; 3105 var pr, ista, soffseth, soffsetw, s, left, top, 3106 o = this.options, that = this; 3107 3108 if(this._helper) { 3109 3110 pr = this._proportionallyResizeElements; 3111 ista = pr.length && (/textarea/i).test(pr[0].nodeName); 3112 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height; 3113 soffsetw = ista ? 0 : that.sizeDiff.width; 3114 3115 s = { width: (that.helper.width() - soffsetw), height: (that.helper.height() - soffseth) }; 3116 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null; 3117 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null; 3118 3119 if (!o.animate) { 3120 this.element.css($.extend(s, { top: top, left: left })); 3121 } 3122 3123 that.helper.height(that.size.height); 3124 that.helper.width(that.size.width); 3125 3126 if (this._helper && !o.animate) { 3127 this._proportionallyResize(); 3128 } 3129 } 3130 3131 $("body").css("cursor", "auto"); 3132 3133 this.element.removeClass("ui-resizable-resizing"); 3134 3135 this._propagate("stop", event); 3136 3137 if (this._helper) { 3138 this.helper.remove(); 3139 } 3140 3141 return false; 3142 3143 }, 3144 3145 _updateVirtualBoundaries: function(forceAspectRatio) { 3146 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b, 3147 o = this.options; 3148 3149 b = { 3150 minWidth: isNumber(o.minWidth) ? o.minWidth : 0, 3151 maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity, 3152 minHeight: isNumber(o.minHeight) ? o.minHeight : 0, 3153 maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity 3154 }; 3155 3156 if(this._aspectRatio || forceAspectRatio) { 3157 // We want to create an enclosing box whose aspect ration is the requested one 3158 // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension 3159 pMinWidth = b.minHeight * this.aspectRatio; 3160 pMinHeight = b.minWidth / this.aspectRatio; 3161 pMaxWidth = b.maxHeight * this.aspectRatio; 3162 pMaxHeight = b.maxWidth / this.aspectRatio; 3163 3164 if(pMinWidth > b.minWidth) { 3165 b.minWidth = pMinWidth; 3166 } 3167 if(pMinHeight > b.minHeight) { 3168 b.minHeight = pMinHeight; 3169 } 3170 if(pMaxWidth < b.maxWidth) { 3171 b.maxWidth = pMaxWidth; 3172 } 3173 if(pMaxHeight < b.maxHeight) { 3174 b.maxHeight = pMaxHeight; 3175 } 3176 } 3177 this._vBoundaries = b; 3178 }, 3179 3180 _updateCache: function(data) { 3181 this.offset = this.helper.offset(); 3182 if (isNumber(data.left)) { 3183 this.position.left = data.left; 3184 } 3185 if (isNumber(data.top)) { 3186 this.position.top = data.top; 3187 } 3188 if (isNumber(data.height)) { 3189 this.size.height = data.height; 3190 } 3191 if (isNumber(data.width)) { 3192 this.size.width = data.width; 3193 } 3194 }, 3195 3196 _updateRatio: function( data ) { 3197 3198 var cpos = this.position, 3199 csize = this.size, 3200 a = this.axis; 3201 3202 if (isNumber(data.height)) { 3203 data.width = (data.height * this.aspectRatio); 3204 } else if (isNumber(data.width)) { 3205 data.height = (data.width / this.aspectRatio); 3206 } 3207 3208 if (a === "sw") { 3209 data.left = cpos.left + (csize.width - data.width); 3210 data.top = null; 3211 } 3212 if (a === "nw") { 3213 data.top = cpos.top + (csize.height - data.height); 3214 data.left = cpos.left + (csize.width - data.width); 3215 } 3216 3217 return data; 3218 }, 3219 3220 _respectSize: function( data ) { 3221 3222 var o = this._vBoundaries, 3223 a = this.axis, 3224 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), 3225 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height), 3226 dw = this.originalPosition.left + this.originalSize.width, 3227 dh = this.position.top + this.size.height, 3228 cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); 3229 if (isminw) { 3230 data.width = o.minWidth; 3231 } 3232 if (isminh) { 3233 data.height = o.minHeight; 3234 } 3235 if (ismaxw) { 3236 data.width = o.maxWidth; 3237 } 3238 if (ismaxh) { 3239 data.height = o.maxHeight; 3240 } 3241 3242 if (isminw && cw) { 3243 data.left = dw - o.minWidth; 3244 } 3245 if (ismaxw && cw) { 3246 data.left = dw - o.maxWidth; 3247 } 3248 if (isminh && ch) { 3249 data.top = dh - o.minHeight; 3250 } 3251 if (ismaxh && ch) { 3252 data.top = dh - o.maxHeight; 3253 } 3254 3255 // fixing jump error on top/left - bug #2330 3256 if (!data.width && !data.height && !data.left && data.top) { 3257 data.top = null; 3258 } else if (!data.width && !data.height && !data.top && data.left) { 3259 data.left = null; 3260 } 3261 3262 return data; 3263 }, 3264 3265 _proportionallyResize: function() { 3266 3267 if (!this._proportionallyResizeElements.length) { 3268 return; 3269 } 3270 3271 var i, j, borders, paddings, prel, 3272 element = this.helper || this.element; 3273 3274 for ( i=0; i < this._proportionallyResizeElements.length; i++) { 3275 3276 prel = this._proportionallyResizeElements[i]; 3277 3278 if (!this.borderDif) { 3279 this.borderDif = []; 3280 borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")]; 3281 paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")]; 3282 3283 for ( j = 0; j < borders.length; j++ ) { 3284 this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 ); 3285 } 3286 } 3287 3288 prel.css({ 3289 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, 3290 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 3291 }); 3292 3293 } 3294 3295 }, 3296 3297 _renderProxy: function() { 3298 3299 var el = this.element, o = this.options; 3300 this.elementOffset = el.offset(); 3301 3302 if(this._helper) { 3303 3304 this.helper = this.helper || $("<div style='overflow:hidden;'></div>"); 3305 3306 this.helper.addClass(this._helper).css({ 3307 width: this.element.outerWidth() - 1, 3308 height: this.element.outerHeight() - 1, 3309 position: "absolute", 3310 left: this.elementOffset.left +"px", 3311 top: this.elementOffset.top +"px", 3312 zIndex: ++o.zIndex //TODO: Don't modify option 3313 }); 3314 3315 this.helper 3316 .appendTo("body") 3317 .disableSelection(); 3318 3319 } else { 3320 this.helper = this.element; 3321 } 3322 3323 }, 3324 3325 _change: { 3326 e: function(event, dx) { 3327 return { width: this.originalSize.width + dx }; 3328 }, 3329 w: function(event, dx) { 3330 var cs = this.originalSize, sp = this.originalPosition; 3331 return { left: sp.left + dx, width: cs.width - dx }; 3332 }, 3333 n: function(event, dx, dy) { 3334 var cs = this.originalSize, sp = this.originalPosition; 3335 return { top: sp.top + dy, height: cs.height - dy }; 3336 }, 3337 s: function(event, dx, dy) { 3338 return { height: this.originalSize.height + dy }; 3339 }, 3340 se: function(event, dx, dy) { 3341 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); 3342 }, 3343 sw: function(event, dx, dy) { 3344 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); 3345 }, 3346 ne: function(event, dx, dy) { 3347 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); 3348 }, 3349 nw: function(event, dx, dy) { 3350 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); 3351 } 3352 }, 3353 3354 _propagate: function(n, event) { 3355 $.ui.plugin.call(this, n, [event, this.ui()]); 3356 (n !== "resize" && this._trigger(n, event, this.ui())); 3357 }, 3358 3359 plugins: {}, 3360 3361 ui: function() { 3362 return { 3363 originalElement: this.originalElement, 3364 element: this.element, 3365 helper: this.helper, 3366 position: this.position, 3367 size: this.size, 3368 originalSize: this.originalSize, 3369 originalPosition: this.originalPosition 3370 }; 3371 } 3372 3373}); 3374 3375/* 3376 * Resizable Extensions 3377 */ 3378 3379$.ui.plugin.add("resizable", "animate", { 3380 3381 stop: function( event ) { 3382 var that = $(this).data("ui-resizable"), 3383 o = that.options, 3384 pr = that._proportionallyResizeElements, 3385 ista = pr.length && (/textarea/i).test(pr[0].nodeName), 3386 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height, 3387 soffsetw = ista ? 0 : that.sizeDiff.width, 3388 style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) }, 3389 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null, 3390 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null; 3391 3392 that.element.animate( 3393 $.extend(style, top && left ? { top: top, left: left } : {}), { 3394 duration: o.animateDuration, 3395 easing: o.animateEasing, 3396 step: function() { 3397 3398 var data = { 3399 width: parseInt(that.element.css("width"), 10), 3400 height: parseInt(that.element.css("height"), 10), 3401 top: parseInt(that.element.css("top"), 10), 3402 left: parseInt(that.element.css("left"), 10) 3403 }; 3404 3405 if (pr && pr.length) { 3406 $(pr[0]).css({ width: data.width, height: data.height }); 3407 } 3408 3409 // propagating resize, and updating values for each animation step 3410 that._updateCache(data); 3411 that._propagate("resize", event); 3412 3413 } 3414 } 3415 ); 3416 } 3417 3418}); 3419 3420$.ui.plugin.add("resizable", "containment", { 3421 3422 start: function() { 3423 var element, p, co, ch, cw, width, height, 3424 that = $(this).data("ui-resizable"), 3425 o = that.options, 3426 el = that.element, 3427 oc = o.containment, 3428 ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; 3429 3430 if (!ce) { 3431 return; 3432 } 3433 3434 that.containerElement = $(ce); 3435 3436 if (/document/.test(oc) || oc === document) { 3437 that.containerOffset = { left: 0, top: 0 }; 3438 that.containerPosition = { left: 0, top: 0 }; 3439 3440 that.parentData = { 3441 element: $(document), left: 0, top: 0, 3442 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight 3443 }; 3444 } 3445 3446 // i'm a node, so compute top, left, right, bottom 3447 else { 3448 element = $(ce); 3449 p = []; 3450 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); }); 3451 3452 that.containerOffset = element.offset(); 3453 that.containerPosition = element.position(); 3454 that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; 3455 3456 co = that.containerOffset; 3457 ch = that.containerSize.height; 3458 cw = that.containerSize.width; 3459 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ); 3460 height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); 3461 3462 that.parentData = { 3463 element: ce, left: co.left, top: co.top, width: width, height: height 3464 }; 3465 } 3466 }, 3467 3468 resize: function( event ) { 3469 var woset, hoset, isParent, isOffsetRelative, 3470 that = $(this).data("ui-resizable"), 3471 o = that.options, 3472 co = that.containerOffset, cp = that.position, 3473 pRatio = that._aspectRatio || event.shiftKey, 3474 cop = { top:0, left:0 }, ce = that.containerElement; 3475 3476 if (ce[0] !== document && (/static/).test(ce.css("position"))) { 3477 cop = co; 3478 } 3479 3480 if (cp.left < (that._helper ? co.left : 0)) { 3481 that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left)); 3482 if (pRatio) { 3483 that.size.height = that.size.width / that.aspectRatio; 3484 } 3485 that.position.left = o.helper ? co.left : 0; 3486 } 3487 3488 if (cp.top < (that._helper ? co.top : 0)) { 3489 that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top); 3490 if (pRatio) { 3491 that.size.width = that.size.height * that.aspectRatio; 3492 } 3493 that.position.top = that._helper ? co.top : 0; 3494 } 3495 3496 that.offset.left = that.parentData.left+that.position.left; 3497 that.offset.top = that.parentData.top+that.position.top; 3498 3499 woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width ); 3500 hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height ); 3501 3502 isParent = that.containerElement.get(0) === that.element.parent().get(0); 3503 isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position")); 3504 3505 if(isParent && isOffsetRelative) { 3506 woset -= that.parentData.left; 3507 } 3508 3509 if (woset + that.size.width >= that.parentData.width) { 3510 that.size.width = that.parentData.width - woset; 3511 if (pRatio) { 3512 that.size.height = that.size.width / that.aspectRatio; 3513 } 3514 } 3515 3516 if (hoset + that.size.height >= that.parentData.height) { 3517 that.size.height = that.parentData.height - hoset; 3518 if (pRatio) { 3519 that.size.width = that.size.height * that.aspectRatio; 3520 } 3521 } 3522 }, 3523 3524 stop: function(){ 3525 var that = $(this).data("ui-resizable"), 3526 o = that.options, 3527 co = that.containerOffset, 3528 cop = that.containerPosition, 3529 ce = that.containerElement, 3530 helper = $(that.helper), 3531 ho = helper.offset(), 3532 w = helper.outerWidth() - that.sizeDiff.width, 3533 h = helper.outerHeight() - that.sizeDiff.height; 3534 3535 if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) { 3536 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); 3537 } 3538 3539 if (that._helper && !o.animate && (/static/).test(ce.css("position"))) { 3540 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); 3541 } 3542 3543 } 3544}); 3545 3546$.ui.plugin.add("resizable", "alsoResize", { 3547 3548 start: function () { 3549 var that = $(this).data("ui-resizable"), 3550 o = that.options, 3551 _store = function (exp) { 3552 $(exp).each(function() { 3553 var el = $(this); 3554 el.data("ui-resizable-alsoresize", { 3555 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), 3556 left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10) 3557 }); 3558 }); 3559 }; 3560 3561 if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) { 3562 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); } 3563 else { $.each(o.alsoResize, function (exp) { _store(exp); }); } 3564 }else{ 3565 _store(o.alsoResize); 3566 } 3567 }, 3568 3569 resize: function (event, ui) { 3570 var that = $(this).data("ui-resizable"), 3571 o = that.options, 3572 os = that.originalSize, 3573 op = that.originalPosition, 3574 delta = { 3575 height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0, 3576 top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0 3577 }, 3578 3579 _alsoResize = function (exp, c) { 3580 $(exp).each(function() { 3581 var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {}, 3582 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"]; 3583 3584 $.each(css, function (i, prop) { 3585 var sum = (start[prop]||0) + (delta[prop]||0); 3586 if (sum && sum >= 0) { 3587 style[prop] = sum || null; 3588 } 3589 }); 3590 3591 el.css(style); 3592 }); 3593 }; 3594 3595 if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) { 3596 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); }); 3597 }else{ 3598 _alsoResize(o.alsoResize); 3599 } 3600 }, 3601 3602 stop: function () { 3603 $(this).removeData("resizable-alsoresize"); 3604 } 3605}); 3606 3607$.ui.plugin.add("resizable", "ghost", { 3608 3609 start: function() { 3610 3611 var that = $(this).data("ui-resizable"), o = that.options, cs = that.size; 3612 3613 that.ghost = that.originalElement.clone(); 3614 that.ghost 3615 .css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) 3616 .addClass("ui-resizable-ghost") 3617 .addClass(typeof o.ghost === "string" ? o.ghost : ""); 3618 3619 that.ghost.appendTo(that.helper); 3620 3621 }, 3622 3623 resize: function(){ 3624 var that = $(this).data("ui-resizable"); 3625 if (that.ghost) { 3626 that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width }); 3627 } 3628 }, 3629 3630 stop: function() { 3631 var that = $(this).data("ui-resizable"); 3632 if (that.ghost && that.helper) { 3633 that.helper.get(0).removeChild(that.ghost.get(0)); 3634 } 3635 } 3636 3637}); 3638 3639$.ui.plugin.add("resizable", "grid", { 3640 3641 resize: function() { 3642 var that = $(this).data("ui-resizable"), 3643 o = that.options, 3644 cs = that.size, 3645 os = that.originalSize, 3646 op = that.originalPosition, 3647 a = that.axis, 3648 grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid, 3649 gridX = (grid[0]||1), 3650 gridY = (grid[1]||1), 3651 ox = Math.round((cs.width - os.width) / gridX) * gridX, 3652 oy = Math.round((cs.height - os.height) / gridY) * gridY, 3653 newWidth = os.width + ox, 3654 newHeight = os.height + oy, 3655 isMaxWidth = o.maxWidth && (o.maxWidth < newWidth), 3656 isMaxHeight = o.maxHeight && (o.maxHeight < newHeight), 3657 isMinWidth = o.minWidth && (o.minWidth > newWidth), 3658 isMinHeight = o.minHeight && (o.minHeight > newHeight); 3659 3660 o.grid = grid; 3661 3662 if (isMinWidth) { 3663 newWidth = newWidth + gridX; 3664 } 3665 if (isMinHeight) { 3666 newHeight = newHeight + gridY; 3667 } 3668 if (isMaxWidth) { 3669 newWidth = newWidth - gridX; 3670 } 3671 if (isMaxHeight) { 3672 newHeight = newHeight - gridY; 3673 } 3674 3675 if (/^(se|s|e)$/.test(a)) { 3676 that.size.width = newWidth; 3677 that.size.height = newHeight; 3678 } else if (/^(ne)$/.test(a)) { 3679 that.size.width = newWidth; 3680 that.size.height = newHeight; 3681 that.position.top = op.top - oy; 3682 } else if (/^(sw)$/.test(a)) { 3683 that.size.width = newWidth; 3684 that.size.height = newHeight; 3685 that.position.left = op.left - ox; 3686 } else { 3687 that.size.width = newWidth; 3688 that.size.height = newHeight; 3689 that.position.top = op.top - oy; 3690 that.position.left = op.left - ox; 3691 } 3692 } 3693 3694}); 3695 3696})(jQuery); 3697(function( $, undefined ) { 3698 3699$.widget("ui.selectable", $.ui.mouse, { 3700 version: "1.10.2", 3701 options: { 3702 appendTo: "body", 3703 autoRefresh: true, 3704 distance: 0, 3705 filter: "*", 3706 tolerance: "touch", 3707 3708 // callbacks 3709 selected: null, 3710 selecting: null, 3711 start: null, 3712 stop: null, 3713 unselected: null, 3714 unselecting: null 3715 }, 3716 _create: function() { 3717 var selectees, 3718 that = this; 3719 3720 this.element.addClass("ui-selectable"); 3721 3722 this.dragged = false; 3723 3724 // cache selectee children based on filter 3725 this.refresh = function() { 3726 selectees = $(that.options.filter, that.element[0]); 3727 selectees.addClass("ui-selectee"); 3728 selectees.each(function() { 3729 var $this = $(this), 3730 pos = $this.offset(); 3731 $.data(this, "selectable-item", { 3732 element: this, 3733 $element: $this, 3734 left: pos.left, 3735 top: pos.top, 3736 right: pos.left + $this.outerWidth(), 3737 bottom: pos.top + $this.outerHeight(), 3738 startselected: false, 3739 selected: $this.hasClass("ui-selected"), 3740 selecting: $this.hasClass("ui-selecting"), 3741 unselecting: $this.hasClass("ui-unselecting") 3742 }); 3743 }); 3744 }; 3745 this.refresh(); 3746 3747 this.selectees = selectees.addClass("ui-selectee"); 3748 3749 this._mouseInit(); 3750 3751 this.helper = $("<div class='ui-selectable-helper'></div>"); 3752 }, 3753 3754 _destroy: function() { 3755 this.selectees 3756 .removeClass("ui-selectee") 3757 .removeData("selectable-item"); 3758 this.element 3759 .removeClass("ui-selectable ui-selectable-disabled"); 3760 this._mouseDestroy(); 3761 }, 3762 3763 _mouseStart: function(event) { 3764 var that = this, 3765 options = this.options; 3766 3767 this.opos = [event.pageX, event.pageY]; 3768 3769 if (this.options.disabled) { 3770 return; 3771 } 3772 3773 this.selectees = $(options.filter, this.element[0]); 3774 3775 this._trigger("start", event); 3776 3777 $(options.appendTo).append(this.helper); 3778 // position helper (lasso) 3779 this.helper.css({ 3780 "left": event.pageX, 3781 "top": event.pageY, 3782 "width": 0, 3783 "height": 0 3784 }); 3785 3786 if (options.autoRefresh) { 3787 this.refresh(); 3788 } 3789 3790 this.selectees.filter(".ui-selected").each(function() { 3791 var selectee = $.data(this, "selectable-item"); 3792 selectee.startselected = true; 3793 if (!event.metaKey && !event.ctrlKey) { 3794 selectee.$element.removeClass("ui-selected"); 3795 selectee.selected = false; 3796 selectee.$element.addClass("ui-unselecting"); 3797 selectee.unselecting = true; 3798 // selectable UNSELECTING callback 3799 that._trigger("unselecting", event, { 3800 unselecting: selectee.element 3801 }); 3802 } 3803 }); 3804 3805 $(event.target).parents().addBack().each(function() { 3806 var doSelect, 3807 selectee = $.data(this, "selectable-item"); 3808 if (selectee) { 3809 doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected"); 3810 selectee.$element 3811 .removeClass(doSelect ? "ui-unselecting" : "ui-selected") 3812 .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); 3813 selectee.unselecting = !doSelect; 3814 selectee.selecting = doSelect; 3815 selectee.selected = doSelect; 3816 // selectable (UN)SELECTING callback 3817 if (doSelect) { 3818 that._trigger("selecting", event, { 3819 selecting: selectee.element 3820 }); 3821 } else { 3822 that._trigger("unselecting", event, { 3823 unselecting: selectee.element 3824 }); 3825 } 3826 return false; 3827 } 3828 }); 3829 3830 }, 3831 3832 _mouseDrag: function(event) { 3833 3834 this.dragged = true; 3835 3836 if (this.options.disabled) { 3837 return; 3838 } 3839 3840 var tmp, 3841 that = this, 3842 options = this.options, 3843 x1 = this.opos[0], 3844 y1 = this.opos[1], 3845 x2 = event.pageX, 3846 y2 = event.pageY; 3847 3848 if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; } 3849 if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; } 3850 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); 3851 3852 this.selectees.each(function() { 3853 var selectee = $.data(this, "selectable-item"), 3854 hit = false; 3855 3856 //prevent helper from being selected if appendTo: selectable 3857 if (!selectee || selectee.element === that.element[0]) { 3858 return; 3859 } 3860 3861 if (options.tolerance === "touch") { 3862 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); 3863 } else if (options.tolerance === "fit") { 3864 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); 3865 } 3866 3867 if (hit) { 3868 // SELECT 3869 if (selectee.selected) { 3870 selectee.$element.removeClass("ui-selected"); 3871 selectee.selected = false; 3872 } 3873 if (selectee.unselecting) { 3874 selectee.$element.removeClass("ui-unselecting"); 3875 selectee.unselecting = false; 3876 } 3877 if (!selectee.selecting) { 3878 selectee.$element.addClass("ui-selecting"); 3879 selectee.selecting = true; 3880 // selectable SELECTING callback 3881 that._trigger("selecting", event, { 3882 selecting: selectee.element 3883 }); 3884 } 3885 } else { 3886 // UNSELECT 3887 if (selectee.selecting) { 3888 if ((event.metaKey || event.ctrlKey) && selectee.startselected) { 3889 selectee.$element.removeClass("ui-selecting"); 3890 selectee.selecting = false; 3891 selectee.$element.addClass("ui-selected"); 3892 selectee.selected = true; 3893 } else { 3894 selectee.$element.removeClass("ui-selecting"); 3895 selectee.selecting = false; 3896 if (selectee.startselected) { 3897 selectee.$element.addClass("ui-unselecting"); 3898 selectee.unselecting = true; 3899 } 3900 // selectable UNSELECTING callback 3901 that._trigger("unselecting", event, { 3902 unselecting: selectee.element 3903 }); 3904 } 3905 } 3906 if (selectee.selected) { 3907 if (!event.metaKey && !event.ctrlKey && !selectee.startselected) { 3908 selectee.$element.removeClass("ui-selected"); 3909 selectee.selected = false; 3910 3911 selectee.$element.addClass("ui-unselecting"); 3912 selectee.unselecting = true; 3913 // selectable UNSELECTING callback 3914 that._trigger("unselecting", event, { 3915 unselecting: selectee.element 3916 }); 3917 } 3918 } 3919 } 3920 }); 3921 3922 return false; 3923 }, 3924 3925 _mouseStop: function(event) { 3926 var that = this; 3927 3928 this.dragged = false; 3929 3930 $(".ui-unselecting", this.element[0]).each(function() { 3931 var selectee = $.data(this, "selectable-item"); 3932 selectee.$element.removeClass("ui-unselecting"); 3933 selectee.unselecting = false; 3934 selectee.startselected = false; 3935 that._trigger("unselected", event, { 3936 unselected: selectee.element 3937 }); 3938 }); 3939 $(".ui-selecting", this.element[0]).each(function() { 3940 var selectee = $.data(this, "selectable-item"); 3941 selectee.$element.removeClass("ui-selecting").addClass("ui-selected"); 3942 selectee.selecting = false; 3943 selectee.selected = true; 3944 selectee.startselected = true; 3945 that._trigger("selected", event, { 3946 selected: selectee.element 3947 }); 3948 }); 3949 this._trigger("stop", event); 3950 3951 this.helper.remove(); 3952 3953 return false; 3954 } 3955 3956}); 3957 3958})(jQuery); 3959(function( $, undefined ) { 3960 3961/*jshint loopfunc: true */ 3962 3963function isOverAxis( x, reference, size ) { 3964 return ( x > reference ) && ( x < ( reference + size ) ); 3965} 3966 3967function isFloating(item) { 3968 return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display")); 3969} 3970 3971$.widget("ui.sortable", $.ui.mouse, { 3972 version: "1.10.2", 3973 widgetEventPrefix: "sort", 3974 ready: false, 3975 options: { 3976 appendTo: "parent", 3977 axis: false, 3978 connectWith: false, 3979 containment: false, 3980 cursor: "auto", 3981 cursorAt: false, 3982 dropOnEmpty: true, 3983 forcePlaceholderSize: false, 3984 forceHelperSize: false, 3985 grid: false, 3986 handle: false, 3987 helper: "original", 3988 items: "> *", 3989 opacity: false, 3990 placeholder: false, 3991 revert: false, 3992 scroll: true, 3993 scrollSensitivity: 20, 3994 scrollSpeed: 20, 3995 scope: "default", 3996 tolerance: "intersect", 3997 zIndex: 1000, 3998 3999 // callbacks 4000 activate: null, 4001 beforeStop: null, 4002 change: null, 4003 deactivate: null, 4004 out: null, 4005 over: null, 4006 receive: null, 4007 remove: null, 4008 sort: null, 4009 start: null, 4010 stop: null, 4011 update: null 4012 }, 4013 _create: function() { 4014 4015 var o = this.options; 4016 this.containerCache = {}; 4017 this.element.addClass("ui-sortable"); 4018 4019 //Get the items 4020 this.refresh(); 4021 4022 //Let's determine if the items are being displayed horizontally 4023 this.floating = this.items.length ? o.axis === "x" || isFloating(this.items[0].item) : false; 4024 4025 //Let's determine the parent's offset 4026 this.offset = this.element.offset(); 4027 4028 //Initialize mouse events for interaction 4029 this._mouseInit(); 4030 4031 //We're ready to go 4032 this.ready = true; 4033 4034 }, 4035 4036 _destroy: function() { 4037 this.element 4038 .removeClass("ui-sortable ui-sortable-disabled"); 4039 this._mouseDestroy(); 4040 4041 for ( var i = this.items.length - 1; i >= 0; i-- ) { 4042 this.items[i].item.removeData(this.widgetName + "-item"); 4043 } 4044 4045 return this; 4046 }, 4047 4048 _setOption: function(key, value){ 4049 if ( key === "disabled" ) { 4050 this.options[ key ] = value; 4051 4052 this.widget().toggleClass( "ui-sortable-disabled", !!value ); 4053 } else { 4054 // Don't call widget base _setOption for disable as it adds ui-state-disabled class 4055 $.Widget.prototype._setOption.apply(this, arguments); 4056 } 4057 }, 4058 4059 _mouseCapture: function(event, overrideHandle) { 4060 var currentItem = null, 4061 validHandle = false, 4062 that = this; 4063 4064 if (this.reverting) { 4065 return false; 4066 } 4067 4068 if(this.options.disabled || this.options.type === "static") { 4069 return false; 4070 } 4071 4072 //We have to refresh the items data once first 4073 this._refreshItems(event); 4074 4075 //Find out if the clicked node (or one of its parents) is a actual item in this.items 4076 $(event.target).parents().each(function() { 4077 if($.data(this, that.widgetName + "-item") === that) { 4078 currentItem = $(this); 4079 return false; 4080 } 4081 }); 4082 if($.data(event.target, that.widgetName + "-item") === that) { 4083 currentItem = $(event.target); 4084 } 4085 4086 if(!currentItem) { 4087 return false; 4088 } 4089 if(this.options.handle && !overrideHandle) { 4090 $(this.options.handle, currentItem).find("*").addBack().each(function() { 4091 if(this === event.target) { 4092 validHandle = true; 4093 } 4094 }); 4095 if(!validHandle) { 4096 return false; 4097 } 4098 } 4099 4100 this.currentItem = currentItem; 4101 this._removeCurrentsFromItems(); 4102 return true; 4103 4104 }, 4105 4106 _mouseStart: function(event, overrideHandle, noActivation) { 4107 4108 var i, body, 4109 o = this.options; 4110 4111 this.currentContainer = this; 4112 4113 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture 4114 this.refreshPositions(); 4115 4116 //Create and append the visible helper 4117 this.helper = this._createHelper(event); 4118 4119 //Cache the helper size 4120 this._cacheHelperProportions(); 4121 4122 /* 4123 * - Position generation - 4124 * This block generates everything position related - it's the core of draggables. 4125 */ 4126 4127 //Cache the margins of the original element 4128 this._cacheMargins(); 4129 4130 //Get the next scrolling parent 4131 this.scrollParent = this.helper.scrollParent(); 4132 4133 //The element's absolute position on the page minus margins 4134 this.offset = this.currentItem.offset(); 4135 this.offset = { 4136 top: this.offset.top - this.margins.top, 4137 left: this.offset.left - this.margins.left 4138 }; 4139 4140 $.extend(this.offset, { 4141 click: { //Where the click happened, relative to the element 4142 left: event.pageX - this.offset.left, 4143 top: event.pageY - this.offset.top 4144 }, 4145 parent: this._getParentOffset(), 4146 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper 4147 }); 4148 4149 // Only after we got the offset, we can change the helper's position to absolute 4150 // TODO: Still need to figure out a way to make relative sorting possible 4151 this.helper.css("position", "absolute"); 4152 this.cssPosition = this.helper.css("position"); 4153 4154 //Generate the original position 4155 this.originalPosition = this._generatePosition(event); 4156 this.originalPageX = event.pageX; 4157 this.originalPageY = event.pageY; 4158 4159 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 4160 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); 4161 4162 //Cache the former DOM position 4163 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; 4164 4165 //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 4166 if(this.helper[0] !== this.currentItem[0]) { 4167 this.currentItem.hide(); 4168 } 4169 4170 //Create the placeholder 4171 this._createPlaceholder(); 4172 4173 //Set a containment if given in the options 4174 if(o.containment) { 4175 this._setContainment(); 4176 } 4177 4178 if( o.cursor && o.cursor !== "auto" ) { // cursor option 4179 body = this.document.find( "body" ); 4180 4181 // support: IE 4182 this.storedCursor = body.css( "cursor" ); 4183 body.css( "cursor", o.cursor ); 4184 4185 this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body ); 4186 } 4187 4188 if(o.opacity) { // opacity option 4189 if (this.helper.css("opacity")) { 4190 this._storedOpacity = this.helper.css("opacity"); 4191 } 4192 this.helper.css("opacity", o.opacity); 4193 } 4194 4195 if(o.zIndex) { // zIndex option 4196 if (this.helper.css("zIndex")) { 4197 this._storedZIndex = this.helper.css("zIndex"); 4198 } 4199 this.helper.css("zIndex", o.zIndex); 4200 } 4201 4202 //Prepare scrolling 4203 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { 4204 this.overflowOffset = this.scrollParent.offset(); 4205 } 4206 4207 //Call callbacks 4208 this._trigger("start", event, this._uiHash()); 4209 4210 //Recache the helper size 4211 if(!this._preserveHelperProportions) { 4212 this._cacheHelperProportions(); 4213 } 4214 4215 4216 //Post "activate" events to possible containers 4217 if( !noActivation ) { 4218 for ( i = this.containers.length - 1; i >= 0; i-- ) { 4219 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); 4220 } 4221 } 4222 4223 //Prepare possible droppables 4224 if($.ui.ddmanager) { 4225 $.ui.ddmanager.current = this; 4226 } 4227 4228 if ($.ui.ddmanager && !o.dropBehaviour) { 4229 $.ui.ddmanager.prepareOffsets(this, event); 4230 } 4231 4232 this.dragging = true; 4233 4234 this.helper.addClass("ui-sortable-helper"); 4235 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position 4236 return true; 4237 4238 }, 4239 4240 _mouseDrag: function(event) { 4241 var i, item, itemElement, intersection, 4242 o = this.options, 4243 scrolled = false; 4244 4245 //Compute the helpers position 4246 this.position = this._generatePosition(event); 4247 this.positionAbs = this._convertPositionTo("absolute"); 4248 4249 if (!this.lastPositionAbs) { 4250 this.lastPositionAbs = this.positionAbs; 4251 } 4252 4253 //Do scrolling 4254 if(this.options.scroll) { 4255 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { 4256 4257 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { 4258 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; 4259 } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) { 4260 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; 4261 } 4262 4263 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { 4264 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; 4265 } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) { 4266 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; 4267 } 4268 4269 } else { 4270 4271 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { 4272 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); 4273 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { 4274 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); 4275 } 4276 4277 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { 4278 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); 4279 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { 4280 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); 4281 } 4282 4283 } 4284 4285 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { 4286 $.ui.ddmanager.prepareOffsets(this, event); 4287 } 4288 } 4289 4290 //Regenerate the absolute position used for position checks 4291 this.positionAbs = this._convertPositionTo("absolute"); 4292 4293 //Set the helper position 4294 if(!this.options.axis || this.options.axis !== "y") { 4295 this.helper[0].style.left = this.position.left+"px"; 4296 } 4297 if(!this.options.axis || this.options.axis !== "x") { 4298 this.helper[0].style.top = this.position.top+"px"; 4299 } 4300 4301 //Rearrange 4302 for (i = this.items.length - 1; i >= 0; i--) { 4303 4304 //Cache variables and intersection, continue if no intersection 4305 item = this.items[i]; 4306 itemElement = item.item[0]; 4307 intersection = this._intersectsWithPointer(item); 4308 if (!intersection) { 4309 continue; 4310 } 4311 4312 // Only put the placeholder inside the current Container, skip all 4313 // items form other containers. This works because when moving 4314 // an item from one container to another the 4315 // currentContainer is switched before the placeholder is moved. 4316 // 4317 // Without this moving items in "sub-sortables" can cause the placeholder to jitter 4318 // beetween the outer and inner container. 4319 if (item.instance !== this.currentContainer) { 4320 continue; 4321 } 4322 4323 // cannot intersect with itself 4324 // no useless actions that have been done before 4325 // no action if the item moved is the parent of the item checked 4326 if (itemElement !== this.currentItem[0] && 4327 this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement && 4328 !$.contains(this.placeholder[0], itemElement) && 4329 (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true) 4330 ) { 4331 4332 this.direction = intersection === 1 ? "down" : "up"; 4333 4334 if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) { 4335 this._rearrange(event, item); 4336 } else { 4337 break; 4338 } 4339 4340 this._trigger("change", event, this._uiHash()); 4341 break; 4342 } 4343 } 4344 4345 //Post events to containers 4346 this._contactContainers(event); 4347 4348 //Interconnect with droppables 4349 if($.ui.ddmanager) { 4350 $.ui.ddmanager.drag(this, event); 4351 } 4352 4353 //Call callbacks 4354 this._trigger("sort", event, this._uiHash()); 4355 4356 this.lastPositionAbs = this.positionAbs; 4357 return false; 4358 4359 }, 4360 4361 _mouseStop: function(event, noPropagation) { 4362 4363 if(!event) { 4364 return; 4365 } 4366 4367 //If we are using droppables, inform the manager about the drop 4368 if ($.ui.ddmanager && !this.options.dropBehaviour) { 4369 $.ui.ddmanager.drop(this, event); 4370 } 4371 4372 if(this.options.revert) { 4373 var that = this, 4374 cur = this.placeholder.offset(), 4375 axis = this.options.axis, 4376 animation = {}; 4377 4378 if ( !axis || axis === "x" ) { 4379 animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft); 4380 } 4381 if ( !axis || axis === "y" ) { 4382 animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop); 4383 } 4384 this.reverting = true; 4385 $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() { 4386 that._clear(event); 4387 }); 4388 } else { 4389 this._clear(event, noPropagation); 4390 } 4391 4392 return false; 4393 4394 }, 4395 4396 cancel: function() { 4397 4398 if(this.dragging) { 4399 4400 this._mouseUp({ target: null }); 4401 4402 if(this.options.helper === "original") { 4403 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); 4404 } else { 4405 this.currentItem.show(); 4406 } 4407 4408 //Post deactivating events to containers 4409 for (var i = this.containers.length - 1; i >= 0; i--){ 4410 this.containers[i]._trigger("deactivate", null, this._uiHash(this)); 4411 if(this.containers[i].containerCache.over) { 4412 this.containers[i]._trigger("out", null, this._uiHash(this)); 4413 this.containers[i].containerCache.over = 0; 4414 } 4415 } 4416 4417 } 4418 4419 if (this.placeholder) { 4420 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! 4421 if(this.placeholder[0].parentNode) { 4422 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 4423 } 4424 if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) { 4425 this.helper.remove(); 4426 } 4427 4428 $.extend(this, { 4429 helper: null, 4430 dragging: false, 4431 reverting: false, 4432 _noFinalSort: null 4433 }); 4434 4435 if(this.domPosition.prev) { 4436 $(this.domPosition.prev).after(this.currentItem); 4437 } else { 4438 $(this.domPosition.parent).prepend(this.currentItem); 4439 } 4440 } 4441 4442 return this; 4443 4444 }, 4445 4446 serialize: function(o) { 4447 4448 var items = this._getItemsAsjQuery(o && o.connected), 4449 str = []; 4450 o = o || {}; 4451 4452 $(items).each(function() { 4453 var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/)); 4454 if (res) { 4455 str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2])); 4456 } 4457 }); 4458 4459 if(!str.length && o.key) { 4460 str.push(o.key + "="); 4461 } 4462 4463 return str.join("&"); 4464 4465 }, 4466 4467 toArray: function(o) { 4468 4469 var items = this._getItemsAsjQuery(o && o.connected), 4470 ret = []; 4471 4472 o = o || {}; 4473 4474 items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); }); 4475 return ret; 4476 4477 }, 4478 4479 /* Be careful with the following core functions */ 4480 _intersectsWith: function(item) { 4481 4482 var x1 = this.positionAbs.left, 4483 x2 = x1 + this.helperProportions.width, 4484 y1 = this.positionAbs.top, 4485 y2 = y1 + this.helperProportions.height, 4486 l = item.left, 4487 r = l + item.width, 4488 t = item.top, 4489 b = t + item.height, 4490 dyClick = this.offset.click.top, 4491 dxClick = this.offset.click.left, 4492 isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r; 4493 4494 if ( this.options.tolerance === "pointer" || 4495 this.options.forcePointerForContainers || 4496 (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"]) 4497 ) { 4498 return isOverElement; 4499 } else { 4500 4501 return (l < x1 + (this.helperProportions.width / 2) && // Right Half 4502 x2 - (this.helperProportions.width / 2) < r && // Left Half 4503 t < y1 + (this.helperProportions.height / 2) && // Bottom Half 4504 y2 - (this.helperProportions.height / 2) < b ); // Top Half 4505 4506 } 4507 }, 4508 4509 _intersectsWithPointer: function(item) { 4510 4511 var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), 4512 isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), 4513 isOverElement = isOverElementHeight && isOverElementWidth, 4514 verticalDirection = this._getDragVerticalDirection(), 4515 horizontalDirection = this._getDragHorizontalDirection(); 4516 4517 if (!isOverElement) { 4518 return false; 4519 } 4520 4521 return this.floating ? 4522 ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 ) 4523 : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) ); 4524 4525 }, 4526 4527 _intersectsWithSides: function(item) { 4528 4529 var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), 4530 isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), 4531 verticalDirection = this._getDragVerticalDirection(), 4532 horizontalDirection = this._getDragHorizontalDirection(); 4533 4534 if (this.floating && horizontalDirection) { 4535 return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf)); 4536 } else { 4537 return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf)); 4538 } 4539 4540 }, 4541 4542 _getDragVerticalDirection: function() { 4543 var delta = this.positionAbs.top - this.lastPositionAbs.top; 4544 return delta !== 0 && (delta > 0 ? "down" : "up"); 4545 }, 4546 4547 _getDragHorizontalDirection: function() { 4548 var delta = this.positionAbs.left - this.lastPositionAbs.left; 4549 return delta !== 0 && (delta > 0 ? "right" : "left"); 4550 }, 4551 4552 refresh: function(event) { 4553 this._refreshItems(event); 4554 this.refreshPositions(); 4555 return this; 4556 }, 4557 4558 _connectWith: function() { 4559 var options = this.options; 4560 return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith; 4561 }, 4562 4563 _getItemsAsjQuery: function(connected) { 4564 4565 var i, j, cur, inst, 4566 items = [], 4567 queries = [], 4568 connectWith = this._connectWith(); 4569 4570 if(connectWith && connected) { 4571 for (i = connectWith.length - 1; i >= 0; i--){ 4572 cur = $(connectWith[i]); 4573 for ( j = cur.length - 1; j >= 0; j--){ 4574 inst = $.data(cur[j], this.widgetFullName); 4575 if(inst && inst !== this && !inst.options.disabled) { 4576 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]); 4577 } 4578 } 4579 } 4580 } 4581 4582 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]); 4583 4584 for (i = queries.length - 1; i >= 0; i--){ 4585 queries[i][0].each(function() { 4586 items.push(this); 4587 }); 4588 } 4589 4590 return $(items); 4591 4592 }, 4593 4594 _removeCurrentsFromItems: function() { 4595 4596 var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); 4597 4598 this.items = $.grep(this.items, function (item) { 4599 for (var j=0; j < list.length; j++) { 4600 if(list[j] === item.item[0]) { 4601 return false; 4602 } 4603 } 4604 return true; 4605 }); 4606 4607 }, 4608 4609 _refreshItems: function(event) { 4610 4611 this.items = []; 4612 this.containers = [this]; 4613 4614 var i, j, cur, inst, targetData, _queries, item, queriesLength, 4615 items = this.items, 4616 queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]], 4617 connectWith = this._connectWith(); 4618 4619 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down 4620 for (i = connectWith.length - 1; i >= 0; i--){ 4621 cur = $(connectWith[i]); 4622 for (j = cur.length - 1; j >= 0; j--){ 4623 inst = $.data(cur[j], this.widgetFullName); 4624 if(inst && inst !== this && !inst.options.disabled) { 4625 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); 4626 this.containers.push(inst); 4627 } 4628 } 4629 } 4630 } 4631 4632 for (i = queries.length - 1; i >= 0; i--) { 4633 targetData = queries[i][1]; 4634 _queries = queries[i][0]; 4635 4636 for (j=0, queriesLength = _queries.length; j < queriesLength; j++) { 4637 item = $(_queries[j]); 4638 4639 item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager) 4640 4641 items.push({ 4642 item: item, 4643 instance: targetData, 4644 width: 0, height: 0, 4645 left: 0, top: 0 4646 }); 4647 } 4648 } 4649 4650 }, 4651 4652 refreshPositions: function(fast) { 4653 4654 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change 4655 if(this.offsetParent && this.helper) { 4656 this.offset.parent = this._getParentOffset(); 4657 } 4658 4659 var i, item, t, p; 4660 4661 for (i = this.items.length - 1; i >= 0; i--){ 4662 item = this.items[i]; 4663 4664 //We ignore calculating positions of all connected containers when we're not over them 4665 if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) { 4666 continue; 4667 } 4668 4669 t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; 4670 4671 if (!fast) { 4672 item.width = t.outerWidth(); 4673 item.height = t.outerHeight(); 4674 } 4675 4676 p = t.offset(); 4677 item.left = p.left; 4678 item.top = p.top; 4679 } 4680 4681 if(this.options.custom && this.options.custom.refreshContainers) { 4682 this.options.custom.refreshContainers.call(this); 4683 } else { 4684 for (i = this.containers.length - 1; i >= 0; i--){ 4685 p = this.containers[i].element.offset(); 4686 this.containers[i].containerCache.left = p.left; 4687 this.containers[i].containerCache.top = p.top; 4688 this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); 4689 this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); 4690 } 4691 } 4692 4693 return this; 4694 }, 4695 4696 _createPlaceholder: function(that) { 4697 that = that || this; 4698 var className, 4699 o = that.options; 4700 4701 if(!o.placeholder || o.placeholder.constructor === String) { 4702 className = o.placeholder; 4703 o.placeholder = { 4704 element: function() { 4705 4706 var nodeName = that.currentItem[0].nodeName.toLowerCase(), 4707 element = $( that.document[0].createElement( nodeName ) ) 4708 .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder") 4709 .removeClass("ui-sortable-helper"); 4710 4711 if ( nodeName === "tr" ) { 4712 // Use a high colspan to force the td to expand the full 4713 // width of the table (browsers are smart enough to 4714 // handle this properly) 4715 element.append( "<td colspan='99'> </td>" ); 4716 } else if ( nodeName === "img" ) { 4717 element.attr( "src", that.currentItem.attr( "src" ) ); 4718 } 4719 4720 if ( !className ) { 4721 element.css( "visibility", "hidden" ); 4722 } 4723 4724 return element; 4725 }, 4726 update: function(container, p) { 4727 4728 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that 4729 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified 4730 if(className && !o.forcePlaceholderSize) { 4731 return; 4732 } 4733 4734 //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
4735 if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); } 4736 if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); } 4737 } 4738 }; 4739 } 4740 4741 //Create the placeholder 4742 that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem)); 4743 4744 //Append it after the actual current item 4745 that.currentItem.after(that.placeholder); 4746 4747 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) 4748 o.placeholder.update(that, that.placeholder); 4749 4750 }, 4751 4752 _contactContainers: function(event) { 4753 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating, 4754 innermostContainer = null, 4755 innermostIndex = null; 4756 4757 // get innermost container that intersects with item 4758 for (i = this.containers.length - 1; i >= 0; i--) { 4759 4760 // never consider a container that's located within the item itself 4761 if($.contains(this.currentItem[0], this.containers[i].element[0])) { 4762 continue; 4763 } 4764 4765 if(this._intersectsWith(this.containers[i].containerCache)) { 4766 4767 // if we've already found a container and it's more "inner" than this, then continue 4768 if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) { 4769 continue; 4770 } 4771 4772 innermostContainer = this.containers[i]; 4773 innermostIndex = i; 4774 4775 } else { 4776 // container doesn't intersect. trigger "out" event if necessary 4777 if(this.containers[i].containerCache.over) { 4778 this.containers[i]._trigger("out", event, this._uiHash(this)); 4779 this.containers[i].containerCache.over = 0; 4780 } 4781 } 4782 4783 } 4784 4785 // if no intersecting containers found, return 4786 if(!innermostContainer) { 4787 return; 4788 } 4789 4790 // move the item into the container if it's not there already 4791 if(this.containers.length === 1) { 4792 if (!this.containers[innermostIndex].containerCache.over) { 4793 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 4794 this.containers[innermostIndex].containerCache.over = 1; 4795 } 4796 } else { 4797 4798 //When entering a new container, we will find the item with the least distance and append our item near it 4799 dist = 10000; 4800 itemWithLeastDistance = null; 4801 floating = innermostContainer.floating || isFloating(this.currentItem); 4802 posProperty = floating ? "left" : "top"; 4803 sizeProperty = floating ? "width" : "height"; 4804 base = this.positionAbs[posProperty] + this.offset.click[posProperty]; 4805 for (j = this.items.length - 1; j >= 0; j--) { 4806 if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) { 4807 continue; 4808 } 4809 if(this.items[j].item[0] === this.currentItem[0]) { 4810 continue; 4811 } 4812 if (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) { 4813 continue; 4814 } 4815 cur = this.items[j].item.offset()[posProperty]; 4816 nearBottom = false; 4817 if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){ 4818 nearBottom = true; 4819 cur += this.items[j][sizeProperty]; 4820 } 4821 4822 if(Math.abs(cur - base) < dist) { 4823 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j
vendor: 13,544 bytes, lines 4823-5144
4823]; 4824 this.direction = nearBottom ? "up": "down"; 4825 } 4826 } 4827 4828 //Check if dropOnEmpty is enabled 4829 if(!itemWithLeastDistance && !this.options.dropOnEmpty) { 4830 return; 4831 } 4832 4833 if(this.currentContainer === this.containers[innermostIndex]) { 4834 return; 4835 } 4836 4837 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 4838 this._trigger("change", event, this._uiHash()); 4839 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 4840 this.currentContainer = this.containers[innermostIndex]; 4841 4842 //Update the placeholder 4843 this.options.placeholder.update(this.currentContainer, this.placeholder); 4844 4845 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 4846 this.containers[innermostIndex].containerCache.over = 1; 4847 } 4848 4849 4850 }, 4851 4852 _createHelper: function(event) { 4853 4854 var o = this.options, 4855 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem); 4856 4857 //Add the helper to the DOM if that didn't happen already 4858 if(!helper.parents("body").length) { 4859 $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); 4860 } 4861 4862 if(helper[0] === this.currentItem[0]) { 4863 this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") }; 4864 } 4865 4866 if(!helper[0].style.width || o.forceHelperSize) { 4867 helper.width(this.currentItem.width()); 4868 } 4869 if(!helper[0].style.height || o.forceHelperSize) { 4870 helper.height(this.currentItem.height()); 4871 } 4872 4873 return helper; 4874 4875 }, 4876 4877 _adjustOffsetFromHelper: function(obj) { 4878 if (typeof obj === "string") { 4879 obj = obj.split(" "); 4880 } 4881 if ($.isArray(obj)) { 4882 obj = {left: +obj[0], top: +obj[1] || 0}; 4883 } 4884 if ("left" in obj) { 4885 this.offset.click.left = obj.left + this.margins.left; 4886 } 4887 if ("right" in obj) { 4888 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 4889 } 4890 if ("top" in obj) { 4891 this.offset.click.top = obj.top + this.margins.top; 4892 } 4893 if ("bottom" in obj) { 4894 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 4895 } 4896 }, 4897 4898 _getParentOffset: function() { 4899 4900 4901 //Get the offsetParent and cache its position 4902 this.offsetParent = this.helper.offsetParent(); 4903 var po = this.offsetParent.offset(); 4904 4905 // This is a special case where we need to modify a offset calculated on start, since the following happened: 4906 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent 4907 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that 4908 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag 4909 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { 4910 po.left += this.scrollParent.scrollLeft(); 4911 po.top += this.scrollParent.scrollTop(); 4912 } 4913 4914 // This needs to be actually done for all browsers, since pageX/pageY includes this information 4915 // with an ugly IE fix 4916 if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { 4917 po = { top: 0, left: 0 }; 4918 } 4919 4920 return { 4921 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), 4922 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) 4923 }; 4924 4925 }, 4926 4927 _getRelativeOffset: function() { 4928 4929 if(this.cssPosition === "relative") { 4930 var p = this.currentItem.position(); 4931 return { 4932 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), 4933 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() 4934 }; 4935 } else { 4936 return { top: 0, left: 0 }; 4937 } 4938 4939 }, 4940 4941 _cacheMargins: function() { 4942 this.margins = { 4943 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), 4944 top: (parseInt(this.currentItem.css("marginTop"),10) || 0) 4945 }; 4946 }, 4947 4948 _cacheHelperProportions: function() { 4949 this.helperProportions = { 4950 width: this.helper.outerWidth(), 4951 height: this.helper.outerHeight() 4952 }; 4953 }, 4954 4955 _setContainment: function() { 4956 4957 var ce, co, over, 4958 o = this.options; 4959 if(o.containment === "parent") { 4960 o.containment = this.helper[0].parentNode; 4961 } 4962 if(o.containment === "document" || o.containment === "window") { 4963 this.containment = [ 4964 0 - this.offset.relative.left - this.offset.parent.left, 4965 0 - this.offset.relative.top - this.offset.parent.top, 4966 $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left, 4967 ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top 4968 ]; 4969 } 4970 4971 if(!(/^(document|window|parent)$/).test(o.containment)) { 4972 ce = $(o.containment)[0]; 4973 co = $(o.containment).offset(); 4974 over = ($(ce).css("overflow") !== "hidden"); 4975 4976 this.containment = [ 4977 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, 4978 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, 4979 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, 4980 co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top 4981 ]; 4982 } 4983 4984 }, 4985 4986 _convertPositionTo: function(d, pos) { 4987 4988 if(!pos) { 4989 pos = this.position; 4990 } 4991 var mod = d === "absolute" ? 1 : -1, 4992 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, 4993 scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 4994 4995 return { 4996 top: ( 4997 pos.top + // The absolute mouse position 4998 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 4999 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) 5000 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) 5001 ), 5002 left: ( 5003 pos.left + // The absolute mouse position 5004 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 5005 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) 5006 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) 5007 ) 5008 }; 5009 5010 }, 5011 5012 _generatePosition: function(event) { 5013 5014 var top, left, 5015 o = this.options, 5016 pageX = event.pageX, 5017 pageY = event.pageY, 5018 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); 5019 5020 // This is another very weird special case that only happens for relative elements: 5021 // 1. If the css position is relative 5022 // 2. and the scroll parent is the document or similar to the offset parent 5023 // we have to refresh the relative offset during the scroll so there are no jumps 5024 if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) { 5025 this.offset.relative = this._getRelativeOffset(); 5026 } 5027 5028 /* 5029 * - Position constraining - 5030 * Constrain the position to a mix of grid, containment. 5031 */ 5032 5033 if(this.originalPosition) { //If we are not dragging yet, we won't check for options 5034 5035 if(this.containment) { 5036 if(event.pageX - this.offset.click.left < this.containment[0]) { 5037 pageX = this.containment[0] + this.offset.click.left; 5038 } 5039 if(event.pageY - this.offset.click.top < this.containment[1]) { 5040 pageY = this.containment[1] + this.offset.click.top; 5041 } 5042 if(event.pageX - this.offset.click.left > this.containment[2]) { 5043 pageX = this.containment[2] + this.offset.click.left; 5044 } 5045 if(event.pageY - this.offset.click.top > this.containment[3]) { 5046 pageY = this.containment[3] + this.offset.click.top; 5047 } 5048 } 5049 5050 if(o.grid) { 5051 top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; 5052 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; 5053 5054 left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; 5055 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; 5056 } 5057 5058 } 5059 5060 return { 5061 top: ( 5062 pageY - // The absolute mouse position 5063 this.offset.click.top - // Click offset (relative to the element) 5064 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent 5065 this.offset.parent.top + // The offsetParent's offset without borders (offset + border) 5066 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) 5067 ), 5068 left: ( 5069 pageX - // The absolute mouse position 5070 this.offset.click.left - // Click offset (relative to the element) 5071 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent 5072 this.offset.parent.left + // The offsetParent's offset without borders (offset + border) 5073 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) 5074 ) 5075 }; 5076 5077 }, 5078 5079 _rearrange: function(event, i, a, hardRefresh) { 5080 5081 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)); 5082 5083 //Various things done here to improve the performance: 5084 // 1. we create a setTimeout, that calls refreshPositions 5085 // 2. on the instance, we have a counter variable, that get's higher after every append 5086 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same 5087 // 4. this lets only the last addition to the timeout stack through 5088 this.counter = this.counter ? ++this.counter : 1; 5089 var counter = this.counter; 5090 5091 this._delay(function() { 5092 if(counter === this.counter) { 5093 this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove 5094 } 5095 }); 5096 5097 }, 5098 5099 _clear: function(event, noPropagation) { 5100 5101 this.reverting = false; 5102 // We delay all events that have to be triggered to after the point where the placeholder has been removed and 5103 // everything else normalized again 5104 var i, 5105 delayedTriggers = []; 5106 5107 // We first have to update the dom position of the actual currentItem 5108 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) 5109 if(!this._noFinalSort && this.currentItem.parent().length) { 5110 this.placeholder.before(this.currentItem); 5111 } 5112 this._noFinalSort = null; 5113 5114 if(this.helper[0] === this.currentItem[0]) { 5115 for(i in this._storedCSS) { 5116 if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") { 5117 this._storedCSS[i] = ""; 5118 } 5119 } 5120 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); 5121 } else { 5122 this.currentItem.show(); 5123 } 5124 5125 if(this.fromOutside && !noPropagation) { 5126 delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); 5127 } 5128 if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) { 5129 delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed 5130 } 5131 5132 // Check if the items Container has Changed and trigger appropriate 5133 // events. 5134 if (this !== this.currentContainer) { 5135 if(!noPropagation) { 5136 delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); 5137 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); 5138 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); 5139 } 5140 } 5141 5142 5143 //Post events to containers 5144 f
vendor: 40,203 bytes, lines 5144-6631
5144or (i = this.containers.length - 1; i >= 0; i--){ 5145 if(!noPropagation) { 5146 delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i])); 5147 } 5148 if(this.containers[i].containerCache.over) { 5149 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i])); 5150 this.containers[i].containerCache.over = 0; 5151 } 5152 } 5153 5154 //Do what was originally in plugins 5155 if ( this.storedCursor ) { 5156 this.document.find( "body" ).css( "cursor", this.storedCursor ); 5157 this.storedStylesheet.remove(); 5158 } 5159 if(this._storedOpacity) { 5160 this.helper.css("opacity", this._storedOpacity); 5161 } 5162 if(this._storedZIndex) { 5163 this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex); 5164 } 5165 5166 this.dragging = false; 5167 if(this.cancelHelperRemoval) { 5168 if(!noPropagation) { 5169 this._trigger("beforeStop", event, this._uiHash()); 5170 for (i=0; i < delayedTriggers.length; i++) { 5171 delayedTriggers[i].call(this, event); 5172 } //Trigger all delayed events 5173 this._trigger("stop", event, this._uiHash()); 5174 } 5175 5176 this.fromOutside = false; 5177 return false; 5178 } 5179 5180 if(!noPropagation) { 5181 this._trigger("beforeStop", event, this._uiHash()); 5182 } 5183 5184 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! 5185 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 5186 5187 if(this.helper[0] !== this.currentItem[0]) { 5188 this.helper.remove(); 5189 } 5190 this.helper = null; 5191 5192 if(!noPropagation) { 5193 for (i=0; i < delayedTriggers.length; i++) { 5194 delayedTriggers[i].call(this, event); 5195 } //Trigger all delayed events 5196 this._trigger("stop", event, this._uiHash()); 5197 } 5198 5199 this.fromOutside = false; 5200 return true; 5201 5202 }, 5203 5204 _trigger: function() { 5205 if ($.Widget.prototype._trigger.apply(this, arguments) === false) { 5206 this.cancel(); 5207 } 5208 }, 5209 5210 _uiHash: function(_inst) { 5211 var inst = _inst || this; 5212 return { 5213 helper: inst.helper, 5214 placeholder: inst.placeholder || $([]), 5215 position: inst.position, 5216 originalPosition: inst.originalPosition, 5217 offset: inst.positionAbs, 5218 item: inst.currentItem, 5219 sender: _inst ? _inst.element : null 5220 }; 5221 } 5222 5223}); 5224 5225})(jQuery); 5226(function( $, undefined ) { 5227 5228var uid = 0, 5229 hideProps = {}, 5230 showProps = {}; 5231 5232hideProps.height = hideProps.paddingTop = hideProps.paddingBottom = 5233 hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide"; 5234showProps.height = showProps.paddingTop = showProps.paddingBottom = 5235 showProps.borderTopWidth = showProps.borderBottomWidth = "show"; 5236 5237$.widget( "ui.accordion", { 5238 version: "1.10.2", 5239 options: { 5240 active: 0, 5241 animate: {}, 5242 collapsible: false, 5243 event: "click", 5244 header: "> li > :first-child,> :not(li):even", 5245 heightStyle: "auto", 5246 icons: { 5247 activeHeader: "ui-icon-triangle-1-s", 5248 header: "ui-icon-triangle-1-e" 5249 }, 5250 5251 // callbacks 5252 activate: null, 5253 beforeActivate: null 5254 }, 5255 5256 _create: function() { 5257 var options = this.options; 5258 this.prevShow = this.prevHide = $(); 5259 this.element.addClass( "ui-accordion ui-widget ui-helper-reset" ) 5260 // ARIA 5261 .attr( "role", "tablist" ); 5262 5263 // don't allow collapsible: false and active: false / null 5264 if ( !options.collapsible && (options.active === false || options.active == null) ) { 5265 options.active = 0; 5266 } 5267 5268 this._processPanels(); 5269 // handle negative values 5270 if ( options.active < 0 ) { 5271 options.active += this.headers.length; 5272 } 5273 this._refresh(); 5274 }, 5275 5276 _getCreateEventData: function() { 5277 return { 5278 header: this.active, 5279 panel: !this.active.length ? $() : this.active.next(), 5280 content: !this.active.length ? $() : this.active.next() 5281 }; 5282 }, 5283 5284 _createIcons: function() { 5285 var icons = this.options.icons; 5286 if ( icons ) { 5287 $( "<span>" ) 5288 .addClass( "ui-accordion-header-icon ui-icon " + icons.header ) 5289 .prependTo( this.headers ); 5290 this.active.children( ".ui-accordion-header-icon" ) 5291 .removeClass( icons.header ) 5292 .addClass( icons.activeHeader ); 5293 this.headers.addClass( "ui-accordion-icons" ); 5294 } 5295 }, 5296 5297 _destroyIcons: function() { 5298 this.headers 5299 .removeClass( "ui-accordion-icons" ) 5300 .children( ".ui-accordion-header-icon" ) 5301 .remove(); 5302 }, 5303 5304 _destroy: function() { 5305 var contents; 5306 5307 // clean up main element 5308 this.element 5309 .removeClass( "ui-accordion ui-widget ui-helper-reset" ) 5310 .removeAttr( "role" ); 5311 5312 // clean up headers 5313 this.headers 5314 .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" ) 5315 .removeAttr( "role" ) 5316 .removeAttr( "aria-selected" ) 5317 .removeAttr( "aria-controls" ) 5318 .removeAttr( "tabIndex" ) 5319 .each(function() { 5320 if ( /^ui-accordion/.test( this.id ) ) { 5321 this.removeAttribute( "id" ); 5322 } 5323 }); 5324 this._destroyIcons(); 5325 5326 // clean up content panels 5327 contents = this.headers.next() 5328 .css( "display", "" ) 5329 .removeAttr( "role" ) 5330 .removeAttr( "aria-expanded" ) 5331 .removeAttr( "aria-hidden" ) 5332 .removeAttr( "aria-labelledby" ) 5333 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" ) 5334 .each(function() { 5335 if ( /^ui-accordion/.test( this.id ) ) { 5336 this.removeAttribute( "id" ); 5337 } 5338 }); 5339 if ( this.options.heightStyle !== "content" ) { 5340 contents.css( "height", "" ); 5341 } 5342 }, 5343 5344 _setOption: function( key, value ) { 5345 if ( key === "active" ) { 5346 // _activate() will handle invalid values and update this.options 5347 this._activate( value ); 5348 return; 5349 } 5350 5351 if ( key === "event" ) { 5352 if ( this.options.event ) { 5353 this._off( this.headers, this.options.event ); 5354 } 5355 this._setupEvents( value ); 5356 } 5357 5358 this._super( key, value ); 5359 5360 // setting collapsible: false while collapsed; open first panel 5361 if ( key === "collapsible" && !value && this.options.active === false ) { 5362 this._activate( 0 ); 5363 } 5364 5365 if ( key === "icons" ) { 5366 this._destroyIcons(); 5367 if ( value ) { 5368 this._createIcons(); 5369 } 5370 } 5371 5372 // #5332 - opacity doesn't cascade to positioned elements in IE 5373 // so we need to add the disabled class to the headers and panels 5374 if ( key === "disabled" ) { 5375 this.headers.add( this.headers.next() ) 5376 .toggleClass( "ui-state-disabled", !!value ); 5377 } 5378 }, 5379 5380 _keydown: function( event ) { 5381 /*jshint maxcomplexity:15*/ 5382 if ( event.altKey || event.ctrlKey ) { 5383 return; 5384 } 5385 5386 var keyCode = $.ui.keyCode, 5387 length = this.headers.length, 5388 currentIndex = this.headers.index( event.target ), 5389 toFocus = false; 5390 5391 switch ( event.keyCode ) { 5392 case keyCode.RIGHT: 5393 case keyCode.DOWN: 5394 toFocus = this.headers[ ( currentIndex + 1 ) % length ]; 5395 break; 5396 case keyCode.LEFT: 5397 case keyCode.UP: 5398 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; 5399 break; 5400 case keyCode.SPACE: 5401 case keyCode.ENTER: 5402 this._eventHandler( event ); 5403 break; 5404 case keyCode.HOME: 5405 toFocus = this.headers[ 0 ]; 5406 break; 5407 case keyCode.END: 5408 toFocus = this.headers[ length - 1 ]; 5409 break; 5410 } 5411 5412 if ( toFocus ) { 5413 $( event.target ).attr( "tabIndex", -1 ); 5414 $( toFocus ).attr( "tabIndex", 0 ); 5415 toFocus.focus(); 5416 event.preventDefault(); 5417 } 5418 }, 5419 5420 _panelKeyDown : function( event ) { 5421 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { 5422 $( event.currentTarget ).prev().focus(); 5423 } 5424 }, 5425 5426 refresh: function() { 5427 var options = this.options; 5428 this._processPanels(); 5429 5430 // was collapsed or no panel 5431 if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) { 5432 options.active = false; 5433 this.active = $(); 5434 // active false only when collapsible is true 5435 } if ( options.active === false ) { 5436 this._activate( 0 ); 5437 // was active, but active panel is gone 5438 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 5439 // all remaining panel are disabled 5440 if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) { 5441 options.active = false; 5442 this.active = $(); 5443 // activate previous panel 5444 } else { 5445 this._activate( Math.max( 0, options.active - 1 ) ); 5446 } 5447 // was active, active panel still exists 5448 } else { 5449 // make sure active index is correct 5450 options.active = this.headers.index( this.active ); 5451 } 5452 5453 this._destroyIcons(); 5454 5455 this._refresh(); 5456 }, 5457 5458 _processPanels: function() { 5459 this.headers = this.element.find( this.options.header ) 5460 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ); 5461 5462 this.headers.next() 5463 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ) 5464 .filter(":not(.ui-accordion-content-active)") 5465 .hide(); 5466 }, 5467 5468 _refresh: function() { 5469 var maxHeight, 5470 options = this.options, 5471 heightStyle = options.heightStyle, 5472 parent = this.element.parent(), 5473 accordionId = this.accordionId = "ui-accordion-" + 5474 (this.element.attr( "id" ) || ++uid); 5475 5476 this.active = this._findActive( options.active ) 5477 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ) 5478 .removeClass( "ui-corner-all" ); 5479 this.active.next() 5480 .addClass( "ui-accordion-content-active" ) 5481 .show(); 5482 5483 this.headers 5484 .attr( "role", "tab" ) 5485 .each(function( i ) { 5486 var header = $( this ), 5487 headerId = header.attr( "id" ), 5488 panel = header.next(), 5489 panelId = panel.attr( "id" ); 5490 if ( !headerId ) { 5491 headerId = accordionId + "-header-" + i; 5492 header.attr( "id", headerId ); 5493 } 5494 if ( !panelId ) { 5495 panelId = accordionId + "-panel-" + i; 5496 panel.attr( "id", panelId ); 5497 } 5498 header.attr( "aria-controls", panelId ); 5499 panel.attr( "aria-labelledby", headerId ); 5500 }) 5501 .next() 5502 .attr( "role", "tabpanel" ); 5503 5504 this.headers 5505 .not( this.active ) 5506 .attr({ 5507 "aria-selected": "false", 5508 tabIndex: -1 5509 }) 5510 .next() 5511 .attr({ 5512 "aria-expanded": "false", 5513 "aria-hidden": "true" 5514 }) 5515 .hide(); 5516 5517 // make sure at least one header is in the tab order 5518 if ( !this.active.length ) { 5519 this.headers.eq( 0 ).attr( "tabIndex", 0 ); 5520 } else { 5521 this.active.attr({ 5522 "aria-selected": "true", 5523 tabIndex: 0 5524 }) 5525 .next() 5526 .attr({ 5527 "aria-expanded": "true", 5528 "aria-hidden": "false" 5529 }); 5530 } 5531 5532 this._createIcons(); 5533 5534 this._setupEvents( options.event ); 5535 5536 if ( heightStyle === "fill" ) { 5537 maxHeight = parent.height(); 5538 this.element.siblings( ":visible" ).each(function() { 5539 var elem = $( this ), 5540 position = elem.css( "position" ); 5541 5542 if ( position === "absolute" || position === "fixed" ) { 5543 return; 5544 } 5545 maxHeight -= elem.outerHeight( true ); 5546 }); 5547 5548 this.headers.each(function() { 5549 maxHeight -= $( this ).outerHeight( true ); 5550 }); 5551 5552 this.headers.next() 5553 .each(function() { 5554 $( this ).height( Math.max( 0, maxHeight - 5555 $( this ).innerHeight() + $( this ).height() ) ); 5556 }) 5557 .css( "overflow", "auto" ); 5558 } else if ( heightStyle === "auto" ) { 5559 maxHeight = 0; 5560 this.headers.next() 5561 .each(function() { 5562 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); 5563 }) 5564 .height( maxHeight ); 5565 } 5566 }, 5567 5568 _activate: function( index ) { 5569 var active = this._findActive( index )[ 0 ]; 5570 5571 // trying to activate the already active panel 5572 if ( active === this.active[ 0 ] ) { 5573 return; 5574 } 5575 5576 // trying to collapse, simulate a click on the currently active header 5577 active = active || this.active[ 0 ]; 5578 5579 this._eventHandler({ 5580 target: active, 5581 currentTarget: active, 5582 preventDefault: $.noop 5583 }); 5584 }, 5585 5586 _findActive: function( selector ) { 5587 return typeof selector === "number" ? this.headers.eq( selector ) : $(); 5588 }, 5589 5590 _setupEvents: function( event ) { 5591 var events = { 5592 keydown: "_keydown" 5593 }; 5594 if ( event ) { 5595 $.each( event.split(" "), function( index, eventName ) { 5596 events[ eventName ] = "_eventHandler"; 5597 }); 5598 } 5599 5600 this._off( this.headers.add( this.headers.next() ) ); 5601 this._on( this.headers, events ); 5602 this._on( this.headers.next(), { keydown: "_panelKeyDown" }); 5603 this._hoverable( this.headers ); 5604 this._focusable( this.headers ); 5605 }, 5606 5607 _eventHandler: function( event ) { 5608 var options = this.options, 5609 active = this.active, 5610 clicked = $( event.currentTarget ), 5611 clickedIsActive = clicked[ 0 ] === active[ 0 ], 5612 collapsing = clickedIsActive && options.collapsible, 5613 toShow = collapsing ? $() : clicked.next(), 5614 toHide = active.next(), 5615 eventData = { 5616 oldHeader: active, 5617 oldPanel: toHide, 5618 newHeader: collapsing ? $() : clicked, 5619 newPanel: toShow 5620 }; 5621 5622 event.preventDefault(); 5623 5624 if ( 5625 // click on active header, but not collapsible 5626 ( clickedIsActive && !options.collapsible ) || 5627 // allow canceling activation 5628 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 5629 return; 5630 } 5631 5632 options.active = collapsing ? false : this.headers.index( clicked ); 5633 5634 // when the call to ._toggle() comes after the class changes 5635 // it causes a very odd bug in IE 8 (see #6720) 5636 this.active = clickedIsActive ? $() : clicked; 5637 this._toggle( eventData ); 5638 5639 // switch classes 5640 // corner classes on the previously active header stay after the animation 5641 active.removeClass( "ui-accordion-header-active ui-state-active" ); 5642 if ( options.icons ) { 5643 active.children( ".ui-accordion-header-icon" ) 5644 .removeClass( options.icons.activeHeader ) 5645 .addClass( options.icons.header ); 5646 } 5647 5648 if ( !clickedIsActive ) { 5649 clicked 5650 .removeClass( "ui-corner-all" ) 5651 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ); 5652 if ( options.icons ) { 5653 clicked.children( ".ui-accordion-header-icon" ) 5654 .removeClass( options.icons.header ) 5655 .addClass( options.icons.activeHeader ); 5656 } 5657 5658 clicked 5659 .next() 5660 .addClass( "ui-accordion-content-active" ); 5661 } 5662 }, 5663 5664 _toggle: function( data ) { 5665 var toShow = data.newPanel, 5666 toHide = this.prevShow.length ? this.prevShow : data.oldPanel; 5667 5668 // handle activating a panel during the animation for another activation 5669 this.prevShow.add( this.prevHide ).stop( true, true ); 5670 this.prevShow = toShow; 5671 this.prevHide = toHide; 5672 5673 if ( this.options.animate ) { 5674 this._animate( toShow, toHide, data ); 5675 } else { 5676 toHide.hide(); 5677 toShow.show(); 5678 this._toggleComplete( data ); 5679 } 5680 5681 toHide.attr({ 5682 "aria-expanded": "false", 5683 "aria-hidden": "true" 5684 }); 5685 toHide.prev().attr( "aria-selected", "false" ); 5686 // if we're switching panels, remove the old header from the tab order 5687 // if we're opening from collapsed state, remove the previous header from the tab order 5688 // if we're collapsing, then keep the collapsing header in the tab order 5689 if ( toShow.length && toHide.length ) { 5690 toHide.prev().attr( "tabIndex", -1 ); 5691 } else if ( toShow.length ) { 5692 this.headers.filter(function() { 5693 return $( this ).attr( "tabIndex" ) === 0; 5694 }) 5695 .attr( "tabIndex", -1 ); 5696 } 5697 5698 toShow 5699 .attr({ 5700 "aria-expanded": "true", 5701 "aria-hidden": "false" 5702 }) 5703 .prev() 5704 .attr({ 5705 "aria-selected": "true", 5706 tabIndex: 0 5707 }); 5708 }, 5709 5710 _animate: function( toShow, toHide, data ) { 5711 var total, easing, duration, 5712 that = this, 5713 adjust = 0, 5714 down = toShow.length && 5715 ( !toHide.length || ( toShow.index() < toHide.index() ) ), 5716 animate = this.options.animate || {}, 5717 options = down && animate.down || animate, 5718 complete = function() { 5719 that._toggleComplete( data ); 5720 }; 5721 5722 if ( typeof options === "number" ) { 5723 duration = options; 5724 } 5725 if ( typeof options === "string" ) { 5726 easing = options; 5727 } 5728 // fall back from options to animation in case of partial down settings 5729 easing = easing || options.easing || animate.easing; 5730 duration = duration || options.duration || animate.duration; 5731 5732 if ( !toHide.length ) { 5733 return toShow.animate( showProps, duration, easing, complete ); 5734 } 5735 if ( !toShow.length ) { 5736 return toHide.animate( hideProps, duration, easing, complete ); 5737 } 5738 5739 total = toShow.show().outerHeight(); 5740 toHide.animate( hideProps, { 5741 duration: duration, 5742 easing: easing, 5743 step: function( now, fx ) { 5744 fx.now = Math.round( now ); 5745 } 5746 }); 5747 toShow 5748 .hide() 5749 .animate( showProps, { 5750 duration: duration, 5751 easing: easing, 5752 complete: complete, 5753 step: function( now, fx ) { 5754 fx.now = Math.round( now ); 5755 if ( fx.prop !== "height" ) { 5756 adjust += fx.now; 5757 } else if ( that.options.heightStyle !== "content" ) { 5758 fx.now = Math.round( total - toHide.outerHeight() - adjust ); 5759 adjust = 0; 5760 } 5761 } 5762 }); 5763 }, 5764 5765 _toggleComplete: function( data ) { 5766 var toHide = data.oldPanel; 5767 5768 toHide 5769 .removeClass( "ui-accordion-content-active" ) 5770 .prev() 5771 .removeClass( "ui-corner-top" ) 5772 .addClass( "ui-corner-all" ); 5773 5774 // Work around for rendering bug in IE (#5421) 5775 if ( toHide.length ) { 5776 toHide.parent()[0].className = toHide.parent()[0].className; 5777 } 5778 5779 this._trigger( "activate", null, data ); 5780 } 5781}); 5782 5783})( jQuery ); 5784(function( $, undefined ) { 5785 5786// used to prevent race conditions with remote data sources 5787var requestIndex = 0; 5788 5789$.widget( "ui.autocomplete", { 5790 version: "1.10.2", 5791 defaultElement: "<input>", 5792 options: { 5793 appendTo: null, 5794 autoFocus: false, 5795 delay: 300, 5796 minLength: 1, 5797 position: { 5798 my: "left top", 5799 at: "left bottom", 5800 collision: "none" 5801 }, 5802 source: null, 5803 5804 // callbacks 5805 change: null, 5806 close: null, 5807 focus: null, 5808 open: null, 5809 response: null, 5810 search: null, 5811 select: null 5812 }, 5813 5814 pending: 0, 5815 5816 _create: function() { 5817 // Some browsers only repeat keydown events, not keypress events, 5818 // so we use the suppressKeyPress flag to determine if we've already 5819 // handled the keydown event. #7269 5820 // Unfortunately the code for & in keypress is the same as the up arrow, 5821 // so we use the suppressKeyPressRepeat flag to avoid handling keypress 5822 // events when we know the keydown event was used to modify the 5823 // search term. #7799 5824 var suppressKeyPress, suppressKeyPressRepeat, suppressInput, 5825 nodeName = this.element[0].nodeName.toLowerCase(), 5826 isTextarea = nodeName === "textarea", 5827 isInput = nodeName === "input"; 5828 5829 this.isMultiLine = 5830 // Textareas are always multi-line 5831 isTextarea ? true : 5832 // Inputs are always single-line, even if inside a contentEditable element 5833 // IE also treats inputs as contentEditable 5834 isInput ? false : 5835 // All other element types are determined by whether or not they're contentEditable 5836 this.element.prop( "isContentEditable" ); 5837 5838 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ]; 5839 this.isNewMenu = true; 5840 5841 this.element 5842 .addClass( "ui-autocomplete-input" ) 5843 .attr( "autocomplete", "off" ); 5844 5845 this._on( this.element, { 5846 keydown: function( event ) { 5847 /*jshint maxcomplexity:15*/ 5848 if ( this.element.prop( "readOnly" ) ) { 5849 suppressKeyPress = true; 5850 suppressInput = true; 5851 suppressKeyPressRepeat = true; 5852 return; 5853 } 5854 5855 suppressKeyPress = false; 5856 suppressInput = false; 5857 suppressKeyPressRepeat = false; 5858 var keyCode = $.ui.keyCode; 5859 switch( event.keyCode ) { 5860 case keyCode.PAGE_UP: 5861 suppressKeyPress = true; 5862 this._move( "previousPage", event ); 5863 break; 5864 case keyCode.PAGE_DOWN: 5865 suppressKeyPress = true; 5866 this._move( "nextPage", event ); 5867 break; 5868 case keyCode.UP: 5869 suppressKeyPress = true; 5870 this._keyEvent( "previous", event ); 5871 break; 5872 case keyCode.DOWN: 5873 suppressKeyPress = true; 5874 this._keyEvent( "next", event ); 5875 break; 5876 case keyCode.ENTER: 5877 case keyCode.NUMPAD_ENTER: 5878 // when menu is open and has focus 5879 if ( this.menu.active ) { 5880 // #6055 - Opera still allows the keypress to occur 5881 // which causes forms to submit 5882 suppressKeyPress = true; 5883 event.preventDefault(); 5884 this.menu.select( event ); 5885 } 5886 break; 5887 case keyCode.TAB: 5888 if ( this.menu.active ) { 5889 this.menu.select( event ); 5890 } 5891 break; 5892 case keyCode.ESCAPE: 5893 if ( this.menu.element.is( ":visible" ) ) { 5894 this._value( this.term ); 5895 this.close( event ); 5896 // Different browsers have different default behavior for escape 5897 // Single press can mean undo or clear 5898 // Double press in IE means clear the whole form 5899 event.preventDefault(); 5900 } 5901 break; 5902 default: 5903 suppressKeyPressRepeat = true; 5904 // search timeout should be triggered before the input value is changed 5905 this._searchTimeout( event ); 5906 break; 5907 } 5908 }, 5909 keypress: function( event ) { 5910 if ( suppressKeyPress ) { 5911 suppressKeyPress = false; 5912 event.preventDefault(); 5913 return; 5914 } 5915 if ( suppressKeyPressRepeat ) { 5916 return; 5917 } 5918 5919 // replicate some key handlers to allow them to repeat in Firefox and Opera 5920 var keyCode = $.ui.keyCode; 5921 switch( event.keyCode ) { 5922 case keyCode.PAGE_UP: 5923 this._move( "previousPage", event ); 5924 break; 5925 case keyCode.PAGE_DOWN: 5926 this._move( "nextPage", event ); 5927 break; 5928 case keyCode.UP: 5929 this._keyEvent( "previous", event ); 5930 break; 5931 case keyCode.DOWN: 5932 this._keyEvent( "next", event ); 5933 break; 5934 } 5935 }, 5936 input: function( event ) { 5937 if ( suppressInput ) { 5938 suppressInput = false; 5939 event.preventDefault(); 5940 return; 5941 } 5942 this._searchTimeout( event ); 5943 }, 5944 focus: function() { 5945 this.selectedItem = null; 5946 this.previous = this._value(); 5947 }, 5948 blur: function( event ) { 5949 if ( this.cancelBlur ) { 5950 delete this.cancelBlur; 5951 return; 5952 } 5953 5954 clearTimeout( this.searching ); 5955 this.close( event ); 5956 this._change( event ); 5957 } 5958 }); 5959 5960 this._initSource(); 5961 this.menu = $( "<ul>" ) 5962 .addClass( "ui-autocomplete ui-front" ) 5963 .appendTo( this._appendTo() ) 5964 .menu({ 5965 // custom key handling for now 5966 input: $(), 5967 // disable ARIA support, the live region takes care of that 5968 role: null 5969 }) 5970 .hide() 5971 .data( "ui-menu" ); 5972 5973 this._on( this.menu.element, { 5974 mousedown: function( event ) { 5975 // prevent moving focus out of the text field 5976 event.preventDefault(); 5977 5978 // IE doesn't prevent moving focus even with event.preventDefault() 5979 // so we set a flag to know when we should ignore the blur event 5980 this.cancelBlur = true; 5981 this._delay(function() { 5982 delete this.cancelBlur; 5983 }); 5984 5985 // clicking on the scrollbar causes focus to shift to the body 5986 // but we can't detect a mouseup or a click immediately afterward 5987 // so we have to track the next mousedown and close the menu if 5988 // the user clicks somewhere outside of the autocomplete 5989 var menuElement = this.menu.element[ 0 ]; 5990 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { 5991 this._delay(function() { 5992 var that = this; 5993 this.document.one( "mousedown", function( event ) { 5994 if ( event.target !== that.element[ 0 ] && 5995 event.target !== menuElement && 5996 !$.contains( menuElement, event.target ) ) { 5997 that.close(); 5998 } 5999 }); 6000 }); 6001 } 6002 }, 6003 menufocus: function( event, ui ) { 6004 // support: Firefox 6005 // Prevent accidental activation of menu items in Firefox (#7024 #9118) 6006 if ( this.isNewMenu ) { 6007 this.isNewMenu = false; 6008 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) { 6009 this.menu.blur(); 6010 6011 this.document.one( "mousemove", function() { 6012 $( event.target ).trigger( event.originalEvent ); 6013 }); 6014 6015 return; 6016 } 6017 } 6018 6019 var item = ui.item.data( "ui-autocomplete-item" ); 6020 if ( false !== this._trigger( "focus", event, { item: item } ) ) { 6021 // use value to match what will end up in the input, if it was a key event 6022 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) { 6023 this._value( item.value ); 6024 } 6025 } else { 6026 // Normally the input is populated with the item's value as the 6027 // menu is navigated, causing screen readers to notice a change and 6028 // announce the item. Since the focus event was canceled, this doesn't 6029 // happen, so we update the live region so that screen readers can 6030 // still notice the change and announce it. 6031 this.liveRegion.text( item.value ); 6032 } 6033 }, 6034 menuselect: function( event, ui ) { 6035 var item = ui.item.data( "ui-autocomplete-item" ), 6036 previous = this.previous; 6037 6038 // only trigger when focus was lost (click on menu) 6039 if ( this.element[0] !== this.document[0].activeElement ) { 6040 this.element.focus(); 6041 this.previous = previous; 6042 // #6109 - IE triggers two focus events and the second 6043 // is asynchronous, so we need to reset the previous 6044 // term synchronously and asynchronously :-( 6045 this._delay(function() { 6046 this.previous = previous; 6047 this.selectedItem = item; 6048 }); 6049 } 6050 6051 if ( false !== this._trigger( "select", event, { item: item } ) ) { 6052 this._value( item.value ); 6053 } 6054 // reset the term after the select event 6055 // this allows custom select handling to work properly 6056 this.term = this._value(); 6057 6058 this.close( event ); 6059 this.selectedItem = item; 6060 } 6061 }); 6062 6063 this.liveRegion = $( "<span>", { 6064 role: "status", 6065 "aria-live": "polite" 6066 }) 6067 .addClass( "ui-helper-hidden-accessible" ) 6068 .insertAfter( this.element ); 6069 6070 // turning off autocomplete prevents the browser from remembering the 6071 // value when navigating through history, so we re-enable autocomplete 6072 // if the page is unloaded before the widget is destroyed. #7790 6073 this._on( this.window, { 6074 beforeunload: function() { 6075 this.element.removeAttr( "autocomplete" ); 6076 } 6077 }); 6078 }, 6079 6080 _destroy: function() { 6081 clearTimeout( this.searching ); 6082 this.element 6083 .removeClass( "ui-autocomplete-input" ) 6084 .removeAttr( "autocomplete" ); 6085 this.menu.element.remove(); 6086 this.liveRegion.remove(); 6087 }, 6088 6089 _setOption: function( key, value ) { 6090 this._super( key, value ); 6091 if ( key === "source" ) { 6092 this._initSource(); 6093 } 6094 if ( key === "appendTo" ) { 6095 this.menu.element.appendTo( this._appendTo() ); 6096 } 6097 if ( key === "disabled" && value && this.xhr ) { 6098 this.xhr.abort(); 6099 } 6100 }, 6101 6102 _appendTo: function() { 6103 var element = this.options.appendTo; 6104 6105 if ( element ) { 6106 element = element.jquery || element.nodeType ? 6107 $( element ) : 6108 this.document.find( element ).eq( 0 ); 6109 } 6110 6111 if ( !element ) { 6112 element = this.element.closest( ".ui-front" ); 6113 } 6114 6115 if ( !element.length ) { 6116 element = this.document[0].body; 6117 } 6118 6119 return element; 6120 }, 6121 6122 _initSource: function() { 6123 var array, url, 6124 that = this; 6125 if ( $.isArray(this.options.source) ) { 6126 array = this.options.source; 6127 this.source = function( request, response ) { 6128 response( $.ui.autocomplete.filter( array, request.term ) ); 6129 }; 6130 } else if ( typeof this.options.source === "string" ) { 6131 url = this.options.source; 6132 this.source = function( request, response ) { 6133 if ( that.xhr ) { 6134 that.xhr.abort(); 6135 } 6136 that.xhr = $.ajax({ 6137 url: url, 6138 data: request, 6139 dataType: "json", 6140 success: function( data ) { 6141 response( data ); 6142 }, 6143 error: function() { 6144 response( [] ); 6145 } 6146 }); 6147 }; 6148 } else { 6149 this.source = this.options.source; 6150 } 6151 }, 6152 6153 _searchTimeout: function( event ) { 6154 clearTimeout( this.searching ); 6155 this.searching = this._delay(function() { 6156 // only search if the value has changed 6157 if ( this.term !== this._value() ) { 6158 this.selectedItem = null; 6159 this.search( null, event ); 6160 } 6161 }, this.options.delay ); 6162 }, 6163 6164 search: function( value, event ) { 6165 value = value != null ? value : this._value(); 6166 6167 // always save the actual value, not the one passed as an argument 6168 this.term = this._value(); 6169 6170 if ( value.length < this.options.minLength ) { 6171 return this.close( event ); 6172 } 6173 6174 if ( this._trigger( "search", event ) === false ) { 6175 return; 6176 } 6177 6178 return this._search( value ); 6179 }, 6180 6181 _search: function( value ) { 6182 this.pending++; 6183 this.element.addClass( "ui-autocomplete-loading" ); 6184 this.cancelSearch = false; 6185 6186 this.source( { term: value }, this._response() ); 6187 }, 6188 6189 _response: function() { 6190 var that = this, 6191 index = ++requestIndex; 6192 6193 return function( content ) { 6194 if ( index === requestIndex ) { 6195 that.__response( content ); 6196 } 6197 6198 that.pending--; 6199 if ( !that.pending ) { 6200 that.element.removeClass( "ui-autocomplete-loading" ); 6201 } 6202 }; 6203 }, 6204 6205 __response: function( content ) { 6206 if ( content ) { 6207 content = this._normalize( content ); 6208 } 6209 this._trigger( "response", null, { content: content } ); 6210 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) { 6211 this._suggest( content ); 6212 this._trigger( "open" ); 6213 } else { 6214 // use ._close() instead of .close() so we don't cancel future searches 6215 this._close(); 6216 } 6217 }, 6218 6219 close: function( event ) { 6220 this.cancelSearch = true; 6221 this._close( event ); 6222 }, 6223 6224 _close: function( event ) { 6225 if ( this.menu.element.is( ":visible" ) ) { 6226 this.menu.element.hide(); 6227 this.menu.blur(); 6228 this.isNewMenu = true; 6229 this._trigger( "close", event ); 6230 } 6231 }, 6232 6233 _change: function( event ) { 6234 if ( this.previous !== this._value() ) { 6235 this._trigger( "change", event, { item: this.selectedItem } ); 6236 } 6237 }, 6238 6239 _normalize: function( items ) { 6240 // assume all items have the right format when the first item is complete 6241 if ( items.length && items[0].label && items[0].value ) { 6242 return items; 6243 } 6244 return $.map( items, function( item ) { 6245 if ( typeof item === "string" ) { 6246 return { 6247 label: item, 6248 value: item 6249 }; 6250 } 6251 return $.extend({ 6252 label: item.label || item.value, 6253 value: item.value || item.label 6254 }, item ); 6255 }); 6256 }, 6257 6258 _suggest: function( items ) { 6259 var ul = this.menu.element.empty(); 6260 this._renderMenu( ul, items ); 6261 this.isNewMenu = true; 6262 this.menu.refresh(); 6263 6264 // size and position menu 6265 ul.show(); 6266 this._resizeMenu(); 6267 ul.position( $.extend({ 6268 of: this.element 6269 }, this.options.position )); 6270 6271 if ( this.options.autoFocus ) { 6272 this.menu.next(); 6273 } 6274 }, 6275 6276 _resizeMenu: function() { 6277 var ul = this.menu.element; 6278 ul.outerWidth( Math.max( 6279 // Firefox wraps long text (possibly a rounding bug) 6280 // so we add 1px to avoid the wrapping (#7513) 6281 ul.width( "" ).outerWidth() + 1, 6282 this.element.outerWidth() 6283 ) ); 6284 }, 6285 6286 _renderMenu: function( ul, items ) { 6287 var that = this; 6288 $.each( items, function( index, item ) { 6289 that._renderItemData( ul, item ); 6290 }); 6291 }, 6292 6293 _renderItemData: function( ul, item ) { 6294 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item ); 6295 }, 6296 6297 _renderItem: function( ul, item ) { 6298 return $( "<li>" ) 6299 .append( $( "<a>" ).text( item.label ) ) 6300 .appendTo( ul ); 6301 }, 6302 6303 _move: function( direction, event ) { 6304 if ( !this.menu.element.is( ":visible" ) ) { 6305 this.search( null, event ); 6306 return; 6307 } 6308 if ( this.menu.isFirstItem() && /^previous/.test( direction ) || 6309 this.menu.isLastItem() && /^next/.test( direction ) ) { 6310 this._value( this.term ); 6311 this.menu.blur(); 6312 return; 6313 } 6314 this.menu[ direction ]( event ); 6315 }, 6316 6317 widget: function() { 6318 return this.menu.element; 6319 }, 6320 6321 _value: function() { 6322 return this.valueMethod.apply( this.element, arguments ); 6323 }, 6324 6325 _keyEvent: function( keyEvent, event ) { 6326 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 6327 this._move( keyEvent, event ); 6328 6329 // prevents moving cursor to beginning/end of the text field in some browsers 6330 event.preventDefault(); 6331 } 6332 } 6333}); 6334 6335$.extend( $.ui.autocomplete, { 6336 escapeRegex: function( value ) { 6337 return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); 6338 }, 6339 filter: function(array, term) { 6340 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); 6341 return $.grep( array, function(value) { 6342 return matcher.test( value.label || value.value || value ); 6343 }); 6344 } 6345}); 6346 6347 6348// live region extension, adding a `messages` option 6349// NOTE: This is an experimental API. We are still investigating 6350// a full solution for string manipulation and internationalization. 6351$.widget( "ui.autocomplete", $.ui.autocomplete, { 6352 options: { 6353 messages: { 6354 noResults: "No search results.", 6355 results: function( amount ) { 6356 return amount + ( amount > 1 ? " results are" : " result is" ) + 6357 " available, use up and down arrow keys to navigate."; 6358 } 6359 } 6360 }, 6361 6362 __response: function( content ) { 6363 var message; 6364 this._superApply( arguments ); 6365 if ( this.options.disabled || this.cancelSearch ) { 6366 return; 6367 } 6368 if ( content && content.length ) { 6369 message = this.options.messages.results( content.length ); 6370 } else { 6371 message = this.options.messages.noResults; 6372 } 6373 this.liveRegion.text( message ); 6374 } 6375}); 6376 6377}( jQuery )); 6378(function( $, undefined ) { 6379 6380var lastActive, startXPos, startYPos, clickDragged, 6381 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", 6382 stateClasses = "ui-state-hover ui-state-active ", 6383 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", 6384 formResetHandler = function() { 6385 var buttons = $( this ).find( ":ui-button" ); 6386 setTimeout(function() { 6387 buttons.button( "refresh" ); 6388 }, 1 ); 6389 }, 6390 radioGroup = function( radio ) { 6391 var name = radio.name, 6392 form = radio.form, 6393 radios = $( [] ); 6394 if ( name ) { 6395 name = name.replace( /'/g, "\\'" ); 6396 if ( form ) { 6397 radios = $( form ).find( "[name='" + name + "']" ); 6398 } else { 6399 radios = $( "[name='" + name + "']", radio.ownerDocument ) 6400 .filter(function() { 6401 return !this.form; 6402 }); 6403 } 6404 } 6405 return radios; 6406 }; 6407 6408$.widget( "ui.button", { 6409 version: "1.10.2", 6410 defaultElement: "<button>", 6411 options: { 6412 disabled: null, 6413 text: true, 6414 label: null, 6415 icons: { 6416 primary: null, 6417 secondary: null 6418 } 6419 }, 6420 _create: function() { 6421 this.element.closest( "form" ) 6422 .unbind( "reset" + this.eventNamespace ) 6423 .bind( "reset" + this.eventNamespace, formResetHandler ); 6424 6425 if ( typeof this.options.disabled !== "boolean" ) { 6426 this.options.disabled = !!this.element.prop( "disabled" ); 6427 } else { 6428 this.element.prop( "disabled", this.options.disabled ); 6429 } 6430 6431 this._determineButtonType(); 6432 this.hasTitle = !!this.buttonElement.attr( "title" ); 6433 6434 var that = this, 6435 options = this.options, 6436 toggleButton = this.type === "checkbox" || this.type === "radio", 6437 activeClass = !toggleButton ? "ui-state-active" : "", 6438 focusClass = "ui-state-focus"; 6439 6440 if ( options.label === null ) { 6441 options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html()); 6442 } 6443 6444 this._hoverable( this.buttonElement ); 6445 6446 this.buttonElement 6447 .addClass( baseClasses ) 6448 .attr( "role", "button" ) 6449 .bind( "mouseenter" + this.eventNamespace, function() { 6450 if ( options.disabled ) { 6451 return; 6452 } 6453 if ( this === lastActive ) { 6454 $( this ).addClass( "ui-state-active" ); 6455 } 6456 }) 6457 .bind( "mouseleave" + this.eventNamespace, function() { 6458 if ( options.disabled ) { 6459 return; 6460 } 6461 $( this ).removeClass( activeClass ); 6462 }) 6463 .bind( "click" + this.eventNamespace, function( event ) { 6464 if ( options.disabled ) { 6465 event.preventDefault(); 6466 event.stopImmediatePropagation(); 6467 } 6468 }); 6469 6470 this.element 6471 .bind( "focus" + this.eventNamespace, function() { 6472 // no need to check disabled, focus won't be triggered anyway 6473 that.buttonElement.addClass( focusClass ); 6474 }) 6475 .bind( "blur" + this.eventNamespace, function() { 6476 that.buttonElement.removeClass( focusClass ); 6477 }); 6478 6479 if ( toggleButton ) { 6480 this.element.bind( "change" + this.eventNamespace, function() { 6481 if ( clickDragged ) { 6482 return; 6483 } 6484 that.refresh(); 6485 }); 6486 // if mouse moves between mousedown and mouseup (drag) set clickDragged flag 6487 // prevents issue where button state changes but checkbox/radio checked state 6488 // does not in Firefox (see ticket #6970) 6489 this.buttonElement 6490 .bind( "mousedown" + this.eventNamespace, function( event ) { 6491 if ( options.disabled ) { 6492 return; 6493 } 6494 clickDragged = false; 6495 startXPos = event.pageX; 6496 startYPos = event.pageY; 6497 }) 6498 .bind( "mouseup" + this.eventNamespace, function( event ) { 6499 if ( options.disabled ) { 6500 return; 6501 } 6502 if ( startXPos !== event.pageX || startYPos !== event.pageY ) { 6503 clickDragged = true; 6504 } 6505 }); 6506 } 6507 6508 if ( this.type === "checkbox" ) { 6509 this.buttonElement.bind( "click" + this.eventNamespace, function() { 6510 if ( options.disabled || clickDragged ) { 6511 return false; 6512 } 6513 }); 6514 } else if ( this.type === "radio" ) { 6515 this.buttonElement.bind( "click" + this.eventNamespace, function() { 6516 if ( options.disabled || clickDragged ) { 6517 return false; 6518 } 6519 $( this ).addClass( "ui-state-active" ); 6520 that.buttonElement.attr( "aria-pressed", "true" ); 6521 6522 var radio = that.element[ 0 ]; 6523 radioGroup( radio ) 6524 .not( radio ) 6525 .map(function() { 6526 return $( this ).button( "widget" )[ 0 ]; 6527 }) 6528 .removeClass( "ui-state-active" ) 6529 .attr( "aria-pressed", "false" ); 6530 }); 6531 } else { 6532 this.buttonElement 6533 .bind( "mousedown" + this.eventNamespace, function() { 6534 if ( options.disabled ) { 6535 return false; 6536 } 6537 $( this ).addClass( "ui-state-active" ); 6538 lastActive = this; 6539 that.document.one( "mouseup", function() { 6540 lastActive = null; 6541 }); 6542 }) 6543 .bind( "mouseup" + this.eventNamespace, function() { 6544 if ( options.disabled ) { 6545 return false; 6546 } 6547 $( this ).removeClass( "ui-state-active" ); 6548 }) 6549 .bind( "keydown" + this.eventNamespace, function(event) { 6550 if ( options.disabled ) { 6551 return false; 6552 } 6553 if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) { 6554 $( this ).addClass( "ui-state-active" ); 6555 } 6556 }) 6557 // see #8559, we bind to blur here in case the button element loses 6558 // focus between keydown and keyup, it would be left in an "active" state 6559 .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() { 6560 $( this ).removeClass( "ui-state-active" ); 6561 }); 6562 6563 if ( this.buttonElement.is("a") ) { 6564 this.buttonElement.keyup(function(event) { 6565 if ( event.keyCode === $.ui.keyCode.SPACE ) { 6566 // TODO pass through original event correctly (just as 2nd argument doesn't work) 6567 $( this ).click(); 6568 } 6569 }); 6570 } 6571 } 6572 6573 // TODO: pull out $.Widget's handling for the disabled option into 6574 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can 6575 // be overridden by individual plugins 6576 this._setOption( "disabled", options.disabled ); 6577 this._resetButton(); 6578 }, 6579 6580 _determineButtonType: function() { 6581 var ancestor, labelSelector, checked; 6582 6583 if ( this.element.is("[type=checkbox]") ) { 6584 this.type = "checkbox"; 6585 } else if ( this.element.is("[type=radio]") ) { 6586 this.type = "radio"; 6587 } else if ( this.element.is("input") ) { 6588 this.type = "input"; 6589 } else { 6590 this.type = "button"; 6591 } 6592 6593 if ( this.type === "checkbox" || this.type === "radio" ) { 6594 // we don't search against the document in case the element 6595 // is disconnected from the DOM 6596 ancestor = this.element.parents().last(); 6597 labelSelector = "label[for='" + this.element.attr("id") + "']"; 6598 this.buttonElement = ancestor.find( labelSelector ); 6599 if ( !this.buttonElement.length ) { 6600 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); 6601 this.buttonElement = ancestor.filter( labelSelector ); 6602 if ( !this.buttonElement.length ) { 6603 this.buttonElement = ancestor.find( labelSelector ); 6604 } 6605 } 6606 this.element.addClass( "ui-helper-hidden-accessible" ); 6607 6608 checked = this.element.is( ":checked" ); 6609 if ( checked ) { 6610 this.buttonElement.addClass( "ui-state-active" ); 6611 } 6612 this.buttonElement.prop( "aria-pressed", checked ); 6613 } else { 6614 this.buttonElement = this.element; 6615 } 6616 }, 6617 6618 widget: function() { 6619 return this.buttonElement; 6620 }, 6621 6622 _destroy: function() { 6623 this.element 6624 .removeClass( "ui-helper-hidden-accessible" ); 6625 this.buttonElement 6626 .removeClass( baseClasses + " " + stateClasses + " " + typeClasses ) 6627 .removeAttr( "role" ) 6628 .removeAttr( "aria-pressed" ) 6629 .html( this.buttonElement.find(".ui-button-text").html() ); 6630 6631 if ( !this.hasTitle ) {
vendor: 4,097 bytes, lines 6632-6788
6632 this.buttonElement.removeAttr( "title" ); 6633 } 6634 }, 6635 6636 _setOption: function( key, value ) { 6637 this._super( key, value ); 6638 if ( key === "disabled" ) { 6639 if ( value ) { 6640 this.element.prop( "disabled", true ); 6641 } else { 6642 this.element.prop( "disabled", false ); 6643 } 6644 return; 6645 } 6646 this._resetButton(); 6647 }, 6648 6649 refresh: function() { 6650 //See #8237 & #8828 6651 var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" ); 6652 6653 if ( isDisabled !== this.options.disabled ) { 6654 this._setOption( "disabled", isDisabled ); 6655 } 6656 if ( this.type === "radio" ) { 6657 radioGroup( this.element[0] ).each(function() { 6658 if ( $( this ).is( ":checked" ) ) { 6659 $( this ).button( "widget" ) 6660 .addClass( "ui-state-active" ) 6661 .attr( "aria-pressed", "true" ); 6662 } else { 6663 $( this ).button( "widget" ) 6664 .removeClass( "ui-state-active" ) 6665 .attr( "aria-pressed", "false" ); 6666 } 6667 }); 6668 } else if ( this.type === "checkbox" ) { 6669 if ( this.element.is( ":checked" ) ) { 6670 this.buttonElement 6671 .addClass( "ui-state-active" ) 6672 .attr( "aria-pressed", "true" ); 6673 } else { 6674 this.buttonElement 6675 .removeClass( "ui-state-active" ) 6676 .attr( "aria-pressed", "false" ); 6677 } 6678 } 6679 }, 6680 6681 _resetButton: function() { 6682 if ( this.type === "input" ) { 6683 if ( this.options.label ) { 6684 this.element.val( this.options.label ); 6685 } 6686 return; 6687 } 6688 var buttonElement = this.buttonElement.removeClass( typeClasses ), 6689 buttonText = $( "<span></span>", this.document[0] ) 6690 .addClass( "ui-button-text" ) 6691 .html( this.options.label ) 6692 .appendTo( buttonElement.empty() ) 6693 .text(), 6694 icons = this.options.icons, 6695 multipleIcons = icons.primary && icons.secondary, 6696 buttonClasses = []; 6697 6698 if ( icons.primary || icons.secondary ) { 6699 if ( this.options.text ) { 6700 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) ); 6701 } 6702 6703 if ( icons.primary ) { 6704 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" ); 6705 } 6706 6707 if ( icons.secondary ) { 6708 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" ); 6709 } 6710 6711 if ( !this.options.text ) { 6712 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" ); 6713 6714 if ( !this.hasTitle ) { 6715 buttonElement.attr( "title", $.trim( buttonText ) ); 6716 } 6717 } 6718 } else { 6719 buttonClasses.push( "ui-button-text-only" ); 6720 } 6721 buttonElement.addClass( buttonClasses.join( " " ) ); 6722 } 6723}); 6724 6725$.widget( "ui.buttonset", { 6726 version: "1.10.2", 6727 options: { 6728 items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)" 6729 }, 6730 6731 _create: function() { 6732 this.element.addClass( "ui-buttonset" ); 6733 }, 6734 6735 _init: function() { 6736 this.refresh(); 6737 }, 6738 6739 _setOption: function( key, value ) { 6740 if ( key === "disabled" ) { 6741 this.buttons.button( "option", key, value ); 6742 } 6743 6744 this._super( key, value ); 6745 }, 6746 6747 refresh: function() { 6748 var rtl = this.element.css( "direction" ) === "rtl"; 6749 6750 this.buttons = this.element.find( this.options.items ) 6751 .filter( ":ui-button" ) 6752 .button( "refresh" ) 6753 .end() 6754 .not( ":ui-button" ) 6755 .button() 6756 .end() 6757 .map(function() { 6758 return $( this ).button( "widget" )[ 0 ]; 6759 }) 6760 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" ) 6761 .filter( ":first" ) 6762 .addClass( rtl ? "ui-corner-right" : "ui-corner-left" ) 6763 .end() 6764 .filter( ":last" ) 6765 .addClass( rtl ? "ui-corner-left" : "ui-corner-right" ) 6766 .end() 6767 .end(); 6768 }, 6769 6770 _destroy: function() { 6771 this.element.removeClass( "ui-buttonset" ); 6772 this.buttons 6773 .map(function() { 6774 return $( this ).button( "widget" )[ 0 ]; 6775 }) 6776 .removeClass( "ui-corner-left ui-corner-right" ) 6777 .end() 6778 .button( "destroy" ); 6779 } 6780}); 6781 6782}( jQuery ) ); 6783(function( $, undefined ) { 6784 6785$.extend($.ui, { datepicker: { version: "1.10.2" } }); 6786 6787var PROP_NAME = "datepicker", 6788 dpuuid = new Date().getTime()
vendor: 29,048 bytes, lines 6788-7525
6788, 6789 instActive; 6790 6791/* Date picker manager. 6792 Use the singleton instance of this class, $.datepicker, to interact with the date picker. 6793 Settings for (groups of) date pickers are maintained in an instance object, 6794 allowing multiple different settings on the same page. */ 6795 6796function Datepicker() { 6797 this._curInst = null; // The current instance in use 6798 this._keyEvent = false; // If the last event was a key event 6799 this._disabledInputs = []; // List of date picker inputs that have been disabled 6800 this._datepickerShowing = false; // True if the popup picker is showing , false if not 6801 this._inDialog = false; // True if showing within a "dialog", false if not 6802 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division 6803 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class 6804 this._appendClass = "ui-datepicker-append"; // The name of the append marker class 6805 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class 6806 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class 6807 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class 6808 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class 6809 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class 6810 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class 6811 this.regional = []; // Available regional settings, indexed by language code 6812 this.regional[""] = { // Default regional settings 6813 closeText: "Done", // Display text for close link 6814 prevText: "Prev", // Display text for previous month link 6815 nextText: "Next", // Display text for next month link 6816 currentText: "Today", // Display text for current month link 6817 monthNames: ["January","February","March","April","May","June", 6818 "July","August","September","October","November","December"], // Names of months for drop-down and formatting 6819 monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting 6820 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting 6821 dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting 6822 dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday 6823 weekHeader: "Wk", // Column header for week of the year 6824 dateFormat: "mm/dd/yy", // See format options on parseDate 6825 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... 6826 isRTL: false, // True if right-to-left language, false if left-to-right 6827 showMonthAfterYear: false, // True if the year select precedes month, false for month then year 6828 yearSuffix: "" // Additional text to append to the year in the month headers 6829 }; 6830 this._defaults = { // Global defaults for all the date picker instances 6831 showOn: "focus", // "focus" for popup on focus, 6832 // "button" for trigger button, or "both" for either 6833 showAnim: "fadeIn", // Name of jQuery animation for popup 6834 showOptions: {}, // Options for enhanced animations 6835 defaultDate: null, // Used when field is blank: actual date, 6836 // +/-number for offset from today, null for today 6837 appendText: "", // Display text following the input box, e.g. showing the format 6838 buttonText: "...", // Text for trigger button 6839 buttonImage: "", // URL for trigger button image 6840 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button 6841 hideIfNoPrevNext: false, // True to hide next/previous month links 6842 // if not applicable, false to just disable them 6843 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links 6844 gotoCurrent: false, // True if today link goes back to current selection instead 6845 changeMonth: false, // True if month can be selected directly, false if only prev/next 6846 changeYear: false, // True if year can be selected directly, false if only prev/next 6847 yearRange: "c-10:c+10", // Range of years to display in drop-down, 6848 // either relative to today's year (-nn:+nn), relative to currently displayed year 6849 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) 6850 showOtherMonths: false, // True to show dates in other months, false to leave blank 6851 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable 6852 showWeek: false, // True to show week of the year, false to not show it 6853 calculateWeek: this.iso8601Week, // How to calculate the week of the year, 6854 // takes a Date and returns the number of the week for it 6855 shortYearCutoff: "+10", // Short year values < this are in the current century, 6856 // > this are in the previous century, 6857 // string value starting with "+" for current year + value 6858 minDate: null, // The earliest selectable date, or null for no limit 6859 maxDate: null, // The latest selectable date, or null for no limit 6860 duration: "fast", // Duration of display/closure 6861 beforeShowDay: null, // Function that takes a date and returns an array with 6862 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "", 6863 // [2] = cell title (optional), e.g. $.datepicker.noWeekends 6864 beforeShow: null, // Function that takes an input field and 6865 // returns a set of custom settings for the date picker 6866 onSelect: null, // Define a callback function when a date is selected 6867 onChangeMonthYear: null, // Define a callback function when the month or year is changed 6868 onClose: null, // Define a callback function when the datepicker is closed 6869 numberOfMonths: 1, // Number of months to show at a time 6870 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) 6871 stepMonths: 1, // Number of months to step back/forward 6872 stepBigMonths: 12, // Number of months to step back/forward for the big links 6873 altField: "", // Selector for an alternate field to store selected dates into 6874 altFormat: "", // The date format to use for the alternate field 6875 constrainInput: true, // The input is constrained by the current date format 6876 showButtonPanel: false, // True to show button panel, false to not show it 6877 autoSize: false, // True to size the input for the date format, false to leave as is 6878 disabled: false // The initial disabled state 6879 }; 6880 $.extend(this._defaults, this.regional[""]); 6881 this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")); 6882} 6883 6884$.extend(Datepicker.prototype, { 6885 /* Class name added to elements to indicate already configured with a date picker. */ 6886 markerClassName: "hasDatepicker", 6887 6888 //Keep track of the maximum number of rows displayed (see #7043) 6889 maxRows: 4, 6890 6891 // TODO rename to "widget" when switching to widget factory 6892 _widgetDatepicker: function() { 6893 return this.dpDiv; 6894 }, 6895 6896 /* Override the default settings for all instances of the date picker. 6897 * @param settings object - the new settings to use as defaults (anonymous object) 6898 * @return the manager object 6899 */ 6900 setDefaults: function(settings) { 6901 extendRemove(this._defaults, settings || {}); 6902 return this; 6903 }, 6904 6905 /* Attach the date picker to a jQuery selection. 6906 * @param target element - the target input field or division or span 6907 * @param settings object - the new settings to use for this date picker instance (anonymous) 6908 */ 6909 _attachDatepicker: function(target, settings) { 6910 var nodeName, inline, inst; 6911 nodeName = target.nodeName.toLowerCase(); 6912 inline = (nodeName === "div" || nodeName === "span"); 6913 if (!target.id) { 6914 this.uuid += 1; 6915 target.id = "dp" + this.uuid; 6916 } 6917 inst = this._newInst($(target), inline); 6918 inst.settings = $.extend({}, settings || {}); 6919 if (nodeName === "input") { 6920 this._connectDatepicker(target, inst); 6921 } else if (inline) { 6922 this._inlineDatepicker(target, inst); 6923 } 6924 }, 6925 6926 /* Create a new instance object. */ 6927 _newInst: function(target, inline) { 6928 var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars 6929 return {id: id, input: target, // associated target 6930 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection 6931 drawMonth: 0, drawYear: 0, // month being drawn 6932 inline: inline, // is datepicker inline or not 6933 dpDiv: (!inline ? this.dpDiv : // presentation div 6934 bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))}; 6935 }, 6936 6937 /* Attach the date picker to an input field. */ 6938 _connectDatepicker: function(target, inst) { 6939 var input = $(target); 6940 inst.append = $([]); 6941 inst.trigger = $([]); 6942 if (input.hasClass(this.markerClassName)) { 6943 return; 6944 } 6945 this._attachments(input, inst); 6946 input.addClass(this.markerClassName).keydown(this._doKeyDown). 6947 keypress(this._doKeyPress).keyup(this._doKeyUp); 6948 this._autoSize(inst); 6949 $.data(target, PROP_NAME, inst); 6950 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) 6951 if( inst.settings.disabled ) { 6952 this._disableDatepicker( target ); 6953 } 6954 }, 6955 6956 /* Make attachments based on settings. */ 6957 _attachments: function(input, inst) { 6958 var showOn, buttonText, buttonImage, 6959 appendText = this._get(inst, "appendText"), 6960 isRTL = this._get(inst, "isRTL"); 6961 6962 if (inst.append) { 6963 inst.append.remove(); 6964 } 6965 if (appendText) { 6966 inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>"); 6967 input[isRTL ? "before" : "after"](inst.append); 6968 } 6969 6970 input.unbind("focus", this._showDatepicker); 6971 6972 if (inst.trigger) { 6973 inst.trigger.remove(); 6974 } 6975 6976 showOn = this._get(inst, "showOn"); 6977 if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field 6978 input.focus(this._showDatepicker); 6979 } 6980 if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked 6981 buttonText = this._get(inst, "buttonText"); 6982 buttonImage = this._get(inst, "buttonImage"); 6983 inst.trigger = $(this._get(inst, "buttonImageOnly") ? 6984 $("<img/>").addClass(this._triggerClass). 6985 attr({ src: buttonImage, alt: buttonText, title: buttonText }) : 6986 $("<button type='button'></button>").addClass(this._triggerClass). 6987 html(!buttonImage ? buttonText : $("<img/>").attr( 6988 { src:buttonImage, alt:buttonText, title:buttonText }))); 6989 input[isRTL ? "before" : "after"](inst.trigger); 6990 inst.trigger.click(function() { 6991 if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) { 6992 $.datepicker._hideDatepicker(); 6993 } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) { 6994 $.datepicker._hideDatepicker(); 6995 $.datepicker._showDatepicker(input[0]); 6996 } else { 6997 $.datepicker._showDatepicker(input[0]); 6998 } 6999 return false; 7000 }); 7001 } 7002 }, 7003 7004 /* Apply the maximum length for the date format. */ 7005 _autoSize: function(inst) { 7006 if (this._get(inst, "autoSize") && !inst.inline) { 7007 var findMax, max, maxI, i, 7008 date = new Date(2009, 12 - 1, 20), // Ensure double digits 7009 dateFormat = this._get(inst, "dateFormat"); 7010 7011 if (dateFormat.match(/[DM]/)) { 7012 findMax = function(names) { 7013 max = 0; 7014 maxI = 0; 7015 for (i = 0; i < names.length; i++) { 7016 if (names[i].length > max) { 7017 max = names[i].length; 7018 maxI = i; 7019 } 7020 } 7021 return maxI; 7022 }; 7023 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? 7024 "monthNames" : "monthNamesShort")))); 7025 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? 7026 "dayNames" : "dayNamesShort"))) + 20 - date.getDay()); 7027 } 7028 inst.input.attr("size", this._formatDate(inst, date).length); 7029 } 7030 }, 7031 7032 /* Attach an inline date picker to a div. */ 7033 _inlineDatepicker: function(target, inst) { 7034 var divSpan = $(target); 7035 if (divSpan.hasClass(this.markerClassName)) { 7036 return; 7037 } 7038 divSpan.addClass(this.markerClassName).append(inst.dpDiv); 7039 $.data(target, PROP_NAME, inst); 7040 this._setDate(inst, this._getDefaultDate(inst), true); 7041 this._updateDatepicker(inst); 7042 this._updateAlternate(inst); 7043 //If disabled option is true, disable the datepicker before showing it (see ticket #5665) 7044 if( inst.settings.disabled ) { 7045 this._disableDatepicker( target ); 7046 } 7047 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements 7048 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height 7049 inst.dpDiv.css( "display", "block" ); 7050 }, 7051 7052 /* Pop-up the date picker in a "dialog" box. 7053 * @param input element - ignored 7054 * @param date string or Date - the initial date to display 7055 * @param onSelect function - the function to call when a date is selected 7056 * @param settings object - update the dialog date picker instance's settings (anonymous object) 7057 * @param pos int[2] - coordinates for the dialog's position within the screen or 7058 * event - with x/y coordinates or 7059 * leave empty for default (screen centre) 7060 * @return the manager object 7061 */ 7062 _dialogDatepicker: function(input, date, onSelect, settings, pos) { 7063 var id, browserWidth, browserHeight, scrollX, scrollY, 7064 inst = this._dialogInst; // internal instance 7065 7066 if (!inst) { 7067 this.uuid += 1; 7068 id = "dp" + this.uuid; 7069 this._dialogInput = $("<input type='text' id='" + id + 7070 "' style='position: absolute; top: -100px; width: 0px;'/>"); 7071 this._dialogInput.keydown(this._doKeyDown); 7072 $("body").append(this._dialogInput); 7073 inst = this._dialogInst = this._newInst(this._dialogInput, false); 7074 inst.settings = {}; 7075 $.data(this._dialogInput[0], PROP_NAME, inst); 7076 } 7077 extendRemove(inst.settings, settings || {}); 7078 date = (date && date.constructor === Date ? this._formatDate(inst, date) : date); 7079 this._dialogInput.val(date); 7080 7081 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); 7082 if (!this._pos) { 7083 browserWidth = document.documentElement.clientWidth; 7084 browserHeight = document.documentElement.clientHeight; 7085 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; 7086 scrollY = document.documentElement.scrollTop || document.body.scrollTop; 7087 this._pos = // should use actual width/height below 7088 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; 7089 } 7090 7091 // move input on screen for focus, but hidden behind dialog 7092 this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px"); 7093 inst.settings.onSelect = onSelect; 7094 this._inDialog = true; 7095 this.dpDiv.addClass(this._dialogClass); 7096 this._showDatepicker(this._dialogInput[0]); 7097 if ($.blockUI) { 7098 $.blockUI(this.dpDiv); 7099 } 7100 $.data(this._dialogInput[0], PROP_NAME, inst); 7101 return this; 7102 }, 7103 7104 /* Detach a datepicker from its control. 7105 * @param target element - the target input field or division or span 7106 */ 7107 _destroyDatepicker: function(target) { 7108 var nodeName, 7109 $target = $(target), 7110 inst = $.data(target, PROP_NAME); 7111 7112 if (!$target.hasClass(this.markerClassName)) { 7113 return; 7114 } 7115 7116 nodeName = target.nodeName.toLowerCase(); 7117 $.removeData(target, PROP_NAME); 7118 if (nodeName === "input") { 7119 inst.append.remove(); 7120 inst.trigger.remove(); 7121 $target.removeClass(this.markerClassName). 7122 unbind("focus", this._showDatepicker). 7123 unbind("keydown", this._doKeyDown). 7124 unbind("keypress", this._doKeyPress). 7125 unbind("keyup", this._doKeyUp); 7126 } else if (nodeName === "div" || nodeName === "span") { 7127 $target.removeClass(this.markerClassName).empty(); 7128 } 7129 }, 7130 7131 /* Enable the date picker to a jQuery selection. 7132 * @param target element - the target input field or division or span 7133 */ 7134 _enableDatepicker: function(target) { 7135 var nodeName, inline, 7136 $target = $(target), 7137 inst = $.data(target, PROP_NAME); 7138 7139 if (!$target.hasClass(this.markerClassName)) { 7140 return; 7141 } 7142 7143 nodeName = target.nodeName.toLowerCase(); 7144 if (nodeName === "input") { 7145 target.disabled = false; 7146 inst.trigger.filter("button"). 7147 each(function() { this.disabled = false; }).end(). 7148 filter("img").css({opacity: "1.0", cursor: ""}); 7149 } else if (nodeName === "div" || nodeName === "span") { 7150 inline = $target.children("." + this._inlineClass); 7151 inline.children().removeClass("ui-state-disabled"); 7152 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 7153 prop("disabled", false); 7154 } 7155 this._disabledInputs = $.map(this._disabledInputs, 7156 function(value) { return (value === target ? null : value); }); // delete entry 7157 }, 7158 7159 /* Disable the date picker to a jQuery selection. 7160 * @param target element - the target input field or division or span 7161 */ 7162 _disableDatepicker: function(target) { 7163 var nodeName, inline, 7164 $target = $(target), 7165 inst = $.data(target, PROP_NAME); 7166 7167 if (!$target.hasClass(this.markerClassName)) { 7168 return; 7169 } 7170 7171 nodeName = target.nodeName.toLowerCase(); 7172 if (nodeName === "input") { 7173 target.disabled = true; 7174 inst.trigger.filter("button"). 7175 each(function() { this.disabled = true; }).end(). 7176 filter("img").css({opacity: "0.5", cursor: "default"}); 7177 } else if (nodeName === "div" || nodeName === "span") { 7178 inline = $target.children("." + this._inlineClass); 7179 inline.children().addClass("ui-state-disabled"); 7180 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 7181 prop("disabled", true); 7182 } 7183 this._disabledInputs = $.map(this._disabledInputs, 7184 function(value) { return (value === target ? null : value); }); // delete entry 7185 this._disabledInputs[this._disabledInputs.length] = target; 7186 }, 7187 7188 /* Is the first field in a jQuery collection disabled as a datepicker? 7189 * @param target element - the target input field or division or span 7190 * @return boolean - true if disabled, false if enabled 7191 */ 7192 _isDisabledDatepicker: function(target) { 7193 if (!target) { 7194 return false; 7195 } 7196 for (var i = 0; i < this._disabledInputs.length; i++) { 7197 if (this._disabledInputs[i] === target) { 7198 return true; 7199 } 7200 } 7201 return false; 7202 }, 7203 7204 /* Retrieve the instance data for the target control. 7205 * @param target element - the target input field or division or span 7206 * @return object - the associated instance data 7207 * @throws error if a jQuery problem getting data 7208 */ 7209 _getInst: function(target) { 7210 try { 7211 return $.data(target, PROP_NAME); 7212 } 7213 catch (err) { 7214 throw "Missing instance data for this datepicker"; 7215 } 7216 }, 7217 7218 /* Update or retrieve the settings for a date picker attached to an input field or division. 7219 * @param target element - the target input field or division or span 7220 * @param name object - the new settings to update or 7221 * string - the name of the setting to change or retrieve, 7222 * when retrieving also "all" for all instance settings or 7223 * "defaults" for all global defaults 7224 * @param value any - the new value for the setting 7225 * (omit if above is an object or to retrieve a value) 7226 */ 7227 _optionDatepicker: function(target, name, value) { 7228 var settings, date, minDate, maxDate, 7229 inst = this._getInst(target); 7230 7231 if (arguments.length === 2 && typeof name === "string") { 7232 return (name === "defaults" ? $.extend({}, $.datepicker._defaults) : 7233 (inst ? (name === "all" ? $.extend({}, inst.settings) : 7234 this._get(inst, name)) : null)); 7235 } 7236 7237 settings = name || {}; 7238 if (typeof name === "string") { 7239 settings = {}; 7240 settings[name] = value; 7241 } 7242 7243 if (inst) { 7244 if (this._curInst === inst) { 7245 this._hideDatepicker(); 7246 } 7247 7248 date = this._getDateDatepicker(target, true); 7249 minDate = this._getMinMaxDate(inst, "min"); 7250 maxDate = this._getMinMaxDate(inst, "max"); 7251 extendRemove(inst.settings, settings); 7252 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided 7253 if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) { 7254 inst.settings.minDate = this._formatDate(inst, minDate); 7255 } 7256 if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) { 7257 inst.settings.maxDate = this._formatDate(inst, maxDate); 7258 } 7259 if ( "disabled" in settings ) { 7260 if ( settings.disabled ) { 7261 this._disableDatepicker(target); 7262 } else { 7263 this._enableDatepicker(target); 7264 } 7265 } 7266 this._attachments($(target), inst); 7267 this._autoSize(inst); 7268 this._setDate(inst, date); 7269 this._updateAlternate(inst); 7270 this._updateDatepicker(inst); 7271 } 7272 }, 7273 7274 // change method deprecated 7275 _changeDatepicker: function(target, name, value) { 7276 this._optionDatepicker(target, name, value); 7277 }, 7278 7279 /* Redraw the date picker attached to an input field or division. 7280 * @param target element - the target input field or division or span 7281 */ 7282 _refreshDatepicker: function(target) { 7283 var inst = this._getInst(target); 7284 if (inst) { 7285 this._updateDatepicker(inst); 7286 } 7287 }, 7288 7289 /* Set the dates for a jQuery selection. 7290 * @param target element - the target input field or division or span 7291 * @param date Date - the new date 7292 */ 7293 _setDateDatepicker: function(target, date) { 7294 var inst = this._getInst(target); 7295 if (inst) { 7296 this._setDate(inst, date); 7297 this._updateDatepicker(inst); 7298 this._updateAlternate(inst); 7299 } 7300 }, 7301 7302 /* Get the date(s) for the first entry in a jQuery selection. 7303 * @param target element - the target input field or division or span 7304 * @param noDefault boolean - true if no default date is to be used 7305 * @return Date - the current date 7306 */ 7307 _getDateDatepicker: function(target, noDefault) { 7308 var inst = this._getInst(target); 7309 if (inst && !inst.inline) { 7310 this._setDateFromField(inst, noDefault); 7311 } 7312 return (inst ? this._getDate(inst) : null); 7313 }, 7314 7315 /* Handle keystrokes. */ 7316 _doKeyDown: function(event) { 7317 var onSelect, dateStr, sel, 7318 inst = $.datepicker._getInst(event.target), 7319 handled = true, 7320 isRTL = inst.dpDiv.is(".ui-datepicker-rtl"); 7321 7322 inst._keyEvent = true; 7323 if ($.datepicker._datepickerShowing) { 7324 switch (event.keyCode) { 7325 case 9: $.datepicker._hideDatepicker(); 7326 handled = false; 7327 break; // hide on tab out 7328 case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." + 7329 $.datepicker._currentClass + ")", inst.dpDiv); 7330 if (sel[0]) { 7331 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); 7332 } 7333 7334 onSelect = $.datepicker._get(inst, "onSelect"); 7335 if (onSelect) { 7336 dateStr = $.datepicker._formatDate(inst); 7337 7338 // trigger custom callback 7339 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); 7340 } else { 7341 $.datepicker._hideDatepicker(); 7342 } 7343 7344 return false; // don't submit the form 7345 case 27: $.datepicker._hideDatepicker(); 7346 break; // hide on escape 7347 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7348 -$.datepicker._get(inst, "stepBigMonths") : 7349 -$.datepicker._get(inst, "stepMonths")), "M"); 7350 break; // previous month/year on page up/+ ctrl 7351 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7352 +$.datepicker._get(inst, "stepBigMonths") : 7353 +$.datepicker._get(inst, "stepMonths")), "M"); 7354 break; // next month/year on page down/+ ctrl 7355 case 35: if (event.ctrlKey || event.metaKey) { 7356 $.datepicker._clearDate(event.target); 7357 } 7358 handled = event.ctrlKey || event.metaKey; 7359 break; // clear on ctrl or command +end 7360 case 36: if (event.ctrlKey || event.metaKey) { 7361 $.datepicker._gotoToday(event.target); 7362 } 7363 handled = event.ctrlKey || event.metaKey; 7364 break; // current on ctrl or command +home 7365 case 37: if (event.ctrlKey || event.metaKey) { 7366 $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D"); 7367 } 7368 handled = event.ctrlKey || event.metaKey; 7369 // -1 day on ctrl or command +left 7370 if (event.originalEvent.altKey) { 7371 $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7372 -$.datepicker._get(inst, "stepBigMonths") : 7373 -$.datepicker._get(inst, "stepMonths")), "M"); 7374 } 7375 // next month/year on alt +left on Mac 7376 break; 7377 case 38: if (event.ctrlKey || event.metaKey) { 7378 $.datepicker._adjustDate(event.target, -7, "D"); 7379 } 7380 handled = event.ctrlKey || event.metaKey; 7381 break; // -1 week on ctrl or command +up 7382 case 39: if (event.ctrlKey || event.metaKey) { 7383 $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D"); 7384 } 7385 handled = event.ctrlKey || event.metaKey; 7386 // +1 day on ctrl or command +right 7387 if (event.originalEvent.altKey) { 7388 $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7389 +$.datepicker._get(inst, "stepBigMonths") : 7390 +$.datepicker._get(inst, "stepMonths")), "M"); 7391 } 7392 // next month/year on alt +right 7393 break; 7394 case 40: if (event.ctrlKey || event.metaKey) { 7395 $.datepicker._adjustDate(event.target, +7, "D"); 7396 } 7397 handled = event.ctrlKey || event.metaKey; 7398 break; // +1 week on ctrl or command +down 7399 default: handled = false; 7400 } 7401 } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home 7402 $.datepicker._showDatepicker(this); 7403 } else { 7404 handled = false; 7405 } 7406 7407 if (handled) { 7408 event.preventDefault(); 7409 event.stopPropagation(); 7410 } 7411 }, 7412 7413 /* Filter entered characters - based on date format. */ 7414 _doKeyPress: function(event) { 7415 var chars, chr, 7416 inst = $.datepicker._getInst(event.target); 7417 7418 if ($.datepicker._get(inst, "constrainInput")) { 7419 chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat")); 7420 chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode); 7421 return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1); 7422 } 7423 }, 7424 7425 /* Synchronise manual entry and field/alternate field. */ 7426 _doKeyUp: function(event) { 7427 var date, 7428 inst = $.datepicker._getInst(event.target); 7429 7430 if (inst.input.val() !== inst.lastVal) { 7431 try { 7432 date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), 7433 (inst.input ? inst.input.val() : null), 7434 $.datepicker._getFormatConfig(inst)); 7435 7436 if (date) { // only if valid 7437 $.datepicker._setDateFromField(inst); 7438 $.datepicker._updateAlternate(inst); 7439 $.datepicker._updateDatepicker(inst); 7440 } 7441 } 7442 catch (err) { 7443 } 7444 } 7445 return true; 7446 }, 7447 7448 /* Pop-up the date picker for a given input field. 7449 * If false returned from beforeShow event handler do not show. 7450 * @param input element - the input field attached to the date picker or 7451 * event - if triggered by focus 7452 */ 7453 _showDatepicker: function(input) { 7454 input = input.target || input; 7455 if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger 7456 input = $("input", input.parentNode)[0]; 7457 } 7458 7459 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here 7460 return; 7461 } 7462 7463 var inst, beforeShow, beforeShowSettings, isFixed, 7464 offset, showAnim, duration; 7465 7466 inst = $.datepicker._getInst(input); 7467 if ($.datepicker._curInst && $.datepicker._curInst !== inst) { 7468 $.datepicker._curInst.dpDiv.stop(true, true); 7469 if ( inst && $.datepicker._datepickerShowing ) { 7470 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] ); 7471 } 7472 } 7473 7474 beforeShow = $.datepicker._get(inst, "beforeShow"); 7475 beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; 7476 if(beforeShowSettings === false){ 7477 return; 7478 } 7479 extendRemove(inst.settings, beforeShowSettings); 7480 7481 inst.lastVal = null; 7482 $.datepicker._lastInput = input; 7483 $.datepicker._setDateFromField(inst); 7484 7485 if ($.datepicker._inDialog) { // hide cursor 7486 input.value = ""; 7487 } 7488 if (!$.datepicker._pos) { // position below input 7489 $.datepicker._pos = $.datepicker._findPos(input); 7490 $.datepicker._pos[1] += input.offsetHeight; // add the height 7491 } 7492 7493 isFixed = false; 7494 $(input).parents().each(function() { 7495 isFixed |= $(this).css("position") === "fixed"; 7496 return !isFixed; 7497 }); 7498 7499 offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; 7500 $.datepicker._pos = null; 7501 //to avoid flashes on Firefox 7502 inst.dpDiv.empty(); 7503 // determine sizing offscreen 7504 inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"}); 7505 $.datepicker._updateDatepicker(inst); 7506 // fix width for dynamic number of date pickers 7507 // and adjust position before showing 7508 offset = $.datepicker._checkOffset(inst, offset, isFixed); 7509 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? 7510 "static" : (isFixed ? "fixed" : "absolute")), display: "none", 7511 left: offset.left + "px", top: offset.top + "px"}); 7512 7513 if (!inst.inline) { 7514 showAnim = $.datepicker._get(inst, "showAnim"); 7515 duration = $.datepicker._get(inst, "duration"); 7516 inst.dpDiv.zIndex($(input).zIndex()+1); 7517 $.datepicker._datepickerShowing = true; 7518 7519 if ( $.effects && $.effects.effect[ showAnim ] ) { 7520 inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration); 7521 } else { 7522 inst.dpDiv[showAnim || "show"](showAnim ? duration : null); 7523 } 7524 7525 if (
vendor: 1,611 bytes, lines 7525-7566
7525inst.input.is(":visible") && !inst.input.is(":disabled")) { 7526 inst.input.focus(); 7527 } 7528 $.datepicker._curInst = inst; 7529 } 7530 }, 7531 7532 /* Generate the date picker content. */ 7533 _updateDatepicker: function(inst) { 7534 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) 7535 instActive = inst; // for delegate hover events 7536 inst.dpDiv.empty().append(this._generateHTML(inst)); 7537 this._attachHandlers(inst); 7538 inst.dpDiv.find("." + this._dayOverClass + " a").mouseover(); 7539 7540 var origyearshtml, 7541 numMonths = this._getNumberOfMonths(inst), 7542 cols = numMonths[1], 7543 width = 17; 7544 7545 inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""); 7546 if (cols > 1) { 7547 inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em"); 7548 } 7549 inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") + 7550 "Class"]("ui-datepicker-multi"); 7551 inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") + 7552 "Class"]("ui-datepicker-rtl"); 7553 7554 // #6694 - don't focus the input if it's already focused 7555 // this breaks the change event in IE 7556 if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input && 7557 inst.input.is(":visible") && !inst.input.is(":disabled") && inst.input[0] !== document.activeElement) { 7558 inst.input.focus(); 7559 } 7560 7561 // deffered render of the years select (to avoid flashes on Firefox) 7562 if( inst.yearshtml ){ 7563 origyearshtml = inst.yearshtml; 7564 setTimeout(function(){ 7565 //assure that inst.yearshtml didn't change. 7566 if( origyearshtml === inst.yearshtml && inst.yearshtml ){
7567 inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml); 7568 } 7569 origyearshtml = inst.yearshtml = null; 7570 }, 0); 7571 } 7572 }, 7573 7574 /* Retrieve the size of left and top borders for an element. 7575 * @param elem (jQuery object) the element of interest 7576 * @return (number[2]) the left and top borders 7577 */ 7578 _getBorders: function(elem) { 7579 var convert = function(value) { 7580 return {thin: 1, medium: 2, thick: 3}[value] || value; 7581 }; 7582 return [parseFloat(convert(elem.css("border-left-width"))), 7583 parseFloat(convert(elem.css("border-top-width")))]
vendor: 23,574 bytes, lines 7583-8330
7583; 7584 }, 7585 7586 /* Check positioning to remain on screen. */ 7587 _checkOffset: function(inst, offset, isFixed) { 7588 var dpWidth = inst.dpDiv.outerWidth(), 7589 dpHeight = inst.dpDiv.outerHeight(), 7590 inputWidth = inst.input ? inst.input.outerWidth() : 0, 7591 inputHeight = inst.input ? inst.input.outerHeight() : 0, 7592 viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()), 7593 viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop()); 7594 7595 offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0); 7596 offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0; 7597 offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; 7598 7599 // now check if datepicker is showing outside window viewport - move to a better place if so. 7600 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? 7601 Math.abs(offset.left + dpWidth - viewWidth) : 0); 7602 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? 7603 Math.abs(dpHeight + inputHeight) : 0); 7604 7605 return offset; 7606 }, 7607 7608 /* Find an object's position on the screen. */ 7609 _findPos: function(obj) { 7610 var position, 7611 inst = this._getInst(obj), 7612 isRTL = this._get(inst, "isRTL"); 7613 7614 while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) { 7615 obj = obj[isRTL ? "previousSibling" : "nextSibling"]; 7616 } 7617 7618 position = $(obj).offset(); 7619 return [position.left, position.top]; 7620 }, 7621 7622 /* Hide the date picker from view. 7623 * @param input element - the input field attached to the date picker 7624 */ 7625 _hideDatepicker: function(input) { 7626 var showAnim, duration, postProcess, onClose, 7627 inst = this._curInst; 7628 7629 if (!inst || (input && inst !== $.data(input, PROP_NAME))) { 7630 return; 7631 } 7632 7633 if (this._datepickerShowing) { 7634 showAnim = this._get(inst, "showAnim"); 7635 duration = this._get(inst, "duration"); 7636 postProcess = function() { 7637 $.datepicker._tidyDialog(inst); 7638 }; 7639 7640 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed 7641 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) { 7642 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess); 7643 } else { 7644 inst.dpDiv[(showAnim === "slideDown" ? "slideUp" : 7645 (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess); 7646 } 7647 7648 if (!showAnim) { 7649 postProcess(); 7650 } 7651 this._datepickerShowing = false; 7652 7653 onClose = this._get(inst, "onClose"); 7654 if (onClose) { 7655 onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]); 7656 } 7657 7658 this._lastInput = null; 7659 if (this._inDialog) { 7660 this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" }); 7661 if ($.blockUI) { 7662 $.unblockUI(); 7663 $("body").append(this.dpDiv); 7664 } 7665 } 7666 this._inDialog = false; 7667 } 7668 }, 7669 7670 /* Tidy up after a dialog display. */ 7671 _tidyDialog: function(inst) { 7672 inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar"); 7673 }, 7674 7675 /* Close date picker if clicked elsewhere. */ 7676 _checkExternalClick: function(event) { 7677 if (!$.datepicker._curInst) { 7678 return; 7679 } 7680 7681 var $target = $(event.target), 7682 inst = $.datepicker._getInst($target[0]); 7683 7684 if ( ( ( $target[0].id !== $.datepicker._mainDivId && 7685 $target.parents("#" + $.datepicker._mainDivId).length === 0 && 7686 !$target.hasClass($.datepicker.markerClassName) && 7687 !$target.closest("." + $.datepicker._triggerClass).length && 7688 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) || 7689 ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) { 7690 $.datepicker._hideDatepicker(); 7691 } 7692 }, 7693 7694 /* Adjust one of the date sub-fields. */ 7695 _adjustDate: function(id, offset, period) { 7696 var target = $(id), 7697 inst = this._getInst(target[0]); 7698 7699 if (this._isDisabledDatepicker(target[0])) { 7700 return; 7701 } 7702 this._adjustInstDate(inst, offset + 7703 (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning 7704 period); 7705 this._updateDatepicker(inst); 7706 }, 7707 7708 /* Action for current link. */ 7709 _gotoToday: function(id) { 7710 var date, 7711 target = $(id), 7712 inst = this._getInst(target[0]); 7713 7714 if (this._get(inst, "gotoCurrent") && inst.currentDay) { 7715 inst.selectedDay = inst.currentDay; 7716 inst.drawMonth = inst.selectedMonth = inst.currentMonth; 7717 inst.drawYear = inst.selectedYear = inst.currentYear; 7718 } else { 7719 date = new Date(); 7720 inst.selectedDay = date.getDate(); 7721 inst.drawMonth = inst.selectedMonth = date.getMonth(); 7722 inst.drawYear = inst.selectedYear = date.getFullYear(); 7723 } 7724 this._notifyChange(inst); 7725 this._adjustDate(target); 7726 }, 7727 7728 /* Action for selecting a new month/year. */ 7729 _selectMonthYear: function(id, select, period) { 7730 var target = $(id), 7731 inst = this._getInst(target[0]); 7732 7733 inst["selected" + (period === "M" ? "Month" : "Year")] = 7734 inst["draw" + (period === "M" ? "Month" : "Year")] = 7735 parseInt(select.options[select.selectedIndex].value,10); 7736 7737 this._notifyChange(inst); 7738 this._adjustDate(target); 7739 }, 7740 7741 /* Action for selecting a day. */ 7742 _selectDay: function(id, month, year, td) { 7743 var inst, 7744 target = $(id); 7745 7746 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { 7747 return; 7748 } 7749 7750 inst = this._getInst(target[0]); 7751 inst.selectedDay = inst.currentDay = $("a", td).html(); 7752 inst.selectedMonth = inst.currentMonth = month; 7753 inst.selectedYear = inst.currentYear = year; 7754 this._selectDate(id, this._formatDate(inst, 7755 inst.currentDay, inst.currentMonth, inst.currentYear)); 7756 }, 7757 7758 /* Erase the input field and hide the date picker. */ 7759 _clearDate: function(id) { 7760 var target = $(id); 7761 this._selectDate(target, ""); 7762 }, 7763 7764 /* Update the input field with the selected date. */ 7765 _selectDate: function(id, dateStr) { 7766 var onSelect, 7767 target = $(id), 7768 inst = this._getInst(target[0]); 7769 7770 dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); 7771 if (inst.input) { 7772 inst.input.val(dateStr); 7773 } 7774 this._updateAlternate(inst); 7775 7776 onSelect = this._get(inst, "onSelect"); 7777 if (onSelect) { 7778 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback 7779 } else if (inst.input) { 7780 inst.input.trigger("change"); // fire the change event 7781 } 7782 7783 if (inst.inline){ 7784 this._updateDatepicker(inst); 7785 } else { 7786 this._hideDatepicker(); 7787 this._lastInput = inst.input[0]; 7788 if (typeof(inst.input[0]) !== "object") { 7789 inst.input.focus(); // restore focus 7790 } 7791 this._lastInput = null; 7792 } 7793 }, 7794 7795 /* Update any alternate field to synchronise with the main field. */ 7796 _updateAlternate: function(inst) { 7797 var altFormat, date, dateStr, 7798 altField = this._get(inst, "altField"); 7799 7800 if (altField) { // update alternate field too 7801 altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat"); 7802 date = this._getDate(inst); 7803 dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); 7804 $(altField).each(function() { $(this).val(dateStr); }); 7805 } 7806 }, 7807 7808 /* Set as beforeShowDay function to prevent selection of weekends. 7809 * @param date Date - the date to customise 7810 * @return [boolean, string] - is this date selectable?, what is its CSS class? 7811 */ 7812 noWeekends: function(date) { 7813 var day = date.getDay(); 7814 return [(day > 0 && day < 6), ""]; 7815 }, 7816 7817 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. 7818 * @param date Date - the date to get the week for 7819 * @return number - the number of the week within the year that contains this date 7820 */ 7821 iso8601Week: function(date) { 7822 var time, 7823 checkDate = new Date(date.getTime()); 7824 7825 // Find Thursday of this week starting on Monday 7826 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); 7827 7828 time = checkDate.getTime(); 7829 checkDate.setMonth(0); // Compare with Jan 1 7830 checkDate.setDate(1); 7831 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; 7832 }, 7833 7834 /* Parse a string value into a date object. 7835 * See formatDate below for the possible formats. 7836 * 7837 * @param format string - the expected format of the date 7838 * @param value string - the date in the above format 7839 * @param settings Object - attributes include: 7840 * shortYearCutoff number - the cutoff year for determining the century (optional) 7841 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 7842 * dayNames string[7] - names of the days from Sunday (optional) 7843 * monthNamesShort string[12] - abbreviated names of the months (optional) 7844 * monthNames string[12] - names of the months (optional) 7845 * @return Date - the extracted date value or null if value is blank 7846 */ 7847 parseDate: function (format, value, settings) { 7848 if (format == null || value == null) { 7849 throw "Invalid arguments"; 7850 } 7851 7852 value = (typeof value === "object" ? value.toString() : value + ""); 7853 if (value === "") { 7854 return null; 7855 } 7856 7857 var iFormat, dim, extra, 7858 iValue = 0, 7859 shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff, 7860 shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp : 7861 new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)), 7862 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, 7863 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, 7864 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, 7865 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, 7866 year = -1, 7867 month = -1, 7868 day = -1, 7869 doy = -1, 7870 literal = false, 7871 date, 7872 // Check whether a format character is doubled 7873 lookAhead = function(match) { 7874 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 7875 if (matches) { 7876 iFormat++; 7877 } 7878 return matches; 7879 }, 7880 // Extract a number from the string value 7881 getNumber = function(match) { 7882 var isDoubled = lookAhead(match), 7883 size = (match === "@" ? 14 : (match === "!" ? 20 : 7884 (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))), 7885 digits = new RegExp("^\\d{1," + size + "}"), 7886 num = value.substring(iValue).match(digits); 7887 if (!num) { 7888 throw "Missing number at position " + iValue; 7889 } 7890 iValue += num[0].length; 7891 return parseInt(num[0], 10); 7892 }, 7893 // Extract a name from the string value and convert to an index 7894 getName = function(match, shortNames, longNames) { 7895 var index = -1, 7896 names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { 7897 return [ [k, v] ]; 7898 }).sort(function (a, b) { 7899 return -(a[1].length - b[1].length); 7900 }); 7901 7902 $.each(names, function (i, pair) { 7903 var name = pair[1]; 7904 if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) { 7905 index = pair[0]; 7906 iValue += name.length; 7907 return false; 7908 } 7909 }); 7910 if (index !== -1) { 7911 return index + 1; 7912 } else { 7913 throw "Unknown name at position " + iValue; 7914 } 7915 }, 7916 // Confirm that a literal character matches the string value 7917 checkLiteral = function() { 7918 if (value.charAt(iValue) !== format.charAt(iFormat)) { 7919 throw "Unexpected literal at position " + iValue; 7920 } 7921 iValue++; 7922 }; 7923 7924 for (iFormat = 0; iFormat < format.length; iFormat++) { 7925 if (literal) { 7926 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 7927 literal = false; 7928 } else { 7929 checkLiteral(); 7930 } 7931 } else { 7932 switch (format.charAt(iFormat)) { 7933 case "d": 7934 day = getNumber("d"); 7935 break; 7936 case "D": 7937 getName("D", dayNamesShort, dayNames); 7938 break; 7939 case "o": 7940 doy = getNumber("o"); 7941 break; 7942 case "m": 7943 month = getNumber("m"); 7944 break; 7945 case "M": 7946 month = getName("M", monthNamesShort, monthNames); 7947 break; 7948 case "y": 7949 year = getNumber("y"); 7950 break; 7951 case "@": 7952 date = new Date(getNumber("@")); 7953 year = date.getFullYear(); 7954 month = date.getMonth() + 1; 7955 day = date.getDate(); 7956 break; 7957 case "!": 7958 date = new Date((getNumber("!") - this._ticksTo1970) / 10000); 7959 year = date.getFullYear(); 7960 month = date.getMonth() + 1; 7961 day = date.getDate(); 7962 break; 7963 case "'": 7964 if (lookAhead("'")){ 7965 checkLiteral(); 7966 } else { 7967 literal = true; 7968 } 7969 break; 7970 default: 7971 checkLiteral(); 7972 } 7973 } 7974 } 7975 7976 if (iValue < value.length){ 7977 extra = value.substr(iValue); 7978 if (!/^\s+/.test(extra)) { 7979 throw "Extra/unparsed characters found in date: " + extra; 7980 } 7981 } 7982 7983 if (year === -1) { 7984 year = new Date().getFullYear(); 7985 } else if (year < 100) { 7986 year += new Date().getFullYear() - new Date().getFullYear() % 100 + 7987 (year <= shortYearCutoff ? 0 : -100); 7988 } 7989 7990 if (doy > -1) { 7991 month = 1; 7992 day = doy; 7993 do { 7994 dim = this._getDaysInMonth(year, month - 1); 7995 if (day <= dim) { 7996 break; 7997 } 7998 month++; 7999 day -= dim; 8000 } while (true); 8001 } 8002 8003 date = this._daylightSavingAdjust(new Date(year, month - 1, day)); 8004 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) { 8005 throw "Invalid date"; // E.g. 31/02/00 8006 } 8007 return date; 8008 }, 8009 8010 /* Standard date formats. */ 8011 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601) 8012 COOKIE: "D, dd M yy", 8013 ISO_8601: "yy-mm-dd", 8014 RFC_822: "D, d M y", 8015 RFC_850: "DD, dd-M-y", 8016 RFC_1036: "D, d M y", 8017 RFC_1123: "D, d M yy", 8018 RFC_2822: "D, d M yy", 8019 RSS: "D, d M y", // RFC 822 8020 TICKS: "!", 8021 TIMESTAMP: "@", 8022 W3C: "yy-mm-dd", // ISO 8601 8023 8024 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + 8025 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), 8026 8027 /* Format a date object into a string value. 8028 * The format can be combinations of the following: 8029 * d - day of month (no leading zero) 8030 * dd - day of month (two digit) 8031 * o - day of year (no leading zeros) 8032 * oo - day of year (three digit) 8033 * D - day name short 8034 * DD - day name long 8035 * m - month of year (no leading zero) 8036 * mm - month of year (two digit) 8037 * M - month name short 8038 * MM - month name long 8039 * y - year (two digit) 8040 * yy - year (four digit) 8041 * @ - Unix timestamp (ms since 01/01/1970) 8042 * ! - Windows ticks (100ns since 01/01/0001) 8043 * "..." - literal text 8044 * '' - single quote 8045 * 8046 * @param format string - the desired format of the date 8047 * @param date Date - the date value to format 8048 * @param settings Object - attributes include: 8049 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 8050 * dayNames string[7] - names of the days from Sunday (optional) 8051 * monthNamesShort string[12] - abbreviated names of the months (optional) 8052 * monthNames string[12] - names of the months (optional) 8053 * @return string - the date in the above format 8054 */ 8055 formatDate: function (format, date, settings) { 8056 if (!date) { 8057 return ""; 8058 } 8059 8060 var iFormat, 8061 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, 8062 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, 8063 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, 8064 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, 8065 // Check whether a format character is doubled 8066 lookAhead = function(match) { 8067 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 8068 if (matches) { 8069 iFormat++; 8070 } 8071 return matches; 8072 }, 8073 // Format a number, with leading zero if necessary 8074 formatNumber = function(match, value, len) { 8075 var num = "" + value; 8076 if (lookAhead(match)) { 8077 while (num.length < len) { 8078 num = "0" + num; 8079 } 8080 } 8081 return num; 8082 }, 8083 // Format a name, short or long as requested 8084 formatName = function(match, value, shortNames, longNames) { 8085 return (lookAhead(match) ? longNames[value] : shortNames[value]); 8086 }, 8087 output = "", 8088 literal = false; 8089 8090 if (date) { 8091 for (iFormat = 0; iFormat < format.length; iFormat++) { 8092 if (literal) { 8093 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 8094 literal = false; 8095 } else { 8096 output += format.charAt(iFormat); 8097 } 8098 } else { 8099 switch (format.charAt(iFormat)) { 8100 case "d": 8101 output += formatNumber("d", date.getDate(), 2); 8102 break; 8103 case "D": 8104 output += formatName("D", date.getDay(), dayNamesShort, dayNames); 8105 break; 8106 case "o": 8107 output += formatNumber("o", 8108 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); 8109 break; 8110 case "m": 8111 output += formatNumber("m", date.getMonth() + 1, 2); 8112 break; 8113 case "M": 8114 output += formatName("M", date.getMonth(), monthNamesShort, monthNames); 8115 break; 8116 case "y": 8117 output += (lookAhead("y") ? date.getFullYear() : 8118 (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100); 8119 break; 8120 case "@": 8121 output += date.getTime(); 8122 break; 8123 case "!": 8124 output += date.getTime() * 10000 + this._ticksTo1970; 8125 break; 8126 case "'": 8127 if (lookAhead("'")) { 8128 output += "'"; 8129 } else { 8130 literal = true; 8131 } 8132 break; 8133 default: 8134 output += format.charAt(iFormat); 8135 } 8136 } 8137 } 8138 } 8139 return output; 8140 }, 8141 8142 /* Extract all possible characters from the date format. */ 8143 _possibleChars: function (format) { 8144 var iFormat, 8145 chars = "", 8146 literal = false, 8147 // Check whether a format character is doubled 8148 lookAhead = function(match) { 8149 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 8150 if (matches) { 8151 iFormat++; 8152 } 8153 return matches; 8154 }; 8155 8156 for (iFormat = 0; iFormat < format.length; iFormat++) { 8157 if (literal) { 8158 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 8159 literal = false; 8160 } else { 8161 chars += format.charAt(iFormat); 8162 } 8163 } else { 8164 switch (format.charAt(iFormat)) { 8165 case "d": case "m": case "y": case "@": 8166 chars += "0123456789"; 8167 break; 8168 case "D": case "M": 8169 return null; // Accept anything 8170 case "'": 8171 if (lookAhead("'")) { 8172 chars += "'"; 8173 } else { 8174 literal = true; 8175 } 8176 break; 8177 default: 8178 chars += format.charAt(iFormat); 8179 } 8180 } 8181 } 8182 return chars; 8183 }, 8184 8185 /* Get a setting value, defaulting if necessary. */ 8186 _get: function(inst, name) { 8187 return inst.settings[name] !== undefined ? 8188 inst.settings[name] : this._defaults[name]; 8189 }, 8190 8191 /* Parse existing date and initialise date picker. */ 8192 _setDateFromField: function(inst, noDefault) { 8193 if (inst.input.val() === inst.lastVal) { 8194 return; 8195 } 8196 8197 var dateFormat = this._get(inst, "dateFormat"), 8198 dates = inst.lastVal = inst.input ? inst.input.val() : null, 8199 defaultDate = this._getDefaultDate(inst), 8200 date = defaultDate, 8201 settings = this._getFormatConfig(inst); 8202 8203 try { 8204 date = this.parseDate(dateFormat, dates, settings) || defaultDate; 8205 } catch (event) { 8206 dates = (noDefault ? "" : dates); 8207 } 8208 inst.selectedDay = date.getDate(); 8209 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8210 inst.drawYear = inst.selectedYear = date.getFullYear(); 8211 inst.currentDay = (dates ? date.getDate() : 0); 8212 inst.currentMonth = (dates ? date.getMonth() : 0); 8213 inst.currentYear = (dates ? date.getFullYear() : 0); 8214 this._adjustInstDate(inst); 8215 }, 8216 8217 /* Retrieve the default date shown on opening. */ 8218 _getDefaultDate: function(inst) { 8219 return this._restrictMinMax(inst, 8220 this._determineDate(inst, this._get(inst, "defaultDate"), new Date())); 8221 }, 8222 8223 /* A date may be specified as an exact value or a relative one. */ 8224 _determineDate: function(inst, date, defaultDate) { 8225 var offsetNumeric = function(offset) { 8226 var date = new Date(); 8227 date.setDate(date.getDate() + offset); 8228 return date; 8229 }, 8230 offsetString = function(offset) { 8231 try { 8232 return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), 8233 offset, $.datepicker._getFormatConfig(inst)); 8234 } 8235 catch (e) { 8236 // Ignore 8237 } 8238 8239 var date = (offset.toLowerCase().match(/^c/) ? 8240 $.datepicker._getDate(inst) : null) || new Date(), 8241 year = date.getFullYear(), 8242 month = date.getMonth(), 8243 day = date.getDate(), 8244 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, 8245 matches = pattern.exec(offset); 8246 8247 while (matches) { 8248 switch (matches[2] || "d") { 8249 case "d" : case "D" : 8250 day += parseInt(matches[1],10); break; 8251 case "w" : case "W" : 8252 day += parseInt(matches[1],10) * 7; break; 8253 case "m" : case "M" : 8254 month += parseInt(matches[1],10); 8255 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 8256 break; 8257 case "y": case "Y" : 8258 year += parseInt(matches[1],10); 8259 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 8260 break; 8261 } 8262 matches = pattern.exec(offset); 8263 } 8264 return new Date(year, month, day); 8265 }, 8266 newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) : 8267 (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); 8268 8269 newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate); 8270 if (newDate) { 8271 newDate.setHours(0); 8272 newDate.setMinutes(0); 8273 newDate.setSeconds(0); 8274 newDate.setMilliseconds(0); 8275 } 8276 return this._daylightSavingAdjust(newDate); 8277 }, 8278 8279 /* Handle switch to/from daylight saving. 8280 * Hours may be non-zero on daylight saving cut-over: 8281 * > 12 when midnight changeover, but then cannot generate 8282 * midnight datetime, so jump to 1AM, otherwise reset. 8283 * @param date (Date) the date to check 8284 * @return (Date) the corrected date 8285 */ 8286 _daylightSavingAdjust: function(date) { 8287 if (!date) { 8288 return null; 8289 } 8290 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); 8291 return date; 8292 }, 8293 8294 /* Set the date(s) directly. */ 8295 _setDate: function(inst, date, noChange) { 8296 var clear = !date, 8297 origMonth = inst.selectedMonth, 8298 origYear = inst.selectedYear, 8299 newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); 8300 8301 inst.selectedDay = inst.currentDay = newDate.getDate(); 8302 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); 8303 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); 8304 if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) { 8305 this._notifyChange(inst); 8306 } 8307 this._adjustInstDate(inst); 8308 if (inst.input) { 8309 inst.input.val(clear ? "" : this._formatDate(inst)); 8310 } 8311 }, 8312 8313 /* Retrieve the date(s) directly. */ 8314 _getDate: function(inst) { 8315 var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null : 8316 this._daylightSavingAdjust(new Date( 8317 inst.currentYear, inst.currentMonth, inst.currentDay))); 8318 return startDate; 8319 }, 8320 8321 /* Attach the onxxx handlers. These are declared statically so 8322 * they work with static code transformers like Caja. 8323 */ 8324 _attachHandlers: function(inst) { 8325 var stepMonths = this._get(inst, "stepMonths"), 8326 id = "#" + inst.id.replace( /\\\\/g, "\\" ); 8327 inst.dpDiv.find("[data-handler]").map(function () { 8328 var handler = { 8329 prev: function () { 8330
8330window["DP_jQuery_" + dpuuid].datepicker._adjustDate(id, -stepMonths, "M"); 8331 }, 8332 next: function () { 8333 window["DP_jQuery_" + dpuuid].datepicker._adjustDate(id, +stepMonths, "M"); 8334 }, 8335 hide: function () { 8336 window["DP_jQuery_" + dpuuid].datepicker._hideDatepicker(); 8337 }, 8338 today: function () { 8339 window["DP_jQuery_" + dpuuid].datepicker._gotoToday(id); 8340 }, 8341 selectDay: function () { 8342 window["DP_jQuery_" + dpuuid].datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this); 8343 return false; 8344 }, 8345 selectMonth: function () { 8346 window["DP_jQuery_" + dpuuid].datepicker._selectMonthYear(id, this, "M"); 8347 return false; 8348 }, 8349 selectYear: function () { 8350 window["DP_jQuery_" + dpuuid]
vendor: 20,874 bytes, lines 8350-8813
8350.datepicker._selectMonthYear(id, this, "Y"); 8351 return false; 8352 } 8353 }; 8354 $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]); 8355 }); 8356 }, 8357 8358 /* Generate the HTML for the current state of the date picker. */ 8359 _generateHTML: function(inst) { 8360 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate, 8361 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin, 8362 monthNames, monthNamesShort, beforeShowDay, showOtherMonths, 8363 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate, 8364 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows, 8365 printDate, dRow, tbody, daySettings, otherMonth, unselectable, 8366 tempDate = new Date(), 8367 today = this._daylightSavingAdjust( 8368 new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time 8369 isRTL = this._get(inst, "isRTL"), 8370 showButtonPanel = this._get(inst, "showButtonPanel"), 8371 hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"), 8372 navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"), 8373 numMonths = this._getNumberOfMonths(inst), 8374 showCurrentAtPos = this._get(inst, "showCurrentAtPos"), 8375 stepMonths = this._get(inst, "stepMonths"), 8376 isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1), 8377 currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : 8378 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))), 8379 minDate = this._getMinMaxDate(inst, "min"), 8380 maxDate = this._getMinMaxDate(inst, "max"), 8381 drawMonth = inst.drawMonth - showCurrentAtPos, 8382 drawYear = inst.drawYear; 8383 8384 if (drawMonth < 0) { 8385 drawMonth += 12; 8386 drawYear--; 8387 } 8388 if (maxDate) { 8389 maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), 8390 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); 8391 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); 8392 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { 8393 drawMonth--; 8394 if (drawMonth < 0) { 8395 drawMonth = 11; 8396 drawYear--; 8397 } 8398 } 8399 } 8400 inst.drawMonth = drawMonth; 8401 inst.drawYear = drawYear; 8402 8403 prevText = this._get(inst, "prevText"); 8404 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, 8405 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), 8406 this._getFormatConfig(inst))); 8407 8408 prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? 8409 "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" + 8410 " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" : 8411 (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>")); 8412 8413 nextText = this._get(inst, "nextText"); 8414 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, 8415 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), 8416 this._getFormatConfig(inst))); 8417 8418 next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? 8419 "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" + 8420 " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" : 8421 (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>")); 8422 8423 currentText = this._get(inst, "currentText"); 8424 gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today); 8425 currentText = (!navigationAsDateFormat ? currentText : 8426 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); 8427 8428 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'>" + 8429 this._get(inst, "closeText") + "</button>" : ""); 8430 8431 buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") + 8432 (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'" + 8433 ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : ""; 8434 8435 firstDay = parseInt(this._get(inst, "firstDay"),10); 8436 firstDay = (isNaN(firstDay) ? 0 : firstDay); 8437 8438 showWeek = this._get(inst, "showWeek"); 8439 dayNames = this._get(inst, "dayNames"); 8440 dayNamesMin = this._get(inst, "dayNamesMin"); 8441 monthNames = this._get(inst, "monthNames"); 8442 monthNamesShort = this._get(inst, "monthNamesShort"); 8443 beforeShowDay = this._get(inst, "beforeShowDay"); 8444 showOtherMonths = this._get(inst, "showOtherMonths"); 8445 selectOtherMonths = this._get(inst, "selectOtherMonths"); 8446 defaultDate = this._getDefaultDate(inst); 8447 html = ""; 8448 dow; 8449 for (row = 0; row < numMonths[0]; row++) { 8450 group = ""; 8451 this.maxRows = 4; 8452 for (col = 0; col < numMonths[1]; col++) { 8453 selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); 8454 cornerClass = " ui-corner-all"; 8455 calender = ""; 8456 if (isMultiMonth) { 8457 calender += "<div class='ui-datepicker-group"; 8458 if (numMonths[1] > 1) { 8459 switch (col) { 8460 case 0: calender += " ui-datepicker-group-first"; 8461 cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break; 8462 case numMonths[1]-1: calender += " ui-datepicker-group-last"; 8463 cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break; 8464 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break; 8465 } 8466 } 8467 calender += "'>"; 8468 } 8469 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" + 8470 (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") + 8471 (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") + 8472 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, 8473 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers 8474 "</div><table class='ui-datepicker-calendar'><thead>" + 8475 "<tr>"; 8476 thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : ""); 8477 for (dow = 0; dow < 7; dow++) { // days of the week 8478 day = (dow + firstDay) % 7; 8479 thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" + 8480 "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>"; 8481 } 8482 calender += thead + "</tr></thead><tbody>"; 8483 daysInMonth = this._getDaysInMonth(drawYear, drawMonth); 8484 if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) { 8485 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); 8486 } 8487 leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; 8488 curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate 8489 numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) 8490 this.maxRows = numRows; 8491 printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); 8492 for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows 8493 calender += "<tr>"; 8494 tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" + 8495 this._get(inst, "calculateWeek")(printDate) + "</td>"); 8496 for (dow = 0; dow < 7; dow++) { // create date picker days 8497 daySettings = (beforeShowDay ? 8498 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]); 8499 otherMonth = (printDate.getMonth() !== drawMonth); 8500 unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || 8501 (minDate && printDate < minDate) || (maxDate && printDate > maxDate); 8502 tbody += "<td class='" + 8503 ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends 8504 (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months 8505 ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key 8506 (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ? 8507 // or defaultDate is current printedDate and defaultDate is selectedDate 8508 " " + this._dayOverClass : "") + // highlight selected day 8509 (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days 8510 (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates 8511 (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day 8512 (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different) 8513 ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "'") + "'" : "") + // cell title 8514 (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions 8515 (otherMonth && !showOtherMonths ? " " : // display for other months 8516 (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" + 8517 (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") + 8518 (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day 8519 (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months 8520 "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date 8521 printDate.setDate(printDate.getDate() + 1); 8522 printDate = this._daylightSavingAdjust(printDate); 8523 } 8524 calender += tbody + "</tr>"; 8525 } 8526 drawMonth++; 8527 if (drawMonth > 11) { 8528 drawMonth = 0; 8529 drawYear++; 8530 } 8531 calender += "</tbody></table>" + (isMultiMonth ? "</div>" + 8532 ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : ""); 8533 group += calender; 8534 } 8535 html += group; 8536 } 8537 html += buttonPanel; 8538 inst._keyEvent = false; 8539 return html; 8540 }, 8541 8542 /* Generate the month and year header. */ 8543 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, 8544 secondary, monthNames, monthNamesShort) { 8545 8546 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear, 8547 changeMonth = this._get(inst, "changeMonth"), 8548 changeYear = this._get(inst, "changeYear"), 8549 showMonthAfterYear = this._get(inst, "showMonthAfterYear"), 8550 html = "<div class='ui-datepicker-title'>", 8551 monthHtml = ""; 8552 8553 // month selection 8554 if (secondary || !changeMonth) { 8555 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>"; 8556 } else { 8557 inMinYear = (minDate && minDate.getFullYear() === drawYear); 8558 inMaxYear = (maxDate && maxDate.getFullYear() === drawYear); 8559 monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>"; 8560 for ( month = 0; month < 12; month++) { 8561 if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) { 8562 monthHtml += "<option value='" + month + "'" + 8563 (month === drawMonth ? " selected='selected'" : "") + 8564 ">" + monthNamesShort[month] + "</option>"; 8565 } 8566 } 8567 monthHtml += "</select>"; 8568 } 8569 8570 if (!showMonthAfterYear) { 8571 html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : ""); 8572 } 8573 8574 // year selection 8575 if ( !inst.yearshtml ) { 8576 inst.yearshtml = ""; 8577 if (secondary || !changeYear) { 8578 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>"; 8579 } else { 8580 // determine range of years to display 8581 years = this._get(inst, "yearRange").split(":"); 8582 thisYear = new Date().getFullYear(); 8583 determineYear = function(value) { 8584 var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) : 8585 (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) : 8586 parseInt(value, 10))); 8587 return (isNaN(year) ? thisYear : year); 8588 }; 8589 year = determineYear(years[0]); 8590 endYear = Math.max(year, determineYear(years[1] || "")); 8591 year = (minDate ? Math.max(year, minDate.getFullYear()) : year); 8592 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); 8593 inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>"; 8594 for (; year <= endYear; year++) { 8595 inst.yearshtml += "<option value='" + year + "'" + 8596 (year === drawYear ? " selected='selected'" : "") + 8597 ">" + year + "</option>"; 8598 } 8599 inst.yearshtml += "</select>"; 8600 8601 html += inst.yearshtml; 8602 inst.yearshtml = null; 8603 } 8604 } 8605 8606 html += this._get(inst, "yearSuffix"); 8607 if (showMonthAfterYear) { 8608 html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml; 8609 } 8610 html += "</div>"; // Close datepicker_header 8611 return html; 8612 }, 8613 8614 /* Adjust one of the date sub-fields. */ 8615 _adjustInstDate: function(inst, offset, period) { 8616 var year = inst.drawYear + (period === "Y" ? offset : 0), 8617 month = inst.drawMonth + (period === "M" ? offset : 0), 8618 day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0), 8619 date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day))); 8620 8621 inst.selectedDay = date.getDate(); 8622 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8623 inst.drawYear = inst.selectedYear = date.getFullYear(); 8624 if (period === "M" || period === "Y") { 8625 this._notifyChange(inst); 8626 } 8627 }, 8628 8629 /* Ensure a date is within any min/max bounds. */ 8630 _restrictMinMax: function(inst, date) { 8631 var minDate = this._getMinMaxDate(inst, "min"), 8632 maxDate = this._getMinMaxDate(inst, "max"), 8633 newDate = (minDate && date < minDate ? minDate : date); 8634 return (maxDate && newDate > maxDate ? maxDate : newDate); 8635 }, 8636 8637 /* Notify change of month/year. */ 8638 _notifyChange: function(inst) { 8639 var onChange = this._get(inst, "onChangeMonthYear"); 8640 if (onChange) { 8641 onChange.apply((inst.input ? inst.input[0] : null), 8642 [inst.selectedYear, inst.selectedMonth + 1, inst]); 8643 } 8644 }, 8645 8646 /* Determine the number of months to show. */ 8647 _getNumberOfMonths: function(inst) { 8648 var numMonths = this._get(inst, "numberOfMonths"); 8649 return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths)); 8650 }, 8651 8652 /* Determine the current maximum date - ensure no time components are set. */ 8653 _getMinMaxDate: function(inst, minMax) { 8654 return this._determineDate(inst, this._get(inst, minMax + "Date"), null); 8655 }, 8656 8657 /* Find the number of days in a given month. */ 8658 _getDaysInMonth: function(year, month) { 8659 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); 8660 }, 8661 8662 /* Find the day of the week of the first of a month. */ 8663 _getFirstDayOfMonth: function(year, month) { 8664 return new Date(year, month, 1).getDay(); 8665 }, 8666 8667 /* Determines if we should allow a "next/prev" month display change. */ 8668 _canAdjustMonth: function(inst, offset, curYear, curMonth) { 8669 var numMonths = this._getNumberOfMonths(inst), 8670 date = this._daylightSavingAdjust(new Date(curYear, 8671 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); 8672 8673 if (offset < 0) { 8674 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); 8675 } 8676 return this._isInRange(inst, date); 8677 }, 8678 8679 /* Is the given date in the accepted range? */ 8680 _isInRange: function(inst, date) { 8681 var yearSplit, currentYear, 8682 minDate = this._getMinMaxDate(inst, "min"), 8683 maxDate = this._getMinMaxDate(inst, "max"), 8684 minYear = null, 8685 maxYear = null, 8686 years = this._get(inst, "yearRange"); 8687 if (years){ 8688 yearSplit = years.split(":"); 8689 currentYear = new Date().getFullYear(); 8690 minYear = parseInt(yearSplit[0], 10); 8691 maxYear = parseInt(yearSplit[1], 10); 8692 if ( yearSplit[0].match(/[+\-].*/) ) { 8693 minYear += currentYear; 8694 } 8695 if ( yearSplit[1].match(/[+\-].*/) ) { 8696 maxYear += currentYear; 8697 } 8698 } 8699 8700 return ((!minDate || date.getTime() >= minDate.getTime()) && 8701 (!maxDate || date.getTime() <= maxDate.getTime()) && 8702 (!minYear || date.getFullYear() >= minYear) && 8703 (!maxYear || date.getFullYear() <= maxYear)); 8704 }, 8705 8706 /* Provide the configuration settings for formatting/parsing. */ 8707 _getFormatConfig: function(inst) { 8708 var shortYearCutoff = this._get(inst, "shortYearCutoff"); 8709 shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff : 8710 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); 8711 return {shortYearCutoff: shortYearCutoff, 8712 dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"), 8713 monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")}; 8714 }, 8715 8716 /* Format the given date for display. */ 8717 _formatDate: function(inst, day, month, year) { 8718 if (!day) { 8719 inst.currentDay = inst.selectedDay; 8720 inst.currentMonth = inst.selectedMonth; 8721 inst.currentYear = inst.selectedYear; 8722 } 8723 var date = (day ? (typeof day === "object" ? day : 8724 this._daylightSavingAdjust(new Date(year, month, day))) : 8725 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); 8726 return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst)); 8727 } 8728}); 8729 8730/* 8731 * Bind hover events for datepicker elements. 8732 * Done via delegate so the binding only occurs once in the lifetime of the parent div. 8733 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. 8734 */ 8735function bindHover(dpDiv) { 8736 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a"; 8737 return dpDiv.delegate(selector, "mouseout", function() { 8738 $(this).removeClass("ui-state-hover"); 8739 if (this.className.indexOf("ui-datepicker-prev") !== -1) { 8740 $(this).removeClass("ui-datepicker-prev-hover"); 8741 } 8742 if (this.className.indexOf("ui-datepicker-next") !== -1) { 8743 $(this).removeClass("ui-datepicker-next-hover"); 8744 } 8745 }) 8746 .delegate(selector, "mouseover", function(){ 8747 if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) { 8748 $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); 8749 $(this).addClass("ui-state-hover"); 8750 if (this.className.indexOf("ui-datepicker-prev") !== -1) { 8751 $(this).addClass("ui-datepicker-prev-hover"); 8752 } 8753 if (this.className.indexOf("ui-datepicker-next") !== -1) { 8754 $(this).addClass("ui-datepicker-next-hover"); 8755 } 8756 } 8757 }); 8758} 8759 8760/* jQuery extend now ignores nulls! */ 8761function extendRemove(target, props) { 8762 $.extend(target, props); 8763 for (var name in props) { 8764 if (props[name] == null) { 8765 target[name] = props[name]; 8766 } 8767 } 8768 return target; 8769} 8770 8771/* Invoke the datepicker functionality. 8772 @param options string - a command, optionally followed by additional parameters or 8773 Object - settings for attaching new datepicker functionality 8774 @return jQuery object */ 8775$.fn.datepicker = function(options){ 8776 8777 /* Verify an empty collection wasn't passed - Fixes #6976 */ 8778 if ( !this.length ) { 8779 return this; 8780 } 8781 8782 /* Initialise the date picker. */ 8783 if (!$.datepicker.initialized) { 8784 $(document).mousedown($.datepicker._checkExternalClick); 8785 $.datepicker.initialized = true; 8786 } 8787 8788 /* Append datepicker main container to body if not exist. */ 8789 if ($("#"+$.datepicker._mainDivId).length === 0) { 8790 $("body").append($.datepicker.dpDiv); 8791 } 8792 8793 var otherArgs = Array.prototype.slice.call(arguments, 1); 8794 if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) { 8795 return $.datepicker["_" + options + "Datepicker"]. 8796 apply($.datepicker, [this[0]].concat(otherArgs)); 8797 } 8798 if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") { 8799 return $.datepicker["_" + options + "Datepicker"]. 8800 apply($.datepicker, [this[0]].concat(otherArgs)); 8801 } 8802 return this.each(function() { 8803 typeof options === "string" ? 8804 $.datepicker["_" + options + "Datepicker"]. 8805 apply($.datepicker, [this].concat(otherArgs)) : 8806 $.datepicker._attachDatepicker(this, options); 8807 }); 8808}; 8809 8810$.datepicker = new Datepicker(); // singleton instance 8811$.datepicker.initialized = false; 8812$.datepicker.uuid = new Date().getTime(); 8813$.datepicker.version = "1.10.
vendor: 17,808 bytes, lines 8813-9529
88132"; 8814 8815// Workaround for #4055 8816// Add another global to avoid noConflict issues with inline event handlers 8817window["DP_jQuery_" + dpuuid] = $; 8818 8819})(jQuery); 8820(function( $, undefined ) { 8821 8822var sizeRelatedOptions = { 8823 buttons: true, 8824 height: true, 8825 maxHeight: true, 8826 maxWidth: true, 8827 minHeight: true, 8828 minWidth: true, 8829 width: true 8830 }, 8831 resizableRelatedOptions = { 8832 maxHeight: true, 8833 maxWidth: true, 8834 minHeight: true, 8835 minWidth: true 8836 }; 8837 8838$.widget( "ui.dialog", { 8839 version: "1.10.2", 8840 options: { 8841 appendTo: "body", 8842 autoOpen: true, 8843 buttons: [], 8844 closeOnEscape: true, 8845 closeText: "close", 8846 dialogClass: "", 8847 draggable: true, 8848 hide: null, 8849 height: "auto", 8850 maxHeight: null, 8851 maxWidth: null, 8852 minHeight: 150, 8853 minWidth: 150, 8854 modal: false, 8855 position: { 8856 my: "center", 8857 at: "center", 8858 of: window, 8859 collision: "fit", 8860 // Ensure the titlebar is always visible 8861 using: function( pos ) { 8862 var topOffset = $( this ).css( pos ).offset().top; 8863 if ( topOffset < 0 ) { 8864 $( this ).css( "top", pos.top - topOffset ); 8865 } 8866 } 8867 }, 8868 resizable: true, 8869 show: null, 8870 title: null, 8871 width: 300, 8872 8873 // callbacks 8874 beforeClose: null, 8875 close: null, 8876 drag: null, 8877 dragStart: null, 8878 dragStop: null, 8879 focus: null, 8880 open: null, 8881 resize: null, 8882 resizeStart: null, 8883 resizeStop: null 8884 }, 8885 8886 _create: function() { 8887 this.originalCss = { 8888 display: this.element[0].style.display, 8889 width: this.element[0].style.width, 8890 minHeight: this.element[0].style.minHeight, 8891 maxHeight: this.element[0].style.maxHeight, 8892 height: this.element[0].style.height 8893 }; 8894 this.originalPosition = { 8895 parent: this.element.parent(), 8896 index: this.element.parent().children().index( this.element ) 8897 }; 8898 this.originalTitle = this.element.attr("title"); 8899 this.options.title = this.options.title || this.originalTitle; 8900 8901 this._createWrapper(); 8902 8903 this.element 8904 .show() 8905 .removeAttr("title") 8906 .addClass("ui-dialog-content ui-widget-content") 8907 .appendTo( this.uiDialog ); 8908 8909 this._createTitlebar(); 8910 this._createButtonPane(); 8911 8912 if ( this.options.draggable && $.fn.draggable ) { 8913 this._makeDraggable(); 8914 } 8915 if ( this.options.resizable && $.fn.resizable ) { 8916 this._makeResizable(); 8917 } 8918 8919 this._isOpen = false; 8920 }, 8921 8922 _init: function() { 8923 if ( this.options.autoOpen ) { 8924 this.open(); 8925 } 8926 }, 8927 8928 _appendTo: function() { 8929 var element = this.options.appendTo; 8930 if ( element && (element.jquery || element.nodeType) ) { 8931 return $( element ); 8932 } 8933 return this.document.find( element || "body" ).eq( 0 ); 8934 }, 8935 8936 _destroy: function() { 8937 var next, 8938 originalPosition = this.originalPosition; 8939 8940 this._destroyOverlay(); 8941 8942 this.element 8943 .removeUniqueId() 8944 .removeClass("ui-dialog-content ui-widget-content") 8945 .css( this.originalCss ) 8946 // Without detaching first, the following becomes really slow 8947 .detach(); 8948 8949 this.uiDialog.stop( true, true ).remove(); 8950 8951 if ( this.originalTitle ) { 8952 this.element.attr( "title", this.originalTitle ); 8953 } 8954 8955 next = originalPosition.parent.children().eq( originalPosition.index ); 8956 // Don't try to place the dialog next to itself (#8613) 8957 if ( next.length && next[0] !== this.element[0] ) { 8958 next.before( this.element ); 8959 } else { 8960 originalPosition.parent.append( this.element ); 8961 } 8962 }, 8963 8964 widget: function() { 8965 return this.uiDialog; 8966 }, 8967 8968 disable: $.noop, 8969 enable: $.noop, 8970 8971 close: function( event ) { 8972 var that = this; 8973 8974 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) { 8975 return; 8976 } 8977 8978 this._isOpen = false; 8979 this._destroyOverlay(); 8980 8981 if ( !this.opener.filter(":focusable").focus().length ) { 8982 // Hiding a focused element doesn't trigger blur in WebKit 8983 // so in case we have nothing to focus on, explicitly blur the active element 8984 // https://bugs.webkit.org/show_bug.cgi?id=47182 8985 $( this.document[0].activeElement ).blur(); 8986 } 8987 8988 this._hide( this.uiDialog, this.options.hide, function() { 8989 that._trigger( "close", event ); 8990 }); 8991 }, 8992 8993 isOpen: function() { 8994 return this._isOpen; 8995 }, 8996 8997 moveToTop: function() { 8998 this._moveToTop(); 8999 }, 9000 9001 _moveToTop: function( event, silent ) { 9002 var moved = !!this.uiDialog.nextAll(":visible").insertBefore( this.uiDialog ).length; 9003 if ( moved && !silent ) { 9004 this._trigger( "focus", event ); 9005 } 9006 return moved; 9007 }, 9008 9009 open: function() { 9010 var that = this; 9011 if ( this._isOpen ) { 9012 if ( this._moveToTop() ) { 9013 this._focusTabbable(); 9014 } 9015 return; 9016 } 9017 9018 this._isOpen = true; 9019 this.opener = $( this.document[0].activeElement ); 9020 9021 this._size(); 9022 this._position(); 9023 this._createOverlay(); 9024 this._moveToTop( null, true ); 9025 this._show( this.uiDialog, this.options.show, function() { 9026 that._focusTabbable(); 9027 that._trigger("focus"); 9028 }); 9029 9030 this._trigger("open"); 9031 }, 9032 9033 _focusTabbable: function() { 9034 // Set focus to the first match: 9035 // 1. First element inside the dialog matching [autofocus] 9036 // 2. Tabbable element inside the content element 9037 // 3. Tabbable element inside the buttonpane 9038 // 4. The close button 9039 // 5. The dialog itself 9040 var hasFocus = this.element.find("[autofocus]"); 9041 if ( !hasFocus.length ) { 9042 hasFocus = this.element.find(":tabbable"); 9043 } 9044 if ( !hasFocus.length ) { 9045 hasFocus = this.uiDialogButtonPane.find(":tabbable"); 9046 } 9047 if ( !hasFocus.length ) { 9048 hasFocus = this.uiDialogTitlebarClose.filter(":tabbable"); 9049 } 9050 if ( !hasFocus.length ) { 9051 hasFocus = this.uiDialog; 9052 } 9053 hasFocus.eq( 0 ).focus(); 9054 }, 9055 9056 _keepFocus: function( event ) { 9057 function checkFocus() { 9058 var activeElement = this.document[0].activeElement, 9059 isActive = this.uiDialog[0] === activeElement || 9060 $.contains( this.uiDialog[0], activeElement ); 9061 if ( !isActive ) { 9062 this._focusTabbable(); 9063 } 9064 } 9065 event.preventDefault(); 9066 checkFocus.call( this ); 9067 // support: IE 9068 // IE <= 8 doesn't prevent moving focus even with event.preventDefault() 9069 // so we check again later 9070 this._delay( checkFocus ); 9071 }, 9072 9073 _createWrapper: function() { 9074 this.uiDialog = $("<div>") 9075 .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " + 9076 this.options.dialogClass ) 9077 .hide() 9078 .attr({ 9079 // Setting tabIndex makes the div focusable 9080 tabIndex: -1, 9081 role: "dialog" 9082 }) 9083 .appendTo( this._appendTo() ); 9084 9085 this._on( this.uiDialog, { 9086 keydown: function( event ) { 9087 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && 9088 event.keyCode === $.ui.keyCode.ESCAPE ) { 9089 event.preventDefault(); 9090 this.close( event ); 9091 return; 9092 } 9093 9094 // prevent tabbing out of dialogs 9095 if ( event.keyCode !== $.ui.keyCode.TAB ) { 9096 return; 9097 } 9098 var tabbables = this.uiDialog.find(":tabbable"), 9099 first = tabbables.filter(":first"), 9100 last = tabbables.filter(":last"); 9101 9102 if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) { 9103 first.focus( 1 ); 9104 event.preventDefault(); 9105 } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) { 9106 last.focus( 1 ); 9107 event.preventDefault(); 9108 } 9109 }, 9110 mousedown: function( event ) { 9111 if ( this._moveToTop( event ) ) { 9112 this._focusTabbable(); 9113 } 9114 } 9115 }); 9116 9117 // We assume that any existing aria-describedby attribute means 9118 // that the dialog content is marked up properly 9119 // otherwise we brute force the content as the description 9120 if ( !this.element.find("[aria-describedby]").length ) { 9121 this.uiDialog.attr({ 9122 "aria-describedby": this.element.uniqueId().attr("id") 9123 }); 9124 } 9125 }, 9126 9127 _createTitlebar: function() { 9128 var uiDialogTitle; 9129 9130 this.uiDialogTitlebar = $("<div>") 9131 .addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix") 9132 .prependTo( this.uiDialog ); 9133 this._on( this.uiDialogTitlebar, { 9134 mousedown: function( event ) { 9135 // Don't prevent click on close button (#8838) 9136 // Focusing a dialog that is partially scrolled out of view 9137 // causes the browser to scroll it into view, preventing the click event 9138 if ( !$( event.target ).closest(".ui-dialog-titlebar-close") ) { 9139 // Dialog isn't getting focus when dragging (#8063) 9140 this.uiDialog.focus(); 9141 } 9142 } 9143 }); 9144 9145 this.uiDialogTitlebarClose = $("<button></button>") 9146 .button({ 9147 label: this.options.closeText, 9148 icons: { 9149 primary: "ui-icon-closethick" 9150 }, 9151 text: false 9152 }) 9153 .addClass("ui-dialog-titlebar-close") 9154 .appendTo( this.uiDialogTitlebar ); 9155 this._on( this.uiDialogTitlebarClose, { 9156 click: function( event ) { 9157 event.preventDefault(); 9158 this.close( event ); 9159 } 9160 }); 9161 9162 uiDialogTitle = $("<span>") 9163 .uniqueId() 9164 .addClass("ui-dialog-title") 9165 .prependTo( this.uiDialogTitlebar ); 9166 this._title( uiDialogTitle ); 9167 9168 this.uiDialog.attr({ 9169 "aria-labelledby": uiDialogTitle.attr("id") 9170 }); 9171 }, 9172 9173 _title: function( title ) { 9174 if ( !this.options.title ) { 9175 title.html(" "); 9176 } 9177 title.text( this.options.title ); 9178 }, 9179 9180 _createButtonPane: function() { 9181 this.uiDialogButtonPane = $("<div>") 9182 .addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"); 9183 9184 this.uiButtonSet = $("<div>") 9185 .addClass("ui-dialog-buttonset") 9186 .appendTo( this.uiDialogButtonPane ); 9187 9188 this._createButtons(); 9189 }, 9190 9191 _createButtons: function() { 9192 var that = this, 9193 buttons = this.options.buttons; 9194 9195 // if we already have a button pane, remove it 9196 this.uiDialogButtonPane.remove(); 9197 this.uiButtonSet.empty(); 9198 9199 if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) { 9200 this.uiDialog.removeClass("ui-dialog-buttons"); 9201 return; 9202 } 9203 9204 $.each( buttons, function( name, props ) { 9205 var click, buttonOptions; 9206 props = $.isFunction( props ) ? 9207 { click: props, text: name } : 9208 props; 9209 // Default to a non-submitting button 9210 props = $.extend( { type: "button" }, props ); 9211 // Change the context for the click callback to be the main element 9212 click = props.click; 9213 props.click = function() { 9214 click.apply( that.element[0], arguments ); 9215 }; 9216 buttonOptions = { 9217 icons: props.icons, 9218 text: props.showText 9219 }; 9220 delete props.icons; 9221 delete props.showText; 9222 $( "<button></button>", props ) 9223 .button( buttonOptions ) 9224 .appendTo( that.uiButtonSet ); 9225 }); 9226 this.uiDialog.addClass("ui-dialog-buttons"); 9227 this.uiDialogButtonPane.appendTo( this.uiDialog ); 9228 }, 9229 9230 _makeDraggable: function() { 9231 var that = this, 9232 options = this.options; 9233 9234 function filteredUi( ui ) { 9235 return { 9236 position: ui.position, 9237 offset: ui.offset 9238 }; 9239 } 9240 9241 this.uiDialog.draggable({ 9242 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", 9243 handle: ".ui-dialog-titlebar", 9244 containment: "document", 9245 start: function( event, ui ) { 9246 $( this ).addClass("ui-dialog-dragging"); 9247 that._blockFrames(); 9248 that._trigger( "dragStart", event, filteredUi( ui ) ); 9249 }, 9250 drag: function( event, ui ) { 9251 that._trigger( "drag", event, filteredUi( ui ) ); 9252 }, 9253 stop: function( event, ui ) { 9254 options.position = [ 9255 ui.position.left - that.document.scrollLeft(), 9256 ui.position.top - that.document.scrollTop() 9257 ]; 9258 $( this ).removeClass("ui-dialog-dragging"); 9259 that._unblockFrames(); 9260 that._trigger( "dragStop", event, filteredUi( ui ) ); 9261 } 9262 }); 9263 }, 9264 9265 _makeResizable: function() { 9266 var that = this, 9267 options = this.options, 9268 handles = options.resizable, 9269 // .ui-resizable has position: relative defined in the stylesheet 9270 // but dialogs have to use absolute or fixed positioning 9271 position = this.uiDialog.css("position"), 9272 resizeHandles = typeof handles === "string" ? 9273 handles : 9274 "n,e,s,w,se,sw,ne,nw"; 9275 9276 function filteredUi( ui ) { 9277 return { 9278 originalPosition: ui.originalPosition, 9279 originalSize: ui.originalSize, 9280 position: ui.position, 9281 size: ui.size 9282 }; 9283 } 9284 9285 this.uiDialog.resizable({ 9286 cancel: ".ui-dialog-content", 9287 containment: "document", 9288 alsoResize: this.element, 9289 maxWidth: options.maxWidth, 9290 maxHeight: options.maxHeight, 9291 minWidth: options.minWidth, 9292 minHeight: this._minHeight(), 9293 handles: resizeHandles, 9294 start: function( event, ui ) { 9295 $( this ).addClass("ui-dialog-resizing"); 9296 that._blockFrames(); 9297 that._trigger( "resizeStart", event, filteredUi( ui ) ); 9298 }, 9299 resize: function( event, ui ) { 9300 that._trigger( "resize", event, filteredUi( ui ) ); 9301 }, 9302 stop: function( event, ui ) { 9303 options.height = $( this ).height(); 9304 options.width = $( this ).width(); 9305 $( this ).removeClass("ui-dialog-resizing"); 9306 that._unblockFrames(); 9307 that._trigger( "resizeStop", event, filteredUi( ui ) ); 9308 } 9309 }) 9310 .css( "position", position ); 9311 }, 9312 9313 _minHeight: function() { 9314 var options = this.options; 9315 9316 return options.height === "auto" ? 9317 options.minHeight : 9318 Math.min( options.minHeight, options.height ); 9319 }, 9320 9321 _position: function() { 9322 // Need to show the dialog to get the actual offset in the position plugin 9323 var isVisible = this.uiDialog.is(":visible"); 9324 if ( !isVisible ) { 9325 this.uiDialog.show(); 9326 } 9327 this.uiDialog.position( this.options.position ); 9328 if ( !isVisible ) { 9329 this.uiDialog.hide(); 9330 } 9331 }, 9332 9333 _setOptions: function( options ) { 9334 var that = this, 9335 resize = false, 9336 resizableOptions = {}; 9337 9338 $.each( options, function( key, value ) { 9339 that._setOption( key, value ); 9340 9341 if ( key in sizeRelatedOptions ) { 9342 resize = true; 9343 } 9344 if ( key in resizableRelatedOptions ) { 9345 resizableOptions[ key ] = value; 9346 } 9347 }); 9348 9349 if ( resize ) { 9350 this._size(); 9351 this._position(); 9352 } 9353 if ( this.uiDialog.is(":data(ui-resizable)") ) { 9354 this.uiDialog.resizable( "option", resizableOptions ); 9355 } 9356 }, 9357 9358 _setOption: function( key, value ) { 9359 /*jshint maxcomplexity:15*/ 9360 var isDraggable, isResizable, 9361 uiDialog = this.uiDialog; 9362 9363 if ( key === "dialogClass" ) { 9364 uiDialog 9365 .removeClass( this.options.dialogClass ) 9366 .addClass( value ); 9367 } 9368 9369 if ( key === "disabled" ) { 9370 return; 9371 } 9372 9373 this._super( key, value ); 9374 9375 if ( key === "appendTo" ) { 9376 this.uiDialog.appendTo( this._appendTo() ); 9377 } 9378 9379 if ( key === "buttons" ) { 9380 this._createButtons(); 9381 } 9382 9383 if ( key === "closeText" ) { 9384 this.uiDialogTitlebarClose.button({ 9385 // Ensure that we always pass a string 9386 label: "" + value 9387 }); 9388 } 9389 9390 if ( key === "draggable" ) { 9391 isDraggable = uiDialog.is(":data(ui-draggable)"); 9392 if ( isDraggable && !value ) { 9393 uiDialog.draggable("destroy"); 9394 } 9395 9396 if ( !isDraggable && value ) { 9397 this._makeDraggable(); 9398 } 9399 } 9400 9401 if ( key === "position" ) { 9402 this._position(); 9403 } 9404 9405 if ( key === "resizable" ) { 9406 // currently resizable, becoming non-resizable 9407 isResizable = uiDialog.is(":data(ui-resizable)"); 9408 if ( isResizable && !value ) { 9409 uiDialog.resizable("destroy"); 9410 } 9411 9412 // currently resizable, changing handles 9413 if ( isResizable && typeof value === "string" ) { 9414 uiDialog.resizable( "option", "handles", value ); 9415 } 9416 9417 // currently non-resizable, becoming resizable 9418 if ( !isResizable && value !== false ) { 9419 this._makeResizable(); 9420 } 9421 } 9422 9423 if ( key === "title" ) { 9424 this._title( this.uiDialogTitlebar.find(".ui-dialog-title") ); 9425 } 9426 }, 9427 9428 _size: function() { 9429 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content 9430 // divs will both have width and height set, so we need to reset them 9431 var nonContentHeight, minContentHeight, maxContentHeight, 9432 options = this.options; 9433 9434 // Reset content sizing 9435 this.element.show().css({ 9436 width: "auto", 9437 minHeight: 0, 9438 maxHeight: "none", 9439 height: 0 9440 }); 9441 9442 if ( options.minWidth > options.width ) { 9443 options.width = options.minWidth; 9444 } 9445 9446 // reset wrapper sizing 9447 // determine the height of all the non-content elements 9448 nonContentHeight = this.uiDialog.css({ 9449 height: "auto", 9450 width: options.width 9451 }) 9452 .outerHeight(); 9453 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); 9454 maxContentHeight = typeof options.maxHeight === "number" ? 9455 Math.max( 0, options.maxHeight - nonContentHeight ) : 9456 "none"; 9457 9458 if ( options.height === "auto" ) { 9459 this.element.css({ 9460 minHeight: minContentHeight, 9461 maxHeight: maxContentHeight, 9462 height: "auto" 9463 }); 9464 } else { 9465 this.element.height( Math.max( 0, options.height - nonContentHeight ) ); 9466 } 9467 9468 if (this.uiDialog.is(":data(ui-resizable)") ) { 9469 this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); 9470 } 9471 }, 9472 9473 _blockFrames: function() { 9474 this.iframeBlocks = this.document.find( "iframe" ).map(function() { 9475 var iframe = $( this ); 9476 9477 return $( "<div>" ) 9478 .css({ 9479 position: "absolute", 9480 width: iframe.outerWidth(), 9481 height: iframe.outerHeight() 9482 }) 9483 .appendTo( iframe.parent() ) 9484 .offset( iframe.offset() )[0]; 9485 }); 9486 }, 9487 9488 _unblockFrames: function() { 9489 if ( this.iframeBlocks ) { 9490 this.iframeBlocks.remove(); 9491 delete this.iframeBlocks; 9492 } 9493 }, 9494 9495 _allowInteraction: function( event ) { 9496 if ( $( event.target ).closest(".ui-dialog").length ) { 9497 return true; 9498 } 9499 9500 // TODO: Remove hack when datepicker implements 9501 // the .ui-front logic (#8989) 9502 return !!$( event.target ).closest(".ui-datepicker").length; 9503 }, 9504 9505 _createOverlay: function() { 9506 if ( !this.options.modal ) { 9507 return; 9508 } 9509 9510 var that = this, 9511 widgetFullName = this.widgetFullName; 9512 if ( !$.ui.dialog.overlayInstances ) { 9513 // Prevent use of anchors and inputs. 9514 // We use a delay in case the overlay is created from an 9515 // event that we're going to be cancelling. (#2804) 9516 this._delay(function() { 9517 // Handle .dialog().dialog("close") (#4065) 9518 if ( $.ui.dialog.overlayInstances ) { 9519 this.document.bind( "focusin.dialog", function( event ) { 9520 if ( !that._allowInteraction( event ) ) { 9521 event.preventDefault(); 9522 $(".ui-dialog:visible:last .ui-dialog-content") 9523 .data( widgetFullName )._focusTabbable(); 9524 } 9525 }); 9526 } 9527 }); 9528 } 9529
9530 this.overlay = $("<div>") 9531 .addClass("ui-widget-overlay ui-front") 9532 .appendTo( this._appendTo() ); 9533 this._on( this.overlay, { 9534 mousedown: "_keepFocus" 9535 }); 9536 $.ui.dialog.overlayInstances++; 9537 }, 9538 9539 _destroyOverlay: function() { 9540 if ( !this.options.modal ) { 9541 return; 9542 } 9543 9544 if ( this.overlay ) { 9545 $.ui.dialog.overlayInstances--; 9546 9547 if ( !$.ui.dialog.overlayInstances ) { 9548 this.document.unbind( "focusin.dialog" ); 9549 } 9550 this.overlay.remove(); 9551 this.overlay = null; 9552 } 9553 } 9554}); 9555 9556$.ui.dialog.overlayInstances = 0; 9557 9558// DEPRECATED 9559if ( $.uiBackCompat !== false ) { 9560 // position option with array notation 9561 // just override with old implementation 9562 $.widget( "ui.dialog", $.ui.dialog, { 9563 _position: function() { 9564 var position = this.options.position, 9565 myAt = [], 9566 offset = [ 0, 0 ], 9567 isVisible; 9568 9569 if ( position ) { 9570 if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) { 9571 myAt = position.split ? position.split(" ") : [ position[0], position[1] ]; 9572 if ( myAt.length === 1 ) { 9573 myAt[1] = myAt[0]; 9574 } 9575 9576 $.each( [ "left", "top" ], function( i, offsetPosition ) { 9577 if ( +myAt[ i ] === myAt[ i ] ) { 9578 offset[ i ] = myAt[ i ]; 9579 myAt[ i ] = offsetPosition; 9580 } 9581 }); 9582 9583 position = { 9584 my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " + 9585 myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]), 9586 at: myAt.join(" ") 9587 }; 9588 } 9589 9590 position = $.extend( {}, $.ui.dialog.prototype.options.position, position ); 9591 } else { 9592 position = $.ui.dialog.prototype.options.position; 9593 } 9594 9595 // need to show the dialog to get the actual offset in the position plugin 9596 isVisible = this.uiDialog.is(":visible"); 9597 if ( !isVisible ) { 9598 this.uiDialog.show(); 9599 } 9600 this.uiDialog.position( position ); 9601 if ( !isVisible ) { 9602 this.uiDialog.hide(); 9603 } 9604 } 9605 }); 9606} 9607 9608}( jQuery ) ); 9609(function( $, undefined ) { 9610 9611$.widget( "ui.menu", { 9612 version: "1.10.2", 9613 defaultElement: "<ul>", 9614 delay: 300, 9615 options: { 9616 icons: { 9617 submenu: "ui-icon-carat-1-e" 9618 }, 9619 menus: "ul", 9620 position: { 9621 my: "left top", 9622 at: "right top" 9623 }, 9624 role: "menu", 9625 9626 // callbacks 9627 blur: null, 9628 focus: null, 9629 select: null 9630 }, 9631 9632 _create: function() { 9633 this.activeMenu = this.element; 9634 // flag used to prevent firing of the click handler 9635 // as the event bubbles up through nested menus 9636 this.mouseHandled = false; 9637 this.element 9638 .uniqueId() 9639 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) 9640 .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ) 9641 .attr({ 9642 role: this.options.role, 9643 tabIndex: 0 9644 }) 9645 // need to catch all clicks on disabled menu 9646 // not possible through _on 9647 .bind( "click" + this.eventNamespace, $.proxy(function( event ) { 9648 if ( this.options.disabled ) { 9649 event.preventDefault(); 9650 } 9651 }, this )); 9652 9653 if ( this.options.disabled ) { 9654 this.element 9655 .addClass( "ui-state-disabled" ) 9656 .attr( "aria-disabled", "true" ); 9657 } 9658 9659 this._on({ 9660 // Prevent focus from sticking to links inside menu after clicking 9661 // them (focus should always stay on UL during navigation). 9662 "mousedown .ui-menu-item > a": function( event ) { 9663 event.preventDefault(); 9664 }, 9665 "click .ui-state-disabled > a": function( event ) { 9666 event.preventDefault(); 9667 }, 9668 "click .ui-menu-item:has(a)": function( event ) { 9669 var target = $( event.target ).closest( ".ui-menu-item" ); 9670 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) { 9671 this.mouseHandled = true; 9672 9673 this.select( event ); 9674 // Open submenu on click 9675 if ( target.has( ".ui-menu" ).length ) { 9676 this.expand( event ); 9677 } else if ( !this.element.is( ":focus" ) ) { 9678 // Redirect focus to the menu 9679 this.element.trigger( "focus", [ true ] ); 9680 9681 // If the active item is on the top level, let it stay active. 9682 // Otherwise, blur the active item since it is no longer visible. 9683 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) { 9684 clearTimeout( this.timer ); 9685 } 9686 } 9687 } 9688 }, 9689 "mouseenter .ui-menu-item": function( event ) { 9690 var target = $( event.currentTarget ); 9691 // Remove ui-state-active class from siblings of the newly focused menu item 9692 // to avoid a jump caused by adjacent elements both having a class with a border 9693 target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" ); 9694 this.focus( event, target ); 9695 }, 9696 mouseleave: "collapseAll", 9697 "mouseleave .ui-menu": "collapseAll", 9698 focus: function( event, keepActiveItem ) { 9699 // If there's already an active item, keep it active 9700 // If not, activate the first item 9701 var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 ); 9702 9703 if ( !keepActiveItem ) { 9704 this.focus( event, item ); 9705 } 9706 }, 9707 blur: function( event ) { 9708 this._delay(function() { 9709 if ( !$.contains( this.element[0], this.document[0].activeElement ) ) { 9710 this.collapseAll( event ); 9711 } 9712 }); 9713 }, 9714 keydown: "_keydown" 9715 }); 9716 9717 this.refresh(); 9718
vendor: 133,980 bytes, lines 9719-14955
9719 // Clicks outside of a menu collapse any open menus 9720 this._on( this.document, { 9721 click: function( event ) { 9722 if ( !$( event.target ).closest( ".ui-menu" ).length ) { 9723 this.collapseAll( event ); 9724 } 9725 9726 // Reset the mouseHandled flag 9727 this.mouseHandled = false; 9728 } 9729 }); 9730 }, 9731 9732 _destroy: function() { 9733 // Destroy (sub)menus 9734 this.element 9735 .removeAttr( "aria-activedescendant" ) 9736 .find( ".ui-menu" ).addBack() 9737 .removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" ) 9738 .removeAttr( "role" ) 9739 .removeAttr( "tabIndex" ) 9740 .removeAttr( "aria-labelledby" ) 9741 .removeAttr( "aria-expanded" ) 9742 .removeAttr( "aria-hidden" ) 9743 .removeAttr( "aria-disabled" ) 9744 .removeUniqueId() 9745 .show(); 9746 9747 // Destroy menu items 9748 this.element.find( ".ui-menu-item" ) 9749 .removeClass( "ui-menu-item" ) 9750 .removeAttr( "role" ) 9751 .removeAttr( "aria-disabled" ) 9752 .children( "a" ) 9753 .removeUniqueId() 9754 .removeClass( "ui-corner-all ui-state-hover" ) 9755 .removeAttr( "tabIndex" ) 9756 .removeAttr( "role" ) 9757 .removeAttr( "aria-haspopup" ) 9758 .children().each( function() { 9759 var elem = $( this ); 9760 if ( elem.data( "ui-menu-submenu-carat" ) ) { 9761 elem.remove(); 9762 } 9763 }); 9764 9765 // Destroy menu dividers 9766 this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" ); 9767 }, 9768 9769 _keydown: function( event ) { 9770 /*jshint maxcomplexity:20*/ 9771 var match, prev, character, skip, regex, 9772 preventDefault = true; 9773 9774 function escape( value ) { 9775 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ); 9776 } 9777 9778 switch ( event.keyCode ) { 9779 case $.ui.keyCode.PAGE_UP: 9780 this.previousPage( event ); 9781 break; 9782 case $.ui.keyCode.PAGE_DOWN: 9783 this.nextPage( event ); 9784 break; 9785 case $.ui.keyCode.HOME: 9786 this._move( "first", "first", event ); 9787 break; 9788 case $.ui.keyCode.END: 9789 this._move( "last", "last", event ); 9790 break; 9791 case $.ui.keyCode.UP: 9792 this.previous( event ); 9793 break; 9794 case $.ui.keyCode.DOWN: 9795 this.next( event ); 9796 break; 9797 case $.ui.keyCode.LEFT: 9798 this.collapse( event ); 9799 break; 9800 case $.ui.keyCode.RIGHT: 9801 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { 9802 this.expand( event ); 9803 } 9804 break; 9805 case $.ui.keyCode.ENTER: 9806 case $.ui.keyCode.SPACE: 9807 this._activate( event ); 9808 break; 9809 case $.ui.keyCode.ESCAPE: 9810 this.collapse( event ); 9811 break; 9812 default: 9813 preventDefault = false; 9814 prev = this.previousFilter || ""; 9815 character = String.fromCharCode( event.keyCode ); 9816 skip = false; 9817 9818 clearTimeout( this.filterTimer ); 9819 9820 if ( character === prev ) { 9821 skip = true; 9822 } else { 9823 character = prev + character; 9824 } 9825 9826 regex = new RegExp( "^" + escape( character ), "i" ); 9827 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { 9828 return regex.test( $( this ).children( "a" ).text() ); 9829 }); 9830 match = skip && match.index( this.active.next() ) !== -1 ? 9831 this.active.nextAll( ".ui-menu-item" ) : 9832 match; 9833 9834 // If no matches on the current filter, reset to the last character pressed 9835 // to move down the menu to the first item that starts with that character 9836 if ( !match.length ) { 9837 character = String.fromCharCode( event.keyCode ); 9838 regex = new RegExp( "^" + escape( character ), "i" ); 9839 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { 9840 return regex.test( $( this ).children( "a" ).text() ); 9841 }); 9842 } 9843 9844 if ( match.length ) { 9845 this.focus( event, match ); 9846 if ( match.length > 1 ) { 9847 this.previousFilter = character; 9848 this.filterTimer = this._delay(function() { 9849 delete this.previousFilter; 9850 }, 1000 ); 9851 } else { 9852 delete this.previousFilter; 9853 } 9854 } else { 9855 delete this.previousFilter; 9856 } 9857 } 9858 9859 if ( preventDefault ) { 9860 event.preventDefault(); 9861 } 9862 }, 9863 9864 _activate: function( event ) { 9865 if ( !this.active.is( ".ui-state-disabled" ) ) { 9866 if ( this.active.children( "a[aria-haspopup='true']" ).length ) { 9867 this.expand( event ); 9868 } else { 9869 this.select( event ); 9870 } 9871 } 9872 }, 9873 9874 refresh: function() { 9875 var menus, 9876 icon = this.options.icons.submenu, 9877 submenus = this.element.find( this.options.menus ); 9878 9879 // Initialize nested menus 9880 submenus.filter( ":not(.ui-menu)" ) 9881 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) 9882 .hide() 9883 .attr({ 9884 role: this.options.role, 9885 "aria-hidden": "true", 9886 "aria-expanded": "false" 9887 }) 9888 .each(function() { 9889 var menu = $( this ), 9890 item = menu.prev( "a" ), 9891 submenuCarat = $( "<span>" ) 9892 .addClass( "ui-menu-icon ui-icon " + icon ) 9893 .data( "ui-menu-submenu-carat", true ); 9894 9895 item 9896 .attr( "aria-haspopup", "true" ) 9897 .prepend( submenuCarat ); 9898 menu.attr( "aria-labelledby", item.attr( "id" ) ); 9899 }); 9900 9901 menus = submenus.add( this.element ); 9902 9903 // Don't refresh list items that are already adapted 9904 menus.children( ":not(.ui-menu-item):has(a)" ) 9905 .addClass( "ui-menu-item" ) 9906 .attr( "role", "presentation" ) 9907 .children( "a" ) 9908 .uniqueId() 9909 .addClass( "ui-corner-all" ) 9910 .attr({ 9911 tabIndex: -1, 9912 role: this._itemRole() 9913 }); 9914 9915 // Initialize unlinked menu-items containing spaces and/or dashes only as dividers 9916 menus.children( ":not(.ui-menu-item)" ).each(function() { 9917 var item = $( this ); 9918 // hyphen, em dash, en dash 9919 if ( !/[^\-\u2014\u2013\s]/.test( item.text() ) ) { 9920 item.addClass( "ui-widget-content ui-menu-divider" ); 9921 } 9922 }); 9923 9924 // Add aria-disabled attribute to any disabled menu item 9925 menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); 9926 9927 // If the active item has been removed, blur the menu 9928 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 9929 this.blur(); 9930 } 9931 }, 9932 9933 _itemRole: function() { 9934 return { 9935 menu: "menuitem", 9936 listbox: "option" 9937 }[ this.options.role ]; 9938 }, 9939 9940 _setOption: function( key, value ) { 9941 if ( key === "icons" ) { 9942 this.element.find( ".ui-menu-icon" ) 9943 .removeClass( this.options.icons.submenu ) 9944 .addClass( value.submenu ); 9945 } 9946 this._super( key, value ); 9947 }, 9948 9949 focus: function( event, item ) { 9950 var nested, focused; 9951 this.blur( event, event && event.type === "focus" ); 9952 9953 this._scrollIntoView( item ); 9954 9955 this.active = item.first(); 9956 focused = this.active.children( "a" ).addClass( "ui-state-focus" ); 9957 // Only update aria-activedescendant if there's a role 9958 // otherwise we assume focus is managed elsewhere 9959 if ( this.options.role ) { 9960 this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); 9961 } 9962 9963 // Highlight active parent menu item, if any 9964 this.active 9965 .parent() 9966 .closest( ".ui-menu-item" ) 9967 .children( "a:first" ) 9968 .addClass( "ui-state-active" ); 9969 9970 if ( event && event.type === "keydown" ) { 9971 this._close(); 9972 } else { 9973 this.timer = this._delay(function() { 9974 this._close(); 9975 }, this.delay ); 9976 } 9977 9978 nested = item.children( ".ui-menu" ); 9979 if ( nested.length && ( /^mouse/.test( event.type ) ) ) { 9980 this._startOpening(nested); 9981 } 9982 this.activeMenu = item.parent(); 9983 9984 this._trigger( "focus", event, { item: item } ); 9985 }, 9986 9987 _scrollIntoView: function( item ) { 9988 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; 9989 if ( this._hasScroll() ) { 9990 borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0; 9991 paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0; 9992 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; 9993 scroll = this.activeMenu.scrollTop(); 9994 elementHeight = this.activeMenu.height(); 9995 itemHeight = item.height(); 9996 9997 if ( offset < 0 ) { 9998 this.activeMenu.scrollTop( scroll + offset ); 9999 } else if ( offset + itemHeight > elementHeight ) { 10000 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); 10001 } 10002 } 10003 }, 10004 10005 blur: function( event, fromFocus ) { 10006 if ( !fromFocus ) { 10007 clearTimeout( this.timer ); 10008 } 10009 10010 if ( !this.active ) { 10011 return; 10012 } 10013 10014 this.active.children( "a" ).removeClass( "ui-state-focus" ); 10015 this.active = null; 10016 10017 this._trigger( "blur", event, { item: this.active } ); 10018 }, 10019 10020 _startOpening: function( submenu ) { 10021 clearTimeout( this.timer ); 10022 10023 // Don't open if already open fixes a Firefox bug that caused a .5 pixel 10024 // shift in the submenu position when mousing over the carat icon 10025 if ( submenu.attr( "aria-hidden" ) !== "true" ) { 10026 return; 10027 } 10028 10029 this.timer = this._delay(function() { 10030 this._close(); 10031 this._open( submenu ); 10032 }, this.delay ); 10033 }, 10034 10035 _open: function( submenu ) { 10036 var position = $.extend({ 10037 of: this.active 10038 }, this.options.position ); 10039 10040 clearTimeout( this.timer ); 10041 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) ) 10042 .hide() 10043 .attr( "aria-hidden", "true" ); 10044 10045 submenu 10046 .show() 10047 .removeAttr( "aria-hidden" ) 10048 .attr( "aria-expanded", "true" ) 10049 .position( position ); 10050 }, 10051 10052 collapseAll: function( event, all ) { 10053 clearTimeout( this.timer ); 10054 this.timer = this._delay(function() { 10055 // If we were passed an event, look for the submenu that contains the event 10056 var currentMenu = all ? this.element : 10057 $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); 10058 10059 // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway 10060 if ( !currentMenu.length ) { 10061 currentMenu = this.element; 10062 } 10063 10064 this._close( currentMenu ); 10065 10066 this.blur( event ); 10067 this.activeMenu = currentMenu; 10068 }, this.delay ); 10069 }, 10070 10071 // With no arguments, closes the currently active menu - if nothing is active 10072 // it closes all menus. If passed an argument, it will search for menus BELOW 10073 _close: function( startMenu ) { 10074 if ( !startMenu ) { 10075 startMenu = this.active ? this.active.parent() : this.element; 10076 } 10077 10078 startMenu 10079 .find( ".ui-menu" ) 10080 .hide() 10081 .attr( "aria-hidden", "true" ) 10082 .attr( "aria-expanded", "false" ) 10083 .end() 10084 .find( "a.ui-state-active" ) 10085 .removeClass( "ui-state-active" ); 10086 }, 10087 10088 collapse: function( event ) { 10089 var newItem = this.active && 10090 this.active.parent().closest( ".ui-menu-item", this.element ); 10091 if ( newItem && newItem.length ) { 10092 this._close(); 10093 this.focus( event, newItem ); 10094 } 10095 }, 10096 10097 expand: function( event ) { 10098 var newItem = this.active && 10099 this.active 10100 .children( ".ui-menu " ) 10101 .children( ".ui-menu-item" ) 10102 .first(); 10103 10104 if ( newItem && newItem.length ) { 10105 this._open( newItem.parent() ); 10106 10107 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT 10108 this._delay(function() { 10109 this.focus( event, newItem ); 10110 }); 10111 } 10112 }, 10113 10114 next: function( event ) { 10115 this._move( "next", "first", event ); 10116 }, 10117 10118 previous: function( event ) { 10119 this._move( "prev", "last", event ); 10120 }, 10121 10122 isFirstItem: function() { 10123 return this.active && !this.active.prevAll( ".ui-menu-item" ).length; 10124 }, 10125 10126 isLastItem: function() { 10127 return this.active && !this.active.nextAll( ".ui-menu-item" ).length; 10128 }, 10129 10130 _move: function( direction, filter, event ) { 10131 var next; 10132 if ( this.active ) { 10133 if ( direction === "first" || direction === "last" ) { 10134 next = this.active 10135 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) 10136 .eq( -1 ); 10137 } else { 10138 next = this.active 10139 [ direction + "All" ]( ".ui-menu-item" ) 10140 .eq( 0 ); 10141 } 10142 } 10143 if ( !next || !next.length || !this.active ) { 10144 next = this.activeMenu.children( ".ui-menu-item" )[ filter ](); 10145 } 10146 10147 this.focus( event, next ); 10148 }, 10149 10150 nextPage: function( event ) { 10151 var item, base, height; 10152 10153 if ( !this.active ) { 10154 this.next( event ); 10155 return; 10156 } 10157 if ( this.isLastItem() ) { 10158 return; 10159 } 10160 if ( this._hasScroll() ) { 10161 base = this.active.offset().top; 10162 height = this.element.height(); 10163 this.active.nextAll( ".ui-menu-item" ).each(function() { 10164 item = $( this ); 10165 return item.offset().top - base - height < 0; 10166 }); 10167 10168 this.focus( event, item ); 10169 } else { 10170 this.focus( event, this.activeMenu.children( ".ui-menu-item" ) 10171 [ !this.active ? "first" : "last" ]() ); 10172 } 10173 }, 10174 10175 previousPage: function( event ) { 10176 var item, base, height; 10177 if ( !this.active ) { 10178 this.next( event ); 10179 return; 10180 } 10181 if ( this.isFirstItem() ) { 10182 return; 10183 } 10184 if ( this._hasScroll() ) { 10185 base = this.active.offset().top; 10186 height = this.element.height(); 10187 this.active.prevAll( ".ui-menu-item" ).each(function() { 10188 item = $( this ); 10189 return item.offset().top - base + height > 0; 10190 }); 10191 10192 this.focus( event, item ); 10193 } else { 10194 this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() ); 10195 } 10196 }, 10197 10198 _hasScroll: function() { 10199 return this.element.outerHeight() < this.element.prop( "scrollHeight" ); 10200 }, 10201 10202 select: function( event ) { 10203 // TODO: It should never be possible to not have an active item at this 10204 // point, but the tests don't trigger mouseenter before click. 10205 this.active = this.active || $( event.target ).closest( ".ui-menu-item" ); 10206 var ui = { item: this.active }; 10207 if ( !this.active.has( ".ui-menu" ).length ) { 10208 this.collapseAll( event, true ); 10209 } 10210 this._trigger( "select", event, ui ); 10211 } 10212}); 10213 10214}( jQuery )); 10215(function( $, undefined ) { 10216 10217$.widget( "ui.progressbar", { 10218 version: "1.10.2", 10219 options: { 10220 max: 100, 10221 value: 0, 10222 10223 change: null, 10224 complete: null 10225 }, 10226 10227 min: 0, 10228 10229 _create: function() { 10230 // Constrain initial value 10231 this.oldValue = this.options.value = this._constrainedValue(); 10232 10233 this.element 10234 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) 10235 .attr({ 10236 // Only set static values, aria-valuenow and aria-valuemax are 10237 // set inside _refreshValue() 10238 role: "progressbar", 10239 "aria-valuemin": this.min 10240 }); 10241 10242 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" ) 10243 .appendTo( this.element ); 10244 10245 this._refreshValue(); 10246 }, 10247 10248 _destroy: function() { 10249 this.element 10250 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) 10251 .removeAttr( "role" ) 10252 .removeAttr( "aria-valuemin" ) 10253 .removeAttr( "aria-valuemax" ) 10254 .removeAttr( "aria-valuenow" ); 10255 10256 this.valueDiv.remove(); 10257 }, 10258 10259 value: function( newValue ) { 10260 if ( newValue === undefined ) { 10261 return this.options.value; 10262 } 10263 10264 this.options.value = this._constrainedValue( newValue ); 10265 this._refreshValue(); 10266 }, 10267 10268 _constrainedValue: function( newValue ) { 10269 if ( newValue === undefined ) { 10270 newValue = this.options.value; 10271 } 10272 10273 this.indeterminate = newValue === false; 10274 10275 // sanitize value 10276 if ( typeof newValue !== "number" ) { 10277 newValue = 0; 10278 } 10279 10280 return this.indeterminate ? false : 10281 Math.min( this.options.max, Math.max( this.min, newValue ) ); 10282 }, 10283 10284 _setOptions: function( options ) { 10285 // Ensure "value" option is set after other values (like max) 10286 var value = options.value; 10287 delete options.value; 10288 10289 this._super( options ); 10290 10291 this.options.value = this._constrainedValue( value ); 10292 this._refreshValue(); 10293 }, 10294 10295 _setOption: function( key, value ) { 10296 if ( key === "max" ) { 10297 // Don't allow a max less than min 10298 value = Math.max( this.min, value ); 10299 } 10300 10301 this._super( key, value ); 10302 }, 10303 10304 _percentage: function() { 10305 return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min ); 10306 }, 10307 10308 _refreshValue: function() { 10309 var value = this.options.value, 10310 percentage = this._percentage(); 10311 10312 this.valueDiv 10313 .toggle( this.indeterminate || value > this.min ) 10314 .toggleClass( "ui-corner-right", value === this.options.max ) 10315 .width( percentage.toFixed(0) + "%" ); 10316 10317 this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate ); 10318 10319 if ( this.indeterminate ) { 10320 this.element.removeAttr( "aria-valuenow" ); 10321 if ( !this.overlayDiv ) { 10322 this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv ); 10323 } 10324 } else { 10325 this.element.attr({ 10326 "aria-valuemax": this.options.max, 10327 "aria-valuenow": value 10328 }); 10329 if ( this.overlayDiv ) { 10330 this.overlayDiv.remove(); 10331 this.overlayDiv = null; 10332 } 10333 } 10334 10335 if ( this.oldValue !== value ) { 10336 this.oldValue = value; 10337 this._trigger( "change" ); 10338 } 10339 if ( value === this.options.max ) { 10340 this._trigger( "complete" ); 10341 } 10342 } 10343}); 10344 10345})( jQuery ); 10346(function( $, undefined ) { 10347 10348// number of pages in a slider 10349// (how many times can you page up/down to go through the whole range) 10350var numPages = 5; 10351 10352$.widget( "ui.slider", $.ui.mouse, { 10353 version: "1.10.2", 10354 widgetEventPrefix: "slide", 10355 10356 options: { 10357 animate: false, 10358 distance: 0, 10359 max: 100, 10360 min: 0, 10361 orientation: "horizontal", 10362 range: false, 10363 step: 1, 10364 value: 0, 10365 values: null, 10366 10367 // callbacks 10368 change: null, 10369 slide: null, 10370 start: null, 10371 stop: null 10372 }, 10373 10374 _create: function() { 10375 this._keySliding = false; 10376 this._mouseSliding = false; 10377 this._animateOff = true; 10378 this._handleIndex = null; 10379 this._detectOrientation(); 10380 this._mouseInit(); 10381 10382 this.element 10383 .addClass( "ui-slider" + 10384 " ui-slider-" + this.orientation + 10385 " ui-widget" + 10386 " ui-widget-content" + 10387 " ui-corner-all"); 10388 10389 this._refresh(); 10390 this._setOption( "disabled", this.options.disabled ); 10391 10392 this._animateOff = false; 10393 }, 10394 10395 _refresh: function() { 10396 this._createRange(); 10397 this._createHandles(); 10398 this._setupEvents(); 10399 this._refreshValue(); 10400 }, 10401 10402 _createHandles: function() { 10403 var i, handleCount, 10404 options = this.options, 10405 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), 10406 handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>", 10407 handles = []; 10408 10409 handleCount = ( options.values && options.values.length ) || 1; 10410 10411 if ( existingHandles.length > handleCount ) { 10412 existingHandles.slice( handleCount ).remove(); 10413 existingHandles = existingHandles.slice( 0, handleCount ); 10414 } 10415 10416 for ( i = existingHandles.length; i < handleCount; i++ ) { 10417 handles.push( handle ); 10418 } 10419 10420 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) ); 10421 10422 this.handle = this.handles.eq( 0 ); 10423 10424 this.handles.each(function( i ) { 10425 $( this ).data( "ui-slider-handle-index", i ); 10426 }); 10427 }, 10428 10429 _createRange: function() { 10430 var options = this.options, 10431 classes = ""; 10432 10433 if ( options.range ) { 10434 if ( options.range === true ) { 10435 if ( !options.values ) { 10436 options.values = [ this._valueMin(), this._valueMin() ]; 10437 } else if ( options.values.length && options.values.length !== 2 ) { 10438 options.values = [ options.values[0], options.values[0] ]; 10439 } else if ( $.isArray( options.values ) ) { 10440 options.values = options.values.slice(0); 10441 } 10442 } 10443 10444 if ( !this.range || !this.range.length ) { 10445 this.range = $( "<div></div>" ) 10446 .appendTo( this.element ); 10447 10448 classes = "ui-slider-range" + 10449 // note: this isn't the most fittingly semantic framework class for this element, 10450 // but worked best visually with a variety of themes 10451 " ui-widget-header ui-corner-all"; 10452 } else { 10453 this.range.removeClass( "ui-slider-range-min ui-slider-range-max" ) 10454 // Handle range switching from true to min/max 10455 .css({ 10456 "left": "", 10457 "bottom": "" 10458 }); 10459 } 10460 10461 this.range.addClass( classes + 10462 ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) ); 10463 } else { 10464 this.range = $([]); 10465 } 10466 }, 10467 10468 _setupEvents: function() { 10469 var elements = this.handles.add( this.range ).filter( "a" ); 10470 this._off( elements ); 10471 this._on( elements, this._handleEvents ); 10472 this._hoverable( elements ); 10473 this._focusable( elements ); 10474 }, 10475 10476 _destroy: function() { 10477 this.handles.remove(); 10478 this.range.remove(); 10479 10480 this.element 10481 .removeClass( "ui-slider" + 10482 " ui-slider-horizontal" + 10483 " ui-slider-vertical" + 10484 " ui-widget" + 10485 " ui-widget-content" + 10486 " ui-corner-all" ); 10487 10488 this._mouseDestroy(); 10489 }, 10490 10491 _mouseCapture: function( event ) { 10492 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, 10493 that = this, 10494 o = this.options; 10495 10496 if ( o.disabled ) { 10497 return false; 10498 } 10499 10500 this.elementSize = { 10501 width: this.element.outerWidth(), 10502 height: this.element.outerHeight() 10503 }; 10504 this.elementOffset = this.element.offset(); 10505 10506 position = { x: event.pageX, y: event.pageY }; 10507 normValue = this._normValueFromMouse( position ); 10508 distance = this._valueMax() - this._valueMin() + 1; 10509 this.handles.each(function( i ) { 10510 var thisDistance = Math.abs( normValue - that.values(i) ); 10511 if (( distance > thisDistance ) || 10512 ( distance === thisDistance && 10513 (i === that._lastChangedValue || that.values(i) === o.min ))) { 10514 distance = thisDistance; 10515 closestHandle = $( this ); 10516 index = i; 10517 } 10518 }); 10519 10520 allowed = this._start( event, index ); 10521 if ( allowed === false ) { 10522 return false; 10523 } 10524 this._mouseSliding = true; 10525 10526 this._handleIndex = index; 10527 10528 closestHandle 10529 .addClass( "ui-state-active" ) 10530 .focus(); 10531 10532 offset = closestHandle.offset(); 10533 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" ); 10534 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { 10535 left: event.pageX - offset.left - ( closestHandle.width() / 2 ), 10536 top: event.pageY - offset.top - 10537 ( closestHandle.height() / 2 ) - 10538 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - 10539 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + 10540 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) 10541 }; 10542 10543 if ( !this.handles.hasClass( "ui-state-hover" ) ) { 10544 this._slide( event, index, normValue ); 10545 } 10546 this._animateOff = true; 10547 return true; 10548 }, 10549 10550 _mouseStart: function() { 10551 return true; 10552 }, 10553 10554 _mouseDrag: function( event ) { 10555 var position = { x: event.pageX, y: event.pageY }, 10556 normValue = this._normValueFromMouse( position ); 10557 10558 this._slide( event, this._handleIndex, normValue ); 10559 10560 return false; 10561 }, 10562 10563 _mouseStop: function( event ) { 10564 this.handles.removeClass( "ui-state-active" ); 10565 this._mouseSliding = false; 10566 10567 this._stop( event, this._handleIndex ); 10568 this._change( event, this._handleIndex ); 10569 10570 this._handleIndex = null; 10571 this._clickOffset = null; 10572 this._animateOff = false; 10573 10574 return false; 10575 }, 10576 10577 _detectOrientation: function() { 10578 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; 10579 }, 10580 10581 _normValueFromMouse: function( position ) { 10582 var pixelTotal, 10583 pixelMouse, 10584 percentMouse, 10585 valueTotal, 10586 valueMouse; 10587 10588 if ( this.orientation === "horizontal" ) { 10589 pixelTotal = this.elementSize.width; 10590 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); 10591 } else { 10592 pixelTotal = this.elementSize.height; 10593 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); 10594 } 10595 10596 percentMouse = ( pixelMouse / pixelTotal ); 10597 if ( percentMouse > 1 ) { 10598 percentMouse = 1; 10599 } 10600 if ( percentMouse < 0 ) { 10601 percentMouse = 0; 10602 } 10603 if ( this.orientation === "vertical" ) { 10604 percentMouse = 1 - percentMouse; 10605 } 10606 10607 valueTotal = this._valueMax() - this._valueMin(); 10608 valueMouse = this._valueMin() + percentMouse * valueTotal; 10609 10610 return this._trimAlignValue( valueMouse ); 10611 }, 10612 10613 _start: function( event, index ) { 10614 var uiHash = { 10615 handle: this.handles[ index ], 10616 value: this.value() 10617 }; 10618 if ( this.options.values && this.options.values.length ) { 10619 uiHash.value = this.values( index ); 10620 uiHash.values = this.values(); 10621 } 10622 return this._trigger( "start", event, uiHash ); 10623 }, 10624 10625 _slide: function( event, index, newVal ) { 10626 var otherVal, 10627 newValues, 10628 allowed; 10629 10630 if ( this.options.values && this.options.values.length ) { 10631 otherVal = this.values( index ? 0 : 1 ); 10632 10633 if ( ( this.options.values.length === 2 && this.options.range === true ) && 10634 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) 10635 ) { 10636 newVal = otherVal; 10637 } 10638 10639 if ( newVal !== this.values( index ) ) { 10640 newValues = this.values(); 10641 newValues[ index ] = newVal; 10642 // A slide can be canceled by returning false from the slide callback 10643 allowed = this._trigger( "slide", event, { 10644 handle: this.handles[ index ], 10645 value: newVal, 10646 values: newValues 10647 } ); 10648 otherVal = this.values( index ? 0 : 1 ); 10649 if ( allowed !== false ) { 10650 this.values( index, newVal, true ); 10651 } 10652 } 10653 } else { 10654 if ( newVal !== this.value() ) { 10655 // A slide can be canceled by returning false from the slide callback 10656 allowed = this._trigger( "slide", event, { 10657 handle: this.handles[ index ], 10658 value: newVal 10659 } ); 10660 if ( allowed !== false ) { 10661 this.value( newVal ); 10662 } 10663 } 10664 } 10665 }, 10666 10667 _stop: function( event, index ) { 10668 var uiHash = { 10669 handle: this.handles[ index ], 10670 value: this.value() 10671 }; 10672 if ( this.options.values && this.options.values.length ) { 10673 uiHash.value = this.values( index ); 10674 uiHash.values = this.values(); 10675 } 10676 10677 this._trigger( "stop", event, uiHash ); 10678 }, 10679 10680 _change: function( event, index ) { 10681 if ( !this._keySliding && !this._mouseSliding ) { 10682 var uiHash = { 10683 handle: this.handles[ index ], 10684 value: this.value() 10685 }; 10686 if ( this.options.values && this.options.values.length ) { 10687 uiHash.value = this.values( index ); 10688 uiHash.values = this.values(); 10689 } 10690 10691 //store the last changed value index for reference when handles overlap 10692 this._lastChangedValue = index; 10693 10694 this._trigger( "change", event, uiHash ); 10695 } 10696 }, 10697 10698 value: function( newValue ) { 10699 if ( arguments.length ) { 10700 this.options.value = this._trimAlignValue( newValue ); 10701 this._refreshValue(); 10702 this._change( null, 0 ); 10703 return; 10704 } 10705 10706 return this._value(); 10707 }, 10708 10709 values: function( index, newValue ) { 10710 var vals, 10711 newValues, 10712 i; 10713 10714 if ( arguments.length > 1 ) { 10715 this.options.values[ index ] = this._trimAlignValue( newValue ); 10716 this._refreshValue(); 10717 this._change( null, index ); 10718 return; 10719 } 10720 10721 if ( arguments.length ) { 10722 if ( $.isArray( arguments[ 0 ] ) ) { 10723 vals = this.options.values; 10724 newValues = arguments[ 0 ]; 10725 for ( i = 0; i < vals.length; i += 1 ) { 10726 vals[ i ] = this._trimAlignValue( newValues[ i ] ); 10727 this._change( null, i ); 10728 } 10729 this._refreshValue(); 10730 } else { 10731 if ( this.options.values && this.options.values.length ) { 10732 return this._values( index ); 10733 } else { 10734 return this.value(); 10735 } 10736 } 10737 } else { 10738 return this._values(); 10739 } 10740 }, 10741 10742 _setOption: function( key, value ) { 10743 var i, 10744 valsLength = 0; 10745 10746 if ( key === "range" && this.options.range === true ) { 10747 if ( value === "min" ) { 10748 this.options.value = this._values( 0 ); 10749 this.options.values = null; 10750 } else if ( value === "max" ) { 10751 this.options.value = this._values( this.options.values.length-1 ); 10752 this.options.values = null; 10753 } 10754 } 10755 10756 if ( $.isArray( this.options.values ) ) { 10757 valsLength = this.options.values.length; 10758 } 10759 10760 $.Widget.prototype._setOption.apply( this, arguments ); 10761 10762 switch ( key ) { 10763 case "orientation": 10764 this._detectOrientation(); 10765 this.element 10766 .removeClass( "ui-slider-horizontal ui-slider-vertical" ) 10767 .addClass( "ui-slider-" + this.orientation ); 10768 this._refreshValue(); 10769 break; 10770 case "value": 10771 this._animateOff = true; 10772 this._refreshValue(); 10773 this._change( null, 0 ); 10774 this._animateOff = false; 10775 break; 10776 case "values": 10777 this._animateOff = true; 10778 this._refreshValue(); 10779 for ( i = 0; i < valsLength; i += 1 ) { 10780 this._change( null, i ); 10781 } 10782 this._animateOff = false; 10783 break; 10784 case "min": 10785 case "max": 10786 this._animateOff = true; 10787 this._refreshValue(); 10788 this._animateOff = false; 10789 break; 10790 case "range": 10791 this._animateOff = true; 10792 this._refresh(); 10793 this._animateOff = false; 10794 break; 10795 } 10796 }, 10797 10798 //internal value getter 10799 // _value() returns value trimmed by min and max, aligned by step 10800 _value: function() { 10801 var val = this.options.value; 10802 val = this._trimAlignValue( val ); 10803 10804 return val; 10805 }, 10806 10807 //internal values getter 10808 // _values() returns array of values trimmed by min and max, aligned by step 10809 // _values( index ) returns single value trimmed by min and max, aligned by step 10810 _values: function( index ) { 10811 var val, 10812 vals, 10813 i; 10814 10815 if ( arguments.length ) { 10816 val = this.options.values[ index ]; 10817 val = this._trimAlignValue( val ); 10818 10819 return val; 10820 } else if ( this.options.values && this.options.values.length ) { 10821 // .slice() creates a copy of the array 10822 // this copy gets trimmed by min and max and then returned 10823 vals = this.options.values.slice(); 10824 for ( i = 0; i < vals.length; i+= 1) { 10825 vals[ i ] = this._trimAlignValue( vals[ i ] ); 10826 } 10827 10828 return vals; 10829 } else { 10830 return []; 10831 } 10832 }, 10833 10834 // returns the step-aligned value that val is closest to, between (inclusive) min and max 10835 _trimAlignValue: function( val ) { 10836 if ( val <= this._valueMin() ) { 10837 return this._valueMin(); 10838 } 10839 if ( val >= this._valueMax() ) { 10840 return this._valueMax(); 10841 } 10842 var step = ( this.options.step > 0 ) ? this.options.step : 1, 10843 valModStep = (val - this._valueMin()) % step, 10844 alignValue = val - valModStep; 10845 10846 if ( Math.abs(valModStep) * 2 >= step ) { 10847 alignValue += ( valModStep > 0 ) ? step : ( -step ); 10848 } 10849 10850 // Since JavaScript has problems with large floats, round 10851 // the final value to 5 digits after the decimal point (see #4124) 10852 return parseFloat( alignValue.toFixed(5) ); 10853 }, 10854 10855 _valueMin: function() { 10856 return this.options.min; 10857 }, 10858 10859 _valueMax: function() { 10860 return this.options.max; 10861 }, 10862 10863 _refreshValue: function() { 10864 var lastValPercent, valPercent, value, valueMin, valueMax, 10865 oRange = this.options.range, 10866 o = this.options, 10867 that = this, 10868 animate = ( !this._animateOff ) ? o.animate : false, 10869 _set = {}; 10870 10871 if ( this.options.values && this.options.values.length ) { 10872 this.handles.each(function( i ) { 10873 valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100; 10874 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 10875 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 10876 if ( that.options.range === true ) { 10877 if ( that.orientation === "horizontal" ) { 10878 if ( i === 0 ) { 10879 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); 10880 } 10881 if ( i === 1 ) { 10882 that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); 10883 } 10884 } else { 10885 if ( i === 0 ) { 10886 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); 10887 } 10888 if ( i === 1 ) { 10889 that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); 10890 } 10891 } 10892 } 10893 lastValPercent = valPercent; 10894 }); 10895 } else { 10896 value = this.value(); 10897 valueMin = this._valueMin(); 10898 valueMax = this._valueMax(); 10899 valPercent = ( valueMax !== valueMin ) ? 10900 ( value - valueMin ) / ( valueMax - valueMin ) * 100 : 10901 0; 10902 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 10903 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 10904 10905 if ( oRange === "min" && this.orientation === "horizontal" ) { 10906 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); 10907 } 10908 if ( oRange === "max" && this.orientation === "horizontal" ) { 10909 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); 10910 } 10911 if ( oRange === "min" && this.orientation === "vertical" ) { 10912 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); 10913 } 10914 if ( oRange === "max" && this.orientation === "vertical" ) { 10915 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); 10916 } 10917 } 10918 }, 10919 10920 _handleEvents: { 10921 keydown: function( event ) { 10922 /*jshint maxcomplexity:25*/ 10923 var allowed, curVal, newVal, step, 10924 index = $( event.target ).data( "ui-slider-handle-index" ); 10925 10926 switch ( event.keyCode ) { 10927 case $.ui.keyCode.HOME: 10928 case $.ui.keyCode.END: 10929 case $.ui.keyCode.PAGE_UP: 10930 case $.ui.keyCode.PAGE_DOWN: 10931 case $.ui.keyCode.UP: 10932 case $.ui.keyCode.RIGHT: 10933 case $.ui.keyCode.DOWN: 10934 case $.ui.keyCode.LEFT: 10935 event.preventDefault(); 10936 if ( !this._keySliding ) { 10937 this._keySliding = true; 10938 $( event.target ).addClass( "ui-state-active" ); 10939 allowed = this._start( event, index ); 10940 if ( allowed === false ) { 10941 return; 10942 } 10943 } 10944 break; 10945 } 10946 10947 step = this.options.step; 10948 if ( this.options.values && this.options.values.length ) { 10949 curVal = newVal = this.values( index ); 10950 } else { 10951 curVal = newVal = this.value(); 10952 } 10953 10954 switch ( event.keyCode ) { 10955 case $.ui.keyCode.HOME: 10956 newVal = this._valueMin(); 10957 break; 10958 case $.ui.keyCode.END: 10959 newVal = this._valueMax(); 10960 break; 10961 case $.ui.keyCode.PAGE_UP: 10962 newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) ); 10963 break; 10964 case $.ui.keyCode.PAGE_DOWN: 10965 newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) ); 10966 break; 10967 case $.ui.keyCode.UP: 10968 case $.ui.keyCode.RIGHT: 10969 if ( curVal === this._valueMax() ) { 10970 return; 10971 } 10972 newVal = this._trimAlignValue( curVal + step ); 10973 break; 10974 case $.ui.keyCode.DOWN: 10975 case $.ui.keyCode.LEFT: 10976 if ( curVal === this._valueMin() ) { 10977 return; 10978 } 10979 newVal = this._trimAlignValue( curVal - step ); 10980 break; 10981 } 10982 10983 this._slide( event, index, newVal ); 10984 }, 10985 click: function( event ) { 10986 event.preventDefault(); 10987 }, 10988 keyup: function( event ) { 10989 var index = $( event.target ).data( "ui-slider-handle-index" ); 10990 10991 if ( this._keySliding ) { 10992 this._keySliding = false; 10993 this._stop( event, index ); 10994 this._change( event, index ); 10995 $( event.target ).removeClass( "ui-state-active" ); 10996 } 10997 } 10998 } 10999 11000}); 11001 11002}(jQuery)); 11003(function( $ ) { 11004 11005function modifier( fn ) { 11006 return function() { 11007 var previous = this.element.val(); 11008 fn.apply( this, arguments ); 11009 this._refresh(); 11010 if ( previous !== this.element.val() ) { 11011 this._trigger( "change" ); 11012 } 11013 }; 11014} 11015 11016$.widget( "ui.spinner", { 11017 version: "1.10.2", 11018 defaultElement: "<input>", 11019 widgetEventPrefix: "spin", 11020 options: { 11021 culture: null, 11022 icons: { 11023 down: "ui-icon-triangle-1-s", 11024 up: "ui-icon-triangle-1-n" 11025 }, 11026 incremental: true, 11027 max: null, 11028 min: null, 11029 numberFormat: null, 11030 page: 10, 11031 step: 1, 11032 11033 change: null, 11034 spin: null, 11035 start: null, 11036 stop: null 11037 }, 11038 11039 _create: function() { 11040 // handle string values that need to be parsed 11041 this._setOption( "max", this.options.max ); 11042 this._setOption( "min", this.options.min ); 11043 this._setOption( "step", this.options.step ); 11044 11045 // format the value, but don't constrain 11046 this._value( this.element.val(), true ); 11047 11048 this._draw(); 11049 this._on( this._events ); 11050 this._refresh(); 11051 11052 // turning off autocomplete prevents the browser from remembering the 11053 // value when navigating through history, so we re-enable autocomplete 11054 // if the page is unloaded before the widget is destroyed. #7790 11055 this._on( this.window, { 11056 beforeunload: function() { 11057 this.element.removeAttr( "autocomplete" ); 11058 } 11059 }); 11060 }, 11061 11062 _getCreateOptions: function() { 11063 var options = {}, 11064 element = this.element; 11065 11066 $.each( [ "min", "max", "step" ], function( i, option ) { 11067 var value = element.attr( option ); 11068 if ( value !== undefined && value.length ) { 11069 options[ option ] = value; 11070 } 11071 }); 11072 11073 return options; 11074 }, 11075 11076 _events: { 11077 keydown: function( event ) { 11078 if ( this._start( event ) && this._keydown( event ) ) { 11079 event.preventDefault(); 11080 } 11081 }, 11082 keyup: "_stop", 11083 focus: function() { 11084 this.previous = this.element.val(); 11085 }, 11086 blur: function( event ) { 11087 if ( this.cancelBlur ) { 11088 delete this.cancelBlur; 11089 return; 11090 } 11091 11092 this._stop(); 11093 this._refresh(); 11094 if ( this.previous !== this.element.val() ) { 11095 this._trigger( "change", event ); 11096 } 11097 }, 11098 mousewheel: function( event, delta ) { 11099 if ( !delta ) { 11100 return; 11101 } 11102 if ( !this.spinning && !this._start( event ) ) { 11103 return false; 11104 } 11105 11106 this._spin( (delta > 0 ? 1 : -1) * this.options.step, event ); 11107 clearTimeout( this.mousewheelTimer ); 11108 this.mousewheelTimer = this._delay(function() { 11109 if ( this.spinning ) { 11110 this._stop( event ); 11111 } 11112 }, 100 ); 11113 event.preventDefault(); 11114 }, 11115 "mousedown .ui-spinner-button": function( event ) { 11116 var previous; 11117 11118 // We never want the buttons to have focus; whenever the user is 11119 // interacting with the spinner, the focus should be on the input. 11120 // If the input is focused then this.previous is properly set from 11121 // when the input first received focus. If the input is not focused 11122 // then we need to set this.previous based on the value before spinning. 11123 previous = this.element[0] === this.document[0].activeElement ? 11124 this.previous : this.element.val(); 11125 function checkFocus() { 11126 var isActive = this.element[0] === this.document[0].activeElement; 11127 if ( !isActive ) { 11128 this.element.focus(); 11129 this.previous = previous; 11130 // support: IE 11131 // IE sets focus asynchronously, so we need to check if focus 11132 // moved off of the input because the user clicked on the button. 11133 this._delay(function() { 11134 this.previous = previous; 11135 }); 11136 } 11137 } 11138 11139 // ensure focus is on (or stays on) the text field 11140 event.preventDefault(); 11141 checkFocus.call( this ); 11142 11143 // support: IE 11144 // IE doesn't prevent moving focus even with event.preventDefault() 11145 // so we set a flag to know when we should ignore the blur event 11146 // and check (again) if focus moved off of the input. 11147 this.cancelBlur = true; 11148 this._delay(function() { 11149 delete this.cancelBlur; 11150 checkFocus.call( this ); 11151 }); 11152 11153 if ( this._start( event ) === false ) { 11154 return; 11155 } 11156 11157 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 11158 }, 11159 "mouseup .ui-spinner-button": "_stop", 11160 "mouseenter .ui-spinner-button": function( event ) { 11161 // button will add ui-state-active if mouse was down while mouseleave and kept down 11162 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) { 11163 return; 11164 } 11165 11166 if ( this._start( event ) === false ) { 11167 return false; 11168 } 11169 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 11170 }, 11171 // TODO: do we really want to consider this a stop? 11172 // shouldn't we just stop the repeater and wait until mouseup before 11173 // we trigger the stop event? 11174 "mouseleave .ui-spinner-button": "_stop" 11175 }, 11176 11177 _draw: function() { 11178 var uiSpinner = this.uiSpinner = this.element 11179 .addClass( "ui-spinner-input" ) 11180 .attr( "autocomplete", "off" ) 11181 .wrap( this._uiSpinnerHtml() ) 11182 .parent() 11183 // add buttons 11184 .append( this._buttonHtml() ); 11185 11186 this.element.attr( "role", "spinbutton" ); 11187 11188 // button bindings 11189 this.buttons = uiSpinner.find( ".ui-spinner-button" ) 11190 .attr( "tabIndex", -1 ) 11191 .button() 11192 .removeClass( "ui-corner-all" ); 11193 11194 // IE 6 doesn't understand height: 50% for the buttons 11195 // unless the wrapper has an explicit height 11196 if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) && 11197 uiSpinner.height() > 0 ) { 11198 uiSpinner.height( uiSpinner.height() ); 11199 } 11200 11201 // disable spinner if element was already disabled 11202 if ( this.options.disabled ) { 11203 this.disable(); 11204 } 11205 }, 11206 11207 _keydown: function( event ) { 11208 var options = this.options, 11209 keyCode = $.ui.keyCode; 11210 11211 switch ( event.keyCode ) { 11212 case keyCode.UP: 11213 this._repeat( null, 1, event ); 11214 return true; 11215 case keyCode.DOWN: 11216 this._repeat( null, -1, event ); 11217 return true; 11218 case keyCode.PAGE_UP: 11219 this._repeat( null, options.page, event ); 11220 return true; 11221 case keyCode.PAGE_DOWN: 11222 this._repeat( null, -options.page, event ); 11223 return true; 11224 } 11225 11226 return false; 11227 }, 11228 11229 _uiSpinnerHtml: function() { 11230 return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"; 11231 }, 11232 11233 _buttonHtml: function() { 11234 return "" + 11235 "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" + 11236 "<span class='ui-icon " + this.options.icons.up + "'>▲</span>" + 11237 "</a>" + 11238 "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" + 11239 "<span class='ui-icon " + this.options.icons.down + "'>▼</span>" + 11240 "</a>"; 11241 }, 11242 11243 _start: function( event ) { 11244 if ( !this.spinning && this._trigger( "start", event ) === false ) { 11245 return false; 11246 } 11247 11248 if ( !this.counter ) { 11249 this.counter = 1; 11250 } 11251 this.spinning = true; 11252 return true; 11253 }, 11254 11255 _repeat: function( i, steps, event ) { 11256 i = i || 500; 11257 11258 clearTimeout( this.timer ); 11259 this.timer = this._delay(function() { 11260 this._repeat( 40, steps, event ); 11261 }, i ); 11262 11263 this._spin( steps * this.options.step, event ); 11264 }, 11265 11266 _spin: function( step, event ) { 11267 var value = this.value() || 0; 11268 11269 if ( !this.counter ) { 11270 this.counter = 1; 11271 } 11272 11273 value = this._adjustValue( value + step * this._increment( this.counter ) ); 11274 11275 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) { 11276 this._value( value ); 11277 this.counter++; 11278 } 11279 }, 11280 11281 _increment: function( i ) { 11282 var incremental = this.options.incremental; 11283 11284 if ( incremental ) { 11285 return $.isFunction( incremental ) ? 11286 incremental( i ) : 11287 Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 ); 11288 } 11289 11290 return 1; 11291 }, 11292 11293 _precision: function() { 11294 var precision = this._precisionOf( this.options.step ); 11295 if ( this.options.min !== null ) { 11296 precision = Math.max( precision, this._precisionOf( this.options.min ) ); 11297 } 11298 return precision; 11299 }, 11300 11301 _precisionOf: function( num ) { 11302 var str = num.toString(), 11303 decimal = str.indexOf( "." ); 11304 return decimal === -1 ? 0 : str.length - decimal - 1; 11305 }, 11306 11307 _adjustValue: function( value ) { 11308 var base, aboveMin, 11309 options = this.options; 11310 11311 // make sure we're at a valid step 11312 // - find out where we are relative to the base (min or 0) 11313 base = options.min !== null ? options.min : 0; 11314 aboveMin = value - base; 11315 // - round to the nearest step 11316 aboveMin = Math.round(aboveMin / options.step) * options.step; 11317 // - rounding is based on 0, so adjust back to our base 11318 value = base + aboveMin; 11319 11320 // fix precision from bad JS floating point math 11321 value = parseFloat( value.toFixed( this._precision() ) ); 11322 11323 // clamp the value 11324 if ( options.max !== null && value > options.max) { 11325 return options.max; 11326 } 11327 if ( options.min !== null && value < options.min ) { 11328 return options.min; 11329 } 11330 11331 return value; 11332 }, 11333 11334 _stop: function( event ) { 11335 if ( !this.spinning ) { 11336 return; 11337 } 11338 11339 clearTimeout( this.timer ); 11340 clearTimeout( this.mousewheelTimer ); 11341 this.counter = 0; 11342 this.spinning = false; 11343 this._trigger( "stop", event ); 11344 }, 11345 11346 _setOption: function( key, value ) { 11347 if ( key === "culture" || key === "numberFormat" ) { 11348 var prevValue = this._parse( this.element.val() ); 11349 this.options[ key ] = value; 11350 this.element.val( this._format( prevValue ) ); 11351 return; 11352 } 11353 11354 if ( key === "max" || key === "min" || key === "step" ) { 11355 if ( typeof value === "string" ) { 11356 value = this._parse( value ); 11357 } 11358 } 11359 if ( key === "icons" ) { 11360 this.buttons.first().find( ".ui-icon" ) 11361 .removeClass( this.options.icons.up ) 11362 .addClass( value.up ); 11363 this.buttons.last().find( ".ui-icon" ) 11364 .removeClass( this.options.icons.down ) 11365 .addClass( value.down ); 11366 } 11367 11368 this._super( key, value ); 11369 11370 if ( key === "disabled" ) { 11371 if ( value ) { 11372 this.element.prop( "disabled", true ); 11373 this.buttons.button( "disable" ); 11374 } else { 11375 this.element.prop( "disabled", false ); 11376 this.buttons.button( "enable" ); 11377 } 11378 } 11379 }, 11380 11381 _setOptions: modifier(function( options ) { 11382 this._super( options ); 11383 this._value( this.element.val() ); 11384 }), 11385 11386 _parse: function( val ) { 11387 if ( typeof val === "string" && val !== "" ) { 11388 val = window.Globalize && this.options.numberFormat ? 11389 Globalize.parseFloat( val, 10, this.options.culture ) : +val; 11390 } 11391 return val === "" || isNaN( val ) ? null : val; 11392 }, 11393 11394 _format: function( value ) { 11395 if ( value === "" ) { 11396 return ""; 11397 } 11398 return window.Globalize && this.options.numberFormat ? 11399 Globalize.format( value, this.options.numberFormat, this.options.culture ) : 11400 value; 11401 }, 11402 11403 _refresh: function() { 11404 this.element.attr({ 11405 "aria-valuemin": this.options.min, 11406 "aria-valuemax": this.options.max, 11407 // TODO: what should we do with values that can't be parsed? 11408 "aria-valuenow": this._parse( this.element.val() ) 11409 }); 11410 }, 11411 11412 // update the value without triggering change 11413 _value: function( value, allowAny ) { 11414 var parsed; 11415 if ( value !== "" ) { 11416 parsed = this._parse( value ); 11417 if ( parsed !== null ) { 11418 if ( !allowAny ) { 11419 parsed = this._adjustValue( parsed ); 11420 } 11421 value = this._format( parsed ); 11422 } 11423 } 11424 this.element.val( value ); 11425 this._refresh(); 11426 }, 11427 11428 _destroy: function() { 11429 this.element 11430 .removeClass( "ui-spinner-input" ) 11431 .prop( "disabled", false ) 11432 .removeAttr( "autocomplete" ) 11433 .removeAttr( "role" ) 11434 .removeAttr( "aria-valuemin" ) 11435 .removeAttr( "aria-valuemax" ) 11436 .removeAttr( "aria-valuenow" ); 11437 this.uiSpinner.replaceWith( this.element ); 11438 }, 11439 11440 stepUp: modifier(function( steps ) { 11441 this._stepUp( steps ); 11442 }), 11443 _stepUp: function( steps ) { 11444 if ( this._start() ) { 11445 this._spin( (steps || 1) * this.options.step ); 11446 this._stop(); 11447 } 11448 }, 11449 11450 stepDown: modifier(function( steps ) { 11451 this._stepDown( steps ); 11452 }), 11453 _stepDown: function( steps ) { 11454 if ( this._start() ) { 11455 this._spin( (steps || 1) * -this.options.step ); 11456 this._stop(); 11457 } 11458 }, 11459 11460 pageUp: modifier(function( pages ) { 11461 this._stepUp( (pages || 1) * this.options.page ); 11462 }), 11463 11464 pageDown: modifier(function( pages ) { 11465 this._stepDown( (pages || 1) * this.options.page ); 11466 }), 11467 11468 value: function( newVal ) { 11469 if ( !arguments.length ) { 11470 return this._parse( this.element.val() ); 11471 } 11472 modifier( this._value ).call( this, newVal ); 11473 }, 11474 11475 widget: function() { 11476 return this.uiSpinner; 11477 } 11478}); 11479 11480}( jQuery ) ); 11481(function( $, undefined ) { 11482 11483var tabId = 0, 11484 rhash = /#.*$/; 11485 11486function getNextTabId() { 11487 return ++tabId; 11488} 11489 11490function isLocal( anchor ) { 11491 return anchor.hash.length > 1 && 11492 decodeURIComponent( anchor.href.replace( rhash, "" ) ) === 11493 decodeURIComponent( location.href.replace( rhash, "" ) ); 11494} 11495 11496$.widget( "ui.tabs", { 11497 version: "1.10.2", 11498 delay: 300, 11499 options: { 11500 active: null, 11501 collapsible: false, 11502 event: "click", 11503 heightStyle: "content", 11504 hide: null, 11505 show: null, 11506 11507 // callbacks 11508 activate: null, 11509 beforeActivate: null, 11510 beforeLoad: null, 11511 load: null 11512 }, 11513 11514 _create: function() { 11515 var that = this, 11516 options = this.options; 11517 11518 this.running = false; 11519 11520 this.element 11521 .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ) 11522 .toggleClass( "ui-tabs-collapsible", options.collapsible ) 11523 // Prevent users from focusing disabled tabs via click 11524 .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) { 11525 if ( $( this ).is( ".ui-state-disabled" ) ) { 11526 event.preventDefault(); 11527 } 11528 }) 11529 // support: IE <9 11530 // Preventing the default action in mousedown doesn't prevent IE 11531 // from focusing the element, so if the anchor gets focused, blur. 11532 // We don't have to worry about focusing the previously focused 11533 // element since clicking on a non-focusable element should focus 11534 // the body anyway. 11535 .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() { 11536 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) { 11537 this.blur(); 11538 } 11539 }); 11540 11541 this._processTabs(); 11542 options.active = this._initialActive(); 11543 11544 // Take disabling tabs via class attribute from HTML 11545 // into account and update option properly. 11546 if ( $.isArray( options.disabled ) ) { 11547 options.disabled = $.unique( options.disabled.concat( 11548 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { 11549 return that.tabs.index( li ); 11550 }) 11551 ) ).sort(); 11552 } 11553 11554 // check for length avoids error when initializing empty list 11555 if ( this.options.active !== false && this.anchors.length ) { 11556 this.active = this._findActive( options.active ); 11557 } else { 11558 this.active = $(); 11559 } 11560 11561 this._refresh(); 11562 11563 if ( this.active.length ) { 11564 this.load( options.active ); 11565 } 11566 }, 11567 11568 _initialActive: function() { 11569 var active = this.options.active, 11570 collapsible = this.options.collapsible, 11571 locationHash = location.hash.substring( 1 ); 11572 11573 if ( active === null ) { 11574 // check the fragment identifier in the URL 11575 if ( locationHash ) { 11576 this.tabs.each(function( i, tab ) { 11577 if ( $( tab ).attr( "aria-controls" ) === locationHash ) { 11578 active = i; 11579 return false; 11580 } 11581 }); 11582 } 11583 11584 // check for a tab marked active via a class 11585 if ( active === null ) { 11586 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); 11587 } 11588 11589 // no active tab, set to false 11590 if ( active === null || active === -1 ) { 11591 active = this.tabs.length ? 0 : false; 11592 } 11593 } 11594 11595 // handle numbers: negative, out of range 11596 if ( active !== false ) { 11597 active = this.tabs.index( this.tabs.eq( active ) ); 11598 if ( active === -1 ) { 11599 active = collapsible ? false : 0; 11600 } 11601 } 11602 11603 // don't allow collapsible: false and active: false 11604 if ( !collapsible && active === false && this.anchors.length ) { 11605 active = 0; 11606 } 11607 11608 return active; 11609 }, 11610 11611 _getCreateEventData: function() { 11612 return { 11613 tab: this.active, 11614 panel: !this.active.length ? $() : this._getPanelForTab( this.active ) 11615 }; 11616 }, 11617 11618 _tabKeydown: function( event ) { 11619 /*jshint maxcomplexity:15*/ 11620 var focusedTab = $( this.document[0].activeElement ).closest( "li" ), 11621 selectedIndex = this.tabs.index( focusedTab ), 11622 goingForward = true; 11623 11624 if ( this._handlePageNav( event ) ) { 11625 return; 11626 } 11627 11628 switch ( event.keyCode ) { 11629 case $.ui.keyCode.RIGHT: 11630 case $.ui.keyCode.DOWN: 11631 selectedIndex++; 11632 break; 11633 case $.ui.keyCode.UP: 11634 case $.ui.keyCode.LEFT: 11635 goingForward = false; 11636 selectedIndex--; 11637 break; 11638 case $.ui.keyCode.END: 11639 selectedIndex = this.anchors.length - 1; 11640 break; 11641 case $.ui.keyCode.HOME: 11642 selectedIndex = 0; 11643 break; 11644 case $.ui.keyCode.SPACE: 11645 // Activate only, no collapsing 11646 event.preventDefault(); 11647 clearTimeout( this.activating ); 11648 this._activate( selectedIndex ); 11649 return; 11650 case $.ui.keyCode.ENTER: 11651 // Toggle (cancel delayed activation, allow collapsing) 11652 event.preventDefault(); 11653 clearTimeout( this.activating ); 11654 // Determine if we should collapse or activate 11655 this._activate( selectedIndex === this.options.active ? false : selectedIndex ); 11656 return; 11657 default: 11658 return; 11659 } 11660 11661 // Focus the appropriate tab, based on which key was pressed 11662 event.preventDefault(); 11663 clearTimeout( this.activating ); 11664 selectedIndex = this._focusNextTab( selectedIndex, goingForward ); 11665 11666 // Navigating with control key will prevent automatic activation 11667 if ( !event.ctrlKey ) { 11668 // Update aria-selected immediately so that AT think the tab is already selected. 11669 // Otherwise AT may confuse the user by stating that they need to activate the tab, 11670 // but the tab will already be activated by the time the announcement finishes. 11671 focusedTab.attr( "aria-selected", "false" ); 11672 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); 11673 11674 this.activating = this._delay(function() { 11675 this.option( "active", selectedIndex ); 11676 }, this.delay ); 11677 } 11678 }, 11679 11680 _panelKeydown: function( event ) { 11681 if ( this._handlePageNav( event ) ) { 11682 return; 11683 } 11684 11685 // Ctrl+up moves focus to the current tab 11686 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { 11687 event.preventDefault(); 11688 this.active.focus(); 11689 } 11690 }, 11691 11692 // Alt+page up/down moves focus to the previous/next tab (and activates) 11693 _handlePageNav: function( event ) { 11694 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { 11695 this._activate( this._focusNextTab( this.options.active - 1, false ) ); 11696 return true; 11697 } 11698 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { 11699 this._activate( this._focusNextTab( this.options.active + 1, true ) ); 11700 return true; 11701 } 11702 }, 11703 11704 _findNextTab: function( index, goingForward ) { 11705 var lastTabIndex = this.tabs.length - 1; 11706 11707 function constrain() { 11708 if ( index > lastTabIndex ) { 11709 index = 0; 11710 } 11711 if ( index < 0 ) { 11712 index = lastTabIndex; 11713 } 11714 return index; 11715 } 11716 11717 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { 11718 index = goingForward ? index + 1 : index - 1; 11719 } 11720 11721 return index; 11722 }, 11723 11724 _focusNextTab: function( index, goingForward ) { 11725 index = this._findNextTab( index, goingForward ); 11726 this.tabs.eq( index ).focus(); 11727 return index; 11728 }, 11729 11730 _setOption: function( key, value ) { 11731 if ( key === "active" ) { 11732 // _activate() will handle invalid values and update this.options 11733 this._activate( value ); 11734 return; 11735 } 11736 11737 if ( key === "disabled" ) { 11738 // don't use the widget factory's disabled handling 11739 this._setupDisabled( value ); 11740 return; 11741 } 11742 11743 this._super( key, value); 11744 11745 if ( key === "collapsible" ) { 11746 this.element.toggleClass( "ui-tabs-collapsible", value ); 11747 // Setting collapsible: false while collapsed; open first panel 11748 if ( !value && this.options.active === false ) { 11749 this._activate( 0 ); 11750 } 11751 } 11752 11753 if ( key === "event" ) { 11754 this._setupEvents( value ); 11755 } 11756 11757 if ( key === "heightStyle" ) { 11758 this._setupHeightStyle( value ); 11759 } 11760 }, 11761 11762 _tabId: function( tab ) { 11763 return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId(); 11764 }, 11765 11766 _sanitizeSelector: function( hash ) { 11767 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : ""; 11768 }, 11769 11770 refresh: function() { 11771 var options = this.options, 11772 lis = this.tablist.children( ":has(a[href])" ); 11773 11774 // get disabled tabs from class attribute from HTML 11775 // this will get converted to a boolean if needed in _refresh() 11776 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { 11777 return lis.index( tab ); 11778 }); 11779 11780 this._processTabs(); 11781 11782 // was collapsed or no tabs 11783 if ( options.active === false || !this.anchors.length ) { 11784 options.active = false; 11785 this.active = $(); 11786 // was active, but active tab is gone 11787 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { 11788 // all remaining tabs are disabled 11789 if ( this.tabs.length === options.disabled.length ) { 11790 options.active = false; 11791 this.active = $(); 11792 // activate previous tab 11793 } else { 11794 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); 11795 } 11796 // was active, active tab still exists 11797 } else { 11798 // make sure active index is correct 11799 options.active = this.tabs.index( this.active ); 11800 } 11801 11802 this._refresh(); 11803 }, 11804 11805 _refresh: function() { 11806 this._setupDisabled( this.options.disabled ); 11807 this._setupEvents( this.options.event ); 11808 this._setupHeightStyle( this.options.heightStyle ); 11809 11810 this.tabs.not( this.active ).attr({ 11811 "aria-selected": "false", 11812 tabIndex: -1 11813 }); 11814 this.panels.not( this._getPanelForTab( this.active ) ) 11815 .hide() 11816 .attr({ 11817 "aria-expanded": "false", 11818 "aria-hidden": "true" 11819 }); 11820 11821 // Make sure one tab is in the tab order 11822 if ( !this.active.length ) { 11823 this.tabs.eq( 0 ).attr( "tabIndex", 0 ); 11824 } else { 11825 this.active 11826 .addClass( "ui-tabs-active ui-state-active" ) 11827 .attr({ 11828 "aria-selected": "true", 11829 tabIndex: 0 11830 }); 11831 this._getPanelForTab( this.active ) 11832 .show() 11833 .attr({ 11834 "aria-expanded": "true", 11835 "aria-hidden": "false" 11836 }); 11837 } 11838 }, 11839 11840 _processTabs: function() { 11841 var that = this; 11842 11843 this.tablist = this._getList() 11844 .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) 11845 .attr( "role", "tablist" ); 11846 11847 this.tabs = this.tablist.find( "> li:has(a[href])" ) 11848 .addClass( "ui-state-default ui-corner-top" ) 11849 .attr({ 11850 role: "tab", 11851 tabIndex: -1 11852 }); 11853 11854 this.anchors = this.tabs.map(function() { 11855 return $( "a", this )[ 0 ]; 11856 }) 11857 .addClass( "ui-tabs-anchor" ) 11858 .attr({ 11859 role: "presentation", 11860 tabIndex: -1 11861 }); 11862 11863 this.panels = $(); 11864 11865 this.anchors.each(function( i, anchor ) { 11866 var selector, panel, panelId, 11867 anchorId = $( anchor ).uniqueId().attr( "id" ), 11868 tab = $( anchor ).closest( "li" ), 11869 originalAriaControls = tab.attr( "aria-controls" ); 11870 11871 // inline tab 11872 if ( isLocal( anchor ) ) { 11873 selector = anchor.hash; 11874 panel = that.element.find( that._sanitizeSelector( selector ) ); 11875 // remote tab 11876 } else { 11877 panelId = that._tabId( tab ); 11878 selector = "#" + panelId; 11879 panel = that.element.find( selector ); 11880 if ( !panel.length ) { 11881 panel = that._createPanel( panelId ); 11882 panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); 11883 } 11884 panel.attr( "aria-live", "polite" ); 11885 } 11886 11887 if ( panel.length) { 11888 that.panels = that.panels.add( panel ); 11889 } 11890 if ( originalAriaControls ) { 11891 tab.data( "ui-tabs-aria-controls", originalAriaControls ); 11892 } 11893 tab.attr({ 11894 "aria-controls": selector.substring( 1 ), 11895 "aria-labelledby": anchorId 11896 }); 11897 panel.attr( "aria-labelledby", anchorId ); 11898 }); 11899 11900 this.panels 11901 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) 11902 .attr( "role", "tabpanel" ); 11903 }, 11904 11905 // allow overriding how to find the list for rare usage scenarios (#7715) 11906 _getList: function() { 11907 return this.element.find( "ol,ul" ).eq( 0 ); 11908 }, 11909 11910 _createPanel: function( id ) { 11911 return $( "<div>" ) 11912 .attr( "id", id ) 11913 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) 11914 .data( "ui-tabs-destroy", true ); 11915 }, 11916 11917 _setupDisabled: function( disabled ) { 11918 if ( $.isArray( disabled ) ) { 11919 if ( !disabled.length ) { 11920 disabled = false; 11921 } else if ( disabled.length === this.anchors.length ) { 11922 disabled = true; 11923 } 11924 } 11925 11926 // disable tabs 11927 for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) { 11928 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { 11929 $( li ) 11930 .addClass( "ui-state-disabled" ) 11931 .attr( "aria-disabled", "true" ); 11932 } else { 11933 $( li ) 11934 .removeClass( "ui-state-disabled" ) 11935 .removeAttr( "aria-disabled" ); 11936 } 11937 } 11938 11939 this.options.disabled = disabled; 11940 }, 11941 11942 _setupEvents: function( event ) { 11943 var events = { 11944 click: function( event ) { 11945 event.preventDefault(); 11946 } 11947 }; 11948 if ( event ) { 11949 $.each( event.split(" "), function( index, eventName ) { 11950 events[ eventName ] = "_eventHandler"; 11951 }); 11952 } 11953 11954 this._off( this.anchors.add( this.tabs ).add( this.panels ) ); 11955 this._on( this.anchors, events ); 11956 this._on( this.tabs, { keydown: "_tabKeydown" } ); 11957 this._on( this.panels, { keydown: "_panelKeydown" } ); 11958 11959 this._focusable( this.tabs ); 11960 this._hoverable( this.tabs ); 11961 }, 11962 11963 _setupHeightStyle: function( heightStyle ) { 11964 var maxHeight, 11965 parent = this.element.parent(); 11966 11967 if ( heightStyle === "fill" ) { 11968 maxHeight = parent.height(); 11969 maxHeight -= this.element.outerHeight() - this.element.height(); 11970 11971 this.element.siblings( ":visible" ).each(function() { 11972 var elem = $( this ), 11973 position = elem.css( "position" ); 11974 11975 if ( position === "absolute" || position === "fixed" ) { 11976 return; 11977 } 11978 maxHeight -= elem.outerHeight( true ); 11979 }); 11980 11981 this.element.children().not( this.panels ).each(function() { 11982 maxHeight -= $( this ).outerHeight( true ); 11983 }); 11984 11985 this.panels.each(function() { 11986 $( this ).height( Math.max( 0, maxHeight - 11987 $( this ).innerHeight() + $( this ).height() ) ); 11988 }) 11989 .css( "overflow", "auto" ); 11990 } else if ( heightStyle === "auto" ) { 11991 maxHeight = 0; 11992 this.panels.each(function() { 11993 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); 11994 }).height( maxHeight ); 11995 } 11996 }, 11997 11998 _eventHandler: function( event ) { 11999 var options = this.options, 12000 active = this.active, 12001 anchor = $( event.currentTarget ), 12002 tab = anchor.closest( "li" ), 12003 clickedIsActive = tab[ 0 ] === active[ 0 ], 12004 collapsing = clickedIsActive && options.collapsible, 12005 toShow = collapsing ? $() : this._getPanelForTab( tab ), 12006 toHide = !active.length ? $() : this._getPanelForTab( active ), 12007 eventData = { 12008 oldTab: active, 12009 oldPanel: toHide, 12010 newTab: collapsing ? $() : tab, 12011 newPanel: toShow 12012 }; 12013 12014 event.preventDefault(); 12015 12016 if ( tab.hasClass( "ui-state-disabled" ) || 12017 // tab is already loading 12018 tab.hasClass( "ui-tabs-loading" ) || 12019 // can't switch durning an animation 12020 this.running || 12021 // click on active header, but not collapsible 12022 ( clickedIsActive && !options.collapsible ) || 12023 // allow canceling activation 12024 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 12025 return; 12026 } 12027 12028 options.active = collapsing ? false : this.tabs.index( tab ); 12029 12030 this.active = clickedIsActive ? $() : tab; 12031 if ( this.xhr ) { 12032 this.xhr.abort(); 12033 } 12034 12035 if ( !toHide.length && !toShow.length ) { 12036 $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); 12037 } 12038 12039 if ( toShow.length ) { 12040 this.load( this.tabs.index( tab ), event ); 12041 } 12042 this._toggle( event, eventData ); 12043 }, 12044 12045 // handles show/hide for selecting tabs 12046 _toggle: function( event, eventData ) { 12047 var that = this, 12048 toShow = eventData.newPanel, 12049 toHide = eventData.oldPanel; 12050 12051 this.running = true; 12052 12053 function complete() { 12054 that.running = false; 12055 that._trigger( "activate", event, eventData ); 12056 } 12057 12058 function show() { 12059 eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); 12060 12061 if ( toShow.length && that.options.show ) { 12062 that._show( toShow, that.options.show, complete ); 12063 } else { 12064 toShow.show(); 12065 complete(); 12066 } 12067 } 12068 12069 // start out by hiding, then showing, then completing 12070 if ( toHide.length && this.options.hide ) { 12071 this._hide( toHide, this.options.hide, function() { 12072 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); 12073 show(); 12074 }); 12075 } else { 12076 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); 12077 toHide.hide(); 12078 show(); 12079 } 12080 12081 toHide.attr({ 12082 "aria-expanded": "false", 12083 "aria-hidden": "true" 12084 }); 12085 eventData.oldTab.attr( "aria-selected", "false" ); 12086 // If we're switching tabs, remove the old tab from the tab order. 12087 // If we're opening from collapsed state, remove the previous tab from the tab order. 12088 // If we're collapsing, then keep the collapsing tab in the tab order. 12089 if ( toShow.length && toHide.length ) { 12090 eventData.oldTab.attr( "tabIndex", -1 ); 12091 } else if ( toShow.length ) { 12092 this.tabs.filter(function() { 12093 return $( this ).attr( "tabIndex" ) === 0; 12094 }) 12095 .attr( "tabIndex", -1 ); 12096 } 12097 12098 toShow.attr({ 12099 "aria-expanded": "true", 12100 "aria-hidden": "false" 12101 }); 12102 eventData.newTab.attr({ 12103 "aria-selected": "true", 12104 tabIndex: 0 12105 }); 12106 }, 12107 12108 _activate: function( index ) { 12109 var anchor, 12110 active = this._findActive( index ); 12111 12112 // trying to activate the already active panel 12113 if ( active[ 0 ] === this.active[ 0 ] ) { 12114 return; 12115 } 12116 12117 // trying to collapse, simulate a click on the current active header 12118 if ( !active.length ) { 12119 active = this.active; 12120 } 12121 12122 anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; 12123 this._eventHandler({ 12124 target: anchor, 12125 currentTarget: anchor, 12126 preventDefault: $.noop 12127 }); 12128 }, 12129 12130 _findActive: function( index ) { 12131 return index === false ? $() : this.tabs.eq( index ); 12132 }, 12133 12134 _getIndex: function( index ) { 12135 // meta-function to give users option to provide a href string instead of a numerical index. 12136 if ( typeof index === "string" ) { 12137 index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) ); 12138 } 12139 12140 return index; 12141 }, 12142 12143 _destroy: function() { 12144 if ( this.xhr ) { 12145 this.xhr.abort(); 12146 } 12147 12148 this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ); 12149 12150 this.tablist 12151 .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) 12152 .removeAttr( "role" ); 12153 12154 this.anchors 12155 .removeClass( "ui-tabs-anchor" ) 12156 .removeAttr( "role" ) 12157 .removeAttr( "tabIndex" ) 12158 .removeUniqueId(); 12159 12160 this.tabs.add( this.panels ).each(function() { 12161 if ( $.data( this, "ui-tabs-destroy" ) ) { 12162 $( this ).remove(); 12163 } else { 12164 $( this ) 12165 .removeClass( "ui-state-default ui-state-active ui-state-disabled " + 12166 "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" ) 12167 .removeAttr( "tabIndex" ) 12168 .removeAttr( "aria-live" ) 12169 .removeAttr( "aria-busy" ) 12170 .removeAttr( "aria-selected" ) 12171 .removeAttr( "aria-labelledby" ) 12172 .removeAttr( "aria-hidden" ) 12173 .removeAttr( "aria-expanded" ) 12174 .removeAttr( "role" ); 12175 } 12176 }); 12177 12178 this.tabs.each(function() { 12179 var li = $( this ), 12180 prev = li.data( "ui-tabs-aria-controls" ); 12181 if ( prev ) { 12182 li 12183 .attr( "aria-controls", prev ) 12184 .removeData( "ui-tabs-aria-controls" ); 12185 } else { 12186 li.removeAttr( "aria-controls" ); 12187 } 12188 }); 12189 12190 this.panels.show(); 12191 12192 if ( this.options.heightStyle !== "content" ) { 12193 this.panels.css( "height", "" ); 12194 } 12195 }, 12196 12197 enable: function( index ) { 12198 var disabled = this.options.disabled; 12199 if ( disabled === false ) { 12200 return; 12201 } 12202 12203 if ( index === undefined ) { 12204 disabled = false; 12205 } else { 12206 index = this._getIndex( index ); 12207 if ( $.isArray( disabled ) ) { 12208 disabled = $.map( disabled, function( num ) { 12209 return num !== index ? num : null; 12210 }); 12211 } else { 12212 disabled = $.map( this.tabs, function( li, num ) { 12213 return num !== index ? num : null; 12214 }); 12215 } 12216 } 12217 this._setupDisabled( disabled ); 12218 }, 12219 12220 disable: function( index ) { 12221 var disabled = this.options.disabled; 12222 if ( disabled === true ) { 12223 return; 12224 } 12225 12226 if ( index === undefined ) { 12227 disabled = true; 12228 } else { 12229 index = this._getIndex( index ); 12230 if ( $.inArray( index, disabled ) !== -1 ) { 12231 return; 12232 } 12233 if ( $.isArray( disabled ) ) { 12234 disabled = $.merge( [ index ], disabled ).sort(); 12235 } else { 12236 disabled = [ index ]; 12237 } 12238 } 12239 this._setupDisabled( disabled ); 12240 }, 12241 12242 load: function( index, event ) { 12243 index = this._getIndex( index ); 12244 var that = this, 12245 tab = this.tabs.eq( index ), 12246 anchor = tab.find( ".ui-tabs-anchor" ), 12247 panel = this._getPanelForTab( tab ), 12248 eventData = { 12249 tab: tab, 12250 panel: panel 12251 }; 12252 12253 // not remote 12254 if ( isLocal( anchor[ 0 ] ) ) { 12255 return; 12256 } 12257 12258 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); 12259 12260 // support: jQuery <1.8 12261 // jQuery <1.8 returns false if the request is canceled in beforeSend, 12262 // but as of 1.8, $.ajax() always returns a jqXHR object. 12263 if ( this.xhr && this.xhr.statusText !== "canceled" ) { 12264 tab.addClass( "ui-tabs-loading" ); 12265 panel.attr( "aria-busy", "true" ); 12266 12267 this.xhr 12268 .success(function( response ) { 12269 // support: jQuery <1.8 12270 // http://bugs.jquery.com/ticket/11778 12271 setTimeout(function() { 12272 panel.html( response ); 12273 that._trigger( "load", event, eventData ); 12274 }, 1 ); 12275 }) 12276 .complete(function( jqXHR, status ) { 12277 // support: jQuery <1.8 12278 // http://bugs.jquery.com/ticket/11778 12279 setTimeout(function() { 12280 if ( status === "abort" ) { 12281 that.panels.stop( false, true ); 12282 } 12283 12284 tab.removeClass( "ui-tabs-loading" ); 12285 panel.removeAttr( "aria-busy" ); 12286 12287 if ( jqXHR === that.xhr ) { 12288 delete that.xhr; 12289 } 12290 }, 1 ); 12291 }); 12292 } 12293 }, 12294 12295 _ajaxSettings: function( anchor, event, eventData ) { 12296 var that = this; 12297 return { 12298 url: anchor.attr( "href" ), 12299 beforeSend: function( jqXHR, settings ) { 12300 return that._trigger( "beforeLoad", event, 12301 $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) ); 12302 } 12303 }; 12304 }, 12305 12306 _getPanelForTab: function( tab ) { 12307 var id = $( tab ).attr( "aria-controls" ); 12308 return this.element.find( this._sanitizeSelector( "#" + id ) ); 12309 } 12310}); 12311 12312})( jQuery ); 12313(function( $ ) { 12314 12315var increments = 0; 12316 12317function addDescribedBy( elem, id ) { 12318 var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ); 12319 describedby.push( id ); 12320 elem 12321 .data( "ui-tooltip-id", id ) 12322 .attr( "aria-describedby", $.trim( describedby.join( " " ) ) ); 12323} 12324 12325function removeDescribedBy( elem ) { 12326 var id = elem.data( "ui-tooltip-id" ), 12327 describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ), 12328 index = $.inArray( id, describedby ); 12329 if ( index !== -1 ) { 12330 describedby.splice( index, 1 ); 12331 } 12332 12333 elem.removeData( "ui-tooltip-id" ); 12334 describedby = $.trim( describedby.join( " " ) ); 12335 if ( describedby ) { 12336 elem.attr( "aria-describedby", describedby ); 12337 } else { 12338 elem.removeAttr( "aria-describedby" ); 12339 } 12340} 12341 12342$.widget( "ui.tooltip", { 12343 version: "1.10.2", 12344 options: { 12345 content: function() { 12346 // support: IE<9, Opera in jQuery <1.7 12347 // .text() can't accept undefined, so coerce to a string 12348 var title = $( this ).attr( "title" ) || ""; 12349 // Escape title, since we're going from an attribute to raw HTML 12350 return $( "<a>" ).text( title ).html(); 12351 }, 12352 hide: true, 12353 // Disabled elements have inconsistent behavior across browsers (#8661) 12354 items: "[title]:not([disabled])", 12355 position: { 12356 my: "left top+15", 12357 at: "left bottom", 12358 collision: "flipfit flip" 12359 }, 12360 show: true, 12361 tooltipClass: null, 12362 track: false, 12363 12364 // callbacks 12365 close: null, 12366 open: null 12367 }, 12368 12369 _create: function() { 12370 this._on({ 12371 mouseover: "open", 12372 focusin: "open" 12373 }); 12374 12375 // IDs of generated tooltips, needed for destroy 12376 this.tooltips = {}; 12377 // IDs of parent tooltips where we removed the title attribute 12378 this.parents = {}; 12379 12380 if ( this.options.disabled ) { 12381 this._disable(); 12382 } 12383 }, 12384 12385 _setOption: function( key, value ) { 12386 var that = this; 12387 12388 if ( key === "disabled" ) { 12389 this[ value ? "_disable" : "_enable" ](); 12390 this.options[ key ] = value; 12391 // disable element style changes 12392 return; 12393 } 12394 12395 this._super( key, value ); 12396 12397 if ( key === "content" ) { 12398 $.each( this.tooltips, function( id, element ) { 12399 that._updateContent( element ); 12400 }); 12401 } 12402 }, 12403 12404 _disable: function() { 12405 var that = this; 12406 12407 // close open tooltips 12408 $.each( this.tooltips, function( id, element ) { 12409 var event = $.Event( "blur" ); 12410 event.target = event.currentTarget = element[0]; 12411 that.close( event, true ); 12412 }); 12413 12414 // remove title attributes to prevent native tooltips 12415 this.element.find( this.options.items ).addBack().each(function() { 12416 var element = $( this ); 12417 if ( element.is( "[title]" ) ) { 12418 element 12419 .data( "ui-tooltip-title", element.attr( "title" ) ) 12420 .attr( "title", "" ); 12421 } 12422 }); 12423 }, 12424 12425 _enable: function() { 12426 // restore title attributes 12427 this.element.find( this.options.items ).addBack().each(function() { 12428 var element = $( this ); 12429 if ( element.data( "ui-tooltip-title" ) ) { 12430 element.attr( "title", element.data( "ui-tooltip-title" ) ); 12431 } 12432 }); 12433 }, 12434 12435 open: function( event ) { 12436 var that = this, 12437 target = $( event ? event.target : this.element ) 12438 // we need closest here due to mouseover bubbling, 12439 // but always pointing at the same event target 12440 .closest( this.options.items ); 12441 12442 // No element to show a tooltip for or the tooltip is already open 12443 if ( !target.length || target.data( "ui-tooltip-id" ) ) { 12444 return; 12445 } 12446 12447 if ( target.attr( "title" ) ) { 12448 target.data( "ui-tooltip-title", target.attr( "title" ) ); 12449 } 12450 12451 target.data( "ui-tooltip-open", true ); 12452 12453 // kill parent tooltips, custom or native, for hover 12454 if ( event && event.type === "mouseover" ) { 12455 target.parents().each(function() { 12456 var parent = $( this ), 12457 blurEvent; 12458 if ( parent.data( "ui-tooltip-open" ) ) { 12459 blurEvent = $.Event( "blur" ); 12460 blurEvent.target = blurEvent.currentTarget = this; 12461 that.close( blurEvent, true ); 12462 } 12463 if ( parent.attr( "title" ) ) { 12464 parent.uniqueId(); 12465 that.parents[ this.id ] = { 12466 element: this, 12467 title: parent.attr( "title" ) 12468 }; 12469 parent.attr( "title", "" ); 12470 } 12471 }); 12472 } 12473 12474 this._updateContent( target, event ); 12475 }, 12476 12477 _updateContent: function( target, event ) { 12478 var content, 12479 contentOption = this.options.content, 12480 that = this, 12481 eventType = event ? event.type : null; 12482 12483 if ( typeof contentOption === "string" ) { 12484 return this._open( event, target, contentOption ); 12485 } 12486 12487 content = contentOption.call( target[0], function( response ) { 12488 // ignore async response if tooltip was closed already 12489 if ( !target.data( "ui-tooltip-open" ) ) { 12490 return; 12491 } 12492 // IE may instantly serve a cached response for ajax requests 12493 // delay this call to _open so the other call to _open runs first 12494 that._delay(function() { 12495 // jQuery creates a special event for focusin when it doesn't 12496 // exist natively. To improve performance, the native event 12497 // object is reused and the type is changed. Therefore, we can't 12498 // rely on the type being correct after the event finished 12499 // bubbling, so we set it back to the previous value. (#8740) 12500 if ( event ) { 12501 event.type = eventType; 12502 } 12503 this._open( event, target, response ); 12504 }); 12505 }); 12506 if ( content ) { 12507 this._open( event, target, content ); 12508 } 12509 }, 12510 12511 _open: function( event, target, content ) { 12512 var tooltip, events, delayedShow, 12513 positionOption = $.extend( {}, this.options.position ); 12514 12515 if ( !content ) { 12516 return; 12517 } 12518 12519 // Content can be updated multiple times. If the tooltip already 12520 // exists, then just update the content and bail. 12521 tooltip = this._find( target ); 12522 if ( tooltip.length ) { 12523 tooltip.find( ".ui-tooltip-content" ).html( content ); 12524 return; 12525 } 12526 12527 // if we have a title, clear it to prevent the native tooltip 12528 // we have to check first to avoid defining a title if none exists 12529 // (we don't want to cause an element to start matching [title]) 12530 // 12531 // We use removeAttr only for key events, to allow IE to export the correct 12532 // accessible attributes. For mouse events, set to empty string to avoid 12533 // native tooltip showing up (happens only when removing inside mouseover). 12534 if ( target.is( "[title]" ) ) { 12535 if ( event && event.type === "mouseover" ) { 12536 target.attr( "title", "" ); 12537 } else { 12538 target.removeAttr( "title" ); 12539 } 12540 } 12541 12542 tooltip = this._tooltip( target ); 12543 addDescribedBy( target, tooltip.attr( "id" ) ); 12544 tooltip.find( ".ui-tooltip-content" ).html( content ); 12545 12546 function position( event ) { 12547 positionOption.of = event; 12548 if ( tooltip.is( ":hidden" ) ) { 12549 return; 12550 } 12551 tooltip.position( positionOption ); 12552 } 12553 if ( this.options.track && event && /^mouse/.test( event.type ) ) { 12554 this._on( this.document, { 12555 mousemove: position 12556 }); 12557 // trigger once to override element-relative positioning 12558 position( event ); 12559 } else { 12560 tooltip.position( $.extend({ 12561 of: target 12562 }, this.options.position ) ); 12563 } 12564 12565 tooltip.hide(); 12566 12567 this._show( tooltip, this.options.show ); 12568 // Handle tracking tooltips that are shown with a delay (#8644). As soon 12569 // as the tooltip is visible, position the tooltip using the most recent 12570 // event. 12571 if ( this.options.show && this.options.show.delay ) { 12572 delayedShow = this.delayedShow = setInterval(function() { 12573 if ( tooltip.is( ":visible" ) ) { 12574 position( positionOption.of ); 12575 clearInterval( delayedShow ); 12576 } 12577 }, $.fx.interval ); 12578 } 12579 12580 this._trigger( "open", event, { tooltip: tooltip } ); 12581 12582 events = { 12583 keyup: function( event ) { 12584 if ( event.keyCode === $.ui.keyCode.ESCAPE ) { 12585 var fakeEvent = $.Event(event); 12586 fakeEvent.currentTarget = target[0]; 12587 this.close( fakeEvent, true ); 12588 } 12589 }, 12590 remove: function() { 12591 this._removeTooltip( tooltip ); 12592 } 12593 }; 12594 if ( !event || event.type === "mouseover" ) { 12595 events.mouseleave = "close"; 12596 } 12597 if ( !event || event.type === "focusin" ) { 12598 events.focusout = "close"; 12599 } 12600 this._on( true, target, events ); 12601 }, 12602 12603 close: function( event ) { 12604 var that = this, 12605 target = $( event ? event.currentTarget : this.element ), 12606 tooltip = this._find( target ); 12607 12608 // disabling closes the tooltip, so we need to track when we're closing 12609 // to avoid an infinite loop in case the tooltip becomes disabled on close 12610 if ( this.closing ) { 12611 return; 12612 } 12613 12614 // Clear the interval for delayed tracking tooltips 12615 clearInterval( this.delayedShow ); 12616 12617 // only set title if we had one before (see comment in _open()) 12618 if ( target.data( "ui-tooltip-title" ) ) { 12619 target.attr( "title", target.data( "ui-tooltip-title" ) ); 12620 } 12621 12622 removeDescribedBy( target ); 12623 12624 tooltip.stop( true ); 12625 this._hide( tooltip, this.options.hide, function() { 12626 that._removeTooltip( $( this ) ); 12627 }); 12628 12629 target.removeData( "ui-tooltip-open" ); 12630 this._off( target, "mouseleave focusout keyup" ); 12631 // Remove 'remove' binding only on delegated targets 12632 if ( target[0] !== this.element[0] ) { 12633 this._off( target, "remove" ); 12634 } 12635 this._off( this.document, "mousemove" ); 12636 12637 if ( event && event.type === "mouseleave" ) { 12638 $.each( this.parents, function( id, parent ) { 12639 $( parent.element ).attr( "title", parent.title ); 12640 delete that.parents[ id ]; 12641 }); 12642 } 12643 12644 this.closing = true; 12645 this._trigger( "close", event, { tooltip: tooltip } ); 12646 this.closing = false; 12647 }, 12648 12649 _tooltip: function( element ) { 12650 var id = "ui-tooltip-" + increments++, 12651 tooltip = $( "<div>" ) 12652 .attr({ 12653 id: id, 12654 role: "tooltip" 12655 }) 12656 .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " + 12657 ( this.options.tooltipClass || "" ) ); 12658 $( "<div>" ) 12659 .addClass( "ui-tooltip-content" ) 12660 .appendTo( tooltip ); 12661 tooltip.appendTo( this.document[0].body ); 12662 this.tooltips[ id ] = element; 12663 return tooltip; 12664 }, 12665 12666 _find: function( target ) { 12667 var id = target.data( "ui-tooltip-id" ); 12668 return id ? $( "#" + id ) : $(); 12669 }, 12670 12671 _removeTooltip: function( tooltip ) { 12672 tooltip.remove(); 12673 delete this.tooltips[ tooltip.attr( "id" ) ]; 12674 }, 12675 12676 _destroy: function() { 12677 var that = this; 12678 12679 // close open tooltips 12680 $.each( this.tooltips, function( id, element ) { 12681 // Delegate to close method to handle common cleanup 12682 var event = $.Event( "blur" ); 12683 event.target = event.currentTarget = element[0]; 12684 that.close( event, true ); 12685 12686 // Remove immediately; destroying an open tooltip doesn't use the 12687 // hide animation 12688 $( "#" + id ).remove(); 12689 12690 // Restore the title 12691 if ( element.data( "ui-tooltip-title" ) ) { 12692 element.attr( "title", element.data( "ui-tooltip-title" ) ); 12693 element.removeData( "ui-tooltip-title" ); 12694 } 12695 }); 12696 } 12697}); 12698 12699}( jQuery ) ); 12700(function($, undefined) { 12701 12702var dataSpace = "ui-effects-"; 12703 12704$.effects = { 12705 effect: {} 12706}; 12707 12708/*! 12709 * jQuery Color Animations v2.1.2 12710 * https://github.com/jquery/jquery-color 12711 * 12712 * Copyright 2013 jQuery Foundation and other contributors 12713 * Released under the MIT license. 12714 * http://jquery.org/license 12715 * 12716 * Date: Wed Jan 16 08:47:09 2013 -0600 12717 */ 12718(function( jQuery, undefined ) { 12719 12720 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", 12721 12722 // plusequals test for += 100 -= 100 12723 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, 12724 // a set of RE's that can match strings and generate color tuples. 12725 stringParsers = [{ 12726 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 12727 parse: function( execResult ) { 12728 return [ 12729 execResult[ 1 ], 12730 execResult[ 2 ], 12731 execResult[ 3 ], 12732 execResult[ 4 ] 12733 ]; 12734 } 12735 }, { 12736 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 12737 parse: function( execResult ) { 12738 return [ 12739 execResult[ 1 ] * 2.55, 12740 execResult[ 2 ] * 2.55, 12741 execResult[ 3 ] * 2.55, 12742 execResult[ 4 ] 12743 ]; 12744 } 12745 }, { 12746 // this regex ignores A-F because it's compared against an already lowercased string 12747 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/, 12748 parse: function( execResult ) { 12749 return [ 12750 parseInt( execResult[ 1 ], 16 ), 12751 parseInt( execResult[ 2 ], 16 ), 12752 parseInt( execResult[ 3 ], 16 ) 12753 ]; 12754 } 12755 }, { 12756 // this regex ignores A-F because it's compared against an already lowercased string 12757 re: /#([a-f0-9])([a-f0-9])([a-f0-9])/, 12758 parse: function( execResult ) { 12759 return [ 12760 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), 12761 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), 12762 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ) 12763 ]; 12764 } 12765 }, { 12766 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 12767 space: "hsla", 12768 parse: function( execResult ) { 12769 return [ 12770 execResult[ 1 ], 12771 execResult[ 2 ] / 100, 12772 execResult[ 3 ] / 100, 12773 execResult[ 4 ] 12774 ]; 12775 } 12776 }], 12777 12778 // jQuery.Color( ) 12779 color = jQuery.Color = function( color, green, blue, alpha ) { 12780 return new jQuery.Color.fn.parse( color, green, blue, alpha ); 12781 }, 12782 spaces = { 12783 rgba: { 12784 props: { 12785 red: { 12786 idx: 0, 12787 type: "byte" 12788 }, 12789 green: { 12790 idx: 1, 12791 type: "byte" 12792 }, 12793 blue: { 12794 idx: 2, 12795 type: "byte" 12796 } 12797 } 12798 }, 12799 12800 hsla: { 12801 props: { 12802 hue: { 12803 idx: 0, 12804 type: "degrees" 12805 }, 12806 saturation: { 12807 idx: 1, 12808 type: "percent" 12809 }, 12810 lightness: { 12811 idx: 2, 12812 type: "percent" 12813 } 12814 } 12815 } 12816 }, 12817 propTypes = { 12818 "byte": { 12819 floor: true, 12820 max: 255 12821 }, 12822 "percent": { 12823 max: 1 12824 }, 12825 "degrees": { 12826 mod: 360, 12827 floor: true 12828 } 12829 }, 12830 support = color.support = {}, 12831 12832 // element for support tests 12833 supportElem = jQuery( "<p>" )[ 0 ], 12834 12835 // colors = jQuery.Color.names 12836 colors, 12837 12838 // local aliases of functions called often 12839 each = jQuery.each; 12840 12841// determine rgba support immediately 12842supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; 12843support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; 12844 12845// define cache name and alpha properties 12846// for rgba and hsla spaces 12847each( spaces, function( spaceName, space ) { 12848 space.cache = "_" + spaceName; 12849 space.props.alpha = { 12850 idx: 3, 12851 type: "percent", 12852 def: 1 12853 }; 12854}); 12855 12856function clamp( value, prop, allowEmpty ) { 12857 var type = propTypes[ prop.type ] || {}; 12858 12859 if ( value == null ) { 12860 return (allowEmpty || !prop.def) ? null : prop.def; 12861 } 12862 12863 // ~~ is an short way of doing floor for positive numbers 12864 value = type.floor ? ~~value : parseFloat( value ); 12865 12866 // IE will pass in empty strings as value for alpha, 12867 // which will hit this case 12868 if ( isNaN( value ) ) { 12869 return prop.def; 12870 } 12871 12872 if ( type.mod ) { 12873 // we add mod before modding to make sure that negatives values 12874 // get converted properly: -10 -> 350 12875 return (value + type.mod) % type.mod; 12876 } 12877 12878 // for now all property types without mod have min and max 12879 return 0 > value ? 0 : type.max < value ? type.max : value; 12880} 12881 12882function stringParse( string ) { 12883 var inst = color(), 12884 rgba = inst._rgba = []; 12885 12886 string = string.toLowerCase(); 12887 12888 each( stringParsers, function( i, parser ) { 12889 var parsed, 12890 match = parser.re.exec( string ), 12891 values = match && parser.parse( match ), 12892 spaceName = parser.space || "rgba"; 12893 12894 if ( values ) { 12895 parsed = inst[ spaceName ]( values ); 12896 12897 // if this was an rgba parse the assignment might happen twice 12898 // oh well.... 12899 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; 12900 rgba = inst._rgba = parsed._rgba; 12901 12902 // exit each( stringParsers ) here because we matched 12903 return false; 12904 } 12905 }); 12906 12907 // Found a stringParser that handled it 12908 if ( rgba.length ) { 12909 12910 // if this came from a parsed string, force "transparent" when alpha is 0 12911 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) 12912 if ( rgba.join() === "0,0,0,0" ) { 12913 jQuery.extend( rgba, colors.transparent ); 12914 } 12915 return inst; 12916 } 12917 12918 // named colors 12919 return colors[ string ]; 12920} 12921 12922color.fn = jQuery.extend( color.prototype, { 12923 parse: function( red, green, blue, alpha ) { 12924 if ( red === undefined ) { 12925 this._rgba = [ null, null, null, null ]; 12926 return this; 12927 } 12928 if ( red.jquery || red.nodeType ) { 12929 red = jQuery( red ).css( green ); 12930 green = undefined; 12931 } 12932 12933 var inst = this, 12934 type = jQuery.type( red ), 12935 rgba = this._rgba = []; 12936 12937 // more than 1 argument specified - assume ( red, green, blue, alpha ) 12938 if ( green !== undefined ) { 12939 red = [ red, green, blue, alpha ]; 12940 type = "array"; 12941 } 12942 12943 if ( type === "string" ) { 12944 return this.parse( stringParse( red ) || colors._default ); 12945 } 12946 12947 if ( type === "array" ) { 12948 each( spaces.rgba.props, function( key, prop ) { 12949 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); 12950 }); 12951 return this; 12952 } 12953 12954 if ( type === "object" ) { 12955 if ( red instanceof color ) { 12956 each( spaces, function( spaceName, space ) { 12957 if ( red[ space.cache ] ) { 12958 inst[ space.cache ] = red[ space.cache ].slice(); 12959 } 12960 }); 12961 } else { 12962 each( spaces, function( spaceName, space ) { 12963 var cache = space.cache; 12964 each( space.props, function( key, prop ) { 12965 12966 // if the cache doesn't exist, and we know how to convert 12967 if ( !inst[ cache ] && space.to ) { 12968 12969 // if the value was null, we don't need to copy it 12970 // if the key was alpha, we don't need to copy it either 12971 if ( key === "alpha" || red[ key ] == null ) { 12972 return; 12973 } 12974 inst[ cache ] = space.to( inst._rgba ); 12975 } 12976 12977 // this is the only case where we allow nulls for ALL properties. 12978 // call clamp with alwaysAllowEmpty 12979 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); 12980 }); 12981 12982 // everything defined but alpha? 12983 if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { 12984 // use the default of 1 12985 inst[ cache ][ 3 ] = 1; 12986 if ( space.from ) { 12987 inst._rgba = space.from( inst[ cache ] ); 12988 } 12989 } 12990 }); 12991 } 12992 return this; 12993 } 12994 }, 12995 is: function( compare ) { 12996 var is = color( compare ), 12997 same = true, 12998 inst = this; 12999 13000 each( spaces, function( _, space ) { 13001 var localCache, 13002 isCache = is[ space.cache ]; 13003 if (isCache) { 13004 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; 13005 each( space.props, function( _, prop ) { 13006 if ( isCache[ prop.idx ] != null ) { 13007 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); 13008 return same; 13009 } 13010 }); 13011 } 13012 return same; 13013 }); 13014 return same; 13015 }, 13016 _space: function() { 13017 var used = [], 13018 inst = this; 13019 each( spaces, function( spaceName, space ) { 13020 if ( inst[ space.cache ] ) { 13021 used.push( spaceName ); 13022 } 13023 }); 13024 return used.pop(); 13025 }, 13026 transition: function( other, distance ) { 13027 var end = color( other ), 13028 spaceName = end._space(), 13029 space = spaces[ spaceName ], 13030 startColor = this.alpha() === 0 ? color( "transparent" ) : this, 13031 start = startColor[ space.cache ] || space.to( startColor._rgba ), 13032 result = start.slice(); 13033 13034 end = end[ space.cache ]; 13035 each( space.props, function( key, prop ) { 13036 var index = prop.idx, 13037 startValue = start[ index ], 13038 endValue = end[ index ], 13039 type = propTypes[ prop.type ] || {}; 13040 13041 // if null, don't override start value 13042 if ( endValue === null ) { 13043 return; 13044 } 13045 // if null - use end 13046 if ( startValue === null ) { 13047 result[ index ] = endValue; 13048 } else { 13049 if ( type.mod ) { 13050 if ( endValue - startValue > type.mod / 2 ) { 13051 startValue += type.mod; 13052 } else if ( startValue - endValue > type.mod / 2 ) { 13053 startValue -= type.mod; 13054 } 13055 } 13056 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); 13057 } 13058 }); 13059 return this[ spaceName ]( result ); 13060 }, 13061 blend: function( opaque ) { 13062 // if we are already opaque - return ourself 13063 if ( this._rgba[ 3 ] === 1 ) { 13064 return this; 13065 } 13066 13067 var rgb = this._rgba.slice(), 13068 a = rgb.pop(), 13069 blend = color( opaque )._rgba; 13070 13071 return color( jQuery.map( rgb, function( v, i ) { 13072 return ( 1 - a ) * blend[ i ] + a * v; 13073 })); 13074 }, 13075 toRgbaString: function() { 13076 var prefix = "rgba(", 13077 rgba = jQuery.map( this._rgba, function( v, i ) { 13078 return v == null ? ( i > 2 ? 1 : 0 ) : v; 13079 }); 13080 13081 if ( rgba[ 3 ] === 1 ) { 13082 rgba.pop(); 13083 prefix = "rgb("; 13084 } 13085 13086 return prefix + rgba.join() + ")"; 13087 }, 13088 toHslaString: function() { 13089 var prefix = "hsla(", 13090 hsla = jQuery.map( this.hsla(), function( v, i ) { 13091 if ( v == null ) { 13092 v = i > 2 ? 1 : 0; 13093 } 13094 13095 // catch 1 and 2 13096 if ( i && i < 3 ) { 13097 v = Math.round( v * 100 ) + "%"; 13098 } 13099 return v; 13100 }); 13101 13102 if ( hsla[ 3 ] === 1 ) { 13103 hsla.pop(); 13104 prefix = "hsl("; 13105 } 13106 return prefix + hsla.join() + ")"; 13107 }, 13108 toHexString: function( includeAlpha ) { 13109 var rgba = this._rgba.slice(), 13110 alpha = rgba.pop(); 13111 13112 if ( includeAlpha ) { 13113 rgba.push( ~~( alpha * 255 ) ); 13114 } 13115 13116 return "#" + jQuery.map( rgba, function( v ) { 13117 13118 // default to 0 when nulls exist 13119 v = ( v || 0 ).toString( 16 ); 13120 return v.length === 1 ? "0" + v : v; 13121 }).join(""); 13122 }, 13123 toString: function() { 13124 return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); 13125 } 13126}); 13127color.fn.parse.prototype = color.fn; 13128 13129// hsla conversions adapted from: 13130// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 13131 13132function hue2rgb( p, q, h ) { 13133 h = ( h + 1 ) % 1; 13134 if ( h * 6 < 1 ) { 13135 return p + (q - p) * h * 6; 13136 } 13137 if ( h * 2 < 1) { 13138 return q; 13139 } 13140 if ( h * 3 < 2 ) { 13141 return p + (q - p) * ((2/3) - h) * 6; 13142 } 13143 return p; 13144} 13145 13146spaces.hsla.to = function ( rgba ) { 13147 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { 13148 return [ null, null, null, rgba[ 3 ] ]; 13149 } 13150 var r = rgba[ 0 ] / 255, 13151 g = rgba[ 1 ] / 255, 13152 b = rgba[ 2 ] / 255, 13153 a = rgba[ 3 ], 13154 max = Math.max( r, g, b ), 13155 min = Math.min( r, g, b ), 13156 diff = max - min, 13157 add = max + min, 13158 l = add * 0.5, 13159 h, s; 13160 13161 if ( min === max ) { 13162 h = 0; 13163 } else if ( r === max ) { 13164 h = ( 60 * ( g - b ) / diff ) + 360; 13165 } else if ( g === max ) { 13166 h = ( 60 * ( b - r ) / diff ) + 120; 13167 } else { 13168 h = ( 60 * ( r - g ) / diff ) + 240; 13169 } 13170 13171 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0% 13172 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) 13173 if ( diff === 0 ) { 13174 s = 0; 13175 } else if ( l <= 0.5 ) { 13176 s = diff / add; 13177 } else { 13178 s = diff / ( 2 - add ); 13179 } 13180 return [ Math.round(h) % 360, s, l, a == null ? 1 : a ]; 13181}; 13182 13183spaces.hsla.from = function ( hsla ) { 13184 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { 13185 return [ null, null, null, hsla[ 3 ] ]; 13186 } 13187 var h = hsla[ 0 ] / 360, 13188 s = hsla[ 1 ], 13189 l = hsla[ 2 ], 13190 a = hsla[ 3 ], 13191 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, 13192 p = 2 * l - q; 13193 13194 return [ 13195 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), 13196 Math.round( hue2rgb( p, q, h ) * 255 ), 13197 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), 13198 a 13199 ]; 13200}; 13201 13202 13203each( spaces, function( spaceName, space ) { 13204 var props = space.props, 13205 cache = space.cache, 13206 to = space.to, 13207 from = space.from; 13208 13209 // makes rgba() and hsla() 13210 color.fn[ spaceName ] = function( value ) { 13211 13212 // generate a cache for this space if it doesn't exist 13213 if ( to && !this[ cache ] ) { 13214 this[ cache ] = to( this._rgba ); 13215 } 13216 if ( value === undefined ) { 13217 return this[ cache ].slice(); 13218 } 13219 13220 var ret, 13221 type = jQuery.type( value ), 13222 arr = ( type === "array" || type === "object" ) ? value : arguments, 13223 local = this[ cache ].slice(); 13224 13225 each( props, function( key, prop ) { 13226 var val = arr[ type === "object" ? key : prop.idx ]; 13227 if ( val == null ) { 13228 val = local[ prop.idx ]; 13229 } 13230 local[ prop.idx ] = clamp( val, prop ); 13231 }); 13232 13233 if ( from ) { 13234 ret = color( from( local ) ); 13235 ret[ cache ] = local; 13236 return ret; 13237 } else { 13238 return color( local ); 13239 } 13240 }; 13241 13242 // makes red() green() blue() alpha() hue() saturation() lightness() 13243 each( props, function( key, prop ) { 13244 // alpha is included in more than one space 13245 if ( color.fn[ key ] ) { 13246 return; 13247 } 13248 color.fn[ key ] = function( value ) { 13249 var vtype = jQuery.type( value ), 13250 fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ), 13251 local = this[ fn ](), 13252 cur = local[ prop.idx ], 13253 match; 13254 13255 if ( vtype === "undefined" ) { 13256 return cur; 13257 } 13258 13259 if ( vtype === "function" ) { 13260 value = value.call( this, cur ); 13261 vtype = jQuery.type( value ); 13262 } 13263 if ( value == null && prop.empty ) { 13264 return this; 13265 } 13266 if ( vtype === "string" ) { 13267 match = rplusequals.exec( value ); 13268 if ( match ) { 13269 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); 13270 } 13271 } 13272 local[ prop.idx ] = value; 13273 return this[ fn ]( local ); 13274 }; 13275 }); 13276}); 13277 13278// add cssHook and .fx.step function for each named hook. 13279// accept a space separated string of properties 13280color.hook = function( hook ) { 13281 var hooks = hook.split( " " ); 13282 each( hooks, function( i, hook ) { 13283 jQuery.cssHooks[ hook ] = { 13284 set: function( elem, value ) { 13285 var parsed, curElem, 13286 backgroundColor = ""; 13287 13288 if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) { 13289 value = color( parsed || value ); 13290 if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { 13291 curElem = hook === "backgroundColor" ? elem.parentNode : elem; 13292 while ( 13293 (backgroundColor === "" || backgroundColor === "transparent") && 13294 curElem && curElem.style 13295 ) { 13296 try { 13297 backgroundColor = jQuery.css( curElem, "backgroundColor" ); 13298 curElem = curElem.parentNode; 13299 } catch ( e ) { 13300 } 13301 } 13302 13303 value = value.blend( backgroundColor && backgroundColor !== "transparent" ? 13304 backgroundColor : 13305 "_default" ); 13306 } 13307 13308 value = value.toRgbaString(); 13309 } 13310 try { 13311 elem.style[ hook ] = value; 13312 } catch( e ) { 13313 // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' 13314 } 13315 } 13316 }; 13317 jQuery.fx.step[ hook ] = function( fx ) { 13318 if ( !fx.colorInit ) { 13319 fx.start = color( fx.elem, hook ); 13320 fx.end = color( fx.end ); 13321 fx.colorInit = true; 13322 } 13323 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); 13324 }; 13325 }); 13326 13327}; 13328 13329color.hook( stepHooks ); 13330 13331jQuery.cssHooks.borderColor = { 13332 expand: function( value ) { 13333 var expanded = {}; 13334 13335 each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) { 13336 expanded[ "border" + part + "Color" ] = value; 13337 }); 13338 return expanded; 13339 } 13340}; 13341 13342// Basic color names only. 13343// Usage of any of the other color names requires adding yourself or including 13344// jquery.color.svg-names.js. 13345colors = jQuery.Color.names = { 13346 // 4.1. Basic color keywords 13347 aqua: "#00ffff", 13348 black: "#000000", 13349 blue: "#0000ff", 13350 fuchsia: "#ff00ff", 13351 gray: "#808080", 13352 green: "#008000", 13353 lime: "#00ff00", 13354 maroon: "#800000", 13355 navy: "#000080", 13356 olive: "#808000", 13357 purple: "#800080", 13358 red: "#ff0000", 13359 silver: "#c0c0c0", 13360 teal: "#008080", 13361 white: "#ffffff", 13362 yellow: "#ffff00", 13363 13364 // 4.2.3. "transparent" color keyword 13365 transparent: [ null, null, null, 0 ], 13366 13367 _default: "#ffffff" 13368}; 13369 13370})( jQuery ); 13371 13372 13373/******************************************************************************/ 13374/****************************** CLASS ANIMATIONS ******************************/ 13375/******************************************************************************/ 13376(function() { 13377 13378var classAnimationActions = [ "add", "remove", "toggle" ], 13379 shorthandStyles = { 13380 border: 1, 13381 borderBottom: 1, 13382 borderColor: 1, 13383 borderLeft: 1, 13384 borderRight: 1, 13385 borderTop: 1, 13386 borderWidth: 1, 13387 margin: 1, 13388 padding: 1 13389 }; 13390 13391$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) { 13392 $.fx.step[ prop ] = function( fx ) { 13393 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { 13394 jQuery.style( fx.elem, prop, fx.end ); 13395 fx.setAttr = true; 13396 } 13397 }; 13398}); 13399 13400function getElementStyles( elem ) { 13401 var key, len, 13402 style = elem.ownerDocument.defaultView ? 13403 elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : 13404 elem.currentStyle, 13405 styles = {}; 13406 13407 if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { 13408 len = style.length; 13409 while ( len-- ) { 13410 key = style[ len ]; 13411 if ( typeof style[ key ] === "string" ) { 13412 styles[ $.camelCase( key ) ] = style[ key ]; 13413 } 13414 } 13415 // support: Opera, IE <9 13416 } else { 13417 for ( key in style ) { 13418 if ( typeof style[ key ] === "string" ) { 13419 styles[ key ] = style[ key ]; 13420 } 13421 } 13422 } 13423 13424 return styles; 13425} 13426 13427 13428function styleDifference( oldStyle, newStyle ) { 13429 var diff = {}, 13430 name, value; 13431 13432 for ( name in newStyle ) { 13433 value = newStyle[ name ]; 13434 if ( oldStyle[ name ] !== value ) { 13435 if ( !shorthandStyles[ name ] ) { 13436 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { 13437 diff[ name ] = value; 13438 } 13439 } 13440 } 13441 } 13442 13443 return diff; 13444} 13445 13446// support: jQuery <1.8 13447if ( !$.fn.addBack ) { 13448 $.fn.addBack = function( selector ) { 13449 return this.add( selector == null ? 13450 this.prevObject : this.prevObject.filter( selector ) 13451 ); 13452 }; 13453} 13454 13455$.effects.animateClass = function( value, duration, easing, callback ) { 13456 var o = $.speed( duration, easing, callback ); 13457 13458 return this.queue( function() { 13459 var animated = $( this ), 13460 baseClass = animated.attr( "class" ) || "", 13461 applyClassChange, 13462 allAnimations = o.children ? animated.find( "*" ).addBack() : animated; 13463 13464 // map the animated objects to store the original styles. 13465 allAnimations = allAnimations.map(function() { 13466 var el = $( this ); 13467 return { 13468 el: el, 13469 start: getElementStyles( this ) 13470 }; 13471 }); 13472 13473 // apply class change 13474 applyClassChange = function() { 13475 $.each( classAnimationActions, function(i, action) { 13476 if ( value[ action ] ) { 13477 animated[ action + "Class" ]( value[ action ] ); 13478 } 13479 }); 13480 }; 13481 applyClassChange(); 13482 13483 // map all animated objects again - calculate new styles and diff 13484 allAnimations = allAnimations.map(function() { 13485 this.end = getElementStyles( this.el[ 0 ] ); 13486 this.diff = styleDifference( this.start, this.end ); 13487 return this; 13488 }); 13489 13490 // apply original class 13491 animated.attr( "class", baseClass ); 13492 13493 // map all animated objects again - this time collecting a promise 13494 allAnimations = allAnimations.map(function() { 13495 var styleInfo = this, 13496 dfd = $.Deferred(), 13497 opts = $.extend({}, o, { 13498 queue: false, 13499 complete: function() { 13500 dfd.resolve( styleInfo ); 13501 } 13502 }); 13503 13504 this.el.animate( this.diff, opts ); 13505 return dfd.promise(); 13506 }); 13507 13508 // once all animations have completed: 13509 $.when.apply( $, allAnimations.get() ).done(function() { 13510 13511 // set the final class 13512 applyClassChange(); 13513 13514 // for each animated element, 13515 // clear all css properties that were animated 13516 $.each( arguments, function() { 13517 var el = this.el; 13518 $.each( this.diff, function(key) { 13519 el.css( key, "" ); 13520 }); 13521 }); 13522 13523 // this is guarnteed to be there if you use jQuery.speed() 13524 // it also handles dequeuing the next anim... 13525 o.complete.call( animated[ 0 ] ); 13526 }); 13527 }); 13528}; 13529 13530$.fn.extend({ 13531 addClass: (function( orig ) { 13532 return function( classNames, speed, easing, callback ) { 13533 return speed ? 13534 $.effects.animateClass.call( this, 13535 { add: classNames }, speed, easing, callback ) : 13536 orig.apply( this, arguments ); 13537 }; 13538 })( $.fn.addClass ), 13539 13540 removeClass: (function( orig ) { 13541 return function( classNames, speed, easing, callback ) { 13542 return arguments.length > 1 ? 13543 $.effects.animateClass.call( this, 13544 { remove: classNames }, speed, easing, callback ) : 13545 orig.apply( this, arguments ); 13546 }; 13547 })( $.fn.removeClass ), 13548 13549 toggleClass: (function( orig ) { 13550 return function( classNames, force, speed, easing, callback ) { 13551 if ( typeof force === "boolean" || force === undefined ) { 13552 if ( !speed ) { 13553 // without speed parameter 13554 return orig.apply( this, arguments ); 13555 } else { 13556 return $.effects.animateClass.call( this, 13557 (force ? { add: classNames } : { remove: classNames }), 13558 speed, easing, callback ); 13559 } 13560 } else { 13561 // without force parameter 13562 return $.effects.animateClass.call( this, 13563 { toggle: classNames }, force, speed, easing ); 13564 } 13565 }; 13566 })( $.fn.toggleClass ), 13567 13568 switchClass: function( remove, add, speed, easing, callback) { 13569 return $.effects.animateClass.call( this, { 13570 add: add, 13571 remove: remove 13572 }, speed, easing, callback ); 13573 } 13574}); 13575 13576})(); 13577 13578/******************************************************************************/ 13579/*********************************** EFFECTS **********************************/ 13580/******************************************************************************/ 13581 13582(function() { 13583 13584$.extend( $.effects, { 13585 version: "1.10.2", 13586 13587 // Saves a set of properties in a data storage 13588 save: function( element, set ) { 13589 for( var i=0; i < set.length; i++ ) { 13590 if ( set[ i ] !== null ) { 13591 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); 13592 } 13593 } 13594 }, 13595 13596 // Restores a set of previously saved properties from a data storage 13597 restore: function( element, set ) { 13598 var val, i; 13599 for( i=0; i < set.length; i++ ) { 13600 if ( set[ i ] !== null ) { 13601 val = element.data( dataSpace + set[ i ] ); 13602 // support: jQuery 1.6.2 13603 // http://bugs.jquery.com/ticket/9917 13604 // jQuery 1.6.2 incorrectly returns undefined for any falsy value. 13605 // We can't differentiate between "" and 0 here, so we just assume 13606 // empty string since it's likely to be a more common value... 13607 if ( val === undefined ) { 13608 val = ""; 13609 } 13610 element.css( set[ i ], val ); 13611 } 13612 } 13613 }, 13614 13615 setMode: function( el, mode ) { 13616 if (mode === "toggle") { 13617 mode = el.is( ":hidden" ) ? "show" : "hide"; 13618 } 13619 return mode; 13620 }, 13621 13622 // Translates a [top,left] array into a baseline value 13623 // this should be a little more flexible in the future to handle a string & hash 13624 getBaseline: function( origin, original ) { 13625 var y, x; 13626 switch ( origin[ 0 ] ) { 13627 case "top": y = 0; break; 13628 case "middle": y = 0.5; break; 13629 case "bottom": y = 1; break; 13630 default: y = origin[ 0 ] / original.height; 13631 } 13632 switch ( origin[ 1 ] ) { 13633 case "left": x = 0; break; 13634 case "center": x = 0.5; break; 13635 case "right": x = 1; break; 13636 default: x = origin[ 1 ] / original.width; 13637 } 13638 return { 13639 x: x, 13640 y: y 13641 }; 13642 }, 13643 13644 // Wraps the element around a wrapper that copies position properties 13645 createWrapper: function( element ) { 13646 13647 // if the element is already wrapped, return it 13648 if ( element.parent().is( ".ui-effects-wrapper" )) { 13649 return element.parent(); 13650 } 13651 13652 // wrap the element 13653 var props = { 13654 width: element.outerWidth(true), 13655 height: element.outerHeight(true), 13656 "float": element.css( "float" ) 13657 }, 13658 wrapper = $( "<div></div>" ) 13659 .addClass( "ui-effects-wrapper" ) 13660 .css({ 13661 fontSize: "100%", 13662 background: "transparent", 13663 border: "none", 13664 margin: 0, 13665 padding: 0 13666 }), 13667 // Store the size in case width/height are defined in % - Fixes #5245 13668 size = { 13669 width: element.width(), 13670 height: element.height() 13671 }, 13672 active = document.activeElement; 13673 13674 // support: Firefox 13675 // Firefox incorrectly exposes anonymous content 13676 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 13677 try { 13678 active.id; 13679 } catch( e ) { 13680 active = document.body; 13681 } 13682 13683 element.wrap( wrapper ); 13684 13685 // Fixes #7595 - Elements lose focus when wrapped. 13686 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 13687 $( active ).focus(); 13688 } 13689 13690 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element 13691 13692 // transfer positioning properties to the wrapper 13693 if ( element.css( "position" ) === "static" ) { 13694 wrapper.css({ position: "relative" }); 13695 element.css({ position: "relative" }); 13696 } else { 13697 $.extend( props, { 13698 position: element.css( "position" ), 13699 zIndex: element.css( "z-index" ) 13700 }); 13701 $.each([ "top", "left", "bottom", "right" ], function(i, pos) { 13702 props[ pos ] = element.css( pos ); 13703 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { 13704 props[ pos ] = "auto"; 13705 } 13706 }); 13707 element.css({ 13708 position: "relative", 13709 top: 0, 13710 left: 0, 13711 right: "auto", 13712 bottom: "auto" 13713 }); 13714 } 13715 element.css(size); 13716 13717 return wrapper.css( props ).show(); 13718 }, 13719 13720 removeWrapper: function( element ) { 13721 var active = document.activeElement; 13722 13723 if ( element.parent().is( ".ui-effects-wrapper" ) ) { 13724 element.parent().replaceWith( element ); 13725 13726 // Fixes #7595 - Elements lose focus when wrapped. 13727 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 13728 $( active ).focus(); 13729 } 13730 } 13731 13732 13733 return element; 13734 }, 13735 13736 setTransition: function( element, list, factor, value ) { 13737 value = value || {}; 13738 $.each( list, function( i, x ) { 13739 var unit = element.cssUnit( x ); 13740 if ( unit[ 0 ] > 0 ) { 13741 value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; 13742 } 13743 }); 13744 return value; 13745 } 13746}); 13747 13748// return an effect options object for the given parameters: 13749function _normalizeArguments( effect, options, speed, callback ) { 13750 13751 // allow passing all options as the first parameter 13752 if ( $.isPlainObject( effect ) ) { 13753 options = effect; 13754 effect = effect.effect; 13755 } 13756 13757 // convert to an object 13758 effect = { effect: effect }; 13759 13760 // catch (effect, null, ...) 13761 if ( options == null ) { 13762 options = {}; 13763 } 13764 13765 // catch (effect, callback) 13766 if ( $.isFunction( options ) ) { 13767 callback = options; 13768 speed = null; 13769 options = {}; 13770 } 13771 13772 // catch (effect, speed, ?) 13773 if ( typeof options === "number" || $.fx.speeds[ options ] ) { 13774 callback = speed; 13775 speed = options; 13776 options = {}; 13777 } 13778 13779 // catch (effect, options, callback) 13780 if ( $.isFunction( speed ) ) { 13781 callback = speed; 13782 speed = null; 13783 } 13784 13785 // add options to effect 13786 if ( options ) { 13787 $.extend( effect, options ); 13788 } 13789 13790 speed = speed || options.duration; 13791 effect.duration = $.fx.off ? 0 : 13792 typeof speed === "number" ? speed : 13793 speed in $.fx.speeds ? $.fx.speeds[ speed ] : 13794 $.fx.speeds._default; 13795 13796 effect.complete = callback || options.complete; 13797 13798 return effect; 13799} 13800 13801function standardAnimationOption( option ) { 13802 // Valid standard speeds (nothing, number, named speed) 13803 if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) { 13804 return true; 13805 } 13806 13807 // Invalid strings - treat as "normal" speed 13808 if ( typeof option === "string" && !$.effects.effect[ option ] ) { 13809 return true; 13810 } 13811 13812 // Complete callback 13813 if ( $.isFunction( option ) ) { 13814 return true; 13815 } 13816 13817 // Options hash (but not naming an effect) 13818 if ( typeof option === "object" && !option.effect ) { 13819 return true; 13820 } 13821 13822 // Didn't match any standard API 13823 return false; 13824} 13825 13826$.fn.extend({ 13827 effect: function( /* effect, options, speed, callback */ ) { 13828 var args = _normalizeArguments.apply( this, arguments ), 13829 mode = args.mode, 13830 queue = args.queue, 13831 effectMethod = $.effects.effect[ args.effect ]; 13832 13833 if ( $.fx.off || !effectMethod ) { 13834 // delegate to the original method (e.g., .show()) if possible 13835 if ( mode ) { 13836 return this[ mode ]( args.duration, args.complete ); 13837 } else { 13838 return this.each( function() { 13839 if ( args.complete ) { 13840 args.complete.call( this ); 13841 } 13842 }); 13843 } 13844 } 13845 13846 function run( next ) { 13847 var elem = $( this ), 13848 complete = args.complete, 13849 mode = args.mode; 13850 13851 function done() { 13852 if ( $.isFunction( complete ) ) { 13853 complete.call( elem[0] ); 13854 } 13855 if ( $.isFunction( next ) ) { 13856 next(); 13857 } 13858 } 13859 13860 // If the element already has the correct final state, delegate to 13861 // the core methods so the internal tracking of "olddisplay" works. 13862 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { 13863 elem[ mode ](); 13864 done(); 13865 } else { 13866 effectMethod.call( elem[0], args, done ); 13867 } 13868 } 13869 13870 return queue === false ? this.each( run ) : this.queue( queue || "fx", run ); 13871 }, 13872 13873 show: (function( orig ) { 13874 return function( option ) { 13875 if ( standardAnimationOption( option ) ) { 13876 return orig.apply( this, arguments ); 13877 } else { 13878 var args = _normalizeArguments.apply( this, arguments ); 13879 args.mode = "show"; 13880 return this.effect.call( this, args ); 13881 } 13882 }; 13883 })( $.fn.show ), 13884 13885 hide: (function( orig ) { 13886 return function( option ) { 13887 if ( standardAnimationOption( option ) ) { 13888 return orig.apply( this, arguments ); 13889 } else { 13890 var args = _normalizeArguments.apply( this, arguments ); 13891 args.mode = "hide"; 13892 return this.effect.call( this, args ); 13893 } 13894 }; 13895 })( $.fn.hide ), 13896 13897 toggle: (function( orig ) { 13898 return function( option ) { 13899 if ( standardAnimationOption( option ) || typeof option === "boolean" ) { 13900 return orig.apply( this, arguments ); 13901 } else { 13902 var args = _normalizeArguments.apply( this, arguments ); 13903 args.mode = "toggle"; 13904 return this.effect.call( this, args ); 13905 } 13906 }; 13907 })( $.fn.toggle ), 13908 13909 // helper functions 13910 cssUnit: function(key) { 13911 var style = this.css( key ), 13912 val = []; 13913 13914 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { 13915 if ( style.indexOf( unit ) > 0 ) { 13916 val = [ parseFloat( style ), unit ]; 13917 } 13918 }); 13919 return val; 13920 } 13921}); 13922 13923})(); 13924 13925/******************************************************************************/ 13926/*********************************** EASING ***********************************/ 13927/******************************************************************************/ 13928 13929(function() { 13930 13931// based on easing equations from Robert Penner (http://www.robertpenner.com/easing) 13932 13933var baseEasings = {}; 13934 13935$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { 13936 baseEasings[ name ] = function( p ) { 13937 return Math.pow( p, i + 2 ); 13938 }; 13939}); 13940 13941$.extend( baseEasings, { 13942 Sine: function ( p ) { 13943 return 1 - Math.cos( p * Math.PI / 2 ); 13944 }, 13945 Circ: function ( p ) { 13946 return 1 - Math.sqrt( 1 - p * p ); 13947 }, 13948 Elastic: function( p ) { 13949 return p === 0 || p === 1 ? p : 13950 -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 ); 13951 }, 13952 Back: function( p ) { 13953 return p * p * ( 3 * p - 2 ); 13954 }, 13955 Bounce: function ( p ) { 13956 var pow2, 13957 bounce = 4; 13958 13959 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} 13960 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); 13961 } 13962}); 13963 13964$.each( baseEasings, function( name, easeIn ) { 13965 $.easing[ "easeIn" + name ] = easeIn; 13966 $.easing[ "easeOut" + name ] = function( p ) { 13967 return 1 - easeIn( 1 - p ); 13968 }; 13969 $.easing[ "easeInOut" + name ] = function( p ) { 13970 return p < 0.5 ? 13971 easeIn( p * 2 ) / 2 : 13972 1 - easeIn( p * -2 + 2 ) / 2; 13973 }; 13974}); 13975 13976})(); 13977 13978})(jQuery); 13979(function( $, undefined ) { 13980 13981var rvertical = /up|down|vertical/, 13982 rpositivemotion = /up|left|vertical|horizontal/; 13983 13984$.effects.effect.blind = function( o, done ) { 13985 // Create element 13986 var el = $( this ), 13987 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 13988 mode = $.effects.setMode( el, o.mode || "hide" ), 13989 direction = o.direction || "up", 13990 vertical = rvertical.test( direction ), 13991 ref = vertical ? "height" : "width", 13992 ref2 = vertical ? "top" : "left", 13993 motion = rpositivemotion.test( direction ), 13994 animation = {}, 13995 show = mode === "show", 13996 wrapper, distance, margin; 13997 13998 // if already wrapped, the wrapper's properties are my property. #6245 13999 if ( el.parent().is( ".ui-effects-wrapper" ) ) { 14000 $.effects.save( el.parent(), props ); 14001 } else { 14002 $.effects.save( el, props ); 14003 } 14004 el.show(); 14005 wrapper = $.effects.createWrapper( el ).css({ 14006 overflow: "hidden" 14007 }); 14008 14009 distance = wrapper[ ref ](); 14010 margin = parseFloat( wrapper.css( ref2 ) ) || 0; 14011 14012 animation[ ref ] = show ? distance : 0; 14013 if ( !motion ) { 14014 el 14015 .css( vertical ? "bottom" : "right", 0 ) 14016 .css( vertical ? "top" : "left", "auto" ) 14017 .css({ position: "absolute" }); 14018 14019 animation[ ref2 ] = show ? margin : distance + margin; 14020 } 14021 14022 // start at 0 if we are showing 14023 if ( show ) { 14024 wrapper.css( ref, 0 ); 14025 if ( ! motion ) { 14026 wrapper.css( ref2, margin + distance ); 14027 } 14028 } 14029 14030 // Animate 14031 wrapper.animate( animation, { 14032 duration: o.duration, 14033 easing: o.easing, 14034 queue: false, 14035 complete: function() { 14036 if ( mode === "hide" ) { 14037 el.hide(); 14038 } 14039 $.effects.restore( el, props ); 14040 $.effects.removeWrapper( el ); 14041 done(); 14042 } 14043 }); 14044 14045}; 14046 14047})(jQuery); 14048(function( $, undefined ) { 14049 14050$.effects.effect.bounce = function( o, done ) { 14051 var el = $( this ), 14052 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 14053 14054 // defaults: 14055 mode = $.effects.setMode( el, o.mode || "effect" ), 14056 hide = mode === "hide", 14057 show = mode === "show", 14058 direction = o.direction || "up", 14059 distance = o.distance, 14060 times = o.times || 5, 14061 14062 // number of internal animations 14063 anims = times * 2 + ( show || hide ? 1 : 0 ), 14064 speed = o.duration / anims, 14065 easing = o.easing, 14066 14067 // utility: 14068 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 14069 motion = ( direction === "up" || direction === "left" ), 14070 i, 14071 upAnim, 14072 downAnim, 14073 14074 // we will need to re-assemble the queue to stack our animations in place 14075 queue = el.queue(), 14076 queuelen = queue.length; 14077 14078 // Avoid touching opacity to prevent clearType and PNG issues in IE 14079 if ( show || hide ) { 14080 props.push( "opacity" ); 14081 } 14082 14083 $.effects.save( el, props ); 14084 el.show(); 14085 $.effects.createWrapper( el ); // Create Wrapper 14086 14087 // default distance for the BIGGEST bounce is the outer Distance / 3 14088 if ( !distance ) { 14089 distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; 14090 } 14091 14092 if ( show ) { 14093 downAnim = { opacity: 1 }; 14094 downAnim[ ref ] = 0; 14095 14096 // if we are showing, force opacity 0 and set the initial position 14097 // then do the "first" animation 14098 el.css( "opacity", 0 ) 14099 .css( ref, motion ? -distance * 2 : distance * 2 ) 14100 .animate( downAnim, speed, easing ); 14101 } 14102 14103 // start at the smallest distance if we are hiding 14104 if ( hide ) { 14105 distance = distance / Math.pow( 2, times - 1 ); 14106 } 14107 14108 downAnim = {}; 14109 downAnim[ ref ] = 0; 14110 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here 14111 for ( i = 0; i < times; i++ ) { 14112 upAnim = {}; 14113 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 14114 14115 el.animate( upAnim, speed, easing ) 14116 .animate( downAnim, speed, easing ); 14117 14118 distance = hide ? distance * 2 : distance / 2; 14119 } 14120 14121 // Last Bounce when Hiding 14122 if ( hide ) { 14123 upAnim = { opacity: 0 }; 14124 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 14125 14126 el.animate( upAnim, speed, easing ); 14127 } 14128 14129 el.queue(function() { 14130 if ( hide ) { 14131 el.hide(); 14132 } 14133 $.effects.restore( el, props ); 14134 $.effects.removeWrapper( el ); 14135 done(); 14136 }); 14137 14138 // inject all the animations we just queued to be first in line (after "inprogress") 14139 if ( queuelen > 1) { 14140 queue.splice.apply( queue, 14141 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); 14142 } 14143 el.dequeue(); 14144 14145}; 14146 14147})(jQuery); 14148(function( $, undefined ) { 14149 14150$.effects.effect.clip = function( o, done ) { 14151 // Create element 14152 var el = $( this ), 14153 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 14154 mode = $.effects.setMode( el, o.mode || "hide" ), 14155 show = mode === "show", 14156 direction = o.direction || "vertical", 14157 vert = direction === "vertical", 14158 size = vert ? "height" : "width", 14159 position = vert ? "top" : "left", 14160 animation = {}, 14161 wrapper, animate, distance; 14162 14163 // Save & Show 14164 $.effects.save( el, props ); 14165 el.show(); 14166 14167 // Create Wrapper 14168 wrapper = $.effects.createWrapper( el ).css({ 14169 overflow: "hidden" 14170 }); 14171 animate = ( el[0].tagName === "IMG" ) ? wrapper : el; 14172 distance = animate[ size ](); 14173 14174 // Shift 14175 if ( show ) { 14176 animate.css( size, 0 ); 14177 animate.css( position, distance / 2 ); 14178 } 14179 14180 // Create Animation Object: 14181 animation[ size ] = show ? distance : 0; 14182 animation[ position ] = show ? 0 : distance / 2; 14183 14184 // Animate 14185 animate.animate( animation, { 14186 queue: false, 14187 duration: o.duration, 14188 easing: o.easing, 14189 complete: function() { 14190 if ( !show ) { 14191 el.hide(); 14192 } 14193 $.effects.restore( el, props ); 14194 $.effects.removeWrapper( el ); 14195 done(); 14196 } 14197 }); 14198 14199}; 14200 14201})(jQuery); 14202(function( $, undefined ) { 14203 14204$.effects.effect.drop = function( o, done ) { 14205 14206 var el = $( this ), 14207 props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ], 14208 mode = $.effects.setMode( el, o.mode || "hide" ), 14209 show = mode === "show", 14210 direction = o.direction || "left", 14211 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 14212 motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg", 14213 animation = { 14214 opacity: show ? 1 : 0 14215 }, 14216 distance; 14217 14218 // Adjust 14219 $.effects.save( el, props ); 14220 el.show(); 14221 $.effects.createWrapper( el ); 14222 14223 distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2; 14224 14225 if ( show ) { 14226 el 14227 .css( "opacity", 0 ) 14228 .css( ref, motion === "pos" ? -distance : distance ); 14229 } 14230 14231 // Animation 14232 animation[ ref ] = ( show ? 14233 ( motion === "pos" ? "+=" : "-=" ) : 14234 ( motion === "pos" ? "-=" : "+=" ) ) + 14235 distance; 14236 14237 // Animate 14238 el.animate( animation, { 14239 queue: false, 14240 duration: o.duration, 14241 easing: o.easing, 14242 complete: function() { 14243 if ( mode === "hide" ) { 14244 el.hide(); 14245 } 14246 $.effects.restore( el, props ); 14247 $.effects.removeWrapper( el ); 14248 done(); 14249 } 14250 }); 14251}; 14252 14253})(jQuery); 14254(function( $, undefined ) { 14255 14256$.effects.effect.explode = function( o, done ) { 14257 14258 var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3, 14259 cells = rows, 14260 el = $( this ), 14261 mode = $.effects.setMode( el, o.mode || "hide" ), 14262 show = mode === "show", 14263 14264 // show and then visibility:hidden the element before calculating offset 14265 offset = el.show().css( "visibility", "hidden" ).offset(), 14266 14267 // width and height of a piece 14268 width = Math.ceil( el.outerWidth() / cells ), 14269 height = Math.ceil( el.outerHeight() / rows ), 14270 pieces = [], 14271 14272 // loop 14273 i, j, left, top, mx, my; 14274 14275 // children animate complete: 14276 function childComplete() { 14277 pieces.push( this ); 14278 if ( pieces.length === rows * cells ) { 14279 animComplete(); 14280 } 14281 } 14282 14283 // clone the element for each row and cell. 14284 for( i = 0; i < rows ; i++ ) { // ===> 14285 top = offset.top + i * height; 14286 my = i - ( rows - 1 ) / 2 ; 14287 14288 for( j = 0; j < cells ; j++ ) { // ||| 14289 left = offset.left + j * width; 14290 mx = j - ( cells - 1 ) / 2 ; 14291 14292 // Create a clone of the now hidden main element that will be absolute positioned 14293 // within a wrapper div off the -left and -top equal to size of our pieces 14294 el 14295 .clone() 14296 .appendTo( "body" ) 14297 .wrap( "<div></div>" ) 14298 .css({ 14299 position: "absolute", 14300 visibility: "visible", 14301 left: -j * width, 14302 top: -i * height 14303 }) 14304 14305 // select the wrapper - make it overflow: hidden and absolute positioned based on 14306 // where the original was located +left and +top equal to the size of pieces 14307 .parent() 14308 .addClass( "ui-effects-explode" ) 14309 .css({ 14310 position: "absolute", 14311 overflow: "hidden", 14312 width: width, 14313 height: height, 14314 left: left + ( show ? mx * width : 0 ), 14315 top: top + ( show ? my * height : 0 ), 14316 opacity: show ? 0 : 1 14317 }).animate({ 14318 left: left + ( show ? 0 : mx * width ), 14319 top: top + ( show ? 0 : my * height ), 14320 opacity: show ? 1 : 0 14321 }, o.duration || 500, o.easing, childComplete ); 14322 } 14323 } 14324 14325 function animComplete() { 14326 el.css({ 14327 visibility: "visible" 14328 }); 14329 $( pieces ).remove(); 14330 if ( !show ) { 14331 el.hide(); 14332 } 14333 done(); 14334 } 14335}; 14336 14337})(jQuery); 14338(function( $, undefined ) { 14339 14340$.effects.effect.fade = function( o, done ) { 14341 var el = $( this ), 14342 mode = $.effects.setMode( el, o.mode || "toggle" ); 14343 14344 el.animate({ 14345 opacity: mode 14346 }, { 14347 queue: false, 14348 duration: o.duration, 14349 easing: o.easing, 14350 complete: done 14351 }); 14352}; 14353 14354})( jQuery ); 14355(function( $, undefined ) { 14356 14357$.effects.effect.fold = function( o, done ) { 14358 14359 // Create element 14360 var el = $( this ), 14361 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 14362 mode = $.effects.setMode( el, o.mode || "hide" ), 14363 show = mode === "show", 14364 hide = mode === "hide", 14365 size = o.size || 15, 14366 percent = /([0-9]+)%/.exec( size ), 14367 horizFirst = !!o.horizFirst, 14368 widthFirst = show !== horizFirst, 14369 ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ], 14370 duration = o.duration / 2, 14371 wrapper, distance, 14372 animation1 = {}, 14373 animation2 = {}; 14374 14375 $.effects.save( el, props ); 14376 el.show(); 14377 14378 // Create Wrapper 14379 wrapper = $.effects.createWrapper( el ).css({ 14380 overflow: "hidden" 14381 }); 14382 distance = widthFirst ? 14383 [ wrapper.width(), wrapper.height() ] : 14384 [ wrapper.height(), wrapper.width() ]; 14385 14386 if ( percent ) { 14387 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; 14388 } 14389 if ( show ) { 14390 wrapper.css( horizFirst ? { 14391 height: 0, 14392 width: size 14393 } : { 14394 height: size, 14395 width: 0 14396 }); 14397 } 14398 14399 // Animation 14400 animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size; 14401 animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0; 14402 14403 // Animate 14404 wrapper 14405 .animate( animation1, duration, o.easing ) 14406 .animate( animation2, duration, o.easing, function() { 14407 if ( hide ) { 14408 el.hide(); 14409 } 14410 $.effects.restore( el, props ); 14411 $.effects.removeWrapper( el ); 14412 done(); 14413 }); 14414 14415}; 14416 14417})(jQuery); 14418(function( $, undefined ) { 14419 14420$.effects.effect.highlight = function( o, done ) { 14421 var elem = $( this ), 14422 props = [ "backgroundImage", "backgroundColor", "opacity" ], 14423 mode = $.effects.setMode( elem, o.mode || "show" ), 14424 animation = { 14425 backgroundColor: elem.css( "backgroundColor" ) 14426 }; 14427 14428 if (mode === "hide") { 14429 animation.opacity = 0; 14430 } 14431 14432 $.effects.save( elem, props ); 14433 14434 elem 14435 .show() 14436 .css({ 14437 backgroundImage: "none", 14438 backgroundColor: o.color || "#ffff99" 14439 }) 14440 .animate( animation, { 14441 queue: false, 14442 duration: o.duration, 14443 easing: o.easing, 14444 complete: function() { 14445 if ( mode === "hide" ) { 14446 elem.hide(); 14447 } 14448 $.effects.restore( elem, props ); 14449 done(); 14450 } 14451 }); 14452}; 14453 14454})(jQuery); 14455(function( $, undefined ) { 14456 14457$.effects.effect.pulsate = function( o, done ) { 14458 var elem = $( this ), 14459 mode = $.effects.setMode( elem, o.mode || "show" ), 14460 show = mode === "show", 14461 hide = mode === "hide", 14462 showhide = ( show || mode === "hide" ), 14463 14464 // showing or hiding leaves of the "last" animation 14465 anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), 14466 duration = o.duration / anims, 14467 animateTo = 0, 14468 queue = elem.queue(), 14469 queuelen = queue.length, 14470 i; 14471 14472 if ( show || !elem.is(":visible")) { 14473 elem.css( "opacity", 0 ).show(); 14474 animateTo = 1; 14475 } 14476 14477 // anims - 1 opacity "toggles" 14478 for ( i = 1; i < anims; i++ ) { 14479 elem.animate({ 14480 opacity: animateTo 14481 }, duration, o.easing ); 14482 animateTo = 1 - animateTo; 14483 } 14484 14485 elem.animate({ 14486 opacity: animateTo 14487 }, duration, o.easing); 14488 14489 elem.queue(function() { 14490 if ( hide ) { 14491 elem.hide(); 14492 } 14493 done(); 14494 }); 14495 14496 // We just queued up "anims" animations, we need to put them next in the queue 14497 if ( queuelen > 1 ) { 14498 queue.splice.apply( queue, 14499 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); 14500 } 14501 elem.dequeue(); 14502}; 14503 14504})(jQuery); 14505(function( $, undefined ) { 14506 14507$.effects.effect.puff = function( o, done ) { 14508 var elem = $( this ), 14509 mode = $.effects.setMode( elem, o.mode || "hide" ), 14510 hide = mode === "hide", 14511 percent = parseInt( o.percent, 10 ) || 150, 14512 factor = percent / 100, 14513 original = { 14514 height: elem.height(), 14515 width: elem.width(), 14516 outerHeight: elem.outerHeight(), 14517 outerWidth: elem.outerWidth() 14518 }; 14519 14520 $.extend( o, { 14521 effect: "scale", 14522 queue: false, 14523 fade: true, 14524 mode: mode, 14525 complete: done, 14526 percent: hide ? percent : 100, 14527 from: hide ? 14528 original : 14529 { 14530 height: original.height * factor, 14531 width: original.width * factor, 14532 outerHeight: original.outerHeight * factor, 14533 outerWidth: original.outerWidth * factor 14534 } 14535 }); 14536 14537 elem.effect( o ); 14538}; 14539 14540$.effects.effect.scale = function( o, done ) { 14541 14542 // Create element 14543 var el = $( this ), 14544 options = $.extend( true, {}, o ), 14545 mode = $.effects.setMode( el, o.mode || "effect" ), 14546 percent = parseInt( o.percent, 10 ) || 14547 ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ), 14548 direction = o.direction || "both", 14549 origin = o.origin, 14550 original = { 14551 height: el.height(), 14552 width: el.width(), 14553 outerHeight: el.outerHeight(), 14554 outerWidth: el.outerWidth() 14555 }, 14556 factor = { 14557 y: direction !== "horizontal" ? (percent / 100) : 1, 14558 x: direction !== "vertical" ? (percent / 100) : 1 14559 }; 14560 14561 // We are going to pass this effect to the size effect: 14562 options.effect = "size"; 14563 options.queue = false; 14564 options.complete = done; 14565 14566 // Set default origin and restore for show/hide 14567 if ( mode !== "effect" ) { 14568 options.origin = origin || ["middle","center"]; 14569 options.restore = true; 14570 } 14571 14572 options.from = o.from || ( mode === "show" ? { 14573 height: 0, 14574 width: 0, 14575 outerHeight: 0, 14576 outerWidth: 0 14577 } : original ); 14578 options.to = { 14579 height: original.height * factor.y, 14580 width: original.width * factor.x, 14581 outerHeight: original.outerHeight * factor.y, 14582 outerWidth: original.outerWidth * factor.x 14583 }; 14584 14585 // Fade option to support puff 14586 if ( options.fade ) { 14587 if ( mode === "show" ) { 14588 options.from.opacity = 0; 14589 options.to.opacity = 1; 14590 } 14591 if ( mode === "hide" ) { 14592 options.from.opacity = 1; 14593 options.to.opacity = 0; 14594 } 14595 } 14596 14597 // Animate 14598 el.effect( options ); 14599 14600}; 14601 14602$.effects.effect.size = function( o, done ) { 14603 14604 // Create element 14605 var original, baseline, factor, 14606 el = $( this ), 14607 props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ], 14608 14609 // Always restore 14610 props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ], 14611 14612 // Copy for children 14613 props2 = [ "width", "height", "overflow" ], 14614 cProps = [ "fontSize" ], 14615 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], 14616 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], 14617 14618 // Set options 14619 mode = $.effects.setMode( el, o.mode || "effect" ), 14620 restore = o.restore || mode !== "effect", 14621 scale = o.scale || "both", 14622 origin = o.origin || [ "middle", "center" ], 14623 position = el.css( "position" ), 14624 props = restore ? props0 : props1, 14625 zero = { 14626 height: 0, 14627 width: 0, 14628 outerHeight: 0, 14629 outerWidth: 0 14630 }; 14631 14632 if ( mode === "show" ) { 14633 el.show(); 14634 } 14635 original = { 14636 height: el.height(), 14637 width: el.width(), 14638 outerHeight: el.outerHeight(), 14639 outerWidth: el.outerWidth() 14640 }; 14641 14642 if ( o.mode === "toggle" && mode === "show" ) { 14643 el.from = o.to || zero; 14644 el.to = o.from || original; 14645 } else { 14646 el.from = o.from || ( mode === "show" ? zero : original ); 14647 el.to = o.to || ( mode === "hide" ? zero : original ); 14648 } 14649 14650 // Set scaling factor 14651 factor = { 14652 from: { 14653 y: el.from.height / original.height, 14654 x: el.from.width / original.width 14655 }, 14656 to: { 14657 y: el.to.height / original.height, 14658 x: el.to.width / original.width 14659 } 14660 }; 14661 14662 // Scale the css box 14663 if ( scale === "box" || scale === "both" ) { 14664 14665 // Vertical props scaling 14666 if ( factor.from.y !== factor.to.y ) { 14667 props = props.concat( vProps ); 14668 el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from ); 14669 el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to ); 14670 } 14671 14672 // Horizontal props scaling 14673 if ( factor.from.x !== factor.to.x ) { 14674 props = props.concat( hProps ); 14675 el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from ); 14676 el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to ); 14677 } 14678 } 14679 14680 // Scale the content 14681 if ( scale === "content" || scale === "both" ) { 14682 14683 // Vertical props scaling 14684 if ( factor.from.y !== factor.to.y ) { 14685 props = props.concat( cProps ).concat( props2 ); 14686 el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from ); 14687 el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to ); 14688 } 14689 } 14690 14691 $.effects.save( el, props ); 14692 el.show(); 14693 $.effects.createWrapper( el ); 14694 el.css( "overflow", "hidden" ).css( el.from ); 14695 14696 // Adjust 14697 if (origin) { // Calculate baseline shifts 14698 baseline = $.effects.getBaseline( origin, original ); 14699 el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y; 14700 el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x; 14701 el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y; 14702 el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x; 14703 } 14704 el.css( el.from ); // set top & left 14705 14706 // Animate 14707 if ( scale === "content" || scale === "both" ) { // Scale the children 14708 14709 // Add margins/font-size 14710 vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps); 14711 hProps = hProps.concat([ "marginLeft", "marginRight" ]); 14712 props2 = props0.concat(vProps).concat(hProps); 14713 14714 el.find( "*[width]" ).each( function(){ 14715 var child = $( this ), 14716 c_original = { 14717 height: child.height(), 14718 width: child.width(), 14719 outerHeight: child.outerHeight(), 14720 outerWidth: child.outerWidth() 14721 }; 14722 if (restore) { 14723 $.effects.save(child, props2); 14724 } 14725 14726 child.from = { 14727 height: c_original.height * factor.from.y, 14728 width: c_original.width * factor.from.x, 14729 outerHeight: c_original.outerHeight * factor.from.y, 14730 outerWidth: c_original.outerWidth * factor.from.x 14731 }; 14732 child.to = { 14733 height: c_original.height * factor.to.y, 14734 width: c_original.width * factor.to.x, 14735 outerHeight: c_original.height * factor.to.y, 14736 outerWidth: c_original.width * factor.to.x 14737 }; 14738 14739 // Vertical props scaling 14740 if ( factor.from.y !== factor.to.y ) { 14741 child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from ); 14742 child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to ); 14743 } 14744 14745 // Horizontal props scaling 14746 if ( factor.from.x !== factor.to.x ) { 14747 child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from ); 14748 child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to ); 14749 } 14750 14751 // Animate children 14752 child.css( child.from ); 14753 child.animate( child.to, o.duration, o.easing, function() { 14754 14755 // Restore children 14756 if ( restore ) { 14757 $.effects.restore( child, props2 ); 14758 } 14759 }); 14760 }); 14761 } 14762 14763 // Animate 14764 el.animate( el.to, { 14765 queue: false, 14766 duration: o.duration, 14767 easing: o.easing, 14768 complete: function() { 14769 if ( el.to.opacity === 0 ) { 14770 el.css( "opacity", el.from.opacity ); 14771 } 14772 if( mode === "hide" ) { 14773 el.hide(); 14774 } 14775 $.effects.restore( el, props ); 14776 if ( !restore ) { 14777 14778 // we need to calculate our new positioning based on the scaling 14779 if ( position === "static" ) { 14780 el.css({ 14781 position: "relative", 14782 top: el.to.top, 14783 left: el.to.left 14784 }); 14785 } else { 14786 $.each([ "top", "left" ], function( idx, pos ) { 14787 el.css( pos, function( _, str ) { 14788 var val = parseInt( str, 10 ), 14789 toRef = idx ? el.to.left : el.to.top; 14790 14791 // if original was "auto", recalculate the new value from wrapper 14792 if ( str === "auto" ) { 14793 return toRef + "px"; 14794 } 14795 14796 return val + toRef + "px"; 14797 }); 14798 }); 14799 } 14800 } 14801 14802 $.effects.removeWrapper( el ); 14803 done(); 14804 } 14805 }); 14806 14807}; 14808 14809})(jQuery); 14810(function( $, undefined ) { 14811 14812$.effects.effect.shake = function( o, done ) { 14813 14814 var el = $( this ), 14815 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 14816 mode = $.effects.setMode( el, o.mode || "effect" ), 14817 direction = o.direction || "left", 14818 distance = o.distance || 20, 14819 times = o.times || 3, 14820 anims = times * 2 + 1, 14821 speed = Math.round(o.duration/anims), 14822 ref = (direction === "up" || direction === "down") ? "top" : "left", 14823 positiveMotion = (direction === "up" || direction === "left"), 14824 animation = {}, 14825 animation1 = {}, 14826 animation2 = {}, 14827 i, 14828 14829 // we will need to re-assemble the queue to stack our animations in place 14830 queue = el.queue(), 14831 queuelen = queue.length; 14832 14833 $.effects.save( el, props ); 14834 el.show(); 14835 $.effects.createWrapper( el ); 14836 14837 // Animation 14838 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; 14839 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; 14840 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; 14841 14842 // Animate 14843 el.animate( animation, speed, o.easing ); 14844 14845 // Shakes 14846 for ( i = 1; i < times; i++ ) { 14847 el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing ); 14848 } 14849 el 14850 .animate( animation1, speed, o.easing ) 14851 .animate( animation, speed / 2, o.easing ) 14852 .queue(function() { 14853 if ( mode === "hide" ) { 14854 el.hide(); 14855 } 14856 $.effects.restore( el, props ); 14857 $.effects.removeWrapper( el ); 14858 done(); 14859 }); 14860 14861 // inject all the animations we just queued to be first in line (after "inprogress") 14862 if ( queuelen > 1) { 14863 queue.splice.apply( queue, 14864 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); 14865 } 14866 el.dequeue(); 14867 14868}; 14869 14870})(jQuery); 14871(function( $, undefined ) { 14872 14873$.effects.effect.slide = function( o, done ) { 14874 14875 // Create element 14876 var el = $( this ), 14877 props = [ "position", "top", "bottom", "left", "right", "width", "height" ], 14878 mode = $.effects.setMode( el, o.mode || "show" ), 14879 show = mode === "show", 14880 direction = o.direction || "left", 14881 ref = (direction === "up" || direction === "down") ? "top" : "left", 14882 positiveMotion = (direction === "up" || direction === "left"), 14883 distance, 14884 animation = {}; 14885 14886 // Adjust 14887 $.effects.save( el, props ); 14888 el.show(); 14889 distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ); 14890 14891 $.effects.createWrapper( el ).css({ 14892 overflow: "hidden" 14893 }); 14894 14895 if ( show ) { 14896 el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance ); 14897 } 14898 14899 // Animation 14900 animation[ ref ] = ( show ? 14901 ( positiveMotion ? "+=" : "-=") : 14902 ( positiveMotion ? "-=" : "+=")) + 14903 distance; 14904 14905 // Animate 14906 el.animate( animation, { 14907 queue: false, 14908 duration: o.duration, 14909 easing: o.easing, 14910 complete: function() { 14911 if ( mode === "hide" ) { 14912 el.hide(); 14913 } 14914 $.effects.restore( el, props ); 14915 $.effects.removeWrapper( el ); 14916 done(); 14917 } 14918 }); 14919}; 14920 14921})(jQuery); 14922(function( $, undefined ) { 14923 14924$.effects.effect.transfer = function( o, done ) { 14925 var elem = $( this ), 14926 target = $( o.to ), 14927 targetFixed = target.css( "position" ) === "fixed", 14928 body = $("body"), 14929 fixTop = targetFixed ? body.scrollTop() : 0, 14930 fixLeft = targetFixed ? body.scrollLeft() : 0, 14931 endPosition = target.offset(), 14932 animation = { 14933 top: endPosition.top - fixTop , 14934 left: endPosition.left - fixLeft , 14935 height: target.innerHeight(), 14936 width: target.innerWidth() 14937 }, 14938 startPosition = elem.offset(), 14939 transfer = $( "<div class='ui-effects-transfer'></div>" ) 14940 .appendTo( document.body ) 14941 .addClass( o.className ) 14942 .css({ 14943 top: startPosition.top - fixTop , 14944 left: startPosition.left - fixLeft , 14945 height: elem.innerHeight(), 14946 width: elem.innerWidth(), 14947 position: targetFixed ? "fixed" : "absolute" 14948 }) 14949 .animate( animation, o.duration, o.easing, function() { 14950 transfer.remove(); 14951 done(); 14952 }); 14953}; 14954 14955})(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.