vendor: 8,543 bytes, lines 1-294
1/*! jQuery UI - v1.10.4 - 2014-01-17 2* http://jqueryui.com 3* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.effect.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.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, jquery.ui.menu.js, jquery.ui.position.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js 4* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */ 5(function( $, undefined ) { 6 7var uuid = 0, 8 runiqueId = /^ui-id-\d+$/; 9 10// $.ui might exist from components with no dependencies, e.g., $.ui.position 11$.ui = $.ui || {}; 12 13$.extend( $.ui, { 14 version: "1.10.4", 15 16 keyCode: { 17 BACKSPACE: 8, 18 COMMA: 188, 19 DELETE: 46, 20 DOWN: 40, 21 END: 35, 22 ENTER: 13, 23 ESCAPE: 27, 24 HOME: 36, 25 LEFT: 37, 26 NUMPAD_ADD: 107, 27 NUMPAD_DECIMAL: 110, 28 NUMPAD_DIVIDE: 111, 29 NUMPAD_ENTER: 108, 30 NUMPAD_MULTIPLY: 106, 31 NUMPAD_SUBTRACT: 109, 32 PAGE_DOWN: 34, 33 PAGE_UP: 33, 34 PERIOD: 190, 35 RIGHT: 39, 36 SPACE: 32, 37 TAB: 9, 38 UP: 38 39 } 40}); 41 42// plugins 43$.fn.extend({ 44 focus: (function( orig ) { 45 return function( delay, fn ) { 46 return typeof delay === "number" ? 47 this.each(function() { 48 var elem = this; 49 setTimeout(function() { 50 $( elem ).focus(); 51 if ( fn ) { 52 fn.call( elem ); 53 } 54 }, delay ); 55 }) : 56 orig.apply( this, arguments ); 57 }; 58 })( $.fn.focus ), 59 60 scrollParent: function() { 61 var scrollParent; 62 if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) { 63 scrollParent = this.parents().filter(function() { 64 return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); 65 }).eq(0); 66 } else { 67 scrollParent = this.parents().filter(function() { 68 return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x")); 69 }).eq(0); 70 } 71 72 return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent; 73 }, 74 75 zIndex: function( zIndex ) { 76 if ( zIndex !== undefined ) { 77 return this.css( "zIndex", zIndex ); 78 } 79 80 if ( this.length ) { 81 var elem = $( this[ 0 ] ), position, value; 82 while ( elem.length && elem[ 0 ] !== document ) { 83 // Ignore z-index if position is set to a value where z-index is ignored by the browser 84 // This makes behavior of this function consistent across browsers 85 // WebKit always returns auto if the element is positioned 86 position = elem.css( "position" ); 87 if ( position === "absolute" || position === "relative" || position === "fixed" ) { 88 // IE returns 0 when zIndex is not specified 89 // other browsers return a string 90 // we ignore the case of nested elements with an explicit value of 0 91 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 92 value = parseInt( elem.css( "zIndex" ), 10 ); 93 if ( !isNaN( value ) && value !== 0 ) { 94 return value; 95 } 96 } 97 elem = elem.parent(); 98 } 99 } 100 101 return 0; 102 }, 103 104 uniqueId: function() { 105 return this.each(function() { 106 if ( !this.id ) { 107 this.id = "ui-id-" + (++uuid); 108 } 109 }); 110 }, 111 112 removeUniqueId: function() { 113 return this.each(function() { 114 if ( runiqueId.test( this.id ) ) { 115 $( this ).removeAttr( "id" ); 116 } 117 }); 118 } 119}); 120 121// selectors 122function focusable( element, isTabIndexNotNaN ) { 123 var map, mapName, img, 124 nodeName = element.nodeName.toLowerCase(); 125 if ( "area" === nodeName ) { 126 map = element.parentNode; 127 mapName = map.name; 128 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { 129 return false; 130 } 131 img = $( "img[usemap=#" + mapName + "]" )[0]; 132 return !!img && visible( img ); 133 } 134 return ( /input|select|textarea|button|object/.test( nodeName ) ? 135 !element.disabled : 136 "a" === nodeName ? 137 element.href || isTabIndexNotNaN : 138 isTabIndexNotNaN) && 139 // the element and all of its ancestors must be visible 140 visible( element ); 141} 142 143function visible( element ) { 144 return $.expr.filters.visible( element ) && 145 !$( element ).parents().addBack().filter(function() { 146 return $.css( this, "visibility" ) === "hidden"; 147 }).length; 148} 149 150$.extend( $.expr[ ":" ], { 151 data: $.expr.createPseudo ? 152 $.expr.createPseudo(function( dataName ) { 153 return function( elem ) { 154 return !!$.data( elem, dataName ); 155 }; 156 }) : 157 // support: jQuery <1.8 158 function( elem, i, match ) { 159 return !!$.data( elem, match[ 3 ] ); 160 }, 161 162 focusable: function( element ) { 163 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); 164 }, 165 166 tabbable: function( element ) { 167 var tabIndex = $.attr( element, "tabindex" ), 168 isTabIndexNaN = isNaN( tabIndex ); 169 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); 170 } 171}); 172 173// support: jQuery <1.8 174if ( !$( "<a>" ).outerWidth( 1 ).jquery ) { 175 $.each( [ "Width", "Height" ], function( i, name ) { 176 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], 177 type = name.toLowerCase(), 178 orig = { 179 innerWidth: $.fn.innerWidth, 180 innerHeight: $.fn.innerHeight, 181 outerWidth: $.fn.outerWidth, 182 outerHeight: $.fn.outerHeight 183 }; 184 185 function reduce( elem, size, border, margin ) { 186 $.each( side, function() { 187 size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; 188 if ( border ) { 189 size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; 190 } 191 if ( margin ) { 192 size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; 193 } 194 }); 195 return size; 196 } 197 198 $.fn[ "inner" + name ] = function( size ) { 199 if ( size === undefined ) { 200 return orig[ "inner" + name ].call( this ); 201 } 202 203 return this.each(function() { 204 $( this ).css( type, reduce( this, size ) + "px" ); 205 }); 206 }; 207 208 $.fn[ "outer" + name] = function( size, margin ) { 209 if ( typeof size !== "number" ) { 210 return orig[ "outer" + name ].call( this, size ); 211 } 212 213 return this.each(function() { 214 $( this).css( type, reduce( this, size, true, margin ) + "px" ); 215 }); 216 }; 217 }); 218} 219 220// support: jQuery <1.8 221if ( !$.fn.addBack ) { 222 $.fn.addBack = function( selector ) { 223 return this.add( selector == null ? 224 this.prevObject : this.prevObject.filter( selector ) 225 ); 226 }; 227} 228 229// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413) 230if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) { 231 $.fn.removeData = (function( removeData ) { 232 return function( key ) { 233 if ( arguments.length ) { 234 return removeData.call( this, $.camelCase( key ) ); 235 } else { 236 return removeData.call( this ); 237 } 238 }; 239 })( $.fn.removeData ); 240} 241 242 243 244 245 246// deprecated 247$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() ); 248 249$.support.selectstart = "onselectstart" in document.createElement( "div" ); 250$.fn.extend({ 251 disableSelection: function() { 252 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + 253 ".ui-disableSelection", function( event ) { 254 event.preventDefault(); 255 }); 256 }, 257 258 enableSelection: function() { 259 return this.unbind( ".ui-disableSelection" ); 260 } 261}); 262 263$.extend( $.ui, { 264 // $.ui.plugin is deprecated. Use $.widget() extensions instead. 265 plugin: { 266 add: function( module, option, set ) { 267 var i, 268 proto = $.ui[ module ].prototype; 269 for ( i in set ) { 270 proto.plugins[ i ] = proto.plugins[ i ] || []; 271 proto.plugins[ i ].push( [ option, set[ i ] ] ); 272 } 273 }, 274 call: function( instance, name, args ) { 275 var i, 276 set = instance.plugins[ name ]; 277 if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) { 278 return; 279 } 280 281 for ( i = 0; i < set.length; i++ ) { 282 if ( instance.options[ set[ i ][ 0 ] ] ) { 283 set[ i ][ 1 ].apply( instance.element, args ); 284 } 285 } 286 } 287 }, 288 289 // only used by resizable 290 hasScroll: function( el, a ) { 291 292 //If overflow is hidden, the element might have extra content, but the user wants to hide it 293 if ( $( el ).css( "overflow" ) === "hidden") { 294 return false;
vendor: 6,506 bytes, lines 295-498
295 } 296 297 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", 298 has = false; 299 300 if ( el[ scroll ] > 0 ) { 301 return true; 302 } 303 304 // TODO: determine which cases actually cause this to happen 305 // if the element doesn't have the scroll set, see if it's possible to 306 // set the scroll 307 el[ scroll ] = 1; 308 has = ( el[ scroll ] > 0 ); 309 el[ scroll ] = 0; 310 return has; 311 } 312}); 313 314})( jQuery ); 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) : 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;
vendor: 8,807 bytes, lines 499-830
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 ( arguments.length === 1 ) { 624 return curOption[ key ] === undefined ? null : curOption[ key ]; 625 } 626 curOption[ key ] = value; 627 } else { 628 if ( arguments.length === 1 ) { 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 828(function( $, undefined ) { 829 830var mouseHandled = false;
vendor: 97,508 bytes, lines 831-4124
831$( document ).mouseup( function() { 832 mouseHandled = false; 833}); 834 835$.widget("ui.mouse", { 836 version: "1.10.4", 837 options: { 838 cancel: "input,textarea,button,select,option", 839 distance: 1, 840 delay: 0 841 }, 842 _mouseInit: function() { 843 var that = this; 844 845 this.element 846 .bind("mousedown."+this.widgetName, function(event) { 847 return that._mouseDown(event); 848 }) 849 .bind("click."+this.widgetName, function(event) { 850 if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) { 851 $.removeData(event.target, that.widgetName + ".preventClickEvent"); 852 event.stopImmediatePropagation(); 853 return false; 854 } 855 }); 856 857 this.started = false; 858 }, 859 860 // TODO: make sure destroying one instance of mouse doesn't mess with 861 // other instances of mouse 862 _mouseDestroy: function() { 863 this.element.unbind("."+this.widgetName); 864 if ( this._mouseMoveDelegate ) { 865 $(document) 866 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate) 867 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate); 868 } 869 }, 870 871 _mouseDown: function(event) { 872 // don't let more than one widget handle mouseStart 873 if( mouseHandled ) { return; } 874 875 // we may have missed mouseup (out of window) 876 (this._mouseStarted && this._mouseUp(event)); 877 878 this._mouseDownEvent = event; 879 880 var that = this, 881 btnIsLeft = (event.which === 1), 882 // event.target.nodeName works around a bug in IE 8 with 883 // disabled inputs (#7620) 884 elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); 885 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { 886 return true; 887 } 888 889 this.mouseDelayMet = !this.options.delay; 890 if (!this.mouseDelayMet) { 891 this._mouseDelayTimer = setTimeout(function() { 892 that.mouseDelayMet = true; 893 }, this.options.delay); 894 } 895 896 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 897 this._mouseStarted = (this._mouseStart(event) !== false); 898 if (!this._mouseStarted) { 899 event.preventDefault(); 900 return true; 901 } 902 } 903 904 // Click event may never have fired (Gecko & Opera) 905 if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) { 906 $.removeData(event.target, this.widgetName + ".preventClickEvent"); 907 } 908 909 // these delegates are required to keep context 910 this._mouseMoveDelegate = function(event) { 911 return that._mouseMove(event); 912 }; 913 this._mouseUpDelegate = function(event) { 914 return that._mouseUp(event); 915 }; 916 $(document) 917 .bind("mousemove."+this.widgetName, this._mouseMoveDelegate) 918 .bind("mouseup."+this.widgetName, this._mouseUpDelegate); 919 920 event.preventDefault(); 921 922 mouseHandled = true; 923 return true; 924 }, 925 926 _mouseMove: function(event) { 927 // IE mouseup check - mouseup happened when mouse was out of window 928 if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) { 929 return this._mouseUp(event); 930 } 931 932 if (this._mouseStarted) { 933 this._mouseDrag(event); 934 return event.preventDefault(); 935 } 936 937 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 938 this._mouseStarted = 939 (this._mouseStart(this._mouseDownEvent, event) !== false); 940 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); 941 } 942 943 return !this._mouseStarted; 944 }, 945 946 _mouseUp: function(event) { 947 $(document) 948 .unbind("mousemove."+this.widgetName, this._mouseMoveDelegate) 949 .unbind("mouseup."+this.widgetName, this._mouseUpDelegate); 950 951 if (this._mouseStarted) { 952 this._mouseStarted = false; 953 954 if (event.target === this._mouseDownEvent.target) { 955 $.data(event.target, this.widgetName + ".preventClickEvent", true); 956 } 957 958 this._mouseStop(event); 959 } 960 961 return false; 962 }, 963 964 _mouseDistanceMet: function(event) { 965 return (Math.max( 966 Math.abs(this._mouseDownEvent.pageX - event.pageX), 967 Math.abs(this._mouseDownEvent.pageY - event.pageY) 968 ) >= this.options.distance 969 ); 970 }, 971 972 _mouseDelayMet: function(/* event */) { 973 return this.mouseDelayMet; 974 }, 975 976 // These are placeholder methods, to be overriden by extending plugin 977 _mouseStart: function(/* event */) {}, 978 _mouseDrag: function(/* event */) {}, 979 _mouseStop: function(/* event */) {}, 980 _mouseCapture: function(/* event */) { return true; } 981}); 982 983})(jQuery); 984 985(function( $, undefined ) { 986 987$.widget("ui.draggable", $.ui.mouse, { 988 version: "1.10.4", 989 widgetEventPrefix: "drag", 990 options: { 991 addClasses: true, 992 appendTo: "parent", 993 axis: false, 994 connectToSortable: false, 995 containment: false, 996 cursor: "auto", 997 cursorAt: false, 998 grid: false, 999 handle: false, 1000 helper: "original", 1001 iframeFix: false, 1002 opacity: false, 1003 refreshPositions: false, 1004 revert: false, 1005 revertDuration: 500, 1006 scope: "default", 1007 scroll: true, 1008 scrollSensitivity: 20, 1009 scrollSpeed: 20, 1010 snap: false, 1011 snapMode: "both", 1012 snapTolerance: 20, 1013 stack: false, 1014 zIndex: false, 1015 1016 // callbacks 1017 drag: null, 1018 start: null, 1019 stop: null 1020 }, 1021 _create: function() { 1022 1023 if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) { 1024 this.element[0].style.position = "relative"; 1025 } 1026 if (this.options.addClasses){ 1027 this.element.addClass("ui-draggable"); 1028 } 1029 if (this.options.disabled){ 1030 this.element.addClass("ui-draggable-disabled"); 1031 } 1032 1033 this._mouseInit(); 1034 1035 }, 1036 1037 _destroy: function() { 1038 this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" ); 1039 this._mouseDestroy(); 1040 }, 1041 1042 _mouseCapture: function(event) { 1043 1044 var o = this.options; 1045 1046 // among others, prevent a drag on a resizable-handle 1047 if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) { 1048 return false; 1049 } 1050 1051 //Quit if we're not on a valid handle 1052 this.handle = this._getHandle(event); 1053 if (!this.handle) { 1054 return false; 1055 } 1056 1057 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { 1058 $("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>") 1059 .css({ 1060 width: this.offsetWidth+"px", height: this.offsetHeight+"px", 1061 position: "absolute", opacity: "0.001", zIndex: 1000 1062 }) 1063 .css($(this).offset()) 1064 .appendTo("body"); 1065 }); 1066 1067 return true; 1068 1069 }, 1070 1071 _mouseStart: function(event) { 1072 1073 var o = this.options; 1074 1075 //Create and append the visible helper 1076 this.helper = this._createHelper(event); 1077 1078 this.helper.addClass("ui-draggable-dragging"); 1079 1080 //Cache the helper size 1081 this._cacheHelperProportions(); 1082 1083 //If ddmanager is used for droppables, set the global draggable 1084 if($.ui.ddmanager) { 1085 $.ui.ddmanager.current = this; 1086 } 1087 1088 /* 1089 * - Position generation - 1090 * This block generates everything position related - it's the core of draggables. 1091 */ 1092 1093 //Cache the margins of the original element 1094 this._cacheMargins(); 1095 1096 //Store the helper's css position 1097 this.cssPosition = this.helper.css( "position" ); 1098 this.scrollParent = this.helper.scrollParent(); 1099 this.offsetParent = this.helper.offsetParent(); 1100 this.offsetParentCssPosition = this.offsetParent.css( "position" ); 1101 1102 //The element's absolute position on the page minus margins 1103 this.offset = this.positionAbs = this.element.offset(); 1104 this.offset = { 1105 top: this.offset.top - this.margins.top, 1106 left: this.offset.left - this.margins.left 1107 }; 1108 1109 //Reset scroll cache 1110 this.offset.scroll = false; 1111 1112 $.extend(this.offset, { 1113 click: { //Where the click happened, relative to the element 1114 left: event.pageX - this.offset.left, 1115 top: event.pageY - this.offset.top 1116 }, 1117 parent: this._getParentOffset(), 1118 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper 1119 }); 1120 1121 //Generate the original position 1122 this.originalPosition = this.position = this._generatePosition(event); 1123 this.originalPageX = event.pageX; 1124 this.originalPageY = event.pageY; 1125 1126 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 1127 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); 1128 1129 //Set a containment if given in the options 1130 this._setContainment(); 1131 1132 //Trigger event + callbacks 1133 if(this._trigger("start", event) === false) { 1134 this._clear(); 1135 return false; 1136 } 1137 1138 //Recache the helper size 1139 this._cacheHelperProportions(); 1140 1141 //Prepare the droppable offsets 1142 if ($.ui.ddmanager && !o.dropBehaviour) { 1143 $.ui.ddmanager.prepareOffsets(this, event); 1144 } 1145 1146 1147 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position 1148 1149 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) 1150 if ( $.ui.ddmanager ) { 1151 $.ui.ddmanager.dragStart(this, event); 1152 } 1153 1154 return true; 1155 }, 1156 1157 _mouseDrag: function(event, noPropagation) { 1158 // reset any necessary cached properties (see #5009) 1159 if ( this.offsetParentCssPosition === "fixed" ) { 1160 this.offset.parent = this._getParentOffset(); 1161 } 1162 1163 //Compute the helpers position 1164 this.position = this._generatePosition(event); 1165 this.positionAbs = this._convertPositionTo("absolute"); 1166 1167 //Call plugins and callbacks and use the resulting position if something is returned 1168 if (!noPropagation) { 1169 var ui = this._uiHash(); 1170 if(this._trigger("drag", event, ui) === false) { 1171 this._mouseUp({}); 1172 return false; 1173 } 1174 this.position = ui.position; 1175 } 1176 1177 if(!this.options.axis || this.options.axis !== "y") { 1178 this.helper[0].style.left = this.position.left+"px"; 1179 } 1180 if(!this.options.axis || this.options.axis !== "x") { 1181 this.helper[0].style.top = this.position.top+"px"; 1182 } 1183 if($.ui.ddmanager) { 1184 $.ui.ddmanager.drag(this, event); 1185 } 1186 1187 return false; 1188 }, 1189 1190 _mouseStop: function(event) { 1191 1192 //If we are using droppables, inform the manager about the drop 1193 var that = this, 1194 dropped = false; 1195 if ($.ui.ddmanager && !this.options.dropBehaviour) { 1196 dropped = $.ui.ddmanager.drop(this, event); 1197 } 1198 1199 //if a drop comes from outside (a sortable) 1200 if(this.dropped) { 1201 dropped = this.dropped; 1202 this.dropped = false; 1203 } 1204 1205 //if the original element is no longer in the DOM don't bother to continue (see #8269) 1206 if ( this.options.helper === "original" && !$.contains( this.element[ 0 ].ownerDocument, this.element[ 0 ] ) ) { 1207 return false; 1208 } 1209 1210 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))) { 1211 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { 1212 if(that._trigger("stop", event) !== false) { 1213 that._clear(); 1214 } 1215 }); 1216 } else { 1217 if(this._trigger("stop", event) !== false) { 1218 this._clear(); 1219 } 1220 } 1221 1222 return false; 1223 }, 1224 1225 _mouseUp: function(event) { 1226 //Remove frame helpers 1227 $("div.ui-draggable-iframeFix").each(function() { 1228 this.parentNode.removeChild(this); 1229 }); 1230 1231 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) 1232 if( $.ui.ddmanager ) { 1233 $.ui.ddmanager.dragStop(this, event); 1234 } 1235 1236 return $.ui.mouse.prototype._mouseUp.call(this, event); 1237 }, 1238 1239 cancel: function() { 1240 1241 if(this.helper.is(".ui-draggable-dragging")) { 1242 this._mouseUp({}); 1243 } else { 1244 this._clear(); 1245 } 1246 1247 return this; 1248 1249 }, 1250 1251 _getHandle: function(event) { 1252 return this.options.handle ? 1253 !!$( event.target ).closest( this.element.find( this.options.handle ) ).length : 1254 true; 1255 }, 1256 1257 _createHelper: function(event) { 1258 1259 var o = this.options, 1260 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element); 1261 1262 if(!helper.parents("body").length) { 1263 helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo)); 1264 } 1265 1266 if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) { 1267 helper.css("position", "absolute"); 1268 } 1269 1270 return helper; 1271 1272 }, 1273 1274 _adjustOffsetFromHelper: function(obj) { 1275 if (typeof obj === "string") { 1276 obj = obj.split(" "); 1277 } 1278 if ($.isArray(obj)) { 1279 obj = {left: +obj[0], top: +obj[1] || 0}; 1280 } 1281 if ("left" in obj) { 1282 this.offset.click.left = obj.left + this.margins.left; 1283 } 1284 if ("right" in obj) { 1285 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 1286 } 1287 if ("top" in obj) { 1288 this.offset.click.top = obj.top + this.margins.top; 1289 } 1290 if ("bottom" in obj) { 1291 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 1292 } 1293 }, 1294 1295 _getParentOffset: function() { 1296 1297 //Get the offsetParent and cache its position 1298 var po = this.offsetParent.offset(); 1299 1300 // This is a special case where we need to modify a offset calculated on start, since the following happened: 1301 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent 1302 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that 1303 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag 1304 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { 1305 po.left += this.scrollParent.scrollLeft(); 1306 po.top += this.scrollParent.scrollTop(); 1307 } 1308 1309 //This needs to be actually done for all browsers, since pageX/pageY includes this information 1310 //Ugly IE fix 1311 if((this.offsetParent[0] === document.body) || 1312 (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { 1313 po = { top: 0, left: 0 }; 1314 } 1315 1316 return { 1317 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), 1318 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) 1319 }; 1320 1321 }, 1322 1323 _getRelativeOffset: function() { 1324 1325 if(this.cssPosition === "relative") { 1326 var p = this.element.position(); 1327 return { 1328 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), 1329 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() 1330 }; 1331 } else { 1332 return { top: 0, left: 0 }; 1333 } 1334 1335 }, 1336 1337 _cacheMargins: function() { 1338 this.margins = { 1339 left: (parseInt(this.element.css("marginLeft"),10) || 0), 1340 top: (parseInt(this.element.css("marginTop"),10) || 0), 1341 right: (parseInt(this.element.css("marginRight"),10) || 0), 1342 bottom: (parseInt(this.element.css("marginBottom"),10) || 0) 1343 }; 1344 }, 1345 1346 _cacheHelperProportions: function() { 1347 this.helperProportions = { 1348 width: this.helper.outerWidth(), 1349 height: this.helper.outerHeight() 1350 }; 1351 }, 1352 1353 _setContainment: function() { 1354 1355 var over, c, ce, 1356 o = this.options; 1357 1358 if ( !o.containment ) { 1359 this.containment = null; 1360 return; 1361 } 1362 1363 if ( o.containment === "window" ) { 1364 this.containment = [ 1365 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left, 1366 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top, 1367 $( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left, 1368 $( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top 1369 ]; 1370 return; 1371 } 1372 1373 if ( o.containment === "document") { 1374 this.containment = [ 1375 0, 1376 0, 1377 $( document ).width() - this.helperProportions.width - this.margins.left, 1378 ( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top 1379 ]; 1380 return; 1381 } 1382 1383 if ( o.containment.constructor === Array ) { 1384 this.containment = o.containment; 1385 return; 1386 } 1387 1388 if ( o.containment === "parent" ) { 1389 o.containment = this.helper[ 0 ].parentNode; 1390 } 1391 1392 c = $( o.containment ); 1393 ce = c[ 0 ]; 1394 1395 if( !ce ) { 1396 return; 1397 } 1398 1399 over = c.css( "overflow" ) !== "hidden"; 1400 1401 this.containment = [ 1402 ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ), 1403 ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ) , 1404 ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - this.helperProportions.width - this.margins.left - this.margins.right, 1405 ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - this.helperProportions.height - this.margins.top - this.margins.bottom 1406 ]; 1407 this.relative_container = c; 1408 }, 1409 1410 _convertPositionTo: function(d, pos) { 1411 1412 if(!pos) { 1413 pos = this.position; 1414 } 1415 1416 var mod = d === "absolute" ? 1 : -1, 1417 scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent; 1418 1419 //Cache the scroll 1420 if (!this.offset.scroll) { 1421 this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()}; 1422 } 1423 1424 return { 1425 top: ( 1426 pos.top + // The absolute mouse position 1427 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 1428 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) 1429 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) * mod ) 1430 ), 1431 left: ( 1432 pos.left + // The absolute mouse position 1433 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 1434 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) 1435 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) * mod ) 1436 ) 1437 }; 1438 1439 }, 1440 1441 _generatePosition: function(event) { 1442 1443 var containment, co, top, left, 1444 o = this.options, 1445 scroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent, 1446 pageX = event.pageX, 1447 pageY = event.pageY; 1448 1449 //Cache the scroll 1450 if (!this.offset.scroll) { 1451 this.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()}; 1452 } 1453 1454 /* 1455 * - Position constraining - 1456 * Constrain the position to a mix of grid, containment. 1457 */ 1458 1459 // If we are not dragging yet, we won't check for options 1460 if ( this.originalPosition ) { 1461 if ( this.containment ) { 1462 if ( this.relative_container ){ 1463 co = this.relative_container.offset(); 1464 containment = [ 1465 this.containment[ 0 ] + co.left, 1466 this.containment[ 1 ] + co.top, 1467 this.containment[ 2 ] + co.left, 1468 this.containment[ 3 ] + co.top 1469 ]; 1470 } 1471 else { 1472 containment = this.containment; 1473 } 1474 1475 if(event.pageX - this.offset.click.left < containment[0]) { 1476 pageX = containment[0] + this.offset.click.left; 1477 } 1478 if(event.pageY - this.offset.click.top < containment[1]) { 1479 pageY = containment[1] + this.offset.click.top; 1480 } 1481 if(event.pageX - this.offset.click.left > containment[2]) { 1482 pageX = containment[2] + this.offset.click.left; 1483 } 1484 if(event.pageY - this.offset.click.top > containment[3]) { 1485 pageY = containment[3] + this.offset.click.top; 1486 } 1487 } 1488 1489 if(o.grid) { 1490 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) 1491 top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; 1492 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; 1493 1494 left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; 1495 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; 1496 } 1497 1498 } 1499 1500 return { 1501 top: ( 1502 pageY - // The absolute mouse position 1503 this.offset.click.top - // Click offset (relative to the element) 1504 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent 1505 this.offset.parent.top + // The offsetParent's offset without borders (offset + border) 1506 ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) 1507 ), 1508 left: ( 1509 pageX - // The absolute mouse position 1510 this.offset.click.left - // Click offset (relative to the element) 1511 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent 1512 this.offset.parent.left + // The offsetParent's offset without borders (offset + border) 1513 ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) 1514 ) 1515 }; 1516 1517 }, 1518 1519 _clear: function() { 1520 this.helper.removeClass("ui-draggable-dragging"); 1521 if(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) { 1522 this.helper.remove(); 1523 } 1524 this.helper = null; 1525 this.cancelHelperRemoval = false; 1526 }, 1527 1528 // From now on bulk stuff - mainly helpers 1529 1530 _trigger: function(type, event, ui) { 1531 ui = ui || this._uiHash(); 1532 $.ui.plugin.call(this, type, [event, ui]); 1533 //The absolute position has to be recalculated after plugins 1534 if(type === "drag") { 1535 this.positionAbs = this._convertPositionTo("absolute"); 1536 } 1537 return $.Widget.prototype._trigger.call(this, type, event, ui); 1538 }, 1539 1540 plugins: {}, 1541 1542 _uiHash: function() { 1543 return { 1544 helper: this.helper, 1545 position: this.position, 1546 originalPosition: this.originalPosition, 1547 offset: this.positionAbs 1548 }; 1549 } 1550 1551}); 1552 1553$.ui.plugin.add("draggable", "connectToSortable", { 1554 start: function(event, ui) { 1555 1556 var inst = $(this).data("ui-draggable"), o = inst.options, 1557 uiSortable = $.extend({}, ui, { item: inst.element }); 1558 inst.sortables = []; 1559 $(o.connectToSortable).each(function() { 1560 var sortable = $.data(this, "ui-sortable"); 1561 if (sortable && !sortable.options.disabled) { 1562 inst.sortables.push({ 1563 instance: sortable, 1564 shouldRevert: sortable.options.revert 1565 }); 1566 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). 1567 sortable._trigger("activate", event, uiSortable); 1568 } 1569 }); 1570 1571 }, 1572 stop: function(event, ui) { 1573 1574 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper 1575 var inst = $(this).data("ui-draggable"), 1576 uiSortable = $.extend({}, ui, { item: inst.element }); 1577 1578 $.each(inst.sortables, function() { 1579 if(this.instance.isOver) { 1580 1581 this.instance.isOver = 0; 1582 1583 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance 1584 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) 1585 1586 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid" 1587 if(this.shouldRevert) { 1588 this.instance.options.revert = this.shouldRevert; 1589 } 1590 1591 //Trigger the stop of the sortable 1592 this.instance._mouseStop(event); 1593 1594 this.instance.options.helper = this.instance.options._helper; 1595 1596 //If the helper has been the original item, restore properties in the sortable 1597 if(inst.options.helper === "original") { 1598 this.instance.currentItem.css({ top: "auto", left: "auto" }); 1599 } 1600 1601 } else { 1602 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance 1603 this.instance._trigger("deactivate", event, uiSortable); 1604 } 1605 1606 }); 1607 1608 }, 1609 drag: function(event, ui) { 1610 1611 var inst = $(this).data("ui-draggable"), that = this; 1612 1613 $.each(inst.sortables, function() { 1614 1615 var innermostIntersecting = false, 1616 thisSortable = this; 1617 1618 //Copy over some variables to allow calling the sortable's native _intersectsWith 1619 this.instance.positionAbs = inst.positionAbs; 1620 this.instance.helperProportions = inst.helperProportions; 1621 this.instance.offset.click = inst.offset.click; 1622 1623 if(this.instance._intersectsWith(this.instance.containerCache)) { 1624 innermostIntersecting = true; 1625 $.each(inst.sortables, function () { 1626 this.instance.positionAbs = inst.positionAbs; 1627 this.instance.helperProportions = inst.helperProportions; 1628 this.instance.offset.click = inst.offset.click; 1629 if (this !== thisSortable && 1630 this.instance._intersectsWith(this.instance.containerCache) && 1631 $.contains(thisSortable.instance.element[0], this.instance.element[0]) 1632 ) { 1633 innermostIntersecting = false; 1634 } 1635 return innermostIntersecting; 1636 }); 1637 } 1638 1639 1640 if(innermostIntersecting) { 1641 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once 1642 if(!this.instance.isOver) { 1643 1644 this.instance.isOver = 1; 1645 //Now we fake the start of dragging for the sortable instance, 1646 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem 1647 //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) 1648 this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true); 1649 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it 1650 this.instance.options.helper = function() { return ui.helper[0]; }; 1651 1652 event.target = this.instance.currentItem[0]; 1653 this.instance._mouseCapture(event, true); 1654 this.instance._mouseStart(event, true, true); 1655 1656 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes 1657 this.instance.offset.click.top = inst.offset.click.top; 1658 this.instance.offset.click.left = inst.offset.click.left; 1659 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; 1660 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; 1661 1662 inst._trigger("toSortable", event); 1663 inst.dropped = this.instance.element; //draggable revert needs that 1664 //hack so receive/update callbacks work (mostly) 1665 inst.currentItem = inst.element; 1666 this.instance.fromOutside = inst; 1667 1668 } 1669 1670 //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 1671 if(this.instance.currentItem) { 1672 this.instance._mouseDrag(event); 1673 } 1674 1675 } else { 1676 1677 //If it doesn't intersect with the sortable, and it intersected before, 1678 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval 1679 if(this.instance.isOver) { 1680 1681 this.instance.isOver = 0; 1682 this.instance.cancelHelperRemoval = true; 1683 1684 //Prevent reverting on this forced stop 1685 this.instance.options.revert = false; 1686 1687 // The out event needs to be triggered independently 1688 this.instance._trigger("out", event, this.instance._uiHash(this.instance)); 1689 1690 this.instance._mouseStop(event, true); 1691 this.instance.options.helper = this.instance.options._helper; 1692 1693 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size 1694 this.instance.currentItem.remove(); 1695 if(this.instance.placeholder) { 1696 this.instance.placeholder.remove(); 1697 } 1698 1699 inst._trigger("fromSortable", event); 1700 inst.dropped = false; //draggable revert needs that 1701 } 1702 1703 } 1704 1705 }); 1706 1707 } 1708}); 1709 1710$.ui.plugin.add("draggable", "cursor", { 1711 start: function() { 1712 var t = $("body"), o = $(this).data("ui-draggable").options; 1713 if (t.css("cursor")) { 1714 o._cursor = t.css("cursor"); 1715 } 1716 t.css("cursor", o.cursor); 1717 }, 1718 stop: function() { 1719 var o = $(this).data("ui-draggable").options; 1720 if (o._cursor) { 1721 $("body").css("cursor", o._cursor); 1722 } 1723 } 1724}); 1725 1726$.ui.plugin.add("draggable", "opacity", { 1727 start: function(event, ui) { 1728 var t = $(ui.helper), o = $(this).data("ui-draggable").options; 1729 if(t.css("opacity")) { 1730 o._opacity = t.css("opacity"); 1731 } 1732 t.css("opacity", o.opacity); 1733 }, 1734 stop: function(event, ui) { 1735 var o = $(this).data("ui-draggable").options; 1736 if(o._opacity) { 1737 $(ui.helper).css("opacity", o._opacity); 1738 } 1739 } 1740}); 1741 1742$.ui.plugin.add("draggable", "scroll", { 1743 start: function() { 1744 var i = $(this).data("ui-draggable"); 1745 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") { 1746 i.overflowOffset = i.scrollParent.offset(); 1747 } 1748 }, 1749 drag: function( event ) { 1750 1751 var i = $(this).data("ui-draggable"), o = i.options, scrolled = false; 1752 1753 if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") { 1754 1755 if(!o.axis || o.axis !== "x") { 1756 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { 1757 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; 1758 } else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) { 1759 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; 1760 } 1761 } 1762 1763 if(!o.axis || o.axis !== "y") { 1764 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { 1765 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; 1766 } else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) { 1767 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; 1768 } 1769 } 1770 1771 } else { 1772 1773 if(!o.axis || o.axis !== "x") { 1774 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { 1775 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); 1776 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { 1777 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); 1778 } 1779 } 1780 1781 if(!o.axis || o.axis !== "y") { 1782 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { 1783 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); 1784 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { 1785 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); 1786 } 1787 } 1788 1789 } 1790 1791 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { 1792 $.ui.ddmanager.prepareOffsets(i, event); 1793 } 1794 1795 } 1796}); 1797 1798$.ui.plugin.add("draggable", "snap", { 1799 start: function() { 1800 1801 var i = $(this).data("ui-draggable"), 1802 o = i.options; 1803 1804 i.snapElements = []; 1805 1806 $(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() { 1807 var $t = $(this), 1808 $o = $t.offset(); 1809 if(this !== i.element[0]) { 1810 i.snapElements.push({ 1811 item: this, 1812 width: $t.outerWidth(), height: $t.outerHeight(), 1813 top: $o.top, left: $o.left 1814 }); 1815 } 1816 }); 1817 1818 }, 1819 drag: function(event, ui) { 1820 1821 var ts, bs, ls, rs, l, r, t, b, i, first, 1822 inst = $(this).data("ui-draggable"), 1823 o = inst.options, 1824 d = o.snapTolerance, 1825 x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, 1826 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; 1827 1828 for (i = inst.snapElements.length - 1; i >= 0; i--){ 1829 1830 l = inst.snapElements[i].left; 1831 r = l + inst.snapElements[i].width; 1832 t = inst.snapElements[i].top; 1833 b = t + inst.snapElements[i].height; 1834 1835 if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) { 1836 if(inst.snapElements[i].snapping) { 1837 (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); 1838 } 1839 inst.snapElements[i].snapping = false; 1840 continue; 1841 } 1842 1843 if(o.snapMode !== "inner") { 1844 ts = Math.abs(t - y2) <= d; 1845 bs = Math.abs(b - y1) <= d; 1846 ls = Math.abs(l - x2) <= d; 1847 rs = Math.abs(r - x1) <= d; 1848 if(ts) { 1849 ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; 1850 } 1851 if(bs) { 1852 ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; 1853 } 1854 if(ls) { 1855 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; 1856 } 1857 if(rs) { 1858 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; 1859 } 1860 } 1861 1862 first = (ts || bs || ls || rs); 1863 1864 if(o.snapMode !== "outer") { 1865 ts = Math.abs(t - y1) <= d; 1866 bs = Math.abs(b - y2) <= d; 1867 ls = Math.abs(l - x1) <= d; 1868 rs = Math.abs(r - x2) <= d; 1869 if(ts) { 1870 ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; 1871 } 1872 if(bs) { 1873 ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; 1874 } 1875 if(ls) { 1876 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; 1877 } 1878 if(rs) { 1879 ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; 1880 } 1881 } 1882 1883 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) { 1884 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); 1885 } 1886 inst.snapElements[i].snapping = (ts || bs || ls || rs || first); 1887 1888 } 1889 1890 } 1891}); 1892 1893$.ui.plugin.add("draggable", "stack", { 1894 start: function() { 1895 var min, 1896 o = this.data("ui-draggable").options, 1897 group = $.makeArray($(o.stack)).sort(function(a,b) { 1898 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); 1899 }); 1900 1901 if (!group.length) { return; } 1902 1903 min = parseInt($(group[0]).css("zIndex"), 10) || 0; 1904 $(group).each(function(i) { 1905 $(this).css("zIndex", min + i); 1906 }); 1907 this.css("zIndex", (min + group.length)); 1908 } 1909}); 1910 1911$.ui.plugin.add("draggable", "zIndex", { 1912 start: function(event, ui) { 1913 var t = $(ui.helper), o = $(this).data("ui-draggable").options; 1914 if(t.css("zIndex")) { 1915 o._zIndex = t.css("zIndex"); 1916 } 1917 t.css("zIndex", o.zIndex); 1918 }, 1919 stop: function(event, ui) { 1920 var o = $(this).data("ui-draggable").options; 1921 if(o._zIndex) { 1922 $(ui.helper).css("zIndex", o._zIndex); 1923 } 1924 } 1925}); 1926 1927})(jQuery); 1928 1929(function( $, undefined ) { 1930 1931function isOverAxis( x, reference, size ) { 1932 return ( x > reference ) && ( x < ( reference + size ) ); 1933} 1934 1935$.widget("ui.droppable", { 1936 version: "1.10.4", 1937 widgetEventPrefix: "drop", 1938 options: { 1939 accept: "*", 1940 activeClass: false, 1941 addClasses: true, 1942 greedy: false, 1943 hoverClass: false, 1944 scope: "default", 1945 tolerance: "intersect", 1946 1947 // callbacks 1948 activate: null, 1949 deactivate: null, 1950 drop: null, 1951 out: null, 1952 over: null 1953 }, 1954 _create: function() { 1955 1956 var proportions, 1957 o = this.options, 1958 accept = o.accept; 1959 1960 this.isover = false; 1961 this.isout = true; 1962 1963 this.accept = $.isFunction(accept) ? accept : function(d) { 1964 return d.is(accept); 1965 }; 1966 1967 this.proportions = function( /* valueToWrite */ ) { 1968 if ( arguments.length ) { 1969 // Store the droppable's proportions 1970 proportions = arguments[ 0 ]; 1971 } else { 1972 // Retrieve or derive the droppable's proportions 1973 return proportions ? 1974 proportions : 1975 proportions = { 1976 width: this.element[ 0 ].offsetWidth, 1977 height: this.element[ 0 ].offsetHeight 1978 }; 1979 } 1980 }; 1981 1982 // Add the reference and positions to the manager 1983 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; 1984 $.ui.ddmanager.droppables[o.scope].push(this); 1985 1986 (o.addClasses && this.element.addClass("ui-droppable")); 1987 1988 }, 1989 1990 _destroy: function() { 1991 var i = 0, 1992 drop = $.ui.ddmanager.droppables[this.options.scope]; 1993 1994 for ( ; i < drop.length; i++ ) { 1995 if ( drop[i] === this ) { 1996 drop.splice(i, 1); 1997 } 1998 } 1999 2000 this.element.removeClass("ui-droppable ui-droppable-disabled"); 2001 }, 2002 2003 _setOption: function(key, value) { 2004 2005 if(key === "accept") { 2006 this.accept = $.isFunction(value) ? value : function(d) { 2007 return d.is(value); 2008 }; 2009 } 2010 $.Widget.prototype._setOption.apply(this, arguments); 2011 }, 2012 2013 _activate: function(event) { 2014 var draggable = $.ui.ddmanager.current; 2015 if(this.options.activeClass) { 2016 this.element.addClass(this.options.activeClass); 2017 } 2018 if(draggable){ 2019 this._trigger("activate", event, this.ui(draggable)); 2020 } 2021 }, 2022 2023 _deactivate: function(event) { 2024 var draggable = $.ui.ddmanager.current; 2025 if(this.options.activeClass) { 2026 this.element.removeClass(this.options.activeClass); 2027 } 2028 if(draggable){ 2029 this._trigger("deactivate", event, this.ui(draggable)); 2030 } 2031 }, 2032 2033 _over: function(event) { 2034 2035 var draggable = $.ui.ddmanager.current; 2036 2037 // Bail if draggable and droppable are same element 2038 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { 2039 return; 2040 } 2041 2042 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 2043 if(this.options.hoverClass) { 2044 this.element.addClass(this.options.hoverClass); 2045 } 2046 this._trigger("over", event, this.ui(draggable)); 2047 } 2048 2049 }, 2050 2051 _out: function(event) { 2052 2053 var draggable = $.ui.ddmanager.current; 2054 2055 // Bail if draggable and droppable are same element 2056 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { 2057 return; 2058 } 2059 2060 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 2061 if(this.options.hoverClass) { 2062 this.element.removeClass(this.options.hoverClass); 2063 } 2064 this._trigger("out", event, this.ui(draggable)); 2065 } 2066 2067 }, 2068 2069 _drop: function(event,custom) { 2070 2071 var draggable = custom || $.ui.ddmanager.current, 2072 childrenIntersection = false; 2073 2074 // Bail if draggable and droppable are same element 2075 if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) { 2076 return false; 2077 } 2078 2079 this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() { 2080 var inst = $.data(this, "ui-droppable"); 2081 if( 2082 inst.options.greedy && 2083 !inst.options.disabled && 2084 inst.options.scope === draggable.options.scope && 2085 inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) && 2086 $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) 2087 ) { childrenIntersection = true; return false; } 2088 }); 2089 if(childrenIntersection) { 2090 return false; 2091 } 2092 2093 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 2094 if(this.options.activeClass) { 2095 this.element.removeClass(this.options.activeClass); 2096 } 2097 if(this.options.hoverClass) { 2098 this.element.removeClass(this.options.hoverClass); 2099 } 2100 this._trigger("drop", event, this.ui(draggable)); 2101 return this.element; 2102 } 2103 2104 return false; 2105 2106 }, 2107 2108 ui: function(c) { 2109 return { 2110 draggable: (c.currentItem || c.element), 2111 helper: c.helper, 2112 position: c.position, 2113 offset: c.positionAbs 2114 }; 2115 } 2116 2117}); 2118 2119$.ui.intersect = function(draggable, droppable, toleranceMode) { 2120 2121 if (!droppable.offset) { 2122 return false; 2123 } 2124 2125 var draggableLeft, draggableTop, 2126 x1 = (draggable.positionAbs || draggable.position.absolute).left, 2127 y1 = (draggable.positionAbs || draggable.position.absolute).top, 2128 x2 = x1 + draggable.helperProportions.width, 2129 y2 = y1 + draggable.helperProportions.height, 2130 l = droppable.offset.left, 2131 t = droppable.offset.top, 2132 r = l + droppable.proportions().width, 2133 b = t + droppable.proportions().height; 2134 2135 switch (toleranceMode) { 2136 case "fit": 2137 return (l <= x1 && x2 <= r && t <= y1 && y2 <= b); 2138 case "intersect": 2139 return (l < x1 + (draggable.helperProportions.width / 2) && // Right Half 2140 x2 - (draggable.helperProportions.width / 2) < r && // Left Half 2141 t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half 2142 y2 - (draggable.helperProportions.height / 2) < b ); // Top Half 2143 case "pointer": 2144 draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left); 2145 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top); 2146 return isOverAxis( draggableTop, t, droppable.proportions().height ) && isOverAxis( draggableLeft, l, droppable.proportions().width ); 2147 case "touch": 2148 return ( 2149 (y1 >= t && y1 <= b) || // Top edge touching 2150 (y2 >= t && y2 <= b) || // Bottom edge touching 2151 (y1 < t && y2 > b) // Surrounded vertically 2152 ) && ( 2153 (x1 >= l && x1 <= r) || // Left edge touching 2154 (x2 >= l && x2 <= r) || // Right edge touching 2155 (x1 < l && x2 > r) // Surrounded horizontally 2156 ); 2157 default: 2158 return false; 2159 } 2160 2161}; 2162 2163/* 2164 This manager tracks offsets of draggables and droppables 2165*/ 2166$.ui.ddmanager = { 2167 current: null, 2168 droppables: { "default": [] }, 2169 prepareOffsets: function(t, event) { 2170 2171 var i, j, 2172 m = $.ui.ddmanager.droppables[t.options.scope] || [], 2173 type = event ? event.type : null, // workaround for #2317 2174 list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack(); 2175 2176 droppablesLoop: for (i = 0; i < m.length; i++) { 2177 2178 //No disabled and non-accepted 2179 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) { 2180 continue; 2181 } 2182 2183 // Filter out elements in the current dragged item 2184 for (j=0; j < list.length; j++) { 2185 if(list[j] === m[i].element[0]) { 2186 m[i].proportions().height = 0; 2187 continue droppablesLoop; 2188 } 2189 } 2190 2191 m[i].visible = m[i].element.css("display") !== "none"; 2192 if(!m[i].visible) { 2193 continue; 2194 } 2195 2196 //Activate the droppable if used directly from draggables 2197 if(type === "mousedown") { 2198 m[i]._activate.call(m[i], event); 2199 } 2200 2201 m[ i ].offset = m[ i ].element.offset(); 2202 m[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth, height: m[ i ].element[ 0 ].offsetHeight }); 2203 2204 } 2205 2206 }, 2207 drop: function(draggable, event) { 2208 2209 var dropped = false; 2210 // Create a copy of the droppables in case the list changes during the drop (#9116) 2211 $.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function() { 2212 2213 if(!this.options) { 2214 return; 2215 } 2216 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) { 2217 dropped = this._drop.call(this, event) || dropped; 2218 } 2219 2220 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 2221 this.isout = true; 2222 this.isover = false; 2223 this._deactivate.call(this, event); 2224 } 2225 2226 }); 2227 return dropped; 2228 2229 }, 2230 dragStart: function( draggable, event ) { 2231 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) 2232 draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() { 2233 if( !draggable.options.refreshPositions ) { 2234 $.ui.ddmanager.prepareOffsets( draggable, event ); 2235 } 2236 }); 2237 }, 2238 drag: function(draggable, event) { 2239 2240 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. 2241 if(draggable.options.refreshPositions) { 2242 $.ui.ddmanager.prepareOffsets(draggable, event); 2243 } 2244 2245 //Run through all droppables and check their positions based on specific tolerance options 2246 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { 2247 2248 if(this.options.disabled || this.greedyChild || !this.visible) { 2249 return; 2250 } 2251 2252 var parentInstance, scope, parent, 2253 intersects = $.ui.intersect(draggable, this, this.options.tolerance), 2254 c = !intersects && this.isover ? "isout" : (intersects && !this.isover ? "isover" : null); 2255 if(!c) { 2256 return; 2257 } 2258 2259 if (this.options.greedy) { 2260 // find droppable parents with same scope 2261 scope = this.options.scope; 2262 parent = this.element.parents(":data(ui-droppable)").filter(function () { 2263 return $.data(this, "ui-droppable").options.scope === scope; 2264 }); 2265 2266 if (parent.length) { 2267 parentInstance = $.data(parent[0], "ui-droppable"); 2268 parentInstance.greedyChild = (c === "isover"); 2269 } 2270 } 2271 2272 // we just moved into a greedy child 2273 if (parentInstance && c === "isover") { 2274 parentInstance.isover = false; 2275 parentInstance.isout = true; 2276 parentInstance._out.call(parentInstance, event); 2277 } 2278 2279 this[c] = true; 2280 this[c === "isout" ? "isover" : "isout"] = false; 2281 this[c === "isover" ? "_over" : "_out"].call(this, event); 2282 2283 // we just moved out of a greedy child 2284 if (parentInstance && c === "isout") { 2285 parentInstance.isout = false; 2286 parentInstance.isover = true; 2287 parentInstance._over.call(parentInstance, event); 2288 } 2289 }); 2290 2291 }, 2292 dragStop: function( draggable, event ) { 2293 draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" ); 2294 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) 2295 if( !draggable.options.refreshPositions ) { 2296 $.ui.ddmanager.prepareOffsets( draggable, event ); 2297 } 2298 } 2299}; 2300 2301})(jQuery); 2302 2303(function( $, undefined ) { 2304 2305function num(v) { 2306 return parseInt(v, 10) || 0; 2307} 2308 2309function isNumber(value) { 2310 return !isNaN(parseInt(value, 10)); 2311} 2312 2313$.widget("ui.resizable", $.ui.mouse, { 2314 version: "1.10.4", 2315 widgetEventPrefix: "resize", 2316 options: { 2317 alsoResize: false, 2318 animate: false, 2319 animateDuration: "slow", 2320 animateEasing: "swing", 2321 aspectRatio: false, 2322 autoHide: false, 2323 containment: false, 2324 ghost: false, 2325 grid: false, 2326 handles: "e,s,se", 2327 helper: false, 2328 maxHeight: null, 2329 maxWidth: null, 2330 minHeight: 10, 2331 minWidth: 10, 2332 // See #7960 2333 zIndex: 90, 2334 2335 // callbacks 2336 resize: null, 2337 start: null, 2338 stop: null 2339 }, 2340 _create: function() { 2341 2342 var n, i, handle, axis, hname, 2343 that = this, 2344 o = this.options; 2345 this.element.addClass("ui-resizable"); 2346 2347 $.extend(this, { 2348 _aspectRatio: !!(o.aspectRatio), 2349 aspectRatio: o.aspectRatio, 2350 originalElement: this.element, 2351 _proportionallyResizeElements: [], 2352 _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null 2353 }); 2354 2355 //Wrap the element if it cannot hold child nodes 2356 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { 2357 2358 //Create a wrapper element and set the wrapper to the new current internal element 2359 this.element.wrap( 2360 $("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({ 2361 position: this.element.css("position"), 2362 width: this.element.outerWidth(), 2363 height: this.element.outerHeight(), 2364 top: this.element.css("top"), 2365 left: this.element.css("left") 2366 }) 2367 ); 2368 2369 //Overwrite the original this.element 2370 this.element = this.element.parent().data( 2371 "ui-resizable", this.element.data("ui-resizable") 2372 ); 2373 2374 this.elementIsWrapper = true; 2375 2376 //Move margins to the wrapper 2377 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); 2378 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); 2379 2380 //Prevent Safari textarea resize 2381 this.originalResizeStyle = this.originalElement.css("resize"); 2382 this.originalElement.css("resize", "none"); 2383 2384 //Push the actual element to our proportionallyResize internal array 2385 this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" })); 2386 2387 // avoid IE jump (hard set the margin) 2388 this.originalElement.css({ margin: this.originalElement.css("margin") }); 2389 2390 // fix handlers offset 2391 this._proportionallyResize(); 2392 2393 } 2394 2395 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" }); 2396 if(this.handles.constructor === String) { 2397 2398 if ( this.handles === "all") { 2399 this.handles = "n,e,s,w,se,sw,ne,nw"; 2400 } 2401 2402 n = this.handles.split(","); 2403 this.handles = {}; 2404 2405 for(i = 0; i < n.length; i++) { 2406 2407 handle = $.trim(n[i]); 2408 hname = "ui-resizable-"+handle; 2409 axis = $("<div class='ui-resizable-handle " + hname + "'></div>"); 2410 2411 // Apply zIndex to all handles - see #7960 2412 axis.css({ zIndex: o.zIndex }); 2413 2414 //TODO : What's going on here? 2415 if ("se" === handle) { 2416 axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se"); 2417 } 2418 2419 //Insert into internal handles object and append to element 2420 this.handles[handle] = ".ui-resizable-"+handle; 2421 this.element.append(axis); 2422 } 2423 2424 } 2425 2426 this._renderAxis = function(target) { 2427 2428 var i, axis, padPos, padWrapper; 2429 2430 target = target || this.element; 2431 2432 for(i in this.handles) { 2433 2434 if(this.handles[i].constructor === String) { 2435 this.handles[i] = $(this.handles[i], this.element).show(); 2436 } 2437 2438 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) 2439 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { 2440 2441 axis = $(this.handles[i], this.element); 2442 2443 //Checking the correct pad and border 2444 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); 2445 2446 //The padding type i have to apply... 2447 padPos = [ "padding", 2448 /ne|nw|n/.test(i) ? "Top" : 2449 /se|sw|s/.test(i) ? "Bottom" : 2450 /^e$/.test(i) ? "Right" : "Left" ].join(""); 2451 2452 target.css(padPos, padWrapper); 2453 2454 this._proportionallyResize(); 2455 2456 } 2457 2458 //TODO: What's that good for? There's not anything to be executed left 2459 if(!$(this.handles[i]).length) { 2460 continue; 2461 } 2462 } 2463 }; 2464 2465 //TODO: make renderAxis a prototype function 2466 this._renderAxis(this.element); 2467 2468 this._handles = $(".ui-resizable-handle", this.element) 2469 .disableSelection(); 2470 2471 //Matching axis name 2472 this._handles.mouseover(function() { 2473 if (!that.resizing) { 2474 if (this.className) { 2475 axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); 2476 } 2477 //Axis, default = se 2478 that.axis = axis && axis[1] ? axis[1] : "se"; 2479 } 2480 }); 2481 2482 //If we want to auto hide the elements 2483 if (o.autoHide) { 2484 this._handles.hide(); 2485 $(this.element) 2486 .addClass("ui-resizable-autohide") 2487 .mouseenter(function() { 2488 if (o.disabled) { 2489 return; 2490 } 2491 $(this).removeClass("ui-resizable-autohide"); 2492 that._handles.show(); 2493 }) 2494 .mouseleave(function(){ 2495 if (o.disabled) { 2496 return; 2497 } 2498 if (!that.resizing) { 2499 $(this).addClass("ui-resizable-autohide"); 2500 that._handles.hide(); 2501 } 2502 }); 2503 } 2504 2505 //Initialize the mouse interaction 2506 this._mouseInit(); 2507 2508 }, 2509 2510 _destroy: function() { 2511 2512 this._mouseDestroy(); 2513 2514 var wrapper, 2515 _destroy = function(exp) { 2516 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") 2517 .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove(); 2518 }; 2519 2520 //TODO: Unwrap at same DOM position 2521 if (this.elementIsWrapper) { 2522 _destroy(this.element); 2523 wrapper = this.element; 2524 this.originalElement.css({ 2525 position: wrapper.css("position"), 2526 width: wrapper.outerWidth(), 2527 height: wrapper.outerHeight(), 2528 top: wrapper.css("top"), 2529 left: wrapper.css("left") 2530 }).insertAfter( wrapper ); 2531 wrapper.remove(); 2532 } 2533 2534 this.originalElement.css("resize", this.originalResizeStyle); 2535 _destroy(this.originalElement); 2536 2537 return this; 2538 }, 2539 2540 _mouseCapture: function(event) { 2541 var i, handle, 2542 capture = false; 2543 2544 for (i in this.handles) { 2545 handle = $(this.handles[i])[0]; 2546 if (handle === event.target || $.contains(handle, event.target)) { 2547 capture = true; 2548 } 2549 } 2550 2551 return !this.options.disabled && capture; 2552 }, 2553 2554 _mouseStart: function(event) { 2555 2556 var curleft, curtop, cursor, 2557 o = this.options, 2558 iniPos = this.element.position(), 2559 el = this.element; 2560 2561 this.resizing = true; 2562 2563 // bugfix for http://dev.jquery.com/ticket/1749 2564 if ( (/absolute/).test( el.css("position") ) ) { 2565 el.css({ position: "absolute", top: el.css("top"), left: el.css("left") }); 2566 } else if (el.is(".ui-draggable")) { 2567 el.css({ position: "absolute", top: iniPos.top, left: iniPos.left }); 2568 } 2569 2570 this._renderProxy(); 2571 2572 curleft = num(this.helper.css("left")); 2573 curtop = num(this.helper.css("top")); 2574 2575 if (o.containment) { 2576 curleft += $(o.containment).scrollLeft() || 0; 2577 curtop += $(o.containment).scrollTop() || 0; 2578 } 2579 2580 //Store needed variables 2581 this.offset = this.helper.offset(); 2582 this.position = { left: curleft, top: curtop }; 2583 this.size = this._helper ? { width: this.helper.width(), height: this.helper.height() } : { width: el.width(), height: el.height() }; 2584 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; 2585 this.originalPosition = { left: curleft, top: curtop }; 2586 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; 2587 this.originalMousePosition = { left: event.pageX, top: event.pageY }; 2588 2589 //Aspect Ratio 2590 this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); 2591 2592 cursor = $(".ui-resizable-" + this.axis).css("cursor"); 2593 $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor); 2594 2595 el.addClass("ui-resizable-resizing"); 2596 this._propagate("start", event); 2597 return true; 2598 }, 2599 2600 _mouseDrag: function(event) { 2601 2602 //Increase performance, avoid regex 2603 var data, 2604 el = this.helper, props = {}, 2605 smp = this.originalMousePosition, 2606 a = this.axis, 2607 prevTop = this.position.top, 2608 prevLeft = this.position.left, 2609 prevWidth = this.size.width, 2610 prevHeight = this.size.height, 2611 dx = (event.pageX-smp.left)||0, 2612 dy = (event.pageY-smp.top)||0, 2613 trigger = this._change[a]; 2614 2615 if (!trigger) { 2616 return false; 2617 } 2618 2619 // Calculate the attrs that will be change 2620 data = trigger.apply(this, [event, dx, dy]); 2621 2622 // Put this in the mouseDrag handler since the user can start pressing shift while resizing 2623 this._updateVirtualBoundaries(event.shiftKey); 2624 if (this._aspectRatio || event.shiftKey) { 2625 data = this._updateRatio(data, event); 2626 } 2627 2628 data = this._respectSize(data, event); 2629 2630 this._updateCache(data); 2631 2632 // plugins callbacks need to be called first 2633 this._propagate("resize", event); 2634 2635 if (this.position.top !== prevTop) { 2636 props.top = this.position.top + "px"; 2637 } 2638 if (this.position.left !== prevLeft) { 2639 props.left = this.position.left + "px"; 2640 } 2641 if (this.size.width !== prevWidth) { 2642 props.width = this.size.width + "px"; 2643 } 2644 if (this.size.height !== prevHeight) { 2645 props.height = this.size.height + "px"; 2646 } 2647 el.css(props); 2648 2649 if (!this._helper && this._proportionallyResizeElements.length) { 2650 this._proportionallyResize(); 2651 } 2652 2653 // Call the user callback if the element was resized 2654 if ( ! $.isEmptyObject(props) ) { 2655 this._trigger("resize", event, this.ui()); 2656 } 2657 2658 return false; 2659 }, 2660 2661 _mouseStop: function(event) { 2662 2663 this.resizing = false; 2664 var pr, ista, soffseth, soffsetw, s, left, top, 2665 o = this.options, that = this; 2666 2667 if(this._helper) { 2668 2669 pr = this._proportionallyResizeElements; 2670 ista = pr.length && (/textarea/i).test(pr[0].nodeName); 2671 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height; 2672 soffsetw = ista ? 0 : that.sizeDiff.width; 2673 2674 s = { width: (that.helper.width() - soffsetw), height: (that.helper.height() - soffseth) }; 2675 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null; 2676 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null; 2677 2678 if (!o.animate) { 2679 this.element.css($.extend(s, { top: top, left: left })); 2680 } 2681 2682 that.helper.height(that.size.height); 2683 that.helper.width(that.size.width); 2684 2685 if (this._helper && !o.animate) { 2686 this._proportionallyResize(); 2687 } 2688 } 2689 2690 $("body").css("cursor", "auto"); 2691 2692 this.element.removeClass("ui-resizable-resizing"); 2693 2694 this._propagate("stop", event); 2695 2696 if (this._helper) { 2697 this.helper.remove(); 2698 } 2699 2700 return false; 2701 2702 }, 2703 2704 _updateVirtualBoundaries: function(forceAspectRatio) { 2705 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b, 2706 o = this.options; 2707 2708 b = { 2709 minWidth: isNumber(o.minWidth) ? o.minWidth : 0, 2710 maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity, 2711 minHeight: isNumber(o.minHeight) ? o.minHeight : 0, 2712 maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity 2713 }; 2714 2715 if(this._aspectRatio || forceAspectRatio) { 2716 // We want to create an enclosing box whose aspect ration is the requested one 2717 // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension 2718 pMinWidth = b.minHeight * this.aspectRatio; 2719 pMinHeight = b.minWidth / this.aspectRatio; 2720 pMaxWidth = b.maxHeight * this.aspectRatio; 2721 pMaxHeight = b.maxWidth / this.aspectRatio; 2722 2723 if(pMinWidth > b.minWidth) { 2724 b.minWidth = pMinWidth; 2725 } 2726 if(pMinHeight > b.minHeight) { 2727 b.minHeight = pMinHeight; 2728 } 2729 if(pMaxWidth < b.maxWidth) { 2730 b.maxWidth = pMaxWidth; 2731 } 2732 if(pMaxHeight < b.maxHeight) { 2733 b.maxHeight = pMaxHeight; 2734 } 2735 } 2736 this._vBoundaries = b; 2737 }, 2738 2739 _updateCache: function(data) { 2740 this.offset = this.helper.offset(); 2741 if (isNumber(data.left)) { 2742 this.position.left = data.left; 2743 } 2744 if (isNumber(data.top)) { 2745 this.position.top = data.top; 2746 } 2747 if (isNumber(data.height)) { 2748 this.size.height = data.height; 2749 } 2750 if (isNumber(data.width)) { 2751 this.size.width = data.width; 2752 } 2753 }, 2754 2755 _updateRatio: function( data ) { 2756 2757 var cpos = this.position, 2758 csize = this.size, 2759 a = this.axis; 2760 2761 if (isNumber(data.height)) { 2762 data.width = (data.height * this.aspectRatio); 2763 } else if (isNumber(data.width)) { 2764 data.height = (data.width / this.aspectRatio); 2765 } 2766 2767 if (a === "sw") { 2768 data.left = cpos.left + (csize.width - data.width); 2769 data.top = null; 2770 } 2771 if (a === "nw") { 2772 data.top = cpos.top + (csize.height - data.height); 2773 data.left = cpos.left + (csize.width - data.width); 2774 } 2775 2776 return data; 2777 }, 2778 2779 _respectSize: function( data ) { 2780 2781 var o = this._vBoundaries, 2782 a = this.axis, 2783 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), 2784 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height), 2785 dw = this.originalPosition.left + this.originalSize.width, 2786 dh = this.position.top + this.size.height, 2787 cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); 2788 if (isminw) { 2789 data.width = o.minWidth; 2790 } 2791 if (isminh) { 2792 data.height = o.minHeight; 2793 } 2794 if (ismaxw) { 2795 data.width = o.maxWidth; 2796 } 2797 if (ismaxh) { 2798 data.height = o.maxHeight; 2799 } 2800 2801 if (isminw && cw) { 2802 data.left = dw - o.minWidth; 2803 } 2804 if (ismaxw && cw) { 2805 data.left = dw - o.maxWidth; 2806 } 2807 if (isminh && ch) { 2808 data.top = dh - o.minHeight; 2809 } 2810 if (ismaxh && ch) { 2811 data.top = dh - o.maxHeight; 2812 } 2813 2814 // fixing jump error on top/left - bug #2330 2815 if (!data.width && !data.height && !data.left && data.top) { 2816 data.top = null; 2817 } else if (!data.width && !data.height && !data.top && data.left) { 2818 data.left = null; 2819 } 2820 2821 return data; 2822 }, 2823 2824 _proportionallyResize: function() { 2825 2826 if (!this._proportionallyResizeElements.length) { 2827 return; 2828 } 2829 2830 var i, j, borders, paddings, prel, 2831 element = this.helper || this.element; 2832 2833 for ( i=0; i < this._proportionallyResizeElements.length; i++) { 2834 2835 prel = this._proportionallyResizeElements[i]; 2836 2837 if (!this.borderDif) { 2838 this.borderDif = []; 2839 borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")]; 2840 paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")]; 2841 2842 for ( j = 0; j < borders.length; j++ ) { 2843 this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 ); 2844 } 2845 } 2846 2847 prel.css({ 2848 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, 2849 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 2850 }); 2851 2852 } 2853 2854 }, 2855 2856 _renderProxy: function() { 2857 2858 var el = this.element, o = this.options; 2859 this.elementOffset = el.offset(); 2860 2861 if(this._helper) { 2862 2863 this.helper = this.helper || $("<div style='overflow:hidden;'></div>"); 2864 2865 this.helper.addClass(this._helper).css({ 2866 width: this.element.outerWidth() - 1, 2867 height: this.element.outerHeight() - 1, 2868 position: "absolute", 2869 left: this.elementOffset.left +"px", 2870 top: this.elementOffset.top +"px", 2871 zIndex: ++o.zIndex //TODO: Don't modify option 2872 }); 2873 2874 this.helper 2875 .appendTo("body") 2876 .disableSelection(); 2877 2878 } else { 2879 this.helper = this.element; 2880 } 2881 2882 }, 2883 2884 _change: { 2885 e: function(event, dx) { 2886 return { width: this.originalSize.width + dx }; 2887 }, 2888 w: function(event, dx) { 2889 var cs = this.originalSize, sp = this.originalPosition; 2890 return { left: sp.left + dx, width: cs.width - dx }; 2891 }, 2892 n: function(event, dx, dy) { 2893 var cs = this.originalSize, sp = this.originalPosition; 2894 return { top: sp.top + dy, height: cs.height - dy }; 2895 }, 2896 s: function(event, dx, dy) { 2897 return { height: this.originalSize.height + dy }; 2898 }, 2899 se: function(event, dx, dy) { 2900 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); 2901 }, 2902 sw: function(event, dx, dy) { 2903 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); 2904 }, 2905 ne: function(event, dx, dy) { 2906 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); 2907 }, 2908 nw: function(event, dx, dy) { 2909 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); 2910 } 2911 }, 2912 2913 _propagate: function(n, event) { 2914 $.ui.plugin.call(this, n, [event, this.ui()]); 2915 (n !== "resize" && this._trigger(n, event, this.ui())); 2916 }, 2917 2918 plugins: {}, 2919 2920 ui: function() { 2921 return { 2922 originalElement: this.originalElement, 2923 element: this.element, 2924 helper: this.helper, 2925 position: this.position, 2926 size: this.size, 2927 originalSize: this.originalSize, 2928 originalPosition: this.originalPosition 2929 }; 2930 } 2931 2932}); 2933 2934/* 2935 * Resizable Extensions 2936 */ 2937 2938$.ui.plugin.add("resizable", "animate", { 2939 2940 stop: function( event ) { 2941 var that = $(this).data("ui-resizable"), 2942 o = that.options, 2943 pr = that._proportionallyResizeElements, 2944 ista = pr.length && (/textarea/i).test(pr[0].nodeName), 2945 soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height, 2946 soffsetw = ista ? 0 : that.sizeDiff.width, 2947 style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) }, 2948 left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null, 2949 top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null; 2950 2951 that.element.animate( 2952 $.extend(style, top && left ? { top: top, left: left } : {}), { 2953 duration: o.animateDuration, 2954 easing: o.animateEasing, 2955 step: function() { 2956 2957 var data = { 2958 width: parseInt(that.element.css("width"), 10), 2959 height: parseInt(that.element.css("height"), 10), 2960 top: parseInt(that.element.css("top"), 10), 2961 left: parseInt(that.element.css("left"), 10) 2962 }; 2963 2964 if (pr && pr.length) { 2965 $(pr[0]).css({ width: data.width, height: data.height }); 2966 } 2967 2968 // propagating resize, and updating values for each animation step 2969 that._updateCache(data); 2970 that._propagate("resize", event); 2971 2972 } 2973 } 2974 ); 2975 } 2976 2977}); 2978 2979$.ui.plugin.add("resizable", "containment", { 2980 2981 start: function() { 2982 var element, p, co, ch, cw, width, height, 2983 that = $(this).data("ui-resizable"), 2984 o = that.options, 2985 el = that.element, 2986 oc = o.containment, 2987 ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; 2988 2989 if (!ce) { 2990 return; 2991 } 2992 2993 that.containerElement = $(ce); 2994 2995 if (/document/.test(oc) || oc === document) { 2996 that.containerOffset = { left: 0, top: 0 }; 2997 that.containerPosition = { left: 0, top: 0 }; 2998 2999 that.parentData = { 3000 element: $(document), left: 0, top: 0, 3001 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight 3002 }; 3003 } 3004 3005 // i'm a node, so compute top, left, right, bottom 3006 else { 3007 element = $(ce); 3008 p = []; 3009 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); }); 3010 3011 that.containerOffset = element.offset(); 3012 that.containerPosition = element.position(); 3013 that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; 3014 3015 co = that.containerOffset; 3016 ch = that.containerSize.height; 3017 cw = that.containerSize.width; 3018 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ); 3019 height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); 3020 3021 that.parentData = { 3022 element: ce, left: co.left, top: co.top, width: width, height: height 3023 }; 3024 } 3025 }, 3026 3027 resize: function( event ) { 3028 var woset, hoset, isParent, isOffsetRelative, 3029 that = $(this).data("ui-resizable"), 3030 o = that.options, 3031 co = that.containerOffset, cp = that.position, 3032 pRatio = that._aspectRatio || event.shiftKey, 3033 cop = { top:0, left:0 }, ce = that.containerElement; 3034 3035 if (ce[0] !== document && (/static/).test(ce.css("position"))) { 3036 cop = co; 3037 } 3038 3039 if (cp.left < (that._helper ? co.left : 0)) { 3040 that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left)); 3041 if (pRatio) { 3042 that.size.height = that.size.width / that.aspectRatio; 3043 } 3044 that.position.left = o.helper ? co.left : 0; 3045 } 3046 3047 if (cp.top < (that._helper ? co.top : 0)) { 3048 that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top); 3049 if (pRatio) { 3050 that.size.width = that.size.height * that.aspectRatio; 3051 } 3052 that.position.top = that._helper ? co.top : 0; 3053 } 3054 3055 that.offset.left = that.parentData.left+that.position.left; 3056 that.offset.top = that.parentData.top+that.position.top; 3057 3058 woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width ); 3059 hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height ); 3060 3061 isParent = that.containerElement.get(0) === that.element.parent().get(0); 3062 isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position")); 3063 3064 if ( isParent && isOffsetRelative ) { 3065 woset -= Math.abs( that.parentData.left ); 3066 } 3067 3068 if (woset + that.size.width >= that.parentData.width) { 3069 that.size.width = that.parentData.width - woset; 3070 if (pRatio) { 3071 that.size.height = that.size.width / that.aspectRatio; 3072 } 3073 } 3074 3075 if (hoset + that.size.height >= that.parentData.height) { 3076 that.size.height = that.parentData.height - hoset; 3077 if (pRatio) { 3078 that.size.width = that.size.height * that.aspectRatio; 3079 } 3080 } 3081 }, 3082 3083 stop: function(){ 3084 var that = $(this).data("ui-resizable"), 3085 o = that.options, 3086 co = that.containerOffset, 3087 cop = that.containerPosition, 3088 ce = that.containerElement, 3089 helper = $(that.helper), 3090 ho = helper.offset(), 3091 w = helper.outerWidth() - that.sizeDiff.width, 3092 h = helper.outerHeight() - that.sizeDiff.height; 3093 3094 if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) { 3095 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); 3096 } 3097 3098 if (that._helper && !o.animate && (/static/).test(ce.css("position"))) { 3099 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); 3100 } 3101 3102 } 3103}); 3104 3105$.ui.plugin.add("resizable", "alsoResize", { 3106 3107 start: function () { 3108 var that = $(this).data("ui-resizable"), 3109 o = that.options, 3110 _store = function (exp) { 3111 $(exp).each(function() { 3112 var el = $(this); 3113 el.data("ui-resizable-alsoresize", { 3114 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), 3115 left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10) 3116 }); 3117 }); 3118 }; 3119 3120 if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) { 3121 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); } 3122 else { $.each(o.alsoResize, function (exp) { _store(exp); }); } 3123 }else{ 3124 _store(o.alsoResize); 3125 } 3126 }, 3127 3128 resize: function (event, ui) { 3129 var that = $(this).data("ui-resizable"), 3130 o = that.options, 3131 os = that.originalSize, 3132 op = that.originalPosition, 3133 delta = { 3134 height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0, 3135 top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0 3136 }, 3137 3138 _alsoResize = function (exp, c) { 3139 $(exp).each(function() { 3140 var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {}, 3141 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"]; 3142 3143 $.each(css, function (i, prop) { 3144 var sum = (start[prop]||0) + (delta[prop]||0); 3145 if (sum && sum >= 0) { 3146 style[prop] = sum || null; 3147 } 3148 }); 3149 3150 el.css(style); 3151 }); 3152 }; 3153 3154 if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) { 3155 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); }); 3156 }else{ 3157 _alsoResize(o.alsoResize); 3158 } 3159 }, 3160 3161 stop: function () { 3162 $(this).removeData("resizable-alsoresize"); 3163 } 3164}); 3165 3166$.ui.plugin.add("resizable", "ghost", { 3167 3168 start: function() { 3169 3170 var that = $(this).data("ui-resizable"), o = that.options, cs = that.size; 3171 3172 that.ghost = that.originalElement.clone(); 3173 that.ghost 3174 .css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) 3175 .addClass("ui-resizable-ghost") 3176 .addClass(typeof o.ghost === "string" ? o.ghost : ""); 3177 3178 that.ghost.appendTo(that.helper); 3179 3180 }, 3181 3182 resize: function(){ 3183 var that = $(this).data("ui-resizable"); 3184 if (that.ghost) { 3185 that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width }); 3186 } 3187 }, 3188 3189 stop: function() { 3190 var that = $(this).data("ui-resizable"); 3191 if (that.ghost && that.helper) { 3192 that.helper.get(0).removeChild(that.ghost.get(0)); 3193 } 3194 } 3195 3196}); 3197 3198$.ui.plugin.add("resizable", "grid", { 3199 3200 resize: function() { 3201 var that = $(this).data("ui-resizable"), 3202 o = that.options, 3203 cs = that.size, 3204 os = that.originalSize, 3205 op = that.originalPosition, 3206 a = that.axis, 3207 grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid, 3208 gridX = (grid[0]||1), 3209 gridY = (grid[1]||1), 3210 ox = Math.round((cs.width - os.width) / gridX) * gridX, 3211 oy = Math.round((cs.height - os.height) / gridY) * gridY, 3212 newWidth = os.width + ox, 3213 newHeight = os.height + oy, 3214 isMaxWidth = o.maxWidth && (o.maxWidth < newWidth), 3215 isMaxHeight = o.maxHeight && (o.maxHeight < newHeight), 3216 isMinWidth = o.minWidth && (o.minWidth > newWidth), 3217 isMinHeight = o.minHeight && (o.minHeight > newHeight); 3218 3219 o.grid = grid; 3220 3221 if (isMinWidth) { 3222 newWidth = newWidth + gridX; 3223 } 3224 if (isMinHeight) { 3225 newHeight = newHeight + gridY; 3226 } 3227 if (isMaxWidth) { 3228 newWidth = newWidth - gridX; 3229 } 3230 if (isMaxHeight) { 3231 newHeight = newHeight - gridY; 3232 } 3233 3234 if (/^(se|s|e)$/.test(a)) { 3235 that.size.width = newWidth; 3236 that.size.height = newHeight; 3237 } else if (/^(ne)$/.test(a)) { 3238 that.size.width = newWidth; 3239 that.size.height = newHeight; 3240 that.position.top = op.top - oy; 3241 } else if (/^(sw)$/.test(a)) { 3242 that.size.width = newWidth; 3243 that.size.height = newHeight; 3244 that.position.left = op.left - ox; 3245 } else { 3246 if ( newHeight - gridY > 0 ) { 3247 that.size.height = newHeight; 3248 that.position.top = op.top - oy; 3249 } else { 3250 that.size.height = gridY; 3251 that.position.top = op.top + os.height - gridY; 3252 } 3253 if ( newWidth - gridX > 0 ) { 3254 that.size.width = newWidth; 3255 that.position.left = op.left - ox; 3256 } else { 3257 that.size.width = gridX; 3258 that.position.left = op.left + os.width - gridX; 3259 } 3260 } 3261 } 3262 3263}); 3264 3265})(jQuery); 3266 3267(function( $, undefined ) { 3268 3269$.widget("ui.selectable", $.ui.mouse, { 3270 version: "1.10.4", 3271 options: { 3272 appendTo: "body", 3273 autoRefresh: true, 3274 distance: 0, 3275 filter: "*", 3276 tolerance: "touch", 3277 3278 // callbacks 3279 selected: null, 3280 selecting: null, 3281 start: null, 3282 stop: null, 3283 unselected: null, 3284 unselecting: null 3285 }, 3286 _create: function() { 3287 var selectees, 3288 that = this; 3289 3290 this.element.addClass("ui-selectable"); 3291 3292 this.dragged = false; 3293 3294 // cache selectee children based on filter 3295 this.refresh = function() { 3296 selectees = $(that.options.filter, that.element[0]); 3297 selectees.addClass("ui-selectee"); 3298 selectees.each(function() { 3299 var $this = $(this), 3300 pos = $this.offset(); 3301 $.data(this, "selectable-item", { 3302 element: this, 3303 $element: $this, 3304 left: pos.left, 3305 top: pos.top, 3306 right: pos.left + $this.outerWidth(), 3307 bottom: pos.top + $this.outerHeight(), 3308 startselected: false, 3309 selected: $this.hasClass("ui-selected"), 3310 selecting: $this.hasClass("ui-selecting"), 3311 unselecting: $this.hasClass("ui-unselecting") 3312 }); 3313 }); 3314 }; 3315 this.refresh(); 3316 3317 this.selectees = selectees.addClass("ui-selectee"); 3318 3319 this._mouseInit(); 3320 3321 this.helper = $("<div class='ui-selectable-helper'></div>"); 3322 }, 3323 3324 _destroy: function() { 3325 this.selectees 3326 .removeClass("ui-selectee") 3327 .removeData("selectable-item"); 3328 this.element 3329 .removeClass("ui-selectable ui-selectable-disabled"); 3330 this._mouseDestroy(); 3331 }, 3332 3333 _mouseStart: function(event) { 3334 var that = this, 3335 options = this.options; 3336 3337 this.opos = [event.pageX, event.pageY]; 3338 3339 if (this.options.disabled) { 3340 return; 3341 } 3342 3343 this.selectees = $(options.filter, this.element[0]); 3344 3345 this._trigger("start", event); 3346 3347 $(options.appendTo).append(this.helper); 3348 // position helper (lasso) 3349 this.helper.css({ 3350 "left": event.pageX, 3351 "top": event.pageY, 3352 "width": 0, 3353 "height": 0 3354 }); 3355 3356 if (options.autoRefresh) { 3357 this.refresh(); 3358 } 3359 3360 this.selectees.filter(".ui-selected").each(function() { 3361 var selectee = $.data(this, "selectable-item"); 3362 selectee.startselected = true; 3363 if (!event.metaKey && !event.ctrlKey) { 3364 selectee.$element.removeClass("ui-selected"); 3365 selectee.selected = false; 3366 selectee.$element.addClass("ui-unselecting"); 3367 selectee.unselecting = true; 3368 // selectable UNSELECTING callback 3369 that._trigger("unselecting", event, { 3370 unselecting: selectee.element 3371 }); 3372 } 3373 }); 3374 3375 $(event.target).parents().addBack().each(function() { 3376 var doSelect, 3377 selectee = $.data(this, "selectable-item"); 3378 if (selectee) { 3379 doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected"); 3380 selectee.$element 3381 .removeClass(doSelect ? "ui-unselecting" : "ui-selected") 3382 .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); 3383 selectee.unselecting = !doSelect; 3384 selectee.selecting = doSelect; 3385 selectee.selected = doSelect; 3386 // selectable (UN)SELECTING callback 3387 if (doSelect) { 3388 that._trigger("selecting", event, { 3389 selecting: selectee.element 3390 }); 3391 } else { 3392 that._trigger("unselecting", event, { 3393 unselecting: selectee.element 3394 }); 3395 } 3396 return false; 3397 } 3398 }); 3399 3400 }, 3401 3402 _mouseDrag: function(event) { 3403 3404 this.dragged = true; 3405 3406 if (this.options.disabled) { 3407 return; 3408 } 3409 3410 var tmp, 3411 that = this, 3412 options = this.options, 3413 x1 = this.opos[0], 3414 y1 = this.opos[1], 3415 x2 = event.pageX, 3416 y2 = event.pageY; 3417 3418 if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; } 3419 if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; } 3420 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); 3421 3422 this.selectees.each(function() { 3423 var selectee = $.data(this, "selectable-item"), 3424 hit = false; 3425 3426 //prevent helper from being selected if appendTo: selectable 3427 if (!selectee || selectee.element === that.element[0]) { 3428 return; 3429 } 3430 3431 if (options.tolerance === "touch") { 3432 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); 3433 } else if (options.tolerance === "fit") { 3434 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); 3435 } 3436 3437 if (hit) { 3438 // SELECT 3439 if (selectee.selected) { 3440 selectee.$element.removeClass("ui-selected"); 3441 selectee.selected = false; 3442 } 3443 if (selectee.unselecting) { 3444 selectee.$element.removeClass("ui-unselecting"); 3445 selectee.unselecting = false; 3446 } 3447 if (!selectee.selecting) { 3448 selectee.$element.addClass("ui-selecting"); 3449 selectee.selecting = true; 3450 // selectable SELECTING callback 3451 that._trigger("selecting", event, { 3452 selecting: selectee.element 3453 }); 3454 } 3455 } else { 3456 // UNSELECT 3457 if (selectee.selecting) { 3458 if ((event.metaKey || event.ctrlKey) && selectee.startselected) { 3459 selectee.$element.removeClass("ui-selecting"); 3460 selectee.selecting = false; 3461 selectee.$element.addClass("ui-selected"); 3462 selectee.selected = true; 3463 } else { 3464 selectee.$element.removeClass("ui-selecting"); 3465 selectee.selecting = false; 3466 if (selectee.startselected) { 3467 selectee.$element.addClass("ui-unselecting"); 3468 selectee.unselecting = true; 3469 } 3470 // selectable UNSELECTING callback 3471 that._trigger("unselecting", event, { 3472 unselecting: selectee.element 3473 }); 3474 } 3475 } 3476 if (selectee.selected) { 3477 if (!event.metaKey && !event.ctrlKey && !selectee.startselected) { 3478 selectee.$element.removeClass("ui-selected"); 3479 selectee.selected = false; 3480 3481 selectee.$element.addClass("ui-unselecting"); 3482 selectee.unselecting = true; 3483 // selectable UNSELECTING callback 3484 that._trigger("unselecting", event, { 3485 unselecting: selectee.element 3486 }); 3487 } 3488 } 3489 } 3490 }); 3491 3492 return false; 3493 }, 3494 3495 _mouseStop: function(event) { 3496 var that = this; 3497 3498 this.dragged = false; 3499 3500 $(".ui-unselecting", this.element[0]).each(function() { 3501 var selectee = $.data(this, "selectable-item"); 3502 selectee.$element.removeClass("ui-unselecting"); 3503 selectee.unselecting = false; 3504 selectee.startselected = false; 3505 that._trigger("unselected", event, { 3506 unselected: selectee.element 3507 }); 3508 }); 3509 $(".ui-selecting", this.element[0]).each(function() { 3510 var selectee = $.data(this, "selectable-item"); 3511 selectee.$element.removeClass("ui-selecting").addClass("ui-selected"); 3512 selectee.selecting = false; 3513 selectee.selected = true; 3514 selectee.startselected = true; 3515 that._trigger("selected", event, { 3516 selected: selectee.element 3517 }); 3518 }); 3519 this._trigger("stop", event); 3520 3521 this.helper.remove(); 3522 3523 return false; 3524 } 3525 3526}); 3527 3528})(jQuery); 3529 3530(function( $, undefined ) { 3531 3532function isOverAxis( x, reference, size ) { 3533 return ( x > reference ) && ( x < ( reference + size ) ); 3534} 3535 3536function isFloating(item) { 3537 return (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display")); 3538} 3539 3540$.widget("ui.sortable", $.ui.mouse, { 3541 version: "1.10.4", 3542 widgetEventPrefix: "sort", 3543 ready: false, 3544 options: { 3545 appendTo: "parent", 3546 axis: false, 3547 connectWith: false, 3548 containment: false, 3549 cursor: "auto", 3550 cursorAt: false, 3551 dropOnEmpty: true, 3552 forcePlaceholderSize: false, 3553 forceHelperSize: false, 3554 grid: false, 3555 handle: false, 3556 helper: "original", 3557 items: "> *", 3558 opacity: false, 3559 placeholder: false, 3560 revert: false, 3561 scroll: true, 3562 scrollSensitivity: 20, 3563 scrollSpeed: 20, 3564 scope: "default", 3565 tolerance: "intersect", 3566 zIndex: 1000, 3567 3568 // callbacks 3569 activate: null, 3570 beforeStop: null, 3571 change: null, 3572 deactivate: null, 3573 out: null, 3574 over: null, 3575 receive: null, 3576 remove: null, 3577 sort: null, 3578 start: null, 3579 stop: null, 3580 update: null 3581 }, 3582 _create: function() { 3583 3584 var o = this.options; 3585 this.containerCache = {}; 3586 this.element.addClass("ui-sortable"); 3587 3588 //Get the items 3589 this.refresh(); 3590 3591 //Let's determine if the items are being displayed horizontally 3592 this.floating = this.items.length ? o.axis === "x" || isFloating(this.items[0].item) : false; 3593 3594 //Let's determine the parent's offset 3595 this.offset = this.element.offset(); 3596 3597 //Initialize mouse events for interaction 3598 this._mouseInit(); 3599 3600 //We're ready to go 3601 this.ready = true; 3602 3603 }, 3604 3605 _destroy: function() { 3606 this.element 3607 .removeClass("ui-sortable ui-sortable-disabled"); 3608 this._mouseDestroy(); 3609 3610 for ( var i = this.items.length - 1; i >= 0; i-- ) { 3611 this.items[i].item.removeData(this.widgetName + "-item"); 3612 } 3613 3614 return this; 3615 }, 3616 3617 _setOption: function(key, value){ 3618 if ( key === "disabled" ) { 3619 this.options[ key ] = value; 3620 3621 this.widget().toggleClass( "ui-sortable-disabled", !!value ); 3622 } else { 3623 // Don't call widget base _setOption for disable as it adds ui-state-disabled class 3624 $.Widget.prototype._setOption.apply(this, arguments); 3625 } 3626 }, 3627 3628 _mouseCapture: function(event, overrideHandle) { 3629 var currentItem = null, 3630 validHandle = false, 3631 that = this; 3632 3633 if (this.reverting) { 3634 return false; 3635 } 3636 3637 if(this.options.disabled || this.options.type === "static") { 3638 return false; 3639 } 3640 3641 //We have to refresh the items data once first 3642 this._refreshItems(event); 3643 3644 //Find out if the clicked node (or one of its parents) is a actual item in this.items 3645 $(event.target).parents().each(function() { 3646 if($.data(this, that.widgetName + "-item") === that) { 3647 currentItem = $(this); 3648 return false; 3649 } 3650 }); 3651 if($.data(event.target, that.widgetName + "-item") === that) { 3652 currentItem = $(event.target); 3653 } 3654 3655 if(!currentItem) { 3656 return false; 3657 } 3658 if(this.options.handle && !overrideHandle) { 3659 $(this.options.handle, currentItem).find("*").addBack().each(function() { 3660 if(this === event.target) { 3661 validHandle = true; 3662 } 3663 }); 3664 if(!validHandle) { 3665 return false; 3666 } 3667 } 3668 3669 this.currentItem = currentItem; 3670 this._removeCurrentsFromItems(); 3671 return true; 3672 3673 }, 3674 3675 _mouseStart: function(event, overrideHandle, noActivation) { 3676 3677 var i, body, 3678 o = this.options; 3679 3680 this.currentContainer = this; 3681 3682 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture 3683 this.refreshPositions(); 3684 3685 //Create and append the visible helper 3686 this.helper = this._createHelper(event); 3687 3688 //Cache the helper size 3689 this._cacheHelperProportions(); 3690 3691 /* 3692 * - Position generation - 3693 * This block generates everything position related - it's the core of draggables. 3694 */ 3695 3696 //Cache the margins of the original element 3697 this._cacheMargins(); 3698 3699 //Get the next scrolling parent 3700 this.scrollParent = this.helper.scrollParent(); 3701 3702 //The element's absolute position on the page minus margins 3703 this.offset = this.currentItem.offset(); 3704 this.offset = { 3705 top: this.offset.top - this.margins.top, 3706 left: this.offset.left - this.margins.left 3707 }; 3708 3709 $.extend(this.offset, { 3710 click: { //Where the click happened, relative to the element 3711 left: event.pageX - this.offset.left, 3712 top: event.pageY - this.offset.top 3713 }, 3714 parent: this._getParentOffset(), 3715 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper 3716 }); 3717 3718 // Only after we got the offset, we can change the helper's position to absolute 3719 // TODO: Still need to figure out a way to make relative sorting possible 3720 this.helper.css("position", "absolute"); 3721 this.cssPosition = this.helper.css("position"); 3722 3723 //Generate the original position 3724 this.originalPosition = this._generatePosition(event); 3725 this.originalPageX = event.pageX; 3726 this.originalPageY = event.pageY; 3727 3728 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied 3729 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); 3730 3731 //Cache the former DOM position 3732 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; 3733 3734 //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 3735 if(this.helper[0] !== this.currentItem[0]) { 3736 this.currentItem.hide(); 3737 } 3738 3739 //Create the placeholder 3740 this._createPlaceholder(); 3741 3742 //Set a containment if given in the options 3743 if(o.containment) { 3744 this._setContainment(); 3745 } 3746 3747 if( o.cursor && o.cursor !== "auto" ) { // cursor option 3748 body = this.document.find( "body" ); 3749 3750 // support: IE 3751 this.storedCursor = body.css( "cursor" ); 3752 body.css( "cursor", o.cursor ); 3753 3754 this.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body ); 3755 } 3756 3757 if(o.opacity) { // opacity option 3758 if (this.helper.css("opacity")) { 3759 this._storedOpacity = this.helper.css("opacity"); 3760 } 3761 this.helper.css("opacity", o.opacity); 3762 } 3763 3764 if(o.zIndex) { // zIndex option 3765 if (this.helper.css("zIndex")) { 3766 this._storedZIndex = this.helper.css("zIndex"); 3767 } 3768 this.helper.css("zIndex", o.zIndex); 3769 } 3770 3771 //Prepare scrolling 3772 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { 3773 this.overflowOffset = this.scrollParent.offset(); 3774 } 3775 3776 //Call callbacks 3777 this._trigger("start", event, this._uiHash()); 3778 3779 //Recache the helper size 3780 if(!this._preserveHelperProportions) { 3781 this._cacheHelperProportions(); 3782 } 3783 3784 3785 //Post "activate" events to possible containers 3786 if( !noActivation ) { 3787 for ( i = this.containers.length - 1; i >= 0; i-- ) { 3788 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) ); 3789 } 3790 } 3791 3792 //Prepare possible droppables 3793 if($.ui.ddmanager) { 3794 $.ui.ddmanager.current = this; 3795 } 3796 3797 if ($.ui.ddmanager && !o.dropBehaviour) { 3798 $.ui.ddmanager.prepareOffsets(this, event); 3799 } 3800 3801 this.dragging = true; 3802 3803 this.helper.addClass("ui-sortable-helper"); 3804 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position 3805 return true; 3806 3807 }, 3808 3809 _mouseDrag: function(event) { 3810 var i, item, itemElement, intersection, 3811 o = this.options, 3812 scrolled = false; 3813 3814 //Compute the helpers position 3815 this.position = this._generatePosition(event); 3816 this.positionAbs = this._convertPositionTo("absolute"); 3817 3818 if (!this.lastPositionAbs) { 3819 this.lastPositionAbs = this.positionAbs; 3820 } 3821 3822 //Do scrolling 3823 if(this.options.scroll) { 3824 if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") { 3825 3826 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) { 3827 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; 3828 } else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) { 3829 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; 3830 } 3831 3832 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) { 3833 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; 3834 } else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) { 3835 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; 3836 } 3837 3838 } else { 3839 3840 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) { 3841 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); 3842 } else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) { 3843 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); 3844 } 3845 3846 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) { 3847 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); 3848 } else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) { 3849 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); 3850 } 3851 3852 } 3853 3854 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) { 3855 $.ui.ddmanager.prepareOffsets(this, event); 3856 } 3857 } 3858 3859 //Regenerate the absolute position used for position checks 3860 this.positionAbs = this._convertPositionTo("absolute"); 3861 3862 //Set the helper position 3863 if(!this.options.axis || this.options.axis !== "y") { 3864 this.helper[0].style.left = this.position.left+"px"; 3865 } 3866 if(!this.options.axis || this.options.axis !== "x") { 3867 this.helper[0].style.top = this.position.top+"px"; 3868 } 3869 3870 //Rearrange 3871 for (i = this.items.length - 1; i >= 0; i--) { 3872 3873 //Cache variables and intersection, continue if no intersection 3874 item = this.items[i]; 3875 itemElement = item.item[0]; 3876 intersection = this._intersectsWithPointer(item); 3877 if (!intersection) { 3878 continue; 3879 } 3880 3881 // Only put the placeholder inside the current Container, skip all 3882 // items from other containers. This works because when moving 3883 // an item from one container to another the 3884 // currentContainer is switched before the placeholder is moved. 3885 // 3886 // Without this, moving items in "sub-sortables" can cause 3887 // the placeholder to jitter beetween the outer and inner container. 3888 if (item.instance !== this.currentContainer) { 3889 continue; 3890 } 3891 3892 // cannot intersect with itself 3893 // no useless actions that have been done before 3894 // no action if the item moved is the parent of the item checked 3895 if (itemElement !== this.currentItem[0] && 3896 this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement && 3897 !$.contains(this.placeholder[0], itemElement) && 3898 (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true) 3899 ) { 3900 3901 this.direction = intersection === 1 ? "down" : "up"; 3902 3903 if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) { 3904 this._rearrange(event, item); 3905 } else { 3906 break; 3907 } 3908 3909 this._trigger("change", event, this._uiHash()); 3910 break; 3911 } 3912 } 3913 3914 //Post events to containers 3915 this._contactContainers(event); 3916 3917 //Interconnect with droppables 3918 if($.ui.ddmanager) { 3919 $.ui.ddmanager.drag(this, event); 3920 } 3921 3922 //Call callbacks 3923 this._trigger("sort", event, this._uiHash()); 3924 3925 this.lastPositionAbs = this.positionAbs; 3926 return false; 3927 3928 }, 3929 3930 _mouseStop: function(event, noPropagation) { 3931 3932 if(!event) { 3933 return; 3934 } 3935 3936 //If we are using droppables, inform the manager about the drop 3937 if ($.ui.ddmanager && !this.options.dropBehaviour) { 3938 $.ui.ddmanager.drop(this, event); 3939 } 3940 3941 if(this.options.revert) { 3942 var that = this, 3943 cur = this.placeholder.offset(), 3944 axis = this.options.axis, 3945 animation = {}; 3946 3947 if ( !axis || axis === "x" ) { 3948 animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft); 3949 } 3950 if ( !axis || axis === "y" ) { 3951 animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop); 3952 } 3953 this.reverting = true; 3954 $(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() { 3955 that._clear(event); 3956 }); 3957 } else { 3958 this._clear(event, noPropagation); 3959 } 3960 3961 return false; 3962 3963 }, 3964 3965 cancel: function() { 3966 3967 if(this.dragging) { 3968 3969 this._mouseUp({ target: null }); 3970 3971 if(this.options.helper === "original") { 3972 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); 3973 } else { 3974 this.currentItem.show(); 3975 } 3976 3977 //Post deactivating events to containers 3978 for (var i = this.containers.length - 1; i >= 0; i--){ 3979 this.containers[i]._trigger("deactivate", null, this._uiHash(this)); 3980 if(this.containers[i].containerCache.over) { 3981 this.containers[i]._trigger("out", null, this._uiHash(this)); 3982 this.containers[i].containerCache.over = 0; 3983 } 3984 } 3985 3986 } 3987 3988 if (this.placeholder) { 3989 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! 3990 if(this.placeholder[0].parentNode) { 3991 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 3992 } 3993 if(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) { 3994 this.helper.remove(); 3995 } 3996 3997 $.extend(this, { 3998 helper: null, 3999 dragging: false, 4000 reverting: false, 4001 _noFinalSort: null 4002 }); 4003 4004 if(this.domPosition.prev) { 4005 $(this.domPosition.prev).after(this.currentItem); 4006 } else { 4007 $(this.domPosition.parent).prepend(this.currentItem); 4008 } 4009 } 4010 4011 return this; 4012 4013 }, 4014 4015 serialize: function(o) { 4016 4017 var items = this._getItemsAsjQuery(o && o.connected), 4018 str = []; 4019 o = o || {}; 4020 4021 $(items).each(function() { 4022 var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/)); 4023 if (res) { 4024 str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2])); 4025 } 4026 }); 4027 4028 if(!str.length && o.key) { 4029 str.push(o.key + "="); 4030 } 4031 4032 return str.join("&"); 4033 4034 }, 4035 4036 toArray: function(o) { 4037 4038 var items = this._getItemsAsjQuery(o && o.connected), 4039 ret = []; 4040 4041 o = o || {}; 4042 4043 items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); }); 4044 return ret; 4045 4046 }, 4047 4048 /* Be careful with the following core functions */ 4049 _intersectsWith: function(item) { 4050 4051 var x1 = this.positionAbs.left, 4052 x2 = x1 + this.helperProportions.width, 4053 y1 = this.positionAbs.top, 4054 y2 = y1 + this.helperProportions.height, 4055 l = item.left, 4056 r = l + item.width, 4057 t = item.top, 4058 b = t + item.height, 4059 dyClick = this.offset.click.top, 4060 dxClick = this.offset.click.left, 4061 isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ), 4062 isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ), 4063 isOverElement = isOverElementHeight && isOverElementWidth; 4064 4065 if ( this.options.tolerance === "pointer" || 4066 this.options.forcePointerForContainers || 4067 (this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"]) 4068 ) { 4069 return isOverElement; 4070 } else { 4071 4072 return (l < x1 + (this.helperProportions.width / 2) && // Right Half 4073 x2 - (this.helperProportions.width / 2) < r && // Left Half 4074 t < y1 + (this.helperProportions.height / 2) && // Bottom Half 4075 y2 - (this.helperProportions.height / 2) < b ); // Top Half 4076 4077 } 4078 }, 4079 4080 _intersectsWithPointer: function(item) { 4081 4082 var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), 4083 isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), 4084 isOverElement = isOverElementHeight && isOverElementWidth, 4085 verticalDirection = this._getDragVerticalDirection(), 4086 horizontalDirection = this._getDragHorizontalDirection(); 4087 4088 if (!isOverElement) { 4089 return false; 4090 } 4091 4092 return this.floating ? 4093 ( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 ) 4094 : ( verticalDirection && (verticalDirection === "down" ? 2 : 1) ); 4095 4096 }, 4097 4098 _intersectsWithSides: function(item) { 4099 4100 var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), 4101 isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), 4102 verticalDirection = this._getDragVerticalDirection(), 4103 horizontalDirection = this._getDragHorizontalDirection(); 4104 4105 if (this.floating && horizontalDirection) { 4106 return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf)); 4107 } else { 4108 return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf)); 4109 } 4110 4111 }, 4112 4113 _getDragVerticalDirection: function() { 4114 var delta = this.positionAbs.top - this.lastPositionAbs.top; 4115 return delta !== 0 && (delta > 0 ? "down" : "up"); 4116 }, 4117 4118 _getDragHorizontalDirection: function() { 4119 var delta = this.positionAbs.left - this.lastPositionAbs.left; 4120 return delta !== 0 && (delta > 0 ? "right" : "left"); 4121 }, 4122 4123 refresh: function(event) { 4124 this._refreshItems(event
vendor: 4,154 bytes, lines 4124-4260
4124); 4125 this.refreshPositions(); 4126 return this; 4127 }, 4128 4129 _connectWith: function() { 4130 var options = this.options; 4131 return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith; 4132 }, 4133 4134 _getItemsAsjQuery: function(connected) { 4135 4136 var i, j, cur, inst, 4137 items = [], 4138 queries = [], 4139 connectWith = this._connectWith(); 4140 4141 if(connectWith && connected) { 4142 for (i = connectWith.length - 1; i >= 0; i--){ 4143 cur = $(connectWith[i]); 4144 for ( j = cur.length - 1; j >= 0; j--){ 4145 inst = $.data(cur[j], this.widgetFullName); 4146 if(inst && inst !== this && !inst.options.disabled) { 4147 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]); 4148 } 4149 } 4150 } 4151 } 4152 4153 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]); 4154 4155 function addItems() { 4156 items.push( this ); 4157 } 4158 for (i = queries.length - 1; i >= 0; i--){ 4159 queries[i][0].each( addItems ); 4160 } 4161 4162 return $(items); 4163 4164 }, 4165 4166 _removeCurrentsFromItems: function() { 4167 4168 var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); 4169 4170 this.items = $.grep(this.items, function (item) { 4171 for (var j=0; j < list.length; j++) { 4172 if(list[j] === item.item[0]) { 4173 return false; 4174 } 4175 } 4176 return true; 4177 }); 4178 4179 }, 4180 4181 _refreshItems: function(event) { 4182 4183 this.items = []; 4184 this.containers = [this]; 4185 4186 var i, j, cur, inst, targetData, _queries, item, queriesLength, 4187 items = this.items, 4188 queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]], 4189 connectWith = this._connectWith(); 4190 4191 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down 4192 for (i = connectWith.length - 1; i >= 0; i--){ 4193 cur = $(connectWith[i]); 4194 for (j = cur.length - 1; j >= 0; j--){ 4195 inst = $.data(cur[j], this.widgetFullName); 4196 if(inst && inst !== this && !inst.options.disabled) { 4197 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); 4198 this.containers.push(inst); 4199 } 4200 } 4201 } 4202 } 4203 4204 for (i = queries.length - 1; i >= 0; i--) { 4205 targetData = queries[i][1]; 4206 _queries = queries[i][0]; 4207 4208 for (j=0, queriesLength = _queries.length; j < queriesLength; j++) { 4209 item = $(_queries[j]); 4210 4211 item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager) 4212 4213 items.push({ 4214 item: item, 4215 instance: targetData, 4216 width: 0, height: 0, 4217 left: 0, top: 0 4218 }); 4219 } 4220 } 4221 4222 }, 4223 4224 refreshPositions: function(fast) { 4225 4226 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change 4227 if(this.offsetParent && this.helper) { 4228 this.offset.parent = this._getParentOffset(); 4229 } 4230 4231 var i, item, t, p; 4232 4233 for (i = this.items.length - 1; i >= 0; i--){ 4234 item = this.items[i]; 4235 4236 //We ignore calculating positions of all connected containers when we're not over them 4237 if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) { 4238 continue; 4239 } 4240 4241 t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; 4242 4243 if (!fast) { 4244 item.width = t.outerWidth(); 4245 item.height = t.outerHeight(); 4246 } 4247 4248 p = t.offset(); 4249 item.left = p.left; 4250 item.top = p.top; 4251 } 4252 4253 if(this.options.custom && this.options.custom.refreshContainers) { 4254 this.options.custom.refreshContainers.call(this); 4255 } else { 4256 for (i = this.containers.length - 1; i >= 0; i--){ 4257 p = this.containers[i].element.offset(); 4258 this.containers[i].containerCache.left = p.left; 4259 this.containers[i].containerCache.top = p.top; 4260 this.containers[i].containerCache.width
vendor: 1,591 bytes, lines 4260-4307
4260 = this.containers[i].element.outerWidth(); 4261 this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); 4262 } 4263 } 4264 4265 return this; 4266 }, 4267 4268 _createPlaceholder: function(that) { 4269 that = that || this; 4270 var className, 4271 o = that.options; 4272 4273 if(!o.placeholder || o.placeholder.constructor === String) { 4274 className = o.placeholder; 4275 o.placeholder = { 4276 element: function() { 4277 4278 var nodeName = that.currentItem[0].nodeName.toLowerCase(), 4279 element = $( "<" + nodeName + ">", that.document[0] ) 4280 .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder") 4281 .removeClass("ui-sortable-helper"); 4282 4283 if ( nodeName === "tr" ) { 4284 that.currentItem.children().each(function() { 4285 $( "<td> </td>", that.document[0] ) 4286 .attr( "colspan", $( this ).attr( "colspan" ) || 1 ) 4287 .appendTo( element ); 4288 }); 4289 } else if ( nodeName === "img" ) { 4290 element.attr( "src", that.currentItem.attr( "src" ) ); 4291 } 4292 4293 if ( !className ) { 4294 element.css( "visibility", "hidden" ); 4295 } 4296 4297 return element; 4298 }, 4299 update: function(container, p) { 4300 4301 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that 4302 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified 4303 if(className && !o.forcePlaceholderSize) { 4304 return; 4305 } 4306 4307 //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
4308 if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); } 4309 if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); } 4310 } 4311 }; 4312 } 4313 4314 //Create the placeholder 4315 that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem)); 4316 4317 //Append it after the actual current item 4318 that.currentItem.after(that.placeholder); 4319 4320 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) 4321 o.placeholder.update(that, that.placeholder); 4322 4323 }, 4324 4325 _contactContainers: function(event) { 4326 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating, 4327 innermostContainer = null, 4328 innermostIndex = null; 4329 4330 // get innermost container that intersects with item 4331 for (i = this.containers.length - 1; i >= 0; i--) { 4332 4333 // never consider a container that's located within the item itself 4334 if($.contains(this.currentItem[0], this.containers[i].element[0])) { 4335 continue; 4336 } 4337 4338 if(this._intersectsWith(this.containers[i].containerCache)) { 4339 4340 // if we've already found a container and it's more "inner" than this, then continue 4341 if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) { 4342 continue; 4343 } 4344 4345 innermostContainer = this.containers[i]; 4346 innermostIndex = i; 4347 4348 } else { 4349 // container doesn't intersect. trigger "out" event if necessary 4350 if(this.containers[i].containerCache.over) { 4351 this.containers[i]._trigger("out", event, this._uiHash(this)); 4352 this.containers[i].containerCache.over = 0; 4353 } 4354 } 4355 4356 } 4357 4358 // if no intersecting containers found, return 4359 if(!innermostContainer) { 4360 return; 4361 } 4362 4363 // move the item into the container if it's not there already 4364 if(this.containers.length === 1) { 4365 if (!this.containers[innermostIndex].containerCache.over) { 4366 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 4367 this.containers[innermostIndex].containerCache.over = 1; 4368 } 4369 } else { 4370 4371 //When entering a new container, we will find the item with the least distance and append our item near it 4372 dist = 10000; 4373 itemWithLeastDistance = null; 4374 floating = innermostContainer.floating || isFloating(this.currentItem); 4375 posProperty = floating ? "left" : "top"; 4376 sizeProperty = floating ? "width" : "height"; 4377 base = this.positionAbs[posProperty] + this.offset.click[posProperty]; 4378 for (j = this.items.length - 1; j >= 0; j--) { 4379 if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) { 4380 continue; 4381 } 4382 if(this.items[j].item[0] === this.currentItem[0]) { 4383 continue; 4384 } 4385 if (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) { 4386 continue; 4387 } 4388 cur = this.items[j].item.offset()[posProperty]; 4389 nearBottom = false; 4390 if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){ 4391 nearBottom = true; 4392 cur += this.items[j][sizeProperty]; 4393 } 4394 4395 if(Math.abs(cur - base) < dist) { 4396 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j
vendor: 15,870 bytes, lines 4396-4802
4396]; 4397 this.direction = nearBottom ? "up": "down"; 4398 } 4399 } 4400 4401 //Check if dropOnEmpty is enabled 4402 if(!itemWithLeastDistance && !this.options.dropOnEmpty) { 4403 return; 4404 } 4405 4406 if(this.currentContainer === this.containers[innermostIndex]) { 4407 return; 4408 } 4409 4410 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 4411 this._trigger("change", event, this._uiHash()); 4412 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 4413 this.currentContainer = this.containers[innermostIndex]; 4414 4415 //Update the placeholder 4416 this.options.placeholder.update(this.currentContainer, this.placeholder); 4417 4418 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 4419 this.containers[innermostIndex].containerCache.over = 1; 4420 } 4421 4422 4423 }, 4424 4425 _createHelper: function(event) { 4426 4427 var o = this.options, 4428 helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem); 4429 4430 //Add the helper to the DOM if that didn't happen already 4431 if(!helper.parents("body").length) { 4432 $(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); 4433 } 4434 4435 if(helper[0] === this.currentItem[0]) { 4436 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") }; 4437 } 4438 4439 if(!helper[0].style.width || o.forceHelperSize) { 4440 helper.width(this.currentItem.width()); 4441 } 4442 if(!helper[0].style.height || o.forceHelperSize) { 4443 helper.height(this.currentItem.height()); 4444 } 4445 4446 return helper; 4447 4448 }, 4449 4450 _adjustOffsetFromHelper: function(obj) { 4451 if (typeof obj === "string") { 4452 obj = obj.split(" "); 4453 } 4454 if ($.isArray(obj)) { 4455 obj = {left: +obj[0], top: +obj[1] || 0}; 4456 } 4457 if ("left" in obj) { 4458 this.offset.click.left = obj.left + this.margins.left; 4459 } 4460 if ("right" in obj) { 4461 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 4462 } 4463 if ("top" in obj) { 4464 this.offset.click.top = obj.top + this.margins.top; 4465 } 4466 if ("bottom" in obj) { 4467 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 4468 } 4469 }, 4470 4471 _getParentOffset: function() { 4472 4473 4474 //Get the offsetParent and cache its position 4475 this.offsetParent = this.helper.offsetParent(); 4476 var po = this.offsetParent.offset(); 4477 4478 // This is a special case where we need to modify a offset calculated on start, since the following happened: 4479 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent 4480 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that 4481 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag 4482 if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) { 4483 po.left += this.scrollParent.scrollLeft(); 4484 po.top += this.scrollParent.scrollTop(); 4485 } 4486 4487 // This needs to be actually done for all browsers, since pageX/pageY includes this information 4488 // with an ugly IE fix 4489 if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) { 4490 po = { top: 0, left: 0 }; 4491 } 4492 4493 return { 4494 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), 4495 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) 4496 }; 4497 4498 }, 4499 4500 _getRelativeOffset: function() { 4501 4502 if(this.cssPosition === "relative") { 4503 var p = this.currentItem.position(); 4504 return { 4505 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), 4506 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() 4507 }; 4508 } else { 4509 return { top: 0, left: 0 }; 4510 } 4511 4512 }, 4513 4514 _cacheMargins: function() { 4515 this.margins = { 4516 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), 4517 top: (parseInt(this.currentItem.css("marginTop"),10) || 0) 4518 }; 4519 }, 4520 4521 _cacheHelperProportions: function() { 4522 this.helperProportions = { 4523 width: this.helper.outerWidth(), 4524 height: this.helper.outerHeight() 4525 }; 4526 }, 4527 4528 _setContainment: function() { 4529 4530 var ce, co, over, 4531 o = this.options; 4532 if(o.containment === "parent") { 4533 o.containment = this.helper[0].parentNode; 4534 } 4535 if(o.containment === "document" || o.containment === "window") { 4536 this.containment = [ 4537 0 - this.offset.relative.left - this.offset.parent.left, 4538 0 - this.offset.relative.top - this.offset.parent.top, 4539 $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left, 4540 ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top 4541 ]; 4542 } 4543 4544 if(!(/^(document|window|parent)$/).test(o.containment)) { 4545 ce = $(o.containment)[0]; 4546 co = $(o.containment).offset(); 4547 over = ($(ce).css("overflow") !== "hidden"); 4548 4549 this.containment = [ 4550 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, 4551 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, 4552 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, 4553 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 4554 ]; 4555 } 4556 4557 }, 4558 4559 _convertPositionTo: function(d, pos) { 4560 4561 if(!pos) { 4562 pos = this.position; 4563 } 4564 var mod = d === "absolute" ? 1 : -1, 4565 scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, 4566 scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 4567 4568 return { 4569 top: ( 4570 pos.top + // The absolute mouse position 4571 this.offset.relative.top * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 4572 this.offset.parent.top * mod - // The offsetParent's offset without borders (offset + border) 4573 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) 4574 ), 4575 left: ( 4576 pos.left + // The absolute mouse position 4577 this.offset.relative.left * mod + // Only for relative positioned nodes: Relative offset from element to offset parent 4578 this.offset.parent.left * mod - // The offsetParent's offset without borders (offset + border) 4579 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) 4580 ) 4581 }; 4582 4583 }, 4584 4585 _generatePosition: function(event) { 4586 4587 var top, left, 4588 o = this.options, 4589 pageX = event.pageX, 4590 pageY = event.pageY, 4591 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); 4592 4593 // This is another very weird special case that only happens for relative elements: 4594 // 1. If the css position is relative 4595 // 2. and the scroll parent is the document or similar to the offset parent 4596 // we have to refresh the relative offset during the scroll so there are no jumps 4597 if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) { 4598 this.offset.relative = this._getRelativeOffset(); 4599 } 4600 4601 /* 4602 * - Position constraining - 4603 * Constrain the position to a mix of grid, containment. 4604 */ 4605 4606 if(this.originalPosition) { //If we are not dragging yet, we won't check for options 4607 4608 if(this.containment) { 4609 if(event.pageX - this.offset.click.left < this.containment[0]) { 4610 pageX = this.containment[0] + this.offset.click.left; 4611 } 4612 if(event.pageY - this.offset.click.top < this.containment[1]) { 4613 pageY = this.containment[1] + this.offset.click.top; 4614 } 4615 if(event.pageX - this.offset.click.left > this.containment[2]) { 4616 pageX = this.containment[2] + this.offset.click.left; 4617 } 4618 if(event.pageY - this.offset.click.top > this.containment[3]) { 4619 pageY = this.containment[3] + this.offset.click.top; 4620 } 4621 } 4622 4623 if(o.grid) { 4624 top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; 4625 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; 4626 4627 left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; 4628 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; 4629 } 4630 4631 } 4632 4633 return { 4634 top: ( 4635 pageY - // The absolute mouse position 4636 this.offset.click.top - // Click offset (relative to the element) 4637 this.offset.relative.top - // Only for relative positioned nodes: Relative offset from element to offset parent 4638 this.offset.parent.top + // The offsetParent's offset without borders (offset + border) 4639 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) 4640 ), 4641 left: ( 4642 pageX - // The absolute mouse position 4643 this.offset.click.left - // Click offset (relative to the element) 4644 this.offset.relative.left - // Only for relative positioned nodes: Relative offset from element to offset parent 4645 this.offset.parent.left + // The offsetParent's offset without borders (offset + border) 4646 ( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) 4647 ) 4648 }; 4649 4650 }, 4651 4652 _rearrange: function(event, i, a, hardRefresh) { 4653 4654 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)); 4655 4656 //Various things done here to improve the performance: 4657 // 1. we create a setTimeout, that calls refreshPositions 4658 // 2. on the instance, we have a counter variable, that get's higher after every append 4659 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same 4660 // 4. this lets only the last addition to the timeout stack through 4661 this.counter = this.counter ? ++this.counter : 1; 4662 var counter = this.counter; 4663 4664 this._delay(function() { 4665 if(counter === this.counter) { 4666 this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove 4667 } 4668 }); 4669 4670 }, 4671 4672 _clear: function(event, noPropagation) { 4673 4674 this.reverting = false; 4675 // We delay all events that have to be triggered to after the point where the placeholder has been removed and 4676 // everything else normalized again 4677 var i, 4678 delayedTriggers = []; 4679 4680 // We first have to update the dom position of the actual currentItem 4681 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) 4682 if(!this._noFinalSort && this.currentItem.parent().length) { 4683 this.placeholder.before(this.currentItem); 4684 } 4685 this._noFinalSort = null; 4686 4687 if(this.helper[0] === this.currentItem[0]) { 4688 for(i in this._storedCSS) { 4689 if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") { 4690 this._storedCSS[i] = ""; 4691 } 4692 } 4693 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); 4694 } else { 4695 this.currentItem.show(); 4696 } 4697 4698 if(this.fromOutside && !noPropagation) { 4699 delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); 4700 } 4701 if((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) { 4702 delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed 4703 } 4704 4705 // Check if the items Container has Changed and trigger appropriate 4706 // events. 4707 if (this !== this.currentContainer) { 4708 if(!noPropagation) { 4709 delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); 4710 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); 4711 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); 4712 } 4713 } 4714 4715 4716 //Post events to containers 4717 function delayEvent( type, instance, container ) { 4718 return function( event ) { 4719 container._trigger( type, event, instance._uiHash( instance ) ); 4720 }; 4721 } 4722 for (i = this.containers.length - 1; i >= 0; i--){ 4723 if (!noPropagation) { 4724 delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) ); 4725 } 4726 if(this.containers[i].containerCache.over) { 4727 delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) ); 4728 this.containers[i].containerCache.over = 0; 4729 } 4730 } 4731 4732 //Do what was originally in plugins 4733 if ( this.storedCursor ) { 4734 this.document.find( "body" ).css( "cursor", this.storedCursor ); 4735 this.storedStylesheet.remove(); 4736 } 4737 if(this._storedOpacity) { 4738 this.helper.css("opacity", this._storedOpacity); 4739 } 4740 if(this._storedZIndex) { 4741 this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex); 4742 } 4743 4744 this.dragging = false; 4745 if(this.cancelHelperRemoval) { 4746 if(!noPropagation) { 4747 this._trigger("beforeStop", event, this._uiHash()); 4748 for (i=0; i < delayedTriggers.length; i++) { 4749 delayedTriggers[i].call(this, event); 4750 } //Trigger all delayed events 4751 this._trigger("stop", event, this._uiHash()); 4752 } 4753 4754 this.fromOutside = false; 4755 return false; 4756 } 4757 4758 if(!noPropagation) { 4759 this._trigger("beforeStop", event, this._uiHash()); 4760 } 4761 4762 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! 4763 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 4764 4765 if(this.helper[0] !== this.currentItem[0]) { 4766 this.helper.remove(); 4767 } 4768 this.helper = null; 4769 4770 if(!noPropagation) { 4771 for (i=0; i < delayedTriggers.length; i++) { 4772 delayedTriggers[i].call(this, event); 4773 } //Trigger all delayed events 4774 this._trigger("stop", event, this._uiHash()); 4775 } 4776 4777 this.fromOutside = false; 4778 return true; 4779 4780 }, 4781 4782 _trigger: function() { 4783 if ($.Widget.prototype._trigger.apply(this, arguments) === false) { 4784 this.cancel(); 4785 } 4786 }, 4787 4788 _uiHash: function(_inst) { 4789 var inst = _inst || this; 4790 return { 4791 helper: inst.helper, 4792 placeholder: inst.placeholder || $([]), 4793 position: inst.position, 4794 originalPosition: inst.originalPosition, 4795 offset: inst.positionAbs, 4796 item: inst.currentItem, 4797 sender: _inst ? _inst.element : null 4798 }; 4799 } 4800 4801}); 4802
vendor: 70,403 bytes, lines 4803-7526
4803})(jQuery); 4804 4805(function($, undefined) { 4806 4807var dataSpace = "ui-effects-"; 4808 4809$.effects = { 4810 effect: {} 4811}; 4812 4813/*! 4814 * jQuery Color Animations v2.1.2 4815 * https://github.com/jquery/jquery-color 4816 * 4817 * Copyright 2013 jQuery Foundation and other contributors 4818 * Released under the MIT license. 4819 * http://jquery.org/license 4820 * 4821 * Date: Wed Jan 16 08:47:09 2013 -0600 4822 */ 4823(function( jQuery, undefined ) { 4824 4825 var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", 4826 4827 // plusequals test for += 100 -= 100 4828 rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, 4829 // a set of RE's that can match strings and generate color tuples. 4830 stringParsers = [{ 4831 re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 4832 parse: function( execResult ) { 4833 return [ 4834 execResult[ 1 ], 4835 execResult[ 2 ], 4836 execResult[ 3 ], 4837 execResult[ 4 ] 4838 ]; 4839 } 4840 }, { 4841 re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 4842 parse: function( execResult ) { 4843 return [ 4844 execResult[ 1 ] * 2.55, 4845 execResult[ 2 ] * 2.55, 4846 execResult[ 3 ] * 2.55, 4847 execResult[ 4 ] 4848 ]; 4849 } 4850 }, { 4851 // this regex ignores A-F because it's compared against an already lowercased string 4852 re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/, 4853 parse: function( execResult ) { 4854 return [ 4855 parseInt( execResult[ 1 ], 16 ), 4856 parseInt( execResult[ 2 ], 16 ), 4857 parseInt( execResult[ 3 ], 16 ) 4858 ]; 4859 } 4860 }, { 4861 // this regex ignores A-F because it's compared against an already lowercased string 4862 re: /#([a-f0-9])([a-f0-9])([a-f0-9])/, 4863 parse: function( execResult ) { 4864 return [ 4865 parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), 4866 parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), 4867 parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ) 4868 ]; 4869 } 4870 }, { 4871 re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, 4872 space: "hsla", 4873 parse: function( execResult ) { 4874 return [ 4875 execResult[ 1 ], 4876 execResult[ 2 ] / 100, 4877 execResult[ 3 ] / 100, 4878 execResult[ 4 ] 4879 ]; 4880 } 4881 }], 4882 4883 // jQuery.Color( ) 4884 color = jQuery.Color = function( color, green, blue, alpha ) { 4885 return new jQuery.Color.fn.parse( color, green, blue, alpha ); 4886 }, 4887 spaces = { 4888 rgba: { 4889 props: { 4890 red: { 4891 idx: 0, 4892 type: "byte" 4893 }, 4894 green: { 4895 idx: 1, 4896 type: "byte" 4897 }, 4898 blue: { 4899 idx: 2, 4900 type: "byte" 4901 } 4902 } 4903 }, 4904 4905 hsla: { 4906 props: { 4907 hue: { 4908 idx: 0, 4909 type: "degrees" 4910 }, 4911 saturation: { 4912 idx: 1, 4913 type: "percent" 4914 }, 4915 lightness: { 4916 idx: 2, 4917 type: "percent" 4918 } 4919 } 4920 } 4921 }, 4922 propTypes = { 4923 "byte": { 4924 floor: true, 4925 max: 255 4926 }, 4927 "percent": { 4928 max: 1 4929 }, 4930 "degrees": { 4931 mod: 360, 4932 floor: true 4933 } 4934 }, 4935 support = color.support = {}, 4936 4937 // element for support tests 4938 supportElem = jQuery( "<p>" )[ 0 ], 4939 4940 // colors = jQuery.Color.names 4941 colors, 4942 4943 // local aliases of functions called often 4944 each = jQuery.each; 4945 4946// determine rgba support immediately 4947supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; 4948support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; 4949 4950// define cache name and alpha properties 4951// for rgba and hsla spaces 4952each( spaces, function( spaceName, space ) { 4953 space.cache = "_" + spaceName; 4954 space.props.alpha = { 4955 idx: 3, 4956 type: "percent", 4957 def: 1 4958 }; 4959}); 4960 4961function clamp( value, prop, allowEmpty ) { 4962 var type = propTypes[ prop.type ] || {}; 4963 4964 if ( value == null ) { 4965 return (allowEmpty || !prop.def) ? null : prop.def; 4966 } 4967 4968 // ~~ is an short way of doing floor for positive numbers 4969 value = type.floor ? ~~value : parseFloat( value ); 4970 4971 // IE will pass in empty strings as value for alpha, 4972 // which will hit this case 4973 if ( isNaN( value ) ) { 4974 return prop.def; 4975 } 4976 4977 if ( type.mod ) { 4978 // we add mod before modding to make sure that negatives values 4979 // get converted properly: -10 -> 350 4980 return (value + type.mod) % type.mod; 4981 } 4982 4983 // for now all property types without mod have min and max 4984 return 0 > value ? 0 : type.max < value ? type.max : value; 4985} 4986 4987function stringParse( string ) { 4988 var inst = color(), 4989 rgba = inst._rgba = []; 4990 4991 string = string.toLowerCase(); 4992 4993 each( stringParsers, function( i, parser ) { 4994 var parsed, 4995 match = parser.re.exec( string ), 4996 values = match && parser.parse( match ), 4997 spaceName = parser.space || "rgba"; 4998 4999 if ( values ) { 5000 parsed = inst[ spaceName ]( values ); 5001 5002 // if this was an rgba parse the assignment might happen twice 5003 // oh well.... 5004 inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; 5005 rgba = inst._rgba = parsed._rgba; 5006 5007 // exit each( stringParsers ) here because we matched 5008 return false; 5009 } 5010 }); 5011 5012 // Found a stringParser that handled it 5013 if ( rgba.length ) { 5014 5015 // if this came from a parsed string, force "transparent" when alpha is 0 5016 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) 5017 if ( rgba.join() === "0,0,0,0" ) { 5018 jQuery.extend( rgba, colors.transparent ); 5019 } 5020 return inst; 5021 } 5022 5023 // named colors 5024 return colors[ string ]; 5025} 5026 5027color.fn = jQuery.extend( color.prototype, { 5028 parse: function( red, green, blue, alpha ) { 5029 if ( red === undefined ) { 5030 this._rgba = [ null, null, null, null ]; 5031 return this; 5032 } 5033 if ( red.jquery || red.nodeType ) { 5034 red = jQuery( red ).css( green ); 5035 green = undefined; 5036 } 5037 5038 var inst = this, 5039 type = jQuery.type( red ), 5040 rgba = this._rgba = []; 5041 5042 // more than 1 argument specified - assume ( red, green, blue, alpha ) 5043 if ( green !== undefined ) { 5044 red = [ red, green, blue, alpha ]; 5045 type = "array"; 5046 } 5047 5048 if ( type === "string" ) { 5049 return this.parse( stringParse( red ) || colors._default ); 5050 } 5051 5052 if ( type === "array" ) { 5053 each( spaces.rgba.props, function( key, prop ) { 5054 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); 5055 }); 5056 return this; 5057 } 5058 5059 if ( type === "object" ) { 5060 if ( red instanceof color ) { 5061 each( spaces, function( spaceName, space ) { 5062 if ( red[ space.cache ] ) { 5063 inst[ space.cache ] = red[ space.cache ].slice(); 5064 } 5065 }); 5066 } else { 5067 each( spaces, function( spaceName, space ) { 5068 var cache = space.cache; 5069 each( space.props, function( key, prop ) { 5070 5071 // if the cache doesn't exist, and we know how to convert 5072 if ( !inst[ cache ] && space.to ) { 5073 5074 // if the value was null, we don't need to copy it 5075 // if the key was alpha, we don't need to copy it either 5076 if ( key === "alpha" || red[ key ] == null ) { 5077 return; 5078 } 5079 inst[ cache ] = space.to( inst._rgba ); 5080 } 5081 5082 // this is the only case where we allow nulls for ALL properties. 5083 // call clamp with alwaysAllowEmpty 5084 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); 5085 }); 5086 5087 // everything defined but alpha? 5088 if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { 5089 // use the default of 1 5090 inst[ cache ][ 3 ] = 1; 5091 if ( space.from ) { 5092 inst._rgba = space.from( inst[ cache ] ); 5093 } 5094 } 5095 }); 5096 } 5097 return this; 5098 } 5099 }, 5100 is: function( compare ) { 5101 var is = color( compare ), 5102 same = true, 5103 inst = this; 5104 5105 each( spaces, function( _, space ) { 5106 var localCache, 5107 isCache = is[ space.cache ]; 5108 if (isCache) { 5109 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; 5110 each( space.props, function( _, prop ) { 5111 if ( isCache[ prop.idx ] != null ) { 5112 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); 5113 return same; 5114 } 5115 }); 5116 } 5117 return same; 5118 }); 5119 return same; 5120 }, 5121 _space: function() { 5122 var used = [], 5123 inst = this; 5124 each( spaces, function( spaceName, space ) { 5125 if ( inst[ space.cache ] ) { 5126 used.push( spaceName ); 5127 } 5128 }); 5129 return used.pop(); 5130 }, 5131 transition: function( other, distance ) { 5132 var end = color( other ), 5133 spaceName = end._space(), 5134 space = spaces[ spaceName ], 5135 startColor = this.alpha() === 0 ? color( "transparent" ) : this, 5136 start = startColor[ space.cache ] || space.to( startColor._rgba ), 5137 result = start.slice(); 5138 5139 end = end[ space.cache ]; 5140 each( space.props, function( key, prop ) { 5141 var index = prop.idx, 5142 startValue = start[ index ], 5143 endValue = end[ index ], 5144 type = propTypes[ prop.type ] || {}; 5145 5146 // if null, don't override start value 5147 if ( endValue === null ) { 5148 return; 5149 } 5150 // if null - use end 5151 if ( startValue === null ) { 5152 result[ index ] = endValue; 5153 } else { 5154 if ( type.mod ) { 5155 if ( endValue - startValue > type.mod / 2 ) { 5156 startValue += type.mod; 5157 } else if ( startValue - endValue > type.mod / 2 ) { 5158 startValue -= type.mod; 5159 } 5160 } 5161 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); 5162 } 5163 }); 5164 return this[ spaceName ]( result ); 5165 }, 5166 blend: function( opaque ) { 5167 // if we are already opaque - return ourself 5168 if ( this._rgba[ 3 ] === 1 ) { 5169 return this; 5170 } 5171 5172 var rgb = this._rgba.slice(), 5173 a = rgb.pop(), 5174 blend = color( opaque )._rgba; 5175 5176 return color( jQuery.map( rgb, function( v, i ) { 5177 return ( 1 - a ) * blend[ i ] + a * v; 5178 })); 5179 }, 5180 toRgbaString: function() { 5181 var prefix = "rgba(", 5182 rgba = jQuery.map( this._rgba, function( v, i ) { 5183 return v == null ? ( i > 2 ? 1 : 0 ) : v; 5184 }); 5185 5186 if ( rgba[ 3 ] === 1 ) { 5187 rgba.pop(); 5188 prefix = "rgb("; 5189 } 5190 5191 return prefix + rgba.join() + ")"; 5192 }, 5193 toHslaString: function() { 5194 var prefix = "hsla(", 5195 hsla = jQuery.map( this.hsla(), function( v, i ) { 5196 if ( v == null ) { 5197 v = i > 2 ? 1 : 0; 5198 } 5199 5200 // catch 1 and 2 5201 if ( i && i < 3 ) { 5202 v = Math.round( v * 100 ) + "%"; 5203 } 5204 return v; 5205 }); 5206 5207 if ( hsla[ 3 ] === 1 ) { 5208 hsla.pop(); 5209 prefix = "hsl("; 5210 } 5211 return prefix + hsla.join() + ")"; 5212 }, 5213 toHexString: function( includeAlpha ) { 5214 var rgba = this._rgba.slice(), 5215 alpha = rgba.pop(); 5216 5217 if ( includeAlpha ) { 5218 rgba.push( ~~( alpha * 255 ) ); 5219 } 5220 5221 return "#" + jQuery.map( rgba, function( v ) { 5222 5223 // default to 0 when nulls exist 5224 v = ( v || 0 ).toString( 16 ); 5225 return v.length === 1 ? "0" + v : v; 5226 }).join(""); 5227 }, 5228 toString: function() { 5229 return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); 5230 } 5231}); 5232color.fn.parse.prototype = color.fn; 5233 5234// hsla conversions adapted from: 5235// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 5236 5237function hue2rgb( p, q, h ) { 5238 h = ( h + 1 ) % 1; 5239 if ( h * 6 < 1 ) { 5240 return p + (q - p) * h * 6; 5241 } 5242 if ( h * 2 < 1) { 5243 return q; 5244 } 5245 if ( h * 3 < 2 ) { 5246 return p + (q - p) * ((2/3) - h) * 6; 5247 } 5248 return p; 5249} 5250 5251spaces.hsla.to = function ( rgba ) { 5252 if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { 5253 return [ null, null, null, rgba[ 3 ] ]; 5254 } 5255 var r = rgba[ 0 ] / 255, 5256 g = rgba[ 1 ] / 255, 5257 b = rgba[ 2 ] / 255, 5258 a = rgba[ 3 ], 5259 max = Math.max( r, g, b ), 5260 min = Math.min( r, g, b ), 5261 diff = max - min, 5262 add = max + min, 5263 l = add * 0.5, 5264 h, s; 5265 5266 if ( min === max ) { 5267 h = 0; 5268 } else if ( r === max ) { 5269 h = ( 60 * ( g - b ) / diff ) + 360; 5270 } else if ( g === max ) { 5271 h = ( 60 * ( b - r ) / diff ) + 120; 5272 } else { 5273 h = ( 60 * ( r - g ) / diff ) + 240; 5274 } 5275 5276 // chroma (diff) == 0 means greyscale which, by definition, saturation = 0% 5277 // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) 5278 if ( diff === 0 ) { 5279 s = 0; 5280 } else if ( l <= 0.5 ) { 5281 s = diff / add; 5282 } else { 5283 s = diff / ( 2 - add ); 5284 } 5285 return [ Math.round(h) % 360, s, l, a == null ? 1 : a ]; 5286}; 5287 5288spaces.hsla.from = function ( hsla ) { 5289 if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { 5290 return [ null, null, null, hsla[ 3 ] ]; 5291 } 5292 var h = hsla[ 0 ] / 360, 5293 s = hsla[ 1 ], 5294 l = hsla[ 2 ], 5295 a = hsla[ 3 ], 5296 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, 5297 p = 2 * l - q; 5298 5299 return [ 5300 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), 5301 Math.round( hue2rgb( p, q, h ) * 255 ), 5302 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), 5303 a 5304 ]; 5305}; 5306 5307 5308each( spaces, function( spaceName, space ) { 5309 var props = space.props, 5310 cache = space.cache, 5311 to = space.to, 5312 from = space.from; 5313 5314 // makes rgba() and hsla() 5315 color.fn[ spaceName ] = function( value ) { 5316 5317 // generate a cache for this space if it doesn't exist 5318 if ( to && !this[ cache ] ) { 5319 this[ cache ] = to( this._rgba ); 5320 } 5321 if ( value === undefined ) { 5322 return this[ cache ].slice(); 5323 } 5324 5325 var ret, 5326 type = jQuery.type( value ), 5327 arr = ( type === "array" || type === "object" ) ? value : arguments, 5328 local = this[ cache ].slice(); 5329 5330 each( props, function( key, prop ) { 5331 var val = arr[ type === "object" ? key : prop.idx ]; 5332 if ( val == null ) { 5333 val = local[ prop.idx ]; 5334 } 5335 local[ prop.idx ] = clamp( val, prop ); 5336 }); 5337 5338 if ( from ) { 5339 ret = color( from( local ) ); 5340 ret[ cache ] = local; 5341 return ret; 5342 } else { 5343 return color( local ); 5344 } 5345 }; 5346 5347 // makes red() green() blue() alpha() hue() saturation() lightness() 5348 each( props, function( key, prop ) { 5349 // alpha is included in more than one space 5350 if ( color.fn[ key ] ) { 5351 return; 5352 } 5353 color.fn[ key ] = function( value ) { 5354 var vtype = jQuery.type( value ), 5355 fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ), 5356 local = this[ fn ](), 5357 cur = local[ prop.idx ], 5358 match; 5359 5360 if ( vtype === "undefined" ) { 5361 return cur; 5362 } 5363 5364 if ( vtype === "function" ) { 5365 value = value.call( this, cur ); 5366 vtype = jQuery.type( value ); 5367 } 5368 if ( value == null && prop.empty ) { 5369 return this; 5370 } 5371 if ( vtype === "string" ) { 5372 match = rplusequals.exec( value ); 5373 if ( match ) { 5374 value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); 5375 } 5376 } 5377 local[ prop.idx ] = value; 5378 return this[ fn ]( local ); 5379 }; 5380 }); 5381}); 5382 5383// add cssHook and .fx.step function for each named hook. 5384// accept a space separated string of properties 5385color.hook = function( hook ) { 5386 var hooks = hook.split( " " ); 5387 each( hooks, function( i, hook ) { 5388 jQuery.cssHooks[ hook ] = { 5389 set: function( elem, value ) { 5390 var parsed, curElem, 5391 backgroundColor = ""; 5392 5393 if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) { 5394 value = color( parsed || value ); 5395 if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { 5396 curElem = hook === "backgroundColor" ? elem.parentNode : elem; 5397 while ( 5398 (backgroundColor === "" || backgroundColor === "transparent") && 5399 curElem && curElem.style 5400 ) { 5401 try { 5402 backgroundColor = jQuery.css( curElem, "backgroundColor" ); 5403 curElem = curElem.parentNode; 5404 } catch ( e ) { 5405 } 5406 } 5407 5408 value = value.blend( backgroundColor && backgroundColor !== "transparent" ? 5409 backgroundColor : 5410 "_default" ); 5411 } 5412 5413 value = value.toRgbaString(); 5414 } 5415 try { 5416 elem.style[ hook ] = value; 5417 } catch( e ) { 5418 // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' 5419 } 5420 } 5421 }; 5422 jQuery.fx.step[ hook ] = function( fx ) { 5423 if ( !fx.colorInit ) { 5424 fx.start = color( fx.elem, hook ); 5425 fx.end = color( fx.end ); 5426 fx.colorInit = true; 5427 } 5428 jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); 5429 }; 5430 }); 5431 5432}; 5433 5434color.hook( stepHooks ); 5435 5436jQuery.cssHooks.borderColor = { 5437 expand: function( value ) { 5438 var expanded = {}; 5439 5440 each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) { 5441 expanded[ "border" + part + "Color" ] = value; 5442 }); 5443 return expanded; 5444 } 5445}; 5446 5447// Basic color names only. 5448// Usage of any of the other color names requires adding yourself or including 5449// jquery.color.svg-names.js. 5450colors = jQuery.Color.names = { 5451 // 4.1. Basic color keywords 5452 aqua: "#00ffff", 5453 black: "#000000", 5454 blue: "#0000ff", 5455 fuchsia: "#ff00ff", 5456 gray: "#808080", 5457 green: "#008000", 5458 lime: "#00ff00", 5459 maroon: "#800000", 5460 navy: "#000080", 5461 olive: "#808000", 5462 purple: "#800080", 5463 red: "#ff0000", 5464 silver: "#c0c0c0", 5465 teal: "#008080", 5466 white: "#ffffff", 5467 yellow: "#ffff00", 5468 5469 // 4.2.3. "transparent" color keyword 5470 transparent: [ null, null, null, 0 ], 5471 5472 _default: "#ffffff" 5473}; 5474 5475})( jQuery ); 5476 5477 5478/******************************************************************************/ 5479/****************************** CLASS ANIMATIONS ******************************/ 5480/******************************************************************************/ 5481(function() { 5482 5483var classAnimationActions = [ "add", "remove", "toggle" ], 5484 shorthandStyles = { 5485 border: 1, 5486 borderBottom: 1, 5487 borderColor: 1, 5488 borderLeft: 1, 5489 borderRight: 1, 5490 borderTop: 1, 5491 borderWidth: 1, 5492 margin: 1, 5493 padding: 1 5494 }; 5495 5496$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) { 5497 $.fx.step[ prop ] = function( fx ) { 5498 if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { 5499 jQuery.style( fx.elem, prop, fx.end ); 5500 fx.setAttr = true; 5501 } 5502 }; 5503}); 5504 5505function getElementStyles( elem ) { 5506 var key, len, 5507 style = elem.ownerDocument.defaultView ? 5508 elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : 5509 elem.currentStyle, 5510 styles = {}; 5511 5512 if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { 5513 len = style.length; 5514 while ( len-- ) { 5515 key = style[ len ]; 5516 if ( typeof style[ key ] === "string" ) { 5517 styles[ $.camelCase( key ) ] = style[ key ]; 5518 } 5519 } 5520 // support: Opera, IE <9 5521 } else { 5522 for ( key in style ) { 5523 if ( typeof style[ key ] === "string" ) { 5524 styles[ key ] = style[ key ]; 5525 } 5526 } 5527 } 5528 5529 return styles; 5530} 5531 5532 5533function styleDifference( oldStyle, newStyle ) { 5534 var diff = {}, 5535 name, value; 5536 5537 for ( name in newStyle ) { 5538 value = newStyle[ name ]; 5539 if ( oldStyle[ name ] !== value ) { 5540 if ( !shorthandStyles[ name ] ) { 5541 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { 5542 diff[ name ] = value; 5543 } 5544 } 5545 } 5546 } 5547 5548 return diff; 5549} 5550 5551// support: jQuery <1.8 5552if ( !$.fn.addBack ) { 5553 $.fn.addBack = function( selector ) { 5554 return this.add( selector == null ? 5555 this.prevObject : this.prevObject.filter( selector ) 5556 ); 5557 }; 5558} 5559 5560$.effects.animateClass = function( value, duration, easing, callback ) { 5561 var o = $.speed( duration, easing, callback ); 5562 5563 return this.queue( function() { 5564 var animated = $( this ), 5565 baseClass = animated.attr( "class" ) || "", 5566 applyClassChange, 5567 allAnimations = o.children ? animated.find( "*" ).addBack() : animated; 5568 5569 // map the animated objects to store the original styles. 5570 allAnimations = allAnimations.map(function() { 5571 var el = $( this ); 5572 return { 5573 el: el, 5574 start: getElementStyles( this ) 5575 }; 5576 }); 5577 5578 // apply class change 5579 applyClassChange = function() { 5580 $.each( classAnimationActions, function(i, action) { 5581 if ( value[ action ] ) { 5582 animated[ action + "Class" ]( value[ action ] ); 5583 } 5584 }); 5585 }; 5586 applyClassChange(); 5587 5588 // map all animated objects again - calculate new styles and diff 5589 allAnimations = allAnimations.map(function() { 5590 this.end = getElementStyles( this.el[ 0 ] ); 5591 this.diff = styleDifference( this.start, this.end ); 5592 return this; 5593 }); 5594 5595 // apply original class 5596 animated.attr( "class", baseClass ); 5597 5598 // map all animated objects again - this time collecting a promise 5599 allAnimations = allAnimations.map(function() { 5600 var styleInfo = this, 5601 dfd = $.Deferred(), 5602 opts = $.extend({}, o, { 5603 queue: false, 5604 complete: function() { 5605 dfd.resolve( styleInfo ); 5606 } 5607 }); 5608 5609 this.el.animate( this.diff, opts ); 5610 return dfd.promise(); 5611 }); 5612 5613 // once all animations have completed: 5614 $.when.apply( $, allAnimations.get() ).done(function() { 5615 5616 // set the final class 5617 applyClassChange(); 5618 5619 // for each animated element, 5620 // clear all css properties that were animated 5621 $.each( arguments, function() { 5622 var el = this.el; 5623 $.each( this.diff, function(key) { 5624 el.css( key, "" ); 5625 }); 5626 }); 5627 5628 // this is guarnteed to be there if you use jQuery.speed() 5629 // it also handles dequeuing the next anim... 5630 o.complete.call( animated[ 0 ] ); 5631 }); 5632 }); 5633}; 5634 5635$.fn.extend({ 5636 addClass: (function( orig ) { 5637 return function( classNames, speed, easing, callback ) { 5638 return speed ? 5639 $.effects.animateClass.call( this, 5640 { add: classNames }, speed, easing, callback ) : 5641 orig.apply( this, arguments ); 5642 }; 5643 })( $.fn.addClass ), 5644 5645 removeClass: (function( orig ) { 5646 return function( classNames, speed, easing, callback ) { 5647 return arguments.length > 1 ? 5648 $.effects.animateClass.call( this, 5649 { remove: classNames }, speed, easing, callback ) : 5650 orig.apply( this, arguments ); 5651 }; 5652 })( $.fn.removeClass ), 5653 5654 toggleClass: (function( orig ) { 5655 return function( classNames, force, speed, easing, callback ) { 5656 if ( typeof force === "boolean" || force === undefined ) { 5657 if ( !speed ) { 5658 // without speed parameter 5659 return orig.apply( this, arguments ); 5660 } else { 5661 return $.effects.animateClass.call( this, 5662 (force ? { add: classNames } : { remove: classNames }), 5663 speed, easing, callback ); 5664 } 5665 } else { 5666 // without force parameter 5667 return $.effects.animateClass.call( this, 5668 { toggle: classNames }, force, speed, easing ); 5669 } 5670 }; 5671 })( $.fn.toggleClass ), 5672 5673 switchClass: function( remove, add, speed, easing, callback) { 5674 return $.effects.animateClass.call( this, { 5675 add: add, 5676 remove: remove 5677 }, speed, easing, callback ); 5678 } 5679}); 5680 5681})(); 5682 5683/******************************************************************************/ 5684/*********************************** EFFECTS **********************************/ 5685/******************************************************************************/ 5686 5687(function() { 5688 5689$.extend( $.effects, { 5690 version: "1.10.4", 5691 5692 // Saves a set of properties in a data storage 5693 save: function( element, set ) { 5694 for( var i=0; i < set.length; i++ ) { 5695 if ( set[ i ] !== null ) { 5696 element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); 5697 } 5698 } 5699 }, 5700 5701 // Restores a set of previously saved properties from a data storage 5702 restore: function( element, set ) { 5703 var val, i; 5704 for( i=0; i < set.length; i++ ) { 5705 if ( set[ i ] !== null ) { 5706 val = element.data( dataSpace + set[ i ] ); 5707 // support: jQuery 1.6.2 5708 // http://bugs.jquery.com/ticket/9917 5709 // jQuery 1.6.2 incorrectly returns undefined for any falsy value. 5710 // We can't differentiate between "" and 0 here, so we just assume 5711 // empty string since it's likely to be a more common value... 5712 if ( val === undefined ) { 5713 val = ""; 5714 } 5715 element.css( set[ i ], val ); 5716 } 5717 } 5718 }, 5719 5720 setMode: function( el, mode ) { 5721 if (mode === "toggle") { 5722 mode = el.is( ":hidden" ) ? "show" : "hide"; 5723 } 5724 return mode; 5725 }, 5726 5727 // Translates a [top,left] array into a baseline value 5728 // this should be a little more flexible in the future to handle a string & hash 5729 getBaseline: function( origin, original ) { 5730 var y, x; 5731 switch ( origin[ 0 ] ) { 5732 case "top": y = 0; break; 5733 case "middle": y = 0.5; break; 5734 case "bottom": y = 1; break; 5735 default: y = origin[ 0 ] / original.height; 5736 } 5737 switch ( origin[ 1 ] ) { 5738 case "left": x = 0; break; 5739 case "center": x = 0.5; break; 5740 case "right": x = 1; break; 5741 default: x = origin[ 1 ] / original.width; 5742 } 5743 return { 5744 x: x, 5745 y: y 5746 }; 5747 }, 5748 5749 // Wraps the element around a wrapper that copies position properties 5750 createWrapper: function( element ) { 5751 5752 // if the element is already wrapped, return it 5753 if ( element.parent().is( ".ui-effects-wrapper" )) { 5754 return element.parent(); 5755 } 5756 5757 // wrap the element 5758 var props = { 5759 width: element.outerWidth(true), 5760 height: element.outerHeight(true), 5761 "float": element.css( "float" ) 5762 }, 5763 wrapper = $( "<div></div>" ) 5764 .addClass( "ui-effects-wrapper" ) 5765 .css({ 5766 fontSize: "100%", 5767 background: "transparent", 5768 border: "none", 5769 margin: 0, 5770 padding: 0 5771 }), 5772 // Store the size in case width/height are defined in % - Fixes #5245 5773 size = { 5774 width: element.width(), 5775 height: element.height() 5776 }, 5777 active = document.activeElement; 5778 5779 // support: Firefox 5780 // Firefox incorrectly exposes anonymous content 5781 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 5782 try { 5783 active.id; 5784 } catch( e ) { 5785 active = document.body; 5786 } 5787 5788 element.wrap( wrapper ); 5789 5790 // Fixes #7595 - Elements lose focus when wrapped. 5791 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 5792 $( active ).focus(); 5793 } 5794 5795 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element 5796 5797 // transfer positioning properties to the wrapper 5798 if ( element.css( "position" ) === "static" ) { 5799 wrapper.css({ position: "relative" }); 5800 element.css({ position: "relative" }); 5801 } else { 5802 $.extend( props, { 5803 position: element.css( "position" ), 5804 zIndex: element.css( "z-index" ) 5805 }); 5806 $.each([ "top", "left", "bottom", "right" ], function(i, pos) { 5807 props[ pos ] = element.css( pos ); 5808 if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { 5809 props[ pos ] = "auto"; 5810 } 5811 }); 5812 element.css({ 5813 position: "relative", 5814 top: 0, 5815 left: 0, 5816 right: "auto", 5817 bottom: "auto" 5818 }); 5819 } 5820 element.css(size); 5821 5822 return wrapper.css( props ).show(); 5823 }, 5824 5825 removeWrapper: function( element ) { 5826 var active = document.activeElement; 5827 5828 if ( element.parent().is( ".ui-effects-wrapper" ) ) { 5829 element.parent().replaceWith( element ); 5830 5831 // Fixes #7595 - Elements lose focus when wrapped. 5832 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 5833 $( active ).focus(); 5834 } 5835 } 5836 5837 5838 return element; 5839 }, 5840 5841 setTransition: function( element, list, factor, value ) { 5842 value = value || {}; 5843 $.each( list, function( i, x ) { 5844 var unit = element.cssUnit( x ); 5845 if ( unit[ 0 ] > 0 ) { 5846 value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; 5847 } 5848 }); 5849 return value; 5850 } 5851}); 5852 5853// return an effect options object for the given parameters: 5854function _normalizeArguments( effect, options, speed, callback ) { 5855 5856 // allow passing all options as the first parameter 5857 if ( $.isPlainObject( effect ) ) { 5858 options = effect; 5859 effect = effect.effect; 5860 } 5861 5862 // convert to an object 5863 effect = { effect: effect }; 5864 5865 // catch (effect, null, ...) 5866 if ( options == null ) { 5867 options = {}; 5868 } 5869 5870 // catch (effect, callback) 5871 if ( $.isFunction( options ) ) { 5872 callback = options; 5873 speed = null; 5874 options = {}; 5875 } 5876 5877 // catch (effect, speed, ?) 5878 if ( typeof options === "number" || $.fx.speeds[ options ] ) { 5879 callback = speed; 5880 speed = options; 5881 options = {}; 5882 } 5883 5884 // catch (effect, options, callback) 5885 if ( $.isFunction( speed ) ) { 5886 callback = speed; 5887 speed = null; 5888 } 5889 5890 // add options to effect 5891 if ( options ) { 5892 $.extend( effect, options ); 5893 } 5894 5895 speed = speed || options.duration; 5896 effect.duration = $.fx.off ? 0 : 5897 typeof speed === "number" ? speed : 5898 speed in $.fx.speeds ? $.fx.speeds[ speed ] : 5899 $.fx.speeds._default; 5900 5901 effect.complete = callback || options.complete; 5902 5903 return effect; 5904} 5905 5906function standardAnimationOption( option ) { 5907 // Valid standard speeds (nothing, number, named speed) 5908 if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) { 5909 return true; 5910 } 5911 5912 // Invalid strings - treat as "normal" speed 5913 if ( typeof option === "string" && !$.effects.effect[ option ] ) { 5914 return true; 5915 } 5916 5917 // Complete callback 5918 if ( $.isFunction( option ) ) { 5919 return true; 5920 } 5921 5922 // Options hash (but not naming an effect) 5923 if ( typeof option === "object" && !option.effect ) { 5924 return true; 5925 } 5926 5927 // Didn't match any standard API 5928 return false; 5929} 5930 5931$.fn.extend({ 5932 effect: function( /* effect, options, speed, callback */ ) { 5933 var args = _normalizeArguments.apply( this, arguments ), 5934 mode = args.mode, 5935 queue = args.queue, 5936 effectMethod = $.effects.effect[ args.effect ]; 5937 5938 if ( $.fx.off || !effectMethod ) { 5939 // delegate to the original method (e.g., .show()) if possible 5940 if ( mode ) { 5941 return this[ mode ]( args.duration, args.complete ); 5942 } else { 5943 return this.each( function() { 5944 if ( args.complete ) { 5945 args.complete.call( this ); 5946 } 5947 }); 5948 } 5949 } 5950 5951 function run( next ) { 5952 var elem = $( this ), 5953 complete = args.complete, 5954 mode = args.mode; 5955 5956 function done() { 5957 if ( $.isFunction( complete ) ) { 5958 complete.call( elem[0] ); 5959 } 5960 if ( $.isFunction( next ) ) { 5961 next(); 5962 } 5963 } 5964 5965 // If the element already has the correct final state, delegate to 5966 // the core methods so the internal tracking of "olddisplay" works. 5967 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { 5968 elem[ mode ](); 5969 done(); 5970 } else { 5971 effectMethod.call( elem[0], args, done ); 5972 } 5973 } 5974 5975 return queue === false ? this.each( run ) : this.queue( queue || "fx", run ); 5976 }, 5977 5978 show: (function( orig ) { 5979 return function( option ) { 5980 if ( standardAnimationOption( option ) ) { 5981 return orig.apply( this, arguments ); 5982 } else { 5983 var args = _normalizeArguments.apply( this, arguments ); 5984 args.mode = "show"; 5985 return this.effect.call( this, args ); 5986 } 5987 }; 5988 })( $.fn.show ), 5989 5990 hide: (function( orig ) { 5991 return function( option ) { 5992 if ( standardAnimationOption( option ) ) { 5993 return orig.apply( this, arguments ); 5994 } else { 5995 var args = _normalizeArguments.apply( this, arguments ); 5996 args.mode = "hide"; 5997 return this.effect.call( this, args ); 5998 } 5999 }; 6000 })( $.fn.hide ), 6001 6002 toggle: (function( orig ) { 6003 return function( option ) { 6004 if ( standardAnimationOption( option ) || typeof option === "boolean" ) { 6005 return orig.apply( this, arguments ); 6006 } else { 6007 var args = _normalizeArguments.apply( this, arguments ); 6008 args.mode = "toggle"; 6009 return this.effect.call( this, args ); 6010 } 6011 }; 6012 })( $.fn.toggle ), 6013 6014 // helper functions 6015 cssUnit: function(key) { 6016 var style = this.css( key ), 6017 val = []; 6018 6019 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { 6020 if ( style.indexOf( unit ) > 0 ) { 6021 val = [ parseFloat( style ), unit ]; 6022 } 6023 }); 6024 return val; 6025 } 6026}); 6027 6028})(); 6029 6030/******************************************************************************/ 6031/*********************************** EASING ***********************************/ 6032/******************************************************************************/ 6033 6034(function() { 6035 6036// based on easing equations from Robert Penner (http://www.robertpenner.com/easing) 6037 6038var baseEasings = {}; 6039 6040$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { 6041 baseEasings[ name ] = function( p ) { 6042 return Math.pow( p, i + 2 ); 6043 }; 6044}); 6045 6046$.extend( baseEasings, { 6047 Sine: function ( p ) { 6048 return 1 - Math.cos( p * Math.PI / 2 ); 6049 }, 6050 Circ: function ( p ) { 6051 return 1 - Math.sqrt( 1 - p * p ); 6052 }, 6053 Elastic: function( p ) { 6054 return p === 0 || p === 1 ? p : 6055 -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 ); 6056 }, 6057 Back: function( p ) { 6058 return p * p * ( 3 * p - 2 ); 6059 }, 6060 Bounce: function ( p ) { 6061 var pow2, 6062 bounce = 4; 6063 6064 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} 6065 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); 6066 } 6067}); 6068 6069$.each( baseEasings, function( name, easeIn ) { 6070 $.easing[ "easeIn" + name ] = easeIn; 6071 $.easing[ "easeOut" + name ] = function( p ) { 6072 return 1 - easeIn( 1 - p ); 6073 }; 6074 $.easing[ "easeInOut" + name ] = function( p ) { 6075 return p < 0.5 ? 6076 easeIn( p * 2 ) / 2 : 6077 1 - easeIn( p * -2 + 2 ) / 2; 6078 }; 6079}); 6080 6081})(); 6082 6083})(jQuery); 6084 6085(function( $, undefined ) { 6086 6087var uid = 0, 6088 hideProps = {}, 6089 showProps = {}; 6090 6091hideProps.height = hideProps.paddingTop = hideProps.paddingBottom = 6092 hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide"; 6093showProps.height = showProps.paddingTop = showProps.paddingBottom = 6094 showProps.borderTopWidth = showProps.borderBottomWidth = "show"; 6095 6096$.widget( "ui.accordion", { 6097 version: "1.10.4", 6098 options: { 6099 active: 0, 6100 animate: {}, 6101 collapsible: false, 6102 event: "click", 6103 header: "> li > :first-child,> :not(li):even", 6104 heightStyle: "auto", 6105 icons: { 6106 activeHeader: "ui-icon-triangle-1-s", 6107 header: "ui-icon-triangle-1-e" 6108 }, 6109 6110 // callbacks 6111 activate: null, 6112 beforeActivate: null 6113 }, 6114 6115 _create: function() { 6116 var options = this.options; 6117 this.prevShow = this.prevHide = $(); 6118 this.element.addClass( "ui-accordion ui-widget ui-helper-reset" ) 6119 // ARIA 6120 .attr( "role", "tablist" ); 6121 6122 // don't allow collapsible: false and active: false / null 6123 if ( !options.collapsible && (options.active === false || options.active == null) ) { 6124 options.active = 0; 6125 } 6126 6127 this._processPanels(); 6128 // handle negative values 6129 if ( options.active < 0 ) { 6130 options.active += this.headers.length; 6131 } 6132 this._refresh(); 6133 }, 6134 6135 _getCreateEventData: function() { 6136 return { 6137 header: this.active, 6138 panel: !this.active.length ? $() : this.active.next(), 6139 content: !this.active.length ? $() : this.active.next() 6140 }; 6141 }, 6142 6143 _createIcons: function() { 6144 var icons = this.options.icons; 6145 if ( icons ) { 6146 $( "<span>" ) 6147 .addClass( "ui-accordion-header-icon ui-icon " + icons.header ) 6148 .prependTo( this.headers ); 6149 this.active.children( ".ui-accordion-header-icon" ) 6150 .removeClass( icons.header ) 6151 .addClass( icons.activeHeader ); 6152 this.headers.addClass( "ui-accordion-icons" ); 6153 } 6154 }, 6155 6156 _destroyIcons: function() { 6157 this.headers 6158 .removeClass( "ui-accordion-icons" ) 6159 .children( ".ui-accordion-header-icon" ) 6160 .remove(); 6161 }, 6162 6163 _destroy: function() { 6164 var contents; 6165 6166 // clean up main element 6167 this.element 6168 .removeClass( "ui-accordion ui-widget ui-helper-reset" ) 6169 .removeAttr( "role" ); 6170 6171 // clean up headers 6172 this.headers 6173 .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" ) 6174 .removeAttr( "role" ) 6175 .removeAttr( "aria-expanded" ) 6176 .removeAttr( "aria-selected" ) 6177 .removeAttr( "aria-controls" ) 6178 .removeAttr( "tabIndex" ) 6179 .each(function() { 6180 if ( /^ui-accordion/.test( this.id ) ) { 6181 this.removeAttribute( "id" ); 6182 } 6183 }); 6184 this._destroyIcons(); 6185 6186 // clean up content panels 6187 contents = this.headers.next() 6188 .css( "display", "" ) 6189 .removeAttr( "role" ) 6190 .removeAttr( "aria-hidden" ) 6191 .removeAttr( "aria-labelledby" ) 6192 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" ) 6193 .each(function() { 6194 if ( /^ui-accordion/.test( this.id ) ) { 6195 this.removeAttribute( "id" ); 6196 } 6197 }); 6198 if ( this.options.heightStyle !== "content" ) { 6199 contents.css( "height", "" ); 6200 } 6201 }, 6202 6203 _setOption: function( key, value ) { 6204 if ( key === "active" ) { 6205 // _activate() will handle invalid values and update this.options 6206 this._activate( value ); 6207 return; 6208 } 6209 6210 if ( key === "event" ) { 6211 if ( this.options.event ) { 6212 this._off( this.headers, this.options.event ); 6213 } 6214 this._setupEvents( value ); 6215 } 6216 6217 this._super( key, value ); 6218 6219 // setting collapsible: false while collapsed; open first panel 6220 if ( key === "collapsible" && !value && this.options.active === false ) { 6221 this._activate( 0 ); 6222 } 6223 6224 if ( key === "icons" ) { 6225 this._destroyIcons(); 6226 if ( value ) { 6227 this._createIcons(); 6228 } 6229 } 6230 6231 // #5332 - opacity doesn't cascade to positioned elements in IE 6232 // so we need to add the disabled class to the headers and panels 6233 if ( key === "disabled" ) { 6234 this.headers.add( this.headers.next() ) 6235 .toggleClass( "ui-state-disabled", !!value ); 6236 } 6237 }, 6238 6239 _keydown: function( event ) { 6240 if ( event.altKey || event.ctrlKey ) { 6241 return; 6242 } 6243 6244 var keyCode = $.ui.keyCode, 6245 length = this.headers.length, 6246 currentIndex = this.headers.index( event.target ), 6247 toFocus = false; 6248 6249 switch ( event.keyCode ) { 6250 case keyCode.RIGHT: 6251 case keyCode.DOWN: 6252 toFocus = this.headers[ ( currentIndex + 1 ) % length ]; 6253 break; 6254 case keyCode.LEFT: 6255 case keyCode.UP: 6256 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; 6257 break; 6258 case keyCode.SPACE: 6259 case keyCode.ENTER: 6260 this._eventHandler( event ); 6261 break; 6262 case keyCode.HOME: 6263 toFocus = this.headers[ 0 ]; 6264 break; 6265 case keyCode.END: 6266 toFocus = this.headers[ length - 1 ]; 6267 break; 6268 } 6269 6270 if ( toFocus ) { 6271 $( event.target ).attr( "tabIndex", -1 ); 6272 $( toFocus ).attr( "tabIndex", 0 ); 6273 toFocus.focus(); 6274 event.preventDefault(); 6275 } 6276 }, 6277 6278 _panelKeyDown : function( event ) { 6279 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { 6280 $( event.currentTarget ).prev().focus(); 6281 } 6282 }, 6283 6284 refresh: function() { 6285 var options = this.options; 6286 this._processPanels(); 6287 6288 // was collapsed or no panel 6289 if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) { 6290 options.active = false; 6291 this.active = $(); 6292 // active false only when collapsible is true 6293 } else if ( options.active === false ) { 6294 this._activate( 0 ); 6295 // was active, but active panel is gone 6296 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 6297 // all remaining panel are disabled 6298 if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) { 6299 options.active = false; 6300 this.active = $(); 6301 // activate previous panel 6302 } else { 6303 this._activate( Math.max( 0, options.active - 1 ) ); 6304 } 6305 // was active, active panel still exists 6306 } else { 6307 // make sure active index is correct 6308 options.active = this.headers.index( this.active ); 6309 } 6310 6311 this._destroyIcons(); 6312 6313 this._refresh(); 6314 }, 6315 6316 _processPanels: function() { 6317 this.headers = this.element.find( this.options.header ) 6318 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ); 6319 6320 this.headers.next() 6321 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ) 6322 .filter(":not(.ui-accordion-content-active)") 6323 .hide(); 6324 }, 6325 6326 _refresh: function() { 6327 var maxHeight, 6328 options = this.options, 6329 heightStyle = options.heightStyle, 6330 parent = this.element.parent(), 6331 accordionId = this.accordionId = "ui-accordion-" + 6332 (this.element.attr( "id" ) || ++uid); 6333 6334 this.active = this._findActive( options.active ) 6335 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ) 6336 .removeClass( "ui-corner-all" ); 6337 this.active.next() 6338 .addClass( "ui-accordion-content-active" ) 6339 .show(); 6340 6341 this.headers 6342 .attr( "role", "tab" ) 6343 .each(function( i ) { 6344 var header = $( this ), 6345 headerId = header.attr( "id" ), 6346 panel = header.next(), 6347 panelId = panel.attr( "id" ); 6348 if ( !headerId ) { 6349 headerId = accordionId + "-header-" + i; 6350 header.attr( "id", headerId ); 6351 } 6352 if ( !panelId ) { 6353 panelId = accordionId + "-panel-" + i; 6354 panel.attr( "id", panelId ); 6355 } 6356 header.attr( "aria-controls", panelId ); 6357 panel.attr( "aria-labelledby", headerId ); 6358 }) 6359 .next() 6360 .attr( "role", "tabpanel" ); 6361 6362 this.headers 6363 .not( this.active ) 6364 .attr({ 6365 "aria-selected": "false", 6366 "aria-expanded": "false", 6367 tabIndex: -1 6368 }) 6369 .next() 6370 .attr({ 6371 "aria-hidden": "true" 6372 }) 6373 .hide(); 6374 6375 // make sure at least one header is in the tab order 6376 if ( !this.active.length ) { 6377 this.headers.eq( 0 ).attr( "tabIndex", 0 ); 6378 } else { 6379 this.active.attr({ 6380 "aria-selected": "true", 6381 "aria-expanded": "true", 6382 tabIndex: 0 6383 }) 6384 .next() 6385 .attr({ 6386 "aria-hidden": "false" 6387 }); 6388 } 6389 6390 this._createIcons(); 6391 6392 this._setupEvents( options.event ); 6393 6394 if ( heightStyle === "fill" ) { 6395 maxHeight = parent.height(); 6396 this.element.siblings( ":visible" ).each(function() { 6397 var elem = $( this ), 6398 position = elem.css( "position" ); 6399 6400 if ( position === "absolute" || position === "fixed" ) { 6401 return; 6402 } 6403 maxHeight -= elem.outerHeight( true ); 6404 }); 6405 6406 this.headers.each(function() { 6407 maxHeight -= $( this ).outerHeight( true ); 6408 }); 6409 6410 this.headers.next() 6411 .each(function() { 6412 $( this ).height( Math.max( 0, maxHeight - 6413 $( this ).innerHeight() + $( this ).height() ) ); 6414 }) 6415 .css( "overflow", "auto" ); 6416 } else if ( heightStyle === "auto" ) { 6417 maxHeight = 0; 6418 this.headers.next() 6419 .each(function() { 6420 maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); 6421 }) 6422 .height( maxHeight ); 6423 } 6424 }, 6425 6426 _activate: function( index ) { 6427 var active = this._findActive( index )[ 0 ]; 6428 6429 // trying to activate the already active panel 6430 if ( active === this.active[ 0 ] ) { 6431 return; 6432 } 6433 6434 // trying to collapse, simulate a click on the currently active header 6435 active = active || this.active[ 0 ]; 6436 6437 this._eventHandler({ 6438 target: active, 6439 currentTarget: active, 6440 preventDefault: $.noop 6441 }); 6442 }, 6443 6444 _findActive: function( selector ) { 6445 return typeof selector === "number" ? this.headers.eq( selector ) : $(); 6446 }, 6447 6448 _setupEvents: function( event ) { 6449 var events = { 6450 keydown: "_keydown" 6451 }; 6452 if ( event ) { 6453 $.each( event.split(" "), function( index, eventName ) { 6454 events[ eventName ] = "_eventHandler"; 6455 }); 6456 } 6457 6458 this._off( this.headers.add( this.headers.next() ) ); 6459 this._on( this.headers, events ); 6460 this._on( this.headers.next(), { keydown: "_panelKeyDown" }); 6461 this._hoverable( this.headers ); 6462 this._focusable( this.headers ); 6463 }, 6464 6465 _eventHandler: function( event ) { 6466 var options = this.options, 6467 active = this.active, 6468 clicked = $( event.currentTarget ), 6469 clickedIsActive = clicked[ 0 ] === active[ 0 ], 6470 collapsing = clickedIsActive && options.collapsible, 6471 toShow = collapsing ? $() : clicked.next(), 6472 toHide = active.next(), 6473 eventData = { 6474 oldHeader: active, 6475 oldPanel: toHide, 6476 newHeader: collapsing ? $() : clicked, 6477 newPanel: toShow 6478 }; 6479 6480 event.preventDefault(); 6481 6482 if ( 6483 // click on active header, but not collapsible 6484 ( clickedIsActive && !options.collapsible ) || 6485 // allow canceling activation 6486 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 6487 return; 6488 } 6489 6490 options.active = collapsing ? false : this.headers.index( clicked ); 6491 6492 // when the call to ._toggle() comes after the class changes 6493 // it causes a very odd bug in IE 8 (see #6720) 6494 this.active = clickedIsActive ? $() : clicked; 6495 this._toggle( eventData ); 6496 6497 // switch classes 6498 // corner classes on the previously active header stay after the animation 6499 active.removeClass( "ui-accordion-header-active ui-state-active" ); 6500 if ( options.icons ) { 6501 active.children( ".ui-accordion-header-icon" ) 6502 .removeClass( options.icons.activeHeader ) 6503 .addClass( options.icons.header ); 6504 } 6505 6506 if ( !clickedIsActive ) { 6507 clicked 6508 .removeClass( "ui-corner-all" ) 6509 .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ); 6510 if ( options.icons ) { 6511 clicked.children( ".ui-accordion-header-icon" ) 6512 .removeClass( options.icons.header ) 6513 .addClass( options.icons.activeHeader ); 6514 } 6515 6516 clicked 6517 .next() 6518 .addClass( "ui-accordion-content-active" ); 6519 } 6520 }, 6521 6522 _toggle: function( data ) { 6523 var toShow = data.newPanel, 6524 toHide = this.prevShow.length ? this.prevShow : data.oldPanel; 6525 6526 // handle activating a panel during the animation for another activation 6527 this.prevShow.add( this.prevHide ).stop( true, true ); 6528 this.prevShow = toShow; 6529 this.prevHide = toHide; 6530 6531 if ( this.options.animate ) { 6532 this._animate( toShow, toHide, data ); 6533 } else { 6534 toHide.hide(); 6535 toShow.show(); 6536 this._toggleComplete( data ); 6537 } 6538 6539 toHide.attr({ 6540 "aria-hidden": "true" 6541 }); 6542 toHide.prev().attr( "aria-selected", "false" ); 6543 // if we're switching panels, remove the old header from the tab order 6544 // if we're opening from collapsed state, remove the previous header from the tab order 6545 // if we're collapsing, then keep the collapsing header in the tab order 6546 if ( toShow.length && toHide.length ) { 6547 toHide.prev().attr({ 6548 "tabIndex": -1, 6549 "aria-expanded": "false" 6550 }); 6551 } else if ( toShow.length ) { 6552 this.headers.filter(function() { 6553 return $( this ).attr( "tabIndex" ) === 0; 6554 }) 6555 .attr( "tabIndex", -1 ); 6556 } 6557 6558 toShow 6559 .attr( "aria-hidden", "false" ) 6560 .prev() 6561 .attr({ 6562 "aria-selected": "true", 6563 tabIndex: 0, 6564 "aria-expanded": "true" 6565 }); 6566 }, 6567 6568 _animate: function( toShow, toHide, data ) { 6569 var total, easing, duration, 6570 that = this, 6571 adjust = 0, 6572 down = toShow.length && 6573 ( !toHide.length || ( toShow.index() < toHide.index() ) ), 6574 animate = this.options.animate || {}, 6575 options = down && animate.down || animate, 6576 complete = function() { 6577 that._toggleComplete( data ); 6578 }; 6579 6580 if ( typeof options === "number" ) { 6581 duration = options; 6582 } 6583 if ( typeof options === "string" ) { 6584 easing = options; 6585 } 6586 // fall back from options to animation in case of partial down settings 6587 easing = easing || options.easing || animate.easing; 6588 duration = duration || options.duration || animate.duration; 6589 6590 if ( !toHide.length ) { 6591 return toShow.animate( showProps, duration, easing, complete ); 6592 } 6593 if ( !toShow.length ) { 6594 return toHide.animate( hideProps, duration, easing, complete ); 6595 } 6596 6597 total = toShow.show().outerHeight(); 6598 toHide.animate( hideProps, { 6599 duration: duration, 6600 easing: easing, 6601 step: function( now, fx ) { 6602 fx.now = Math.round( now ); 6603 } 6604 }); 6605 toShow 6606 .hide() 6607 .animate( showProps, { 6608 duration: duration, 6609 easing: easing, 6610 complete: complete, 6611 step: function( now, fx ) { 6612 fx.now = Math.round( now ); 6613 if ( fx.prop !== "height" ) { 6614 adjust += fx.now; 6615 } else if ( that.options.heightStyle !== "content" ) { 6616 fx.now = Math.round( total - toHide.outerHeight() - adjust ); 6617 adjust = 0; 6618 } 6619 } 6620 }); 6621 }, 6622 6623 _toggleComplete: function( data ) { 6624 var toHide = data.oldPanel; 6625 6626 toHide 6627 .removeClass( "ui-accordion-content-active" ) 6628 .prev() 6629 .removeClass( "ui-corner-top" ) 6630 .addClass( "ui-corner-all" ); 6631 6632 // Work around for rendering bug in IE (#5421) 6633 if ( toHide.length ) { 6634 toHide.parent()[0].className = toHide.parent()[0].className; 6635 } 6636 this._trigger( "activate", null, data ); 6637 } 6638}); 6639 6640})( jQuery ); 6641 6642(function( $, undefined ) { 6643 6644$.widget( "ui.autocomplete", { 6645 version: "1.10.4", 6646 defaultElement: "<input>", 6647 options: { 6648 appendTo: null, 6649 autoFocus: false, 6650 delay: 300, 6651 minLength: 1, 6652 position: { 6653 my: "left top", 6654 at: "left bottom", 6655 collision: "none" 6656 }, 6657 source: null, 6658 6659 // callbacks 6660 change: null, 6661 close: null, 6662 focus: null, 6663 open: null, 6664 response: null, 6665 search: null, 6666 select: null 6667 }, 6668 6669 requestIndex: 0, 6670 pending: 0, 6671 6672 _create: function() { 6673 // Some browsers only repeat keydown events, not keypress events, 6674 // so we use the suppressKeyPress flag to determine if we've already 6675 // handled the keydown event. #7269 6676 // Unfortunately the code for & in keypress is the same as the up arrow, 6677 // so we use the suppressKeyPressRepeat flag to avoid handling keypress 6678 // events when we know the keydown event was used to modify the 6679 // search term. #7799 6680 var suppressKeyPress, suppressKeyPressRepeat, suppressInput, 6681 nodeName = this.element[0].nodeName.toLowerCase(), 6682 isTextarea = nodeName === "textarea", 6683 isInput = nodeName === "input"; 6684 6685 this.isMultiLine = 6686 // Textareas are always multi-line 6687 isTextarea ? true : 6688 // Inputs are always single-line, even if inside a contentEditable element 6689 // IE also treats inputs as contentEditable 6690 isInput ? false : 6691 // All other element types are determined by whether or not they're contentEditable 6692 this.element.prop( "isContentEditable" ); 6693 6694 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ]; 6695 this.isNewMenu = true; 6696 6697 this.element 6698 .addClass( "ui-autocomplete-input" ) 6699 .attr( "autocomplete", "off" ); 6700 6701 this._on( this.element, { 6702 keydown: function( event ) { 6703 if ( this.element.prop( "readOnly" ) ) { 6704 suppressKeyPress = true; 6705 suppressInput = true; 6706 suppressKeyPressRepeat = true; 6707 return; 6708 } 6709 6710 suppressKeyPress = false; 6711 suppressInput = false; 6712 suppressKeyPressRepeat = false; 6713 var keyCode = $.ui.keyCode; 6714 switch( event.keyCode ) { 6715 case keyCode.PAGE_UP: 6716 suppressKeyPress = true; 6717 this._move( "previousPage", event ); 6718 break; 6719 case keyCode.PAGE_DOWN: 6720 suppressKeyPress = true; 6721 this._move( "nextPage", event ); 6722 break; 6723 case keyCode.UP: 6724 suppressKeyPress = true; 6725 this._keyEvent( "previous", event ); 6726 break; 6727 case keyCode.DOWN: 6728 suppressKeyPress = true; 6729 this._keyEvent( "next", event ); 6730 break; 6731 case keyCode.ENTER: 6732 case keyCode.NUMPAD_ENTER: 6733 // when menu is open and has focus 6734 if ( this.menu.active ) { 6735 // #6055 - Opera still allows the keypress to occur 6736 // which causes forms to submit 6737 suppressKeyPress = true; 6738 event.preventDefault(); 6739 this.menu.select( event ); 6740 } 6741 break; 6742 case keyCode.TAB: 6743 if ( this.menu.active ) { 6744 this.menu.select( event ); 6745 } 6746 break; 6747 case keyCode.ESCAPE: 6748 if ( this.menu.element.is( ":visible" ) ) { 6749 this._value( this.term ); 6750 this.close( event ); 6751 // Different browsers have different default behavior for escape 6752 // Single press can mean undo or clear 6753 // Double press in IE means clear the whole form 6754 event.preventDefault(); 6755 } 6756 break; 6757 default: 6758 suppressKeyPressRepeat = true; 6759 // search timeout should be triggered before the input value is changed 6760 this._searchTimeout( event ); 6761 break; 6762 } 6763 }, 6764 keypress: function( event ) { 6765 if ( suppressKeyPress ) { 6766 suppressKeyPress = false; 6767 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 6768 event.preventDefault(); 6769 } 6770 return; 6771 } 6772 if ( suppressKeyPressRepeat ) { 6773 return; 6774 } 6775 6776 // replicate some key handlers to allow them to repeat in Firefox and Opera 6777 var keyCode = $.ui.keyCode; 6778 switch( event.keyCode ) { 6779 case keyCode.PAGE_UP: 6780 this._move( "previousPage", event ); 6781 break; 6782 case keyCode.PAGE_DOWN: 6783 this._move( "nextPage", event ); 6784 break; 6785 case keyCode.UP: 6786 this._keyEvent( "previous", event ); 6787 break; 6788 case keyCode.DOWN: 6789 this._keyEvent( "next", event ); 6790 break; 6791 } 6792 }, 6793 input: function( event ) { 6794 if ( suppressInput ) { 6795 suppressInput = false; 6796 event.preventDefault(); 6797 return; 6798 } 6799 this._searchTimeout( event ); 6800 }, 6801 focus: function() { 6802 this.selectedItem = null; 6803 this.previous = this._value(); 6804 }, 6805 blur: function( event ) { 6806 if ( this.cancelBlur ) { 6807 delete this.cancelBlur; 6808 return; 6809 } 6810 6811 clearTimeout( this.searching ); 6812 this.close( event ); 6813 this._change( event ); 6814 } 6815 }); 6816 6817 this._initSource(); 6818 this.menu = $( "<ul>" ) 6819 .addClass( "ui-autocomplete ui-front" ) 6820 .appendTo( this._appendTo() ) 6821 .menu({ 6822 // disable ARIA support, the live region takes care of that 6823 role: null 6824 }) 6825 .hide() 6826 .data( "ui-menu" ); 6827 6828 this._on( this.menu.element, { 6829 mousedown: function( event ) { 6830 // prevent moving focus out of the text field 6831 event.preventDefault(); 6832 6833 // IE doesn't prevent moving focus even with event.preventDefault() 6834 // so we set a flag to know when we should ignore the blur event 6835 this.cancelBlur = true; 6836 this._delay(function() { 6837 delete this.cancelBlur; 6838 }); 6839 6840 // clicking on the scrollbar causes focus to shift to the body 6841 // but we can't detect a mouseup or a click immediately afterward 6842 // so we have to track the next mousedown and close the menu if 6843 // the user clicks somewhere outside of the autocomplete 6844 var menuElement = this.menu.element[ 0 ]; 6845 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { 6846 this._delay(function() { 6847 var that = this; 6848 this.document.one( "mousedown", function( event ) { 6849 if ( event.target !== that.element[ 0 ] && 6850 event.target !== menuElement && 6851 !$.contains( menuElement, event.target ) ) { 6852 that.close(); 6853 } 6854 }); 6855 }); 6856 } 6857 }, 6858 menufocus: function( event, ui ) { 6859 // support: Firefox 6860 // Prevent accidental activation of menu items in Firefox (#7024 #9118) 6861 if ( this.isNewMenu ) { 6862 this.isNewMenu = false; 6863 if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) { 6864 this.menu.blur(); 6865 6866 this.document.one( "mousemove", function() { 6867 $( event.target ).trigger( event.originalEvent ); 6868 }); 6869 6870 return; 6871 } 6872 } 6873 6874 var item = ui.item.data( "ui-autocomplete-item" ); 6875 if ( false !== this._trigger( "focus", event, { item: item } ) ) { 6876 // use value to match what will end up in the input, if it was a key event 6877 if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) { 6878 this._value( item.value ); 6879 } 6880 } else { 6881 // Normally the input is populated with the item's value as the 6882 // menu is navigated, causing screen readers to notice a change and 6883 // announce the item. Since the focus event was canceled, this doesn't 6884 // happen, so we update the live region so that screen readers can 6885 // still notice the change and announce it. 6886 this.liveRegion.text( item.value ); 6887 } 6888 }, 6889 menuselect: function( event, ui ) { 6890 var item = ui.item.data( "ui-autocomplete-item" ), 6891 previous = this.previous; 6892 6893 // only trigger when focus was lost (click on menu) 6894 if ( this.element[0] !== this.document[0].activeElement ) { 6895 this.element.focus(); 6896 this.previous = previous; 6897 // #6109 - IE triggers two focus events and the second 6898 // is asynchronous, so we need to reset the previous 6899 // term synchronously and asynchronously :-( 6900 this._delay(function() { 6901 this.previous = previous; 6902 this.selectedItem = item; 6903 }); 6904 } 6905 6906 if ( false !== this._trigger( "select", event, { item: item } ) ) { 6907 this._value( item.value ); 6908 } 6909 // reset the term after the select event 6910 // this allows custom select handling to work properly 6911 this.term = this._value(); 6912 6913 this.close( event ); 6914 this.selectedItem = item; 6915 } 6916 }); 6917 6918 this.liveRegion = $( "<span>", { 6919 role: "status", 6920 "aria-live": "polite" 6921 }) 6922 .addClass( "ui-helper-hidden-accessible" ) 6923 .insertBefore( this.element ); 6924 6925 // turning off autocomplete prevents the browser from remembering the 6926 // value when navigating through history, so we re-enable autocomplete 6927 // if the page is unloaded before the widget is destroyed. #7790 6928 this._on( this.window, { 6929 beforeunload: function() { 6930 this.element.removeAttr( "autocomplete" ); 6931 } 6932 }); 6933 }, 6934 6935 _destroy: function() { 6936 clearTimeout( this.searching ); 6937 this.element 6938 .removeClass( "ui-autocomplete-input" ) 6939 .removeAttr( "autocomplete" ); 6940 this.menu.element.remove(); 6941 this.liveRegion.remove(); 6942 }, 6943 6944 _setOption: function( key, value ) { 6945 this._super( key, value ); 6946 if ( key === "source" ) { 6947 this._initSource(); 6948 } 6949 if ( key === "appendTo" ) { 6950 this.menu.element.appendTo( this._appendTo() ); 6951 } 6952 if ( key === "disabled" && value && this.xhr ) { 6953 this.xhr.abort(); 6954 } 6955 }, 6956 6957 _appendTo: function() { 6958 var element = this.options.appendTo; 6959 6960 if ( element ) { 6961 element = element.jquery || element.nodeType ? 6962 $( element ) : 6963 this.document.find( element ).eq( 0 ); 6964 } 6965 6966 if ( !element ) { 6967 element = this.element.closest( ".ui-front" ); 6968 } 6969 6970 if ( !element.length ) { 6971 element = this.document[0].body; 6972 } 6973 6974 return element; 6975 }, 6976 6977 _initSource: function() { 6978 var array, url, 6979 that = this; 6980 if ( $.isArray(this.options.source) ) { 6981 array = this.options.source; 6982 this.source = function( request, response ) { 6983 response( $.ui.autocomplete.filter( array, request.term ) ); 6984 }; 6985 } else if ( typeof this.options.source === "string" ) { 6986 url = this.options.source; 6987 this.source = function( request, response ) { 6988 if ( that.xhr ) { 6989 that.xhr.abort(); 6990 } 6991 that.xhr = $.ajax({ 6992 url: url, 6993 data: request, 6994 dataType: "json", 6995 success: function( data ) { 6996 response( data ); 6997 }, 6998 error: function() { 6999 response( [] ); 7000 } 7001 }); 7002 }; 7003 } else { 7004 this.source = this.options.source; 7005 } 7006 }, 7007 7008 _searchTimeout: function( event ) { 7009 clearTimeout( this.searching ); 7010 this.searching = this._delay(function() { 7011 // only search if the value has changed 7012 if ( this.term !== this._value() ) { 7013 this.selectedItem = null; 7014 this.search( null, event ); 7015 } 7016 }, this.options.delay ); 7017 }, 7018 7019 search: function( value, event ) { 7020 value = value != null ? value : this._value(); 7021 7022 // always save the actual value, not the one passed as an argument 7023 this.term = this._value(); 7024 7025 if ( value.length < this.options.minLength ) { 7026 return this.close( event ); 7027 } 7028 7029 if ( this._trigger( "search", event ) === false ) { 7030 return; 7031 } 7032 7033 return this._search( value ); 7034 }, 7035 7036 _search: function( value ) { 7037 this.pending++; 7038 this.element.addClass( "ui-autocomplete-loading" ); 7039 this.cancelSearch = false; 7040 7041 this.source( { term: value }, this._response() ); 7042 }, 7043 7044 _response: function() { 7045 var index = ++this.requestIndex; 7046 7047 return $.proxy(function( content ) { 7048 if ( index === this.requestIndex ) { 7049 this.__response( content ); 7050 } 7051 7052 this.pending--; 7053 if ( !this.pending ) { 7054 this.element.removeClass( "ui-autocomplete-loading" ); 7055 } 7056 }, this ); 7057 }, 7058 7059 __response: function( content ) { 7060 if ( content ) { 7061 content = this._normalize( content ); 7062 } 7063 this._trigger( "response", null, { content: content } ); 7064 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) { 7065 this._suggest( content ); 7066 this._trigger( "open" ); 7067 } else { 7068 // use ._close() instead of .close() so we don't cancel future searches 7069 this._close(); 7070 } 7071 }, 7072 7073 close: function( event ) { 7074 this.cancelSearch = true; 7075 this._close( event ); 7076 }, 7077 7078 _close: function( event ) { 7079 if ( this.menu.element.is( ":visible" ) ) { 7080 this.menu.element.hide(); 7081 this.menu.blur(); 7082 this.isNewMenu = true; 7083 this._trigger( "close", event ); 7084 } 7085 }, 7086 7087 _change: function( event ) { 7088 if ( this.previous !== this._value() ) { 7089 this._trigger( "change", event, { item: this.selectedItem } ); 7090 } 7091 }, 7092 7093 _normalize: function( items ) { 7094 // assume all items have the right format when the first item is complete 7095 if ( items.length && items[0].label && items[0].value ) { 7096 return items; 7097 } 7098 return $.map( items, function( item ) { 7099 if ( typeof item === "string" ) { 7100 return { 7101 label: item, 7102 value: item 7103 }; 7104 } 7105 return $.extend({ 7106 label: item.label || item.value, 7107 value: item.value || item.label 7108 }, item ); 7109 }); 7110 }, 7111 7112 _suggest: function( items ) { 7113 var ul = this.menu.element.empty(); 7114 this._renderMenu( ul, items ); 7115 this.isNewMenu = true; 7116 this.menu.refresh(); 7117 7118 // size and position menu 7119 ul.show(); 7120 this._resizeMenu(); 7121 ul.position( $.extend({ 7122 of: this.element 7123 }, this.options.position )); 7124 7125 if ( this.options.autoFocus ) { 7126 this.menu.next(); 7127 } 7128 }, 7129 7130 _resizeMenu: function() { 7131 var ul = this.menu.element; 7132 ul.outerWidth( Math.max( 7133 // Firefox wraps long text (possibly a rounding bug) 7134 // so we add 1px to avoid the wrapping (#7513) 7135 ul.width( "" ).outerWidth() + 1, 7136 this.element.outerWidth() 7137 ) ); 7138 }, 7139 7140 _renderMenu: function( ul, items ) { 7141 var that = this; 7142 $.each( items, function( index, item ) { 7143 that._renderItemData( ul, item ); 7144 }); 7145 }, 7146 7147 _renderItemData: function( ul, item ) { 7148 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item ); 7149 }, 7150 7151 _renderItem: function( ul, item ) { 7152 return $( "<li>" ) 7153 .append( $( "<a>" ).text( item.label ) ) 7154 .appendTo( ul ); 7155 }, 7156 7157 _move: function( direction, event ) { 7158 if ( !this.menu.element.is( ":visible" ) ) { 7159 this.search( null, event ); 7160 return; 7161 } 7162 if ( this.menu.isFirstItem() && /^previous/.test( direction ) || 7163 this.menu.isLastItem() && /^next/.test( direction ) ) { 7164 this._value( this.term ); 7165 this.menu.blur(); 7166 return; 7167 } 7168 this.menu[ direction ]( event ); 7169 }, 7170 7171 widget: function() { 7172 return this.menu.element; 7173 }, 7174 7175 _value: function() { 7176 return this.valueMethod.apply( this.element, arguments ); 7177 }, 7178 7179 _keyEvent: function( keyEvent, event ) { 7180 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 7181 this._move( keyEvent, event ); 7182 7183 // prevents moving cursor to beginning/end of the text field in some browsers 7184 event.preventDefault(); 7185 } 7186 } 7187}); 7188 7189$.extend( $.ui.autocomplete, { 7190 escapeRegex: function( value ) { 7191 return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); 7192 }, 7193 filter: function(array, term) { 7194 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); 7195 return $.grep( array, function(value) { 7196 return matcher.test( value.label || value.value || value ); 7197 }); 7198 } 7199}); 7200 7201 7202// live region extension, adding a `messages` option 7203// NOTE: This is an experimental API. We are still investigating 7204// a full solution for string manipulation and internationalization. 7205$.widget( "ui.autocomplete", $.ui.autocomplete, { 7206 options: { 7207 messages: { 7208 noResults: "No search results.", 7209 results: function( amount ) { 7210 return amount + ( amount > 1 ? " results are" : " result is" ) + 7211 " available, use up and down arrow keys to navigate."; 7212 } 7213 } 7214 }, 7215 7216 __response: function( content ) { 7217 var message; 7218 this._superApply( arguments ); 7219 if ( this.options.disabled || this.cancelSearch ) { 7220 return; 7221 } 7222 if ( content && content.length ) { 7223 message = this.options.messages.results( content.length ); 7224 } else { 7225 message = this.options.messages.noResults; 7226 } 7227 this.liveRegion.text( message ); 7228 } 7229}); 7230 7231}( jQuery )); 7232 7233(function( $, undefined ) { 7234 7235var lastActive, 7236 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", 7237 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", 7238 formResetHandler = function() { 7239 var form = $( this ); 7240 setTimeout(function() { 7241 form.find( ":ui-button" ).button( "refresh" ); 7242 }, 1 ); 7243 }, 7244 radioGroup = function( radio ) { 7245 var name = radio.name, 7246 form = radio.form, 7247 radios = $( [] ); 7248 if ( name ) { 7249 name = name.replace( /'/g, "\\'" ); 7250 if ( form ) { 7251 radios = $( form ).find( "[name='" + name + "']" ); 7252 } else { 7253 radios = $( "[name='" + name + "']", radio.ownerDocument ) 7254 .filter(function() { 7255 return !this.form; 7256 }); 7257 } 7258 } 7259 return radios; 7260 }; 7261 7262$.widget( "ui.button", { 7263 version: "1.10.4", 7264 defaultElement: "<button>", 7265 options: { 7266 disabled: null, 7267 text: true, 7268 label: null, 7269 icons: { 7270 primary: null, 7271 secondary: null 7272 } 7273 }, 7274 _create: function() { 7275 this.element.closest( "form" ) 7276 .unbind( "reset" + this.eventNamespace ) 7277 .bind( "reset" + this.eventNamespace, formResetHandler ); 7278 7279 if ( typeof this.options.disabled !== "boolean" ) { 7280 this.options.disabled = !!this.element.prop( "disabled" ); 7281 } else { 7282 this.element.prop( "disabled", this.options.disabled ); 7283 } 7284 7285 this._determineButtonType(); 7286 this.hasTitle = !!this.buttonElement.attr( "title" ); 7287 7288 var that = this, 7289 options = this.options, 7290 toggleButton = this.type === "checkbox" || this.type === "radio", 7291 activeClass = !toggleButton ? "ui-state-active" : ""; 7292 7293 if ( options.label === null ) { 7294 options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html()); 7295 } 7296 7297 this._hoverable( this.buttonElement ); 7298 7299 this.buttonElement 7300 .addClass( baseClasses ) 7301 .attr( "role", "button" ) 7302 .bind( "mouseenter" + this.eventNamespace, function() { 7303 if ( options.disabled ) { 7304 return; 7305 } 7306 if ( this === lastActive ) { 7307 $( this ).addClass( "ui-state-active" ); 7308 } 7309 }) 7310 .bind( "mouseleave" + this.eventNamespace, function() { 7311 if ( options.disabled ) { 7312 return; 7313 } 7314 $( this ).removeClass( activeClass ); 7315 }) 7316 .bind( "click" + this.eventNamespace, function( event ) { 7317 if ( options.disabled ) { 7318 event.preventDefault(); 7319 event.stopImmediatePropagation(); 7320 } 7321 }); 7322 7323 // Can't use _focusable() because the element that receives focus 7324 // and the element that gets the ui-state-focus class are different 7325 this._on({ 7326 focus: function() { 7327 this.buttonElement.addClass( "ui-state-focus" ); 7328 }, 7329 blur: function() { 7330 this.buttonElement.removeClass( "ui-state-focus" ); 7331 } 7332 }); 7333 7334 if ( toggleButton ) { 7335 this.element.bind( "change" + this.eventNamespace, function() { 7336 that.refresh(); 7337 }); 7338 } 7339 7340 if ( this.type === "checkbox" ) { 7341 this.buttonElement.bind( "click" + this.eventNamespace, function() { 7342 if ( options.disabled ) { 7343 return false; 7344 } 7345 }); 7346 } else if ( this.type === "radio" ) { 7347 this.buttonElement.bind( "click" + this.eventNamespace, function() { 7348 if ( options.disabled ) { 7349 return false; 7350 } 7351 $( this ).addClass( "ui-state-active" ); 7352 that.buttonElement.attr( "aria-pressed", "true" ); 7353 7354 var radio = that.element[ 0 ]; 7355 radioGroup( radio ) 7356 .not( radio ) 7357 .map(function() { 7358 return $( this ).button( "widget" )[ 0 ]; 7359 }) 7360 .removeClass( "ui-state-active" ) 7361 .attr( "aria-pressed", "false" ); 7362 }); 7363 } else { 7364 this.buttonElement 7365 .bind( "mousedown" + this.eventNamespace, function() { 7366 if ( options.disabled ) { 7367 return false; 7368 } 7369 $( this ).addClass( "ui-state-active" ); 7370 lastActive = this; 7371 that.document.one( "mouseup", function() { 7372 lastActive = null; 7373 }); 7374 }) 7375 .bind( "mouseup" + this.eventNamespace, function() { 7376 if ( options.disabled ) { 7377 return false; 7378 } 7379 $( this ).removeClass( "ui-state-active" ); 7380 }) 7381 .bind( "keydown" + this.eventNamespace, function(event) { 7382 if ( options.disabled ) { 7383 return false; 7384 } 7385 if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) { 7386 $( this ).addClass( "ui-state-active" ); 7387 } 7388 }) 7389 // see #8559, we bind to blur here in case the button element loses 7390 // focus between keydown and keyup, it would be left in an "active" state 7391 .bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() { 7392 $( this ).removeClass( "ui-state-active" ); 7393 }); 7394 7395 if ( this.buttonElement.is("a") ) { 7396 this.buttonElement.keyup(function(event) { 7397 if ( event.keyCode === $.ui.keyCode.SPACE ) { 7398 // TODO pass through original event correctly (just as 2nd argument doesn't work) 7399 $( this ).click(); 7400 } 7401 }); 7402 } 7403 } 7404 7405 // TODO: pull out $.Widget's handling for the disabled option into 7406 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can 7407 // be overridden by individual plugins 7408 this._setOption( "disabled", options.disabled ); 7409 this._resetButton(); 7410 }, 7411 7412 _determineButtonType: function() { 7413 var ancestor, labelSelector, checked; 7414 7415 if ( this.element.is("[type=checkbox]") ) { 7416 this.type = "checkbox"; 7417 } else if ( this.element.is("[type=radio]") ) { 7418 this.type = "radio"; 7419 } else if ( this.element.is("input") ) { 7420 this.type = "input"; 7421 } else { 7422 this.type = "button"; 7423 } 7424 7425 if ( this.type === "checkbox" || this.type === "radio" ) { 7426 // we don't search against the document in case the element 7427 // is disconnected from the DOM 7428 ancestor = this.element.parents().last(); 7429 labelSelector = "label[for='" + this.element.attr("id") + "']"; 7430 this.buttonElement = ancestor.find( labelSelector ); 7431 if ( !this.buttonElement.length ) { 7432 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); 7433 this.buttonElement = ancestor.filter( labelSelector ); 7434 if ( !this.buttonElement.length ) { 7435 this.buttonElement = ancestor.find( labelSelector ); 7436 } 7437 } 7438 this.element.addClass( "ui-helper-hidden-accessible" ); 7439 7440 checked = this.element.is( ":checked" ); 7441 if ( checked ) { 7442 this.buttonElement.addClass( "ui-state-active" ); 7443 } 7444 this.buttonElement.prop( "aria-pressed", checked ); 7445 } else { 7446 this.buttonElement = this.element; 7447 } 7448 }, 7449 7450 widget: function() { 7451 return this.buttonElement; 7452 }, 7453 7454 _destroy: function() { 7455 this.element 7456 .removeClass( "ui-helper-hidden-accessible" ); 7457 this.buttonElement 7458 .removeClass( baseClasses + " ui-state-active " + typeClasses ) 7459 .removeAttr( "role" ) 7460 .removeAttr( "aria-pressed" ) 7461 .html( this.buttonElement.find(".ui-button-text").html() ); 7462 7463 if ( !this.hasTitle ) { 7464 this.buttonElement.removeAttr( "title" ); 7465 } 7466 }, 7467 7468 _setOption: function( key, value ) { 7469 this._super( key, value ); 7470 if ( key === "disabled" ) { 7471 this.element.prop( "disabled", !!value ); 7472 if ( value ) { 7473 this.buttonElement.removeClass( "ui-state-focus" ); 7474 } 7475 return; 7476 } 7477 this._resetButton(); 7478 }, 7479 7480 refresh: function() { 7481 //See #8237 & #8828 7482 var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" ); 7483 7484 if ( isDisabled !== this.options.disabled ) { 7485 this._setOption( "disabled", isDisabled ); 7486 } 7487 if ( this.type === "radio" ) { 7488 radioGroup( this.element[0] ).each(function() { 7489 if ( $( this ).is( ":checked" ) ) { 7490 $( this ).button( "widget" ) 7491 .addClass( "ui-state-active" ) 7492 .attr( "aria-pressed", "true" ); 7493 } else { 7494 $( this ).button( "widget" ) 7495 .removeClass( "ui-state-active" ) 7496 .attr( "aria-pressed", "false" ); 7497 } 7498 }); 7499 } else if ( this.type === "checkbox" ) { 7500 if ( this.element.is( ":checked" ) ) { 7501 this.buttonElement 7502 .addClass( "ui-state-active" ) 7503 .attr( "aria-pressed", "true" ); 7504 } else { 7505 this.buttonElement 7506 .removeClass( "ui-state-active" ) 7507 .attr( "aria-pressed", "false" ); 7508 } 7509 } 7510 }, 7511 7512 _resetButton: function() { 7513 if ( this.type === "input" ) { 7514 if ( this.options.label ) { 7515 this.element.val( this.options.label ); 7516 } 7517 return; 7518 } 7519 var buttonElement = this.buttonElement.removeClass( typeClasses ), 7520 buttonText = $( "<span></span>", this.document[0] ) 7521 .addClass( "ui-button-text" ) 7522 .html( this.options.label ) 7523 .appendTo( buttonElement.empty() ) 7524 .text(), 7525 icons = this.options.icons, 7526 multipleIcons = icons.primary && icons.secondary,
vendor: 2,268 bytes, lines 7527-7617
7527 buttonClasses = []; 7528 7529 if ( icons.primary || icons.secondary ) { 7530 if ( this.options.text ) { 7531 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) ); 7532 } 7533 7534 if ( icons.primary ) { 7535 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" ); 7536 } 7537 7538 if ( icons.secondary ) { 7539 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" ); 7540 } 7541 7542 if ( !this.options.text ) { 7543 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" ); 7544 7545 if ( !this.hasTitle ) { 7546 buttonElement.attr( "title", $.trim( buttonText ) ); 7547 } 7548 } 7549 } else { 7550 buttonClasses.push( "ui-button-text-only" ); 7551 } 7552 buttonElement.addClass( buttonClasses.join( " " ) ); 7553 } 7554}); 7555 7556$.widget( "ui.buttonset", { 7557 version: "1.10.4", 7558 options: { 7559 items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)" 7560 }, 7561 7562 _create: function() { 7563 this.element.addClass( "ui-buttonset" ); 7564 }, 7565 7566 _init: function() { 7567 this.refresh(); 7568 }, 7569 7570 _setOption: function( key, value ) { 7571 if ( key === "disabled" ) { 7572 this.buttons.button( "option", key, value ); 7573 } 7574 7575 this._super( key, value ); 7576 }, 7577 7578 refresh: function() { 7579 var rtl = this.element.css( "direction" ) === "rtl"; 7580 7581 this.buttons = this.element.find( this.options.items ) 7582 .filter( ":ui-button" ) 7583 .button( "refresh" ) 7584 .end() 7585 .not( ":ui-button" ) 7586 .button() 7587 .end() 7588 .map(function() { 7589 return $( this ).button( "widget" )[ 0 ]; 7590 }) 7591 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" ) 7592 .filter( ":first" ) 7593 .addClass( rtl ? "ui-corner-right" : "ui-corner-left" ) 7594 .end() 7595 .filter( ":last" ) 7596 .addClass( rtl ? "ui-corner-left" : "ui-corner-right" ) 7597 .end() 7598 .end(); 7599 }, 7600 7601 _destroy: function() { 7602 this.element.removeClass( "ui-buttonset" ); 7603 this.buttons 7604 .map(function() { 7605 return $( this ).button( "widget" )[ 0 ]; 7606 }) 7607 .removeClass( "ui-corner-left ui-corner-right" ) 7608 .end() 7609 .button( "destroy" ); 7610 } 7611}); 7612 7613}( jQuery ) ); 7614 7615(function( $, undefined ) { 7616 7617$.extend($.ui, { datepicker: { version: "1.10.4
vendor: 75,965 bytes, lines 7617-9637
7617" } }); 7618 7619var PROP_NAME = "datepicker", 7620 instActive; 7621 7622/* Date picker manager. 7623 Use the singleton instance of this class, $.datepicker, to interact with the date picker. 7624 Settings for (groups of) date pickers are maintained in an instance object, 7625 allowing multiple different settings on the same page. */ 7626 7627function Datepicker() { 7628 this._curInst = null; // The current instance in use 7629 this._keyEvent = false; // If the last event was a key event 7630 this._disabledInputs = []; // List of date picker inputs that have been disabled 7631 this._datepickerShowing = false; // True if the popup picker is showing , false if not 7632 this._inDialog = false; // True if showing within a "dialog", false if not 7633 this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division 7634 this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class 7635 this._appendClass = "ui-datepicker-append"; // The name of the append marker class 7636 this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class 7637 this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class 7638 this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class 7639 this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class 7640 this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class 7641 this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class 7642 this.regional = []; // Available regional settings, indexed by language code 7643 this.regional[""] = { // Default regional settings 7644 closeText: "Done", // Display text for close link 7645 prevText: "Prev", // Display text for previous month link 7646 nextText: "Next", // Display text for next month link 7647 currentText: "Today", // Display text for current month link 7648 monthNames: ["January","February","March","April","May","June", 7649 "July","August","September","October","November","December"], // Names of months for drop-down and formatting 7650 monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting 7651 dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting 7652 dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting 7653 dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday 7654 weekHeader: "Wk", // Column header for week of the year 7655 dateFormat: "mm/dd/yy", // See format options on parseDate 7656 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... 7657 isRTL: false, // True if right-to-left language, false if left-to-right 7658 showMonthAfterYear: false, // True if the year select precedes month, false for month then year 7659 yearSuffix: "" // Additional text to append to the year in the month headers 7660 }; 7661 this._defaults = { // Global defaults for all the date picker instances 7662 showOn: "focus", // "focus" for popup on focus, 7663 // "button" for trigger button, or "both" for either 7664 showAnim: "fadeIn", // Name of jQuery animation for popup 7665 showOptions: {}, // Options for enhanced animations 7666 defaultDate: null, // Used when field is blank: actual date, 7667 // +/-number for offset from today, null for today 7668 appendText: "", // Display text following the input box, e.g. showing the format 7669 buttonText: "...", // Text for trigger button 7670 buttonImage: "", // URL for trigger button image 7671 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button 7672 hideIfNoPrevNext: false, // True to hide next/previous month links 7673 // if not applicable, false to just disable them 7674 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links 7675 gotoCurrent: false, // True if today link goes back to current selection instead 7676 changeMonth: false, // True if month can be selected directly, false if only prev/next 7677 changeYear: false, // True if year can be selected directly, false if only prev/next 7678 yearRange: "c-10:c+10", // Range of years to display in drop-down, 7679 // either relative to today's year (-nn:+nn), relative to currently displayed year 7680 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) 7681 showOtherMonths: false, // True to show dates in other months, false to leave blank 7682 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable 7683 showWeek: false, // True to show week of the year, false to not show it 7684 calculateWeek: this.iso8601Week, // How to calculate the week of the year, 7685 // takes a Date and returns the number of the week for it 7686 shortYearCutoff: "+10", // Short year values < this are in the current century, 7687 // > this are in the previous century, 7688 // string value starting with "+" for current year + value 7689 minDate: null, // The earliest selectable date, or null for no limit 7690 maxDate: null, // The latest selectable date, or null for no limit 7691 duration: "fast", // Duration of display/closure 7692 beforeShowDay: null, // Function that takes a date and returns an array with 7693 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "", 7694 // [2] = cell title (optional), e.g. $.datepicker.noWeekends 7695 beforeShow: null, // Function that takes an input field and 7696 // returns a set of custom settings for the date picker 7697 onSelect: null, // Define a callback function when a date is selected 7698 onChangeMonthYear: null, // Define a callback function when the month or year is changed 7699 onClose: null, // Define a callback function when the datepicker is closed 7700 numberOfMonths: 1, // Number of months to show at a time 7701 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) 7702 stepMonths: 1, // Number of months to step back/forward 7703 stepBigMonths: 12, // Number of months to step back/forward for the big links 7704 altField: "", // Selector for an alternate field to store selected dates into 7705 altFormat: "", // The date format to use for the alternate field 7706 constrainInput: true, // The input is constrained by the current date format 7707 showButtonPanel: false, // True to show button panel, false to not show it 7708 autoSize: false, // True to size the input for the date format, false to leave as is 7709 disabled: false // The initial disabled state 7710 }; 7711 $.extend(this._defaults, this.regional[""]); 7712 this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")); 7713} 7714 7715$.extend(Datepicker.prototype, { 7716 /* Class name added to elements to indicate already configured with a date picker. */ 7717 markerClassName: "hasDatepicker", 7718 7719 //Keep track of the maximum number of rows displayed (see #7043) 7720 maxRows: 4, 7721 7722 // TODO rename to "widget" when switching to widget factory 7723 _widgetDatepicker: function() { 7724 return this.dpDiv; 7725 }, 7726 7727 /* Override the default settings for all instances of the date picker. 7728 * @param settings object - the new settings to use as defaults (anonymous object) 7729 * @return the manager object 7730 */ 7731 setDefaults: function(settings) { 7732 extendRemove(this._defaults, settings || {}); 7733 return this; 7734 }, 7735 7736 /* Attach the date picker to a jQuery selection. 7737 * @param target element - the target input field or division or span 7738 * @param settings object - the new settings to use for this date picker instance (anonymous) 7739 */ 7740 _attachDatepicker: function(target, settings) { 7741 var nodeName, inline, inst; 7742 nodeName = target.nodeName.toLowerCase(); 7743 inline = (nodeName === "div" || nodeName === "span"); 7744 if (!target.id) { 7745 this.uuid += 1; 7746 target.id = "dp" + this.uuid; 7747 } 7748 inst = this._newInst($(target), inline); 7749 inst.settings = $.extend({}, settings || {}); 7750 if (nodeName === "input") { 7751 this._connectDatepicker(target, inst); 7752 } else if (inline) { 7753 this._inlineDatepicker(target, inst); 7754 } 7755 }, 7756 7757 /* Create a new instance object. */ 7758 _newInst: function(target, inline) { 7759 var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars 7760 return {id: id, input: target, // associated target 7761 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection 7762 drawMonth: 0, drawYear: 0, // month being drawn 7763 inline: inline, // is datepicker inline or not 7764 dpDiv: (!inline ? this.dpDiv : // presentation div 7765 bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))}; 7766 }, 7767 7768 /* Attach the date picker to an input field. */ 7769 _connectDatepicker: function(target, inst) { 7770 var input = $(target); 7771 inst.append = $([]); 7772 inst.trigger = $([]); 7773 if (input.hasClass(this.markerClassName)) { 7774 return; 7775 } 7776 this._attachments(input, inst); 7777 input.addClass(this.markerClassName).keydown(this._doKeyDown). 7778 keypress(this._doKeyPress).keyup(this._doKeyUp); 7779 this._autoSize(inst); 7780 $.data(target, PROP_NAME, inst); 7781 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) 7782 if( inst.settings.disabled ) { 7783 this._disableDatepicker( target ); 7784 } 7785 }, 7786 7787 /* Make attachments based on settings. */ 7788 _attachments: function(input, inst) { 7789 var showOn, buttonText, buttonImage, 7790 appendText = this._get(inst, "appendText"), 7791 isRTL = this._get(inst, "isRTL"); 7792 7793 if (inst.append) { 7794 inst.append.remove(); 7795 } 7796 if (appendText) { 7797 inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>"); 7798 input[isRTL ? "before" : "after"](inst.append); 7799 } 7800 7801 input.unbind("focus", this._showDatepicker); 7802 7803 if (inst.trigger) { 7804 inst.trigger.remove(); 7805 } 7806 7807 showOn = this._get(inst, "showOn"); 7808 if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field 7809 input.focus(this._showDatepicker); 7810 } 7811 if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked 7812 buttonText = this._get(inst, "buttonText"); 7813 buttonImage = this._get(inst, "buttonImage"); 7814 inst.trigger = $(this._get(inst, "buttonImageOnly") ? 7815 $("<img/>").addClass(this._triggerClass). 7816 attr({ src: buttonImage, alt: buttonText, title: buttonText }) : 7817 $("<button type='button'></button>").addClass(this._triggerClass). 7818 html(!buttonImage ? buttonText : $("<img/>").attr( 7819 { src:buttonImage, alt:buttonText, title:buttonText }))); 7820 input[isRTL ? "before" : "after"](inst.trigger); 7821 inst.trigger.click(function() { 7822 if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) { 7823 $.datepicker._hideDatepicker(); 7824 } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) { 7825 $.datepicker._hideDatepicker(); 7826 $.datepicker._showDatepicker(input[0]); 7827 } else { 7828 $.datepicker._showDatepicker(input[0]); 7829 } 7830 return false; 7831 }); 7832 } 7833 }, 7834 7835 /* Apply the maximum length for the date format. */ 7836 _autoSize: function(inst) { 7837 if (this._get(inst, "autoSize") && !inst.inline) { 7838 var findMax, max, maxI, i, 7839 date = new Date(2009, 12 - 1, 20), // Ensure double digits 7840 dateFormat = this._get(inst, "dateFormat"); 7841 7842 if (dateFormat.match(/[DM]/)) { 7843 findMax = function(names) { 7844 max = 0; 7845 maxI = 0; 7846 for (i = 0; i < names.length; i++) { 7847 if (names[i].length > max) { 7848 max = names[i].length; 7849 maxI = i; 7850 } 7851 } 7852 return maxI; 7853 }; 7854 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? 7855 "monthNames" : "monthNamesShort")))); 7856 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? 7857 "dayNames" : "dayNamesShort"))) + 20 - date.getDay()); 7858 } 7859 inst.input.attr("size", this._formatDate(inst, date).length); 7860 } 7861 }, 7862 7863 /* Attach an inline date picker to a div. */ 7864 _inlineDatepicker: function(target, inst) { 7865 var divSpan = $(target); 7866 if (divSpan.hasClass(this.markerClassName)) { 7867 return; 7868 } 7869 divSpan.addClass(this.markerClassName).append(inst.dpDiv); 7870 $.data(target, PROP_NAME, inst); 7871 this._setDate(inst, this._getDefaultDate(inst), true); 7872 this._updateDatepicker(inst); 7873 this._updateAlternate(inst); 7874 //If disabled option is true, disable the datepicker before showing it (see ticket #5665) 7875 if( inst.settings.disabled ) { 7876 this._disableDatepicker( target ); 7877 } 7878 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements 7879 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height 7880 inst.dpDiv.css( "display", "block" ); 7881 }, 7882 7883 /* Pop-up the date picker in a "dialog" box. 7884 * @param input element - ignored 7885 * @param date string or Date - the initial date to display 7886 * @param onSelect function - the function to call when a date is selected 7887 * @param settings object - update the dialog date picker instance's settings (anonymous object) 7888 * @param pos int[2] - coordinates for the dialog's position within the screen or 7889 * event - with x/y coordinates or 7890 * leave empty for default (screen centre) 7891 * @return the manager object 7892 */ 7893 _dialogDatepicker: function(input, date, onSelect, settings, pos) { 7894 var id, browserWidth, browserHeight, scrollX, scrollY, 7895 inst = this._dialogInst; // internal instance 7896 7897 if (!inst) { 7898 this.uuid += 1; 7899 id = "dp" + this.uuid; 7900 this._dialogInput = $("<input type='text' id='" + id + 7901 "' style='position: absolute; top: -100px; width: 0px;'/>"); 7902 this._dialogInput.keydown(this._doKeyDown); 7903 $("body").append(this._dialogInput); 7904 inst = this._dialogInst = this._newInst(this._dialogInput, false); 7905 inst.settings = {}; 7906 $.data(this._dialogInput[0], PROP_NAME, inst); 7907 } 7908 extendRemove(inst.settings, settings || {}); 7909 date = (date && date.constructor === Date ? this._formatDate(inst, date) : date); 7910 this._dialogInput.val(date); 7911 7912 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); 7913 if (!this._pos) { 7914 browserWidth = document.documentElement.clientWidth; 7915 browserHeight = document.documentElement.clientHeight; 7916 scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; 7917 scrollY = document.documentElement.scrollTop || document.body.scrollTop; 7918 this._pos = // should use actual width/height below 7919 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; 7920 } 7921 7922 // move input on screen for focus, but hidden behind dialog 7923 this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px"); 7924 inst.settings.onSelect = onSelect; 7925 this._inDialog = true; 7926 this.dpDiv.addClass(this._dialogClass); 7927 this._showDatepicker(this._dialogInput[0]); 7928 if ($.blockUI) { 7929 $.blockUI(this.dpDiv); 7930 } 7931 $.data(this._dialogInput[0], PROP_NAME, inst); 7932 return this; 7933 }, 7934 7935 /* Detach a datepicker from its control. 7936 * @param target element - the target input field or division or span 7937 */ 7938 _destroyDatepicker: function(target) { 7939 var nodeName, 7940 $target = $(target), 7941 inst = $.data(target, PROP_NAME); 7942 7943 if (!$target.hasClass(this.markerClassName)) { 7944 return; 7945 } 7946 7947 nodeName = target.nodeName.toLowerCase(); 7948 $.removeData(target, PROP_NAME); 7949 if (nodeName === "input") { 7950 inst.append.remove(); 7951 inst.trigger.remove(); 7952 $target.removeClass(this.markerClassName). 7953 unbind("focus", this._showDatepicker). 7954 unbind("keydown", this._doKeyDown). 7955 unbind("keypress", this._doKeyPress). 7956 unbind("keyup", this._doKeyUp); 7957 } else if (nodeName === "div" || nodeName === "span") { 7958 $target.removeClass(this.markerClassName).empty(); 7959 } 7960 }, 7961 7962 /* Enable the date picker to a jQuery selection. 7963 * @param target element - the target input field or division or span 7964 */ 7965 _enableDatepicker: function(target) { 7966 var nodeName, inline, 7967 $target = $(target), 7968 inst = $.data(target, PROP_NAME); 7969 7970 if (!$target.hasClass(this.markerClassName)) { 7971 return; 7972 } 7973 7974 nodeName = target.nodeName.toLowerCase(); 7975 if (nodeName === "input") { 7976 target.disabled = false; 7977 inst.trigger.filter("button"). 7978 each(function() { this.disabled = false; }).end(). 7979 filter("img").css({opacity: "1.0", cursor: ""}); 7980 } else if (nodeName === "div" || nodeName === "span") { 7981 inline = $target.children("." + this._inlineClass); 7982 inline.children().removeClass("ui-state-disabled"); 7983 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 7984 prop("disabled", false); 7985 } 7986 this._disabledInputs = $.map(this._disabledInputs, 7987 function(value) { return (value === target ? null : value); }); // delete entry 7988 }, 7989 7990 /* Disable the date picker to a jQuery selection. 7991 * @param target element - the target input field or division or span 7992 */ 7993 _disableDatepicker: function(target) { 7994 var nodeName, inline, 7995 $target = $(target), 7996 inst = $.data(target, PROP_NAME); 7997 7998 if (!$target.hasClass(this.markerClassName)) { 7999 return; 8000 } 8001 8002 nodeName = target.nodeName.toLowerCase(); 8003 if (nodeName === "input") { 8004 target.disabled = true; 8005 inst.trigger.filter("button"). 8006 each(function() { this.disabled = true; }).end(). 8007 filter("img").css({opacity: "0.5", cursor: "default"}); 8008 } else if (nodeName === "div" || nodeName === "span") { 8009 inline = $target.children("." + this._inlineClass); 8010 inline.children().addClass("ui-state-disabled"); 8011 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 8012 prop("disabled", true); 8013 } 8014 this._disabledInputs = $.map(this._disabledInputs, 8015 function(value) { return (value === target ? null : value); }); // delete entry 8016 this._disabledInputs[this._disabledInputs.length] = target; 8017 }, 8018 8019 /* Is the first field in a jQuery collection disabled as a datepicker? 8020 * @param target element - the target input field or division or span 8021 * @return boolean - true if disabled, false if enabled 8022 */ 8023 _isDisabledDatepicker: function(target) { 8024 if (!target) { 8025 return false; 8026 } 8027 for (var i = 0; i < this._disabledInputs.length; i++) { 8028 if (this._disabledInputs[i] === target) { 8029 return true; 8030 } 8031 } 8032 return false; 8033 }, 8034 8035 /* Retrieve the instance data for the target control. 8036 * @param target element - the target input field or division or span 8037 * @return object - the associated instance data 8038 * @throws error if a jQuery problem getting data 8039 */ 8040 _getInst: function(target) { 8041 try { 8042 return $.data(target, PROP_NAME); 8043 } 8044 catch (err) { 8045 throw "Missing instance data for this datepicker"; 8046 } 8047 }, 8048 8049 /* Update or retrieve the settings for a date picker attached to an input field or division. 8050 * @param target element - the target input field or division or span 8051 * @param name object - the new settings to update or 8052 * string - the name of the setting to change or retrieve, 8053 * when retrieving also "all" for all instance settings or 8054 * "defaults" for all global defaults 8055 * @param value any - the new value for the setting 8056 * (omit if above is an object or to retrieve a value) 8057 */ 8058 _optionDatepicker: function(target, name, value) { 8059 var settings, date, minDate, maxDate, 8060 inst = this._getInst(target); 8061 8062 if (arguments.length === 2 && typeof name === "string") { 8063 return (name === "defaults" ? $.extend({}, $.datepicker._defaults) : 8064 (inst ? (name === "all" ? $.extend({}, inst.settings) : 8065 this._get(inst, name)) : null)); 8066 } 8067 8068 settings = name || {}; 8069 if (typeof name === "string") { 8070 settings = {}; 8071 settings[name] = value; 8072 } 8073 8074 if (inst) { 8075 if (this._curInst === inst) { 8076 this._hideDatepicker(); 8077 } 8078 8079 date = this._getDateDatepicker(target, true); 8080 minDate = this._getMinMaxDate(inst, "min"); 8081 maxDate = this._getMinMaxDate(inst, "max"); 8082 extendRemove(inst.settings, settings); 8083 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided 8084 if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) { 8085 inst.settings.minDate = this._formatDate(inst, minDate); 8086 } 8087 if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) { 8088 inst.settings.maxDate = this._formatDate(inst, maxDate); 8089 } 8090 if ( "disabled" in settings ) { 8091 if ( settings.disabled ) { 8092 this._disableDatepicker(target); 8093 } else { 8094 this._enableDatepicker(target); 8095 } 8096 } 8097 this._attachments($(target), inst); 8098 this._autoSize(inst); 8099 this._setDate(inst, date); 8100 this._updateAlternate(inst); 8101 this._updateDatepicker(inst); 8102 } 8103 }, 8104 8105 // change method deprecated 8106 _changeDatepicker: function(target, name, value) { 8107 this._optionDatepicker(target, name, value); 8108 }, 8109 8110 /* Redraw the date picker attached to an input field or division. 8111 * @param target element - the target input field or division or span 8112 */ 8113 _refreshDatepicker: function(target) { 8114 var inst = this._getInst(target); 8115 if (inst) { 8116 this._updateDatepicker(inst); 8117 } 8118 }, 8119 8120 /* Set the dates for a jQuery selection. 8121 * @param target element - the target input field or division or span 8122 * @param date Date - the new date 8123 */ 8124 _setDateDatepicker: function(target, date) { 8125 var inst = this._getInst(target); 8126 if (inst) { 8127 this._setDate(inst, date); 8128 this._updateDatepicker(inst); 8129 this._updateAlternate(inst); 8130 } 8131 }, 8132 8133 /* Get the date(s) for the first entry in a jQuery selection. 8134 * @param target element - the target input field or division or span 8135 * @param noDefault boolean - true if no default date is to be used 8136 * @return Date - the current date 8137 */ 8138 _getDateDatepicker: function(target, noDefault) { 8139 var inst = this._getInst(target); 8140 if (inst && !inst.inline) { 8141 this._setDateFromField(inst, noDefault); 8142 } 8143 return (inst ? this._getDate(inst) : null); 8144 }, 8145 8146 /* Handle keystrokes. */ 8147 _doKeyDown: function(event) { 8148 var onSelect, dateStr, sel, 8149 inst = $.datepicker._getInst(event.target), 8150 handled = true, 8151 isRTL = inst.dpDiv.is(".ui-datepicker-rtl"); 8152 8153 inst._keyEvent = true; 8154 if ($.datepicker._datepickerShowing) { 8155 switch (event.keyCode) { 8156 case 9: $.datepicker._hideDatepicker(); 8157 handled = false; 8158 break; // hide on tab out 8159 case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." + 8160 $.datepicker._currentClass + ")", inst.dpDiv); 8161 if (sel[0]) { 8162 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); 8163 } 8164 8165 onSelect = $.datepicker._get(inst, "onSelect"); 8166 if (onSelect) { 8167 dateStr = $.datepicker._formatDate(inst); 8168 8169 // trigger custom callback 8170 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); 8171 } else { 8172 $.datepicker._hideDatepicker(); 8173 } 8174 8175 return false; // don't submit the form 8176 case 27: $.datepicker._hideDatepicker(); 8177 break; // hide on escape 8178 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 8179 -$.datepicker._get(inst, "stepBigMonths") : 8180 -$.datepicker._get(inst, "stepMonths")), "M"); 8181 break; // previous month/year on page up/+ ctrl 8182 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 8183 +$.datepicker._get(inst, "stepBigMonths") : 8184 +$.datepicker._get(inst, "stepMonths")), "M"); 8185 break; // next month/year on page down/+ ctrl 8186 case 35: if (event.ctrlKey || event.metaKey) { 8187 $.datepicker._clearDate(event.target); 8188 } 8189 handled = event.ctrlKey || event.metaKey; 8190 break; // clear on ctrl or command +end 8191 case 36: if (event.ctrlKey || event.metaKey) { 8192 $.datepicker._gotoToday(event.target); 8193 } 8194 handled = event.ctrlKey || event.metaKey; 8195 break; // current on ctrl or command +home 8196 case 37: if (event.ctrlKey || event.metaKey) { 8197 $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D"); 8198 } 8199 handled = event.ctrlKey || event.metaKey; 8200 // -1 day on ctrl or command +left 8201 if (event.originalEvent.altKey) { 8202 $.datepicker._adjustDate(event.target, (event.ctrlKey ? 8203 -$.datepicker._get(inst, "stepBigMonths") : 8204 -$.datepicker._get(inst, "stepMonths")), "M"); 8205 } 8206 // next month/year on alt +left on Mac 8207 break; 8208 case 38: if (event.ctrlKey || event.metaKey) { 8209 $.datepicker._adjustDate(event.target, -7, "D"); 8210 } 8211 handled = event.ctrlKey || event.metaKey; 8212 break; // -1 week on ctrl or command +up 8213 case 39: if (event.ctrlKey || event.metaKey) { 8214 $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D"); 8215 } 8216 handled = event.ctrlKey || event.metaKey; 8217 // +1 day on ctrl or command +right 8218 if (event.originalEvent.altKey) { 8219 $.datepicker._adjustDate(event.target, (event.ctrlKey ? 8220 +$.datepicker._get(inst, "stepBigMonths") : 8221 +$.datepicker._get(inst, "stepMonths")), "M"); 8222 } 8223 // next month/year on alt +right 8224 break; 8225 case 40: if (event.ctrlKey || event.metaKey) { 8226 $.datepicker._adjustDate(event.target, +7, "D"); 8227 } 8228 handled = event.ctrlKey || event.metaKey; 8229 break; // +1 week on ctrl or command +down 8230 default: handled = false; 8231 } 8232 } else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home 8233 $.datepicker._showDatepicker(this); 8234 } else { 8235 handled = false; 8236 } 8237 8238 if (handled) { 8239 event.preventDefault(); 8240 event.stopPropagation(); 8241 } 8242 }, 8243 8244 /* Filter entered characters - based on date format. */ 8245 _doKeyPress: function(event) { 8246 var chars, chr, 8247 inst = $.datepicker._getInst(event.target); 8248 8249 if ($.datepicker._get(inst, "constrainInput")) { 8250 chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat")); 8251 chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode); 8252 return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1); 8253 } 8254 }, 8255 8256 /* Synchronise manual entry and field/alternate field. */ 8257 _doKeyUp: function(event) { 8258 var date, 8259 inst = $.datepicker._getInst(event.target); 8260 8261 if (inst.input.val() !== inst.lastVal) { 8262 try { 8263 date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), 8264 (inst.input ? inst.input.val() : null), 8265 $.datepicker._getFormatConfig(inst)); 8266 8267 if (date) { // only if valid 8268 $.datepicker._setDateFromField(inst); 8269 $.datepicker._updateAlternate(inst); 8270 $.datepicker._updateDatepicker(inst); 8271 } 8272 } 8273 catch (err) { 8274 } 8275 } 8276 return true; 8277 }, 8278 8279 /* Pop-up the date picker for a given input field. 8280 * If false returned from beforeShow event handler do not show. 8281 * @param input element - the input field attached to the date picker or 8282 * event - if triggered by focus 8283 */ 8284 _showDatepicker: function(input) { 8285 input = input.target || input; 8286 if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger 8287 input = $("input", input.parentNode)[0]; 8288 } 8289 8290 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here 8291 return; 8292 } 8293 8294 var inst, beforeShow, beforeShowSettings, isFixed, 8295 offset, showAnim, duration; 8296 8297 inst = $.datepicker._getInst(input); 8298 if ($.datepicker._curInst && $.datepicker._curInst !== inst) { 8299 $.datepicker._curInst.dpDiv.stop(true, true); 8300 if ( inst && $.datepicker._datepickerShowing ) { 8301 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] ); 8302 } 8303 } 8304 8305 beforeShow = $.datepicker._get(inst, "beforeShow"); 8306 beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; 8307 if(beforeShowSettings === false){ 8308 return; 8309 } 8310 extendRemove(inst.settings, beforeShowSettings); 8311 8312 inst.lastVal = null; 8313 $.datepicker._lastInput = input; 8314 $.datepicker._setDateFromField(inst); 8315 8316 if ($.datepicker._inDialog) { // hide cursor 8317 input.value = ""; 8318 } 8319 if (!$.datepicker._pos) { // position below input 8320 $.datepicker._pos = $.datepicker._findPos(input); 8321 $.datepicker._pos[1] += input.offsetHeight; // add the height 8322 } 8323 8324 isFixed = false; 8325 $(input).parents().each(function() { 8326 isFixed |= $(this).css("position") === "fixed"; 8327 return !isFixed; 8328 }); 8329 8330 offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; 8331 $.datepicker._pos = null; 8332 //to avoid flashes on Firefox 8333 inst.dpDiv.empty(); 8334 // determine sizing offscreen 8335 inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"}); 8336 $.datepicker._updateDatepicker(inst); 8337 // fix width for dynamic number of date pickers 8338 // and adjust position before showing 8339 offset = $.datepicker._checkOffset(inst, offset, isFixed); 8340 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? 8341 "static" : (isFixed ? "fixed" : "absolute")), display: "none", 8342 left: offset.left + "px", top: offset.top + "px"}); 8343 8344 if (!inst.inline) { 8345 showAnim = $.datepicker._get(inst, "showAnim"); 8346 duration = $.datepicker._get(inst, "duration"); 8347 inst.dpDiv.zIndex($(input).zIndex()+1); 8348 $.datepicker._datepickerShowing = true; 8349 8350 if ( $.effects && $.effects.effect[ showAnim ] ) { 8351 inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration); 8352 } else { 8353 inst.dpDiv[showAnim || "show"](showAnim ? duration : null); 8354 } 8355 8356 if ( $.datepicker._shouldFocusInput( inst ) ) { 8357 inst.input.focus(); 8358 } 8359 8360 $.datepicker._curInst = inst; 8361 } 8362 }, 8363 8364 /* Generate the date picker content. */ 8365 _updateDatepicker: function(inst) { 8366 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) 8367 instActive = inst; // for delegate hover events 8368 inst.dpDiv.empty().append(this._generateHTML(inst)); 8369 this._attachHandlers(inst); 8370 inst.dpDiv.find("." + this._dayOverClass + " a").mouseover(); 8371 8372 var origyearshtml, 8373 numMonths = this._getNumberOfMonths(inst), 8374 cols = numMonths[1], 8375 width = 17; 8376 8377 inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""); 8378 if (cols > 1) { 8379 inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em"); 8380 } 8381 inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") + 8382 "Class"]("ui-datepicker-multi"); 8383 inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") + 8384 "Class"]("ui-datepicker-rtl"); 8385 8386 if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) { 8387 inst.input.focus(); 8388 } 8389 8390 // deffered render of the years select (to avoid flashes on Firefox) 8391 if( inst.yearshtml ){ 8392 origyearshtml = inst.yearshtml; 8393 setTimeout(function(){ 8394 //assure that inst.yearshtml didn't change. 8395 if( origyearshtml === inst.yearshtml && inst.yearshtml ){ 8396 inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml); 8397 } 8398 origyearshtml = inst.yearshtml = null; 8399 }, 0); 8400 } 8401 }, 8402 8403 // #6694 - don't focus the input if it's already focused 8404 // this breaks the change event in IE 8405 // Support: IE and jQuery <1.9 8406 _shouldFocusInput: function( inst ) { 8407 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" ); 8408 }, 8409 8410 /* Check positioning to remain on screen. */ 8411 _checkOffset: function(inst, offset, isFixed) { 8412 var dpWidth = inst.dpDiv.outerWidth(), 8413 dpHeight = inst.dpDiv.outerHeight(), 8414 inputWidth = inst.input ? inst.input.outerWidth() : 0, 8415 inputHeight = inst.input ? inst.input.outerHeight() : 0, 8416 viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()), 8417 viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop()); 8418 8419 offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0); 8420 offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0; 8421 offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; 8422 8423 // now check if datepicker is showing outside window viewport - move to a better place if so. 8424 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? 8425 Math.abs(offset.left + dpWidth - viewWidth) : 0); 8426 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? 8427 Math.abs(dpHeight + inputHeight) : 0); 8428 8429 return offset; 8430 }, 8431 8432 /* Find an object's position on the screen. */ 8433 _findPos: function(obj) { 8434 var position, 8435 inst = this._getInst(obj), 8436 isRTL = this._get(inst, "isRTL"); 8437 8438 while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) { 8439 obj = obj[isRTL ? "previousSibling" : "nextSibling"]; 8440 } 8441 8442 position = $(obj).offset(); 8443 return [position.left, position.top]; 8444 }, 8445 8446 /* Hide the date picker from view. 8447 * @param input element - the input field attached to the date picker 8448 */ 8449 _hideDatepicker: function(input) { 8450 var showAnim, duration, postProcess, onClose, 8451 inst = this._curInst; 8452 8453 if (!inst || (input && inst !== $.data(input, PROP_NAME))) { 8454 return; 8455 } 8456 8457 if (this._datepickerShowing) { 8458 showAnim = this._get(inst, "showAnim"); 8459 duration = this._get(inst, "duration"); 8460 postProcess = function() { 8461 $.datepicker._tidyDialog(inst); 8462 }; 8463 8464 // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed 8465 if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) { 8466 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess); 8467 } else { 8468 inst.dpDiv[(showAnim === "slideDown" ? "slideUp" : 8469 (showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess); 8470 } 8471 8472 if (!showAnim) { 8473 postProcess(); 8474 } 8475 this._datepickerShowing = false; 8476 8477 onClose = this._get(inst, "onClose"); 8478 if (onClose) { 8479 onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]); 8480 } 8481 8482 this._lastInput = null; 8483 if (this._inDialog) { 8484 this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" }); 8485 if ($.blockUI) { 8486 $.unblockUI(); 8487 $("body").append(this.dpDiv); 8488 } 8489 } 8490 this._inDialog = false; 8491 } 8492 }, 8493 8494 /* Tidy up after a dialog display. */ 8495 _tidyDialog: function(inst) { 8496 inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar"); 8497 }, 8498 8499 /* Close date picker if clicked elsewhere. */ 8500 _checkExternalClick: function(event) { 8501 if (!$.datepicker._curInst) { 8502 return; 8503 } 8504 8505 var $target = $(event.target), 8506 inst = $.datepicker._getInst($target[0]); 8507 8508 if ( ( ( $target[0].id !== $.datepicker._mainDivId && 8509 $target.parents("#" + $.datepicker._mainDivId).length === 0 && 8510 !$target.hasClass($.datepicker.markerClassName) && 8511 !$target.closest("." + $.datepicker._triggerClass).length && 8512 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) || 8513 ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) { 8514 $.datepicker._hideDatepicker(); 8515 } 8516 }, 8517 8518 /* Adjust one of the date sub-fields. */ 8519 _adjustDate: function(id, offset, period) { 8520 var target = $(id), 8521 inst = this._getInst(target[0]); 8522 8523 if (this._isDisabledDatepicker(target[0])) { 8524 return; 8525 } 8526 this._adjustInstDate(inst, offset + 8527 (period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning 8528 period); 8529 this._updateDatepicker(inst); 8530 }, 8531 8532 /* Action for current link. */ 8533 _gotoToday: function(id) { 8534 var date, 8535 target = $(id), 8536 inst = this._getInst(target[0]); 8537 8538 if (this._get(inst, "gotoCurrent") && inst.currentDay) { 8539 inst.selectedDay = inst.currentDay; 8540 inst.drawMonth = inst.selectedMonth = inst.currentMonth; 8541 inst.drawYear = inst.selectedYear = inst.currentYear; 8542 } else { 8543 date = new Date(); 8544 inst.selectedDay = date.getDate(); 8545 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8546 inst.drawYear = inst.selectedYear = date.getFullYear(); 8547 } 8548 this._notifyChange(inst); 8549 this._adjustDate(target); 8550 }, 8551 8552 /* Action for selecting a new month/year. */ 8553 _selectMonthYear: function(id, select, period) { 8554 var target = $(id), 8555 inst = this._getInst(target[0]); 8556 8557 inst["selected" + (period === "M" ? "Month" : "Year")] = 8558 inst["draw" + (period === "M" ? "Month" : "Year")] = 8559 parseInt(select.options[select.selectedIndex].value,10); 8560 8561 this._notifyChange(inst); 8562 this._adjustDate(target); 8563 }, 8564 8565 /* Action for selecting a day. */ 8566 _selectDay: function(id, month, year, td) { 8567 var inst, 8568 target = $(id); 8569 8570 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { 8571 return; 8572 } 8573 8574 inst = this._getInst(target[0]); 8575 inst.selectedDay = inst.currentDay = $("a", td).html(); 8576 inst.selectedMonth = inst.currentMonth = month; 8577 inst.selectedYear = inst.currentYear = year; 8578 this._selectDate(id, this._formatDate(inst, 8579 inst.currentDay, inst.currentMonth, inst.currentYear)); 8580 }, 8581 8582 /* Erase the input field and hide the date picker. */ 8583 _clearDate: function(id) { 8584 var target = $(id); 8585 this._selectDate(target, ""); 8586 }, 8587 8588 /* Update the input field with the selected date. */ 8589 _selectDate: function(id, dateStr) { 8590 var onSelect, 8591 target = $(id), 8592 inst = this._getInst(target[0]); 8593 8594 dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); 8595 if (inst.input) { 8596 inst.input.val(dateStr); 8597 } 8598 this._updateAlternate(inst); 8599 8600 onSelect = this._get(inst, "onSelect"); 8601 if (onSelect) { 8602 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback 8603 } else if (inst.input) { 8604 inst.input.trigger("change"); // fire the change event 8605 } 8606 8607 if (inst.inline){ 8608 this._updateDatepicker(inst); 8609 } else { 8610 this._hideDatepicker(); 8611 this._lastInput = inst.input[0]; 8612 if (typeof(inst.input[0]) !== "object") { 8613 inst.input.focus(); // restore focus 8614 } 8615 this._lastInput = null; 8616 } 8617 }, 8618 8619 /* Update any alternate field to synchronise with the main field. */ 8620 _updateAlternate: function(inst) { 8621 var altFormat, date, dateStr, 8622 altField = this._get(inst, "altField"); 8623 8624 if (altField) { // update alternate field too 8625 altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat"); 8626 date = this._getDate(inst); 8627 dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); 8628 $(altField).each(function() { $(this).val(dateStr); }); 8629 } 8630 }, 8631 8632 /* Set as beforeShowDay function to prevent selection of weekends. 8633 * @param date Date - the date to customise 8634 * @return [boolean, string] - is this date selectable?, what is its CSS class? 8635 */ 8636 noWeekends: function(date) { 8637 var day = date.getDay(); 8638 return [(day > 0 && day < 6), ""]; 8639 }, 8640 8641 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. 8642 * @param date Date - the date to get the week for 8643 * @return number - the number of the week within the year that contains this date 8644 */ 8645 iso8601Week: function(date) { 8646 var time, 8647 checkDate = new Date(date.getTime()); 8648 8649 // Find Thursday of this week starting on Monday 8650 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); 8651 8652 time = checkDate.getTime(); 8653 checkDate.setMonth(0); // Compare with Jan 1 8654 checkDate.setDate(1); 8655 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; 8656 }, 8657 8658 /* Parse a string value into a date object. 8659 * See formatDate below for the possible formats. 8660 * 8661 * @param format string - the expected format of the date 8662 * @param value string - the date in the above format 8663 * @param settings Object - attributes include: 8664 * shortYearCutoff number - the cutoff year for determining the century (optional) 8665 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 8666 * dayNames string[7] - names of the days from Sunday (optional) 8667 * monthNamesShort string[12] - abbreviated names of the months (optional) 8668 * monthNames string[12] - names of the months (optional) 8669 * @return Date - the extracted date value or null if value is blank 8670 */ 8671 parseDate: function (format, value, settings) { 8672 if (format == null || value == null) { 8673 throw "Invalid arguments"; 8674 } 8675 8676 value = (typeof value === "object" ? value.toString() : value + ""); 8677 if (value === "") { 8678 return null; 8679 } 8680 8681 var iFormat, dim, extra, 8682 iValue = 0, 8683 shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff, 8684 shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp : 8685 new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)), 8686 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, 8687 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, 8688 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, 8689 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, 8690 year = -1, 8691 month = -1, 8692 day = -1, 8693 doy = -1, 8694 literal = false, 8695 date, 8696 // Check whether a format character is doubled 8697 lookAhead = function(match) { 8698 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 8699 if (matches) { 8700 iFormat++; 8701 } 8702 return matches; 8703 }, 8704 // Extract a number from the string value 8705 getNumber = function(match) { 8706 var isDoubled = lookAhead(match), 8707 size = (match === "@" ? 14 : (match === "!" ? 20 : 8708 (match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))), 8709 digits = new RegExp("^\\d{1," + size + "}"), 8710 num = value.substring(iValue).match(digits); 8711 if (!num) { 8712 throw "Missing number at position " + iValue; 8713 } 8714 iValue += num[0].length; 8715 return parseInt(num[0], 10); 8716 }, 8717 // Extract a name from the string value and convert to an index 8718 getName = function(match, shortNames, longNames) { 8719 var index = -1, 8720 names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { 8721 return [ [k, v] ]; 8722 }).sort(function (a, b) { 8723 return -(a[1].length - b[1].length); 8724 }); 8725 8726 $.each(names, function (i, pair) { 8727 var name = pair[1]; 8728 if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) { 8729 index = pair[0]; 8730 iValue += name.length; 8731 return false; 8732 } 8733 }); 8734 if (index !== -1) { 8735 return index + 1; 8736 } else { 8737 throw "Unknown name at position " + iValue; 8738 } 8739 }, 8740 // Confirm that a literal character matches the string value 8741 checkLiteral = function() { 8742 if (value.charAt(iValue) !== format.charAt(iFormat)) { 8743 throw "Unexpected literal at position " + iValue; 8744 } 8745 iValue++; 8746 }; 8747 8748 for (iFormat = 0; iFormat < format.length; iFormat++) { 8749 if (literal) { 8750 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 8751 literal = false; 8752 } else { 8753 checkLiteral(); 8754 } 8755 } else { 8756 switch (format.charAt(iFormat)) { 8757 case "d": 8758 day = getNumber("d"); 8759 break; 8760 case "D": 8761 getName("D", dayNamesShort, dayNames); 8762 break; 8763 case "o": 8764 doy = getNumber("o"); 8765 break; 8766 case "m": 8767 month = getNumber("m"); 8768 break; 8769 case "M": 8770 month = getName("M", monthNamesShort, monthNames); 8771 break; 8772 case "y": 8773 year = getNumber("y"); 8774 break; 8775 case "@": 8776 date = new Date(getNumber("@")); 8777 year = date.getFullYear(); 8778 month = date.getMonth() + 1; 8779 day = date.getDate(); 8780 break; 8781 case "!": 8782 date = new Date((getNumber("!") - this._ticksTo1970) / 10000); 8783 year = date.getFullYear(); 8784 month = date.getMonth() + 1; 8785 day = date.getDate(); 8786 break; 8787 case "'": 8788 if (lookAhead("'")){ 8789 checkLiteral(); 8790 } else { 8791 literal = true; 8792 } 8793 break; 8794 default: 8795 checkLiteral(); 8796 } 8797 } 8798 } 8799 8800 if (iValue < value.length){ 8801 extra = value.substr(iValue); 8802 if (!/^\s+/.test(extra)) { 8803 throw "Extra/unparsed characters found in date: " + extra; 8804 } 8805 } 8806 8807 if (year === -1) { 8808 year = new Date().getFullYear(); 8809 } else if (year < 100) { 8810 year += new Date().getFullYear() - new Date().getFullYear() % 100 + 8811 (year <= shortYearCutoff ? 0 : -100); 8812 } 8813 8814 if (doy > -1) { 8815 month = 1; 8816 day = doy; 8817 do { 8818 dim = this._getDaysInMonth(year, month - 1); 8819 if (day <= dim) { 8820 break; 8821 } 8822 month++; 8823 day -= dim; 8824 } while (true); 8825 } 8826 8827 date = this._daylightSavingAdjust(new Date(year, month - 1, day)); 8828 if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) { 8829 throw "Invalid date"; // E.g. 31/02/00 8830 } 8831 return date; 8832 }, 8833 8834 /* Standard date formats. */ 8835 ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601) 8836 COOKIE: "D, dd M yy", 8837 ISO_8601: "yy-mm-dd", 8838 RFC_822: "D, d M y", 8839 RFC_850: "DD, dd-M-y", 8840 RFC_1036: "D, d M y", 8841 RFC_1123: "D, d M yy", 8842 RFC_2822: "D, d M yy", 8843 RSS: "D, d M y", // RFC 822 8844 TICKS: "!", 8845 TIMESTAMP: "@", 8846 W3C: "yy-mm-dd", // ISO 8601 8847 8848 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + 8849 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), 8850 8851 /* Format a date object into a string value. 8852 * The format can be combinations of the following: 8853 * d - day of month (no leading zero) 8854 * dd - day of month (two digit) 8855 * o - day of year (no leading zeros) 8856 * oo - day of year (three digit) 8857 * D - day name short 8858 * DD - day name long 8859 * m - month of year (no leading zero) 8860 * mm - month of year (two digit) 8861 * M - month name short 8862 * MM - month name long 8863 * y - year (two digit) 8864 * yy - year (four digit) 8865 * @ - Unix timestamp (ms since 01/01/1970) 8866 * ! - Windows ticks (100ns since 01/01/0001) 8867 * "..." - literal text 8868 * '' - single quote 8869 * 8870 * @param format string - the desired format of the date 8871 * @param date Date - the date value to format 8872 * @param settings Object - attributes include: 8873 * dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 8874 * dayNames string[7] - names of the days from Sunday (optional) 8875 * monthNamesShort string[12] - abbreviated names of the months (optional) 8876 * monthNames string[12] - names of the months (optional) 8877 * @return string - the date in the above format 8878 */ 8879 formatDate: function (format, date, settings) { 8880 if (!date) { 8881 return ""; 8882 } 8883 8884 var iFormat, 8885 dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, 8886 dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, 8887 monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, 8888 monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, 8889 // Check whether a format character is doubled 8890 lookAhead = function(match) { 8891 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 8892 if (matches) { 8893 iFormat++; 8894 } 8895 return matches; 8896 }, 8897 // Format a number, with leading zero if necessary 8898 formatNumber = function(match, value, len) { 8899 var num = "" + value; 8900 if (lookAhead(match)) { 8901 while (num.length < len) { 8902 num = "0" + num; 8903 } 8904 } 8905 return num; 8906 }, 8907 // Format a name, short or long as requested 8908 formatName = function(match, value, shortNames, longNames) { 8909 return (lookAhead(match) ? longNames[value] : shortNames[value]); 8910 }, 8911 output = "", 8912 literal = false; 8913 8914 if (date) { 8915 for (iFormat = 0; iFormat < format.length; iFormat++) { 8916 if (literal) { 8917 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 8918 literal = false; 8919 } else { 8920 output += format.charAt(iFormat); 8921 } 8922 } else { 8923 switch (format.charAt(iFormat)) { 8924 case "d": 8925 output += formatNumber("d", date.getDate(), 2); 8926 break; 8927 case "D": 8928 output += formatName("D", date.getDay(), dayNamesShort, dayNames); 8929 break; 8930 case "o": 8931 output += formatNumber("o", 8932 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); 8933 break; 8934 case "m": 8935 output += formatNumber("m", date.getMonth() + 1, 2); 8936 break; 8937 case "M": 8938 output += formatName("M", date.getMonth(), monthNamesShort, monthNames); 8939 break; 8940 case "y": 8941 output += (lookAhead("y") ? date.getFullYear() : 8942 (date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100); 8943 break; 8944 case "@": 8945 output += date.getTime(); 8946 break; 8947 case "!": 8948 output += date.getTime() * 10000 + this._ticksTo1970; 8949 break; 8950 case "'": 8951 if (lookAhead("'")) { 8952 output += "'"; 8953 } else { 8954 literal = true; 8955 } 8956 break; 8957 default: 8958 output += format.charAt(iFormat); 8959 } 8960 } 8961 } 8962 } 8963 return output; 8964 }, 8965 8966 /* Extract all possible characters from the date format. */ 8967 _possibleChars: function (format) { 8968 var iFormat, 8969 chars = "", 8970 literal = false, 8971 // Check whether a format character is doubled 8972 lookAhead = function(match) { 8973 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match); 8974 if (matches) { 8975 iFormat++; 8976 } 8977 return matches; 8978 }; 8979 8980 for (iFormat = 0; iFormat < format.length; iFormat++) { 8981 if (literal) { 8982 if (format.charAt(iFormat) === "'" && !lookAhead("'")) { 8983 literal = false; 8984 } else { 8985 chars += format.charAt(iFormat); 8986 } 8987 } else { 8988 switch (format.charAt(iFormat)) { 8989 case "d": case "m": case "y": case "@": 8990 chars += "0123456789"; 8991 break; 8992 case "D": case "M": 8993 return null; // Accept anything 8994 case "'": 8995 if (lookAhead("'")) { 8996 chars += "'"; 8997 } else { 8998 literal = true; 8999 } 9000 break; 9001 default: 9002 chars += format.charAt(iFormat); 9003 } 9004 } 9005 } 9006 return chars; 9007 }, 9008 9009 /* Get a setting value, defaulting if necessary. */ 9010 _get: function(inst, name) { 9011 return inst.settings[name] !== undefined ? 9012 inst.settings[name] : this._defaults[name]; 9013 }, 9014 9015 /* Parse existing date and initialise date picker. */ 9016 _setDateFromField: function(inst, noDefault) { 9017 if (inst.input.val() === inst.lastVal) { 9018 return; 9019 } 9020 9021 var dateFormat = this._get(inst, "dateFormat"), 9022 dates = inst.lastVal = inst.input ? inst.input.val() : null, 9023 defaultDate = this._getDefaultDate(inst), 9024 date = defaultDate, 9025 settings = this._getFormatConfig(inst); 9026 9027 try { 9028 date = this.parseDate(dateFormat, dates, settings) || defaultDate; 9029 } catch (event) { 9030 dates = (noDefault ? "" : dates); 9031 } 9032 inst.selectedDay = date.getDate(); 9033 inst.drawMonth = inst.selectedMonth = date.getMonth(); 9034 inst.drawYear = inst.selectedYear = date.getFullYear(); 9035 inst.currentDay = (dates ? date.getDate() : 0); 9036 inst.currentMonth = (dates ? date.getMonth() : 0); 9037 inst.currentYear = (dates ? date.getFullYear() : 0); 9038 this._adjustInstDate(inst); 9039 }, 9040 9041 /* Retrieve the default date shown on opening. */ 9042 _getDefaultDate: function(inst) { 9043 return this._restrictMinMax(inst, 9044 this._determineDate(inst, this._get(inst, "defaultDate"), new Date())); 9045 }, 9046 9047 /* A date may be specified as an exact value or a relative one. */ 9048 _determineDate: function(inst, date, defaultDate) { 9049 var offsetNumeric = function(offset) { 9050 var date = new Date(); 9051 date.setDate(date.getDate() + offset); 9052 return date; 9053 }, 9054 offsetString = function(offset) { 9055 try { 9056 return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), 9057 offset, $.datepicker._getFormatConfig(inst)); 9058 } 9059 catch (e) { 9060 // Ignore 9061 } 9062 9063 var date = (offset.toLowerCase().match(/^c/) ? 9064 $.datepicker._getDate(inst) : null) || new Date(), 9065 year = date.getFullYear(), 9066 month = date.getMonth(), 9067 day = date.getDate(), 9068 pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, 9069 matches = pattern.exec(offset); 9070 9071 while (matches) { 9072 switch (matches[2] || "d") { 9073 case "d" : case "D" : 9074 day += parseInt(matches[1],10); break; 9075 case "w" : case "W" : 9076 day += parseInt(matches[1],10) * 7; break; 9077 case "m" : case "M" : 9078 month += parseInt(matches[1],10); 9079 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 9080 break; 9081 case "y": case "Y" : 9082 year += parseInt(matches[1],10); 9083 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 9084 break; 9085 } 9086 matches = pattern.exec(offset); 9087 } 9088 return new Date(year, month, day); 9089 }, 9090 newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) : 9091 (typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); 9092 9093 newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate); 9094 if (newDate) { 9095 newDate.setHours(0); 9096 newDate.setMinutes(0); 9097 newDate.setSeconds(0); 9098 newDate.setMilliseconds(0); 9099 } 9100 return this._daylightSavingAdjust(newDate); 9101 }, 9102 9103 /* Handle switch to/from daylight saving. 9104 * Hours may be non-zero on daylight saving cut-over: 9105 * > 12 when midnight changeover, but then cannot generate 9106 * midnight datetime, so jump to 1AM, otherwise reset. 9107 * @param date (Date) the date to check 9108 * @return (Date) the corrected date 9109 */ 9110 _daylightSavingAdjust: function(date) { 9111 if (!date) { 9112 return null; 9113 } 9114 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); 9115 return date; 9116 }, 9117 9118 /* Set the date(s) directly. */ 9119 _setDate: function(inst, date, noChange) { 9120 var clear = !date, 9121 origMonth = inst.selectedMonth, 9122 origYear = inst.selectedYear, 9123 newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); 9124 9125 inst.selectedDay = inst.currentDay = newDate.getDate(); 9126 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); 9127 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); 9128 if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) { 9129 this._notifyChange(inst); 9130 } 9131 this._adjustInstDate(inst); 9132 if (inst.input) { 9133 inst.input.val(clear ? "" : this._formatDate(inst)); 9134 } 9135 }, 9136 9137 /* Retrieve the date(s) directly. */ 9138 _getDate: function(inst) { 9139 var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null : 9140 this._daylightSavingAdjust(new Date( 9141 inst.currentYear, inst.currentMonth, inst.currentDay))); 9142 return startDate; 9143 }, 9144 9145 /* Attach the onxxx handlers. These are declared statically so 9146 * they work with static code transformers like Caja. 9147 */ 9148 _attachHandlers: function(inst) { 9149 var stepMonths = this._get(inst, "stepMonths"), 9150 id = "#" + inst.id.replace( /\\\\/g, "\\" ); 9151 inst.dpDiv.find("[data-handler]").map(function () { 9152 var handler = { 9153 prev: function () { 9154 $.datepicker._adjustDate(id, -stepMonths, "M"); 9155 }, 9156 next: function () { 9157 $.datepicker._adjustDate(id, +stepMonths, "M"); 9158 }, 9159 hide: function () { 9160 $.datepicker._hideDatepicker(); 9161 }, 9162 today: function () { 9163 $.datepicker._gotoToday(id); 9164 }, 9165 selectDay: function () { 9166 $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this); 9167 return false; 9168 }, 9169 selectMonth: function () { 9170 $.datepicker._selectMonthYear(id, this, "M"); 9171 return false; 9172 }, 9173 selectYear: function () { 9174 $.datepicker._selectMonthYear(id, this, "Y"); 9175 return false; 9176 } 9177 }; 9178 $(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]); 9179 }); 9180 }, 9181 9182 /* Generate the HTML for the current state of the date picker. */ 9183 _generateHTML: function(inst) { 9184 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate, 9185 controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin, 9186 monthNames, monthNamesShort, beforeShowDay, showOtherMonths, 9187 selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate, 9188 cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows, 9189 printDate, dRow, tbody, daySettings, otherMonth, unselectable, 9190 tempDate = new Date(), 9191 today = this._daylightSavingAdjust( 9192 new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time 9193 isRTL = this._get(inst, "isRTL"), 9194 showButtonPanel = this._get(inst, "showButtonPanel"), 9195 hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"), 9196 navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"), 9197 numMonths = this._getNumberOfMonths(inst), 9198 showCurrentAtPos = this._get(inst, "showCurrentAtPos"), 9199 stepMonths = this._get(inst, "stepMonths"), 9200 isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1), 9201 currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : 9202 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))), 9203 minDate = this._getMinMaxDate(inst, "min"), 9204 maxDate = this._getMinMaxDate(inst, "max"), 9205 drawMonth = inst.drawMonth - showCurrentAtPos, 9206 drawYear = inst.drawYear; 9207 9208 if (drawMonth < 0) { 9209 drawMonth += 12; 9210 drawYear--; 9211 } 9212 if (maxDate) { 9213 maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), 9214 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); 9215 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); 9216 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { 9217 drawMonth--; 9218 if (drawMonth < 0) { 9219 drawMonth = 11; 9220 drawYear--; 9221 } 9222 } 9223 } 9224 inst.drawMonth = drawMonth; 9225 inst.drawYear = drawYear; 9226 9227 prevText = this._get(inst, "prevText"); 9228 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, 9229 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), 9230 this._getFormatConfig(inst))); 9231 9232 prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? 9233 "<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" + 9234 " title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" : 9235 (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>")); 9236 9237 nextText = this._get(inst, "nextText"); 9238 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, 9239 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), 9240 this._getFormatConfig(inst))); 9241 9242 next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? 9243 "<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" + 9244 " title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" : 9245 (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>")); 9246 9247 currentText = this._get(inst, "currentText"); 9248 gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today); 9249 currentText = (!navigationAsDateFormat ? currentText : 9250 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); 9251 9252 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'>" + 9253 this._get(inst, "closeText") + "</button>" : ""); 9254 9255 buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") + 9256 (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'" + 9257 ">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : ""; 9258 9259 firstDay = parseInt(this._get(inst, "firstDay"),10); 9260 firstDay = (isNaN(firstDay) ? 0 : firstDay); 9261 9262 showWeek = this._get(inst, "showWeek"); 9263 dayNames = this._get(inst, "dayNames"); 9264 dayNamesMin = this._get(inst, "dayNamesMin"); 9265 monthNames = this._get(inst, "monthNames"); 9266 monthNamesShort = this._get(inst, "monthNamesShort"); 9267 beforeShowDay = this._get(inst, "beforeShowDay"); 9268 showOtherMonths = this._get(inst, "showOtherMonths"); 9269 selectOtherMonths = this._get(inst, "selectOtherMonths"); 9270 defaultDate = this._getDefaultDate(inst); 9271 html = ""; 9272 dow; 9273 for (row = 0; row < numMonths[0]; row++) { 9274 group = ""; 9275 this.maxRows = 4; 9276 for (col = 0; col < numMonths[1]; col++) { 9277 selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); 9278 cornerClass = " ui-corner-all"; 9279 calender = ""; 9280 if (isMultiMonth) { 9281 calender += "<div class='ui-datepicker-group"; 9282 if (numMonths[1] > 1) { 9283 switch (col) { 9284 case 0: calender += " ui-datepicker-group-first"; 9285 cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break; 9286 case numMonths[1]-1: calender += " ui-datepicker-group-last"; 9287 cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break; 9288 default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break; 9289 } 9290 } 9291 calender += "'>"; 9292 } 9293 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" + 9294 (/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") + 9295 (/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") + 9296 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, 9297 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers 9298 "</div><table class='ui-datepicker-calendar'><thead>" + 9299 "<tr>"; 9300 thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : ""); 9301 for (dow = 0; dow < 7; dow++) { // days of the week 9302 day = (dow + firstDay) % 7; 9303 thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" + 9304 "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>"; 9305 } 9306 calender += thead + "</tr></thead><tbody>"; 9307 daysInMonth = this._getDaysInMonth(drawYear, drawMonth); 9308 if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) { 9309 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); 9310 } 9311 leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; 9312 curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate 9313 numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) 9314 this.maxRows = numRows; 9315 printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); 9316 for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows 9317 calender += "<tr>"; 9318 tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" + 9319 this._get(inst, "calculateWeek")(printDate) + "</td>"); 9320 for (dow = 0; dow < 7; dow++) { // create date picker days 9321 daySettings = (beforeShowDay ? 9322 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]); 9323 otherMonth = (printDate.getMonth() !== drawMonth); 9324 unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || 9325 (minDate && printDate < minDate) || (maxDate && printDate > maxDate); 9326 tbody += "<td class='" + 9327 ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends 9328 (otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months 9329 ((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key 9330 (defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ? 9331 // or defaultDate is current printedDate and defaultDate is selectedDate 9332 " " + this._dayOverClass : "") + // highlight selected day 9333 (unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") + // highlight unselectable days 9334 (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates 9335 (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day 9336 (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different) 9337 ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "'") + "'" : "") + // cell title 9338 (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions 9339 (otherMonth && !showOtherMonths ? " " : // display for other months 9340 (unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" + 9341 (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") + 9342 (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day 9343 (otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months 9344 "' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date 9345 printDate.setDate(printDate.getDate() + 1); 9346 printDate = this._daylightSavingAdjust(printDate); 9347 } 9348 calender += tbody + "</tr>"; 9349 } 9350 drawMonth++; 9351 if (drawMonth > 11) { 9352 drawMonth = 0; 9353 drawYear++; 9354 } 9355 calender += "</tbody></table>" + (isMultiMonth ? "</div>" + 9356 ((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : ""); 9357 group += calender; 9358 } 9359 html += group; 9360 } 9361 html += buttonPanel; 9362 inst._keyEvent = false; 9363 return html; 9364 }, 9365 9366 /* Generate the month and year header. */ 9367 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, 9368 secondary, monthNames, monthNamesShort) { 9369 9370 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear, 9371 changeMonth = this._get(inst, "changeMonth"), 9372 changeYear = this._get(inst, "changeYear"), 9373 showMonthAfterYear = this._get(inst, "showMonthAfterYear"), 9374 html = "<div class='ui-datepicker-title'>", 9375 monthHtml = ""; 9376 9377 // month selection 9378 if (secondary || !changeMonth) { 9379 monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>"; 9380 } else { 9381 inMinYear = (minDate && minDate.getFullYear() === drawYear); 9382 inMaxYear = (maxDate && maxDate.getFullYear() === drawYear); 9383 monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>"; 9384 for ( month = 0; month < 12; month++) { 9385 if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) { 9386 monthHtml += "<option value='" + month + "'" + 9387 (month === drawMonth ? " selected='selected'" : "") + 9388 ">" + monthNamesShort[month] + "</option>"; 9389 } 9390 } 9391 monthHtml += "</select>"; 9392 } 9393 9394 if (!showMonthAfterYear) { 9395 html += monthHtml + (secondary || !(changeMonth && changeYear) ? " " : ""); 9396 } 9397 9398 // year selection 9399 if ( !inst.yearshtml ) { 9400 inst.yearshtml = ""; 9401 if (secondary || !changeYear) { 9402 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>"; 9403 } else { 9404 // determine range of years to display 9405 years = this._get(inst, "yearRange").split(":"); 9406 thisYear = new Date().getFullYear(); 9407 determineYear = function(value) { 9408 var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) : 9409 (value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) : 9410 parseInt(value, 10))); 9411 return (isNaN(year) ? thisYear : year); 9412 }; 9413 year = determineYear(years[0]); 9414 endYear = Math.max(year, determineYear(years[1] || "")); 9415 year = (minDate ? Math.max(year, minDate.getFullYear()) : year); 9416 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); 9417 inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>"; 9418 for (; year <= endYear; year++) { 9419 inst.yearshtml += "<option value='" + year + "'" + 9420 (year === drawYear ? " selected='selected'" : "") + 9421 ">" + year + "</option>"; 9422 } 9423 inst.yearshtml += "</select>"; 9424 9425 html += inst.yearshtml; 9426 inst.yearshtml = null; 9427 } 9428 } 9429 9430 html += this._get(inst, "yearSuffix"); 9431 if (showMonthAfterYear) { 9432 html += (secondary || !(changeMonth && changeYear) ? " " : "") + monthHtml; 9433 } 9434 html += "</div>"; // Close datepicker_header 9435 return html; 9436 }, 9437 9438 /* Adjust one of the date sub-fields. */ 9439 _adjustInstDate: function(inst, offset, period) { 9440 var year = inst.drawYear + (period === "Y" ? offset : 0), 9441 month = inst.drawMonth + (period === "M" ? offset : 0), 9442 day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0), 9443 date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day))); 9444 9445 inst.selectedDay = date.getDate(); 9446 inst.drawMonth = inst.selectedMonth = date.getMonth(); 9447 inst.drawYear = inst.selectedYear = date.getFullYear(); 9448 if (period === "M" || period === "Y") { 9449 this._notifyChange(inst); 9450 } 9451 }, 9452 9453 /* Ensure a date is within any min/max bounds. */ 9454 _restrictMinMax: function(inst, date) { 9455 var minDate = this._getMinMaxDate(inst, "min"), 9456 maxDate = this._getMinMaxDate(inst, "max"), 9457 newDate = (minDate && date < minDate ? minDate : date); 9458 return (maxDate && newDate > maxDate ? maxDate : newDate); 9459 }, 9460 9461 /* Notify change of month/year. */ 9462 _notifyChange: function(inst) { 9463 var onChange = this._get(inst, "onChangeMonthYear"); 9464 if (onChange) { 9465 onChange.apply((inst.input ? inst.input[0] : null), 9466 [inst.selectedYear, inst.selectedMonth + 1, inst]); 9467 } 9468 }, 9469 9470 /* Determine the number of months to show. */ 9471 _getNumberOfMonths: function(inst) { 9472 var numMonths = this._get(inst, "numberOfMonths"); 9473 return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths)); 9474 }, 9475 9476 /* Determine the current maximum date - ensure no time components are set. */ 9477 _getMinMaxDate: function(inst, minMax) { 9478 return this._determineDate(inst, this._get(inst, minMax + "Date"), null); 9479 }, 9480 9481 /* Find the number of days in a given month. */ 9482 _getDaysInMonth: function(year, month) { 9483 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); 9484 }, 9485 9486 /* Find the day of the week of the first of a month. */ 9487 _getFirstDayOfMonth: function(year, month) { 9488 return new Date(year, month, 1).getDay(); 9489 }, 9490 9491 /* Determines if we should allow a "next/prev" month display change. */ 9492 _canAdjustMonth: function(inst, offset, curYear, curMonth) { 9493 var numMonths = this._getNumberOfMonths(inst), 9494 date = this._daylightSavingAdjust(new Date(curYear, 9495 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); 9496 9497 if (offset < 0) { 9498 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); 9499 } 9500 return this._isInRange(inst, date); 9501 }, 9502 9503 /* Is the given date in the accepted range? */ 9504 _isInRange: function(inst, date) { 9505 var yearSplit, currentYear, 9506 minDate = this._getMinMaxDate(inst, "min"), 9507 maxDate = this._getMinMaxDate(inst, "max"), 9508 minYear = null, 9509 maxYear = null, 9510 years = this._get(inst, "yearRange"); 9511 if (years){ 9512 yearSplit = years.split(":"); 9513 currentYear = new Date().getFullYear(); 9514 minYear = parseInt(yearSplit[0], 10); 9515 maxYear = parseInt(yearSplit[1], 10); 9516 if ( yearSplit[0].match(/[+\-].*/) ) { 9517 minYear += currentYear; 9518 } 9519 if ( yearSplit[1].match(/[+\-].*/) ) { 9520 maxYear += currentYear; 9521 } 9522 } 9523 9524 return ((!minDate || date.getTime() >= minDate.getTime()) && 9525 (!maxDate || date.getTime() <= maxDate.getTime()) && 9526 (!minYear || date.getFullYear() >= minYear) && 9527 (!maxYear || date.getFullYear() <= maxYear)); 9528 }, 9529 9530 /* Provide the configuration settings for formatting/parsing. */ 9531 _getFormatConfig: function(inst) { 9532 var shortYearCutoff = this._get(inst, "shortYearCutoff"); 9533 shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff : 9534 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); 9535 return {shortYearCutoff: shortYearCutoff, 9536 dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"), 9537 monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")}; 9538 }, 9539 9540 /* Format the given date for display. */ 9541 _formatDate: function(inst, day, month, year) { 9542 if (!day) { 9543 inst.currentDay = inst.selectedDay; 9544 inst.currentMonth = inst.selectedMonth; 9545 inst.currentYear = inst.selectedYear; 9546 } 9547 var date = (day ? (typeof day === "object" ? day : 9548 this._daylightSavingAdjust(new Date(year, month, day))) : 9549 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); 9550 return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst)); 9551 } 9552}); 9553 9554/* 9555 * Bind hover events for datepicker elements. 9556 * Done via delegate so the binding only occurs once in the lifetime of the parent div. 9557 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. 9558 */ 9559function bindHover(dpDiv) { 9560 var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a"; 9561 return dpDiv.delegate(selector, "mouseout", function() { 9562 $(this).removeClass("ui-state-hover"); 9563 if (this.className.indexOf("ui-datepicker-prev") !== -1) { 9564 $(this).removeClass("ui-datepicker-prev-hover"); 9565 } 9566 if (this.className.indexOf("ui-datepicker-next") !== -1) { 9567 $(this).removeClass("ui-datepicker-next-hover"); 9568 } 9569 }) 9570 .delegate(selector, "mouseover", function(){ 9571 if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) { 9572 $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); 9573 $(this).addClass("ui-state-hover"); 9574 if (this.className.indexOf("ui-datepicker-prev") !== -1) { 9575 $(this).addClass("ui-datepicker-prev-hover"); 9576 } 9577 if (this.className.indexOf("ui-datepicker-next") !== -1) { 9578 $(this).addClass("ui-datepicker-next-hover"); 9579 } 9580 } 9581 }); 9582} 9583 9584/* jQuery extend now ignores nulls! */ 9585function extendRemove(target, props) { 9586 $.extend(target, props); 9587 for (var name in props) { 9588 if (props[name] == null) { 9589 target[name] = props[name]; 9590 } 9591 } 9592 return target; 9593} 9594 9595/* Invoke the datepicker functionality. 9596 @param options string - a command, optionally followed by additional parameters or 9597 Object - settings for attaching new datepicker functionality 9598 @return jQuery object */ 9599$.fn.datepicker = function(options){ 9600 9601 /* Verify an empty collection wasn't passed - Fixes #6976 */ 9602 if ( !this.length ) { 9603 return this; 9604 } 9605 9606 /* Initialise the date picker. */ 9607 if (!$.datepicker.initialized) { 9608 $(document).mousedown($.datepicker._checkExternalClick); 9609 $.datepicker.initialized = true; 9610 } 9611 9612 /* Append datepicker main container to body if not exist. */ 9613 if ($("#"+$.datepicker._mainDivId).length === 0) { 9614 $("body").append($.datepicker.dpDiv); 9615 } 9616 9617 var otherArgs = Array.prototype.slice.call(arguments, 1); 9618 if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) { 9619 return $.datepicker["_" + options + "Datepicker"]. 9620 apply($.datepicker, [this[0]].concat(otherArgs)); 9621 } 9622 if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") { 9623 return $.datepicker["_" + options + "Datepicker"]. 9624 apply($.datepicker, [this[0]].concat(otherArgs)); 9625 } 9626 return this.each(function() { 9627 typeof options === "string" ? 9628 $.datepicker["_" + options + "Datepicker"]. 9629 apply($.datepicker, [this].concat(otherArgs)) : 9630 $.datepicker._attachDatepicker(this, options); 9631 }); 9632}; 9633 9634$.datepicker = new Datepicker(); // singleton instance 9635$.datepicker.initialized = false; 9636$.datepicker.uuid = new Date().getTime(); 9637$.datepicker.version = "1.10.
vendor: 18,168 bytes, lines 9637-10365
96374"; 9638 9639})(jQuery); 9640 9641(function( $, undefined ) { 9642 9643var sizeRelatedOptions = { 9644 buttons: true, 9645 height: true, 9646 maxHeight: true, 9647 maxWidth: true, 9648 minHeight: true, 9649 minWidth: true, 9650 width: true 9651 }, 9652 resizableRelatedOptions = { 9653 maxHeight: true, 9654 maxWidth: true, 9655 minHeight: true, 9656 minWidth: true 9657 }; 9658 9659$.widget( "ui.dialog", { 9660 version: "1.10.4", 9661 options: { 9662 appendTo: "body", 9663 autoOpen: true, 9664 buttons: [], 9665 closeOnEscape: true, 9666 closeText: "close", 9667 dialogClass: "", 9668 draggable: true, 9669 hide: null, 9670 height: "auto", 9671 maxHeight: null, 9672 maxWidth: null, 9673 minHeight: 150, 9674 minWidth: 150, 9675 modal: false, 9676 position: { 9677 my: "center", 9678 at: "center", 9679 of: window, 9680 collision: "fit", 9681 // Ensure the titlebar is always visible 9682 using: function( pos ) { 9683 var topOffset = $( this ).css( pos ).offset().top; 9684 if ( topOffset < 0 ) { 9685 $( this ).css( "top", pos.top - topOffset ); 9686 } 9687 } 9688 }, 9689 resizable: true, 9690 show: null, 9691 title: null, 9692 width: 300, 9693 9694 // callbacks 9695 beforeClose: null, 9696 close: null, 9697 drag: null, 9698 dragStart: null, 9699 dragStop: null, 9700 focus: null, 9701 open: null, 9702 resize: null, 9703 resizeStart: null, 9704 resizeStop: null 9705 }, 9706 9707 _create: function() { 9708 this.originalCss = { 9709 display: this.element[0].style.display, 9710 width: this.element[0].style.width, 9711 minHeight: this.element[0].style.minHeight, 9712 maxHeight: this.element[0].style.maxHeight, 9713 height: this.element[0].style.height 9714 }; 9715 this.originalPosition = { 9716 parent: this.element.parent(), 9717 index: this.element.parent().children().index( this.element ) 9718 }; 9719 this.originalTitle = this.element.attr("title"); 9720 this.options.title = this.options.title || this.originalTitle; 9721 9722 this._createWrapper(); 9723 9724 this.element 9725 .show() 9726 .removeAttr("title") 9727 .addClass("ui-dialog-content ui-widget-content") 9728 .appendTo( this.uiDialog ); 9729 9730 this._createTitlebar(); 9731 this._createButtonPane(); 9732 9733 if ( this.options.draggable && $.fn.draggable ) { 9734 this._makeDraggable(); 9735 } 9736 if ( this.options.resizable && $.fn.resizable ) { 9737 this._makeResizable(); 9738 } 9739 9740 this._isOpen = false; 9741 }, 9742 9743 _init: function() { 9744 if ( this.options.autoOpen ) { 9745 this.open(); 9746 } 9747 }, 9748 9749 _appendTo: function() { 9750 var element = this.options.appendTo; 9751 if ( element && (element.jquery || element.nodeType) ) { 9752 return $( element ); 9753 } 9754 return this.document.find( element || "body" ).eq( 0 ); 9755 }, 9756 9757 _destroy: function() { 9758 var next, 9759 originalPosition = this.originalPosition; 9760 9761 this._destroyOverlay(); 9762 9763 this.element 9764 .removeUniqueId() 9765 .removeClass("ui-dialog-content ui-widget-content") 9766 .css( this.originalCss ) 9767 // Without detaching first, the following becomes really slow 9768 .detach(); 9769 9770 this.uiDialog.stop( true, true ).remove(); 9771 9772 if ( this.originalTitle ) { 9773 this.element.attr( "title", this.originalTitle ); 9774 } 9775 9776 next = originalPosition.parent.children().eq( originalPosition.index ); 9777 // Don't try to place the dialog next to itself (#8613) 9778 if ( next.length && next[0] !== this.element[0] ) { 9779 next.before( this.element ); 9780 } else { 9781 originalPosition.parent.append( this.element ); 9782 } 9783 }, 9784 9785 widget: function() { 9786 return this.uiDialog; 9787 }, 9788 9789 disable: $.noop, 9790 enable: $.noop, 9791 9792 close: function( event ) { 9793 var activeElement, 9794 that = this; 9795 9796 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) { 9797 return; 9798 } 9799 9800 this._isOpen = false; 9801 this._destroyOverlay(); 9802 9803 if ( !this.opener.filter(":focusable").focus().length ) { 9804 9805 // support: IE9 9806 // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe> 9807 try { 9808 activeElement = this.document[ 0 ].activeElement; 9809 9810 // Support: IE9, IE10 9811 // If the <body> is blurred, IE will switch windows, see #4520 9812 if ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) { 9813 9814 // Hiding a focused element doesn't trigger blur in WebKit 9815 // so in case we have nothing to focus on, explicitly blur the active element 9816 // https://bugs.webkit.org/show_bug.cgi?id=47182 9817 $( activeElement ).blur(); 9818 } 9819 } catch ( error ) {} 9820 } 9821 9822 this._hide( this.uiDialog, this.options.hide, function() { 9823 that._trigger( "close", event ); 9824 }); 9825 }, 9826 9827 isOpen: function() { 9828 return this._isOpen; 9829 }, 9830 9831 moveToTop: function() { 9832 this._moveToTop(); 9833 }, 9834 9835 _moveToTop: function( event, silent ) { 9836 var moved = !!this.uiDialog.nextAll(":visible").insertBefore( this.uiDialog ).length; 9837 if ( moved && !silent ) { 9838 this._trigger( "focus", event ); 9839 } 9840 return moved; 9841 }, 9842 9843 open: function() { 9844 var that = this; 9845 if ( this._isOpen ) { 9846 if ( this._moveToTop() ) { 9847 this._focusTabbable(); 9848 } 9849 return; 9850 } 9851 9852 this._isOpen = true; 9853 this.opener = $( this.document[0].activeElement ); 9854 9855 this._size(); 9856 this._position(); 9857 this._createOverlay(); 9858 this._moveToTop( null, true ); 9859 this._show( this.uiDialog, this.options.show, function() { 9860 that._focusTabbable(); 9861 that._trigger("focus"); 9862 }); 9863 9864 this._trigger("open"); 9865 }, 9866 9867 _focusTabbable: function() { 9868 // Set focus to the first match: 9869 // 1. First element inside the dialog matching [autofocus] 9870 // 2. Tabbable element inside the content element 9871 // 3. Tabbable element inside the buttonpane 9872 // 4. The close button 9873 // 5. The dialog itself 9874 var hasFocus = this.element.find("[autofocus]"); 9875 if ( !hasFocus.length ) { 9876 hasFocus = this.element.find(":tabbable"); 9877 } 9878 if ( !hasFocus.length ) { 9879 hasFocus = this.uiDialogButtonPane.find(":tabbable"); 9880 } 9881 if ( !hasFocus.length ) { 9882 hasFocus = this.uiDialogTitlebarClose.filter(":tabbable"); 9883 } 9884 if ( !hasFocus.length ) { 9885 hasFocus = this.uiDialog; 9886 } 9887 hasFocus.eq( 0 ).focus(); 9888 }, 9889 9890 _keepFocus: function( event ) { 9891 function checkFocus() { 9892 var activeElement = this.document[0].activeElement, 9893 isActive = this.uiDialog[0] === activeElement || 9894 $.contains( this.uiDialog[0], activeElement ); 9895 if ( !isActive ) { 9896 this._focusTabbable(); 9897 } 9898 } 9899 event.preventDefault(); 9900 checkFocus.call( this ); 9901 // support: IE 9902 // IE <= 8 doesn't prevent moving focus even with event.preventDefault() 9903 // so we check again later 9904 this._delay( checkFocus ); 9905 }, 9906 9907 _createWrapper: function() { 9908 this.uiDialog = $("<div>") 9909 .addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " + 9910 this.options.dialogClass ) 9911 .hide() 9912 .attr({ 9913 // Setting tabIndex makes the div focusable 9914 tabIndex: -1, 9915 role: "dialog" 9916 }) 9917 .appendTo( this._appendTo() ); 9918 9919 this._on( this.uiDialog, { 9920 keydown: function( event ) { 9921 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && 9922 event.keyCode === $.ui.keyCode.ESCAPE ) { 9923 event.preventDefault(); 9924 this.close( event ); 9925 return; 9926 } 9927 9928 // prevent tabbing out of dialogs 9929 if ( event.keyCode !== $.ui.keyCode.TAB ) { 9930 return; 9931 } 9932 var tabbables = this.uiDialog.find(":tabbable"), 9933 first = tabbables.filter(":first"), 9934 last = tabbables.filter(":last"); 9935 9936 if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) { 9937 first.focus( 1 ); 9938 event.preventDefault(); 9939 } else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) { 9940 last.focus( 1 ); 9941 event.preventDefault(); 9942 } 9943 }, 9944 mousedown: function( event ) { 9945 if ( this._moveToTop( event ) ) { 9946 this._focusTabbable(); 9947 } 9948 } 9949 }); 9950 9951 // We assume that any existing aria-describedby attribute means 9952 // that the dialog content is marked up properly 9953 // otherwise we brute force the content as the description 9954 if ( !this.element.find("[aria-describedby]").length ) { 9955 this.uiDialog.attr({ 9956 "aria-describedby": this.element.uniqueId().attr("id") 9957 }); 9958 } 9959 }, 9960 9961 _createTitlebar: function() { 9962 var uiDialogTitle; 9963 9964 this.uiDialogTitlebar = $("<div>") 9965 .addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix") 9966 .prependTo( this.uiDialog ); 9967 this._on( this.uiDialogTitlebar, { 9968 mousedown: function( event ) { 9969 // Don't prevent click on close button (#8838) 9970 // Focusing a dialog that is partially scrolled out of view 9971 // causes the browser to scroll it into view, preventing the click event 9972 if ( !$( event.target ).closest(".ui-dialog-titlebar-close") ) { 9973 // Dialog isn't getting focus when dragging (#8063) 9974 this.uiDialog.focus(); 9975 } 9976 } 9977 }); 9978 9979 // support: IE 9980 // Use type="button" to prevent enter keypresses in textboxes from closing the 9981 // dialog in IE (#9312) 9982 this.uiDialogTitlebarClose = $( "<button type='button'></button>" ) 9983 .button({ 9984 label: this.options.closeText, 9985 icons: { 9986 primary: "ui-icon-closethick" 9987 }, 9988 text: false 9989 }) 9990 .addClass("ui-dialog-titlebar-close") 9991 .appendTo( this.uiDialogTitlebar ); 9992 this._on( this.uiDialogTitlebarClose, { 9993 click: function( event ) { 9994 event.preventDefault(); 9995 this.close( event ); 9996 } 9997 }); 9998 9999 uiDialogTitle = $("<span>") 10000 .uniqueId() 10001 .addClass("ui-dialog-title") 10002 .prependTo( this.uiDialogTitlebar ); 10003 this._title( uiDialogTitle ); 10004 10005 this.uiDialog.attr({ 10006 "aria-labelledby": uiDialogTitle.attr("id") 10007 }); 10008 }, 10009 10010 _title: function( title ) { 10011 if ( !this.options.title ) { 10012 title.html(" "); 10013 } 10014 title.text( this.options.title ); 10015 }, 10016 10017 _createButtonPane: function() { 10018 this.uiDialogButtonPane = $("<div>") 10019 .addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"); 10020 10021 this.uiButtonSet = $("<div>") 10022 .addClass("ui-dialog-buttonset") 10023 .appendTo( this.uiDialogButtonPane ); 10024 10025 this._createButtons(); 10026 }, 10027 10028 _createButtons: function() { 10029 var that = this, 10030 buttons = this.options.buttons; 10031 10032 // if we already have a button pane, remove it 10033 this.uiDialogButtonPane.remove(); 10034 this.uiButtonSet.empty(); 10035 10036 if ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) { 10037 this.uiDialog.removeClass("ui-dialog-buttons"); 10038 return; 10039 } 10040 10041 $.each( buttons, function( name, props ) { 10042 var click, buttonOptions; 10043 props = $.isFunction( props ) ? 10044 { click: props, text: name } : 10045 props; 10046 // Default to a non-submitting button 10047 props = $.extend( { type: "button" }, props ); 10048 // Change the context for the click callback to be the main element 10049 click = props.click; 10050 props.click = function() { 10051 click.apply( that.element[0], arguments ); 10052 }; 10053 buttonOptions = { 10054 icons: props.icons, 10055 text: props.showText 10056 }; 10057 delete props.icons; 10058 delete props.showText; 10059 $( "<button></button>", props ) 10060 .button( buttonOptions ) 10061 .appendTo( that.uiButtonSet ); 10062 }); 10063 this.uiDialog.addClass("ui-dialog-buttons"); 10064 this.uiDialogButtonPane.appendTo( this.uiDialog ); 10065 }, 10066 10067 _makeDraggable: function() { 10068 var that = this, 10069 options = this.options; 10070 10071 function filteredUi( ui ) { 10072 return { 10073 position: ui.position, 10074 offset: ui.offset 10075 }; 10076 } 10077 10078 this.uiDialog.draggable({ 10079 cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", 10080 handle: ".ui-dialog-titlebar", 10081 containment: "document", 10082 start: function( event, ui ) { 10083 $( this ).addClass("ui-dialog-dragging"); 10084 that._blockFrames(); 10085 that._trigger( "dragStart", event, filteredUi( ui ) ); 10086 }, 10087 drag: function( event, ui ) { 10088 that._trigger( "drag", event, filteredUi( ui ) ); 10089 }, 10090 stop: function( event, ui ) { 10091 options.position = [ 10092 ui.position.left - that.document.scrollLeft(), 10093 ui.position.top - that.document.scrollTop() 10094 ]; 10095 $( this ).removeClass("ui-dialog-dragging"); 10096 that._unblockFrames(); 10097 that._trigger( "dragStop", event, filteredUi( ui ) ); 10098 } 10099 }); 10100 }, 10101 10102 _makeResizable: function() { 10103 var that = this, 10104 options = this.options, 10105 handles = options.resizable, 10106 // .ui-resizable has position: relative defined in the stylesheet 10107 // but dialogs have to use absolute or fixed positioning 10108 position = this.uiDialog.css("position"), 10109 resizeHandles = typeof handles === "string" ? 10110 handles : 10111 "n,e,s,w,se,sw,ne,nw"; 10112 10113 function filteredUi( ui ) { 10114 return { 10115 originalPosition: ui.originalPosition, 10116 originalSize: ui.originalSize, 10117 position: ui.position, 10118 size: ui.size 10119 }; 10120 } 10121 10122 this.uiDialog.resizable({ 10123 cancel: ".ui-dialog-content", 10124 containment: "document", 10125 alsoResize: this.element, 10126 maxWidth: options.maxWidth, 10127 maxHeight: options.maxHeight, 10128 minWidth: options.minWidth, 10129 minHeight: this._minHeight(), 10130 handles: resizeHandles, 10131 start: function( event, ui ) { 10132 $( this ).addClass("ui-dialog-resizing"); 10133 that._blockFrames(); 10134 that._trigger( "resizeStart", event, filteredUi( ui ) ); 10135 }, 10136 resize: function( event, ui ) { 10137 that._trigger( "resize", event, filteredUi( ui ) ); 10138 }, 10139 stop: function( event, ui ) { 10140 options.height = $( this ).height(); 10141 options.width = $( this ).width(); 10142 $( this ).removeClass("ui-dialog-resizing"); 10143 that._unblockFrames(); 10144 that._trigger( "resizeStop", event, filteredUi( ui ) ); 10145 } 10146 }) 10147 .css( "position", position ); 10148 }, 10149 10150 _minHeight: function() { 10151 var options = this.options; 10152 10153 return options.height === "auto" ? 10154 options.minHeight : 10155 Math.min( options.minHeight, options.height ); 10156 }, 10157 10158 _position: function() { 10159 // Need to show the dialog to get the actual offset in the position plugin 10160 var isVisible = this.uiDialog.is(":visible"); 10161 if ( !isVisible ) { 10162 this.uiDialog.show(); 10163 } 10164 this.uiDialog.position( this.options.position ); 10165 if ( !isVisible ) { 10166 this.uiDialog.hide(); 10167 } 10168 }, 10169 10170 _setOptions: function( options ) { 10171 var that = this, 10172 resize = false, 10173 resizableOptions = {}; 10174 10175 $.each( options, function( key, value ) { 10176 that._setOption( key, value ); 10177 10178 if ( key in sizeRelatedOptions ) { 10179 resize = true; 10180 } 10181 if ( key in resizableRelatedOptions ) { 10182 resizableOptions[ key ] = value; 10183 } 10184 }); 10185 10186 if ( resize ) { 10187 this._size(); 10188 this._position(); 10189 } 10190 if ( this.uiDialog.is(":data(ui-resizable)") ) { 10191 this.uiDialog.resizable( "option", resizableOptions ); 10192 } 10193 }, 10194 10195 _setOption: function( key, value ) { 10196 var isDraggable, isResizable, 10197 uiDialog = this.uiDialog; 10198 10199 if ( key === "dialogClass" ) { 10200 uiDialog 10201 .removeClass( this.options.dialogClass ) 10202 .addClass( value ); 10203 } 10204 10205 if ( key === "disabled" ) { 10206 return; 10207 } 10208 10209 this._super( key, value ); 10210 10211 if ( key === "appendTo" ) { 10212 this.uiDialog.appendTo( this._appendTo() ); 10213 } 10214 10215 if ( key === "buttons" ) { 10216 this._createButtons(); 10217 } 10218 10219 if ( key === "closeText" ) { 10220 this.uiDialogTitlebarClose.button({ 10221 // Ensure that we always pass a string 10222 label: "" + value 10223 }); 10224 } 10225 10226 if ( key === "draggable" ) { 10227 isDraggable = uiDialog.is(":data(ui-draggable)"); 10228 if ( isDraggable && !value ) { 10229 uiDialog.draggable("destroy"); 10230 } 10231 10232 if ( !isDraggable && value ) { 10233 this._makeDraggable(); 10234 } 10235 } 10236 10237 if ( key === "position" ) { 10238 this._position(); 10239 } 10240 10241 if ( key === "resizable" ) { 10242 // currently resizable, becoming non-resizable 10243 isResizable = uiDialog.is(":data(ui-resizable)"); 10244 if ( isResizable && !value ) { 10245 uiDialog.resizable("destroy"); 10246 } 10247 10248 // currently resizable, changing handles 10249 if ( isResizable && typeof value === "string" ) { 10250 uiDialog.resizable( "option", "handles", value ); 10251 } 10252 10253 // currently non-resizable, becoming resizable 10254 if ( !isResizable && value !== false ) { 10255 this._makeResizable(); 10256 } 10257 } 10258 10259 if ( key === "title" ) { 10260 this._title( this.uiDialogTitlebar.find(".ui-dialog-title") ); 10261 } 10262 }, 10263 10264 _size: function() { 10265 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content 10266 // divs will both have width and height set, so we need to reset them 10267 var nonContentHeight, minContentHeight, maxContentHeight, 10268 options = this.options; 10269 10270 // Reset content sizing 10271 this.element.show().css({ 10272 width: "auto", 10273 minHeight: 0, 10274 maxHeight: "none", 10275 height: 0 10276 }); 10277 10278 if ( options.minWidth > options.width ) { 10279 options.width = options.minWidth; 10280 } 10281 10282 // reset wrapper sizing 10283 // determine the height of all the non-content elements 10284 nonContentHeight = this.uiDialog.css({ 10285 height: "auto", 10286 width: options.width 10287 }) 10288 .outerHeight(); 10289 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); 10290 maxContentHeight = typeof options.maxHeight === "number" ? 10291 Math.max( 0, options.maxHeight - nonContentHeight ) : 10292 "none"; 10293 10294 if ( options.height === "auto" ) { 10295 this.element.css({ 10296 minHeight: minContentHeight, 10297 maxHeight: maxContentHeight, 10298 height: "auto" 10299 }); 10300 } else { 10301 this.element.height( Math.max( 0, options.height - nonContentHeight ) ); 10302 } 10303 10304 if (this.uiDialog.is(":data(ui-resizable)") ) { 10305 this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); 10306 } 10307 }, 10308 10309 _blockFrames: function() { 10310 this.iframeBlocks = this.document.find( "iframe" ).map(function() { 10311 var iframe = $( this ); 10312 10313 return $( "<div>" ) 10314 .css({ 10315 position: "absolute", 10316 width: iframe.outerWidth(), 10317 height: iframe.outerHeight() 10318 }) 10319 .appendTo( iframe.parent() ) 10320 .offset( iframe.offset() )[0]; 10321 }); 10322 }, 10323 10324 _unblockFrames: function() { 10325 if ( this.iframeBlocks ) { 10326 this.iframeBlocks.remove(); 10327 delete this.iframeBlocks; 10328 } 10329 }, 10330 10331 _allowInteraction: function( event ) { 10332 if ( $( event.target ).closest(".ui-dialog").length ) { 10333 return true; 10334 } 10335 10336 // TODO: Remove hack when datepicker implements 10337 // the .ui-front logic (#8989) 10338 return !!$( event.target ).closest(".ui-datepicker").length; 10339 }, 10340 10341 _createOverlay: function() { 10342 if ( !this.options.modal ) { 10343 return; 10344 } 10345 10346 var that = this, 10347 widgetFullName = this.widgetFullName; 10348 if ( !$.ui.dialog.overlayInstances ) { 10349 // Prevent use of anchors and inputs. 10350 // We use a delay in case the overlay is created from an 10351 // event that we're going to be cancelling. (#2804) 10352 this._delay(function() { 10353 // Handle .dialog().dialog("close") (#4065) 10354 if ( $.ui.dialog.overlayInstances ) { 10355 this.document.bind( "focusin.dialog", function( event ) { 10356 if ( !that._allowInteraction( event ) ) { 10357 event.preventDefault(); 10358 $(".ui-dialog:visible:last .ui-dialog-content") 10359 .data( widgetFullName )._focusTabbable(); 10360 } 10361 }); 10362 } 10363 }); 10364 } 10365
vendor: 7,122 bytes, lines 10366-10657
10366 this.overlay = $("<div>") 10367 .addClass("ui-widget-overlay ui-front") 10368 .appendTo( this._appendTo() ); 10369 this._on( this.overlay, { 10370 mousedown: "_keepFocus" 10371 }); 10372 $.ui.dialog.overlayInstances++; 10373 }, 10374 10375 _destroyOverlay: function() { 10376 if ( !this.options.modal ) { 10377 return; 10378 } 10379 10380 if ( this.overlay ) { 10381 $.ui.dialog.overlayInstances--; 10382 10383 if ( !$.ui.dialog.overlayInstances ) { 10384 this.document.unbind( "focusin.dialog" ); 10385 } 10386 this.overlay.remove(); 10387 this.overlay = null; 10388 } 10389 } 10390}); 10391 10392$.ui.dialog.overlayInstances = 0; 10393 10394// DEPRECATED 10395if ( $.uiBackCompat !== false ) { 10396 // position option with array notation 10397 // just override with old implementation 10398 $.widget( "ui.dialog", $.ui.dialog, { 10399 _position: function() { 10400 var position = this.options.position, 10401 myAt = [], 10402 offset = [ 0, 0 ], 10403 isVisible; 10404 10405 if ( position ) { 10406 if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) { 10407 myAt = position.split ? position.split(" ") : [ position[0], position[1] ]; 10408 if ( myAt.length === 1 ) { 10409 myAt[1] = myAt[0]; 10410 } 10411 10412 $.each( [ "left", "top" ], function( i, offsetPosition ) { 10413 if ( +myAt[ i ] === myAt[ i ] ) { 10414 offset[ i ] = myAt[ i ]; 10415 myAt[ i ] = offsetPosition; 10416 } 10417 }); 10418 10419 position = { 10420 my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " + 10421 myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]), 10422 at: myAt.join(" ") 10423 }; 10424 } 10425 10426 position = $.extend( {}, $.ui.dialog.prototype.options.position, position ); 10427 } else { 10428 position = $.ui.dialog.prototype.options.position; 10429 } 10430 10431 // need to show the dialog to get the actual offset in the position plugin 10432 isVisible = this.uiDialog.is(":visible"); 10433 if ( !isVisible ) { 10434 this.uiDialog.show(); 10435 } 10436 this.uiDialog.position( position ); 10437 if ( !isVisible ) { 10438 this.uiDialog.hide(); 10439 } 10440 } 10441 }); 10442} 10443 10444}( jQuery ) ); 10445 10446(function( $, undefined ) { 10447 10448var rvertical = /up|down|vertical/, 10449 rpositivemotion = /up|left|vertical|horizontal/; 10450 10451$.effects.effect.blind = function( o, done ) { 10452 // Create element 10453 var el = $( this ), 10454 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 10455 mode = $.effects.setMode( el, o.mode || "hide" ), 10456 direction = o.direction || "up", 10457 vertical = rvertical.test( direction ), 10458 ref = vertical ? "height" : "width", 10459 ref2 = vertical ? "top" : "left", 10460 motion = rpositivemotion.test( direction ), 10461 animation = {}, 10462 show = mode === "show", 10463 wrapper, distance, margin; 10464 10465 // if already wrapped, the wrapper's properties are my property. #6245 10466 if ( el.parent().is( ".ui-effects-wrapper" ) ) { 10467 $.effects.save( el.parent(), props ); 10468 } else { 10469 $.effects.save( el, props ); 10470 } 10471 el.show(); 10472 wrapper = $.effects.createWrapper( el ).css({ 10473 overflow: "hidden" 10474 }); 10475 10476 distance = wrapper[ ref ](); 10477 margin = parseFloat( wrapper.css( ref2 ) ) || 0; 10478 10479 animation[ ref ] = show ? distance : 0; 10480 if ( !motion ) { 10481 el 10482 .css( vertical ? "bottom" : "right", 0 ) 10483 .css( vertical ? "top" : "left", "auto" ) 10484 .css({ position: "absolute" }); 10485 10486 animation[ ref2 ] = show ? margin : distance + margin; 10487 } 10488 10489 // start at 0 if we are showing 10490 if ( show ) { 10491 wrapper.css( ref, 0 ); 10492 if ( ! motion ) { 10493 wrapper.css( ref2, margin + distance ); 10494 } 10495 } 10496 10497 // Animate 10498 wrapper.animate( animation, { 10499 duration: o.duration, 10500 easing: o.easing, 10501 queue: false, 10502 complete: function() { 10503 if ( mode === "hide" ) { 10504 el.hide(); 10505 } 10506 $.effects.restore( el, props ); 10507 $.effects.removeWrapper( el ); 10508 done(); 10509 } 10510 }); 10511 10512}; 10513 10514})(jQuery); 10515 10516(function( $, undefined ) { 10517 10518$.effects.effect.bounce = function( o, done ) { 10519 var el = $( this ), 10520 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 10521 10522 // defaults: 10523 mode = $.effects.setMode( el, o.mode || "effect" ), 10524 hide = mode === "hide", 10525 show = mode === "show", 10526 direction = o.direction || "up", 10527 distance = o.distance, 10528 times = o.times || 5, 10529 10530 // number of internal animations 10531 anims = times * 2 + ( show || hide ? 1 : 0 ), 10532 speed = o.duration / anims, 10533 easing = o.easing, 10534 10535 // utility: 10536 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 10537 motion = ( direction === "up" || direction === "left" ), 10538 i, 10539 upAnim, 10540 downAnim, 10541 10542 // we will need to re-assemble the queue to stack our animations in place 10543 queue = el.queue(), 10544 queuelen = queue.length; 10545 10546 // Avoid touching opacity to prevent clearType and PNG issues in IE 10547 if ( show || hide ) { 10548 props.push( "opacity" ); 10549 } 10550 10551 $.effects.save( el, props ); 10552 el.show(); 10553 $.effects.createWrapper( el ); // Create Wrapper 10554 10555 // default distance for the BIGGEST bounce is the outer Distance / 3 10556 if ( !distance ) { 10557 distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; 10558 } 10559 10560 if ( show ) { 10561 downAnim = { opacity: 1 }; 10562 downAnim[ ref ] = 0; 10563 10564 // if we are showing, force opacity 0 and set the initial position 10565 // then do the "first" animation 10566 el.css( "opacity", 0 ) 10567 .css( ref, motion ? -distance * 2 : distance * 2 ) 10568 .animate( downAnim, speed, easing ); 10569 } 10570 10571 // start at the smallest distance if we are hiding 10572 if ( hide ) { 10573 distance = distance / Math.pow( 2, times - 1 ); 10574 } 10575 10576 downAnim = {}; 10577 downAnim[ ref ] = 0; 10578 // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here 10579 for ( i = 0; i < times; i++ ) { 10580 upAnim = {}; 10581 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 10582 10583 el.animate( upAnim, speed, easing ) 10584 .animate( downAnim, speed, easing ); 10585 10586 distance = hide ? distance * 2 : distance / 2; 10587 } 10588 10589 // Last Bounce when Hiding 10590 if ( hide ) { 10591 upAnim = { opacity: 0 }; 10592 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; 10593 10594 el.animate( upAnim, speed, easing ); 10595 } 10596 10597 el.queue(function() { 10598 if ( hide ) { 10599 el.hide(); 10600 } 10601 $.effects.restore( el, props ); 10602 $.effects.removeWrapper( el ); 10603 done(); 10604 }); 10605 10606 // inject all the animations we just queued to be first in line (after "inprogress") 10607 if ( queuelen > 1) { 10608 queue.splice.apply( queue, 10609 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); 10610 } 10611 el.dequeue(); 10612 10613}; 10614 10615})(jQuery); 10616 10617(function( $, undefined ) { 10618 10619$.effects.effect.clip = function( o, done ) { 10620 // Create element 10621 var el = $( this ), 10622 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 10623 mode = $.effects.setMode( el, o.mode || "hide" ), 10624 show = mode === "show", 10625 direction = o.direction || "vertical", 10626 vert = direction === "vertical", 10627 size = vert ? "height" : "width", 10628 position = vert ? "top" : "left", 10629 animation = {}, 10630 wrapper, animate, distance; 10631 10632 // Save & Show 10633 $.effects.save( el, props ); 10634 el.show(); 10635 10636 // Create Wrapper 10637 wrapper = $.effects.createWrapper( el ).css({ 10638 overflow: "hidden" 10639 }); 10640 animate = ( el[0].tagName === "IMG" ) ? wrapper : el; 10641 distance = animate[ size ](); 10642 10643 // Shift 10644 if ( show ) { 10645 animate.css( size, 0 ); 10646 animate.css( position, distance / 2 ); 10647 } 10648 10649 // Create Animation Object: 10650 animation[ size ] = show ? distance : 0; 10651 animation[ position ] = show ? 0 : distance / 2; 10652 10653 // Animate 10654 animate.animate( animation, { 10655 queue: false, 10656 duration: o.duration, 10657 easing: o.easing,
vendor: 116,514 bytes, lines 10658-15040
10658 complete: function() { 10659 if ( !show ) { 10660 el.hide(); 10661 } 10662 $.effects.restore( el, props ); 10663 $.effects.removeWrapper( el ); 10664 done(); 10665 } 10666 }); 10667 10668}; 10669 10670})(jQuery); 10671 10672(function( $, undefined ) { 10673 10674$.effects.effect.drop = function( o, done ) { 10675 10676 var el = $( this ), 10677 props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ], 10678 mode = $.effects.setMode( el, o.mode || "hide" ), 10679 show = mode === "show", 10680 direction = o.direction || "left", 10681 ref = ( direction === "up" || direction === "down" ) ? "top" : "left", 10682 motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg", 10683 animation = { 10684 opacity: show ? 1 : 0 10685 }, 10686 distance; 10687 10688 // Adjust 10689 $.effects.save( el, props ); 10690 el.show(); 10691 $.effects.createWrapper( el ); 10692 10693 distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2; 10694 10695 if ( show ) { 10696 el 10697 .css( "opacity", 0 ) 10698 .css( ref, motion === "pos" ? -distance : distance ); 10699 } 10700 10701 // Animation 10702 animation[ ref ] = ( show ? 10703 ( motion === "pos" ? "+=" : "-=" ) : 10704 ( motion === "pos" ? "-=" : "+=" ) ) + 10705 distance; 10706 10707 // Animate 10708 el.animate( animation, { 10709 queue: false, 10710 duration: o.duration, 10711 easing: o.easing, 10712 complete: function() { 10713 if ( mode === "hide" ) { 10714 el.hide(); 10715 } 10716 $.effects.restore( el, props ); 10717 $.effects.removeWrapper( el ); 10718 done(); 10719 } 10720 }); 10721}; 10722 10723})(jQuery); 10724 10725(function( $, undefined ) { 10726 10727$.effects.effect.explode = function( o, done ) { 10728 10729 var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3, 10730 cells = rows, 10731 el = $( this ), 10732 mode = $.effects.setMode( el, o.mode || "hide" ), 10733 show = mode === "show", 10734 10735 // show and then visibility:hidden the element before calculating offset 10736 offset = el.show().css( "visibility", "hidden" ).offset(), 10737 10738 // width and height of a piece 10739 width = Math.ceil( el.outerWidth() / cells ), 10740 height = Math.ceil( el.outerHeight() / rows ), 10741 pieces = [], 10742 10743 // loop 10744 i, j, left, top, mx, my; 10745 10746 // children animate complete: 10747 function childComplete() { 10748 pieces.push( this ); 10749 if ( pieces.length === rows * cells ) { 10750 animComplete(); 10751 } 10752 } 10753 10754 // clone the element for each row and cell. 10755 for( i = 0; i < rows ; i++ ) { // ===> 10756 top = offset.top + i * height; 10757 my = i - ( rows - 1 ) / 2 ; 10758 10759 for( j = 0; j < cells ; j++ ) { // ||| 10760 left = offset.left + j * width; 10761 mx = j - ( cells - 1 ) / 2 ; 10762 10763 // Create a clone of the now hidden main element that will be absolute positioned 10764 // within a wrapper div off the -left and -top equal to size of our pieces 10765 el 10766 .clone() 10767 .appendTo( "body" ) 10768 .wrap( "<div></div>" ) 10769 .css({ 10770 position: "absolute", 10771 visibility: "visible", 10772 left: -j * width, 10773 top: -i * height 10774 }) 10775 10776 // select the wrapper - make it overflow: hidden and absolute positioned based on 10777 // where the original was located +left and +top equal to the size of pieces 10778 .parent() 10779 .addClass( "ui-effects-explode" ) 10780 .css({ 10781 position: "absolute", 10782 overflow: "hidden", 10783 width: width, 10784 height: height, 10785 left: left + ( show ? mx * width : 0 ), 10786 top: top + ( show ? my * height : 0 ), 10787 opacity: show ? 0 : 1 10788 }).animate({ 10789 left: left + ( show ? 0 : mx * width ), 10790 top: top + ( show ? 0 : my * height ), 10791 opacity: show ? 1 : 0 10792 }, o.duration || 500, o.easing, childComplete ); 10793 } 10794 } 10795 10796 function animComplete() { 10797 el.css({ 10798 visibility: "visible" 10799 }); 10800 $( pieces ).remove(); 10801 if ( !show ) { 10802 el.hide(); 10803 } 10804 done(); 10805 } 10806}; 10807 10808})(jQuery); 10809 10810(function( $, undefined ) { 10811 10812$.effects.effect.fade = function( o, done ) { 10813 var el = $( this ), 10814 mode = $.effects.setMode( el, o.mode || "toggle" ); 10815 10816 el.animate({ 10817 opacity: mode 10818 }, { 10819 queue: false, 10820 duration: o.duration, 10821 easing: o.easing, 10822 complete: done 10823 }); 10824}; 10825 10826})( jQuery ); 10827 10828(function( $, undefined ) { 10829 10830$.effects.effect.fold = function( o, done ) { 10831 10832 // Create element 10833 var el = $( this ), 10834 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 10835 mode = $.effects.setMode( el, o.mode || "hide" ), 10836 show = mode === "show", 10837 hide = mode === "hide", 10838 size = o.size || 15, 10839 percent = /([0-9]+)%/.exec( size ), 10840 horizFirst = !!o.horizFirst, 10841 widthFirst = show !== horizFirst, 10842 ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ], 10843 duration = o.duration / 2, 10844 wrapper, distance, 10845 animation1 = {}, 10846 animation2 = {}; 10847 10848 $.effects.save( el, props ); 10849 el.show(); 10850 10851 // Create Wrapper 10852 wrapper = $.effects.createWrapper( el ).css({ 10853 overflow: "hidden" 10854 }); 10855 distance = widthFirst ? 10856 [ wrapper.width(), wrapper.height() ] : 10857 [ wrapper.height(), wrapper.width() ]; 10858 10859 if ( percent ) { 10860 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; 10861 } 10862 if ( show ) { 10863 wrapper.css( horizFirst ? { 10864 height: 0, 10865 width: size 10866 } : { 10867 height: size, 10868 width: 0 10869 }); 10870 } 10871 10872 // Animation 10873 animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size; 10874 animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0; 10875 10876 // Animate 10877 wrapper 10878 .animate( animation1, duration, o.easing ) 10879 .animate( animation2, duration, o.easing, function() { 10880 if ( hide ) { 10881 el.hide(); 10882 } 10883 $.effects.restore( el, props ); 10884 $.effects.removeWrapper( el ); 10885 done(); 10886 }); 10887 10888}; 10889 10890})(jQuery); 10891 10892(function( $, undefined ) { 10893 10894$.effects.effect.highlight = function( o, done ) { 10895 var elem = $( this ), 10896 props = [ "backgroundImage", "backgroundColor", "opacity" ], 10897 mode = $.effects.setMode( elem, o.mode || "show" ), 10898 animation = { 10899 backgroundColor: elem.css( "backgroundColor" ) 10900 }; 10901 10902 if (mode === "hide") { 10903 animation.opacity = 0; 10904 } 10905 10906 $.effects.save( elem, props ); 10907 10908 elem 10909 .show() 10910 .css({ 10911 backgroundImage: "none", 10912 backgroundColor: o.color || "#ffff99" 10913 }) 10914 .animate( animation, { 10915 queue: false, 10916 duration: o.duration, 10917 easing: o.easing, 10918 complete: function() { 10919 if ( mode === "hide" ) { 10920 elem.hide(); 10921 } 10922 $.effects.restore( elem, props ); 10923 done(); 10924 } 10925 }); 10926}; 10927 10928})(jQuery); 10929 10930(function( $, undefined ) { 10931 10932$.effects.effect.pulsate = function( o, done ) { 10933 var elem = $( this ), 10934 mode = $.effects.setMode( elem, o.mode || "show" ), 10935 show = mode === "show", 10936 hide = mode === "hide", 10937 showhide = ( show || mode === "hide" ), 10938 10939 // showing or hiding leaves of the "last" animation 10940 anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), 10941 duration = o.duration / anims, 10942 animateTo = 0, 10943 queue = elem.queue(), 10944 queuelen = queue.length, 10945 i; 10946 10947 if ( show || !elem.is(":visible")) { 10948 elem.css( "opacity", 0 ).show(); 10949 animateTo = 1; 10950 } 10951 10952 // anims - 1 opacity "toggles" 10953 for ( i = 1; i < anims; i++ ) { 10954 elem.animate({ 10955 opacity: animateTo 10956 }, duration, o.easing ); 10957 animateTo = 1 - animateTo; 10958 } 10959 10960 elem.animate({ 10961 opacity: animateTo 10962 }, duration, o.easing); 10963 10964 elem.queue(function() { 10965 if ( hide ) { 10966 elem.hide(); 10967 } 10968 done(); 10969 }); 10970 10971 // We just queued up "anims" animations, we need to put them next in the queue 10972 if ( queuelen > 1 ) { 10973 queue.splice.apply( queue, 10974 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); 10975 } 10976 elem.dequeue(); 10977}; 10978 10979})(jQuery); 10980 10981(function( $, undefined ) { 10982 10983$.effects.effect.puff = function( o, done ) { 10984 var elem = $( this ), 10985 mode = $.effects.setMode( elem, o.mode || "hide" ), 10986 hide = mode === "hide", 10987 percent = parseInt( o.percent, 10 ) || 150, 10988 factor = percent / 100, 10989 original = { 10990 height: elem.height(), 10991 width: elem.width(), 10992 outerHeight: elem.outerHeight(), 10993 outerWidth: elem.outerWidth() 10994 }; 10995 10996 $.extend( o, { 10997 effect: "scale", 10998 queue: false, 10999 fade: true, 11000 mode: mode, 11001 complete: done, 11002 percent: hide ? percent : 100, 11003 from: hide ? 11004 original : 11005 { 11006 height: original.height * factor, 11007 width: original.width * factor, 11008 outerHeight: original.outerHeight * factor, 11009 outerWidth: original.outerWidth * factor 11010 } 11011 }); 11012 11013 elem.effect( o ); 11014}; 11015 11016$.effects.effect.scale = function( o, done ) { 11017 11018 // Create element 11019 var el = $( this ), 11020 options = $.extend( true, {}, o ), 11021 mode = $.effects.setMode( el, o.mode || "effect" ), 11022 percent = parseInt( o.percent, 10 ) || 11023 ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ), 11024 direction = o.direction || "both", 11025 origin = o.origin, 11026 original = { 11027 height: el.height(), 11028 width: el.width(), 11029 outerHeight: el.outerHeight(), 11030 outerWidth: el.outerWidth() 11031 }, 11032 factor = { 11033 y: direction !== "horizontal" ? (percent / 100) : 1, 11034 x: direction !== "vertical" ? (percent / 100) : 1 11035 }; 11036 11037 // We are going to pass this effect to the size effect: 11038 options.effect = "size"; 11039 options.queue = false; 11040 options.complete = done; 11041 11042 // Set default origin and restore for show/hide 11043 if ( mode !== "effect" ) { 11044 options.origin = origin || ["middle","center"]; 11045 options.restore = true; 11046 } 11047 11048 options.from = o.from || ( mode === "show" ? { 11049 height: 0, 11050 width: 0, 11051 outerHeight: 0, 11052 outerWidth: 0 11053 } : original ); 11054 options.to = { 11055 height: original.height * factor.y, 11056 width: original.width * factor.x, 11057 outerHeight: original.outerHeight * factor.y, 11058 outerWidth: original.outerWidth * factor.x 11059 }; 11060 11061 // Fade option to support puff 11062 if ( options.fade ) { 11063 if ( mode === "show" ) { 11064 options.from.opacity = 0; 11065 options.to.opacity = 1; 11066 } 11067 if ( mode === "hide" ) { 11068 options.from.opacity = 1; 11069 options.to.opacity = 0; 11070 } 11071 } 11072 11073 // Animate 11074 el.effect( options ); 11075 11076}; 11077 11078$.effects.effect.size = function( o, done ) { 11079 11080 // Create element 11081 var original, baseline, factor, 11082 el = $( this ), 11083 props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ], 11084 11085 // Always restore 11086 props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ], 11087 11088 // Copy for children 11089 props2 = [ "width", "height", "overflow" ], 11090 cProps = [ "fontSize" ], 11091 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], 11092 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], 11093 11094 // Set options 11095 mode = $.effects.setMode( el, o.mode || "effect" ), 11096 restore = o.restore || mode !== "effect", 11097 scale = o.scale || "both", 11098 origin = o.origin || [ "middle", "center" ], 11099 position = el.css( "position" ), 11100 props = restore ? props0 : props1, 11101 zero = { 11102 height: 0, 11103 width: 0, 11104 outerHeight: 0, 11105 outerWidth: 0 11106 }; 11107 11108 if ( mode === "show" ) { 11109 el.show(); 11110 } 11111 original = { 11112 height: el.height(), 11113 width: el.width(), 11114 outerHeight: el.outerHeight(), 11115 outerWidth: el.outerWidth() 11116 }; 11117 11118 if ( o.mode === "toggle" && mode === "show" ) { 11119 el.from = o.to || zero; 11120 el.to = o.from || original; 11121 } else { 11122 el.from = o.from || ( mode === "show" ? zero : original ); 11123 el.to = o.to || ( mode === "hide" ? zero : original ); 11124 } 11125 11126 // Set scaling factor 11127 factor = { 11128 from: { 11129 y: el.from.height / original.height, 11130 x: el.from.width / original.width 11131 }, 11132 to: { 11133 y: el.to.height / original.height, 11134 x: el.to.width / original.width 11135 } 11136 }; 11137 11138 // Scale the css box 11139 if ( scale === "box" || scale === "both" ) { 11140 11141 // Vertical props scaling 11142 if ( factor.from.y !== factor.to.y ) { 11143 props = props.concat( vProps ); 11144 el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from ); 11145 el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to ); 11146 } 11147 11148 // Horizontal props scaling 11149 if ( factor.from.x !== factor.to.x ) { 11150 props = props.concat( hProps ); 11151 el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from ); 11152 el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to ); 11153 } 11154 } 11155 11156 // Scale the content 11157 if ( scale === "content" || scale === "both" ) { 11158 11159 // Vertical props scaling 11160 if ( factor.from.y !== factor.to.y ) { 11161 props = props.concat( cProps ).concat( props2 ); 11162 el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from ); 11163 el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to ); 11164 } 11165 } 11166 11167 $.effects.save( el, props ); 11168 el.show(); 11169 $.effects.createWrapper( el ); 11170 el.css( "overflow", "hidden" ).css( el.from ); 11171 11172 // Adjust 11173 if (origin) { // Calculate baseline shifts 11174 baseline = $.effects.getBaseline( origin, original ); 11175 el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y; 11176 el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x; 11177 el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y; 11178 el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x; 11179 } 11180 el.css( el.from ); // set top & left 11181 11182 // Animate 11183 if ( scale === "content" || scale === "both" ) { // Scale the children 11184 11185 // Add margins/font-size 11186 vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps); 11187 hProps = hProps.concat([ "marginLeft", "marginRight" ]); 11188 props2 = props0.concat(vProps).concat(hProps); 11189 11190 el.find( "*[width]" ).each( function(){ 11191 var child = $( this ), 11192 c_original = { 11193 height: child.height(), 11194 width: child.width(), 11195 outerHeight: child.outerHeight(), 11196 outerWidth: child.outerWidth() 11197 }; 11198 if (restore) { 11199 $.effects.save(child, props2); 11200 } 11201 11202 child.from = { 11203 height: c_original.height * factor.from.y, 11204 width: c_original.width * factor.from.x, 11205 outerHeight: c_original.outerHeight * factor.from.y, 11206 outerWidth: c_original.outerWidth * factor.from.x 11207 }; 11208 child.to = { 11209 height: c_original.height * factor.to.y, 11210 width: c_original.width * factor.to.x, 11211 outerHeight: c_original.height * factor.to.y, 11212 outerWidth: c_original.width * factor.to.x 11213 }; 11214 11215 // Vertical props scaling 11216 if ( factor.from.y !== factor.to.y ) { 11217 child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from ); 11218 child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to ); 11219 } 11220 11221 // Horizontal props scaling 11222 if ( factor.from.x !== factor.to.x ) { 11223 child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from ); 11224 child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to ); 11225 } 11226 11227 // Animate children 11228 child.css( child.from ); 11229 child.animate( child.to, o.duration, o.easing, function() { 11230 11231 // Restore children 11232 if ( restore ) { 11233 $.effects.restore( child, props2 ); 11234 } 11235 }); 11236 }); 11237 } 11238 11239 // Animate 11240 el.animate( el.to, { 11241 queue: false, 11242 duration: o.duration, 11243 easing: o.easing, 11244 complete: function() { 11245 if ( el.to.opacity === 0 ) { 11246 el.css( "opacity", el.from.opacity ); 11247 } 11248 if( mode === "hide" ) { 11249 el.hide(); 11250 } 11251 $.effects.restore( el, props ); 11252 if ( !restore ) { 11253 11254 // we need to calculate our new positioning based on the scaling 11255 if ( position === "static" ) { 11256 el.css({ 11257 position: "relative", 11258 top: el.to.top, 11259 left: el.to.left 11260 }); 11261 } else { 11262 $.each([ "top", "left" ], function( idx, pos ) { 11263 el.css( pos, function( _, str ) { 11264 var val = parseInt( str, 10 ), 11265 toRef = idx ? el.to.left : el.to.top; 11266 11267 // if original was "auto", recalculate the new value from wrapper 11268 if ( str === "auto" ) { 11269 return toRef + "px"; 11270 } 11271 11272 return val + toRef + "px"; 11273 }); 11274 }); 11275 } 11276 } 11277 11278 $.effects.removeWrapper( el ); 11279 done(); 11280 } 11281 }); 11282 11283}; 11284 11285})(jQuery); 11286 11287(function( $, undefined ) { 11288 11289$.effects.effect.shake = function( o, done ) { 11290 11291 var el = $( this ), 11292 props = [ "position", "top", "bottom", "left", "right", "height", "width" ], 11293 mode = $.effects.setMode( el, o.mode || "effect" ), 11294 direction = o.direction || "left", 11295 distance = o.distance || 20, 11296 times = o.times || 3, 11297 anims = times * 2 + 1, 11298 speed = Math.round(o.duration/anims), 11299 ref = (direction === "up" || direction === "down") ? "top" : "left", 11300 positiveMotion = (direction === "up" || direction === "left"), 11301 animation = {}, 11302 animation1 = {}, 11303 animation2 = {}, 11304 i, 11305 11306 // we will need to re-assemble the queue to stack our animations in place 11307 queue = el.queue(), 11308 queuelen = queue.length; 11309 11310 $.effects.save( el, props ); 11311 el.show(); 11312 $.effects.createWrapper( el ); 11313 11314 // Animation 11315 animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; 11316 animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; 11317 animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; 11318 11319 // Animate 11320 el.animate( animation, speed, o.easing ); 11321 11322 // Shakes 11323 for ( i = 1; i < times; i++ ) { 11324 el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing ); 11325 } 11326 el 11327 .animate( animation1, speed, o.easing ) 11328 .animate( animation, speed / 2, o.easing ) 11329 .queue(function() { 11330 if ( mode === "hide" ) { 11331 el.hide(); 11332 } 11333 $.effects.restore( el, props ); 11334 $.effects.removeWrapper( el ); 11335 done(); 11336 }); 11337 11338 // inject all the animations we just queued to be first in line (after "inprogress") 11339 if ( queuelen > 1) { 11340 queue.splice.apply( queue, 11341 [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); 11342 } 11343 el.dequeue(); 11344 11345}; 11346 11347})(jQuery); 11348 11349(function( $, undefined ) { 11350 11351$.effects.effect.slide = function( o, done ) { 11352 11353 // Create element 11354 var el = $( this ), 11355 props = [ "position", "top", "bottom", "left", "right", "width", "height" ], 11356 mode = $.effects.setMode( el, o.mode || "show" ), 11357 show = mode === "show", 11358 direction = o.direction || "left", 11359 ref = (direction === "up" || direction === "down") ? "top" : "left", 11360 positiveMotion = (direction === "up" || direction === "left"), 11361 distance, 11362 animation = {}; 11363 11364 // Adjust 11365 $.effects.save( el, props ); 11366 el.show(); 11367 distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ); 11368 11369 $.effects.createWrapper( el ).css({ 11370 overflow: "hidden" 11371 }); 11372 11373 if ( show ) { 11374 el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance ); 11375 } 11376 11377 // Animation 11378 animation[ ref ] = ( show ? 11379 ( positiveMotion ? "+=" : "-=") : 11380 ( positiveMotion ? "-=" : "+=")) + 11381 distance; 11382 11383 // Animate 11384 el.animate( animation, { 11385 queue: false, 11386 duration: o.duration, 11387 easing: o.easing, 11388 complete: function() { 11389 if ( mode === "hide" ) { 11390 el.hide(); 11391 } 11392 $.effects.restore( el, props ); 11393 $.effects.removeWrapper( el ); 11394 done(); 11395 } 11396 }); 11397}; 11398 11399})(jQuery); 11400 11401(function( $, undefined ) { 11402 11403$.effects.effect.transfer = function( o, done ) { 11404 var elem = $( this ), 11405 target = $( o.to ), 11406 targetFixed = target.css( "position" ) === "fixed", 11407 body = $("body"), 11408 fixTop = targetFixed ? body.scrollTop() : 0, 11409 fixLeft = targetFixed ? body.scrollLeft() : 0, 11410 endPosition = target.offset(), 11411 animation = { 11412 top: endPosition.top - fixTop , 11413 left: endPosition.left - fixLeft , 11414 height: target.innerHeight(), 11415 width: target.innerWidth() 11416 }, 11417 startPosition = elem.offset(), 11418 transfer = $( "<div class='ui-effects-transfer'></div>" ) 11419 .appendTo( document.body ) 11420 .addClass( o.className ) 11421 .css({ 11422 top: startPosition.top - fixTop , 11423 left: startPosition.left - fixLeft , 11424 height: elem.innerHeight(), 11425 width: elem.innerWidth(), 11426 position: targetFixed ? "fixed" : "absolute" 11427 }) 11428 .animate( animation, o.duration, o.easing, function() { 11429 transfer.remove(); 11430 done(); 11431 }); 11432}; 11433 11434})(jQuery); 11435 11436(function( $, undefined ) { 11437 11438$.widget( "ui.menu", { 11439 version: "1.10.4", 11440 defaultElement: "<ul>", 11441 delay: 300, 11442 options: { 11443 icons: { 11444 submenu: "ui-icon-carat-1-e" 11445 }, 11446 menus: "ul", 11447 position: { 11448 my: "left top", 11449 at: "right top" 11450 }, 11451 role: "menu", 11452 11453 // callbacks 11454 blur: null, 11455 focus: null, 11456 select: null 11457 }, 11458 11459 _create: function() { 11460 this.activeMenu = this.element; 11461 // flag used to prevent firing of the click handler 11462 // as the event bubbles up through nested menus 11463 this.mouseHandled = false; 11464 this.element 11465 .uniqueId() 11466 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) 11467 .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ) 11468 .attr({ 11469 role: this.options.role, 11470 tabIndex: 0 11471 }) 11472 // need to catch all clicks on disabled menu 11473 // not possible through _on 11474 .bind( "click" + this.eventNamespace, $.proxy(function( event ) { 11475 if ( this.options.disabled ) { 11476 event.preventDefault(); 11477 } 11478 }, this )); 11479 11480 if ( this.options.disabled ) { 11481 this.element 11482 .addClass( "ui-state-disabled" ) 11483 .attr( "aria-disabled", "true" ); 11484 } 11485 11486 this._on({ 11487 // Prevent focus from sticking to links inside menu after clicking 11488 // them (focus should always stay on UL during navigation). 11489 "mousedown .ui-menu-item > a": function( event ) { 11490 event.preventDefault(); 11491 }, 11492 "click .ui-state-disabled > a": function( event ) { 11493 event.preventDefault(); 11494 }, 11495 "click .ui-menu-item:has(a)": function( event ) { 11496 var target = $( event.target ).closest( ".ui-menu-item" ); 11497 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) { 11498 this.select( event ); 11499 11500 // Only set the mouseHandled flag if the event will bubble, see #9469. 11501 if ( !event.isPropagationStopped() ) { 11502 this.mouseHandled = true; 11503 } 11504 11505 // Open submenu on click 11506 if ( target.has( ".ui-menu" ).length ) { 11507 this.expand( event ); 11508 } else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) { 11509 11510 // Redirect focus to the menu 11511 this.element.trigger( "focus", [ true ] ); 11512 11513 // If the active item is on the top level, let it stay active. 11514 // Otherwise, blur the active item since it is no longer visible. 11515 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) { 11516 clearTimeout( this.timer ); 11517 } 11518 } 11519 } 11520 }, 11521 "mouseenter .ui-menu-item": function( event ) { 11522 var target = $( event.currentTarget ); 11523 // Remove ui-state-active class from siblings of the newly focused menu item 11524 // to avoid a jump caused by adjacent elements both having a class with a border 11525 target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" ); 11526 this.focus( event, target ); 11527 }, 11528 mouseleave: "collapseAll", 11529 "mouseleave .ui-menu": "collapseAll", 11530 focus: function( event, keepActiveItem ) { 11531 // If there's already an active item, keep it active 11532 // If not, activate the first item 11533 var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 ); 11534 11535 if ( !keepActiveItem ) { 11536 this.focus( event, item ); 11537 } 11538 }, 11539 blur: function( event ) { 11540 this._delay(function() { 11541 if ( !$.contains( this.element[0], this.document[0].activeElement ) ) { 11542 this.collapseAll( event ); 11543 } 11544 }); 11545 }, 11546 keydown: "_keydown" 11547 }); 11548 11549 this.refresh(); 11550 11551 // Clicks outside of a menu collapse any open menus 11552 this._on( this.document, { 11553 click: function( event ) { 11554 if ( !$( event.target ).closest( ".ui-menu" ).length ) { 11555 this.collapseAll( event ); 11556 } 11557 11558 // Reset the mouseHandled flag 11559 this.mouseHandled = false; 11560 } 11561 }); 11562 }, 11563 11564 _destroy: function() { 11565 // Destroy (sub)menus 11566 this.element 11567 .removeAttr( "aria-activedescendant" ) 11568 .find( ".ui-menu" ).addBack() 11569 .removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" ) 11570 .removeAttr( "role" ) 11571 .removeAttr( "tabIndex" ) 11572 .removeAttr( "aria-labelledby" ) 11573 .removeAttr( "aria-expanded" ) 11574 .removeAttr( "aria-hidden" ) 11575 .removeAttr( "aria-disabled" ) 11576 .removeUniqueId() 11577 .show(); 11578 11579 // Destroy menu items 11580 this.element.find( ".ui-menu-item" ) 11581 .removeClass( "ui-menu-item" ) 11582 .removeAttr( "role" ) 11583 .removeAttr( "aria-disabled" ) 11584 .children( "a" ) 11585 .removeUniqueId() 11586 .removeClass( "ui-corner-all ui-state-hover" ) 11587 .removeAttr( "tabIndex" ) 11588 .removeAttr( "role" ) 11589 .removeAttr( "aria-haspopup" ) 11590 .children().each( function() { 11591 var elem = $( this ); 11592 if ( elem.data( "ui-menu-submenu-carat" ) ) { 11593 elem.remove(); 11594 } 11595 }); 11596 11597 // Destroy menu dividers 11598 this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" ); 11599 }, 11600 11601 _keydown: function( event ) { 11602 var match, prev, character, skip, regex, 11603 preventDefault = true; 11604 11605 function escape( value ) { 11606 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ); 11607 } 11608 11609 switch ( event.keyCode ) { 11610 case $.ui.keyCode.PAGE_UP: 11611 this.previousPage( event ); 11612 break; 11613 case $.ui.keyCode.PAGE_DOWN: 11614 this.nextPage( event ); 11615 break; 11616 case $.ui.keyCode.HOME: 11617 this._move( "first", "first", event ); 11618 break; 11619 case $.ui.keyCode.END: 11620 this._move( "last", "last", event ); 11621 break; 11622 case $.ui.keyCode.UP: 11623 this.previous( event ); 11624 break; 11625 case $.ui.keyCode.DOWN: 11626 this.next( event ); 11627 break; 11628 case $.ui.keyCode.LEFT: 11629 this.collapse( event ); 11630 break; 11631 case $.ui.keyCode.RIGHT: 11632 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { 11633 this.expand( event ); 11634 } 11635 break; 11636 case $.ui.keyCode.ENTER: 11637 case $.ui.keyCode.SPACE: 11638 this._activate( event ); 11639 break; 11640 case $.ui.keyCode.ESCAPE: 11641 this.collapse( event ); 11642 break; 11643 default: 11644 preventDefault = false; 11645 prev = this.previousFilter || ""; 11646 character = String.fromCharCode( event.keyCode ); 11647 skip = false; 11648 11649 clearTimeout( this.filterTimer ); 11650 11651 if ( character === prev ) { 11652 skip = true; 11653 } else { 11654 character = prev + character; 11655 } 11656 11657 regex = new RegExp( "^" + escape( character ), "i" ); 11658 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { 11659 return regex.test( $( this ).children( "a" ).text() ); 11660 }); 11661 match = skip && match.index( this.active.next() ) !== -1 ? 11662 this.active.nextAll( ".ui-menu-item" ) : 11663 match; 11664 11665 // If no matches on the current filter, reset to the last character pressed 11666 // to move down the menu to the first item that starts with that character 11667 if ( !match.length ) { 11668 character = String.fromCharCode( event.keyCode ); 11669 regex = new RegExp( "^" + escape( character ), "i" ); 11670 match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { 11671 return regex.test( $( this ).children( "a" ).text() ); 11672 }); 11673 } 11674 11675 if ( match.length ) { 11676 this.focus( event, match ); 11677 if ( match.length > 1 ) { 11678 this.previousFilter = character; 11679 this.filterTimer = this._delay(function() { 11680 delete this.previousFilter; 11681 }, 1000 ); 11682 } else { 11683 delete this.previousFilter; 11684 } 11685 } else { 11686 delete this.previousFilter; 11687 } 11688 } 11689 11690 if ( preventDefault ) { 11691 event.preventDefault(); 11692 } 11693 }, 11694 11695 _activate: function( event ) { 11696 if ( !this.active.is( ".ui-state-disabled" ) ) { 11697 if ( this.active.children( "a[aria-haspopup='true']" ).length ) { 11698 this.expand( event ); 11699 } else { 11700 this.select( event ); 11701 } 11702 } 11703 }, 11704 11705 refresh: function() { 11706 var menus, 11707 icon = this.options.icons.submenu, 11708 submenus = this.element.find( this.options.menus ); 11709 11710 this.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ); 11711 11712 // Initialize nested menus 11713 submenus.filter( ":not(.ui-menu)" ) 11714 .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) 11715 .hide() 11716 .attr({ 11717 role: this.options.role, 11718 "aria-hidden": "true", 11719 "aria-expanded": "false" 11720 }) 11721 .each(function() { 11722 var menu = $( this ), 11723 item = menu.prev( "a" ), 11724 submenuCarat = $( "<span>" ) 11725 .addClass( "ui-menu-icon ui-icon " + icon ) 11726 .data( "ui-menu-submenu-carat", true ); 11727 11728 item 11729 .attr( "aria-haspopup", "true" ) 11730 .prepend( submenuCarat ); 11731 menu.attr( "aria-labelledby", item.attr( "id" ) ); 11732 }); 11733 11734 menus = submenus.add( this.element ); 11735 11736 // Don't refresh list items that are already adapted 11737 menus.children( ":not(.ui-menu-item):has(a)" ) 11738 .addClass( "ui-menu-item" ) 11739 .attr( "role", "presentation" ) 11740 .children( "a" ) 11741 .uniqueId() 11742 .addClass( "ui-corner-all" ) 11743 .attr({ 11744 tabIndex: -1, 11745 role: this._itemRole() 11746 }); 11747 11748 // Initialize unlinked menu-items containing spaces and/or dashes only as dividers 11749 menus.children( ":not(.ui-menu-item)" ).each(function() { 11750 var item = $( this ); 11751 // hyphen, em dash, en dash 11752 if ( !/[^\-\u2014\u2013\s]/.test( item.text() ) ) { 11753 item.addClass( "ui-widget-content ui-menu-divider" ); 11754 } 11755 }); 11756 11757 // Add aria-disabled attribute to any disabled menu item 11758 menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); 11759 11760 // If the active item has been removed, blur the menu 11761 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { 11762 this.blur(); 11763 } 11764 }, 11765 11766 _itemRole: function() { 11767 return { 11768 menu: "menuitem", 11769 listbox: "option" 11770 }[ this.options.role ]; 11771 }, 11772 11773 _setOption: function( key, value ) { 11774 if ( key === "icons" ) { 11775 this.element.find( ".ui-menu-icon" ) 11776 .removeClass( this.options.icons.submenu ) 11777 .addClass( value.submenu ); 11778 } 11779 this._super( key, value ); 11780 }, 11781 11782 focus: function( event, item ) { 11783 var nested, focused; 11784 this.blur( event, event && event.type === "focus" ); 11785 11786 this._scrollIntoView( item ); 11787 11788 this.active = item.first(); 11789 focused = this.active.children( "a" ).addClass( "ui-state-focus" ); 11790 // Only update aria-activedescendant if there's a role 11791 // otherwise we assume focus is managed elsewhere 11792 if ( this.options.role ) { 11793 this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); 11794 } 11795 11796 // Highlight active parent menu item, if any 11797 this.active 11798 .parent() 11799 .closest( ".ui-menu-item" ) 11800 .children( "a:first" ) 11801 .addClass( "ui-state-active" ); 11802 11803 if ( event && event.type === "keydown" ) { 11804 this._close(); 11805 } else { 11806 this.timer = this._delay(function() { 11807 this._close(); 11808 }, this.delay ); 11809 } 11810 11811 nested = item.children( ".ui-menu" ); 11812 if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) { 11813 this._startOpening(nested); 11814 } 11815 this.activeMenu = item.parent(); 11816 11817 this._trigger( "focus", event, { item: item } ); 11818 }, 11819 11820 _scrollIntoView: function( item ) { 11821 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; 11822 if ( this._hasScroll() ) { 11823 borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0; 11824 paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0; 11825 offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; 11826 scroll = this.activeMenu.scrollTop(); 11827 elementHeight = this.activeMenu.height(); 11828 itemHeight = item.height(); 11829 11830 if ( offset < 0 ) { 11831 this.activeMenu.scrollTop( scroll + offset ); 11832 } else if ( offset + itemHeight > elementHeight ) { 11833 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); 11834 } 11835 } 11836 }, 11837 11838 blur: function( event, fromFocus ) { 11839 if ( !fromFocus ) { 11840 clearTimeout( this.timer ); 11841 } 11842 11843 if ( !this.active ) { 11844 return; 11845 } 11846 11847 this.active.children( "a" ).removeClass( "ui-state-focus" ); 11848 this.active = null; 11849 11850 this._trigger( "blur", event, { item: this.active } ); 11851 }, 11852 11853 _startOpening: function( submenu ) { 11854 clearTimeout( this.timer ); 11855 11856 // Don't open if already open fixes a Firefox bug that caused a .5 pixel 11857 // shift in the submenu position when mousing over the carat icon 11858 if ( submenu.attr( "aria-hidden" ) !== "true" ) { 11859 return; 11860 } 11861 11862 this.timer = this._delay(function() { 11863 this._close(); 11864 this._open( submenu ); 11865 }, this.delay ); 11866 }, 11867 11868 _open: function( submenu ) { 11869 var position = $.extend({ 11870 of: this.active 11871 }, this.options.position ); 11872 11873 clearTimeout( this.timer ); 11874 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) ) 11875 .hide() 11876 .attr( "aria-hidden", "true" ); 11877 11878 submenu 11879 .show() 11880 .removeAttr( "aria-hidden" ) 11881 .attr( "aria-expanded", "true" ) 11882 .position( position ); 11883 }, 11884 11885 collapseAll: function( event, all ) { 11886 clearTimeout( this.timer ); 11887 this.timer = this._delay(function() { 11888 // If we were passed an event, look for the submenu that contains the event 11889 var currentMenu = all ? this.element : 11890 $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); 11891 11892 // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway 11893 if ( !currentMenu.length ) { 11894 currentMenu = this.element; 11895 } 11896 11897 this._close( currentMenu ); 11898 11899 this.blur( event ); 11900 this.activeMenu = currentMenu; 11901 }, this.delay ); 11902 }, 11903 11904 // With no arguments, closes the currently active menu - if nothing is active 11905 // it closes all menus. If passed an argument, it will search for menus BELOW 11906 _close: function( startMenu ) { 11907 if ( !startMenu ) { 11908 startMenu = this.active ? this.active.parent() : this.element; 11909 } 11910 11911 startMenu 11912 .find( ".ui-menu" ) 11913 .hide() 11914 .attr( "aria-hidden", "true" ) 11915 .attr( "aria-expanded", "false" ) 11916 .end() 11917 .find( "a.ui-state-active" ) 11918 .removeClass( "ui-state-active" ); 11919 }, 11920 11921 collapse: function( event ) { 11922 var newItem = this.active && 11923 this.active.parent().closest( ".ui-menu-item", this.element ); 11924 if ( newItem && newItem.length ) { 11925 this._close(); 11926 this.focus( event, newItem ); 11927 } 11928 }, 11929 11930 expand: function( event ) { 11931 var newItem = this.active && 11932 this.active 11933 .children( ".ui-menu " ) 11934 .children( ".ui-menu-item" ) 11935 .first(); 11936 11937 if ( newItem && newItem.length ) { 11938 this._open( newItem.parent() ); 11939 11940 // Delay so Firefox will not hide activedescendant change in expanding submenu from AT 11941 this._delay(function() { 11942 this.focus( event, newItem ); 11943 }); 11944 } 11945 }, 11946 11947 next: function( event ) { 11948 this._move( "next", "first", event ); 11949 }, 11950 11951 previous: function( event ) { 11952 this._move( "prev", "last", event ); 11953 }, 11954 11955 isFirstItem: function() { 11956 return this.active && !this.active.prevAll( ".ui-menu-item" ).length; 11957 }, 11958 11959 isLastItem: function() { 11960 return this.active && !this.active.nextAll( ".ui-menu-item" ).length; 11961 }, 11962 11963 _move: function( direction, filter, event ) { 11964 var next; 11965 if ( this.active ) { 11966 if ( direction === "first" || direction === "last" ) { 11967 next = this.active 11968 [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) 11969 .eq( -1 ); 11970 } else { 11971 next = this.active 11972 [ direction + "All" ]( ".ui-menu-item" ) 11973 .eq( 0 ); 11974 } 11975 } 11976 if ( !next || !next.length || !this.active ) { 11977 next = this.activeMenu.children( ".ui-menu-item" )[ filter ](); 11978 } 11979 11980 this.focus( event, next ); 11981 }, 11982 11983 nextPage: function( event ) { 11984 var item, base, height; 11985 11986 if ( !this.active ) { 11987 this.next( event ); 11988 return; 11989 } 11990 if ( this.isLastItem() ) { 11991 return; 11992 } 11993 if ( this._hasScroll() ) { 11994 base = this.active.offset().top; 11995 height = this.element.height(); 11996 this.active.nextAll( ".ui-menu-item" ).each(function() { 11997 item = $( this ); 11998 return item.offset().top - base - height < 0; 11999 }); 12000 12001 this.focus( event, item ); 12002 } else { 12003 this.focus( event, this.activeMenu.children( ".ui-menu-item" ) 12004 [ !this.active ? "first" : "last" ]() ); 12005 } 12006 }, 12007 12008 previousPage: function( event ) { 12009 var item, base, height; 12010 if ( !this.active ) { 12011 this.next( event ); 12012 return; 12013 } 12014 if ( this.isFirstItem() ) { 12015 return; 12016 } 12017 if ( this._hasScroll() ) { 12018 base = this.active.offset().top; 12019 height = this.element.height(); 12020 this.active.prevAll( ".ui-menu-item" ).each(function() { 12021 item = $( this ); 12022 return item.offset().top - base + height > 0; 12023 }); 12024 12025 this.focus( event, item ); 12026 } else { 12027 this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() ); 12028 } 12029 }, 12030 12031 _hasScroll: function() { 12032 return this.element.outerHeight() < this.element.prop( "scrollHeight" ); 12033 }, 12034 12035 select: function( event ) { 12036 // TODO: It should never be possible to not have an active item at this 12037 // point, but the tests don't trigger mouseenter before click. 12038 this.active = this.active || $( event.target ).closest( ".ui-menu-item" ); 12039 var ui = { item: this.active }; 12040 if ( !this.active.has( ".ui-menu" ).length ) { 12041 this.collapseAll( event, true ); 12042 } 12043 this._trigger( "select", event, ui ); 12044 } 12045}); 12046 12047}( jQuery )); 12048 12049(function( $, undefined ) { 12050 12051$.ui = $.ui || {}; 12052 12053var cachedScrollbarWidth, 12054 max = Math.max, 12055 abs = Math.abs, 12056 round = Math.round, 12057 rhorizontal = /left|center|right/, 12058 rvertical = /top|center|bottom/, 12059 roffset = /[\+\-]\d+(\.[\d]+)?%?/, 12060 rposition = /^\w+/, 12061 rpercent = /%$/, 12062 _position = $.fn.position; 12063 12064function getOffsets( offsets, width, height ) { 12065 return [ 12066 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), 12067 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) 12068 ]; 12069} 12070 12071function parseCss( element, property ) { 12072 return parseInt( $.css( element, property ), 10 ) || 0; 12073} 12074 12075function getDimensions( elem ) { 12076 var raw = elem[0]; 12077 if ( raw.nodeType === 9 ) { 12078 return { 12079 width: elem.width(), 12080 height: elem.height(), 12081 offset: { top: 0, left: 0 } 12082 }; 12083 } 12084 if ( $.isWindow( raw ) ) { 12085 return { 12086 width: elem.width(), 12087 height: elem.height(), 12088 offset: { top: elem.scrollTop(), left: elem.scrollLeft() } 12089 }; 12090 } 12091 if ( raw.preventDefault ) { 12092 return { 12093 width: 0, 12094 height: 0, 12095 offset: { top: raw.pageY, left: raw.pageX } 12096 }; 12097 } 12098 return { 12099 width: elem.outerWidth(), 12100 height: elem.outerHeight(), 12101 offset: elem.offset() 12102 }; 12103} 12104 12105$.position = { 12106 scrollbarWidth: function() { 12107 if ( cachedScrollbarWidth !== undefined ) { 12108 return cachedScrollbarWidth; 12109 } 12110 var w1, w2, 12111 div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ), 12112 innerDiv = div.children()[0]; 12113 12114 $( "body" ).append( div ); 12115 w1 = innerDiv.offsetWidth; 12116 div.css( "overflow", "scroll" ); 12117 12118 w2 = innerDiv.offsetWidth; 12119 12120 if ( w1 === w2 ) { 12121 w2 = div[0].clientWidth; 12122 } 12123 12124 div.remove(); 12125 12126 return (cachedScrollbarWidth = w1 - w2); 12127 }, 12128 getScrollInfo: function( within ) { 12129 var overflowX = within.isWindow || within.isDocument ? "" : 12130 within.element.css( "overflow-x" ), 12131 overflowY = within.isWindow || within.isDocument ? "" : 12132 within.element.css( "overflow-y" ), 12133 hasOverflowX = overflowX === "scroll" || 12134 ( overflowX === "auto" && within.width < within.element[0].scrollWidth ), 12135 hasOverflowY = overflowY === "scroll" || 12136 ( overflowY === "auto" && within.height < within.element[0].scrollHeight ); 12137 return { 12138 width: hasOverflowY ? $.position.scrollbarWidth() : 0, 12139 height: hasOverflowX ? $.position.scrollbarWidth() : 0 12140 }; 12141 }, 12142 getWithinInfo: function( element ) { 12143 var withinElement = $( element || window ), 12144 isWindow = $.isWindow( withinElement[0] ), 12145 isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9; 12146 return { 12147 element: withinElement, 12148 isWindow: isWindow, 12149 isDocument: isDocument, 12150 offset: withinElement.offset() || { left: 0, top: 0 }, 12151 scrollLeft: withinElement.scrollLeft(), 12152 scrollTop: withinElement.scrollTop(), 12153 width: isWindow ? withinElement.width() : withinElement.outerWidth(), 12154 height: isWindow ? withinElement.height() : withinElement.outerHeight() 12155 }; 12156 } 12157}; 12158 12159$.fn.position = function( options ) { 12160 if ( !options || !options.of ) { 12161 return _position.apply( this, arguments ); 12162 } 12163 12164 // make a copy, we don't want to modify arguments 12165 options = $.extend( {}, options ); 12166 12167 var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, 12168 target = $( options.of ), 12169 within = $.position.getWithinInfo( options.within ), 12170 scrollInfo = $.position.getScrollInfo( within ), 12171 collision = ( options.collision || "flip" ).split( " " ), 12172 offsets = {}; 12173 12174 dimensions = getDimensions( target ); 12175 if ( target[0].preventDefault ) { 12176 // force left top to allow flipping 12177 options.at = "left top"; 12178 } 12179 targetWidth = dimensions.width; 12180 targetHeight = dimensions.height; 12181 targetOffset = dimensions.offset; 12182 // clone to reuse original targetOffset later 12183 basePosition = $.extend( {}, targetOffset ); 12184 12185 // force my and at to have valid horizontal and vertical positions 12186 // if a value is missing or invalid, it will be converted to center 12187 $.each( [ "my", "at" ], function() { 12188 var pos = ( options[ this ] || "" ).split( " " ), 12189 horizontalOffset, 12190 verticalOffset; 12191 12192 if ( pos.length === 1) { 12193 pos = rhorizontal.test( pos[ 0 ] ) ? 12194 pos.concat( [ "center" ] ) : 12195 rvertical.test( pos[ 0 ] ) ? 12196 [ "center" ].concat( pos ) : 12197 [ "center", "center" ]; 12198 } 12199 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; 12200 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; 12201 12202 // calculate offsets 12203 horizontalOffset = roffset.exec( pos[ 0 ] ); 12204 verticalOffset = roffset.exec( pos[ 1 ] ); 12205 offsets[ this ] = [ 12206 horizontalOffset ? horizontalOffset[ 0 ] : 0, 12207 verticalOffset ? verticalOffset[ 0 ] : 0 12208 ]; 12209 12210 // reduce to just the positions without the offsets 12211 options[ this ] = [ 12212 rposition.exec( pos[ 0 ] )[ 0 ], 12213 rposition.exec( pos[ 1 ] )[ 0 ] 12214 ]; 12215 }); 12216 12217 // normalize collision option 12218 if ( collision.length === 1 ) { 12219 collision[ 1 ] = collision[ 0 ]; 12220 } 12221 12222 if ( options.at[ 0 ] === "right" ) { 12223 basePosition.left += targetWidth; 12224 } else if ( options.at[ 0 ] === "center" ) { 12225 basePosition.left += targetWidth / 2; 12226 } 12227 12228 if ( options.at[ 1 ] === "bottom" ) { 12229 basePosition.top += targetHeight; 12230 } else if ( options.at[ 1 ] === "center" ) { 12231 basePosition.top += targetHeight / 2; 12232 } 12233 12234 atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); 12235 basePosition.left += atOffset[ 0 ]; 12236 basePosition.top += atOffset[ 1 ]; 12237 12238 return this.each(function() { 12239 var collisionPosition, using, 12240 elem = $( this ), 12241 elemWidth = elem.outerWidth(), 12242 elemHeight = elem.outerHeight(), 12243 marginLeft = parseCss( this, "marginLeft" ), 12244 marginTop = parseCss( this, "marginTop" ), 12245 collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width, 12246 collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height, 12247 position = $.extend( {}, basePosition ), 12248 myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); 12249 12250 if ( options.my[ 0 ] === "right" ) { 12251 position.left -= elemWidth; 12252 } else if ( options.my[ 0 ] === "center" ) { 12253 position.left -= elemWidth / 2; 12254 } 12255 12256 if ( options.my[ 1 ] === "bottom" ) { 12257 position.top -= elemHeight; 12258 } else if ( options.my[ 1 ] === "center" ) { 12259 position.top -= elemHeight / 2; 12260 } 12261 12262 position.left += myOffset[ 0 ]; 12263 position.top += myOffset[ 1 ]; 12264 12265 // if the browser doesn't support fractions, then round for consistent results 12266 if ( !$.support.offsetFractions ) { 12267 position.left = round( position.left ); 12268 position.top = round( position.top ); 12269 } 12270 12271 collisionPosition = { 12272 marginLeft: marginLeft, 12273 marginTop: marginTop 12274 }; 12275 12276 $.each( [ "left", "top" ], function( i, dir ) { 12277 if ( $.ui.position[ collision[ i ] ] ) { 12278 $.ui.position[ collision[ i ] ][ dir ]( position, { 12279 targetWidth: targetWidth, 12280 targetHeight: targetHeight, 12281 elemWidth: elemWidth, 12282 elemHeight: elemHeight, 12283 collisionPosition: collisionPosition, 12284 collisionWidth: collisionWidth, 12285 collisionHeight: collisionHeight, 12286 offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], 12287 my: options.my, 12288 at: options.at, 12289 within: within, 12290 elem : elem 12291 }); 12292 } 12293 }); 12294 12295 if ( options.using ) { 12296 // adds feedback as second argument to using callback, if present 12297 using = function( props ) { 12298 var left = targetOffset.left - position.left, 12299 right = left + targetWidth - elemWidth, 12300 top = targetOffset.top - position.top, 12301 bottom = top + targetHeight - elemHeight, 12302 feedback = { 12303 target: { 12304 element: target, 12305 left: targetOffset.left, 12306 top: targetOffset.top, 12307 width: targetWidth, 12308 height: targetHeight 12309 }, 12310 element: { 12311 element: elem, 12312 left: position.left, 12313 top: position.top, 12314 width: elemWidth, 12315 height: elemHeight 12316 }, 12317 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", 12318 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" 12319 }; 12320 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { 12321 feedback.horizontal = "center"; 12322 } 12323 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { 12324 feedback.vertical = "middle"; 12325 } 12326 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { 12327 feedback.important = "horizontal"; 12328 } else { 12329 feedback.important = "vertical"; 12330 } 12331 options.using.call( this, props, feedback ); 12332 }; 12333 } 12334 12335 elem.offset( $.extend( position, { using: using } ) ); 12336 }); 12337}; 12338 12339$.ui.position = { 12340 fit: { 12341 left: function( position, data ) { 12342 var within = data.within, 12343 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, 12344 outerWidth = within.width, 12345 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 12346 overLeft = withinOffset - collisionPosLeft, 12347 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, 12348 newOverRight; 12349 12350 // element is wider than within 12351 if ( data.collisionWidth > outerWidth ) { 12352 // element is initially over the left side of within 12353 if ( overLeft > 0 && overRight <= 0 ) { 12354 newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset; 12355 position.left += overLeft - newOverRight; 12356 // element is initially over right side of within 12357 } else if ( overRight > 0 && overLeft <= 0 ) { 12358 position.left = withinOffset; 12359 // element is initially over both left and right sides of within 12360 } else { 12361 if ( overLeft > overRight ) { 12362 position.left = withinOffset + outerWidth - data.collisionWidth; 12363 } else { 12364 position.left = withinOffset; 12365 } 12366 } 12367 // too far left -> align with left edge 12368 } else if ( overLeft > 0 ) { 12369 position.left += overLeft; 12370 // too far right -> align with right edge 12371 } else if ( overRight > 0 ) { 12372 position.left -= overRight; 12373 // adjust based on position and margin 12374 } else { 12375 position.left = max( position.left - collisionPosLeft, position.left ); 12376 } 12377 }, 12378 top: function( position, data ) { 12379 var within = data.within, 12380 withinOffset = within.isWindow ? within.scrollTop : within.offset.top, 12381 outerHeight = data.within.height, 12382 collisionPosTop = position.top - data.collisionPosition.marginTop, 12383 overTop = withinOffset - collisionPosTop, 12384 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, 12385 newOverBottom; 12386 12387 // element is taller than within 12388 if ( data.collisionHeight > outerHeight ) { 12389 // element is initially over the top of within 12390 if ( overTop > 0 && overBottom <= 0 ) { 12391 newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset; 12392 position.top += overTop - newOverBottom; 12393 // element is initially over bottom of within 12394 } else if ( overBottom > 0 && overTop <= 0 ) { 12395 position.top = withinOffset; 12396 // element is initially over both top and bottom of within 12397 } else { 12398 if ( overTop > overBottom ) { 12399 position.top = withinOffset + outerHeight - data.collisionHeight; 12400 } else { 12401 position.top = withinOffset; 12402 } 12403 } 12404 // too far up -> align with top 12405 } else if ( overTop > 0 ) { 12406 position.top += overTop; 12407 // too far down -> align with bottom edge 12408 } else if ( overBottom > 0 ) { 12409 position.top -= overBottom; 12410 // adjust based on position and margin 12411 } else { 12412 position.top = max( position.top - collisionPosTop, position.top ); 12413 } 12414 } 12415 }, 12416 flip: { 12417 left: function( position, data ) { 12418 var within = data.within, 12419 withinOffset = within.offset.left + within.scrollLeft, 12420 outerWidth = within.width, 12421 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, 12422 collisionPosLeft = position.left - data.collisionPosition.marginLeft, 12423 overLeft = collisionPosLeft - offsetLeft, 12424 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, 12425 myOffset = data.my[ 0 ] === "left" ? 12426 -data.elemWidth : 12427 data.my[ 0 ] === "right" ? 12428 data.elemWidth : 12429 0, 12430 atOffset = data.at[ 0 ] === "left" ? 12431 data.targetWidth : 12432 data.at[ 0 ] === "right" ? 12433 -data.targetWidth : 12434 0, 12435 offset = -2 * data.offset[ 0 ], 12436 newOverRight, 12437 newOverLeft; 12438 12439 if ( overLeft < 0 ) { 12440 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset; 12441 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { 12442 position.left += myOffset + atOffset + offset; 12443 } 12444 } 12445 else if ( overRight > 0 ) { 12446 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft; 12447 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { 12448 position.left += myOffset + atOffset + offset; 12449 } 12450 } 12451 }, 12452 top: function( position, data ) { 12453 var within = data.within, 12454 withinOffset = within.offset.top + within.scrollTop, 12455 outerHeight = within.height, 12456 offsetTop = within.isWindow ? within.scrollTop : within.offset.top, 12457 collisionPosTop = position.top - data.collisionPosition.marginTop, 12458 overTop = collisionPosTop - offsetTop, 12459 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, 12460 top = data.my[ 1 ] === "top", 12461 myOffset = top ? 12462 -data.elemHeight : 12463 data.my[ 1 ] === "bottom" ? 12464 data.elemHeight : 12465 0, 12466 atOffset = data.at[ 1 ] === "top" ? 12467 data.targetHeight : 12468 data.at[ 1 ] === "bottom" ? 12469 -data.targetHeight : 12470 0, 12471 offset = -2 * data.offset[ 1 ], 12472 newOverTop, 12473 newOverBottom; 12474 if ( overTop < 0 ) { 12475 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset; 12476 if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) { 12477 position.top += myOffset + atOffset + offset; 12478 } 12479 } 12480 else if ( overBottom > 0 ) { 12481 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop; 12482 if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) { 12483 position.top += myOffset + atOffset + offset; 12484 } 12485 } 12486 } 12487 }, 12488 flipfit: { 12489 left: function() { 12490 $.ui.position.flip.left.apply( this, arguments ); 12491 $.ui.position.fit.left.apply( this, arguments ); 12492 }, 12493 top: function() { 12494 $.ui.position.flip.top.apply( this, arguments ); 12495 $.ui.position.fit.top.apply( this, arguments ); 12496 } 12497 } 12498}; 12499 12500// fraction support test 12501(function () { 12502 var testElement, testElementParent, testElementStyle, offsetLeft, i, 12503 body = document.getElementsByTagName( "body" )[ 0 ], 12504 div = document.createElement( "div" ); 12505 12506 //Create a "fake body" for testing based on method used in jQuery.support 12507 testElement = document.createElement( body ? "div" : "body" ); 12508 testElementStyle = { 12509 visibility: "hidden", 12510 width: 0, 12511 height: 0, 12512 border: 0, 12513 margin: 0, 12514 background: "none" 12515 }; 12516 if ( body ) { 12517 $.extend( testElementStyle, { 12518 position: "absolute", 12519 left: "-1000px", 12520 top: "-1000px" 12521 }); 12522 } 12523 for ( i in testElementStyle ) { 12524 testElement.style[ i ] = testElementStyle[ i ]; 12525 } 12526 testElement.appendChild( div ); 12527 testElementParent = body || document.documentElement; 12528 testElementParent.insertBefore( testElement, testElementParent.firstChild ); 12529 12530 div.style.cssText = "position: absolute; left: 10.7432222px;"; 12531 12532 offsetLeft = $( div ).offset().left; 12533 $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11; 12534 12535 testElement.innerHTML = ""; 12536 testElementParent.removeChild( testElement ); 12537})(); 12538 12539}( jQuery ) ); 12540 12541(function( $, undefined ) { 12542 12543$.widget( "ui.progressbar", { 12544 version: "1.10.4", 12545 options: { 12546 max: 100, 12547 value: 0, 12548 12549 change: null, 12550 complete: null 12551 }, 12552 12553 min: 0, 12554 12555 _create: function() { 12556 // Constrain initial value 12557 this.oldValue = this.options.value = this._constrainedValue(); 12558 12559 this.element 12560 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) 12561 .attr({ 12562 // Only set static values, aria-valuenow and aria-valuemax are 12563 // set inside _refreshValue() 12564 role: "progressbar", 12565 "aria-valuemin": this.min 12566 }); 12567 12568 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" ) 12569 .appendTo( this.element ); 12570 12571 this._refreshValue(); 12572 }, 12573 12574 _destroy: function() { 12575 this.element 12576 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) 12577 .removeAttr( "role" ) 12578 .removeAttr( "aria-valuemin" ) 12579 .removeAttr( "aria-valuemax" ) 12580 .removeAttr( "aria-valuenow" ); 12581 12582 this.valueDiv.remove(); 12583 }, 12584 12585 value: function( newValue ) { 12586 if ( newValue === undefined ) { 12587 return this.options.value; 12588 } 12589 12590 this.options.value = this._constrainedValue( newValue ); 12591 this._refreshValue(); 12592 }, 12593 12594 _constrainedValue: function( newValue ) { 12595 if ( newValue === undefined ) { 12596 newValue = this.options.value; 12597 } 12598 12599 this.indeterminate = newValue === false; 12600 12601 // sanitize value 12602 if ( typeof newValue !== "number" ) { 12603 newValue = 0; 12604 } 12605 12606 return this.indeterminate ? false : 12607 Math.min( this.options.max, Math.max( this.min, newValue ) ); 12608 }, 12609 12610 _setOptions: function( options ) { 12611 // Ensure "value" option is set after other values (like max) 12612 var value = options.value; 12613 delete options.value; 12614 12615 this._super( options ); 12616 12617 this.options.value = this._constrainedValue( value ); 12618 this._refreshValue(); 12619 }, 12620 12621 _setOption: function( key, value ) { 12622 if ( key === "max" ) { 12623 // Don't allow a max less than min 12624 value = Math.max( this.min, value ); 12625 } 12626 12627 this._super( key, value ); 12628 }, 12629 12630 _percentage: function() { 12631 return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min ); 12632 }, 12633 12634 _refreshValue: function() { 12635 var value = this.options.value, 12636 percentage = this._percentage(); 12637 12638 this.valueDiv 12639 .toggle( this.indeterminate || value > this.min ) 12640 .toggleClass( "ui-corner-right", value === this.options.max ) 12641 .width( percentage.toFixed(0) + "%" ); 12642 12643 this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate ); 12644 12645 if ( this.indeterminate ) { 12646 this.element.removeAttr( "aria-valuenow" ); 12647 if ( !this.overlayDiv ) { 12648 this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv ); 12649 } 12650 } else { 12651 this.element.attr({ 12652 "aria-valuemax": this.options.max, 12653 "aria-valuenow": value 12654 }); 12655 if ( this.overlayDiv ) { 12656 this.overlayDiv.remove(); 12657 this.overlayDiv = null; 12658 } 12659 } 12660 12661 if ( this.oldValue !== value ) { 12662 this.oldValue = value; 12663 this._trigger( "change" ); 12664 } 12665 if ( value === this.options.max ) { 12666 this._trigger( "complete" ); 12667 } 12668 } 12669}); 12670 12671})( jQuery ); 12672 12673(function( $, undefined ) { 12674 12675// number of pages in a slider 12676// (how many times can you page up/down to go through the whole range) 12677var numPages = 5; 12678 12679$.widget( "ui.slider", $.ui.mouse, { 12680 version: "1.10.4", 12681 widgetEventPrefix: "slide", 12682 12683 options: { 12684 animate: false, 12685 distance: 0, 12686 max: 100, 12687 min: 0, 12688 orientation: "horizontal", 12689 range: false, 12690 step: 1, 12691 value: 0, 12692 values: null, 12693 12694 // callbacks 12695 change: null, 12696 slide: null, 12697 start: null, 12698 stop: null 12699 }, 12700 12701 _create: function() { 12702 this._keySliding = false; 12703 this._mouseSliding = false; 12704 this._animateOff = true; 12705 this._handleIndex = null; 12706 this._detectOrientation(); 12707 this._mouseInit(); 12708 12709 this.element 12710 .addClass( "ui-slider" + 12711 " ui-slider-" + this.orientation + 12712 " ui-widget" + 12713 " ui-widget-content" + 12714 " ui-corner-all"); 12715 12716 this._refresh(); 12717 this._setOption( "disabled", this.options.disabled ); 12718 12719 this._animateOff = false; 12720 }, 12721 12722 _refresh: function() { 12723 this._createRange(); 12724 this._createHandles(); 12725 this._setupEvents(); 12726 this._refreshValue(); 12727 }, 12728 12729 _createHandles: function() { 12730 var i, handleCount, 12731 options = this.options, 12732 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), 12733 handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>", 12734 handles = []; 12735 12736 handleCount = ( options.values && options.values.length ) || 1; 12737 12738 if ( existingHandles.length > handleCount ) { 12739 existingHandles.slice( handleCount ).remove(); 12740 existingHandles = existingHandles.slice( 0, handleCount ); 12741 } 12742 12743 for ( i = existingHandles.length; i < handleCount; i++ ) { 12744 handles.push( handle ); 12745 } 12746 12747 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) ); 12748 12749 this.handle = this.handles.eq( 0 ); 12750 12751 this.handles.each(function( i ) { 12752 $( this ).data( "ui-slider-handle-index", i ); 12753 }); 12754 }, 12755 12756 _createRange: function() { 12757 var options = this.options, 12758 classes = ""; 12759 12760 if ( options.range ) { 12761 if ( options.range === true ) { 12762 if ( !options.values ) { 12763 options.values = [ this._valueMin(), this._valueMin() ]; 12764 } else if ( options.values.length && options.values.length !== 2 ) { 12765 options.values = [ options.values[0], options.values[0] ]; 12766 } else if ( $.isArray( options.values ) ) { 12767 options.values = options.values.slice(0); 12768 } 12769 } 12770 12771 if ( !this.range || !this.range.length ) { 12772 this.range = $( "<div></div>" ) 12773 .appendTo( this.element ); 12774 12775 classes = "ui-slider-range" + 12776 // note: this isn't the most fittingly semantic framework class for this element, 12777 // but worked best visually with a variety of themes 12778 " ui-widget-header ui-corner-all"; 12779 } else { 12780 this.range.removeClass( "ui-slider-range-min ui-slider-range-max" ) 12781 // Handle range switching from true to min/max 12782 .css({ 12783 "left": "", 12784 "bottom": "" 12785 }); 12786 } 12787 12788 this.range.addClass( classes + 12789 ( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) ); 12790 } else { 12791 if ( this.range ) { 12792 this.range.remove(); 12793 } 12794 this.range = null; 12795 } 12796 }, 12797 12798 _setupEvents: function() { 12799 var elements = this.handles.add( this.range ).filter( "a" ); 12800 this._off( elements ); 12801 this._on( elements, this._handleEvents ); 12802 this._hoverable( elements ); 12803 this._focusable( elements ); 12804 }, 12805 12806 _destroy: function() { 12807 this.handles.remove(); 12808 if ( this.range ) { 12809 this.range.remove(); 12810 } 12811 12812 this.element 12813 .removeClass( "ui-slider" + 12814 " ui-slider-horizontal" + 12815 " ui-slider-vertical" + 12816 " ui-widget" + 12817 " ui-widget-content" + 12818 " ui-corner-all" ); 12819 12820 this._mouseDestroy(); 12821 }, 12822 12823 _mouseCapture: function( event ) { 12824 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, 12825 that = this, 12826 o = this.options; 12827 12828 if ( o.disabled ) { 12829 return false; 12830 } 12831 12832 this.elementSize = { 12833 width: this.element.outerWidth(), 12834 height: this.element.outerHeight() 12835 }; 12836 this.elementOffset = this.element.offset(); 12837 12838 position = { x: event.pageX, y: event.pageY }; 12839 normValue = this._normValueFromMouse( position ); 12840 distance = this._valueMax() - this._valueMin() + 1; 12841 this.handles.each(function( i ) { 12842 var thisDistance = Math.abs( normValue - that.values(i) ); 12843 if (( distance > thisDistance ) || 12844 ( distance === thisDistance && 12845 (i === that._lastChangedValue || that.values(i) === o.min ))) { 12846 distance = thisDistance; 12847 closestHandle = $( this ); 12848 index = i; 12849 } 12850 }); 12851 12852 allowed = this._start( event, index ); 12853 if ( allowed === false ) { 12854 return false; 12855 } 12856 this._mouseSliding = true; 12857 12858 this._handleIndex = index; 12859 12860 closestHandle 12861 .addClass( "ui-state-active" ) 12862 .focus(); 12863 12864 offset = closestHandle.offset(); 12865 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" ); 12866 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { 12867 left: event.pageX - offset.left - ( closestHandle.width() / 2 ), 12868 top: event.pageY - offset.top - 12869 ( closestHandle.height() / 2 ) - 12870 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - 12871 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + 12872 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) 12873 }; 12874 12875 if ( !this.handles.hasClass( "ui-state-hover" ) ) { 12876 this._slide( event, index, normValue ); 12877 } 12878 this._animateOff = true; 12879 return true; 12880 }, 12881 12882 _mouseStart: function() { 12883 return true; 12884 }, 12885 12886 _mouseDrag: function( event ) { 12887 var position = { x: event.pageX, y: event.pageY }, 12888 normValue = this._normValueFromMouse( position ); 12889 12890 this._slide( event, this._handleIndex, normValue ); 12891 12892 return false; 12893 }, 12894 12895 _mouseStop: function( event ) { 12896 this.handles.removeClass( "ui-state-active" ); 12897 this._mouseSliding = false; 12898 12899 this._stop( event, this._handleIndex ); 12900 this._change( event, this._handleIndex ); 12901 12902 this._handleIndex = null; 12903 this._clickOffset = null; 12904 this._animateOff = false; 12905 12906 return false; 12907 }, 12908 12909 _detectOrientation: function() { 12910 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; 12911 }, 12912 12913 _normValueFromMouse: function( position ) { 12914 var pixelTotal, 12915 pixelMouse, 12916 percentMouse, 12917 valueTotal, 12918 valueMouse; 12919 12920 if ( this.orientation === "horizontal" ) { 12921 pixelTotal = this.elementSize.width; 12922 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); 12923 } else { 12924 pixelTotal = this.elementSize.height; 12925 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); 12926 } 12927 12928 percentMouse = ( pixelMouse / pixelTotal ); 12929 if ( percentMouse > 1 ) { 12930 percentMouse = 1; 12931 } 12932 if ( percentMouse < 0 ) { 12933 percentMouse = 0; 12934 } 12935 if ( this.orientation === "vertical" ) { 12936 percentMouse = 1 - percentMouse; 12937 } 12938 12939 valueTotal = this._valueMax() - this._valueMin(); 12940 valueMouse = this._valueMin() + percentMouse * valueTotal; 12941 12942 return this._trimAlignValue( valueMouse ); 12943 }, 12944 12945 _start: function( event, index ) { 12946 var uiHash = { 12947 handle: this.handles[ index ], 12948 value: this.value() 12949 }; 12950 if ( this.options.values && this.options.values.length ) { 12951 uiHash.value = this.values( index ); 12952 uiHash.values = this.values(); 12953 } 12954 return this._trigger( "start", event, uiHash ); 12955 }, 12956 12957 _slide: function( event, index, newVal ) { 12958 var otherVal, 12959 newValues, 12960 allowed; 12961 12962 if ( this.options.values && this.options.values.length ) { 12963 otherVal = this.values( index ? 0 : 1 ); 12964 12965 if ( ( this.options.values.length === 2 && this.options.range === true ) && 12966 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) 12967 ) { 12968 newVal = otherVal; 12969 } 12970 12971 if ( newVal !== this.values( index ) ) { 12972 newValues = this.values(); 12973 newValues[ index ] = newVal; 12974 // A slide can be canceled by returning false from the slide callback 12975 allowed = this._trigger( "slide", event, { 12976 handle: this.handles[ index ], 12977 value: newVal, 12978 values: newValues 12979 } ); 12980 otherVal = this.values( index ? 0 : 1 ); 12981 if ( allowed !== false ) { 12982 this.values( index, newVal ); 12983 } 12984 } 12985 } else { 12986 if ( newVal !== this.value() ) { 12987 // A slide can be canceled by returning false from the slide callback 12988 allowed = this._trigger( "slide", event, { 12989 handle: this.handles[ index ], 12990 value: newVal 12991 } ); 12992 if ( allowed !== false ) { 12993 this.value( newVal ); 12994 } 12995 } 12996 } 12997 }, 12998 12999 _stop: function( event, index ) { 13000 var uiHash = { 13001 handle: this.handles[ index ], 13002 value: this.value() 13003 }; 13004 if ( this.options.values && this.options.values.length ) { 13005 uiHash.value = this.values( index ); 13006 uiHash.values = this.values(); 13007 } 13008 13009 this._trigger( "stop", event, uiHash ); 13010 }, 13011 13012 _change: function( event, index ) { 13013 if ( !this._keySliding && !this._mouseSliding ) { 13014 var uiHash = { 13015 handle: this.handles[ index ], 13016 value: this.value() 13017 }; 13018 if ( this.options.values && this.options.values.length ) { 13019 uiHash.value = this.values( index ); 13020 uiHash.values = this.values(); 13021 } 13022 13023 //store the last changed value index for reference when handles overlap 13024 this._lastChangedValue = index; 13025 13026 this._trigger( "change", event, uiHash ); 13027 } 13028 }, 13029 13030 value: function( newValue ) { 13031 if ( arguments.length ) { 13032 this.options.value = this._trimAlignValue( newValue ); 13033 this._refreshValue(); 13034 this._change( null, 0 ); 13035 return; 13036 } 13037 13038 return this._value(); 13039 }, 13040 13041 values: function( index, newValue ) { 13042 var vals, 13043 newValues, 13044 i; 13045 13046 if ( arguments.length > 1 ) { 13047 this.options.values[ index ] = this._trimAlignValue( newValue ); 13048 this._refreshValue(); 13049 this._change( null, index ); 13050 return; 13051 } 13052 13053 if ( arguments.length ) { 13054 if ( $.isArray( arguments[ 0 ] ) ) { 13055 vals = this.options.values; 13056 newValues = arguments[ 0 ]; 13057 for ( i = 0; i < vals.length; i += 1 ) { 13058 vals[ i ] = this._trimAlignValue( newValues[ i ] ); 13059 this._change( null, i ); 13060 } 13061 this._refreshValue(); 13062 } else { 13063 if ( this.options.values && this.options.values.length ) { 13064 return this._values( index ); 13065 } else { 13066 return this.value(); 13067 } 13068 } 13069 } else { 13070 return this._values(); 13071 } 13072 }, 13073 13074 _setOption: function( key, value ) { 13075 var i, 13076 valsLength = 0; 13077 13078 if ( key === "range" && this.options.range === true ) { 13079 if ( value === "min" ) { 13080 this.options.value = this._values( 0 ); 13081 this.options.values = null; 13082 } else if ( value === "max" ) { 13083 this.options.value = this._values( this.options.values.length-1 ); 13084 this.options.values = null; 13085 } 13086 } 13087 13088 if ( $.isArray( this.options.values ) ) { 13089 valsLength = this.options.values.length; 13090 } 13091 13092 $.Widget.prototype._setOption.apply( this, arguments ); 13093 13094 switch ( key ) { 13095 case "orientation": 13096 this._detectOrientation(); 13097 this.element 13098 .removeClass( "ui-slider-horizontal ui-slider-vertical" ) 13099 .addClass( "ui-slider-" + this.orientation ); 13100 this._refreshValue(); 13101 break; 13102 case "value": 13103 this._animateOff = true; 13104 this._refreshValue(); 13105 this._change( null, 0 ); 13106 this._animateOff = false; 13107 break; 13108 case "values": 13109 this._animateOff = true; 13110 this._refreshValue(); 13111 for ( i = 0; i < valsLength; i += 1 ) { 13112 this._change( null, i ); 13113 } 13114 this._animateOff = false; 13115 break; 13116 case "min": 13117 case "max": 13118 this._animateOff = true; 13119 this._refreshValue(); 13120 this._animateOff = false; 13121 break; 13122 case "range": 13123 this._animateOff = true; 13124 this._refresh(); 13125 this._animateOff = false; 13126 break; 13127 } 13128 }, 13129 13130 //internal value getter 13131 // _value() returns value trimmed by min and max, aligned by step 13132 _value: function() { 13133 var val = this.options.value; 13134 val = this._trimAlignValue( val ); 13135 13136 return val; 13137 }, 13138 13139 //internal values getter 13140 // _values() returns array of values trimmed by min and max, aligned by step 13141 // _values( index ) returns single value trimmed by min and max, aligned by step 13142 _values: function( index ) { 13143 var val, 13144 vals, 13145 i; 13146 13147 if ( arguments.length ) { 13148 val = this.options.values[ index ]; 13149 val = this._trimAlignValue( val ); 13150 13151 return val; 13152 } else if ( this.options.values && this.options.values.length ) { 13153 // .slice() creates a copy of the array 13154 // this copy gets trimmed by min and max and then returned 13155 vals = this.options.values.slice(); 13156 for ( i = 0; i < vals.length; i+= 1) { 13157 vals[ i ] = this._trimAlignValue( vals[ i ] ); 13158 } 13159 13160 return vals; 13161 } else { 13162 return []; 13163 } 13164 }, 13165 13166 // returns the step-aligned value that val is closest to, between (inclusive) min and max 13167 _trimAlignValue: function( val ) { 13168 if ( val <= this._valueMin() ) { 13169 return this._valueMin(); 13170 } 13171 if ( val >= this._valueMax() ) { 13172 return this._valueMax(); 13173 } 13174 var step = ( this.options.step > 0 ) ? this.options.step : 1, 13175 valModStep = (val - this._valueMin()) % step, 13176 alignValue = val - valModStep; 13177 13178 if ( Math.abs(valModStep) * 2 >= step ) { 13179 alignValue += ( valModStep > 0 ) ? step : ( -step ); 13180 } 13181 13182 // Since JavaScript has problems with large floats, round 13183 // the final value to 5 digits after the decimal point (see #4124) 13184 return parseFloat( alignValue.toFixed(5) ); 13185 }, 13186 13187 _valueMin: function() { 13188 return this.options.min; 13189 }, 13190 13191 _valueMax: function() { 13192 return this.options.max; 13193 }, 13194 13195 _refreshValue: function() { 13196 var lastValPercent, valPercent, value, valueMin, valueMax, 13197 oRange = this.options.range, 13198 o = this.options, 13199 that = this, 13200 animate = ( !this._animateOff ) ? o.animate : false, 13201 _set = {}; 13202 13203 if ( this.options.values && this.options.values.length ) { 13204 this.handles.each(function( i ) { 13205 valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100; 13206 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 13207 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 13208 if ( that.options.range === true ) { 13209 if ( that.orientation === "horizontal" ) { 13210 if ( i === 0 ) { 13211 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); 13212 } 13213 if ( i === 1 ) { 13214 that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); 13215 } 13216 } else { 13217 if ( i === 0 ) { 13218 that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); 13219 } 13220 if ( i === 1 ) { 13221 that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); 13222 } 13223 } 13224 } 13225 lastValPercent = valPercent; 13226 }); 13227 } else { 13228 value = this.value(); 13229 valueMin = this._valueMin(); 13230 valueMax = this._valueMax(); 13231 valPercent = ( valueMax !== valueMin ) ? 13232 ( value - valueMin ) / ( valueMax - valueMin ) * 100 : 13233 0; 13234 _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 13235 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 13236 13237 if ( oRange === "min" && this.orientation === "horizontal" ) { 13238 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); 13239 } 13240 if ( oRange === "max" && this.orientation === "horizontal" ) { 13241 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); 13242 } 13243 if ( oRange === "min" && this.orientation === "vertical" ) { 13244 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); 13245 } 13246 if ( oRange === "max" && this.orientation === "vertical" ) { 13247 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); 13248 } 13249 } 13250 }, 13251 13252 _handleEvents: { 13253 keydown: function( event ) { 13254 var allowed, curVal, newVal, step, 13255 index = $( event.target ).data( "ui-slider-handle-index" ); 13256 13257 switch ( event.keyCode ) { 13258 case $.ui.keyCode.HOME: 13259 case $.ui.keyCode.END: 13260 case $.ui.keyCode.PAGE_UP: 13261 case $.ui.keyCode.PAGE_DOWN: 13262 case $.ui.keyCode.UP: 13263 case $.ui.keyCode.RIGHT: 13264 case $.ui.keyCode.DOWN: 13265 case $.ui.keyCode.LEFT: 13266 event.preventDefault(); 13267 if ( !this._keySliding ) { 13268 this._keySliding = true; 13269 $( event.target ).addClass( "ui-state-active" ); 13270 allowed = this._start( event, index ); 13271 if ( allowed === false ) { 13272 return; 13273 } 13274 } 13275 break; 13276 } 13277 13278 step = this.options.step; 13279 if ( this.options.values && this.options.values.length ) { 13280 curVal = newVal = this.values( index ); 13281 } else { 13282 curVal = newVal = this.value(); 13283 } 13284 13285 switch ( event.keyCode ) { 13286 case $.ui.keyCode.HOME: 13287 newVal = this._valueMin(); 13288 break; 13289 case $.ui.keyCode.END: 13290 newVal = this._valueMax(); 13291 break; 13292 case $.ui.keyCode.PAGE_UP: 13293 newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) ); 13294 break; 13295 case $.ui.keyCode.PAGE_DOWN: 13296 newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) ); 13297 break; 13298 case $.ui.keyCode.UP: 13299 case $.ui.keyCode.RIGHT: 13300 if ( curVal === this._valueMax() ) { 13301 return; 13302 } 13303 newVal = this._trimAlignValue( curVal + step ); 13304 break; 13305 case $.ui.keyCode.DOWN: 13306 case $.ui.keyCode.LEFT: 13307 if ( curVal === this._valueMin() ) { 13308 return; 13309 } 13310 newVal = this._trimAlignValue( curVal - step ); 13311 break; 13312 } 13313 13314 this._slide( event, index, newVal ); 13315 }, 13316 click: function( event ) { 13317 event.preventDefault(); 13318 }, 13319 keyup: function( event ) { 13320 var index = $( event.target ).data( "ui-slider-handle-index" ); 13321 13322 if ( this._keySliding ) { 13323 this._keySliding = false; 13324 this._stop( event, index ); 13325 this._change( event, index ); 13326 $( event.target ).removeClass( "ui-state-active" ); 13327 } 13328 } 13329 } 13330 13331}); 13332 13333}(jQuery)); 13334 13335(function( $ ) { 13336 13337function modifier( fn ) { 13338 return function() { 13339 var previous = this.element.val(); 13340 fn.apply( this, arguments ); 13341 this._refresh(); 13342 if ( previous !== this.element.val() ) { 13343 this._trigger( "change" ); 13344 } 13345 }; 13346} 13347 13348$.widget( "ui.spinner", { 13349 version: "1.10.4", 13350 defaultElement: "<input>", 13351 widgetEventPrefix: "spin", 13352 options: { 13353 culture: null, 13354 icons: { 13355 down: "ui-icon-triangle-1-s", 13356 up: "ui-icon-triangle-1-n" 13357 }, 13358 incremental: true, 13359 max: null, 13360 min: null, 13361 numberFormat: null, 13362 page: 10, 13363 step: 1, 13364 13365 change: null, 13366 spin: null, 13367 start: null, 13368 stop: null 13369 }, 13370 13371 _create: function() { 13372 // handle string values that need to be parsed 13373 this._setOption( "max", this.options.max ); 13374 this._setOption( "min", this.options.min ); 13375 this._setOption( "step", this.options.step ); 13376 13377 // Only format if there is a value, prevents the field from being marked 13378 // as invalid in Firefox, see #9573. 13379 if ( this.value() !== "" ) { 13380 // Format the value, but don't constrain. 13381 this._value( this.element.val(), true ); 13382 } 13383 13384 this._draw(); 13385 this._on( this._events ); 13386 this._refresh(); 13387 13388 // turning off autocomplete prevents the browser from remembering the 13389 // value when navigating through history, so we re-enable autocomplete 13390 // if the page is unloaded before the widget is destroyed. #7790 13391 this._on( this.window, { 13392 beforeunload: function() { 13393 this.element.removeAttr( "autocomplete" ); 13394 } 13395 }); 13396 }, 13397 13398 _getCreateOptions: function() { 13399 var options = {}, 13400 element = this.element; 13401 13402 $.each( [ "min", "max", "step" ], function( i, option ) { 13403 var value = element.attr( option ); 13404 if ( value !== undefined && value.length ) { 13405 options[ option ] = value; 13406 } 13407 }); 13408 13409 return options; 13410 }, 13411 13412 _events: { 13413 keydown: function( event ) { 13414 if ( this._start( event ) && this._keydown( event ) ) { 13415 event.preventDefault(); 13416 } 13417 }, 13418 keyup: "_stop", 13419 focus: function() { 13420 this.previous = this.element.val(); 13421 }, 13422 blur: function( event ) { 13423 if ( this.cancelBlur ) { 13424 delete this.cancelBlur; 13425 return; 13426 } 13427 13428 this._stop(); 13429 this._refresh(); 13430 if ( this.previous !== this.element.val() ) { 13431 this._trigger( "change", event ); 13432 } 13433 }, 13434 mousewheel: function( event, delta ) { 13435 if ( !delta ) { 13436 return; 13437 } 13438 if ( !this.spinning && !this._start( event ) ) { 13439 return false; 13440 } 13441 13442 this._spin( (delta > 0 ? 1 : -1) * this.options.step, event ); 13443 clearTimeout( this.mousewheelTimer ); 13444 this.mousewheelTimer = this._delay(function() { 13445 if ( this.spinning ) { 13446 this._stop( event ); 13447 } 13448 }, 100 ); 13449 event.preventDefault(); 13450 }, 13451 "mousedown .ui-spinner-button": function( event ) { 13452 var previous; 13453 13454 // We never want the buttons to have focus; whenever the user is 13455 // interacting with the spinner, the focus should be on the input. 13456 // If the input is focused then this.previous is properly set from 13457 // when the input first received focus. If the input is not focused 13458 // then we need to set this.previous based on the value before spinning. 13459 previous = this.element[0] === this.document[0].activeElement ? 13460 this.previous : this.element.val(); 13461 function checkFocus() { 13462 var isActive = this.element[0] === this.document[0].activeElement; 13463 if ( !isActive ) { 13464 this.element.focus(); 13465 this.previous = previous; 13466 // support: IE 13467 // IE sets focus asynchronously, so we need to check if focus 13468 // moved off of the input because the user clicked on the button. 13469 this._delay(function() { 13470 this.previous = previous; 13471 }); 13472 } 13473 } 13474 13475 // ensure focus is on (or stays on) the text field 13476 event.preventDefault(); 13477 checkFocus.call( this ); 13478 13479 // support: IE 13480 // IE doesn't prevent moving focus even with event.preventDefault() 13481 // so we set a flag to know when we should ignore the blur event 13482 // and check (again) if focus moved off of the input. 13483 this.cancelBlur = true; 13484 this._delay(function() { 13485 delete this.cancelBlur; 13486 checkFocus.call( this ); 13487 }); 13488 13489 if ( this._start( event ) === false ) { 13490 return; 13491 } 13492 13493 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 13494 }, 13495 "mouseup .ui-spinner-button": "_stop", 13496 "mouseenter .ui-spinner-button": function( event ) { 13497 // button will add ui-state-active if mouse was down while mouseleave and kept down 13498 if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) { 13499 return; 13500 } 13501 13502 if ( this._start( event ) === false ) { 13503 return false; 13504 } 13505 this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); 13506 }, 13507 // TODO: do we really want to consider this a stop? 13508 // shouldn't we just stop the repeater and wait until mouseup before 13509 // we trigger the stop event? 13510 "mouseleave .ui-spinner-button": "_stop" 13511 }, 13512 13513 _draw: function() { 13514 var uiSpinner = this.uiSpinner = this.element 13515 .addClass( "ui-spinner-input" ) 13516 .attr( "autocomplete", "off" ) 13517 .wrap( this._uiSpinnerHtml() ) 13518 .parent() 13519 // add buttons 13520 .append( this._buttonHtml() ); 13521 13522 this.element.attr( "role", "spinbutton" ); 13523 13524 // button bindings 13525 this.buttons = uiSpinner.find( ".ui-spinner-button" ) 13526 .attr( "tabIndex", -1 ) 13527 .button() 13528 .removeClass( "ui-corner-all" ); 13529 13530 // IE 6 doesn't understand height: 50% for the buttons 13531 // unless the wrapper has an explicit height 13532 if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) && 13533 uiSpinner.height() > 0 ) { 13534 uiSpinner.height( uiSpinner.height() ); 13535 } 13536 13537 // disable spinner if element was already disabled 13538 if ( this.options.disabled ) { 13539 this.disable(); 13540 } 13541 }, 13542 13543 _keydown: function( event ) { 13544 var options = this.options, 13545 keyCode = $.ui.keyCode; 13546 13547 switch ( event.keyCode ) { 13548 case keyCode.UP: 13549 this._repeat( null, 1, event ); 13550 return true; 13551 case keyCode.DOWN: 13552 this._repeat( null, -1, event ); 13553 return true; 13554 case keyCode.PAGE_UP: 13555 this._repeat( null, options.page, event ); 13556 return true; 13557 case keyCode.PAGE_DOWN: 13558 this._repeat( null, -options.page, event ); 13559 return true; 13560 } 13561 13562 return false; 13563 }, 13564 13565 _uiSpinnerHtml: function() { 13566 return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"; 13567 }, 13568 13569 _buttonHtml: function() { 13570 return "" + 13571 "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" + 13572 "<span class='ui-icon " + this.options.icons.up + "'>▲</span>" + 13573 "</a>" + 13574 "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" + 13575 "<span class='ui-icon " + this.options.icons.down + "'>▼</span>" + 13576 "</a>"; 13577 }, 13578 13579 _start: function( event ) { 13580 if ( !this.spinning && this._trigger( "start", event ) === false ) { 13581 return false; 13582 } 13583 13584 if ( !this.counter ) { 13585 this.counter = 1; 13586 } 13587 this.spinning = true; 13588 return true; 13589 }, 13590 13591 _repeat: function( i, steps, event ) { 13592 i = i || 500; 13593 13594 clearTimeout( this.timer ); 13595 this.timer = this._delay(function() { 13596 this._repeat( 40, steps, event ); 13597 }, i ); 13598 13599 this._spin( steps * this.options.step, event ); 13600 }, 13601 13602 _spin: function( step, event ) { 13603 var value = this.value() || 0; 13604 13605 if ( !this.counter ) { 13606 this.counter = 1; 13607 } 13608 13609 value = this._adjustValue( value + step * this._increment( this.counter ) ); 13610 13611 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) { 13612 this._value( value ); 13613 this.counter++; 13614 } 13615 }, 13616 13617 _increment: function( i ) { 13618 var incremental = this.options.incremental; 13619 13620 if ( incremental ) { 13621 return $.isFunction( incremental ) ? 13622 incremental( i ) : 13623 Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 ); 13624 } 13625 13626 return 1; 13627 }, 13628 13629 _precision: function() { 13630 var precision = this._precisionOf( this.options.step ); 13631 if ( this.options.min !== null ) { 13632 precision = Math.max( precision, this._precisionOf( this.options.min ) ); 13633 } 13634 return precision; 13635 }, 13636 13637 _precisionOf: function( num ) { 13638 var str = num.toString(), 13639 decimal = str.indexOf( "." ); 13640 return decimal === -1 ? 0 : str.length - decimal - 1; 13641 }, 13642 13643 _adjustValue: function( value ) { 13644 var base, aboveMin, 13645 options = this.options; 13646 13647 // make sure we're at a valid step 13648 // - find out where we are relative to the base (min or 0) 13649 base = options.min !== null ? options.min : 0; 13650 aboveMin = value - base; 13651 // - round to the nearest step 13652 aboveMin = Math.round(aboveMin / options.step) * options.step; 13653 // - rounding is based on 0, so adjust back to our base 13654 value = base + aboveMin; 13655 13656 // fix precision from bad JS floating point math 13657 value = parseFloat( value.toFixed( this._precision() ) ); 13658 13659 // clamp the value 13660 if ( options.max !== null && value > options.max) { 13661 return options.max; 13662 } 13663 if ( options.min !== null && value < options.min ) { 13664 return options.min; 13665 } 13666 13667 return value; 13668 }, 13669 13670 _stop: function( event ) { 13671 if ( !this.spinning ) { 13672 return; 13673 } 13674 13675 clearTimeout( this.timer ); 13676 clearTimeout( this.mousewheelTimer ); 13677 this.counter = 0; 13678 this.spinning = false; 13679 this._trigger( "stop", event ); 13680 }, 13681 13682 _setOption: function( key, value ) { 13683 if ( key === "culture" || key === "numberFormat" ) { 13684 var prevValue = this._parse( this.element.val() ); 13685 this.options[ key ] = value; 13686 this.element.val( this._format( prevValue ) ); 13687 return; 13688 } 13689 13690 if ( key === "max" || key === "min" || key === "step" ) { 13691 if ( typeof value === "string" ) { 13692 value = this._parse( value ); 13693 } 13694 } 13695 if ( key === "icons" ) { 13696 this.buttons.first().find( ".ui-icon" ) 13697 .removeClass( this.options.icons.up ) 13698 .addClass( value.up ); 13699 this.buttons.last().find( ".ui-icon" ) 13700 .removeClass( this.options.icons.down ) 13701 .addClass( value.down ); 13702 } 13703 13704 this._super( key, value ); 13705 13706 if ( key === "disabled" ) { 13707 if ( value ) { 13708 this.element.prop( "disabled", true ); 13709 this.buttons.button( "disable" ); 13710 } else { 13711 this.element.prop( "disabled", false ); 13712 this.buttons.button( "enable" ); 13713 } 13714 } 13715 }, 13716 13717 _setOptions: modifier(function( options ) { 13718 this._super( options ); 13719 this._value( this.element.val() ); 13720 }), 13721 13722 _parse: function( val ) { 13723 if ( typeof val === "string" && val !== "" ) { 13724 val = window.Globalize && this.options.numberFormat ? 13725 Globalize.parseFloat( val, 10, this.options.culture ) : +val; 13726 } 13727 return val === "" || isNaN( val ) ? null : val; 13728 }, 13729 13730 _format: function( value ) { 13731 if ( value === "" ) { 13732 return ""; 13733 } 13734 return window.Globalize && this.options.numberFormat ? 13735 Globalize.format( value, this.options.numberFormat, this.options.culture ) : 13736 value; 13737 }, 13738 13739 _refresh: function() { 13740 this.element.attr({ 13741 "aria-valuemin": this.options.min, 13742 "aria-valuemax": this.options.max, 13743 // TODO: what should we do with values that can't be parsed? 13744 "aria-valuenow": this._parse( this.element.val() ) 13745 }); 13746 }, 13747 13748 // update the value without triggering change 13749 _value: function( value, allowAny ) { 13750 var parsed; 13751 if ( value !== "" ) { 13752 parsed = this._parse( value ); 13753 if ( parsed !== null ) { 13754 if ( !allowAny ) { 13755 parsed = this._adjustValue( parsed ); 13756 } 13757 value = this._format( parsed ); 13758 } 13759 } 13760 this.element.val( value ); 13761 this._refresh(); 13762 }, 13763 13764 _destroy: function() { 13765 this.element 13766 .removeClass( "ui-spinner-input" ) 13767 .prop( "disabled", false ) 13768 .removeAttr( "autocomplete" ) 13769 .removeAttr( "role" ) 13770 .removeAttr( "aria-valuemin" ) 13771 .removeAttr( "aria-valuemax" ) 13772 .removeAttr( "aria-valuenow" ); 13773 this.uiSpinner.replaceWith( this.element ); 13774 }, 13775 13776 stepUp: modifier(function( steps ) { 13777 this._stepUp( steps ); 13778 }), 13779 _stepUp: function( steps ) { 13780 if ( this._start() ) { 13781 this._spin( (steps || 1) * this.options.step ); 13782 this._stop(); 13783 } 13784 }, 13785 13786 stepDown: modifier(function( steps ) { 13787 this._stepDown( steps ); 13788 }), 13789 _stepDown: function( steps ) { 13790 if ( this._start() ) { 13791 this._spin( (steps || 1) * -this.options.step ); 13792 this._stop(); 13793 } 13794 }, 13795 13796 pageUp: modifier(function( pages ) { 13797 this._stepUp( (pages || 1) * this.options.page ); 13798 }), 13799 13800 pageDown: modifier(function( pages ) { 13801 this._stepDown( (pages || 1) * this.options.page ); 13802 }), 13803 13804 value: function( newVal ) { 13805 if ( !arguments.length ) { 13806 return this._parse( this.element.val() ); 13807 } 13808 modifier( this._value ).call( this, newVal ); 13809 }, 13810 13811 widget: function() { 13812 return this.uiSpinner; 13813 } 13814}); 13815 13816}( jQuery ) ); 13817 13818(function( $, undefined ) { 13819 13820var tabId = 0, 13821 rhash = /#.*$/; 13822 13823function getNextTabId() { 13824 return ++tabId; 13825} 13826 13827function isLocal( anchor ) { 13828 // support: IE7 13829 // IE7 doesn't normalize the href property when set via script (#9317) 13830 anchor = anchor.cloneNode( false ); 13831 13832 return anchor.hash.length > 1 && 13833 decodeURIComponent( anchor.href.replace( rhash, "" ) ) === 13834 decodeURIComponent( location.href.replace( rhash, "" ) ); 13835} 13836 13837$.widget( "ui.tabs", { 13838 version: "1.10.4", 13839 delay: 300, 13840 options: { 13841 active: null, 13842 collapsible: false, 13843 event: "click", 13844 heightStyle: "content", 13845 hide: null, 13846 show: null, 13847 13848 // callbacks 13849 activate: null, 13850 beforeActivate: null, 13851 beforeLoad: null, 13852 load: null 13853 }, 13854 13855 _create: function() { 13856 var that = this, 13857 options = this.options; 13858 13859 this.running = false; 13860 13861 this.element 13862 .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ) 13863 .toggleClass( "ui-tabs-collapsible", options.collapsible ) 13864 // Prevent users from focusing disabled tabs via click 13865 .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) { 13866 if ( $( this ).is( ".ui-state-disabled" ) ) { 13867 event.preventDefault(); 13868 } 13869 }) 13870 // support: IE <9 13871 // Preventing the default action in mousedown doesn't prevent IE 13872 // from focusing the element, so if the anchor gets focused, blur. 13873 // We don't have to worry about focusing the previously focused 13874 // element since clicking on a non-focusable element should focus 13875 // the body anyway. 13876 .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() { 13877 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) { 13878 this.blur(); 13879 } 13880 }); 13881 13882 this._processTabs(); 13883 options.active = this._initialActive(); 13884 13885 // Take disabling tabs via class attribute from HTML 13886 // into account and update option properly. 13887 if ( $.isArray( options.disabled ) ) { 13888 options.disabled = $.unique( options.disabled.concat( 13889 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { 13890 return that.tabs.index( li ); 13891 }) 13892 ) ).sort(); 13893 } 13894 13895 // check for length avoids error when initializing empty list 13896 if ( this.options.active !== false && this.anchors.length ) { 13897 this.active = this._findActive( options.active ); 13898 } else { 13899 this.active = $(); 13900 } 13901 13902 this._refresh(); 13903 13904 if ( this.active.length ) { 13905 this.load( options.active ); 13906 } 13907 }, 13908 13909 _initialActive: function() { 13910 var active = this.options.active, 13911 collapsible = this.options.collapsible, 13912 locationHash = location.hash.substring( 1 ); 13913 13914 if ( active === null ) { 13915 // check the fragment identifier in the URL 13916 if ( locationHash ) { 13917 this.tabs.each(function( i, tab ) { 13918 if ( $( tab ).attr( "aria-controls" ) === locationHash ) { 13919 active = i; 13920 return false; 13921 } 13922 }); 13923 } 13924 13925 // check for a tab marked active via a class 13926 if ( active === null ) { 13927 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); 13928 } 13929 13930 // no active tab, set to false 13931 if ( active === null || active === -1 ) { 13932 active = this.tabs.length ? 0 : false; 13933 } 13934 } 13935 13936 // handle numbers: negative, out of range 13937 if ( active !== false ) { 13938 active = this.tabs.index( this.tabs.eq( active ) ); 13939 if ( active === -1 ) { 13940 active = collapsible ? false : 0; 13941 } 13942 } 13943 13944 // don't allow collapsible: false and active: false 13945 if ( !collapsible && active === false && this.anchors.length ) { 13946 active = 0; 13947 } 13948 13949 return active; 13950 }, 13951 13952 _getCreateEventData: function() { 13953 return { 13954 tab: this.active, 13955 panel: !this.active.length ? $() : this._getPanelForTab( this.active ) 13956 }; 13957 }, 13958 13959 _tabKeydown: function( event ) { 13960 var focusedTab = $( this.document[0].activeElement ).closest( "li" ), 13961 selectedIndex = this.tabs.index( focusedTab ), 13962 goingForward = true; 13963 13964 if ( this._handlePageNav( event ) ) { 13965 return; 13966 } 13967 13968 switch ( event.keyCode ) { 13969 case $.ui.keyCode.RIGHT: 13970 case $.ui.keyCode.DOWN: 13971 selectedIndex++; 13972 break; 13973 case $.ui.keyCode.UP: 13974 case $.ui.keyCode.LEFT: 13975 goingForward = false; 13976 selectedIndex--; 13977 break; 13978 case $.ui.keyCode.END: 13979 selectedIndex = this.anchors.length - 1; 13980 break; 13981 case $.ui.keyCode.HOME: 13982 selectedIndex = 0; 13983 break; 13984 case $.ui.keyCode.SPACE: 13985 // Activate only, no collapsing 13986 event.preventDefault(); 13987 clearTimeout( this.activating ); 13988 this._activate( selectedIndex ); 13989 return; 13990 case $.ui.keyCode.ENTER: 13991 // Toggle (cancel delayed activation, allow collapsing) 13992 event.preventDefault(); 13993 clearTimeout( this.activating ); 13994 // Determine if we should collapse or activate 13995 this._activate( selectedIndex === this.options.active ? false : selectedIndex ); 13996 return; 13997 default: 13998 return; 13999 } 14000 14001 // Focus the appropriate tab, based on which key was pressed 14002 event.preventDefault(); 14003 clearTimeout( this.activating ); 14004 selectedIndex = this._focusNextTab( selectedIndex, goingForward ); 14005 14006 // Navigating with control key will prevent automatic activation 14007 if ( !event.ctrlKey ) { 14008 // Update aria-selected immediately so that AT think the tab is already selected. 14009 // Otherwise AT may confuse the user by stating that they need to activate the tab, 14010 // but the tab will already be activated by the time the announcement finishes. 14011 focusedTab.attr( "aria-selected", "false" ); 14012 this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); 14013 14014 this.activating = this._delay(function() { 14015 this.option( "active", selectedIndex ); 14016 }, this.delay ); 14017 } 14018 }, 14019 14020 _panelKeydown: function( event ) { 14021 if ( this._handlePageNav( event ) ) { 14022 return; 14023 } 14024 14025 // Ctrl+up moves focus to the current tab 14026 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { 14027 event.preventDefault(); 14028 this.active.focus(); 14029 } 14030 }, 14031 14032 // Alt+page up/down moves focus to the previous/next tab (and activates) 14033 _handlePageNav: function( event ) { 14034 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { 14035 this._activate( this._focusNextTab( this.options.active - 1, false ) ); 14036 return true; 14037 } 14038 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { 14039 this._activate( this._focusNextTab( this.options.active + 1, true ) ); 14040 return true; 14041 } 14042 }, 14043 14044 _findNextTab: function( index, goingForward ) { 14045 var lastTabIndex = this.tabs.length - 1; 14046 14047 function constrain() { 14048 if ( index > lastTabIndex ) { 14049 index = 0; 14050 } 14051 if ( index < 0 ) { 14052 index = lastTabIndex; 14053 } 14054 return index; 14055 } 14056 14057 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { 14058 index = goingForward ? index + 1 : index - 1; 14059 } 14060 14061 return index; 14062 }, 14063 14064 _focusNextTab: function( index, goingForward ) { 14065 index = this._findNextTab( index, goingForward ); 14066 this.tabs.eq( index ).focus(); 14067 return index; 14068 }, 14069 14070 _setOption: function( key, value ) { 14071 if ( key === "active" ) { 14072 // _activate() will handle invalid values and update this.options 14073 this._activate( value ); 14074 return; 14075 } 14076 14077 if ( key === "disabled" ) { 14078 // don't use the widget factory's disabled handling 14079 this._setupDisabled( value ); 14080 return; 14081 } 14082 14083 this._super( key, value); 14084 14085 if ( key === "collapsible" ) { 14086 this.element.toggleClass( "ui-tabs-collapsible", value ); 14087 // Setting collapsible: false while collapsed; open first panel 14088 if ( !value && this.options.active === false ) { 14089 this._activate( 0 ); 14090 } 14091 } 14092 14093 if ( key === "event" ) { 14094 this._setupEvents( value ); 14095 } 14096 14097 if ( key === "heightStyle" ) { 14098 this._setupHeightStyle( value ); 14099 } 14100 }, 14101 14102 _tabId: function( tab ) { 14103 return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId(); 14104 }, 14105 14106 _sanitizeSelector: function( hash ) { 14107 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : ""; 14108 }, 14109 14110 refresh: function() { 14111 var options = this.options, 14112 lis = this.tablist.children( ":has(a[href])" ); 14113 14114 // get disabled tabs from class attribute from HTML 14115 // this will get converted to a boolean if needed in _refresh() 14116 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { 14117 return lis.index( tab ); 14118 }); 14119 14120 this._processTabs(); 14121 14122 // was collapsed or no tabs 14123 if ( options.active === false || !this.anchors.length ) { 14124 options.active = false; 14125 this.active = $(); 14126 // was active, but active tab is gone 14127 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { 14128 // all remaining tabs are disabled 14129 if ( this.tabs.length === options.disabled.length ) { 14130 options.active = false; 14131 this.active = $(); 14132 // activate previous tab 14133 } else { 14134 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); 14135 } 14136 // was active, active tab still exists 14137 } else { 14138 // make sure active index is correct 14139 options.active = this.tabs.index( this.active ); 14140 } 14141 14142 this._refresh(); 14143 }, 14144 14145 _refresh: function() { 14146 this._setupDisabled( this.options.disabled ); 14147 this._setupEvents( this.options.event ); 14148 this._setupHeightStyle( this.options.heightStyle ); 14149 14150 this.tabs.not( this.active ).attr({ 14151 "aria-selected": "false", 14152 tabIndex: -1 14153 }); 14154 this.panels.not( this._getPanelForTab( this.active ) ) 14155 .hide() 14156 .attr({ 14157 "aria-expanded": "false", 14158 "aria-hidden": "true" 14159 }); 14160 14161 // Make sure one tab is in the tab order 14162 if ( !this.active.length ) { 14163 this.tabs.eq( 0 ).attr( "tabIndex", 0 ); 14164 } else { 14165 this.active 14166 .addClass( "ui-tabs-active ui-state-active" ) 14167 .attr({ 14168 "aria-selected": "true", 14169 tabIndex: 0 14170 }); 14171 this._getPanelForTab( this.active ) 14172 .show() 14173 .attr({ 14174 "aria-expanded": "true", 14175 "aria-hidden": "false" 14176 }); 14177 } 14178 }, 14179 14180 _processTabs: function() { 14181 var that = this; 14182 14183 this.tablist = this._getList() 14184 .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) 14185 .attr( "role", "tablist" ); 14186 14187 this.tabs = this.tablist.find( "> li:has(a[href])" ) 14188 .addClass( "ui-state-default ui-corner-top" ) 14189 .attr({ 14190 role: "tab", 14191 tabIndex: -1 14192 }); 14193 14194 this.anchors = this.tabs.map(function() { 14195 return $( "a", this )[ 0 ]; 14196 }) 14197 .addClass( "ui-tabs-anchor" ) 14198 .attr({ 14199 role: "presentation", 14200 tabIndex: -1 14201 }); 14202 14203 this.panels = $(); 14204 14205 this.anchors.each(function( i, anchor ) { 14206 var selector, panel, panelId, 14207 anchorId = $( anchor ).uniqueId().attr( "id" ), 14208 tab = $( anchor ).closest( "li" ), 14209 originalAriaControls = tab.attr( "aria-controls" ); 14210 14211 // inline tab 14212 if ( isLocal( anchor ) ) { 14213 selector = anchor.hash; 14214 panel = that.element.find( that._sanitizeSelector( selector ) ); 14215 // remote tab 14216 } else { 14217 panelId = that._tabId( tab ); 14218 selector = "#" + panelId; 14219 panel = that.element.find( selector ); 14220 if ( !panel.length ) { 14221 panel = that._createPanel( panelId ); 14222 panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); 14223 } 14224 panel.attr( "aria-live", "polite" ); 14225 } 14226 14227 if ( panel.length) { 14228 that.panels = that.panels.add( panel ); 14229 } 14230 if ( originalAriaControls ) { 14231 tab.data( "ui-tabs-aria-controls", originalAriaControls ); 14232 } 14233 tab.attr({ 14234 "aria-controls": selector.substring( 1 ), 14235 "aria-labelledby": anchorId 14236 }); 14237 panel.attr( "aria-labelledby", anchorId ); 14238 }); 14239 14240 this.panels 14241 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) 14242 .attr( "role", "tabpanel" ); 14243 }, 14244 14245 // allow overriding how to find the list for rare usage scenarios (#7715) 14246 _getList: function() { 14247 return this.tablist || this.element.find( "ol,ul" ).eq( 0 ); 14248 }, 14249 14250 _createPanel: function( id ) { 14251 return $( "<div>" ) 14252 .attr( "id", id ) 14253 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) 14254 .data( "ui-tabs-destroy", true ); 14255 }, 14256 14257 _setupDisabled: function( disabled ) { 14258 if ( $.isArray( disabled ) ) { 14259 if ( !disabled.length ) { 14260 disabled = false; 14261 } else if ( disabled.length === this.anchors.length ) { 14262 disabled = true; 14263 } 14264 } 14265 14266 // disable tabs 14267 for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) { 14268 if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { 14269 $( li ) 14270 .addClass( "ui-state-disabled" ) 14271 .attr( "aria-disabled", "true" ); 14272 } else { 14273 $( li ) 14274 .removeClass( "ui-state-disabled" ) 14275 .removeAttr( "aria-disabled" ); 14276 } 14277 } 14278 14279 this.options.disabled = disabled; 14280 }, 14281 14282 _setupEvents: function( event ) { 14283 var events = { 14284 click: function( event ) { 14285 event.preventDefault(); 14286 } 14287 }; 14288 if ( event ) { 14289 $.each( event.split(" "), function( index, eventName ) { 14290 events[ eventName ] = "_eventHandler"; 14291 }); 14292 } 14293 14294 this._off( this.anchors.add( this.tabs ).add( this.panels ) ); 14295 this._on( this.anchors, events ); 14296 this._on( this.tabs, { keydown: "_tabKeydown" } ); 14297 this._on( this.panels, { keydown: "_panelKeydown" } ); 14298 14299 this._focusable( this.tabs ); 14300 this._hoverable( this.tabs ); 14301 }, 14302 14303 _setupHeightStyle: function( heightStyle ) { 14304 var maxHeight, 14305 parent = this.element.parent(); 14306 14307 if ( heightStyle === "fill" ) { 14308 maxHeight = parent.height(); 14309 maxHeight -= this.element.outerHeight() - this.element.height(); 14310 14311 this.element.siblings( ":visible" ).each(function() { 14312 var elem = $( this ), 14313 position = elem.css( "position" ); 14314 14315 if ( position === "absolute" || position === "fixed" ) { 14316 return; 14317 } 14318 maxHeight -= elem.outerHeight( true ); 14319 }); 14320 14321 this.element.children().not( this.panels ).each(function() { 14322 maxHeight -= $( this ).outerHeight( true ); 14323 }); 14324 14325 this.panels.each(function() { 14326 $( this ).height( Math.max( 0, maxHeight - 14327 $( this ).innerHeight() + $( this ).height() ) ); 14328 }) 14329 .css( "overflow", "auto" ); 14330 } else if ( heightStyle === "auto" ) { 14331 maxHeight = 0; 14332 this.panels.each(function() { 14333 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); 14334 }).height( maxHeight ); 14335 } 14336 }, 14337 14338 _eventHandler: function( event ) { 14339 var options = this.options, 14340 active = this.active, 14341 anchor = $( event.currentTarget ), 14342 tab = anchor.closest( "li" ), 14343 clickedIsActive = tab[ 0 ] === active[ 0 ], 14344 collapsing = clickedIsActive && options.collapsible, 14345 toShow = collapsing ? $() : this._getPanelForTab( tab ), 14346 toHide = !active.length ? $() : this._getPanelForTab( active ), 14347 eventData = { 14348 oldTab: active, 14349 oldPanel: toHide, 14350 newTab: collapsing ? $() : tab, 14351 newPanel: toShow 14352 }; 14353 14354 event.preventDefault(); 14355 14356 if ( tab.hasClass( "ui-state-disabled" ) || 14357 // tab is already loading 14358 tab.hasClass( "ui-tabs-loading" ) || 14359 // can't switch durning an animation 14360 this.running || 14361 // click on active header, but not collapsible 14362 ( clickedIsActive && !options.collapsible ) || 14363 // allow canceling activation 14364 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { 14365 return; 14366 } 14367 14368 options.active = collapsing ? false : this.tabs.index( tab ); 14369 14370 this.active = clickedIsActive ? $() : tab; 14371 if ( this.xhr ) { 14372 this.xhr.abort(); 14373 } 14374 14375 if ( !toHide.length && !toShow.length ) { 14376 $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); 14377 } 14378 14379 if ( toShow.length ) { 14380 this.load( this.tabs.index( tab ), event ); 14381 } 14382 this._toggle( event, eventData ); 14383 }, 14384 14385 // handles show/hide for selecting tabs 14386 _toggle: function( event, eventData ) { 14387 var that = this, 14388 toShow = eventData.newPanel, 14389 toHide = eventData.oldPanel; 14390 14391 this.running = true; 14392 14393 function complete() { 14394 that.running = false; 14395 that._trigger( "activate", event, eventData ); 14396 } 14397 14398 function show() { 14399 eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); 14400 14401 if ( toShow.length && that.options.show ) { 14402 that._show( toShow, that.options.show, complete ); 14403 } else { 14404 toShow.show(); 14405 complete(); 14406 } 14407 } 14408 14409 // start out by hiding, then showing, then completing 14410 if ( toHide.length && this.options.hide ) { 14411 this._hide( toHide, this.options.hide, function() { 14412 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); 14413 show(); 14414 }); 14415 } else { 14416 eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); 14417 toHide.hide(); 14418 show(); 14419 } 14420 14421 toHide.attr({ 14422 "aria-expanded": "false", 14423 "aria-hidden": "true" 14424 }); 14425 eventData.oldTab.attr( "aria-selected", "false" ); 14426 // If we're switching tabs, remove the old tab from the tab order. 14427 // If we're opening from collapsed state, remove the previous tab from the tab order. 14428 // If we're collapsing, then keep the collapsing tab in the tab order. 14429 if ( toShow.length && toHide.length ) { 14430 eventData.oldTab.attr( "tabIndex", -1 ); 14431 } else if ( toShow.length ) { 14432 this.tabs.filter(function() { 14433 return $( this ).attr( "tabIndex" ) === 0; 14434 }) 14435 .attr( "tabIndex", -1 ); 14436 } 14437 14438 toShow.attr({ 14439 "aria-expanded": "true", 14440 "aria-hidden": "false" 14441 }); 14442 eventData.newTab.attr({ 14443 "aria-selected": "true", 14444 tabIndex: 0 14445 }); 14446 }, 14447 14448 _activate: function( index ) { 14449 var anchor, 14450 active = this._findActive( index ); 14451 14452 // trying to activate the already active panel 14453 if ( active[ 0 ] === this.active[ 0 ] ) { 14454 return; 14455 } 14456 14457 // trying to collapse, simulate a click on the current active header 14458 if ( !active.length ) { 14459 active = this.active; 14460 } 14461 14462 anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; 14463 this._eventHandler({ 14464 target: anchor, 14465 currentTarget: anchor, 14466 preventDefault: $.noop 14467 }); 14468 }, 14469 14470 _findActive: function( index ) { 14471 return index === false ? $() : this.tabs.eq( index ); 14472 }, 14473 14474 _getIndex: function( index ) { 14475 // meta-function to give users option to provide a href string instead of a numerical index. 14476 if ( typeof index === "string" ) { 14477 index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) ); 14478 } 14479 14480 return index; 14481 }, 14482 14483 _destroy: function() { 14484 if ( this.xhr ) { 14485 this.xhr.abort(); 14486 } 14487 14488 this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ); 14489 14490 this.tablist 14491 .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) 14492 .removeAttr( "role" ); 14493 14494 this.anchors 14495 .removeClass( "ui-tabs-anchor" ) 14496 .removeAttr( "role" ) 14497 .removeAttr( "tabIndex" ) 14498 .removeUniqueId(); 14499 14500 this.tabs.add( this.panels ).each(function() { 14501 if ( $.data( this, "ui-tabs-destroy" ) ) { 14502 $( this ).remove(); 14503 } else { 14504 $( this ) 14505 .removeClass( "ui-state-default ui-state-active ui-state-disabled " + 14506 "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" ) 14507 .removeAttr( "tabIndex" ) 14508 .removeAttr( "aria-live" ) 14509 .removeAttr( "aria-busy" ) 14510 .removeAttr( "aria-selected" ) 14511 .removeAttr( "aria-labelledby" ) 14512 .removeAttr( "aria-hidden" ) 14513 .removeAttr( "aria-expanded" ) 14514 .removeAttr( "role" ); 14515 } 14516 }); 14517 14518 this.tabs.each(function() { 14519 var li = $( this ), 14520 prev = li.data( "ui-tabs-aria-controls" ); 14521 if ( prev ) { 14522 li 14523 .attr( "aria-controls", prev ) 14524 .removeData( "ui-tabs-aria-controls" ); 14525 } else { 14526 li.removeAttr( "aria-controls" ); 14527 } 14528 }); 14529 14530 this.panels.show(); 14531 14532 if ( this.options.heightStyle !== "content" ) { 14533 this.panels.css( "height", "" ); 14534 } 14535 }, 14536 14537 enable: function( index ) { 14538 var disabled = this.options.disabled; 14539 if ( disabled === false ) { 14540 return; 14541 } 14542 14543 if ( index === undefined ) { 14544 disabled = false; 14545 } else { 14546 index = this._getIndex( index ); 14547 if ( $.isArray( disabled ) ) { 14548 disabled = $.map( disabled, function( num ) { 14549 return num !== index ? num : null; 14550 }); 14551 } else { 14552 disabled = $.map( this.tabs, function( li, num ) { 14553 return num !== index ? num : null; 14554 }); 14555 } 14556 } 14557 this._setupDisabled( disabled ); 14558 }, 14559 14560 disable: function( index ) { 14561 var disabled = this.options.disabled; 14562 if ( disabled === true ) { 14563 return; 14564 } 14565 14566 if ( index === undefined ) { 14567 disabled = true; 14568 } else { 14569 index = this._getIndex( index ); 14570 if ( $.inArray( index, disabled ) !== -1 ) { 14571 return; 14572 } 14573 if ( $.isArray( disabled ) ) { 14574 disabled = $.merge( [ index ], disabled ).sort(); 14575 } else { 14576 disabled = [ index ]; 14577 } 14578 } 14579 this._setupDisabled( disabled ); 14580 }, 14581 14582 load: function( index, event ) { 14583 index = this._getIndex( index ); 14584 var that = this, 14585 tab = this.tabs.eq( index ), 14586 anchor = tab.find( ".ui-tabs-anchor" ), 14587 panel = this._getPanelForTab( tab ), 14588 eventData = { 14589 tab: tab, 14590 panel: panel 14591 }; 14592 14593 // not remote 14594 if ( isLocal( anchor[ 0 ] ) ) { 14595 return; 14596 } 14597 14598 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); 14599 14600 // support: jQuery <1.8 14601 // jQuery <1.8 returns false if the request is canceled in beforeSend, 14602 // but as of 1.8, $.ajax() always returns a jqXHR object. 14603 if ( this.xhr && this.xhr.statusText !== "canceled" ) { 14604 tab.addClass( "ui-tabs-loading" ); 14605 panel.attr( "aria-busy", "true" ); 14606 14607 this.xhr 14608 .success(function( response ) { 14609 // support: jQuery <1.8 14610 // http://bugs.jquery.com/ticket/11778 14611 setTimeout(function() { 14612 panel.html( response ); 14613 that._trigger( "load", event, eventData ); 14614 }, 1 ); 14615 }) 14616 .complete(function( jqXHR, status ) { 14617 // support: jQuery <1.8 14618 // http://bugs.jquery.com/ticket/11778 14619 setTimeout(function() { 14620 if ( status === "abort" ) { 14621 that.panels.stop( false, true ); 14622 } 14623 14624 tab.removeClass( "ui-tabs-loading" ); 14625 panel.removeAttr( "aria-busy" ); 14626 14627 if ( jqXHR === that.xhr ) { 14628 delete that.xhr; 14629 } 14630 }, 1 ); 14631 }); 14632 } 14633 }, 14634 14635 _ajaxSettings: function( anchor, event, eventData ) { 14636 var that = this; 14637 return { 14638 url: anchor.attr( "href" ), 14639 beforeSend: function( jqXHR, settings ) { 14640 return that._trigger( "beforeLoad", event, 14641 $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) ); 14642 } 14643 }; 14644 }, 14645 14646 _getPanelForTab: function( tab ) { 14647 var id = $( tab ).attr( "aria-controls" ); 14648 return this.element.find( this._sanitizeSelector( "#" + id ) ); 14649 } 14650}); 14651 14652})( jQuery ); 14653 14654(function( $ ) { 14655 14656var increments = 0; 14657 14658function addDescribedBy( elem, id ) { 14659 var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ); 14660 describedby.push( id ); 14661 elem 14662 .data( "ui-tooltip-id", id ) 14663 .attr( "aria-describedby", $.trim( describedby.join( " " ) ) ); 14664} 14665 14666function removeDescribedBy( elem ) { 14667 var id = elem.data( "ui-tooltip-id" ), 14668 describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ), 14669 index = $.inArray( id, describedby ); 14670 if ( index !== -1 ) { 14671 describedby.splice( index, 1 ); 14672 } 14673 14674 elem.removeData( "ui-tooltip-id" ); 14675 describedby = $.trim( describedby.join( " " ) ); 14676 if ( describedby ) { 14677 elem.attr( "aria-describedby", describedby ); 14678 } else { 14679 elem.removeAttr( "aria-describedby" ); 14680 } 14681} 14682 14683$.widget( "ui.tooltip", { 14684 version: "1.10.4", 14685 options: { 14686 content: function() { 14687 // support: IE<9, Opera in jQuery <1.7 14688 // .text() can't accept undefined, so coerce to a string 14689 var title = $( this ).attr( "title" ) || ""; 14690 // Escape title, since we're going from an attribute to raw HTML 14691 return $( "<a>" ).text( title ).html(); 14692 }, 14693 hide: true, 14694 // Disabled elements have inconsistent behavior across browsers (#8661) 14695 items: "[title]:not([disabled])", 14696 position: { 14697 my: "left top+15", 14698 at: "left bottom", 14699 collision: "flipfit flip" 14700 }, 14701 show: true, 14702 tooltipClass: null, 14703 track: false, 14704 14705 // callbacks 14706 close: null, 14707 open: null 14708 }, 14709 14710 _create: function() { 14711 this._on({ 14712 mouseover: "open", 14713 focusin: "open" 14714 }); 14715 14716 // IDs of generated tooltips, needed for destroy 14717 this.tooltips = {}; 14718 // IDs of parent tooltips where we removed the title attribute 14719 this.parents = {}; 14720 14721 if ( this.options.disabled ) { 14722 this._disable(); 14723 } 14724 }, 14725 14726 _setOption: function( key, value ) { 14727 var that = this; 14728 14729 if ( key === "disabled" ) { 14730 this[ value ? "_disable" : "_enable" ](); 14731 this.options[ key ] = value; 14732 // disable element style changes 14733 return; 14734 } 14735 14736 this._super( key, value ); 14737 14738 if ( key === "content" ) { 14739 $.each( this.tooltips, function( id, element ) { 14740 that._updateContent( element ); 14741 }); 14742 } 14743 }, 14744 14745 _disable: function() { 14746 var that = this; 14747 14748 // close open tooltips 14749 $.each( this.tooltips, function( id, element ) { 14750 var event = $.Event( "blur" ); 14751 event.target = event.currentTarget = element[0]; 14752 that.close( event, true ); 14753 }); 14754 14755 // remove title attributes to prevent native tooltips 14756 this.element.find( this.options.items ).addBack().each(function() { 14757 var element = $( this ); 14758 if ( element.is( "[title]" ) ) { 14759 element 14760 .data( "ui-tooltip-title", element.attr( "title" ) ) 14761 .attr( "title", "" ); 14762 } 14763 }); 14764 }, 14765 14766 _enable: function() { 14767 // restore title attributes 14768 this.element.find( this.options.items ).addBack().each(function() { 14769 var element = $( this ); 14770 if ( element.data( "ui-tooltip-title" ) ) { 14771 element.attr( "title", element.data( "ui-tooltip-title" ) ); 14772 } 14773 }); 14774 }, 14775 14776 open: function( event ) { 14777 var that = this, 14778 target = $( event ? event.target : this.element ) 14779 // we need closest here due to mouseover bubbling, 14780 // but always pointing at the same event target 14781 .closest( this.options.items ); 14782 14783 // No element to show a tooltip for or the tooltip is already open 14784 if ( !target.length || target.data( "ui-tooltip-id" ) ) { 14785 return; 14786 } 14787 14788 if ( target.attr( "title" ) ) { 14789 target.data( "ui-tooltip-title", target.attr( "title" ) ); 14790 } 14791 14792 target.data( "ui-tooltip-open", true ); 14793 14794 // kill parent tooltips, custom or native, for hover 14795 if ( event && event.type === "mouseover" ) { 14796 target.parents().each(function() { 14797 var parent = $( this ), 14798 blurEvent; 14799 if ( parent.data( "ui-tooltip-open" ) ) { 14800 blurEvent = $.Event( "blur" ); 14801 blurEvent.target = blurEvent.currentTarget = this; 14802 that.close( blurEvent, true ); 14803 } 14804 if ( parent.attr( "title" ) ) { 14805 parent.uniqueId(); 14806 that.parents[ this.id ] = { 14807 element: this, 14808 title: parent.attr( "title" ) 14809 }; 14810 parent.attr( "title", "" ); 14811 } 14812 }); 14813 } 14814 14815 this._updateContent( target, event ); 14816 }, 14817 14818 _updateContent: function( target, event ) { 14819 var content, 14820 contentOption = this.options.content, 14821 that = this, 14822 eventType = event ? event.type : null; 14823 14824 if ( typeof contentOption === "string" ) { 14825 return this._open( event, target, contentOption ); 14826 } 14827 14828 content = contentOption.call( target[0], function( response ) { 14829 // ignore async response if tooltip was closed already 14830 if ( !target.data( "ui-tooltip-open" ) ) { 14831 return; 14832 } 14833 // IE may instantly serve a cached response for ajax requests 14834 // delay this call to _open so the other call to _open runs first 14835 that._delay(function() { 14836 // jQuery creates a special event for focusin when it doesn't 14837 // exist natively. To improve performance, the native event 14838 // object is reused and the type is changed. Therefore, we can't 14839 // rely on the type being correct after the event finished 14840 // bubbling, so we set it back to the previous value. (#8740) 14841 if ( event ) { 14842 event.type = eventType; 14843 } 14844 this._open( event, target, response ); 14845 }); 14846 }); 14847 if ( content ) { 14848 this._open( event, target, content ); 14849 } 14850 }, 14851 14852 _open: function( event, target, content ) { 14853 var tooltip, events, delayedShow, 14854 positionOption = $.extend( {}, this.options.position ); 14855 14856 if ( !content ) { 14857 return; 14858 } 14859 14860 // Content can be updated multiple times. If the tooltip already 14861 // exists, then just update the content and bail. 14862 tooltip = this._find( target ); 14863 if ( tooltip.length ) { 14864 tooltip.find( ".ui-tooltip-content" ).html( content ); 14865 return; 14866 } 14867 14868 // if we have a title, clear it to prevent the native tooltip 14869 // we have to check first to avoid defining a title if none exists 14870 // (we don't want to cause an element to start matching [title]) 14871 // 14872 // We use removeAttr only for key events, to allow IE to export the correct 14873 // accessible attributes. For mouse events, set to empty string to avoid 14874 // native tooltip showing up (happens only when removing inside mouseover). 14875 if ( target.is( "[title]" ) ) { 14876 if ( event && event.type === "mouseover" ) { 14877 target.attr( "title", "" ); 14878 } else { 14879 target.removeAttr( "title" ); 14880 } 14881 } 14882 14883 tooltip = this._tooltip( target ); 14884 addDescribedBy( target, tooltip.attr( "id" ) ); 14885 tooltip.find( ".ui-tooltip-content" ).html( content ); 14886 14887 function position( event ) { 14888 positionOption.of = event; 14889 if ( tooltip.is( ":hidden" ) ) { 14890 return; 14891 } 14892 tooltip.position( positionOption ); 14893 } 14894 if ( this.options.track && event && /^mouse/.test( event.type ) ) { 14895 this._on( this.document, { 14896 mousemove: position 14897 }); 14898 // trigger once to override element-relative positioning 14899 position( event ); 14900 } else { 14901 tooltip.position( $.extend({ 14902 of: target 14903 }, this.options.position ) ); 14904 } 14905 14906 tooltip.hide(); 14907 14908 this._show( tooltip, this.options.show ); 14909 // Handle tracking tooltips that are shown with a delay (#8644). As soon 14910 // as the tooltip is visible, position the tooltip using the most recent 14911 // event. 14912 if ( this.options.show && this.options.show.delay ) { 14913 delayedShow = this.delayedShow = setInterval(function() { 14914 if ( tooltip.is( ":visible" ) ) { 14915 position( positionOption.of ); 14916 clearInterval( delayedShow ); 14917 } 14918 }, $.fx.interval ); 14919 } 14920 14921 this._trigger( "open", event, { tooltip: tooltip } ); 14922 14923 events = { 14924 keyup: function( event ) { 14925 if ( event.keyCode === $.ui.keyCode.ESCAPE ) { 14926 var fakeEvent = $.Event(event); 14927 fakeEvent.currentTarget = target[0]; 14928 this.close( fakeEvent, true ); 14929 } 14930 }, 14931 remove: function() { 14932 this._removeTooltip( tooltip ); 14933 } 14934 }; 14935 if ( !event || event.type === "mouseover" ) { 14936 events.mouseleave = "close"; 14937 } 14938 if ( !event || event.type === "focusin" ) { 14939 events.focusout = "close"; 14940 } 14941 this._on( true, target, events ); 14942 }, 14943 14944 close: function( event ) { 14945 var that = this, 14946 target = $( event ? event.currentTarget : this.element ), 14947 tooltip = this._find( target ); 14948 14949 // disabling closes the tooltip, so we need to track when we're closing 14950 // to avoid an infinite loop in case the tooltip becomes disabled on close 14951 if ( this.closing ) { 14952 return; 14953 } 14954 14955 // Clear the interval for delayed tracking tooltips 14956 clearInterval( this.delayedShow ); 14957 14958 // only set title if we had one before (see comment in _open()) 14959 if ( target.data( "ui-tooltip-title" ) ) { 14960 target.attr( "title", target.data( "ui-tooltip-title" ) ); 14961 } 14962 14963 removeDescribedBy( target ); 14964 14965 tooltip.stop( true ); 14966 this._hide( tooltip, this.options.hide, function() { 14967 that._removeTooltip( $( this ) ); 14968 }); 14969 14970 target.removeData( "ui-tooltip-open" ); 14971 this._off( target, "mouseleave focusout keyup" ); 14972 // Remove 'remove' binding only on delegated targets 14973 if ( target[0] !== this.element[0] ) { 14974 this._off( target, "remove" ); 14975 } 14976 this._off( this.document, "mousemove" ); 14977 14978 if ( event && event.type === "mouseleave" ) { 14979 $.each( this.parents, function( id, parent ) { 14980 $( parent.element ).attr( "title", parent.title ); 14981 delete that.parents[ id ]; 14982 }); 14983 } 14984 14985 this.closing = true; 14986 this._trigger( "close", event, { tooltip: tooltip } ); 14987 this.closing = false; 14988 }, 14989 14990 _tooltip: function( element ) { 14991 var id = "ui-tooltip-" + increments++, 14992 tooltip = $( "<div>" ) 14993 .attr({ 14994 id: id, 14995 role: "tooltip" 14996 }) 14997 .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " + 14998 ( this.options.tooltipClass || "" ) ); 14999 $( "<div>" ) 15000 .addClass( "ui-tooltip-content" ) 15001 .appendTo( tooltip ); 15002 tooltip.appendTo( this.document[0].body ); 15003 this.tooltips[ id ] = element; 15004 return tooltip; 15005 }, 15006 15007 _find: function( target ) { 15008 var id = target.data( "ui-tooltip-id" ); 15009 return id ? $( "#" + id ) : $(); 15010 }, 15011 15012 _removeTooltip: function( tooltip ) { 15013 tooltip.remove(); 15014 delete this.tooltips[ tooltip.attr( "id" ) ]; 15015 }, 15016 15017 _destroy: function() { 15018 var that = this; 15019 15020 // close open tooltips 15021 $.each( this.tooltips, function( id, element ) { 15022 // Delegate to close method to handle common cleanup 15023 var event = $.Event( "blur" ); 15024 event.target = event.currentTarget = element[0]; 15025 that.close( event, true ); 15026 15027 // Remove immediately; destroying an open tooltip doesn't use the 15028 // hide animation 15029 $( "#" + id ).remove(); 15030 15031 // Restore the title 15032 if ( element.data( "ui-tooltip-title" ) ) { 15033 element.attr( "title", element.data( "ui-tooltip-title" ) ); 15034 element.removeData( "ui-tooltip-title" ); 15035 } 15036 }); 15037 } 15038}); 15039 15040}( 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.