1/*! jQuery UI - v1.8.24 - 2012-09-28 2* https://github.com/jquery/jquery-ui 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.effects.core.js, jquery.effects.blind.js, jquery.effects.bounce.js, jquery.effects.clip.js, jquery.effects.drop.js, jquery.effects.explode.js, jquery.effects.fade.js, jquery.effects.fold.js, jquery.effects.highlight.js, jquery.effects.pulsate.js, jquery.effects.scale.js, jquery.effects.shake.js, jquery.effects.slide.js, jquery.effects.transfer.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.position.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.tabs.js 4* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ 5 6(function( $, undefined ) { 7 8// prevent duplicate loading 9// this is only a problem because we proxy existing functions 10// and we don't want to double proxy them 11$.ui = $.ui || {}; 12if ( $.ui.version ) { 13 return; 14} 15 16$.extend( $.ui, { 17 version: "1.8.24", 18 19 keyCode: { 20 ALT: 18, 21 BACKSPACE: 8, 22 CAPS_LOCK: 20, 23 COMMA: 188, 24 COMMAND: 91, 25 COMMAND_LEFT: 91, // COMMAND 26 COMMAND_RIGHT: 93, 27 CONTROL: 17, 28 DELETE: 46, 29 DOWN: 40, 30 END: 35, 31 ENTER: 13, 32 ESCAPE: 27, 33 HOME: 36, 34 INSERT: 45, 35 LEFT: 37, 36 MENU: 93, // COMMAND_RIGHT 37 NUMPAD_ADD: 107, 38 NUMPAD_DECIMAL: 110, 39 NUMPAD_DIVIDE: 111, 40 NUMPAD_ENTER: 108, 41 NUMPAD_MULTIPLY: 106, 42 NUMPAD_SUBTRACT: 109, 43 PAGE_DOWN: 34, 44 PAGE_UP: 33, 45 PERIOD: 190, 46 RIGHT: 39, 47 SHIFT: 16, 48 SPACE: 32, 49 TAB: 9, 50 UP: 38, 51 WINDOWS: 91 // COMMAND 52 } 53}); 54 55// plugins 56$.fn.extend({ 57 propAttr: $.fn.prop || $.fn.attr, 58 59 _focus: $.fn.focus, 60 focus: function( delay, fn ) { 61 return typeof delay === "number" ? 62 this.each(function() { 63 var elem = this; 64 setTimeout(function() { 65 $( elem ).focus(); 66 if ( fn ) { 67 fn.call( elem ); 68 } 69 }, delay ); 70 }) : 71 this._focus.apply( this, arguments ); 72 }, 73 74 scrollParent: function() { 75 var scrollParent; 76 if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) { 77 scrollParent = this.parents().filter(function() { 78 return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); 79 }).eq(0); 80 } else { 81 scrollParent = this.parents().filter(function() { 82 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1)); 83 }).eq(0); 84 } 85 86 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent; 87 }, 88 89 zIndex: function( zIndex ) { 90 if ( zIndex !== undefined ) { 91 return this.css( "zIndex", zIndex ); 92 } 93 94 if ( this.length ) { 95 var elem = $( this[ 0 ] ), position, value; 96 while ( elem.length && elem[ 0 ] !== document ) { 97 // Ignore z-index if position is set to a value where z-index is ignored by the browser 98 // This makes behavior of this function consistent across browsers 99 // WebKit always returns auto if the element is positioned 100 position = elem.css( "position" ); 101 if ( position === "absolute" || position === "relative" || position === "fixed" ) { 102 // IE returns 0 when zIndex is not specified 103 // other browsers return a string 104 // we ignore the case of nested elements with an explicit value of 0 105 // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> 106 value = parseInt( elem.css( "zIndex" ), 10 ); 107 if ( !isNaN( value ) && value !== 0 ) { 108 return value; 109 } 110 } 111 elem = elem.parent(); 112 } 113 } 114 115 return 0; 116 }, 117 118 disableSelection: function() { 119 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + 120 ".ui-disableSelection", function( event ) { 121 event.preventDefault(); 122 }); 123 }, 124 125 enableSelection: function() { 126 return this.unbind( ".ui-disableSelection" ); 127 } 128}); 129 130// support: jQuery <1.8 131if ( !$( "<a>" ).outerWidth( 1 ).jquery ) { 132 $.each( [ "Width", "Height" ], function( i, name ) { 133 var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], 134 type = name.toLowerCase(), 135 orig = { 136 innerWidth: $.fn.innerWidth, 137 innerHeight: $.fn.innerHeight, 138 outerWidth: $.fn.outerWidth, 139 outerHeight: $.fn.outerHeight 140 }; 141 142 function reduce( elem, size, border, margin ) { 143 $.each( side, function() { 144 size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0; 145 if ( border ) { 146 size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0; 147 } 148 if ( margin ) { 149 size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0; 150 } 151 }); 152 return size; 153 } 154
155 $.fn[ "inner" + name ] = function( size ) { 156 if ( size === undefined ) { 157 return orig[ "inner" + name ].call( this ); 158 } 159 160 return this.each(function() { 161 $( this ).css( type, reduce( this, size ) + "px" ); 162 }); 163 }; 164 165 $.fn[ "outer" + name] = function( size, margin ) { 166 if ( typeof size !== "number" ) { 167 return orig[ "outer" + name ].call( this, size ); 168 } 169 170 return this.each(function() { 171 $( this).css( type, reduce( this, size, true, margin ) + "px" ); 172 }); 173 }; 174 }); 175} 176 177// selectors 178function focusable( element, isTabIndexNotNaN ) { 179 var nodeName = element.nodeName.toLowerCase(); 180 if ( "area" === nodeName ) { 181 var map = element.parentNode, 182 mapName = map.name, 183 img; 184 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { 185 return false; 186 } 187 img = $( "img[usemap=#" + mapName + "]" )[0]; 188 return !!img && visible( img ); 189 } 190 return ( /input|select|textarea|button|object/.test( nodeName ) 191 ? !element.disabled 192 : "a" == nodeName 193 ? element.href || isTabIndexNotNaN 194 : isTabIndexNotNaN) 195 // the element and all of its ancestors must be visible 196 && visible( element ); 197} 198 199function visible( element ) { 200 return !$( element ).parents().andSelf().filter(function() { 201 return $.curCSS( this, "visibility" ) === "hidden" || 202 $.expr.filters.hidden( this ); 203 }).length; 204} 205 206$.extend( $.expr[ ":" ], { 207 data: $.expr.createPseudo ? 208 $.expr.createPseudo(function( dataName ) { 209 return function( elem ) { 210 return !!$.data( elem, dataName ); 211 }; 212 }) : 213 // support: jQuery <1.8 214 function( elem, i, match ) { 215 return !!$.data( elem, match[ 3 ] ); 216 }, 217 218 focusable: function( element ) { 219 return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); 220 }, 221 222 tabbable: function( element ) { 223 var tabIndex = $.attr( element, "tabindex" ), 224 isTabIndexNaN = isNaN( tabIndex ); 225 return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); 226 } 227}); 228 229// support 230$(function() { 231 var body = document.body, 232 div = body.appendChild( div = document.createElement( "div" ) ); 233 234 // access offsetHeight before setting the style to prevent a layout bug 235 // in IE 9 which causes the elemnt to continue to take up space even 236 // after it is removed from the DOM (#8026) 237 div.offsetHeight; 238 239 $.extend( div.style, { 240 minHeight: "100px", 241 height: "auto", 242 padding: 0, 243 borderWidth: 0 244 }); 245 246 $.support.minHeight = div.offsetHeight === 100; 247 $.support.selectstart = "onselectstart" in div; 248 249 // set display to none to avoid a layout bug in IE 250 // http://dev.jquery.com/ticket/4014 251 body.removeChild( div ).style.display = "none"; 252}); 253 254// jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css 255if ( !$.curCSS ) { 256 $.curCSS = $.css; 257} 258 259 260 261 262 263// deprecated 264$.extend( $.ui, { 265 // $.ui.plugin is deprecated. Use the proxy pattern instead. 266 plugin: { 267 add: function( module, option, set ) { 268 var proto = $.ui[ module ].prototype; 269 for ( var 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 set = instance.plugins[ name ]; 276 if ( !set || !instance.element[ 0 ].parentNode ) { 277 return; 278 } 279 280 for ( var i = 0; i < set.length; i++ ) { 281 if ( instance.options[ set[ i ][ 0 ] ] ) { 282 set[ i ][ 1 ].apply( instance.element, args ); 283 } 284 } 285 } 286 }, 287 288 // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains() 289 contains: function( a, b ) { 290 return document.compareDocumentPosition ? 291 a.compareDocumentPosition( b ) & 16 : 292 a !== b && a.contains( b ); 293 }, 294 295 // only used by resizable 296 hasScroll: function( el, a ) { 297 298 //If overflow is hidden, the element might have extra content, but the user wants to hide it 299 if ( $( el ).css( "overflow" ) === "hidden") { 300 return false; 301 } 302 303 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", 304 has = false; 305 306 if ( el[ scroll ] > 0 ) { 307 return true; 308 } 309 310 // TODO: determine which cases actually cause this to happen 311 // if the element doesn't have the scroll set, see if it's possible to 312 // set the scroll 313 el[ scroll ] = 1; 314 has = ( el[ scroll ] > 0 ); 315 el[ scroll ] = 0; 316 return has; 317 }, 318
319 // these are odd functions, fix the API or move into individual plugins 320 isOverAxis: function( x, reference, size ) { 321 //Determines when x coordinate is over "b" element axis 322 return ( x > reference ) && ( x < ( reference + size ) ); 323 }, 324 isOver: function( y, x, top, left, height, width ) { 325 //Determines when x, y coordinates is over "b" element 326 return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width ); 327 } 328}); 329 330})( jQuery ); 331 332(function( $, undefined ) { 333 334// jQuery 1.4+ 335if ( $.cleanData ) { 336 var _cleanData = $.cleanData; 337 $.cleanData = function( elems ) { 338 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { 339 try { 340 $( elem ).triggerHandler( "remove" ); 341 // http://bugs.jquery.com/ticket/8235 342 } catch( e ) {} 343 } 344 _cleanData( elems ); 345 }; 346} else { 347 var _remove = $.fn.remove; 348 $.fn.remove = function( selector, keepData ) { 349 return this.each(function() { 350 if ( !keepData ) { 351 if ( !selector || $.filter( selector, [ this ] ).length ) { 352 $( "*", this ).add( [ this ] ).each(function() { 353 try { 354 $( this ).triggerHandler( "remove" ); 355 // http://bugs.jquery.com/ticket/8235 356 } catch( e ) {} 357 }); 358 } 359 } 360 return _remove.call( $(this), selector, keepData ); 361 }); 362 }; 363} 364 365$.widget = function( name, base, prototype ) { 366 var namespace = name.split( "." )[ 0 ], 367 fullName; 368 name = name.split( "." )[ 1 ]; 369 fullName = namespace + "-" + name; 370 371 if ( !prototype ) { 372 prototype = base; 373 base = $.Widget; 374 } 375 376 // create selector for plugin 377 $.expr[ ":" ][ fullName ] = function( elem ) { 378 return !!$.data( elem, name ); 379 }; 380 381 $[ namespace ] = $[ namespace ] || {}; 382 $[ namespace ][ name ] = function( options, element ) { 383 // allow instantiation without initializing for simple inheritance 384 if ( arguments.length ) { 385 this._createWidget( options, element ); 386 } 387 }; 388 389 var basePrototype = new base(); 390 // we need to make the options hash a property directly on the new instance 391 // otherwise we'll modify the options hash on the prototype that we're 392 // inheriting from 393// $.each( basePrototype, function( key, val ) { 394// if ( $.isPlainObject(val) ) { 395// basePrototype[ key ] = $.extend( {}, val ); 396// } 397// }); 398 basePrototype.options = $.extend( true, {}, basePrototype.options ); 399 $[ namespace ][ name ].prototype = $.extend( true, basePrototype, { 400 namespace: namespace, 401 widgetName: name, 402 widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name, 403 widgetBaseClass: fullName 404 }, prototype ); 405 406 $.widget.bridge( name, $[ namespace ][ name ] ); 407}; 408 409$.widget.bridge = function( name, object ) { 410 $.fn[ name ] = function( options ) { 411 var isMethodCall = typeof options === "string", 412 args = Array.prototype.slice.call( arguments, 1 ), 413 returnValue = this; 414 415 // allow multiple hashes to be passed on init 416 options = !isMethodCall && args.length ? 417 $.extend.apply( null, [ true, options ].concat(args) ) : 418 options; 419 420 // prevent calls to internal methods 421 if ( isMethodCall && options.charAt( 0 ) === "_" ) { 422 return returnValue; 423 } 424 425 if ( isMethodCall ) { 426 this.each(function() { 427 var instance = $.data( this, name ), 428 methodValue = instance && $.isFunction( instance[options] ) ? 429 instance[ options ].apply( instance, args ) : 430 instance; 431 // TODO: add this back in 1.9 and use $.error() (see #5972) 432// if ( !instance ) { 433// throw "cannot call methods on " + name + " prior to initialization; " + 434// "attempted to call method '" + options + "'"; 435// } 436// if ( !$.isFunction( instance[options] ) ) { 437// throw "no such method '" + options + "' for " + name + " widget instance"; 438// } 439// var methodValue = instance[ options ].apply( instance, args ); 440 if ( methodValue !== instance && methodValue !== undefined ) { 441 returnValue = methodValue; 442 return false; 443 } 444 }); 445 } else { 446 this.each(function() { 447 var instance = $.data( this, name ); 448 if ( instance ) { 449 instance.option( options || {} )._init(); 450 } else { 451 $.data( this, name, new object( options, this ) ); 452 } 453 }); 454 } 455 456 return returnValue; 457 }; 458}; 459 460$.Widget = function( options, element ) { 461 // allow instantiation without initializing for simple inheritance 462 if ( arguments.length ) { 463 this._createWidget( options, element ); 464 } 465}; 466 467$.Widget.prototype = { 468 widgetName: "widget", 469 widgetEventPrefix: "", 470 options: { 471 disabled: false 472 }, 473 _createWidget: function( options, element ) { 474 // $.widget.bridge stores the plugin instance, but we do it anyway 475 // so that it's stored even before the _create function runs 476 $.data( element, this.widgetName, this ); 477 this.element = $( element ); 478 this.options = $.extend( true, {}, 479 this.options, 480 this._getCreateOptions(), 481 options ); 482 483 var self = this; 484 this.element.bind( "remove." + this.widgetName, function() { 485 self.destroy(); 486 }); 487 488 this._create(); 489 this._trigger( "create" ); 490 this._init(); 491 }, 492 _getCreateOptions: function() { 493 return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ]; 494 }, 495 _create: function() {}, 496 _init: function() {}, 497 498 destroy: function() { 499 this.element 500 .unbind( "." + this.widgetName ) 501 .removeData( this.widgetName ); 502 this.widget() 503 .unbind( "." + this.widgetName ) 504 .removeAttr( "aria-disabled" ) 505 .removeClass( 506 this.widgetBaseClass + "-disabled " + 507 "ui-state-disabled" ); 508 }, 509 510 widget: function() { 511 return this.element; 512 }, 513 514 option: function( key, value ) { 515 var options = key; 516 517 if ( arguments.length === 0 ) { 518 // don't return a reference to the internal hash 519 return $.extend( {}, this.options ); 520 } 521 522 if (typeof key === "string" ) { 523 if ( value === undefined ) { 524 return this.options[ key ]; 525 } 526 options = {}; 527 options[ key ] = value; 528 } 529 530 this._setOptions( options ); 531 532 return this; 533 }, 534 _setOptions: function( options ) { 535 var self = this; 536 $.each( options, function( key, value ) { 537 self._setOption( key, value ); 538 }); 539 540 return this; 541 }, 542 _setOption: function( key, value ) { 543 this.options[ key ] = value; 544 545 if ( key === "disabled" ) { 546 this.widget() 547 [ value ? "addClass" : "removeClass"]( 548 this.widgetBaseClass + "-disabled" + " " + 549 "ui-state-disabled" ) 550 .attr( "aria-disabled", value ); 551 } 552 553 return this; 554 }, 555 556 enable: function() { 557 return this._setOption( "disabled", false ); 558 }, 559 disable: function() { 560 return this._setOption( "disabled", true ); 561 }, 562 563 _trigger: function( type, event, data ) { 564 var prop, orig, 565 callback = this.options[ type ]; 566 567 data = data || {}; 568 event = $.Event( event ); 569 event.type = ( type === this.widgetEventPrefix ? 570 type : 571 this.widgetEventPrefix + type ).toLowerCase(); 572 // the original event may come from any element 573 // so we need to reset the target on the new event 574 event.target = this.element[ 0 ]; 575 576 // copy original event properties over to the new event 577 orig = event.originalEvent; 578 if ( orig ) { 579 for ( prop in orig ) { 580 if ( !( prop in event ) ) { 581 event[ prop ] = orig[ prop ]; 582 } 583 } 584 } 585 586 this.element.trigger( event, data ); 587 588 return !( $.isFunction(callback) && 589 callback.call( this.element[0], event, data ) === false || 590 event.isDefaultPrevented() ); 591 } 592}; 593 594}
vendor: 2,391 bytes, lines 594-677
594)( jQuery ); 595 596(function( $, undefined ) { 597 598var mouseHandled = false; 599$( document ).mouseup( function( e ) { 600 mouseHandled = false; 601}); 602 603$.widget("ui.mouse", { 604 options: { 605 cancel: ':input,option', 606 distance: 1, 607 delay: 0 608 }, 609 _mouseInit: function() { 610 var self = this; 611 612 this.element 613 .bind('mousedown.'+this.widgetName, function(event) { 614 return self._mouseDown(event); 615 }) 616 .bind('click.'+this.widgetName, function(event) { 617 if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) { 618 $.removeData(event.target, self.widgetName + '.preventClickEvent'); 619 event.stopImmediatePropagation(); 620 return false; 621 } 622 }); 623 624 this.started = false; 625 }, 626 627 // TODO: make sure destroying one instance of mouse doesn't mess with 628 // other instances of mouse 629 _mouseDestroy: function() { 630 this.element.unbind('.'+this.widgetName); 631 if ( this._mouseMoveDelegate ) { 632 $(document) 633 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate) 634 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate); 635 } 636 }, 637 638 _mouseDown: function(event) { 639 // don't let more than one widget handle mouseStart 640 if( mouseHandled ) { return }; 641 642 // we may have missed mouseup (out of window) 643 (this._mouseStarted && this._mouseUp(event)); 644 645 this._mouseDownEvent = event; 646 647 var self = this, 648 btnIsLeft = (event.which == 1), 649 // event.target.nodeName works around a bug in IE 8 with 650 // disabled inputs (#7620) 651 elIsCancel = (typeof this.options.cancel == "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); 652 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { 653 return true; 654 } 655 656 this.mouseDelayMet = !this.options.delay; 657 if (!this.mouseDelayMet) { 658 this._mouseDelayTimer = setTimeout(function() { 659 self.mouseDelayMet = true; 660 }, this.options.delay); 661 } 662 663 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 664 this._mouseStarted = (this._mouseStart(event) !== false); 665 if (!this._mouseStarted) { 666 event.preventDefault(); 667 return true; 668 } 669 } 670 671 // Click event may never have fired (Gecko & Opera) 672 if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) { 673 $.removeData(event.target, this.widgetName + '.preventClickEvent'); 674 } 675 676 // these delegates are required to keep context 677 this._mouseMoveDelegate = function(event) {
678 return self._mouseMove(event); 679 }; 680 this._mouseUpDelegate = function(event) { 681 return self._mouseUp(event); 682 }; 683 $(document) 684 .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate) 685 .bind('mouseup.'+this.widgetName, this._mouseUpDelegate); 686 687 event.preventDefault(); 688 689 mouseHandled = true; 690 return true; 691 }, 692 693 _mouseMove: function(event) { 694 // IE mouseup check - mouseup happened when mouse was out of window 695 if ($.browser.msie && !(document.documentMode >= 9) && !event.button) { 696 return this._mouseUp(event); 697 } 698 699 if (this._mouseStarted) { 700 this._mouseDrag(event); 701 return event.preventDefault(); 702 } 703 704 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { 705 this._mouseStarted = 706 (this._mouseStart(this._mouseDownEvent, event) !== false); 707 (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); 708 } 709 710 return !this._mouseStarted; 711 }, 712 713 _mouseUp: function(event) { 714 $(document) 715 .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate) 716 .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate); 717 718 if (this._mouseStarted) { 719 this._mouseStarted = false; 720 721 if (event.target == this._mouseDownEvent.target) { 722 $.data(event.target, this.widgetName + '.preventClickEvent', true); 723 } 724 725 this._mouseStop(event); 726 } 727 728 return false; 729 }, 730 731 _mouseDistanceMet: function(event) { 732 return (Math.max( 733 Math.abs(this._mouseDownEvent.pageX - event.pageX), 734 Math.abs(this._mouseDownEvent.pageY - event.pageY) 735 ) >= this.options.distance 736 ); 737 }, 738 739 _mouseDelayMet: function(event) { 740 return this.mouseDelayMet; 741 }, 742 743 // These are placeholder methods, to be overriden by extending plugin 744 _mouseStart: function(event) {}, 745 _mouseDrag: function(event) {}, 746 _mouseStop: function(event) {}, 747 _mouseCapture: function(event) { return true; } 748}); 749 750})(jQuery); 751 752(function( $, undefined ) { 753 754$.widget("ui.draggable", $.ui.mouse, { 755 widgetEventPrefix: "drag", 756 options: { 757 addClasses: true, 758 appendTo: "parent", 759 axis: false, 760 connectToSortable: false, 761 containment: false, 762 cursor: "auto", 763 cursorAt: false, 764 grid: false, 765 handle: false, 766 helper: "original", 767 iframeFix: false, 768 opacity: false, 769 refreshPositions: false, 770 revert: false, 771 revertDuration: 500, 772 scope: "default", 773 scroll: true, 774 scrollSensitivity: 20, 775 scrollSpeed: 20, 776 snap: false, 777 snapMode: "both", 778 snapTolerance: 20, 779 stack: false, 780 zIndex: false 781 }, 782 _create: function() { 783 784 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position"))) 785 this.element[0].style.position = 'relative'; 786 787 (this.options.addClasses && this.element.addClass("ui-draggable")); 788 (this.options.disabled && this.element.addClass("ui-draggable-disabled")); 789 790 this._mouseInit(); 791 792 }, 793 794 destroy: function() { 795 if(!this.element.data('draggable')) return; 796 this.element 797 .removeData("draggable") 798 .unbind(".draggable") 799 .removeClass("ui-draggable" 800 + " ui-draggable-dragging" 801 + " ui-draggable-disabled"); 802 this._mouseDestroy(); 803 804 return this; 805 }, 806 807 _mouseCapture: function(event) { 808 809 var o = this.options; 810 811 // among others, prevent a drag on a resizable-handle 812 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle')) 813 return false; 814 815 //Quit if we're not on a valid handle 816 this.handle = this._getHandle(event); 817 if (!this.handle) 818 return false; 819 820 if ( o.iframeFix ) { 821 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { 822 $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>') 823 .css({ 824 width: this.offsetWidth+"px", height: this.offsetHeight+"px", 825 position: "absolute", opacity: "0.001", zIndex: 1000 826 }) 827 .css($(this).offset()) 828 .appendTo("body"); 829 }); 830 } 831 832 return true; 833 834 }, 835 836 _mouseStart: function(event) { 837 838 var o = this.options; 839 840 //Create and append the visible helper 841 this.helper = this._createHelper(event); 842 843 this.helper.addClass("ui-draggable-dragging"); 844 845 //Cache the helper size 846 this._cacheHelperProportions(); 847 848 //If ddmanager is used for droppables, set the global draggable 849 if($.ui.ddmanager) 850 $.ui.ddmanager.current = this; 851 852 /* 853 * - Position generation - 854 * This block generates everything position related - it's the core of draggables. 855 */ 856 857 //Cache the margins of the original element 858 this._cacheMargins(); 859 860 //Store the helper's css position 861 this.cssPosition = this.helper.css("position"); 862 this.scrollParent = this.helper.scrollParent(); 863 864 //The element's absolute position on the page minus margins 865 this.offset = this.positionAbs = this.element.offset(); 866 this.offset = { 867 top: this.offset.top - this.margins.top, 868 left: this.offset.left - this.margins.left 869 }; 870 871 $.extend(this.offset, { 872 click: { //Where the click happened, relative to the element 873 left: event.pageX - this.offset.left, 874 top: event.pageY - this.offset.top 875 }, 876 parent: this._getParentOffset(), 877 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper 878 }); 879 880 //Generate the original position 881 this.originalPosition = this.position = this._generatePosition(event); 882 this.originalPageX = event.pageX; 883 this.originalPageY = event.pageY; 884 885 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied 886 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); 887 888 //Set a containment if given in the options 889 if(o.containment) 890 this._setContainment(); 891 892 //Trigger event + callbacks 893 if(this._trigger("start", event) === false) { 894 this._clear(); 895 return false;
896 } 897 898 //Recache the helper size 899 this._cacheHelperProportions(); 900 901 //Prepare the droppable offsets 902 if ($.ui.ddmanager && !o.dropBehaviour) 903 $.ui.ddmanager.prepareOffsets(this, event); 904 905 906 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position 907 908 //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) 909 if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event); 910 911 return true; 912 }, 913 914 _mouseDrag: function(event, noPropagation) { 915 916 //Compute the helpers position 917 this.position = this._generatePosition(event); 918 this.positionAbs = this._convertPositionTo("absolute"); 919 920 //Call plugins and callbacks and use the resulting position if something is returned 921 if (!noPropagation) { 922 var ui = this._uiHash(); 923 if(this._trigger('drag', event, ui) === false) { 924 this._mouseUp({}); 925 return false; 926 } 927 this.position = ui.position; 928 } 929 930 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; 931 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; 932 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); 933 934 return false; 935 }, 936 937 _mouseStop: function(event) { 938 939 //If we are using droppables, inform the manager about the drop 940 var dropped = false; 941 if ($.ui.ddmanager && !this.options.dropBehaviour) 942 dropped = $.ui.ddmanager.drop(this, event); 943 944 //if a drop comes from outside (a sortable) 945 if(this.dropped) { 946 dropped = this.dropped; 947 this.dropped = false; 948 } 949 950 //if the original element is no longer in the DOM don't bother to continue (see #8269) 951 var element = this.element[0], elementInDom = false;
952 while ( element && (element = element.parentNode) ) { 953 if (element == document ) { 954 elementInDom = true; 955 } 956 } 957 if ( !elementInDom && this.options.helper === "original" ) 958 return false; 959 960 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))) { 961 var self = this; 962 $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { 963 if(self._trigger("stop", event) !== false) { 964 self._clear(); 965 } 966 }); 967 } else { 968 if(this._trigger("stop", event) !== false) { 969 this._clear(); 970 } 971 } 972 973 return false; 974 }, 975 976 _mouseUp: function(event) { 977 //Remove frame helpers 978 $("div.ui-draggable-iframeFix").each(function() { 979 this.parentNode.removeChild(this); 980 }); 981 982 //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) 983 if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event); 984 985 return $.ui.mouse.prototype._mouseUp.call(this, event); 986 }, 987 988 cancel: function() { 989 990 if(this.helper.is(".ui-draggable-dragging")) { 991 this._mouseUp({}); 992 } else { 993 this._clear(); 994 } 995 996 return this; 997 998 }, 999 1000 _getHandle: function(event) { 1001 1002 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false; 1003 $(this.options.handle, this.element) 1004 .find("*") 1005 .andSelf() 1006 .each(function() { 1007 if(this == event.target) handle = true; 1008 }); 1009 1010 return handle; 1011 1012 }, 1013 1014 _createHelper: function(event) { 1015 1016 var o = this.options; 1017 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element); 1018 1019 if(!helper.parents('body').length) 1020 helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)); 1021 1022 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) 1023 helper.css("position", "absolute"); 1024 1025 return helper; 1026 1027 }, 1028 1029 _adjustOffsetFromHelper: function(obj) { 1030 if (typeof obj == 'string') { 1031 obj = obj.split(' '); 1032 } 1033 if ($.isArray(obj)) { 1034 obj = {left: +obj[0], top: +obj[1] || 0}; 1035 } 1036 if ('left' in obj) { 1037 this.offset.click.left = obj.left + this.margins.left; 1038 } 1039 if ('right' in obj) { 1040 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 1041 } 1042 if ('top' in obj) { 1043 this.offset.click.top = obj.top + this.margins.top; 1044 } 1045 if ('bottom' in obj) { 1046 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 1047 } 1048 }, 1049 1050 _getParentOffset: function() { 1051 1052 //Get the offsetParent and cache its position 1053 this.offsetParent = this.helper.offsetParent(); 1054 var po = this.offsetParent.offset(); 1055 1056 // This is a special case where we need to modify a offset calculated on start, since the following happened: 1057 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent 1058 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that 1059 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag 1060 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) { 1061 po.left += this.scrollParent.scrollLeft(); 1062 po.top += this.scrollParent.scrollTop(); 1063 } 1064 1065 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information 1066 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix 1067 po = { top: 0, left: 0 }; 1068 1069 return { 1070 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), 1071 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) 1072 }; 1073 1074 }, 1075 1076 _getRelativeOffset: function() { 1077 1078 if(this.cssPosition == "relative") { 1079 var p = this.element.position(); 1080 return { 1081 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), 1082 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() 1083 }; 1084 } else { 1085 return { top: 0, left: 0 }; 1086 } 1087 1088 }, 1089 1090 _cacheMargins: function() { 1091 this.margins = { 1092 left: (parseInt(this.element.css("marginLeft"),10) || 0), 1093 top: (parseInt(this.element.css("marginTop"),10) || 0), 1094 right: (parseInt(this.element.css("marginRight"),10) || 0), 1095 bottom: (parseInt(this.element.css("marginBottom"),10) || 0) 1096 }; 1097 }, 1098 1099 _cacheHelperProportions: function() { 1100 this.helperProportions = { 1101 width: this.helper.outerWidth(), 1102 height: this.helper.outerHeight() 1103 }; 1104 }, 1105 1106 _setContainment: function() { 1107 1108 var o = this.options; 1109 if(o.containment == 'parent') o.containment = this.helper[0].parentNode; 1110 if(o.containment == 'document' || o.containment == 'window') this.containment = [ 1111 o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left, 1112 o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top, 1113 (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, 1114 (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top 1115 ]; 1116 1117 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) { 1118 var c = $(o.containment); 1119 var ce = c[0]; if(!ce) return; 1120 var co = c.offset(); 1121 var over = ($(ce).css("overflow") != 'hidden'); 1122 1123 this.containment = [ 1124 (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
1125 (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0), 1126 (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right, 1127 (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom 1128 ]; 1129 this.relative_container = c; 1130 1131 } else if(o.containment.constructor == Array) { 1132 this.containment = o.containment; 1133 } 1134 1135 }, 1136 1137 _convertPositionTo: function(d, pos) { 1138 1139 if(!pos) pos = this.position; 1140 var mod = d == "absolute" ? 1 : -1; 1141 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 1142 1143 return { 1144 top: ( 1145 pos.top // The absolute mouse position 1146 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent 1147 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) 1148 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) 1149 ), 1150 left: ( 1151 pos.left // The absolute mouse position 1152 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent 1153 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) 1154 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) 1155 ) 1156 }; 1157 1158 }, 1159 1160 _generatePosition: function(event) { 1161 1162 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 1163 var pageX = event.pageX; 1164 var pageY = event.pageY; 1165 1166 /* 1167 * - Position constraining - 1168 * Constrain the position to a mix of grid, containment. 1169 */ 1170 1171 if(this.originalPosition) { //If we are not dragging yet, we won't check for options 1172 var containment; 1173 if(this.containment) { 1174 if (this.relative_container){ 1175 var co = this.relative_container.offset(); 1176 containment = [ this.containment[0] + co.left, 1177 this.containment[1] + co.top, 1178 this.containment[2] + co.left, 1179 this.containment[3] + co.top ]; 1180 } 1181 else { 1182 containment = this.containment; 1183 } 1184 1185 if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left; 1186 if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top; 1187 if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left; 1188 if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top; 1189 } 1190 1191 if(o.grid) { 1192 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) 1193 var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; 1194 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; 1195 1196 var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; 1197 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; 1198 } 1199 1200 } 1201 1202 return { 1203 top: ( 1204 pageY // The absolute mouse position 1205 - this.offset.click.top // Click offset (relative to the element) 1206 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent 1207 - this.offset.parent.top // The offsetParent's offset without borders (offset + border) 1208 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) 1209 ), 1210 left: ( 1211 pageX // The absolute mouse position 1212 - this.offset.click.left // Click offset (relative to the element) 1213 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent 1214 - this.offset.parent.left // The offsetParent's offset without borders (offset + border) 1215 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) 1216 ) 1217 }; 1218 1219 }, 1220 1221 _clear: function() { 1222 this.helper.removeClass("ui-draggable-dragging"); 1223 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove(); 1224 //if($.ui.ddmanager) $.ui.ddmanager.current = null; 1225 this.helper = null; 1226 this.cancelHelperRemoval = false;
1227 }, 1228 1229 // From now on bulk stuff - mainly helpers 1230 1231 _trigger: function(type, event, ui) { 1232 ui = ui || this._uiHash(); 1233 $.ui.plugin.call(this, type, [event, ui]); 1234 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins 1235 return $.Widget.prototype._trigger.call(this, type, event, ui); 1236 }, 1237 1238 plugins: {}, 1239 1240 _uiHash: function(event) { 1241 return { 1242 helper: this.helper, 1243 position: this.position, 1244 originalPosition: this.originalPosition, 1245 offset: this.positionAbs 1246 }; 1247 } 1248 1249}); 1250 1251$.extend($.ui.draggable, { 1252 version: "1.8.24" 1253}); 1254 1255$.ui.plugin.add("draggable", "connectToSortable", { 1256 start: function(event, ui) { 1257 1258 var inst = $(this).data("draggable"), o = inst.options, 1259 uiSortable = $.extend({}, ui, { item: inst.element }); 1260 inst.sortables = []; 1261 $(o.connectToSortable).each(function() { 1262 var sortable = $.data(this, 'sortable'); 1263 if (sortable && !sortable.options.disabled) { 1264 inst.sortables.push({ 1265 instance: sortable, 1266 shouldRevert: sortable.options.revert 1267 }); 1268 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). 1269 sortable._trigger("activate", event, uiSortable); 1270 } 1271 }); 1272 1273 }, 1274 stop: function(event, ui) { 1275 1276 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper 1277 var inst = $(this).data("draggable"), 1278 uiSortable = $.extend({}, ui, { item: inst.element }); 1279 1280 $.each(inst.sortables, function() { 1281 if(this.instance.isOver) { 1282 1283 this.instance.isOver = 0; 1284 1285 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance 1286 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) 1287 1288 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid' 1289 if(this.shouldRevert) this.instance.options.revert = true; 1290 1291 //Trigger the stop of the sortable 1292 this.instance._mouseStop(event); 1293 1294 this.instance.options.helper = this.instance.options._helper; 1295 1296 //If the helper has been the original item, restore properties in the sortable 1297 if(inst.options.helper == 'original') 1298 this.instance.currentItem.css({ top: 'auto', left: 'auto' }); 1299 1300 } else { 1301 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance 1302 this.instance._trigger("deactivate", event, uiSortable); 1303 } 1304 1305 }); 1306 1307 }, 1308 drag: function(event, ui) { 1309 1310 var inst = $(this).data("draggable"), self = this; 1311 1312 var checkPos = function(o) { 1313 var dyClick = this.offset.click.top, dxClick = this.offset.click.left; 1314 var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left; 1315 var itemHeight = o.height, itemWidth = o.width; 1316 var itemTop = o.top, itemLeft = o.left; 1317 1318 return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth); 1319 }; 1320 1321 $.each(inst.sortables, function(i) { 1322 1323 //Copy over some variables to allow calling the sortable's native _intersectsWith 1324 this.instance.positionAbs = inst.positionAbs; 1325 this.instance.helperProportions = inst.helperProportions; 1326 this.instance.offset.click = inst.offset.click; 1327 1328 if(this.instance._intersectsWith(this.instance.containerCache)) { 1329 1330 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once 1331 if(!this.instance.isOver) { 1332 1333 this.instance.isOver = 1; 1334 //Now we fake the start of dragging for the sortable instance, 1335 //by cloning the list group item, appending it to the sortable and using it as inst.currentItem 1336 //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) 1337 this.instance.currentItem = $(self).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true); 1338 this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it 1339 this.instance.options.helper = function() { return ui.helper[0]; }; 1340 1341 event.target = this.instance.currentItem[0]; 1342 this.instance._mouseCapture(event, true); 1343 this.instance._mouseStart(event, true, true); 1344
1345 //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes 1346 this.instance.offset.click.top = inst.offset.click.top; 1347 this.instance.offset.click.left = inst.offset.click.left; 1348 this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; 1349 this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; 1350 1351 inst._trigger("toSortable", event); 1352 inst.dropped = this.instance.element; //draggable revert needs that 1353 //hack so receive/update callbacks work (mostly) 1354 inst.currentItem = inst.element; 1355 this.instance.fromOutside = inst; 1356 1357 } 1358 1359 //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 1360 if(this.instance.currentItem) this.instance._mouseDrag(event); 1361 1362 } else { 1363 1364 //If it doesn't intersect with the sortable, and it intersected before, 1365 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval 1366 if(this.instance.isOver) { 1367 1368 this.instance.isOver = 0; 1369 this.instance.cancelHelperRemoval = true; 1370 1371 //Prevent reverting on this forced stop 1372 this.instance.options.revert = false; 1373 1374 // The out event needs to be triggered independently 1375 this.instance._trigger('out', event, this.instance._uiHash(this.instance)); 1376 1377 this.instance._mouseStop(event, true); 1378 this.instance.options.helper = this.instance.options._helper; 1379 1380 //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size 1381 this.instance.currentItem.remove(); 1382 if(this.instance.placeholder) this.instance.placeholder.remove(); 1383 1384 inst._trigger("fromSortable", event); 1385 inst.dropped = false; //draggable revert needs that 1386 } 1387 1388 }; 1389 1390 }); 1391 1392 } 1393}); 1394 1395$.ui.plugin.add("draggable", "cursor", { 1396 start: function(event, ui) { 1397 var t = $('body'), o = $(this).data('draggable').options; 1398 if (t.css("cursor")) o._cursor = t.css("cursor"); 1399 t.css("cursor", o.cursor); 1400 }, 1401 stop: function(event, ui) { 1402 var o = $(this).data('draggable').options; 1403 if (o._cursor) $('body').css("cursor", o._cursor); 1404 } 1405}); 1406 1407$.ui.plugin.add("draggable", "opacity", { 1408 start: function(event, ui) { 1409 var t = $(ui.helper), o = $(this).data('draggable').options; 1410 if(t.css("opacity")) o._opacity = t.css("opacity"); 1411 t.css('opacity', o.opacity); 1412 }, 1413 stop: function(event, ui) { 1414 var o = $(this).data('draggable').options; 1415 if(o._opacity) $(ui.helper).css('opacity', o._opacity); 1416 } 1417}); 1418 1419$.ui.plugin.add("draggable", "scroll", { 1420 start: function(event, ui) { 1421 var i = $(this).data("draggable"); 1422 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset(); 1423 }, 1424 drag: function(event, ui) { 1425 1426 var i = $(this).data("draggable"), o = i.options, scrolled = false; 1427 1428 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') { 1429 1430 if(!o.axis || o.axis != 'x') { 1431 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) 1432 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; 1433 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) 1434 i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; 1435 } 1436 1437 if(!o.axis || o.axis != 'y') { 1438 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) 1439 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; 1440 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) 1441 i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; 1442 } 1443 1444 } else { 1445 1446 if(!o.axis || o.axis != 'x') { 1447 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) 1448 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); 1449 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) 1450 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); 1451 } 1452 1453 if(!o.axis || o.axis != 'y') { 1454 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) 1455 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); 1456 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) 1457 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); 1458 } 1459 1460 } 1461 1462 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) 1463 $.ui.ddmanager.prepareOffsets(i, event); 1464 1465 } 1466}); 1467 1468$.ui.plugin.add("draggable", "snap", { 1469 start: function(event, ui) { 1470 1471 var i = $(this).data("draggable"), o = i.options; 1472 i.snapElements = []; 1473 1474 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() { 1475 var $t = $(this); var $o = $t.offset(); 1476 if(this != i.element[0]) i.snapElements.push({ 1477 item: this, 1478 width: $t.outerWidth(), height: $t.outerHeight(), 1479 top: $o.top, left: $o.left 1480 }); 1481 }); 1482 1483 }, 1484 drag: function(event, ui) { 1485 1486 var inst = $(this).data("draggable"), o = inst.options; 1487 var d = o.snapTolerance; 1488 1489 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, 1490 y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; 1491 1492 for (var i = inst.snapElements.length - 1; i >= 0; i--){ 1493 1494 var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width, 1495 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height; 1496 1497 //Yes, I know, this is insane ;) 1498 if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) { 1499 if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); 1500 inst.snapElements[i].snapping = false;
1501 continue; 1502 } 1503 1504 if(o.snapMode != 'inner') { 1505 var ts = Math.abs(t - y2) <= d; 1506 var bs = Math.abs(b - y1) <= d; 1507 var ls = Math.abs(l - x2) <= d; 1508 var rs = Math.abs(r - x1) <= d; 1509 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; 1510 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; 1511 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; 1512 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; 1513 } 1514 1515 var first = (ts || bs || ls || rs); 1516 1517 if(o.snapMode != 'outer') { 1518 var ts = Math.abs(t - y1) <= d; 1519 var bs = Math.abs(b - y2) <= d; 1520 var ls = Math.abs(l - x1) <= d; 1521 var rs = Math.abs(r - x2) <= d; 1522 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; 1523 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; 1524 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; 1525 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; 1526 } 1527 1528 if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) 1529 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); 1530 inst.snapElements[i].snapping = (ts || bs || ls || rs || first); 1531 1532 }; 1533 1534 } 1535}); 1536 1537$.ui.plugin.add("draggable", "stack", { 1538 start: function(event, ui) { 1539 1540 var o = $(this).data("draggable").options; 1541 1542 var group = $.makeArray($(o.stack)).sort(function(a,b) { 1543 return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); 1544 }); 1545 if (!group.length) { return; } 1546 1547 var min = parseInt(group[0].style.zIndex) || 0; 1548 $(group).each(function(i) { 1549 this.style.zIndex = min + i; 1550 }); 1551 1552 this[0].style.zIndex = min + group.length; 1553 1554 } 1555}); 1556 1557$.ui.plugin.add("draggable", "zIndex", { 1558 start: function(event, ui) { 1559 var t = $(ui.helper), o = $(this).data("draggable").options; 1560 if(t.css("zIndex")) o._zIndex = t.css("zIndex"); 1561 t.css('zIndex', o.zIndex); 1562 }, 1563 stop: function(event, ui) { 1564 var o = $(this).data("draggable").options; 1565 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex); 1566 } 1567}); 1568 1569})(jQuery); 1570 1571(function( $, undefined ) { 1572 1573$.widget("ui.droppable", { 1574 widgetEventPrefix: "drop", 1575 options: { 1576 accept: '*', 1577 activeClass: false, 1578 addClasses: true, 1579 greedy: false, 1580 hoverClass: false, 1581 scope: 'default', 1582 tolerance: 'intersect' 1583 }, 1584 _create: function() { 1585 1586 var o = this.options, accept = o.accept; 1587 this.isover = 0; this.isout = 1; 1588 1589 this.accept = $.isFunction(accept) ? accept : function(d) { 1590 return d.is(accept); 1591 }; 1592 1593 //Store the droppable's proportions 1594 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight }; 1595 1596 // Add the reference and positions to the manager 1597 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; 1598 $.ui.ddmanager.droppables[o.scope].push(this); 1599 1600 (o.addClasses && this.element.addClass("ui-droppable")); 1601 1602 }, 1603 1604 destroy: function() { 1605 var drop = $.ui.ddmanager.droppables[this.options.scope]; 1606 for ( var i = 0; i < drop.length; i++ ) 1607 if ( drop[i] == this ) 1608 drop.splice(i, 1); 1609 1610 this.element 1611 .removeClass("ui-droppable ui-droppable-disabled") 1612 .removeData("droppable") 1613 .unbind(".droppable"); 1614 1615 return this; 1616 }, 1617 1618 _setOption: function(key, value) { 1619 1620 if(key == 'accept') { 1621 this.accept = $.isFunction(value) ? value : function(d) { 1622 return d.is(value); 1623 }; 1624 } 1625 $.Widget.prototype._setOption.apply(this, arguments); 1626 }, 1627 1628 _activate: function(event) { 1629 var draggable = $.ui.ddmanager.current; 1630 if(this.options.activeClass) this.element.addClass(this.options.activeClass); 1631 (draggable && this._trigger('activate', event, this.ui(draggable))); 1632 }, 1633 1634 _deactivate: function(event) { 1635 var draggable = $.ui.ddmanager.current; 1636 if(this.options.activeClass) this.element.removeClass(this.options.activeClass); 1637 (draggable && this._trigger('deactivate', event, this.ui(draggable))); 1638 }, 1639 1640 _over: function(event) { 1641 1642 var draggable = $.ui.ddmanager.current; 1643 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element 1644 1645 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 1646 if(this.options.hoverClass) this.element.addClass(this.options.hoverClass); 1647 this._trigger('over', event, this.ui(draggable)); 1648 } 1649 1650 }, 1651 1652 _out: function(event) { 1653 1654 var draggable = $.ui.ddmanager.current; 1655 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element 1656 1657 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 1658 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); 1659 this._trigger('out', event, this.ui(draggable)); 1660 } 1661 1662 }, 1663 1664 _drop: function(event,custom) { 1665 1666 var draggable = custom || $.ui.ddmanager.current; 1667 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element 1668 1669 var childrenIntersection = false;
1670 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() { 1671 var inst = $.data(this, 'droppable'); 1672 if( 1673 inst.options.greedy 1674 && !inst.options.disabled 1675 && inst.options.scope == draggable.options.scope 1676 && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) 1677 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) 1678 ) { childrenIntersection = true; return false; } 1679 }); 1680 if(childrenIntersection) return false; 1681 1682 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 1683 if(this.options.activeClass) this.element.removeClass(this.options.activeClass); 1684 if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); 1685 this._trigger('drop', event, this.ui(draggable)); 1686 return this.element; 1687 } 1688 1689 return false; 1690 1691 }, 1692 1693 ui: function(c) { 1694 return { 1695 draggable: (c.currentItem || c.element), 1696 helper: c.helper, 1697 position: c.position, 1698 offset: c.positionAbs 1699 }; 1700 } 1701 1702}); 1703 1704$.extend($.ui.droppable, { 1705 version: "1.8.24" 1706}); 1707 1708$.ui.intersect = function(draggable, droppable, toleranceMode) { 1709 1710 if (!droppable.offset) return false; 1711 1712 var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, 1713 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height; 1714 var l = droppable.offset.left, r = l + droppable.proportions.width, 1715 t = droppable.offset.top, b = t + droppable.proportions.height; 1716 1717 switch (toleranceMode) { 1718 case 'fit': 1719 return (l <= x1 && x2 <= r 1720 && t <= y1 && y2 <= b); 1721 break; 1722 case 'intersect': 1723 return (l < x1 + (draggable.helperProportions.width / 2) // Right Half 1724 && x2 - (draggable.helperProportions.width / 2) < r // Left Half 1725 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half 1726 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half 1727 break; 1728 case 'pointer': 1729 var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left), 1730 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top), 1731 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width); 1732 return isOver; 1733 break; 1734 case 'touch': 1735 return ( 1736 (y1 >= t && y1 <= b) || // Top edge touching 1737 (y2 >= t && y2 <= b) || // Bottom edge touching 1738 (y1 < t && y2 > b) // Surrounded vertically 1739 ) && ( 1740 (x1 >= l && x1 <= r) || // Left edge touching 1741 (x2 >= l && x2 <= r) || // Right edge touching 1742 (x1 < l && x2 > r) // Surrounded horizontally 1743 ); 1744 break; 1745 default: 1746 return false; 1747 break; 1748 } 1749 1750}; 1751 1752/* 1753 This manager tracks offsets of draggables and droppables 1754*/ 1755$.ui.ddmanager = { 1756 current: null, 1757 droppables: { 'default': [] }, 1758 prepareOffsets: function(t, event) { 1759 1760 var m = $.ui.ddmanager.droppables[t.options.scope] || []; 1761 var type = event ? event.type : null; // workaround for #2317 1762 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf(); 1763 1764 droppablesLoop: for (var i = 0; i < m.length; i++) { 1765 1766 if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted 1767 for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item 1768 m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue 1769 1770 if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables 1771 1772 m[i].offset = m[i].element.offset(); 1773 m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight }; 1774 1775 } 1776 1777 }, 1778 drop: function(draggable, event) { 1779 1780 var dropped = false;
1781 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { 1782 1783 if(!this.options) return; 1784 if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) 1785 dropped = this._drop.call(this, event) || dropped; 1786 1787 if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { 1788 this.isout = 1; this.isover = 0; 1789 this._deactivate.call(this, event); 1790 } 1791 1792 }); 1793 return dropped; 1794 1795 }, 1796 dragStart: function( draggable, event ) { 1797 //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) 1798 draggable.element.parents( ":not(body,html)" ).bind( "scroll.droppable", function() { 1799 if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); 1800 }); 1801 }, 1802 drag: function(draggable, event) { 1803 1804 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. 1805 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event); 1806 1807 //Run through all droppables and check their positions based on specific tolerance options 1808 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { 1809 1810 if(this.options.disabled || this.greedyChild || !this.visible) return; 1811 var intersects = $.ui.intersect(draggable, this, this.options.tolerance); 1812 1813 var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null); 1814 if(!c) return; 1815 1816 var parentInstance; 1817 if (this.options.greedy) { 1818 // find droppable parents with same scope 1819 var scope = this.options.scope; 1820 var parent = this.element.parents(':data(droppable)').filter(function () { 1821 return $.data(this, 'droppable').options.scope === scope; 1822 }); 1823 1824 if (parent.length) { 1825 parentInstance = $.data(parent[0], 'droppable'); 1826 parentInstance.greedyChild = (c == 'isover' ? 1 : 0); 1827 } 1828 } 1829 1830 // we just moved into a greedy child 1831 if (parentInstance && c == 'isover') { 1832 parentInstance['isover'] = 0; 1833 parentInstance['isout'] = 1; 1834 parentInstance._out.call(parentInstance, event); 1835 } 1836 1837 this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0; 1838 this[c == "isover" ? "_over" : "_out"].call(this, event); 1839 1840 // we just moved out of a greedy child 1841 if (parentInstance && c == 'isout') { 1842 parentInstance['isout'] = 0; 1843 parentInstance['isover'] = 1; 1844 parentInstance._over.call(parentInstance, event); 1845 } 1846 }); 1847 1848 }, 1849 dragStop: function( draggable, event ) { 1850 draggable.element.parents( ":not(body,html)" ).unbind( "scroll.droppable" ); 1851 //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) 1852 if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); 1853 } 1854}; 1855 1856})(jQuery); 1857 1858(function( $, undefined ) { 1859 1860$.widget("ui.resizable", $.ui.mouse, { 1861 widgetEventPrefix: "resize", 1862 options: { 1863 alsoResize: false, 1864 animate: false, 1865 animateDuration: "slow", 1866 animateEasing: "swing", 1867 aspectRatio: false, 1868 autoHide: false, 1869 containment: false, 1870 ghost: false, 1871 grid: false, 1872 handles: "e,s,se", 1873 helper: false, 1874 maxHeight: null, 1875 maxWidth: null, 1876 minHeight: 10, 1877 minWidth: 10, 1878 zIndex: 1000 1879 }, 1880 _create: function() { 1881 1882 var self = this, o = this.options; 1883 this.element.addClass("ui-resizable"); 1884 1885 $.extend(this, { 1886 _aspectRatio: !!(o.aspectRatio), 1887 aspectRatio: o.aspectRatio, 1888 originalElement: this.element, 1889 _proportionallyResizeElements: [], 1890 _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null 1891 }); 1892 1893 //Wrap the element if it cannot hold child nodes 1894 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { 1895 1896 //Create a wrapper element and set the wrapper to the new current internal element 1897 this.element.wrap( 1898 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({ 1899 position: this.element.css('position'), 1900 width: this.element.outerWidth(), 1901 height: this.element.outerHeight(), 1902 top: this.element.css('top'), 1903 left: this.element.css('left') 1904 }) 1905 ); 1906 1907 //Overwrite the original this.element 1908 this.element = this.element.parent().data( 1909 "resizable", this.element.data('resizable') 1910 ); 1911 1912 this.elementIsWrapper = true; 1913 1914 //Move margins to the wrapper 1915 this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); 1916 this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); 1917 1918 //Prevent Safari textarea resize 1919 this.originalResizeStyle = this.originalElement.css('resize'); 1920 this.originalElement.css('resize', 'none'); 1921 1922 //Push the actual element to our proportionallyResize internal array 1923 this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' })); 1924 1925 // avoid IE jump (hard set the margin) 1926 this.originalElement.css({ margin: this.originalElement.css('margin') }); 1927 1928 // fix handlers offset 1929 this._proportionallyResize(); 1930 1931 } 1932 1933 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' }); 1934 if(this.handles.constructor == String) { 1935 1936 if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw'; 1937 var n = this.handles.split(","); this.handles = {}; 1938 1939 for(var i = 0; i < n.length; i++) { 1940 1941 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle; 1942 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>'); 1943 1944 // Apply zIndex to all handles - see #7960 1945 axis.css({ zIndex: o.zIndex }); 1946 1947 //TODO : What's going on here? 1948 if ('se' == handle) { 1949 axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se'); 1950 }; 1951 1952 //Insert into internal handles object and append to element 1953 this.handles[handle] = '.ui-resizable-'+handle; 1954 this.element.append(axis); 1955 } 1956 1957 } 1958 1959 this._renderAxis = function(target) { 1960 1961 target = target || this.element; 1962 1963 for(var i in this.handles) { 1964 1965 if(this.handles[i].constructor == String) 1966 this.handles[i] = $(this.handles[i], this.element).show(); 1967 1968 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) 1969 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { 1970 1971 var axis = $(this.handles[i], this.element), padWrapper = 0; 1972 1973 //Checking the correct pad and border 1974 padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); 1975 1976 //The padding type i have to apply... 1977 var padPos = [ 'padding',
1978 /ne|nw|n/.test(i) ? 'Top' : 1979 /se|sw|s/.test(i) ? 'Bottom' : 1980 /^e$/.test(i) ? 'Right' : 'Left' ].join(""); 1981 1982 target.css(padPos, padWrapper); 1983 1984 this._proportionallyResize(); 1985 1986 } 1987 1988 //TODO: What's that good for? There's not anything to be executed left 1989 if(!$(this.handles[i]).length) 1990 continue; 1991 1992 } 1993 }; 1994 1995 //TODO: make renderAxis a prototype function 1996 this._renderAxis(this.element); 1997 1998 this._handles = $('.ui-resizable-handle', this.element) 1999 .disableSelection(); 2000 2001 //Matching axis name 2002 this._handles.mouseover(function() { 2003 if (!self.resizing) { 2004 if (this.className) 2005 var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); 2006 //Axis, default = se 2007 self.axis = axis && axis[1] ? axis[1] : 'se'; 2008 } 2009 }); 2010 2011 //If we want to auto hide the elements 2012 if (o.autoHide) { 2013 this._handles.hide(); 2014 $(this.element) 2015 .addClass("ui-resizable-autohide") 2016 .hover(function() { 2017 if (o.disabled) return; 2018 $(this).removeClass("ui-resizable-autohide"); 2019 self._handles.show(); 2020 }, 2021 function(){ 2022 if (o.disabled) return; 2023 if (!self.resizing) { 2024 $(this).addClass("ui-resizable-autohide"); 2025 self._handles.hide(); 2026 } 2027 }); 2028 } 2029 2030 //Initialize the mouse interaction 2031 this._mouseInit(); 2032 2033 }, 2034 2035 destroy: function() { 2036 2037 this._mouseDestroy(); 2038 2039 var _destroy = function(exp) { 2040 $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") 2041 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove(); 2042 }; 2043 2044 //TODO: Unwrap at same DOM position 2045 if (this.elementIsWrapper) { 2046 _destroy(this.element); 2047 var wrapper = this.element; 2048 wrapper.after( 2049 this.originalElement.css({ 2050 position: wrapper.css('position'), 2051 width: wrapper.outerWidth(), 2052 height: wrapper.outerHeight(), 2053 top: wrapper.css('top'), 2054 left: wrapper.css('left') 2055 }) 2056 ).remove(); 2057 } 2058 2059 this.originalElement.css('resize', this.originalResizeStyle); 2060 _destroy(this.originalElement); 2061 2062 return this; 2063 }, 2064 2065 _mouseCapture: function(event) { 2066 var handle = false; 2067 for (var i in this.handles) { 2068 if ($(this.handles[i])[0] == event.target) { 2069 handle = true; 2070 } 2071 } 2072 2073 return !this.options.disabled && handle; 2074 }, 2075 2076 _mouseStart: function(event) { 2077 2078 var o = this.options, iniPos = this.element.position(), el = this.element; 2079 2080 this.resizing = true; 2081 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() }; 2082 2083 // bugfix for http://dev.jquery.com/ticket/1749 2084 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) { 2085 el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left }); 2086 } 2087 2088 this._renderProxy(); 2089 2090 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top')); 2091 2092 if (o.containment) { 2093 curleft += $(o.containment).scrollLeft() || 0; 2094 curtop += $(o.containment).scrollTop() || 0; 2095 } 2096 2097 //Store needed variables 2098 this.offset = this.helper.offset(); 2099 this.position = { left: curleft, top: curtop }; 2100 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; 2101 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; 2102 this.originalPosition = { left: curleft, top: curtop }; 2103 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; 2104 this.originalMousePosition = { left: event.pageX, top: event.pageY }; 2105 2106 //Aspect Ratio 2107 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); 2108 2109 var cursor = $('.ui-resizable-' + this.axis).css('cursor'); 2110 $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor); 2111 2112 el.addClass("ui-resizable-resizing"); 2113 this._propagate("start", event); 2114 return true; 2115 }, 2116 2117 _mouseDrag: function(event) { 2118 2119 //Increase performance, avoid regex 2120 var el = this.helper, o = this.options, props = {}, 2121 self = this, smp = this.originalMousePosition, a = this.axis; 2122 2123 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0; 2124 var trigger = this._change[a]; 2125 if (!trigger) return false;
2126 2127 // Calculate the attrs that will be change 2128 var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff; 2129 2130 // Put this in the mouseDrag handler since the user can start pressing shift while resizing 2131 this._updateVirtualBoundaries(event.shiftKey); 2132 if (this._aspectRatio || event.shiftKey) 2133 data = this._updateRatio(data, event); 2134 2135 data = this._respectSize(data, event); 2136 2137 // plugins callbacks need to be called first 2138 this._propagate("resize", event); 2139 2140 el.css({ 2141 top: this.position.top + "px", left: this.position.left + "px", 2142 width: this.size.width + "px", height: this.size.height + "px" 2143 }); 2144 2145 if (!this._helper && this._proportionallyResizeElements.length) 2146 this._proportionallyResize(); 2147 2148 this._updateCache(data); 2149 2150 // calling the user callback at the end 2151 this._trigger('resize', event, this.ui()); 2152 2153 return false; 2154 }, 2155 2156 _mouseStop: function(event) { 2157 2158 this.resizing = false; 2159 var o = this.options, self = this; 2160 2161 if(this._helper) { 2162 var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), 2163 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height, 2164 soffsetw = ista ? 0 : self.sizeDiff.width; 2165 2166 var s = { width: (self.helper.width() - soffsetw), height: (self.helper.height() - soffseth) }, 2167 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null, 2168 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null; 2169 2170 if (!o.animate) 2171 this.element.css($.extend(s, { top: top, left: left })); 2172 2173 self.helper.height(self.size.height); 2174 self.helper.width(self.size.width); 2175 2176 if (this._helper && !o.animate) this._proportionallyResize(); 2177 } 2178 2179 $('body').css('cursor', 'auto'); 2180 2181 this.element.removeClass("ui-resizable-resizing"); 2182 2183 this._propagate("stop", event); 2184 2185 if (this._helper) this.helper.remove(); 2186 return false; 2187 2188 }, 2189 2190 _updateVirtualBoundaries: function(forceAspectRatio) { 2191 var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b; 2192 2193 b = { 2194 minWidth: isNumber(o.minWidth) ? o.minWidth : 0, 2195 maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity, 2196 minHeight: isNumber(o.minHeight) ? o.minHeight : 0, 2197 maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity 2198 }; 2199 2200 if(this._aspectRatio || forceAspectRatio) { 2201 // We want to create an enclosing box whose aspect ration is the requested one 2202 // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension 2203 pMinWidth = b.minHeight * this.aspectRatio; 2204 pMinHeight = b.minWidth / this.aspectRatio; 2205 pMaxWidth = b.maxHeight * this.aspectRatio; 2206 pMaxHeight = b.maxWidth / this.aspectRatio; 2207 2208 if(pMinWidth > b.minWidth) b.minWidth = pMinWidth; 2209 if(pMinHeight > b.minHeight) b.minHeight = pMinHeight; 2210 if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth; 2211 if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight; 2212 } 2213 this._vBoundaries = b; 2214 }, 2215 2216 _updateCache: function(data) { 2217 var o = this.options; 2218 this.offset = this.helper.offset(); 2219 if (isNumber(data.left)) this.position.left = data.left; 2220 if (isNumber(data.top)) this.position.top = data.top; 2221 if (isNumber(data.height)) this.size.height = data.height; 2222 if (isNumber(data.width)) this.size.width = data.width; 2223 }, 2224 2225 _updateRatio: function(data, event) { 2226 2227 var o = this.options, cpos = this.position, csize = this.size, a = this.axis; 2228 2229 if (isNumber(data.height)) data.width = (data.height * this.aspectRatio); 2230 else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio); 2231 2232 if (a == 'sw') { 2233 data.left = cpos.left + (csize.width - data.width); 2234 data.top = null; 2235 } 2236 if (a == 'nw') { 2237 data.top = cpos.top + (csize.height - data.height); 2238 data.left = cpos.left + (csize.width - data.width); 2239 } 2240 2241 return data; 2242 }, 2243 2244 _respectSize: function(data, event) { 2245 2246 var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis, 2247 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), 2248 isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height); 2249 2250 if (isminw) data.width = o.minWidth; 2251 if (isminh) data.height = o.minHeight; 2252 if (ismaxw) data.width = o.maxWidth; 2253 if (ismaxh) data.height = o.maxHeight; 2254 2255 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height; 2256 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); 2257 2258 if (isminw && cw) data.left = dw - o.minWidth; 2259 if (ismaxw && cw) data.left = dw - o.maxWidth; 2260 if (isminh && ch) data.top = dh - o.minHeight; 2261 if (ismaxh && ch) data.top = dh - o.maxHeight; 2262 2263 // fixing jump error on top/left - bug #2330 2264 var isNotwh = !data.width && !data.height; 2265 if (isNotwh && !data.left && data.top) data.top = null; 2266 else if (isNotwh && !data.top && data.left) data.left = null; 2267 2268 return data; 2269 }, 2270 2271 _proportionallyResize: function() { 2272 2273 var o = this.options; 2274 if (!this._proportionallyResizeElements.length) return; 2275 var element = this.helper || this.element; 2276 2277 for (var i=0; i < this._proportionallyResizeElements.length; i++) { 2278 2279 var prel = this._proportionallyResizeElements[i]; 2280 2281 if (!this.borderDif) { 2282 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')], 2283 p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')]; 2284 2285 this.borderDif = $.map(b, function(v, i) { 2286 var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0; 2287 return border + padding; 2288 }); 2289 } 2290 2291 if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length))) 2292 continue; 2293 2294 prel.css({ 2295 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, 2296 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 2297 }); 2298 2299 }; 2300 2301 }, 2302 2303 _renderProxy: function() { 2304 2305 var el = this.element, o = this.options; 2306 this.elementOffset = el.offset(); 2307 2308 if(this._helper) { 2309 2310 this.helper = this.helper || $('<div style="overflow:hidden;"></div>'); 2311 2312 // fix ie6 offset TODO: This seems broken 2313 var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0), 2314 pxyoffset = ( ie6 ? 2 : -1 ); 2315 2316 this.helper.addClass(this._helper).css({ 2317 width: this.element.outerWidth() + pxyoffset, 2318 height: this.element.outerHeight() + pxyoffset, 2319 position: 'absolute', 2320 left: this.elementOffset.left - ie6offset +'px', 2321 top: this.elementOffset.top - ie6offset +'px', 2322 zIndex: ++o.zIndex //TODO: Don't modify option 2323 }); 2324 2325 this.helper 2326 .appendTo("body") 2327 .disableSelection(); 2328 2329 } else { 2330 this.helper = this.element; 2331 } 2332 2333 }, 2334 2335 _change: { 2336 e: function(event, dx, dy) { 2337 return { width: this.originalSize.width + dx }; 2338 }, 2339 w: function(event, dx, dy) { 2340 var o = this.options, cs = this.originalSize, sp = this.originalPosition; 2341 return { left: sp.left + dx, width: cs.width - dx }; 2342 }, 2343 n: function(event, dx, dy) { 2344 var o = this.options, cs = this.originalSize, sp = this.originalPosition; 2345 return { top: sp.top + dy, height: cs.height - dy }; 2346 }, 2347 s: function(event, dx, dy) { 2348 return { height: this.originalSize.height + dy }; 2349 }, 2350 se: function(event, dx, dy) { 2351 return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); 2352 }, 2353 sw: function(event, dx, dy) { 2354 return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); 2355 }, 2356 ne: function(event, dx, dy) { 2357 return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); 2358 }, 2359 nw: function(event, dx, dy) { 2360 return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); 2361 } 2362 }, 2363 2364 _propagate: function(n, event) { 2365 $.ui.plugin.call(this, n, [event, this.ui()]); 2366 (n != "resize" && this._trigger(n, event, this.ui())); 2367 }, 2368 2369 plugins: {}, 2370 2371 ui: function() { 2372 return { 2373 originalElement: this.originalElement, 2374 element: this.element, 2375 helper: this.helper, 2376 position: this.position, 2377 size: this.size, 2378 originalSize: this.originalSize, 2379 originalPosition: this.originalPosition 2380 }; 2381 } 2382 2383}); 2384 2385$.extend($.ui.resizable, { 2386 version: "1.8.24" 2387}); 2388 2389/* 2390 * Resizable Extensions 2391 */ 2392 2393$.ui.plugin.add("resizable", "alsoResize", { 2394 2395 start: function (event, ui) { 2396 var self = $(this).data("resizable"), o = self.options; 2397 2398 var _store = function (exp) { 2399 $(exp).each(function() { 2400 var el = $(this); 2401 el.data("resizable-alsoresize", { 2402 width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), 2403 left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10) 2404 }); 2405 }); 2406 }; 2407 2408 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) { 2409 if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); } 2410 else { $.each(o.alsoResize, function (exp) { _store(exp); }); } 2411 }else{ 2412 _store(o.alsoResize); 2413 } 2414 }, 2415 2416 resize: function (event, ui) { 2417 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition; 2418 2419 var delta = { 2420 height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0, 2421 top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0 2422 }, 2423 2424 _alsoResize = function (exp, c) { 2425 $(exp).each(function() { 2426 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 2427 css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left']; 2428
2429 $.each(css, function (i, prop) { 2430 var sum = (start[prop]||0) + (delta[prop]||0); 2431 if (sum && sum >= 0) 2432 style[prop] = sum || null; 2433 }); 2434 2435 el.css(style); 2436 }); 2437 }; 2438 2439 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) { 2440 $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); }); 2441 }else{ 2442 _alsoResize(o.alsoResize); 2443 } 2444 }, 2445 2446 stop: function (event, ui) { 2447 $(this).removeData("resizable-alsoresize"); 2448 } 2449}); 2450 2451$.ui.plugin.add("resizable", "animate", { 2452 2453 stop: function(event, ui) { 2454 var self = $(this).data("resizable"), o = self.options; 2455 2456 var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), 2457 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height, 2458 soffsetw = ista ? 0 : self.sizeDiff.width; 2459 2460 var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) }, 2461 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null, 2462 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null; 2463 2464 self.element.animate( 2465 $.extend(style, top && left ? { top: top, left: left } : {}), { 2466 duration: o.animateDuration, 2467 easing: o.animateEasing, 2468 step: function() { 2469 2470 var data = { 2471 width: parseInt(self.element.css('width'), 10), 2472 height: parseInt(self.element.css('height'), 10), 2473 top: parseInt(self.element.css('top'), 10), 2474 left: parseInt(self.element.css('left'), 10) 2475 }; 2476 2477 if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height }); 2478 2479 // propagating resize, and updating values for each animation step 2480 self._updateCache(data); 2481 self._propagate("resize", event); 2482 2483 } 2484 } 2485 ); 2486 } 2487 2488}); 2489 2490$.ui.plugin.add("resizable", "containment", { 2491 2492 start: function(event, ui) { 2493 var self = $(this).data("resizable"), o = self.options, el = self.element; 2494 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; 2495 if (!ce) return; 2496 2497 self.containerElement = $(ce); 2498 2499 if (/document/.test(oc) || oc == document) { 2500 self.containerOffset = { left: 0, top: 0 }; 2501 self.containerPosition = { left: 0, top: 0 }; 2502 2503 self.parentData = { 2504 element: $(document), left: 0, top: 0, 2505 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight 2506 }; 2507 } 2508 2509 // i'm a node, so compute top, left, right, bottom 2510 else { 2511 var element = $(ce), p = []; 2512 $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); }); 2513 2514 self.containerOffset = element.offset(); 2515 self.containerPosition = element.position(); 2516 self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; 2517 2518 var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width, 2519 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); 2520 2521 self.parentData = { 2522 element: ce, left: co.left, top: co.top, width: width, height: height 2523 }; 2524 } 2525 }, 2526 2527 resize: function(event, ui) { 2528 var self = $(this).data("resizable"), o = self.options, 2529 ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position, 2530 pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement; 2531 2532 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co; 2533 2534 if (cp.left < (self._helper ? co.left : 0)) { 2535 self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left)); 2536 if (pRatio) self.size.height = self.size.width / self.aspectRatio; 2537 self.position.left = o.helper ? co.left : 0; 2538 } 2539 2540 if (cp.top < (self._helper ? co.top : 0)) { 2541 self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top); 2542 if (pRatio) self.size.width = self.size.height * self.aspectRatio; 2543 self.position.top = self._helper ? co.top : 0; 2544 } 2545 2546 self.offset.left = self.parentData.left+self.position.left; 2547 self.offset.top = self.parentData.top+self.position.top; 2548 2549 var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ), 2550 hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height ); 2551 2552 var isParent = self.containerElement.get(0) == self.element.parent().get(0), 2553 isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position')); 2554 2555 if(isParent && isOffsetRelative) woset -= self.parentData.left; 2556 2557 if (woset + self.size.width >= self.parentData.width) { 2558 self.size.width = self.parentData.width - woset; 2559 if (pRatio) self.size.height = self.size.width / self.aspectRatio; 2560 } 2561 2562 if (hoset + self.size.height >= self.parentData.height) { 2563 self.size.height = self.parentData.height - hoset; 2564 if (pRatio) self.size.width = self.size.height * self.aspectRatio; 2565 } 2566 }, 2567 2568 stop: function(event, ui){ 2569 var self = $(this).data("resizable"), o = self.options, cp = self.position, 2570 co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement; 2571 2572 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height; 2573
2574 if (self._helper && !o.animate && (/relative/).test(ce.css('position'))) 2575 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); 2576 2577 if (self._helper && !o.animate && (/static/).test(ce.css('position'))) 2578 $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); 2579 2580 } 2581}); 2582 2583$.ui.plugin.add("resizable", "ghost", { 2584 2585 start: function(event, ui) { 2586 2587 var self = $(this).data("resizable"), o = self.options, cs = self.size; 2588 2589 self.ghost = self.originalElement.clone(); 2590 self.ghost 2591 .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) 2592 .addClass('ui-resizable-ghost') 2593 .addClass(typeof o.ghost == 'string' ? o.ghost : ''); 2594 2595 self.ghost.appendTo(self.helper); 2596 2597 }, 2598 2599 resize: function(event, ui){ 2600 var self = $(this).data("resizable"), o = self.options; 2601 if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width }); 2602 }, 2603 2604 stop: function(event, ui){ 2605 var self = $(this).data("resizable"), o = self.options; 2606 if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0)); 2607 } 2608 2609}); 2610 2611$.ui.plugin.add("resizable", "grid", { 2612 2613 resize: function(event, ui) { 2614 var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey; 2615 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid; 2616 var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1); 2617 2618 if (/^(se|s|e)$/.test(a)) { 2619 self.size.width = os.width + ox; 2620 self.size.height = os.height + oy; 2621 } 2622 else if (/^(ne)$/.test(a)) { 2623 self.size.width = os.width + ox; 2624 self.size.height = os.height + oy; 2625 self.position.top = op.top - oy; 2626 } 2627 else if (/^(sw)$/.test(a)) { 2628 self.size.width = os.width + ox; 2629 self.size.height = os.height + oy; 2630 self.position.left = op.left - ox; 2631 } 2632 else { 2633 self.size.width = os.width + ox; 2634 self.size.height = os.height + oy; 2635 self.position.top = op.top - oy; 2636 self.position.left = op.left - ox; 2637 } 2638 } 2639 2640}); 2641 2642var num = function(v) { 2643 return parseInt(v, 10) || 0; 2644}; 2645 2646var isNumber = function(value) { 2647 return !isNaN(parseInt(value, 10)); 2648}; 2649 2650})(jQuery); 2651 2652(function( $, undefined ) { 2653 2654$.widget("ui.selectable", $.ui.mouse, { 2655 options: { 2656 appendTo: 'body', 2657 autoRefresh: true, 2658 distance: 0, 2659 filter: '*', 2660 tolerance: 'touch' 2661 }, 2662 _create: function() { 2663 var self = this; 2664 2665 this.element.addClass("ui-selectable"); 2666 2667 this.dragged = false; 2668 2669 // cache selectee children based on filter 2670 var selectees; 2671 this.refresh = function() { 2672 selectees = $(self.options.filter, self.element[0]); 2673 selectees.addClass("ui-selectee"); 2674 selectees.each(function() { 2675 var $this = $(this); 2676 var pos = $this.offset(); 2677 $.data(this, "selectable-item", { 2678 element: this, 2679 $element: $this, 2680 left: pos.left, 2681 top: pos.top, 2682 right: pos.left + $this.outerWidth(), 2683 bottom: pos.top + $this.outerHeight(), 2684 startselected: false, 2685 selected: $this.hasClass('ui-selected'), 2686 selecting: $this.hasClass('ui-selecting'), 2687 unselecting: $this.hasClass('ui-unselecting') 2688 }); 2689 }); 2690 }; 2691 this.refresh(); 2692 2693 this.selectees = selectees.addClass("ui-selectee"); 2694 2695 this._mouseInit(); 2696 2697 this.helper = $("<div class='ui-selectable-helper'></div>"); 2698 }, 2699 2700 destroy: function() { 2701 this.selectees 2702 .removeClass("ui-selectee") 2703 .removeData("selectable-item"); 2704 this.element 2705 .removeClass("ui-selectable ui-selectable-disabled") 2706 .removeData("selectable") 2707 .unbind(".selectable"); 2708 this._mouseDestroy(); 2709 2710 return this; 2711 }, 2712 2713 _mouseStart: function(event) { 2714 var self = this; 2715 2716 this.opos = [event.pageX, event.pageY]; 2717 2718 if (this.options.disabled) 2719 return; 2720 2721 var options = this.options; 2722 2723 this.selectees = $(options.filter, this.element[0]); 2724 2725 this._trigger("start", event); 2726 2727 $(options.appendTo).append(this.helper); 2728 // position helper (lasso) 2729 this.helper.css({ 2730 "left": event.clientX, 2731 "top": event.clientY, 2732 "width": 0, 2733 "height": 0 2734 }); 2735 2736 if (options.autoRefresh) { 2737 this.refresh(); 2738 } 2739 2740 this.selectees.filter('.ui-selected').each(function() { 2741 var selectee = $.data(this, "selectable-item"); 2742 selectee.startselected = true; 2743 if (!event.metaKey && !event.ctrlKey) { 2744 selectee.$element.removeClass('ui-selected'); 2745 selectee.selected = false;
vendor: 4,195 bytes, lines 2746-2884
2746 selectee.$element.addClass('ui-unselecting'); 2747 selectee.unselecting = true; 2748 // selectable UNSELECTING callback 2749 self._trigger("unselecting", event, { 2750 unselecting: selectee.element 2751 }); 2752 } 2753 }); 2754 2755 $(event.target).parents().andSelf().each(function() { 2756 var selectee = $.data(this, "selectable-item"); 2757 if (selectee) { 2758 var doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass('ui-selected'); 2759 selectee.$element 2760 .removeClass(doSelect ? "ui-unselecting" : "ui-selected") 2761 .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); 2762 selectee.unselecting = !doSelect; 2763 selectee.selecting = doSelect; 2764 selectee.selected = doSelect; 2765 // selectable (UN)SELECTING callback 2766 if (doSelect) { 2767 self._trigger("selecting", event, { 2768 selecting: selectee.element 2769 }); 2770 } else { 2771 self._trigger("unselecting", event, { 2772 unselecting: selectee.element 2773 }); 2774 } 2775 return false; 2776 } 2777 }); 2778 2779 }, 2780 2781 _mouseDrag: function(event) { 2782 var self = this; 2783 this.dragged = true; 2784 2785 if (this.options.disabled) 2786 return; 2787 2788 var options = this.options; 2789 2790 var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY; 2791 if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; } 2792 if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; } 2793 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); 2794 2795 this.selectees.each(function() { 2796 var selectee = $.data(this, "selectable-item"); 2797 //prevent helper from being selected if appendTo: selectable 2798 if (!selectee || selectee.element == self.element[0]) 2799 return; 2800 var hit = false; 2801 if (options.tolerance == 'touch') { 2802 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); 2803 } else if (options.tolerance == 'fit') { 2804 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); 2805 } 2806 2807 if (hit) { 2808 // SELECT 2809 if (selectee.selected) { 2810 selectee.$element.removeClass('ui-selected'); 2811 selectee.selected = false; 2812 } 2813 if (selectee.unselecting) { 2814 selectee.$element.removeClass('ui-unselecting'); 2815 selectee.unselecting = false; 2816 } 2817 if (!selectee.selecting) { 2818 selectee.$element.addClass('ui-selecting'); 2819 selectee.selecting = true; 2820 // selectable SELECTING callback 2821 self._trigger("selecting", event, { 2822 selecting: selectee.element 2823 }); 2824 } 2825 } else { 2826 // UNSELECT 2827 if (selectee.selecting) { 2828 if ((event.metaKey || event.ctrlKey) && selectee.startselected) { 2829 selectee.$element.removeClass('ui-selecting'); 2830 selectee.selecting = false; 2831 selectee.$element.addClass('ui-selected'); 2832 selectee.selected = true; 2833 } else { 2834 selectee.$element.removeClass('ui-selecting'); 2835 selectee.selecting = false; 2836 if (selectee.startselected) { 2837 selectee.$element.addClass('ui-unselecting'); 2838 selectee.unselecting = true; 2839 } 2840 // selectable UNSELECTING callback 2841 self._trigger("unselecting", event, { 2842 unselecting: selectee.element 2843 }); 2844 } 2845 } 2846 if (selectee.selected) { 2847 if (!event.metaKey && !event.ctrlKey && !selectee.startselected) { 2848 selectee.$element.removeClass('ui-selected'); 2849 selectee.selected = false; 2850 2851 selectee.$element.addClass('ui-unselecting'); 2852 selectee.unselecting = true; 2853 // selectable UNSELECTING callback 2854 self._trigger("unselecting", event, { 2855 unselecting: selectee.element 2856 }); 2857 } 2858 } 2859 } 2860 }); 2861 2862 return false; 2863 }, 2864 2865 _mouseStop: function(event) { 2866 var self = this; 2867 2868 this.dragged = false; 2869 2870 var options = this.options; 2871 2872 $('.ui-unselecting', this.element[0]).each(function() { 2873 var selectee = $.data(this, "selectable-item"); 2874 selectee.$element.removeClass('ui-unselecting'); 2875 selectee.unselecting = false; 2876 selectee.startselected = false; 2877 self._trigger("unselected", event, { 2878 unselected: selectee.element 2879 }); 2880 }); 2881 $('.ui-selecting', this.element[0]).each(function() { 2882 var selectee = $.data(this, "selectable-item"); 2883 selectee.$element.removeClass('ui-selecting').addClass('ui-selected'); 2884 selectee.selecting = false;
2885 selectee.selected = true; 2886 selectee.startselected = true; 2887 self._trigger("selected", event, { 2888 selected: selectee.element 2889 }); 2890 }); 2891 this._trigger("stop", event); 2892 2893 this.helper.remove(); 2894 2895 return false; 2896 } 2897 2898}); 2899 2900$.extend($.ui.selectable, { 2901 version: "1.8.24" 2902}); 2903 2904})(jQuery); 2905 2906(function( $, undefined ) { 2907 2908$.widget("ui.sortable", $.ui.mouse, { 2909 widgetEventPrefix: "sort", 2910 ready: false, 2911 options: { 2912 appendTo: "parent", 2913 axis: false, 2914 connectWith: false, 2915 containment: false, 2916 cursor: 'auto', 2917 cursorAt: false, 2918 dropOnEmpty: true, 2919 forcePlaceholderSize: false, 2920 forceHelperSize: false, 2921 grid: false, 2922 handle: false, 2923 helper: "original", 2924 items: '> *', 2925 opacity: false, 2926 placeholder: false, 2927 revert: false, 2928 scroll: true, 2929 scrollSensitivity: 20, 2930 scrollSpeed: 20, 2931 scope: "default", 2932 tolerance: "intersect", 2933 zIndex: 1000 2934 }, 2935 _create: function() { 2936 2937 var o = this.options; 2938 this.containerCache = {}; 2939 this.element.addClass("ui-sortable"); 2940 2941 //Get the items 2942 this.refresh(); 2943 2944 //Let's determine if the items are being displayed horizontally 2945 this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false; 2946 2947 //Let's determine the parent's offset 2948 this.offset = this.element.offset(); 2949 2950 //Initialize mouse events for interaction 2951 this._mouseInit(); 2952 2953 //We're ready to go 2954 this.ready = true 2955 2956 }, 2957 2958 destroy: function() { 2959 $.Widget.prototype.destroy.call( this ); 2960 this.element 2961 .removeClass("ui-sortable ui-sortable-disabled"); 2962 this._mouseDestroy(); 2963 2964 for ( var i = this.items.length - 1; i >= 0; i-- ) 2965 this.items[i].item.removeData(this.widgetName + "-item"); 2966 2967 return this; 2968 }, 2969 2970 _setOption: function(key, value){ 2971 if ( key === "disabled" ) { 2972 this.options[ key ] = value; 2973 2974 this.widget() 2975 [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" ); 2976 } else { 2977 // Don't call widget base _setOption for disable as it adds ui-state-disabled class 2978 $.Widget.prototype._setOption.apply(this, arguments); 2979 } 2980 }, 2981 2982 _mouseCapture: function(event, overrideHandle) { 2983 var that = this; 2984 2985 if (this.reverting) { 2986 return false; 2987 } 2988 2989 if(this.options.disabled || this.options.type == 'static') return false; 2990 2991 //We have to refresh the items data once first 2992 this._refreshItems(event); 2993 2994 //Find out if the clicked node (or one of its parents) is a actual item in this.items 2995 var currentItem = null, self = this, nodes = $(event.target).parents().each(function() { 2996 if($.data(this, that.widgetName + '-item') == self) { 2997 currentItem = $(this); 2998 return false; 2999 } 3000 }); 3001 if($.data(event.target, that.widgetName + '-item') == self) currentItem = $(event.target); 3002 3003 if(!currentItem) return false; 3004 if(this.options.handle && !overrideHandle) { 3005 var validHandle = false; 3006 3007 $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; }); 3008 if(!validHandle) return false; 3009 } 3010 3011 this.currentItem = currentItem; 3012 this._removeCurrentsFromItems(); 3013 return true; 3014 3015 }, 3016 3017 _mouseStart: function(event, overrideHandle, noActivation) { 3018 3019 var o = this.options, self = this; 3020 this.currentContainer = this; 3021 3022 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture 3023 this.refreshPositions(); 3024 3025 //Create and append the visible helper 3026 this.helper = this._createHelper(event); 3027 3028 //Cache the helper size 3029 this._cacheHelperProportions(); 3030 3031 /* 3032 * - Position generation - 3033 * This block generates everything position related - it's the core of draggables. 3034 */ 3035 3036 //Cache the margins of the original element 3037 this._cacheMargins(); 3038 3039 //Get the next scrolling parent 3040 this.scrollParent = this.helper.scrollParent(); 3041 3042 //The element's absolute position on the page minus margins 3043 this.offset = this.currentItem.offset(); 3044 this.offset = { 3045 top: this.offset.top - this.margins.top, 3046 left: this.offset.left - this.margins.left 3047 }; 3048 3049 $.extend(this.offset, { 3050 click: { //Where the click happened, relative to the element 3051 left: event.pageX - this.offset.left, 3052 top: event.pageY - this.offset.top 3053 }, 3054 parent: this._getParentOffset(), 3055 relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper 3056 }); 3057 3058 // Only after we got the offset, we can change the helper's position to absolute 3059 // TODO: Still need to figure out a way to make relative sorting possible 3060 this.helper.css("position", "absolute"); 3061 this.cssPosition = this.helper.css("position"); 3062 3063 //Generate the original position 3064 this.originalPosition = this._generatePosition(event); 3065 this.originalPageX = event.pageX; 3066 this.originalPageY = event.pageY; 3067 3068 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied 3069 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); 3070 3071 //Cache the former DOM position 3072 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; 3073 3074 //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 3075 if(this.helper[0] != this.currentItem[0]) { 3076 this.currentItem.hide(); 3077 } 3078 3079 //Create the placeholder 3080 this._createPlaceholder(); 3081 3082 //Set a containment if given in the options 3083 if(o.containment) 3084 this._setContainment(); 3085 3086 if(o.cursor) { // cursor option 3087 if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor"); 3088 $('body').css("cursor", o.cursor); 3089 } 3090 3091 if(o.opacity) { // opacity option 3092 if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity"); 3093 this.helper.css("opacity", o.opacity); 3094 } 3095 3096 if(o.zIndex) { // zIndex option 3097 if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex"); 3098 this.helper.css("zIndex", o.zIndex); 3099 } 3100 3101 //Prepare scrolling 3102 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') 3103 this.overflowOffset = this.scrollParent.offset(); 3104 3105 //Call callbacks 3106 this._trigger("start", event, this._uiHash()); 3107 3108 //Recache the helper size 3109 if(!this._preserveHelperProportions) 3110 this._cacheHelperProportions(); 3111 3112 3113 //Post 'activate' events to possible containers 3114 if(!noActivation) { 3115 for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); } 3116 } 3117 3118 //Prepare possible droppables 3119 if($.ui.ddmanager) 3120 $.ui.ddmanager.current = this; 3121 3122 if ($.ui.ddmanager && !o.dropBehaviour) 3123 $.ui.ddmanager.prepareOffsets(this, event); 3124 3125 this.dragging = true; 3126 3127 this.helper.addClass("ui-sortable-helper"); 3128 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position 3129 return true; 3130 3131 }, 3132 3133 _mouseDrag: function(event) { 3134 3135 //Compute the helpers position 3136 this.position = this._generatePosition(event); 3137 this.positionAbs = this._convertPositionTo("absolute"); 3138 3139 if (!this.lastPositionAbs) { 3140 this.lastPositionAbs = this.positionAbs; 3141 } 3142 3143 //Do scrolling 3144 if(this.options.scroll) { 3145 var o = this.options, scrolled = false;
3146 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') { 3147 3148 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) 3149 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; 3150 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) 3151 this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; 3152 3153 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) 3154 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; 3155 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) 3156 this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; 3157 3158 } else { 3159 3160 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) 3161 scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); 3162 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) 3163 scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); 3164 3165 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) 3166 scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); 3167 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) 3168 scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); 3169 3170 } 3171 3172 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) 3173 $.ui.ddmanager.prepareOffsets(this, event); 3174 } 3175 3176 //Regenerate the absolute position used for position checks 3177 this.positionAbs = this._convertPositionTo("absolute"); 3178 3179 //Set the helper position 3180 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; 3181 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; 3182 3183 //Rearrange 3184 for (var i = this.items.length - 1; i >= 0; i--) { 3185 3186 //Cache variables and intersection, continue if no intersection 3187 var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item); 3188 if (!intersection) continue; 3189 3190 // Only put the placeholder inside the current Container, skip all 3191 // items form other containers. This works because when moving 3192 // an item from one container to another the 3193 // currentContainer is switched before the placeholder is moved. 3194 // 3195 // Without this moving items in "sub-sortables" can cause the placeholder to jitter 3196 // beetween the outer and inner container. 3197 if (item.instance !== this.currentContainer) continue; 3198 3199 if (itemElement != this.currentItem[0] //cannot intersect with itself 3200 && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before 3201 && !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked 3202 && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true) 3203 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container 3204 ) { 3205 3206 this.direction = intersection == 1 ? "down" : "up"; 3207 3208 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) { 3209 this._rearrange(event, item); 3210 } else { 3211 break; 3212 } 3213 3214 this._trigger("change", event, this._uiHash()); 3215 break; 3216 } 3217 } 3218 3219 //Post events to containers 3220 this._contactContainers(event); 3221 3222 //Interconnect with droppables 3223 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); 3224 3225 //Call callbacks 3226 this._trigger('sort', event, this._uiHash()); 3227 3228 this.lastPositionAbs = this.positionAbs; 3229 return false; 3230 3231 }, 3232 3233 _mouseStop: function(event, noPropagation) { 3234 3235 if(!event) return; 3236 3237 //If we are using droppables, inform the manager about the drop 3238 if ($.ui.ddmanager && !this.options.dropBehaviour) 3239 $.ui.ddmanager.drop(this, event); 3240 3241 if(this.options.revert) { 3242 var self = this; 3243 var cur = self.placeholder.offset(); 3244 3245 self.reverting = true; 3246 3247 $(this.helper).animate({ 3248 left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft), 3249 top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop) 3250 }, parseInt(this.options.revert, 10) || 500, function() { 3251 self._clear(event); 3252 }); 3253 } else { 3254 this._clear(event, noPropagation); 3255 } 3256 3257 return false;
3258 3259 }, 3260 3261 cancel: function() { 3262 3263 var self = this; 3264 3265 if(this.dragging) { 3266 3267 this._mouseUp({ target: null }); 3268 3269 if(this.options.helper == "original") 3270 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); 3271 else 3272 this.currentItem.show(); 3273 3274 //Post deactivating events to containers 3275 for (var i = this.containers.length - 1; i >= 0; i--){ 3276 this.containers[i]._trigger("deactivate", null, self._uiHash(this)); 3277 if(this.containers[i].containerCache.over) { 3278 this.containers[i]._trigger("out", null, self._uiHash(this)); 3279 this.containers[i].containerCache.over = 0; 3280 } 3281 } 3282 3283 } 3284 3285 if (this.placeholder) { 3286 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! 3287 if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 3288 if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove(); 3289 3290 $.extend(this, { 3291 helper: null, 3292 dragging: false, 3293 reverting: false, 3294 _noFinalSort: null 3295 }); 3296 3297 if(this.domPosition.prev) { 3298 $(this.domPosition.prev).after(this.currentItem); 3299 } else { 3300 $(this.domPosition.parent).prepend(this.currentItem); 3301 } 3302 } 3303 3304 return this; 3305 3306 }, 3307 3308 serialize: function(o) { 3309 3310 var items = this._getItemsAsjQuery(o && o.connected); 3311 var str = []; o = o || {}; 3312 3313 $(items).each(function() { 3314 var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/)); 3315 if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2])); 3316 }); 3317 3318 if(!str.length && o.key) { 3319 str.push(o.key + '='); 3320 } 3321 3322 return str.join('&'); 3323 3324 }, 3325 3326 toArray: function(o) { 3327 3328 var items = this._getItemsAsjQuery(o && o.connected); 3329 var ret = []; o = o || {}; 3330 3331 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); }); 3332 return ret; 3333 3334 }, 3335 3336 /* Be careful with the following core functions */ 3337 _intersectsWith: function(item) { 3338 3339 var x1 = this.positionAbs.left, 3340 x2 = x1 + this.helperProportions.width, 3341 y1 = this.positionAbs.top, 3342 y2 = y1 + this.helperProportions.height; 3343 3344 var l = item.left, 3345 r = l + item.width, 3346 t = item.top, 3347 b = t + item.height; 3348 3349 var dyClick = this.offset.click.top, 3350 dxClick = this.offset.click.left; 3351 3352 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r; 3353 3354 if( this.options.tolerance == "pointer" 3355 || this.options.forcePointerForContainers 3356 || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height']) 3357 ) { 3358 return isOverElement; 3359 } else { 3360 3361 return (l < x1 + (this.helperProportions.width / 2) // Right Half 3362 && x2 - (this.helperProportions.width / 2) < r // Left Half 3363 && t < y1 + (this.helperProportions.height / 2) // Bottom Half 3364 && y2 - (this.helperProportions.height / 2) < b ); // Top Half 3365 3366 } 3367 }, 3368 3369 _intersectsWithPointer: function(item) { 3370 3371 var isOverElementHeight = (this.options.axis === 'x') || $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), 3372 isOverElementWidth = (this.options.axis === 'y') || $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), 3373 isOverElement = isOverElementHeight && isOverElementWidth, 3374 verticalDirection = this._getDragVerticalDirection(), 3375 horizontalDirection = this._getDragHorizontalDirection(); 3376 3377 if (!isOverElement) 3378 return false; 3379 3380 return this.floating ? 3381 ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 ) 3382 : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) ); 3383 3384 }, 3385 3386 _intersectsWithSides: function(item) { 3387 3388 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), 3389 isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), 3390 verticalDirection = this._getDragVerticalDirection(), 3391 horizontalDirection = this._getDragHorizontalDirection(); 3392 3393 if (this.floating && horizontalDirection) { 3394 return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf)); 3395 } else { 3396 return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf)); 3397 } 3398 3399 }, 3400 3401 _getDragVerticalDirection: function() { 3402 var delta = this.positionAbs.top - this.lastPositionAbs.top; 3403 return delta != 0 && (delta > 0 ? "down" : "up"); 3404 }, 3405 3406 _getDragHorizontalDirection: function() { 3407 var delta = this.positionAbs.left - this.lastPositionAbs.left; 3408 return delta != 0 && (delta > 0 ? "right" : "left"); 3409 }, 3410 3411 refresh: function(event) { 3412 this._refreshItems(event); 3413 this.refreshPositions(); 3414 return this; 3415 }, 3416 3417 _connectWith: function() { 3418 var options = this.options; 3419 return options.connectWith.constructor == String
3420 ? [options.connectWith] 3421 : options.connectWith; 3422 }, 3423 3424 _getItemsAsjQuery: function(connected) { 3425 3426 var self = this; 3427 var items = []; 3428 var queries = []; 3429 var connectWith = this._connectWith(); 3430 3431 if(connectWith && connected) { 3432 for (var i = connectWith.length - 1; i >= 0; i--){ 3433 var cur = $(connectWith[i]); 3434 for (var j = cur.length - 1; j >= 0; j--){ 3435 var inst = $.data(cur[j], this.widgetName); 3436 if(inst && inst != this && !inst.options.disabled) { 3437 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]); 3438 } 3439 }; 3440 }; 3441 } 3442 3443 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]); 3444 3445 for (var i = queries.length - 1; i >= 0; i--){ 3446 queries[i][0].each(function() { 3447 items.push(this); 3448 }); 3449 }; 3450 3451 return $(items); 3452 3453 }, 3454 3455 _removeCurrentsFromItems: function() { 3456 3457 var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); 3458 3459 for (var i=0; i < this.items.length; i++) { 3460 3461 for (var j=0; j < list.length; j++) { 3462 if(list[j] == this.items[i].item[0]) 3463 this.items.splice(i,1); 3464 }; 3465 3466 }; 3467 3468 }, 3469 3470 _refreshItems: function(event) { 3471 3472 this.items = []; 3473 this.containers = [this]; 3474 var items = this.items; 3475 var self = this; 3476 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]]; 3477 var connectWith = this._connectWith(); 3478 3479 if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down 3480 for (var i = connectWith.length - 1; i >= 0; i--){ 3481 var cur = $(connectWith[i]); 3482 for (var j = cur.length - 1; j >= 0; j--){ 3483 var inst = $.data(cur[j], this.widgetName); 3484 if(inst && inst != this && !inst.options.disabled) { 3485 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); 3486 this.containers.push(inst); 3487 } 3488 }; 3489 }; 3490 } 3491 3492 for (var i = queries.length - 1; i >= 0; i--) { 3493 var targetData = queries[i][1]; 3494 var _queries = queries[i][0]; 3495 3496 for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) { 3497 var item = $(_queries[j]); 3498 3499 item.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager) 3500 3501 items.push({ 3502 item: item, 3503 instance: targetData, 3504 width: 0, height: 0, 3505 left: 0, top: 0 3506 }); 3507 }; 3508 }; 3509 3510 }, 3511 3512 refreshPositions: function(fast) { 3513 3514 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change 3515 if(this.offsetParent && this.helper) { 3516 this.offset.parent = this._getParentOffset(); 3517 } 3518 3519 for (var i = this.items.length - 1; i >= 0; i--){ 3520 var item = this.items[i]; 3521 3522 //We ignore calculating positions of all connected containers when we're not over them 3523 if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0]) 3524 continue; 3525 3526 var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; 3527 3528 if (!fast) { 3529 item.width = t.outerWidth(); 3530 item.height = t.outerHeight(); 3531 } 3532 3533 var p = t.offset(); 3534 item.left = p.left; 3535 item.top = p.top; 3536 }; 3537 3538 if(this.options.custom && this.options.custom.refreshContainers
3538) { 3539 this.options.custom.refreshContainers.call(this); 3540 } else { 3541 for (var i = this.containers.length - 1; i >= 0; i--){ 3542 var p = this.containers[i].element.offset(); 3543 this.containers[i].containerCache.left = p.left; 3544 this.containers[i].containerCache.top = p.top; 3545 this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); 3546 this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); 3547 }; 3548 } 3549 3550 return this; 3551 }, 3552 3553 _createPlaceholder: function(that) { 3554 3555 var self = that || this, o = self.options; 3556 3557 if(!o.placeholder || o.placeholder.constructor == String) { 3558 var className = o.placeholder; 3559 o.placeholder = { 3560 element: function() { 3561 3562 var el = $(document.createElement(self.currentItem[0].nodeName)) 3563 .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder") 3564 .removeClass("ui-sortable-helper")[0]; 3565 3566 if(!className) 3567 el.style.visibility = "hidden"; 3568 3569 return el; 3570 }, 3571 update: function(container, p) { 3572 3573 // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that 3574 // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified 3575 if(className && !o.forcePlaceholderSize) return; 3576 3577 //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
3578 if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); }; 3579 if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); }; 3580 } 3581 }; 3582 } 3583 3584 //Create the placeholder 3585 self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem)); 3586 3587 //Append it after the actual current item 3588 self.currentItem.after(self.placeholder); 3589 3590 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) 3591 o.placeholder.update(self, self.placeholder); 3592 3593 }, 3594 3595 _contactContainers: function(event) { 3596 3597 // get innermost container that intersects with item 3598 var innermostContainer = null, innermostIndex = null; 3599 3600 3601 for (var i = this.containers.length - 1; i >= 0; i--){ 3602 3603 // never consider a container that's located within the item itself 3604 if($.ui.contains(this.currentItem[0], this.containers[i].element[0])) 3605 continue; 3606 3607 if(this._intersectsWith(this.containers[i].containerCache)) { 3608 3609 // if we've already found a container and it's more "inner" than this, then continue 3610 if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0])) 3611 continue; 3612 3613 innermostContainer = this.containers[i]; 3614 innermostIndex = i; 3615 3616 } else { 3617 // container doesn't intersect. trigger "out" event if necessary 3618 if(this.containers[i].containerCache.over) { 3619 this.containers[i]._trigger("out", event, this._uiHash(this)); 3620 this.containers[i].containerCache.over = 0; 3621 } 3622 } 3623 3624 } 3625 3626 // if no intersecting containers found, return 3627 if(!innermostContainer) return; 3628 3629 // move the item into the container if it's not there already 3630 if(this.containers.length === 1) { 3631 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 3632 this.containers[innermostIndex].containerCache.over = 1; 3633 } else if(this.currentContainer != this.containers[innermostIndex]) { 3634 3635 //When entering a new container, we will find the item with the least distance and append our item near it 3636 var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 3637 for (var j = this.items.length - 1; j >= 0; j--) { 3638 if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 3639 var cur = this.containers[innermostIndex].floating ? this.items[j].item.offset().left : this.items[j].item.offset().top; 3640 if(Math.abs(cur - base) < dist) { 3641 dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 3642 this.direction = (cur - base > 0) ? 'down' : 'up'; 3643 } 3644 } 3645 3646 if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 3647 return; 3648 3649 this.currentContainer = this.containers[innermostIndex]; 3650 itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 3651 this._trigger("change", event, this._uiHash()); 3652 this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 3653 3654 //Update the placeholder 3655 this.options.placeholder.update(this.currentContainer, this.placeholder); 3656 3657 this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 3658 this.containers[innermostIndex].containerCache.over = 1; 3659 } 3660 3661 3662 }, 3663 3664 _createHelper: function(event) { 3665 3666 var o = this.options; 3667 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem); 3668 3669 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already 3670 $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); 3671 3672 if(helper[0] == this.currentItem[0]) 3673 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
3673: this.currentItem.css("left") }; 3674 3675 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width()); 3676 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height()); 3677 3678 return helper; 3679 3680 }, 3681 3682 _adjustOffsetFromHelper: function(obj) { 3683 if (typeof obj == 'string') { 3684 obj = obj.split(' '); 3685 } 3686 if ($.isArray(obj)) { 3687 obj = {left: +obj[0], top: +obj[1] || 0}; 3688 } 3689 if ('left' in obj) { 3690 this.offset.click.left = obj.left + this.margins.left; 3691 } 3692 if ('right' in obj) { 3693 this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; 3694 } 3695 if ('top' in obj) { 3696 this.offset.click.top = obj.top + this.margins.top; 3697 } 3698 if ('bottom' in obj) { 3699 this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; 3700 } 3701 }, 3702 3703 _getParentOffset: function() { 3704 3705 3706 //Get the offsetParent and cache its position 3707 this.offsetParent = this.helper.offsetParent(); 3708 var po = this.offsetParent.offset(); 3709 3710 // This is a special case where we need to modify a offset calculated on start, since the following happened: 3711 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent 3712 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that 3713 // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag 3714 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) { 3715 po.left += this.scrollParent.scrollLeft(); 3716 po.top += this.scrollParent.scrollTop(); 3717 } 3718 3719 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information 3720 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix 3721 po = { top: 0, left: 0 }; 3722 3723 return { 3724 top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), 3725 left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) 3726 }; 3727 3728 }, 3729 3730 _getRelativeOffset: function() { 3731 3732 if(this.cssPosition == "relative") { 3733 var p = this.currentItem.position(); 3734 return { 3735 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), 3736 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() 3737 }; 3738 } else { 3739 return { top: 0, left: 0 }; 3740 } 3741 3742 }, 3743 3744 _cacheMargins: function() { 3745 this.margins = { 3746 left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), 3747 top: (parseInt(this.currentItem.css("marginTop"),10) || 0) 3748 }; 3749 }, 3750 3751 _cacheHelperProportions: function() { 3752 this.helperProportions = { 3753 width: this.helper.outerWidth(), 3754 height: this.helper.outerHeight() 3755 }; 3756 }, 3757 3758 _setContainment: function() { 3759 3760 var o = this.options; 3761 if(o.containment == 'parent') o.containment = this.helper[0].parentNode; 3762 if(o.containment == 'document' || o.containment == 'window') this.containment = [ 3763 0 - this.offset.relative.left - this.offset.parent.left, 3764 0 - this.offset.relative.top - this.offset.parent.top, 3765 $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, 3766 ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top 3767 ]; 3768 3769 if(!(/^(document|window|parent)$/).test(o.containment)) { 3770 var ce = $(o.containment)[0]; 3771 var co = $(o.containment).offset(); 3772 var over = ($(ce).css("overflow") != 'hidden'); 3773 3774 this.containment = [ 3775 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, 3776 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, 3777 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, 3778 co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),
377810) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top 3779 ]; 3780 } 3781 3782 }, 3783 3784 _convertPositionTo: function(d, pos) { 3785 3786 if(!pos) pos = this.position; 3787 var mod = d == "absolute" ? 1 : -1; 3788 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 3789 3790 return { 3791 top: ( 3792 pos.top // The absolute mouse position 3793 + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent 3794 + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) 3795 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) 3796 ), 3797 left: ( 3798 pos.left // The absolute mouse position 3799 + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent 3800 + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) 3801 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) 3802 ) 3803 }; 3804 3805 }, 3806 3807 _generatePosition: function(event) { 3808 3809 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); 3810 3811 // This is another very weird special case that only happens for relative elements: 3812 // 1. If the css position is relative 3813 // 2. and the scroll parent is the document or similar to the offset parent 3814 // we have to refresh the relative offset during the scroll so there are no jumps 3815 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) { 3816 this.offset.relative = this._getRelativeOffset(); 3817 } 3818 3819 var pageX = event.pageX; 3820 var pageY = event.pageY; 3821 3822 /* 3823 * - Position constraining - 3824 * Constrain the position to a mix of grid, containment. 3825 */ 3826 3827 if(this.originalPosition) { //If we are not dragging yet, we won't check for options 3828 3829 if(this.containment) { 3830 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left; 3831 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top; 3832 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left; 3833 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top; 3834 } 3835 3836 if(o.grid) { 3837 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; 3838 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; 3839 3840 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; 3841 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; 3842 } 3843 3844 } 3845 3846 return { 3847 top: ( 3848 pageY // The absolute mouse position 3849 - this.offset.click.top // Click offset (relative to the element) 3850 - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent 3851 - this.offset.parent.top // The offsetParent's offset without borders (offset + border) 3852 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) 3853 ), 3854 left: ( 3855 pageX // The absolute mouse position 3856 - this.offset.click.left // Click offset (relative to the element) 3857 - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent 3858 - this.offset.parent.left // The offsetParent's offset without borders (offset + border) 3859 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) 3860 ) 3861 }; 3862 3863 }, 3864 3865 _rearrange: function(event, i, a, hardRefresh) { 3866 3867 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)); 3868 3869 //Various things done here to improve the performance: 3870 // 1. we create a setTimeout, that calls refreshPositions 3871 // 2. on the instance, we have a counter variable, that get's higher after every append 3872 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same 3873 // 4. this lets only the last addition to the timeout stack through 3874 this.counter = this.counter ? ++this.counter : 1;
3875 var self = this, counter = this.counter; 3876 3877 window.setTimeout(function() { 3878 if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove 3879 },0); 3880 3881 }, 3882 3883 _clear: function(event, noPropagation) { 3884 3885 this.reverting = false; 3886 // We delay all events that have to be triggered to after the point where the placeholder has been removed and 3887 // everything else normalized again 3888 var delayedTriggers = [], self = this; 3889 3890 // We first have to update the dom position of the actual currentItem 3891 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) 3892 if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem); 3893 this._noFinalSort = null; 3894 3895 if(this.helper[0] == this.currentItem[0]) { 3896 for(var i in this._storedCSS) { 3897 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = ''; 3898 } 3899 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); 3900 } else { 3901 this.currentItem.show(); 3902 } 3903 3904 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); 3905 if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed 3906 3907 // Check if the items Container has Changed and trigger appropriate 3908 // events. 3909 if (this !== this.currentContainer) { 3910 if(!noPropagation) { 3911 delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); 3912 delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); 3913 delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); 3914 } 3915 } 3916 3917 //Post events to containers 3918 for (var i = this.containers.length - 1; i >= 0; i--){ 3919 if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i])); 3920 if(this.containers[i].containerCache.over) { 3921 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i])); 3922 this.containers[i].containerCache.over = 0; 3923 } 3924 } 3925 3926 //Do what was originally in plugins 3927 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor 3928 if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity 3929 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index 3930 3931 this.dragging = false; 3932 if(this.cancelHelperRemoval) { 3933 if(!noPropagation) { 3934 this._trigger("beforeStop", event, this._uiHash()); 3935 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events 3936 this._trigger("stop", event, this._uiHash()); 3937 } 3938 3939 this.fromOutside = false;
3940 return false; 3941 } 3942 3943 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash()); 3944 3945 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! 3946 this.placeholder[0].parentNode.removeChild(this.placeholder[0]); 3947 3948 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null; 3949 3950 if(!noPropagation) { 3951 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events 3952 this._trigger("stop", event, this._uiHash()); 3953 } 3954 3955 this.fromOutside = false; 3956 return true; 3957 3958 }, 3959 3960 _trigger: function() { 3961 if ($.Widget.prototype._trigger.apply(this, arguments) === false) { 3962 this.cancel(); 3963 } 3964 }, 3965 3966 _uiHash: function(inst) { 3967 var self = inst || this; 3968 return { 3969 helper: self.helper, 3970 placeholder: self.placeholder || $([]), 3971 position: self.position, 3972 originalPosition: self.originalPosition, 3973 offset: self.positionAbs, 3974 item: self.currentItem, 3975 sender: inst ? inst.element : null 3976 }; 3977 } 3978 3979}); 3980 3981$.extend($.ui.sortable, { 3982 version: "1.8.24" 3983}); 3984 3985})(jQuery); 3986 3987;jQuery.effects || (function($, undefined) { 3988 3989$.effects = {}; 3990 3991 3992 3993/******************************************************************************/ 3994/****************************** COLOR ANIMATIONS ******************************/ 3995/******************************************************************************/ 3996 3997// override the animation for color styles 3998$.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', 3999 'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'], 4000function(i, attr) { 4001 $.fx.step[attr] = function(fx) { 4002 if (!fx.colorInit) { 4003 fx.start = getColor(fx.elem, attr); 4004 fx.end = getRGB(fx.end); 4005 fx.colorInit = true; 4006 } 4007 4008 fx.elem.style[attr] = 'rgb(' + 4009 Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' + 4010 Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' + 4011 Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')'; 4012 }; 4013}); 4014 4015// Color Conversion functions from highlightFade 4016// By Blair Mitchelmore 4017// http://jquery.offput.ca/highlightFade/ 4018 4019// Parse strings looking for color tuples [255,255,255] 4020function getRGB(color) { 4021 var result; 4022 4023 // Check if we're already dealing with an array of colors 4024 if ( color && color.constructor == Array && color.length == 3 ) 4025 return color; 4026 4027 // Look for rgb(num,num,num) 4028 if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color)) 4029 return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)]; 4030 4031 // Look for rgb(num%,num%,num%) 4032 if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color)) 4033 return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55]; 4034 4035 // Look for #a0b1c2 4036 if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color)) 4037 return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)]; 4038 4039 // Look for #fff 4040 if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color)) 4041 return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)]; 4042 4043 // Look for rgba(0, 0, 0, 0) == transparent in Safari 3 4044 if (result = /rgba\(0, 0, 0, 0\)/.exec(color)) 4045 return colors['transparent']; 4046 4047 // Otherwise, we're most likely dealing with a named color 4048 return colors[$.trim(color).toLowerCase()]; 4049} 4050 4051function getColor(elem, attr) { 4052 var color; 4053 4054 do { 4055 // jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css 4056 color = ($.curCSS || $.css)(elem, attr); 4057 4058 // Keep going until we find an element that has color, or we hit the body 4059 if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") ) 4060 break; 4061 4062 attr = "backgroundColor"; 4063 } while ( elem = elem.parentNode ); 4064 4065 return getRGB(color); 4066}; 4067 4068// Some named colors to work with 4069// From Interface by Stefan Petre 4070// http://interface.eyecon.ro/ 4071 4072var colors = { 4073 aqua:[0,255,255], 4074 azure:[240,255,255], 4075 beige:[245,245,220], 4076 black:[0,0,0], 4077 blue:[0,0,255], 4078 brown:[165,42,42], 4079 cyan:[0,255,255], 4080 darkblue:[0,0,139], 4081 darkcyan:[0,139,139], 4082 darkgrey:[169,169,169], 4083 darkgreen:[0,100,0], 4084 darkkhaki:[189,183,107], 4085 darkmagenta:[139,0,139], 4086 darkolivegreen:[85,107,47], 4087 darkorange:[255,140,0], 4088 darkorchid:[153,50,204], 4089 darkred:[139,0,0], 4090 darksalmon:[233,150,122], 4091 darkviolet:[148,0,211], 4092 fuchsia:[255,0,255], 4093 gold:[255,215,0], 4094 green:[0,128,0], 4095 indigo:[75,0,130], 4096 khaki:[240,230,140], 4097 lightblue:[173,216,230], 4098 lightcyan:[224,255,255], 4099 lightgreen:[144,238,144], 4100 lightgrey:[211,211,211], 4101 lightpink:[255,182,193], 4102 lightyellow:[255,255,224], 4103 lime:[0,255,0], 4104 magenta:[255,0,255], 4105 maroon:[128,0,0], 4106 navy:[0,0,128], 4107 olive:[128,128,0], 4108 orange:[255,165,0], 4109 pink:[255,192,203], 4110 purple:[128,0,128], 4111 violet:[128,0,128], 4112 red:[255,0,0], 4113 silver:[192,192,192], 4114 white:[255,255,255], 4115 yellow:[255,255,0],
4116 transparent: [255,255,255] 4117}; 4118 4119 4120 4121/******************************************************************************/ 4122/****************************** CLASS ANIMATIONS ******************************/ 4123/******************************************************************************/ 4124 4125var classAnimationActions = ['add', 'remove', 'toggle'], 4126 shorthandStyles = { 4127 border: 1, 4128 borderBottom: 1, 4129 borderColor: 1, 4130 borderLeft: 1, 4131 borderRight: 1, 4132 borderTop: 1, 4133 borderWidth: 1, 4134 margin: 1, 4135 padding: 1 4136 }; 4137 4138function getElementStyles() { 4139 var style = document.defaultView 4140 ? document.defaultView.getComputedStyle(this, null) 4141 : this.currentStyle, 4142 newStyle = {}, 4143 key, 4144 camelCase; 4145 4146 // webkit enumerates style porperties 4147 if (style && style.length && style[0] && style[style[0]]) { 4148 var len = style.length; 4149 while (len--) { 4150 key = style[len]; 4151 if (typeof style[key] == 'string') { 4152 camelCase = key.replace(/\-(\w)/g, function(all, letter){ 4153 return letter.toUpperCase(); 4154 }); 4155 newStyle[camelCase] = style[key]; 4156 } 4157 } 4158 } else { 4159 for (key in style) { 4160 if (typeof style[key] === 'string') { 4161 newStyle[key] = style[key]; 4162 } 4163 } 4164 } 4165 4166 return newStyle; 4167} 4168 4169function filterStyles(styles) { 4170 var name, value; 4171 for (name in styles) { 4172 value = styles[name]; 4173 if ( 4174 // ignore null and undefined values 4175 value == null || 4176 // ignore functions (when does this occur?) 4177 $.isFunction(value) || 4178 // shorthand styles that need to be expanded 4179 name in shorthandStyles || 4180 // ignore scrollbars (break in IE) 4181 (/scrollbar/).test(name) || 4182 4183 // only colors or values that can be converted to numbers 4184 (!(/color/i).test(name) && isNaN(parseFloat(value))) 4185 ) { 4186 delete styles[name]; 4187 } 4188 } 4189 4190 return styles; 4191} 4192 4193function styleDifference(oldStyle, newStyle) { 4194 var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459 4195 name; 4196 4197 for (name in newStyle) { 4198 if (oldStyle[name] != newStyle[name]) { 4199 diff[name] = newStyle[name]; 4200 } 4201 } 4202 4203 return diff; 4204} 4205 4206$.effects.animateClass = function(value, duration, easing, callback) { 4207 if ($.isFunction(easing)) { 4208 callback = easing; 4209 easing = null; 4210 } 4211 4212 return this.queue(function() { 4213 var that = $(this), 4214 originalStyleAttr = that.attr('style') || ' ', 4215 originalStyle = filterStyles(getElementStyles.call(this)), 4216 newStyle, 4217 className = that.attr('class') || ""; 4218 4219 $.each(classAnimationActions, function(i, action) { 4220 if (value[action]) { 4221 that[action + 'Class'](value[action]); 4222 } 4223 }); 4224 newStyle = filterStyles(getElementStyles.call(this)); 4225 that.attr('class', className); 4226 4227 that.animate(styleDifference(originalStyle, newStyle), { 4228 queue: false, 4229 duration: duration, 4230 easing: easing, 4231 complete: function() { 4232 $.each(classAnimationActions, function(i, action) { 4233 if (value[action]) { that[action + 'Class'](value[action]); } 4234 }); 4235 // work around bug in IE by clearing the cssText before setting it 4236 if (typeof that.attr('style') == 'object') { 4237 that.attr('style').cssText = ''; 4238 that.attr('style').cssText = originalStyleAttr; 4239 } else { 4240 that.attr('style', originalStyleAttr); 4241 } 4242 if (callback) { callback.apply(this, arguments); } 4243 $.dequeue( this ); 4244 } 4245 }); 4246 }); 4247}; 4248 4249$.fn.extend({ 4250 _addClass: $.fn.addClass, 4251 addClass: function(classNames, speed, easing, callback) { 4252 return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames); 4253 }, 4254 4255 _removeClass: $.fn.removeClass, 4256 removeClass: function(classNames,speed,easing,callback) { 4257 return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames); 4258 }, 4259 4260 _toggleClass: $.fn.toggleClass, 4261 toggleClass: function(classNames, force, speed, easing, callback) { 4262 if ( typeof force == "boolean" || force === undefined ) { 4263 if ( !speed ) { 4264 // without speed parameter; 4265 return this._toggleClass(classNames, force); 4266 } else { 4267 return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]); 4268 } 4269 } else { 4270 // without switch parameter; 4271 return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]); 4272 } 4273 }, 4274 4275 switchClass: function(remove,add,speed,easing,callback) { 4276 return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]); 4277 } 4278}); 4279 4280 4281 4282/******************************************************************************/ 4283/*********************************** EFFECTS **********************************/ 4284/******************************************************************************/ 4285 4286$.extend($.effects, { 4287 version: "1.8.24", 4288 4289 // Saves a set of properties in a data storage 4290 save: function(element, set) { 4291 for(var i=0; i < set.length; i++) { 4292 if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]); 4293 } 4294 }, 4295 4296 // Restores a set of previously saved properties from a data storage 4297 restore: function(element, set) { 4298 for(var i=0; i < set.length; i++) { 4299 if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i])); 4300 } 4301 }, 4302 4303 setMode: function(el, mode) { 4304 if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle 4305 return mode; 4306 }, 4307 4308 getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value 4309 // this should be a little more flexible in the future to handle a string & hash 4310 var y, x; 4311 switch (origin[0]) { 4312 case 'top': y = 0; break; 4313 case 'middle': y = 0.5; break; 4314 case 'bottom': y = 1; break; 4315 default: y = origin[0] / original.height; 4316 }; 4317 switch (origin[1]) { 4318 case 'left': x = 0; break; 4319 case 'center': x = 0.5; break; 4320 case 'right': x = 1; break; 4321 default: x = origin[1] / original.width; 4322 }; 4323 return {x: x, y: y}; 4324 }, 4325
4326 // Wraps the element around a wrapper that copies position properties 4327 createWrapper: function(element) { 4328 4329 // if the element is already wrapped, return it 4330 if (element.parent().is('.ui-effects-wrapper')) { 4331 return element.parent(); 4332 } 4333 4334 // wrap the element 4335 var props = { 4336 width: element.outerWidth(true), 4337 height: element.outerHeight(true), 4338 'float': element.css('float') 4339 }, 4340 wrapper = $('<div></div>') 4341 .addClass('ui-effects-wrapper') 4342 .css({ 4343 fontSize: '100%', 4344 background: 'transparent', 4345 border: 'none', 4346 margin: 0, 4347 padding: 0 4348 }), 4349 active = document.activeElement; 4350 4351 // support: Firefox 4352 // Firefox incorrectly exposes anonymous content 4353 // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 4354 try { 4355 active.id; 4356 } catch( e ) { 4357 active = document.body; 4358 } 4359 4360 element.wrap( wrapper ); 4361 4362 // Fixes #7595 - Elements lose focus when wrapped. 4363 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 4364 $( active ).focus(); 4365 } 4366 4367 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element 4368 4369 // transfer positioning properties to the wrapper 4370 if (element.css('position') == 'static') { 4371 wrapper.css({ position: 'relative' }); 4372 element.css({ position: 'relative' }); 4373 } else { 4374 $.extend(props, { 4375 position: element.css('position'), 4376 zIndex: element.css('z-index') 4377 }); 4378 $.each(['top', 'left', 'bottom', 'right'], function(i, pos) { 4379 props[pos] = element.css(pos); 4380 if (isNaN(parseInt(props[pos], 10))) { 4381 props[pos] = 'auto'; 4382 } 4383 }); 4384 element.css({position: 'relative', top: 0, left: 0, right: 'auto', bottom: 'auto' }); 4385 } 4386 4387 return wrapper.css(props).show(); 4388 }, 4389 4390 removeWrapper: function(element) { 4391 var parent, 4392 active = document.activeElement; 4393 4394 if (element.parent().is('.ui-effects-wrapper')) { 4395 parent = element.parent().replaceWith(element); 4396 // Fixes #7595 - Elements lose focus when wrapped. 4397 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { 4398 $( active ).focus(); 4399 } 4400 return parent; 4401 } 4402 4403 return element; 4404 }, 4405 4406 setTransition: function(element, list, factor, value) { 4407 value = value || {}; 4408 $.each(list, function(i, x){ 4409 var unit = element.cssUnit(x); 4410 if (unit[0] > 0) value[x] = unit[0] * factor + unit[1]; 4411 }); 4412 return value; 4413 } 4414}); 4415 4416 4417function _normalizeArguments(effect, options, speed, callback) { 4418 // shift params for method overloading 4419 if (typeof effect == 'object') { 4420 callback = options; 4421 speed = null; 4422 options = effect; 4423 effect = options.effect; 4424 } 4425 if ($.isFunction(options)) { 4426 callback = options; 4427 speed = null; 4428 options = {}; 4429 } 4430 if (typeof options == 'number' || $.fx.speeds[options]) { 4431 callback = speed; 4432 speed = options; 4433 options = {}; 4434 } 4435 if ($.isFunction(speed)) { 4436 callback = speed; 4437 speed = null; 4438 } 4439 4440 options = options || {}; 4441 4442 speed = speed || options.duration; 4443 speed = $.fx.off ? 0 : typeof speed == 'number' 4444 ? speed : speed in $.fx.speeds ? $.fx.speeds[speed] : $.fx.speeds._default; 4445 4446 callback = callback || options.complete; 4447 4448 return [effect, options, speed, callback]; 4449} 4450 4451function standardSpeed( speed ) { 4452 // valid standard speeds 4453 if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) { 4454 return true; 4455 } 4456 4457 // invalid strings - treat as "normal" speed 4458 if ( typeof speed === "string" && !$.effects[ speed ] ) { 4459 return true; 4460 } 4461 4462 return false; 4463} 4464 4465$.fn.extend({ 4466 effect: function(effect, options, speed, callback) { 4467 var args = _normalizeArguments.apply(this, arguments), 4468 // TODO: make effects take actual parameters instead of a hash 4469 args2 = { 4470 options: args[1], 4471 duration: args[2], 4472 callback: args[3] 4473 }, 4474 mode = args2.options.mode, 4475 effectMethod = $.effects[effect]; 4476 4477 if ( $.fx.off || !effectMethod ) { 4478 // delegate to the original method (e.g., .show()) if possible 4479 if ( mode ) { 4480 return this[ mode ]( args2.duration, args2.callback ); 4481 } else { 4482 return this.each(function() { 4483 if ( args2.callback ) { 4484 args2.callback.call( this ); 4485 } 4486 }); 4487 } 4488 } 4489 4490 return effectMethod.call(this, args2); 4491 }, 4492 4493 _show: $.fn.show, 4494 show: function(speed) { 4495 if ( standardSpeed( speed ) ) { 4496 return this._show.apply(this, arguments); 4497 } else { 4498 var args = _normalizeArguments.apply(this, arguments); 4499 args[1].mode = 'show'; 4500 return this.effect.apply(this, args); 4501 } 4502 }, 4503 4504 _hide: $.fn.hide, 4505 hide: function(speed) { 4506 if ( standardSpeed( speed ) ) { 4507 return this._hide.apply(this, arguments); 4508 } else { 4509 var args = _normalizeArguments.apply(this, arguments); 4510 args[1].mode = 'hide'; 4511 return this.effect.apply(this, args); 4512 } 4513 }, 4514 4515 // jQuery core overloads toggle and creates _toggle 4516 __toggle: $.fn.toggle, 4517 toggle: function(speed) { 4518 if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) { 4519 return this.__toggle.apply(this, arguments); 4520 } else { 4521 var args = _normalizeArguments.apply(this, arguments); 4522 args[1].mode = 'toggle'; 4523 return this.effect.apply(this, args); 4524 } 4525 }, 4526 4527 // helper functions 4528 cssUnit: function(key) { 4529 var style = this.css(key), val = []; 4530 $.each( ['em','px','%','pt'], function(i, unit){ 4531 if(style.indexOf(unit) > 0) 4532 val = [parseFloat(style), unit]; 4533 }); 4534 return val; 4535 } 4536}); 4537 4538 4539 4540/******************************************************************************/ 4541/*********************************** EASING ***********************************/ 4542/******************************************************************************/ 4543 4544// based on easing equations from Robert Penner (http://www.robertpenner.com/easing) 4545 4546var baseEasings = {}; 4547 4548$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { 4549 baseEasings[ name ] = function( p ) { 4550 return Math.pow( p, i + 2 ); 4551 }; 4552}); 4553 4554$.extend( baseEasings, { 4555 Sine: function ( p ) { 4556 return 1 - Math.cos( p * Math.PI / 2 ); 4557 }, 4558 Circ: function ( p ) { 4559 return 1 - Math.sqrt( 1 - p * p ); 4560 }, 4561 Elastic: function( p ) { 4562 return p === 0 || p === 1 ? p : 4563 -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 ); 4564 }, 4565 Back: function( p ) { 4566 return p * p * ( 3 * p - 2 ); 4567 }, 4568 Bounce: function ( p ) { 4569 var pow2, 4570 bounce = 4; 4571 4572 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} 4573 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); 4574 } 4575}); 4576 4577$.each( baseEasings, function( name, easeIn ) {
4578 $.easing[ "easeIn" + name ] = easeIn; 4579 $.easing[ "easeOut" + name ] = function( p ) { 4580 return 1 - easeIn( 1 - p ); 4581 }; 4582 $.easing[ "easeInOut" + name ] = function( p ) { 4583 return p < .5 ? 4584 easeIn( p * 2 ) / 2 : 4585 easeIn( p * -2 + 2 ) / -2 + 1; 4586 }; 4587}); 4588 4589})(jQuery); 4590 4591(function( $, undefined ) { 4592 4593$.effects.blind = function(o) { 4594 4595 return this.queue(function() { 4596 4597 // Create element 4598 var el = $(this), props = ['position','top','bottom','left','right']; 4599 4600 // Set options 4601 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode 4602 var direction = o.options.direction || 'vertical'; // Default direction 4603 4604 // Adjust 4605 $.effects.save(el, props); el.show(); // Save & Show 4606 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper 4607 var ref = (direction == 'vertical') ? 'height' : 'width'; 4608 var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width(); 4609 if(mode == 'show') wrapper.css(ref, 0); // Shift 4610 4611 // Animation 4612 var animation = {}; 4613 animation[ref] = mode == 'show' ? distance : 0; 4614 4615 // Animate 4616 wrapper.animate(animation, o.duration, o.options.easing, function() { 4617 if(mode == 'hide') el.hide(); // Hide 4618 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore 4619 if(o.callback) o.callback.apply(el[0], arguments); // Callback 4620 el.dequeue(); 4621 }); 4622 4623 }); 4624 4625}; 4626 4627})(jQuery); 4628 4629(function( $, undefined ) { 4630 4631$.effects.bounce = function(o) { 4632 4633 return this.queue(function() { 4634 4635 // Create element 4636 var el = $(this), props = ['position','top','bottom','left','right']; 4637 4638 // Set options 4639 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode 4640 var direction = o.options.direction || 'up'; // Default direction 4641 var distance = o.options.distance || 20; // Default distance 4642 var times = o.options.times || 5; // Default # of times 4643 var speed = o.duration || 250; // Default speed per bounce 4644 if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE 4645 4646 // Adjust 4647 $.effects.save(el, props); el.show(); // Save & Show 4648 $.effects.createWrapper(el); // Create Wrapper 4649 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; 4650 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; 4651 var distance = o.options.distance || (ref == 'top' ? el.outerHeight(true) / 3 : el.outerWidth(true) / 3); 4652 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift 4653 if (mode == 'hide') distance = distance / (times * 2); 4654 if (mode != 'hide') times--; 4655 4656 // Animate 4657 if (mode == 'show') { // Show Bounce 4658 var animation = {opacity: 1}; 4659 animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance; 4660 el.animate(animation, speed / 2, o.options.easing); 4661 distance = distance / 2; 4662 times--; 4663 }; 4664 for (var i = 0; i < times; i++) { // Bounces 4665 var animation1 = {}, animation2 = {}; 4666 animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance; 4667 animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance; 4668 el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing); 4669 distance = (mode == 'hide') ? distance * 2 : distance / 2; 4670 }; 4671 if (mode == 'hide') { // Last Bounce 4672 var animation = {opacity: 0}; 4673 animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance; 4674 el.animate(animation, speed / 2, o.options.easing, function(){ 4675 el.hide(); // Hide 4676 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore 4677 if(o.callback) o.callback.apply(this, arguments); // Callback 4678 }); 4679 } else { 4680 var animation1 = {}, animation2 = {}; 4681 animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance; 4682 animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance; 4683 el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){ 4684 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore 4685 if(o.callback) o.callback.apply(this, arguments); // Callback 4686 }); 4687 }; 4688 el.queue('fx', function() { el.dequeue(); }); 4689 el.dequeue(); 4690 }); 4691 4692}; 4693 4694})(jQuery); 4695 4696(function( $, undefined ) { 4697 4698$.effects.clip = function(o) { 4699 4700 return this.queue(function() { 4701 4702 // Create element 4703 var el = $(this), props = ['position','top','bottom','left','right','height','width']; 4704 4705 // Set options 4706 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode 4707 var direction = o.options.direction || 'vertical'; // Default direction 4708 4709 // Adjust 4710 $.effects.save(el, props); el.show(); // Save & Show 4711 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper 4712 var animate = el[0].tagName == 'IMG' ? wrapper : el; 4713 var ref = { 4714 size: (direction == 'vertical') ? 'height' : 'width', 4715 position: (direction == 'vertical') ? 'top' : 'left' 4716 }; 4717 var distance = (direction == 'vertical') ? animate.height() : animate.width(); 4718 if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift 4719 4720 // Animation 4721 var animation = {};
4722 animation[ref.size] = mode == 'show' ? distance : 0; 4723 animation[ref.position] = mode == 'show' ? 0 : distance / 2; 4724 4725 // Animate 4726 animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { 4727 if(mode == 'hide') el.hide(); // Hide 4728 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore 4729 if(o.callback) o.callback.apply(el[0], arguments); // Callback 4730 el.dequeue(); 4731 }}); 4732 4733 }); 4734 4735}; 4736 4737})(jQuery); 4738 4739(function( $, undefined ) { 4740 4741$.effects.drop = function(o) { 4742 4743 return this.queue(function() { 4744 4745 // Create element 4746 var el = $(this), props = ['position','top','bottom','left','right','opacity']; 4747 4748 // Set options 4749 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode 4750 var direction = o.options.direction || 'left'; // Default Direction 4751 4752 // Adjust 4753 $.effects.save(el, props); el.show(); // Save & Show 4754 $.effects.createWrapper(el); // Create Wrapper 4755 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; 4756 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; 4757 var distance = o.options.distance || (ref == 'top' ? el.outerHeight( true ) / 2 : el.outerWidth( true ) / 2); 4758 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift 4759 4760 // Animation 4761 var animation = {opacity: mode == 'show' ? 1 : 0}; 4762 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance; 4763 4764 // Animate 4765 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { 4766 if(mode == 'hide') el.hide(); // Hide 4767 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore 4768 if(o.callback) o.callback.apply(this, arguments); // Callback 4769 el.dequeue(); 4770 }}); 4771 4772 }); 4773 4774}; 4775 4776})(jQuery); 4777 4778(function( $, undefined ) { 4779 4780$.effects.explode = function(o) { 4781 4782 return this.queue(function() { 4783 4784 var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3; 4785 var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3; 4786 4787 o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode; 4788 var el = $(this).show().css('visibility', 'hidden'); 4789 var offset = el.offset(); 4790 4791 //Substract the margins - not fixing the problem yet. 4792 offset.top -= parseInt(el.css("marginTop"),10) || 0; 4793 offset.left -= parseInt(el.css("marginLeft"),10) || 0; 4794 4795 var width = el.outerWidth(true); 4796 var height = el.outerHeight(true); 4797 4798 for(var i=0;i<rows;i++) { // = 4799 for(var j=0;j<cells;j++) { // || 4800 el 4801 .clone() 4802 .appendTo('body') 4803 .wrap('<div></div>') 4804 .css({ 4805 position: 'absolute', 4806 visibility: 'visible', 4807 left: -j*(width/cells), 4808 top: -i*(height/rows) 4809 }) 4810 .parent() 4811 .addClass('ui-effects-explode') 4812 .css({ 4813 position: 'absolute', 4814 overflow: 'hidden', 4815 width: width/cells, 4816 height: height/rows, 4817 left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0), 4818 top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0), 4819 opacity: o.options.mode == 'show' ? 0 : 1 4820 }).animate({ 4821 left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)), 4822 top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)), 4823 opacity: o.options.mode == 'show' ? 1 : 0 4824 }, o.duration || 500); 4825 } 4826 } 4827 4828 // Set a timeout, to call the callback approx. when the other animations have finished 4829 setTimeout(function() { 4830 4831 o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide(); 4832 if(o.callback) o.callback.apply(el[0]); // Callback 4833 el.dequeue(); 4834 4835 $('div.ui-effects-explode').remove(); 4836 4837 }, o.duration || 500); 4838 4839 4840 }); 4841 4842}; 4843 4844})(jQuery); 4845 4846(function( $, undefined ) { 4847 4848$.effects.fade = function(o) { 4849 return this.queue(function() { 4850 var elem = $(this), 4851 mode = $.effects.setMode(elem, o.options.mode || 'hide'); 4852 4853 elem.animate({ opacity: mode }, { 4854 queue: false, 4855 duration: o.duration, 4856 easing: o.options.easing, 4857 complete: function() {
4858 (o.callback && o.callback.apply(this, arguments)); 4859 elem.dequeue(); 4860 } 4861 }); 4862 }); 4863}; 4864 4865})(jQuery); 4866 4867(function( $, undefined ) { 4868 4869$.effects.fold = function(o) { 4870 4871 return this.queue(function() { 4872 4873 // Create element 4874 var el = $(this), props = ['position','top','bottom','left','right']; 4875 4876 // Set options 4877 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode 4878 var size = o.options.size || 15; // Default fold size 4879 var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value 4880 var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2; 4881 4882 // Adjust 4883 $.effects.save(el, props); el.show(); // Save & Show 4884 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper 4885 var widthFirst = ((mode == 'show') != horizFirst); 4886 var ref = widthFirst ? ['width', 'height'] : ['height', 'width']; 4887 var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()]; 4888 var percent = /([0-9]+)%/.exec(size); 4889 if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1]; 4890 if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift 4891 4892 // Animation 4893 var animation1 = {}, animation2 = {}; 4894 animation1[ref[0]] = mode == 'show' ? distance[0] : size; 4895 animation2[ref[1]] = mode == 'show' ? distance[1] : 0; 4896 4897 // Animate 4898 wrapper.animate(animation1, duration, o.options.easing) 4899 .animate(animation2, duration, o.options.easing, function() { 4900 if(mode == 'hide') el.hide(); // Hide 4901 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore 4902 if(o.callback) o.callback.apply(el[0], arguments); // Callback 4903 el.dequeue(); 4904 }); 4905 4906 }); 4907 4908}; 4909 4910})(jQuery); 4911 4912(function( $, undefined ) { 4913 4914$.effects.highlight = function(o) { 4915 return this.queue(function() { 4916 var elem = $(this), 4917 props = ['backgroundImage', 'backgroundColor', 'opacity'], 4918 mode = $.effects.setMode(elem, o.options.mode || 'show'), 4919 animation = { 4920 backgroundColor: elem.css('backgroundColor') 4921 }; 4922 4923 if (mode == 'hide') { 4924 animation.opacity = 0; 4925 } 4926 4927 $.effects.save(elem, props); 4928 elem 4929 .show() 4930 .css({ 4931 backgroundImage: 'none', 4932 backgroundColor: o.options.color || '#ffff99' 4933 }) 4934 .animate(animation, { 4935 queue: false, 4936 duration: o.duration, 4937 easing: o.options.easing, 4938 complete: function() { 4939 (mode == 'hide' && elem.hide()); 4940 $.effects.restore(elem, props); 4941 (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter')); 4942 (o.callback && o.callback.apply(this, arguments)); 4943 elem.dequeue(); 4944 } 4945 }); 4946 }); 4947}; 4948 4949})(jQuery); 4950 4951(function( $, undefined ) { 4952 4953$.effects.pulsate = function(o) { 4954 return this.queue(function() { 4955 var elem = $(this), 4956 mode = $.effects.setMode(elem, o.options.mode || 'show'), 4957 times = ((o.options.times || 5) * 2) - 1, 4958 duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2, 4959 isVisible = elem.is(':visible'), 4960 animateTo = 0; 4961 4962 if (!isVisible) { 4963 elem.css('opacity', 0).show(); 4964 animateTo = 1; 4965 } 4966 4967 if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) { 4968 times--; 4969 } 4970 4971 for (var i = 0; i < times; i++) { 4972 elem.animate({ opacity: animateTo }, duration, o.options.easing); 4973 animateTo = (animateTo + 1) % 2; 4974 } 4975 4976 elem.animate({ opacity: animateTo }, duration, o.options.easing, function() { 4977 if (animateTo == 0) { 4978 elem.hide(); 4979 } 4980 (o.callback && o.callback.apply(this, arguments)); 4981 }); 4982 4983 elem 4984 .queue('fx', function() { elem.dequeue(); }) 4985 .dequeue(); 4986 }); 4987}; 4988 4989})(jQuery); 4990 4991(function( $, undefined ) { 4992 4993$.effects.puff = function(o) { 4994 return this.queue(function() { 4995 var elem = $(this), 4996 mode = $.effects.setMode(elem, o.options.mode || 'hide'), 4997 percent = parseInt(o.options.percent, 10) || 150, 4998 factor = percent / 100, 4999 original = { height: elem.height(), width: elem.width() }; 5000 5001 $.extend(o.options, { 5002 fade: true, 5003 mode: mode, 5004 percent: mode == 'hide' ? percent : 100, 5005 from: mode == 'hide' 5006 ? original 5007 : { 5008 height: original.height * factor, 5009 width: original.width * factor 5010 } 5011 }); 5012 5013 elem.effect('scale', o.options, o.duration, o.callback); 5014 elem.dequeue(); 5015 }); 5016}; 5017 5018$.effects.scale = function(o) { 5019 5020 return this.queue(function() { 5021 5022 // Create element 5023 var el = $(this); 5024 5025 // Set options 5026 var options = $.extend(true, {}, o.options); 5027 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode 5028 var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent 5029 var direction = o.options.direction || 'both'; // Set default axis 5030 var origin = o.options.origin; // The origin of the scaling 5031 if (mode != 'effect') { // Set default origin and restore for show/hide 5032 options.origin = origin || ['middle','center']; 5033 options.restore = true; 5034 } 5035 var original = {height: el.height(), width: el.width()}; // Save original 5036 el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state 5037 5038 // Adjust 5039 var factor = { // Set scaling factor 5040 y: direction != 'horizontal' ? (percent / 100) : 1, 5041 x: direction != 'vertical' ? (percent / 100) : 1 5042 }; 5043 el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state 5044 5045 if (o.options.fade) { // Fade option to support puff 5046 if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;}; 5047 if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;}; 5048 }; 5049 5050 // Animation 5051 options.from = el.from; options.to = el.to; options.mode = mode; 5052 5053 // Animate 5054 el.effect('size', options, o.duration, o.callback); 5055 el.dequeue(); 5056 }); 5057 5058}; 5059 5060$.effects.size = function(o) { 5061 5062 return this.queue(function() { 5063 5064 // Create element 5065 var el = $(this), props = ['position','top','bottom','left','right','width','height','overflow','opacity']; 5066 var props1 = ['position','top','bottom','left','right','overflow','opacity']; // Always restore 5067 var props2 = ['width','height','overflow']; // Copy for children 5068 var cProps = ['fontSize']; 5069 var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom']; 5070 var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight']; 5071 5072 // Set options 5073 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode 5074 var restore = o.options.restore || false; // Default restore 5075 var scale = o.options.scale || 'both'; // Default scale mode 5076 var origin = o.options.origin; // The origin of the sizing 5077 var original = {height: el.height(), width: el.width()}; // Save original 5078 el.from = o.options.from || original; // Default from state 5079 el.to = o.options.to || original; // Default to state 5080 // Adjust 5081 if (origin) { // Calculate baseline shifts 5082 var baseline = $.effects.getBaseline(origin, original); 5083 el.from.top = (original.height - el.from.height) * baseline.y; 5084 el.from.left = (original.width - el.from.width) * baseline.x; 5085 el.to.top = (original.height - el.to.height) * baseline.y; 5086 el.to.left = (original.width - el.to.width) * baseline.x; 5087 }; 5088 var factor = { // Set scaling factor 5089 from: {y: el.from.height / original.height, x: el.from.width / original.width}, 5090 to: {y: el.to.height / original.height, x: el.to.width / original.width} 5091 }; 5092 if (scale == 'box' || scale == 'both') { // Scale the css box 5093 if (factor.from.y != factor.to.y) { // Vertical props scaling 5094 props = props.concat(vProps); 5095 el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from); 5096 el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to); 5097 }; 5098 if (factor.from.x != factor.to.x) { // Horizontal props scaling 5099 props = props.concat(hProps); 5100 el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from); 5101 el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to); 5102 }; 5103 }; 5104 if (scale == 'content' || scale == 'both') { // Scale the content 5105 if (factor.from.y != factor.to.y) { // Vertical props scaling 5106 props = props.concat(cProps); 5107 el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from); 5108 el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to); 5109 }; 5110 }; 5111 $.effects.save(el, restore ? props : props1); el.show(); // Save & Show 5112 $.effects.createWrapper(el); // Create Wrapper 5113 el.css('overflow','hidden').css(el.from); // Shift 5114 5115 // Animate 5116 if (scale == 'content' || scale == 'both') { // Scale the children 5117 vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size 5118 hProps = hProps.concat(['marginLeft','marginRight']); // Add margins 5119 props2 = props.concat(vProps).concat(hProps); // Concat 5120 el.find("*[width]").each(function(){ 5121 var child = $(this); 5122 if (restore) $.effects.save(child, props2); 5123 var c_original = {height: child.height(), width: child.width()}; // Save original 5124 child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x}; 5125 child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x}; 5126 if (factor.from.y != factor.to.y) { // Vertical props scaling 5127 child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from); 5128 child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to); 5129 }; 5130 if (factor.from.x != factor.to.x) { // Horizontal props scaling 5131 child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from); 5132 child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to); 5133 }; 5134 child.css(child.from); // Shift children
5135 child.animate(child.to, o.duration, o.options.easing, function(){ 5136 if (restore) $.effects.restore(child, props2); // Restore children 5137 }); // Animate children 5138 }); 5139 }; 5140 5141 // Animate 5142 el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { 5143 if (el.to.opacity === 0) { 5144 el.css('opacity', el.from.opacity); 5145 } 5146 if(mode == 'hide') el.hide(); // Hide 5147 $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore 5148 if(o.callback) o.callback.apply(this, arguments); // Callback 5149 el.dequeue(); 5150 }}); 5151 5152 }); 5153 5154}; 5155 5156})(jQuery); 5157 5158(function( $, undefined ) { 5159 5160$.effects.shake = function(o) { 5161 5162 return this.queue(function() { 5163 5164 // Create element 5165 var el = $(this), props = ['position','top','bottom','left','right']; 5166 5167 // Set options 5168 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode 5169 var direction = o.options.direction || 'left'; // Default direction 5170 var distance = o.options.distance || 20; // Default distance 5171 var times = o.options.times || 3; // Default # of times 5172 var speed = o.duration || o.options.duration || 140; // Default speed per shake 5173 5174 // Adjust 5175 $.effects.save(el, props); el.show(); // Save & Show 5176 $.effects.createWrapper(el); // Create Wrapper 5177 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; 5178 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; 5179 5180 // Animation 5181 var animation = {}, animation1 = {}, animation2 = {}; 5182 animation[ref] = (motion == 'pos' ? '-=' : '+=') + distance; 5183 animation1[ref] = (motion == 'pos' ? '+=' : '-=') + distance * 2; 5184 animation2[ref] = (motion == 'pos' ? '-=' : '+=') + distance * 2; 5185 5186 // Animate 5187 el.animate(animation, speed, o.options.easing); 5188 for (var i = 1; i < times; i++) { // Shakes 5189 el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing); 5190 }; 5191 el.animate(animation1, speed, o.options.easing). 5192 animate(animation, speed / 2, o.options.easing, function(){ // Last shake 5193 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore 5194 if(o.callback) o.callback.apply(this, arguments); // Callback 5195 }); 5196 el.queue('fx', function() { el.dequeue(); }); 5197 el.dequeue(); 5198 }); 5199 5200}; 5201 5202})(jQuery); 5203 5204(function( $, undefined ) { 5205 5206$.effects.slide = function(o) { 5207 5208 return this.queue(function() { 5209 5210 // Create element 5211 var el = $(this), props = ['position','top','bottom','left','right']; 5212 5213 // Set options 5214 var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode 5215 var direction = o.options.direction || 'left'; // Default Direction 5216 5217 // Adjust 5218 $.effects.save(el, props); el.show(); // Save & Show 5219 $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper 5220 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left'; 5221 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg'; 5222 var distance = o.options.distance || (ref == 'top' ? el.outerHeight( true ) : el.outerWidth( true )); 5223 if (mode == 'show') el.css(ref, motion == 'pos' ? (isNaN(distance) ? "-" + distance : -distance) : distance); // Shift 5224 5225 // Animation 5226 var animation = {}; 5227 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance; 5228 5229 // Animate 5230 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() { 5231 if(mode == 'hide') el.hide(); // Hide 5232 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore 5233 if(o.callback) o.callback.apply(this, arguments); // Callback 5234 el.dequeue(); 5235 }}); 5236 5237 }); 5238 5239}; 5240 5241})(jQuery); 5242 5243(function( $, undefined ) { 5244 5245$.effects.transfer = function(o) { 5246 return this.queue(function() { 5247 var elem = $(this), 5248 target = $(o.options.to), 5249 endPosition = target.offset(), 5250 animation = { 5251 top: endPosition.top, 5252 left: endPosition.left, 5253 height: target.innerHeight(), 5254 width: target.innerWidth() 5255 }, 5256 startPosition = elem.offset(), 5257 transfer = $('<div class="ui-effects-transfer"></div>') 5258 .appendTo(document.body) 5259 .addClass(o.options.className) 5260 .css({ 5261 top: startPosition.top, 5262 left: startPosition.left,
5263 height: elem.innerHeight(), 5264 width: elem.innerWidth(), 5265 position: 'absolute' 5266 }) 5267 .animate(animation, o.duration, o.options.easing, function() { 5268 transfer.remove(); 5269 (o.callback && o.callback.apply(elem[0], arguments)); 5270 elem.dequeue(); 5271 }); 5272 }); 5273}; 5274 5275})(jQuery); 5276 5277(function( $, undefined ) { 5278 5279$.widget( "ui.accordion", { 5280 options: { 5281 active: 0, 5282 animated: "slide", 5283 autoHeight: true, 5284 clearStyle: false, 5285 collapsible: false, 5286 event: "click", 5287 fillSpace: false, 5288 header: "> li > :first-child,> :not(li):even", 5289 icons: { 5290 header: "ui-icon-triangle-1-e", 5291 headerSelected: "ui-icon-triangle-1-s" 5292 }, 5293 navigation: false, 5294 navigationFilter: function() { 5295 return this.href.toLowerCase() === location.href.toLowerCase(); 5296 } 5297 }, 5298 5299 _create: function() { 5300 var self = this, 5301 options = self.options; 5302 5303 self.running = 0; 5304 5305 self.element 5306 .addClass( "ui-accordion ui-widget ui-helper-reset" ) 5307 // in lack of child-selectors in CSS 5308 // we need to mark top-LIs in a UL-accordion for some IE-fix 5309 .children( "li" ) 5310 .addClass( "ui-accordion-li-fix" ); 5311 5312 self.headers = self.element.find( options.header ) 5313 .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ) 5314 .bind( "mouseenter.accordion", function() { 5315 if ( options.disabled ) { 5316 return; 5317 } 5318 $( this ).addClass( "ui-state-hover" ); 5319 }) 5320 .bind( "mouseleave.accordion", function() { 5321 if ( options.disabled ) { 5322 return; 5323 } 5324 $( this ).removeClass( "ui-state-hover" ); 5325 }) 5326 .bind( "focus.accordion", function() { 5327 if ( options.disabled ) { 5328 return; 5329 } 5330 $( this ).addClass( "ui-state-focus" ); 5331 }) 5332 .bind( "blur.accordion", function() { 5333 if ( options.disabled ) { 5334 return; 5335 } 5336 $( this ).removeClass( "ui-state-focus" ); 5337 }); 5338 5339 self.headers.next() 5340 .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ); 5341 5342 if ( options.navigation ) { 5343 var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 ); 5344 if ( current.length ) { 5345 var header = current.closest( ".ui-accordion-header" ); 5346 if ( header.length ) { 5347 // anchor within header 5348 self.active = header; 5349 } else { 5350 // anchor within content 5351 self.active = current.closest( ".ui-accordion-content" ).prev(); 5352 } 5353 } 5354 } 5355 5356 self.active = self._findActive( self.active || options.active ) 5357 .addClass( "ui-state-default ui-state-active" ) 5358 .toggleClass( "ui-corner-all" ) 5359 .toggleClass( "ui-corner-top" ); 5360 self.active.next().addClass( "ui-accordion-content-active" ); 5361 5362 self._createIcons(); 5363 self.resize(); 5364 5365 // ARIA 5366 self.element.attr( "role", "tablist" ); 5367 5368 self.headers 5369 .attr( "role", "tab" ) 5370 .bind( "keydown.accordion", function( event ) { 5371 return self._keydown( event ); 5372 }) 5373 .next() 5374 .attr( "role", "tabpanel" ); 5375 5376 self.headers 5377 .not( self.active || "" ) 5378 .attr({ 5379 "aria-expanded": "false", 5380 "aria-selected": "false", 5381 tabIndex: -1 5382 }) 5383 .next() 5384 .hide(); 5385 5386 // make sure at least one header is in the tab order 5387 if ( !self.active.length ) { 5388 self.headers.eq( 0 ).attr( "tabIndex", 0 ); 5389 } else { 5390 self.active 5391 .attr({ 5392 "aria-expanded": "true", 5393 "aria-selected": "true", 5394 tabIndex: 0 5395 }); 5396 } 5397 5398 // only need links in tab order for Safari 5399 if ( !$.browser.safari ) { 5400 self.headers.find( "a" ).attr( "tabIndex", -1 ); 5401 } 5402 5403 if ( options.event ) { 5404 self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) { 5405 self._clickHandler.call( self, event, this ); 5406 event.preventDefault(); 5407 }); 5408 } 5409 }, 5410 5411 _createIcons: function() { 5412 var options = this.options; 5413 if ( options.icons ) { 5414 $( "<span></span>" ) 5415 .addClass( "ui-icon " + options.icons.header ) 5416 .prependTo( this.headers ); 5417 this.active.children( ".ui-icon" ) 5418 .toggleClass(options.icons.header) 5419 .toggleClass(options.icons.headerSelected); 5420 this.element.addClass( "ui-accordion-icons" ); 5421 } 5422 }, 5423 5424 _destroyIcons: function() { 5425 this.headers.children( ".ui-icon" ).remove(); 5426 this.element.removeClass( "ui-accordion-icons" ); 5427 }, 5428 5429 destroy: function() { 5430 var options = this.options; 5431 5432 this.element 5433 .removeClass( "ui-accordion ui-widget ui-helper-reset" ) 5434 .removeAttr( "role" ); 5435 5436 this.headers 5437 .unbind( ".accordion" ) 5438 .removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" ) 5439 .removeAttr( "role" ) 5440 .removeAttr( "aria-expanded" ) 5441 .removeAttr( "aria-selected" ) 5442 .removeAttr( "tabIndex" ); 5443 5444 this.headers.find( "a" ).removeAttr( "tabIndex" ); 5445 this._destroyIcons(); 5446 var contents = this.headers.next() 5447 .css( "display", "" ) 5448 .removeAttr( "role" ) 5449 .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" ); 5450 if ( options.autoHeight || options.fillHeight ) { 5451 contents.css( "height", "" ); 5452 } 5453 5454 return $.Widget.prototype.destroy.call( this ); 5455 }, 5456 5457 _setOption: function( key, value ) { 5458 $.Widget.prototype._setOption.apply( this, arguments ); 5459 5460 if ( key == "active" ) { 5461 this.activate( value ); 5462 } 5463 if ( key == "icons" ) { 5464 this._destroyIcons(); 5465 if ( value ) { 5466 this._createIcons(); 5467 } 5468 } 5469 // #5332 - opacity doesn't cascade to positioned elements in IE 5470 // so we need to add the disabled class to the headers and panels 5471 if ( key == "disabled" ) { 5472 this.headers.add(this.headers.next()) 5473 [ value ? "addClass" : "removeClass" ]( 5474 "ui-accordion-disabled ui-state-disabled" ); 5475 } 5476 }, 5477 5478 _keydown: function( event ) { 5479 if ( this.options.disabled || event.altKey || event.ctrlKey ) { 5480 return; 5481 } 5482 5483 var keyCode = $.ui.keyCode, 5484 length = this.headers.length, 5485 currentIndex = this.headers.index( event.target ), 5486 toFocus = false;
5487 5488 switch ( event.keyCode ) { 5489 case keyCode.RIGHT: 5490 case keyCode.DOWN: 5491 toFocus = this.headers[ ( currentIndex + 1 ) % length ]; 5492 break; 5493 case keyCode.LEFT: 5494 case keyCode.UP: 5495 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; 5496 break; 5497 case keyCode.SPACE: 5498 case keyCode.ENTER: 5499 this._clickHandler( { target: event.target }, event.target ); 5500 event.preventDefault(); 5501 } 5502 5503 if ( toFocus ) { 5504 $( event.target ).attr( "tabIndex", -1 ); 5505 $( toFocus ).attr( "tabIndex", 0 ); 5506 toFocus.focus(); 5507 return false; 5508 } 5509 5510 return true; 5511 }, 5512 5513 resize: function() { 5514 var options = this.options, 5515 maxHeight; 5516 5517 if ( options.fillSpace ) { 5518 if ( $.browser.msie ) { 5519 var defOverflow = this.element.parent().css( "overflow" ); 5520 this.element.parent().css( "overflow", "hidden"); 5521 } 5522 maxHeight = this.element.parent().height(); 5523 if ($.browser.msie) { 5524 this.element.parent().css( "overflow", defOverflow ); 5525 } 5526 5527 this.headers.each(function() { 5528 maxHeight -= $( this ).outerHeight( true ); 5529 }); 5530 5531 this.headers.next() 5532 .each(function() { 5533 $( this ).height( Math.max( 0, maxHeight - 5534 $( this ).innerHeight() + $( this ).height() ) ); 5535 }) 5536 .css( "overflow", "auto" ); 5537 } else if ( options.autoHeight ) { 5538 maxHeight = 0; 5539 this.headers.next() 5540 .each(function() { 5541 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); 5542 }) 5543 .height( maxHeight ); 5544 } 5545 5546 return this; 5547 }, 5548 5549 activate: function( index ) { 5550 // TODO this gets called on init, changing the option without an explicit call for that 5551 this.options.active = index; 5552 // call clickHandler with custom event 5553 var active = this._findActive( index )[ 0 ]; 5554 this._clickHandler( { target: active }, active ); 5555 5556 return this; 5557 }, 5558 5559 _findActive: function( selector ) { 5560 return selector 5561 ? typeof selector === "number" 5562 ? this.headers.filter( ":eq(" + selector + ")" ) 5563 : this.headers.not( this.headers.not( selector ) ) 5564 : selector === false 5565 ? $( [] ) 5566 : this.headers.filter( ":eq(0)" ); 5567 }, 5568 5569 // TODO isn't event.target enough? why the separate target argument? 5570 _clickHandler: function( event, target ) { 5571 var options = this.options; 5572 if ( options.disabled ) { 5573 return; 5574 } 5575 5576 // called only when using activate(false) to close all parts programmatically 5577 if ( !event.target ) { 5578 if ( !options.collapsible ) { 5579 return; 5580 } 5581 this.active 5582 .removeClass( "ui-state-active ui-corner-top" ) 5583 .addClass( "ui-state-default ui-corner-all" ) 5584 .children( ".ui-icon" ) 5585 .removeClass( options.icons.headerSelected ) 5586 .addClass( options.icons.header ); 5587 this.active.next().addClass( "ui-accordion-content-active" ); 5588 var toHide = this.active.next(), 5589 data = { 5590 options: options, 5591 newHeader: $( [] ), 5592 oldHeader: options.active, 5593 newContent: $( [] ), 5594 oldContent: toHide 5595 }, 5596 toShow = ( this.active = $( [] ) ); 5597 this._toggle( toShow, toHide, data ); 5598 return; 5599 } 5600 5601 // get the click target 5602 var clicked = $( event.currentTarget || target ), 5603 clickedIsActive = clicked[0] === this.active[0]; 5604 5605 // TODO the option is changed, is that correct? 5606 // TODO if it is correct, shouldn't that happen after determining that the click is valid? 5607 options.active = options.collapsible && clickedIsActive ? 5608 false : 5609 this.headers.index( clicked ); 5610 5611 // if animations are still active, or the active header is the target, ignore click 5612 if ( this.running || ( !options.collapsible && clickedIsActive ) ) { 5613 return; 5614 } 5615 5616 // find elements to show and hide 5617 var active = this.active, 5618 toShow = clicked.next(), 5619 toHide = this.active.next(), 5620 data = { 5621 options: options, 5622 newHeader: clickedIsActive && options.collapsible ? $([]) : clicked, 5623 oldHeader: this.active, 5624 newContent: clickedIsActive && options.collapsible ? $([]) : toShow, 5625 oldContent: toHide 5626 }, 5627 down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] ); 5628 5629 // when the call to ._toggle() comes after the class changes 5630 // it causes a very odd bug in IE 8 (see #6720) 5631 this.active = clickedIsActive ? $([]) : clicked; 5632 this._toggle( toShow, toHide, data, clickedIsActive, down ); 5633 5634 // switch classes 5635 active 5636 .removeClass( "ui-state-active ui-corner-top" ) 5637 .addClass( "ui-state-default ui-corner-all" ) 5638 .children( ".ui-icon" ) 5639 .removeClass( options.icons.headerSelected )
5640 .addClass( options.icons.header ); 5641 if ( !clickedIsActive ) { 5642 clicked 5643 .removeClass( "ui-state-default ui-corner-all" ) 5644 .addClass( "ui-state-active ui-corner-top" ) 5645 .children( ".ui-icon" ) 5646 .removeClass( options.icons.header ) 5647 .addClass( options.icons.headerSelected ); 5648 clicked 5649 .next() 5650 .addClass( "ui-accordion-content-active" ); 5651 } 5652 5653 return; 5654 }, 5655 5656 _toggle: function( toShow, toHide, data, clickedIsActive, down ) { 5657 var self = this, 5658 options = self.options; 5659 5660 self.toShow = toShow; 5661 self.toHide = toHide; 5662 self.data = data; 5663 5664 var complete = function() { 5665 if ( !self ) { 5666 return; 5667 } 5668 return self._completed.apply( self, arguments ); 5669 }; 5670 5671 // trigger changestart event 5672 self._trigger( "changestart", null, self.data ); 5673 5674 // count elements to animate 5675 self.running = toHide.size() === 0 ? toShow.size() : toHide.size(); 5676 5677 if ( options.animated ) { 5678 var animOptions = {}; 5679 5680 if ( options.collapsible && clickedIsActive ) { 5681 animOptions = { 5682 toShow: $( [] ), 5683 toHide: toHide, 5684 complete: complete, 5685 down: down, 5686 autoHeight: options.autoHeight || options.fillSpace 5687 }; 5688 } else { 5689 animOptions = { 5690 toShow: toShow, 5691 toHide: toHide, 5692 complete: complete, 5693 down: down, 5694 autoHeight: options.autoHeight || options.fillSpace 5695 }; 5696 } 5697 5698 if ( !options.proxied ) { 5699 options.proxied = options.animated; 5700 } 5701 5702 if ( !options.proxiedDuration ) { 5703 options.proxiedDuration = options.duration; 5704 } 5705 5706 options.animated = $.isFunction( options.proxied ) ? 5707 options.proxied( animOptions ) : 5708 options.proxied; 5709 5710 options.duration = $.isFunction( options.proxiedDuration ) ? 5711 options.proxiedDuration( animOptions ) : 5712 options.proxiedDuration; 5713 5714 var animations = $.ui.accordion.animations, 5715 duration = options.duration, 5716 easing = options.animated; 5717 5718 if ( easing && !animations[ easing ] && !$.easing[ easing ] ) { 5719 easing = "slide"; 5720 } 5721 if ( !animations[ easing ] ) { 5722 animations[ easing ] = function( options ) { 5723 this.slide( options, { 5724 easing: easing, 5725 duration: duration || 700 5726 }); 5727 }; 5728 } 5729 5730 animations[ easing ]( animOptions ); 5731 } else { 5732 if ( options.collapsible && clickedIsActive ) { 5733 toShow.toggle(); 5734 } else { 5735 toHide.hide(); 5736 toShow.show(); 5737 } 5738 5739 complete( true ); 5740 } 5741 5742 // TODO assert that the blur and focus triggers are really necessary, remove otherwise 5743 toHide.prev() 5744 .attr({ 5745 "aria-expanded": "false", 5746 "aria-selected": "false", 5747 tabIndex: -1 5748 }) 5749 .blur(); 5750 toShow.prev() 5751 .attr({ 5752 "aria-expanded": "true", 5753 "aria-selected": "true", 5754 tabIndex: 0 5755 }) 5756 .focus(); 5757 }, 5758 5759 _completed: function( cancel ) { 5760 this.running = cancel ? 0 : --this.running; 5761 if ( this.running ) { 5762 return; 5763 } 5764 5765 if ( this.options.clearStyle ) { 5766 this.toShow.add( this.toHide ).css({ 5767 height: "", 5768 overflow: "" 5769 }); 5770 } 5771 5772 // other classes are removed before the animation; this one needs to stay until completed 5773 this.toHide.removeClass( "ui-accordion-content-active" ); 5774 // Work around for rendering bug in IE (#5421) 5775 if ( this.toHide.length ) { 5776 this.toHide.parent()[0].className = this.toHide.parent()[0].className; 5777 } 5778 5779 this._trigger( "change", null, this.data ); 5780 } 5781}); 5782 5783$.extend( $.ui.accordion, { 5784 version: "1.8.24", 5785 animations: { 5786 slide: function( options, additions ) { 5787 options = $.extend({ 5788 easing: "swing", 5789 duration: 300 5790 }, options, additions ); 5791 if ( !options.toHide.size() ) { 5792 options.toShow.animate({ 5793 height: "show", 5794 paddingTop: "show", 5795 paddingBottom: "show" 5796 }, options ); 5797 return; 5798 } 5799 if ( !options.toShow.size() ) { 5800 options.toHide.animate({ 5801 height: "hide", 5802 paddingTop: "hide", 5803 paddingBottom: "hide" 5804 }, options ); 5805 return; 5806 } 5807 var overflow = options.toShow.css( "overflow" ), 5808 percentDone = 0, 5809 showProps = {}, 5810 hideProps = {}, 5811 fxAttrs = [ "height", "paddingTop", "paddingBottom" ], 5812 originalWidth; 5813 // fix width before calculating height of hidden element 5814 var s = options.toShow; 5815 originalWidth = s[0].style.width; 5816 s.width( s.parent().width() 5817 - parseFloat( s.css( "paddingLeft" ) ) 5818 - parseFloat( s.css( "paddingRight" ) ) 5819 - ( parseFloat( s.css( "borderLeftWidth" ) ) || 0 ) 5820 - ( parseFloat( s.css( "borderRightWidth" ) ) || 0 ) ); 5821 5822 $.each( fxAttrs, function( i, prop ) { 5823 hideProps[ prop ] = "hide"; 5824 5825 var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ ); 5826 showProps[ prop ] = { 5827 value: parts[ 1 ], 5828 unit: parts[ 2 ] || "px" 5829 }; 5830 }); 5831 options.toShow.css({ height: 0, overflow: "hidden" }).show(); 5832 options.toHide 5833 .filter( ":hidden" ) 5834 .each( options.complete ) 5835 .end() 5836 .filter( ":visible" ) 5837 .animate( hideProps, { 5838 step: function( now, settings ) { 5839 // only calculate the percent when animating height 5840 // IE gets very inconsistent results when animating elements 5841 // with small values, which is common for padding 5842 if ( settings.prop == "height" ) { 5843 percentDone = ( settings.end - settings.start === 0 ) ? 0 : 5844 ( settings.now - settings.start ) / ( settings.end - settings.start ); 5845 } 5846 5847 options.toShow[ 0 ].style[ settings.prop ] = 5848 ( percentDone * showProps[ settings.prop ].value ) 5849 + showProps[ settings.prop ].unit; 5850 }, 5851 duration: options.duration, 5852 easing: options.easing, 5853 complete: function() { 5854 if ( !options.autoHeight ) { 5855 options.toShow.css( "height", "" ); 5856 } 5857 options.toShow.css({ 5858 width: originalWidth, 5859 overflow: overflow 5860 }); 5861 options.complete(); 5862 } 5863 }); 5864 }, 5865 bounceslide: function( options ) { 5866 this.slide( options, { 5867 easing: options.down ? "easeOutBounce" : "swing", 5868 duration: options.down ? 1000 : 200 5869 }); 5870 } 5871 } 5872}); 5873 5874})( jQuery ); 5875 5876(function( $, undefined ) { 5877 5878// used to prevent race conditions with remote data sources 5879var requestIndex = 0; 5880 5881$.widget( "ui.autocomplete", { 5882 options: { 5883 appendTo: "body", 5884 autoFocus: false, 5885 delay: 300, 5886 minLength: 1, 5887 position: { 5888 my: "left top", 5889 at: "left bottom", 5890 collision: "none" 5891 }, 5892 source: null 5893 }, 5894 5895 pending: 0, 5896 5897 _create: function() { 5898 var self = this, 5899 doc = this.element[ 0 ].ownerDocument, 5900 suppressKeyPress; 5901 this.isMultiLine = this.element.is( "textarea" ); 5902 5903 this.element 5904 .addClass( "ui-autocomplete-input" ) 5905 .attr( "autocomplete", "off" ) 5906 // TODO verify these actually work as intended 5907 .attr({ 5908 role: "textbox", 5909 "aria-autocomplete": "list", 5910 "aria-haspopup": "true" 5911 }) 5912 .bind( "keydown.autocomplete", function( event ) { 5913 if ( self.options.disabled || self.element.propAttr( "readOnly" ) ) { 5914 return; 5915 } 5916 5917 suppressKeyPress = false;
5918 var keyCode = $.ui.keyCode; 5919 switch( event.keyCode ) { 5920 case keyCode.PAGE_UP: 5921 self._move( "previousPage", event ); 5922 break; 5923 case keyCode.PAGE_DOWN: 5924 self._move( "nextPage", event ); 5925 break; 5926 case keyCode.UP: 5927 self._keyEvent( "previous", event ); 5928 break; 5929 case keyCode.DOWN: 5930 self._keyEvent( "next", event ); 5931 break; 5932 case keyCode.ENTER: 5933 case keyCode.NUMPAD_ENTER: 5934 // when menu is open and has focus 5935 if ( self.menu.active ) { 5936 // #6055 - Opera still allows the keypress to occur 5937 // which causes forms to submit 5938 suppressKeyPress = true; 5939 event.preventDefault(); 5940 } 5941 //passthrough - ENTER and TAB both select the current element 5942 case keyCode.TAB: 5943 if ( !self.menu.active ) { 5944 return; 5945 } 5946 self.menu.select( event ); 5947 break; 5948 case keyCode.ESCAPE: 5949 self.element.val( self.term ); 5950 self.close( event ); 5951 break; 5952 default: 5953 // keypress is triggered before the input value is changed 5954 clearTimeout( self.searching ); 5955 self.searching = setTimeout(function() { 5956 // only search if the value has changed 5957 if ( self.term != self.element.val() ) { 5958 self.selectedItem = null; 5959 self.search( null, event ); 5960 } 5961 }, self.options.delay ); 5962 break; 5963 } 5964 }) 5965 .bind( "keypress.autocomplete", function( event ) { 5966 if ( suppressKeyPress ) { 5967 suppressKeyPress = false; 5968 event.preventDefault(); 5969 } 5970 }) 5971 .bind( "focus.autocomplete", function() { 5972 if ( self.options.disabled ) { 5973 return; 5974 } 5975 5976 self.selectedItem = null; 5977 self.previous = self.element.val(); 5978 }) 5979 .bind( "blur.autocomplete", function( event ) { 5980 if ( self.options.disabled ) { 5981 return; 5982 } 5983 5984 clearTimeout( self.searching ); 5985 // clicks on the menu (or a button to trigger a search) will cause a blur event 5986 self.closing = setTimeout(function() { 5987 self.close( event ); 5988 self._change( event ); 5989 }, 150 ); 5990 }); 5991 this._initSource(); 5992 this.menu = $( "<ul></ul>" ) 5993 .addClass( "ui-autocomplete" ) 5994 .appendTo( $( this.options.appendTo || "body", doc )[0] ) 5995 // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown) 5996 .mousedown(function( event ) { 5997 // clicking on the scrollbar causes focus to shift to the body 5998 // but we can't detect a mouseup or a click immediately afterward 5999 // so we have to track the next mousedown and close the menu if 6000 // the user clicks somewhere outside of the autocomplete 6001 var menuElement = self.menu.element[ 0 ]; 6002 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { 6003 setTimeout(function() { 6004 $( document ).one( 'mousedown', function( event ) { 6005 if ( event.target !== self.element[ 0 ] && 6006 event.target !== menuElement && 6007 !$.ui.contains( menuElement, event.target ) ) { 6008 self.close(); 6009 } 6010 }); 6011 }, 1 ); 6012 } 6013 6014 // use another timeout to make sure the blur-event-handler on the input was already triggered 6015 setTimeout(function() { 6016 clearTimeout( self.closing ); 6017 }, 13); 6018 }) 6019 .menu({ 6020 focus: function( event, ui ) { 6021 var item = ui.item.data( "item.autocomplete" ); 6022 if ( false !== self._trigger( "focus", event, { item: item } ) ) { 6023 // use value to match what will end up in the input, if it was a key event 6024 if ( /^key/.test(event.originalEvent.type) ) { 6025 self.element.val( item.value ); 6026 } 6027 } 6028 }, 6029 selected: function( event, ui ) { 6030 var item = ui.item.data( "item.autocomplete" ), 6031 previous = self.previous; 6032 6033 // only trigger when focus was lost (click on menu) 6034 if ( self.element[0] !== doc.activeElement ) { 6035 self.element.focus(); 6036 self.previous = previous; 6037 // #6109 - IE triggers two focus events and the second 6038 // is asynchronous, so we need to reset the previous 6039 // term synchronously and asynchronously :-( 6040 setTimeout(function() { 6041 self.previous = previous; 6042 self.selectedItem = item; 6043 }, 1); 6044 } 6045 6046 if ( false !== self._trigger( "select", event, { item: item } ) ) { 6047 self.element.val( item.value ); 6048 } 6049 // reset the term after the select event 6050 // this allows custom select handling to work properly 6051 self.term = self.element.val(); 6052 6053 self.close( event ); 6054 self.selectedItem = item; 6055 }, 6056 blur: function( event, ui ) { 6057 // don't set the value of the text field if it's already correct 6058 // this prevents moving the cursor unnecessarily 6059 if ( self.menu.element.is(":visible") && 6060 ( self.element.val() !== self.term ) ) { 6061 self.element.val( self.term ); 6062 } 6063 } 6064 }) 6065 .zIndex( this.element.zIndex() + 1 ) 6066 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781 6067 .css({ top: 0, left: 0 }) 6068 .hide() 6069 .data( "menu" ); 6070 if ( $.fn.bgiframe ) { 6071 this.menu.element.bgiframe(); 6072 } 6073 // turning off autocomplete prevents the browser from remembering the 6074 // value when navigating through history, so we re-enable autocomplete 6075 // if the page is unloaded before the widget is destroyed. #7790 6076 self.beforeunloadHandler = function() { 6077 self.element.removeAttr( "autocomplete" ); 6078 }; 6079 $( window ).bind( "beforeunload", self.beforeunloadHandler ); 6080 }, 6081 6082 destroy: function() { 6083 this.element 6084 .removeClass( "ui-autocomplete-input" ) 6085 .removeAttr( "autocomplete" ) 6086 .removeAttr( "role" ) 6087 .removeAttr( "aria-autocomplete" ) 6088 .removeAttr( "aria-haspopup" ); 6089 this.menu.element.remove(); 6090 $( window ).unbind( "beforeunload", this.beforeunloadHandler ); 6091 $.Widget.prototype.destroy.call( this ); 6092 }, 6093 6094 _setOption: function( key, value ) { 6095 $.Widget.prototype._setOption.apply( this, arguments ); 6096 if ( key === "source" ) { 6097 this._initSource(); 6098 } 6099 if ( key === "appendTo" ) { 6100 this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] ) 6101 } 6102 if ( key === "disabled" && value && this.xhr ) { 6103 this.xhr.abort(); 6104 } 6105 }, 6106 6107 _initSource: function() { 6108 var self = this, 6109 array, 6110 url; 6111 if ( $.isArray(this.options.source) ) { 6112 array = this.options.source; 6113 this.source = function( request, response ) { 6114 response( $.ui.autocomplete.filter(array, request.term) ); 6115 }; 6116 } else if ( typeof this.options.source === "string" ) { 6117 url = this.options.source; 6118 this.source = function( request, response ) { 6119 if ( self.xhr ) { 6120 self.xhr.abort(); 6121 } 6122 self.xhr = $.ajax({ 6123 url: url, 6124 data: request, 6125 dataType: "json", 6126 success: function( data, status ) { 6127 response( data ); 6128 }, 6129 error: function() { 6130 response( [] ); 6131 } 6132 }); 6133 }; 6134 } else { 6135 this.source = this.options.source; 6136 } 6137 }, 6138 6139 search: function( value, event ) { 6140 value = value != null ? value : this.element.val(); 6141 6142 // always save the actual value, not the one passed as an argument 6143 this.term = this.element.val(); 6144 6145 if ( value.length < this.options.minLength ) { 6146 return this.close( event ); 6147 } 6148 6149 clearTimeout( this.closing ); 6150 if ( this._trigger( "search", event ) === false ) { 6151 return; 6152 } 6153 6154 return this._search( value ); 6155 }, 6156 6157 _search: function( value ) { 6158 this.pending++; 6159 this.element.addClass( "ui-autocomplete-loading" ); 6160 6161 this.source( { term: value }, this._response() ); 6162 }, 6163 6164 _response: function() { 6165 var that = this, 6166 index = ++requestIndex; 6167 6168 return function( content ) { 6169 if ( index === requestIndex ) { 6170 that.__response( content ); 6171 } 6172 6173 that.pending--; 6174 if ( !that.pending ) { 6175 that.element.removeClass( "ui-autocomplete-loading" ); 6176 } 6177 }; 6178 }, 6179 6180 __response: function( content ) { 6181 if ( !this.options.disabled && content && content.length ) { 6182 content = this._normalize( content ); 6183 this._suggest( content ); 6184 this._trigger( "open" ); 6185 } else { 6186 this.close(); 6187 } 6188 }, 6189 6190 close: function( event ) { 6191 clearTimeout( this.closing ); 6192 if ( this.menu.element.is(":visible") ) { 6193 this.menu.element.hide(); 6194 this.menu.deactivate(); 6195 this._trigger( "close", event ); 6196 } 6197 }, 6198 6199 _change: function( event ) { 6200 if ( this.previous !== this.element.val() ) { 6201 this._trigger( "change", event, { item: this.selectedItem } ); 6202 } 6203 }, 6204 6205 _normalize: function( items ) { 6206 // assume all items have the right format when the first item is complete 6207 if ( items.length && items[0].label && items[0].value ) { 6208 return items; 6209 } 6210 return $.map( items, function(item) { 6211 if ( typeof item === "string" ) { 6212 return { 6213 label: item, 6214 value: item 6215 }; 6216 } 6217 return $.extend({ 6218 label: item.label || item.value, 6219 value: item.value || item.label 6220 }, item ); 6221 }); 6222 }, 6223 6224 _suggest: function( items ) { 6225 var ul = this.menu.element 6226 .empty() 6227 .zIndex( this.element.zIndex() + 1 ); 6228 this._renderMenu( ul, items ); 6229 // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate 6230 this.menu.deactivate(); 6231 this.menu.refresh(); 6232 6233 // size and position menu 6234 ul.show(); 6235 this._resizeMenu(); 6236 ul.position( $.extend({ 6237 of: this.element 6238 }, this.options.position )); 6239 6240 if ( this.options.autoFocus ) { 6241 this.menu.next( new $.Event("mouseover") ); 6242 } 6243 }, 6244 6245 _resizeMenu: function() { 6246 var ul = this.menu.element; 6247 ul.outerWidth( Math.max( 6248 // Firefox wraps long text (possibly a rounding bug) 6249 // so we add 1px to avoid the wrapping (#7513) 6250 ul.width( "" ).outerWidth() + 1, 6251 this.element.outerWidth() 6252 ) ); 6253 }, 6254 6255 _renderMenu: function( ul, items ) { 6256 var self = this; 6257 $.each( items, function( index, item ) { 6258 self._renderItem( ul, item ); 6259 }); 6260 }, 6261 6262 _renderItem: function( ul, item) { 6263 return $( "<li></li>" ) 6264 .data( "item.autocomplete", item ) 6265 .append( $( "<a></a>" ).text( item.label ) ) 6266 .appendTo( ul ); 6267 }, 6268 6269 _move: function( direction, event ) { 6270 if ( !this.menu.element.is(":visible") ) { 6271 this.search( null, event ); 6272 return; 6273 } 6274 if ( this.menu.first() && /^previous/.test(direction) || 6275 this.menu.last() && /^next/.test(direction) ) { 6276 this.element.val( this.term ); 6277 this.menu.deactivate(); 6278 return; 6279 } 6280 this.menu[ direction ]( event ); 6281 }, 6282 6283 widget: function() { 6284 return this.menu.element; 6285 }, 6286 _keyEvent: function( keyEvent, event ) { 6287 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { 6288 this._move( keyEvent, event ); 6289 6290 // prevents moving cursor to beginning/end of the text field in some browsers 6291 event.preventDefault(); 6292 } 6293 } 6294}); 6295 6296$.extend( $.ui.autocomplete, { 6297 escapeRegex: function( value ) { 6298 return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); 6299 }, 6300 filter: function(array, term) { 6301 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); 6302 return $.grep( array, function(value) { 6303 return matcher.test( value.label || value.value || value ); 6304 }); 6305 } 6306}); 6307 6308}( jQuery )); 6309 6310/* 6311 * jQuery UI Menu (not officially released) 6312 * 6313 * This widget isn't yet finished and the API is subject to change. We plan to finish 6314 * it for the next release. You're welcome to give it a try anyway and give us feedback,
6315 * as long as you're okay with migrating your code later on. We can help with that, too. 6316 * 6317 * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) 6318 * Dual licensed under the MIT or GPL Version 2 licenses. 6319 * http://jquery.org/license 6320 * 6321 * http://docs.jquery.com/UI/Menu 6322 * 6323 * Depends: 6324 * jquery.ui.core.js 6325 * jquery.ui.widget.js 6326 */ 6327(function($) { 6328 6329$.widget("ui.menu", { 6330 _create: function() { 6331 var self = this; 6332 this.element 6333 .addClass("ui-menu ui-widget ui-widget-content ui-corner-all") 6334 .attr({ 6335 role: "listbox", 6336 "aria-activedescendant": "ui-active-menuitem" 6337 }) 6338 .click(function( event ) { 6339 if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) { 6340 return; 6341 } 6342 // temporary 6343 event.preventDefault(); 6344 self.select( event ); 6345 }); 6346 this.refresh(); 6347 }, 6348 6349 refresh: function() { 6350 var self = this; 6351 6352 // don't refresh list items that are already adapted 6353 var items = this.element.children("li:not(.ui-menu-item):has(a)") 6354 .addClass("ui-menu-item") 6355 .attr("role", "menuitem"); 6356 6357 items.children("a") 6358 .addClass("ui-corner-all") 6359 .attr("tabindex", -1) 6360 // mouseenter doesn't work with event delegation 6361 .mouseenter(function( event ) { 6362 self.activate( event, $(this).parent() ); 6363 }) 6364 .mouseleave(function() { 6365 self.deactivate(); 6366 }); 6367 }, 6368 6369 activate: function( event, item ) { 6370 this.deactivate(); 6371 if (this.hasScroll()) { 6372 var offset = item.offset().top - this.element.offset().top, 6373 scroll = this.element.scrollTop(), 6374 elementHeight = this.element.height(); 6375 if (offset < 0) { 6376 this.element.scrollTop( scroll + offset); 6377 } else if (offset >= elementHeight) { 6378 this.element.scrollTop( scroll + offset - elementHeight + item.height()); 6379 } 6380 } 6381 this.active = item.eq(0) 6382 .children("a") 6383 .addClass("ui-state-hover") 6384 .attr("id", "ui-active-menuitem") 6385 .end(); 6386 this._trigger("focus", event, { item: item }); 6387 }, 6388 6389 deactivate: function() { 6390 if (!this.active) { return; } 6391 6392 this.active.children("a") 6393 .removeClass("ui-state-hover") 6394 .removeAttr("id"); 6395 this._trigger("blur"); 6396 this.active = null; 6397 }, 6398 6399 next: function(event) { 6400 this.move("next", ".ui-menu-item:first", event); 6401 }, 6402 6403 previous: function(event) { 6404 this.move("prev", ".ui-menu-item:last", event); 6405 }, 6406 6407 first: function() { 6408 return this.active && !this.active.prevAll(".ui-menu-item").length; 6409 }, 6410 6411 last: function() { 6412 return this.active && !this.active.nextAll(".ui-menu-item").length; 6413 }, 6414 6415 move: function(direction, edge, event) { 6416 if (!this.active) { 6417 this.activate(event, this.element.children(edge)); 6418 return; 6419 } 6420 var next = this.active[direction + "All"](".ui-menu-item").eq(0); 6421 if (next.length) { 6422 this.activate(event, next); 6423 } else { 6424 this.activate(event, this.element.children(edge)); 6425 } 6426 }, 6427 6428 // TODO merge with previousPage 6429 nextPage: function(event) { 6430 if (this.hasScroll()) { 6431 // TODO merge with no-scroll-else 6432 if (!this.active || this.last()) { 6433 this.activate(event, this.element.children(".ui-menu-item:first")); 6434 return; 6435 } 6436 var base = this.active.offset().top, 6437 height = this.element.height(), 6438 result = this.element.children(".ui-menu-item").filter(function() { 6439 var close = $(this).offset().top - base - height + $(this).height(); 6440 // TODO improve approximation 6441 return close < 10 && close > -10; 6442 }); 6443 6444 // TODO try to catch this earlier when scrollTop indicates the last page anyway 6445 if (!result.length) { 6446 result = this.element.children(".ui-menu-item:last"); 6447 } 6448 this.activate(event, result); 6449 } else { 6450 this.activate(event, this.element.children(".ui-menu-item") 6451 .filter(!this.active || this.last() ? ":first" : ":last")); 6452 } 6453 }, 6454 6455 // TODO merge with nextPage 6456 previousPage: function(event) { 6457 if (this.hasScroll()) { 6458 // TODO merge with no-scroll-else 6459 if (!this.active || this.first()) { 6460 this.activate(event, this.element.children(".ui-menu-item:last")); 6461 return; 6462 } 6463 6464 var base = this.active.offset().top, 6465 height = this.element.height(), 6466 result = this.element.children(".ui-menu-item").filter(function() { 6467 var close = $(this).offset().top - base + height - $(this).height(); 6468 // TODO improve approximation 6469 return close < 10 && close > -10; 6470 }); 6471 6472 // TODO try to catch this earlier when scrollTop indicates the last page anyway 6473 if (!result.length) { 6474 result = this.element.children(".ui-menu-item:first"); 6475 } 6476 this.activate(event, result); 6477 } else { 6478 this.activate(event, this.element.children(".ui-menu-item") 6479 .filter(!this.active || this.first() ? ":last" : ":first")); 6480 } 6481 }, 6482 6483 hasScroll: function() { 6484 return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight"); 6485 }, 6486 6487 select: function( event ) { 6488 this._trigger("selected", event, { item: this.active }); 6489 } 6490}); 6491 6492}(jQuery)); 6493 6494(function( $, undefined ) { 6495 6496var lastActive, startXPos, startYPos, clickDragged, 6497 baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", 6498 stateClasses = "ui-state-hover ui-state-active ", 6499 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", 6500 formResetHandler = function() { 6501 var buttons = $( this ).find( ":ui-button" ); 6502 setTimeout(function() { 6503 buttons.button( "refresh" ); 6504 }, 1 ); 6505 }, 6506 radioGroup = function( radio ) { 6507 var name = radio.name, 6508 form = radio.form, 6509 radios = $( [] ); 6510 if ( name ) { 6511 if ( form ) { 6512 radios = $( form ).find( "[name='" + name + "']" ); 6513 } else { 6514 radios = $( "[name='" + name + "']", radio.ownerDocument ) 6515 .filter(function() { 6516 return !this.form; 6517 }); 6518 } 6519 } 6520 return radios; 6521 }; 6522 6523$.widget( "ui.button", { 6524 options: { 6525 disabled: null, 6526 text: true, 6527 label: null, 6528 icons: { 6529 primary: null, 6530 secondary: null 6531 } 6532 }, 6533 _create: function() { 6534 this.element.closest( "form" ) 6535 .unbind( "reset.button" ) 6536 .bind( "reset.button", formResetHandler ); 6537 6538 if ( typeof this.options.disabled !== "boolean" ) { 6539 this.options.disabled = !!this.element.propAttr( "disabled" ); 6540 } else { 6541 this.element.propAttr( "disabled", this.options.disabled ); 6542 } 6543 6544 this._determineButtonType(); 6545 this.hasTitle = !!this.buttonElement.attr( "title" ); 6546 6547 var self = this, 6548 options = this.options, 6549 toggleButton = this.type === "checkbox" || this.type === "radio", 6550 hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ), 6551 focusClass = "ui-state-focus"; 6552 6553 if ( options.label === null ) { 6554 options.label = this.buttonElement.html(); 6555 } 6556 6557 this.buttonElement 6558 .addClass( baseClasses ) 6559 .attr( "role", "button" ) 6560 .bind( "mouseenter.button", function() { 6561 if ( options.disabled ) { 6562 return; 6563 } 6564 $( this ).addClass( "ui-state-hover" ); 6565 if ( this === lastActive ) { 6566 $( this ).addClass( "ui-state-active" ); 6567 } 6568 }) 6569 .bind( "mouseleave.button", function() { 6570 if ( options.disabled ) { 6571 return; 6572 } 6573 $( this ).removeClass( hoverClass ); 6574 }) 6575 .bind( "click.button", function( event ) { 6576 if ( options.disabled ) { 6577 event.preventDefault(); 6578 event.stopImmediatePropagation(); 6579 } 6580 }); 6581 6582 this.element 6583 .bind( "focus.button", function() { 6584 // no need to check disabled, focus won't be triggered anyway 6585 self.buttonElement.addClass( focusClass ); 6586 }) 6587 .bind( "blur.button", function() { 6588 self.buttonElement.removeClass( focusClass ); 6589 }); 6590 6591 if ( toggleButton ) { 6592 this.element.bind( "change.button", function() { 6593 if ( clickDragged ) { 6594 return; 6595 } 6596 self.refresh(); 6597 }); 6598 // if mouse moves between mousedown and mouseup (drag) set clickDragged flag 6599 // prevents issue where button state changes but checkbox/radio checked state 6600 // does not in Firefox (see ticket #6970) 6601 this.buttonElement 6602 .bind( "mousedown.button", function( event ) { 6603 if ( options.disabled ) { 6604 return; 6605 } 6606 clickDragged = false;
vendor: 16,047 bytes, lines 6607-7033
6607 startXPos = event.pageX; 6608 startYPos = event.pageY; 6609 }) 6610 .bind( "mouseup.button", function( event ) { 6611 if ( options.disabled ) { 6612 return; 6613 } 6614 if ( startXPos !== event.pageX || startYPos !== event.pageY ) { 6615 clickDragged = true; 6616 } 6617 }); 6618 } 6619 6620 if ( this.type === "checkbox" ) { 6621 this.buttonElement.bind( "click.button", function() { 6622 if ( options.disabled || clickDragged ) { 6623 return false; 6624 } 6625 $( this ).toggleClass( "ui-state-active" ); 6626 self.buttonElement.attr( "aria-pressed", self.element[0].checked ); 6627 }); 6628 } else if ( this.type === "radio" ) { 6629 this.buttonElement.bind( "click.button", function() { 6630 if ( options.disabled || clickDragged ) { 6631 return false; 6632 } 6633 $( this ).addClass( "ui-state-active" ); 6634 self.buttonElement.attr( "aria-pressed", "true" ); 6635 6636 var radio = self.element[ 0 ]; 6637 radioGroup( radio ) 6638 .not( radio ) 6639 .map(function() { 6640 return $( this ).button( "widget" )[ 0 ]; 6641 }) 6642 .removeClass( "ui-state-active" ) 6643 .attr( "aria-pressed", "false" ); 6644 }); 6645 } else { 6646 this.buttonElement 6647 .bind( "mousedown.button", function() { 6648 if ( options.disabled ) { 6649 return false; 6650 } 6651 $( this ).addClass( "ui-state-active" ); 6652 lastActive = this; 6653 $( document ).one( "mouseup", function() { 6654 lastActive = null; 6655 }); 6656 }) 6657 .bind( "mouseup.button", function() { 6658 if ( options.disabled ) { 6659 return false; 6660 } 6661 $( this ).removeClass( "ui-state-active" ); 6662 }) 6663 .bind( "keydown.button", function(event) { 6664 if ( options.disabled ) { 6665 return false; 6666 } 6667 if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) { 6668 $( this ).addClass( "ui-state-active" ); 6669 } 6670 }) 6671 .bind( "keyup.button", function() { 6672 $( this ).removeClass( "ui-state-active" ); 6673 }); 6674 6675 if ( this.buttonElement.is("a") ) { 6676 this.buttonElement.keyup(function(event) { 6677 if ( event.keyCode === $.ui.keyCode.SPACE ) { 6678 // TODO pass through original event correctly (just as 2nd argument doesn't work) 6679 $( this ).click(); 6680 } 6681 }); 6682 } 6683 } 6684 6685 // TODO: pull out $.Widget's handling for the disabled option into 6686 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can 6687 // be overridden by individual plugins 6688 this._setOption( "disabled", options.disabled ); 6689 this._resetButton(); 6690 }, 6691 6692 _determineButtonType: function() { 6693 6694 if ( this.element.is(":checkbox") ) { 6695 this.type = "checkbox"; 6696 } else if ( this.element.is(":radio") ) { 6697 this.type = "radio"; 6698 } else if ( this.element.is("input") ) { 6699 this.type = "input"; 6700 } else { 6701 this.type = "button"; 6702 } 6703 6704 if ( this.type === "checkbox" || this.type === "radio" ) { 6705 // we don't search against the document in case the element 6706 // is disconnected from the DOM 6707 var ancestor = this.element.parents().filter(":last"), 6708 labelSelector = "label[for='" + this.element.attr("id") + "']"; 6709 this.buttonElement = ancestor.find( labelSelector ); 6710 if ( !this.buttonElement.length ) { 6711 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); 6712 this.buttonElement = ancestor.filter( labelSelector ); 6713 if ( !this.buttonElement.length ) { 6714 this.buttonElement = ancestor.find( labelSelector ); 6715 } 6716 } 6717 this.element.addClass( "ui-helper-hidden-accessible" ); 6718 6719 var checked = this.element.is( ":checked" ); 6720 if ( checked ) { 6721 this.buttonElement.addClass( "ui-state-active" ); 6722 } 6723 this.buttonElement.attr( "aria-pressed", checked ); 6724 } else { 6725 this.buttonElement = this.element; 6726 } 6727 }, 6728 6729 widget: function() { 6730 return this.buttonElement; 6731 }, 6732 6733 destroy: function() { 6734 this.element 6735 .removeClass( "ui-helper-hidden-accessible" ); 6736 this.buttonElement 6737 .removeClass( baseClasses + " " + stateClasses + " " + typeClasses ) 6738 .removeAttr( "role" ) 6739 .removeAttr( "aria-pressed" ) 6740 .html( this.buttonElement.find(".ui-button-text").html() ); 6741 6742 if ( !this.hasTitle ) { 6743 this.buttonElement.removeAttr( "title" ); 6744 } 6745 6746 $.Widget.prototype.destroy.call( this ); 6747 }, 6748 6749 _setOption: function( key, value ) { 6750 $.Widget.prototype._setOption.apply( this, arguments ); 6751 if ( key === "disabled" ) { 6752 if ( value ) { 6753 this.element.propAttr( "disabled", true ); 6754 } else { 6755 this.element.propAttr( "disabled", false ); 6756 } 6757 return; 6758 } 6759 this._resetButton(); 6760 }, 6761 6762 refresh: function() { 6763 var isDisabled = this.element.is( ":disabled" ); 6764 if ( isDisabled !== this.options.disabled ) { 6765 this._setOption( "disabled", isDisabled ); 6766 } 6767 if ( this.type === "radio" ) { 6768 radioGroup( this.element[0] ).each(function() { 6769 if ( $( this ).is( ":checked" ) ) { 6770 $( this ).button( "widget" ) 6771 .addClass( "ui-state-active" ) 6772 .attr( "aria-pressed", "true" ); 6773 } else { 6774 $( this ).button( "widget" ) 6775 .removeClass( "ui-state-active" ) 6776 .attr( "aria-pressed", "false" ); 6777 } 6778 }); 6779 } else if ( this.type === "checkbox" ) { 6780 if ( this.element.is( ":checked" ) ) { 6781 this.buttonElement 6782 .addClass( "ui-state-active" ) 6783 .attr( "aria-pressed", "true" ); 6784 } else { 6785 this.buttonElement 6786 .removeClass( "ui-state-active" ) 6787 .attr( "aria-pressed", "false" ); 6788 } 6789 } 6790 }, 6791 6792 _resetButton: function() { 6793 if ( this.type === "input" ) { 6794 if ( this.options.label ) { 6795 this.element.val( this.options.label ); 6796 } 6797 return; 6798 } 6799 var buttonElement = this.buttonElement.removeClass( typeClasses ), 6800 buttonText = $( "<span></span>", this.element[0].ownerDocument ) 6801 .addClass( "ui-button-text" ) 6802 .html( this.options.label ) 6803 .appendTo( buttonElement.empty() ) 6804 .text(), 6805 icons = this.options.icons, 6806 multipleIcons = icons.primary && icons.secondary, 6807 buttonClasses = []; 6808 6809 if ( icons.primary || icons.secondary ) { 6810 if ( this.options.text ) { 6811 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) ); 6812 } 6813 6814 if ( icons.primary ) { 6815 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" ); 6816 } 6817 6818 if ( icons.secondary ) { 6819 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" ); 6820 } 6821 6822 if ( !this.options.text ) { 6823 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" ); 6824 6825 if ( !this.hasTitle ) { 6826 buttonElement.attr( "title", buttonText ); 6827 } 6828 } 6829 } else { 6830 buttonClasses.push( "ui-button-text-only" ); 6831 } 6832 buttonElement.addClass( buttonClasses.join( " " ) ); 6833 } 6834}); 6835 6836$.widget( "ui.buttonset", { 6837 options: { 6838 items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" 6839 }, 6840 6841 _create: function() { 6842 this.element.addClass( "ui-buttonset" ); 6843 }, 6844 6845 _init: function() { 6846 this.refresh(); 6847 }, 6848 6849 _setOption: function( key, value ) { 6850 if ( key === "disabled" ) { 6851 this.buttons.button( "option", key, value ); 6852 } 6853 6854 $.Widget.prototype._setOption.apply( this, arguments ); 6855 }, 6856 6857 refresh: function() { 6858 var rtl = this.element.css( "direction" ) === "rtl"; 6859 6860 this.buttons = this.element.find( this.options.items ) 6861 .filter( ":ui-button" ) 6862 .button( "refresh" ) 6863 .end() 6864 .not( ":ui-button" ) 6865 .button() 6866 .end() 6867 .map(function() { 6868 return $( this ).button( "widget" )[ 0 ]; 6869 }) 6870 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" ) 6871 .filter( ":first" ) 6872 .addClass( rtl ? "ui-corner-right" : "ui-corner-left" ) 6873 .end() 6874 .filter( ":last" ) 6875 .addClass( rtl ? "ui-corner-left" : "ui-corner-right" ) 6876 .end() 6877 .end(); 6878 }, 6879 6880 destroy: function() { 6881 this.element.removeClass( "ui-buttonset" ); 6882 this.buttons 6883 .map(function() { 6884 return $( this ).button( "widget" )[ 0 ]; 6885 }) 6886 .removeClass( "ui-corner-left ui-corner-right" ) 6887 .end() 6888 .button( "destroy" ); 6889 6890 $.Widget.prototype.destroy.call( this ); 6891 } 6892}); 6893 6894}( jQuery ) ); 6895 6896(function( $, undefined ) { 6897 6898$.extend($.ui, { datepicker: { version: "1.8.24" } }); 6899 6900var PROP_NAME = 'datepicker'; 6901var dpuuid = new Date().getTime(); 6902var instActive; 6903 6904/* Date picker manager. 6905 Use the singleton instance of this class, $.datepicker, to interact with the date picker. 6906 Settings for (groups of) date pickers are maintained in an instance object, 6907 allowing multiple different settings on the same page. */ 6908 6909function Datepicker() { 6910 this.debug = false; // Change this to true to start debugging 6911 this._curInst = null; // The current instance in use 6912 this._keyEvent = false; // If the last event was a key event 6913 this._disabledInputs = []; // List of date picker inputs that have been disabled 6914 this._datepickerShowing = false; // True if the popup picker is showing , false if not 6915 this._inDialog = false; // True if showing within a "dialog", false if not 6916 this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division 6917 this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class 6918 this._appendClass = 'ui-datepicker-append'; // The name of the append marker class 6919 this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class 6920 this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class 6921 this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class 6922 this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class 6923 this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class 6924 this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class 6925 this.regional = []; // Available regional settings, indexed by language code 6926 this.regional[''] = { // Default regional settings 6927 closeText: 'Done', // Display text for close link 6928 prevText: 'Prev', // Display text for previous month link 6929 nextText: 'Next', // Display text for next month link 6930 currentText: 'Today', // Display text for current month link 6931 monthNames: ['January','February','March','April','May','June', 6932 'July','August','September','October','November','December'], // Names of months for drop-down and formatting 6933 monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting 6934 dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting 6935 dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting 6936 dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday 6937 weekHeader: 'Wk', // Column header for week of the year 6938 dateFormat: 'mm/dd/yy', // See format options on parseDate 6939 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... 6940 isRTL: false, // True if right-to-left language, false if left-to-right 6941 showMonthAfterYear: false, // True if the year select precedes month, false for month then year 6942 yearSuffix: '' // Additional text to append to the year in the month headers 6943 }; 6944 this._defaults = { // Global defaults for all the date picker instances 6945 showOn: 'focus', // 'focus' for popup on focus, 6946 // 'button' for trigger button, or 'both' for either 6947 showAnim: 'fadeIn', // Name of jQuery animation for popup 6948 showOptions: {}, // Options for enhanced animations 6949 defaultDate: null, // Used when field is blank: actual date, 6950 // +/-number for offset from today, null for today 6951 appendText: '', // Display text following the input box, e.g. showing the format 6952 buttonText: '...', // Text for trigger button 6953 buttonImage: '', // URL for trigger button image 6954 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button 6955 hideIfNoPrevNext: false, // True to hide next/previous month links 6956 // if not applicable, false to just disable them 6957 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links 6958 gotoCurrent: false, // True if today link goes back to current selection instead 6959 changeMonth: false, // True if month can be selected directly, false if only prev/next 6960 changeYear: false, // True if year can be selected directly, false if only prev/next 6961 yearRange: 'c-10:c+10', // Range of years to display in drop-down, 6962 // either relative to today's year (-nn:+nn), relative to currently displayed year 6963 // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) 6964 showOtherMonths: false, // True to show dates in other months, false to leave blank 6965 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable 6966 showWeek: false, // True to show week of the year, false to not show it 6967 calculateWeek: this.iso8601Week, // How to calculate the week of the year, 6968 // takes a Date and returns the number of the week for it 6969 shortYearCutoff: '+10', // Short year values < this are in the current century, 6970 // > this are in the previous century, 6971 // string value starting with '+' for current year + value 6972 minDate: null, // The earliest selectable date, or null for no limit 6973 maxDate: null, // The latest selectable date, or null for no limit 6974 duration: 'fast', // Duration of display/closure 6975 beforeShowDay: null, // Function that takes a date and returns an array with 6976 // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '', 6977 // [2] = cell title (optional), e.g. $.datepicker.noWeekends 6978 beforeShow: null, // Function that takes an input field and 6979 // returns a set of custom settings for the date picker 6980 onSelect: null, // Define a callback function when a date is selected 6981 onChangeMonthYear: null, // Define a callback function when the month or year is changed 6982 onClose: null, // Define a callback function when the datepicker is closed 6983 numberOfMonths: 1, // Number of months to show at a time 6984 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) 6985 stepMonths: 1, // Number of months to step back/forward 6986 stepBigMonths: 12, // Number of months to step back/forward for the big links 6987 altField: '', // Selector for an alternate field to store selected dates into 6988 altFormat: '', // The date format to use for the alternate field 6989 constrainInput: true, // The input is constrained by the current date format 6990 showButtonPanel: false, // True to show button panel, false to not show it 6991 autoSize: false, // True to size the input for the date format, false to leave as is 6992 disabled: false // The initial disabled state 6993 }; 6994 $.extend(this._defaults, this.regional['']); 6995 this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')); 6996} 6997 6998$.extend(Datepicker.prototype, { 6999 /* Class name added to elements to indicate already configured with a date picker. */ 7000 markerClassName: 'hasDatepicker', 7001 7002 //Keep track of the maximum number of rows displayed (see #7043) 7003 maxRows: 4, 7004 7005 /* Debug logging (if enabled). */ 7006 log: function () { 7007 if (this.debug) 7008 console.log.apply('', arguments); 7009 }, 7010 7011 // TODO rename to "widget" when switching to widget factory 7012 _widgetDatepicker: function() { 7013 return this.dpDiv; 7014 }, 7015 7016 /* Override the default settings for all instances of the date picker. 7017 @param settings object - the new settings to use as defaults (anonymous object) 7018 @return the manager object */ 7019 setDefaults: function(settings) { 7020 extendRemove(this._defaults, settings || {}); 7021 return this; 7022 }, 7023 7024 /* Attach the date picker to a jQuery selection. 7025 @param target element - the target input field or division or span 7026 @param settings object - the new settings to use for this date picker instance (anonymous) */ 7027 _attachDatepicker: function(target, settings) { 7028 // check for settings on the control itself - in namespace 'date:' 7029 var inlineSettings = null; 7030 for (var attrName in this._defaults) { 7031 var attrValue = target.getAttribute('date:' + attrName); 7032 if (attrValue) { 7033 inlineSettings = inlineSettings || {};
7034 try { 7035 inlineSettings[attrName] = eval(attrValue); 7036 } catch (err) { 7037 inlineSettings[attrName] = attrValue; 7038 } 7039 } 7040 } 7041 var nodeName = target.nodeName.toLowerCase(); 7042 var inline = (nodeName == 'div' || nodeName == 'span'); 7043 if (!target.id) { 7044 this.uuid += 1; 7045 target.id = 'dp' + this.uuid; 7046 } 7047 var inst = this._newInst($(target), inline); 7048 inst.settings = $.extend({}, settings || {}, inlineSettings || {}); 7049 if (nodeName == 'input') { 7050 this._connectDatepicker(target, inst); 7051 } else if (inline) { 7052 this._inlineDatepicker(target, inst); 7053 } 7054 }, 7055 7056 /* Create a new instance object. */ 7057 _newInst: function(target, inline) { 7058 var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars 7059 return {id: id, input: target, // associated target 7060 selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection 7061 drawMonth: 0, drawYear: 0, // month being drawn 7062 inline: inline, // is datepicker inline or not 7063 dpDiv: (!inline ? this.dpDiv : // presentation div 7064 bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))}; 7065 }, 7066 7067 /* Attach the date picker to an input field. */ 7068 _connectDatepicker: function(target, inst) { 7069 var input = $(target); 7070 inst.append = $([]); 7071 inst.trigger = $([]); 7072 if (input.hasClass(this.markerClassName)) 7073 return; 7074 this._attachments(input, inst); 7075 input.addClass(this.markerClassName).keydown(this._doKeyDown). 7076 keypress(this._doKeyPress).keyup(this._doKeyUp). 7077 bind("setData.datepicker", function(event, key, value) { 7078 inst.settings[key] = value; 7079 }).bind("getData.datepicker", function(event, key) { 7080 return this._get(inst, key); 7081 }); 7082 this._autoSize(inst); 7083 $.data(target, PROP_NAME, inst); 7084 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) 7085 if( inst.settings.disabled ) { 7086 this._disableDatepicker( target ); 7087 } 7088 }, 7089 7090 /* Make attachments based on settings. */ 7091 _attachments: function(input, inst) { 7092 var appendText = this._get(inst, 'appendText'); 7093 var isRTL = this._get(inst, 'isRTL'); 7094 if (inst.append) 7095 inst.append.remove(); 7096 if (appendText) { 7097 inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>'); 7098 input[isRTL ? 'before' : 'after'](inst.append); 7099 } 7100 input.unbind('focus', this._showDatepicker); 7101 if (inst.trigger) 7102 inst.trigger.remove(); 7103 var showOn = this._get(inst, 'showOn'); 7104 if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field 7105 input.focus(this._showDatepicker); 7106 if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked 7107 var buttonText = this._get(inst, 'buttonText'); 7108 var buttonImage = this._get(inst, 'buttonImage'); 7109 inst.trigger = $(this._get(inst, 'buttonImageOnly') ? 7110 $('<img/>').addClass(this._triggerClass). 7111 attr({ src: buttonImage, alt: buttonText, title: buttonText }) : 7112 $('<button type="button"></button>').addClass(this._triggerClass). 7113 html(buttonImage == '' ? buttonText : $('<img/>').attr( 7114 { src:buttonImage, alt:buttonText, title:buttonText }))); 7115 input[isRTL ? 'before' : 'after'](inst.trigger); 7116 inst.trigger.click(function() { 7117 if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0]) 7118 $.datepicker._hideDatepicker(); 7119 else if ($.datepicker._datepickerShowing && $.datepicker._lastInput != input[0]) { 7120 $.datepicker._hideDatepicker(); 7121 $.datepicker._showDatepicker(input[0]); 7122 } else 7123 $.datepicker._showDatepicker(input[0]); 7124 return false; 7125 }); 7126 } 7127 }, 7128 7129 /* Apply the maximum length for the date format. */ 7130 _autoSize: function(inst) { 7131 if (this._get(inst, 'autoSize') && !inst.inline) { 7132 var date = new Date(2009, 12 - 1, 20); // Ensure double digits 7133 var dateFormat = this._get(inst, 'dateFormat'); 7134 if (dateFormat.match(/[DM]/)) { 7135 var findMax = function(names) { 7136 var max = 0; 7137 var maxI = 0; 7138 for (var i = 0; i < names.length; i++) { 7139 if (names[i].length > max) { 7140 max = names[i].length; 7141 maxI = i; 7142 } 7143 }
7144 return maxI; 7145 }; 7146 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? 7147 'monthNames' : 'monthNamesShort')))); 7148 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? 7149 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay()); 7150 } 7151 inst.input.attr('size', this._formatDate(inst, date).length); 7152 } 7153 }, 7154 7155 /* Attach an inline date picker to a div. */ 7156 _inlineDatepicker: function(target, inst) { 7157 var divSpan = $(target); 7158 if (divSpan.hasClass(this.markerClassName)) 7159 return; 7160 divSpan.addClass(this.markerClassName).append(inst.dpDiv). 7161 bind("setData.datepicker", function(event, key, value){ 7162 inst.settings[key] = value; 7163 }).bind("getData.datepicker", function(event, key){ 7164 return this._get(inst, key); 7165 }); 7166 $.data(target, PROP_NAME, inst); 7167 this._setDate(inst, this._getDefaultDate(inst), true); 7168 this._updateDatepicker(inst); 7169 this._updateAlternate(inst); 7170 //If disabled option is true, disable the datepicker before showing it (see ticket #5665) 7171 if( inst.settings.disabled ) { 7172 this._disableDatepicker( target ); 7173 } 7174 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements 7175 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height 7176 inst.dpDiv.css( "display", "block" ); 7177 }, 7178 7179 /* Pop-up the date picker in a "dialog" box. 7180 @param input element - ignored 7181 @param date string or Date - the initial date to display 7182 @param onSelect function - the function to call when a date is selected 7183 @param settings object - update the dialog date picker instance's settings (anonymous object) 7184 @param pos int[2] - coordinates for the dialog's position within the screen or 7185 event - with x/y coordinates or 7186 leave empty for default (screen centre) 7187 @return the manager object */ 7188 _dialogDatepicker: function(input, date, onSelect, settings, pos) { 7189 var inst = this._dialogInst; // internal instance 7190 if (!inst) { 7191 this.uuid += 1; 7192 var id = 'dp' + this.uuid; 7193 this._dialogInput = $('<input type="text" id="' + id + 7194 '" style="position: absolute; top: -100px; width: 0px;"/>'); 7195 this._dialogInput.keydown(this._doKeyDown); 7196 $('body').append(this._dialogInput); 7197 inst = this._dialogInst = this._newInst(this._dialogInput, false); 7198 inst.settings = {}; 7199 $.data(this._dialogInput[0], PROP_NAME, inst); 7200 } 7201 extendRemove(inst.settings, settings || {}); 7202 date = (date && date.constructor == Date ? this._formatDate(inst, date) : date); 7203 this._dialogInput.val(date); 7204 7205 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); 7206 if (!this._pos) { 7207 var browserWidth = document.documentElement.clientWidth; 7208 var browserHeight = document.documentElement.clientHeight; 7209 var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; 7210 var scrollY = document.documentElement.scrollTop || document.body.scrollTop; 7211 this._pos = // should use actual width/height below 7212 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; 7213 } 7214 7215 // move input on screen for focus, but hidden behind dialog 7216 this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px'); 7217 inst.settings.onSelect = onSelect; 7218 this._inDialog = true; 7219 this.dpDiv.addClass(this._dialogClass); 7220 this._showDatepicker(this._dialogInput[0]); 7221 if ($.blockUI) 7222 $.blockUI(this.dpDiv); 7223 $.data(this._dialogInput[0], PROP_NAME, inst); 7224 return this; 7225 }, 7226 7227 /* Detach a datepicker from its control. 7228 @param target element - the target input field or division or span */ 7229 _destroyDatepicker: function(target) { 7230 var $target = $(target); 7231 var inst = $.data(target, PROP_NAME); 7232 if (!$target.hasClass(this.markerClassName)) { 7233 return; 7234 } 7235 var nodeName = target.nodeName.toLowerCase(); 7236 $.removeData(target, PROP_NAME); 7237 if (nodeName == 'input') { 7238 inst.append.remove(); 7239 inst.trigger.remove(); 7240 $target.removeClass(this.markerClassName). 7241 unbind('focus', this._showDatepicker). 7242 unbind('keydown', this._doKeyDown). 7243 unbind('keypress', this._doKeyPress). 7244 unbind('keyup', this._doKeyUp); 7245 } else if (nodeName == 'div' || nodeName == 'span') 7246 $target.removeClass(this.markerClassName).empty(); 7247 }, 7248 7249 /* Enable the date picker to a jQuery selection. 7250 @param target element - the target input field or division or span */ 7251 _enableDatepicker: function(target) { 7252 var $target = $(target); 7253 var inst = $.data(target, PROP_NAME); 7254 if (!$target.hasClass(this.markerClassName)) { 7255 return; 7256 } 7257 var nodeName = target.nodeName.toLowerCase(); 7258 if (nodeName == 'input') { 7259 target.disabled = false;
7260 inst.trigger.filter('button'). 7261 each(function() { this.disabled = false; }).end(). 7262 filter('img').css({opacity: '1.0', cursor: ''}); 7263 } 7264 else if (nodeName == 'div' || nodeName == 'span') { 7265 var inline = $target.children('.' + this._inlineClass); 7266 inline.children().removeClass('ui-state-disabled'); 7267 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 7268 removeAttr("disabled"); 7269 } 7270 this._disabledInputs = $.map(this._disabledInputs, 7271 function(value) { return (value == target ? null : value); }); // delete entry 7272 }, 7273 7274 /* Disable the date picker to a jQuery selection. 7275 @param target element - the target input field or division or span */ 7276 _disableDatepicker: function(target) { 7277 var $target = $(target); 7278 var inst = $.data(target, PROP_NAME); 7279 if (!$target.hasClass(this.markerClassName)) { 7280 return; 7281 } 7282 var nodeName = target.nodeName.toLowerCase(); 7283 if (nodeName == 'input') { 7284 target.disabled = true; 7285 inst.trigger.filter('button'). 7286 each(function() { this.disabled = true; }).end(). 7287 filter('img').css({opacity: '0.5', cursor: 'default'}); 7288 } 7289 else if (nodeName == 'div' || nodeName == 'span') { 7290 var inline = $target.children('.' + this._inlineClass); 7291 inline.children().addClass('ui-state-disabled'); 7292 inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). 7293 attr("disabled", "disabled"); 7294 } 7295 this._disabledInputs = $.map(this._disabledInputs, 7296 function(value) { return (value == target ? null : value); }); // delete entry 7297 this._disabledInputs[this._disabledInputs.length] = target; 7298 }, 7299 7300 /* Is the first field in a jQuery collection disabled as a datepicker? 7301 @param target element - the target input field or division or span 7302 @return boolean - true if disabled, false if enabled */ 7303 _isDisabledDatepicker: function(target) { 7304 if (!target) { 7305 return false; 7306 } 7307 for (var i = 0; i < this._disabledInputs.length; i++) { 7308 if (this._disabledInputs[i] == target) 7309 return true; 7310 } 7311 return false; 7312 }, 7313 7314 /* Retrieve the instance data for the target control. 7315 @param target element - the target input field or division or span 7316 @return object - the associated instance data 7317 @throws error if a jQuery problem getting data */ 7318 _getInst: function(target) { 7319 try { 7320 return $.data(target, PROP_NAME); 7321 } 7322 catch (err) { 7323 throw 'Missing instance data for this datepicker'; 7324 } 7325 }, 7326 7327 /* Update or retrieve the settings for a date picker attached to an input field or division. 7328 @param target element - the target input field or division or span 7329 @param name object - the new settings to update or 7330 string - the name of the setting to change or retrieve, 7331 when retrieving also 'all' for all instance settings or 7332 'defaults' for all global defaults 7333 @param value any - the new value for the setting 7334 (omit if above is an object or to retrieve a value) */ 7335 _optionDatepicker: function(target, name, value) { 7336 var inst = this._getInst(target); 7337 if (arguments.length == 2 && typeof name == 'string') { 7338 return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) : 7339 (inst ? (name == 'all' ? $.extend({}, inst.settings) : 7340 this._get(inst, name)) : null)); 7341 } 7342 var settings = name || {}; 7343 if (typeof name == 'string') { 7344 settings = {}; 7345 settings[name] = value; 7346 } 7347 if (inst) { 7348 if (this._curInst == inst) { 7349 this._hideDatepicker(); 7350 } 7351 var date = this._getDateDatepicker(target, true); 7352 var minDate = this._getMinMaxDate(inst, 'min'); 7353 var maxDate = this._getMinMaxDate(inst, 'max'); 7354 extendRemove(inst.settings, settings); 7355 // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided 7356 if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined) 7357 inst.settings.minDate = this._formatDate(inst, minDate); 7358 if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined) 7359 inst.settings.maxDate = this._formatDate(inst, maxDate); 7360 this._attachments($(target), inst); 7361 this._autoSize(inst); 7362 this._setDate(inst, date); 7363 this._updateAlternate(inst); 7364 this._updateDatepicker(inst); 7365 } 7366 }, 7367 7368 // change method deprecated 7369 _changeDatepicker: function(target, name, value) { 7370 this._optionDatepicker(target, name, value); 7371 }, 7372 7373 /* Redraw the date picker attached to an input field or division. 7374 @param target element - the target input field or division or span */ 7375 _refreshDatepicker: function(target) { 7376 var inst = this._getInst(target); 7377 if (inst) { 7378 this._updateDatepicker(inst); 7379 } 7380 }, 7381 7382 /* Set the dates for a jQuery selection. 7383 @param target element - the target input field or division or span 7384 @param date Date - the new date */ 7385 _setDateDatepicker: function(target, date) { 7386 var inst = this._getInst(target); 7387 if (inst) { 7388 this._setDate(inst, date); 7389 this._updateDatepicker(inst); 7390 this._updateAlternate(inst); 7391 } 7392 }, 7393 7394 /* Get the date(s) for the first entry in a jQuery selection. 7395 @param target element - the target input field or division or span 7396 @param noDefault boolean - true if no default date is to be used 7397 @return Date - the current date */ 7398 _getDateDatepicker: function(target, noDefault) { 7399 var inst = this._getInst(target); 7400 if (inst && !inst.inline) 7401 this._setDateFromField(inst, noDefault); 7402 return (inst ? this._getDate(inst) : null); 7403 }, 7404 7405 /* Handle keystrokes. */ 7406 _doKeyDown: function(event) { 7407 var inst = $.datepicker._getInst(event.target); 7408 var handled = true; 7409 var isRTL = inst.dpDiv.is('.ui-datepicker-rtl'); 7410 inst._keyEvent = true; 7411 if ($.datepicker._datepickerShowing) 7412 switch (event.keyCode) { 7413 case 9: $.datepicker._hideDatepicker(); 7414 handled = false;
7415 break; // hide on tab out 7416 case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' + 7417 $.datepicker._currentClass + ')', inst.dpDiv); 7418 if (sel[0]) 7419 $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); 7420 var onSelect = $.datepicker._get(inst, 'onSelect'); 7421 if (onSelect) { 7422 var dateStr = $.datepicker._formatDate(inst); 7423 7424 // trigger custom callback 7425 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); 7426 } 7427 else 7428 $.datepicker._hideDatepicker(); 7429 return false; // don't submit the form 7430 break; // select the value on enter 7431 case 27: $.datepicker._hideDatepicker(); 7432 break; // hide on escape 7433 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7434 -$.datepicker._get(inst, 'stepBigMonths') : 7435 -$.datepicker._get(inst, 'stepMonths')), 'M'); 7436 break; // previous month/year on page up/+ ctrl 7437 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7438 +$.datepicker._get(inst, 'stepBigMonths') : 7439 +$.datepicker._get(inst, 'stepMonths')), 'M'); 7440 break; // next month/year on page down/+ ctrl 7441 case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target); 7442 handled = event.ctrlKey || event.metaKey; 7443 break; // clear on ctrl or command +end 7444 case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target); 7445 handled = event.ctrlKey || event.metaKey; 7446 break; // current on ctrl or command +home 7447 case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D'); 7448 handled = event.ctrlKey || event.metaKey; 7449 // -1 day on ctrl or command +left 7450 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7451 -$.datepicker._get(inst, 'stepBigMonths') : 7452 -$.datepicker._get(inst, 'stepMonths')), 'M'); 7453 // next month/year on alt +left on Mac 7454 break; 7455 case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D'); 7456 handled = event.ctrlKey || event.metaKey; 7457 break; // -1 week on ctrl or command +up 7458 case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D'); 7459 handled = event.ctrlKey || event.metaKey; 7460 // +1 day on ctrl or command +right 7461 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? 7462 +$.datepicker._get(inst, 'stepBigMonths') : 7463 +$.datepicker._get(inst, 'stepMonths')), 'M'); 7464 // next month/year on alt +right 7465 break; 7466 case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D'); 7467 handled = event.ctrlKey || event.metaKey; 7468 break; // +1 week on ctrl or command +down 7469 default: handled = false; 7470 } 7471 else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home 7472 $.datepicker._showDatepicker(this); 7473 else { 7474 handled = false; 7475 } 7476 if (handled) { 7477 event.preventDefault(); 7478 event.stopPropagation(); 7479 } 7480 }, 7481 7482 /* Filter entered characters - based on date format. */ 7483 _doKeyPress: function(event) { 7484 var inst = $.datepicker._getInst(event.target); 7485 if ($.datepicker._get(inst, 'constrainInput')) { 7486 var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')); 7487 var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode); 7488 return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1); 7489 } 7490 }, 7491 7492 /* Synchronise manual entry and field/alternate field. */ 7493 _doKeyUp: function(event) { 7494 var inst = $.datepicker._getInst(event.target);
7495 if (inst.input.val() != inst.lastVal) { 7496 try { 7497 var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'), 7498 (inst.input ? inst.input.val() : null), 7499 $.datepicker._getFormatConfig(inst)); 7500 if (date) { // only if valid 7501 $.datepicker._setDateFromField(inst); 7502 $.datepicker._updateAlternate(inst); 7503 $.datepicker._updateDatepicker(inst); 7504 } 7505 } 7506 catch (err) { 7507 $.datepicker.log(err); 7508 } 7509 } 7510 return true; 7511 }, 7512 7513 /* Pop-up the date picker for a given input field. 7514 If false returned from beforeShow event handler do not show. 7515 @param input element - the input field attached to the date picker or 7516 event - if triggered by focus */ 7517 _showDatepicker: function(input) { 7518 input = input.target || input; 7519 if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger 7520 input = $('input', input.parentNode)[0]; 7521 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here 7522 return; 7523 var inst = $.datepicker._getInst(input); 7524 if ($.datepicker._curInst && $.datepicker._curInst != inst) { 7525 $.datepicker._curInst.dpDiv.stop(true, true); 7526 if ( inst && $.datepicker._datepickerShowing ) { 7527 $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] ); 7528 } 7529 } 7530 var beforeShow = $.datepicker._get(inst, 'beforeShow'); 7531 var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; 7532 if(beforeShowSettings === false){ 7533 //false 7534 return; 7535 } 7536 extendRemove(inst.settings, beforeShowSettings); 7537 inst.lastVal = null; 7538 $.datepicker._lastInput = input; 7539 $.datepicker._setDateFromField(inst); 7540 if ($.datepicker._inDialog) // hide cursor 7541 input.value = ''; 7542 if (!$.datepicker._pos) { // position below input 7543 $.datepicker._pos = $.datepicker._findPos(input); 7544 $.datepicker._pos[1] += input.offsetHeight; // add the height 7545 } 7546 var isFixed = false; 7547 $(input).parents().each(function() { 7548 isFixed |= $(this).css('position') == 'fixed'; 7549 return !isFixed; 7550 }); 7551 if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled 7552 $.datepicker._pos[0] -= document.documentElement.scrollLeft; 7553 $.datepicker._pos[1] -= document.documentElement.scrollTop; 7554 } 7555 var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; 7556 $.datepicker._pos = null; 7557 //to avoid flashes on Firefox 7558 inst.dpDiv.empty(); 7559 // determine sizing offscreen 7560 inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'}); 7561 $.datepicker._updateDatepicker(inst); 7562 // fix width for dynamic number of date pickers 7563 // and adjust position before showing 7564 offset = $.datepicker._checkOffset(inst, offset, isFixed); 7565 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? 7566 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none', 7567 left: offset.left + 'px', top: offset.top + 'px'}); 7568 if (!inst.inline) { 7569 var showAnim = $.datepicker._get(inst, 'showAnim'); 7570 var duration = $.datepicker._get(inst, 'duration'); 7571 var postProcess = function() { 7572 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only 7573 if( !! cover.length ){ 7574 var borders = $.datepicker._getBorders(inst.dpDiv); 7575 cover.css({left: -borders[0], top: -borders[1], 7576 width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()}); 7577 } 7578 }; 7579 inst.dpDiv.zIndex($(input).zIndex()+1); 7580 $.datepicker._datepickerShowing = true; 7581 if ($.effects && $.effects[showAnim]) 7582 inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess); 7583 else 7584 inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess); 7585 if (!showAnim || !duration) 7586 postProcess(); 7587 if (inst.input.is(':visible') && !inst.input.is(':disabled')) 7588 inst.input.focus(); 7589 $.datepicker._curInst = inst; 7590 } 7591 }, 7592 7593 /* Generate the date picker content. */ 7594 _updateDatepicker: function(inst) { 7595 var self = this; 7596 self.maxRows = 4; //Reset the max number of rows being displayed (see #7043) 7597 var borders = $.datepicker._getBorders(inst.dpDiv); 7598 instActive = inst; // for delegate hover events 7599 inst.dpDiv.empty().append(this._generateHTML(inst)); 7600 this._attachHandlers(inst);
7601 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only 7602 if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6 7603 cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()}) 7604 } 7605 inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover(); 7606 var numMonths = this._getNumberOfMonths(inst); 7607 var cols = numMonths[1]; 7608 var width = 17; 7609 inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width(''); 7610 if (cols > 1) 7611 inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em'); 7612 inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') + 7613 'Class']('ui-datepicker-multi'); 7614 inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') + 7615 'Class']('ui-datepicker-rtl'); 7616 if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input && 7617 // #6694 - don't focus the input if it's already focused 7618 // this breaks the change event in IE 7619 inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement) 7620 inst.input.focus(); 7621 // deffered render of the years select (to avoid flashes on Firefox) 7622 if( inst.yearshtml ){ 7623 var origyearshtml = inst.yearshtml; 7624 setTimeout(function(){ 7625 //assure that inst.yearshtml didn't change. 7626 if( origyearshtml === inst.yearshtml && inst.yearshtml ){ 7627 inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml); 7628 } 7629 origyearshtml = inst.yearshtml = null; 7630 }, 0); 7631 } 7632 }, 7633 7634 /* Retrieve the size of left and top borders for an element. 7635 @param elem (jQuery object) the element of interest 7636 @return (number[2]) the left and top borders */ 7637 _getBorders: function(elem) { 7638 var convert = function(value) { 7639 return {thin: 1, medium: 2, thick: 3}[value] || value; 7640 }; 7641 return [parseFloat(convert(elem.css('border-left-width'))), 7642 parseFloat(convert(elem.css('border-top-width')))]; 7643 }, 7644 7645 /* Check positioning to remain on screen. */ 7646 _checkOffset: function(inst, offset, isFixed) { 7647 var dpWidth = inst.dpDiv.outerWidth(); 7648 var dpHeight = inst.dpDiv.outerHeight(); 7649 var inputWidth = inst.input ? inst.input.outerWidth() : 0; 7650 var inputHeight = inst.input ? inst.input.outerHeight() : 0; 7651 var viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()); 7652 var viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop()); 7653 7654 offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0); 7655 offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0; 7656 offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; 7657 7658 // now check if datepicker is showing outside window viewport - move to a better place if so. 7659 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? 7660 Math.abs(offset.left + dpWidth - viewWidth) : 0); 7661 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? 7662 Math.abs(dpHeight + inputHeight) : 0); 7663 7664 return offset; 7665 }, 7666 7667 /* Find an object's position on the screen. */ 7668 _findPos: function(obj) { 7669 var inst = this._getInst(obj); 7670 var isRTL = this._get(inst, 'isRTL'); 7671 while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) { 7672 obj = obj[isRTL ? 'previousSibling' : 'nextSibling']; 7673 } 7674 var position = $(obj).offset(); 7675 return [position.left, position.top]; 7676 }, 7677 7678 /* Hide the date picker from view. 7679 @param input element - the input field attached to the date picker */ 7680 _hideDatepicker: function(input) { 7681 var inst = this._curInst; 7682 if (!inst || (input && inst != $.data(input, PROP_NAME))) 7683 return; 7684 if (this._datepickerShowing) { 7685 var showAnim = this._get(inst, 'showAnim'); 7686 var duration = this._get(inst, 'duration'); 7687 var postProcess = function() { 7688 $.datepicker._tidyDialog(inst); 7689 }; 7690 if ($.effects && $.effects[showAnim]) 7691 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess); 7692 else 7693 inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' : 7694 (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess); 7695 if (!showAnim) 7696 postProcess(); 7697 this._datepickerShowing = false;
7698 var onClose = this._get(inst, 'onClose'); 7699 if (onClose) 7700 onClose.apply((inst.input ? inst.input[0] : null), 7701 [(inst.input ? inst.input.val() : ''), inst]); 7702 this._lastInput = null; 7703 if (this._inDialog) { 7704 this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' }); 7705 if ($.blockUI) { 7706 $.unblockUI(); 7707 $('body').append(this.dpDiv); 7708 } 7709 } 7710 this._inDialog = false; 7711 } 7712 }, 7713 7714 /* Tidy up after a dialog display. */ 7715 _tidyDialog: function(inst) { 7716 inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar'); 7717 }, 7718 7719 /* Close date picker if clicked elsewhere. */ 7720 _checkExternalClick: function(event) { 7721 if (!$.datepicker._curInst) 7722 return; 7723 7724 var $target = $(event.target), 7725 inst = $.datepicker._getInst($target[0]); 7726 7727 if ( ( ( $target[0].id != $.datepicker._mainDivId && 7728 $target.parents('#' + $.datepicker._mainDivId).length == 0 && 7729 !$target.hasClass($.datepicker.markerClassName) && 7730 !$target.closest("." + $.datepicker._triggerClass).length && 7731 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) || 7732 ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst != inst ) ) 7733 $.datepicker._hideDatepicker(); 7734 }, 7735 7736 /* Adjust one of the date sub-fields. */ 7737 _adjustDate: function(id, offset, period) { 7738 var target = $(id); 7739 var inst = this._getInst(target[0]); 7740 if (this._isDisabledDatepicker(target[0])) { 7741 return; 7742 } 7743 this._adjustInstDate(inst, offset + 7744 (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning 7745 period); 7746 this._updateDatepicker(inst); 7747 }, 7748 7749 /* Action for current link. */ 7750 _gotoToday: function(id) { 7751 var target = $(id); 7752 var inst = this._getInst(target[0]); 7753 if (this._get(inst, 'gotoCurrent') && inst.currentDay) { 7754 inst.selectedDay = inst.currentDay; 7755 inst.drawMonth = inst.selectedMonth = inst.currentMonth; 7756 inst.drawYear = inst.selectedYear = inst.currentYear; 7757 } 7758 else { 7759 var date = new Date(); 7760 inst.selectedDay = date.getDate(); 7761 inst.drawMonth = inst.selectedMonth = date.getMonth(); 7762 inst.drawYear = inst.selectedYear = date.getFullYear(); 7763 } 7764 this._notifyChange(inst); 7765 this._adjustDate(target); 7766 }, 7767 7768 /* Action for selecting a new month/year. */ 7769 _selectMonthYear: function(id, select, period) { 7770 var target = $(id); 7771 var inst = this._getInst(target[0]); 7772 inst['selected' + (period == 'M' ? 'Month' : 'Year')] = 7773 inst['draw' + (period == 'M' ? 'Month' : 'Year')] = 7774 parseInt(select.options[select.selectedIndex].value,10); 7775 this._notifyChange(inst); 7776 this._adjustDate(target); 7777 }, 7778 7779 /* Action for selecting a day. */ 7780 _selectDay: function(id, month, year, td) { 7781 var target = $(id); 7782 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { 7783 return; 7784 } 7785 var inst = this._getInst(target[0]); 7786 inst.selectedDay = inst.currentDay = $('a', td).html(); 7787 inst.selectedMonth = inst.currentMonth = month; 7788 inst.selectedYear = inst.currentYear = year; 7789 this._selectDate(id, this._formatDate(inst, 7790 inst.currentDay, inst.currentMonth, inst.currentYear)); 7791 }, 7792 7793 /* Erase the input field and hide the date picker. */ 7794 _clearDate: function(id) { 7795 var target = $(id); 7796 var inst = this._getInst(target[0]); 7797 this._selectDate(target, ''); 7798 }, 7799 7800 /* Update the input field with the selected date. */ 7801 _selectDate: function(id, dateStr) { 7802 var target = $(id); 7803 var inst = this._getInst(target[0]); 7804 dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); 7805 if (inst.input) 7806 inst.input.val(dateStr); 7807 this._updateAlternate(inst); 7808 var onSelect = this._get(inst, 'onSelect'); 7809 if (onSelect) 7810 onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback 7811 else if (inst.input) 7812 inst.input.trigger('change'); // fire the change event 7813 if (inst.inline) 7814 this._updateDatepicker(inst); 7815 else { 7816 this._hideDatepicker(); 7817 this._lastInput = inst.input[0]; 7818 if (typeof(inst.input[0]) != 'object') 7819 inst.input.focus(); // restore focus 7820 this._lastInput = null; 7821 } 7822 }, 7823 7824 /* Update any alternate field to synchronise with the main field. */ 7825 _updateAlternate: function(inst) { 7826 var altField = this._get(inst, 'altField'); 7827 if (altField) { // update alternate field too 7828 var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat'); 7829 var date = this._getDate(inst); 7830 var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); 7831 $(altField).each(function() { $(this).val(dateStr); }); 7832 } 7833 }, 7834 7835 /* Set as beforeShowDay function to prevent selection of weekends. 7836 @param date Date - the date to customise 7837 @return [boolean, string] - is this date selectable?, what is its CSS class? */ 7838 noWeekends: function(date) { 7839 var day = date.getDay(); 7840 return [(day > 0 && day < 6), '']; 7841 }, 7842 7843 /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. 7844 @param date Date - the date to get the week for 7845 @return number - the number of the week within the year that contains this date */ 7846 iso8601Week: function(date) { 7847 var checkDate = new Date(date.getTime()); 7848 // Find Thursday of this week starting on Monday 7849 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); 7850 var time = checkDate.getTime(); 7851 checkDate.setMonth(0); // Compare with Jan 1 7852 checkDate.setDate(1); 7853 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; 7854 }, 7855 7856 /* Parse a string value into a date object. 7857 See formatDate below for the possible formats. 7858
7859 @param format string - the expected format of the date 7860 @param value string - the date in the above format 7861 @param settings Object - attributes include: 7862 shortYearCutoff number - the cutoff year for determining the century (optional) 7863 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 7864 dayNames string[7] - names of the days from Sunday (optional) 7865 monthNamesShort string[12] - abbreviated names of the months (optional) 7866 monthNames string[12] - names of the months (optional) 7867 @return Date - the extracted date value or null if value is blank */ 7868 parseDate: function (format, value, settings) { 7869 if (format == null || value == null) 7870 throw 'Invalid arguments'; 7871 value = (typeof value == 'object' ? value.toString() : value + ''); 7872 if (value == '') 7873 return null; 7874 var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff; 7875 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : 7876 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); 7877 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; 7878 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; 7879 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; 7880 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; 7881 var year = -1; 7882 var month = -1; 7883 var day = -1; 7884 var doy = -1; 7885 var literal = false; 7886 // Check whether a format character is doubled 7887 var lookAhead = function(match) { 7888 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); 7889 if (matches) 7890 iFormat++; 7891 return matches; 7892 }; 7893 // Extract a number from the string value 7894 var getNumber = function(match) { 7895 var isDoubled = lookAhead(match); 7896 var size = (match == '@' ? 14 : (match == '!' ? 20 : 7897 (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2)))); 7898 var digits = new RegExp('^\\d{1,' + size + '}'); 7899 var num = value.substring(iValue).match(digits); 7900 if (!num) 7901 throw 'Missing number at position ' + iValue; 7902 iValue += num[0].length; 7903 return parseInt(num[0], 10); 7904 }; 7905 // Extract a name from the string value and convert to an index 7906 var getName = function(match, shortNames, longNames) { 7907 var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { 7908 return [ [k, v] ]; 7909 }).sort(function (a, b) { 7910 return -(a[1].length - b[1].length); 7911 }); 7912 var index = -1; 7913 $.each(names, function (i, pair) { 7914 var name = pair[1]; 7915 if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) { 7916 index = pair[0]; 7917 iValue += name.length; 7918 return false; 7919 } 7920 }); 7921 if (index != -1) 7922 return index + 1; 7923 else 7924 throw 'Unknown name at position ' + iValue; 7925 }; 7926 // Confirm that a literal character matches the string value 7927 var checkLiteral = function() { 7928 if (value.charAt(iValue) != format.charAt(iFormat)) 7929 throw 'Unexpected literal at position ' + iValue; 7930 iValue++; 7931 }; 7932 var iValue = 0; 7933 for (var iFormat = 0; iFormat < format.length; iFormat++) { 7934 if (literal) 7935 if (format.charAt(iFormat) == "'" && !lookAhead("'")) 7936 literal = false; 7937 else 7938 checkLiteral(); 7939 else 7940 switch (format.charAt(iFormat)) { 7941 case 'd': 7942 day = getNumber('d'); 7943 break; 7944 case 'D': 7945 getName('D', dayNamesShort, dayNames); 7946 break; 7947 case 'o': 7948 doy = getNumber('o'); 7949 break; 7950 case 'm': 7951 month = getNumber('m'); 7952 break; 7953 case 'M': 7954 month = getName('M', monthNamesShort, monthNames); 7955 break; 7956 case 'y': 7957 year = getNumber('y'); 7958 break; 7959 case '@': 7960 var date = new Date(getNumber('@')); 7961 year = date.getFullYear(); 7962 month = date.getMonth() + 1; 7963 day = date.getDate(); 7964 break; 7965 case '!': 7966 var date = new Date((getNumber('!') - this._ticksTo1970) / 10000); 7967 year = date.getFullYear();
7968 month = date.getMonth() + 1; 7969 day = date.getDate(); 7970 break; 7971 case "'": 7972 if (lookAhead("'")) 7973 checkLiteral(); 7974 else 7975 literal = true; 7976 break; 7977 default: 7978 checkLiteral(); 7979 } 7980 } 7981 if (iValue < value.length){ 7982 throw "Extra/unparsed characters found in date: " + value.substring(iValue); 7983 } 7984 if (year == -1) 7985 year = new Date().getFullYear(); 7986 else if (year < 100) 7987 year += new Date().getFullYear() - new Date().getFullYear() % 100 + 7988 (year <= shortYearCutoff ? 0 : -100); 7989 if (doy > -1) { 7990 month = 1; 7991 day = doy; 7992 do { 7993 var dim = this._getDaysInMonth(year, month - 1); 7994 if (day <= dim) 7995 break; 7996 month++; 7997 day -= dim; 7998 } while (true); 7999 } 8000 var date = this._daylightSavingAdjust(new Date(year, month - 1, day)); 8001 if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day) 8002 throw 'Invalid date'; // E.g. 31/02/00 8003 return date; 8004 }, 8005 8006 /* Standard date formats. */ 8007 ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601) 8008 COOKIE: 'D, dd M yy', 8009 ISO_8601: 'yy-mm-dd', 8010 RFC_822: 'D, d M y', 8011 RFC_850: 'DD, dd-M-y', 8012 RFC_1036: 'D, d M y', 8013 RFC_1123: 'D, d M yy', 8014 RFC_2822: 'D, d M yy', 8015 RSS: 'D, d M y', // RFC 822 8016 TICKS: '!', 8017 TIMESTAMP: '@', 8018 W3C: 'yy-mm-dd', // ISO 8601 8019 8020 _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + 8021 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), 8022 8023 /* Format a date object into a string value. 8024 The format can be combinations of the following: 8025 d - day of month (no leading zero) 8026 dd - day of month (two digit) 8027 o - day of year (no leading zeros) 8028 oo - day of year (three digit) 8029 D - day name short 8030 DD - day name long 8031 m - month of year (no leading zero) 8032 mm - month of year (two digit) 8033 M - month name short 8034 MM - month name long 8035 y - year (two digit) 8036 yy - year (four digit) 8037 @ - Unix timestamp (ms since 01/01/1970) 8038 ! - Windows ticks (100ns since 01/01/0001) 8039 '...' - literal text 8040 '' - single quote 8041 8042 @param format string - the desired format of the date 8043 @param date Date - the date value to format 8044 @param settings Object - attributes include: 8045 dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) 8046 dayNames string[7] - names of the days from Sunday (optional) 8047 monthNamesShort string[12] - abbreviated names of the months (optional) 8048 monthNames string[12] - names of the months (optional) 8049 @return string - the date in the above format */ 8050 formatDate: function (format, date, settings) { 8051 if (!date) 8052 return ''; 8053 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; 8054 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; 8055 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; 8056 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; 8057 // Check whether a format character is doubled 8058 var lookAhead = function(match) { 8059 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); 8060 if (matches) 8061 iFormat++; 8062 return matches; 8063 }; 8064 // Format a number, with leading zero if necessary 8065 var formatNumber = function(match, value, len) { 8066 var num = '' + value; 8067 if (lookAhead(match)) 8068 while (num.length < len) 8069 num = '0' + num; 8070 return num; 8071 }; 8072 // Format a name, short or long as requested 8073 var formatName = function(match, value, shortNames, longNames) { 8074 return (lookAhead(match) ? longNames[value] : shortNames[value]); 8075 }; 8076 var output = ''; 8077 var literal = false; 8078 if (date) 8079 for (var iFormat = 0; iFormat < format.length; iFormat++) { 8080 if (literal) 8081 if (format.charAt(iFormat) == "'" && !lookAhead("'")) 8082 literal = false; 8083 else 8084 output += format.charAt(iFormat); 8085 else 8086 switch (format.charAt(iFormat)) { 8087 case 'd': 8088 output += formatNumber('d', date.getDate(), 2); 8089 break; 8090 case 'D': 8091 output += formatName('D', date.getDay(), dayNamesShort, dayNames); 8092 break; 8093 case 'o': 8094 output += formatNumber('o', 8095 Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); 8096 break; 8097 case 'm': 8098 output += formatNumber('m', date.getMonth() + 1, 2); 8099 break; 8100 case 'M': 8101 output += formatName('M', date.getMonth(), monthNamesShort, monthNames); 8102 break; 8103 case 'y': 8104 output += (lookAhead('y') ? date.getFullYear() : 8105 (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100); 8106 break; 8107 case '@': 8108 output += date.getTime(); 8109 break; 8110 case '!': 8111 output += date.getTime() * 10000 + this._ticksTo1970; 8112 break;
8113 case "'": 8114 if (lookAhead("'")) 8115 output += "'"; 8116 else 8117 literal = true; 8118 break; 8119 default: 8120 output += format.charAt(iFormat); 8121 } 8122 } 8123 return output; 8124 }, 8125 8126 /* Extract all possible characters from the date format. */ 8127 _possibleChars: function (format) { 8128 var chars = ''; 8129 var literal = false; 8130 // Check whether a format character is doubled 8131 var lookAhead = function(match) { 8132 var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); 8133 if (matches) 8134 iFormat++; 8135 return matches; 8136 }; 8137 for (var iFormat = 0; iFormat < format.length; iFormat++) 8138 if (literal) 8139 if (format.charAt(iFormat) == "'" && !lookAhead("'")) 8140 literal = false; 8141 else 8142 chars += format.charAt(iFormat); 8143 else 8144 switch (format.charAt(iFormat)) { 8145 case 'd': case 'm': case 'y': case '@': 8146 chars += '0123456789'; 8147 break; 8148 case 'D': case 'M': 8149 return null; // Accept anything 8150 case "'": 8151 if (lookAhead("'")) 8152 chars += "'"; 8153 else 8154 literal = true; 8155 break; 8156 default: 8157 chars += format.charAt(iFormat); 8158 } 8159 return chars; 8160 }, 8161 8162 /* Get a setting value, defaulting if necessary. */ 8163 _get: function(inst, name) { 8164 return inst.settings[name] !== undefined ? 8165 inst.settings[name] : this._defaults[name]; 8166 }, 8167 8168 /* Parse existing date and initialise date picker. */ 8169 _setDateFromField: function(inst, noDefault) { 8170 if (inst.input.val() == inst.lastVal) { 8171 return; 8172 } 8173 var dateFormat = this._get(inst, 'dateFormat'); 8174 var dates = inst.lastVal = inst.input ? inst.input.val() : null; 8175 var date, defaultDate; 8176 date = defaultDate = this._getDefaultDate(inst); 8177 var settings = this._getFormatConfig(inst); 8178 try { 8179 date = this.parseDate(dateFormat, dates, settings) || defaultDate; 8180 } catch (event) { 8181 this.log(event); 8182 dates = (noDefault ? '' : dates); 8183 } 8184 inst.selectedDay = date.getDate(); 8185 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8186 inst.drawYear = inst.selectedYear = date.getFullYear(); 8187 inst.currentDay = (dates ? date.getDate() : 0); 8188 inst.currentMonth = (dates ? date.getMonth() : 0); 8189 inst.currentYear = (dates ? date.getFullYear() : 0); 8190 this._adjustInstDate(inst); 8191 }, 8192 8193 /* Retrieve the default date shown on opening. */ 8194 _getDefaultDate: function(inst) { 8195 return this._restrictMinMax(inst, 8196 this._determineDate(inst, this._get(inst, 'defaultDate'), new Date())); 8197 }, 8198 8199 /* A date may be specified as an exact value or a relative one. */ 8200 _determineDate: function(inst, date, defaultDate) { 8201 var offsetNumeric = function(offset) { 8202 var date = new Date(); 8203 date.setDate(date.getDate() + offset); 8204 return date; 8205 }; 8206 var offsetString = function(offset) { 8207 try { 8208 return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'), 8209 offset, $.datepicker._getFormatConfig(inst)); 8210 } 8211 catch (e) { 8212 // Ignore 8213 } 8214 var date = (offset.toLowerCase().match(/^c/) ? 8215 $.datepicker._getDate(inst) : null) || new Date(); 8216 var year = date.getFullYear(); 8217 var month = date.getMonth(); 8218 var day = date.getDate(); 8219 var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g; 8220 var matches = pattern.exec(offset); 8221 while (matches) { 8222 switch (matches[2] || 'd') { 8223 case 'd' : case 'D' : 8224 day += parseInt(matches[1],10); break; 8225 case 'w' : case 'W' : 8226 day += parseInt(matches[1],10) * 7; break; 8227 case 'm' : case 'M' : 8228 month += parseInt(matches[1],10); 8229 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 8230 break; 8231 case 'y': case 'Y' : 8232 year += parseInt(matches[1],10); 8233 day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); 8234 break; 8235 } 8236 matches = pattern.exec(offset); 8237 } 8238 return new Date(year, month, day); 8239 }; 8240 var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) : 8241 (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); 8242 newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate); 8243 if (newDate) { 8244 newDate.setHours(0); 8245 newDate.setMinutes(0); 8246 newDate.setSeconds(0); 8247 newDate.setMilliseconds(0); 8248 } 8249 return this._daylightSavingAdjust(newDate); 8250 }, 8251 8252 /* Handle switch to/from daylight saving. 8253 Hours may be non-zero on daylight saving cut-over: 8254 > 12 when midnight changeover, but then cannot generate 8255 midnight datetime, so jump to 1AM, otherwise reset. 8256 @param date (Date) the date to check 8257 @return (Date) the corrected date */ 8258 _daylightSavingAdjust: function(date) { 8259 if (!date) return null; 8260 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); 8261 return date; 8262 }, 8263 8264 /* Set the date(s) directly. */ 8265 _setDate: function(inst, date, noChange) { 8266 var clear = !date; 8267 var origMonth = inst.selectedMonth; 8268 var origYear = inst.selectedYear; 8269 var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); 8270 inst.selectedDay = inst.currentDay = newDate.getDate(); 8271 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); 8272 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); 8273 if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange) 8274 this._notifyChange(inst); 8275 this._adjustInstDate(inst); 8276 if (inst.input) { 8277 inst.input.val(clear ? '' : this._formatDate(inst)); 8278 } 8279 }, 8280 8281 /* Retrieve the date(s) directly. */ 8282 _getDate: function(inst) { 8283 var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null : 8284 this._daylightSavingAdjust(new Date( 8285 inst.currentYear, inst.currentMonth, inst.currentDay))); 8286 return startDate; 8287 }, 8288 8289 /* Attach the onxxx handlers. These are declared statically so 8290 * they work with static code transformers like Caja. 8291 */ 8292 _attachHandlers: function(inst) { 8293 var stepMonths = this._get(inst, 'stepMonths'); 8294 var id = '#' + inst.id.replace( /\\\\/g, "\\" );
8295 inst.dpDiv.find('[data-handler]').map(function () { 8296 var handler = { 8297 prev: function () { 8298 window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, -stepMonths, 'M'); 8299 }, 8300 next: function () { 8301 window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, +stepMonths, 'M'); 8302 }, 8303 hide: function () { 8304 window['DP_jQuery_' + dpuuid].datepicker._hideDatepicker(); 8305 }, 8306 today: function () { 8307 window['DP_jQuery_' + dpuuid].datepicker._gotoToday(id); 8308 }, 8309 selectDay: function () { 8310 window['DP_jQuery_' + dpuuid].datepicker._selectDay(id, +this.getAttribute('data-month'), +this.getAttribute('data-year'), this); 8311 return false; 8312 }, 8313 selectMonth: function () { 8314 window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'M'); 8315 return false; 8316 }, 8317 selectYear: function () { 8318 window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'Y'); 8319 return false; 8320 } 8321 }; 8322 $(this).bind(this.getAttribute('data-event'), handler[this.getAttribute('data-handler')]); 8323 }); 8324 }, 8325 8326 /* Generate the HTML for the current state of the date picker. */ 8327 _generateHTML: function(inst) { 8328 var today = new Date(); 8329 today = this._daylightSavingAdjust( 8330 new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time 8331 var isRTL = this._get(inst, 'isRTL'); 8332 var showButtonPanel = this._get(inst, 'showButtonPanel'); 8333 var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext'); 8334 var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat'); 8335 var numMonths = this._getNumberOfMonths(inst); 8336 var showCurrentAtPos = this._get(inst, 'showCurrentAtPos'); 8337 var stepMonths = this._get(inst, 'stepMonths'); 8338 var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1); 8339 var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : 8340 new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); 8341 var minDate = this._getMinMaxDate(inst, 'min'); 8342 var maxDate = this._getMinMaxDate(inst, 'max'); 8343 var drawMonth = inst.drawMonth - showCurrentAtPos; 8344 var drawYear = inst.drawYear; 8345 if (drawMonth < 0) { 8346 drawMonth += 12; 8347 drawYear--; 8348 } 8349 if (maxDate) { 8350 var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), 8351 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); 8352 maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); 8353 while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { 8354 drawMonth--; 8355 if (drawMonth < 0) { 8356 drawMonth = 11; 8357 drawYear--; 8358 } 8359 } 8360 } 8361 inst.drawMonth = drawMonth; 8362 inst.drawYear = drawYear; 8363 var prevText = this._get(inst, 'prevText'); 8364 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, 8365 this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), 8366 this._getFormatConfig(inst))); 8367 var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? 8368 '<a class="ui-datepicker-prev ui-corner-all" data-handler="prev" data-event="click"' + 8369 ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' : 8370 (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>')); 8371 var nextText = this._get(inst, 'nextText'); 8372 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, 8373 this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), 8374 this._getFormatConfig(inst))); 8375 var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? 8376 '<a class="ui-datepicker-next ui-corner-all" data-handler="next" data-event="click"' + 8377 ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' : 8378 (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>')); 8379 var currentText = this._get(inst, 'currentText'); 8380 var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today); 8381 currentText = (!navigationAsDateFormat ? currentText : 8382 this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); 8383 var 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">' + 8384 this._get(inst, 'closeText') + '</button>' : ''); 8385 var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') + 8386 (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"' + 8387 '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : ''; 8388 var firstDay = parseInt(this._get(inst, 'firstDay'),10); 8389 firstDay = (isNaN(firstDay) ? 0 : firstDay); 8390 var showWeek = this._get(inst, 'showWeek'); 8391 var dayNames = this._get(inst, 'dayNames'); 8392 var dayNamesShort = this._get(inst, 'dayNamesShort'); 8393 var dayNamesMin = this._get(inst, 'dayNamesMin'); 8394 var monthNames = this._get(inst, 'monthNames'); 8395 var monthNamesShort = this._get(inst, 'monthNamesShort'); 8396 var beforeShowDay = this._get(inst, 'beforeShowDay'); 8397 var showOtherMonths = this._get(inst, 'showOtherMonths'); 8398 var selectOtherMonths = this._get(inst, 'selectOtherMonths'); 8399 var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week; 8400 var defaultDate = this._getDefaultDate(inst); 8401 var html = ''; 8402 for (var row = 0; row < numMonths[0]; row++) { 8403 var group = ''; 8404 this.maxRows = 4; 8405 for (var col = 0; col < numMonths[1]; col++) { 8406 var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); 8407 var cornerClass = ' ui-corner-all'; 8408 var calender = ''; 8409 if (isMultiMonth) { 8410 calender += '<div class="ui-datepicker-group'; 8411 if (numMonths[1] > 1) 8412 switch (col) { 8413 case 0: calender += ' ui-datepicker-group-first'; 8414 cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break; 8415 case numMonths[1]-1: calender += ' ui-datepicker-group-last'; 8416 cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break; 8417 default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break; 8418 } 8419 calender += '">'; 8420 } 8421 calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' + 8422 (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') + 8423 (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') + 8424 this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, 8425 row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers 8426 '</div><table class="ui-datepicker-calendar"><thead>' + 8427 '<tr>'; 8428 var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : ''); 8429 for (var dow = 0; dow < 7; dow++) { // days of the week 8430 var day = (dow + firstDay) % 7; 8431 thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>
8431' + 8432 '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>'; 8433 } 8434 calender += thead + '</tr></thead><tbody>'; 8435 var daysInMonth = this._getDaysInMonth(drawYear, drawMonth); 8436 if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth) 8437 inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); 8438 var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; 8439 var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate 8440 var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) 8441 this.maxRows = numRows; 8442 var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); 8443 for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows 8444 calender += '<tr>'; 8445 var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' + 8446 this._get(inst, 'calculateWeek')(printDate) + '</td>'); 8447 for (var dow = 0; dow < 7; dow++) { // create date picker days 8448 var daySettings = (beforeShowDay ? 8449 beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']); 8450 var otherMonth = (printDate.getMonth() != drawMonth); 8451 var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || 8452 (minDate && printDate < minDate) || (maxDate && printDate > maxDate); 8453 tbody += '<td class="' + 8454 ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends 8455 (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months 8456 ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key 8457 (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ? 8458 // or defaultDate is current printedDate and defaultDate is selectedDate 8459 ' ' + this._dayOverClass : '') + // highlight selected day 8460 (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days 8461 (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates 8462 (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day 8463 (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different) 8464 ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title 8465 (unselectable ? '' : ' data-handler="selectDay" data-event="click" data-month="' + printDate.getMonth() + '" data-year="' + printDate.getFullYear() + '"') + '>' + // actions 8466 (otherMonth && !showOtherMonths ? ' ' : // display for other months 8467 (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' + 8468 (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') + 8469 (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day 8470 (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months 8471 '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date 8472 printDate.setDate(printDate.getDate() + 1); 8473 printDate = this._daylightSavingAdjust(printDate); 8474 } 8475 calender += tbody + '</tr>'; 8476 } 8477 drawMonth++; 8478 if (drawMonth > 11) { 8479 drawMonth = 0; 8480 drawYear++; 8481 } 8482 calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 8483 ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : ''); 8484 group += calender; 8485 } 8486 html += group; 8487 } 8488 html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ? 8489 '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : ''); 8490 inst._keyEvent = false; 8491 return html; 8492 }, 8493 8494 /* Generate the month and year header. */ 8495 _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, 8496 secondary, monthNames, monthNamesShort) { 8497 var changeMonth = this._get(inst, 'changeMonth'); 8498 var changeYear = this._get(inst, 'changeYear'); 8499 var showMonthAfterYear = this._get(inst, 'showMonthAfterYear'); 8500 var html = '<div class="ui-datepicker-title">'; 8501 var monthHtml = ''; 8502 // month selection 8503 if (secondary || !changeMonth) 8504 monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>'; 8505 else { 8506 var inMinYear = (minDate && minDate.getFullYear() == drawYear); 8507 var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear); 8508 monthHtml += '<select class="ui-datepicker-month" data-handler="selectMonth" data-event="change">';
8509 for (var month = 0; month < 12; month++) { 8510 if ((!inMinYear || month >= minDate.getMonth()) && 8511 (!inMaxYear || month <= maxDate.getMonth())) 8512 monthHtml += '<option value="' + month + '"' + 8513 (month == drawMonth ? ' selected="selected"' : '') + 8514 '>' + monthNamesShort[month] + '</option>'; 8515 } 8516 monthHtml += '</select>'; 8517 } 8518 if (!showMonthAfterYear) 8519 html += monthHtml + (secondary || !(changeMonth && changeYear) ? ' ' : ''); 8520 // year selection 8521 if ( !inst.yearshtml ) { 8522 inst.yearshtml = ''; 8523 if (secondary || !changeYear) 8524 html += '<span class="ui-datepicker-year">' + drawYear + '</span>'; 8525 else { 8526 // determine range of years to display 8527 var years = this._get(inst, 'yearRange').split(':'); 8528 var thisYear = new Date().getFullYear(); 8529 var determineYear = function(value) { 8530 var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) : 8531 (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) : 8532 parseInt(value, 10))); 8533 return (isNaN(year) ? thisYear : year); 8534 }; 8535 var year = determineYear(years[0]); 8536 var endYear = Math.max(year, determineYear(years[1] || '')); 8537 year = (minDate ? Math.max(year, minDate.getFullYear()) : year); 8538 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); 8539 inst.yearshtml += '<select class="ui-datepicker-year" data-handler="selectYear" data-event="change">'; 8540 for (; year <= endYear; year++) { 8541 inst.yearshtml += '<option value="' + year + '"' + 8542 (year == drawYear ? ' selected="selected"' : '') + 8543 '>' + year + '</option>'; 8544 } 8545 inst.yearshtml += '</select>'; 8546 8547 html += inst.yearshtml; 8548 inst.yearshtml = null; 8549 } 8550 } 8551 html += this._get(inst, 'yearSuffix'); 8552 if (showMonthAfterYear) 8553 html += (secondary || !(changeMonth && changeYear) ? ' ' : '') + monthHtml; 8554 html += '</div>'; // Close datepicker_header 8555 return html; 8556 }, 8557 8558 /* Adjust one of the date sub-fields. */ 8559 _adjustInstDate: function(inst, offset, period) { 8560 var year = inst.drawYear + (period == 'Y' ? offset : 0); 8561 var month = inst.drawMonth + (period == 'M' ? offset : 0); 8562 var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + 8563 (period == 'D' ? offset : 0); 8564 var date = this._restrictMinMax(inst, 8565 this._daylightSavingAdjust(new Date(year, month, day))); 8566 inst.selectedDay = date.getDate(); 8567 inst.drawMonth = inst.selectedMonth = date.getMonth(); 8568 inst.drawYear = inst.selectedYear = date.getFullYear(); 8569 if (period == 'M' || period == 'Y') 8570 this._notifyChange(inst); 8571 }, 8572 8573 /* Ensure a date is within any min/max bounds. */ 8574 _restrictMinMax: function(inst, date) { 8575 var minDate = this._getMinMaxDate(inst, 'min'); 8576 var maxDate = this._getMinMaxDate(inst, 'max'); 8577 var newDate = (minDate && date < minDate ? minDate : date); 8578 newDate = (maxDate && newDate > maxDate ? maxDate : newDate); 8579 return newDate; 8580 }, 8581 8582 /* Notify change of month/year. */ 8583 _notifyChange: function(inst) { 8584 var onChange = this._get(inst, 'onChangeMonthYear'); 8585 if (onChange) 8586 onChange.apply((inst.input ? inst.input[0] : null), 8587 [inst.selectedYear, inst.selectedMonth + 1, inst]); 8588 }, 8589 8590 /* Determine the number of months to show. */ 8591 _getNumberOfMonths: function(inst) { 8592 var numMonths = this._get(inst, 'numberOfMonths'); 8593 return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths)); 8594 }, 8595 8596 /* Determine the current maximum date - ensure no time components are set. */ 8597 _getMinMaxDate: function(inst, minMax) { 8598 return this._determineDate(inst, this._get(inst, minMax + 'Date'), null); 8599 }, 8600 8601 /* Find the number of days in a given month. */ 8602 _getDaysInMonth: function(year, month) { 8603 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); 8604 }, 8605 8606 /* Find the day of the week of the first of a month. */ 8607 _getFirstDayOfMonth: function(year, month) { 8608 return new Date(year, month, 1).getDay(); 8609 }, 8610 8611 /* Determines if we should allow a "next/prev" month display change. */ 8612 _canAdjustMonth: function(inst, offset, curYear, curMonth) { 8613 var numMonths = this._getNumberOfMonths(inst); 8614 var date = this._daylightSavingAdjust(new Date(curYear, 8615 curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); 8616 if (offset < 0) 8617 date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); 8618 return this._isInRange(inst, date); 8619 }, 8620 8621 /* Is the given date in the accepted range? */ 8622 _isInRange: function(inst, date) { 8623 var minDate = this._getMinMaxDate(inst, 'min'); 8624 var maxDate = this._getMinMaxDate(inst, 'max'); 8625 return ((!minDate || date.getTime() >= minDate.getTime()) && 8626 (!maxDate || date.getTime() <= maxDate.getTime())); 8627 }, 8628 8629 /* Provide the configuration settings for formatting/parsing. */ 8630 _getFormatConfig: function(inst) { 8631 var shortYearCutoff = this._get(inst, 'shortYearCutoff'); 8632 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : 8633 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); 8634 return {shortYearCutoff: shortYearCutoff, 8635 dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'), 8636 monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')}; 8637 }, 8638 8639 /* Format the given date for display. */ 8640 _formatDate: function(inst, day, month, year) { 8641 if (!day) { 8642 inst.currentDay = inst.selectedDay; 8643 inst.currentMonth = inst.selectedMonth; 8644 inst.currentYear = inst.selectedYear; 8645 } 8646 var date = (day ? (typeof day == 'object' ? day : 8647 this._daylightSavingAdjust(new Date(year, month, day))) : 8648 this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); 8649 return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst)); 8650 } 8651}); 8652 8653/* 8654 * Bind hover events for datepicker elements. 8655 * Done via delegate so the binding only occurs once in the lifetime of the parent div. 8656 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. 8657 */ 8658function bindHover(dpDiv) { 8659 var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a'; 8660 return dpDiv.bind('mouseout', function(event) { 8661 var elem = $( event.target ).closest( selector ); 8662 if ( !elem.length ) { 8663 return; 8664 } 8665 elem.removeClass( "ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover" ); 8666 }) 8667 .bind('mouseover', function(event) { 8668 var elem = $( event.target ).closest( selector ); 8669 if ($.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0]) || 8670 !elem.length ) { 8671 return; 8672 } 8673 elem.parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover'); 8674 elem.addClass('ui-state-hover'); 8675 if (elem.hasClass('ui-datepicker-prev')) elem.addClass('ui-datepicker-prev-hover'); 8676 if (elem.hasClass('ui-datepicker-next')) elem.addClass('ui-datepicker-next-hover'); 8677 }); 8678} 8679 8680/* jQuery extend now ignores nulls! */ 8681function extendRemove(target, props) { 8682 $.extend(target, props); 8683 for (var name in props) 8684 if (props[name] == null || props[name] == undefined) 8685 target[name] = props[name]; 8686 return target; 8687}; 8688 8689/* Determine whether an object is an array. */ 8690function isArray(a) { 8691 return (a && (($.browser.safari && typeof a == 'object' && a.length) || 8692 (a.constructor && a.constructor.toString().match(/\Array\(\)/)))); 8693}; 8694 8695/* Invoke the datepicker functionality. 8696 @param options string - a command, optionally followed by additional parameters or 8697 Object - settings for attaching new datepicker functionality 8698 @return jQuery object */ 8699$.fn.datepicker = function(options){ 8700 8701 /* Verify an empty collection wasn't passed - Fixes #6976 */ 8702 if ( !this.length ) { 8703 return this; 8704 } 8705 8706 /* Initialise the date picker. */ 8707 if (!$.datepicker.initialized) { 8708 $(document).mousedown($.datepicker._checkExternalClick). 8709 find('body').append($.datepicker.dpDiv); 8710 $.datepicker.initialized = true; 8711 } 8712 8713 var otherArgs = Array.prototype.slice.call(arguments, 1); 8714 if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget')) 8715 return $.datepicker['_' + options + 'Datepicker']. 8716 apply($.datepicker, [this[0]].concat(otherArgs)); 8717 if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string') 8718 return $.datepicker['_' + options + 'Datepicker']. 8719 apply($.datepicker, [this[0]].concat(otherArgs)); 8720 return this.each(function() { 8721 typeof options == 'string' ? 8722 $.datepicker['_' + options + 'Datepicker']. 8723 apply($.datepicker, [this].concat(otherArgs)) : 8724 $.datepicker._attachDatepicker(this, options); 8725 }); 8726}; 8727 8728$.datepicker = new Datepicker(); // singleton instance 8729$.datepicker.initialized = false;
8730$.datepicker.uuid = new Date().getTime(); 8731$.datepicker.version = "1.8.24"; 8732 8733// Workaround for #4055 8734// Add another global to avoid noConflict issues with inline event handlers 8735window['DP_jQuery_' + dpuuid] = $; 8736 8737})(jQuery); 8738 8739(function( $, undefined ) { 8740 8741var uiDialogClasses = 8742 'ui-dialog ' + 8743 'ui-widget ' + 8744 'ui-widget-content ' + 8745 'ui-corner-all ', 8746 sizeRelatedOptions = { 8747 buttons: true, 8748 height: true, 8749 maxHeight: true, 8750 maxWidth: true, 8751 minHeight: true, 8752 minWidth: true, 8753 width: true 8754 }, 8755 resizableRelatedOptions = { 8756 maxHeight: true, 8757 maxWidth: true, 8758 minHeight: true, 8759 minWidth: true 8760 }; 8761 8762$.widget("ui.dialog", { 8763 options: { 8764 autoOpen: true, 8765 buttons: {}, 8766 closeOnEscape: true, 8767 closeText: 'close', 8768 dialogClass: '', 8769 draggable: true, 8770 hide: null, 8771 height: 'auto', 8772 maxHeight: false, 8773 maxWidth: false, 8774 minHeight: 150, 8775 minWidth: 150, 8776 modal: false, 8777 position: { 8778 my: 'center', 8779 at: 'center', 8780 collision: 'fit', 8781 // ensure that the titlebar is never outside the document 8782 using: function(pos) { 8783 var topOffset = $(this).css(pos).offset().top; 8784 if (topOffset < 0) { 8785 $(this).css('top', pos.top - topOffset); 8786 } 8787 } 8788 }, 8789 resizable: true, 8790 show: null, 8791 stack: true, 8792 title: '', 8793 width: 300, 8794 zIndex: 1000 8795 }, 8796 8797 _create: function() { 8798 this.originalTitle = this.element.attr('title'); 8799 // #5742 - .attr() might return a DOMElement 8800 if ( typeof this.originalTitle !== "string" ) { 8801 this.originalTitle = ""; 8802 } 8803 8804 this.options.title = this.options.title || this.originalTitle; 8805 var self = this, 8806 options = self.options, 8807 8808 title = options.title || ' ', 8809 titleId = $.ui.dialog.getTitleId(self.element), 8810 8811 uiDialog = (self.uiDialog = $('<div></div>')) 8812 .appendTo(document.body) 8813 .hide() 8814 .addClass(uiDialogClasses + options.dialogClass) 8815 .css({ 8816 zIndex: options.zIndex 8817 }) 8818 // setting tabIndex makes the div focusable 8819 // setting outline to 0 prevents a border on focus in Mozilla 8820 .attr('tabIndex', -1).css('outline', 0).keydown(function(event) { 8821 if (options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && 8822 event.keyCode === $.ui.keyCode.ESCAPE) { 8823 8824 self.close(event); 8825 event.preventDefault(); 8826 } 8827 }) 8828 .attr({ 8829 role: 'dialog', 8830 'aria-labelledby': titleId 8831 }) 8832 .mousedown(function(event) { 8833 self.moveToTop(false, event); 8834 }), 8835 8836 uiDialogContent = self.element 8837 .show() 8838 .removeAttr('title') 8839 .addClass( 8840 'ui-dialog-content ' + 8841 'ui-widget-content') 8842 .appendTo(uiDialog), 8843 8844 uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>')) 8845 .addClass( 8846 'ui-dialog-titlebar ' + 8847 'ui-widget-header ' + 8848 'ui-corner-all ' + 8849 'ui-helper-clearfix' 8850 ) 8851 .prependTo(uiDialog), 8852 8853 uiDialogTitlebarClose = $('<a href="#"></a>') 8854 .addClass( 8855 'ui-dialog-titlebar-close ' + 8856 'ui-corner-all' 8857 ) 8858 .attr('role', 'button') 8859 .hover( 8860 function() { 8861 uiDialogTitlebarClose.addClass('ui-state-hover'); 8862 }, 8863 function() { 8864 uiDialogTitlebarClose.removeClass('ui-state-hover'); 8865 } 8866 ) 8867 .focus(function() { 8868 uiDialogTitlebarClose.addClass('ui-state-focus'); 8869 }) 8870 .blur(function() { 8871 uiDialogTitlebarClose.removeClass('ui-state-focus'); 8872 }) 8873 .click(function(event) { 8874 self.close(event); 8875 return false; 8876 }) 8877 .appendTo(uiDialogTitlebar), 8878 8879 uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>')) 8880 .addClass( 8881 'ui-icon ' + 8882 'ui-icon-closethick' 8883 ) 8884 .text(options.closeText) 8885 .appendTo(uiDialogTitlebarClose), 8886 8887 uiDialogTitle = $('<span></span>') 8888 .addClass('ui-dialog-title') 8889 .attr('id', titleId) 8890 .html(title) 8891 .prependTo(uiDialogTitlebar); 8892 8893 //handling of deprecated beforeclose (vs beforeClose) option 8894 //Ticket #4669 http://dev.jqueryui.com/ticket/4669 8895 //TODO: remove in 1.9pre 8896 if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) { 8897 options.beforeClose = options.beforeclose; 8898 } 8899 8900 uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection(); 8901 8902 if (options.draggable && $.fn.draggable) { 8903 self._makeDraggable(); 8904 } 8905 if (options.resizable && $.fn.resizable) { 8906 self._makeResizable(); 8907 } 8908 8909 self._createButtons(options.buttons); 8910 self._isOpen = false;
8911 8912 if ($.fn.bgiframe) { 8913 uiDialog.bgiframe(); 8914 } 8915 }, 8916 8917 _init: function() { 8918 if ( this.options.autoOpen ) { 8919 this.open(); 8920 } 8921 }, 8922 8923 destroy: function() { 8924 var self = this; 8925 8926 if (self.overlay) { 8927 self.overlay.destroy(); 8928 } 8929 self.uiDialog.hide(); 8930 self.element 8931 .unbind('.dialog') 8932 .removeData('dialog') 8933 .removeClass('ui-dialog-content ui-widget-content') 8934 .hide().appendTo('body'); 8935 self.uiDialog.remove(); 8936 8937 if (self.originalTitle) { 8938 self.element.attr('title', self.originalTitle); 8939 } 8940 8941 return self; 8942 }, 8943 8944 widget: function() { 8945 return this.uiDialog; 8946 }, 8947 8948 close: function(event) { 8949 var self = this, 8950 maxZ, thisZ; 8951 8952 if (false === self._trigger('beforeClose', event)) { 8953 return; 8954 } 8955 8956 if (self.overlay) { 8957 self.overlay.destroy(); 8958 } 8959 self.uiDialog.unbind('keypress.ui-dialog'); 8960 8961 self._isOpen = false; 8962 8963 if (self.options.hide) { 8964 self.uiDialog.hide(self.options.hide, function() { 8965 self._trigger('close', event); 8966 }); 8967 } else { 8968 self.uiDialog.hide(); 8969 self._trigger('close', event); 8970 } 8971 8972 $.ui.dialog.overlay.resize(); 8973 8974 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) 8975 if (self.options.modal) { 8976 maxZ = 0; 8977 $('.ui-dialog').each(function() { 8978 if (this !== self.uiDialog[0]) { 8979 thisZ = $(this).css('z-index'); 8980 if(!isNaN(thisZ)) { 8981 maxZ = Math.max(maxZ, thisZ); 8982 } 8983 } 8984 }); 8985 $.ui.dialog.maxZ = maxZ; 8986 } 8987 8988 return self; 8989 }, 8990 8991 isOpen: function() { 8992 return this._isOpen; 8993 }, 8994 8995 // the force parameter allows us to move modal dialogs to their correct 8996 // position on open 8997 moveToTop: function(force, event) { 8998 var self = this, 8999 options = self.options, 9000 saveScroll; 9001 9002 if ((options.modal && !force) || 9003 (!options.stack && !options.modal)) { 9004 return self._trigger('focus', event); 9005 } 9006 9007 if (options.zIndex > $.ui.dialog.maxZ) { 9008 $.ui.dialog.maxZ = options.zIndex; 9009 } 9010 if (self.overlay) { 9011 $.ui.dialog.maxZ += 1; 9012 self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ); 9013 } 9014 9015 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed. 9016 // http://ui.jquery.com/bugs/ticket/3193 9017 saveScroll = { scrollTop: self.element.scrollTop(), scrollLeft: self.element.scrollLeft() }; 9018 $.ui.dialog.maxZ += 1; 9019 self.uiDialog.css('z-index', $.ui.dialog.maxZ); 9020 self.element.attr(saveScroll); 9021 self._trigger('focus', event); 9022 9023 return self; 9024 }, 9025 9026 open: function() { 9027 if (this._isOpen) { return; } 9028 9029 var self = this, 9030 options = self.options, 9031 uiDialog = self.uiDialog; 9032 9033 self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null; 9034 self._size(); 9035 self._position(options.position); 9036 uiDialog.show(options.show); 9037 self.moveToTop(true); 9038 9039 // prevent tabbing out of modal dialogs 9040 if ( options.modal ) { 9041 uiDialog.bind( "keydown.ui-dialog", function( event ) { 9042 if ( event.keyCode !== $.ui.keyCode.TAB ) { 9043 return; 9044 } 9045 9046 var tabbables = $(':tabbable', this), 9047 first = tabbables.filter(':first'), 9048 last = tabbables.filter(':last'); 9049 9050 if (event.target === last[0] && !event.shiftKey) { 9051 first.focus(1); 9052 return false; 9053 } else if (event.target === first[0] && event.shiftKey) { 9054 last.focus(1); 9055 return false; 9056 } 9057 }); 9058 } 9059 9060 // set focus to the first tabbable element in the content area or the first button 9061 // if there are no tabbable elements, set focus on the dialog itself 9062 $(self.element.find(':tabbable').get().concat( 9063 uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat( 9064 uiDialog.get()))).eq(0).focus(); 9065 9066 self._isOpen = true; 9067 self._trigger('open'); 9068 9069 return self; 9070 }, 9071 9072 _createButtons: function(buttons) { 9073 var self = this, 9074 hasButtons = false, 9075 uiDialogButtonPane = $('<div></div>') 9076 .addClass( 9077 'ui-dialog-buttonpane ' + 9078 'ui-widget-content ' + 9079 'ui-helper-clearfix' 9080 ), 9081 uiButtonSet = $( "<div></div>" ) 9082 .addClass( "ui-dialog-buttonset" ) 9083 .appendTo( uiDialogButtonPane ); 9084 9085 // if we already have a button pane, remove it 9086 self.uiDialog.find('.ui-dialog-buttonpane').remove(); 9087 9088 if (typeof buttons === 'object' && buttons !== null) { 9089 $.each(buttons, function() { 9090 return !(hasButtons = true); 9091 }); 9092 } 9093 if (hasButtons) { 9094 $.each(buttons, function(name, props) { 9095 props = $.isFunction( props ) ? 9096 { click: props, text: name } : 9097 props; 9098 var button = $('<button type="button"></button>') 9099 .click(function() { 9100 props.click.apply(self.element[0], arguments); 9101 }) 9102 .appendTo(uiButtonSet); 9103 // can't use .attr( props, true ) with jQuery 1.3.2. 9104 $.each( props, function( key, value ) { 9105 if ( key === "click" ) { 9106 return; 9107 } 9108 if ( key in button ) { 9109 button[ key ]( value ); 9110 } else { 9111 button.attr( key, value ); 9112 } 9113 }); 9114 if ($.fn.button) { 9115 button.button(); 9116 } 9117 }); 9118 uiDialogButtonPane.appendTo(self.uiDialog); 9119 } 9120 }, 9121 9122 _makeDraggable: function() { 9123 var self = this, 9124 options = self.options, 9125 doc = $(document), 9126 heightBeforeDrag; 9127 9128 function filteredUi(ui) { 9129 return { 9130 position: ui.position, 9131 offset: ui.offset 9132 }; 9133 } 9134 9135 self.uiDialog.draggable({ 9136 cancel: '.ui-dialog-content, .ui-dialog-titlebar-close', 9137 handle: '.ui-dialog-titlebar', 9138 containment: 'document', 9139 start: function(event, ui) { 9140 heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height(); 9141 $(this).height($(this).height()).addClass("ui-dialog-dragging"); 9142 self._trigger('dragStart', event, filteredUi(ui)); 9143 }, 9144 drag: function(event, ui) { 9145 self._trigger('drag', event, filteredUi(ui)); 9146 }, 9147 stop: function(event, ui) { 9148 options.position = [ui.position.left - doc.scrollLeft(), 9149 ui.position.top - doc.scrollTop()]; 9150 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag); 9151 self._trigger('dragStop', event, filteredUi(ui)); 9152 $.ui.dialog.overlay.resize(); 9153 } 9154 }); 9155 }, 9156 9157 _makeResizable: function(handles) { 9158 handles = (handles === undefined ? this.options.resizable : handles); 9159 var self = this, 9160 options = self.options, 9161 // .ui-resizable has position: relative defined in the stylesheet 9162 // but dialogs have to use absolute or fixed positioning 9163 position = self.uiDialog.css('position'), 9164 resizeHandles = (typeof handles === 'string' ? 9165 handles : 9166 'n,e,s,w,se,sw,ne,nw' 9167 ); 9168 9169 function filteredUi(ui) { 9170 return { 9171 originalPosition: ui.originalPosition, 9172 originalSize: ui.originalSize, 9173 position: ui.position, 9174 size: ui.size 9175 }; 9176 } 9177 9178 self.uiDialog.resizable({ 9179 cancel: '.ui-dialog-content', 9180 containment: 'document', 9181 alsoResize: self.element, 9182 maxWidth: options.maxWidth, 9183 maxHeight: options.maxHeight, 9184 minWidth: options.minWidth, 9185 minHeight: self._minHeight(), 9186 handles: resizeHandles, 9187 start: function(event, ui) { 9188 $(this).addClass("ui-dialog-resizing"); 9189 self._trigger('resizeStart', event, filteredUi(ui)); 9190 }, 9191 resize: function(event, ui) { 9192 self._trigger('resize', event, filteredUi(ui)); 9193 }, 9194 stop: function(event, ui) { 9195 $(this).removeClass("ui-dialog-resizing"); 9196 options.height = $(this).height(); 9197 options.width = $(this).width(); 9198 self._trigger('resizeStop', event, filteredUi(ui)); 9199 $.ui.dialog.overlay.resize(); 9200 } 9201 }) 9202 .css('position', position) 9203 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se'); 9204 }, 9205 9206 _minHeight: function() { 9207 var options = this.options; 9208 9209 if (options.height === 'auto') { 9210 return options.minHeight; 9211 } else { 9212 return Math.min(options.minHeight, options.height); 9213 } 9214 }, 9215 9216 _position: function(position) { 9217 var myAt = [], 9218 offset = [0, 0], 9219 isVisible; 9220 9221 if (position) { 9222 // deep extending converts arrays to objects in jQuery <= 1.3.2 :-( 9223 // if (typeof position == 'string' || $.isArray(position)) { 9224 // myAt = $.isArray(position) ? position : position.split(' '); 9225 9226 if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) { 9227 myAt = position.split ? position.split(' ') : [position[0], position[1]]; 9228 if (myAt.length === 1) { 9229 myAt[1] = myAt[0]; 9230 } 9231 9232 $.each(['left', 'top'], function(i, offsetPosition) { 9233 if (+myAt[i] === myAt[i]) { 9234 offset[i] = myAt[i]; 9235 myAt[i] = offsetPosition; 9236 } 9237 }); 9238 9239 position = { 9240 my: myAt.join(" "), 9241 at: myAt.join(" "),
9242 offset: offset.join(" ") 9243 }; 9244 } 9245 9246 position = $.extend({}, $.ui.dialog.prototype.options.position, position); 9247 } else { 9248 position = $.ui.dialog.prototype.options.position; 9249 } 9250 9251 // need to show the dialog to get the actual offset in the position plugin 9252 isVisible = this.uiDialog.is(':visible'); 9253 if (!isVisible) { 9254 this.uiDialog.show(); 9255 } 9256 this.uiDialog 9257 // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781 9258 .css({ top: 0, left: 0 }) 9259 .position($.extend({ of: window }, position)); 9260 if (!isVisible) { 9261 this.uiDialog.hide(); 9262 } 9263 }, 9264 9265 _setOptions: function( options ) { 9266 var self = this, 9267 resizableOptions = {}, 9268 resize = false; 9269 9270 $.each( options, function( key, value ) { 9271 self._setOption( key, value ); 9272 9273 if ( key in sizeRelatedOptions ) { 9274 resize = true; 9275 } 9276 if ( key in resizableRelatedOptions ) { 9277 resizableOptions[ key ] = value; 9278 } 9279 }); 9280 9281 if ( resize ) { 9282 this._size(); 9283 } 9284 if ( this.uiDialog.is( ":data(resizable)" ) ) { 9285 this.uiDialog.resizable( "option", resizableOptions ); 9286 } 9287 }, 9288 9289 _setOption: function(key, value){ 9290 var self = this, 9291 uiDialog = self.uiDialog; 9292 9293 switch (key) { 9294 //handling of deprecated beforeclose (vs beforeClose) option 9295 //Ticket #4669 http://dev.jqueryui.com/ticket/4669 9296 //TODO: remove in 1.9pre 9297 case "beforeclose": 9298 key = "beforeClose"; 9299 break; 9300 case "buttons": 9301 self._createButtons(value); 9302 break; 9303 case "closeText": 9304 // ensure that we always pass a string 9305 self.uiDialogTitlebarCloseText.text("" + value); 9306 break; 9307 case "dialogClass": 9308 uiDialog 9309 .removeClass(self.options.dialogClass) 9310 .addClass(uiDialogClasses + value); 9311 break; 9312 case "disabled": 9313 if (value) { 9314 uiDialog.addClass('ui-dialog-disabled'); 9315 } else { 9316 uiDialog.removeClass('ui-dialog-disabled'); 9317 } 9318 break; 9319 case "draggable": 9320 var isDraggable = uiDialog.is( ":data(draggable)" ); 9321 if ( isDraggable && !value ) { 9322 uiDialog.draggable( "destroy" ); 9323 } 9324 9325 if ( !isDraggable && value ) { 9326 self._makeDraggable(); 9327 } 9328 break; 9329 case "position": 9330 self._position(value); 9331 break; 9332 case "resizable": 9333 // currently resizable, becoming non-resizable 9334 var isResizable = uiDialog.is( ":data(resizable)" ); 9335 if (isResizable && !value) { 9336 uiDialog.resizable('destroy'); 9337 } 9338 9339 // currently resizable, changing handles 9340 if (isResizable && typeof value === 'string') { 9341 uiDialog.resizable('option', 'handles', value); 9342 } 9343 9344 // currently non-resizable, becoming resizable 9345 if (!isResizable && value !== false) { 9346 self._makeResizable(value); 9347 } 9348 break; 9349 case "title": 9350 // convert whatever was passed in o a string, for html() to not throw up 9351 $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || ' ')); 9352 break; 9353 } 9354 9355 $.Widget.prototype._setOption.apply(self, arguments); 9356 }, 9357 9358 _size: function() { 9359 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content 9360 * divs will both have width and height set, so we need to reset them 9361 */ 9362 var options = this.options, 9363 nonContentHeight, 9364 minContentHeight, 9365 isVisible = this.uiDialog.is( ":visible" ); 9366 9367 // reset content sizing 9368 this.element.show().css({ 9369 width: 'auto', 9370 minHeight: 0, 9371 height: 0 9372 }); 9373 9374 if (options.minWidth > options.width) { 9375 options.width = options.minWidth; 9376 } 9377 9378 // reset wrapper sizing 9379 // determine the height of all the non-content elements 9380 nonContentHeight = this.uiDialog.css({ 9381 height: 'auto', 9382 width: options.width 9383 }) 9384 .height(); 9385 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); 9386 9387 if ( options.height === "auto" ) { 9388 // only needed for IE6 support 9389 if ( $.support.minHeight ) { 9390 this.element.css({ 9391 minHeight: minContentHeight, 9392 height: "auto" 9393 }); 9394 } else { 9395 this.uiDialog.show(); 9396 var autoHeight = this.element.css( "height", "auto" ).height(); 9397 if ( !isVisible ) { 9398 this.uiDialog.hide(); 9399 } 9400 this.element.height( Math.max( autoHeight, minContentHeight ) ); 9401 } 9402 } else { 9403 this.element.height( Math.max( options.height - nonContentHeight, 0 ) ); 9404 } 9405 9406 if (this.uiDialog.is(':data(resizable)')) { 9407 this.uiDialog.resizable('option', 'minHeight', this._minHeight()); 9408 } 9409 } 9410}); 9411 9412$.extend($.ui.dialog, { 9413 version: "1.8.24", 9414 9415 uuid: 0, 9416 maxZ: 0, 9417 9418 getTitleId: function($el) { 9419 var id = $el.attr('id'); 9420 if (!id) { 9421 this.uuid += 1; 9422 id = this.uuid; 9423 } 9424 return 'ui-dialog-title-' + id; 9425 }, 9426 9427 overlay: function(dialog) { 9428 this.$el = $.ui.dialog.overlay.create(dialog); 9429 } 9430}); 9431 9432$.extend($.ui.dialog.overlay, { 9433 instances: [], 9434 // reuse old instances due to IE memory leak with alpha transparency (see #5185) 9435 oldInstances: [], 9436 maxZ: 0, 9437 events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','), 9438 function(event) { return event + '.dialog-overlay'; }).join(' '), 9439 create: function(dialog) { 9440 if (this.instances.length === 0) { 9441 // prevent use of anchors and inputs 9442 // we use a setTimeout in case the overlay is created from an 9443 // event that we're going to be cancelling (see #2804) 9444 setTimeout(function() { 9445 // handle $(el).dialog().dialog('close') (see #4065) 9446 if ($.ui.dialog.overlay.instances.length) { 9447 $(document).bind($.ui.dialog.overlay.events, function(event) { 9448 // stop events if the z-index of the target is < the z-index of the overlay 9449 // we cannot return true when we don't want to cancel the event (#3523) 9450 if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) { 9451 return false;
9452 } 9453 }); 9454 } 9455 }, 1); 9456 9457 // allow closing by pressing the escape key 9458 $(document).bind('keydown.dialog-overlay', function(event) { 9459 if (dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && 9460 event.keyCode === $.ui.keyCode.ESCAPE) { 9461 9462 dialog.close(event); 9463 event.preventDefault(); 9464 } 9465 }); 9466 9467 // handle window resize 9468 $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize); 9469 } 9470 9471 var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay')) 9472 .appendTo(document.body) 9473 .css({ 9474 width: this.width(), 9475 height: this.height() 9476 }); 9477 9478 if ($.fn.bgiframe) { 9479 $el.bgiframe(); 9480 } 9481 9482 this.instances.push($el); 9483 return $el; 9484 }, 9485 9486 destroy: function($el) { 9487 var indexOf = $.inArray($el, this.instances); 9488 if (indexOf != -1){ 9489 this.oldInstances.push(this.instances.splice(indexOf, 1)[0]); 9490 } 9491 9492 if (this.instances.length === 0) { 9493 $([document, window]).unbind('.dialog-overlay'); 9494 } 9495 9496 $el.remove(); 9497 9498 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) 9499 var maxZ = 0; 9500 $.each(this.instances, function() { 9501 maxZ = Math.max(maxZ, this.css('z-index')); 9502 }); 9503 this.maxZ = maxZ; 9504 }, 9505 9506 height: function() { 9507 var scrollHeight, 9508 offsetHeight; 9509 // handle IE 6 9510 if ($.browser.msie && $.browser.version < 7) { 9511 scrollHeight = Math.max( 9512 document.documentElement.scrollHeight, 9513 document.body.scrollHeight 9514 ); 9515 offsetHeight = Math.max( 9516 document.documentElement.offsetHeight, 9517 document.body.offsetHeight 9518 ); 9519 9520 if (scrollHeight < offsetHeight) { 9521 return $(window).height() + 'px'; 9522 } else { 9523 return scrollHeight + 'px'; 9524 } 9525 // handle "good" browsers 9526 } else { 9527 return $(document).height() + 'px'; 9528 } 9529 }, 9530 9531 width: function() { 9532 var scrollWidth, 9533 offsetWidth; 9534 // handle IE 9535 if ( $.browser.msie ) { 9536 scrollWidth = Math.max( 9537 document.documentElement.scrollWidth, 9538 document.body.scrollWidth 9539 ); 9540 offsetWidth = Math.max( 9541 document.documentElement.offsetWidth, 9542 document.body.offsetWidth 9543 ); 9544 9545 if (scrollWidth < offsetWidth) { 9546 return $(window).width() + 'px'; 9547 } else { 9548 return scrollWidth + 'px'; 9549 } 9550 // handle "good" browsers 9551 } else { 9552 return $(document).width() + 'px'; 9553 } 9554 }, 9555 9556 resize: function() { 9557 /* If the dialog is draggable and the user drags it past the 9558 * right edge of the window, the document becomes wider so we 9559 * need to stretch the overlay. If the user then drags the 9560 * dialog back to the left, the document will become narrower, 9561 * so we need to shrink the overlay to the appropriate size. 9562 * This is handled by shrinking the overlay before setting it 9563 * to the full document size. 9564 */ 9565 var $overlays = $([]); 9566 $.each($.ui.dialog.overlay.instances, function() { 9567 $overlays = $overlays.add(this); 9568 }); 9569 9570 $overlays.css({ 9571 width: 0, 9572 height: 0 9573 }).css({ 9574 width: $.ui.dialog.overlay.width(), 9575 height: $.ui.dialog.overlay.height() 9576 }); 9577 } 9578}); 9579 9580$.extend($.ui.dialog.overlay.prototype, { 9581 destroy: function() { 9582 $.ui.dialog.overlay.destroy(this.$el); 9583 } 9584}); 9585 9586}(jQuery)); 9587 9588(function( $, undefined ) { 9589 9590$.ui = $.ui || {}; 9591 9592var horizontalPositions = /left|center|right/, 9593 verticalPositions = /top|center|bottom/, 9594 center = "center", 9595 support = {}, 9596 _position = $.fn.position, 9597 _offset = $.fn.offset; 9598 9599$.fn.position = function( options ) { 9600 if ( !options || !options.of ) { 9601 return _position.apply( this, arguments ); 9602 } 9603 9604 // make a copy, we don't want to modify arguments 9605 options = $.extend( {}, options ); 9606 9607 var target = $( options.of ), 9608 targetElem = target[0], 9609 collision = ( options.collision || "flip" ).split( " " ), 9610 offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ], 9611 targetWidth, 9612 targetHeight, 9613 basePosition; 9614 9615 if ( targetElem.nodeType === 9 ) { 9616 targetWidth = target.width(); 9617 targetHeight = target.height(); 9618 basePosition = { top: 0, left: 0 }; 9619 // TODO: use $.isWindow() in 1.9 9620 } else if ( targetElem.setTimeout ) { 9621 targetWidth = target.width(); 9622 targetHeight = target.height(); 9623 basePosition = { top: target.scrollTop(), left: target.scrollLeft() }; 9624 } else if ( targetElem.preventDefault ) { 9625 // force left top to allow flipping 9626 options.at = "left top"; 9627 targetWidth = targetHeight = 0; 9628 basePosition = { top: options.of.pageY, left: options.of.pageX }; 9629 } else { 9630 targetWidth = target.outerWidth(); 9631 targetHeight = target.outerHeight(); 9632 basePosition = target.offset(); 9633 } 9634 9635 // force my and at to have valid horizontal and veritcal positions 9636 // if a value is missing or invalid, it will be converted to center 9637 $.each( [ "my", "at" ], function() { 9638 var pos = ( options[this] || "" ).split( " " ); 9639 if ( pos.length === 1) { 9640 pos = horizontalPositions.test( pos[0] ) ? 9641 pos.concat( [center] ) : 9642 verticalPositions.test( pos[0] ) ? 9643 [ center ].concat( pos ) : 9644 [ center, center ]; 9645 } 9646 pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center; 9647 pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center; 9648 options[ this ] = pos; 9649 }); 9650
9651 // normalize collision option 9652 if ( collision.length === 1 ) { 9653 collision[ 1 ] = collision[ 0 ]; 9654 } 9655 9656 // normalize offset option 9657 offset[ 0 ] = parseInt( offset[0], 10 ) || 0; 9658 if ( offset.length === 1 ) { 9659 offset[ 1 ] = offset[ 0 ]; 9660 } 9661 offset[ 1 ] = parseInt( offset[1], 10 ) || 0; 9662 9663 if ( options.at[0] === "right" ) { 9664 basePosition.left += targetWidth; 9665 } else if ( options.at[0] === center ) { 9666 basePosition.left += targetWidth / 2; 9667 } 9668 9669 if ( options.at[1] === "bottom" ) { 9670 basePosition.top += targetHeight; 9671 } else if ( options.at[1] === center ) { 9672 basePosition.top += targetHeight / 2; 9673 } 9674 9675 basePosition.left += offset[ 0 ]; 9676 basePosition.top += offset[ 1 ]; 9677 9678 return this.each(function() { 9679 var elem = $( this ), 9680 elemWidth = elem.outerWidth(), 9681 elemHeight = elem.outerHeight(), 9682 marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0, 9683 marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0, 9684 collisionWidth = elemWidth + marginLeft + 9685 ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ), 9686 collisionHeight = elemHeight + marginTop + 9687 ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ), 9688 position = $.extend( {}, basePosition ), 9689 collisionPosition; 9690 9691 if ( options.my[0] === "right" ) { 9692 position.left -= elemWidth; 9693 } else if ( options.my[0] === center ) { 9694 position.left -= elemWidth / 2; 9695 } 9696 9697 if ( options.my[1] === "bottom" ) { 9698 position.top -= elemHeight; 9699 } else if ( options.my[1] === center ) { 9700 position.top -= elemHeight / 2; 9701 } 9702 9703 // prevent fractions if jQuery version doesn't support them (see #5280) 9704 if ( !support.fractions ) { 9705 position.left = Math.round( position.left ); 9706 position.top = Math.round( position.top ); 9707 } 9708 9709 collisionPosition = { 9710 left: position.left - marginLeft, 9711 top: position.top - marginTop 9712 }; 9713 9714 $.each( [ "left", "top" ], function( i, dir ) { 9715 if ( $.ui.position[ collision[i] ] ) { 9716 $.ui.position[ collision[i] ][ dir ]( position, { 9717 targetWidth: targetWidth, 9718 targetHeight: targetHeight, 9719 elemWidth: elemWidth, 9720 elemHeight: elemHeight, 9721 collisionPosition: collisionPosition, 9722 collisionWidth: collisionWidth, 9723 collisionHeight: collisionHeight, 9724 offset: offset, 9725 my: options.my, 9726 at: options.at 9727 }); 9728 } 9729 }); 9730 9731 if ( $.fn.bgiframe ) { 9732 elem.bgiframe(); 9733 } 9734 elem.offset( $.extend( position, { using: options.using } ) ); 9735 }); 9736}; 9737 9738$.ui.position = { 9739 fit: { 9740 left: function( position, data ) { 9741 var win = $( window ), 9742 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(); 9743 position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left ); 9744 }, 9745 top: function( position, data ) { 9746 var win = $( window ), 9747 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(); 9748 position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top ); 9749 } 9750 }, 9751 9752 flip: { 9753 left: function( position, data ) { 9754 if ( data.at[0] === center ) { 9755 return; 9756 } 9757 var win = $( window ), 9758 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(), 9759 myOffset = data.my[ 0 ] === "left" ? 9760 -data.elemWidth : 9761 data.my[ 0 ] === "right" ? 9762 data.elemWidth : 9763 0, 9764 atOffset = data.at[ 0 ] === "left" ? 9765 data.targetWidth : 9766 -data.targetWidth, 9767 offset = -2 * data.offset[ 0 ]; 9768 position.left += data.collisionPosition.left < 0 ? 9769 myOffset + atOffset + offset : 9770 over > 0 ? 9771 myOffset + atOffset + offset : 9772 0; 9773 }, 9774 top: function( position, data ) { 9775 if ( data.at[1] === center ) { 9776 return; 9777 } 9778 var win = $( window ), 9779 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(), 9780 myOffset = data.my[ 1 ] === "top" ? 9781 -data.elemHeight : 9782 data.my[ 1 ] === "bottom" ? 9783 data.elemHeight : 9784 0, 9785 atOffset = data.at[ 1 ] === "top" ? 9786 data.targetHeight : 9787 -data.targetHeight, 9788 offset = -2 * data.offset[ 1 ]; 9789 position.top += data.collisionPosition.top < 0 ? 9790 myOffset + atOffset + offset : 9791 over > 0 ? 9792 myOffset + atOffset + offset : 9793 0; 9794 } 9795 } 9796}; 9797 9798// offset setter from jQuery 1.4 9799if ( !$.offset.setOffset ) { 9800 $.offset.setOffset = function( elem, options ) { 9801 // set position first, in-case top/left are set even on static elem 9802 if ( /static/.test( $.curCSS( elem, "position" ) ) ) { 9803 elem.style.position = "relative"; 9804 } 9805 var curElem = $( elem ), 9806 curOffset = curElem.offset(), 9807 curTop = parseInt( $.curCSS( elem, "top", true ), 10 ) || 0, 9808 curLeft = parseInt( $.curCSS( elem, "left", true ), 10) || 0, 9809 props = { 9810 top: (options.top - curOffset.top) + curTop, 9811 left: (options.left - curOffset.left) + curLeft 9812 }; 9813 9814 if ( 'using' in options ) { 9815 options.using.call( elem, props ); 9816 } else { 9817 curElem.css( props ); 9818 } 9819 }; 9820 9821 $.fn.offset = function( options ) { 9822 var elem = this[ 0 ]; 9823 if ( !elem || !elem.ownerDocument ) { return null; } 9824 if ( options ) { 9825 if ( $.isFunction( options ) ) { 9826 return this.each(function( i ) { 9827 $( this ).offset( options.call( this, i, $( this ).offset() ) ); 9828 }); 9829 } 9830 return this.each(function() { 9831 $.offset.setOffset( this, options ); 9832 }); 9833 } 9834 return _offset.call( this ); 9835 }; 9836} 9837 9838// jQuery <1.4.3 uses curCSS, in 1.4.3 - 1.7.2 curCSS = css, 1.8+ only has css 9839if ( !$.curCSS ) { 9840 $.curCSS = $.css; 9841} 9842 9843// fraction support test (older versions of jQuery don't support fractions) 9844(function () { 9845 var body = document.getElementsByTagName( "body" )[ 0 ], 9846 div = document.createElement( "div" ), 9847 testElement, testElementParent, testElementStyle, offset, offsetTotal; 9848 9849 //Create a "fake body" for testing based on method used in jQuery.support 9850 testElement = document.createElement( body ? "div" : "body" ); 9851 testElementStyle = { 9852 visibility: "hidden", 9853 width: 0, 9854 height: 0, 9855 border: 0, 9856 margin: 0, 9857 background: "none" 9858 }; 9859 if ( body ) { 9860 $.extend( testElementStyle, { 9861 position: "absolute", 9862 left: "-1000px", 9863 top: "-1000px" 9864 }); 9865 } 9866 for ( var i in testElementStyle ) { 9867 testElement.style[ i ] = testElementStyle[ i ]; 9868 } 9869 testElement.appendChild( div ); 9870 testElementParent = body || document.documentElement; 9871 testElementParent.insertBefore( testElement, testElementParent.firstChild ); 9872 9873 div.style.cssText = "position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;"; 9874 9875 offset = $( div ).offset( function( _, offset ) { 9876 return offset; 9877 }).offset(); 9878 9879 testElement.innerHTML = ""; 9880 testElementParent.removeChild( testElement ); 9881 9882 offsetTotal = offset.top + offset.left + ( body ? 2000 : 0 ); 9883 support.fractions = offsetTotal > 21 && offsetTotal < 22; 9884})(); 9885 9886}( jQuery )); 9887 9888(function( $, undefined ) { 9889 9890$.widget( "ui.progressbar", { 9891 options: { 9892 value: 0, 9893 max: 100 9894 }, 9895 9896 min: 0, 9897 9898 _create: function() { 9899 this.element 9900 .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) 9901 .attr({ 9902 role: "progressbar", 9903 "aria-valuemin": this.min, 9904 "aria-valuemax": this.options.max,
9905 "aria-valuenow": this._value() 9906 }); 9907 9908 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" ) 9909 .appendTo( this.element ); 9910 9911 this.oldValue = this._value(); 9912 this._refreshValue(); 9913 }, 9914 9915 destroy: function() { 9916 this.element 9917 .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) 9918 .removeAttr( "role" ) 9919 .removeAttr( "aria-valuemin" ) 9920 .removeAttr( "aria-valuemax" ) 9921 .removeAttr( "aria-valuenow" ); 9922 9923 this.valueDiv.remove(); 9924 9925 $.Widget.prototype.destroy.apply( this, arguments ); 9926 }, 9927 9928 value: function( newValue ) { 9929 if ( newValue === undefined ) { 9930 return this._value(); 9931 } 9932 9933 this._setOption( "value", newValue ); 9934 return this; 9935 }, 9936 9937 _setOption: function( key, value ) { 9938 if ( key === "value" ) { 9939 this.options.value = value; 9940 this._refreshValue(); 9941 if ( this._value() === this.options.max ) { 9942 this._trigger( "complete" ); 9943 } 9944 } 9945 9946 $.Widget.prototype._setOption.apply( this, arguments ); 9947 }, 9948 9949 _value: function() { 9950 var val = this.options.value; 9951 // normalize invalid value 9952 if ( typeof val !== "number" ) { 9953 val = 0; 9954 } 9955 return Math.min( this.options.max, Math.max( this.min, val ) ); 9956 }, 9957 9958 _percentage: function() { 9959 return 100 * this._value() / this.options.max; 9960 }, 9961 9962 _refreshValue: function() { 9963 var value = this.value(); 9964 var percentage = this._percentage(); 9965 9966 if ( this.oldValue !== value ) { 9967 this.oldValue = value; 9968 this._trigger( "change" ); 9969 } 9970 9971 this.valueDiv 9972 .toggle( value > this.min ) 9973 .toggleClass( "ui-corner-right", value === this.options.max ) 9974 .width( percentage.toFixed(0) + "%" ); 9975 this.element.attr( "aria-valuenow", value ); 9976 } 9977}); 9978 9979$.extend( $.ui.progressbar, { 9980 version: "1.8.24" 9981}); 9982 9983})( jQuery ); 9984 9985(function( $, undefined ) { 9986 9987// number of pages in a slider 9988// (how many times can you page up/down to go through the whole range) 9989var numPages = 5; 9990 9991$.widget( "ui.slider", $.ui.mouse, { 9992 9993 widgetEventPrefix: "slide", 9994 9995 options: { 9996 animate: false, 9997 distance: 0, 9998 max: 100, 9999 min: 0, 10000 orientation: "horizontal", 10001 range: false, 10002 step: 1, 10003 value: 0, 10004 values: null 10005 }, 10006 10007 _create: function() { 10008 var self = this, 10009 o = this.options, 10010 existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), 10011 handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>", 10012 handleCount = ( o.values && o.values.length ) || 1, 10013 handles = []; 10014 10015 this._keySliding = false; 10016 this._mouseSliding = false; 10017 this._animateOff = true; 10018 this._handleIndex = null; 10019 this._detectOrientation(); 10020 this._mouseInit(); 10021 10022 this.element 10023 .addClass( "ui-slider" + 10024 " ui-slider-" + this.orientation + 10025 " ui-widget" + 10026 " ui-widget-content" + 10027 " ui-corner-all" + 10028 ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) ); 10029 10030 this.range = $([]); 10031 10032 if ( o.range ) { 10033 if ( o.range === true ) { 10034 if ( !o.values ) { 10035 o.values = [ this._valueMin(), this._valueMin() ]; 10036 } 10037 if ( o.values.length && o.values.length !== 2 ) { 10038 o.values = [ o.values[0], o.values[0] ]; 10039 } 10040 } 10041 10042 this.range = $( "<div></div>" ) 10043 .appendTo( this.element ) 10044 .addClass( "ui-slider-range" + 10045 // note: this isn't the most fittingly semantic framework class for this element, 10046 // but worked best visually with a variety of themes 10047 " ui-widget-header" + 10048 ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) ); 10049 } 10050 10051 for ( var i = existingHandles.length; i < handleCount; i += 1 ) { 10052 handles.push( handle ); 10053 } 10054 10055 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) ); 10056 10057 this.handle = this.handles.eq( 0 ); 10058 10059 this.handles.add( this.range ).filter( "a" ) 10060 .click(function( event ) { 10061 event.preventDefault(); 10062 }) 10063 .hover(function() { 10064 if ( !o.disabled ) { 10065 $( this ).addClass( "ui-state-hover" ); 10066 } 10067 }, function() { 10068 $( this ).removeClass( "ui-state-hover" ); 10069 }) 10070 .focus(function() { 10071 if ( !o.disabled ) { 10072 $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" ); 10073 $( this ).addClass( "ui-state-focus" ); 10074 } else { 10075 $( this ).blur(); 10076 } 10077 }) 10078 .blur(function() { 10079 $( this ).removeClass( "ui-state-focus" ); 10080 }); 10081 10082 this.handles.each(function( i ) { 10083 $( this ).data( "index.ui-slider-handle", i ); 10084 }); 10085 10086 this.handles 10087 .keydown(function( event ) { 10088 var index = $( this ).data( "index.ui-slider-handle" ), 10089 allowed, 10090 curVal, 10091 newVal, 10092 step; 10093 10094 if ( self.options.disabled ) { 10095 return; 10096 } 10097 10098 switch ( event.keyCode ) { 10099 case $.ui.keyCode.HOME: 10100 case $.ui.keyCode.END: 10101 case $.ui.keyCode.PAGE_UP: 10102 case $.ui.keyCode.PAGE_DOWN: 10103 case $.ui.keyCode.UP: 10104 case $.ui.keyCode.RIGHT: 10105 case $.ui.keyCode.DOWN: 10106 case $.ui.keyCode.LEFT: 10107 event.preventDefault(); 10108 if ( !self._keySliding ) { 10109 self._keySliding = true; 10110 $( this ).addClass( "ui-state-active" ); 10111 allowed = self._start( event, index ); 10112 if ( allowed === false ) { 10113 return; 10114 } 10115 } 10116 break; 10117 } 10118 10119 step = self.options.step; 10120 if ( self.options.values && self.options.values.length ) { 10121 curVal = newVal = self.values( index ); 10122 } else { 10123 curVal = newVal = self.value(); 10124 } 10125 10126 switch ( event.keyCode ) { 10127 case $.ui.keyCode.HOME: 10128 newVal = self._valueMin(); 10129 break; 10130 case $.ui.keyCode.END: 10131 newVal = self._valueMax(); 10132 break; 10133 case $.ui.keyCode.PAGE_UP: 10134 newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) ); 10135 break; 10136 case $.ui.keyCode.PAGE_DOWN: 10137 newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) ); 10138 break; 10139 case $.ui.keyCode.UP: 10140 case $.ui.keyCode.RIGHT: 10141 if ( curVal === self._valueMax() ) { 10142 return; 10143 } 10144 newVal = self._trimAlignValue( curVal + step ); 10145 break; 10146 case $.ui.keyCode.DOWN: 10147 case $.ui.keyCode.LEFT: 10148 if ( curVal === self._valueMin() ) { 10149 return; 10150 } 10151 newVal = self._trimAlignValue( curVal - step ); 10152 break; 10153 } 10154 10155 self._slide( event, index, newVal ); 10156 }) 10157 .keyup(function( event ) { 10158 var index = $( this ).data( "index.ui-slider-handle" ); 10159 10160 if ( self._keySliding ) { 10161 self._keySliding = false;
vendor: 11,399 bytes, lines 10162-10598
10162 self._stop( event, index ); 10163 self._change( event, index ); 10164 $( this ).removeClass( "ui-state-active" ); 10165 } 10166 10167 }); 10168 10169 this._refreshValue(); 10170 10171 this._animateOff = false; 10172 }, 10173 10174 destroy: function() { 10175 this.handles.remove(); 10176 this.range.remove(); 10177 10178 this.element 10179 .removeClass( "ui-slider" + 10180 " ui-slider-horizontal" + 10181 " ui-slider-vertical" + 10182 " ui-slider-disabled" + 10183 " ui-widget" + 10184 " ui-widget-content" + 10185 " ui-corner-all" ) 10186 .removeData( "slider" ) 10187 .unbind( ".slider" ); 10188 10189 this._mouseDestroy(); 10190 10191 return this; 10192 }, 10193 10194 _mouseCapture: function( event ) { 10195 var o = this.options, 10196 position, 10197 normValue, 10198 distance, 10199 closestHandle, 10200 self, 10201 index, 10202 allowed, 10203 offset, 10204 mouseOverHandle; 10205 10206 if ( o.disabled ) { 10207 return false; 10208 } 10209 10210 this.elementSize = { 10211 width: this.element.outerWidth(), 10212 height: this.element.outerHeight() 10213 }; 10214 this.elementOffset = this.element.offset(); 10215 10216 position = { x: event.pageX, y: event.pageY }; 10217 normValue = this._normValueFromMouse( position ); 10218 distance = this._valueMax() - this._valueMin() + 1; 10219 self = this; 10220 this.handles.each(function( i ) { 10221 var thisDistance = Math.abs( normValue - self.values(i) ); 10222 if ( distance > thisDistance ) { 10223 distance = thisDistance; 10224 closestHandle = $( this ); 10225 index = i; 10226 } 10227 }); 10228 10229 // workaround for bug #3736 (if both handles of a range are at 0, 10230 // the first is always used as the one with least distance, 10231 // and moving it is obviously prevented by preventing negative ranges) 10232 if( o.range === true && this.values(1) === o.min ) { 10233 index += 1; 10234 closestHandle = $( this.handles[index] ); 10235 } 10236 10237 allowed = this._start( event, index ); 10238 if ( allowed === false ) { 10239 return false; 10240 } 10241 this._mouseSliding = true; 10242 10243 self._handleIndex = index; 10244 10245 closestHandle 10246 .addClass( "ui-state-active" ) 10247 .focus(); 10248 10249 offset = closestHandle.offset(); 10250 mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" ); 10251 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { 10252 left: event.pageX - offset.left - ( closestHandle.width() / 2 ), 10253 top: event.pageY - offset.top - 10254 ( closestHandle.height() / 2 ) - 10255 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - 10256 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + 10257 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) 10258 }; 10259 10260 if ( !this.handles.hasClass( "ui-state-hover" ) ) { 10261 this._slide( event, index, normValue ); 10262 } 10263 this._animateOff = true; 10264 return true; 10265 }, 10266 10267 _mouseStart: function( event ) { 10268 return true; 10269 }, 10270 10271 _mouseDrag: function( event ) { 10272 var position = { x: event.pageX, y: event.pageY }, 10273 normValue = this._normValueFromMouse( position ); 10274 10275 this._slide( event, this._handleIndex, normValue ); 10276 10277 return false; 10278 }, 10279 10280 _mouseStop: function( event ) { 10281 this.handles.removeClass( "ui-state-active" ); 10282 this._mouseSliding = false; 10283 10284 this._stop( event, this._handleIndex ); 10285 this._change( event, this._handleIndex ); 10286 10287 this._handleIndex = null; 10288 this._clickOffset = null; 10289 this._animateOff = false; 10290 10291 return false; 10292 }, 10293 10294 _detectOrientation: function() { 10295 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; 10296 }, 10297 10298 _normValueFromMouse: function( position ) { 10299 var pixelTotal, 10300 pixelMouse, 10301 percentMouse, 10302 valueTotal, 10303 valueMouse; 10304 10305 if ( this.orientation === "horizontal" ) { 10306 pixelTotal = this.elementSize.width; 10307 pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); 10308 } else { 10309 pixelTotal = this.elementSize.height; 10310 pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); 10311 } 10312 10313 percentMouse = ( pixelMouse / pixelTotal ); 10314 if ( percentMouse > 1 ) { 10315 percentMouse = 1; 10316 } 10317 if ( percentMouse < 0 ) { 10318 percentMouse = 0; 10319 } 10320 if ( this.orientation === "vertical" ) { 10321 percentMouse = 1 - percentMouse; 10322 } 10323 10324 valueTotal = this._valueMax() - this._valueMin(); 10325 valueMouse = this._valueMin() + percentMouse * valueTotal; 10326 10327 return this._trimAlignValue( valueMouse ); 10328 }, 10329 10330 _start: function( event, index ) { 10331 var uiHash = { 10332 handle: this.handles[ index ], 10333 value: this.value() 10334 }; 10335 if ( this.options.values && this.options.values.length ) { 10336 uiHash.value = this.values( index ); 10337 uiHash.values = this.values(); 10338 } 10339 return this._trigger( "start", event, uiHash ); 10340 }, 10341 10342 _slide: function( event, index, newVal ) { 10343 var otherVal, 10344 newValues, 10345 allowed; 10346 10347 if ( this.options.values && this.options.values.length ) { 10348 otherVal = this.values( index ? 0 : 1 ); 10349 10350 if ( ( this.options.values.length === 2 && this.options.range === true ) && 10351 ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) 10352 ) { 10353 newVal = otherVal; 10354 } 10355 10356 if ( newVal !== this.values( index ) ) { 10357 newValues = this.values(); 10358 newValues[ index ] = newVal; 10359 // A slide can be canceled by returning false from the slide callback 10360 allowed = this._trigger( "slide", event, { 10361 handle: this.handles[ index ], 10362 value: newVal, 10363 values: newValues 10364 } ); 10365 otherVal = this.values( index ? 0 : 1 ); 10366 if ( allowed !== false ) { 10367 this.values( index, newVal, true ); 10368 } 10369 } 10370 } else { 10371 if ( newVal !== this.value() ) { 10372 // A slide can be canceled by returning false from the slide callback 10373 allowed = this._trigger( "slide", event, { 10374 handle: this.handles[ index ], 10375 value: newVal 10376 } ); 10377 if ( allowed !== false ) { 10378 this.value( newVal ); 10379 } 10380 } 10381 } 10382 }, 10383 10384 _stop: function( event, index ) { 10385 var uiHash = { 10386 handle: this.handles[ index ], 10387 value: this.value() 10388 }; 10389 if ( this.options.values && this.options.values.length ) { 10390 uiHash.value = this.values( index ); 10391 uiHash.values = this.values(); 10392 } 10393 10394 this._trigger( "stop", event, uiHash ); 10395 }, 10396 10397 _change: function( event, index ) { 10398 if ( !this._keySliding && !this._mouseSliding ) { 10399 var uiHash = { 10400 handle: this.handles[ index ], 10401 value: this.value() 10402 }; 10403 if ( this.options.values && this.options.values.length ) { 10404 uiHash.value = this.values( index ); 10405 uiHash.values = this.values(); 10406 } 10407 10408 this._trigger( "change", event, uiHash ); 10409 } 10410 }, 10411 10412 value: function( newValue ) { 10413 if ( arguments.length ) { 10414 this.options.value = this._trimAlignValue( newValue ); 10415 this._refreshValue(); 10416 this._change( null, 0 ); 10417 return; 10418 } 10419 10420 return this._value(); 10421 }, 10422 10423 values: function( index, newValue ) { 10424 var vals, 10425 newValues, 10426 i; 10427 10428 if ( arguments.length > 1 ) { 10429 this.options.values[ index ] = this._trimAlignValue( newValue ); 10430 this._refreshValue(); 10431 this._change( null, index ); 10432 return; 10433 } 10434 10435 if ( arguments.length ) { 10436 if ( $.isArray( arguments[ 0 ] ) ) { 10437 vals = this.options.values; 10438 newValues = arguments[ 0 ]; 10439 for ( i = 0; i < vals.length; i += 1 ) { 10440 vals[ i ] = this._trimAlignValue( newValues[ i ] ); 10441 this._change( null, i ); 10442 } 10443 this._refreshValue(); 10444 } else { 10445 if ( this.options.values && this.options.values.length ) { 10446 return this._values( index ); 10447 } else { 10448 return this.value(); 10449 } 10450 } 10451 } else { 10452 return this._values(); 10453 } 10454 }, 10455 10456 _setOption: function( key, value ) { 10457 var i, 10458 valsLength = 0; 10459 10460 if ( $.isArray( this.options.values ) ) { 10461 valsLength = this.options.values.length; 10462 } 10463 10464 $.Widget.prototype._setOption.apply( this, arguments ); 10465 10466 switch ( key ) { 10467 case "disabled": 10468 if ( value ) { 10469 this.handles.filter( ".ui-state-focus" ).blur(); 10470 this.handles.removeClass( "ui-state-hover" ); 10471 this.handles.propAttr( "disabled", true ); 10472 this.element.addClass( "ui-disabled" ); 10473 } else { 10474 this.handles.propAttr( "disabled", false ); 10475 this.element.removeClass( "ui-disabled" ); 10476 } 10477 break; 10478 case "orientation": 10479 this._detectOrientation(); 10480 this.element 10481 .removeClass( "ui-slider-horizontal ui-slider-vertical" ) 10482 .addClass( "ui-slider-" + this.orientation ); 10483 this._refreshValue(); 10484 break; 10485 case "value": 10486 this._animateOff = true; 10487 this._refreshValue(); 10488 this._change( null, 0 ); 10489 this._animateOff = false; 10490 break; 10491 case "values": 10492 this._animateOff = true; 10493 this._refreshValue(); 10494 for ( i = 0; i < valsLength; i += 1 ) { 10495 this._change( null, i ); 10496 } 10497 this._animateOff = false; 10498 break; 10499 } 10500 }, 10501 10502 //internal value getter 10503 // _value() returns value trimmed by min and max, aligned by step 10504 _value: function() { 10505 var val = this.options.value; 10506 val = this._trimAlignValue( val ); 10507 10508 return val; 10509 }, 10510 10511 //internal values getter 10512 // _values() returns array of values trimmed by min and max, aligned by step 10513 // _values( index ) returns single value trimmed by min and max, aligned by step 10514 _values: function( index ) { 10515 var val, 10516 vals, 10517 i; 10518 10519 if ( arguments.length ) { 10520 val = this.options.values[ index ]; 10521 val = this._trimAlignValue( val ); 10522 10523 return val; 10524 } else { 10525 // .slice() creates a copy of the array 10526 // this copy gets trimmed by min and max and then returned 10527 vals = this.options.values.slice(); 10528 for ( i = 0; i < vals.length; i+= 1) { 10529 vals[ i ] = this._trimAlignValue( vals[ i ] ); 10530 } 10531 10532 return vals; 10533 } 10534 }, 10535 10536 // returns the step-aligned value that val is closest to, between (inclusive) min and max 10537 _trimAlignValue: function( val ) { 10538 if ( val <= this._valueMin() ) { 10539 return this._valueMin(); 10540 } 10541 if ( val >= this._valueMax() ) { 10542 return this._valueMax(); 10543 } 10544 var step = ( this.options.step > 0 ) ? this.options.step : 1, 10545 valModStep = (val - this._valueMin()) % step, 10546 alignValue = val - valModStep; 10547 10548 if ( Math.abs(valModStep) * 2 >= step ) { 10549 alignValue += ( valModStep > 0 ) ? step : ( -step ); 10550 } 10551 10552 // Since JavaScript has problems with large floats, round 10553 // the final value to 5 digits after the decimal point (see #4124) 10554 return parseFloat( alignValue.toFixed(5) ); 10555 }, 10556 10557 _valueMin: function() { 10558 return this.options.min; 10559 }, 10560 10561 _valueMax: function() { 10562 return this.options.max; 10563 }, 10564 10565 _refreshValue: function() { 10566 var oRange = this.options.range, 10567 o = this.options, 10568 self = this, 10569 animate = ( !this._animateOff ) ? o.animate : false, 10570 valPercent, 10571 _set = {}, 10572 lastValPercent, 10573 value, 10574 valueMin, 10575 valueMax; 10576 10577 if ( this.options.values && this.options.values.length ) { 10578 this.handles.each(function( i, j ) { 10579 valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100; 10580 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 10581 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 10582 if ( self.options.range === true ) { 10583 if ( self.orientation === "horizontal" ) { 10584 if ( i === 0 ) { 10585 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); 10586 } 10587 if ( i === 1 ) { 10588 self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); 10589 } 10590 } else { 10591 if ( i === 0 ) { 10592 self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); 10593 } 10594 if ( i === 1 ) { 10595 self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); 10596 } 10597 } 10598 }
10599 lastValPercent = valPercent; 10600 }); 10601 } else { 10602 value = this.value(); 10603 valueMin = this._valueMin(); 10604 valueMax = this._valueMax(); 10605 valPercent = ( valueMax !== valueMin ) ? 10606 ( value - valueMin ) / ( valueMax - valueMin ) * 100 : 10607 0; 10608 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; 10609 this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); 10610 10611 if ( oRange === "min" && this.orientation === "horizontal" ) { 10612 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); 10613 } 10614 if ( oRange === "max" && this.orientation === "horizontal" ) { 10615 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); 10616 } 10617 if ( oRange === "min" && this.orientation === "vertical" ) { 10618 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); 10619 } 10620 if ( oRange === "max" && this.orientation === "vertical" ) { 10621 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); 10622 } 10623 } 10624 } 10625 10626}); 10627 10628$.extend( $.ui.slider, { 10629 version: "1.8.24" 10630}); 10631 10632}(jQuery)); 10633 10634(function( $, undefined ) { 10635 10636var tabId = 0, 10637 listId = 0; 10638 10639function getNextTabId() { 10640 return ++tabId; 10641} 10642 10643function getNextListId() { 10644 return ++listId; 10645} 10646 10647$.widget( "ui.tabs", { 10648 options: { 10649 add: null, 10650 ajaxOptions: null, 10651 cache: false, 10652 cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true } 10653 collapsible: false, 10654 disable: null, 10655 disabled: [], 10656 enable: null, 10657 event: "click", 10658 fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 } 10659 idPrefix: "ui-tabs-", 10660 load: null, 10661 panelTemplate: "<div></div>", 10662 remove: null, 10663 select: null, 10664 show: null, 10665 spinner: "<em>Loading…</em>", 10666 tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>" 10667 }, 10668 10669 _create: function() { 10670 this._tabify( true ); 10671 }, 10672 10673 _setOption: function( key, value ) { 10674 if ( key == "selected" ) { 10675 if (this.options.collapsible && value == this.options.selected ) { 10676 return; 10677 } 10678 this.select( value ); 10679 } else { 10680 this.options[ key ] = value; 10681 this._tabify(); 10682 } 10683 }, 10684 10685 _tabId: function( a ) { 10686 return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) || 10687 this.options.idPrefix + getNextTabId(); 10688 }, 10689 10690 _sanitizeSelector: function( hash ) { 10691 // we need this because an id may contain a ":" 10692 return hash.replace( /:/g, "\\:" ); 10693 }, 10694 10695 _cookie: function() { 10696 var cookie = this.cookie || 10697 ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() ); 10698 return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) ); 10699 }, 10700 10701 _ui: function( tab, panel ) { 10702 return { 10703 tab: tab, 10704 panel: panel, 10705 index: this.anchors.index( tab ) 10706 }; 10707 }, 10708 10709 _cleanup: function() { 10710 // restore all former loading tabs labels 10711 this.lis.filter( ".ui-state-processing" ) 10712 .removeClass( "ui-state-processing" ) 10713 .find( "span:data(label.tabs)" ) 10714 .each(function() { 10715 var el = $( this ); 10716 el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" ); 10717 }); 10718 }, 10719 10720 _tabify: function( init ) { 10721 var self = this, 10722 o = this.options, 10723 fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash 10724 10725 this.list = this.element.find( "ol,ul" ).eq( 0 ); 10726 this.lis = $( " > li:has(a[href])", this.list ); 10727 this.anchors = this.lis.map(function() { 10728 return $( "a", this )[ 0 ]; 10729 }); 10730 this.panels = $( [] ); 10731 10732 this.anchors.each(function( i, a ) { 10733 var href = $( a ).attr( "href" ); 10734 // For dynamically created HTML that contains a hash as href IE < 8 expands 10735 // such href to the full page url with hash and then misinterprets tab as ajax. 10736 // Same consideration applies for an added tab with a fragment identifier 10737 // since a[href=#fragment-identifier] does unexpectedly not match. 10738 // Thus normalize href attribute... 10739 var hrefBase = href.split( "#" )[ 0 ], 10740 baseEl; 10741 if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] || 10742 ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) { 10743 href = a.hash; 10744 a.href = href; 10745 } 10746 10747 // inline tab 10748 if ( fragmentId.test( href ) ) { 10749 self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) ); 10750 // remote tab 10751 // prevent loading the page itself if href is just "#" 10752 } else if ( href && href !== "#" ) {
10753 // required for restore on destroy 10754 $.data( a, "href.tabs", href ); 10755 10756 // TODO until #3808 is fixed strip fragment identifier from url 10757 // (IE fails to load from such url) 10758 $.data( a, "load.tabs", href.replace( /#.*$/, "" ) ); 10759 10760 var id = self._tabId( a ); 10761 a.href = "#" + id; 10762 var $panel = self.element.find( "#" + id ); 10763 if ( !$panel.length ) { 10764 $panel = $( o.panelTemplate ) 10765 .attr( "id", id ) 10766 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) 10767 .insertAfter( self.panels[ i - 1 ] || self.list ); 10768 $panel.data( "destroy.tabs", true ); 10769 } 10770 self.panels = self.panels.add( $panel ); 10771 // invalid tab href 10772 } else { 10773 o.disabled.push( i ); 10774 } 10775 }); 10776 10777 // initialization from scratch 10778 if ( init ) { 10779 // attach necessary classes for styling 10780 this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ); 10781 this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ); 10782 this.lis.addClass( "ui-state-default ui-corner-top" ); 10783 this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ); 10784 10785 // Selected tab 10786 // use "selected" option or try to retrieve: 10787 // 1. from fragment identifier in url 10788 // 2. from cookie 10789 // 3. from selected class attribute on <li> 10790 if ( o.selected === undefined ) { 10791 if ( location.hash ) { 10792 this.anchors.each(function( i, a ) { 10793 if ( a.hash == location.hash ) { 10794 o.selected = i; 10795 return false; 10796 } 10797 }); 10798 } 10799 if ( typeof o.selected !== "number" && o.cookie ) { 10800 o.selected = parseInt( self._cookie(), 10 ); 10801 } 10802 if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) { 10803 o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) ); 10804 } 10805 o.selected = o.selected || ( this.lis.length ? 0 : -1 ); 10806 } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release 10807 o.selected = -1; 10808 } 10809 10810 // sanity check - default to first tab... 10811 o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 ) 10812 ? o.selected 10813 : 0; 10814 10815 // Take disabling tabs via class attribute from HTML 10816 // into account and update option properly. 10817 // A selected tab cannot become disabled. 10818 o.disabled = $.unique( o.disabled.concat( 10819 $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) { 10820 return self.lis.index( n ); 10821 }) 10822 ) ).sort(); 10823 10824 if ( $.inArray( o.selected, o.disabled ) != -1 ) { 10825 o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 ); 10826 } 10827 10828 // highlight selected tab 10829 this.panels.addClass( "ui-tabs-hide" ); 10830 this.lis.removeClass( "ui-tabs-selected ui-state-active" ); 10831 // check for length avoids error when initializing empty list 10832 if ( o.selected >= 0 && this.anchors.length ) { 10833 self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" ); 10834 this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" ); 10835 10836 // seems to be expected behavior that the show callback is fired 10837 self.element.queue( "tabs", function() { 10838 self._trigger( "show", null, 10839 self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) ); 10840 }); 10841 10842 this.load( o.selected ); 10843 } 10844 10845 // clean up to avoid memory leaks in certain versions of IE 6 10846 // TODO: namespace this event 10847 $( window ).bind( "unload", function() { 10848 self.lis.add( self.anchors ).unbind( ".tabs" ); 10849 self.lis = self.anchors = self.panels = null; 10850 }); 10851 // update selected after add/remove 10852 } else { 10853 o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) ); 10854 } 10855 10856 // update collapsible 10857 // TODO: use .toggleClass() 10858 this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" ); 10859 10860 // set or update cookie after init and add/remove respectively 10861 if ( o.cookie ) { 10862 this._cookie( o.selected, o.cookie ); 10863 } 10864 10865 // disable tabs 10866 for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) { 10867 $( li )[ $.inArray( i, o.disabled ) != -1 && 10868 // TODO: use .toggleClass() 10869 !$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" ); 10870 } 10871 10872 // reset cache if switching from cached to not cached 10873 if ( o.cache === false ) { 10874 this.anchors.removeData( "cache.tabs" ); 10875 } 10876 10877 // remove all handlers before, tabify may run on existing tabs after add or option change 10878 this.lis.add( this.anchors ).unbind( ".tabs" ); 10879 10880 if ( o.event !== "mouseover" ) { 10881 var addState = function( state, el ) { 10882 if ( el.is( ":not(.ui-state-disabled)" ) ) { 10883 el.addClass( "ui-state-" + state ); 10884 } 10885 }; 10886 var removeState = function( state, el ) { 10887 el.removeClass( "ui-state-" + state ); 10888 }; 10889 this.lis.bind( "mouseover.tabs" , function() { 10890 addState( "hover", $( this ) ); 10891 }); 10892 this.lis.bind( "mouseout.tabs", function() { 10893 removeState( "hover", $( this ) ); 10894 }); 10895 this.anchors.bind( "focus.tabs", function() { 10896 addState( "focus", $( this ).closest( "li" ) ); 10897 }); 10898 this.anchors.bind( "blur.tabs", function() { 10899 removeState( "focus", $( this ).closest( "li" ) ); 10900 }); 10901 } 10902 10903 // set up animations 10904 var hideFx, showFx; 10905 if ( o.fx ) { 10906 if ( $.isArray( o.fx ) ) { 10907 hideFx = o.fx[ 0 ]; 10908 showFx = o.fx[ 1 ]; 10909 } else { 10910 hideFx = showFx = o.fx; 10911 } 10912 } 10913 10914 // Reset certain styles left over from animation 10915 // and prevent IE's ClearType bug... 10916 function resetStyle( $el, fx ) { 10917 $el.css( "display", "" ); 10918 if ( !$.support.opacity && fx.opacity ) { 10919 $el[ 0 ].style.removeAttribute( "filter" ); 10920 } 10921 } 10922 10923 // Show a tab... 10924 var showTab = showFx 10925 ? function( clicked, $show ) { 10926 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" ); 10927 $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way 10928 .animate( showFx, showFx.duration || "normal", function() { 10929 resetStyle( $show, showFx ); 10930 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) ); 10931 }); 10932 } 10933 : function( clicked, $show ) { 10934 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" ); 10935 $show.removeClass( "ui-tabs-hide" ); 10936 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) ); 10937 }; 10938 10939 // Hide a tab, $show is optional... 10940 var hideTab = hideFx 10941 ? function( clicked, $hide ) { 10942 $hide.animate( hideFx, hideFx.duration || "normal", function() { 10943 self.lis.removeClass( "ui-tabs-selected ui-state-active" ); 10944 $hide.addClass( "ui-tabs-hide" ); 10945 resetStyle( $hide, hideFx ); 10946 self.element.dequeue( "tabs" ); 10947 }); 10948 } 10949 : function( clicked, $hide, $show ) { 10950 self.lis.removeClass( "ui-tabs-selected ui-state-active" ); 10951 $hide.addClass( "ui-tabs-hide" ); 10952 self.element.dequeue( "tabs" ); 10953 }; 10954 10955 // attach tab event handler, unbind to avoid duplicates from former tabifying... 10956 this.anchors.bind( o.event + ".tabs", function() { 10957 var el = this, 10958 $li = $(el).closest( "li" ), 10959 $hide = self.panels.filter( ":not(.ui-tabs-hide)" ), 10960 $show = self.element.find( self._sanitizeSelector( el.hash ) ); 10961 10962 // If tab is already selected and not collapsible or tab disabled or 10963 // or is already loading or click callback returns false stop here. 10964 // Check if click handler returns false last so that it is not executed 10965 // for a disabled or loading tab! 10966 if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) || 10967 $li.hasClass( "ui-state-disabled" ) || 10968 $li.hasClass( "ui-state-processing" ) || 10969 self.panels.filter( ":animated" ).length || 10970 self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) { 10971 this.blur(); 10972 return false;
10973 } 10974 10975 o.selected = self.anchors.index( this ); 10976 10977 self.abort(); 10978 10979 // if tab may be closed 10980 if ( o.collapsible ) { 10981 if ( $li.hasClass( "ui-tabs-selected" ) ) { 10982 o.selected = -1; 10983 10984 if ( o.cookie ) { 10985 self._cookie( o.selected, o.cookie ); 10986 } 10987 10988 self.element.queue( "tabs", function() { 10989 hideTab( el, $hide ); 10990 }).dequeue( "tabs" ); 10991 10992 this.blur(); 10993 return false; 10994 } else if ( !$hide.length ) { 10995 if ( o.cookie ) { 10996 self._cookie( o.selected, o.cookie ); 10997 } 10998 10999 self.element.queue( "tabs", function() { 11000 showTab( el, $show ); 11001 }); 11002 11003 // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171 11004 self.load( self.anchors.index( this ) ); 11005 11006 this.blur(); 11007 return false; 11008 } 11009 } 11010 11011 if ( o.cookie ) { 11012 self._cookie( o.selected, o.cookie ); 11013 } 11014 11015 // show new tab 11016 if ( $show.length ) { 11017 if ( $hide.length ) { 11018 self.element.queue( "tabs", function() { 11019 hideTab( el, $hide ); 11020 }); 11021 } 11022 self.element.queue( "tabs", function() { 11023 showTab( el, $show ); 11024 }); 11025 11026 self.load( self.anchors.index( this ) ); 11027 } else { 11028 throw "jQuery UI Tabs: Mismatching fragment identifier."; 11029 } 11030 11031 // Prevent IE from keeping other link focussed when using the back button 11032 // and remove dotted border from clicked link. This is controlled via CSS 11033 // in modern browsers; blur() removes focus from address bar in Firefox 11034 // which can become a usability and annoying problem with tabs('rotate'). 11035 if ( $.browser.msie ) { 11036 this.blur(); 11037 } 11038 }); 11039 11040 // disable click in any case 11041 this.anchors.bind( "click.tabs", function(){ 11042 return false; 11043 }); 11044 }, 11045 11046 _getIndex: function( index ) { 11047 // meta-function to give users option to provide a href string instead of a numerical index. 11048 // also sanitizes numerical indexes to valid values. 11049 if ( typeof index == "string" ) { 11050 index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) ); 11051 } 11052 11053 return index; 11054 }, 11055 11056 destroy: function() { 11057 var o = this.options; 11058 11059 this.abort(); 11060 11061 this.element 11062 .unbind( ".tabs" ) 11063 .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ) 11064 .removeData( "tabs" ); 11065 11066 this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ); 11067 11068 this.anchors.each(function() { 11069 var href = $.data( this, "href.tabs" ); 11070 if ( href ) { 11071 this.href = href; 11072 } 11073 var $this = $( this ).unbind( ".tabs" ); 11074 $.each( [ "href", "load", "cache" ], function( i, prefix ) { 11075 $this.removeData( prefix + ".tabs" ); 11076 }); 11077 }); 11078 11079 this.lis.unbind( ".tabs" ).add( this.panels ).each(function() { 11080 if ( $.data( this, "destroy.tabs" ) ) { 11081 $( this ).remove(); 11082 } else { 11083 $( this ).removeClass([ 11084 "ui-state-default", 11085 "ui-corner-top", 11086 "ui-tabs-selected", 11087 "ui-state-active", 11088 "ui-state-hover", 11089 "ui-state-focus", 11090 "ui-state-disabled", 11091 "ui-tabs-panel", 11092 "ui-widget-content", 11093 "ui-corner-bottom", 11094 "ui-tabs-hide" 11095 ].join( " " ) ); 11096 } 11097 }); 11098 11099 if ( o.cookie ) { 11100 this._cookie( null, o.cookie ); 11101 } 11102 11103 return this; 11104 }, 11105 11106 add: function( url, label, index ) { 11107 if ( index === undefined ) { 11108 index = this.anchors.length; 11109 } 11110 11111 var self = this, 11112 o = this.options, 11113 $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ), 11114 id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] ); 11115 11116 $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true ); 11117 11118 // try to find an existing element before creating a new one 11119 var $panel = self.element.find( "#" + id ); 11120 if ( !$panel.length ) { 11121 $panel = $( o.panelTemplate ) 11122 .attr( "id", id ) 11123 .data( "destroy.tabs", true ); 11124 } 11125 $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" ); 11126 11127 if ( index >= this.lis.length ) { 11128 $li.appendTo( this.list ); 11129 $panel.appendTo( this.list[ 0 ].parentNode ); 11130 } else { 11131 $li.insertBefore( this.lis[ index ] ); 11132 $panel.insertBefore( this.panels[ index ] ); 11133 } 11134 11135 o.disabled = $.map( o.disabled, function( n, i ) { 11136 return n >= index ? ++n : n; 11137 }); 11138 11139 this._tabify(); 11140 11141 if ( this.anchors.length == 1 ) { 11142 o.selected = 0; 11143 $li.addClass( "ui-tabs-selected ui-state-active" ); 11144 $panel.removeClass( "ui-tabs-hide" ); 11145 this.element.queue( "tabs", function() { 11146 self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) ); 11147 }); 11148 11149 this.load( 0 ); 11150 } 11151 11152 this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); 11153 return this; 11154 }, 11155 11156 remove: function( index ) { 11157 index = this._getIndex( index ); 11158 var o = this.options, 11159 $li = this.lis.eq( index ).remove(), 11160 $panel = this.panels.eq( index ).remove(); 11161 11162 // If selected tab was removed focus tab to the right or 11163 // in case the last tab was removed the tab to the left. 11164 if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) { 11165 this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) ); 11166 } 11167 11168 o.disabled = $.map( 11169 $.grep( o.disabled, function(n, i) {
11170 return n != index; 11171 }), 11172 function( n, i ) { 11173 return n >= index ? --n : n; 11174 }); 11175 11176 this._tabify(); 11177 11178 this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) ); 11179 return this; 11180 }, 11181 11182 enable: function( index ) { 11183 index = this._getIndex( index ); 11184 var o = this.options; 11185 if ( $.inArray( index, o.disabled ) == -1 ) { 11186 return; 11187 } 11188 11189 this.lis.eq( index ).removeClass( "ui-state-disabled" ); 11190 o.disabled = $.grep( o.disabled, function( n, i ) { 11191 return n != index; 11192 }); 11193 11194 this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); 11195 return this; 11196 }, 11197 11198 disable: function( index ) { 11199 index = this._getIndex( index ); 11200 var self = this, o = this.options; 11201 // cannot disable already selected tab 11202 if ( index != o.selected ) { 11203 this.lis.eq( index ).addClass( "ui-state-disabled" ); 11204 11205 o.disabled.push( index ); 11206 o.disabled.sort(); 11207 11208 this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); 11209 } 11210 11211 return this; 11212 }, 11213 11214 select: function( index ) { 11215 index = this._getIndex( index ); 11216 if ( index == -1 ) { 11217 if ( this.options.collapsible && this.options.selected != -1 ) { 11218 index = this.options.selected; 11219 } else { 11220 return this; 11221 } 11222 } 11223 this.anchors.eq( index ).trigger( this.options.event + ".tabs" ); 11224 return this; 11225 }, 11226 11227 load: function( index ) { 11228 index = this._getIndex( index ); 11229 var self = this, 11230 o = this.options, 11231 a = this.anchors.eq( index )[ 0 ], 11232 url = $.data( a, "load.tabs" ); 11233 11234 this.abort(); 11235 11236 // not remote or from cache 11237 if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) { 11238 this.element.dequeue( "tabs" ); 11239 return; 11240 } 11241 11242 // load remote from here on 11243 this.lis.eq( index ).addClass( "ui-state-processing" ); 11244 11245 if ( o.spinner ) { 11246 var span = $( "span", a ); 11247 span.data( "label.tabs", span.html() ).html( o.spinner ); 11248 } 11249 11250 this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, { 11251 url: url, 11252 success: function( r, s ) { 11253 self.element.find( self._sanitizeSelector( a.hash ) ).html( r ); 11254 11255 // take care of tab labels 11256 self._cleanup(); 11257 11258 if ( o.cache ) { 11259 $.data( a, "cache.tabs", true ); 11260 } 11261 11262 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) ); 11263 try { 11264 o.ajaxOptions.success( r, s ); 11265 } 11266 catch ( e ) {} 11267 }, 11268 error: function( xhr, s, e ) { 11269 // take care of tab labels 11270 self._cleanup(); 11271 11272 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) ); 11273 try { 11274 // Passing index avoid a race condition when this method is 11275 // called after the user has selected another tab. 11276 // Pass the anchor that initiated this request allows 11277 // loadError to manipulate the tab content panel via $(a.hash) 11278 o.ajaxOptions.error( xhr, s, index, a ); 11279 } 11280 catch ( e ) {} 11281 } 11282 } ) ); 11283 11284 // last, so that load event is fired before show... 11285 self.element.dequeue( "tabs" ); 11286 11287 return this; 11288 }, 11289 11290 abort: function() { 11291 // stop possibly running animations 11292 this.element.queue( [] ); 11293 this.panels.stop( false, true ); 11294 11295 // "tabs" queue must not contain more than two elements, 11296 // which are the callbacks for the latest clicked tab... 11297 this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) ); 11298 11299 // terminate pending requests from other tabs 11300 if ( this.xhr ) { 11301 this.xhr.abort(); 11302 delete this.xhr; 11303 } 11304 11305 // take care of tab labels 11306 this._cleanup(); 11307 return this; 11308 }, 11309 11310 url: function( index, url ) { 11311 this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url ); 11312 return this; 11313 }, 11314 11315 length: function() { 11316 return this.anchors.length; 11317 } 11318}); 11319 11320$.extend( $.ui.tabs, { 11321 version: "1.8.24" 11322}); 11323 11324/* 11325 * Tabs Extensions 11326 */ 11327 11328/* 11329 * Rotate 11330 */ 11331$.extend( $.ui.tabs.prototype, { 11332 rotation: null, 11333 rotate: function( ms, continuing ) { 11334 var self = this, 11335 o = this.options; 11336 11337 var rotate = self._rotate || ( self._rotate = function( e ) { 11338 clearTimeout( self.rotation ); 11339 self.rotation = setTimeout(function() { 11340 var t = o.selected; 11341 self.select( ++t < self.anchors.length ? t : 0 ); 11342 }, ms ); 11343 11344 if ( e ) { 11345 e.stopPropagation(); 11346 } 11347 }); 11348 11349 var stop = self._unrotate || ( self._unrotate = !continuing 11350 ? function(e) { 11351 if (e.clientX) { // in case of a true click 11352 self.rotate(null); 11353 } 11354 } 11355 : function( e ) { 11356 rotate(); 11357 }); 11358 11359 // start rotation 11360 if ( ms ) {
11361 this.element.bind( "tabsshow", rotate ); 11362 this.anchors.bind( o.event + ".tabs", stop ); 11363 rotate(); 11364 // stop rotation 11365 } else { 11366 clearTimeout( self.rotation ); 11367 this.element.unbind( "tabsshow", rotate ); 11368 this.anchors.unbind( o.event + ".tabs", stop ); 11369 delete this._rotate; 11370 delete this._unrotate; 11371 } 11372 11373 return this; 11374 } 11375}); 11376 11377})( 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.